Skip to content

Commit bf89d5f

Browse files
Merge pull request #2254 from contentstack/enh/dx-3701
integrated centralized logger in import setup
2 parents ab5b003 + 3e6fda5 commit bf89d5f

File tree

18 files changed

+743
-659
lines changed

18 files changed

+743
-659
lines changed

.talismanrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fileignoreconfig:
22
- filename: package-lock.json
3-
checksum: e79c27cf2fa46f146c1f94ea324fc4a2ebc31df8b2eb05720fcc64153e090a3f
3+
checksum: 458eb145e0e0ebab5a168f71757895128e253b6893fbddf561b76528523b713f
44
- filename: pnpm-lock.yaml
55
checksum: fe3e9d9f6eba0158d4985b8bdb8ec6e35419b3a9e9768e5610bf74f2f59454d1
66
- filename: packages/contentstack-import-setup/test/unit/backup-handler.test.ts

package-lock.json

Lines changed: 569 additions & 552 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/contentstack-import-setup/src/commands/cm/stacks/import-setup.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ import {
99
ContentstackClient,
1010
pathValidator,
1111
formatError,
12+
log,
13+
handleAndLogError,
14+
configHandler,
1215
} from '@contentstack/cli-utilities';
1316

14-
import { ImportConfig } from '../../../types';
15-
import { setupImportConfig, log } from '../../../utils';
17+
import { ImportConfig, Context } from '../../../types';
18+
import { setupImportConfig } from '../../../utils';
1619
import { ImportSetup } from '../../../import';
1720

1821
export default class ImportSetupCommand extends Command {
@@ -67,29 +70,41 @@ export default class ImportSetupCommand extends Command {
6770
try {
6871
const { flags } = await this.parse(ImportSetupCommand);
6972
let importSetupConfig = await setupImportConfig(flags);
73+
// Prepare the context object
74+
const context = this.createImportSetupContext(importSetupConfig.apiKey, (importSetupConfig as any).authenticationMethod);
75+
importSetupConfig.context = { ...context };
76+
7077
// Note setting host to create cma client
7178
importSetupConfig.host = this.cmaHost;
7279
importSetupConfig.region = this.region;
7380
importSetupConfig.developerHubBaseUrl = this.developerHubUrl;
7481
const managementAPIClient: ContentstackClient = await managementSDKClient(importSetupConfig);
7582
const importSetup = new ImportSetup(importSetupConfig, managementAPIClient);
7683
await importSetup.start();
77-
log(
78-
importSetupConfig,
84+
log.success(
7985
`Backup folder and mapper files have been successfully created for the stack using the API key ${importSetupConfig.apiKey}.`,
80-
'success',
86+
importSetupConfig.context,
8187
);
82-
log(
83-
importSetupConfig,
88+
log.success(
8489
`The backup folder has been created at '${pathValidator(path.join(importSetupConfig.backupDir))}'.`,
85-
'success',
90+
importSetupConfig.context,
8691
);
8792
} catch (error) {
88-
log(
89-
{ data: '' } as ImportConfig,
90-
`Failed to create the backup folder and mapper files: ${formatError(error)}`,
91-
'error',
92-
);
93+
handleAndLogError(error);
9394
}
9495
}
96+
97+
// Create import setup context object
98+
private createImportSetupContext(apiKey: string, authenticationMethod?: string, module?: string): Context {
99+
return {
100+
command: this.context?.info?.command || 'cm:stacks:import-setup',
101+
module: module || '',
102+
userId: configHandler.get('userUid') || undefined,
103+
email: configHandler.get('email') || undefined,
104+
sessionId: this.context?.sessionId,
105+
apiKey: apiKey || '',
106+
orgId: configHandler.get('oauthOrgUid') || '',
107+
authenticationMethod: authenticationMethod || 'Basic Auth',
108+
};
109+
}
95110
}

packages/contentstack-import-setup/src/import/import-setup.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { ImportConfig, Modules } from '../types';
2-
import { backupHandler, log, setupBranchConfig } from '../utils';
3-
import { ContentstackClient } from '@contentstack/cli-utilities';
4-
import { validateBranch } from '../utils';
2+
import { backupHandler, setupBranchConfig, validateBranch } from '../utils';
3+
import { ContentstackClient, log, handleAndLogError } from '@contentstack/cli-utilities';
54

65
export default class ImportSetup {
76
protected config: ImportConfig;
@@ -64,8 +63,10 @@ export default class ImportSetup {
6463
* @returns {Promise<void>}
6564
*/
6665
protected async runModuleImports() {
66+
log.debug('Starting module imports', { modules: Object.keys(this.dependencyTree) });
6767
for (const moduleName in this.dependencyTree) {
6868
try {
69+
log.debug(`Importing module: ${moduleName}`, { moduleName, dependencies: this.dependencyTree[moduleName] });
6970
const modulePath = `./modules/${moduleName}`;
7071
const { default: ModuleClass } = await import(modulePath);
7172

@@ -77,11 +78,13 @@ export default class ImportSetup {
7778

7879
const moduleInstance = new ModuleClass(modulePayload);
7980
await moduleInstance.start();
81+
log.debug(`Module ${moduleName} imported successfully`);
8082
} catch (error) {
81-
log(this.config, `Error occurred while importing '${moduleName}'`, 'error');
83+
handleAndLogError(error, { ...this.config.context, moduleName }, `Error occurred while importing '${moduleName}'`);
8284
throw error;
8385
}
8486
}
87+
log.debug('All module imports completed');
8588
}
8689

8790
/**
@@ -98,16 +101,22 @@ export default class ImportSetup {
98101
this.config.org_uid = stackDetails.org_uid as string;
99102
}
100103

104+
log.debug('Creating backup directory');
101105
const backupDir = await backupHandler(this.config);
102106
if (backupDir) {
103107
this.config.backupDir = backupDir;
108+
log.debug('Backup directory created', { backupDir });
104109
}
110+
111+
log.debug('Setting up branch configuration');
105112
await setupBranchConfig(this.config, this.stackAPIClient);
113+
log.debug('Branch configuration completed', { branchName: this.config.branchName });
106114

107115
await this.generateDependencyTree();
108116
await this.runModuleImports();
117+
log.debug('Import setup process completed successfully');
109118
} catch (error) {
110-
console.log(error);
119+
handleAndLogError(error, { ...this.config.context }, 'Import setup failed');
111120
throw error;
112121
}
113122
}

packages/contentstack-import-setup/src/import/modules/assets.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as chalk from 'chalk';
2-
import { log, fsUtil } from '../../utils';
2+
import { fsUtil } from '../../utils';
33
import { join } from 'path';
44
import { AssetRecord, ImportConfig, ModuleClassParams } from '../../types';
55
import { isEmpty, orderBy, values } from 'lodash';
6-
import { formatError, FsUtility, sanitizePath } from '@contentstack/cli-utilities';
6+
import { FsUtility, sanitizePath, log, handleAndLogError } from '@contentstack/cli-utilities';
77
import BaseImportSetup from './base-setup';
88

99
export default class AssetImportSetup extends BaseImportSetup {
@@ -20,6 +20,7 @@ export default class AssetImportSetup extends BaseImportSetup {
2020

2121
constructor({ config, stackAPIClient, dependencies }: ModuleClassParams) {
2222
super({ config, stackAPIClient, dependencies });
23+
this.initializeContext('assets');
2324
this.assetsFolderPath = join(sanitizePath(this.config.contentDir), 'assets');
2425
this.assetsFilePath = join(sanitizePath(this.config.contentDir), 'assets', 'assets.json');
2526
this.assetsConfig = config.modules.assets;
@@ -40,10 +41,15 @@ export default class AssetImportSetup extends BaseImportSetup {
4041
async start() {
4142
try {
4243
fsUtil.makeDirectory(this.mapperDirPath);
44+
log.debug('Mapper directory created', { mapperDirPath: this.mapperDirPath });
4345
await this.fetchAndMapAssets();
44-
log(this.config, `The required setup files for the asset have been generated successfully.`, 'success');
46+
log.debug('Asset mapping completed', {
47+
mappedCount: Object.keys(this.assetUidMapper).length,
48+
duplicateCount: Object.keys(this.duplicateAssets).length
49+
});
50+
log.success(`The required setup files for the asset have been generated successfully.`);
4551
} catch (error) {
46-
log(this.config, `Error occurred while generating the asset mapper: ${formatError(error)}.`, 'error');
52+
handleAndLogError(error, { ...this.config.context }, 'Error occurred while generating the asset mapper');
4753
}
4854
}
4955

@@ -53,6 +59,7 @@ export default class AssetImportSetup extends BaseImportSetup {
5359
* @returns {Promise<void>} Promise<void>
5460
*/
5561
async fetchAndMapAssets(): Promise<void> {
62+
log.debug('Starting asset fetch and mapping', { assetsFolderPath: this.assetsFolderPath });
5663
const processName = 'mapping assets';
5764
const indexFileName = 'assets.json';
5865
const basePath = this.assetsFolderPath;
@@ -67,25 +74,24 @@ export default class AssetImportSetup extends BaseImportSetup {
6774
if (items.length === 1) {
6875
this.assetUidMapper[uid] = items[0].uid;
6976
this.assetUrlMapper[url] = items[0].url;
70-
log(this.config, `Mapped asset successfully: '${title}'`, 'info');
77+
log.info(`Mapped asset successfully: '${title}'`);
7178
} else if (items.length > 1) {
7279
this.duplicateAssets[uid] = items.map((asset: any) => {
7380
return { uid: asset.uid, title: asset.title, url: asset.url };
7481
});
75-
log(this.config, `Multiple assets found with the title '${title}'.`, 'info');
82+
log.info(`Multiple assets found with the title '${title}'.`);
7683
} else {
77-
log(this.config, `Asset with title '${title}' not found in the stack!`, 'info');
84+
log.info(`Asset with title '${title}' not found in the stack!`);
7885
}
7986
};
8087
const onReject = ({ error, apiData: { title } = undefined }: any) => {
81-
log(this.config, `Failed to map the asset '${title}'.`, 'error');
82-
log(this.config, formatError(error), 'error');
88+
handleAndLogError(error, { ...this.config.context }, `Failed to map the asset '${title}'`);
8389
};
8490

8591
/* eslint-disable @typescript-eslint/no-unused-vars, guard-for-in */
8692
for (const index in indexer) {
8793
const chunk = await fs.readChunkFiles.next().catch((error) => {
88-
log(this.config, error, 'error');
94+
log.error(String(error), { error });
8995
});
9096

9197
if (chunk) {
@@ -116,7 +122,7 @@ export default class AssetImportSetup extends BaseImportSetup {
116122
}
117123
if (!isEmpty(this.duplicateAssets)) {
118124
fsUtil.writeFile(this.duplicateAssetPath, this.duplicateAssets);
119-
log(this.config, `Duplicate asset files are stored at: ${this.duplicateAssetPath}.`, 'info');
125+
log.info(`Duplicate asset files are stored at: ${this.duplicateAssetPath}.`);
120126
}
121127
}
122128
}

packages/contentstack-import-setup/src/import/modules/base-setup.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { log, fsUtil } from '../../utils';
2-
import { ApiOptions, CustomPromiseHandler, EnvType, ImportConfig, ModuleClassParams } from '../../types';
1+
import { fsUtil } from '../../utils';
2+
import { ApiOptions, CustomPromiseHandler, EnvType, ImportConfig, ModuleClassParams, Modules } from '../../types';
33
import { chunk, entries, isEmpty, isEqual, last } from 'lodash';
4+
import { log, handleAndLogError } from '@contentstack/cli-utilities';
45

56
export default class BaseImportSetup {
67
public config: ImportConfig;
@@ -13,9 +14,22 @@ export default class BaseImportSetup {
1314
this.dependencies = dependencies;
1415
}
1516

17+
/**
18+
* Set the module name in context directly
19+
* @param module - Module name to set
20+
* @returns {void}
21+
*/
22+
protected initializeContext(module?: Modules): void {
23+
if (this.config.context && module) {
24+
this.config.context.module = module;
25+
}
26+
}
27+
1628
async setupDependencies() {
29+
log.debug('Setting up dependencies', { dependencies: this.dependencies });
1730
for (const moduleName of this.dependencies) {
1831
try {
32+
log.debug(`Importing dependency module: ${moduleName}`);
1933
const modulePath = `./${moduleName}`;
2034
const { default: ModuleClass } = await import(modulePath);
2135

@@ -26,8 +40,9 @@ export default class BaseImportSetup {
2640

2741
const moduleInstance = new ModuleClass(modulePayload);
2842
await moduleInstance.start();
43+
log.debug(`Dependency module ${moduleName} imported successfully`);
2944
} catch (error) {
30-
log(this.config, `Error importing '${moduleName}': ${error.message}`, 'error');
45+
handleAndLogError(error, { ...this.config.context }, `Error importing '${moduleName}'`);
3146
}
3247
}
3348
}
@@ -140,7 +155,7 @@ export default class BaseImportSetup {
140155
// info: Batch No. 20 of import assets is complete
141156
if (currentIndexer) batchMsg += `Current chunk processing is (${currentIndexer}/${indexerCount})`;
142157

143-
log(this.config, `Batch No. (${batchNo}/${totelBatches}) of ${processName} is complete`, 'success');
158+
log.success(`Batch No. (${batchNo}/${totelBatches}) of ${processName} is complete`);
144159
}
145160

146161
// if (this.config.modules.assets.displayExecutionTime) {
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
import * as chalk from 'chalk';
2-
import { log, fsUtil } from '../../utils';
2+
import { fsUtil } from '../../utils';
33
import { join } from 'path';
44
import { ImportConfig, ModuleClassParams } from '../../types';
55
import ExtensionImportSetup from './extensions';
66
import BaseImportSetup from './base-setup';
7+
import { log, handleAndLogError } from '@contentstack/cli-utilities';
78

89
export default class ContentTypesImportSetup extends BaseImportSetup {
910
constructor(options: ModuleClassParams) {
1011
super(options);
12+
this.initializeContext('content-types');
1113
}
1214

1315
async start() {
1416
try {
1517
await this.setupDependencies();
16-
log(this.config, `The required setup files for content types have been generated successfully.`, 'success');
18+
log.success(`The required setup files for content types have been generated successfully.`);
1719
} catch (error) {
18-
log(this.config, `Error occurred while generating the content type mapper: ${error.message}.`, 'error');
20+
handleAndLogError(error, { ...this.config.context }, 'Error occurred while generating the content type mapper');
1921
}
2022
}
2123
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
import { log } from '../../utils';
21
import { ModuleClassParams } from '../../types';
32
import BaseImportSetup from './base-setup';
3+
import { log, handleAndLogError } from '@contentstack/cli-utilities';
44

55
export default class EntriesImportSetup extends BaseImportSetup {
66
constructor(options: ModuleClassParams) {
77
super(options);
8+
this.initializeContext('entries');
89
}
910

1011
async start() {
1112
try {
1213
await this.setupDependencies();
13-
log(this.config, `The required setup files for entries have been generated successfully.`, 'success');
14+
log.success(`The required setup files for entries have been generated successfully.`);
1415
} catch (error) {
15-
log(this.config, `Error occurred while generating the entry mapper: ${error.message}.`, 'error');
16+
handleAndLogError(error, { ...this.config.context }, 'Error occurred while generating the entry mapper');
1617
}
1718
}
1819
}

packages/contentstack-import-setup/src/import/modules/extensions.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as chalk from 'chalk';
2-
import { log, fsUtil } from '../../utils';
2+
import { fsUtil, fileHelper } from '../../utils';
33
import { join } from 'path';
44
import { ImportConfig, ModuleClassParams } from '../../types';
55
import { isEmpty } from 'lodash';
6-
import { formatError, sanitizePath } from '@contentstack/cli-utilities';
6+
import { formatError, sanitizePath, log, handleAndLogError } from '@contentstack/cli-utilities';
77

88
export default class ExtensionImportSetup {
99
private config: ImportConfig;
@@ -16,8 +16,11 @@ export default class ExtensionImportSetup {
1616
private extensionsFolderPath: string;
1717
private extUidMapperPath: string;
1818

19-
constructor({ config, stackAPIClient }: ModuleClassParams) {
19+
constructor({ config, stackAPIClient, dependencies }: ModuleClassParams) {
2020
this.config = config;
21+
if (this.config.context) {
22+
this.config.context.module = 'extensions';
23+
}
2124
this.stackAPIClient = stackAPIClient;
2225
this.extensionsFilePath = join(sanitizePath(this.config.contentDir), 'extensions', 'extensions.json');
2326
this.extensionsConfig = config.modules.extensions;
@@ -32,6 +35,10 @@ export default class ExtensionImportSetup {
3235
*/
3336
async start() {
3437
try {
38+
if (!fileHelper.fileExistsSync(this.extensionsFilePath)) {
39+
log.info('No extensions found in the content folder.');
40+
return;
41+
}
3542
const extensions: any = await fsUtil.readFile(this.extensionsFilePath);
3643
if (!isEmpty(extensions)) {
3744
// 2. Create mapper directory
@@ -41,20 +48,20 @@ export default class ExtensionImportSetup {
4148
for (const extension of Object.values(extensions) as any) {
4249
const targetExtension: any = await this.getExtension(extension);
4350
if (!targetExtension) {
44-
log(this.config, `Extension with the title '${extension.title}' not found in the stack.`, 'info');
51+
log.info(`Extension with the title '${extension.title}' not found in the stack.`);
4552
continue;
4653
}
4754
this.extensionMapper[extension.uid] = targetExtension.uid;
4855
}
4956

5057
await fsUtil.writeFile(this.extUidMapperPath, this.extensionMapper);
5158

52-
log(this.config, `The required setup files for extensions have been generated successfully.`, 'success');
59+
log.success(`The required setup files for extensions have been generated successfully.`);
5360
} else {
54-
log(this.config, 'No extensions found in the content folder.', 'info');
61+
log.info('No extensions found in the content folder.');
5562
}
5663
} catch (error) {
57-
log(this.config, `Error occurred while generating the extension mapper: ${formatError(error)}.`, 'error');
64+
handleAndLogError(error, { ...this.config.context }, 'Error occurred while generating the extension mapper');
5865
}
5966
}
6067

0 commit comments

Comments
 (0)