Skip to content

Commit 694c800

Browse files
committed
feat: integrated v2Logger in export plugin
1 parent 6446419 commit 694c800

41 files changed

Lines changed: 591 additions & 328 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,68 @@
1-
{}
1+
{
2+
"ASSET_EXPORT_COMPLETE": "Asset export process completed successfully",
3+
"ASSET_FOLDERS_EXPORT_COMPLETE": "Asset folder structure exported successfully",
4+
"ASSET_METADATA_EXPORT_COMPLETE": "Asset metadata exported successfully",
5+
"ASSET_VERSIONED_METADATA_EXPORT_COMPLETE": "Versioned asset metadata exported successfully",
6+
"ASSET_DOWNLOAD_COMPLETE": "Asset download completed successfully",
7+
"ASSET_DOWNLOAD_SUCCESS": "Asset '%s' (UID: %s) downloaded successfully",
8+
"ASSET_DOWNLOAD_FAILED": "Failed to download asset '%s' (UID: %s)",
9+
"ASSET_WRITE_FAILED": "Failed to write asset file '%s' (UID: %s)",
10+
"ASSET_QUERY_FAILED": "Failed to query asset data from the API",
11+
"ASSET_VERSIONED_QUERY_FAILED": "Failed to query versioned asset data from the API",
12+
"ASSET_COUNT_QUERY_FAILED": "Failed to retrieve total asset count",
13+
14+
"CONTENT_TYPE_EXPORT_COMPLETE": "Content types exported successfully",
15+
"CONTENT_TYPE_NO_TYPES": "No content types found",
16+
"CONTENT_TYPE_EXPORT_FAILED": "Failed to export content types",
17+
"CONTENT_TYPE_NO_TYPES_RETURNED": "API returned no content types for the given query",
18+
19+
"ENVIRONMENT_EXPORT_COMPLETE": "Successfully exported %s environment(s)",
20+
"ENVIRONMENT_EXPORT_SUCCESS": "Environment '%s' exported successfully",
21+
"ENVIRONMENT_NOT_FOUND": "No environments found in the current stack",
22+
23+
"EXTENSION_EXPORT_COMPLETE": "Successfully exported %s extension(s)",
24+
"EXTENSION_EXPORT_SUCCESS": "Extension '%s' exported successfully",
25+
"EXTENSION_NOT_FOUND": "No extensions found in the current stack",
26+
27+
"GLOBAL_FIELDS_EXPORT_COMPLETE": "Successfully exported %s global field(s)",
28+
29+
"LABELS_EXPORT_COMPLETE": "Successfully exported %s label(s)",
30+
"LABEL_EXPORT_SUCCESS": "Label '%s' exported successfully",
31+
"LABELS_NOT_FOUND": "No labels found in the current stack",
32+
33+
"LOCALES_EXPORT_COMPLETE": "Successfully exported %s locale(s) including %s master locale(s)",
34+
35+
"TAXONOMY_EXPORT_COMPLETE": "Successfully exported %s taxonomy entries",
36+
"TAXONOMY_EXPORT_SUCCESS": "Taxonomy '%s' exported successfully",
37+
"TAXONOMY_NOT_FOUND": "No taxonomies found in the current stack",
38+
39+
"WEBHOOK_EXPORT_COMPLETE": "Successfully exported %s webhook(s)",
40+
"WEBHOOK_EXPORT_SUCCESS": "Webhook '%s' exported successfully",
41+
"WEBHOOK_NOT_FOUND": "No webhooks found in the current stack",
42+
43+
"WORKFLOW_EXPORT_COMPLETE": "Successfully exported %s workflow(s)",
44+
"WORKFLOW_EXPORT_SUCCESS": "Workflow '%s' exported successfully",
45+
"WORKFLOW_NOT_FOUND": "No workflows found in the current stack",
46+
47+
"PERSONALIZE_URL_NOT_SET": "Cannot export Personalize project: URL not configured",
48+
"PERSONALIZE_SKIPPING_WITH_MANAGEMENT_TOKEN": "Skipping Personalize project export: Management token not supported",
49+
"PERSONALIZE_MODULE_NOT_IMPLEMENTED": "Module '%s' implementation not found",
50+
"PERSONALIZE_NOT_ENABLED": "Personalize feature is not enabled for this organization",
51+
52+
"MARKETPLACE_APPS_EXPORT_COMPLETE": "Successfully exported %s marketplace app(s)",
53+
"MARKETPLACE_APP_CONFIG_EXPORT": "Exporting configuration for app '%s'",
54+
"MARKETPLACE_APP_CONFIG_SUCCESS": "Successfully exported configuration for app '%s'",
55+
"MARKETPLACE_APP_EXPORT_SUCCESS": "Successfully exported app '%s'",
56+
"MARKETPLACE_APPS_NOT_FOUND": "No marketplace apps found in the current stack",
57+
"MARKETPLACE_APP_CONFIG_EXPORT_FAILED": "Failed to export configuration for app '%s'",
58+
"MARKETPLACE_APP_MANIFEST_EXPORT_FAILED": "Failed to export manifest for app '%s'",
59+
60+
"ENTRIES_EXPORT_COMPLETE": "Successfully exported entries (Content Type: %s, Locale: %s)",
61+
"ENTRIES_EXPORT_SUCCESS": "All entries exported successfully",
62+
"ENTRIES_VERSIONED_EXPORT_SUCCESS": "Successfully exported versioned entry (Content Type: %s, UID: %s, Locale: %s)",
63+
"ENTRIES_EXPORT_VERSIONS_FAILED": "Failed to export versions for content type '%s' (UID: %s)",
64+
65+
"BRANCH_EXPORT_FAILED": "Failed to export contents from branch (UID: %s)",
66+
67+
"ROLES_NO_CUSTOM_ROLES": "No custom roles found in the current stack"
68+
}

packages/contentstack-export/src/commands/cm/stacks/export.ts

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import {
1010
FlagInput,
1111
pathValidator,
1212
sanitizePath,
13+
configHandler,
14+
v2Logger,
15+
handleAndLogError
1316
} from '@contentstack/cli-utilities';
1417
import { ModuleExporter } from '../../../export';
15-
import { setupExportConfig, log, formatError, writeExportMetaFile } from '../../../utils';
16-
import { ExportConfig } from '../../../types';
18+
import { setupExportConfig, writeExportMetaFile } from '../../../utils';
19+
import { Context, ExportConfig } from '../../../types';
1720

1821
export default class ExportCommand extends Command {
1922
static description: string = messageHandler.parse('Export content from a stack');
@@ -72,19 +75,22 @@ export default class ExportCommand extends Command {
7275
}),
7376
module: flags.string({
7477
char: 'm',
75-
description: '[optional] Specific module name. If not specified, the export command will export all the modules to the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, and taxonomies.',
78+
description:
79+
'[optional] Specific module name. If not specified, the export command will export all the modules to the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, and taxonomies.',
7680
parse: printFlagDeprecation(['-m'], ['--module']),
7781
}),
7882
'content-types': flags.string({
7983
char: 't',
80-
description: '[optional] The UID of the content type(s) whose content you want to export. In case of multiple content types, specify the IDs separated by spaces.',
84+
description:
85+
'[optional] The UID of the content type(s) whose content you want to export. In case of multiple content types, specify the IDs separated by spaces.',
8186
multiple: true,
8287
parse: printFlagDeprecation(['-t'], ['--content-types']),
8388
}),
8489
branch: flags.string({
8590
char: 'B',
8691
// default: 'main',
87-
description: '[optional] The name of the branch where you want to export your content. If you don\'t mention the branch name, then by default the content will be exported from all the branches of your stack.',
92+
description:
93+
"[optional] The name of the branch where you want to export your content. If you don't mention the branch name, then by default the content will be exported from all the branches of your stack.",
8894
parse: printFlagDeprecation(['-B'], ['--branch']),
8995
}),
9096
'secured-assets': flags.boolean({
@@ -101,30 +107,57 @@ export default class ExportCommand extends Command {
101107

102108
async run(): Promise<void> {
103109
let exportDir: string = pathValidator('logs');
110+
let exportConfig: ExportConfig;
104111
try {
105112
const { flags } = await this.parse(ExportCommand);
106-
let exportConfig = await setupExportConfig(flags);
107-
// Note setting host to create cma client
108-
exportConfig.host = this.cmaHost;
109-
exportConfig.region = this.region;
110-
if(this.developerHubUrl) exportConfig.developerHubBaseUrl = this.developerHubUrl;
111-
if (this.personalizeUrl) exportConfig.modules.personalize.baseURL[exportConfig.region.name] = this.personalizeUrl;
113+
exportConfig = await setupExportConfig(flags);
114+
// Prepare the context object
115+
const context = this.createExportContext();
116+
exportConfig.context = context;
117+
118+
// Assign exportConfig variables
119+
this.assignExportConfig(exportConfig);
120+
112121
exportDir = sanitizePath(exportConfig.cliLogsPath || exportConfig.data || exportConfig.exportDir);
113122
const managementAPIClient: ContentstackClient = await managementSDKClient(exportConfig);
114123
const moduleExporter = new ModuleExporter(managementAPIClient, exportConfig);
115124
await moduleExporter.start();
116125
if (!exportConfig.branches?.length) {
117126
writeExportMetaFile(exportConfig);
118127
}
119-
log(exportConfig, `The content of the stack ${exportConfig.apiKey} has been exported successfully!`, 'success');
120-
log(
121-
exportConfig,
122-
`The log has been stored at '${pathValidator(path.join(exportDir, 'logs', 'export'))}'`,
123-
'success',
124-
);
128+
v2Logger.success(`The content of the stack ${exportConfig.apiKey} has been exported successfully!`,exportConfig.context)
129+
v2Logger.success(`The log has been stored at '${pathValidator(path.join(process.cwd(), 'logs'))}'`, exportConfig.context)
125130
} catch (error) {
126-
log({ data: exportDir } as ExportConfig, `Failed to export stack content - ${formatError(error)}`, 'error');
127-
log({ data: exportDir } as ExportConfig, `The log has been stored at ${exportDir}`, 'info');
131+
handleAndLogError(error, { ...exportConfig.context });
132+
}
133+
}
134+
135+
// Create export context object
136+
private createExportContext(): Context {
137+
return {
138+
command: this.context.info.command,
139+
module: '',
140+
userId: configHandler.get('userId'),
141+
email: configHandler.get('email'),
142+
sessionId: this.context.sessionId,
143+
clientId: this.context.clientId,
144+
apiKey: configHandler.get('apiKey') || '',
145+
orgId: configHandler.get('organization_uid') || '',
146+
};
147+
}
148+
149+
// Assign values to exportConfig
150+
private assignExportConfig(exportConfig: ExportConfig): void {
151+
// Note setting host to create cma client
152+
exportConfig.host = this.cmaHost;
153+
exportConfig.region = this.region;
154+
155+
if (this.developerHubUrl) {
156+
exportConfig.developerHubBaseUrl = this.developerHubUrl;
157+
}
158+
159+
if (this.personalizeUrl) {
160+
exportConfig.modules.personalize.baseURL[exportConfig.region.name] = this.personalizeUrl;
128161
}
129162
}
130163
}

packages/contentstack-export/src/export/module-exporter.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as path from 'path';
2-
import { ContentstackClient } from '@contentstack/cli-utilities';
2+
import { ContentstackClient, handleAndLogError, messageHandler, v2Logger } from '@contentstack/cli-utilities';
33
import { setupBranches, setupExportDir, log, formatError, writeExportMetaFile } from '../utils';
44
import startModuleExport from './modules';
55
import startJSModuleExport from './modules-js';
@@ -38,19 +38,29 @@ class ModuleExporter {
3838
this.exportConfig.branchName = branch.uid;
3939
this.stackAPIClient.stackHeaders.branch = branch.uid;
4040
this.exportConfig.branchDir = path.join(this.exportConfig.exportDir, branch.uid);
41-
log(this.exportConfig, `Exporting content from branch ${branch.uid}`, 'success');
41+
v2Logger.info(`Exporting content from branch ${branch.uid}`, this.exportConfig.context);
4242
writeExportMetaFile(this.exportConfig, this.exportConfig.branchDir);
4343
await this.export();
44-
log(this.exportConfig, `The content of branch ${branch.uid} has been exported successfully!`, 'success');
44+
v2Logger.success(
45+
`The content of branch ${branch.uid} has been exported successfully!`,
46+
this.exportConfig.context,
47+
);
4548
} catch (error) {
46-
log(this.exportConfig, formatError(error), 'error');
47-
throw new Error(`Failed to export contents from branch ${branch.uid}`);
49+
handleAndLogError(
50+
error,
51+
{ ...this.exportConfig.context, branch: branch.uid },
52+
messageHandler.parse('FAILED_EXPORT_CONTENT_BRANCH', { branch: branch.uid }),
53+
);
54+
throw new Error(messageHandler.parse('FAILED_EXPORT_CONTENT_BRANCH', { branch: branch.uid }));
4855
}
4956
}
5057
}
5158

5259
async export() {
53-
log(this.exportConfig, `Started to export content, version is ${this.exportConfig.contentVersion}`, 'info');
60+
v2Logger.info(
61+
`Started to export content, version is ${this.exportConfig.contentVersion}`,
62+
this.exportConfig.context,
63+
);
5464
// checks for single module or all modules
5565
if (this.exportConfig.singleModuleExport) {
5666
return this.exportSingleModule(this.exportConfig.moduleName);
@@ -59,7 +69,7 @@ class ModuleExporter {
5969
}
6070

6171
async exportByModuleByName(moduleName: Modules) {
62-
log(this.exportConfig, `Starting export of ${moduleName} module`, 'info');
72+
v2Logger.info(`Exporting module: ${moduleName}`, this.exportConfig.context);
6373
// export the modules by name
6474
// calls the module runner which inturn calls the module itself
6575
let exportedModuleResponse;

packages/contentstack-export/src/export/modules/assets.ts

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ import includes from 'lodash/includes';
1111
import progress from 'progress-stream';
1212
import { createWriteStream } from 'node:fs';
1313
import { resolve as pResolve } from 'node:path';
14-
import { FsUtility, getDirectories, configHandler } from '@contentstack/cli-utilities';
14+
import {
15+
FsUtility,
16+
getDirectories,
17+
configHandler,
18+
v2Logger,
19+
handleAndLogError,
20+
messageHandler,
21+
} from '@contentstack/cli-utilities';
1522

1623
import { ModuleClassParams } from '../../types';
1724
import config from '../../config';
18-
import { log } from '../../utils';
1925
import BaseClass, { CustomPromiseHandler, CustomPromiseHandlerInput } from './base-class';
2026

2127
export default class ExportAssets extends BaseClass {
@@ -26,6 +32,7 @@ export default class ExportAssets extends BaseClass {
2632

2733
constructor({ exportConfig, stackAPIClient }: ModuleClassParams) {
2834
super({ exportConfig, stackAPIClient });
35+
this.exportConfig.context.module = 'assets';
2936
}
3037

3138
get commonQueryParam(): Record<string, unknown> {
@@ -56,8 +63,7 @@ export default class ExportAssets extends BaseClass {
5663

5764
// NOTE step 4: Download all assets
5865
await this.downloadAssets();
59-
60-
log(this.exportConfig, 'Assets exported successfully.!', 'info');
66+
v2Logger.success(messageHandler.parse('ASSET_EXPORT_COMPLETE'), this.exportConfig.context);
6167
}
6268

6369
/**
@@ -77,8 +83,7 @@ export default class ExportAssets extends BaseClass {
7783
if (!isEmpty(items)) this.assetsFolder.push(...items);
7884
};
7985
const onReject = ({ error }: any) => {
80-
log(this.exportConfig, 'Export asset folder query failed', 'error');
81-
log(this.exportConfig, error, 'error');
86+
handleAndLogError(error, { ...this.exportConfig.context });
8287
};
8388

8489
return this.makeConcurrentCall({
@@ -98,7 +103,10 @@ export default class ExportAssets extends BaseClass {
98103
this.assetsFolder,
99104
);
100105
}
101-
log(this.exportConfig, 'Assets folder Exported successfully.!', 'info');
106+
v2Logger.info(
107+
messageHandler.parse('ASSET_FOLDERS_EXPORT_COMPLETE', this.assetsFolder.length),
108+
this.exportConfig.context,
109+
);
102110
});
103111
}
104112

@@ -133,8 +141,7 @@ export default class ExportAssets extends BaseClass {
133141
}
134142

135143
const onReject = ({ error }: any) => {
136-
log(this.exportConfig, 'Export asset query failed', 'error');
137-
log(this.exportConfig, error.message, 'error');
144+
handleAndLogError(error, { ...this.exportConfig.context }, messageHandler.parse('ASSET_QUERY_FAILED'));
138145
};
139146

140147
const onSuccess = ({ response: { items } }: any) => {
@@ -163,7 +170,7 @@ export default class ExportAssets extends BaseClass {
163170
concurrencyLimit: this.assetConfig.fetchConcurrency,
164171
}).then(() => {
165172
fs?.completeFile(true);
166-
log(this.exportConfig, 'Assets metadata exported successfully.!', 'info');
173+
v2Logger.info(messageHandler.parse('ASSET_METADATA_EXPORT_COMPLETE'), this.exportConfig.context);
167174
});
168175
}
169176

@@ -221,8 +228,7 @@ export default class ExportAssets extends BaseClass {
221228
});
222229
};
223230
const onReject = ({ error }: any) => {
224-
log(this.exportConfig, 'Export versioned asset query failed', 'error');
225-
log(this.exportConfig, error, 'error');
231+
handleAndLogError(error, { ...this.exportConfig.context }, messageHandler.parse('ASSET_VERSIONED_QUERY_FAILED'));
226232
};
227233

228234
return this.makeConcurrentCall(
@@ -241,7 +247,7 @@ export default class ExportAssets extends BaseClass {
241247
promisifyHandler,
242248
).then(() => {
243249
fs?.completeFile(true);
244-
log(this.exportConfig, 'Assets folder Exported successfully.!', 'info');
250+
v2Logger.info(messageHandler.parse('ASSET_VERSIONED_METADATA_EXPORT_COMPLETE'), this.exportConfig.context);
245251
});
246252
}
247253

@@ -265,8 +271,7 @@ export default class ExportAssets extends BaseClass {
265271
.count()
266272
.then(({ assets }: any) => assets)
267273
.catch((error: Error) => {
268-
log(this.exportConfig, 'Get count query failed', 'error');
269-
log(this.exportConfig, error, 'error');
274+
handleAndLogError(error, { ...this.exportConfig.context }, messageHandler.parse('ASSET_COUNT_QUERY_FAILED'));
270275
});
271276
}
272277

@@ -306,8 +311,11 @@ export default class ExportAssets extends BaseClass {
306311

307312
const assetWriterStream = createWriteStream(assetFilePath);
308313
assetWriterStream.on('error', (error) => {
309-
log(this.exportConfig, `Downloaded failed ${asset.filename}: ${asset.uid}!`, 'error');
310-
log(this.exportConfig, error, 'error');
314+
handleAndLogError(
315+
error,
316+
{ ...this.exportConfig.context, uid: asset.uid, filename: asset.fileName },
317+
messageHandler.parse('ASSET_DOWNLOAD_FAILED', asset.filename, asset.uid),
318+
);
311319
});
312320
/**
313321
* NOTE if pipe not working as expected add the following code below to fix the issue
@@ -330,13 +338,19 @@ export default class ExportAssets extends BaseClass {
330338
data.pipe(assetWriterStream);
331339
}
332340

333-
log(this.exportConfig, `Downloaded ${asset.filename}: ${asset.uid} successfully!`, 'success');
341+
v2Logger.success(
342+
messageHandler.parse('ASSET_DOWNLOAD_SUCCESS', asset.filename, asset.uid),
343+
this.exportConfig.context,
344+
);
334345
};
335346

336347
const onReject = ({ error, additionalInfo }: any) => {
337348
const { asset } = additionalInfo;
338-
log(this.exportConfig, `Downloaded failed ${asset.filename}: ${asset.uid}!`, 'error');
339-
log(this.exportConfig, error, 'error');
349+
handleAndLogError(
350+
error,
351+
{ ...this.exportConfig.context, uid: asset.uid, filename: asset.filename },
352+
messageHandler.parse('ASSET_DOWNLOAD_FAILED', asset.filename, asset.uid),
353+
);
340354
};
341355

342356
const promisifyHandler: CustomPromiseHandler = (input: CustomPromiseHandlerInput) => {
@@ -364,7 +378,7 @@ export default class ExportAssets extends BaseClass {
364378
},
365379
promisifyHandler,
366380
).then(() => {
367-
log(this.exportConfig, 'Assets download completed successfully.!', 'info');
381+
v2Logger.success(messageHandler.parse('ASSET_DOWNLOAD_COMPLETE'), this.exportConfig.context);
368382
});
369383
}
370384
}

0 commit comments

Comments
 (0)