@contentstack/cli-cm-export 2.0.0-beta.13 → 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.13 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'],
@@ -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.13"
124
+ "version": "2.0.0-beta.14"
125
125
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
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.13",
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.4",
9
- "@contentstack/cli-utilities": "~2.0.0-beta.4",
10
- "@contentstack/cli-variants": "~2.0.0-beta.10",
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",