@contentstack/cli-cm-import 1.25.0 → 1.26.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/import.d.ts +1 -0
- package/lib/commands/cm/stacks/import.js +33 -12
- package/lib/import/module-importer.js +1 -1
- package/lib/import/modules/assets.d.ts +1 -1
- package/lib/import/modules/assets.js +93 -39
- package/lib/import/modules/base-class.js +11 -3
- package/lib/import/modules/content-types.js +79 -28
- package/lib/import/modules/custom-roles.js +95 -19
- package/lib/import/modules/entries.js +128 -57
- package/lib/import/modules/environments.js +48 -14
- package/lib/import/modules/extensions.js +78 -16
- package/lib/import/modules/global-fields.js +86 -19
- package/lib/import/modules/labels.d.ts +4 -4
- package/lib/import/modules/labels.js +60 -18
- package/lib/import/modules/locales.js +63 -20
- package/lib/import/modules/marketplace-apps.js +160 -31
- package/lib/import/modules/personalize.js +33 -7
- package/lib/import/modules/stack.js +5 -0
- package/lib/import/modules/taxonomies.js +52 -13
- package/lib/import/modules/variant-entries.js +21 -3
- package/lib/import/modules/webhooks.js +44 -12
- package/lib/import/modules/workflows.js +65 -21
- package/lib/types/import-config.d.ts +3 -1
- package/lib/types/index.d.ts +22 -0
- package/lib/utils/asset-helper.js +24 -1
- package/lib/utils/backup-handler.js +15 -1
- package/lib/utils/common-helper.js +41 -16
- package/lib/utils/content-type-helper.js +35 -2
- package/lib/utils/entries-helper.js +24 -2
- package/lib/utils/extension-helper.js +35 -1
- package/lib/utils/global-field-helper.js +1 -1
- package/lib/utils/import-config-handler.js +21 -0
- package/lib/utils/login-handler.js +8 -4
- package/lib/utils/marketplace-app-helper.js +50 -11
- package/lib/utils/taxonomies-helper.js +22 -4
- package/oclif.manifest.json +2 -2
- package/package.json +5 -5
|
@@ -9,14 +9,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
const tslib_1 = require("tslib");
|
|
10
10
|
const path = tslib_1.__importStar(require("path"));
|
|
11
11
|
const lodash_1 = require("lodash");
|
|
12
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
12
13
|
const utils_1 = require("../../utils");
|
|
13
14
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
14
15
|
const content_type_helper_1 = require("../../utils/content-type-helper");
|
|
15
|
-
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
16
16
|
class ContentTypesImport extends base_class_1.default {
|
|
17
17
|
constructor({ importConfig, stackAPIClient }) {
|
|
18
18
|
super({ importConfig, stackAPIClient });
|
|
19
19
|
this.isExtensionsUpdate = false;
|
|
20
|
+
this.importConfig.context.module = 'content-types';
|
|
20
21
|
this.cTsConfig = importConfig.modules['content-types'];
|
|
21
22
|
this.gFsConfig = importConfig.modules['global-fields'];
|
|
22
23
|
this.reqConcurrency = this.cTsConfig.writeConcurrency || this.importConfig.writeConcurrency;
|
|
@@ -44,7 +45,7 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
44
45
|
this.extPendingPath = path.join((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'extensions', 'pending_extensions.js');
|
|
45
46
|
}
|
|
46
47
|
async start() {
|
|
47
|
-
var _a;
|
|
48
|
+
var _a, _b;
|
|
48
49
|
/**
|
|
49
50
|
* read content type, check if it is necessary to read the entire dir
|
|
50
51
|
* Seed content types
|
|
@@ -54,46 +55,64 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
54
55
|
*/
|
|
55
56
|
this.cTs = utils_1.fsUtil.readFile(path.join(this.cTsFolderPath, 'schema.json'));
|
|
56
57
|
if (!this.cTs || (0, lodash_1.isEmpty)(this.cTs)) {
|
|
57
|
-
|
|
58
|
+
cli_utilities_1.log.info('No content type found to import', this.importConfig.context);
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
61
|
+
cli_utilities_1.log.debug(`Found ${this.cTs.length} content types to import`, this.importConfig.context);
|
|
60
62
|
await utils_1.fsUtil.makeDirectory(this.cTsMapperPath);
|
|
63
|
+
cli_utilities_1.log.debug('Created content types mapper directory', this.importConfig.context);
|
|
61
64
|
this.installedExtensions = ((await utils_1.fsUtil.readFile(this.marketplaceAppMapperPath)) || { extension_uid: {} }).extension_uid;
|
|
65
|
+
cli_utilities_1.log.debug(`Loaded ${(_a = Object.keys(this.installedExtensions)) === null || _a === void 0 ? void 0 : _a.length} installed extensions`, this.importConfig.context);
|
|
62
66
|
this.taxonomies = utils_1.fsUtil.readFile(this.taxonomiesPath);
|
|
67
|
+
const taxonomyCount = Object.keys(this.taxonomies || {}).length;
|
|
68
|
+
cli_utilities_1.log.debug(`Loaded ${taxonomyCount} taxonomy definitions`, this.importConfig.context);
|
|
69
|
+
cli_utilities_1.log.info('Starting content types seeding process', this.importConfig.context);
|
|
63
70
|
await this.seedCTs();
|
|
64
|
-
if ((
|
|
71
|
+
if ((_b = this.createdCTs) === null || _b === void 0 ? void 0 : _b.length) {
|
|
65
72
|
utils_1.fsUtil.writeFile(this.cTsSuccessPath, this.createdCTs);
|
|
66
|
-
|
|
73
|
+
cli_utilities_1.log.debug(`Written ${this.createdCTs.length} successful content types to file`, this.importConfig.context);
|
|
74
|
+
}
|
|
75
|
+
cli_utilities_1.log.success('Created content types', this.importConfig.context);
|
|
76
|
+
cli_utilities_1.log.info('Starting content types update process', this.importConfig.context);
|
|
67
77
|
await this.updateCTs();
|
|
68
|
-
|
|
78
|
+
cli_utilities_1.log.success('Updated content types with references', this.importConfig.context);
|
|
69
79
|
if (this.fieldRules.length > 0) {
|
|
70
80
|
utils_1.fsUtil.writeFile(path.join(this.cTsFolderPath, 'field_rules_uid.json'), this.fieldRules);
|
|
81
|
+
cli_utilities_1.log.debug(`Written ${this.fieldRules.length} field rules to file`, this.importConfig.context);
|
|
71
82
|
}
|
|
72
|
-
|
|
83
|
+
cli_utilities_1.log.info('Updating the extensions...', this.importConfig.context);
|
|
73
84
|
await this.updatePendingExtensions();
|
|
74
85
|
if (this.isExtensionsUpdate) {
|
|
75
|
-
|
|
86
|
+
cli_utilities_1.log.success('Successfully updated the extensions.', this.importConfig.context);
|
|
87
|
+
}
|
|
88
|
+
cli_utilities_1.log.info('Starting pending global fields update', this.importConfig.context);
|
|
89
|
+
this.pendingGFs = utils_1.fsUtil.readFile(this.gFsPendingPath);
|
|
90
|
+
if (!this.pendingGFs || (0, lodash_1.isEmpty)(this.pendingGFs)) {
|
|
91
|
+
cli_utilities_1.log.info('No pending global fields found to update', this.importConfig.context);
|
|
92
|
+
return;
|
|
76
93
|
}
|
|
77
94
|
await this.updatePendingGFs().catch((error) => {
|
|
78
|
-
(0,
|
|
95
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.importConfig.context));
|
|
79
96
|
});
|
|
80
|
-
|
|
81
|
-
|
|
97
|
+
cli_utilities_1.log.success('Updated pending global fields with content type with references', this.importConfig.context);
|
|
98
|
+
cli_utilities_1.log.success('Content types have been imported successfully!', this.importConfig.context);
|
|
82
99
|
}
|
|
83
100
|
async seedCTs() {
|
|
84
101
|
const onSuccess = ({ response: globalField, apiData: { content_type: { uid = null } = {} } = {} }) => {
|
|
85
102
|
this.createdCTs.push(uid);
|
|
86
|
-
|
|
103
|
+
cli_utilities_1.log.info(`${uid} content type seeded`, this.importConfig.context);
|
|
104
|
+
cli_utilities_1.log.debug(`Successfully seeded content type: ${uid}`, this.importConfig.context);
|
|
87
105
|
};
|
|
88
106
|
const onReject = ({ error, apiData: { content_type: { uid = null } = {} } = {} }) => {
|
|
89
107
|
if (error.errorCode === 115 && (error.errors.uid || error.errors.title)) {
|
|
90
|
-
|
|
108
|
+
cli_utilities_1.log.info(`${uid} content type already exist`, this.importConfig.context);
|
|
109
|
+
cli_utilities_1.log.debug(`Skipping existing content type: ${uid}`, this.importConfig.context);
|
|
91
110
|
}
|
|
92
111
|
else {
|
|
93
|
-
(0,
|
|
94
|
-
process.exit(1);
|
|
112
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Failed to seed content type ${uid}`);
|
|
95
113
|
}
|
|
96
114
|
};
|
|
115
|
+
cli_utilities_1.log.debug(`Starting to seed ${this.cTs.length} content types`, this.importConfig.context);
|
|
97
116
|
return await this.makeConcurrentCall({
|
|
98
117
|
processName: 'Import content types',
|
|
99
118
|
apiContent: this.cTs,
|
|
@@ -114,6 +133,7 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
114
133
|
*/
|
|
115
134
|
serializeCTs(apiOptions) {
|
|
116
135
|
const { apiData: contentType } = apiOptions;
|
|
136
|
+
cli_utilities_1.log.debug(`Serializing content type: ${contentType.uid} (${contentType.title})`, this.importConfig.context);
|
|
117
137
|
const updatedCT = (0, lodash_1.cloneDeep)(utils_1.schemaTemplate);
|
|
118
138
|
updatedCT.content_type.uid = contentType.uid;
|
|
119
139
|
updatedCT.content_type.title = contentType.title;
|
|
@@ -122,12 +142,14 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
122
142
|
}
|
|
123
143
|
async updateCTs() {
|
|
124
144
|
const onSuccess = ({ response: contentType, apiData: { uid } }) => {
|
|
125
|
-
|
|
145
|
+
cli_utilities_1.log.success(`'${uid}' updated with references`, this.importConfig.context);
|
|
146
|
+
cli_utilities_1.log.debug(`Content type update completed for: ${uid}`, this.importConfig.context);
|
|
126
147
|
};
|
|
127
148
|
const onReject = ({ error, apiData: { uid } }) => {
|
|
128
|
-
(0,
|
|
149
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Content type '${uid}' update failed`);
|
|
129
150
|
throw new Error(`Content type '${uid}' update error`);
|
|
130
151
|
};
|
|
152
|
+
cli_utilities_1.log.debug(`Starting to update ${this.cTs.length} content types with references`, this.importConfig.context);
|
|
131
153
|
return await this.makeConcurrentCall({
|
|
132
154
|
processName: 'Update content types',
|
|
133
155
|
apiContent: this.cTs,
|
|
@@ -148,35 +170,50 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
148
170
|
*/
|
|
149
171
|
serializeUpdateCTs(apiOptions) {
|
|
150
172
|
const { apiData: contentType } = apiOptions;
|
|
173
|
+
cli_utilities_1.log.debug(`Serializing update for content type: ${contentType.uid} (${contentType.title})`, this.importConfig.context);
|
|
151
174
|
if (contentType.field_rules) {
|
|
152
175
|
contentType.field_rules = (0, content_type_helper_1.updateFieldRules)(contentType);
|
|
153
176
|
if (!contentType.field_rules.length) {
|
|
154
177
|
delete contentType.field_rules;
|
|
178
|
+
cli_utilities_1.log.debug(`Removed empty field rules for content type: ${contentType.uid}`, this.importConfig.context);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
cli_utilities_1.log.debug(`Updated ${contentType.field_rules.length} field rules for content type: ${contentType.uid}`, this.importConfig.context);
|
|
155
182
|
}
|
|
156
183
|
this.fieldRules.push(contentType.uid);
|
|
157
184
|
}
|
|
158
185
|
//will remove taxonomy if taxonomy doesn't exists in stack
|
|
159
186
|
(0, utils_1.lookUpTaxonomy)(this.importConfig, contentType.schema, this.taxonomies);
|
|
187
|
+
cli_utilities_1.log.debug(`Processed taxonomy lookups for content type: ${contentType.uid}`, this.importConfig.context);
|
|
160
188
|
(0, utils_1.lookupExtension)(this.importConfig, contentType.schema, this.importConfig.preserveStackVersion, this.installedExtensions);
|
|
189
|
+
cli_utilities_1.log.debug(`Processed extension lookups for content type: ${contentType.uid}`, this.importConfig.context);
|
|
161
190
|
const contentTypePayload = this.stack.contentType(contentType.uid);
|
|
162
191
|
Object.assign(contentTypePayload, (0, lodash_1.cloneDeep)(contentType));
|
|
192
|
+
cli_utilities_1.log.debug(`Content type update serialization completed for: ${contentType.uid}`, this.importConfig.context);
|
|
163
193
|
apiOptions.apiData = contentTypePayload;
|
|
164
194
|
return apiOptions;
|
|
165
195
|
}
|
|
166
196
|
async updatePendingGFs() {
|
|
197
|
+
var _a, _b;
|
|
167
198
|
this.pendingGFs = utils_1.fsUtil.readFile(this.gFsPendingPath);
|
|
199
|
+
cli_utilities_1.log.info(`Found ${this.pendingGFs.length} pending global fields to update`, this.importConfig.context);
|
|
168
200
|
this.gFs = utils_1.fsUtil.readFile(path.resolve(this.gFsFolderPath, this.gFsConfig.fileName));
|
|
201
|
+
cli_utilities_1.log.debug(`Found ${((_a = this.pendingGFs) === null || _a === void 0 ? void 0 : _a.length) || 0} pending global fields to update`, this.importConfig.context);
|
|
202
|
+
cli_utilities_1.log.debug(`Loaded ${((_b = this.gFs) === null || _b === void 0 ? void 0 : _b.length) || 0} global fields from file`, this.importConfig.context);
|
|
169
203
|
const onSuccess = ({ response: globalField, apiData: { uid } = undefined }) => {
|
|
170
|
-
|
|
204
|
+
cli_utilities_1.log.info(`Updated the global field ${uid} with content type references`, this.importConfig.context);
|
|
205
|
+
cli_utilities_1.log.debug(`Global field update completed for: ${uid}`, this.importConfig.context);
|
|
171
206
|
};
|
|
172
207
|
const onReject = ({ error, apiData: { uid } = undefined }) => {
|
|
173
|
-
(0,
|
|
208
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Failed to update the global field '${uid}'`);
|
|
174
209
|
};
|
|
210
|
+
const apiContent = (0, lodash_1.map)(this.pendingGFs, (uid) => {
|
|
211
|
+
return { uid };
|
|
212
|
+
});
|
|
213
|
+
cli_utilities_1.log.debug(`Prepared ${apiContent.length} global field update tasks`, this.importConfig.context);
|
|
175
214
|
return await this.makeConcurrentCall({
|
|
176
215
|
processName: 'Update pending global fields',
|
|
177
|
-
apiContent:
|
|
178
|
-
return { uid };
|
|
179
|
-
}),
|
|
216
|
+
apiContent: apiContent,
|
|
180
217
|
apiParams: {
|
|
181
218
|
serializeData: this.serializeUpdateGFs.bind(this),
|
|
182
219
|
reject: onReject.bind(this),
|
|
@@ -194,36 +231,50 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
194
231
|
*/
|
|
195
232
|
serializeUpdateGFs(apiOptions) {
|
|
196
233
|
const { apiData: { uid }, } = apiOptions;
|
|
234
|
+
cli_utilities_1.log.debug(`Serializing global field update for: ${uid}`, this.importConfig.context);
|
|
197
235
|
const globalField = (0, lodash_1.find)(this.gFs, { uid });
|
|
236
|
+
if (!globalField) {
|
|
237
|
+
cli_utilities_1.log.debug(`Global field not found: ${uid}`, this.importConfig.context);
|
|
238
|
+
apiOptions.apiData = null;
|
|
239
|
+
return apiOptions;
|
|
240
|
+
}
|
|
241
|
+
cli_utilities_1.log.debug(`Found global field: ${uid}`, this.importConfig.context);
|
|
198
242
|
(0, utils_1.lookupExtension)(this.importConfig, globalField.schema, this.importConfig.preserveStackVersion, this.installedExtensions);
|
|
243
|
+
cli_utilities_1.log.debug(`Processed extension lookups for global field: ${uid}`, this.importConfig.context);
|
|
199
244
|
const globalFieldPayload = this.stack.globalField(uid, { api_version: '3.2' });
|
|
200
245
|
Object.assign(globalFieldPayload, (0, lodash_1.cloneDeep)(globalField));
|
|
246
|
+
cli_utilities_1.log.debug(`Global field update serialization completed for: ${uid}`, this.importConfig.context);
|
|
201
247
|
apiOptions.apiData = globalFieldPayload;
|
|
202
248
|
return apiOptions;
|
|
203
249
|
}
|
|
204
250
|
async updatePendingExtensions() {
|
|
205
251
|
let apiContent = utils_1.fsUtil.readFile(this.extPendingPath);
|
|
206
|
-
|
|
207
|
-
|
|
252
|
+
cli_utilities_1.log.debug(`Reading pending extensions from: ${this.extPendingPath}`, this.importConfig.context);
|
|
253
|
+
if (!apiContent || (apiContent === null || apiContent === void 0 ? void 0 : apiContent.length) === 0) {
|
|
254
|
+
cli_utilities_1.log.info(`No extensions found to be updated.`, this.importConfig.context);
|
|
255
|
+
cli_utilities_1.log.debug('Skipping extensions update - no pending extensions', this.importConfig.context);
|
|
208
256
|
return;
|
|
209
257
|
}
|
|
258
|
+
cli_utilities_1.log.debug(`Found ${apiContent.length} extensions to update`, this.importConfig.context);
|
|
210
259
|
this.isExtensionsUpdate = true;
|
|
211
260
|
const onSuccess = ({ response, apiData: { uid, title } = { uid: null, title: '' } }) => {
|
|
212
|
-
|
|
261
|
+
cli_utilities_1.log.success(`Successfully updated the '${response.title}' extension.`, this.importConfig.context);
|
|
262
|
+
cli_utilities_1.log.debug(`Extension update completed for: ${uid}`, this.importConfig.context);
|
|
213
263
|
};
|
|
214
264
|
const onReject = ({ error, apiData }) => {
|
|
215
265
|
var _a;
|
|
216
266
|
const { uid } = apiData;
|
|
217
267
|
if ((_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.title) {
|
|
218
268
|
if (!this.importConfig.skipExisting) {
|
|
219
|
-
|
|
269
|
+
cli_utilities_1.log.info(`Extension '${uid}' already exists.`, this.importConfig.context);
|
|
220
270
|
}
|
|
271
|
+
cli_utilities_1.log.debug(`Skipping existing extension: ${uid}`, this.importConfig.context);
|
|
221
272
|
}
|
|
222
273
|
else {
|
|
223
|
-
(0,
|
|
224
|
-
(0, utils_1.log)(this.importConfig, error, 'error');
|
|
274
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Failed to update '${uid}' extension`);
|
|
225
275
|
}
|
|
226
276
|
};
|
|
277
|
+
cli_utilities_1.log.debug('Starting extensions update process', this.importConfig.context);
|
|
227
278
|
return await this.makeConcurrentCall({
|
|
228
279
|
apiContent,
|
|
229
280
|
processName: 'update extensions',
|
|
@@ -4,30 +4,49 @@ 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 lodash_1 = require("lodash");
|
|
8
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
9
|
const utils_1 = require("../../utils");
|
|
8
10
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
9
|
-
const lodash_1 = require("lodash");
|
|
10
11
|
class ImportCustomRoles extends base_class_1.default {
|
|
11
12
|
constructor({ importConfig, stackAPIClient }) {
|
|
12
13
|
super({ importConfig, stackAPIClient });
|
|
13
14
|
this.getTransformUidsFactory = (rule) => {
|
|
15
|
+
var _a, _b, _c;
|
|
16
|
+
cli_utilities_1.log.debug(`Transforming UIDs for rule module: ${rule.module}`, this.importConfig.context);
|
|
14
17
|
if (rule.module === 'environment') {
|
|
15
18
|
if (!(0, isEmpty_1.default)(this.environmentsUidMap)) {
|
|
19
|
+
const originalEnvs = ((_a = rule.environments) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
16
20
|
rule.environments = (0, lodash_1.map)(rule.environments, (env) => this.environmentsUidMap[env]);
|
|
21
|
+
cli_utilities_1.log.debug(`Transformed ${originalEnvs} environment UIDs for rule`, this.importConfig.context);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
cli_utilities_1.log.debug('No environment UID mappings available for transformation', this.importConfig.context);
|
|
17
25
|
}
|
|
18
26
|
}
|
|
19
27
|
else if (rule.module === 'locale') {
|
|
20
28
|
if (!(0, isEmpty_1.default)(this.localesUidMap)) {
|
|
29
|
+
const originalLocales = ((_b = rule.locales) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
21
30
|
rule.locales = (0, lodash_1.map)(rule.locales, (locale) => this.localesUidMap[locale]);
|
|
31
|
+
cli_utilities_1.log.debug(`Transformed ${originalLocales} locale UIDs for rule`, this.importConfig.context);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
cli_utilities_1.log.debug('No locale UID mappings available for transformation', this.importConfig.context);
|
|
22
35
|
}
|
|
23
36
|
}
|
|
24
37
|
else if (rule.module === 'entry') {
|
|
25
38
|
if (!(0, isEmpty_1.default)(this.entriesUidMap)) {
|
|
39
|
+
const originalEntries = ((_c = rule.entries) === null || _c === void 0 ? void 0 : _c.length) || 0;
|
|
26
40
|
rule.entries = (0, lodash_1.map)(rule.entries, (entry) => this.entriesUidMap[entry]);
|
|
41
|
+
cli_utilities_1.log.debug(`Transformed ${originalEntries} entry UIDs for rule`, this.importConfig.context);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
cli_utilities_1.log.debug('No entry UID mappings available for transformation', this.importConfig.context);
|
|
27
45
|
}
|
|
28
46
|
}
|
|
29
47
|
return rule;
|
|
30
48
|
};
|
|
49
|
+
this.importConfig.context.module = 'custom-roles';
|
|
31
50
|
this.customRolesConfig = importConfig.modules.customRoles;
|
|
32
51
|
this.customRolesMapperPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'custom-roles');
|
|
33
52
|
this.customRolesFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.customRolesConfig.dirName);
|
|
@@ -50,85 +69,133 @@ class ImportCustomRoles extends base_class_1.default {
|
|
|
50
69
|
* @returns {Promise<void>} Promise<void>
|
|
51
70
|
*/
|
|
52
71
|
async start() {
|
|
53
|
-
var _a, _b;
|
|
54
|
-
|
|
72
|
+
var _a, _b, _c;
|
|
73
|
+
cli_utilities_1.log.debug('Checking for custom roles folder existence', this.importConfig.context);
|
|
55
74
|
//Step1 check folder exists or not
|
|
56
75
|
if (utils_1.fileHelper.fileExistsSync(this.customRolesFolderPath)) {
|
|
76
|
+
cli_utilities_1.log.debug(`Found custom roles folder: ${this.customRolesFolderPath}`, this.importConfig.context);
|
|
57
77
|
this.customRoles = utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesFolderPath, this.customRolesConfig.fileName), true);
|
|
58
78
|
this.customRolesLocales = utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesFolderPath, this.customRolesConfig.customRolesLocalesFileName), true);
|
|
59
79
|
}
|
|
60
80
|
else {
|
|
61
|
-
|
|
81
|
+
cli_utilities_1.log.info(`No custom-rules are found - '${this.customRolesFolderPath}'`, this.importConfig.context);
|
|
62
82
|
return;
|
|
63
83
|
}
|
|
64
84
|
//create webhooks in mapper directory
|
|
85
|
+
cli_utilities_1.log.debug('Creating custom roles mapper directory', this.importConfig.context);
|
|
65
86
|
await utils_1.fsUtil.makeDirectory(this.customRolesMapperPath);
|
|
87
|
+
cli_utilities_1.log.debug('Loading existing custom roles UID data', this.importConfig.context);
|
|
66
88
|
this.customRolesUidMapper = utils_1.fileHelper.fileExistsSync(this.customRolesUidMapperPath)
|
|
67
|
-
? utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesUidMapperPath), true)
|
|
89
|
+
? utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesUidMapperPath), true) || {}
|
|
68
90
|
: {};
|
|
91
|
+
cli_utilities_1.log.debug('Loading environments UID data', this.importConfig.context);
|
|
69
92
|
this.environmentsUidMap = utils_1.fileHelper.fileExistsSync(this.envUidMapperFolderPath)
|
|
70
|
-
? utils_1.fsUtil.readFile((0, node_path_1.join)(this.envUidMapperFolderPath, 'uid-mapping.json'), true)
|
|
93
|
+
? utils_1.fsUtil.readFile((0, node_path_1.join)(this.envUidMapperFolderPath, 'uid-mapping.json'), true) || {}
|
|
71
94
|
: {};
|
|
95
|
+
cli_utilities_1.log.debug('Loading entries UID data', this.importConfig.context);
|
|
72
96
|
this.entriesUidMap = utils_1.fileHelper.fileExistsSync(this.entriesUidMapperFolderPath)
|
|
73
|
-
? utils_1.fsUtil.readFile((0, node_path_1.join)(this.entriesUidMapperFolderPath, 'uid-mapping.json'), true)
|
|
97
|
+
? utils_1.fsUtil.readFile((0, node_path_1.join)(this.entriesUidMapperFolderPath, 'uid-mapping.json'), true) || {}
|
|
74
98
|
: {};
|
|
99
|
+
if (this.customRolesUidMapper && Object.keys(this.customRolesUidMapper || {}).length > 0) {
|
|
100
|
+
const customRolesUidCount = Object.keys(this.customRolesUidMapper || {}).length;
|
|
101
|
+
cli_utilities_1.log.debug(`Loaded existing custom roles UID data: ${customRolesUidCount} items`, this.importConfig.context);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
cli_utilities_1.log.debug('No existing custom roles UID data found', this.importConfig.context);
|
|
105
|
+
}
|
|
106
|
+
if (this.environmentsUidMap && ((_a = Object.keys(this.environmentsUidMap || {})) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
107
|
+
const envUidCount = Object.keys(this.environmentsUidMap || {}).length;
|
|
108
|
+
cli_utilities_1.log.debug(`Loaded environments UID data: ${envUidCount} items`, this.importConfig.context);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
cli_utilities_1.log.debug('No environments UID data found', this.importConfig.context);
|
|
112
|
+
}
|
|
113
|
+
if (this.entriesUidMap && Object.keys(this.entriesUidMap || {}).length > 0) {
|
|
114
|
+
const entriesUidCount = Object.keys(this.entriesUidMap || {}).length;
|
|
115
|
+
cli_utilities_1.log.debug(`Loaded entries UID data: ${entriesUidCount} items`, this.importConfig.context);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
cli_utilities_1.log.debug('No entries UID data found', this.importConfig.context);
|
|
119
|
+
}
|
|
75
120
|
//source and target stack locale map
|
|
121
|
+
cli_utilities_1.log.debug('Getting locales UID mapping', this.importConfig.context);
|
|
76
122
|
await this.getLocalesUidMap();
|
|
123
|
+
cli_utilities_1.log.debug('Starting custom roles import', this.importConfig.context);
|
|
77
124
|
await this.importCustomRoles();
|
|
78
|
-
|
|
125
|
+
cli_utilities_1.log.debug('Processing custom roles import results', this.importConfig.context);
|
|
126
|
+
if ((_b = this.createdCustomRoles) === null || _b === void 0 ? void 0 : _b.length) {
|
|
79
127
|
utils_1.fsUtil.writeFile(this.createdCustomRolesPath, this.createdCustomRoles);
|
|
128
|
+
cli_utilities_1.log.debug(`Written ${this.createdCustomRoles.length} successful custom roles to file`, this.importConfig.context);
|
|
80
129
|
}
|
|
81
|
-
if ((
|
|
130
|
+
if ((_c = this.failedCustomRoles) === null || _c === void 0 ? void 0 : _c.length) {
|
|
82
131
|
utils_1.fsUtil.writeFile(this.customRolesFailsPath, this.failedCustomRoles);
|
|
132
|
+
cli_utilities_1.log.debug(`Written ${this.failedCustomRoles.length} failed custom roles to file`, this.importConfig.context);
|
|
83
133
|
}
|
|
84
|
-
|
|
134
|
+
cli_utilities_1.log.success('Custom roles have been imported successfully!', this.importConfig.context);
|
|
85
135
|
}
|
|
86
136
|
async getLocalesUidMap() {
|
|
137
|
+
cli_utilities_1.log.debug('Fetching target stack locales', this.importConfig.context);
|
|
87
138
|
const { items } = await this.stack
|
|
88
139
|
.locale()
|
|
89
140
|
.query()
|
|
90
141
|
.find()
|
|
91
|
-
.then((data) =>
|
|
92
|
-
|
|
142
|
+
.then((data) => {
|
|
143
|
+
var _a;
|
|
144
|
+
cli_utilities_1.log.debug(`Found ${((_a = data.items) === null || _a === void 0 ? void 0 : _a.length) || 0} locales in target stack`, this.importConfig.context);
|
|
145
|
+
return data;
|
|
146
|
+
})
|
|
147
|
+
.catch((error) => {
|
|
148
|
+
cli_utilities_1.log.debug('Error fetching target stack locales', this.importConfig.context);
|
|
149
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.importConfig.context));
|
|
150
|
+
});
|
|
93
151
|
this.targetLocalesMap = {};
|
|
94
152
|
this.sourceLocalesMap = {};
|
|
153
|
+
cli_utilities_1.log.debug('Building target locales mapping', this.importConfig.context);
|
|
95
154
|
(0, lodash_1.forEach)(items, (locale) => {
|
|
96
155
|
this.targetLocalesMap[locale.code] = locale.uid;
|
|
97
156
|
});
|
|
157
|
+
cli_utilities_1.log.debug('Building source locales mapping', this.importConfig.context);
|
|
98
158
|
for (const key in this.customRolesLocales) {
|
|
99
159
|
const sourceLocales = this.customRolesLocales[key];
|
|
100
160
|
this.sourceLocalesMap[sourceLocales.code] = key;
|
|
101
161
|
}
|
|
162
|
+
cli_utilities_1.log.debug('Creating locale UID mapping', this.importConfig.context);
|
|
102
163
|
for (const key in this.sourceLocalesMap) {
|
|
103
164
|
const sourceLocaleKey = this.sourceLocalesMap[key];
|
|
104
165
|
this.localesUidMap[sourceLocaleKey] = this.targetLocalesMap[key];
|
|
105
166
|
}
|
|
167
|
+
const localesMappingCount = Object.keys(this.localesUidMap || {}).length;
|
|
168
|
+
cli_utilities_1.log.debug(`Created ${localesMappingCount} locale UID mappings`, this.importConfig.context);
|
|
106
169
|
}
|
|
107
170
|
async importCustomRoles() {
|
|
171
|
+
cli_utilities_1.log.debug('Starting custom roles import process', this.importConfig.context);
|
|
108
172
|
if (this.customRoles === undefined || (0, isEmpty_1.default)(this.customRoles)) {
|
|
109
|
-
|
|
173
|
+
cli_utilities_1.log.info('No custom-roles found', this.importConfig.context);
|
|
110
174
|
return;
|
|
111
175
|
}
|
|
112
176
|
const apiContent = (0, values_1.default)(this.customRoles);
|
|
177
|
+
cli_utilities_1.log.debug(`Importing ${apiContent.length} custom roles`, this.importConfig.context);
|
|
113
178
|
const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
|
|
114
179
|
this.createdCustomRoles.push(response);
|
|
115
180
|
this.customRolesUidMapper[uid] = response.uid;
|
|
116
|
-
|
|
181
|
+
cli_utilities_1.log.success(`custom-role '${name}' imported successfully`, this.importConfig.context);
|
|
182
|
+
cli_utilities_1.log.debug(`Custom role import completed: ${name} (${uid})`, this.importConfig.context);
|
|
117
183
|
utils_1.fsUtil.writeFile(this.customRolesUidMapperPath, this.customRolesUidMapper);
|
|
118
184
|
};
|
|
119
185
|
const onReject = ({ error, apiData }) => {
|
|
120
186
|
var _a;
|
|
121
187
|
const err = (error === null || error === void 0 ? void 0 : error.message) ? JSON.parse(error.message) : error;
|
|
122
188
|
const { name } = apiData;
|
|
189
|
+
cli_utilities_1.log.debug(`Custom role '${name}' import failed`, this.importConfig.context);
|
|
123
190
|
if ((_a = err === null || err === void 0 ? void 0 : err.errors) === null || _a === void 0 ? void 0 : _a.name) {
|
|
124
|
-
|
|
191
|
+
cli_utilities_1.log.info(`custom-role '${name}' already exists`, this.importConfig.context);
|
|
125
192
|
}
|
|
126
193
|
else {
|
|
127
194
|
this.failedCustomRoles.push(apiData);
|
|
128
|
-
(0,
|
|
129
|
-
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
195
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { name }), `custom-role '${name}' failed to be import`);
|
|
130
196
|
}
|
|
131
197
|
};
|
|
198
|
+
cli_utilities_1.log.debug(`Using concurrency limit: ${this.importConfig.fetchConcurrency || 1}`, this.importConfig.context);
|
|
132
199
|
await this.makeConcurrentCall({
|
|
133
200
|
apiContent,
|
|
134
201
|
processName: 'create custom role',
|
|
@@ -141,6 +208,7 @@ class ImportCustomRoles extends base_class_1.default {
|
|
|
141
208
|
},
|
|
142
209
|
concurrencyLimit: this.importConfig.fetchConcurrency || 1,
|
|
143
210
|
}, undefined, false);
|
|
211
|
+
cli_utilities_1.log.debug('Custom roles import process completed', this.importConfig.context);
|
|
144
212
|
}
|
|
145
213
|
/**
|
|
146
214
|
* @method serializeWebhooks
|
|
@@ -148,26 +216,34 @@ class ImportCustomRoles extends base_class_1.default {
|
|
|
148
216
|
* @returns {ApiOptions} ApiOptions
|
|
149
217
|
*/
|
|
150
218
|
serializeWebhooks(apiOptions) {
|
|
219
|
+
var _a;
|
|
151
220
|
const { apiData: customRole } = apiOptions;
|
|
221
|
+
cli_utilities_1.log.debug(`Serializing custom role: ${customRole.name} (${customRole.uid})`, this.importConfig.context);
|
|
152
222
|
if (this.customRolesUidMapper.hasOwnProperty(customRole.uid)) {
|
|
153
|
-
|
|
223
|
+
cli_utilities_1.log.info(`custom-role '${customRole.name}' already exists. Skipping it to avoid duplicates!`, this.importConfig.context);
|
|
224
|
+
cli_utilities_1.log.debug(`Skipping custom role serialization for: ${customRole.uid}`, this.importConfig.context);
|
|
154
225
|
apiOptions.entity = undefined;
|
|
155
226
|
}
|
|
156
227
|
else {
|
|
157
228
|
let branchRuleExists = false;
|
|
229
|
+
cli_utilities_1.log.debug(`Processing ${((_a = customRole.rules) === null || _a === void 0 ? void 0 : _a.length) || 0} rules for custom role: ${customRole.name}`, this.importConfig.context);
|
|
158
230
|
(0, lodash_1.forEach)(customRole.rules, (rule) => {
|
|
159
231
|
rule = this.getTransformUidsFactory(rule);
|
|
160
232
|
// rules.branch is required to create custom roles.
|
|
161
|
-
if (rule.module === 'branch')
|
|
233
|
+
if (rule.module === 'branch') {
|
|
162
234
|
branchRuleExists = true;
|
|
235
|
+
cli_utilities_1.log.debug(`Found branch rule in custom role: ${customRole.name}`, this.importConfig.context);
|
|
236
|
+
}
|
|
163
237
|
});
|
|
164
238
|
if (!branchRuleExists) {
|
|
239
|
+
cli_utilities_1.log.debug(`Adding default branch rule to custom role: ${customRole.name}`, this.importConfig.context);
|
|
165
240
|
customRole.rules.push({
|
|
166
241
|
module: 'branch',
|
|
167
242
|
branches: ['main'],
|
|
168
243
|
acl: { read: true },
|
|
169
244
|
});
|
|
170
245
|
}
|
|
246
|
+
cli_utilities_1.log.debug(`Custom role serialization completed: ${customRole.name}`, this.importConfig.context);
|
|
171
247
|
apiOptions.apiData = customRole;
|
|
172
248
|
}
|
|
173
249
|
return apiOptions;
|