@contentstack/cli-cm-export 2.0.0-beta.7 → 2.0.0-beta.9
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 +1 -1
- package/lib/commands/cm/stacks/export.js +5 -3
- package/lib/constants/index.d.ts +57 -0
- package/lib/constants/index.js +59 -0
- package/lib/export/modules/assets.js +3 -2
- package/lib/export/modules/base-class.d.ts +1 -1
- package/lib/export/modules/base-class.js +3 -2
- package/lib/export/modules/content-types.js +2 -1
- package/lib/export/modules/entries.js +8 -8
- package/lib/export/modules/stack.js +2 -1
- package/lib/export/modules/taxonomies.d.ts +20 -0
- package/lib/export/modules/taxonomies.js +123 -24
- package/oclif.manifest.json +1 -1
- package/package.json +7 -7
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.
|
|
51
|
+
@contentstack/cli-cm-export/2.0.0-beta.9 linux-x64 node-v22.22.0
|
|
52
52
|
$ csdx --help [COMMAND]
|
|
53
53
|
USAGE
|
|
54
54
|
$ csdx COMMAND
|
|
@@ -20,14 +20,15 @@ class ExportCommand extends cli_command_1.Command {
|
|
|
20
20
|
const managementAPIClient = await (0, cli_utilities_1.managementSDKClient)(exportConfig);
|
|
21
21
|
const moduleExporter = new export_1.ModuleExporter(managementAPIClient, exportConfig);
|
|
22
22
|
await moduleExporter.start();
|
|
23
|
+
const sessionLogPath = (0, cli_utilities_1.getSessionLogPath)();
|
|
23
24
|
cli_utilities_1.log.success(`The content of the stack ${exportConfig.apiKey} has been exported successfully!`);
|
|
24
25
|
cli_utilities_1.log.info(`The exported content has been stored at '${exportDir}'`, exportConfig.context);
|
|
25
|
-
cli_utilities_1.log.success(`The log has been stored at '${
|
|
26
|
+
cli_utilities_1.log.success(`The log has been stored at '${sessionLogPath}'`, exportConfig.context);
|
|
26
27
|
// Print comprehensive summary at the end
|
|
27
28
|
if (!exportConfig.branches)
|
|
28
29
|
cli_utilities_1.CLIProgressManager.printGlobalSummary();
|
|
29
30
|
if (!((_a = cli_utilities_1.configHandler.get('log')) === null || _a === void 0 ? void 0 : _a.showConsoleLogs)) {
|
|
30
|
-
cli_utilities_1.cliux.print(`The log has been stored at '${
|
|
31
|
+
cli_utilities_1.cliux.print(`The log has been stored at '${sessionLogPath}'`, { color: 'green' });
|
|
31
32
|
}
|
|
32
33
|
// Clear progress module setting now that export is complete
|
|
33
34
|
(0, cli_utilities_1.clearProgressModuleSetting)();
|
|
@@ -36,9 +37,10 @@ class ExportCommand extends cli_command_1.Command {
|
|
|
36
37
|
// Clear progress module setting even on error
|
|
37
38
|
(0, cli_utilities_1.clearProgressModuleSetting)();
|
|
38
39
|
(0, cli_utilities_1.handleAndLogError)(error);
|
|
40
|
+
const sessionLogPath = (0, cli_utilities_1.getSessionLogPath)();
|
|
39
41
|
if (!((_b = cli_utilities_1.configHandler.get('log')) === null || _b === void 0 ? void 0 : _b.showConsoleLogs)) {
|
|
40
42
|
cli_utilities_1.cliux.print(`Error: ${error}`, { color: 'red' });
|
|
41
|
-
cli_utilities_1.cliux.print(`The log has been stored at '${
|
|
43
|
+
cli_utilities_1.cliux.print(`The log has been stored at '${sessionLogPath}'`, { color: 'green' });
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export declare const PATH_CONSTANTS: {
|
|
2
|
+
/** Root mapper directory (contains module-specific mapper subdirs) */
|
|
3
|
+
readonly MAPPER: "mapper";
|
|
4
|
+
/** Common mapper file names */
|
|
5
|
+
readonly FILES: {
|
|
6
|
+
readonly SUCCESS: "success.json";
|
|
7
|
+
readonly FAILS: "fails.json";
|
|
8
|
+
readonly UID_MAPPING: "uid-mapping.json";
|
|
9
|
+
readonly URL_MAPPING: "url-mapping.json";
|
|
10
|
+
readonly UID_MAPPER: "uid-mapper.json";
|
|
11
|
+
readonly SCHEMA: "schema.json";
|
|
12
|
+
readonly SETTINGS: "settings.json";
|
|
13
|
+
readonly MODIFIED_SCHEMAS: "modified-schemas.json";
|
|
14
|
+
readonly UNIQUE_MAPPING: "unique-mapping.json";
|
|
15
|
+
readonly TAXONOMIES: "taxonomies.json";
|
|
16
|
+
readonly ENVIRONMENTS: "environments.json";
|
|
17
|
+
readonly PENDING_EXTENSIONS: "pending_extensions.js";
|
|
18
|
+
readonly PENDING_GLOBAL_FIELDS: "pending_global_fields.js";
|
|
19
|
+
readonly INDEX: "index.json";
|
|
20
|
+
readonly FOLDER_MAPPING: "folder-mapping.json";
|
|
21
|
+
readonly VERSIONED_ASSETS: "versioned-assets.json";
|
|
22
|
+
};
|
|
23
|
+
/** Module subdirectory names within mapper */
|
|
24
|
+
readonly MAPPER_MODULES: {
|
|
25
|
+
readonly ASSETS: "assets";
|
|
26
|
+
readonly ENTRIES: "entries";
|
|
27
|
+
readonly CONTENT_TYPES: "content_types";
|
|
28
|
+
readonly TAXONOMIES: "taxonomies";
|
|
29
|
+
readonly TAXONOMY_TERMS: "terms";
|
|
30
|
+
readonly GLOBAL_FIELDS: "global_fields";
|
|
31
|
+
readonly EXTENSIONS: "extensions";
|
|
32
|
+
readonly WORKFLOWS: "workflows";
|
|
33
|
+
readonly WEBHOOKS: "webhooks";
|
|
34
|
+
readonly LABELS: "labels";
|
|
35
|
+
readonly ENVIRONMENTS: "environments";
|
|
36
|
+
readonly MARKETPLACE_APPS: "marketplace_apps";
|
|
37
|
+
readonly CUSTOM_ROLES: "custom-roles";
|
|
38
|
+
readonly LANGUAGES: "languages";
|
|
39
|
+
};
|
|
40
|
+
/** Content directory names (used in both import and export) */
|
|
41
|
+
readonly CONTENT_DIRS: {
|
|
42
|
+
readonly ASSETS: "assets";
|
|
43
|
+
readonly ENTRIES: "entries";
|
|
44
|
+
readonly CONTENT_TYPES: "content_types";
|
|
45
|
+
readonly TAXONOMIES: "taxonomies";
|
|
46
|
+
readonly GLOBAL_FIELDS: "global_fields";
|
|
47
|
+
readonly EXTENSIONS: "extensions";
|
|
48
|
+
readonly WEBHOOKS: "webhooks";
|
|
49
|
+
readonly WORKFLOWS: "workflows";
|
|
50
|
+
readonly LABELS: "labels";
|
|
51
|
+
readonly ENVIRONMENTS: "environments";
|
|
52
|
+
readonly STACK: "stack";
|
|
53
|
+
readonly LOCALES: "locales";
|
|
54
|
+
readonly MARKETPLACE_APPS: "marketplace_apps";
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export type PathConstants = typeof PATH_CONSTANTS;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PATH_CONSTANTS = void 0;
|
|
4
|
+
exports.PATH_CONSTANTS = {
|
|
5
|
+
/** Root mapper directory (contains module-specific mapper subdirs) */
|
|
6
|
+
MAPPER: 'mapper',
|
|
7
|
+
/** Common mapper file names */
|
|
8
|
+
FILES: {
|
|
9
|
+
SUCCESS: 'success.json',
|
|
10
|
+
FAILS: 'fails.json',
|
|
11
|
+
UID_MAPPING: 'uid-mapping.json',
|
|
12
|
+
URL_MAPPING: 'url-mapping.json',
|
|
13
|
+
UID_MAPPER: 'uid-mapper.json',
|
|
14
|
+
SCHEMA: 'schema.json',
|
|
15
|
+
SETTINGS: 'settings.json',
|
|
16
|
+
MODIFIED_SCHEMAS: 'modified-schemas.json',
|
|
17
|
+
UNIQUE_MAPPING: 'unique-mapping.json',
|
|
18
|
+
TAXONOMIES: 'taxonomies.json',
|
|
19
|
+
ENVIRONMENTS: 'environments.json',
|
|
20
|
+
PENDING_EXTENSIONS: 'pending_extensions.js',
|
|
21
|
+
PENDING_GLOBAL_FIELDS: 'pending_global_fields.js',
|
|
22
|
+
INDEX: 'index.json',
|
|
23
|
+
FOLDER_MAPPING: 'folder-mapping.json',
|
|
24
|
+
VERSIONED_ASSETS: 'versioned-assets.json',
|
|
25
|
+
},
|
|
26
|
+
/** Module subdirectory names within mapper */
|
|
27
|
+
MAPPER_MODULES: {
|
|
28
|
+
ASSETS: 'assets',
|
|
29
|
+
ENTRIES: 'entries',
|
|
30
|
+
CONTENT_TYPES: 'content_types',
|
|
31
|
+
TAXONOMIES: 'taxonomies',
|
|
32
|
+
TAXONOMY_TERMS: 'terms',
|
|
33
|
+
GLOBAL_FIELDS: 'global_fields',
|
|
34
|
+
EXTENSIONS: 'extensions',
|
|
35
|
+
WORKFLOWS: 'workflows',
|
|
36
|
+
WEBHOOKS: 'webhooks',
|
|
37
|
+
LABELS: 'labels',
|
|
38
|
+
ENVIRONMENTS: 'environments',
|
|
39
|
+
MARKETPLACE_APPS: 'marketplace_apps',
|
|
40
|
+
CUSTOM_ROLES: 'custom-roles',
|
|
41
|
+
LANGUAGES: 'languages',
|
|
42
|
+
},
|
|
43
|
+
/** Content directory names (used in both import and export) */
|
|
44
|
+
CONTENT_DIRS: {
|
|
45
|
+
ASSETS: 'assets',
|
|
46
|
+
ENTRIES: 'entries',
|
|
47
|
+
CONTENT_TYPES: 'content_types',
|
|
48
|
+
TAXONOMIES: 'taxonomies',
|
|
49
|
+
GLOBAL_FIELDS: 'global_fields',
|
|
50
|
+
EXTENSIONS: 'extensions',
|
|
51
|
+
WEBHOOKS: 'webhooks',
|
|
52
|
+
WORKFLOWS: 'workflows',
|
|
53
|
+
LABELS: 'labels',
|
|
54
|
+
ENVIRONMENTS: 'environments',
|
|
55
|
+
STACK: 'stack',
|
|
56
|
+
LOCALES: 'locales',
|
|
57
|
+
MARKETPLACE_APPS: 'marketplace_apps',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -16,6 +16,7 @@ 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
18
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
19
|
+
const constants_1 = require("../../constants");
|
|
19
20
|
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
20
21
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
21
22
|
const utils_1 = require("../../utils");
|
|
@@ -170,7 +171,7 @@ class ExportAssets extends base_class_1.default {
|
|
|
170
171
|
fs = new cli_utilities_1.FsUtility({
|
|
171
172
|
metaHandler,
|
|
172
173
|
moduleName: 'assets',
|
|
173
|
-
indexFileName:
|
|
174
|
+
indexFileName: this.assetConfig.fileName,
|
|
174
175
|
basePath: this.assetsRootPath,
|
|
175
176
|
chunkFileSize: this.assetConfig.chunkFileSize,
|
|
176
177
|
metaPickKeys: (0, merge_1.default)(['uid', 'url', 'filename', 'parent_uid'], this.assetConfig.assetsMetaKeys),
|
|
@@ -235,7 +236,7 @@ class ExportAssets extends base_class_1.default {
|
|
|
235
236
|
if (!fs && !(0, isEmpty_1.default)(response)) {
|
|
236
237
|
fs = new cli_utilities_1.FsUtility({
|
|
237
238
|
moduleName: 'assets',
|
|
238
|
-
indexFileName:
|
|
239
|
+
indexFileName: constants_1.PATH_CONSTANTS.FILES.VERSIONED_ASSETS,
|
|
239
240
|
chunkFileSize: this.assetConfig.chunkFileSize,
|
|
240
241
|
basePath: (0, node_path_1.resolve)(this.assetsRootPath, 'versions'),
|
|
241
242
|
metaPickKeys: (0, merge_1.default)(['uid', 'url', 'filename', '_version', 'parent_uid'], this.assetConfig.assetsMetaKeys),
|
|
@@ -57,7 +57,7 @@ export default abstract class BaseClass {
|
|
|
57
57
|
* - moduleName: The module name to generate the message (e.g., 'Assets', 'Entries')
|
|
58
58
|
* If not provided, uses this.currentModuleName
|
|
59
59
|
* - customSuccessMessage: Optional custom success message. If not provided, generates: "{moduleName} have been exported successfully!"
|
|
60
|
-
* - customWarningMessage: Optional custom warning message. If not provided, generates: "{moduleName} have been exported with some errors. Please check the logs
|
|
60
|
+
* - customWarningMessage: Optional custom warning message. If not provided, generates: "{moduleName} have been exported with some errors. Please check the logs at: {sessionLogPath}"
|
|
61
61
|
* - context: Optional context for logging
|
|
62
62
|
*/
|
|
63
63
|
protected completeProgressWithMessage(options?: CompleteProgressOptions): void;
|
|
@@ -56,7 +56,7 @@ class BaseClass {
|
|
|
56
56
|
* - moduleName: The module name to generate the message (e.g., 'Assets', 'Entries')
|
|
57
57
|
* If not provided, uses this.currentModuleName
|
|
58
58
|
* - customSuccessMessage: Optional custom success message. If not provided, generates: "{moduleName} have been exported successfully!"
|
|
59
|
-
* - customWarningMessage: Optional custom warning message. If not provided, generates: "{moduleName} have been exported with some errors. Please check the logs
|
|
59
|
+
* - customWarningMessage: Optional custom warning message. If not provided, generates: "{moduleName} have been exported with some errors. Please check the logs at: {sessionLogPath}"
|
|
60
60
|
* - context: Optional context for logging
|
|
61
61
|
*/
|
|
62
62
|
completeProgressWithMessage(options) {
|
|
@@ -67,7 +67,8 @@ class BaseClass {
|
|
|
67
67
|
const name = (options === null || options === void 0 ? void 0 : options.moduleName) || this.currentModuleName || 'Module';
|
|
68
68
|
// Generate default messages if not provided
|
|
69
69
|
const successMessage = (options === null || options === void 0 ? void 0 : options.customSuccessMessage) || `${name} have been exported successfully!`;
|
|
70
|
-
const
|
|
70
|
+
const sessionLogPath = (0, cli_utilities_1.getSessionLogPath)();
|
|
71
|
+
const warningMessage = (options === null || options === void 0 ? void 0 : options.customWarningMessage) || `${name} have been exported with some errors. Please check the logs at: ${sessionLogPath}`;
|
|
71
72
|
this.completeProgress(true);
|
|
72
73
|
if (hasErrors) {
|
|
73
74
|
cli_utilities_1.log.warn(warningMessage, logContext);
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const path = tslib_1.__importStar(require("path"));
|
|
5
5
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
|
+
const constants_1 = require("../../constants");
|
|
6
7
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
7
8
|
const utils_1 = require("../../utils");
|
|
8
9
|
class ContentTypesExport extends base_class_1.default {
|
|
@@ -105,7 +106,7 @@ class ContentTypesExport extends base_class_1.default {
|
|
|
105
106
|
await (0, utils_1.executeTask)(contentTypes, writeWithProgress.bind(this), {
|
|
106
107
|
concurrency: this.exportConfig.writeConcurrency,
|
|
107
108
|
});
|
|
108
|
-
const schemaFilePath = path.join(this.contentTypesDirPath,
|
|
109
|
+
const schemaFilePath = path.join(this.contentTypesDirPath, constants_1.PATH_CONSTANTS.FILES.SCHEMA);
|
|
109
110
|
cli_utilities_1.log.debug(`Writing aggregate schema to: ${schemaFilePath}`, this.exportConfig.context);
|
|
110
111
|
return utils_1.fsUtil.writeFile(schemaFilePath, contentTypes);
|
|
111
112
|
}
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const path = tslib_1.__importStar(require("path"));
|
|
5
5
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
|
+
const constants_1 = require("../../constants");
|
|
6
7
|
const cli_variants_1 = require("@contentstack/cli-variants");
|
|
7
|
-
const cli_utilities_2 = require("@contentstack/cli-utilities");
|
|
8
8
|
const utils_1 = require("../../utils");
|
|
9
9
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
10
10
|
class EntriesExport extends base_class_1.default {
|
|
@@ -14,9 +14,9 @@ class EntriesExport extends base_class_1.default {
|
|
|
14
14
|
this.stackAPIClient = stackAPIClient;
|
|
15
15
|
this.exportConfig = exportConfig;
|
|
16
16
|
this.entriesConfig = exportConfig.modules.entries;
|
|
17
|
-
this.entriesDirPath = path.resolve((0,
|
|
18
|
-
this.localesFilePath = path.resolve((0,
|
|
19
|
-
this.schemaFilePath = path.resolve((0,
|
|
17
|
+
this.entriesDirPath = path.resolve((0, cli_utilities_1.sanitizePath)(exportConfig.exportDir), (0, cli_utilities_1.sanitizePath)(exportConfig.branchName || ''), (0, cli_utilities_1.sanitizePath)(this.entriesConfig.dirName));
|
|
18
|
+
this.localesFilePath = path.resolve((0, cli_utilities_1.sanitizePath)(exportConfig.exportDir), (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
|
+
this.schemaFilePath = path.resolve((0, cli_utilities_1.sanitizePath)(exportConfig.exportDir), (0, cli_utilities_1.sanitizePath)(exportConfig.branchName || ''), (0, cli_utilities_1.sanitizePath)(exportConfig.modules.content_types.dirName), constants_1.PATH_CONSTANTS.FILES.SCHEMA);
|
|
20
20
|
this.projectInstance = new cli_variants_1.ExportProjects(this.exportConfig);
|
|
21
21
|
this.exportConfig.context.module = utils_1.MODULE_CONTEXTS.ENTRIES;
|
|
22
22
|
this.currentModuleName = utils_1.MODULE_NAMES[utils_1.MODULE_CONTEXTS.ENTRIES];
|
|
@@ -205,12 +205,12 @@ class EntriesExport extends base_class_1.default {
|
|
|
205
205
|
}
|
|
206
206
|
if (Array.isArray(entriesSearchResponse === null || entriesSearchResponse === void 0 ? void 0 : entriesSearchResponse.items) && ((_b = entriesSearchResponse === null || entriesSearchResponse === void 0 ? void 0 : entriesSearchResponse.items) === null || _b === void 0 ? void 0 : _b.length) > 0) {
|
|
207
207
|
if (options.skip === 0) {
|
|
208
|
-
const entryBasePath = path.join((0,
|
|
208
|
+
const entryBasePath = path.join((0, cli_utilities_1.sanitizePath)(this.entriesDirPath), (0, cli_utilities_1.sanitizePath)(options.contentType), (0, cli_utilities_1.sanitizePath)(options.locale));
|
|
209
209
|
cli_utilities_1.log.debug(`Creating directory for entries at: ${entryBasePath}`, this.exportConfig.context);
|
|
210
210
|
await utils_1.fsUtil.makeDirectory(entryBasePath);
|
|
211
211
|
this.entriesFileHelper = new cli_utilities_1.FsUtility({
|
|
212
212
|
moduleName: 'entries',
|
|
213
|
-
indexFileName:
|
|
213
|
+
indexFileName: constants_1.PATH_CONSTANTS.FILES.INDEX,
|
|
214
214
|
basePath: entryBasePath,
|
|
215
215
|
chunkFileSize: this.entriesConfig.chunkFileSize,
|
|
216
216
|
keepMetadata: false,
|
|
@@ -227,7 +227,7 @@ class EntriesExport extends base_class_1.default {
|
|
|
227
227
|
});
|
|
228
228
|
if (this.entriesConfig.exportVersions) {
|
|
229
229
|
cli_utilities_1.log.debug('Exporting entry versions is enabled.', this.exportConfig.context);
|
|
230
|
-
let versionedEntryPath = path.join((0,
|
|
230
|
+
let versionedEntryPath = path.join((0, cli_utilities_1.sanitizePath)(this.entriesDirPath), (0, cli_utilities_1.sanitizePath)(options.contentType), (0, cli_utilities_1.sanitizePath)(options.locale), 'versions');
|
|
231
231
|
cli_utilities_1.log.debug(`Creating versioned entries directory at: ${versionedEntryPath}.`, this.exportConfig.context);
|
|
232
232
|
utils_1.fsUtil.makeDirectory(versionedEntryPath);
|
|
233
233
|
await this.fetchEntriesVersions(entriesSearchResponse.items, {
|
|
@@ -271,7 +271,7 @@ class EntriesExport extends base_class_1.default {
|
|
|
271
271
|
cli_utilities_1.log.debug(`Fetching versions for ${entries.length} entries...`, this.exportConfig.context);
|
|
272
272
|
const onSuccess = ({ response, apiData: entry }) => {
|
|
273
273
|
var _a;
|
|
274
|
-
const versionFilePath = path.join((0,
|
|
274
|
+
const versionFilePath = path.join((0, cli_utilities_1.sanitizePath)(options.versionedEntryPath), (0, cli_utilities_1.sanitizePath)(`${entry.uid}.json`));
|
|
275
275
|
cli_utilities_1.log.debug(`Writing versioned entry to: ${versionFilePath}`, this.exportConfig.context);
|
|
276
276
|
utils_1.fsUtil.writeFile(versionFilePath, response);
|
|
277
277
|
// Track version progress if the process exists
|
|
@@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
5
5
|
const node_path_1 = require("node:path");
|
|
6
6
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
|
+
const constants_1 = require("../../constants");
|
|
7
8
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
8
9
|
const utils_1 = require("../../utils");
|
|
9
10
|
class ExportStack extends base_class_1.default {
|
|
@@ -191,7 +192,7 @@ class ExportStack extends base_class_1.default {
|
|
|
191
192
|
.settings()
|
|
192
193
|
.then((resp) => {
|
|
193
194
|
var _a;
|
|
194
|
-
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.stackFolderPath,
|
|
195
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.stackFolderPath, constants_1.PATH_CONSTANTS.FILES.SETTINGS), resp);
|
|
195
196
|
// Track progress for stack settings completion
|
|
196
197
|
(_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, 'stack settings', null, utils_1.PROCESS_NAMES.STACK_SETTINGS);
|
|
197
198
|
cli_utilities_1.log.success('Exported stack settings successfully!', this.exportConfig.context);
|
|
@@ -10,6 +10,26 @@ export default class ExportTaxonomies extends BaseClass {
|
|
|
10
10
|
private localesFilePath;
|
|
11
11
|
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
12
12
|
start(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Initialize export setup (create directories, get initial count)
|
|
15
|
+
*/
|
|
16
|
+
private initializeExport;
|
|
17
|
+
/**
|
|
18
|
+
* Setup progress manager with processes
|
|
19
|
+
*/
|
|
20
|
+
private setupProgress;
|
|
21
|
+
/**
|
|
22
|
+
* Determine if locale-based export is supported
|
|
23
|
+
*/
|
|
24
|
+
private determineExportStrategy;
|
|
25
|
+
/**
|
|
26
|
+
* Fetch all taxonomies based on export strategy
|
|
27
|
+
*/
|
|
28
|
+
private fetchAllTaxonomies;
|
|
29
|
+
/**
|
|
30
|
+
* Export all taxonomies with detailed information
|
|
31
|
+
*/
|
|
32
|
+
private exportAllTaxonomies;
|
|
13
33
|
/**
|
|
14
34
|
* Process and export taxonomies for a specific locale
|
|
15
35
|
*/
|
|
@@ -17,44 +17,131 @@ class ExportTaxonomies extends base_class_1.default {
|
|
|
17
17
|
this.taxonomiesConfig = exportConfig.modules.taxonomies;
|
|
18
18
|
this.qs = { include_count: true, limit: this.taxonomiesConfig.limit || 100, skip: 0 };
|
|
19
19
|
this.applyQueryFilters(this.qs, 'taxonomies');
|
|
20
|
-
this.exportConfig.context.module =
|
|
20
|
+
this.exportConfig.context.module = utils_1.MODULE_CONTEXTS.TAXONOMIES;
|
|
21
|
+
this.currentModuleName = utils_1.MODULE_NAMES[utils_1.MODULE_CONTEXTS.TAXONOMIES];
|
|
21
22
|
this.localesFilePath = (0, node_path_1.resolve)((0, cli_utilities_1.sanitizePath)(exportConfig.exportDir), (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));
|
|
22
23
|
}
|
|
23
24
|
async start() {
|
|
24
25
|
var _a;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
try {
|
|
27
|
+
cli_utilities_1.log.debug('Starting export process for taxonomies...', this.exportConfig.context);
|
|
28
|
+
const totalCount = await this.initializeExport();
|
|
29
|
+
if (totalCount === 0) {
|
|
30
|
+
cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('TAXONOMY_NOT_FOUND'), this.exportConfig.context);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const progress = this.setupProgress(totalCount);
|
|
34
|
+
const localesToExport = this.getLocalesToExport();
|
|
35
|
+
if (localesToExport.length === 0) {
|
|
36
|
+
cli_utilities_1.log.warn('No locales found to export', this.exportConfig.context);
|
|
37
|
+
this.completeProgress(true);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Start fetch process
|
|
41
|
+
progress
|
|
42
|
+
.startProcess(utils_1.PROCESS_NAMES.FETCH_TAXONOMIES)
|
|
43
|
+
.updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.FETCH_TAXONOMIES].FETCHING, utils_1.PROCESS_NAMES.FETCH_TAXONOMIES);
|
|
44
|
+
// Determine export strategy and fetch taxonomies
|
|
45
|
+
await this.determineExportStrategy((_a = this.exportConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code);
|
|
46
|
+
await this.fetchAllTaxonomies(localesToExport);
|
|
47
|
+
progress.completeProcess(utils_1.PROCESS_NAMES.FETCH_TAXONOMIES, true);
|
|
48
|
+
// Export taxonomies with detailed information
|
|
49
|
+
const actualCount = await this.exportAllTaxonomies(progress, localesToExport, totalCount);
|
|
50
|
+
// Write metadata and complete
|
|
51
|
+
await this.writeTaxonomiesMetadata();
|
|
52
|
+
cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_COMPLETE', actualCount), this.exportConfig.context);
|
|
53
|
+
this.completeProgress(true);
|
|
36
54
|
}
|
|
37
|
-
|
|
38
|
-
|
|
55
|
+
catch (error) {
|
|
56
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
|
|
57
|
+
this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Taxonomies export failed');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Initialize export setup (create directories, get initial count)
|
|
62
|
+
*/
|
|
63
|
+
async initializeExport() {
|
|
64
|
+
return this.withLoadingSpinner('TAXONOMIES: Analyzing taxonomy structure...', async () => {
|
|
65
|
+
this.taxonomiesFolderPath = (0, node_path_1.resolve)(this.exportConfig.exportDir, this.exportConfig.branchName || '', this.taxonomiesConfig.dirName);
|
|
66
|
+
cli_utilities_1.log.debug(`Taxonomies folder path: '${this.taxonomiesFolderPath}'`, this.exportConfig.context);
|
|
67
|
+
await utils_1.fsUtil.makeDirectory(this.taxonomiesFolderPath);
|
|
68
|
+
cli_utilities_1.log.debug('Created taxonomies directory.', this.exportConfig.context);
|
|
69
|
+
// Get count first for progress tracking
|
|
70
|
+
const countResponse = await this.stack
|
|
71
|
+
.taxonomy()
|
|
72
|
+
.query(Object.assign(Object.assign({}, this.qs), { include_count: true, limit: 1 }))
|
|
73
|
+
.find();
|
|
74
|
+
return countResponse.count || 0;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Setup progress manager with processes
|
|
79
|
+
*/
|
|
80
|
+
setupProgress(totalCount) {
|
|
81
|
+
const progress = this.createNestedProgress(this.currentModuleName);
|
|
82
|
+
// For fetch: count API calls, not individual taxonomies
|
|
83
|
+
const fetchApiCallsCount = Math.ceil(totalCount / (this.qs.limit || 100));
|
|
84
|
+
progress.addProcess(utils_1.PROCESS_NAMES.FETCH_TAXONOMIES, fetchApiCallsCount);
|
|
85
|
+
progress.addProcess(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS, totalCount);
|
|
86
|
+
return progress;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Determine if locale-based export is supported
|
|
90
|
+
*/
|
|
91
|
+
async determineExportStrategy(masterLocale) {
|
|
39
92
|
await this.fetchTaxonomies(masterLocale, true);
|
|
40
93
|
if (!this.isLocaleBasedExportSupported) {
|
|
94
|
+
cli_utilities_1.log.debug('Falling back to legacy export (non-localized)', this.exportConfig.context);
|
|
41
95
|
this.taxonomies = {};
|
|
42
96
|
this.taxonomiesByLocale = {};
|
|
43
|
-
// Fetch taxonomies without locale parameter
|
|
44
|
-
await this.fetchTaxonomies();
|
|
45
|
-
await this.exportTaxonomies();
|
|
46
|
-
await this.writeTaxonomiesMetadata();
|
|
47
97
|
}
|
|
48
98
|
else {
|
|
49
|
-
// Process all locales with locale-based export
|
|
50
99
|
cli_utilities_1.log.debug('Localization enabled, proceeding with locale-based export', this.exportConfig.context);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Fetch all taxonomies based on export strategy
|
|
104
|
+
*/
|
|
105
|
+
async fetchAllTaxonomies(localesToExport) {
|
|
106
|
+
if (!this.isLocaleBasedExportSupported) {
|
|
107
|
+
await this.fetchTaxonomies();
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
51
110
|
for (const localeCode of localesToExport) {
|
|
52
111
|
await this.fetchTaxonomies(localeCode);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Export all taxonomies with detailed information
|
|
117
|
+
*/
|
|
118
|
+
async exportAllTaxonomies(progress, localesToExport, totalCount) {
|
|
119
|
+
var _a;
|
|
120
|
+
const actualCount = (_a = Object.keys(this.taxonomies || {})) === null || _a === void 0 ? void 0 : _a.length;
|
|
121
|
+
cli_utilities_1.log.debug(`Found ${actualCount} taxonomies to export (API reported ${totalCount})`, this.exportConfig.context);
|
|
122
|
+
if (actualCount === 0) {
|
|
123
|
+
cli_utilities_1.log.info('No taxonomies found to export detailed information', this.exportConfig.context);
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
// Update progress total if needed
|
|
127
|
+
if (actualCount !== totalCount) {
|
|
128
|
+
progress.updateProcessTotal(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS, actualCount);
|
|
129
|
+
}
|
|
130
|
+
// Start export process
|
|
131
|
+
progress
|
|
132
|
+
.startProcess(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS)
|
|
133
|
+
.updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS].EXPORTING, utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS);
|
|
134
|
+
// Export based on strategy
|
|
135
|
+
if (!this.isLocaleBasedExportSupported) {
|
|
136
|
+
await this.exportTaxonomies();
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
for (const localeCode of localesToExport) {
|
|
53
140
|
await this.processLocaleExport(localeCode);
|
|
54
141
|
}
|
|
55
|
-
await this.writeTaxonomiesMetadata();
|
|
56
142
|
}
|
|
57
|
-
|
|
143
|
+
progress.completeProcess(utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS, true);
|
|
144
|
+
return actualCount;
|
|
58
145
|
}
|
|
59
146
|
/**
|
|
60
147
|
* Process and export taxonomies for a specific locale
|
|
@@ -77,7 +164,7 @@ class ExportTaxonomies extends base_class_1.default {
|
|
|
77
164
|
cli_utilities_1.log.info(cli_utilities_1.messageHandler.parse('TAXONOMY_NOT_FOUND'), this.exportConfig.context);
|
|
78
165
|
return;
|
|
79
166
|
}
|
|
80
|
-
const taxonomiesFilePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath,
|
|
167
|
+
const taxonomiesFilePath = (0, node_path_1.resolve)(this.taxonomiesFolderPath, this.taxonomiesConfig.fileName);
|
|
81
168
|
cli_utilities_1.log.debug(`Writing taxonomies metadata to: ${taxonomiesFilePath}`, this.exportConfig.context);
|
|
82
169
|
utils_1.fsUtil.writeFile(taxonomiesFilePath, this.taxonomies);
|
|
83
170
|
}
|
|
@@ -90,7 +177,7 @@ class ExportTaxonomies extends base_class_1.default {
|
|
|
90
177
|
* @returns {Promise<void>}
|
|
91
178
|
*/
|
|
92
179
|
async fetchTaxonomies(localeCode, checkLocaleSupport = false) {
|
|
93
|
-
var _a;
|
|
180
|
+
var _a, _b;
|
|
94
181
|
let skip = 0;
|
|
95
182
|
const localeInfo = localeCode ? `for locale: ${localeCode}` : '';
|
|
96
183
|
if (localeCode && !this.taxonomiesByLocale[localeCode]) {
|
|
@@ -117,6 +204,10 @@ class ExportTaxonomies extends base_class_1.default {
|
|
|
117
204
|
this.isLocaleBasedExportSupported = false;
|
|
118
205
|
}
|
|
119
206
|
this.sanitizeTaxonomiesAttribs(items, localeCode);
|
|
207
|
+
// Track progress per API call (only for actual fetch, not locale support check)
|
|
208
|
+
if (!checkLocaleSupport) {
|
|
209
|
+
(_b = this.progressManager) === null || _b === void 0 ? void 0 : _b.tick(true, `fetched ${items.length} taxonomies${localeInfo}`, null, utils_1.PROCESS_NAMES.FETCH_TAXONOMIES);
|
|
210
|
+
}
|
|
120
211
|
skip += this.qs.limit || 100;
|
|
121
212
|
if (skip >= taxonomiesCount) {
|
|
122
213
|
cli_utilities_1.log.debug(`Completed fetching all taxonomies ${localeInfo}`, this.exportConfig.context);
|
|
@@ -183,13 +274,21 @@ class ExportTaxonomies extends base_class_1.default {
|
|
|
183
274
|
cli_utilities_1.log.debug(`Created locale folder: ${exportFolderPath}`, this.exportConfig.context);
|
|
184
275
|
}
|
|
185
276
|
const onSuccess = ({ response, uid }) => {
|
|
277
|
+
var _a, _b;
|
|
278
|
+
const taxonomyName = (_a = this.taxonomies[uid]) === null || _a === void 0 ? void 0 : _a.name;
|
|
186
279
|
const filePath = (0, node_path_1.resolve)(exportFolderPath, `${uid}.json`);
|
|
187
280
|
cli_utilities_1.log.debug(`Writing detailed taxonomy data to: ${filePath}`, this.exportConfig.context);
|
|
188
281
|
utils_1.fsUtil.writeFile(filePath, response);
|
|
189
|
-
|
|
282
|
+
// Track progress for each exported taxonomy
|
|
283
|
+
(_b = this.progressManager) === null || _b === void 0 ? void 0 : _b.tick(true, `taxonomy: ${taxonomyName || uid}`, null, utils_1.PROCESS_NAMES.EXPORT_TAXONOMIES_TERMS);
|
|
284
|
+
cli_utilities_1.log.success(cli_utilities_1.messageHandler.parse('TAXONOMY_EXPORT_SUCCESS', taxonomyName || uid), this.exportConfig.context);
|
|
190
285
|
};
|
|
191
286
|
const onReject = ({ error, uid }) => {
|
|
287
|
+
var _a, _b;
|
|
288
|
+
const taxonomyName = (_a = this.taxonomies[uid]) === null || _a === void 0 ? void 0 : _a.name;
|
|
192
289
|
cli_utilities_1.log.debug(`Failed to export detailed data for taxonomy: ${uid}${localeInfo}`, this.exportConfig.context);
|
|
290
|
+
// Track failure
|
|
291
|
+
(_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);
|
|
193
292
|
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign(Object.assign({}, this.exportConfig.context), { uid }), (localeCode && { locale: localeCode })));
|
|
194
293
|
};
|
|
195
294
|
for (const taxonomyUID of taxonomiesUID) {
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
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.9",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-command": "~
|
|
9
|
-
"@contentstack/cli-utilities": "~
|
|
10
|
-
"@contentstack/cli-variants": "~2.0.0-beta.
|
|
8
|
+
"@contentstack/cli-command": "~2.0.0-beta",
|
|
9
|
+
"@contentstack/cli-utilities": "~2.0.0-beta",
|
|
10
|
+
"@contentstack/cli-variants": "~2.0.0-beta.5",
|
|
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
15
|
"chalk": "^4.1.2",
|
|
16
|
-
"lodash": "^4.17.
|
|
16
|
+
"lodash": "^4.17.23",
|
|
17
17
|
"merge": "^2.1.1",
|
|
18
18
|
"mkdirp": "^1.0.4",
|
|
19
19
|
"progress-stream": "^2.0.0",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"winston": "^3.17.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@contentstack/cli-auth": "~2.0.0-beta.
|
|
25
|
-
"@contentstack/cli-config": "~
|
|
24
|
+
"@contentstack/cli-auth": "~2.0.0-beta.5",
|
|
25
|
+
"@contentstack/cli-config": "~2.0.0-beta.1",
|
|
26
26
|
"@contentstack/cli-dev-dependencies": "~1.3.1",
|
|
27
27
|
"@oclif/plugin-help": "^6.2.28",
|
|
28
28
|
"@oclif/test": "^4.1.13",
|