@contentstack/cli-cm-import 1.28.0 → 2.0.0-beta

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.
Files changed (87) hide show
  1. package/README.md +5 -7
  2. package/lib/commands/cm/stacks/import.d.ts +2 -0
  3. package/lib/commands/cm/stacks/import.js +46 -11
  4. package/lib/config/index.js +0 -1
  5. package/lib/import/module-importer.d.ts +2 -2
  6. package/lib/import/module-importer.js +9 -25
  7. package/lib/import/modules/assets.d.ts +6 -0
  8. package/lib/import/modules/assets.js +102 -25
  9. package/lib/import/modules/base-class.d.ts +17 -0
  10. package/lib/import/modules/base-class.js +45 -0
  11. package/lib/import/modules/content-types.d.ts +7 -10
  12. package/lib/import/modules/content-types.js +132 -68
  13. package/lib/import/modules/custom-roles.d.ts +6 -2
  14. package/lib/import/modules/custom-roles.js +80 -69
  15. package/lib/import/modules/entries.d.ts +7 -0
  16. package/lib/import/modules/entries.js +278 -163
  17. package/lib/import/modules/environments.d.ts +3 -0
  18. package/lib/import/modules/environments.js +69 -38
  19. package/lib/import/modules/extensions.d.ts +3 -0
  20. package/lib/import/modules/extensions.js +99 -64
  21. package/lib/import/modules/global-fields.d.ts +8 -1
  22. package/lib/import/modules/global-fields.js +123 -63
  23. package/lib/import/modules/index.d.ts +1 -0
  24. package/lib/import/modules/index.js +1 -0
  25. package/lib/import/modules/labels.d.ts +3 -0
  26. package/lib/import/modules/labels.js +104 -54
  27. package/lib/import/modules/locales.d.ts +15 -4
  28. package/lib/import/modules/locales.js +194 -94
  29. package/lib/import/modules/marketplace-apps.d.ts +6 -3
  30. package/lib/import/modules/marketplace-apps.js +177 -102
  31. package/lib/import/modules/personalize.d.ts +11 -4
  32. package/lib/import/modules/personalize.js +138 -47
  33. package/lib/import/modules/stack.d.ts +6 -0
  34. package/lib/import/modules/stack.js +71 -27
  35. package/lib/import/modules/taxonomies.d.ts +4 -2
  36. package/lib/import/modules/taxonomies.js +60 -46
  37. package/lib/import/modules/variant-entries.d.ts +7 -4
  38. package/lib/import/modules/variant-entries.js +76 -35
  39. package/lib/import/modules/webhooks.d.ts +3 -0
  40. package/lib/import/modules/webhooks.js +71 -40
  41. package/lib/import/modules/workflows.d.ts +3 -0
  42. package/lib/import/modules/workflows.js +98 -48
  43. package/lib/types/default-config.d.ts +0 -1
  44. package/lib/types/import-config.d.ts +0 -1
  45. package/lib/types/index.d.ts +1 -12
  46. package/lib/utils/backup-handler.js +1 -2
  47. package/lib/utils/constants.d.ts +243 -0
  48. package/lib/utils/constants.js +264 -0
  49. package/lib/utils/import-config-handler.js +2 -7
  50. package/lib/utils/import-path-resolver.d.ts +1 -1
  51. package/lib/utils/import-path-resolver.js +5 -5
  52. package/lib/utils/index.d.ts +1 -1
  53. package/lib/utils/index.js +6 -2
  54. package/lib/utils/marketplace-app-helper.js +3 -8
  55. package/lib/utils/progress-strategy-registry.d.ts +7 -0
  56. package/lib/utils/progress-strategy-registry.js +72 -0
  57. package/lib/utils/setup-branch.js +1 -1
  58. package/oclif.manifest.json +2 -2
  59. package/package.json +2 -2
  60. package/lib/import/modules-js/assets.d.ts +0 -33
  61. package/lib/import/modules-js/assets.js +0 -428
  62. package/lib/import/modules-js/content-types.d.ts +0 -34
  63. package/lib/import/modules-js/content-types.js +0 -204
  64. package/lib/import/modules-js/custom-roles.d.ts +0 -15
  65. package/lib/import/modules-js/custom-roles.js +0 -143
  66. package/lib/import/modules-js/entries.d.ts +0 -54
  67. package/lib/import/modules-js/entries.js +0 -1280
  68. package/lib/import/modules-js/environments.d.ts +0 -13
  69. package/lib/import/modules-js/environments.js +0 -85
  70. package/lib/import/modules-js/extensions.d.ts +0 -18
  71. package/lib/import/modules-js/extensions.js +0 -86
  72. package/lib/import/modules-js/global-fields.d.ts +0 -13
  73. package/lib/import/modules-js/global-fields.js +0 -106
  74. package/lib/import/modules-js/index.d.ts +0 -1
  75. package/lib/import/modules-js/index.js +0 -33
  76. package/lib/import/modules-js/labels.d.ts +0 -20
  77. package/lib/import/modules-js/labels.js +0 -148
  78. package/lib/import/modules-js/locales.d.ts +0 -24
  79. package/lib/import/modules-js/locales.js +0 -196
  80. package/lib/import/modules-js/marketplace-apps.d.ts +0 -63
  81. package/lib/import/modules-js/marketplace-apps.js +0 -429
  82. package/lib/import/modules-js/webhooks.d.ts +0 -17
  83. package/lib/import/modules-js/webhooks.js +0 -85
  84. package/lib/import/modules-js/workflows.d.ts +0 -19
  85. package/lib/import/modules-js/workflows.js +0 -170
  86. package/lib/utils/log.d.ts +0 -12
  87. package/lib/utils/log.js +0 -31
@@ -1,29 +1,24 @@
1
1
  "use strict";
2
- /* eslint-disable no-prototype-builtins */
3
- /*!
4
- * Contentstack Import
5
- * Copyright (c) 2024 Contentstack LLC
6
- * MIT Licensed
7
- */
8
2
  Object.defineProperty(exports, "__esModule", { value: true });
9
3
  const tslib_1 = require("tslib");
10
4
  const path = tslib_1.__importStar(require("path"));
11
5
  const lodash_1 = require("lodash");
12
6
  const cli_utilities_1 = require("@contentstack/cli-utilities");
13
- const utils_1 = require("../../utils");
14
7
  const base_class_1 = tslib_1.__importDefault(require("./base-class"));
15
8
  const content_type_helper_1 = require("../../utils/content-type-helper");
9
+ const utils_1 = require("../../utils");
16
10
  class ContentTypesImport extends base_class_1.default {
17
11
  constructor({ importConfig, stackAPIClient }) {
18
12
  super({ importConfig, stackAPIClient });
19
13
  this.isExtensionsUpdate = false;
20
- this.importConfig.context.module = 'content-types';
14
+ this.importConfig.context.module = utils_1.MODULE_CONTEXTS.CONTENT_TYPES;
15
+ this.currentModuleName = utils_1.MODULE_NAMES[utils_1.MODULE_CONTEXTS.CONTENT_TYPES];
21
16
  this.cTsConfig = importConfig.modules['content-types'];
22
17
  this.gFsConfig = importConfig.modules['global-fields'];
23
18
  this.reqConcurrency = this.cTsConfig.writeConcurrency || this.importConfig.writeConcurrency;
24
19
  this.cTsFolderPath = path.join((0, cli_utilities_1.sanitizePath)(this.importConfig.data), (0, cli_utilities_1.sanitizePath)(this.cTsConfig.dirName));
25
20
  this.cTsMapperPath = path.join((0, cli_utilities_1.sanitizePath)(this.importConfig.data), 'mapper', 'content_types');
26
- this.cTsSuccessPath = path.join((0, cli_utilities_1.sanitizePath)(this.cTsMapperPath), 'success.json');
21
+ this.cTsSuccessPath = path.join((0, cli_utilities_1.sanitizePath)(this.importConfig.data), 'mapper', 'content_types', 'success.json');
27
22
  this.gFsFolderPath = path.resolve((0, cli_utilities_1.sanitizePath)(this.importConfig.data), (0, cli_utilities_1.sanitizePath)(this.gFsConfig.dirName));
28
23
  this.gFsMapperFolderPath = path.join((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'global_fields', 'success.json');
29
24
  this.gFsPendingPath = path.join((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'global_fields', 'pending_global_fields.js');
@@ -41,69 +36,55 @@ class ContentTypesImport extends base_class_1.default {
41
36
  this.gFs = [];
42
37
  this.createdGFs = [];
43
38
  this.pendingGFs = [];
44
- this.taxonomiesPath = path.join((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper/taxonomies', 'success.json');
39
+ this.pendingExts = [];
40
+ this.taxonomiesPath = path.join((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'taxonomies', 'success.json');
45
41
  this.extPendingPath = path.join((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'extensions', 'pending_extensions.js');
46
42
  }
47
43
  async start() {
48
- var _a, _b;
49
- /**
50
- * read content type, check if it is necessary to read the entire dir
51
- * Seed content types
52
- * Update content types, lookup extension.
53
- * Update pending global fields
54
- * write field rules
55
- */
56
- this.cTs = utils_1.fsUtil.readFile(path.join(this.cTsFolderPath, 'schema.json'));
57
- if (!this.cTs || (0, lodash_1.isEmpty)(this.cTs)) {
58
- cli_utilities_1.log.info('No content type found to import', this.importConfig.context);
59
- return;
60
- }
61
- cli_utilities_1.log.debug(`Found ${this.cTs.length} content types to import`, this.importConfig.context);
62
- await utils_1.fsUtil.makeDirectory(this.cTsMapperPath);
63
- cli_utilities_1.log.debug('Created content types mapper directory', this.importConfig.context);
64
- this.installedExtensions = (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);
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);
70
- await this.seedCTs();
71
- if ((_b = this.createdCTs) === null || _b === void 0 ? void 0 : _b.length) {
72
- utils_1.fsUtil.writeFile(this.cTsSuccessPath, this.createdCTs);
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);
77
- await this.updateCTs();
78
- cli_utilities_1.log.success('Updated content types with references', this.importConfig.context);
79
- if (this.fieldRules.length > 0) {
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);
82
- }
83
- cli_utilities_1.log.info('Updating the extensions...', this.importConfig.context);
84
- await this.updatePendingExtensions();
85
- if (this.isExtensionsUpdate) {
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;
44
+ var _a;
45
+ try {
46
+ cli_utilities_1.log.debug('Starting content types import process...', this.importConfig.context);
47
+ await this.analyzeImportData();
48
+ if (!((_a = this.cTs) === null || _a === void 0 ? void 0 : _a.length)) {
49
+ cli_utilities_1.log.info('No content type found to import', this.importConfig.context);
50
+ return;
51
+ }
52
+ await utils_1.fsUtil.makeDirectory(this.cTsMapperPath);
53
+ cli_utilities_1.log.debug('Created content types mapper directory', this.importConfig.context);
54
+ const progress = this.initializeProgress();
55
+ if (this.cTs.length > 0) {
56
+ await this.handleContentTypesCreation(progress);
57
+ await this.handleContentTypesUpdate(progress);
58
+ }
59
+ if (this.fieldRules.length > 0) {
60
+ utils_1.fsUtil.writeFile(path.join(this.cTsFolderPath, 'field_rules_uid.json'), this.fieldRules);
61
+ cli_utilities_1.log.debug(`Written ${this.fieldRules.length} field rules to file`, this.importConfig.context);
62
+ }
63
+ if (this.pendingExts.length > 0) {
64
+ await this.handlePendingExtensions(progress);
65
+ }
66
+ if (this.pendingGFs.length > 0) {
67
+ await this.handlePendingGlobalFields(progress);
68
+ }
69
+ this.completeProgress(true);
70
+ cli_utilities_1.log.success('Content types have been imported successfully!', this.importConfig.context);
93
71
  }
94
- await this.updatePendingGFs().catch((error) => {
72
+ catch (error) {
73
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Content types import failed');
95
74
  (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.importConfig.context));
96
- });
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);
75
+ }
99
76
  }
100
77
  async seedCTs() {
101
78
  const onSuccess = ({ response: globalField, apiData: { content_type: { uid = null } = {} } = {} }) => {
79
+ var _a;
102
80
  this.createdCTs.push(uid);
103
- cli_utilities_1.log.info(`${uid} content type seeded`, this.importConfig.context);
81
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `content type: ${uid}`, null, utils_1.PROCESS_NAMES.CONTENT_TYPES_CREATE);
82
+ cli_utilities_1.log.success(`Content type '${uid}' created successfully`, this.importConfig.context);
104
83
  cli_utilities_1.log.debug(`Successfully seeded content type: ${uid}`, this.importConfig.context);
105
84
  };
106
85
  const onReject = ({ error, apiData: { content_type: { uid = null } = {} } = {} }) => {
86
+ var _a;
87
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, `content type: ${uid}`, (error === null || error === void 0 ? void 0 : error.message) || `Failed to create content type '${uid}'`, utils_1.PROCESS_NAMES.CONTENT_TYPES_CREATE);
107
88
  if (error.errorCode === 115 && (error.errors.uid || error.errors.title)) {
108
89
  cli_utilities_1.log.info(`${uid} content type already exist`, this.importConfig.context);
109
90
  cli_utilities_1.log.debug(`Skipping existing content type: ${uid}`, this.importConfig.context);
@@ -142,12 +123,15 @@ class ContentTypesImport extends base_class_1.default {
142
123
  }
143
124
  async updateCTs() {
144
125
  const onSuccess = ({ response: contentType, apiData: { uid } }) => {
126
+ var _a;
127
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `content type: ${uid}`, null, utils_1.PROCESS_NAMES.CONTENT_TYPES_UPDATE);
145
128
  cli_utilities_1.log.success(`'${uid}' updated with references`, this.importConfig.context);
146
129
  cli_utilities_1.log.debug(`Content type update completed for: ${uid}`, this.importConfig.context);
147
130
  };
148
131
  const onReject = ({ error, apiData: { uid } }) => {
132
+ var _a;
133
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, `content type: ${uid}`, (error === null || error === void 0 ? void 0 : error.message) || `Content type '${uid}' update failed`, utils_1.PROCESS_NAMES.CONTENT_TYPES_UPDATE);
149
134
  (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Content type '${uid}' update failed`);
150
- throw new Error(`Content type '${uid}' update error`);
151
135
  };
152
136
  cli_utilities_1.log.debug(`Starting to update ${this.cTs.length} content types with references`, this.importConfig.context);
153
137
  return await this.makeConcurrentCall({
@@ -195,16 +179,21 @@ class ContentTypesImport extends base_class_1.default {
195
179
  }
196
180
  async updatePendingGFs() {
197
181
  var _a, _b;
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);
200
- this.gFs = utils_1.fsUtil.readFile(path.resolve(this.gFsFolderPath, this.gFsConfig.fileName));
182
+ if (!this.pendingGFs || this.pendingGFs.length === 0) {
183
+ cli_utilities_1.log.info('No pending global fields found to update', this.importConfig.context);
184
+ return;
185
+ }
201
186
  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
187
  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
188
  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);
189
+ var _a;
190
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `global field: ${uid}`, null, utils_1.PROCESS_NAMES.CONTENT_TYPES_GF_UPDATE);
191
+ cli_utilities_1.log.success(`Updated the global field ${uid} with content type references`, this.importConfig.context);
205
192
  cli_utilities_1.log.debug(`Global field update completed for: ${uid}`, this.importConfig.context);
206
193
  };
207
194
  const onReject = ({ error, apiData: { uid } = undefined }) => {
195
+ var _a;
196
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, `global field: ${uid}`, (error === null || error === void 0 ? void 0 : error.message) || `Failed to update the global field '${uid}'`, utils_1.PROCESS_NAMES.CONTENT_TYPES_GF_UPDATE);
208
197
  (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { uid }), `Failed to update the global field '${uid}'`);
209
198
  };
210
199
  const apiContent = (0, lodash_1.map)(this.pendingGFs, (uid) => {
@@ -258,13 +247,16 @@ class ContentTypesImport extends base_class_1.default {
258
247
  cli_utilities_1.log.debug(`Found ${apiContent.length} extensions to update`, this.importConfig.context);
259
248
  this.isExtensionsUpdate = true;
260
249
  const onSuccess = ({ response, apiData: { uid, title } = { uid: null, title: '' } }) => {
250
+ var _a;
251
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `extension: ${response.title || title || uid}`, null, utils_1.PROCESS_NAMES.CONTENT_TYPES_EXT_UPDATE);
261
252
  cli_utilities_1.log.success(`Successfully updated the '${response.title}' extension.`, this.importConfig.context);
262
253
  cli_utilities_1.log.debug(`Extension update completed for: ${uid}`, this.importConfig.context);
263
254
  };
264
255
  const onReject = ({ error, apiData }) => {
265
- var _a;
266
- const { uid } = apiData;
267
- if ((_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.title) {
256
+ var _a, _b;
257
+ const { uid, title } = apiData;
258
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(false, `extension: ${title || uid}`, (error === null || error === void 0 ? void 0 : error.message) || `Failed to update '${uid}' extension`, utils_1.PROCESS_NAMES.CONTENT_TYPES_EXT_UPDATE);
259
+ if ((_b = error === null || error === void 0 ? void 0 : error.errors) === null || _b === void 0 ? void 0 : _b.title) {
268
260
  if (!this.importConfig.skipExisting) {
269
261
  cli_utilities_1.log.info(`Extension '${uid}' already exists.`, this.importConfig.context);
270
262
  }
@@ -287,5 +279,77 @@ class ContentTypesImport extends base_class_1.default {
287
279
  concurrencyLimit: this.importConfig.concurrency || this.importConfig.fetchConcurrency || 1,
288
280
  }, undefined, false);
289
281
  }
282
+ async analyzeImportData() {
283
+ var _a, _b, _c, _d, _e;
284
+ const [cts, gfs, pendingGfs, pendingExt] = await this.withLoadingSpinner('CONTENT TYPES: Analyzing import data...', async () => {
285
+ const cts = utils_1.fsUtil.readFile(path.join(this.cTsFolderPath, 'schema.json'));
286
+ const gfs = utils_1.fsUtil.readFile(path.resolve(this.gFsFolderPath, this.gFsConfig.fileName));
287
+ const pendingGfs = utils_1.fsUtil.readFile(this.gFsPendingPath);
288
+ const pendingExt = utils_1.fsUtil.readFile(this.extPendingPath);
289
+ return [cts, gfs, pendingGfs, pendingExt];
290
+ });
291
+ this.cTs = (Array.isArray(cts) ? cts : []);
292
+ this.gFs = (Array.isArray(gfs) ? gfs : []);
293
+ this.pendingGFs = (Array.isArray(pendingGfs) ? pendingGfs : []);
294
+ this.pendingExts = (Array.isArray(pendingExt) ? pendingExt : []);
295
+ const marketplaceAppData = utils_1.fsUtil.readFile(this.marketplaceAppMapperPath);
296
+ this.installedExtensions = (marketplaceAppData === null || marketplaceAppData === void 0 ? void 0 : marketplaceAppData.extension_uid) || { extension_uid: {} };
297
+ this.taxonomies = utils_1.fsUtil.readFile(this.taxonomiesPath);
298
+ cli_utilities_1.log.debug(`Analysis complete: ${(_a = this.cTs) === null || _a === void 0 ? void 0 : _a.length} content types, ${(_b = this.gFs) === null || _b === void 0 ? void 0 : _b.length} global fields, ${(_c = this.pendingGFs) === null || _c === void 0 ? void 0 : _c.length} pending GFs, ${(_d = Object.keys(this.installedExtensions || {})) === null || _d === void 0 ? void 0 : _d.length} extensions, ${(_e = Object.keys(this.taxonomies || {})) === null || _e === void 0 ? void 0 : _e.length} taxonomies`, this.importConfig.context);
299
+ }
300
+ initializeProgress() {
301
+ const progress = this.createNestedProgress(this.currentModuleName);
302
+ if (this.cTs.length) {
303
+ progress.addProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_CREATE, this.cTs.length);
304
+ progress.addProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_UPDATE, this.cTs.length);
305
+ }
306
+ if (this.pendingGFs.length) {
307
+ progress.addProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_GF_UPDATE, this.pendingGFs.length);
308
+ }
309
+ if (this.pendingExts.length) {
310
+ progress.addProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_EXT_UPDATE, this.pendingExts.length);
311
+ }
312
+ return progress;
313
+ }
314
+ async handlePendingGlobalFields(progress) {
315
+ progress
316
+ .startProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_GF_UPDATE)
317
+ .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.CONTENT_TYPES_GF_UPDATE].UPDATING, utils_1.PROCESS_NAMES.CONTENT_TYPES_GF_UPDATE);
318
+ cli_utilities_1.log.info('Starting pending global fields update process', this.importConfig.context);
319
+ await this.updatePendingGFs();
320
+ progress.completeProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_GF_UPDATE, true);
321
+ }
322
+ async handleContentTypesCreation(progress) {
323
+ var _a;
324
+ progress
325
+ .startProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_CREATE)
326
+ .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.CONTENT_TYPES_CREATE].CREATING, utils_1.PROCESS_NAMES.CONTENT_TYPES_CREATE);
327
+ cli_utilities_1.log.info('Starting content types seeding process', this.importConfig.context);
328
+ await this.seedCTs();
329
+ if ((_a = this.createdCTs) === null || _a === void 0 ? void 0 : _a.length) {
330
+ utils_1.fsUtil.writeFile(this.cTsSuccessPath, this.createdCTs);
331
+ cli_utilities_1.log.debug(`Written ${this.createdCTs.length} successful content types to file`, this.importConfig.context);
332
+ }
333
+ progress.completeProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_CREATE, true);
334
+ }
335
+ async handleContentTypesUpdate(progress) {
336
+ progress
337
+ .startProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_UPDATE)
338
+ .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.CONTENT_TYPES_UPDATE].UPDATING, utils_1.PROCESS_NAMES.CONTENT_TYPES_UPDATE);
339
+ cli_utilities_1.log.info('Starting Update process', this.importConfig.context);
340
+ await this.updateCTs();
341
+ progress.completeProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_UPDATE, true);
342
+ }
343
+ async handlePendingExtensions(progress) {
344
+ progress
345
+ .startProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_EXT_UPDATE)
346
+ .updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.CONTENT_TYPES_EXT_UPDATE].UPDATING, utils_1.PROCESS_NAMES.CONTENT_TYPES_EXT_UPDATE);
347
+ cli_utilities_1.log.info('Starting pending extensions update process', this.importConfig.context);
348
+ await this.updatePendingExtensions();
349
+ progress.completeProcess(utils_1.PROCESS_NAMES.CONTENT_TYPES_EXT_UPDATE, true);
350
+ if (this.isExtensionsUpdate) {
351
+ cli_utilities_1.log.success('Successfully updated the extensions.', this.importConfig.context);
352
+ }
353
+ }
290
354
  }
291
355
  exports.default = ContentTypesImport;
@@ -28,10 +28,14 @@ export default class ImportCustomRoles extends BaseClass {
28
28
  getLocalesUidMap(): Promise<void>;
29
29
  importCustomRoles(): Promise<void>;
30
30
  /**
31
- * @method serializeWebhooks
31
+ * @method serializeCustomRoles
32
32
  * @param {ApiOptions} apiOptions ApiOptions
33
33
  * @returns {ApiOptions} ApiOptions
34
34
  */
35
- serializeWebhooks(apiOptions: ApiOptions): ApiOptions;
35
+ serializeCustomRoles(apiOptions: ApiOptions): ApiOptions;
36
36
  getTransformUidsFactory: (rule: Record<string, any>) => Record<string, any>;
37
+ private analyzeCustomRoles;
38
+ private prepareForImport;
39
+ private loadJsonFileIfExists;
40
+ private handleImportResults;
37
41
  }
@@ -46,7 +46,8 @@ class ImportCustomRoles extends base_class_1.default {
46
46
  }
47
47
  return rule;
48
48
  };
49
- this.importConfig.context.module = 'custom-roles';
49
+ this.importConfig.context.module = utils_1.MODULE_CONTEXTS.CUSTOM_ROLES;
50
+ this.currentModuleName = utils_1.MODULE_NAMES[utils_1.MODULE_CONTEXTS.CUSTOM_ROLES];
50
51
  this.customRolesConfig = importConfig.modules.customRoles;
51
52
  this.customRolesMapperPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'custom-roles');
52
53
  this.customRolesFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.customRolesConfig.dirName);
@@ -69,69 +70,27 @@ class ImportCustomRoles extends base_class_1.default {
69
70
  * @returns {Promise<void>} Promise<void>
70
71
  */
71
72
  async start() {
72
- var _a, _b, _c;
73
- cli_utilities_1.log.debug('Checking for custom roles folder existence', this.importConfig.context);
74
- //Step1 check folder exists or not
75
- if (utils_1.fileHelper.fileExistsSync(this.customRolesFolderPath)) {
76
- cli_utilities_1.log.debug(`Found custom roles folder: ${this.customRolesFolderPath}`, this.importConfig.context);
77
- this.customRoles = utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesFolderPath, this.customRolesConfig.fileName), true);
78
- this.customRolesLocales = utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesFolderPath, this.customRolesConfig.customRolesLocalesFileName), true);
79
- }
80
- else {
81
- cli_utilities_1.log.info(`No custom-rules are found - '${this.customRolesFolderPath}'`, this.importConfig.context);
82
- return;
83
- }
84
- //create webhooks in mapper directory
85
- cli_utilities_1.log.debug('Creating custom roles mapper directory', this.importConfig.context);
86
- await utils_1.fsUtil.makeDirectory(this.customRolesMapperPath);
87
- cli_utilities_1.log.debug('Loading existing custom roles UID data', this.importConfig.context);
88
- this.customRolesUidMapper = utils_1.fileHelper.fileExistsSync(this.customRolesUidMapperPath)
89
- ? utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesUidMapperPath), true) || {}
90
- : {};
91
- cli_utilities_1.log.debug('Loading environments UID data', this.importConfig.context);
92
- this.environmentsUidMap = utils_1.fileHelper.fileExistsSync(this.envUidMapperFolderPath)
93
- ? utils_1.fsUtil.readFile((0, node_path_1.join)(this.envUidMapperFolderPath, 'uid-mapping.json'), true) || {}
94
- : {};
95
- cli_utilities_1.log.debug('Loading entries UID data', this.importConfig.context);
96
- this.entriesUidMap = utils_1.fileHelper.fileExistsSync(this.entriesUidMapperFolderPath)
97
- ? utils_1.fsUtil.readFile((0, node_path_1.join)(this.entriesUidMapperFolderPath, 'uid-mapping.json'), true) || {}
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
- }
120
- //source and target stack locale map
121
- cli_utilities_1.log.debug('Getting locales UID mapping', this.importConfig.context);
122
- await this.getLocalesUidMap();
123
- cli_utilities_1.log.debug('Starting custom roles import', this.importConfig.context);
124
- await this.importCustomRoles();
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) {
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);
73
+ try {
74
+ cli_utilities_1.log.debug('Starting custom roles import process...', this.importConfig.context);
75
+ const [customRolesCount] = await this.analyzeCustomRoles();
76
+ if (customRolesCount === 0) {
77
+ cli_utilities_1.log.info(`No custom-rules are found - '${this.customRolesFolderPath}'`, this.importConfig.context);
78
+ return;
79
+ }
80
+ const progress = this.createSimpleProgress(this.currentModuleName, customRolesCount);
81
+ await this.prepareForImport();
82
+ progress.updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.CUSTOM_ROLES_BUILD_MAPPINGS].BUILDING);
83
+ await this.getLocalesUidMap();
84
+ progress.updateStatus(utils_1.PROCESS_STATUS[utils_1.PROCESS_NAMES.CUSTOM_ROLES_IMPORT].IMPORTING);
85
+ await this.importCustomRoles();
86
+ this.handleImportResults();
87
+ this.completeProgress(true);
88
+ cli_utilities_1.log.success('Custom roles have been imported successfully!', this.importConfig.context);
129
89
  }
130
- if ((_c = this.failedCustomRoles) === null || _c === void 0 ? void 0 : _c.length) {
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);
90
+ catch (error) {
91
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Custom roles import failed');
92
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.importConfig.context));
133
93
  }
134
- cli_utilities_1.log.success('Custom roles have been imported successfully!', this.importConfig.context);
135
94
  }
136
95
  async getLocalesUidMap() {
137
96
  cli_utilities_1.log.debug('Fetching target stack locales', this.importConfig.context);
@@ -176,31 +135,35 @@ class ImportCustomRoles extends base_class_1.default {
176
135
  const apiContent = (0, values_1.default)(this.customRoles);
177
136
  cli_utilities_1.log.debug(`Importing ${apiContent.length} custom roles`, this.importConfig.context);
178
137
  const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
138
+ var _a;
179
139
  this.createdCustomRoles.push(response);
180
140
  this.customRolesUidMapper[uid] = response.uid;
141
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `custom role: ${name}`, `custom role: ${name || uid}`, utils_1.PROCESS_NAMES.CUSTOM_ROLES_IMPORT);
181
142
  cli_utilities_1.log.success(`custom-role '${name}' imported successfully`, this.importConfig.context);
182
143
  cli_utilities_1.log.debug(`Custom role import completed: ${name} (${uid})`, this.importConfig.context);
183
144
  utils_1.fsUtil.writeFile(this.customRolesUidMapperPath, this.customRolesUidMapper);
184
145
  };
185
146
  const onReject = ({ error, apiData }) => {
186
- var _a;
147
+ var _a, _b, _c;
187
148
  const err = (error === null || error === void 0 ? void 0 : error.message) ? JSON.parse(error.message) : error;
188
149
  const { name } = apiData;
189
150
  cli_utilities_1.log.debug(`Custom role '${name}' import failed`, this.importConfig.context);
190
151
  if ((_a = err === null || err === void 0 ? void 0 : err.errors) === null || _a === void 0 ? void 0 : _a.name) {
152
+ (_b = this.progressManager) === null || _b === void 0 ? void 0 : _b.tick(true, `custom role: ${name}`, `custom role: ${name} (already exists)`, utils_1.PROCESS_NAMES.CUSTOM_ROLES_IMPORT);
191
153
  cli_utilities_1.log.info(`custom-role '${name}' already exists`, this.importConfig.context);
192
154
  }
193
155
  else {
194
156
  this.failedCustomRoles.push(apiData);
157
+ (_c = this.progressManager) === null || _c === void 0 ? void 0 : _c.tick(false, `custom role: ${name}`, (error === null || error === void 0 ? void 0 : error.message) || 'Failed to import custom role', utils_1.PROCESS_NAMES.CUSTOM_ROLES_IMPORT);
195
158
  (0, cli_utilities_1.handleAndLogError)(error, Object.assign(Object.assign({}, this.importConfig.context), { name }), `custom-role '${name}' failed to be import`);
196
159
  }
197
160
  };
198
- cli_utilities_1.log.debug(`Using concurrency limit: ${this.importConfig.fetchConcurrency || 1}`, this.importConfig.context);
161
+ cli_utilities_1.log.debug(`Using concurrency limit: ${this.importConfig.fetchConcurrency || 2}`, this.importConfig.context);
199
162
  await this.makeConcurrentCall({
200
163
  apiContent,
201
164
  processName: 'create custom role',
202
165
  apiParams: {
203
- serializeData: this.serializeWebhooks.bind(this),
166
+ serializeData: this.serializeCustomRoles.bind(this),
204
167
  reject: onReject.bind(this),
205
168
  resolve: onSuccess.bind(this),
206
169
  entity: 'create-custom-role',
@@ -211,22 +174,25 @@ class ImportCustomRoles extends base_class_1.default {
211
174
  cli_utilities_1.log.debug('Custom roles import process completed', this.importConfig.context);
212
175
  }
213
176
  /**
214
- * @method serializeWebhooks
177
+ * @method serializeCustomRoles
215
178
  * @param {ApiOptions} apiOptions ApiOptions
216
179
  * @returns {ApiOptions} ApiOptions
217
180
  */
218
- serializeWebhooks(apiOptions) {
219
- var _a;
181
+ serializeCustomRoles(apiOptions) {
182
+ var _a, _b;
220
183
  const { apiData: customRole } = apiOptions;
221
184
  cli_utilities_1.log.debug(`Serializing custom role: ${customRole.name} (${customRole.uid})`, this.importConfig.context);
222
185
  if (this.customRolesUidMapper.hasOwnProperty(customRole.uid)) {
223
186
  cli_utilities_1.log.info(`custom-role '${customRole.name}' already exists. Skipping it to avoid duplicates!`, this.importConfig.context);
224
187
  cli_utilities_1.log.debug(`Skipping custom role serialization for: ${customRole.uid}`, this.importConfig.context);
188
+ // Still tick progress for skipped custom roles
189
+ (_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(true, `custom role: ${customRole.name} (skipped - already exists)`, utils_1.PROCESS_NAMES.CUSTOM_ROLES_IMPORT);
225
190
  apiOptions.entity = undefined;
226
191
  }
227
192
  else {
193
+ cli_utilities_1.log.debug(`Processing custom role: ${customRole.name}`, this.importConfig.context);
228
194
  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);
195
+ cli_utilities_1.log.debug(`Processing ${((_b = customRole.rules) === null || _b === void 0 ? void 0 : _b.length) || 0} rules for custom role: ${customRole.name}`, this.importConfig.context);
230
196
  (0, lodash_1.forEach)(customRole.rules, (rule) => {
231
197
  rule = this.getTransformUidsFactory(rule);
232
198
  // rules.branch is required to create custom roles.
@@ -248,5 +214,50 @@ class ImportCustomRoles extends base_class_1.default {
248
214
  }
249
215
  return apiOptions;
250
216
  }
217
+ async analyzeCustomRoles() {
218
+ return this.withLoadingSpinner('CUSTOM ROLES: Analyzing import data...', async () => {
219
+ cli_utilities_1.log.debug('Checking for custom roles folder existence', this.importConfig.context);
220
+ if (!utils_1.fileHelper.fileExistsSync(this.customRolesFolderPath)) {
221
+ cli_utilities_1.log.info(`No custom-rules are found - '${this.customRolesFolderPath}'`, this.importConfig.context);
222
+ return [0];
223
+ }
224
+ cli_utilities_1.log.debug(`Found custom roles folder: ${this.customRolesFolderPath}`, this.importConfig.context);
225
+ this.customRoles = utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesFolderPath, this.customRolesConfig.fileName), true);
226
+ this.customRolesLocales = utils_1.fsUtil.readFile((0, node_path_1.join)(this.customRolesFolderPath, this.customRolesConfig.customRolesLocalesFileName), true);
227
+ const count = Object.keys(this.customRoles || {}).length;
228
+ cli_utilities_1.log.debug(`Loaded ${count} custom roles from file`, this.importConfig.context);
229
+ return [count];
230
+ });
231
+ }
232
+ async prepareForImport() {
233
+ cli_utilities_1.log.debug('Creating custom roles mapper directory', this.importConfig.context);
234
+ await utils_1.fsUtil.makeDirectory(this.customRolesMapperPath);
235
+ this.customRolesUidMapper = this.loadJsonFileIfExists(this.customRolesUidMapperPath, 'custom roles');
236
+ this.environmentsUidMap = this.loadJsonFileIfExists((0, node_path_1.join)(this.envUidMapperFolderPath, 'uid-mapping.json'), 'environments');
237
+ this.entriesUidMap = this.loadJsonFileIfExists((0, node_path_1.join)(this.entriesUidMapperFolderPath, 'uid-mapping.json'), 'entries');
238
+ }
239
+ loadJsonFileIfExists(path, label) {
240
+ if (utils_1.fileHelper.fileExistsSync(path)) {
241
+ const data = utils_1.fsUtil.readFile(path, true);
242
+ const count = Object.keys(data || {}).length;
243
+ cli_utilities_1.log.debug(`Loaded ${label}: ${count} items`, this.importConfig.context);
244
+ return data || {};
245
+ }
246
+ else {
247
+ cli_utilities_1.log.debug(`No ${label} UID data found`, this.importConfig.context);
248
+ return {};
249
+ }
250
+ }
251
+ handleImportResults() {
252
+ var _a, _b;
253
+ if ((_a = this.createdCustomRoles) === null || _a === void 0 ? void 0 : _a.length) {
254
+ utils_1.fsUtil.writeFile(this.createdCustomRolesPath, this.createdCustomRoles);
255
+ cli_utilities_1.log.debug(`Written ${this.createdCustomRoles.length} successful custom roles to file`, this.importConfig.context);
256
+ }
257
+ if ((_b = this.failedCustomRoles) === null || _b === void 0 ? void 0 : _b.length) {
258
+ utils_1.fsUtil.writeFile(this.customRolesFailsPath, this.failedCustomRoles);
259
+ cli_utilities_1.log.debug(`Written ${this.failedCustomRoles.length} failed custom roles to file`, this.importConfig.context);
260
+ }
261
+ }
251
262
  }
252
263
  exports.default = ImportCustomRoles;
@@ -40,6 +40,13 @@ export default class EntriesImport extends BaseClass {
40
40
  }>;
41
41
  constructor({ importConfig, stackAPIClient }: ModuleClassParams);
42
42
  start(): Promise<any>;
43
+ private analyzeEntryData;
44
+ private initializeProgress;
45
+ private processEntryCreation;
46
+ private processEntryReplacement;
47
+ private processEntryReferenceUpdates;
48
+ private processEntryPublishing;
49
+ private processCleanup;
43
50
  /**
44
51
  * The function `createEntryDataForVariantEntry` writes the `entriesForVariant` data to a JSON file
45
52
  * named `data-for-variant-entry.json`.