@contentstack/cli-cm-import-setup 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/commands/cm/stacks/import-setup.d.ts +1 -0
- package/lib/commands/cm/stacks/import-setup.js +20 -3
- package/lib/config/index.js +6 -1
- package/lib/import/import-setup.js +12 -2
- package/lib/import/modules/assets.js +15 -9
- package/lib/import/modules/base-setup.d.ts +7 -1
- package/lib/import/modules/base-setup.js +16 -3
- package/lib/import/modules/content-types.js +4 -3
- package/lib/import/modules/entries.js +4 -3
- package/lib/import/modules/extensions.d.ts +1 -1
- package/lib/import/modules/extensions.js +12 -5
- package/lib/import/modules/global-fields.js +4 -3
- package/lib/import/modules/marketplace-apps.d.ts +1 -1
- package/lib/import/modules/marketplace-apps.js +12 -5
- package/lib/import/modules/taxonomies.d.ts +35 -4
- package/lib/import/modules/taxonomies.js +168 -29
- package/lib/types/default-config.d.ts +5 -0
- package/lib/types/import-config.d.ts +2 -1
- package/lib/types/index.d.ts +11 -0
- package/lib/utils/common-helper.js +4 -4
- package/lib/utils/file-helper.js +1 -1
- package/lib/utils/import-config-handler.js +1 -1
- package/lib/utils/login-handler.js +3 -4
- package/lib/utils/setup-branch.js +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import-setup
|
|
|
47
47
|
$ csdx COMMAND
|
|
48
48
|
running command...
|
|
49
49
|
$ csdx (--version)
|
|
50
|
-
@contentstack/cli-cm-import-setup/1.
|
|
50
|
+
@contentstack/cli-cm-import-setup/1.7.1 linux-x64 node-v22.21.1
|
|
51
51
|
$ csdx --help [COMMAND]
|
|
52
52
|
USAGE
|
|
53
53
|
$ csdx COMMAND
|
|
@@ -11,6 +11,9 @@ class ImportSetupCommand extends cli_command_1.Command {
|
|
|
11
11
|
try {
|
|
12
12
|
const { flags } = await this.parse(ImportSetupCommand);
|
|
13
13
|
let importSetupConfig = await (0, utils_1.setupImportConfig)(flags);
|
|
14
|
+
// Prepare the context object
|
|
15
|
+
const context = this.createImportSetupContext(importSetupConfig.apiKey, importSetupConfig.authenticationMethod);
|
|
16
|
+
importSetupConfig.context = Object.assign({}, context);
|
|
14
17
|
// Note setting host to create cma client
|
|
15
18
|
importSetupConfig.host = this.cmaHost;
|
|
16
19
|
importSetupConfig.region = this.region;
|
|
@@ -18,13 +21,27 @@ class ImportSetupCommand extends cli_command_1.Command {
|
|
|
18
21
|
const managementAPIClient = await (0, cli_utilities_1.managementSDKClient)(importSetupConfig);
|
|
19
22
|
const importSetup = new import_1.ImportSetup(importSetupConfig, managementAPIClient);
|
|
20
23
|
await importSetup.start();
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
cli_utilities_1.log.success(`Backup folder and mapper files have been successfully created for the stack using the API key ${importSetupConfig.apiKey}.`, importSetupConfig.context);
|
|
25
|
+
cli_utilities_1.log.success(`The backup folder has been created at '${(0, cli_utilities_1.pathValidator)(node_path_1.default.join(importSetupConfig.backupDir))}'.`, importSetupConfig.context);
|
|
23
26
|
}
|
|
24
27
|
catch (error) {
|
|
25
|
-
(0,
|
|
28
|
+
(0, cli_utilities_1.handleAndLogError)(error);
|
|
26
29
|
}
|
|
27
30
|
}
|
|
31
|
+
// Create import setup context object
|
|
32
|
+
createImportSetupContext(apiKey, authenticationMethod, module) {
|
|
33
|
+
var _a, _b, _c;
|
|
34
|
+
return {
|
|
35
|
+
command: ((_b = (_a = this.context) === null || _a === void 0 ? void 0 : _a.info) === null || _b === void 0 ? void 0 : _b.command) || 'cm:stacks:import-setup',
|
|
36
|
+
module: module || '',
|
|
37
|
+
userId: cli_utilities_1.configHandler.get('userUid') || undefined,
|
|
38
|
+
email: cli_utilities_1.configHandler.get('email') || undefined,
|
|
39
|
+
sessionId: (_c = this.context) === null || _c === void 0 ? void 0 : _c.sessionId,
|
|
40
|
+
apiKey: apiKey || '',
|
|
41
|
+
orgId: cli_utilities_1.configHandler.get('oauthOrgUid') || '',
|
|
42
|
+
authenticationMethod: authenticationMethod || 'Basic Auth',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
28
45
|
}
|
|
29
46
|
exports.default = ImportSetupCommand;
|
|
30
47
|
ImportSetupCommand.description = cli_utilities_1.messageHandler.parse('Helps to generate mappers and backup folder for importing (overwriting) specific modules');
|
package/lib/config/index.js
CHANGED
|
@@ -22,6 +22,11 @@ const config = {
|
|
|
22
22
|
fileName: 'custom-roles.json',
|
|
23
23
|
dependencies: ['environments', 'entries'],
|
|
24
24
|
},
|
|
25
|
+
locales: {
|
|
26
|
+
dirName: 'locales',
|
|
27
|
+
fileName: 'locales.json',
|
|
28
|
+
dependencies: [],
|
|
29
|
+
},
|
|
25
30
|
environments: {
|
|
26
31
|
dirName: 'environments',
|
|
27
32
|
fileName: 'environments.json',
|
|
@@ -43,7 +48,7 @@ const config = {
|
|
|
43
48
|
entries: {
|
|
44
49
|
dirName: 'entries',
|
|
45
50
|
fileName: 'entries.json',
|
|
46
|
-
dependencies: ['assets', 'marketplace-apps', 'taxonomies'],
|
|
51
|
+
dependencies: ['assets', 'extensions', 'marketplace-apps', 'taxonomies'],
|
|
47
52
|
},
|
|
48
53
|
'global-fields': {
|
|
49
54
|
dirName: 'global_fields',
|
|
@@ -24,6 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
const utils_1 = require("../utils");
|
|
27
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
27
28
|
class ImportSetup {
|
|
28
29
|
constructor(config, managementAPIClient) {
|
|
29
30
|
this.dependencyTree = {};
|
|
@@ -71,8 +72,10 @@ class ImportSetup {
|
|
|
71
72
|
*/
|
|
72
73
|
async runModuleImports() {
|
|
73
74
|
var _a;
|
|
75
|
+
cli_utilities_1.log.debug('Starting module imports', { modules: Object.keys(this.dependencyTree) });
|
|
74
76
|
for (const moduleName in this.dependencyTree) {
|
|
75
77
|
try {
|
|
78
|
+
cli_utilities_1.log.debug(`Importing module: ${moduleName}`, { moduleName, dependencies: this.dependencyTree[moduleName] });
|
|
76
79
|
const modulePath = `./modules/${moduleName}`;
|
|
77
80
|
const { default: ModuleClass } = await (_a = modulePath, Promise.resolve().then(() => __importStar(require(_a))));
|
|
78
81
|
const modulePayload = {
|
|
@@ -82,12 +85,14 @@ class ImportSetup {
|
|
|
82
85
|
};
|
|
83
86
|
const moduleInstance = new ModuleClass(modulePayload);
|
|
84
87
|
await moduleInstance.start();
|
|
88
|
+
cli_utilities_1.log.debug(`Module ${moduleName} imported successfully`);
|
|
85
89
|
}
|
|
86
90
|
catch (error) {
|
|
87
|
-
(0,
|
|
91
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.config.context), { moduleName }), `Error occurred while importing '${moduleName}'`);
|
|
88
92
|
throw error;
|
|
89
93
|
}
|
|
90
94
|
}
|
|
95
|
+
cli_utilities_1.log.debug('All module imports completed');
|
|
91
96
|
}
|
|
92
97
|
/**
|
|
93
98
|
* Start the import setup process
|
|
@@ -102,16 +107,21 @@ class ImportSetup {
|
|
|
102
107
|
this.config.stackName = stackDetails.name;
|
|
103
108
|
this.config.org_uid = stackDetails.org_uid;
|
|
104
109
|
}
|
|
110
|
+
cli_utilities_1.log.debug('Creating backup directory');
|
|
105
111
|
const backupDir = await (0, utils_1.backupHandler)(this.config);
|
|
106
112
|
if (backupDir) {
|
|
107
113
|
this.config.backupDir = backupDir;
|
|
114
|
+
cli_utilities_1.log.debug('Backup directory created', { backupDir });
|
|
108
115
|
}
|
|
116
|
+
cli_utilities_1.log.debug('Setting up branch configuration');
|
|
109
117
|
await (0, utils_1.setupBranchConfig)(this.config, this.stackAPIClient);
|
|
118
|
+
cli_utilities_1.log.debug('Branch configuration completed', { branchName: this.config.branchName });
|
|
110
119
|
await this.generateDependencyTree();
|
|
111
120
|
await this.runModuleImports();
|
|
121
|
+
cli_utilities_1.log.debug('Import setup process completed successfully');
|
|
112
122
|
}
|
|
113
123
|
catch (error) {
|
|
114
|
-
|
|
124
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Import setup failed');
|
|
115
125
|
throw error;
|
|
116
126
|
}
|
|
117
127
|
}
|
|
@@ -9,6 +9,7 @@ const base_setup_1 = tslib_1.__importDefault(require("./base-setup"));
|
|
|
9
9
|
class AssetImportSetup extends base_setup_1.default {
|
|
10
10
|
constructor({ config, stackAPIClient, dependencies }) {
|
|
11
11
|
super({ config, stackAPIClient, dependencies });
|
|
12
|
+
this.initializeContext('assets');
|
|
12
13
|
this.assetsFolderPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'assets');
|
|
13
14
|
this.assetsFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'assets', 'assets.json');
|
|
14
15
|
this.assetsConfig = config.modules.assets;
|
|
@@ -28,11 +29,16 @@ class AssetImportSetup extends base_setup_1.default {
|
|
|
28
29
|
async start() {
|
|
29
30
|
try {
|
|
30
31
|
utils_1.fsUtil.makeDirectory(this.mapperDirPath);
|
|
32
|
+
cli_utilities_1.log.debug('Mapper directory created', { mapperDirPath: this.mapperDirPath });
|
|
31
33
|
await this.fetchAndMapAssets();
|
|
32
|
-
|
|
34
|
+
cli_utilities_1.log.debug('Asset mapping completed', {
|
|
35
|
+
mappedCount: Object.keys(this.assetUidMapper).length,
|
|
36
|
+
duplicateCount: Object.keys(this.duplicateAssets).length
|
|
37
|
+
});
|
|
38
|
+
cli_utilities_1.log.success(`The required setup files for the asset have been generated successfully.`);
|
|
33
39
|
}
|
|
34
40
|
catch (error) {
|
|
35
|
-
(0,
|
|
41
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Error occurred while generating the asset mapper');
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
44
|
/**
|
|
@@ -41,6 +47,7 @@ class AssetImportSetup extends base_setup_1.default {
|
|
|
41
47
|
* @returns {Promise<void>} Promise<void>
|
|
42
48
|
*/
|
|
43
49
|
async fetchAndMapAssets() {
|
|
50
|
+
cli_utilities_1.log.debug('Starting asset fetch and mapping', { assetsFolderPath: this.assetsFolderPath });
|
|
44
51
|
const processName = 'mapping assets';
|
|
45
52
|
const indexFileName = 'assets.json';
|
|
46
53
|
const basePath = this.assetsFolderPath;
|
|
@@ -51,26 +58,25 @@ class AssetImportSetup extends base_setup_1.default {
|
|
|
51
58
|
if (items.length === 1) {
|
|
52
59
|
this.assetUidMapper[uid] = items[0].uid;
|
|
53
60
|
this.assetUrlMapper[url] = items[0].url;
|
|
54
|
-
|
|
61
|
+
cli_utilities_1.log.info(`Mapped asset successfully: '${title}'`);
|
|
55
62
|
}
|
|
56
63
|
else if (items.length > 1) {
|
|
57
64
|
this.duplicateAssets[uid] = items.map((asset) => {
|
|
58
65
|
return { uid: asset.uid, title: asset.title, url: asset.url };
|
|
59
66
|
});
|
|
60
|
-
|
|
67
|
+
cli_utilities_1.log.info(`Multiple assets found with the title '${title}'.`);
|
|
61
68
|
}
|
|
62
69
|
else {
|
|
63
|
-
|
|
70
|
+
cli_utilities_1.log.info(`Asset with title '${title}' not found in the stack!`);
|
|
64
71
|
}
|
|
65
72
|
};
|
|
66
73
|
const onReject = ({ error, apiData: { title } = undefined }) => {
|
|
67
|
-
(0,
|
|
68
|
-
(0, utils_1.log)(this.config, (0, cli_utilities_1.formatError)(error), 'error');
|
|
74
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), `Failed to map the asset '${title}'`);
|
|
69
75
|
};
|
|
70
76
|
/* eslint-disable @typescript-eslint/no-unused-vars, guard-for-in */
|
|
71
77
|
for (const index in indexer) {
|
|
72
78
|
const chunk = await fs.readChunkFiles.next().catch((error) => {
|
|
73
|
-
|
|
79
|
+
cli_utilities_1.log.error(String(error), { error });
|
|
74
80
|
});
|
|
75
81
|
if (chunk) {
|
|
76
82
|
let apiContent = (0, lodash_1.orderBy)((0, lodash_1.values)(chunk), '_version');
|
|
@@ -95,7 +101,7 @@ class AssetImportSetup extends base_setup_1.default {
|
|
|
95
101
|
}
|
|
96
102
|
if (!(0, lodash_1.isEmpty)(this.duplicateAssets)) {
|
|
97
103
|
utils_1.fsUtil.writeFile(this.duplicateAssetPath, this.duplicateAssets);
|
|
98
|
-
|
|
104
|
+
cli_utilities_1.log.info(`Duplicate asset files are stored at: ${this.duplicateAssetPath}.`);
|
|
99
105
|
}
|
|
100
106
|
}
|
|
101
107
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { ApiOptions, CustomPromiseHandler, EnvType, ImportConfig, ModuleClassParams } from '../../types';
|
|
1
|
+
import { ApiOptions, CustomPromiseHandler, EnvType, ImportConfig, ModuleClassParams, Modules } from '../../types';
|
|
2
2
|
export default class BaseImportSetup {
|
|
3
3
|
config: ImportConfig;
|
|
4
4
|
stackAPIClient: ModuleClassParams['stackAPIClient'];
|
|
5
5
|
dependencies: ModuleClassParams['dependencies'];
|
|
6
6
|
constructor({ config, stackAPIClient, dependencies }: ModuleClassParams);
|
|
7
|
+
/**
|
|
8
|
+
* Set the module name in context directly
|
|
9
|
+
* @param module - Module name to set
|
|
10
|
+
* @returns {void}
|
|
11
|
+
*/
|
|
12
|
+
protected initializeContext(module?: Modules): void;
|
|
7
13
|
setupDependencies(): Promise<void>;
|
|
8
14
|
/**
|
|
9
15
|
* @method delay
|
|
@@ -23,18 +23,30 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
const utils_1 = require("../../utils");
|
|
27
26
|
const lodash_1 = require("lodash");
|
|
27
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
28
28
|
class BaseImportSetup {
|
|
29
29
|
constructor({ config, stackAPIClient, dependencies }) {
|
|
30
30
|
this.config = config;
|
|
31
31
|
this.stackAPIClient = stackAPIClient;
|
|
32
32
|
this.dependencies = dependencies;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Set the module name in context directly
|
|
36
|
+
* @param module - Module name to set
|
|
37
|
+
* @returns {void}
|
|
38
|
+
*/
|
|
39
|
+
initializeContext(module) {
|
|
40
|
+
if (this.config.context && module) {
|
|
41
|
+
this.config.context.module = module;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
34
44
|
async setupDependencies() {
|
|
35
45
|
var _a;
|
|
46
|
+
cli_utilities_1.log.debug('Setting up dependencies', { dependencies: this.dependencies });
|
|
36
47
|
for (const moduleName of this.dependencies) {
|
|
37
48
|
try {
|
|
49
|
+
cli_utilities_1.log.debug(`Importing dependency module: ${moduleName}`);
|
|
38
50
|
const modulePath = `./${moduleName}`;
|
|
39
51
|
const { default: ModuleClass } = await (_a = modulePath, Promise.resolve().then(() => __importStar(require(_a))));
|
|
40
52
|
const modulePayload = {
|
|
@@ -43,9 +55,10 @@ class BaseImportSetup {
|
|
|
43
55
|
};
|
|
44
56
|
const moduleInstance = new ModuleClass(modulePayload);
|
|
45
57
|
await moduleInstance.start();
|
|
58
|
+
cli_utilities_1.log.debug(`Dependency module ${moduleName} imported successfully`);
|
|
46
59
|
}
|
|
47
60
|
catch (error) {
|
|
48
|
-
(0,
|
|
61
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), `Error importing '${moduleName}'`);
|
|
49
62
|
}
|
|
50
63
|
}
|
|
51
64
|
}
|
|
@@ -121,7 +134,7 @@ class BaseImportSetup {
|
|
|
121
134
|
// info: Batch No. 20 of import assets is complete
|
|
122
135
|
if (currentIndexer)
|
|
123
136
|
batchMsg += `Current chunk processing is (${currentIndexer}/${indexerCount})`;
|
|
124
|
-
|
|
137
|
+
cli_utilities_1.log.success(`Batch No. (${batchNo}/${totelBatches}) of ${processName} is complete`);
|
|
125
138
|
}
|
|
126
139
|
// if (this.config.modules.assets.displayExecutionTime) {
|
|
127
140
|
// console.log(
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const utils_1 = require("../../utils");
|
|
5
4
|
const base_setup_1 = tslib_1.__importDefault(require("./base-setup"));
|
|
5
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
6
|
class ContentTypesImportSetup extends base_setup_1.default {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
super(options);
|
|
9
|
+
this.initializeContext('content-types');
|
|
9
10
|
}
|
|
10
11
|
async start() {
|
|
11
12
|
try {
|
|
12
13
|
await this.setupDependencies();
|
|
13
|
-
|
|
14
|
+
cli_utilities_1.log.success(`The required setup files for content types have been generated successfully.`);
|
|
14
15
|
}
|
|
15
16
|
catch (error) {
|
|
16
|
-
(0,
|
|
17
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Error occurred while generating the content type mapper');
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const utils_1 = require("../../utils");
|
|
5
4
|
const base_setup_1 = tslib_1.__importDefault(require("./base-setup"));
|
|
5
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
6
|
class EntriesImportSetup extends base_setup_1.default {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
super(options);
|
|
9
|
+
this.initializeContext('entries');
|
|
9
10
|
}
|
|
10
11
|
async start() {
|
|
11
12
|
try {
|
|
12
13
|
await this.setupDependencies();
|
|
13
|
-
|
|
14
|
+
cli_utilities_1.log.success(`The required setup files for entries have been generated successfully.`);
|
|
14
15
|
}
|
|
15
16
|
catch (error) {
|
|
16
|
-
(0,
|
|
17
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Error occurred while generating the entry mapper');
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -9,7 +9,7 @@ export default class ExtensionImportSetup {
|
|
|
9
9
|
private mapperDirPath;
|
|
10
10
|
private extensionsFolderPath;
|
|
11
11
|
private extUidMapperPath;
|
|
12
|
-
constructor({ config, stackAPIClient }: ModuleClassParams);
|
|
12
|
+
constructor({ config, stackAPIClient, dependencies }: ModuleClassParams);
|
|
13
13
|
/**
|
|
14
14
|
* Start the extension import setup
|
|
15
15
|
* This method reads the extensions from the content folder and generates a mapper file
|
|
@@ -5,8 +5,11 @@ const path_1 = require("path");
|
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
7
|
class ExtensionImportSetup {
|
|
8
|
-
constructor({ config, stackAPIClient }) {
|
|
8
|
+
constructor({ config, stackAPIClient, dependencies }) {
|
|
9
9
|
this.config = config;
|
|
10
|
+
if (this.config.context) {
|
|
11
|
+
this.config.context.module = 'extensions';
|
|
12
|
+
}
|
|
10
13
|
this.stackAPIClient = stackAPIClient;
|
|
11
14
|
this.extensionsFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'extensions', 'extensions.json');
|
|
12
15
|
this.extensionsConfig = config.modules.extensions;
|
|
@@ -20,6 +23,10 @@ class ExtensionImportSetup {
|
|
|
20
23
|
*/
|
|
21
24
|
async start() {
|
|
22
25
|
try {
|
|
26
|
+
if (!utils_1.fileHelper.fileExistsSync(this.extensionsFilePath)) {
|
|
27
|
+
cli_utilities_1.log.info('No extensions found in the content folder.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
23
30
|
const extensions = await utils_1.fsUtil.readFile(this.extensionsFilePath);
|
|
24
31
|
if (!(0, lodash_1.isEmpty)(extensions)) {
|
|
25
32
|
// 2. Create mapper directory
|
|
@@ -28,20 +35,20 @@ class ExtensionImportSetup {
|
|
|
28
35
|
for (const extension of Object.values(extensions)) {
|
|
29
36
|
const targetExtension = await this.getExtension(extension);
|
|
30
37
|
if (!targetExtension) {
|
|
31
|
-
|
|
38
|
+
cli_utilities_1.log.info(`Extension with the title '${extension.title}' not found in the stack.`);
|
|
32
39
|
continue;
|
|
33
40
|
}
|
|
34
41
|
this.extensionMapper[extension.uid] = targetExtension.uid;
|
|
35
42
|
}
|
|
36
43
|
await utils_1.fsUtil.writeFile(this.extUidMapperPath, this.extensionMapper);
|
|
37
|
-
|
|
44
|
+
cli_utilities_1.log.success(`The required setup files for extensions have been generated successfully.`);
|
|
38
45
|
}
|
|
39
46
|
else {
|
|
40
|
-
|
|
47
|
+
cli_utilities_1.log.info('No extensions found in the content folder.');
|
|
41
48
|
}
|
|
42
49
|
}
|
|
43
50
|
catch (error) {
|
|
44
|
-
(0,
|
|
51
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Error occurred while generating the extension mapper');
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
54
|
async getExtension(extension) {
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const utils_1 = require("../../utils");
|
|
5
4
|
const base_setup_1 = tslib_1.__importDefault(require("./base-setup"));
|
|
5
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
6
|
class GlobalFieldsImportSetup extends base_setup_1.default {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
super(options);
|
|
9
|
+
this.initializeContext('global-fields');
|
|
9
10
|
}
|
|
10
11
|
async start() {
|
|
11
12
|
try {
|
|
12
13
|
await this.setupDependencies();
|
|
13
|
-
|
|
14
|
+
cli_utilities_1.log.success(`The required setup files for global fields have been generated successfully.`);
|
|
14
15
|
}
|
|
15
16
|
catch (error) {
|
|
16
|
-
(0,
|
|
17
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Error occurred while generating the global field mapper');
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -14,7 +14,7 @@ export default class marketplaceAppImportSetup {
|
|
|
14
14
|
marketplaceAppPath: string;
|
|
15
15
|
nodeCrypto: NodeCrypto;
|
|
16
16
|
appSdk: ContentstackMarketplaceClient;
|
|
17
|
-
constructor({ config, stackAPIClient }: ModuleClassParams);
|
|
17
|
+
constructor({ config, stackAPIClient, dependencies }: ModuleClassParams);
|
|
18
18
|
/**
|
|
19
19
|
* Start the marketplaceApp import setup
|
|
20
20
|
* This method reads the marketplaceApps from the content folder and generates a mapper file
|
|
@@ -5,8 +5,11 @@ const path_1 = require("path");
|
|
|
5
5
|
const lodash_1 = require("lodash");
|
|
6
6
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
7
|
class marketplaceAppImportSetup {
|
|
8
|
-
constructor({ config, stackAPIClient }) {
|
|
8
|
+
constructor({ config, stackAPIClient, dependencies }) {
|
|
9
9
|
this.config = config;
|
|
10
|
+
if (this.config.context) {
|
|
11
|
+
this.config.context.module = 'marketplace-apps';
|
|
12
|
+
}
|
|
10
13
|
this.stackAPIClient = stackAPIClient;
|
|
11
14
|
this.marketplaceAppsFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'marketplace_apps', 'marketplace_apps.json');
|
|
12
15
|
this.marketplaceAppsConfig = config.modules['marketplace-apps'];
|
|
@@ -20,6 +23,10 @@ class marketplaceAppImportSetup {
|
|
|
20
23
|
*/
|
|
21
24
|
async start() {
|
|
22
25
|
try {
|
|
26
|
+
if (!utils_1.fileHelper.fileExistsSync(this.marketplaceAppsFilePath)) {
|
|
27
|
+
cli_utilities_1.log.info('No Marketplace apps found in the content folder.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
23
30
|
const sourceMarketplaceApps = await utils_1.fsUtil.readFile(this.marketplaceAppsFilePath);
|
|
24
31
|
if (!(0, lodash_1.isEmpty)(sourceMarketplaceApps)) {
|
|
25
32
|
utils_1.fsUtil.makeDirectory(this.marketplaceAppsUidMapperPath); // Use fsUtil
|
|
@@ -30,14 +37,14 @@ class marketplaceAppImportSetup {
|
|
|
30
37
|
const targetMarketplaceApps = await this.getMarketplaceApps();
|
|
31
38
|
this.createMapper(sourceMarketplaceApps, targetMarketplaceApps);
|
|
32
39
|
await utils_1.fsUtil.writeFile((0, path_1.join)(this.marketplaceAppsUidMapperPath, 'uid-mapping.json'), this.marketplaceAppMapper);
|
|
33
|
-
|
|
40
|
+
cli_utilities_1.log.success(`The required setup files for Marketplace apps have been generated successfully.`);
|
|
34
41
|
}
|
|
35
42
|
else {
|
|
36
|
-
|
|
43
|
+
cli_utilities_1.log.info('No Marketplace apps found in the content folder.');
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
46
|
catch (error) {
|
|
40
|
-
(0,
|
|
47
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Error occurred while generating the Marketplace app mapper');
|
|
41
48
|
}
|
|
42
49
|
}
|
|
43
50
|
async getMarketplaceApps() {
|
|
@@ -81,7 +88,7 @@ class marketplaceAppImportSetup {
|
|
|
81
88
|
});
|
|
82
89
|
}
|
|
83
90
|
else {
|
|
84
|
-
|
|
91
|
+
cli_utilities_1.log.info(`No matching Marketplace app found in the target stack with name ${sourceAppName}`);
|
|
85
92
|
}
|
|
86
93
|
});
|
|
87
94
|
}
|
|
@@ -3,6 +3,7 @@ import { ModuleClassParams } from '../../types';
|
|
|
3
3
|
export default class TaxonomiesImportSetup {
|
|
4
4
|
private config;
|
|
5
5
|
private taxonomiesFilePath;
|
|
6
|
+
private taxonomiesFolderPath;
|
|
6
7
|
private stackAPIClient;
|
|
7
8
|
private dependencies;
|
|
8
9
|
private taxonomiesConfig;
|
|
@@ -10,22 +11,51 @@ export default class TaxonomiesImportSetup {
|
|
|
10
11
|
private taxSuccessPath;
|
|
11
12
|
private taxonomiesMapperDirPath;
|
|
12
13
|
private termsMapperDirPath;
|
|
14
|
+
private localesFilePath;
|
|
15
|
+
private isLocaleBasedStructure;
|
|
13
16
|
taxonomiesMapper: Record<string, unknown>;
|
|
14
17
|
termsMapper: Record<string, unknown>;
|
|
15
|
-
|
|
18
|
+
masterLocaleFilePath: string;
|
|
19
|
+
constructor({ config, stackAPIClient, dependencies }: ModuleClassParams);
|
|
16
20
|
/**
|
|
17
21
|
* Start the taxonomies import setup
|
|
18
22
|
* This method reads the taxonomies from the content folder and generates a mapper file
|
|
19
23
|
* @returns {Promise<void>}
|
|
20
24
|
*/
|
|
21
25
|
start(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Setup taxonomies using legacy format (root-level taxonomy files)
|
|
28
|
+
*/
|
|
29
|
+
setupTaxonomiesLegacy(taxonomies: any): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Setup taxonomies using locale-based format (taxonomies organized by locale)
|
|
32
|
+
* For locale-based structure, we query the target stack for each taxonomy+locale combination
|
|
33
|
+
*/
|
|
34
|
+
setupTaxonomiesByLocale(taxonomies: any): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Detect if locale-based folder structure exists
|
|
37
|
+
* @returns {boolean} true if locale-based structure detected, false otherwise
|
|
38
|
+
*/
|
|
39
|
+
detectLocaleBasedStructure(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Get the master locale code
|
|
42
|
+
* First tries to read from master-locale.json, then falls back to config, then 'en-us'
|
|
43
|
+
* @returns {string} The master locale code
|
|
44
|
+
*/
|
|
45
|
+
getMasterLocaleCode(): string;
|
|
46
|
+
/**
|
|
47
|
+
* Load available locales from locales file
|
|
48
|
+
* @returns {Record<string, string>} Map of locale codes
|
|
49
|
+
*/
|
|
50
|
+
loadAvailableLocales(): Record<string, string>;
|
|
22
51
|
/**
|
|
23
52
|
* Retrieves the taxonomies based on the provided taxonomy UID.
|
|
24
53
|
*
|
|
25
54
|
* @param taxonomy - The UID of the taxonomy to retrieve.
|
|
55
|
+
* @param locale - Optional locale code to query taxonomy in specific locale
|
|
26
56
|
* @returns A promise that resolves to the retrieved taxonomies.
|
|
27
57
|
*/
|
|
28
|
-
getTaxonomies(taxonomy: any): Promise<any>;
|
|
58
|
+
getTaxonomies(taxonomy: any, locale?: string): Promise<any>;
|
|
29
59
|
/**
|
|
30
60
|
* Sanitizes the attributes of a taxonomy object.
|
|
31
61
|
*
|
|
@@ -37,11 +67,12 @@ export default class TaxonomiesImportSetup {
|
|
|
37
67
|
* Retrieves all terms of a taxonomy.
|
|
38
68
|
*
|
|
39
69
|
* @param taxonomy - The taxonomy object.
|
|
70
|
+
* @param locale - Optional locale code to query terms in specific locale
|
|
40
71
|
* @param skip - The number of terms to skip (default: 0).
|
|
41
72
|
* @param terms - An array to store the retrieved terms (default: []).
|
|
42
73
|
* @returns A promise that resolves to an array of terms.
|
|
43
74
|
*/
|
|
44
|
-
getAllTermsOfTaxonomy(taxonomy: any, skip?: number, terms?: any[]): Promise<any>;
|
|
75
|
+
getAllTermsOfTaxonomy(taxonomy: any, locale?: string, skip?: number, terms?: any[]): Promise<any>;
|
|
45
76
|
/**
|
|
46
77
|
* Sanitizes the attributes of the given terms.
|
|
47
78
|
*
|
|
@@ -49,5 +80,5 @@ export default class TaxonomiesImportSetup {
|
|
|
49
80
|
* @returns The sanitized terms.
|
|
50
81
|
*/
|
|
51
82
|
sanitizeTermsAttribs(terms: Record<string, unknown>[]): Record<string, unknown>[];
|
|
52
|
-
handleTaxonomyErrorMsg(err: any): void;
|
|
83
|
+
handleTaxonomyErrorMsg(err: any, taxonomyUid?: string, locale?: string): void;
|
|
53
84
|
}
|
|
@@ -7,17 +7,25 @@ const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
|
7
7
|
const utils_1 = require("../../utils");
|
|
8
8
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
9
9
|
class TaxonomiesImportSetup {
|
|
10
|
-
constructor({ config, stackAPIClient }) {
|
|
10
|
+
constructor({ config, stackAPIClient, dependencies }) {
|
|
11
|
+
var _a, _b, _c;
|
|
12
|
+
this.isLocaleBasedStructure = false;
|
|
11
13
|
this.taxonomiesMapper = {};
|
|
12
14
|
this.termsMapper = {};
|
|
13
15
|
this.config = config;
|
|
16
|
+
if (this.config.context) {
|
|
17
|
+
this.config.context.module = 'taxonomies';
|
|
18
|
+
}
|
|
14
19
|
this.stackAPIClient = stackAPIClient;
|
|
15
|
-
this.
|
|
20
|
+
this.taxonomiesFolderPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'taxonomies');
|
|
21
|
+
this.taxonomiesFilePath = (0, path_1.join)(this.taxonomiesFolderPath, 'taxonomies.json');
|
|
16
22
|
this.taxonomiesConfig = config.modules.taxonomies;
|
|
17
23
|
this.taxonomiesMapperDirPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', 'taxonomies');
|
|
18
24
|
this.taxSuccessPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.taxonomiesMapperDirPath), 'success.json');
|
|
19
25
|
this.termsMapperDirPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.taxonomiesMapperDirPath), 'terms');
|
|
20
26
|
this.termsSuccessPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.termsMapperDirPath), 'success.json');
|
|
27
|
+
this.localesFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), ((_a = config.modules.locales) === null || _a === void 0 ? void 0 : _a.dirName) || 'locales', ((_b = config.modules.locales) === null || _b === void 0 ? void 0 : _b.fileName) || 'locales.json');
|
|
28
|
+
this.masterLocaleFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), ((_c = config.modules.locales) === null || _c === void 0 ? void 0 : _c.dirName) || 'locales', 'master-locale.json');
|
|
21
29
|
this.taxonomiesMapper = {};
|
|
22
30
|
this.termsMapper = {};
|
|
23
31
|
}
|
|
@@ -30,20 +38,18 @@ class TaxonomiesImportSetup {
|
|
|
30
38
|
try {
|
|
31
39
|
const taxonomies = utils_1.fsUtil.readFile(this.taxonomiesFilePath);
|
|
32
40
|
if (!(0, isEmpty_1.default)(taxonomies)) {
|
|
41
|
+
// 1. Detect locale-based structure
|
|
42
|
+
this.isLocaleBasedStructure = this.detectLocaleBasedStructure();
|
|
33
43
|
// 2. Create mapper directory
|
|
34
44
|
utils_1.fsUtil.makeDirectory(this.taxonomiesMapperDirPath);
|
|
35
45
|
utils_1.fsUtil.makeDirectory(this.termsMapperDirPath);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.taxonomiesMapper[taxonomy.uid] = targetTaxonomy;
|
|
44
|
-
const terms = await this.getAllTermsOfTaxonomy(targetTaxonomy);
|
|
45
|
-
const sanitizedTerms = this.sanitizeTermsAttribs(terms);
|
|
46
|
-
this.termsMapper[taxonomy.uid] = sanitizedTerms;
|
|
46
|
+
if (this.isLocaleBasedStructure) {
|
|
47
|
+
cli_utilities_1.log.info('Detected locale-based folder structure for taxonomies');
|
|
48
|
+
await this.setupTaxonomiesByLocale(taxonomies);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
cli_utilities_1.log.info('Using legacy folder structure for taxonomies');
|
|
52
|
+
await this.setupTaxonomiesLegacy(taxonomies);
|
|
47
53
|
}
|
|
48
54
|
if (this.taxonomiesMapper !== undefined && !(0, isEmpty_1.default)(this.taxonomiesMapper)) {
|
|
49
55
|
utils_1.fsUtil.writeFile(this.taxSuccessPath, this.taxonomiesMapper);
|
|
@@ -51,28 +57,158 @@ class TaxonomiesImportSetup {
|
|
|
51
57
|
if (this.termsMapper !== undefined && !(0, isEmpty_1.default)(this.termsMapper)) {
|
|
52
58
|
utils_1.fsUtil.writeFile(this.termsSuccessPath, this.termsMapper);
|
|
53
59
|
}
|
|
54
|
-
|
|
60
|
+
cli_utilities_1.log.success(`The required setup files for taxonomies have been generated successfully.`);
|
|
55
61
|
}
|
|
56
62
|
else {
|
|
57
|
-
|
|
63
|
+
cli_utilities_1.log.info('No taxonomies found in the content folder.');
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
catch (error) {
|
|
61
|
-
(0,
|
|
67
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), 'Error generating taxonomies mapper');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Setup taxonomies using legacy format (root-level taxonomy files)
|
|
72
|
+
*/
|
|
73
|
+
async setupTaxonomiesLegacy(taxonomies) {
|
|
74
|
+
for (const taxonomy of Object.values(taxonomies)) {
|
|
75
|
+
let targetTaxonomy = await this.getTaxonomies(taxonomy);
|
|
76
|
+
if (!targetTaxonomy) {
|
|
77
|
+
cli_utilities_1.log.info(`Taxonomies with uid '${taxonomy.uid}' not found in the stack!`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
targetTaxonomy = this.sanitizeTaxonomyAttribs(targetTaxonomy);
|
|
81
|
+
this.taxonomiesMapper[taxonomy.uid] = targetTaxonomy;
|
|
82
|
+
const terms = await this.getAllTermsOfTaxonomy(targetTaxonomy);
|
|
83
|
+
if (Array.isArray(terms) && terms.length > 0) {
|
|
84
|
+
cli_utilities_1.log.info(`Terms found for taxonomy '${taxonomy.uid}', processing...`);
|
|
85
|
+
const sanitizedTerms = this.sanitizeTermsAttribs(terms);
|
|
86
|
+
this.termsMapper[taxonomy.uid] = sanitizedTerms;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
cli_utilities_1.log.info(`No terms found for taxonomy '${taxonomy.uid}', skipping...`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Setup taxonomies using locale-based format (taxonomies organized by locale)
|
|
95
|
+
* For locale-based structure, we query the target stack for each taxonomy+locale combination
|
|
96
|
+
*/
|
|
97
|
+
async setupTaxonomiesByLocale(taxonomies) {
|
|
98
|
+
const locales = this.loadAvailableLocales();
|
|
99
|
+
for (const localeCode of Object.keys(locales)) {
|
|
100
|
+
cli_utilities_1.log.info(`Processing taxonomies for locale: ${localeCode}`);
|
|
101
|
+
for (const taxonomy of Object.values(taxonomies)) {
|
|
102
|
+
// Query target stack for this taxonomy in this locale
|
|
103
|
+
let targetTaxonomy = await this.getTaxonomies(taxonomy, localeCode);
|
|
104
|
+
if (!targetTaxonomy) {
|
|
105
|
+
cli_utilities_1.log.info(`Taxonomy '${taxonomy.uid}' not found in target stack for locale: ${localeCode}`);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
targetTaxonomy = this.sanitizeTaxonomyAttribs(targetTaxonomy);
|
|
109
|
+
// Store with composite key: taxonomyUID_locale
|
|
110
|
+
// const mapperKey = `${taxonomy.uid}_${localeCode}`; // TODO: Unsure about this required or not
|
|
111
|
+
this.taxonomiesMapper[taxonomy.uid] = targetTaxonomy;
|
|
112
|
+
const terms = await this.getAllTermsOfTaxonomy(targetTaxonomy, localeCode);
|
|
113
|
+
if (Array.isArray(terms) && terms.length > 0) {
|
|
114
|
+
cli_utilities_1.log.info(`Terms found for taxonomy '${taxonomy.uid} for locale: ${localeCode}', processing...`);
|
|
115
|
+
const sanitizedTerms = this.sanitizeTermsAttribs(terms);
|
|
116
|
+
this.termsMapper[taxonomy.uid] = sanitizedTerms;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
cli_utilities_1.log.info(`No terms found for taxonomy '${taxonomy.uid} for locale: ${localeCode}', skipping...`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Detect if locale-based folder structure exists
|
|
126
|
+
* @returns {boolean} true if locale-based structure detected, false otherwise
|
|
127
|
+
*/
|
|
128
|
+
detectLocaleBasedStructure() {
|
|
129
|
+
const masterLocaleCode = this.getMasterLocaleCode();
|
|
130
|
+
const masterLocaleFolder = (0, path_1.join)(this.taxonomiesFolderPath, masterLocaleCode);
|
|
131
|
+
// Check if master locale folder exists (indicates new locale-based structure)
|
|
132
|
+
if (!utils_1.fileHelper.fileExistsSync(masterLocaleFolder)) {
|
|
133
|
+
cli_utilities_1.log.info('No locale-based folder structure detected');
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
cli_utilities_1.log.info('Locale-based folder structure detected');
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get the master locale code
|
|
141
|
+
* First tries to read from master-locale.json, then falls back to config, then 'en-us'
|
|
142
|
+
* @returns {string} The master locale code
|
|
143
|
+
*/
|
|
144
|
+
getMasterLocaleCode() {
|
|
145
|
+
var _a;
|
|
146
|
+
// Try to read from master-locale.json file
|
|
147
|
+
if (utils_1.fileHelper.fileExistsSync(this.masterLocaleFilePath)) {
|
|
148
|
+
try {
|
|
149
|
+
const masterLocaleData = utils_1.fsUtil.readFile(this.masterLocaleFilePath, true);
|
|
150
|
+
// The file contains an object with UID as key, extract the code
|
|
151
|
+
const firstLocale = Object.values(masterLocaleData)[0];
|
|
152
|
+
if (firstLocale === null || firstLocale === void 0 ? void 0 : firstLocale.code) {
|
|
153
|
+
cli_utilities_1.log.info(`Master locale loaded from file: ${firstLocale.code}`);
|
|
154
|
+
return firstLocale.code;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
cli_utilities_1.log.warn('Error reading master-locale.json, using fallback', { error });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Fallback to config or default
|
|
162
|
+
const fallbackCode = ((_a = this.config.master_locale) === null || _a === void 0 ? void 0 : _a.code) || 'en-us';
|
|
163
|
+
cli_utilities_1.log.info(`Using fallback master locale: ${fallbackCode}`);
|
|
164
|
+
return fallbackCode;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Load available locales from locales file
|
|
168
|
+
* @returns {Record<string, string>} Map of locale codes
|
|
169
|
+
*/
|
|
170
|
+
loadAvailableLocales() {
|
|
171
|
+
const locales = {};
|
|
172
|
+
// First, get the master locale
|
|
173
|
+
const masterLocaleCode = this.getMasterLocaleCode();
|
|
174
|
+
locales[masterLocaleCode] = masterLocaleCode;
|
|
175
|
+
// Then load additional locales from locales.json if it exists
|
|
176
|
+
if (!utils_1.fileHelper.fileExistsSync(this.localesFilePath)) {
|
|
177
|
+
cli_utilities_1.log.info('No locales file found, using only master locale');
|
|
178
|
+
return locales;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const localesData = utils_1.fsUtil.readFile(this.localesFilePath, true);
|
|
182
|
+
for (const [uid, locale] of Object.entries(localesData)) {
|
|
183
|
+
if (locale === null || locale === void 0 ? void 0 : locale.code) {
|
|
184
|
+
locales[locale.code] = locale.code;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
cli_utilities_1.log.info(`Loaded ${Object.keys(locales).length} locales (1 master + ${Object.keys(locales).length - 1} additional)`);
|
|
188
|
+
return locales;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
cli_utilities_1.log.error('Error loading locales file, using only master locale', { error });
|
|
192
|
+
return locales;
|
|
62
193
|
}
|
|
63
194
|
}
|
|
64
195
|
/**
|
|
65
196
|
* Retrieves the taxonomies based on the provided taxonomy UID.
|
|
66
197
|
*
|
|
67
198
|
* @param taxonomy - The UID of the taxonomy to retrieve.
|
|
199
|
+
* @param locale - Optional locale code to query taxonomy in specific locale
|
|
68
200
|
* @returns A promise that resolves to the retrieved taxonomies.
|
|
69
201
|
*/
|
|
70
|
-
async getTaxonomies(taxonomy) {
|
|
202
|
+
async getTaxonomies(taxonomy, locale) {
|
|
203
|
+
const query = {};
|
|
204
|
+
if (locale) {
|
|
205
|
+
query.locale = locale;
|
|
206
|
+
}
|
|
71
207
|
return await this.stackAPIClient
|
|
72
208
|
.taxonomy(taxonomy.uid)
|
|
73
|
-
.fetch()
|
|
209
|
+
.fetch(query)
|
|
74
210
|
.then((data) => data)
|
|
75
|
-
.catch((err) => this.handleTaxonomyErrorMsg(err));
|
|
211
|
+
.catch((err) => this.handleTaxonomyErrorMsg(err, taxonomy.uid, locale));
|
|
76
212
|
}
|
|
77
213
|
/**
|
|
78
214
|
* Sanitizes the attributes of a taxonomy object.
|
|
@@ -87,19 +223,21 @@ class TaxonomiesImportSetup {
|
|
|
87
223
|
* Retrieves all terms of a taxonomy.
|
|
88
224
|
*
|
|
89
225
|
* @param taxonomy - The taxonomy object.
|
|
226
|
+
* @param locale - Optional locale code to query terms in specific locale
|
|
90
227
|
* @param skip - The number of terms to skip (default: 0).
|
|
91
228
|
* @param terms - An array to store the retrieved terms (default: []).
|
|
92
229
|
* @returns A promise that resolves to an array of terms.
|
|
93
230
|
*/
|
|
94
|
-
async getAllTermsOfTaxonomy(taxonomy, skip = 0, terms = []) {
|
|
231
|
+
async getAllTermsOfTaxonomy(taxonomy, locale, skip = 0, terms = []) {
|
|
95
232
|
const queryParams = {
|
|
96
233
|
include_count: true,
|
|
97
234
|
limit: 100,
|
|
98
235
|
skip,
|
|
236
|
+
depth: 0,
|
|
99
237
|
};
|
|
100
|
-
if (
|
|
101
|
-
queryParams
|
|
102
|
-
|
|
238
|
+
if (locale) {
|
|
239
|
+
queryParams.locale = locale;
|
|
240
|
+
}
|
|
103
241
|
await this.stackAPIClient
|
|
104
242
|
.taxonomy(taxonomy.uid)
|
|
105
243
|
.terms()
|
|
@@ -108,10 +246,10 @@ class TaxonomiesImportSetup {
|
|
|
108
246
|
.then((data) => {
|
|
109
247
|
terms = terms.concat(data.items);
|
|
110
248
|
if (data.count >= skip + queryParams.limit) {
|
|
111
|
-
return this.getAllTermsOfTaxonomy(taxonomy, skip + 100, terms);
|
|
249
|
+
return this.getAllTermsOfTaxonomy(taxonomy, locale, skip + 100, terms);
|
|
112
250
|
}
|
|
113
251
|
})
|
|
114
|
-
.catch((err) => this.handleTaxonomyErrorMsg(err));
|
|
252
|
+
.catch((err) => this.handleTaxonomyErrorMsg(err, taxonomy.uid, locale));
|
|
115
253
|
return terms;
|
|
116
254
|
}
|
|
117
255
|
/**
|
|
@@ -126,15 +264,16 @@ class TaxonomiesImportSetup {
|
|
|
126
264
|
}
|
|
127
265
|
return terms;
|
|
128
266
|
}
|
|
129
|
-
handleTaxonomyErrorMsg(err) {
|
|
267
|
+
handleTaxonomyErrorMsg(err, taxonomyUid, locale) {
|
|
130
268
|
var _a, _b;
|
|
269
|
+
const context = locale ? ` for locale: ${locale}` : '';
|
|
270
|
+
const taxInfo = taxonomyUid ? ` (${taxonomyUid}${context})` : '';
|
|
131
271
|
if ((err === null || err === void 0 ? void 0 : err.errorMessage) || (err === null || err === void 0 ? void 0 : err.message)) {
|
|
132
272
|
const errorMsg = (err === null || err === void 0 ? void 0 : err.errorMessage) || ((_a = err === null || err === void 0 ? void 0 : err.errors) === null || _a === void 0 ? void 0 : _a.taxonomy) || ((_b = err === null || err === void 0 ? void 0 : err.errors) === null || _b === void 0 ? void 0 : _b.term) || (err === null || err === void 0 ? void 0 : err.message);
|
|
133
|
-
|
|
273
|
+
cli_utilities_1.log.error(`${errorMsg}${taxInfo}`, { error: err, taxonomyUid, locale });
|
|
134
274
|
}
|
|
135
275
|
else {
|
|
136
|
-
|
|
137
|
-
(0, utils_1.log)(this.config, err, 'error');
|
|
276
|
+
cli_utilities_1.log.error(`Error fetching taxonomy data${taxInfo}!`, { error: err, taxonomyUid, locale });
|
|
138
277
|
}
|
|
139
278
|
}
|
|
140
279
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Modules } from '.';
|
|
1
|
+
import { Modules, Context } from '.';
|
|
2
2
|
import DefaultConfig from './default-config';
|
|
3
3
|
export interface ExternalConfig {
|
|
4
4
|
source_stack?: string;
|
|
@@ -9,6 +9,7 @@ export interface ExternalConfig {
|
|
|
9
9
|
password?: string;
|
|
10
10
|
}
|
|
11
11
|
export default interface ImportConfig extends DefaultConfig, ExternalConfig {
|
|
12
|
+
context?: Context;
|
|
12
13
|
cliLogsPath?: string;
|
|
13
14
|
contentDir: string;
|
|
14
15
|
data: string;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -112,4 +112,15 @@ export type TaxonomyQueryParams = {
|
|
|
112
112
|
limit: number;
|
|
113
113
|
skip: number;
|
|
114
114
|
depth?: number;
|
|
115
|
+
locale?: string;
|
|
115
116
|
};
|
|
117
|
+
export interface Context {
|
|
118
|
+
command: string;
|
|
119
|
+
module: string;
|
|
120
|
+
userId: string | undefined;
|
|
121
|
+
email: string | undefined;
|
|
122
|
+
sessionId: string | undefined;
|
|
123
|
+
apiKey: string;
|
|
124
|
+
orgId: string;
|
|
125
|
+
authenticationMethod?: string;
|
|
126
|
+
}
|
|
@@ -3,15 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.validateBranch = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
-
const
|
|
6
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
7
|
const validateBranch = async (stackAPIClient, config, branch) => {
|
|
8
8
|
return new Promise(async (resolve, reject) => {
|
|
9
9
|
try {
|
|
10
10
|
const data = await stackAPIClient.branch(branch).fetch();
|
|
11
11
|
if (data && typeof data === 'object') {
|
|
12
12
|
if (data.error_message) {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
cli_utilities_1.log.error(chalk_1.default.red(data.error_message), { error: data.error_message });
|
|
14
|
+
cli_utilities_1.log.error(chalk_1.default.red('No branch found with the name ' + branch), { branch });
|
|
15
15
|
reject({ message: 'No branch found with the name ' + branch, error: data.error_message });
|
|
16
16
|
}
|
|
17
17
|
else {
|
|
@@ -23,7 +23,7 @@ const validateBranch = async (stackAPIClient, config, branch) => {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
|
-
|
|
26
|
+
cli_utilities_1.log.error(chalk_1.default.red('No branch found with the name ' + branch), { error, branch });
|
|
27
27
|
reject({ message: 'No branch found with the name ' + branch, error });
|
|
28
28
|
}
|
|
29
29
|
});
|
package/lib/utils/file-helper.js
CHANGED
|
@@ -58,7 +58,7 @@ const readLargeFile = function (filePath, opts) {
|
|
|
58
58
|
resolve(data);
|
|
59
59
|
});
|
|
60
60
|
parseStream.on('error', function (error) {
|
|
61
|
-
|
|
61
|
+
cli_utilities_1.log.error(`Error reading large file: ${error.message}`, { error, filePath });
|
|
62
62
|
reject(error);
|
|
63
63
|
});
|
|
64
64
|
readStream.pipe(parseStream);
|
|
@@ -23,7 +23,7 @@ const setupConfig = async (importCmdFlags) => {
|
|
|
23
23
|
config.contentDir = (0, cli_utilities_1.sanitizePath)(importCmdFlags['data'] || importCmdFlags['data-dir'] || config.data || (await (0, interactive_1.askContentDir)()));
|
|
24
24
|
const pattern = /[*$%#<>{}!&?]/g;
|
|
25
25
|
if (pattern.test(config.contentDir)) {
|
|
26
|
-
cli_utilities_1.cliux.print(`\nPlease
|
|
26
|
+
cli_utilities_1.cliux.print(`\nPlease enter a directory path without special characters: (*,&,{,},[,],$,%,<,>,?,!)`, {
|
|
27
27
|
color: 'yellow',
|
|
28
28
|
});
|
|
29
29
|
config.contentDir = (0, cli_utilities_1.sanitizePath)(await (0, interactive_1.askContentDir)());
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
* MIT Licensed
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
const logger_1 = require("./logger");
|
|
12
11
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
13
12
|
const login = async (config) => {
|
|
14
13
|
const client = await (0, cli_utilities_1.managementSDKClient)(config);
|
|
@@ -21,7 +20,7 @@ const login = async (config) => {
|
|
|
21
20
|
authtoken: config.authtoken,
|
|
22
21
|
'X-User-Agent': 'contentstack-export/v',
|
|
23
22
|
};
|
|
24
|
-
|
|
23
|
+
cli_utilities_1.log.success('Contentstack account authenticated successfully!');
|
|
25
24
|
return config;
|
|
26
25
|
}
|
|
27
26
|
else {
|
|
@@ -40,10 +39,10 @@ const login = async (config) => {
|
|
|
40
39
|
var _a;
|
|
41
40
|
let errorstack_key = (_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.api_key;
|
|
42
41
|
if (errorstack_key) {
|
|
43
|
-
|
|
42
|
+
cli_utilities_1.log.error('Stack Api key ' + errorstack_key[0] + 'Please enter valid Key', { error });
|
|
44
43
|
throw error;
|
|
45
44
|
}
|
|
46
|
-
|
|
45
|
+
cli_utilities_1.log.error((error === null || error === void 0 ? void 0 : error.errorMessage) || 'Unknown error', { error });
|
|
47
46
|
throw error;
|
|
48
47
|
});
|
|
49
48
|
config.destinationStackName = stack.name;
|
|
@@ -25,7 +25,7 @@ const setupBranchConfig = async (config, stackAPIClient) => {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
catch (error) {
|
|
28
|
-
cli_utilities_1.log.
|
|
28
|
+
cli_utilities_1.log.error('Failed to fetch branches', { error });
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
exports.setupBranchConfig = setupBranchConfig;
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-import-setup",
|
|
3
3
|
"description": "Contentstack CLI plugin to setup the mappers and configurations for the import command",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.7.1",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-command": "~1.
|
|
8
|
+
"@contentstack/cli-command": "~1.7.0",
|
|
9
9
|
"@contentstack/cli-utilities": "~1.15.0",
|
|
10
10
|
"@oclif/core": "^4.3.0",
|
|
11
11
|
"big-json": "^3.2.0",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@types/mkdirp": "^1.0.2",
|
|
25
25
|
"@types/mocha": "^8.2.3",
|
|
26
26
|
"@types/node": "^14.18.63",
|
|
27
|
-
"@types/
|
|
27
|
+
"@types/rewire": "^2.5.30",
|
|
28
28
|
"@types/tar": "^6.1.13",
|
|
29
29
|
"@types/uuid": "^9.0.8",
|
|
30
30
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"mocha": "^10.8.2",
|
|
35
35
|
"nyc": "^15.1.0",
|
|
36
36
|
"oclif": "^4.17.46",
|
|
37
|
-
"
|
|
37
|
+
"rewire": "^9.0.1",
|
|
38
38
|
"ts-node": "^10.9.2",
|
|
39
39
|
"tsx": "^4.20.3",
|
|
40
40
|
"typescript": "^4.9.5"
|