@contentstack/cli-cm-export 2.0.0-beta → 2.0.0-beta.2

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 CHANGED
@@ -48,7 +48,7 @@ $ npm install -g @contentstack/cli-cm-export
48
48
  $ csdx COMMAND
49
49
  running command...
50
50
  $ csdx (--version)
51
- @contentstack/cli-cm-export/2.0.0-beta linux-x64 node-v22.20.0
51
+ @contentstack/cli-cm-export/2.0.0-beta.2 linux-x64 node-v22.21.1
52
52
  $ csdx --help [COMMAND]
53
53
  USAGE
54
54
  $ csdx COMMAND
@@ -158,7 +158,7 @@ class BaseClass {
158
158
  case 'export-taxonomy':
159
159
  return this.stack
160
160
  .taxonomy(uid)
161
- .export()
161
+ .export(queryParam)
162
162
  .then((response) => resolve({ response, uid }))
163
163
  .catch((error) => reject({ error, uid }));
164
164
  default:
@@ -2,21 +2,44 @@ import BaseClass from './base-class';
2
2
  import { ModuleClassParams } from '../../types';
3
3
  export default class ExportTaxonomies extends BaseClass {
4
4
  private taxonomies;
5
+ private taxonomiesByLocale;
5
6
  private taxonomiesConfig;
7
+ private isLocaleBasedExportSupported;
6
8
  private qs;
7
9
  taxonomiesFolderPath: string;
10
+ private localesFilePath;
8
11
  constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
9
12
  start(): Promise<void>;
10
13
  /**
11
- * Fetch in the provided stack
12
- * @param {number} skip
13
- * @returns {Promise<any>}
14
+ * Process and export taxonomies for a specific locale
14
15
  */
15
- getAllTaxonomies(skip?: number): Promise<any>;
16
- sanitizeTaxonomiesAttribs(taxonomies: Record<string, any>[]): void;
16
+ processLocaleExport(localeCode: string): Promise<void>;
17
17
  /**
18
- * Export all taxonomies details using metadata(this.taxonomies) and write it into respective <taxonomy-uid>.json file
19
- * @returns {Promise<any>}
18
+ * Write taxonomies metadata file
20
19
  */
21
- exportTaxonomies(): Promise<any>;
20
+ writeTaxonomiesMetadata(): Promise<void>;
21
+ /**
22
+ * Fetch taxonomies
23
+ *
24
+ * @async
25
+ * @param {?string} [localeCode]
26
+ * @param {boolean} [checkLocaleSupport=false]
27
+ * @returns {Promise<void>}
28
+ */
29
+ fetchTaxonomies(localeCode?: string, checkLocaleSupport?: boolean): Promise<void>;
30
+ /**
31
+ * remove invalid keys and write data into taxonomies
32
+ * @function sanitizeTaxonomiesAttribs
33
+ * @param {Record<string, string>[]} taxonomies
34
+ * @param {?string} [localeCode]
35
+ */
36
+ sanitizeTaxonomiesAttribs(taxonomies: Record<string, string>[], localeCode?: string): void;
37
+ /**
38
+ * Export taxonomies - supports both locale-based and legacy export
39
+ */
40
+ exportTaxonomies(localeCode?: string): Promise<void>;
41
+ /**
42
+ * Get all locales to export
43
+ */
44
+ getLocalesToExport(): string[];
22
45
  }
@@ -11,170 +11,228 @@ const utils_1 = require("../../utils");
11
11
  class ExportTaxonomies extends base_class_1.default {
12
12
  constructor({ exportConfig, stackAPIClient }) {
13
13
  super({ exportConfig, stackAPIClient });
14
+ this.isLocaleBasedExportSupported = true; // Flag to track if locale-based export is supported
14
15
  this.taxonomies = {};
16
+ this.taxonomiesByLocale = {};
15
17
  this.taxonomiesConfig = exportConfig.modules.taxonomies;
16
18
  this.qs = { include_count: true, limit: this.taxonomiesConfig.limit || 100, skip: 0 };
17
19
  this.applyQueryFilters(this.qs, 'taxonomies');
18
- this.exportConfig.context.module = utils_1.MODULE_CONTEXTS.TAXONOMIES;
19
- this.currentModuleName = utils_1.MODULE_NAMES[utils_1.MODULE_CONTEXTS.TAXONOMIES];
20
+ this.exportConfig.context.module = 'taxonomies';
21
+ this.localesFilePath = (0, node_path_1.resolve)((0, cli_utilities_1.sanitizePath)(exportConfig.data), (0, cli_utilities_1.sanitizePath)(exportConfig.branchName || ''), (0, cli_utilities_1.sanitizePath)(exportConfig.modules.locales.dirName), (0, cli_utilities_1.sanitizePath)(exportConfig.modules.locales.fileName));
20
22
  }
21
23
  async start() {
22
24
  var _a;
23
- try {
24
- cli_utilities_1.log.debug('Starting taxonomies export process...', this.exportConfig.context);
25
- // Setup with loading spinner
26
- const [totalCount] = await this.withLoadingSpinner('TAXONOMIES: Analyzing taxonomy structure...', async () => {
27
- this.taxonomiesFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.taxonomiesConfig.dirName);
28
- await utils_1.fsUtil.makeDirectory(this.taxonomiesFolderPath);
29
- // Get count first for progress tracking
30
- const countResponse = await this.stack
31
- .taxonomy()
32
- .query(Object.assign(Object.assign({}, this.qs), { include_count: true, limit: 1 }))
33
- .find();
34
- return [countResponse.count || 0];
35
- });
36
- if (totalCount === 0) {
37
- cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('TAXONOMY_NOT_FOUND'), this.exportConfig.context);
38
- return;
39
- }
40
- // Create nested progress manager
41
- const progress = this.createNestedProgress(this.currentModuleName);
42
- // Add sub-processes
43
- progress.addProcess(utils_1.PROCESS_NAMES.FETCH_TAXONOMIES, totalCount);
44
- progress.addProcess(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS, totalCount);
45
- // Fetch taxonomies
46
- progress
47
- .startProcess(utils_1.PROCESS_NAMES.FETCH_TAXONOMIES)
48
- .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.FETCH_TAXONOMIES].FETCHING, utils_1.PROCESS_NAMES.FETCH_TAXONOMIES);
49
- await this.getAllTaxonomies();
50
- progress.completeProcess(utils_1.PROCESS_NAMES.FETCH_TAXONOMIES, true);
51
- const actualTaxonomyCount = (_a = Object.keys(this.taxonomies || {})) === null || _a === void 0 ? void 0 : _a.length;
52
- cli_utilities_1.log.debug(`Found ${actualTaxonomyCount} taxonomies to export (API reported ${totalCount})`, this.exportConfig.context);
53
- // Update progress for export step if counts differ
54
- if (actualTaxonomyCount !== totalCount && actualTaxonomyCount > 0) {
55
- // Remove the old process and add with correct count
56
- progress.addProcess(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS, actualTaxonomyCount);
57
- }
58
- // Export detailed taxonomies
59
- if (actualTaxonomyCount > 0) {
60
- progress
61
- .startProcess(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS)
62
- .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS].EXPORTING, utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS);
63
- await this.exportTaxonomies();
64
- progress.completeProcess(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS, true);
65
- }
66
- else {
67
- cli_utilities_1.log.info('No taxonomies found to export detailed information', this.exportConfig.context);
68
- }
69
- const taxonomyCount = Object.keys(this.taxonomies || {}).length;
70
- cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_COMPLETE', taxonomyCount), this.exportConfig.context);
71
- this.completeProgress(true);
25
+ cli_utilities_1.log.debug('Starting taxonomies export process...', this.exportConfig.context);
26
+ //create taxonomies folder
27
+ this.taxonomiesFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.taxonomiesConfig.dirName);
28
+ cli_utilities_1.log.debug(`Taxonomies folder path: ${this.taxonomiesFolderPath}`, this.exportConfig.context);
29
+ await utils_1.fsUtil.makeDirectory(this.taxonomiesFolderPath);
30
+ cli_utilities_1.log.debug('Created taxonomies directory', this.exportConfig.context);
31
+ const localesToExport = this.getLocalesToExport();
32
+ cli_utilities_1.log.debug(`Will attempt to export taxonomies for ${localesToExport.length} locale(s): ${localesToExport.join(', ')}`, this.exportConfig.context);
33
+ if (localesToExport.length === 0) {
34
+ cli_utilities_1.log.warn('No locales found to export', this.exportConfig.context);
35
+ return;
72
36
  }
73
- catch (error) {
74
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
75
- this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Taxonomies export failed');
37
+ // Test locale-based export support with master locale
38
+ const masterLocale = (_a = this.exportConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code;
39
+ await this.fetchTaxonomies(masterLocale, true);
40
+ if (!this.isLocaleBasedExportSupported) {
41
+ cli_utilities_1.log.debug('Localization disabled, falling back to legacy export method', this.exportConfig.context);
42
+ await this.exportTaxonomies();
43
+ await this.writeTaxonomiesMetadata();
44
+ }
45
+ else {
46
+ // Process all locales with locale-based export
47
+ cli_utilities_1.log.debug('Localization enabled, proceeding with locale-based export', this.exportConfig.context);
48
+ for (const localeCode of localesToExport) {
49
+ await this.fetchTaxonomies(localeCode);
50
+ await this.processLocaleExport(localeCode);
51
+ }
52
+ await this.writeTaxonomiesMetadata();
76
53
  }
54
+ cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_COMPLETE', (0, keys_1.default)(this.taxonomies || {}).length), this.exportConfig.context);
77
55
  }
78
56
  /**
79
- * Fetch in the provided stack
80
- * @param {number} skip
81
- * @returns {Promise<any>}
57
+ * Process and export taxonomies for a specific locale
82
58
  */
83
- async getAllTaxonomies(skip = 0) {
84
- var _a, _b;
85
- if (skip) {
86
- this.qs.skip = skip;
87
- cli_utilities_1.log.debug(`Fetching taxonomies with skip: ${skip}`, this.exportConfig.context);
59
+ async processLocaleExport(localeCode) {
60
+ const localeTaxonomies = this.taxonomiesByLocale[localeCode];
61
+ if ((localeTaxonomies === null || localeTaxonomies === void 0 ? void 0 : localeTaxonomies.size) > 0) {
62
+ cli_utilities_1.log.info(`Found ${localeTaxonomies.size} taxonomies for locale: ${localeCode}`, this.exportConfig.context);
63
+ await this.exportTaxonomies(localeCode);
88
64
  }
89
65
  else {
90
- cli_utilities_1.log.debug('Fetching taxonomies with initial query', this.exportConfig.context);
66
+ cli_utilities_1.log.debug(`No taxonomies found for locale: ${localeCode}`, this.exportConfig.context);
91
67
  }
92
- cli_utilities_1.log.debug(`Query parameters: ${JSON.stringify(this.qs)}`, this.exportConfig.context);
93
- let taxonomyResult = await this.stack.taxonomy().query(this.qs).find();
94
- cli_utilities_1.log.debug(`Fetched ${((_a = taxonomyResult.items) === null || _a === void 0 ? void 0 : _a.length) || 0} taxonomies out of total ${taxonomyResult.count}`, this.exportConfig.context);
95
- if ((taxonomyResult === null || taxonomyResult === void 0 ? void 0 : taxonomyResult.items) && ((_b = taxonomyResult === null || taxonomyResult === void 0 ? void 0 : taxonomyResult.items) === null || _b === void 0 ? void 0 : _b.length) > 0) {
96
- cli_utilities_1.log.debug(`Processing ${taxonomyResult.items.length} taxonomies`, this.exportConfig.context);
97
- this.sanitizeTaxonomiesAttribs(taxonomyResult.items);
98
- skip += this.taxonomiesConfig.limit;
99
- if (skip >= taxonomyResult.count) {
100
- cli_utilities_1.log.debug('Completed fetching all taxonomies', this.exportConfig.context);
101
- return;
102
- }
103
- cli_utilities_1.log.debug(`Continuing to fetch taxonomies with skip: ${skip}`, this.exportConfig.context);
104
- return await this.getAllTaxonomies(skip);
105
- }
106
- else {
68
+ }
69
+ /**
70
+ * Write taxonomies metadata file
71
+ */
72
+ async writeTaxonomiesMetadata() {
73
+ if (!this.taxonomies || (0, isEmpty_1.default)(this.taxonomies)) {
107
74
  cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('TAXONOMY_NOT_FOUND'), this.exportConfig.context);
75
+ return;
108
76
  }
77
+ const taxonomiesFilePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, 'taxonomies.json');
78
+ cli_utilities_1.log.debug(`Writing taxonomies metadata to: ${taxonomiesFilePath}`, this.exportConfig.context);
79
+ utils_1.fsUtil.writeFile(taxonomiesFilePath, this.taxonomies);
109
80
  }
110
- sanitizeTaxonomiesAttribs(taxonomies) {
81
+ /**
82
+ * Fetch taxonomies
83
+ *
84
+ * @async
85
+ * @param {?string} [localeCode]
86
+ * @param {boolean} [checkLocaleSupport=false]
87
+ * @returns {Promise<void>}
88
+ */
89
+ async fetchTaxonomies(localeCode, checkLocaleSupport = false) {
111
90
  var _a;
112
- cli_utilities_1.log.debug(`Sanitizing ${taxonomies.length} taxonomies`, this.exportConfig.context);
113
- for (let index = 0; index < (taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.length); index++) {
114
- const taxonomy = taxonomies[index];
115
- const taxonomyUid = taxonomy.uid;
116
- const taxonomyName = taxonomy === null || taxonomy === void 0 ? void 0 : taxonomy.name;
117
- cli_utilities_1.log.debug(`Processing taxonomy: ${taxonomyName} (${taxonomyUid})`, this.exportConfig.context);
118
- if (this.taxonomiesConfig.invalidKeys && this.taxonomiesConfig.invalidKeys.length > 0) {
119
- this.taxonomies[taxonomyUid] = (0, omit_1.default)(taxonomy, this.taxonomiesConfig.invalidKeys);
91
+ let skip = 0;
92
+ const localeInfo = localeCode ? `for locale: ${localeCode}` : '';
93
+ if (localeCode && !this.taxonomiesByLocale[localeCode]) {
94
+ this.taxonomiesByLocale[localeCode] = new Set();
95
+ }
96
+ do {
97
+ const queryParams = Object.assign(Object.assign({}, this.qs), { skip });
98
+ if (localeCode) {
99
+ queryParams.locale = localeCode;
120
100
  }
121
- else {
122
- this.taxonomies[taxonomyUid] = taxonomy;
101
+ cli_utilities_1.log.debug(`Fetching taxonomies ${localeInfo} with skip: ${skip}`, this.exportConfig.context);
102
+ try {
103
+ const data = await this.stack.taxonomy().query(queryParams).find();
104
+ const { items, count } = data;
105
+ const taxonomiesCount = (_a = count !== null && count !== void 0 ? count : items === null || items === void 0 ? void 0 : items.length) !== null && _a !== void 0 ? _a : 0;
106
+ cli_utilities_1.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} taxonomies out of total ${taxonomiesCount} ${localeInfo}`, this.exportConfig.context);
107
+ if (!(items === null || items === void 0 ? void 0 : items.length)) {
108
+ cli_utilities_1.log.debug(`No taxonomies found ${localeInfo}`, this.exportConfig.context);
109
+ break;
110
+ }
111
+ // Check localization support
112
+ if (checkLocaleSupport && localeCode && skip === 0 && !items[0].locale) {
113
+ cli_utilities_1.log.debug('API does not support locale-based taxonomy export', this.exportConfig.context);
114
+ this.isLocaleBasedExportSupported = false;
115
+ }
116
+ this.sanitizeTaxonomiesAttribs(items, localeCode);
117
+ skip += this.qs.limit || 100;
118
+ if (skip >= taxonomiesCount) {
119
+ cli_utilities_1.log.debug(`Completed fetching all taxonomies ${localeInfo}`, this.exportConfig.context);
120
+ break;
121
+ }
122
+ }
123
+ catch (error) {
124
+ cli_utilities_1.log.debug(`Error fetching taxonomies ${localeInfo}`, this.exportConfig.context);
125
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), (localeCode && { locale: localeCode })));
126
+ if (checkLocaleSupport) {
127
+ this.isLocaleBasedExportSupported = false;
128
+ }
129
+ // Break to avoid infinite retry loop on errors
130
+ break;
131
+ }
132
+ } while (true);
133
+ }
134
+ /**
135
+ * remove invalid keys and write data into taxonomies
136
+ * @function sanitizeTaxonomiesAttribs
137
+ * @param {Record<string, string>[]} taxonomies
138
+ * @param {?string} [localeCode]
139
+ */
140
+ sanitizeTaxonomiesAttribs(taxonomies, localeCode) {
141
+ const localeInfo = localeCode ? ` for locale: ${localeCode}` : '';
142
+ cli_utilities_1.log.debug(`Processing ${taxonomies.length} taxonomies${localeInfo}`, this.exportConfig.context);
143
+ for (const taxonomy of taxonomies) {
144
+ const taxonomyUID = taxonomy.uid;
145
+ const taxonomyName = taxonomy.name;
146
+ cli_utilities_1.log.debug(`Processing taxonomy: ${taxonomyName} (${taxonomyUID})${localeInfo}`, this.exportConfig.context);
147
+ // Store taxonomy metadata (only once per taxonomy)
148
+ if (!this.taxonomies[taxonomyUID]) {
149
+ this.taxonomies[taxonomyUID] = (0, omit_1.default)(taxonomy, this.taxonomiesConfig.invalidKeys);
150
+ }
151
+ // Track taxonomy for this locale
152
+ if (localeCode) {
153
+ this.taxonomiesByLocale[localeCode].add(taxonomyUID);
123
154
  }
124
- // Track progress for each taxonomy
125
- (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `taxonomy: ${taxonomyName || taxonomyUid}`, null, utils_1.PROCESS_NAMES.FETCH_TAXONOMIES);
126
155
  }
127
- cli_utilities_1.log.debug(`Sanitization complete. Total taxonomies processed: ${Object.keys(this.taxonomies || {}).length}`, this.exportConfig.context);
156
+ cli_utilities_1.log.debug(`Processing complete${localeInfo}. Total taxonomies processed: ${(0, keys_1.default)(this.taxonomies).length}`, this.exportConfig.context);
128
157
  }
129
158
  /**
130
- * Export all taxonomies details using metadata(this.taxonomies) and write it into respective <taxonomy-uid>.json file
131
- * @returns {Promise<any>}
159
+ * Export taxonomies - supports both locale-based and legacy export
132
160
  */
133
- async exportTaxonomies() {
134
- var _a;
135
- cli_utilities_1.log.debug(`Exporting ${(_a = Object.keys(this.taxonomies || {})) === null || _a === void 0 ? void 0 : _a.length} taxonomies with detailed information`, this.exportConfig.context);
136
- if ((0, isEmpty_1.default)(this.taxonomies)) {
137
- cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('TAXONOMY_NOT_FOUND'), this.exportConfig.context);
161
+ async exportTaxonomies(localeCode) {
162
+ const taxonomiesUID = localeCode ? Array.from(this.taxonomiesByLocale[localeCode] || []) : (0, keys_1.default)(this.taxonomies);
163
+ const localeInfo = localeCode ? ` for locale: ${localeCode}` : '';
164
+ if (taxonomiesUID.length === 0) {
165
+ cli_utilities_1.log.debug(`No taxonomies to export${localeInfo}`, this.exportConfig.context);
138
166
  return;
139
167
  }
168
+ cli_utilities_1.log.debug(`Exporting detailed data for ${taxonomiesUID.length} taxonomies${localeInfo}`, this.exportConfig.context);
169
+ const exportFolderPath = localeCode ? (0, node_path_1.resolve)(this.taxonomiesFolderPath, localeCode) : this.taxonomiesFolderPath;
170
+ if (localeCode) {
171
+ await utils_1.fsUtil.makeDirectory(exportFolderPath);
172
+ cli_utilities_1.log.debug(`Created locale folder: ${exportFolderPath}`, this.exportConfig.context);
173
+ }
140
174
  const onSuccess = ({ response, uid }) => {
141
- var _a, _b;
142
- const taxonomyName = (_a = this.taxonomies[uid]) === null || _a === void 0 ? void 0 : _a.name;
143
- const filePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, `${uid}.json`);
144
- cli_utilities_1.log.debug(`Writing detailed taxonomy to: ${filePath}`, this.exportConfig.context);
175
+ const filePath = (0, node_path_1.resolve)(exportFolderPath, `${uid}.json`);
176
+ cli_utilities_1.log.debug(`Writing detailed taxonomy data to: ${filePath}`, this.exportConfig.context);
145
177
  utils_1.fsUtil.writeFile(filePath, response);
146
- // Track progress for each exported taxonomy
147
- (_b = this.progressManager) === null || _b === void 0 ? void 0 : _b.tick(true, `taxonomy: ${taxonomyName || uid}`, null, utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS);
148
- cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_SUCCESS', taxonomyName || uid), this.exportConfig.context);
178
+ cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_SUCCESS', uid), this.exportConfig.context);
149
179
  };
150
180
  const onReject = ({ error, uid }) => {
151
- var _a, _b;
152
- const taxonomyName = (_a = this.taxonomies[uid]) === null || _a === void 0 ? void 0 : _a.name;
153
- // Track failure
154
- (_b = this.progressManager) === null || _b === void 0 ? void 0 : _b.tick(false, `taxonomy: ${taxonomyName || uid}`, (error === null || error === void 0 ? void 0 : error.message) || utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS].FAILED, utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS);
155
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), { uid }), cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_FAILED', taxonomyName || uid));
181
+ cli_utilities_1.log.debug(`Failed to export detailed data for taxonomy: ${uid}${localeInfo}`, this.exportConfig.context);
182
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign(Object.assign({}, this.exportConfig.context), { uid }), (localeCode && { locale: localeCode })));
156
183
  };
157
- const taxonomyUids = (0, keys_1.default)(this.taxonomies);
158
- cli_utilities_1.log.debug(`Starting detailed export for ${taxonomyUids.length} taxonomies`, this.exportConfig.context);
159
- // Export each taxonomy individually
160
- for (const uid of taxonomyUids) {
161
- try {
162
- cli_utilities_1.log.debug(`Exporting detailed taxonomy: ${uid}`, this.exportConfig.context);
163
- await this.makeAPICall({
164
- module: 'export-taxonomy',
165
- uid,
166
- resolve: onSuccess,
167
- reject: onReject,
168
- });
184
+ for (const taxonomyUID of taxonomiesUID) {
185
+ cli_utilities_1.log.debug(`Processing detailed export for taxonomy: ${taxonomyUID}${localeInfo}`, this.exportConfig.context);
186
+ const exportParams = { format: 'json' };
187
+ if (localeCode) {
188
+ exportParams.locale = localeCode;
189
+ if (this.qs.include_fallback !== undefined)
190
+ exportParams.include_fallback = this.qs.include_fallback;
191
+ if (this.qs.fallback_locale)
192
+ exportParams.fallback_locale = this.qs.fallback_locale;
169
193
  }
170
- catch (error) {
171
- onReject({ error, uid });
194
+ if (this.qs.branch)
195
+ exportParams.branch = this.qs.branch;
196
+ await this.makeAPICall({
197
+ reject: onReject,
198
+ resolve: onSuccess,
199
+ uid: taxonomyUID,
200
+ module: 'export-taxonomy',
201
+ queryParam: exportParams,
202
+ });
203
+ }
204
+ cli_utilities_1.log.debug(`Completed detailed taxonomy export process${localeInfo}`, this.exportConfig.context);
205
+ }
206
+ /**
207
+ * Get all locales to export
208
+ */
209
+ getLocalesToExport() {
210
+ var _a;
211
+ cli_utilities_1.log.debug('Determining locales to export...', this.exportConfig.context);
212
+ const masterLocaleCode = ((_a = this.exportConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code) || 'en-us';
213
+ const localeSet = new Set([masterLocaleCode]);
214
+ try {
215
+ const locales = utils_1.fsUtil.readFile(this.localesFilePath);
216
+ if (locales && (0, keys_1.default)(locales || {}).length > 0) {
217
+ cli_utilities_1.log.debug(`Loaded ${(0, keys_1.default)(locales || {}).length} locales from ${this.localesFilePath}`, this.exportConfig.context);
218
+ for (const localeUid of (0, keys_1.default)(locales)) {
219
+ const localeCode = locales[localeUid].code;
220
+ if (localeCode && !localeSet.has(localeCode)) {
221
+ localeSet.add(localeCode);
222
+ cli_utilities_1.log.debug(`Added locale: ${localeCode} (uid: ${localeUid})`, this.exportConfig.context);
223
+ }
224
+ }
225
+ }
226
+ else {
227
+ cli_utilities_1.log.debug(`No locales found in ${this.localesFilePath}`, this.exportConfig.context);
172
228
  }
173
229
  }
174
- // Write the taxonomies index file
175
- const taxonomiesFilePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, this.taxonomiesConfig.fileName);
176
- cli_utilities_1.log.debug(`Writing taxonomies index to: ${taxonomiesFilePath}`, this.exportConfig.context);
177
- utils_1.fsUtil.writeFile(taxonomiesFilePath, this.taxonomies);
230
+ catch (error) {
231
+ cli_utilities_1.log.warn(`Failed to read locales file: ${this.localesFilePath}`, this.exportConfig.context);
232
+ }
233
+ const localesToExport = Array.from(localeSet);
234
+ cli_utilities_1.log.debug(`Total unique locales to export: ${localesToExport.length}`, this.exportConfig.context);
235
+ return localesToExport;
178
236
  }
179
237
  }
180
238
  exports.default = ExportTaxonomies;
@@ -7,86 +7,92 @@ const constants_1 = require("./constants");
7
7
  * to ensure correct item counts in the final summary.
8
8
  */
9
9
  const cli_utilities_1 = require("@contentstack/cli-utilities");
10
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.CONTENT_TYPES], new cli_utilities_1.DefaultProgressStrategy());
11
- // Register strategy for Assets - custom strategy to avoid double counting
12
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ASSETS], new cli_utilities_1.CustomProgressStrategy((processes) => {
13
- // Both ASSET_METADATA and ASSET_DOWNLOADS represent the same assets
14
- // Count only the downloads process to avoid double counting in summary
15
- const downloadsProcess = processes.get(constants_1.PROCESS_NAMES.ASSET_DOWNLOADS);
16
- if (downloadsProcess) {
17
- return {
18
- total: downloadsProcess.total,
19
- success: downloadsProcess.successCount,
20
- failures: downloadsProcess.failureCount,
21
- };
22
- }
23
- // Fallback to metadata process if downloads don't exist
24
- const metadataProcess = processes.get(constants_1.PROCESS_NAMES.ASSET_METADATA);
25
- if (metadataProcess) {
26
- return {
27
- total: metadataProcess.total,
28
- success: metadataProcess.successCount,
29
- failures: metadataProcess.failureCount,
30
- };
31
- }
32
- return null; // Fall back to default aggregation
33
- }));
34
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.GLOBAL_FIELDS], new cli_utilities_1.DefaultProgressStrategy());
35
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.EXTENSIONS], new cli_utilities_1.DefaultProgressStrategy());
36
- // Register strategy for Environments - simple module
37
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ENVIRONMENTS], new cli_utilities_1.DefaultProgressStrategy());
38
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.LOCALES], new cli_utilities_1.DefaultProgressStrategy());
39
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.LABELS], new cli_utilities_1.DefaultProgressStrategy());
40
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.WEBHOOKS], new cli_utilities_1.DefaultProgressStrategy());
41
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.WORKFLOWS], new cli_utilities_1.DefaultProgressStrategy());
42
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.CUSTOM_ROLES], new cli_utilities_1.DefaultProgressStrategy());
43
- // Register strategy for Taxonomies - use Taxonomies & Terms as primary process
44
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.TAXONOMIES], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS));
45
- // Register strategy for Marketplace Apps - complex module with app installations
46
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.MARKETPLACE_APPS], new cli_utilities_1.CustomProgressStrategy((processes) => {
47
- // For marketplace apps, count the actual apps exported
48
- const appsExport = processes.get(constants_1.PROCESS_NAMES.FETCH_APPS);
49
- if (appsExport) {
50
- return {
51
- total: appsExport.total,
52
- success: appsExport.successCount,
53
- failures: appsExport.failureCount,
54
- };
55
- }
56
- const setup = processes.get(constants_1.PROCESS_NAMES.FETCH_CONFIG_MANIFEST);
57
- if (setup) {
58
- return {
59
- total: setup.total,
60
- success: setup.successCount,
61
- failures: setup.failureCount,
62
- };
63
- }
64
- return null;
65
- }));
66
- // Register strategy for Stack Settings - use Settings as primary process
67
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.STACK], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.STACK_SETTINGS));
68
- // Register strategy for Personalize - complex module with projects/experiences
69
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.PERSONALIZE], new cli_utilities_1.CustomProgressStrategy((processes) => {
70
- // For personalize, we want to count projects as the main metric
71
- const projectExport = processes.get(constants_1.PROCESS_NAMES.PERSONALIZE_PROJECTS);
72
- if (projectExport) {
73
- return {
74
- total: projectExport.total,
75
- success: projectExport.successCount,
76
- failures: projectExport.failureCount,
77
- };
78
- }
79
- // Fallback to any other main process
80
- const mainProcess = Array.from(processes.values())[0];
81
- if (mainProcess) {
82
- return {
83
- total: mainProcess.total,
84
- success: mainProcess.successCount,
85
- failures: mainProcess.failureCount,
86
- };
87
- }
88
- return null;
89
- }));
90
- // Register strategy for Entries - use Entries as primary process
91
- cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ENTRIES], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.ENTRIES));
10
+ // Wrap all registrations in try-catch to prevent module loading errors
11
+ try {
12
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.CONTENT_TYPES], new cli_utilities_1.DefaultProgressStrategy());
13
+ // Register strategy for Assets - custom strategy to avoid double counting
14
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ASSETS], new cli_utilities_1.CustomProgressStrategy((processes) => {
15
+ // Both ASSET_METADATA and ASSET_DOWNLOADS represent the same assets
16
+ // Count only the downloads process to avoid double counting in summary
17
+ const downloadsProcess = processes.get(constants_1.PROCESS_NAMES.ASSET_DOWNLOADS);
18
+ if (downloadsProcess) {
19
+ return {
20
+ total: downloadsProcess.total,
21
+ success: downloadsProcess.successCount,
22
+ failures: downloadsProcess.failureCount,
23
+ };
24
+ }
25
+ // Fallback to metadata process if downloads don't exist
26
+ const metadataProcess = processes.get(constants_1.PROCESS_NAMES.ASSET_METADATA);
27
+ if (metadataProcess) {
28
+ return {
29
+ total: metadataProcess.total,
30
+ success: metadataProcess.successCount,
31
+ failures: metadataProcess.failureCount,
32
+ };
33
+ }
34
+ return null; // Fall back to default aggregation
35
+ }));
36
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.GLOBAL_FIELDS], new cli_utilities_1.DefaultProgressStrategy());
37
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.EXTENSIONS], new cli_utilities_1.DefaultProgressStrategy());
38
+ // Register strategy for Environments - simple module
39
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ENVIRONMENTS], new cli_utilities_1.DefaultProgressStrategy());
40
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.LOCALES], new cli_utilities_1.DefaultProgressStrategy());
41
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.LABELS], new cli_utilities_1.DefaultProgressStrategy());
42
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.WEBHOOKS], new cli_utilities_1.DefaultProgressStrategy());
43
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.WORKFLOWS], new cli_utilities_1.DefaultProgressStrategy());
44
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.CUSTOM_ROLES], new cli_utilities_1.DefaultProgressStrategy());
45
+ // Register strategy for Taxonomies - use Taxonomies & Terms as primary process
46
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.TAXONOMIES], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS));
47
+ // Register strategy for Marketplace Apps - complex module with app installations
48
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.MARKETPLACE_APPS], new cli_utilities_1.CustomProgressStrategy((processes) => {
49
+ // For marketplace apps, count the actual apps exported
50
+ const appsExport = processes.get(constants_1.PROCESS_NAMES.FETCH_APPS);
51
+ if (appsExport) {
52
+ return {
53
+ total: appsExport.total,
54
+ success: appsExport.successCount,
55
+ failures: appsExport.failureCount,
56
+ };
57
+ }
58
+ const setup = processes.get(constants_1.PROCESS_NAMES.FETCH_CONFIG_MANIFEST);
59
+ if (setup) {
60
+ return {
61
+ total: setup.total,
62
+ success: setup.successCount,
63
+ failures: setup.failureCount,
64
+ };
65
+ }
66
+ return null;
67
+ }));
68
+ // Register strategy for Stack Settings - use Settings as primary process
69
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.STACK], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.STACK_SETTINGS));
70
+ // Register strategy for Personalize - complex module with projects/experiences
71
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.PERSONALIZE], new cli_utilities_1.CustomProgressStrategy((processes) => {
72
+ // For personalize, we want to count projects as the main metric
73
+ const projectExport = processes.get(constants_1.PROCESS_NAMES.PERSONALIZE_PROJECTS);
74
+ if (projectExport) {
75
+ return {
76
+ total: projectExport.total,
77
+ success: projectExport.successCount,
78
+ failures: projectExport.failureCount,
79
+ };
80
+ }
81
+ // Fallback to any other main process
82
+ const mainProcess = Array.from(processes.values())[0];
83
+ if (mainProcess) {
84
+ return {
85
+ total: mainProcess.total,
86
+ success: mainProcess.successCount,
87
+ failures: mainProcess.failureCount,
88
+ };
89
+ }
90
+ return null;
91
+ }));
92
+ // Register strategy for Entries - use Entries as primary process
93
+ cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ENTRIES], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.ENTRIES));
94
+ }
95
+ catch (error) {
96
+ // Silently ignore registration errors during module loading
97
+ }
92
98
  exports.default = cli_utilities_1.ProgressStrategyRegistry;
@@ -159,5 +159,5 @@
159
159
  ]
160
160
  }
161
161
  },
162
- "version": "2.0.0-beta"
162
+ "version": "2.0.0-beta.2"
163
163
  }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@contentstack/cli-cm-export",
3
3
  "description": "Contentstack CLI plugin to export content from stack",
4
- "version": "2.0.0-beta",
4
+ "version": "2.0.0-beta.2",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
8
8
  "@contentstack/cli-command": "~1.6.1",
9
9
  "@contentstack/cli-variants": "~2.0.0-beta",
10
10
  "@oclif/core": "^4.3.3",
11
- "@contentstack/cli-utilities": "~1.14.1",
11
+ "@contentstack/cli-utilities": "~1.15.0",
12
12
  "async": "^3.2.6",
13
13
  "big-json": "^3.2.0",
14
14
  "bluebird": "^3.7.2",
@@ -27,8 +27,12 @@
27
27
  "@oclif/plugin-help": "^6.2.28",
28
28
  "@oclif/test": "^4.1.13",
29
29
  "@types/big-json": "^3.2.5",
30
+ "@types/chai": "^4.3.11",
30
31
  "@types/mkdirp": "^1.0.2",
32
+ "@types/mocha": "^10.0.6",
31
33
  "@types/progress-stream": "^2.0.5",
34
+ "@types/sinon": "^17.0.2",
35
+ "chai": "^4.4.1",
32
36
  "dotenv": "^16.5.0",
33
37
  "dotenv-expand": "^9.0.0",
34
38
  "eslint": "^8.57.1",
@@ -36,6 +40,8 @@
36
40
  "mocha": "10.8.2",
37
41
  "nyc": "^15.1.0",
38
42
  "oclif": "^4.17.46",
43
+ "sinon": "^17.0.1",
44
+ "source-map-support": "^0.5.21",
39
45
  "ts-node": "^10.9.2",
40
46
  "typescript": "^4.9.5"
41
47
  },
@@ -54,7 +60,8 @@
54
60
  "format": "eslint src/**/*.ts --fix",
55
61
  "test:integration": "INTEGRATION_TEST=true mocha --config ./test/.mocharc.js --forbid-only \"test/run.test.js\"",
56
62
  "test:integration:report": "INTEGRATION_TEST=true nyc --extension .js mocha --forbid-only \"test/run.test.js\"",
57
- "test:unit": "mocha --forbid-only \"test/unit/*.test.ts\""
63
+ "test:unit": "mocha --forbid-only \"test/unit/**/*.test.ts\"",
64
+ "test:unit:report": "nyc --reporter=text --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\""
58
65
  },
59
66
  "engines": {
60
67
  "node": ">=14.0.0"