@contentstack/cli-cm-export 1.20.2 → 1.22.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.
@@ -17,20 +17,20 @@ class ExportStack extends base_class_1.default {
17
17
  async start() {
18
18
  cli_utilities_1.log.debug('Starting stack export process...', this.exportConfig.context);
19
19
  if ((0, cli_utilities_1.isAuthenticated)()) {
20
- cli_utilities_1.log.debug('User is authenticated, fetching stack data...', this.exportConfig.context);
20
+ cli_utilities_1.log.debug('User authenticated.', this.exportConfig.context);
21
21
  const stackData = await this.getStack();
22
22
  if (stackData === null || stackData === void 0 ? void 0 : stackData.org_uid) {
23
- cli_utilities_1.log.debug(`Found organization UID: ${stackData.org_uid}`, this.exportConfig.context);
23
+ cli_utilities_1.log.debug(`Found organization UID: '${stackData.org_uid}'.`, this.exportConfig.context);
24
24
  this.exportConfig.org_uid = stackData.org_uid;
25
25
  this.exportConfig.sourceStackName = stackData.name;
26
- cli_utilities_1.log.debug(`Set source stack name: ${stackData.name}`, this.exportConfig.context);
26
+ cli_utilities_1.log.debug(`Set source stack name: '${stackData.name}'.`, this.exportConfig.context);
27
27
  }
28
28
  else {
29
- cli_utilities_1.log.debug('No stack data found or missing org_uid', this.exportConfig.context);
29
+ cli_utilities_1.log.debug('No stack data found or missing organization UID.', this.exportConfig.context);
30
30
  }
31
31
  }
32
32
  else {
33
- cli_utilities_1.log.debug('User is not authenticated, skipping stack data fetch', this.exportConfig.context);
33
+ cli_utilities_1.log.debug('User is not authenticated.', this.exportConfig.context);
34
34
  }
35
35
  if (this.exportConfig.management_token) {
36
36
  cli_utilities_1.log.info('Skipping stack settings export: Operation is not supported when using a management token.', this.exportConfig.context);
@@ -44,61 +44,61 @@ class ExportStack extends base_class_1.default {
44
44
  return this.getLocales();
45
45
  }
46
46
  else if (this.exportConfig.preserveStackVersion) {
47
- cli_utilities_1.log.debug('Preserve stack version is true, exporting stack...', this.exportConfig.context);
47
+ cli_utilities_1.log.debug('Preserve stack version is set to true.', this.exportConfig.context);
48
48
  return this.exportStack();
49
49
  }
50
50
  else {
51
- cli_utilities_1.log.debug('Master locale already set, skipping locale fetch', this.exportConfig.context);
51
+ cli_utilities_1.log.debug('Master locale is already set.', this.exportConfig.context);
52
52
  }
53
53
  }
54
54
  async getStack() {
55
- cli_utilities_1.log.debug(`Fetching stack data for stack: ${this.exportConfig.source_stack}`, this.exportConfig.context);
55
+ cli_utilities_1.log.debug(`Fetching stack data for: '${this.exportConfig.source_stack}'...`, this.exportConfig.context);
56
56
  const tempAPIClient = await (0, cli_utilities_1.managementSDKClient)({ host: this.exportConfig.host });
57
- cli_utilities_1.log.debug(`Created management SDK client with host: ${this.exportConfig.host}`, this.exportConfig.context);
57
+ cli_utilities_1.log.debug(`Created Management SDK client with host: '${this.exportConfig.host}'.`, this.exportConfig.context);
58
58
  return await tempAPIClient
59
59
  .stack({ api_key: this.exportConfig.source_stack })
60
60
  .fetch()
61
61
  .then((data) => {
62
- cli_utilities_1.log.debug(`Successfully fetched stack data for: ${this.exportConfig.source_stack}`, this.exportConfig.context);
62
+ cli_utilities_1.log.debug(`Successfully fetched stack data for: '${this.exportConfig.source_stack}'.`, this.exportConfig.context);
63
63
  return data;
64
64
  })
65
65
  .catch((error) => {
66
- cli_utilities_1.log.debug(`Failed to fetch stack data for: ${this.exportConfig.source_stack}`, this.exportConfig.context);
66
+ cli_utilities_1.log.debug(`Failed to fetch stack data for: '${this.exportConfig.source_stack}'.`, this.exportConfig.context);
67
67
  return {};
68
68
  });
69
69
  }
70
70
  async getLocales(skip = 0) {
71
71
  if (skip) {
72
72
  this.qs.skip = skip;
73
- cli_utilities_1.log.debug(`Fetching locales with skip: ${skip}`, this.exportConfig.context);
73
+ cli_utilities_1.log.debug(`Fetching locales with skip: ${skip}.`, this.exportConfig.context);
74
74
  }
75
75
  else {
76
- cli_utilities_1.log.debug('Fetching locales with initial query', this.exportConfig.context);
76
+ cli_utilities_1.log.debug('Fetching locales with initial query...', this.exportConfig.context);
77
77
  }
78
- cli_utilities_1.log.debug(`Query parameters: ${JSON.stringify(this.qs)}`, this.exportConfig.context);
78
+ cli_utilities_1.log.debug(`Query parameters: ${JSON.stringify(this.qs)}.`, this.exportConfig.context);
79
79
  return await this.stack
80
80
  .locale()
81
81
  .query(this.qs)
82
82
  .find()
83
83
  .then(async (data) => {
84
84
  const { items, count } = data;
85
- cli_utilities_1.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} locales out of total ${count}`, this.exportConfig.context);
85
+ cli_utilities_1.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} locales out of ${count}.`, this.exportConfig.context);
86
86
  if (items === null || items === void 0 ? void 0 : items.length) {
87
- cli_utilities_1.log.debug(`Processing ${items.length} locales to find master locale`, this.exportConfig.context);
87
+ cli_utilities_1.log.debug(`Processing ${items.length} locales to find the master locale...`, this.exportConfig.context);
88
88
  skip += this.stackConfig.limit || 100;
89
89
  const masterLocalObj = (0, find_1.default)(items, (locale) => {
90
90
  if (locale.fallback_locale === null) {
91
- cli_utilities_1.log.debug(`Found master locale: ${locale.name} (${locale.code})`, this.exportConfig.context);
91
+ cli_utilities_1.log.debug(`Found master locale: '${locale.name}' (code: ${locale.code}).`, this.exportConfig.context);
92
92
  return locale;
93
93
  }
94
94
  });
95
95
  if (masterLocalObj) {
96
- cli_utilities_1.log.debug(`Returning master locale: ${masterLocalObj.name}`, this.exportConfig.context);
96
+ cli_utilities_1.log.debug(`Returning master locale: '${masterLocalObj.name}'.`, this.exportConfig.context);
97
97
  return masterLocalObj;
98
98
  }
99
99
  else if (skip >= count) {
100
100
  cli_utilities_1.log.error(`Master locale not found in the stack ${this.exportConfig.source_stack}. Please ensure that the stack has a master locale.`, this.exportConfig.context);
101
- cli_utilities_1.log.debug('Completed searching all locales without finding master locale', this.exportConfig.context);
101
+ cli_utilities_1.log.debug('Completed search. Master locale not found.', this.exportConfig.context);
102
102
  return;
103
103
  }
104
104
  else {
@@ -107,7 +107,7 @@ class ExportStack extends base_class_1.default {
107
107
  }
108
108
  }
109
109
  else {
110
- cli_utilities_1.log.debug('No locales found to process', this.exportConfig.context);
110
+ cli_utilities_1.log.debug('No locales found to process.', this.exportConfig.context);
111
111
  }
112
112
  })
113
113
  .catch((error) => {
@@ -117,26 +117,26 @@ class ExportStack extends base_class_1.default {
117
117
  });
118
118
  }
119
119
  async exportStack() {
120
- cli_utilities_1.log.debug(`Starting stack export for: ${this.exportConfig.source_stack}`, this.exportConfig.context);
120
+ cli_utilities_1.log.debug(`Starting stack export for: '${this.exportConfig.source_stack}'...`, this.exportConfig.context);
121
121
  await utils_1.fsUtil.makeDirectory(this.stackFolderPath);
122
- cli_utilities_1.log.debug(`Created stack directory at: ${this.stackFolderPath}`, this.exportConfig.context);
122
+ cli_utilities_1.log.debug(`Created stack directory at: '${this.stackFolderPath}'`, this.exportConfig.context);
123
123
  return this.stack
124
124
  .fetch()
125
125
  .then((resp) => {
126
126
  const stackFilePath = (0, node_path_1.resolve)(this.stackFolderPath, this.stackConfig.fileName);
127
- cli_utilities_1.log.debug(`Writing stack data to: ${stackFilePath}`, this.exportConfig.context);
127
+ cli_utilities_1.log.debug(`Writing stack data to: '${stackFilePath}'`, this.exportConfig.context);
128
128
  utils_1.fsUtil.writeFile(stackFilePath, resp);
129
129
  cli_utilities_1.log.success(`Stack details exported successfully for stack ${this.exportConfig.source_stack}`, this.exportConfig.context);
130
- cli_utilities_1.log.debug('Stack export completed successfully', this.exportConfig.context);
130
+ cli_utilities_1.log.debug('Stack export completed successfully.', this.exportConfig.context);
131
131
  return resp;
132
132
  })
133
133
  .catch((error) => {
134
- cli_utilities_1.log.debug(`Error occurred while exporting stack: ${this.exportConfig.source_stack}`, this.exportConfig.context);
134
+ cli_utilities_1.log.debug(`An error occurred while exporting stack: '${this.exportConfig.source_stack}'.`, this.exportConfig.context);
135
135
  (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
136
136
  });
137
137
  }
138
138
  async exportStackSettings() {
139
- cli_utilities_1.log.info('Exporting stack settings', this.exportConfig.context);
139
+ cli_utilities_1.log.info('Exporting stack settings...', this.exportConfig.context);
140
140
  await utils_1.fsUtil.makeDirectory(this.stackFolderPath);
141
141
  return this.stack
142
142
  .settings()
@@ -2,26 +2,45 @@ 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 all taxonomies 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
+ processLocaleExport(localeCode: string): Promise<void>;
17
+ /**
18
+ * Write taxonomies metadata file
19
+ */
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>;
16
30
  /**
17
31
  * remove invalid keys and write data into taxonomies
18
32
  * @function sanitizeTaxonomiesAttribs
19
- * @param taxonomies
33
+ * @param {Record<string, string>[]} taxonomies
34
+ * @param {?string} [localeCode]
20
35
  */
21
- sanitizeTaxonomiesAttribs(taxonomies: Record<string, string>[]): void;
36
+ sanitizeTaxonomiesAttribs(taxonomies: Record<string, string>[], localeCode?: string): void;
22
37
  /**
23
- * Export all taxonomies details using metadata(this.taxonomies) and write it into respective <taxonomy-uid>.json file
24
- * @returns {Promise<void>}
38
+ * Export taxonomies - supports both locale-based and legacy export
39
+ */
40
+ exportTaxonomies(localeCode?: string): Promise<void>;
41
+ /**
42
+ * Get all locales to export
25
43
  */
26
- exportTaxonomies(): Promise<void>;
44
+ getLocalesToExport(): string[];
45
+ private isLocalePlanLimitationError;
27
46
  }
@@ -11,122 +11,245 @@ 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
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));
19
22
  }
20
23
  async start() {
21
- cli_utilities_1.log.debug('Starting taxonomies export process...', this.exportConfig.context);
24
+ var _a;
25
+ cli_utilities_1.log.debug('Starting export process for taxonomies...', this.exportConfig.context);
22
26
  //create taxonomies folder
23
27
  this.taxonomiesFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.taxonomiesConfig.dirName);
24
- cli_utilities_1.log.debug(`Taxonomies folder path: ${this.taxonomiesFolderPath}`, this.exportConfig.context);
28
+ cli_utilities_1.log.debug(`Taxonomies folder path: '${this.taxonomiesFolderPath}'`, this.exportConfig.context);
25
29
  await utils_1.fsUtil.makeDirectory(this.taxonomiesFolderPath);
26
- cli_utilities_1.log.debug('Created taxonomies directory', this.exportConfig.context);
27
- //fetch all taxonomies and write into taxonomies folder
28
- cli_utilities_1.log.debug('Fetching all taxonomies...', this.exportConfig.context);
29
- await this.getAllTaxonomies();
30
- cli_utilities_1.log.debug(`Retrieved ${Object.keys(this.taxonomies).length} taxonomies`, this.exportConfig.context);
31
- if (this.taxonomies === undefined || (0, isEmpty_1.default)(this.taxonomies)) {
32
- cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('TAXONOMY_NOT_FOUND'), this.exportConfig.context);
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);
33
35
  return;
34
36
  }
35
- else {
36
- const taxonomiesFilePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, 'taxonomies.json');
37
- cli_utilities_1.log.debug(`Writing taxonomies metadata to: ${taxonomiesFilePath}`, this.exportConfig.context);
38
- utils_1.fsUtil.writeFile(taxonomiesFilePath, this.taxonomies);
39
- cli_utilities_1.log.debug('Starting detailed taxonomy export...', this.exportConfig.context);
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
+ this.taxonomies = {};
42
+ this.taxonomiesByLocale = {};
43
+ // Fetch taxonomies without locale parameter
44
+ await this.fetchTaxonomies();
40
45
  await this.exportTaxonomies();
46
+ await this.writeTaxonomiesMetadata();
47
+ }
48
+ else {
49
+ // Process all locales with locale-based export
50
+ cli_utilities_1.log.debug('Localization enabled, proceeding with locale-based export', this.exportConfig.context);
51
+ for (const localeCode of localesToExport) {
52
+ await this.fetchTaxonomies(localeCode);
53
+ await this.processLocaleExport(localeCode);
54
+ }
55
+ await this.writeTaxonomiesMetadata();
41
56
  }
42
- cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_COMPLETE', (0, keys_1.default)(this.taxonomies).length), this.exportConfig.context);
57
+ cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_COMPLETE', (0, keys_1.default)(this.taxonomies || {}).length), this.exportConfig.context);
43
58
  }
44
59
  /**
45
- * fetch all taxonomies in the provided stack
46
- * @param {number} skip
47
- * @returns {Promise<any>}
60
+ * Process and export taxonomies for a specific locale
48
61
  */
49
- async getAllTaxonomies(skip = 0) {
50
- if (skip) {
51
- this.qs.skip = skip;
52
- cli_utilities_1.log.debug(`Fetching taxonomies with skip: ${skip}`, this.exportConfig.context);
62
+ async processLocaleExport(localeCode) {
63
+ const localeTaxonomies = this.taxonomiesByLocale[localeCode];
64
+ if ((localeTaxonomies === null || localeTaxonomies === void 0 ? void 0 : localeTaxonomies.size) > 0) {
65
+ cli_utilities_1.log.info(`Found ${localeTaxonomies.size} taxonomies for locale: ${localeCode}`, this.exportConfig.context);
66
+ await this.exportTaxonomies(localeCode);
53
67
  }
54
68
  else {
55
- cli_utilities_1.log.debug('Fetching taxonomies with initial query', this.exportConfig.context);
69
+ cli_utilities_1.log.debug(`No taxonomies found for locale: ${localeCode}`, this.exportConfig.context);
70
+ }
71
+ }
72
+ /**
73
+ * Write taxonomies metadata file
74
+ */
75
+ async writeTaxonomiesMetadata() {
76
+ if (!this.taxonomies || (0, isEmpty_1.default)(this.taxonomies)) {
77
+ cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('TAXONOMY_NOT_FOUND'), this.exportConfig.context);
78
+ return;
56
79
  }
57
- cli_utilities_1.log.debug(`Query parameters: ${JSON.stringify(this.qs)}`, this.exportConfig.context);
58
- await this.stack
59
- .taxonomy()
60
- .query(this.qs)
61
- .find()
62
- .then(async (data) => {
63
- const { items, count } = data;
64
- const taxonomiesCount = count !== undefined ? count : items === null || items === void 0 ? void 0 : items.length;
65
- cli_utilities_1.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} taxonomies out of total ${taxonomiesCount}`, this.exportConfig.context);
66
- if (items === null || items === void 0 ? void 0 : items.length) {
67
- cli_utilities_1.log.debug(`Processing ${items.length} taxonomies`, this.exportConfig.context);
68
- this.sanitizeTaxonomiesAttribs(items);
80
+ const taxonomiesFilePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, 'taxonomies.json');
81
+ cli_utilities_1.log.debug(`Writing taxonomies metadata to: ${taxonomiesFilePath}`, this.exportConfig.context);
82
+ utils_1.fsUtil.writeFile(taxonomiesFilePath, this.taxonomies);
83
+ }
84
+ /**
85
+ * Fetch taxonomies
86
+ *
87
+ * @async
88
+ * @param {?string} [localeCode]
89
+ * @param {boolean} [checkLocaleSupport=false]
90
+ * @returns {Promise<void>}
91
+ */
92
+ async fetchTaxonomies(localeCode, checkLocaleSupport = false) {
93
+ var _a;
94
+ let skip = 0;
95
+ const localeInfo = localeCode ? `for locale: ${localeCode}` : '';
96
+ if (localeCode && !this.taxonomiesByLocale[localeCode]) {
97
+ this.taxonomiesByLocale[localeCode] = new Set();
98
+ }
99
+ do {
100
+ const queryParams = Object.assign(Object.assign({}, this.qs), { skip });
101
+ if (localeCode) {
102
+ queryParams.locale = localeCode;
103
+ }
104
+ cli_utilities_1.log.debug(`Fetching taxonomies ${localeInfo} with skip: ${skip}`, this.exportConfig.context);
105
+ try {
106
+ const data = await this.stack.taxonomy().query(queryParams).find();
107
+ const { items, count } = data;
108
+ const taxonomiesCount = (_a = count !== null && count !== void 0 ? count : items === null || items === void 0 ? void 0 : items.length) !== null && _a !== void 0 ? _a : 0;
109
+ 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);
110
+ if (!(items === null || items === void 0 ? void 0 : items.length)) {
111
+ cli_utilities_1.log.debug(`No taxonomies found ${localeInfo}`, this.exportConfig.context);
112
+ break;
113
+ }
114
+ // Check localization support
115
+ if (checkLocaleSupport && localeCode && skip === 0 && !items[0].locale) {
116
+ cli_utilities_1.log.debug('API does not support locale-based taxonomy export', this.exportConfig.context);
117
+ this.isLocaleBasedExportSupported = false;
118
+ }
119
+ this.sanitizeTaxonomiesAttribs(items, localeCode);
69
120
  skip += this.qs.limit || 100;
70
121
  if (skip >= taxonomiesCount) {
71
- cli_utilities_1.log.debug('Completed fetching all taxonomies', this.exportConfig.context);
72
- return;
122
+ cli_utilities_1.log.debug(`Completed fetching all taxonomies ${localeInfo}`, this.exportConfig.context);
123
+ break;
73
124
  }
74
- cli_utilities_1.log.debug(`Continuing to fetch taxonomies with skip: ${skip}`, this.exportConfig.context);
75
- return await this.getAllTaxonomies(skip);
76
125
  }
77
- else {
78
- cli_utilities_1.log.debug('No taxonomies found to process', this.exportConfig.context);
126
+ catch (error) {
127
+ cli_utilities_1.log.debug(`Error fetching taxonomies ${localeInfo}`, this.exportConfig.context);
128
+ if (checkLocaleSupport && this.isLocalePlanLimitationError(error)) {
129
+ cli_utilities_1.log.debug('Taxonomy localization is not included in your plan. Falling back to non-localized export.', this.exportConfig.context);
130
+ this.isLocaleBasedExportSupported = false;
131
+ }
132
+ else if (checkLocaleSupport) {
133
+ cli_utilities_1.log.debug('Locale-based taxonomy export not supported, will use legacy method', this.exportConfig.context);
134
+ this.isLocaleBasedExportSupported = false;
135
+ }
136
+ else {
137
+ // Log actual errors during normal fetch (not locale check)
138
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), (localeCode && { locale: localeCode })));
139
+ }
140
+ // Break to avoid infinite retry loop on errors
141
+ break;
79
142
  }
80
- })
81
- .catch((error) => {
82
- cli_utilities_1.log.debug('Error occurred while fetching taxonomies', this.exportConfig.context);
83
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
84
- });
143
+ } while (true);
85
144
  }
86
145
  /**
87
146
  * remove invalid keys and write data into taxonomies
88
147
  * @function sanitizeTaxonomiesAttribs
89
- * @param taxonomies
148
+ * @param {Record<string, string>[]} taxonomies
149
+ * @param {?string} [localeCode]
90
150
  */
91
- sanitizeTaxonomiesAttribs(taxonomies) {
92
- var _a;
93
- cli_utilities_1.log.debug(`Sanitizing ${taxonomies.length} taxonomies`, this.exportConfig.context);
94
- for (let index = 0; index < (taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.length); index++) {
95
- const taxonomyUID = taxonomies[index].uid;
96
- const taxonomyName = (_a = taxonomies[index]) === null || _a === void 0 ? void 0 : _a.name;
97
- cli_utilities_1.log.debug(`Processing taxonomy: ${taxonomyName} (${taxonomyUID})`, this.exportConfig.context);
98
- this.taxonomies[taxonomyUID] = (0, omit_1.default)(taxonomies[index], this.taxonomiesConfig.invalidKeys);
151
+ sanitizeTaxonomiesAttribs(taxonomies, localeCode) {
152
+ const localeInfo = localeCode ? ` for locale: ${localeCode}` : '';
153
+ cli_utilities_1.log.debug(`Processing ${taxonomies.length} taxonomies${localeInfo}`, this.exportConfig.context);
154
+ for (const taxonomy of taxonomies) {
155
+ const taxonomyUID = taxonomy.uid;
156
+ const taxonomyName = taxonomy.name;
157
+ cli_utilities_1.log.debug(`Processing taxonomy: ${taxonomyName} (${taxonomyUID})${localeInfo}`, this.exportConfig.context);
158
+ // Store taxonomy metadata (only once per taxonomy)
159
+ if (!this.taxonomies[taxonomyUID]) {
160
+ this.taxonomies[taxonomyUID] = (0, omit_1.default)(taxonomy, this.taxonomiesConfig.invalidKeys);
161
+ }
162
+ // Track taxonomy for this locale
163
+ if (localeCode) {
164
+ this.taxonomiesByLocale[localeCode].add(taxonomyUID);
165
+ }
99
166
  }
100
- cli_utilities_1.log.debug(`Sanitization complete. Total taxonomies processed: ${Object.keys(this.taxonomies).length}`, this.exportConfig.context);
167
+ cli_utilities_1.log.debug(`Processing complete${localeInfo}. Total taxonomies processed: ${(0, keys_1.default)(this.taxonomies).length}`, this.exportConfig.context);
101
168
  }
102
169
  /**
103
- * Export all taxonomies details using metadata(this.taxonomies) and write it into respective <taxonomy-uid>.json file
104
- * @returns {Promise<void>}
170
+ * Export taxonomies - supports both locale-based and legacy export
105
171
  */
106
- async exportTaxonomies() {
107
- const taxonomiesUID = (0, keys_1.default)(this.taxonomies) || [];
108
- cli_utilities_1.log.debug(`Exporting detailed data for ${taxonomiesUID.length} taxonomies`, this.exportConfig.context);
172
+ async exportTaxonomies(localeCode) {
173
+ const taxonomiesUID = localeCode ? Array.from(this.taxonomiesByLocale[localeCode] || []) : (0, keys_1.default)(this.taxonomies);
174
+ const localeInfo = localeCode ? ` for locale: ${localeCode}` : '';
175
+ if (taxonomiesUID.length === 0) {
176
+ cli_utilities_1.log.debug(`No taxonomies to export${localeInfo}`, this.exportConfig.context);
177
+ return;
178
+ }
179
+ cli_utilities_1.log.debug(`Exporting detailed data for ${taxonomiesUID.length} taxonomies${localeInfo}`, this.exportConfig.context);
180
+ const exportFolderPath = localeCode ? (0, node_path_1.resolve)(this.taxonomiesFolderPath, localeCode) : this.taxonomiesFolderPath;
181
+ if (localeCode) {
182
+ await utils_1.fsUtil.makeDirectory(exportFolderPath);
183
+ cli_utilities_1.log.debug(`Created locale folder: ${exportFolderPath}`, this.exportConfig.context);
184
+ }
109
185
  const onSuccess = ({ response, uid }) => {
110
- const filePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, `${uid}.json`);
186
+ const filePath = (0, node_path_1.resolve)(exportFolderPath, `${uid}.json`);
111
187
  cli_utilities_1.log.debug(`Writing detailed taxonomy data to: ${filePath}`, this.exportConfig.context);
112
188
  utils_1.fsUtil.writeFile(filePath, response);
113
189
  cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_SUCCESS', uid), this.exportConfig.context);
114
190
  };
115
191
  const onReject = ({ error, uid }) => {
116
- cli_utilities_1.log.debug(`Failed to export detailed data for taxonomy: ${uid}`, this.exportConfig.context);
117
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), { uid }));
192
+ cli_utilities_1.log.debug(`Failed to export detailed data for taxonomy: ${uid}${localeInfo}`, this.exportConfig.context);
193
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign(Object.assign({}, this.exportConfig.context), { uid }), (localeCode && { locale: localeCode })));
118
194
  };
119
- for (let index = 0; index < (taxonomiesUID === null || taxonomiesUID === void 0 ? void 0 : taxonomiesUID.length); index++) {
120
- const taxonomyUID = taxonomiesUID[index];
121
- cli_utilities_1.log.debug(`Processing detailed export for taxonomy: ${taxonomyUID}`, this.exportConfig.context);
195
+ for (const taxonomyUID of taxonomiesUID) {
196
+ cli_utilities_1.log.debug(`Processing detailed export for taxonomy: ${taxonomyUID}${localeInfo}`, this.exportConfig.context);
197
+ const exportParams = { format: 'json' };
198
+ if (localeCode) {
199
+ exportParams.locale = localeCode;
200
+ if (this.qs.include_fallback !== undefined)
201
+ exportParams.include_fallback = this.qs.include_fallback;
202
+ if (this.qs.fallback_locale)
203
+ exportParams.fallback_locale = this.qs.fallback_locale;
204
+ }
205
+ if (this.qs.branch)
206
+ exportParams.branch = this.qs.branch;
122
207
  await this.makeAPICall({
123
208
  reject: onReject,
124
209
  resolve: onSuccess,
125
210
  uid: taxonomyUID,
126
211
  module: 'export-taxonomy',
212
+ queryParam: exportParams,
127
213
  });
128
214
  }
129
- cli_utilities_1.log.debug('Completed detailed taxonomy export process', this.exportConfig.context);
215
+ cli_utilities_1.log.debug(`Completed detailed taxonomy export process${localeInfo}`, this.exportConfig.context);
216
+ }
217
+ /**
218
+ * Get all locales to export
219
+ */
220
+ getLocalesToExport() {
221
+ var _a;
222
+ cli_utilities_1.log.debug('Determining locales to export...', this.exportConfig.context);
223
+ const masterLocaleCode = ((_a = this.exportConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code) || 'en-us';
224
+ const localeSet = new Set([masterLocaleCode]);
225
+ try {
226
+ const locales = utils_1.fsUtil.readFile(this.localesFilePath);
227
+ if (locales && (0, keys_1.default)(locales || {}).length > 0) {
228
+ cli_utilities_1.log.debug(`Loaded ${(0, keys_1.default)(locales || {}).length} locales from ${this.localesFilePath}`, this.exportConfig.context);
229
+ for (const localeUid of (0, keys_1.default)(locales)) {
230
+ const localeCode = locales[localeUid].code;
231
+ if (localeCode && !localeSet.has(localeCode)) {
232
+ localeSet.add(localeCode);
233
+ cli_utilities_1.log.debug(`Added locale: ${localeCode} (uid: ${localeUid})`, this.exportConfig.context);
234
+ }
235
+ }
236
+ }
237
+ else {
238
+ cli_utilities_1.log.debug(`No locales found in ${this.localesFilePath}`, this.exportConfig.context);
239
+ }
240
+ }
241
+ catch (error) {
242
+ cli_utilities_1.log.warn(`Failed to read locales file: ${this.localesFilePath}`, this.exportConfig.context);
243
+ }
244
+ const localesToExport = Array.from(localeSet);
245
+ cli_utilities_1.log.debug(`Total unique locales to export: ${localesToExport.length}`, this.exportConfig.context);
246
+ return localesToExport;
247
+ }
248
+ isLocalePlanLimitationError(error) {
249
+ var _a, _b;
250
+ return ((error === null || error === void 0 ? void 0 : error.status) === 403 &&
251
+ ((_b = (_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.taxonomies) === null || _b === void 0 ? void 0 : _b.some((msg) => msg.toLowerCase().includes('taxonomy localization') &&
252
+ msg.toLowerCase().includes('not included in your plan'))));
130
253
  }
131
254
  }
132
255
  exports.default = ExportTaxonomies;
@@ -240,7 +240,7 @@ module.exports = class ExportAssets {
240
240
  const assetVersionInfo = bucket || [];
241
241
  return new Promise((resolve, reject) => {
242
242
  if (self.assetDownloadRetry[uid + version] > self.assetDownloadRetryLimit) {
243
- console.log('Reached max', self.assetDownloadRetry[uid + version]);
243
+ console.log('Reached the maximum limit.', self.assetDownloadRetry[uid + version]);
244
244
  return reject(new Error('Asset Max download retry limit exceeded! ' + uid));
245
245
  }
246
246
  if (version <= 0) {
@@ -274,7 +274,7 @@ module.exports = class ExportAssets {
274
274
  .catch((error) => {
275
275
  log(self.config, error, 'error');
276
276
  if (error.status === 408) {
277
- console.log('retrying', uid);
277
+ console.log('Retrying...', uid);
278
278
  // retrying when timeout
279
279
  self.assetDownloadRetry[uid + version]
280
280
  ? ++self.assetDownloadRetry[uid + version]
@@ -313,7 +313,7 @@ module.exports = class ExportAssets {
313
313
  length: assetStreamRequest.headers['content-length'],
314
314
  });
315
315
  str.on('progress', (progressData) => {
316
- console.log(`${asset.filename}: ${Math.round(progressData.percentage)}%`);
316
+ console.log(`${asset.filename}: ${Math.round(progressData.percentage)}% complete`);
317
317
  });
318
318
  assetStreamRequest.pipe(str).pipe(assetFileStream);
319
319
  }
@@ -148,6 +148,12 @@ export default interface DefaultConfig {
148
148
  fileName: string;
149
149
  dependencies?: Modules[];
150
150
  };
151
+ 'composable-studio': {
152
+ dirName: string;
153
+ fileName: string;
154
+ apiBaseUrl: string;
155
+ apiVersion: string;
156
+ };
151
157
  masterLocale: {
152
158
  dirName: string;
153
159
  fileName: string;
@@ -26,7 +26,7 @@ export interface Region {
26
26
  cda: string;
27
27
  uiHost: 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';
29
+ export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies' | 'personalize' | 'composable-studio';
30
30
  export type ModuleClassParams = {
31
31
  stackAPIClient: ReturnType<ContentstackClient['stack']>;
32
32
  exportConfig: ExportConfig;
@@ -96,6 +96,32 @@ export interface StackConfig {
96
96
  dependencies?: Modules[];
97
97
  limit?: number;
98
98
  }
99
+ export interface ComposableStudioConfig {
100
+ dirName: string;
101
+ fileName: string;
102
+ apiBaseUrl: string;
103
+ apiVersion: string;
104
+ }
105
+ export interface ComposableStudioProject {
106
+ name: string;
107
+ description: string;
108
+ canvasUrl: string;
109
+ connectedStackApiKey: string;
110
+ contentTypeUid: string;
111
+ organizationUid: string;
112
+ settings: {
113
+ configuration: {
114
+ environment: string;
115
+ locale: string;
116
+ };
117
+ };
118
+ createdBy: string;
119
+ updatedBy: string;
120
+ deletedAt: boolean;
121
+ createdAt: string;
122
+ updatedAt: string;
123
+ uid: string;
124
+ }
99
125
  export interface Context {
100
126
  command: string;
101
127
  module: string;
@@ -26,7 +26,7 @@ const login = async (config) => {
26
26
  return config;
27
27
  }
28
28
  else {
29
- cli_utilities_1.log.error(`Failed to login, Invalid credentials`, config.context);
29
+ cli_utilities_1.log.error(`Failed to log in!`, config.context);
30
30
  process.exit(1);
31
31
  }
32
32
  }