@contentstack/cli-cm-import 1.28.3 → 1.30.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 +125 -67
- package/lib/commands/cm/stacks/import.js +8 -6
- package/lib/config/index.js +7 -0
- package/lib/import/modules/assets.js +18 -18
- package/lib/import/modules/base-class.d.ts +1 -0
- package/lib/import/modules/base-class.js +3 -1
- package/lib/import/modules/composable-studio.d.ts +43 -0
- package/lib/import/modules/composable-studio.js +231 -0
- package/lib/import/modules/content-types.js +9 -9
- package/lib/import/modules/custom-roles.js +24 -24
- package/lib/import/modules/entries.js +35 -18
- package/lib/import/modules/environments.js +10 -10
- package/lib/import/modules/extensions.js +16 -16
- package/lib/import/modules/global-fields.js +13 -13
- package/lib/import/modules/labels.js +12 -12
- package/lib/import/modules/locales.js +22 -22
- package/lib/import/modules/marketplace-apps.js +53 -53
- package/lib/import/modules/personalize.js +11 -11
- package/lib/import/modules/taxonomies.d.ts +23 -4
- package/lib/import/modules/taxonomies.js +180 -70
- package/lib/import/modules-js/entries.js +1 -1
- package/lib/import/modules-js/marketplace-apps.js +2 -2
- package/lib/types/default-config.d.ts +6 -0
- package/lib/types/index.d.ts +27 -1
- package/lib/utils/content-type-helper.js +2 -2
- package/lib/utils/file-helper.js +1 -1
- package/lib/utils/import-config-handler.js +2 -2
- package/lib/utils/login-handler.js +1 -1
- package/lib/utils/marketplace-app-helper.js +1 -1
- package/lib/utils/taxonomies-helper.js +1 -1
- package/messages/index.json +10 -1
- package/oclif.manifest.json +2 -2
- package/package.json +5 -5
|
@@ -10,6 +10,7 @@ const utils_1 = require("../../utils");
|
|
|
10
10
|
class ImportTaxonomies extends base_class_1.default {
|
|
11
11
|
constructor({ importConfig, stackAPIClient }) {
|
|
12
12
|
super({ importConfig, stackAPIClient });
|
|
13
|
+
this.isLocaleBasedStructure = false;
|
|
13
14
|
this.createdTaxonomies = {};
|
|
14
15
|
this.failedTaxonomies = {};
|
|
15
16
|
this.createdTerms = {};
|
|
@@ -23,34 +24,46 @@ class ImportTaxonomies extends base_class_1.default {
|
|
|
23
24
|
this.taxFailsPath = (0, node_path_1.join)(this.taxonomiesMapperDirPath, 'fails.json');
|
|
24
25
|
this.termsSuccessPath = (0, node_path_1.join)(this.termsMapperDirPath, 'success.json');
|
|
25
26
|
this.termsFailsPath = (0, node_path_1.join)(this.termsMapperDirPath, 'fails.json');
|
|
27
|
+
this.localesFilePath = (0, node_path_1.join)(importConfig.backupDir, importConfig.modules.locales.dirName, importConfig.modules.locales.fileName);
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
30
|
* @method start
|
|
29
31
|
* @returns {Promise<void>} Promise<void>
|
|
30
32
|
*/
|
|
31
33
|
async start() {
|
|
32
|
-
cli_utilities_1.log.debug('Checking for
|
|
34
|
+
cli_utilities_1.log.debug('Checking for taxonomy folder existence…', this.importConfig.context);
|
|
33
35
|
//Step1 check folder exists or not
|
|
34
36
|
if (utils_1.fileHelper.fileExistsSync(this.taxonomiesFolderPath)) {
|
|
35
|
-
cli_utilities_1.log.debug(`Found
|
|
37
|
+
cli_utilities_1.log.debug(`Found taxonomy folder at: ${this.taxonomiesFolderPath}`, this.importConfig.context);
|
|
36
38
|
this.taxonomies = utils_1.fsUtil.readFile((0, node_path_1.join)(this.taxonomiesFolderPath, 'taxonomies.json'), true);
|
|
37
39
|
const taxonomyCount = Object.keys(this.taxonomies || {}).length;
|
|
38
|
-
cli_utilities_1.log.debug(`Loaded ${taxonomyCount} taxonomy items from file
|
|
40
|
+
cli_utilities_1.log.debug(`Loaded ${taxonomyCount} taxonomy items from file.`, this.importConfig.context);
|
|
39
41
|
}
|
|
40
42
|
else {
|
|
41
|
-
cli_utilities_1.log.info(`No
|
|
43
|
+
cli_utilities_1.log.info(`No taxonomies found at: '${this.taxonomiesFolderPath}'`, this.importConfig.context);
|
|
42
44
|
return;
|
|
43
45
|
}
|
|
44
46
|
//Step 2 create taxonomies & terms mapper directory
|
|
45
|
-
cli_utilities_1.log.debug('Creating mapper directories', this.importConfig.context);
|
|
47
|
+
cli_utilities_1.log.debug('Creating mapper directories...', this.importConfig.context);
|
|
46
48
|
await utils_1.fsUtil.makeDirectory(this.taxonomiesMapperDirPath);
|
|
47
49
|
await utils_1.fsUtil.makeDirectory(this.termsMapperDirPath);
|
|
48
|
-
cli_utilities_1.log.debug('Created taxonomies and terms mapper directories', this.importConfig.context);
|
|
49
|
-
// Step 3
|
|
50
|
-
cli_utilities_1.log.debug('
|
|
51
|
-
|
|
52
|
-
//Step 4
|
|
53
|
-
|
|
50
|
+
cli_utilities_1.log.debug('Created taxonomies and terms mapper directories.', this.importConfig.context);
|
|
51
|
+
// Step 3: Check if locale-based structure exists and scan taxonomies by locale
|
|
52
|
+
cli_utilities_1.log.debug('Checking for locale-based folder structure', this.importConfig.context);
|
|
53
|
+
this.isLocaleBasedStructure = this.detectAndScanLocaleStructure();
|
|
54
|
+
// Step 4 import taxonomies
|
|
55
|
+
if (this.isLocaleBasedStructure) {
|
|
56
|
+
cli_utilities_1.log.debug('Detected locale-based folder structure for taxonomies', this.importConfig.context);
|
|
57
|
+
cli_utilities_1.log.debug('Starting taxonomies import...', this.importConfig.context);
|
|
58
|
+
await this.importTaxonomiesByLocale();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
cli_utilities_1.log.debug('Starting taxonomies import', this.importConfig.context);
|
|
62
|
+
await this.importTaxonomiesLegacy();
|
|
63
|
+
cli_utilities_1.log.debug('Using legacy folder structure for taxonomies', this.importConfig.context);
|
|
64
|
+
}
|
|
65
|
+
//Step 5 create taxonomy & related terms success & failure file
|
|
66
|
+
cli_utilities_1.log.debug('Creating success and failure files...', this.importConfig.context);
|
|
54
67
|
this.createSuccessAndFailedFile();
|
|
55
68
|
cli_utilities_1.log.success('Taxonomies imported successfully!', this.importConfig.context);
|
|
56
69
|
}
|
|
@@ -60,50 +73,9 @@ class ImportTaxonomies extends base_class_1.default {
|
|
|
60
73
|
* @async
|
|
61
74
|
* @returns {Promise<any>} Promise<any>
|
|
62
75
|
*/
|
|
63
|
-
async importTaxonomies() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
cli_utilities_1.log.info('No Taxonomies Found!', this.importConfig.context);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const apiContent = (0, values_1.default)(this.taxonomies);
|
|
70
|
-
cli_utilities_1.log.debug(`Starting to import ${apiContent.length} taxonomies`, this.importConfig.context);
|
|
71
|
-
const onSuccess = ({ apiData }) => {
|
|
72
|
-
var _a, _b;
|
|
73
|
-
const taxonomyUID = (_a = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _a === void 0 ? void 0 : _a.uid;
|
|
74
|
-
const taxonomyName = (_b = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _b === void 0 ? void 0 : _b.name;
|
|
75
|
-
const termsCount = Object.keys((apiData === null || apiData === void 0 ? void 0 : apiData.terms) || {}).length;
|
|
76
|
-
this.createdTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
|
|
77
|
-
this.createdTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
|
|
78
|
-
cli_utilities_1.log.success(`Taxonomy '${taxonomyUID}' imported successfully!`, this.importConfig.context);
|
|
79
|
-
cli_utilities_1.log.debug(`Created taxonomy '${taxonomyName}' with ${termsCount} terms`, this.importConfig.context);
|
|
80
|
-
cli_utilities_1.log.debug(`Taxonomy details: ${JSON.stringify({ uid: taxonomyUID, name: taxonomyName, termsCount })}`, this.importConfig.context);
|
|
81
|
-
};
|
|
82
|
-
const onReject = ({ error, apiData }) => {
|
|
83
|
-
var _a, _b, _c, _d;
|
|
84
|
-
const taxonomyUID = (_a = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _a === void 0 ? void 0 : _a.uid;
|
|
85
|
-
const taxonomyName = (_b = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _b === void 0 ? void 0 : _b.name;
|
|
86
|
-
cli_utilities_1.log.debug(`Taxonomy '${taxonomyUID}' failed to import`, this.importConfig.context);
|
|
87
|
-
if ((error === null || error === void 0 ? void 0 : error.status) === 409 && (error === null || error === void 0 ? void 0 : error.statusText) === 'Conflict') {
|
|
88
|
-
cli_utilities_1.log.info(`Taxonomy '${taxonomyUID}' already exists!`, this.importConfig.context);
|
|
89
|
-
cli_utilities_1.log.debug(`Adding existing taxonomy '${taxonomyUID}' to created list`, this.importConfig.context);
|
|
90
|
-
this.createdTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
|
|
91
|
-
this.createdTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
cli_utilities_1.log.debug(`Adding taxonomy '${taxonomyUID}' to failed list`, this.importConfig.context);
|
|
95
|
-
if ((error === null || error === void 0 ? void 0 : error.errorMessage) || (error === null || error === void 0 ? void 0 : error.message)) {
|
|
96
|
-
const errorMsg = (error === null || error === void 0 ? void 0 : error.errorMessage) || ((_c = error === null || error === void 0 ? void 0 : error.errors) === null || _c === void 0 ? void 0 : _c.taxonomy) || ((_d = error === null || error === void 0 ? void 0 : error.errors) === null || _d === void 0 ? void 0 : _d.term) || (error === null || error === void 0 ? void 0 : error.message);
|
|
97
|
-
cli_utilities_1.log.error(`Taxonomy '${taxonomyUID}' failed to be import! ${errorMsg}`, this.importConfig.context);
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { taxonomyUID }), `Taxonomy '${taxonomyUID}' failed to import`);
|
|
101
|
-
}
|
|
102
|
-
this.failedTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
|
|
103
|
-
this.failedTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
cli_utilities_1.log.debug(`Using concurrency limit: ${this.importConfig.concurrency || this.importConfig.fetchConcurrency || 1}`, this.importConfig.context);
|
|
76
|
+
async importTaxonomies({ apiContent, localeCode }) {
|
|
77
|
+
const onSuccess = ({ apiData }) => this.handleSuccess(apiData, localeCode);
|
|
78
|
+
const onReject = ({ error, apiData }) => this.handleFailure(error, apiData, localeCode);
|
|
107
79
|
await this.makeConcurrentCall({
|
|
108
80
|
apiContent,
|
|
109
81
|
processName: 'import taxonomies',
|
|
@@ -113,35 +85,157 @@ class ImportTaxonomies extends base_class_1.default {
|
|
|
113
85
|
resolve: onSuccess,
|
|
114
86
|
entity: 'import-taxonomy',
|
|
115
87
|
includeParamOnCompletion: true,
|
|
88
|
+
queryParam: {
|
|
89
|
+
locale: localeCode,
|
|
90
|
+
},
|
|
116
91
|
},
|
|
117
92
|
concurrencyLimit: this.importConfig.concurrency || this.importConfig.fetchConcurrency || 1,
|
|
118
93
|
}, undefined, false);
|
|
119
|
-
|
|
94
|
+
}
|
|
95
|
+
async importTaxonomiesLegacy() {
|
|
96
|
+
const apiContent = (0, values_1.default)(this.taxonomies);
|
|
97
|
+
await this.importTaxonomies({
|
|
98
|
+
apiContent,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async importTaxonomiesByLocale() {
|
|
102
|
+
const locales = this.loadAvailableLocales();
|
|
103
|
+
const apiContent = (0, values_1.default)(this.taxonomies);
|
|
104
|
+
for (const localeCode of Object.keys(locales)) {
|
|
105
|
+
await this.importTaxonomies({
|
|
106
|
+
apiContent,
|
|
107
|
+
localeCode,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
handleSuccess(apiData, locale) {
|
|
112
|
+
const { taxonomy, terms } = apiData || {};
|
|
113
|
+
const taxonomyUID = taxonomy === null || taxonomy === void 0 ? void 0 : taxonomy.uid;
|
|
114
|
+
const taxonomyName = taxonomy === null || taxonomy === void 0 ? void 0 : taxonomy.name;
|
|
115
|
+
const termsCount = Object.keys(terms || {}).length;
|
|
116
|
+
this.createdTaxonomies[taxonomyUID] = taxonomy;
|
|
117
|
+
this.createdTerms[taxonomyUID] = terms;
|
|
118
|
+
cli_utilities_1.log.success(`Taxonomy '${taxonomyUID}' imported successfully${locale ? ` for locale: ${locale}` : ''}!`, this.importConfig.context);
|
|
119
|
+
cli_utilities_1.log.debug(`Created taxonomy '${taxonomyName}' with ${termsCount} terms${locale ? ` for locale: ${locale}` : ''}`, this.importConfig.context);
|
|
120
|
+
}
|
|
121
|
+
handleFailure(error, apiData, locale) {
|
|
122
|
+
var _a, _b, _c;
|
|
123
|
+
const taxonomyUID = (_a = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy) === null || _a === void 0 ? void 0 : _a.uid;
|
|
124
|
+
if ((error === null || error === void 0 ? void 0 : error.status) === 409 && (error === null || error === void 0 ? void 0 : error.statusText) === 'Conflict') {
|
|
125
|
+
cli_utilities_1.log.info(`Taxonomy '${taxonomyUID}' already exists ${locale ? ` for locale: ${locale}` : ''}!`, this.importConfig.context);
|
|
126
|
+
this.createdTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
|
|
127
|
+
this.createdTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const errMsg = (error === null || error === void 0 ? void 0 : error.errorMessage) || ((_b = error === null || error === void 0 ? void 0 : error.errors) === null || _b === void 0 ? void 0 : _b.taxonomy) || ((_c = error === null || error === void 0 ? void 0 : error.errors) === null || _c === void 0 ? void 0 : _c.term) || (error === null || error === void 0 ? void 0 : error.message);
|
|
131
|
+
if (errMsg) {
|
|
132
|
+
cli_utilities_1.log.error(`Taxonomy '${taxonomyUID}' failed to import${locale ? ` for locale: ${locale}` : ''}! ${errMsg}`, this.importConfig.context);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { taxonomyUID, locale }), `Taxonomy '${taxonomyUID}' failed`);
|
|
136
|
+
}
|
|
137
|
+
this.failedTaxonomies[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.taxonomy;
|
|
138
|
+
this.failedTerms[taxonomyUID] = apiData === null || apiData === void 0 ? void 0 : apiData.terms;
|
|
120
139
|
}
|
|
121
140
|
/**
|
|
122
|
-
*
|
|
123
|
-
* @param {ApiOptions} apiOptions
|
|
124
|
-
* @
|
|
141
|
+
*
|
|
142
|
+
* @param {ApiOptions} apiOptions
|
|
143
|
+
* @param {?string} [localeCode]
|
|
144
|
+
* @returns {ApiOptions}
|
|
125
145
|
*/
|
|
126
146
|
serializeTaxonomy(apiOptions) {
|
|
127
|
-
const { apiData } = apiOptions;
|
|
147
|
+
const { apiData, queryParam: { locale }, } = apiOptions;
|
|
128
148
|
const taxonomyUID = apiData === null || apiData === void 0 ? void 0 : apiData.uid;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
149
|
+
if (!taxonomyUID) {
|
|
150
|
+
cli_utilities_1.log.debug('No taxonomy UID provided for serialization', this.importConfig.context);
|
|
151
|
+
apiOptions.apiData = undefined;
|
|
152
|
+
return apiOptions;
|
|
153
|
+
}
|
|
154
|
+
const context = locale ? ` for locale: ${locale}` : '';
|
|
155
|
+
cli_utilities_1.log.debug(`Serializing taxonomy: ${taxonomyUID}${context}`, this.importConfig.context);
|
|
156
|
+
// Determine file path - if locale is provided, use it directly, otherwise search
|
|
157
|
+
const filePath = locale
|
|
158
|
+
? (0, node_path_1.join)(this.taxonomiesFolderPath, locale, `${taxonomyUID}.json`)
|
|
159
|
+
: this.findTaxonomyFilePath(taxonomyUID);
|
|
160
|
+
if (!filePath || !utils_1.fileHelper.fileExistsSync(filePath)) {
|
|
161
|
+
cli_utilities_1.log.debug(`Taxonomy file not found for: ${taxonomyUID}${context}`, this.importConfig.context);
|
|
162
|
+
apiOptions.apiData = undefined;
|
|
163
|
+
return apiOptions;
|
|
164
|
+
}
|
|
165
|
+
const taxonomyDetails = this.loadTaxonomyFile(filePath, locale || 'auto-detected');
|
|
166
|
+
if (taxonomyDetails) {
|
|
135
167
|
const termCount = Object.keys((taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.terms) || {}).length;
|
|
136
|
-
cli_utilities_1.log.debug(`Taxonomy has ${termCount} term entries`, this.importConfig.context);
|
|
137
|
-
apiOptions.apiData = {
|
|
168
|
+
cli_utilities_1.log.debug(`Taxonomy has ${termCount} term entries${context}`, this.importConfig.context);
|
|
169
|
+
apiOptions.apiData = {
|
|
170
|
+
filePath,
|
|
171
|
+
taxonomy: taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.taxonomy,
|
|
172
|
+
terms: taxonomyDetails === null || taxonomyDetails === void 0 ? void 0 : taxonomyDetails.terms,
|
|
173
|
+
};
|
|
138
174
|
}
|
|
139
175
|
else {
|
|
140
|
-
cli_utilities_1.log.debug(`File does not exist for taxonomy: ${taxonomyUID}`, this.importConfig.context);
|
|
141
176
|
apiOptions.apiData = undefined;
|
|
142
177
|
}
|
|
143
178
|
return apiOptions;
|
|
144
179
|
}
|
|
180
|
+
loadTaxonomyFile(filePath, context) {
|
|
181
|
+
if (!utils_1.fileHelper.fileExistsSync(filePath)) {
|
|
182
|
+
cli_utilities_1.log.debug(`File does not exist: ${filePath}`, this.importConfig.context);
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
const taxonomyDetails = utils_1.fsUtil.readFile(filePath, true);
|
|
187
|
+
cli_utilities_1.log.debug(`Successfully loaded taxonomy from: ${context}`, this.importConfig.context);
|
|
188
|
+
return taxonomyDetails;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
cli_utilities_1.log.debug(`Error loading taxonomy file: ${filePath}`, this.importConfig.context);
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
findTaxonomyFilePath(taxonomyUID) {
|
|
196
|
+
if (this.isLocaleBasedStructure) {
|
|
197
|
+
// For locale-based structure, search in locale folders
|
|
198
|
+
return this.findTaxonomyInLocaleFolders(taxonomyUID);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// For legacy structure, only check the root folder
|
|
202
|
+
const legacyPath = (0, node_path_1.join)(this.taxonomiesFolderPath, `${taxonomyUID}.json`);
|
|
203
|
+
return utils_1.fileHelper.fileExistsSync(legacyPath) ? legacyPath : undefined;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
findTaxonomyInLocaleFolders(taxonomyUID) {
|
|
207
|
+
const locales = this.loadAvailableLocales();
|
|
208
|
+
for (const localeCode of Object.keys(locales)) {
|
|
209
|
+
const filePath = (0, node_path_1.join)(this.taxonomiesFolderPath, localeCode, `${taxonomyUID}.json`);
|
|
210
|
+
if (utils_1.fileHelper.fileExistsSync(filePath)) {
|
|
211
|
+
return filePath;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
loadAvailableLocales() {
|
|
217
|
+
var _a, _b;
|
|
218
|
+
if (!utils_1.fileHelper.fileExistsSync(this.localesFilePath)) {
|
|
219
|
+
cli_utilities_1.log.debug('No locales file found', this.importConfig.context);
|
|
220
|
+
return {};
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const localesData = utils_1.fsUtil.readFile(this.localesFilePath, true);
|
|
224
|
+
const locales = {};
|
|
225
|
+
locales[(_a = this.importConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code] = (_b = this.importConfig.master_locale) === null || _b === void 0 ? void 0 : _b.code;
|
|
226
|
+
for (const [code, locale] of Object.entries(localesData)) {
|
|
227
|
+
if (locale === null || locale === void 0 ? void 0 : locale.code) {
|
|
228
|
+
locales[locale.code] = code;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
cli_utilities_1.log.debug(`Loaded ${Object.keys(locales).length} locales from file`, this.importConfig.context);
|
|
232
|
+
return locales;
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
cli_utilities_1.log.debug('Error loading locales file', this.importConfig.context);
|
|
236
|
+
return {};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
145
239
|
/**
|
|
146
240
|
* create taxonomies success and fail in (mapper/taxonomies)
|
|
147
241
|
* create terms success and fail in (mapper/taxonomies/terms)
|
|
@@ -149,7 +243,7 @@ class ImportTaxonomies extends base_class_1.default {
|
|
|
149
243
|
*/
|
|
150
244
|
createSuccessAndFailedFile() {
|
|
151
245
|
var _a, _b, _c, _d;
|
|
152
|
-
cli_utilities_1.log.debug('Creating success and failed files for taxonomies and terms', this.importConfig.context);
|
|
246
|
+
cli_utilities_1.log.debug('Creating success and failed files for taxonomies and terms...', this.importConfig.context);
|
|
153
247
|
const createdTaxCount = (_a = Object.keys(this.createdTaxonomies)) === null || _a === void 0 ? void 0 : _a.length;
|
|
154
248
|
const failedTaxCount = (_b = Object.keys(this.failedTaxonomies)) === null || _b === void 0 ? void 0 : _b.length;
|
|
155
249
|
const createdTermsCount = (_c = Object.keys(this.createdTerms)) === null || _c === void 0 ? void 0 : _c.length;
|
|
@@ -173,5 +267,21 @@ class ImportTaxonomies extends base_class_1.default {
|
|
|
173
267
|
cli_utilities_1.log.debug(`Written failed terms for ${failedTermsCount} taxonomies to file: ${this.termsFailsPath}`, this.importConfig.context);
|
|
174
268
|
}
|
|
175
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Detect if locale-based folder structure exists and scan taxonomies by locale
|
|
272
|
+
* @returns {boolean} true if locale-based structure detected, false otherwise
|
|
273
|
+
*/
|
|
274
|
+
detectAndScanLocaleStructure() {
|
|
275
|
+
var _a;
|
|
276
|
+
const masterLocaleCode = ((_a = this.importConfig.master_locale) === null || _a === void 0 ? void 0 : _a.code) || 'en-us';
|
|
277
|
+
const masterLocaleFolder = (0, node_path_1.join)(this.taxonomiesFolderPath, masterLocaleCode);
|
|
278
|
+
// Check if master locale folder exists (indicates new locale-based structure)
|
|
279
|
+
if (!utils_1.fileHelper.fileExistsSync(masterLocaleFolder)) {
|
|
280
|
+
cli_utilities_1.log.debug('No locale-based folder structure detected', this.importConfig.context);
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
cli_utilities_1.log.debug('Locale-based folder structure detected', this.importConfig.context);
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
176
286
|
}
|
|
177
287
|
exports.default = ImportTaxonomies;
|
|
@@ -934,7 +934,7 @@ module.exports = class ImportEntries {
|
|
|
934
934
|
addlogs(this.config, `Entries published successfully in '${ctUid}' content type`, 'info');
|
|
935
935
|
})
|
|
936
936
|
.catch((error) => {
|
|
937
|
-
console.log(error);
|
|
937
|
+
console.log('Error', error);
|
|
938
938
|
addlogs(this.config, `failed to publish entry in content type '${ctUid}' ${formatError(error)}`, 'error');
|
|
939
939
|
});
|
|
940
940
|
}
|
|
@@ -65,7 +65,7 @@ module.exports = class ImportMarketplaceApps {
|
|
|
65
65
|
.stack({ api_key: this.config.target_stack })
|
|
66
66
|
.fetch()
|
|
67
67
|
.catch((error) => {
|
|
68
|
-
console.log(error);
|
|
68
|
+
console.log('Error', error);
|
|
69
69
|
});
|
|
70
70
|
if (tempStackData === null || tempStackData === void 0 ? void 0 : tempStackData.org_uid) {
|
|
71
71
|
this.config.org_uid = tempStackData.org_uid;
|
|
@@ -376,7 +376,7 @@ module.exports = class ImportMarketplaceApps {
|
|
|
376
376
|
return updateParam;
|
|
377
377
|
}
|
|
378
378
|
async confirmToCloseProcess(installation) {
|
|
379
|
-
cliux.print(`\nWARNING
|
|
379
|
+
cliux.print(`\nWARNING: ${formatError(installation.message)}\n`, { color: 'yellow' });
|
|
380
380
|
if (!this.config.forceStopMarketplaceAppsPrompt) {
|
|
381
381
|
if (!(await cliux.confirm(chalk.yellow('WARNING!!! The above error may have an impact if the failed app is referenced in entries/content type. Would you like to proceed? (y/n)')))) {
|
|
382
382
|
process.exit();
|
|
@@ -156,6 +156,12 @@ export default interface DefaultConfig {
|
|
|
156
156
|
locale: string;
|
|
157
157
|
} & AnyProperty;
|
|
158
158
|
} & AnyProperty;
|
|
159
|
+
'composable-studio': {
|
|
160
|
+
dirName: string;
|
|
161
|
+
fileName: string;
|
|
162
|
+
apiBaseUrl: string;
|
|
163
|
+
apiVersion: string;
|
|
164
|
+
};
|
|
159
165
|
};
|
|
160
166
|
languagesCode: string[];
|
|
161
167
|
apis: {
|
package/lib/types/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export interface User {
|
|
|
26
26
|
email: string;
|
|
27
27
|
authtoken: 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' | 'variant-entries';
|
|
29
|
+
export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies' | 'personalize' | 'variant-entries' | 'composable-studio';
|
|
30
30
|
export type ModuleClassParams = {
|
|
31
31
|
stackAPIClient: ReturnType<ContentstackClient['stack']>;
|
|
32
32
|
importConfig: ImportConfig;
|
|
@@ -71,6 +71,32 @@ export interface TaxonomiesConfig {
|
|
|
71
71
|
fileName: string;
|
|
72
72
|
dependencies?: Modules[];
|
|
73
73
|
}
|
|
74
|
+
export interface ComposableStudioConfig {
|
|
75
|
+
dirName: string;
|
|
76
|
+
fileName: string;
|
|
77
|
+
apiBaseUrl: string;
|
|
78
|
+
apiVersion: string;
|
|
79
|
+
}
|
|
80
|
+
export interface ComposableStudioProject {
|
|
81
|
+
name: string;
|
|
82
|
+
description: string;
|
|
83
|
+
canvasUrl: string;
|
|
84
|
+
connectedStackApiKey: string;
|
|
85
|
+
contentTypeUid: string;
|
|
86
|
+
organizationUid: string;
|
|
87
|
+
settings: {
|
|
88
|
+
configuration: {
|
|
89
|
+
environment: string;
|
|
90
|
+
locale: string;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
uid?: string;
|
|
94
|
+
createdBy?: string;
|
|
95
|
+
updatedBy?: string;
|
|
96
|
+
deletedAt?: boolean;
|
|
97
|
+
createdAt?: string;
|
|
98
|
+
updatedAt?: string;
|
|
99
|
+
}
|
|
74
100
|
export interface Context {
|
|
75
101
|
command: string;
|
|
76
102
|
module: string;
|
|
@@ -128,7 +128,7 @@ const removeReferenceFields = async function (schema, flag = { supressed: false
|
|
|
128
128
|
catch (error) {
|
|
129
129
|
// Else warn and modify the schema object.
|
|
130
130
|
isContentTypeError = true;
|
|
131
|
-
cli_utilities_1.log.warn(`Content
|
|
131
|
+
cli_utilities_1.log.warn(`Content type ${schema[i].reference_to[j]} does not exist. Removing the field from schema...`);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
if (isContentTypeError) {
|
|
@@ -200,7 +200,7 @@ const updateFieldRules = function (contentType) {
|
|
|
200
200
|
const field = contentType.schema[i];
|
|
201
201
|
fieldDataTypeMap[field.uid] = field.data_type;
|
|
202
202
|
}
|
|
203
|
-
cli_utilities_1.log.debug(`Created field data type mapping for ${Object.keys(fieldDataTypeMap).length} fields
|
|
203
|
+
cli_utilities_1.log.debug(`Created field data type mapping for ${Object.keys(fieldDataTypeMap).length} fields.`);
|
|
204
204
|
const fieldRules = [...contentType.field_rules];
|
|
205
205
|
let len = fieldRules.length;
|
|
206
206
|
let removedRules = 0;
|
package/lib/utils/file-helper.js
CHANGED
|
@@ -26,7 +26,7 @@ const setupConfig = async (importCmdFlags) => {
|
|
|
26
26
|
config.contentDir = (0, cli_utilities_1.sanitizePath)(importCmdFlags['data'] || importCmdFlags['data-dir'] || config.data || (await (0, interactive_1.askContentDir)()));
|
|
27
27
|
const pattern = /[*$%#<>{}!&?]/g;
|
|
28
28
|
if (pattern.test(config.contentDir)) {
|
|
29
|
-
cli_utilities_1.cliux.print(`\nPlease
|
|
29
|
+
cli_utilities_1.cliux.print(`\nPlease enter a directory path without any special characters: (*,&,{,},[,],$,%,<,>,?,!)`, {
|
|
30
30
|
color: 'yellow',
|
|
31
31
|
});
|
|
32
32
|
config.contentDir = (0, cli_utilities_1.sanitizePath)(await (0, interactive_1.askContentDir)());
|
|
@@ -115,7 +115,7 @@ const setupConfig = async (importCmdFlags) => {
|
|
|
115
115
|
}
|
|
116
116
|
// Add authentication details to config for context tracking
|
|
117
117
|
config.authenticationMethod = authenticationMethod;
|
|
118
|
-
cli_utilities_1.log.debug('Import configuration setup completed', Object.assign({}, config));
|
|
118
|
+
cli_utilities_1.log.debug('Import configuration setup completed.', Object.assign({}, config));
|
|
119
119
|
return config;
|
|
120
120
|
};
|
|
121
121
|
exports.default = setupConfig;
|
|
@@ -44,7 +44,7 @@ const login = async (config) => {
|
|
|
44
44
|
let errorstack_key = (_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.api_key;
|
|
45
45
|
if (errorstack_key) {
|
|
46
46
|
const keyError = errorstack_key[0];
|
|
47
|
-
cli_utilities_1.log.error(`Invalid stack API token: ${keyError} Please enter valid stack API token.`);
|
|
47
|
+
cli_utilities_1.log.error(`Invalid stack API token: ${keyError}. Please enter a valid stack API token.`);
|
|
48
48
|
throw error;
|
|
49
49
|
}
|
|
50
50
|
cli_utilities_1.log.error(`Stack fetch error: ${error === null || error === void 0 ? void 0 : error.errorMessage}`);
|
|
@@ -81,7 +81,7 @@ const getConfirmationToCreateApps = async (privateApps, config) => {
|
|
|
81
81
|
return Promise.resolve(true);
|
|
82
82
|
}
|
|
83
83
|
else {
|
|
84
|
-
cli_utilities_1.log.debug('User declined to create private apps (second prompt)');
|
|
84
|
+
cli_utilities_1.log.debug('User declined to create private apps (second prompt).');
|
|
85
85
|
return Promise.resolve(false);
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -14,7 +14,7 @@ const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
|
14
14
|
* @param {ImportConfig} importConfig
|
|
15
15
|
*/
|
|
16
16
|
const lookUpTaxonomy = function (importConfig, schema, taxonomies) {
|
|
17
|
-
cli_utilities_1.log.debug(`Starting taxonomy lookup for schema with ${Object.keys(schema).length} fields
|
|
17
|
+
cli_utilities_1.log.debug(`Starting taxonomy lookup for schema with ${Object.keys(schema).length} fields.`);
|
|
18
18
|
for (let i in schema) {
|
|
19
19
|
if (schema[i].data_type === 'taxonomy') {
|
|
20
20
|
cli_utilities_1.log.debug(`Processing taxonomy field: ${schema[i].uid}`);
|
package/messages/index.json
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"COMPOSABLE_STUDIO_IMPORT_START": "Starting Composable Studio project import...",
|
|
3
|
+
"COMPOSABLE_STUDIO_NOT_FOUND": "No Composable Studio project found in exported data",
|
|
4
|
+
"COMPOSABLE_STUDIO_SKIP_EXISTING": "Skipping Composable Studio import - target stack already has a connected project",
|
|
5
|
+
"COMPOSABLE_STUDIO_IMPORT_COMPLETE": "Successfully imported Composable Studio project '%s'",
|
|
6
|
+
"COMPOSABLE_STUDIO_IMPORT_FAILED": "Failed to import Composable Studio project: %s",
|
|
7
|
+
"COMPOSABLE_STUDIO_NAME_CONFLICT": "Project name '%s' already exists. Please provide a new name:",
|
|
8
|
+
"COMPOSABLE_STUDIO_SUGGEST_NAME": "Suggested name: %s",
|
|
9
|
+
"COMPOSABLE_STUDIO_ENV_MAPPING_FAILED": "Warning: Could not map environment '%s', using empty environment"
|
|
10
|
+
}
|
package/oclif.manifest.json
CHANGED
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
},
|
|
85
85
|
"module": {
|
|
86
86
|
"char": "m",
|
|
87
|
-
"description": "[optional] Specify the module to import into the target stack. If not specified, the import command will import all the modules into the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, personalize projects, and
|
|
87
|
+
"description": "[optional] Specify the module to import into the target stack. If not specified, the import command will import all the modules into the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, personalize projects, taxonomies, and composable-studio.",
|
|
88
88
|
"name": "module",
|
|
89
89
|
"required": false,
|
|
90
90
|
"hasDynamicHelp": false,
|
|
@@ -212,5 +212,5 @@
|
|
|
212
212
|
]
|
|
213
213
|
}
|
|
214
214
|
},
|
|
215
|
-
"version": "1.
|
|
215
|
+
"version": "1.30.0"
|
|
216
216
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-import",
|
|
3
3
|
"description": "Contentstack CLI plugin to import content into stack",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.30.0",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-audit": "~1.
|
|
9
|
-
"@contentstack/cli-command": "~1.
|
|
10
|
-
"@contentstack/cli-utilities": "~1.
|
|
8
|
+
"@contentstack/cli-audit": "~1.16.1",
|
|
9
|
+
"@contentstack/cli-command": "~1.7.0",
|
|
10
|
+
"@contentstack/cli-utilities": "~1.15.0",
|
|
11
11
|
"@contentstack/management": "~1.22.0",
|
|
12
|
-
"@contentstack/cli-variants": "~1.3.
|
|
12
|
+
"@contentstack/cli-variants": "~1.3.5",
|
|
13
13
|
"@oclif/core": "^4.3.0",
|
|
14
14
|
"big-json": "^3.2.0",
|
|
15
15
|
"bluebird": "^3.7.2",
|