@contentstack/cli-variants 1.3.2 → 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 (55) hide show
  1. package/lib/export/attributes.d.ts +2 -2
  2. package/lib/export/attributes.js +51 -23
  3. package/lib/export/audiences.d.ts +2 -2
  4. package/lib/export/audiences.js +50 -24
  5. package/lib/export/events.d.ts +2 -2
  6. package/lib/export/events.js +52 -24
  7. package/lib/export/experiences.js +87 -54
  8. package/lib/export/projects.d.ts +3 -2
  9. package/lib/export/projects.js +55 -63
  10. package/lib/export/variant-entries.d.ts +19 -0
  11. package/lib/export/variant-entries.js +76 -1
  12. package/lib/import/attribute.d.ts +2 -0
  13. package/lib/import/attribute.js +83 -37
  14. package/lib/import/audiences.d.ts +2 -0
  15. package/lib/import/audiences.js +85 -41
  16. package/lib/import/events.d.ts +3 -1
  17. package/lib/import/events.js +86 -30
  18. package/lib/import/experiences.d.ts +2 -0
  19. package/lib/import/experiences.js +93 -39
  20. package/lib/import/project.d.ts +2 -0
  21. package/lib/import/project.js +81 -22
  22. package/lib/import/variant-entries.d.ts +10 -0
  23. package/lib/import/variant-entries.js +139 -53
  24. package/lib/index.d.ts +1 -0
  25. package/lib/index.js +1 -0
  26. package/lib/types/export-config.d.ts +0 -2
  27. package/lib/types/import-config.d.ts +0 -1
  28. package/lib/types/utils.d.ts +1 -1
  29. package/lib/utils/constants.d.ts +91 -0
  30. package/lib/utils/constants.js +93 -0
  31. package/lib/utils/personalization-api-adapter.d.ts +34 -1
  32. package/lib/utils/personalization-api-adapter.js +180 -53
  33. package/lib/utils/variant-api-adapter.d.ts +28 -1
  34. package/lib/utils/variant-api-adapter.js +89 -32
  35. package/package.json +2 -2
  36. package/src/export/attributes.ts +84 -34
  37. package/src/export/audiences.ts +87 -41
  38. package/src/export/events.ts +84 -41
  39. package/src/export/experiences.ts +155 -83
  40. package/src/export/projects.ts +71 -39
  41. package/src/export/variant-entries.ts +136 -12
  42. package/src/import/attribute.ts +105 -49
  43. package/src/import/audiences.ts +110 -54
  44. package/src/import/events.ts +104 -41
  45. package/src/import/experiences.ts +140 -62
  46. package/src/import/project.ts +108 -38
  47. package/src/import/variant-entries.ts +188 -75
  48. package/src/index.ts +2 -1
  49. package/src/types/export-config.ts +0 -2
  50. package/src/types/import-config.ts +0 -1
  51. package/src/types/utils.ts +1 -1
  52. package/src/utils/constants.ts +98 -0
  53. package/src/utils/personalization-api-adapter.ts +212 -76
  54. package/src/utils/variant-api-adapter.ts +137 -50
  55. package/tsconfig.json +1 -1
@@ -13,6 +13,7 @@ const path_1 = require("path");
13
13
  const fs_1 = require("fs");
14
14
  const cli_utilities_1 = require("@contentstack/cli-utilities");
15
15
  const utils_1 = require("../utils");
16
+ const constants_1 = require("../utils/constants");
16
17
  class Audiences extends utils_1.PersonalizationAdapter {
17
18
  constructor(config) {
18
19
  const conf = {
@@ -30,7 +31,8 @@ class Audiences extends utils_1.PersonalizationAdapter {
30
31
  this.audiencesUidMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.audienceMapperDirPath), 'uid-mapping.json');
31
32
  this.attributesMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.mapperDirPath), (0, cli_utilities_1.sanitizePath)(this.attributeConfig.dirName), 'uid-mapping.json');
32
33
  this.audiencesUidMapper = {};
33
- this.config.context.module = 'audiences';
34
+ this.config.context.module = constants_1.MODULE_CONTEXTS.AUDIENCES;
35
+ this.audiences = [];
34
36
  }
35
37
  /**
36
38
  * The function asynchronously imports audiences from a JSON file and creates them in the system.
@@ -38,54 +40,96 @@ class Audiences extends utils_1.PersonalizationAdapter {
38
40
  import() {
39
41
  return __awaiter(this, void 0, void 0, function* () {
40
42
  var _a, _b;
41
- yield this.init();
42
- yield utils_1.fsUtil.makeDirectory(this.audienceMapperDirPath);
43
- cli_utilities_1.log.debug(`Created mapper directory: ${this.audienceMapperDirPath}`, this.config.context);
44
- const { dirName, fileName } = this.audienceConfig;
45
- const audiencesPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(dirName), (0, cli_utilities_1.sanitizePath)(fileName));
46
- cli_utilities_1.log.debug(`Checking for audiences file: ${audiencesPath}`, this.config.context);
47
- if ((0, fs_1.existsSync)(audiencesPath)) {
48
- try {
49
- const audiences = utils_1.fsUtil.readFile(audiencesPath, true);
50
- cli_utilities_1.log.info(`Found ${audiences.length} audiences to import`, this.config.context);
51
- const attributesUid = utils_1.fsUtil.readFile(this.attributesMapperPath, true) || {};
52
- cli_utilities_1.log.debug(`Loaded ${Object.keys(attributesUid).length} attribute mappings for audience processing`, this.config.context);
53
- for (const audience of audiences) {
54
- let { name, definition, description, uid } = audience;
55
- cli_utilities_1.log.debug(`Processing audience: ${name} (${uid})`, this.config.context);
56
- try {
57
- //check whether reference attributes exists or not
58
- if ((_a = definition.rules) === null || _a === void 0 ? void 0 : _a.length) {
59
- cli_utilities_1.log.debug(`Processing ${definition.rules.length} definition rules for audience: ${name}`, this.config.context);
60
- definition.rules = (0, utils_1.lookUpAttributes)(definition.rules, attributesUid);
61
- cli_utilities_1.log.debug(`Processed definition rules, remaining rules: ${definition.rules.length}`, this.config.context);
62
- }
63
- else {
64
- cli_utilities_1.log.debug(`No definition rules found for audience: ${name}`, this.config.context);
65
- }
66
- cli_utilities_1.log.debug(`Creating audience: ${name}`, this.config.context);
67
- const audienceRes = yield this.createAudience({ definition, name, description });
68
- //map old audience uid to new audience uid
69
- //mapper file is used to check whether audience created or not before creating experience
70
- this.audiencesUidMapper[uid] = (_b = audienceRes === null || audienceRes === void 0 ? void 0 : audienceRes.uid) !== null && _b !== void 0 ? _b : '';
71
- cli_utilities_1.log.debug(`Created audience: ${uid} -> ${audienceRes === null || audienceRes === void 0 ? void 0 : audienceRes.uid}`, this.config.context);
43
+ try {
44
+ cli_utilities_1.log.debug('Starting audiences import...', this.config.context);
45
+ const [canImport, audiencesCount] = yield this.analyzeAudiences();
46
+ if (!canImport) {
47
+ cli_utilities_1.log.info('No audiences found to import', this.config.context);
48
+ // Still need to mark as complete for parent progress
49
+ if (this.parentProgressManager) {
50
+ this.parentProgressManager.tick(true, 'audiences module (no data)', null, constants_1.PROCESS_NAMES.AUDIENCES);
51
+ }
52
+ return;
53
+ }
54
+ // Don't create own progress manager if we have a parent
55
+ let progress;
56
+ if (this.parentProgressManager) {
57
+ progress = this.parentProgressManager;
58
+ cli_utilities_1.log.debug('Using parent progress manager for audiences import', this.config.context);
59
+ this.parentProgressManager.updateProcessTotal(constants_1.PROCESS_NAMES.AUDIENCES, audiencesCount);
60
+ }
61
+ else {
62
+ progress = this.createSimpleProgress(constants_1.PROCESS_NAMES.AUDIENCES, audiencesCount);
63
+ cli_utilities_1.log.debug('Created standalone progress manager for audiences import', this.config.context);
64
+ }
65
+ yield this.init();
66
+ yield utils_1.fsUtil.makeDirectory(this.audienceMapperDirPath);
67
+ cli_utilities_1.log.debug(`Created mapper directory: ${this.audienceMapperDirPath}`, this.config.context);
68
+ const attributesUid = utils_1.fsUtil.readFile(this.attributesMapperPath, true) || {};
69
+ cli_utilities_1.log.debug(`Loaded ${Object.keys(attributesUid).length} attribute mappings for audience processing`, this.config.context);
70
+ for (const audience of this.audiences) {
71
+ let { name, definition, description, uid } = audience;
72
+ if (!this.parentProgressManager) {
73
+ progress.updateStatus(constants_1.IMPORT_PROCESS_STATUS[constants_1.PROCESS_NAMES.AUDIENCES].CREATING);
74
+ }
75
+ cli_utilities_1.log.debug(`Processing audience: ${name} (${uid})`, this.config.context);
76
+ try {
77
+ //check whether reference attributes exists or not
78
+ if ((_a = definition.rules) === null || _a === void 0 ? void 0 : _a.length) {
79
+ cli_utilities_1.log.debug(`Processing ${definition.rules.length} definition rules for audience: ${name}`, this.config.context);
80
+ definition.rules = (0, utils_1.lookUpAttributes)(definition.rules, attributesUid);
81
+ cli_utilities_1.log.debug(`Processed definition rules, remaining rules: ${definition.rules.length}`, this.config.context);
72
82
  }
73
- catch (error) {
74
- (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create audience: ${name} (${uid})`);
83
+ else {
84
+ cli_utilities_1.log.debug(`No definition rules found for audience: ${name}`, this.config.context);
75
85
  }
86
+ cli_utilities_1.log.debug(`Creating audience: ${name}`, this.config.context);
87
+ const audienceRes = yield this.createAudience({ definition, name, description });
88
+ //map old audience uid to new audience uid
89
+ //mapper file is used to check whether audience created or not before creating experience
90
+ this.audiencesUidMapper[uid] = (_b = audienceRes === null || audienceRes === void 0 ? void 0 : audienceRes.uid) !== null && _b !== void 0 ? _b : '';
91
+ this.updateProgress(true, `audience: ${name}`, undefined, constants_1.PROCESS_NAMES.AUDIENCES);
92
+ cli_utilities_1.log.debug(`Created audience: ${uid} -> ${audienceRes === null || audienceRes === void 0 ? void 0 : audienceRes.uid}`, this.config.context);
93
+ }
94
+ catch (error) {
95
+ this.updateProgress(false, `audience: ${name}`, error === null || error === void 0 ? void 0 : error.message, constants_1.PROCESS_NAMES.AUDIENCES);
96
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create audience: ${name} (${uid})`);
76
97
  }
77
- utils_1.fsUtil.writeFile(this.audiencesUidMapperPath, this.audiencesUidMapper);
78
- cli_utilities_1.log.debug(`Saved ${Object.keys(this.audiencesUidMapper).length} audience mappings to: ${this.audiencesUidMapperPath}`, this.config.context);
79
- cli_utilities_1.log.success('Audiences imported successfully', this.config.context);
80
98
  }
81
- catch (error) {
82
- (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
99
+ utils_1.fsUtil.writeFile(this.audiencesUidMapperPath, this.audiencesUidMapper);
100
+ cli_utilities_1.log.debug(`Saved ${Object.keys(this.audiencesUidMapper).length} audience mappings`, this.config.context);
101
+ // Only complete progress if we own the progress manager (no parent)
102
+ if (!this.parentProgressManager) {
103
+ this.completeProgress(true);
83
104
  }
105
+ cli_utilities_1.log.success(`Audiences imported successfully! Total audiences: ${audiencesCount}`, this.config.context);
84
106
  }
85
- else {
86
- cli_utilities_1.log.warn(`Audiences file not found: ${audiencesPath}`, this.config.context);
107
+ catch (error) {
108
+ if (!this.parentProgressManager) {
109
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Audiences import failed');
110
+ }
111
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
112
+ throw error;
87
113
  }
88
114
  });
89
115
  }
116
+ analyzeAudiences() {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ return this.withLoadingSpinner('AUDIENCES: Analyzing import data...', () => __awaiter(this, void 0, void 0, function* () {
119
+ var _a;
120
+ const { dirName, fileName } = this.audienceConfig;
121
+ const audiencesPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(dirName), (0, cli_utilities_1.sanitizePath)(fileName));
122
+ cli_utilities_1.log.debug(`Checking for audiences file: ${audiencesPath}`, this.config.context);
123
+ if (!(0, fs_1.existsSync)(audiencesPath)) {
124
+ cli_utilities_1.log.warn(`Audiences file not found: ${audiencesPath}`, this.config.context);
125
+ return [false, 0];
126
+ }
127
+ this.audiences = utils_1.fsUtil.readFile(audiencesPath, true);
128
+ const audiencesCount = ((_a = this.audiences) === null || _a === void 0 ? void 0 : _a.length) || 0;
129
+ cli_utilities_1.log.debug(`Found ${audiencesCount} audiences to import`, this.config.context);
130
+ return [audiencesCount > 0, audiencesCount];
131
+ }));
132
+ });
133
+ }
90
134
  }
91
135
  exports.default = Audiences;
@@ -7,10 +7,12 @@ export default class Events extends PersonalizationAdapter<ImportConfig> {
7
7
  private eventsUidMapperPath;
8
8
  private eventsUidMapper;
9
9
  private personalizeConfig;
10
- private eventsConfig;
10
+ private eventConfig;
11
+ private events;
11
12
  constructor(config: ImportConfig);
12
13
  /**
13
14
  * The function asynchronously imports events from a JSON file and creates them in the system.
14
15
  */
15
16
  import(): Promise<void>;
17
+ private analyzeEvents;
16
18
  }
@@ -13,6 +13,7 @@ const path_1 = require("path");
13
13
  const fs_1 = require("fs");
14
14
  const cli_utilities_1 = require("@contentstack/cli-utilities");
15
15
  const utils_1 = require("../utils");
16
+ const constants_1 = require("../utils/constants");
16
17
  class Events extends utils_1.PersonalizationAdapter {
17
18
  constructor(config) {
18
19
  const conf = {
@@ -23,12 +24,13 @@ class Events extends utils_1.PersonalizationAdapter {
23
24
  super(Object.assign(config, conf));
24
25
  this.config = config;
25
26
  this.personalizeConfig = this.config.modules.personalize;
26
- this.eventsConfig = this.personalizeConfig.events;
27
+ this.eventConfig = this.personalizeConfig.events;
27
28
  this.mapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName));
28
- this.eventMapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.mapperDirPath), (0, cli_utilities_1.sanitizePath)(this.eventsConfig.dirName));
29
+ this.eventMapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.mapperDirPath), (0, cli_utilities_1.sanitizePath)(this.eventConfig.dirName));
29
30
  this.eventsUidMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.eventMapperDirPath), 'uid-mapping.json');
30
31
  this.eventsUidMapper = {};
31
- this.config.context.module = 'events';
32
+ this.events = [];
33
+ this.config.context.module = constants_1.MODULE_CONTEXTS.EVENTS;
32
34
  }
33
35
  /**
34
36
  * The function asynchronously imports events from a JSON file and creates them in the system.
@@ -36,41 +38,95 @@ class Events extends utils_1.PersonalizationAdapter {
36
38
  import() {
37
39
  return __awaiter(this, void 0, void 0, function* () {
38
40
  var _a;
39
- yield this.init();
40
- yield utils_1.fsUtil.makeDirectory(this.eventMapperDirPath);
41
- cli_utilities_1.log.debug(`Created mapper directory: ${this.eventMapperDirPath}`, this.config.context);
42
- const { dirName, fileName } = this.eventsConfig;
43
- const eventsPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(dirName), (0, cli_utilities_1.sanitizePath)(fileName));
44
- cli_utilities_1.log.debug(`Checking for events file: ${eventsPath}`, this.config.context);
45
- if ((0, fs_1.existsSync)(eventsPath)) {
46
- try {
47
- const events = utils_1.fsUtil.readFile(eventsPath, true);
48
- cli_utilities_1.log.info(`Found ${events.length} events to import`, this.config.context);
49
- for (const event of events) {
50
- const { key, description, uid } = event;
51
- cli_utilities_1.log.debug(`Processing event: ${key} (${uid})`, this.config.context);
52
- try {
53
- cli_utilities_1.log.debug(`Creating event: ${key}`, this.config.context);
54
- const eventsResponse = yield this.createEvents({ key, description });
55
- this.eventsUidMapper[uid] = (_a = eventsResponse === null || eventsResponse === void 0 ? void 0 : eventsResponse.uid) !== null && _a !== void 0 ? _a : '';
56
- cli_utilities_1.log.debug(`Created event: ${uid} -> ${eventsResponse === null || eventsResponse === void 0 ? void 0 : eventsResponse.uid}`, this.config.context);
41
+ try {
42
+ cli_utilities_1.log.debug('Starting events import...', this.config.context);
43
+ const [canImport, eventsCount] = yield this.analyzeEvents();
44
+ if (!canImport) {
45
+ cli_utilities_1.log.info('No events found to import', this.config.context);
46
+ // Still need to mark as complete for parent progress
47
+ if (this.parentProgressManager) {
48
+ this.parentProgressManager.tick(true, 'events module (no data)', null, constants_1.PROCESS_NAMES.EVENTS);
49
+ }
50
+ return;
51
+ }
52
+ // Don't create own progress manager if we have a parent
53
+ let progress;
54
+ if (this.parentProgressManager) {
55
+ progress = this.parentProgressManager;
56
+ cli_utilities_1.log.debug('Using parent progress manager for events import', this.config.context);
57
+ this.parentProgressManager.updateProcessTotal(constants_1.PROCESS_NAMES.EVENTS, eventsCount);
58
+ }
59
+ else {
60
+ progress = this.createSimpleProgress(constants_1.PROCESS_NAMES.EVENTS, eventsCount);
61
+ cli_utilities_1.log.debug('Created standalone progress manager for events import', this.config.context);
62
+ }
63
+ yield this.init();
64
+ yield utils_1.fsUtil.makeDirectory(this.eventMapperDirPath);
65
+ cli_utilities_1.log.debug(`Created mapper directory: ${this.eventMapperDirPath}`, this.config.context);
66
+ cli_utilities_1.log.info(`Processing ${eventsCount} events`, this.config.context);
67
+ for (const event of this.events) {
68
+ const { key, description, uid } = event;
69
+ if (!this.parentProgressManager) {
70
+ progress.updateStatus(constants_1.IMPORT_PROCESS_STATUS[constants_1.PROCESS_NAMES.EVENTS].CREATING);
71
+ }
72
+ cli_utilities_1.log.debug(`Processing event: ${key} (${uid})`, this.config.context);
73
+ try {
74
+ cli_utilities_1.log.debug(`Creating event: ${key}`, this.config.context);
75
+ const eventRes = yield this.createEvents({ key, description });
76
+ this.eventsUidMapper[uid] = (_a = eventRes === null || eventRes === void 0 ? void 0 : eventRes.uid) !== null && _a !== void 0 ? _a : '';
77
+ // For parent progress manager, we don't need to specify process name as it will be handled automatically
78
+ if (this.parentProgressManager) {
79
+ this.updateProgress(true, `event: ${key}`);
57
80
  }
58
- catch (error) {
59
- (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create event: ${key} (${uid})`);
81
+ else {
82
+ this.updateProgress(true, `event: ${key}`, undefined, constants_1.PROCESS_NAMES.EVENTS);
60
83
  }
84
+ cli_utilities_1.log.debug(`Created event: ${uid} -> ${eventRes === null || eventRes === void 0 ? void 0 : eventRes.uid}`, this.config.context);
85
+ }
86
+ catch (error) {
87
+ if (this.parentProgressManager) {
88
+ this.updateProgress(false, `event: ${key}`, error === null || error === void 0 ? void 0 : error.message);
89
+ }
90
+ else {
91
+ this.updateProgress(false, `event: ${key}`, error === null || error === void 0 ? void 0 : error.message, constants_1.PROCESS_NAMES.EVENTS);
92
+ }
93
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create event: ${key} (${uid})`);
61
94
  }
62
- utils_1.fsUtil.writeFile(this.eventsUidMapperPath, this.eventsUidMapper);
63
- cli_utilities_1.log.debug(`Saved ${Object.keys(this.eventsUidMapper).length} event mappings to: ${this.eventsUidMapperPath}`, this.config.context);
64
- cli_utilities_1.log.success('Events imported successfully', this.config.context);
65
95
  }
66
- catch (error) {
67
- (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
96
+ utils_1.fsUtil.writeFile(this.eventsUidMapperPath, this.eventsUidMapper);
97
+ cli_utilities_1.log.debug(`Saved ${Object.keys(this.eventsUidMapper).length} event mappings`, this.config.context);
98
+ // Only complete progress if we own the progress manager (no parent)
99
+ if (!this.parentProgressManager) {
100
+ this.completeProgress(true);
68
101
  }
102
+ cli_utilities_1.log.success(`Events imported successfully! Total events: ${eventsCount} - personalization enabled`, this.config.context);
69
103
  }
70
- else {
71
- cli_utilities_1.log.warn(`Events file not found: ${eventsPath}`, this.config.context);
104
+ catch (error) {
105
+ if (!this.parentProgressManager) {
106
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Events import failed');
107
+ }
108
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
109
+ throw error;
72
110
  }
73
111
  });
74
112
  }
113
+ analyzeEvents() {
114
+ return __awaiter(this, void 0, void 0, function* () {
115
+ return this.withLoadingSpinner('EVENTS: Analyzing import data...', () => __awaiter(this, void 0, void 0, function* () {
116
+ var _a;
117
+ const { dirName, fileName } = this.eventConfig;
118
+ const eventsPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(dirName), (0, cli_utilities_1.sanitizePath)(fileName));
119
+ cli_utilities_1.log.debug(`Checking for events file: ${eventsPath}`, this.config.context);
120
+ if (!(0, fs_1.existsSync)(eventsPath)) {
121
+ cli_utilities_1.log.warn(`Events file not found: ${eventsPath}`, this.config.context);
122
+ return [false, 0];
123
+ }
124
+ this.events = utils_1.fsUtil.readFile(eventsPath, true);
125
+ const eventsCount = ((_a = this.events) === null || _a === void 0 ? void 0 : _a.length) || 0;
126
+ cli_utilities_1.log.debug(`Found ${eventsCount} events to import`, this.config.context);
127
+ return [eventsCount > 0, eventsCount];
128
+ }));
129
+ });
130
+ }
75
131
  }
76
132
  exports.default = Events;
@@ -29,11 +29,13 @@ export default class Experiences extends PersonalizationAdapter<ImportConfig> {
29
29
  private personalizeConfig;
30
30
  private audienceConfig;
31
31
  private experienceConfig;
32
+ private experiences;
32
33
  constructor(config: ImportConfig);
33
34
  /**
34
35
  * The function asynchronously imports experiences from a JSON file and creates them in the system.
35
36
  */
36
37
  import(): Promise<void>;
38
+ private analyzeExperiences;
37
39
  /**
38
40
  * function import experience versions from a JSON file and creates them in the project.
39
41
  */
@@ -29,6 +29,7 @@ const values_1 = __importDefault(require("lodash/values"));
29
29
  const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
30
30
  const cli_utilities_1 = require("@contentstack/cli-utilities");
31
31
  const utils_1 = require("../utils");
32
+ const constants_1 = require("../utils/constants");
32
33
  class Experiences extends utils_1.PersonalizationAdapter {
33
34
  constructor(config) {
34
35
  var _a, _b, _c, _d;
@@ -71,7 +72,8 @@ class Experiences extends utils_1.PersonalizationAdapter {
71
72
  this.createdCTs = [];
72
73
  this.audiencesUid = utils_1.fsUtil.readFile(this.audiencesMapperPath, true) || {};
73
74
  this.eventsUid = utils_1.fsUtil.readFile(this.eventsMapperPath, true) || {};
74
- this.config.context.module = 'experiences';
75
+ this.config.context.module = constants_1.MODULE_CONTEXTS.EXPERIENCES;
76
+ this.experiences = [];
75
77
  }
76
78
  /**
77
79
  * The function asynchronously imports experiences from a JSON file and creates them in the system.
@@ -79,21 +81,41 @@ class Experiences extends utils_1.PersonalizationAdapter {
79
81
  import() {
80
82
  return __awaiter(this, void 0, void 0, function* () {
81
83
  var _a;
82
- yield this.init();
83
- yield utils_1.fsUtil.makeDirectory(this.expMapperDirPath);
84
- cli_utilities_1.log.debug(`Created mapper directory: ${this.expMapperDirPath}`, this.config.context);
85
- if ((0, fs_1.existsSync)(this.experiencesPath)) {
86
- cli_utilities_1.log.debug(`Loading experiences from: ${this.experiencesPath}`, this.config.context);
87
- try {
88
- const experiences = utils_1.fsUtil.readFile(this.experiencesPath, true);
89
- cli_utilities_1.log.info(`Found ${experiences.length} experiences to import`, this.config.context);
90
- for (const experience of experiences) {
91
- const { uid } = experience, restExperienceData = __rest(experience, ["uid"]);
92
- cli_utilities_1.log.debug(`Processing experience: ${uid}`, this.config.context);
93
- //check whether reference audience exists or not that referenced in variations having __type equal to AudienceBasedVariation & targeting
94
- let experienceReqObj = (0, utils_1.lookUpAudiences)(restExperienceData, this.audiencesUid);
95
- //check whether events exists or not that referenced in metrics
96
- experienceReqObj = (0, utils_1.lookUpEvents)(experienceReqObj, this.eventsUid);
84
+ try {
85
+ cli_utilities_1.log.debug('Starting experiences import...', this.config.context);
86
+ const [canImport, experiencesCount] = yield this.analyzeExperiences();
87
+ if (!canImport) {
88
+ cli_utilities_1.log.info('No experiences found to import', this.config.context);
89
+ // Still need to mark as complete for parent progress
90
+ if (this.parentProgressManager) {
91
+ this.parentProgressManager.tick(true, 'experiences module (no data)', null, constants_1.PROCESS_NAMES.EXPERIENCES);
92
+ }
93
+ return;
94
+ }
95
+ // If we have a parent progress manager, use it as a sub-module
96
+ // Otherwise create our own simple progress manager
97
+ let progress;
98
+ if (this.parentProgressManager) {
99
+ progress = this.parentProgressManager;
100
+ cli_utilities_1.log.debug('Using parent progress manager for experiences import', this.config.context);
101
+ this.parentProgressManager.updateProcessTotal(constants_1.PROCESS_NAMES.EXPERIENCES, experiencesCount);
102
+ }
103
+ else {
104
+ progress = this.createSimpleProgress(constants_1.PROCESS_NAMES.EXPERIENCES, experiencesCount);
105
+ cli_utilities_1.log.debug('Created standalone progress manager for experiences import', this.config.context);
106
+ }
107
+ yield this.init();
108
+ yield utils_1.fsUtil.makeDirectory(this.expMapperDirPath);
109
+ cli_utilities_1.log.debug(`Created mapper directory: ${this.expMapperDirPath}`, this.config.context);
110
+ cli_utilities_1.log.info(`Processing ${experiencesCount} experiences for import`, this.config.context);
111
+ for (const experience of this.experiences) {
112
+ const { uid } = experience, restExperienceData = __rest(experience, ["uid"]);
113
+ cli_utilities_1.log.debug(`Processing experience: ${uid}`, this.config.context);
114
+ //check whether reference audience exists or not that referenced in variations having __type equal to AudienceBasedVariation & targeting
115
+ let experienceReqObj = (0, utils_1.lookUpAudiences)(restExperienceData, this.audiencesUid);
116
+ //check whether events exists or not that referenced in metrics
117
+ experienceReqObj = (0, utils_1.lookUpEvents)(experienceReqObj, this.eventsUid);
118
+ try {
97
119
  const expRes = (yield this.createExperience(experienceReqObj));
98
120
  //map old experience uid to new experience uid
99
121
  this.experiencesUidMapper[uid] = (_a = expRes === null || expRes === void 0 ? void 0 : expRes.uid) !== null && _a !== void 0 ? _a : '';
@@ -105,37 +127,69 @@ class Experiences extends utils_1.PersonalizationAdapter {
105
127
  catch (error) {
106
128
  (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to import experience versions for ${expRes.uid}`);
107
129
  }
130
+ this.updateProgress(true, `experience: ${experience.name || uid}`, undefined, constants_1.PROCESS_NAMES.EXPERIENCES);
131
+ cli_utilities_1.log.debug(`Successfully processed experience: ${uid}`, this.config.context);
108
132
  }
109
- utils_1.fsUtil.writeFile(this.experiencesUidMapperPath, this.experiencesUidMapper);
110
- cli_utilities_1.log.success('Experiences created successfully', this.config.context);
111
- cli_utilities_1.log.info('Validating variant and variant group creation', this.config.context);
112
- this.pendingVariantAndVariantGrpForExperience = (0, values_1.default)((0, cloneDeep_1.default)(this.experiencesUidMapper));
113
- const jobRes = yield this.validateVariantGroupAndVariantsCreated();
114
- utils_1.fsUtil.writeFile(this.cmsVariantPath, this.cmsVariants);
115
- utils_1.fsUtil.writeFile(this.cmsVariantGroupPath, this.cmsVariantGroups);
116
- if (jobRes) {
117
- cli_utilities_1.log.success('Variant and variant groups created successfully', this.config.context);
118
- }
119
- else {
120
- cli_utilities_1.log.error('Failed to create variants and variant groups', this.config.context);
121
- this.personalizeConfig.importData = false;
122
- }
123
- if (this.personalizeConfig.importData) {
124
- cli_utilities_1.log.info('Attaching content types to experiences', this.config.context);
125
- yield this.attachCTsInExperience();
126
- cli_utilities_1.log.success('Content types attached to experiences successfully', this.config.context);
133
+ catch (error) {
134
+ this.updateProgress(false, `experience: ${experience.name || uid}`, error === null || error === void 0 ? void 0 : error.message, constants_1.PROCESS_NAMES.EXPERIENCES);
135
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create experience: ${uid}`);
127
136
  }
128
- yield this.createVariantIdMapper();
129
137
  }
130
- catch (error) {
131
- (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
138
+ utils_1.fsUtil.writeFile(this.experiencesUidMapperPath, this.experiencesUidMapper);
139
+ cli_utilities_1.log.success('Experiences created successfully', this.config.context);
140
+ cli_utilities_1.log.info('Validating variant and variant group creation', this.config.context);
141
+ this.pendingVariantAndVariantGrpForExperience = (0, values_1.default)((0, cloneDeep_1.default)(this.experiencesUidMapper));
142
+ const jobRes = yield this.validateVariantGroupAndVariantsCreated();
143
+ utils_1.fsUtil.writeFile(this.cmsVariantPath, this.cmsVariants);
144
+ utils_1.fsUtil.writeFile(this.cmsVariantGroupPath, this.cmsVariantGroups);
145
+ if (jobRes) {
146
+ cli_utilities_1.log.success('Variant and variant groups created successfully', this.config.context);
147
+ }
148
+ else {
149
+ cli_utilities_1.log.error('Failed to create variants and variant groups', this.config.context);
150
+ this.personalizeConfig.importData = false;
132
151
  }
152
+ if (this.personalizeConfig.importData) {
153
+ cli_utilities_1.log.info('Attaching content types to experiences', this.config.context);
154
+ yield this.attachCTsInExperience();
155
+ cli_utilities_1.log.success('Content types attached to experiences successfully', this.config.context);
156
+ }
157
+ yield this.createVariantIdMapper();
158
+ // Only complete progress if we own the progress manager (no parent)
159
+ if (!this.parentProgressManager) {
160
+ this.completeProgress(true);
161
+ }
162
+ cli_utilities_1.log.success(`Experiences imported successfully! Total experiences: ${experiencesCount} - personalization enabled`, this.config.context);
133
163
  }
134
- else {
135
- cli_utilities_1.log.warn(`Experiences file not found: ${this.experiencesPath}`, this.config.context);
164
+ catch (error) {
165
+ if (!this.parentProgressManager) {
166
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Experiences import failed');
167
+ }
168
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
169
+ throw error;
136
170
  }
137
171
  });
138
172
  }
173
+ analyzeExperiences() {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ return this.withLoadingSpinner('EXPERIENCES: Analyzing import data...', () => __awaiter(this, void 0, void 0, function* () {
176
+ var _a;
177
+ cli_utilities_1.log.debug(`Checking for experiences file: ${this.experiencesPath}`, this.config.context);
178
+ if (!(0, fs_1.existsSync)(this.experiencesPath)) {
179
+ cli_utilities_1.log.warn(`Experiences file not found: ${this.experiencesPath}`, this.config.context);
180
+ return [false, 0];
181
+ }
182
+ this.experiences = utils_1.fsUtil.readFile(this.experiencesPath, true);
183
+ const experiencesCount = ((_a = this.experiences) === null || _a === void 0 ? void 0 : _a.length) || 0;
184
+ if (experiencesCount < 1) {
185
+ cli_utilities_1.log.warn('No experiences found in file', this.config.context);
186
+ return [false, 0];
187
+ }
188
+ cli_utilities_1.log.debug(`Found ${experiencesCount} experiences to import`, this.config.context);
189
+ return [true, experiencesCount];
190
+ }));
191
+ });
192
+ }
139
193
  /**
140
194
  * function import experience versions from a JSON file and creates them in the project.
141
195
  */
@@ -3,10 +3,12 @@ import { ImportConfig } from '../types';
3
3
  export default class Project extends PersonalizationAdapter<ImportConfig> {
4
4
  readonly config: ImportConfig;
5
5
  private projectMapperFolderPath;
6
+ private projectsData;
6
7
  constructor(config: ImportConfig);
7
8
  /**
8
9
  * The function asynchronously imports projects data from a file and creates projects based on the
9
10
  * data.
10
11
  */
11
12
  import(): Promise<void>;
13
+ private analyzeProjects;
12
14
  }