@contentstack/cli-cm-export 2.0.0-beta.12 → 2.0.0-beta.14

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.12 linux-x64 node-v22.22.1
51
+ @contentstack/cli-cm-export/2.0.0-beta.14 linux-x64 node-v22.22.1
52
52
  $ csdx --help [COMMAND]
53
53
  USAGE
54
54
  $ csdx COMMAND
@@ -201,6 +201,7 @@ const config = {
201
201
  stack: {
202
202
  dirName: 'stack',
203
203
  fileName: 'stack.json',
204
+ invalidKeys: ['SYS_ACL', 'user_uids', 'owner_uid', 'description', 'master_key'],
204
205
  },
205
206
  dependency: {
206
207
  entries: ['stack', 'locales', 'content-types'],
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const map_1 = tslib_1.__importDefault(require("lodash/map"));
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
5
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
6
6
  const chunk_1 = tslib_1.__importDefault(require("lodash/chunk"));
7
7
  const first_1 = tslib_1.__importDefault(require("lodash/first"));
8
8
  const merge_1 = tslib_1.__importDefault(require("lodash/merge"));
@@ -15,7 +15,7 @@ const includes_1 = tslib_1.__importDefault(require("lodash/includes"));
15
15
  const progress_stream_1 = tslib_1.__importDefault(require("progress-stream"));
16
16
  const node_fs_1 = require("node:fs");
17
17
  const node_path_1 = require("node:path");
18
- const cli_utilities_1 = require("@contentstack/cli-utilities");
18
+ const cli_utilities_2 = require("@contentstack/cli-utilities");
19
19
  const constants_1 = require("../../constants");
20
20
  const config_1 = tslib_1.__importDefault(require("../../config"));
21
21
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
@@ -38,10 +38,10 @@ class ExportAssets extends base_class_1.default {
38
38
  }
39
39
  async start() {
40
40
  this.assetsRootPath = (0, node_path_1.resolve)(this.exportConfig.exportDir, this.exportConfig.branchName || '', this.assetConfig.dirName);
41
- cli_utilities_1.log.debug(`Assets root path resolved to: ${this.assetsRootPath}`, this.exportConfig.context);
42
- cli_utilities_1.log.debug('Fetching assets and folders count...', this.exportConfig.context);
41
+ cli_utilities_2.log.debug(`Assets root path resolved to: ${this.assetsRootPath}`, this.exportConfig.context);
42
+ cli_utilities_2.log.debug('Fetching assets and folders count...', this.exportConfig.context);
43
43
  // NOTE step 1: Get assets and it's folder count in parallel
44
- const [assetsCount, assetsFolderCount] = await this.withLoadingSpinner(`${chalk_1.default.bold('ASSETS')}: Analyzing stack content...`, () => Promise.all([this.getAssetsCount(), this.getAssetsCount(true)]));
44
+ const [assetsCount, assetsFolderCount] = await this.withLoadingSpinner(`${(0, cli_utilities_1.getChalk)().bold('ASSETS')}: Analyzing stack content...`, () => Promise.all([this.getAssetsCount(), this.getAssetsCount(true)]));
45
45
  // Create nested progress manager
46
46
  const progress = this.createNestedProgress(this.currentModuleName);
47
47
  // Add sub-processes
@@ -71,7 +71,7 @@ class ExportAssets extends base_class_1.default {
71
71
  }
72
72
  // Get versioned assets
73
73
  if (!(0, isEmpty_1.default)(this.versionedAssets) && this.assetConfig.includeVersionedAssets) {
74
- cli_utilities_1.log.debug('Fetching versioned assets metadata...', this.exportConfig.context);
74
+ cli_utilities_2.log.debug('Fetching versioned assets metadata...', this.exportConfig.context);
75
75
  progress.updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.ASSET_METADATA].FETCHING_VERSION, utils_1.PROCESS_NAMES.ASSET_METADATA);
76
76
  await this.getVersionedAssets();
77
77
  }
@@ -80,7 +80,7 @@ class ExportAssets extends base_class_1.default {
80
80
  progress
81
81
  .startProcess(utils_1.PROCESS_NAMES.ASSET_DOWNLOADS)
82
82
  .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.ASSET_DOWNLOADS].DOWNLOADING, utils_1.PROCESS_NAMES.ASSET_DOWNLOADS);
83
- cli_utilities_1.log.debug('Starting download of all assets...', this.exportConfig.context);
83
+ cli_utilities_2.log.debug('Starting download of all assets...', this.exportConfig.context);
84
84
  await this.downloadAssets();
85
85
  progress.completeProcess(utils_1.PROCESS_NAMES.ASSET_DOWNLOADS, true);
86
86
  }
@@ -99,9 +99,9 @@ class ExportAssets extends base_class_1.default {
99
99
  if (!totalCount)
100
100
  return Promise.resolve();
101
101
  const queryParam = Object.assign(Object.assign({}, this.commonQueryParam), { query: { is_dir: true } });
102
- cli_utilities_1.log.debug(`Fetching asset folders with query: ${JSON.stringify(queryParam)}`, this.exportConfig.context);
102
+ cli_utilities_2.log.debug(`Fetching asset folders with query: ${JSON.stringify(queryParam)}`, this.exportConfig.context);
103
103
  const onSuccess = ({ response: { items } }) => {
104
- cli_utilities_1.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} asset folders`, this.exportConfig.context);
104
+ cli_utilities_2.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} asset folders`, this.exportConfig.context);
105
105
  if (!(0, isEmpty_1.default)(items)) {
106
106
  this.assetsFolder.push(...items);
107
107
  items.forEach((folder) => {
@@ -113,7 +113,7 @@ class ExportAssets extends base_class_1.default {
113
113
  const onReject = ({ error }) => {
114
114
  var _a;
115
115
  (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, 'asset folder', (error === null || error === void 0 ? void 0 : error.message) || utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.ASSET_FOLDERS].FAILED, utils_1.PROCESS_NAMES.ASSET_FOLDERS);
116
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
116
+ (0, cli_utilities_2.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
117
117
  };
118
118
  return this.makeConcurrentCall({
119
119
  totalCount,
@@ -128,10 +128,10 @@ class ExportAssets extends base_class_1.default {
128
128
  }).then(() => {
129
129
  if (!(0, isEmpty_1.default)(this.assetsFolder)) {
130
130
  const path = (0, node_path_1.resolve)(this.assetsRootPath, 'folders.json');
131
- cli_utilities_1.log.debug(`Writing asset folders to ${path}`, this.exportConfig.context);
132
- new cli_utilities_1.FsUtility({ basePath: this.assetsRootPath }).writeFile(path, this.assetsFolder);
131
+ cli_utilities_2.log.debug(`Writing asset folders to ${path}`, this.exportConfig.context);
132
+ new cli_utilities_2.FsUtility({ basePath: this.assetsRootPath }).writeFile(path, this.assetsFolder);
133
133
  }
134
- cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('ASSET_FOLDERS_EXPORT_COMPLETE', this.assetsFolder.length), this.exportConfig.context);
134
+ cli_utilities_2.log.info(cli_utilities_2.messageHandler.parse('ASSET_FOLDERS_EXPORT_COMPLETE', this.assetsFolder.length), this.exportConfig.context);
135
135
  });
136
136
  }
137
137
  /**
@@ -142,7 +142,7 @@ class ExportAssets extends base_class_1.default {
142
142
  getAssets(totalCount) {
143
143
  if (!totalCount)
144
144
  return Promise.resolve();
145
- cli_utilities_1.log.debug(`Fetching ${totalCount} assets...`, this.exportConfig.context);
145
+ cli_utilities_2.log.debug(`Fetching ${totalCount} assets...`, this.exportConfig.context);
146
146
  let fs;
147
147
  let metaHandler;
148
148
  const queryParam = Object.assign(Object.assign({}, this.commonQueryParam), { include_publish_details: true, except: { BASE: this.assetConfig.invalidKeys } });
@@ -150,7 +150,7 @@ class ExportAssets extends base_class_1.default {
150
150
  if (this.assetConfig.includeVersionedAssets) {
151
151
  const customHandler = (array) => {
152
152
  const versionAssets = (0, filter_1.default)(array, ({ _version }) => _version > 1);
153
- cli_utilities_1.log.debug(`Found ${versionAssets.length} versioned assets`, this.exportConfig.context);
153
+ cli_utilities_2.log.debug(`Found ${versionAssets.length} versioned assets`, this.exportConfig.context);
154
154
  if (!(0, isEmpty_1.default)(versionAssets)) {
155
155
  this.versionedAssets.push(...(0, map_1.default)(versionAssets, ({ uid, _version }) => ({
156
156
  [uid]: _version,
@@ -162,13 +162,13 @@ class ExportAssets extends base_class_1.default {
162
162
  const onReject = ({ error }) => {
163
163
  var _a;
164
164
  (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, 'asset', (error === null || error === void 0 ? void 0 : error.message) || utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.ASSET_METADATA].FAILED, utils_1.PROCESS_NAMES.ASSET_METADATA);
165
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context), cli_utilities_1.messageHandler.parse('ASSET_QUERY_FAILED'));
165
+ (0, cli_utilities_2.handleAndLogError)(error, Object.assign({}, this.exportConfig.context), cli_utilities_2.messageHandler.parse('ASSET_QUERY_FAILED'));
166
166
  };
167
167
  const onSuccess = ({ response: { items } }) => {
168
- cli_utilities_1.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} assets`, this.exportConfig.context);
168
+ cli_utilities_2.log.debug(`Fetched ${(items === null || items === void 0 ? void 0 : items.length) || 0} assets`, this.exportConfig.context);
169
169
  if (!fs && !(0, isEmpty_1.default)(items)) {
170
- cli_utilities_1.log.debug('Initializing FsUtility for writing assets metadata', this.exportConfig.context);
171
- fs = new cli_utilities_1.FsUtility({
170
+ cli_utilities_2.log.debug('Initializing FsUtility for writing assets metadata', this.exportConfig.context);
171
+ fs = new cli_utilities_2.FsUtility({
172
172
  metaHandler,
173
173
  moduleName: 'assets',
174
174
  indexFileName: this.assetConfig.fileName,
@@ -178,7 +178,7 @@ class ExportAssets extends base_class_1.default {
178
178
  });
179
179
  }
180
180
  if (!(0, isEmpty_1.default)(items)) {
181
- cli_utilities_1.log.debug(`Writing ${items.length} assets into file`, this.exportConfig.context);
181
+ cli_utilities_2.log.debug(`Writing ${items.length} assets into file`, this.exportConfig.context);
182
182
  fs === null || fs === void 0 ? void 0 : fs.writeIntoFile(items, { mapKeyVal: true });
183
183
  // Track progress for each asset with process name
184
184
  items.forEach((asset) => {
@@ -199,7 +199,7 @@ class ExportAssets extends base_class_1.default {
199
199
  concurrencyLimit: this.assetConfig.fetchConcurrency,
200
200
  }).then(() => {
201
201
  fs === null || fs === void 0 ? void 0 : fs.completeFile(true);
202
- cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('ASSET_METADATA_EXPORT_COMPLETE'), this.exportConfig.context);
202
+ cli_utilities_2.log.info(cli_utilities_2.messageHandler.parse('ASSET_METADATA_EXPORT_COMPLETE'), this.exportConfig.context);
203
203
  });
204
204
  }
205
205
  /**
@@ -207,7 +207,7 @@ class ExportAssets extends base_class_1.default {
207
207
  * @returns Promise<any|void>
208
208
  */
209
209
  getVersionedAssets() {
210
- cli_utilities_1.log.debug('Preparing to fetch versioned assets...', this.exportConfig.context);
210
+ cli_utilities_2.log.debug('Preparing to fetch versioned assets...', this.exportConfig.context);
211
211
  let fs;
212
212
  const queryParam = Object.assign(Object.assign({}, this.commonQueryParam), { include_publish_details: true, except: { BASE: this.assetConfig.invalidKeys } });
213
213
  const versionedAssets = (0, map_1.default)(this.versionedAssets, (element) => {
@@ -218,13 +218,13 @@ class ExportAssets extends base_class_1.default {
218
218
  }
219
219
  return batch;
220
220
  }).flat();
221
- cli_utilities_1.log.debug(`Prepared ${versionedAssets.length} versioned asset queries`, this.exportConfig.context);
221
+ cli_utilities_2.log.debug(`Prepared ${versionedAssets.length} versioned asset queries`, this.exportConfig.context);
222
222
  const apiBatches = (0, chunk_1.default)(versionedAssets, this.assetConfig.fetchConcurrency);
223
223
  const promisifyHandler = (input) => {
224
224
  const { index, batchIndex, apiParams, isLastRequest } = input;
225
225
  const batch = apiBatches[batchIndex][index];
226
226
  const [uid, version] = (0, first_1.default)((0, entries_1.default)(batch));
227
- cli_utilities_1.log.debug(`Fetching versioned asset [UID: ${uid}, Version: ${version}]`, this.exportConfig.context);
227
+ cli_utilities_2.log.debug(`Fetching versioned asset [UID: ${uid}, Version: ${version}]`, this.exportConfig.context);
228
228
  if (apiParams === null || apiParams === void 0 ? void 0 : apiParams.queryParam) {
229
229
  apiParams.uid = uid;
230
230
  apiParams.queryParam.version = version;
@@ -234,7 +234,7 @@ class ExportAssets extends base_class_1.default {
234
234
  };
235
235
  const onSuccess = ({ response }) => {
236
236
  if (!fs && !(0, isEmpty_1.default)(response)) {
237
- fs = new cli_utilities_1.FsUtility({
237
+ fs = new cli_utilities_2.FsUtility({
238
238
  moduleName: 'assets',
239
239
  indexFileName: constants_1.PATH_CONSTANTS.FILES.VERSIONED_ASSETS,
240
240
  chunkFileSize: this.assetConfig.chunkFileSize,
@@ -243,12 +243,12 @@ class ExportAssets extends base_class_1.default {
243
243
  });
244
244
  }
245
245
  if (!(0, isEmpty_1.default)(response)) {
246
- cli_utilities_1.log.debug(`Writing versioned asset: UID=${response.uid}, Version=${response._version}`, this.exportConfig.context);
246
+ cli_utilities_2.log.debug(`Writing versioned asset: UID=${response.uid}, Version=${response._version}`, this.exportConfig.context);
247
247
  fs === null || fs === void 0 ? void 0 : fs.writeIntoFile([response], { mapKeyVal: true, keyName: ['uid', '_version'] });
248
248
  }
249
249
  };
250
250
  const onReject = ({ error }) => {
251
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context), cli_utilities_1.messageHandler.parse('ASSET_VERSIONED_QUERY_FAILED'));
251
+ (0, cli_utilities_2.handleAndLogError)(error, Object.assign({}, this.exportConfig.context), cli_utilities_2.messageHandler.parse('ASSET_VERSIONED_QUERY_FAILED'));
252
252
  };
253
253
  return this.makeConcurrentCall({
254
254
  apiBatches,
@@ -263,24 +263,24 @@ class ExportAssets extends base_class_1.default {
263
263
  concurrencyLimit: this.assetConfig.fetchConcurrency,
264
264
  }, promisifyHandler).then(() => {
265
265
  fs === null || fs === void 0 ? void 0 : fs.completeFile(true);
266
- cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('ASSET_VERSIONED_METADATA_EXPORT_COMPLETE'), this.exportConfig.context);
266
+ cli_utilities_2.log.info(cli_utilities_2.messageHandler.parse('ASSET_VERSIONED_METADATA_EXPORT_COMPLETE'), this.exportConfig.context);
267
267
  });
268
268
  }
269
269
  getAssetsCount(isDir = false) {
270
270
  const queryParam = Object.assign(Object.assign({ limit: 1 }, this.commonQueryParam), { skip: 10 ** 100 });
271
271
  if (isDir)
272
272
  queryParam.query = { is_dir: true };
273
- cli_utilities_1.log.debug(`Querying count of assets${isDir ? ' (folders only)' : ''} with params: ${JSON.stringify(queryParam)}`, this.exportConfig.context);
273
+ cli_utilities_2.log.debug(`Querying count of assets${isDir ? ' (folders only)' : ''} with params: ${JSON.stringify(queryParam)}`, this.exportConfig.context);
274
274
  return this.stack
275
275
  .asset()
276
276
  .query(queryParam)
277
277
  .count()
278
278
  .then(({ assets }) => {
279
- cli_utilities_1.log.debug(`Received asset count: ${assets}`, this.exportConfig.context);
279
+ cli_utilities_2.log.debug(`Received asset count: ${assets}`, this.exportConfig.context);
280
280
  return assets;
281
281
  })
282
282
  .catch((error) => {
283
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context), cli_utilities_1.messageHandler.parse('ASSET_COUNT_QUERY_FAILED'));
283
+ (0, cli_utilities_2.handleAndLogError)(error, Object.assign({}, this.exportConfig.context), cli_utilities_2.messageHandler.parse('ASSET_COUNT_QUERY_FAILED'));
284
284
  });
285
285
  }
286
286
  /**
@@ -288,12 +288,12 @@ class ExportAssets extends base_class_1.default {
288
288
  * @returns Promise<any|void>
289
289
  */
290
290
  async downloadAssets() {
291
- const fs = new cli_utilities_1.FsUtility({
291
+ const fs = new cli_utilities_2.FsUtility({
292
292
  fileExt: 'json',
293
293
  createDirIfNotExist: false,
294
294
  basePath: this.assetsRootPath,
295
295
  });
296
- cli_utilities_1.log.debug('Reading asset metadata for download...', this.exportConfig.context);
296
+ cli_utilities_2.log.debug('Reading asset metadata for download...', this.exportConfig.context);
297
297
  const assetsMetaData = fs.getPlainMeta();
298
298
  let listOfAssets = (0, values_1.default)(assetsMetaData).flat();
299
299
  if (this.assetConfig.includeVersionedAssets) {
@@ -301,21 +301,21 @@ class ExportAssets extends base_class_1.default {
301
301
  listOfAssets.push(...(0, values_1.default)(versionedAssetsMetaData).flat());
302
302
  }
303
303
  listOfAssets = (0, uniqBy_1.default)(listOfAssets, 'url');
304
- cli_utilities_1.log.debug(`Total unique assets to download: ${listOfAssets.length}`, this.exportConfig.context);
304
+ cli_utilities_2.log.debug(`Total unique assets to download: ${listOfAssets.length}`, this.exportConfig.context);
305
305
  const apiBatches = (0, chunk_1.default)(listOfAssets, this.assetConfig.downloadLimit);
306
- const downloadedAssetsDirs = await (0, cli_utilities_1.getDirectories)((0, node_path_1.resolve)(this.assetsRootPath, 'files'));
306
+ const downloadedAssetsDirs = await (0, cli_utilities_2.getDirectories)((0, node_path_1.resolve)(this.assetsRootPath, 'files'));
307
307
  const onSuccess = ({ response: { data }, additionalInfo }) => {
308
308
  var _a;
309
309
  const { asset } = additionalInfo;
310
310
  const assetFolderPath = (0, node_path_1.resolve)(this.assetsRootPath, 'files', asset.uid);
311
311
  const assetFilePath = (0, node_path_1.resolve)(assetFolderPath, asset.filename);
312
- cli_utilities_1.log.debug(`Saving asset to: ${assetFilePath}`, this.exportConfig.context);
312
+ cli_utilities_2.log.debug(`Saving asset to: ${assetFilePath}`, this.exportConfig.context);
313
313
  if (!(0, includes_1.default)(downloadedAssetsDirs, asset.uid)) {
314
314
  fs.createFolderIfNotExist(assetFolderPath);
315
315
  }
316
316
  const assetWriterStream = (0, node_fs_1.createWriteStream)(assetFilePath);
317
317
  assetWriterStream.on('error', (error) => {
318
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), { uid: asset.uid, filename: asset.fileName }), cli_utilities_1.messageHandler.parse('ASSET_DOWNLOAD_FAILED', asset.filename, asset.uid));
318
+ (0, cli_utilities_2.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), { uid: asset.uid, filename: asset.fileName }), cli_utilities_2.messageHandler.parse('ASSET_DOWNLOAD_FAILED', asset.filename, asset.uid));
319
319
  });
320
320
  /**
321
321
  * NOTE if pipe not working as expected add the following code below to fix the issue
@@ -339,21 +339,21 @@ class ExportAssets extends base_class_1.default {
339
339
  data.pipe(assetWriterStream);
340
340
  }
341
341
  (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `Downloaded asset: ${asset.filename || asset.uid}`, null, utils_1.PROCESS_NAMES.ASSET_DOWNLOADS);
342
- cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('ASSET_DOWNLOAD_SUCCESS', asset.filename, asset.uid), this.exportConfig.context);
342
+ cli_utilities_2.log.success(cli_utilities_2.messageHandler.parse('ASSET_DOWNLOAD_SUCCESS', asset.filename, asset.uid), this.exportConfig.context);
343
343
  };
344
344
  const onReject = ({ error, additionalInfo }) => {
345
345
  var _a;
346
346
  const { asset } = additionalInfo;
347
347
  (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, `Failed to download asset: ${asset.filename || asset.uid}`, null, utils_1.PROCESS_NAMES.ASSET_DOWNLOADS);
348
- (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), { uid: asset.uid, filename: asset.filename }), cli_utilities_1.messageHandler.parse('ASSET_DOWNLOAD_FAILED', asset.filename, asset.uid));
348
+ (0, cli_utilities_2.handleAndLogError)(error, Object.assign(Object.assign({}, this.exportConfig.context), { uid: asset.uid, filename: asset.filename }), cli_utilities_2.messageHandler.parse('ASSET_DOWNLOAD_FAILED', asset.filename, asset.uid));
349
349
  };
350
350
  const promisifyHandler = (input) => {
351
351
  const { index, batchIndex } = input;
352
352
  const asset = apiBatches[batchIndex][index];
353
353
  const url = this.assetConfig.securedAssets
354
- ? `${asset.url}?authtoken=${cli_utilities_1.configHandler.get('authtoken')}`
354
+ ? `${asset.url}?authtoken=${cli_utilities_2.configHandler.get('authtoken')}`
355
355
  : asset.url;
356
- cli_utilities_1.log.debug(`Preparing to download asset: ${asset.filename} (UID: ${asset.uid}) from URL: ${url}`, this.exportConfig.context);
356
+ cli_utilities_2.log.debug(`Preparing to download asset: ${asset.filename} (UID: ${asset.uid}) from URL: ${url}`, this.exportConfig.context);
357
357
  return this.makeAPICall({
358
358
  reject: onReject,
359
359
  resolve: onSuccess,
@@ -368,7 +368,7 @@ class ExportAssets extends base_class_1.default {
368
368
  totalCount: listOfAssets.length,
369
369
  concurrencyLimit: this.assetConfig.downloadLimit,
370
370
  }, promisifyHandler).then(() => {
371
- cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('ASSET_DOWNLOAD_COMPLETE'), this.exportConfig.context);
371
+ cli_utilities_2.log.success(cli_utilities_2.messageHandler.parse('ASSET_DOWNLOAD_COMPLETE'), this.exportConfig.context);
372
372
  });
373
373
  }
374
374
  }
@@ -8,6 +8,16 @@ export default class ExportStack extends BaseClass {
8
8
  start(): Promise<void>;
9
9
  getStack(): Promise<any>;
10
10
  getLocales(skip?: number): Promise<any>;
11
- exportStack(): Promise<any>;
11
+ /**
12
+ * Reuse stack snapshot from `getStack()` when present so we do not call `stack.fetch()` twice
13
+ * (same GET /stacks payload as writing stack.json). Falls back to `this.stack.fetch()` otherwise.
14
+ */
15
+ exportStack(preloadedStack?: Record<string, any> | null): Promise<any>;
16
+ private isStackFetchPayload;
17
+ /**
18
+ * Management-token exports cannot use Stack CMA endpoints for full metadata; write api_key from config only.
19
+ */
20
+ private writeStackJsonFromConfigApiKeyOnly;
21
+ private persistStackJsonPayload;
12
22
  exportStackSettings(): Promise<any>;
13
23
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const find_1 = tslib_1.__importDefault(require("lodash/find"));
5
+ const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
5
6
  const node_path_1 = require("node:path");
6
7
  const cli_utilities_1 = require("@contentstack/cli-utilities");
7
8
  const constants_1 = require("../../constants");
@@ -17,35 +18,31 @@ class ExportStack extends base_class_1.default {
17
18
  this.currentModuleName = utils_1.MODULE_NAMES[utils_1.MODULE_CONTEXTS.STACK];
18
19
  }
19
20
  async start() {
21
+ var _a;
20
22
  try {
21
23
  cli_utilities_1.log.debug('Starting stack export process...', this.exportConfig.context);
22
- // Initial analysis with loading spinner
24
+ // Initial analysis with loading spinner (skip getStack when using management token — no SDK snapshot)
23
25
  const [stackData] = await this.withLoadingSpinner('STACK: Analyzing stack configuration...', async () => {
24
- const stackData = (0, cli_utilities_1.isAuthenticated)() ? await this.getStack() : null;
26
+ const stackData = this.exportConfig.management_token || !(0, cli_utilities_1.isAuthenticated)() ? null : await this.getStack();
25
27
  return [stackData];
26
28
  });
27
29
  // Create nested progress manager
28
30
  const progress = this.createNestedProgress(this.currentModuleName);
29
- // Add processes based on configuration
30
- let processCount = 0;
31
- if (stackData === null || stackData === void 0 ? void 0 : stackData.org_uid) {
32
- cli_utilities_1.log.debug(`Found organization UID: '${stackData.org_uid}'.`, this.exportConfig.context);
33
- this.exportConfig.org_uid = stackData.org_uid;
31
+ const orgUid = (_a = stackData === null || stackData === void 0 ? void 0 : stackData.org_uid) !== null && _a !== void 0 ? _a : stackData === null || stackData === void 0 ? void 0 : stackData.organization_uid;
32
+ if (orgUid) {
33
+ cli_utilities_1.log.debug(`Found organization UID: '${orgUid}'.`, this.exportConfig.context);
34
+ this.exportConfig.org_uid = orgUid;
34
35
  this.exportConfig.sourceStackName = stackData.name;
35
36
  cli_utilities_1.log.debug(`Set source stack name: ${stackData.name}`, this.exportConfig.context);
36
37
  }
37
38
  if (!this.exportConfig.management_token) {
38
39
  progress.addProcess(utils_1.PROCESS_NAMES.STACK_SETTINGS, 1);
39
- processCount++;
40
40
  }
41
+ progress.addProcess(utils_1.PROCESS_NAMES.STACK_DETAILS, 1);
41
42
  if (!this.exportConfig.preserveStackVersion && !this.exportConfig.hasOwnProperty('master_locale')) {
42
43
  progress.addProcess(utils_1.PROCESS_NAMES.STACK_LOCALE, 1);
43
- processCount++;
44
- }
45
- else if (this.exportConfig.preserveStackVersion) {
46
- progress.addProcess(utils_1.PROCESS_NAMES.STACK_DETAILS, 1);
47
- processCount++;
48
44
  }
45
+ let stackDetailsExportResult;
49
46
  // Execute processes
50
47
  if (!this.exportConfig.management_token) {
51
48
  progress
@@ -53,9 +50,19 @@ class ExportStack extends base_class_1.default {
53
50
  .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.STACK_SETTINGS].EXPORTING, utils_1.PROCESS_NAMES.STACK_SETTINGS);
54
51
  await this.exportStackSettings();
55
52
  progress.completeProcess(utils_1.PROCESS_NAMES.STACK_SETTINGS, true);
53
+ progress
54
+ .startProcess(utils_1.PROCESS_NAMES.STACK_DETAILS)
55
+ .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.STACK_DETAILS].EXPORTING, utils_1.PROCESS_NAMES.STACK_DETAILS);
56
+ stackDetailsExportResult = await this.exportStack(stackData);
57
+ progress.completeProcess(utils_1.PROCESS_NAMES.STACK_DETAILS, true);
56
58
  }
57
59
  else {
58
60
  cli_utilities_1.log.info('Skipping stack settings export: Operation is not supported when using a management token.', this.exportConfig.context);
61
+ progress
62
+ .startProcess(utils_1.PROCESS_NAMES.STACK_DETAILS)
63
+ .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.STACK_DETAILS].EXPORTING, utils_1.PROCESS_NAMES.STACK_DETAILS);
64
+ stackDetailsExportResult = await this.writeStackJsonFromConfigApiKeyOnly();
65
+ progress.completeProcess(utils_1.PROCESS_NAMES.STACK_DETAILS, true);
59
66
  }
60
67
  if (!this.exportConfig.preserveStackVersion && !this.exportConfig.hasOwnProperty('master_locale')) {
61
68
  progress
@@ -71,13 +78,8 @@ class ExportStack extends base_class_1.default {
71
78
  return masterLocale;
72
79
  }
73
80
  else if (this.exportConfig.preserveStackVersion) {
74
- progress
75
- .startProcess(utils_1.PROCESS_NAMES.STACK_DETAILS)
76
- .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.STACK_DETAILS].EXPORTING, utils_1.PROCESS_NAMES.STACK_DETAILS);
77
- const stackResult = await this.exportStack();
78
- progress.completeProcess(utils_1.PROCESS_NAMES.STACK_DETAILS, true);
79
81
  this.completeProgress(true);
80
- return stackResult;
82
+ return stackDetailsExportResult;
81
83
  }
82
84
  else {
83
85
  cli_utilities_1.log.debug('Locale locale already set, skipping locale fetch', this.exportConfig.context);
@@ -161,22 +163,30 @@ class ExportStack extends base_class_1.default {
161
163
  throw error;
162
164
  });
163
165
  }
164
- async exportStack() {
166
+ /**
167
+ * Reuse stack snapshot from `getStack()` when present so we do not call `stack.fetch()` twice
168
+ * (same GET /stacks payload as writing stack.json). Falls back to `this.stack.fetch()` otherwise.
169
+ */
170
+ async exportStack(preloadedStack) {
171
+ var _a;
165
172
  cli_utilities_1.log.debug(`Starting stack export for: '${this.exportConfig.apiKey}'...`, this.exportConfig.context);
166
173
  await utils_1.fsUtil.makeDirectory(this.stackFolderPath);
167
174
  cli_utilities_1.log.debug(`Created stack directory at: '${this.stackFolderPath}'`, this.exportConfig.context);
175
+ if (this.isStackFetchPayload(preloadedStack)) {
176
+ cli_utilities_1.log.debug('Reusing stack payload from analysis step (no extra stack.fetch).', this.exportConfig.context);
177
+ try {
178
+ return this.persistStackJsonPayload(preloadedStack);
179
+ }
180
+ catch (error) {
181
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, 'stack export', (error === null || error === void 0 ? void 0 : error.message) || utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.STACK_DETAILS].FAILED, utils_1.PROCESS_NAMES.STACK_DETAILS);
182
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
183
+ return undefined;
184
+ }
185
+ }
168
186
  return this.stack
169
187
  .fetch()
170
188
  .then((resp) => {
171
- var _a;
172
- const stackFilePath = (0, node_path_1.resolve)(this.stackFolderPath, this.stackConfig.fileName);
173
- cli_utilities_1.log.debug(`Writing stack data to: '${stackFilePath}'`, this.exportConfig.context);
174
- utils_1.fsUtil.writeFile(stackFilePath, resp);
175
- // Track progress for stack export completion
176
- (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `stack: ${this.exportConfig.apiKey}`, null, utils_1.PROCESS_NAMES.STACK_DETAILS);
177
- cli_utilities_1.log.success(`Stack details exported successfully for stack ${this.exportConfig.apiKey}`, this.exportConfig.context);
178
- cli_utilities_1.log.debug('Stack export completed successfully.', this.exportConfig.context);
179
- return resp;
189
+ return this.persistStackJsonPayload(resp);
180
190
  })
181
191
  .catch((error) => {
182
192
  var _a;
@@ -185,6 +195,40 @@ class ExportStack extends base_class_1.default {
185
195
  (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
186
196
  });
187
197
  }
198
+ isStackFetchPayload(data) {
199
+ return (typeof data === 'object' &&
200
+ data !== null &&
201
+ !Array.isArray(data) &&
202
+ ('api_key' in data || 'uid' in data));
203
+ }
204
+ /**
205
+ * Management-token exports cannot use Stack CMA endpoints for full metadata; write api_key from config only.
206
+ */
207
+ async writeStackJsonFromConfigApiKeyOnly() {
208
+ var _a;
209
+ if (!this.exportConfig.apiKey || typeof this.exportConfig.apiKey !== 'string') {
210
+ throw new Error('Stack API key is required to write stack.json when using a management token.');
211
+ }
212
+ cli_utilities_1.log.debug('Writing config-based stack.json (api_key only, no stack fetch).', this.exportConfig.context);
213
+ await utils_1.fsUtil.makeDirectory(this.stackFolderPath);
214
+ const payload = { api_key: this.exportConfig.apiKey };
215
+ const stackFilePath = (0, node_path_1.resolve)(this.stackFolderPath, this.stackConfig.fileName);
216
+ utils_1.fsUtil.writeFile(stackFilePath, payload);
217
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `stack: ${this.exportConfig.apiKey}`, null, utils_1.PROCESS_NAMES.STACK_DETAILS);
218
+ cli_utilities_1.log.success(`Stack identifier written to stack.json from config for stack ${this.exportConfig.apiKey}`, this.exportConfig.context);
219
+ return payload;
220
+ }
221
+ persistStackJsonPayload(resp) {
222
+ var _a, _b;
223
+ const sanitized = (0, omit_1.default)(resp, (_a = this.stackConfig.invalidKeys) !== null && _a !== void 0 ? _a : []);
224
+ const stackFilePath = (0, node_path_1.resolve)(this.stackFolderPath, this.stackConfig.fileName);
225
+ cli_utilities_1.log.debug(`Writing stack data to: '${stackFilePath}'`, this.exportConfig.context);
226
+ utils_1.fsUtil.writeFile(stackFilePath, sanitized);
227
+ (_b = this.progressManager) === null || _b === void 0 ? void 0 : _b.tick(true, `stack: ${this.exportConfig.apiKey}`, null, utils_1.PROCESS_NAMES.STACK_DETAILS);
228
+ cli_utilities_1.log.success(`Stack details exported successfully for stack ${this.exportConfig.apiKey}`, this.exportConfig.context);
229
+ cli_utilities_1.log.debug('Stack export completed successfully.', this.exportConfig.context);
230
+ return sanitized;
231
+ }
188
232
  async exportStackSettings() {
189
233
  cli_utilities_1.log.info('Exporting stack settings...', this.exportConfig.context);
190
234
  await utils_1.fsUtil.makeDirectory(this.stackFolderPath);
@@ -132,6 +132,7 @@ export default interface DefaultConfig {
132
132
  stack: {
133
133
  dirName: string;
134
134
  fileName: string;
135
+ invalidKeys: string[];
135
136
  dependencies?: Modules[];
136
137
  };
137
138
  dependency: {
@@ -93,6 +93,7 @@ export interface CustomRoleConfig {
93
93
  export interface StackConfig {
94
94
  dirName: string;
95
95
  fileName: string;
96
+ invalidKeys: string[];
96
97
  dependencies?: Modules[];
97
98
  limit?: number;
98
99
  }
@@ -121,5 +121,5 @@
121
121
  ]
122
122
  }
123
123
  },
124
- "version": "2.0.0-beta.12"
124
+ "version": "2.0.0-beta.14"
125
125
  }
package/package.json CHANGED
@@ -1,18 +1,18 @@
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.12",
4
+ "version": "2.0.0-beta.14",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
8
- "@contentstack/cli-command": "~2.0.0-beta.3",
9
- "@contentstack/cli-utilities": "~2.0.0-beta.3",
10
- "@contentstack/cli-variants": "~2.0.0-beta.9",
8
+ "@contentstack/cli-command": "~2.0.0-beta.5",
9
+ "@contentstack/cli-utilities": "~2.0.0-beta.5",
10
+ "@contentstack/cli-variants": "~2.0.0-beta.11",
11
11
  "@oclif/core": "^4.8.0",
12
12
  "async": "^3.2.6",
13
13
  "big-json": "^3.2.0",
14
14
  "bluebird": "^3.7.2",
15
- "chalk": "^4.1.2",
15
+ "chalk": "^5.6.2",
16
16
  "lodash": "^4.17.23",
17
17
  "merge": "^2.1.1",
18
18
  "mkdirp": "^1.0.4",
@@ -21,8 +21,8 @@
21
21
  "winston": "^3.17.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@contentstack/cli-auth": "~2.0.0-beta.7",
25
- "@contentstack/cli-config": "~2.0.0-beta.3",
24
+ "@contentstack/cli-auth": "~2.0.0-beta.9",
25
+ "@contentstack/cli-config": "~2.0.0-beta.5",
26
26
  "@contentstack/cli-dev-dependencies": "~2.0.0-beta.0",
27
27
  "@oclif/plugin-help": "^6.2.28",
28
28
  "@oclif/test": "^4.1.13",