@contentstack/cli-cm-import 1.28.3 → 1.30.0

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.
Files changed (33) hide show
  1. package/README.md +125 -67
  2. package/lib/commands/cm/stacks/import.js +8 -6
  3. package/lib/config/index.js +7 -0
  4. package/lib/import/modules/assets.js +18 -18
  5. package/lib/import/modules/base-class.d.ts +1 -0
  6. package/lib/import/modules/base-class.js +3 -1
  7. package/lib/import/modules/composable-studio.d.ts +43 -0
  8. package/lib/import/modules/composable-studio.js +231 -0
  9. package/lib/import/modules/content-types.js +9 -9
  10. package/lib/import/modules/custom-roles.js +24 -24
  11. package/lib/import/modules/entries.js +35 -18
  12. package/lib/import/modules/environments.js +10 -10
  13. package/lib/import/modules/extensions.js +16 -16
  14. package/lib/import/modules/global-fields.js +13 -13
  15. package/lib/import/modules/labels.js +12 -12
  16. package/lib/import/modules/locales.js +22 -22
  17. package/lib/import/modules/marketplace-apps.js +53 -53
  18. package/lib/import/modules/personalize.js +11 -11
  19. package/lib/import/modules/taxonomies.d.ts +23 -4
  20. package/lib/import/modules/taxonomies.js +180 -70
  21. package/lib/import/modules-js/entries.js +1 -1
  22. package/lib/import/modules-js/marketplace-apps.js +2 -2
  23. package/lib/types/default-config.d.ts +6 -0
  24. package/lib/types/index.d.ts +27 -1
  25. package/lib/utils/content-type-helper.js +2 -2
  26. package/lib/utils/file-helper.js +1 -1
  27. package/lib/utils/import-config-handler.js +2 -2
  28. package/lib/utils/login-handler.js +1 -1
  29. package/lib/utils/marketplace-app-helper.js +1 -1
  30. package/lib/utils/taxonomies-helper.js +1 -1
  31. package/messages/index.json +10 -1
  32. package/oclif.manifest.json +2 -2
  33. package/package.json +5 -5
@@ -10,6 +10,7 @@ const utils_1 = require("../../utils");
10
10
  class ImportTaxonomies extends base_class_1.default {
11
11
  constructor({ importConfig, stackAPIClient }) {
12
12
  super({ importConfig, stackAPIClient });
13
+ this.isLocaleBasedStructure = false;
13
14
  this.createdTaxonomies = {};
14
15
  this.failedTaxonomies = {};
15
16
  this.createdTerms = {};
@@ -23,34 +24,46 @@ class ImportTaxonomies extends base_class_1.default {
23
24
  this.taxFailsPath = (0, node_path_1.join)(this.taxonomiesMapperDirPath, 'fails.json');
24
25
  this.termsSuccessPath = (0, node_path_1.join)(this.termsMapperDirPath, 'success.json');
25
26
  this.termsFailsPath = (0, node_path_1.join)(this.termsMapperDirPath, 'fails.json');
27
+ this.localesFilePath = (0, node_path_1.join)(importConfig.backupDir, importConfig.modules.locales.dirName, importConfig.modules.locales.fileName);
26
28
  }
27
29
  /**
28
30
  * @method start
29
31
  * @returns {Promise<void>} Promise<void>
30
32
  */
31
33
  async start() {
32
- cli_utilities_1.log.debug('Checking for taxonomies folder existence', this.importConfig.context);
34
+ cli_utilities_1.log.debug('Checking for taxonomy folder existence', this.importConfig.context);
33
35
  //Step1 check folder exists or not
34
36
  if (utils_1.fileHelper.fileExistsSync(this.taxonomiesFolderPath)) {
35
- cli_utilities_1.log.debug(`Found taxonomies folder: ${this.taxonomiesFolderPath}`, this.importConfig.context);
37
+ cli_utilities_1.log.debug(`Found taxonomy folder at: ${this.taxonomiesFolderPath}`, this.importConfig.context);
36
38
  this.taxonomies = utils_1.fsUtil.readFile((0, node_path_1.join)(this.taxonomiesFolderPath, 'taxonomies.json'), true);
37
39
  const taxonomyCount = Object.keys(this.taxonomies || {}).length;
38
- cli_utilities_1.log.debug(`Loaded ${taxonomyCount} taxonomy items from file`, this.importConfig.context);
40
+ cli_utilities_1.log.debug(`Loaded ${taxonomyCount} taxonomy items from file.`, this.importConfig.context);
39
41
  }
40
42
  else {
41
- cli_utilities_1.log.info(`No Taxonomies Found! - '${this.taxonomiesFolderPath}'`, this.importConfig.context);
43
+ cli_utilities_1.log.info(`No taxonomies found at: '${this.taxonomiesFolderPath}'`, this.importConfig.context);
42
44
  return;
43
45
  }
44
46
  //Step 2 create taxonomies & terms mapper directory
45
- cli_utilities_1.log.debug('Creating mapper directories', this.importConfig.context);
47
+ cli_utilities_1.log.debug('Creating mapper directories...', this.importConfig.context);
46
48
  await utils_1.fsUtil.makeDirectory(this.taxonomiesMapperDirPath);
47
49
  await utils_1.fsUtil.makeDirectory(this.termsMapperDirPath);
48
- cli_utilities_1.log.debug('Created taxonomies and terms mapper directories', this.importConfig.context);
49
- // Step 3 import taxonomies
50
- cli_utilities_1.log.debug('Starting taxonomies import', this.importConfig.context);
51
- await this.importTaxonomies();
52
- //Step 4 create taxonomy & related terms success & failure file
53
- cli_utilities_1.log.debug('Creating success and failure files', this.importConfig.context);
50
+ cli_utilities_1.log.debug('Created taxonomies and terms mapper directories.', this.importConfig.context);
51
+ // Step 3: Check if locale-based structure exists and scan taxonomies by locale
52
+ cli_utilities_1.log.debug('Checking for locale-based folder structure', this.importConfig.context);
53
+ this.isLocaleBasedStructure = this.detectAndScanLocaleStructure();
54
+ // Step 4 import taxonomies
55
+ if (this.isLocaleBasedStructure) {
56
+ cli_utilities_1.log.debug('Detected locale-based folder structure for taxonomies', this.importConfig.context);
57
+ cli_utilities_1.log.debug('Starting taxonomies import...', this.importConfig.context);
58
+ await this.importTaxonomiesByLocale();
59
+ }
60
+ else {
61
+ cli_utilities_1.log.debug('Starting taxonomies import', this.importConfig.context);
62
+ await this.importTaxonomiesLegacy();
63
+ cli_utilities_1.log.debug('Using legacy folder structure for taxonomies', this.importConfig.context);
64
+ }
65
+ //Step 5 create taxonomy & related terms success & failure file
66
+ cli_utilities_1.log.debug('Creating success and failure files...', this.importConfig.context);
54
67
  this.createSuccessAndFailedFile();
55
68
  cli_utilities_1.log.success('Taxonomies imported successfully!', this.importConfig.context);
56
69
  }
@@ -60,50 +73,9 @@ class ImportTaxonomies extends base_class_1.default {
60
73
  * @async
61
74
  * @returns {Promise<any>} Promise<any>
62
75
  */
63
- async importTaxonomies() {
64
- cli_utilities_1.log.debug('Validating taxonomies data', this.importConfig.context);
65
- if (this.taxonomies === undefined || (0, isEmpty_1.default)(this.taxonomies)) {
66
- cli_utilities_1.log.info('No Taxonomies Found!', this.importConfig.context);
67
- return;
68
- }
69
- const apiContent = (0, values_1.default)(this.taxonomies);
70
- cli_utilities_1.log.debug(`Starting to import ${apiContent.length} taxonomies`, this.importConfig.context);
71
- const onSuccess = ({ apiData }) => {
72
- var _a, _b;
73
- const taxonomyUID = (_a = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _a === void 0 ? void 0 : _a.uid;
74
- const taxonomyName = (_b = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _b === void 0 ? void 0 : _b.name;
75
- const termsCount = Object.keys((apiData === null || apiData === void 0 ? void 0 : apiData.terms) || {}).length;
76
- this.createdTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
77
- this.createdTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
78
- cli_utilities_1.log.success(`Taxonomy '${taxonomyUID}' imported successfully!`, this.importConfig.context);
79
- cli_utilities_1.log.debug(`Created taxonomy '${taxonomyName}' with ${termsCount} terms`, this.importConfig.context);
80
- cli_utilities_1.log.debug(`Taxonomy details: ${JSON.stringify({ uid: taxonomyUID, name: taxonomyName, termsCount })}`, this.importConfig.context);
81
- };
82
- const onReject = ({ error, apiData }) => {
83
- var _a, _b, _c, _d;
84
- const taxonomyUID = (_a = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _a === void 0 ? void 0 : _a.uid;
85
- const taxonomyName = (_b = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _b === void 0 ? void 0 : _b.name;
86
- cli_utilities_1.log.debug(`Taxonomy '${taxonomyUID}' failed to import`, this.importConfig.context);
87
- if ((error === null || error === void 0 ? void 0 : error.status) === 409 && (error === null || error === void 0 ? void 0 : error.statusText) === 'Conflict') {
88
- cli_utilities_1.log.info(`Taxonomy '${taxonomyUID}' already exists!`, this.importConfig.context);
89
- cli_utilities_1.log.debug(`Adding existing taxonomy '${taxonomyUID}' to created list`, this.importConfig.context);
90
- this.createdTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
91
- this.createdTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
92
- }
93
- else {
94
- cli_utilities_1.log.debug(`Adding taxonomy '${taxonomyUID}' to failed list`, this.importConfig.context);
95
- if ((error === null || error === void 0 ? void 0 : error.errorMessage) || (error === null || error === void 0 ? void 0 : error.message)) {
96
- const errorMsg = (error === null || error === void 0 ? void 0 : error.errorMessage) || ((_c = error === null || error === void 0 ? void 0 : error.errors) === null || _c === void 0 ? void 0 : _c.taxonomy) || ((_d = error === null || error === void 0 ? void 0 : error.errors) === null || _d === void 0 ? void 0 : _d.term) || (error === null || error === void 0 ? void 0 : error.message);
97
- cli_utilities_1.log.error(`Taxonomy '${taxonomyUID}' failed to be import! ${errorMsg}`, this.importConfig.context);
98
- }
99
- else {
100
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { taxonomyUID }), `Taxonomy '${taxonomyUID}' failed to import`);
101
- }
102
- this.failedTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
103
- this.failedTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
104
- }
105
- };
106
- cli_utilities_1.log.debug(`Using concurrency limit: ${this.importConfig.concurrency || this.importConfig.fetchConcurrency || 1}`, this.importConfig.context);
76
+ async importTaxonomies({ apiContent, localeCode }) {
77
+ const onSuccess = ({ apiData }) => this.handleSuccess(apiData, localeCode);
78
+ const onReject = ({ error, apiData }) => this.handleFailure(error, apiData, localeCode);
107
79
  await this.makeConcurrentCall({
108
80
  apiContent,
109
81
  processName: 'import taxonomies',
@@ -113,35 +85,157 @@ class ImportTaxonomies extends base_class_1.default {
113
85
  resolve: onSuccess,
114
86
  entity: 'import-taxonomy',
115
87
  includeParamOnCompletion: true,
88
+ queryParam: {
89
+ locale: localeCode,
90
+ },
116
91
  },
117
92
  concurrencyLimit: this.importConfig.concurrency || this.importConfig.fetchConcurrency || 1,
118
93
  }, undefined, false);
119
- cli_utilities_1.log.debug('Taxonomies import process completed', this.importConfig.context);
94
+ }
95
+ async importTaxonomiesLegacy() {
96
+ const apiContent = (0, values_1.default)(this.taxonomies);
97
+ await this.importTaxonomies({
98
+ apiContent,
99
+ });
100
+ }
101
+ async importTaxonomiesByLocale() {
102
+ const locales = this.loadAvailableLocales();
103
+ const apiContent = (0, values_1.default)(this.taxonomies);
104
+ for (const localeCode of Object.keys(locales)) {
105
+ await this.importTaxonomies({
106
+ apiContent,
107
+ localeCode,
108
+ });
109
+ }
110
+ }
111
+ handleSuccess(apiData, locale) {
112
+ const { taxonomy, terms } = apiData || {};
113
+ const taxonomyUID = taxonomy === null || taxonomy === void 0 ? void 0 : taxonomy.uid;
114
+ const taxonomyName = taxonomy === null || taxonomy === void 0 ? void 0 : taxonomy.name;
115
+ const termsCount = Object.keys(terms || {}).length;
116
+ this.createdTaxonomies[taxonomyUID] = taxonomy;
117
+ this.createdTerms[taxonomyUID] = terms;
118
+ cli_utilities_1.log.success(`Taxonomy '${taxonomyUID}' imported successfully${locale ? ` for locale: ${locale}` : ''}!`, this.importConfig.context);
119
+ cli_utilities_1.log.debug(`Created taxonomy '${taxonomyName}' with ${termsCount} terms${locale ? ` for locale: ${locale}` : ''}`, this.importConfig.context);
120
+ }
121
+ handleFailure(error, apiData, locale) {
122
+ var _a, _b, _c;
123
+ const taxonomyUID = (_a = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _a === void 0 ? void 0 : _a.uid;
124
+ if ((error === null || error === void 0 ? void 0 : error.status) === 409 && (error === null || error === void 0 ? void 0 : error.statusText) === 'Conflict') {
125
+ cli_utilities_1.log.info(`Taxonomy '${taxonomyUID}' already exists ${locale ? ` for locale: ${locale}` : ''}!`, this.importConfig.context);
126
+ this.createdTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
127
+ this.createdTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
128
+ return;
129
+ }
130
+ const errMsg = (error === null || error === void 0 ? void 0 : error.errorMessage) || ((_b = error === null || error === void 0 ? void 0 : error.errors) === null || _b === void 0 ? void 0 : _b.taxonomy) || ((_c = error === null || error === void 0 ? void 0 : error.errors) === null || _c === void 0 ? void 0 : _c.term) || (error === null || error === void 0 ? void 0 : error.message);
131
+ if (errMsg) {
132
+ cli_utilities_1.log.error(`Taxonomy '${taxonomyUID}' failed to import${locale ? ` for locale: ${locale}` : ''}! ${errMsg}`, this.importConfig.context);
133
+ }
134
+ else {
135
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { taxonomyUID, locale }), `Taxonomy '${taxonomyUID}' failed`);
136
+ }
137
+ this.failedTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
138
+ this.failedTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
120
139
  }
121
140
  /**
122
- * @method serializeTaxonomy
123
- * @param {ApiOptions} apiOptions ApiOptions
124
- * @returns {ApiOptions} ApiOptions
141
+ *
142
+ * @param {ApiOptions} apiOptions
143
+ * @param {?string} [localeCode]
144
+ * @returns {ApiOptions}
125
145
  */
126
146
  serializeTaxonomy(apiOptions) {
127
- const { apiData } = apiOptions;
147
+ const { apiData, queryParam: { locale }, } = apiOptions;
128
148
  const taxonomyUID = apiData === null || apiData === void 0 ? void 0 : apiData.uid;
129
- const filePath = (0, node_path_1.join)(this.taxonomiesFolderPath, `${taxonomyUID}.json`);
130
- cli_utilities_1.log.debug(`Serializing taxonomy: ${taxonomyUID}`, this.importConfig.context);
131
- cli_utilities_1.log.debug(`Looking for taxonomy file: ${filePath}`, this.importConfig.context);
132
- if (utils_1.fileHelper.fileExistsSync(filePath)) {
133
- const taxonomyDetails = utils_1.fsUtil.readFile(filePath, true);
134
- cli_utilities_1.log.debug(`Successfully loaded taxonomy details from ${filePath}`, this.importConfig.context);
149
+ if (!taxonomyUID) {
150
+ cli_utilities_1.log.debug('No taxonomy UID provided for serialization', this.importConfig.context);
151
+ apiOptions.apiData = undefined;
152
+ return apiOptions;
153
+ }
154
+ const context = locale ? ` for locale: ${locale}` : '';
155
+ cli_utilities_1.log.debug(`Serializing taxonomy: ${taxonomyUID}${context}`, this.importConfig.context);
156
+ // Determine file path - if locale is provided, use it directly, otherwise search
157
+ const filePath = locale
158
+ ? (0, node_path_1.join)(this.taxonomiesFolderPath, locale, `${taxonomyUID}.json`)
159
+ : this.findTaxonomyFilePath(taxonomyUID);
160
+ if (!filePath || !utils_1.fileHelper.fileExistsSync(filePath)) {
161
+ cli_utilities_1.log.debug(`Taxonomy file not found for: ${taxonomyUID}${context}`, this.importConfig.context);
162
+ apiOptions.apiData = undefined;
163
+ return apiOptions;
164
+ }
165
+ const taxonomyDetails = this.loadTaxonomyFile(filePath, locale || 'auto-detected');
166
+ if (taxonomyDetails) {
135
167
  const termCount = Object.keys((taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.terms) || {}).length;
136
- cli_utilities_1.log.debug(`Taxonomy has ${termCount} term entries`, this.importConfig.context);
137
- apiOptions.apiData = { filePath, taxonomy: taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.taxonomy, terms: taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.terms };
168
+ cli_utilities_1.log.debug(`Taxonomy has ${termCount} term entries${context}`, this.importConfig.context);
169
+ apiOptions.apiData = {
170
+ filePath,
171
+ taxonomy: taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.taxonomy,
172
+ terms: taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.terms,
173
+ };
138
174
  }
139
175
  else {
140
- cli_utilities_1.log.debug(`File does not exist for taxonomy: ${taxonomyUID}`, this.importConfig.context);
141
176
  apiOptions.apiData = undefined;
142
177
  }
143
178
  return apiOptions;
144
179
  }
180
+ loadTaxonomyFile(filePath, context) {
181
+ if (!utils_1.fileHelper.fileExistsSync(filePath)) {
182
+ cli_utilities_1.log.debug(`File does not exist: ${filePath}`, this.importConfig.context);
183
+ return undefined;
184
+ }
185
+ try {
186
+ const taxonomyDetails = utils_1.fsUtil.readFile(filePath, true);
187
+ cli_utilities_1.log.debug(`Successfully loaded taxonomy from: ${context}`, this.importConfig.context);
188
+ return taxonomyDetails;
189
+ }
190
+ catch (error) {
191
+ cli_utilities_1.log.debug(`Error loading taxonomy file: ${filePath}`, this.importConfig.context);
192
+ return undefined;
193
+ }
194
+ }
195
+ findTaxonomyFilePath(taxonomyUID) {
196
+ if (this.isLocaleBasedStructure) {
197
+ // For locale-based structure, search in locale folders
198
+ return this.findTaxonomyInLocaleFolders(taxonomyUID);
199
+ }
200
+ else {
201
+ // For legacy structure, only check the root folder
202
+ const legacyPath = (0, node_path_1.join)(this.taxonomiesFolderPath, `${taxonomyUID}.json`);
203
+ return utils_1.fileHelper.fileExistsSync(legacyPath) ? legacyPath : undefined;
204
+ }
205
+ }
206
+ findTaxonomyInLocaleFolders(taxonomyUID) {
207
+ const locales = this.loadAvailableLocales();
208
+ for (const localeCode of Object.keys(locales)) {
209
+ const filePath = (0, node_path_1.join)(this.taxonomiesFolderPath, localeCode, `${taxonomyUID}.json`);
210
+ if (utils_1.fileHelper.fileExistsSync(filePath)) {
211
+ return filePath;
212
+ }
213
+ }
214
+ return undefined;
215
+ }
216
+ loadAvailableLocales() {
217
+ var _a, _b;
218
+ if (!utils_1.fileHelper.fileExistsSync(this.localesFilePath)) {
219
+ cli_utilities_1.log.debug('No locales file found', this.importConfig.context);
220
+ return {};
221
+ }
222
+ try {
223
+ const localesData = utils_1.fsUtil.readFile(this.localesFilePath, true);
224
+ const locales = {};
225
+ locales[(_a = this.importConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code] = (_b = this.importConfig.master_locale) === null || _b === void 0 ? void 0 : _b.code;
226
+ for (const [code, locale] of Object.entries(localesData)) {
227
+ if (locale === null || locale === void 0 ? void 0 : locale.code) {
228
+ locales[locale.code] = code;
229
+ }
230
+ }
231
+ cli_utilities_1.log.debug(`Loaded ${Object.keys(locales).length} locales from file`, this.importConfig.context);
232
+ return locales;
233
+ }
234
+ catch (error) {
235
+ cli_utilities_1.log.debug('Error loading locales file', this.importConfig.context);
236
+ return {};
237
+ }
238
+ }
145
239
  /**
146
240
  * create taxonomies success and fail in (mapper/taxonomies)
147
241
  * create terms success and fail in (mapper/taxonomies/terms)
@@ -149,7 +243,7 @@ class ImportTaxonomies extends base_class_1.default {
149
243
  */
150
244
  createSuccessAndFailedFile() {
151
245
  var _a, _b, _c, _d;
152
- cli_utilities_1.log.debug('Creating success and failed files for taxonomies and terms', this.importConfig.context);
246
+ cli_utilities_1.log.debug('Creating success and failed files for taxonomies and terms...', this.importConfig.context);
153
247
  const createdTaxCount = (_a = Object.keys(this.createdTaxonomies)) === null || _a === void 0 ? void 0 : _a.length;
154
248
  const failedTaxCount = (_b = Object.keys(this.failedTaxonomies)) === null || _b === void 0 ? void 0 : _b.length;
155
249
  const createdTermsCount = (_c = Object.keys(this.createdTerms)) === null || _c === void 0 ? void 0 : _c.length;
@@ -173,5 +267,21 @@ class ImportTaxonomies extends base_class_1.default {
173
267
  cli_utilities_1.log.debug(`Written failed terms for ${failedTermsCount} taxonomies to file: ${this.termsFailsPath}`, this.importConfig.context);
174
268
  }
175
269
  }
270
+ /**
271
+ * Detect if locale-based folder structure exists and scan taxonomies by locale
272
+ * @returns {boolean} true if locale-based structure detected, false otherwise
273
+ */
274
+ detectAndScanLocaleStructure() {
275
+ var _a;
276
+ const masterLocaleCode = ((_a = this.importConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code) || 'en-us';
277
+ const masterLocaleFolder = (0, node_path_1.join)(this.taxonomiesFolderPath, masterLocaleCode);
278
+ // Check if master locale folder exists (indicates new locale-based structure)
279
+ if (!utils_1.fileHelper.fileExistsSync(masterLocaleFolder)) {
280
+ cli_utilities_1.log.debug('No locale-based folder structure detected', this.importConfig.context);
281
+ return false;
282
+ }
283
+ cli_utilities_1.log.debug('Locale-based folder structure detected', this.importConfig.context);
284
+ return true;
285
+ }
176
286
  }
177
287
  exports.default = ImportTaxonomies;
@@ -934,7 +934,7 @@ module.exports = class ImportEntries {
934
934
  addlogs(this.config, `Entries published successfully in '${ctUid}' content type`, 'info');
935
935
  })
936
936
  .catch((error) => {
937
- console.log(error);
937
+ console.log('Error', error);
938
938
  addlogs(this.config, `failed to publish entry in content type '${ctUid}' ${formatError(error)}`, 'error');
939
939
  });
940
940
  }
@@ -65,7 +65,7 @@ module.exports = class ImportMarketplaceApps {
65
65
  .stack({ api_key: this.config.target_stack })
66
66
  .fetch()
67
67
  .catch((error) => {
68
- console.log(error);
68
+ console.log('Error', error);
69
69
  });
70
70
  if (tempStackData === null || tempStackData === void 0 ? void 0 : tempStackData.org_uid) {
71
71
  this.config.org_uid = tempStackData.org_uid;
@@ -376,7 +376,7 @@ module.exports = class ImportMarketplaceApps {
376
376
  return updateParam;
377
377
  }
378
378
  async confirmToCloseProcess(installation) {
379
- cliux.print(`\nWARNING!!! ${formatError(installation.message)}\n`, { color: 'yellow' });
379
+ cliux.print(`\nWARNING: ${formatError(installation.message)}\n`, { color: 'yellow' });
380
380
  if (!this.config.forceStopMarketplaceAppsPrompt) {
381
381
  if (!(await cliux.confirm(chalk.yellow('WARNING!!! The above error may have an impact if the failed app is referenced in entries/content type. Would you like to proceed? (y/n)')))) {
382
382
  process.exit();
@@ -156,6 +156,12 @@ export default interface DefaultConfig {
156
156
  locale: string;
157
157
  } & AnyProperty;
158
158
  } & AnyProperty;
159
+ 'composable-studio': {
160
+ dirName: string;
161
+ fileName: string;
162
+ apiBaseUrl: string;
163
+ apiVersion: string;
164
+ };
159
165
  };
160
166
  languagesCode: string[];
161
167
  apis: {
@@ -26,7 +26,7 @@ export interface User {
26
26
  email: string;
27
27
  authtoken: string;
28
28
  }
29
- export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies' | 'personalize' | 'variant-entries';
29
+ export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies' | 'personalize' | 'variant-entries' | 'composable-studio';
30
30
  export type ModuleClassParams = {
31
31
  stackAPIClient: ReturnType<ContentstackClient['stack']>;
32
32
  importConfig: ImportConfig;
@@ -71,6 +71,32 @@ export interface TaxonomiesConfig {
71
71
  fileName: string;
72
72
  dependencies?: Modules[];
73
73
  }
74
+ export interface ComposableStudioConfig {
75
+ dirName: string;
76
+ fileName: string;
77
+ apiBaseUrl: string;
78
+ apiVersion: string;
79
+ }
80
+ export interface ComposableStudioProject {
81
+ name: string;
82
+ description: string;
83
+ canvasUrl: string;
84
+ connectedStackApiKey: string;
85
+ contentTypeUid: string;
86
+ organizationUid: string;
87
+ settings: {
88
+ configuration: {
89
+ environment: string;
90
+ locale: string;
91
+ };
92
+ };
93
+ uid?: string;
94
+ createdBy?: string;
95
+ updatedBy?: string;
96
+ deletedAt?: boolean;
97
+ createdAt?: string;
98
+ updatedAt?: string;
99
+ }
74
100
  export interface Context {
75
101
  command: string;
76
102
  module: string;
@@ -128,7 +128,7 @@ const removeReferenceFields = async function (schema, flag = { supressed: false
128
128
  catch (error) {
129
129
  // Else warn and modify the schema object.
130
130
  isContentTypeError = true;
131
- cli_utilities_1.log.warn(`Content-type ${schema[i].reference_to[j]} does not exist. Removing the field from schema`);
131
+ cli_utilities_1.log.warn(`Content type ${schema[i].reference_to[j]} does not exist. Removing the field from schema...`);
132
132
  }
133
133
  }
134
134
  if (isContentTypeError) {
@@ -200,7 +200,7 @@ const updateFieldRules = function (contentType) {
200
200
  const field = contentType.schema[i];
201
201
  fieldDataTypeMap[field.uid] = field.data_type;
202
202
  }
203
- cli_utilities_1.log.debug(`Created field data type mapping for ${Object.keys(fieldDataTypeMap).length} fields`);
203
+ cli_utilities_1.log.debug(`Created field data type mapping for ${Object.keys(fieldDataTypeMap).length} fields.`);
204
204
  const fieldRules = [...contentType.field_rules];
205
205
  let len = fieldRules.length;
206
206
  let removedRules = 0;
@@ -58,7 +58,7 @@ const readLargeFile = function (filePath, opts) {
58
58
  resolve(data);
59
59
  });
60
60
  parseStream.on('error', function (error) {
61
- console.log('error', error);
61
+ console.log('Error', error);
62
62
  reject(error);
63
63
  });
64
64
  readStream.pipe(parseStream);
@@ -26,7 +26,7 @@ const setupConfig = async (importCmdFlags) => {
26
26
  config.contentDir = (0, cli_utilities_1.sanitizePath)(importCmdFlags['data'] || importCmdFlags['data-dir'] || config.data || (await (0, interactive_1.askContentDir)()));
27
27
  const pattern = /[*$%#<>{}!&?]/g;
28
28
  if (pattern.test(config.contentDir)) {
29
- cli_utilities_1.cliux.print(`\nPlease add a directory path without any of the special characters: (*,&,{,},[,],$,%,<,>,?,!)`, {
29
+ cli_utilities_1.cliux.print(`\nPlease enter a directory path without any special characters: (*,&,{,},[,],$,%,<,>,?,!)`, {
30
30
  color: 'yellow',
31
31
  });
32
32
  config.contentDir = (0, cli_utilities_1.sanitizePath)(await (0, interactive_1.askContentDir)());
@@ -115,7 +115,7 @@ const setupConfig = async (importCmdFlags) => {
115
115
  }
116
116
  // Add authentication details to config for context tracking
117
117
  config.authenticationMethod = authenticationMethod;
118
- cli_utilities_1.log.debug('Import configuration setup completed', Object.assign({}, config));
118
+ cli_utilities_1.log.debug('Import configuration setup completed.', Object.assign({}, config));
119
119
  return config;
120
120
  };
121
121
  exports.default = setupConfig;
@@ -44,7 +44,7 @@ const login = async (config) => {
44
44
  let errorstack_key = (_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.api_key;
45
45
  if (errorstack_key) {
46
46
  const keyError = errorstack_key[0];
47
- cli_utilities_1.log.error(`Invalid stack API token: ${keyError} Please enter valid stack API token.`);
47
+ cli_utilities_1.log.error(`Invalid stack API token: ${keyError}. Please enter a valid stack API token.`);
48
48
  throw error;
49
49
  }
50
50
  cli_utilities_1.log.error(`Stack fetch error: ${error === null || error === void 0 ? void 0 : error.errorMessage}`);
@@ -81,7 +81,7 @@ const getConfirmationToCreateApps = async (privateApps, config) => {
81
81
  return Promise.resolve(true);
82
82
  }
83
83
  else {
84
- cli_utilities_1.log.debug('User declined to create private apps (second prompt)');
84
+ cli_utilities_1.log.debug('User declined to create private apps (second prompt).');
85
85
  return Promise.resolve(false);
86
86
  }
87
87
  }
@@ -14,7 +14,7 @@ const cli_utilities_1 = require("@contentstack/cli-utilities");
14
14
  * @param {ImportConfig} importConfig
15
15
  */
16
16
  const lookUpTaxonomy = function (importConfig, schema, taxonomies) {
17
- cli_utilities_1.log.debug(`Starting taxonomy lookup for schema with ${Object.keys(schema).length} fields`);
17
+ cli_utilities_1.log.debug(`Starting taxonomy lookup for schema with ${Object.keys(schema).length} fields.`);
18
18
  for (let i in schema) {
19
19
  if (schema[i].data_type === 'taxonomy') {
20
20
  cli_utilities_1.log.debug(`Processing taxonomy field: ${schema[i].uid}`);
@@ -1 +1,10 @@
1
- {}
1
+ {
2
+ "COMPOSABLE_STUDIO_IMPORT_START": "Starting Composable Studio project import...",
3
+ "COMPOSABLE_STUDIO_NOT_FOUND": "No Composable Studio project found in exported data",
4
+ "COMPOSABLE_STUDIO_SKIP_EXISTING": "Skipping Composable Studio import - target stack already has a connected project",
5
+ "COMPOSABLE_STUDIO_IMPORT_COMPLETE": "Successfully imported Composable Studio project '%s'",
6
+ "COMPOSABLE_STUDIO_IMPORT_FAILED": "Failed to import Composable Studio project: %s",
7
+ "COMPOSABLE_STUDIO_NAME_CONFLICT": "Project name '%s' already exists. Please provide a new name:",
8
+ "COMPOSABLE_STUDIO_SUGGEST_NAME": "Suggested name: %s",
9
+ "COMPOSABLE_STUDIO_ENV_MAPPING_FAILED": "Warning: Could not map environment '%s', using empty environment"
10
+ }
@@ -84,7 +84,7 @@
84
84
  },
85
85
  "module": {
86
86
  "char": "m",
87
- "description": "[optional] Specify the module to import into the target stack. If not specified, the import command will import all the modules into the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, personalize projects, and taxonomies.",
87
+ "description": "[optional] Specify the module to import into the target stack. If not specified, the import command will import all the modules into the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, personalize projects, taxonomies, and composable-studio.",
88
88
  "name": "module",
89
89
  "required": false,
90
90
  "hasDynamicHelp": false,
@@ -212,5 +212,5 @@
212
212
  ]
213
213
  }
214
214
  },
215
- "version": "1.28.3"
215
+ "version": "1.30.0"
216
216
  }
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-import",
3
3
  "description": "Contentstack CLI plugin to import content into stack",
4
- "version": "1.28.3",
4
+ "version": "1.30.0",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
8
- "@contentstack/cli-audit": "~1.15.0",
9
- "@contentstack/cli-command": "~1.6.1",
10
- "@contentstack/cli-utilities": "~1.14.4",
8
+ "@contentstack/cli-audit": "~1.16.1",
9
+ "@contentstack/cli-command": "~1.7.0",
10
+ "@contentstack/cli-utilities": "~1.15.0",
11
11
  "@contentstack/management": "~1.22.0",
12
- "@contentstack/cli-variants": "~1.3.4",
12
+ "@contentstack/cli-variants": "~1.3.5",
13
13
  "@oclif/core": "^4.3.0",
14
14
  "big-json": "^3.2.0",
15
15
  "bluebird": "^3.7.2",