@contentstack/cli-cm-import 1.25.1 → 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/content-types.js +76 -31
- 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 +85 -20
- 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/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,51 +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);
|
|
76
87
|
}
|
|
88
|
+
cli_utilities_1.log.info('Starting pending global fields update', this.importConfig.context);
|
|
77
89
|
this.pendingGFs = utils_1.fsUtil.readFile(this.gFsPendingPath);
|
|
78
90
|
if (!this.pendingGFs || (0, lodash_1.isEmpty)(this.pendingGFs)) {
|
|
79
|
-
|
|
91
|
+
cli_utilities_1.log.info('No pending global fields found to update', this.importConfig.context);
|
|
80
92
|
return;
|
|
81
93
|
}
|
|
82
94
|
await this.updatePendingGFs().catch((error) => {
|
|
83
|
-
(0,
|
|
95
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.importConfig.context));
|
|
84
96
|
});
|
|
85
|
-
|
|
86
|
-
|
|
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);
|
|
87
99
|
}
|
|
88
100
|
async seedCTs() {
|
|
89
101
|
const onSuccess = ({ response: globalField, apiData: { content_type: { uid = null } = {} } = {} }) => {
|
|
90
102
|
this.createdCTs.push(uid);
|
|
91
|
-
|
|
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);
|
|
92
105
|
};
|
|
93
106
|
const onReject = ({ error, apiData: { content_type: { uid = null } = {} } = {} }) => {
|
|
94
107
|
if (error.errorCode === 115 && (error.errors.uid || error.errors.title)) {
|
|
95
|
-
|
|
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);
|
|
96
110
|
}
|
|
97
111
|
else {
|
|
98
|
-
(0,
|
|
99
|
-
process.exit(1);
|
|
112
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Failed to seed content type ${uid}`);
|
|
100
113
|
}
|
|
101
114
|
};
|
|
115
|
+
cli_utilities_1.log.debug(`Starting to seed ${this.cTs.length} content types`, this.importConfig.context);
|
|
102
116
|
return await this.makeConcurrentCall({
|
|
103
117
|
processName: 'Import content types',
|
|
104
118
|
apiContent: this.cTs,
|
|
@@ -119,6 +133,7 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
119
133
|
*/
|
|
120
134
|
serializeCTs(apiOptions) {
|
|
121
135
|
const { apiData: contentType } = apiOptions;
|
|
136
|
+
cli_utilities_1.log.debug(`Serializing content type: ${contentType.uid} (${contentType.title})`, this.importConfig.context);
|
|
122
137
|
const updatedCT = (0, lodash_1.cloneDeep)(utils_1.schemaTemplate);
|
|
123
138
|
updatedCT.content_type.uid = contentType.uid;
|
|
124
139
|
updatedCT.content_type.title = contentType.title;
|
|
@@ -127,12 +142,14 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
127
142
|
}
|
|
128
143
|
async updateCTs() {
|
|
129
144
|
const onSuccess = ({ response: contentType, apiData: { uid } }) => {
|
|
130
|
-
|
|
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);
|
|
131
147
|
};
|
|
132
148
|
const onReject = ({ error, apiData: { uid } }) => {
|
|
133
|
-
(0,
|
|
149
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Content type '${uid}' update failed`);
|
|
134
150
|
throw new Error(`Content type '${uid}' update error`);
|
|
135
151
|
};
|
|
152
|
+
cli_utilities_1.log.debug(`Starting to update ${this.cTs.length} content types with references`, this.importConfig.context);
|
|
136
153
|
return await this.makeConcurrentCall({
|
|
137
154
|
processName: 'Update content types',
|
|
138
155
|
apiContent: this.cTs,
|
|
@@ -153,36 +170,50 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
153
170
|
*/
|
|
154
171
|
serializeUpdateCTs(apiOptions) {
|
|
155
172
|
const { apiData: contentType } = apiOptions;
|
|
173
|
+
cli_utilities_1.log.debug(`Serializing update for content type: ${contentType.uid} (${contentType.title})`, this.importConfig.context);
|
|
156
174
|
if (contentType.field_rules) {
|
|
157
175
|
contentType.field_rules = (0, content_type_helper_1.updateFieldRules)(contentType);
|
|
158
176
|
if (!contentType.field_rules.length) {
|
|
159
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);
|
|
160
182
|
}
|
|
161
183
|
this.fieldRules.push(contentType.uid);
|
|
162
184
|
}
|
|
163
185
|
//will remove taxonomy if taxonomy doesn't exists in stack
|
|
164
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);
|
|
165
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);
|
|
166
190
|
const contentTypePayload = this.stack.contentType(contentType.uid);
|
|
167
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);
|
|
168
193
|
apiOptions.apiData = contentTypePayload;
|
|
169
194
|
return apiOptions;
|
|
170
195
|
}
|
|
171
196
|
async updatePendingGFs() {
|
|
197
|
+
var _a, _b;
|
|
172
198
|
this.pendingGFs = utils_1.fsUtil.readFile(this.gFsPendingPath);
|
|
173
|
-
|
|
199
|
+
cli_utilities_1.log.info(`Found ${this.pendingGFs.length} pending global fields to update`, this.importConfig.context);
|
|
174
200
|
this.gFs = utils_1.fsUtil.readFile(path.resolve(this.gFsFolderPath, this.gFsConfig.fileName));
|
|
175
|
-
|
|
176
|
-
|
|
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);
|
|
203
|
+
const onSuccess = ({ response: globalField, apiData: { uid } = undefined }) => {
|
|
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);
|
|
177
206
|
};
|
|
178
207
|
const onReject = ({ error, apiData: { uid } = undefined }) => {
|
|
179
|
-
(0,
|
|
208
|
+
(0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Failed to update the global field '${uid}'`);
|
|
180
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);
|
|
181
214
|
return await this.makeConcurrentCall({
|
|
182
215
|
processName: 'Update pending global fields',
|
|
183
|
-
apiContent:
|
|
184
|
-
return { uid };
|
|
185
|
-
}),
|
|
216
|
+
apiContent: apiContent,
|
|
186
217
|
apiParams: {
|
|
187
218
|
serializeData: this.serializeUpdateGFs.bind(this),
|
|
188
219
|
reject: onReject.bind(this),
|
|
@@ -200,36 +231,50 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
200
231
|
*/
|
|
201
232
|
serializeUpdateGFs(apiOptions) {
|
|
202
233
|
const { apiData: { uid }, } = apiOptions;
|
|
234
|
+
cli_utilities_1.log.debug(`Serializing global field update for: ${uid}`, this.importConfig.context);
|
|
203
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);
|
|
204
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);
|
|
205
244
|
const globalFieldPayload = this.stack.globalField(uid, { api_version: '3.2' });
|
|
206
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);
|
|
207
247
|
apiOptions.apiData = globalFieldPayload;
|
|
208
248
|
return apiOptions;
|
|
209
249
|
}
|
|
210
250
|
async updatePendingExtensions() {
|
|
211
251
|
let apiContent = utils_1.fsUtil.readFile(this.extPendingPath);
|
|
212
|
-
|
|
213
|
-
|
|
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);
|
|
214
256
|
return;
|
|
215
257
|
}
|
|
258
|
+
cli_utilities_1.log.debug(`Found ${apiContent.length} extensions to update`, this.importConfig.context);
|
|
216
259
|
this.isExtensionsUpdate = true;
|
|
217
260
|
const onSuccess = ({ response, apiData: { uid, title } = { uid: null, title: '' } }) => {
|
|
218
|
-
|
|
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);
|
|
219
263
|
};
|
|
220
264
|
const onReject = ({ error, apiData }) => {
|
|
221
265
|
var _a;
|
|
222
266
|
const { uid } = apiData;
|
|
223
267
|
if ((_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.title) {
|
|
224
268
|
if (!this.importConfig.skipExisting) {
|
|
225
|
-
|
|
269
|
+
cli_utilities_1.log.info(`Extension '${uid}' already exists.`, this.importConfig.context);
|
|
226
270
|
}
|
|
271
|
+
cli_utilities_1.log.debug(`Skipping existing extension: ${uid}`, this.importConfig.context);
|
|
227
272
|
}
|
|
228
273
|
else {
|
|
229
|
-
(0,
|
|
230
|
-
(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`);
|
|
231
275
|
}
|
|
232
276
|
};
|
|
277
|
+
cli_utilities_1.log.debug('Starting extensions update process', this.importConfig.context);
|
|
233
278
|
return await this.makeConcurrentCall({
|
|
234
279
|
apiContent,
|
|
235
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;
|