@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.
- package/README.md +3 -3
- package/lib/commands/cm/stacks/export.js +7 -4
- package/lib/config/index.js +7 -0
- package/lib/export/module-exporter.js +4 -3
- package/lib/export/modules/base-class.js +1 -1
- package/lib/export/modules/composable-studio.d.ts +15 -0
- package/lib/export/modules/composable-studio.js +87 -0
- package/lib/export/modules/content-types.js +3 -3
- package/lib/export/modules/custom-roles.js +18 -20
- package/lib/export/modules/entries.js +7 -7
- package/lib/export/modules/environments.js +13 -13
- package/lib/export/modules/extensions.js +16 -16
- package/lib/export/modules/global-fields.js +16 -16
- package/lib/export/modules/labels.js +17 -17
- package/lib/export/modules/locales.js +17 -17
- package/lib/export/modules/marketplace-apps.js +32 -32
- package/lib/export/modules/personalize.js +14 -14
- package/lib/export/modules/stack.js +26 -26
- package/lib/export/modules/taxonomies.d.ts +28 -9
- package/lib/export/modules/taxonomies.js +191 -68
- package/lib/export/modules-js/assets.js +3 -3
- package/lib/types/default-config.d.ts +6 -0
- package/lib/types/index.d.ts +27 -1
- package/lib/utils/basic-login.js +1 -1
- package/lib/utils/export-config-handler.js +5 -5
- package/lib/utils/file-helper.js +1 -1
- package/messages/index.json +6 -0
- package/oclif.manifest.json +2 -2
- package/package.json +14 -7
|
@@ -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
|
|
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}
|
|
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}
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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}
|
|
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}
|
|
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}
|
|
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)}
|
|
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
|
|
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
|
|
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})
|
|
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}
|
|
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
|
|
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}
|
|
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(`
|
|
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
|
-
*
|
|
12
|
-
* @param {number} skip
|
|
13
|
-
* @returns {Promise<any>}
|
|
14
|
+
* Process and export taxonomies for a specific locale
|
|
14
15
|
*/
|
|
15
|
-
|
|
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
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
28
|
-
cli_utilities_1.log.debug(
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
*
|
|
46
|
-
* @param {number} skip
|
|
47
|
-
* @returns {Promise<any>}
|
|
60
|
+
* Process and export taxonomies for a specific locale
|
|
48
61
|
*/
|
|
49
|
-
async
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
cli_utilities_1.log.
|
|
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(
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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(
|
|
72
|
-
|
|
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
|
-
|
|
78
|
-
cli_utilities_1.log.debug(
|
|
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
|
-
|
|
93
|
-
cli_utilities_1.log.debug(`
|
|
94
|
-
for (
|
|
95
|
-
const taxonomyUID =
|
|
96
|
-
const taxonomyName =
|
|
97
|
-
cli_utilities_1.log.debug(`Processing taxonomy: ${taxonomyName} (${taxonomyUID})`, this.exportConfig.context);
|
|
98
|
-
|
|
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(`
|
|
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
|
|
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
|
-
|
|
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)(
|
|
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 (
|
|
120
|
-
|
|
121
|
-
|
|
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(
|
|
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
|
|
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('
|
|
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;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -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;
|
package/lib/utils/basic-login.js
CHANGED