@contentstack/cli-cm-import 1.8.3 → 1.9.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 +1 -1
- package/bin/dev +4 -15
- package/lib/commands/cm/stacks/import.js +5 -2
- package/lib/config/index.js +2 -16
- package/lib/import/module-importer.js +2 -5
- package/lib/import/modules/assets.js +5 -2
- package/lib/import/modules/base-class.js +29 -14
- package/lib/import/modules/custom-roles.d.ts +1 -1
- package/lib/import/modules/custom-roles.js +12 -7
- package/lib/import/modules/entries.js +119 -68
- package/lib/import/modules/environments.d.ts +1 -1
- package/lib/import/modules/environments.js +3 -4
- package/lib/import/modules/extensions.js +3 -4
- package/lib/import/modules/global-fields.js +3 -2
- package/lib/import/modules/labels.d.ts +2 -2
- package/lib/import/modules/labels.js +6 -7
- package/lib/import/modules/marketplace-apps.d.ts +1 -0
- package/lib/import/modules/marketplace-apps.js +11 -5
- package/lib/import/modules/webhooks.d.ts +1 -1
- package/lib/import/modules/webhooks.js +3 -4
- package/lib/import/modules/workflows.js +11 -7
- package/lib/import/modules-js/entries.js +3 -3
- package/lib/import/modules-js/marketplace-apps.d.ts +1 -0
- package/lib/import/modules-js/marketplace-apps.js +9 -2
- package/lib/import/modules-js/workflows.js +5 -1
- package/lib/types/default-config.d.ts +0 -2
- package/lib/types/import-config.d.ts +1 -0
- package/lib/utils/asset-helper.d.ts +1 -1
- package/lib/utils/asset-helper.js +1 -2
- package/lib/utils/backup-handler.js +37 -17
- package/lib/utils/entries-helper.d.ts +6 -3
- package/lib/utils/entries-helper.js +14 -14
- package/lib/utils/import-config-handler.js +7 -0
- package/lib/utils/logger.js +1 -1
- package/lib/utils/marketplace-app-helper.js +9 -2
- package/oclif.manifest.json +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import
|
|
|
47
47
|
$ csdx COMMAND
|
|
48
48
|
running command...
|
|
49
49
|
$ csdx (--version)
|
|
50
|
-
@contentstack/cli-cm-import/1.
|
|
50
|
+
@contentstack/cli-cm-import/1.9.0 linux-x64 node-v18.18.0
|
|
51
51
|
$ csdx --help [COMMAND]
|
|
52
52
|
USAGE
|
|
53
53
|
$ csdx COMMAND
|
package/bin/dev
CHANGED
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// In dev mode -> use ts-node and dev plugins
|
|
9
|
-
process.env.NODE_ENV = 'development';
|
|
10
|
-
|
|
11
|
-
require('ts-node').register({ project });
|
|
12
|
-
|
|
13
|
-
// In dev mode, always show stack traces
|
|
14
|
-
oclif.settings.debug = true;
|
|
15
|
-
|
|
16
|
-
// Start the CLI
|
|
17
|
-
oclif.run().then(oclif.flush).catch(oclif.Errors.handle);
|
|
3
|
+
(async () => {
|
|
4
|
+
const oclif = require('@oclif/core');
|
|
5
|
+
await oclif.execute({ type: 'cjs', development: true, dir: __dirname });
|
|
6
|
+
})();
|
|
@@ -12,20 +12,23 @@ class ImportCommand extends cli_command_1.Command {
|
|
|
12
12
|
// initialize the importer
|
|
13
13
|
// start import
|
|
14
14
|
let contentDir;
|
|
15
|
+
let backupDir;
|
|
15
16
|
try {
|
|
16
17
|
const { flags } = await this.parse(ImportCommand);
|
|
17
18
|
let importConfig = await (0, utils_1.setupImportConfig)(flags);
|
|
18
19
|
// Note setting host to create cma client
|
|
19
20
|
importConfig.host = this.cmaHost;
|
|
20
21
|
contentDir = importConfig.contentDir;
|
|
22
|
+
backupDir = importConfig.backupDir;
|
|
21
23
|
const managementAPIClient = await (0, cli_utilities_1.managementSDKClient)(importConfig);
|
|
22
24
|
const moduleImporter = new import_1.ModuleImporter(managementAPIClient, importConfig);
|
|
23
25
|
await moduleImporter.start();
|
|
24
26
|
(0, utils_1.log)(importConfig, `The content has been imported to the stack ${importConfig.apiKey} successfully!`, 'success');
|
|
27
|
+
(0, utils_1.log)(importConfig, `The log has been stored at '${node_path_1.default.join(importConfig.backupDir, 'logs', 'import')}'`, 'success');
|
|
25
28
|
}
|
|
26
29
|
catch (error) {
|
|
27
|
-
(0, utils_1.log)({ data:
|
|
28
|
-
(0, utils_1.log)({ data:
|
|
30
|
+
(0, utils_1.log)({ data: backupDir }, `Failed to import stack content - ${(0, utils_1.formatError)(error)}`, 'error');
|
|
31
|
+
(0, utils_1.log)({ data: backupDir }, `The log has been stored at ${{ data: backupDir } ? node_path_1.default.join(backupDir || __dirname, 'logs', 'import') : node_path_1.default.join(__dirname, 'logs')}`, 'info');
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
}
|
package/lib/config/index.js
CHANGED
|
@@ -84,9 +84,9 @@ const config = {
|
|
|
84
84
|
publishAssets: true,
|
|
85
85
|
fileName: 'assets.json',
|
|
86
86
|
importSameStructure: true,
|
|
87
|
-
uploadAssetsConcurrency:
|
|
87
|
+
uploadAssetsConcurrency: 2,
|
|
88
88
|
displayExecutionTime: false,
|
|
89
|
-
importFoldersConcurrency:
|
|
89
|
+
importFoldersConcurrency: 1,
|
|
90
90
|
includeVersionedAssets: false,
|
|
91
91
|
host: 'https://api.contentstack.io',
|
|
92
92
|
folderValidKeys: ['name', 'parent_uid'],
|
|
@@ -367,19 +367,6 @@ const config = {
|
|
|
367
367
|
stacks: '/stacks/',
|
|
368
368
|
labels: '/labels/',
|
|
369
369
|
},
|
|
370
|
-
updatedModules: [
|
|
371
|
-
'assets',
|
|
372
|
-
'extensions',
|
|
373
|
-
'locales',
|
|
374
|
-
'marketplace-apps',
|
|
375
|
-
'labels',
|
|
376
|
-
'global-fields',
|
|
377
|
-
'content-types',
|
|
378
|
-
'webhooks',
|
|
379
|
-
'custom-roles',
|
|
380
|
-
'workflows',
|
|
381
|
-
'entries',
|
|
382
|
-
],
|
|
383
370
|
rateLimit: 5,
|
|
384
371
|
preserveStackVersion: false,
|
|
385
372
|
entriesPublish: true,
|
|
@@ -390,7 +377,6 @@ const config = {
|
|
|
390
377
|
developerHubBaseUrl: '',
|
|
391
378
|
marketplaceAppEncryptionKey: 'nF2ejRQcTv',
|
|
392
379
|
getEncryptionKeyMaxRetry: 3,
|
|
393
|
-
useNewModuleStructure: false,
|
|
394
380
|
// useBackedupDir: '',
|
|
395
381
|
// backupConcurrency: 10,
|
|
396
382
|
};
|
|
@@ -47,6 +47,7 @@ class ModuleImporter {
|
|
|
47
47
|
return this.import();
|
|
48
48
|
}
|
|
49
49
|
async import() {
|
|
50
|
+
(0, utils_1.log)(this.importConfig, `Starting to import content version ${this.importConfig.contentVersion}`, 'info');
|
|
50
51
|
// checks for single module or all modules
|
|
51
52
|
if (this.importConfig.singleModuleImport) {
|
|
52
53
|
return this.importByModuleByName(this.importConfig.moduleName);
|
|
@@ -55,14 +56,10 @@ class ModuleImporter {
|
|
|
55
56
|
}
|
|
56
57
|
async importByModuleByName(moduleName) {
|
|
57
58
|
(0, utils_1.log)(this.importConfig, `Starting import of ${moduleName} module`, 'info');
|
|
58
|
-
const basePath = `${this.importConfig.backupDir}/${moduleName}`;
|
|
59
59
|
// import the modules by name
|
|
60
60
|
// calls the module runner which inturn calls the module itself
|
|
61
61
|
// Todo: Implement a mechanism to determine whether module is new or old
|
|
62
|
-
if (this.importConfig.
|
|
63
|
-
this.importConfig.updatedModules.indexOf(moduleName) !== -1
|
|
64
|
-
//&& new FsUtility({ basePath }).isNewFsStructure
|
|
65
|
-
) {
|
|
62
|
+
if (this.importConfig.contentVersion === 2) {
|
|
66
63
|
return (0, modules_1.default)({
|
|
67
64
|
stackAPIClient: this.stackAPIClient,
|
|
68
65
|
importConfig: this.importConfig,
|
|
@@ -7,6 +7,7 @@ const filter_1 = tslib_1.__importDefault(require("lodash/filter"));
|
|
|
7
7
|
const unionBy_1 = tslib_1.__importDefault(require("lodash/unionBy"));
|
|
8
8
|
const orderBy_1 = tslib_1.__importDefault(require("lodash/orderBy"));
|
|
9
9
|
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
10
|
+
const uniq_1 = tslib_1.__importDefault(require("lodash/uniq"));
|
|
10
11
|
const node_fs_1 = require("node:fs");
|
|
11
12
|
const includes_1 = tslib_1.__importDefault(require("lodash/includes"));
|
|
12
13
|
const node_path_1 = require("node:path");
|
|
@@ -210,9 +211,11 @@ class ImportAssets extends base_class_1.default {
|
|
|
210
211
|
};
|
|
211
212
|
const serializeData = (apiOptions) => {
|
|
212
213
|
const { apiData: asset } = apiOptions;
|
|
213
|
-
const publishDetails = (0, filter_1.default)(asset.publish_details,
|
|
214
|
+
const publishDetails = (0, filter_1.default)(asset.publish_details, ({ environment }) => {
|
|
215
|
+
return this.environments.hasOwnProperty(environment);
|
|
216
|
+
});
|
|
217
|
+
const environments = (0, uniq_1.default)((0, map_1.default)(publishDetails, ({ environment }) => this.environments[environment].name));
|
|
214
218
|
const locales = (0, map_1.default)(publishDetails, 'locale');
|
|
215
|
-
const environments = (0, map_1.default)(publishDetails, ({ environment }) => this.environments[environment].name);
|
|
216
219
|
asset.locales = locales;
|
|
217
220
|
asset.environments = environments;
|
|
218
221
|
apiOptions.uid = this.assetsUidMap[asset.uid];
|
|
@@ -90,7 +90,7 @@ class BaseClass {
|
|
|
90
90
|
// info: Batch No. 20 of import assets is complete
|
|
91
91
|
if (currentIndexer)
|
|
92
92
|
batchMsg += `Current chunk processing is (${currentIndexer}/${indexerCount})`;
|
|
93
|
-
(0, utils_1.log)(this.importConfig, `Batch No. (${batchNo}/${totelBatches}) of ${processName} is complete
|
|
93
|
+
(0, utils_1.log)(this.importConfig, `Batch No. (${batchNo}/${totelBatches}) of ${processName} is complete`, 'success');
|
|
94
94
|
}
|
|
95
95
|
if (this.importConfig.modules.assets.displayExecutionTime) {
|
|
96
96
|
console.log(`Time taken to execute: ${exeTime} milliseconds; wait time: ${exeTime < 1000 ? 1000 - exeTime : 0} milliseconds`);
|
|
@@ -105,7 +105,7 @@ class BaseClass {
|
|
|
105
105
|
* @return {Promise} Promise<void>
|
|
106
106
|
*/
|
|
107
107
|
makeAPICall(apiOptions, isLastRequest = false) {
|
|
108
|
-
var _a
|
|
108
|
+
var _a;
|
|
109
109
|
if (apiOptions.serializeData instanceof Function) {
|
|
110
110
|
apiOptions = apiOptions.serializeData(apiOptions);
|
|
111
111
|
}
|
|
@@ -169,18 +169,21 @@ class BaseClass {
|
|
|
169
169
|
case 'create-cts':
|
|
170
170
|
return this.stack.contentType().create(apiData).then(onSuccess).catch(onReject);
|
|
171
171
|
case 'update-cts':
|
|
172
|
-
if (
|
|
173
|
-
return Promise.resolve(
|
|
172
|
+
if (!apiData) {
|
|
173
|
+
return Promise.resolve();
|
|
174
174
|
}
|
|
175
175
|
return apiData.update().then(onSuccess).catch(onReject);
|
|
176
176
|
case 'update-gfs':
|
|
177
|
+
if (!apiData) {
|
|
178
|
+
return Promise.resolve();
|
|
179
|
+
}
|
|
177
180
|
return apiData.update().then(onSuccess).catch(onReject);
|
|
178
181
|
case 'create-environments':
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
return this.stack
|
|
183
|
+
.environment()
|
|
184
|
+
.create({ environment: (0, omit_1.default)(apiData, ['uid']) })
|
|
185
|
+
.then(onSuccess)
|
|
186
|
+
.catch(onReject);
|
|
184
187
|
case 'create-labels':
|
|
185
188
|
return this.stack
|
|
186
189
|
.label()
|
|
@@ -215,6 +218,12 @@ class BaseClass {
|
|
|
215
218
|
.then(onSuccess)
|
|
216
219
|
.catch(onReject);
|
|
217
220
|
case 'create-entries':
|
|
221
|
+
if (!apiData) {
|
|
222
|
+
return Promise.resolve();
|
|
223
|
+
}
|
|
224
|
+
if ((_a = additionalInfo[apiData === null || apiData === void 0 ? void 0 : apiData.uid]) === null || _a === void 0 ? void 0 : _a.isLocalized) {
|
|
225
|
+
return apiData.update({ locale: additionalInfo.locale }).then(onSuccess).catch(onReject);
|
|
226
|
+
}
|
|
218
227
|
return this.stack
|
|
219
228
|
.contentType(additionalInfo.cTUid)
|
|
220
229
|
.entry()
|
|
@@ -222,22 +231,28 @@ class BaseClass {
|
|
|
222
231
|
.then(onSuccess)
|
|
223
232
|
.catch(onReject);
|
|
224
233
|
case 'update-entries':
|
|
234
|
+
if (!apiData) {
|
|
235
|
+
return Promise.resolve();
|
|
236
|
+
}
|
|
225
237
|
return apiData.update({ locale: additionalInfo.locale }).then(onSuccess).catch(onReject);
|
|
226
238
|
case 'publish-entries':
|
|
227
|
-
if (
|
|
228
|
-
return Promise.resolve(
|
|
239
|
+
if (!apiData || !apiData.entryUid) {
|
|
240
|
+
return Promise.resolve();
|
|
229
241
|
}
|
|
230
242
|
return this.stack
|
|
231
243
|
.contentType(additionalInfo.cTUid)
|
|
232
|
-
.entry(
|
|
233
|
-
.publish({
|
|
244
|
+
.entry(apiData.entryUid)
|
|
245
|
+
.publish({
|
|
246
|
+
publishDetails: { environments: apiData.environments, locales: apiData.locales },
|
|
247
|
+
locale: additionalInfo.locale,
|
|
248
|
+
})
|
|
234
249
|
.then(onSuccess)
|
|
235
250
|
.catch(onReject);
|
|
236
251
|
case 'delete-entries':
|
|
237
252
|
return this.stack
|
|
238
253
|
.contentType(apiData.cTUid)
|
|
239
254
|
.entry(apiData.entryUid)
|
|
240
|
-
.delete({ locale:
|
|
255
|
+
.delete({ locale: additionalInfo.locale })
|
|
241
256
|
.then(onSuccess)
|
|
242
257
|
.catch(onReject);
|
|
243
258
|
default:
|
|
@@ -26,7 +26,7 @@ export default class ImportCustomRoles extends BaseClass {
|
|
|
26
26
|
*/
|
|
27
27
|
start(): Promise<void>;
|
|
28
28
|
getLocalesUidMap(): Promise<void>;
|
|
29
|
-
importCustomRoles(): Promise<
|
|
29
|
+
importCustomRoles(): Promise<void>;
|
|
30
30
|
/**
|
|
31
31
|
* @method serializeWebhooks
|
|
32
32
|
* @param {ApiOptions} apiOptions ApiOptions
|
|
@@ -4,7 +4,6 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
5
5
|
const values_1 = tslib_1.__importDefault(require("lodash/values"));
|
|
6
6
|
const node_path_1 = require("node:path");
|
|
7
|
-
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
8
7
|
const utils_1 = require("../../utils");
|
|
9
8
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
10
9
|
const lodash_1 = require("lodash");
|
|
@@ -13,17 +12,23 @@ class ImportCustomRoles extends base_class_1.default {
|
|
|
13
12
|
super({ importConfig, stackAPIClient });
|
|
14
13
|
this.getTransformUidsFactory = (rule) => {
|
|
15
14
|
if (rule.module === 'environment') {
|
|
16
|
-
|
|
15
|
+
if (!(0, isEmpty_1.default)(this.environmentsUidMap)) {
|
|
16
|
+
rule.environments = (0, lodash_1.map)(rule.environments, (env) => this.environmentsUidMap[env]);
|
|
17
|
+
}
|
|
17
18
|
}
|
|
18
19
|
else if (rule.module === 'locale') {
|
|
19
|
-
|
|
20
|
+
if (!(0, isEmpty_1.default)(this.localesUidMap)) {
|
|
21
|
+
rule.locales = (0, lodash_1.map)(rule.locales, (locale) => this.localesUidMap[locale]);
|
|
22
|
+
}
|
|
20
23
|
}
|
|
21
24
|
else if (rule.module === 'entry') {
|
|
22
|
-
|
|
25
|
+
if (!(0, isEmpty_1.default)(this.entriesUidMap)) {
|
|
26
|
+
rule.entries = (0, lodash_1.map)(rule.entries, (entry) => this.entriesUidMap[entry]);
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
return rule;
|
|
25
30
|
};
|
|
26
|
-
this.customRolesConfig =
|
|
31
|
+
this.customRolesConfig = importConfig.modules.customRoles;
|
|
27
32
|
this.customRolesMapperPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'custom-roles');
|
|
28
33
|
this.customRolesFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.customRolesConfig.dirName);
|
|
29
34
|
this.customRolesUidMapperPath = (0, node_path_1.join)(this.customRolesMapperPath, 'uid-mapping.json');
|
|
@@ -102,7 +107,7 @@ class ImportCustomRoles extends base_class_1.default {
|
|
|
102
107
|
async importCustomRoles() {
|
|
103
108
|
if (this.customRoles === undefined || (0, isEmpty_1.default)(this.customRoles)) {
|
|
104
109
|
(0, utils_1.log)(this.importConfig, 'No custom-roles found', 'info');
|
|
105
|
-
return
|
|
110
|
+
return;
|
|
106
111
|
}
|
|
107
112
|
const apiContent = (0, values_1.default)(this.customRoles);
|
|
108
113
|
const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
|
|
@@ -134,7 +139,7 @@ class ImportCustomRoles extends base_class_1.default {
|
|
|
134
139
|
entity: 'create-custom-role',
|
|
135
140
|
includeParamOnCompletion: true,
|
|
136
141
|
},
|
|
137
|
-
concurrencyLimit:
|
|
142
|
+
concurrencyLimit: this.importConfig.fetchConcurrency || 1,
|
|
138
143
|
}, undefined, false);
|
|
139
144
|
}
|
|
140
145
|
/**
|
|
@@ -35,6 +35,7 @@ class EntriesImport extends base_class_1.default {
|
|
|
35
35
|
this.jsonRteCTsWithRef = [];
|
|
36
36
|
this.envs = {};
|
|
37
37
|
this.autoCreatedEntries = [];
|
|
38
|
+
this.failedEntries = [];
|
|
38
39
|
}
|
|
39
40
|
async start() {
|
|
40
41
|
try {
|
|
@@ -57,6 +58,12 @@ class EntriesImport extends base_class_1.default {
|
|
|
57
58
|
}
|
|
58
59
|
await utils_1.fileHelper.writeLargeFile(path.join(this.entriesMapperPath, 'uid-mapping.json'), this.entriesUidMapper); // TBD: manages mapper in one file, should find an alternative
|
|
59
60
|
utils_1.fsUtil.writeFile(path.join(this.entriesMapperPath, 'failed-entries.json'), this.failedEntries);
|
|
61
|
+
if (this.autoCreatedEntries.length > 0) {
|
|
62
|
+
(0, utils_1.log)(this.importConfig, 'Removing entries from master language which got created by default', 'info');
|
|
63
|
+
await this.removeAutoCreatedEntries().catch((error) => {
|
|
64
|
+
(0, utils_1.log)(this.importConfig, `Error while removing auto created entries in master locale ${(0, utils_1.formatError)(error)}`, 'error');
|
|
65
|
+
});
|
|
66
|
+
}
|
|
60
67
|
// Update entries with references
|
|
61
68
|
const entryUpdateRequestOptions = this.populateEntryUpdatePayload();
|
|
62
69
|
for (let entryUpdateRequestOption of entryUpdateRequestOptions) {
|
|
@@ -70,12 +77,6 @@ class EntriesImport extends base_class_1.default {
|
|
|
70
77
|
await this.enableMandatoryCTReferences().catch((error) => {
|
|
71
78
|
(0, utils_1.log)(this.importConfig, `Error while updating content type references ${(0, utils_1.formatError)(error)}`, 'error');
|
|
72
79
|
});
|
|
73
|
-
if (this.autoCreatedEntries.length > 0) {
|
|
74
|
-
(0, utils_1.log)(this.importConfig, 'Removing entries from master language which got created by default', 'info');
|
|
75
|
-
await this.removeAutoCreatedEntries().catch((error) => {
|
|
76
|
-
(0, utils_1.log)(this.importConfig, `Error while removing auto created entries in master locale ${(0, utils_1.formatError)(error)}`, 'error');
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
80
|
// Update field rule of content types which are got removed earlier
|
|
80
81
|
(0, utils_1.log)(this.importConfig, 'Updating the field rules of content type', 'info');
|
|
81
82
|
await this.updateFieldRules().catch((error) => {
|
|
@@ -139,15 +140,6 @@ class EntriesImport extends base_class_1.default {
|
|
|
139
140
|
jsonRteEmbeddedEntries: false,
|
|
140
141
|
};
|
|
141
142
|
(0, utils_1.suppressSchemaReference)(contentType.schema, flag);
|
|
142
|
-
// Check if suppress modified flag
|
|
143
|
-
if (flag.suppressed) {
|
|
144
|
-
this.modifiedCTs.push((0, lodash_1.find)(this.cTs, { uid: contentType.uid }));
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
// Note: Skips the content type from update if no reference found
|
|
148
|
-
apiOptions.additionalInfo = { skip: true };
|
|
149
|
-
return apiOptions;
|
|
150
|
-
}
|
|
151
143
|
if (flag.references) {
|
|
152
144
|
this.refCTs.push(contentType.uid);
|
|
153
145
|
}
|
|
@@ -160,6 +152,15 @@ class EntriesImport extends base_class_1.default {
|
|
|
160
152
|
}
|
|
161
153
|
}
|
|
162
154
|
}
|
|
155
|
+
// Check if suppress modified flag
|
|
156
|
+
if (flag.suppressed) {
|
|
157
|
+
this.modifiedCTs.push((0, lodash_1.find)(this.cTs, { uid: contentType.uid }));
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Note: Skips the content type from update if no reference found
|
|
161
|
+
apiOptions.apiData = null;
|
|
162
|
+
return apiOptions;
|
|
163
|
+
}
|
|
163
164
|
(0, utils_1.lookupExtension)(this.importConfig, contentType.schema, this.importConfig.preserveStackVersion, this.installedExtensions);
|
|
164
165
|
const contentTypePayload = this.stack.contentType(contentType.uid);
|
|
165
166
|
Object.assign(contentTypePayload, (0, lodash_1.cloneDeep)(contentType));
|
|
@@ -189,11 +190,11 @@ class EntriesImport extends base_class_1.default {
|
|
|
189
190
|
if (indexerCount === 0) {
|
|
190
191
|
return Promise.resolve();
|
|
191
192
|
}
|
|
192
|
-
|
|
193
|
+
// log(this.importConfig, `Starting to create entries for ${cTUid} in locale ${locale}`, 'info');
|
|
193
194
|
const isMasterLocale = locale === ((_b = (_a = this.importConfig) === null || _a === void 0 ? void 0 : _a.master_locale) === null || _b === void 0 ? void 0 : _b.code);
|
|
194
195
|
// Write created entries
|
|
195
196
|
const entriesCreateFileHelper = new cli_utilities_1.FsUtility({
|
|
196
|
-
moduleName: '
|
|
197
|
+
moduleName: 'entries',
|
|
197
198
|
indexFileName: 'index.json',
|
|
198
199
|
basePath: path.join(this.entriesMapperPath, cTUid, locale),
|
|
199
200
|
chunkFileSize: this.entriesConfig.chunkFileSize,
|
|
@@ -201,15 +202,30 @@ class EntriesImport extends base_class_1.default {
|
|
|
201
202
|
omitKeys: this.entriesConfig.invalidKeys,
|
|
202
203
|
});
|
|
203
204
|
const contentType = (0, lodash_1.find)(this.cTs, { uid: cTUid });
|
|
204
|
-
const onSuccess = ({ response, apiData: entry, additionalInfo
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
const onSuccess = ({ response, apiData: entry, additionalInfo }) => {
|
|
206
|
+
var _a, _b;
|
|
207
|
+
if ((_a = additionalInfo[entry.uid]) === null || _a === void 0 ? void 0 : _a.isLocalized) {
|
|
208
|
+
let oldUid = additionalInfo[entry.uid].entryOldUid;
|
|
209
|
+
(0, utils_1.log)(this.importConfig, `Localized entry: '${entry.title}' of content type ${cTUid} in locale ${locale}`, 'info');
|
|
210
|
+
entry.uid = oldUid;
|
|
211
|
+
entry.entryOldUid = oldUid;
|
|
212
|
+
entry.sourceEntryFilePath = path.join(basePath, additionalInfo.entryFileName); // stores source file path temporarily
|
|
213
|
+
entriesCreateFileHelper.writeIntoFile({ [oldUid]: entry }, { mapKeyVal: true });
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
(0, utils_1.log)(this.importConfig, `Created entry: '${entry.title}' of content type ${cTUid} in locale ${locale}`, 'info');
|
|
217
|
+
// This is for creating localized entries that do not have a counterpart in master locale.
|
|
218
|
+
// For example : To create entry1 in fr-fr, where en-us is the master locale
|
|
219
|
+
// entry1 will get created in en-us first, then fr-fr version will be created
|
|
220
|
+
// thus entry1 has to be removed from en-us at the end.
|
|
221
|
+
if (!isMasterLocale && !((_b = additionalInfo[entry.uid]) === null || _b === void 0 ? void 0 : _b.isLocalized)) {
|
|
222
|
+
this.autoCreatedEntries.push({ cTUid, locale, entryUid: response.uid });
|
|
223
|
+
}
|
|
224
|
+
this.entriesUidMapper[entry.uid] = response.uid;
|
|
225
|
+
entry.sourceEntryFilePath = path.join(basePath, additionalInfo.entryFileName); // stores source file path temporarily
|
|
226
|
+
entry.entryOldUid = entry.uid; // stores old uid temporarily
|
|
227
|
+
entriesCreateFileHelper.writeIntoFile({ [entry.uid]: entry }, { mapKeyVal: true });
|
|
211
228
|
}
|
|
212
|
-
entriesCreateFileHelper.writeIntoFile({ [response.uid]: entry }, { mapKeyVal: true });
|
|
213
229
|
};
|
|
214
230
|
const onReject = ({ error, apiData: { uid, title } }) => {
|
|
215
231
|
(0, utils_1.log)(this.importConfig, `${title} entry of content type ${cTUid} in locale ${locale} failed to create`, 'error');
|
|
@@ -233,7 +249,7 @@ class EntriesImport extends base_class_1.default {
|
|
|
233
249
|
entity: 'create-entries',
|
|
234
250
|
includeParamOnCompletion: true,
|
|
235
251
|
serializeData: this.serializeEntries.bind(this),
|
|
236
|
-
additionalInfo: { contentType, locale, cTUid, entryFileName: indexer[index] },
|
|
252
|
+
additionalInfo: { contentType, locale, cTUid, entryFileName: indexer[index], isMasterLocale },
|
|
237
253
|
},
|
|
238
254
|
concurrencyLimit: this.importConcurrency,
|
|
239
255
|
}).then(() => {
|
|
@@ -249,21 +265,40 @@ class EntriesImport extends base_class_1.default {
|
|
|
249
265
|
* @returns {ApiOptions} ApiOptions
|
|
250
266
|
*/
|
|
251
267
|
serializeEntries(apiOptions) {
|
|
252
|
-
let { apiData: entry, additionalInfo: { cTUid, locale, contentType }, } = apiOptions;
|
|
253
|
-
|
|
254
|
-
|
|
268
|
+
let { apiData: entry, additionalInfo: { cTUid, locale, contentType, isMasterLocale }, } = apiOptions;
|
|
269
|
+
try {
|
|
270
|
+
if (this.jsonRteCTs.indexOf(cTUid) > -1) {
|
|
271
|
+
entry = (0, utils_1.removeUidsFromJsonRteFields)(entry, contentType.schema);
|
|
272
|
+
}
|
|
273
|
+
// remove entry references from json-rte fields
|
|
274
|
+
if (this.jsonRteCTsWithRef.indexOf(cTUid) > -1) {
|
|
275
|
+
entry = (0, utils_1.removeEntryRefsFromJSONRTE)(entry, contentType.schema);
|
|
276
|
+
}
|
|
277
|
+
// will replace all old asset uid/urls with new ones
|
|
278
|
+
entry = (0, utils_1.lookupAssets)({
|
|
279
|
+
content_type: contentType,
|
|
280
|
+
entry: entry,
|
|
281
|
+
}, this.assetUidMapper, this.assetUrlMapper, path.join(this.entriesPath, cTUid), this.installedExtensions);
|
|
282
|
+
delete entry.publish_details;
|
|
283
|
+
// checking the entry is a localized one or not
|
|
284
|
+
if (!isMasterLocale && this.entriesUidMapper.hasOwnProperty(entry.uid)) {
|
|
285
|
+
const entryResponse = this.stack.contentType(contentType.uid).entry(this.entriesUidMapper[entry.uid]);
|
|
286
|
+
Object.assign(entryResponse, (0, lodash_1.cloneDeep)(entry), { uid: this.entriesUidMapper[entry.uid] });
|
|
287
|
+
apiOptions.apiData = entryResponse;
|
|
288
|
+
apiOptions.additionalInfo[entryResponse.uid] = {
|
|
289
|
+
isLocalized: true,
|
|
290
|
+
entryOldUid: entry.uid
|
|
291
|
+
};
|
|
292
|
+
return apiOptions;
|
|
293
|
+
}
|
|
294
|
+
apiOptions.apiData = entry;
|
|
255
295
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
296
|
+
catch (error) {
|
|
297
|
+
(0, utils_1.log)(this.importConfig, `${entry.title} entry of content type ${cTUid} in locale ${locale} failed to create`, 'error');
|
|
298
|
+
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
299
|
+
this.failedEntries.push({ content_type: cTUid, locale, entry: { uid: entry.uid, title: entry.title } });
|
|
300
|
+
apiOptions.apiData = null;
|
|
259
301
|
}
|
|
260
|
-
// will replace all old asset uid/urls with new ones
|
|
261
|
-
entry = (0, utils_1.lookupAssets)({
|
|
262
|
-
content_type: contentType,
|
|
263
|
-
entry: entry,
|
|
264
|
-
}, this.assetUidMapper, this.assetUrlMapper, path.join(this.entriesPath, cTUid), this.installedExtensions);
|
|
265
|
-
delete entry.publish_details;
|
|
266
|
-
apiOptions.apiData = entry;
|
|
267
302
|
return apiOptions;
|
|
268
303
|
}
|
|
269
304
|
populateEntryUpdatePayload() {
|
|
@@ -288,7 +323,7 @@ class EntriesImport extends base_class_1.default {
|
|
|
288
323
|
if (indexerCount === 0) {
|
|
289
324
|
return Promise.resolve();
|
|
290
325
|
}
|
|
291
|
-
|
|
326
|
+
// log(this.importConfig, `Starting to update entries with references for ${cTUid} in locale ${locale}`, 'info');
|
|
292
327
|
const contentType = (0, lodash_1.find)(this.cTs, { uid: cTUid });
|
|
293
328
|
const onSuccess = ({ response, apiData: { uid, url, title } }) => {
|
|
294
329
|
(0, utils_1.log)(this.importConfig, `Updated entry: '${title}' of content type ${cTUid} in locale ${locale}`, 'info');
|
|
@@ -296,7 +331,12 @@ class EntriesImport extends base_class_1.default {
|
|
|
296
331
|
const onReject = ({ error, apiData: { uid, title } }) => {
|
|
297
332
|
(0, utils_1.log)(this.importConfig, `${title} entry of content type ${cTUid} in locale ${locale} failed to update`, 'error');
|
|
298
333
|
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
299
|
-
this.failedEntries.push({
|
|
334
|
+
this.failedEntries.push({
|
|
335
|
+
content_type: cTUid,
|
|
336
|
+
locale,
|
|
337
|
+
entry: { uid: this.entriesUidMapper[uid], title },
|
|
338
|
+
entryId: uid,
|
|
339
|
+
});
|
|
300
340
|
};
|
|
301
341
|
for (const index in indexer) {
|
|
302
342
|
const chunk = await fs.readChunkFiles.next().catch((error) => {
|
|
@@ -331,26 +371,34 @@ class EntriesImport extends base_class_1.default {
|
|
|
331
371
|
*/
|
|
332
372
|
serializeUpdateEntries(apiOptions) {
|
|
333
373
|
let { apiData: entry, additionalInfo: { cTUid, locale, contentType }, } = apiOptions;
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
374
|
+
try {
|
|
375
|
+
const sourceEntryFilePath = entry.sourceEntryFilePath;
|
|
376
|
+
const sourceEntry = (utils_1.fsUtil.readFile(sourceEntryFilePath) || {})[entry.entryOldUid];
|
|
377
|
+
const newUid = this.entriesUidMapper[entry.entryOldUid];
|
|
378
|
+
// Removing temp values
|
|
379
|
+
delete entry.sourceEntryFilePath;
|
|
380
|
+
delete entry.entryOldUid;
|
|
381
|
+
if (this.jsonRteCTs.indexOf(cTUid) > -1) {
|
|
382
|
+
// the entries stored in eSuccessFilePath, have the same uids as the entries from source data
|
|
383
|
+
entry = (0, utils_1.restoreJsonRteEntryRefs)(entry, sourceEntry, contentType.schema, {
|
|
384
|
+
mappedAssetUids: this.assetUidMapper,
|
|
385
|
+
mappedAssetUrls: this.assetUrlMapper,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
entry = (0, utils_1.lookupEntries)({
|
|
389
|
+
content_type: contentType,
|
|
390
|
+
entry,
|
|
391
|
+
}, this.entriesUidMapper, path.join(this.entriesMapperPath, cTUid, locale));
|
|
392
|
+
const entryResponse = this.stack.contentType(contentType.uid).entry(newUid);
|
|
393
|
+
Object.assign(entryResponse, (0, lodash_1.cloneDeep)(entry), { uid: newUid });
|
|
394
|
+
delete entryResponse.publish_details;
|
|
395
|
+
apiOptions.apiData = entryResponse;
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
(0, utils_1.log)(this.importConfig, `${entry.title} entry of content type ${cTUid} in locale ${locale} failed to update`, 'error');
|
|
399
|
+
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
400
|
+
apiOptions.apiData = null;
|
|
345
401
|
}
|
|
346
|
-
entry = (0, utils_1.lookupEntries)({
|
|
347
|
-
content_type: contentType,
|
|
348
|
-
entry,
|
|
349
|
-
}, this.entriesUidMapper, path.join(this.entriesMapperPath, cTUid, locale));
|
|
350
|
-
const entryResponse = this.stack.contentType(contentType.uid).entry(this.entriesUidMapper[entry.uid]);
|
|
351
|
-
Object.assign(entryResponse, (0, lodash_1.cloneDeep)(entry));
|
|
352
|
-
delete entryResponse.publish_details;
|
|
353
|
-
apiOptions.apiData = entryResponse;
|
|
354
402
|
return apiOptions;
|
|
355
403
|
}
|
|
356
404
|
async enableMandatoryCTReferences() {
|
|
@@ -391,6 +439,7 @@ class EntriesImport extends base_class_1.default {
|
|
|
391
439
|
return apiOptions;
|
|
392
440
|
}
|
|
393
441
|
async removeAutoCreatedEntries() {
|
|
442
|
+
var _a, _b;
|
|
394
443
|
const onSuccess = ({ response, apiData: { entryUid } }) => {
|
|
395
444
|
(0, utils_1.log)(this.importConfig, `Auto created entry in master locale removed - entry uid ${entryUid} `, 'success');
|
|
396
445
|
};
|
|
@@ -405,6 +454,7 @@ class EntriesImport extends base_class_1.default {
|
|
|
405
454
|
resolve: onSuccess.bind(this),
|
|
406
455
|
entity: 'delete-entries',
|
|
407
456
|
includeParamOnCompletion: true,
|
|
457
|
+
additionalInfo: { locale: (_b = (_a = this.importConfig) === null || _a === void 0 ? void 0 : _a.master_locale) === null || _b === void 0 ? void 0 : _b.code },
|
|
408
458
|
},
|
|
409
459
|
concurrencyLimit: this.importConcurrency,
|
|
410
460
|
});
|
|
@@ -418,12 +468,12 @@ class EntriesImport extends base_class_1.default {
|
|
|
418
468
|
const cTs = utils_1.fsUtil.readFile(path.join(this.cTsPath, 'schema.json'));
|
|
419
469
|
const contentType = (0, lodash_1.find)(cTs, { uid: cTUid });
|
|
420
470
|
if (contentType.field_rules) {
|
|
421
|
-
let fieldRuleLength = contentType.field_rules.length;
|
|
422
471
|
const fieldDatatypeMap = {};
|
|
423
472
|
for (let i = 0; i < contentType.schema.length; i++) {
|
|
424
473
|
const field = contentType.schema[i].uid;
|
|
425
474
|
fieldDatatypeMap[field] = contentType.schema[i].data_type;
|
|
426
475
|
}
|
|
476
|
+
let fieldRuleLength = contentType.field_rules.length;
|
|
427
477
|
for (let k = 0; k < fieldRuleLength; k++) {
|
|
428
478
|
let fieldRuleConditionLength = contentType.field_rules[k].conditions.length;
|
|
429
479
|
for (let i = 0; i < fieldRuleConditionLength; i++) {
|
|
@@ -460,7 +510,7 @@ class EntriesImport extends base_class_1.default {
|
|
|
460
510
|
(0, utils_1.log)(this.importConfig, `Updated the field rules of ${cTUid}`, 'info');
|
|
461
511
|
}
|
|
462
512
|
else {
|
|
463
|
-
(0, utils_1.log)(this.importConfig, `No field rules found in content type ${cTUid} to update`, '
|
|
513
|
+
(0, utils_1.log)(this.importConfig, `No field rules found in content type ${cTUid} to update`, 'info');
|
|
464
514
|
}
|
|
465
515
|
}
|
|
466
516
|
}
|
|
@@ -475,12 +525,12 @@ class EntriesImport extends base_class_1.default {
|
|
|
475
525
|
if (indexerCount === 0) {
|
|
476
526
|
return Promise.resolve();
|
|
477
527
|
}
|
|
478
|
-
|
|
479
|
-
const onSuccess = ({ response, apiData: { environments }, additionalInfo
|
|
528
|
+
// log(this.importConfig, `Starting publish entries for ${cTUid} in locale ${locale}`, 'info');
|
|
529
|
+
const onSuccess = ({ response, apiData: { environments, entryUid }, additionalInfo }) => {
|
|
480
530
|
(0, utils_1.log)(this.importConfig, `Published entry: '${entryUid}' of content type ${cTUid} and locale ${locale} in ${environments === null || environments === void 0 ? void 0 : environments.join(',')} environments`, 'info');
|
|
481
531
|
};
|
|
482
|
-
const onReject = ({ error, apiData, additionalInfo
|
|
483
|
-
(0, utils_1.log)(this.importConfig, `${entryUid} entry of content type ${cTUid} in locale ${locale} failed to publish`, 'error');
|
|
532
|
+
const onReject = ({ error, apiData, additionalInfo }) => {
|
|
533
|
+
(0, utils_1.log)(this.importConfig, `${apiData.entryUid} entry of content type ${cTUid} in locale ${locale} failed to publish`, 'error');
|
|
484
534
|
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
485
535
|
};
|
|
486
536
|
for (const index in indexer) {
|
|
@@ -516,10 +566,10 @@ class EntriesImport extends base_class_1.default {
|
|
|
516
566
|
*/
|
|
517
567
|
serializePublishEntries(apiOptions) {
|
|
518
568
|
let { apiData: entry, additionalInfo } = apiOptions;
|
|
519
|
-
additionalInfo.entryUid = this.entriesUidMapper[entry.uid];
|
|
520
569
|
const requestObject = {
|
|
521
570
|
environments: [],
|
|
522
571
|
locales: [],
|
|
572
|
+
entryUid: this.entriesUidMapper[entry.uid],
|
|
523
573
|
};
|
|
524
574
|
if (entry.publish_details && entry.publish_details.length > 0) {
|
|
525
575
|
(0, lodash_1.forEach)(entry.publish_details, (pubObject) => {
|
|
@@ -533,7 +583,8 @@ class EntriesImport extends base_class_1.default {
|
|
|
533
583
|
});
|
|
534
584
|
}
|
|
535
585
|
else {
|
|
536
|
-
|
|
586
|
+
apiOptions.apiData = null;
|
|
587
|
+
return apiOptions;
|
|
537
588
|
}
|
|
538
589
|
apiOptions.apiData = requestObject;
|
|
539
590
|
return apiOptions;
|
|
@@ -17,7 +17,7 @@ export default class ImportEnvironments extends BaseClass {
|
|
|
17
17
|
* @returns {Promise<void>} Promise<void>
|
|
18
18
|
*/
|
|
19
19
|
start(): Promise<void>;
|
|
20
|
-
importEnvironments(): Promise<
|
|
20
|
+
importEnvironments(): Promise<void>;
|
|
21
21
|
/**
|
|
22
22
|
* @method serializeEnvironments
|
|
23
23
|
* @param {ApiOptions} apiOptions ApiOptions
|