@contentstack/cli-variants 1.3.3 → 2.0.0-beta.1

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 +132 -47
  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 +171 -44
  33. package/lib/utils/variant-api-adapter.d.ts +28 -1
  34. package/lib/utils/variant-api-adapter.js +75 -0
  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 +179 -65
  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 +202 -66
  54. package/src/utils/variant-api-adapter.ts +82 -1
  55. package/tsconfig.json +1 -1
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -42,9 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
42
9
  });
43
10
  };
44
11
  Object.defineProperty(exports, "__esModule", { value: true });
45
- const path = __importStar(require("path"));
12
+ const node_path_1 = require("node:path");
46
13
  const cli_utilities_1 = require("@contentstack/cli-utilities");
47
14
  const utils_1 = require("../utils");
15
+ const constants_1 = require("../utils/constants");
48
16
  class ExportProjects extends utils_1.PersonalizationAdapter {
49
17
  constructor(exportConfig) {
50
18
  super({
@@ -54,48 +22,72 @@ class ExportProjects extends utils_1.PersonalizationAdapter {
54
22
  });
55
23
  this.exportConfig = exportConfig;
56
24
  this.personalizeConfig = exportConfig.modules.personalize;
57
- this.projectFolderPath = path.resolve((0, cli_utilities_1.sanitizePath)(exportConfig.data), (0, cli_utilities_1.sanitizePath)(exportConfig.branchName || ''), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), 'projects');
58
- this.exportConfig.context.module = 'projects';
25
+ this.projectsFolderPath = (0, node_path_1.resolve)((0, cli_utilities_1.sanitizePath)(exportConfig.data), (0, cli_utilities_1.sanitizePath)(exportConfig.branchName || ''), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), 'projects');
26
+ this.projectsData = [];
27
+ this.exportConfig.context.module = constants_1.MODULE_CONTEXTS.PROJECTS;
59
28
  }
60
29
  start() {
61
30
  return __awaiter(this, void 0, void 0, function* () {
62
- var _a, _b;
31
+ var _a, _b, _c, _d;
63
32
  try {
64
33
  cli_utilities_1.log.debug('Starting projects export process...', this.exportConfig.context);
65
- cli_utilities_1.log.info(`Starting projects export`, this.exportConfig.context);
66
- cli_utilities_1.log.debug('Initializing personalization adapter...', this.exportConfig.context);
67
- yield this.init();
68
- cli_utilities_1.log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
69
- cli_utilities_1.log.debug(`Creating projects directory at: ${this.projectFolderPath}`, this.exportConfig.context);
70
- yield utils_1.fsUtil.makeDirectory(this.projectFolderPath);
71
- cli_utilities_1.log.debug('Projects directory created successfully', this.exportConfig.context);
72
- cli_utilities_1.log.debug(`Fetching projects for stack API key: ${this.exportConfig.apiKey}`, this.exportConfig.context);
73
- const project = yield this.projects({ connectedStackApiKey: this.exportConfig.apiKey });
74
- cli_utilities_1.log.debug(`Fetched ${(project === null || project === void 0 ? void 0 : project.length) || 0} projects`, this.exportConfig.context);
75
- if (!project || (project === null || project === void 0 ? void 0 : project.length) < 1) {
34
+ cli_utilities_1.log.info('Starting projects export', this.exportConfig.context);
35
+ // Initial setup with loading spinner
36
+ yield this.withLoadingSpinner('PROJECTS: Initializing export and fetching data...', () => __awaiter(this, void 0, void 0, function* () {
37
+ var _a;
38
+ cli_utilities_1.log.debug('Initializing personalization adapter...', this.exportConfig.context);
39
+ yield this.init();
40
+ cli_utilities_1.log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
41
+ cli_utilities_1.log.debug(`Creating projects directory at: ${this.projectsFolderPath}`, this.exportConfig.context);
42
+ yield utils_1.fsUtil.makeDirectory(this.projectsFolderPath);
43
+ cli_utilities_1.log.debug('Projects directory created successfully', this.exportConfig.context);
44
+ cli_utilities_1.log.debug('Fetching projects from personalization API...', this.exportConfig.context);
45
+ // talisman-ignore-line
46
+ this.projectsData = (yield this.projects({ connectedStackApiKey: this.exportConfig.apiKey })) || [];
47
+ cli_utilities_1.log.debug(`Fetched ${((_a = this.projectsData) === null || _a === void 0 ? void 0 : _a.length) || 0} projects`, this.exportConfig.context);
48
+ }));
49
+ if (!((_a = this.projectsData) === null || _a === void 0 ? void 0 : _a.length)) {
76
50
  cli_utilities_1.log.debug('No projects found, disabling personalization', this.exportConfig.context);
77
- cli_utilities_1.log.info(`No Personalize Project connected with the given stack`, this.exportConfig.context);
51
+ cli_utilities_1.log.info('No Personalize Project connected with the given stack', this.exportConfig.context);
78
52
  this.exportConfig.personalizationEnabled = false;
79
53
  return;
80
54
  }
81
- cli_utilities_1.log.debug(`Found ${project.length} projects, enabling personalization`, this.exportConfig.context);
55
+ // Enable personalization and set project config
56
+ cli_utilities_1.log.debug(`Found ${this.projectsData.length} projects, enabling personalization`, this.exportConfig.context);
82
57
  this.exportConfig.personalizationEnabled = true;
83
- this.exportConfig.project_id = (_a = project[0]) === null || _a === void 0 ? void 0 : _a.uid;
84
- cli_utilities_1.log.debug(`Set project ID: ${(_b = project[0]) === null || _b === void 0 ? void 0 : _b.uid}`, this.exportConfig.context);
85
- const projectsFilePath = path.resolve((0, cli_utilities_1.sanitizePath)(this.projectFolderPath), 'projects.json');
86
- cli_utilities_1.log.debug(`Writing projects data to: ${projectsFilePath}`, this.exportConfig.context);
87
- utils_1.fsUtil.writeFile(projectsFilePath, project);
88
- cli_utilities_1.log.debug('Projects export completed successfully', this.exportConfig.context);
89
- cli_utilities_1.log.success(`Projects exported successfully!`, this.exportConfig.context);
90
- }
91
- catch (error) {
92
- if (error !== 'Forbidden') {
93
- cli_utilities_1.log.debug(`Error occurred during projects export: ${error}`, this.exportConfig.context);
94
- cli_utilities_1.log.error('Failed to export projects!', this.exportConfig.context);
58
+ this.exportConfig.project_id = (_b = this.projectsData[0]) === null || _b === void 0 ? void 0 : _b.uid;
59
+ cli_utilities_1.log.debug(`Set project ID: ${(_c = this.projectsData[0]) === null || _c === void 0 ? void 0 : _c.uid}`, this.exportConfig.context);
60
+ let progress;
61
+ if (this.parentProgressManager) {
62
+ progress = this.parentProgressManager;
63
+ this.progressManager = this.parentProgressManager;
64
+ // Parent already has correct count, just update status
65
+ progress.updateStatus(constants_1.EXPORT_PROCESS_STATUS[constants_1.PROCESS_NAMES.PROJECTS].EXPORTING, constants_1.PROCESS_NAMES.PROJECTS);
95
66
  }
96
67
  else {
97
- cli_utilities_1.log.debug('Projects export forbidden, likely due to permissions', this.exportConfig.context);
68
+ progress = this.createNestedProgress(constants_1.PROCESS_NAMES.PROJECTS);
69
+ progress.addProcess(constants_1.PROCESS_NAMES.PROJECTS, (_d = this.projectsData) === null || _d === void 0 ? void 0 : _d.length);
70
+ progress
71
+ .startProcess(constants_1.PROCESS_NAMES.PROJECTS)
72
+ .updateStatus(constants_1.EXPORT_PROCESS_STATUS[constants_1.PROCESS_NAMES.PROJECTS].EXPORTING, constants_1.PROCESS_NAMES.PROJECTS);
98
73
  }
74
+ const projectsFilePath = (0, node_path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.projectsFolderPath), 'projects.json');
75
+ cli_utilities_1.log.debug(`Writing projects to: ${projectsFilePath}`, this.exportConfig.context);
76
+ utils_1.fsUtil.writeFile(projectsFilePath, this.projectsData);
77
+ cli_utilities_1.log.debug('Projects export completed successfully', this.exportConfig.context);
78
+ const processName = constants_1.PROCESS_NAMES.PROJECTS;
79
+ this.updateProgress(true, 'project export', undefined, processName);
80
+ // Complete process only if we're managing our own progress
81
+ if (!this.parentProgressManager) {
82
+ progress.completeProcess(constants_1.PROCESS_NAMES.PROJECTS, true);
83
+ this.completeProgress(true);
84
+ }
85
+ cli_utilities_1.log.success(`Projects exported successfully! Total projects: ${this.projectsData.length} - personalization enabled`, this.exportConfig.context);
86
+ }
87
+ catch (error) {
88
+ cli_utilities_1.log.debug(`Error occurred during projects export: ${error}`, this.exportConfig.context);
89
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Projects export failed');
90
+ (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.exportConfig.context));
99
91
  throw error;
100
92
  }
101
93
  });
@@ -1,10 +1,29 @@
1
+ import { CLIProgressManager } from '@contentstack/cli-utilities';
1
2
  import { ExportConfig } from '../types';
2
3
  import VariantAdapter, { VariantHttpClient } from '../utils/variant-api-adapter';
3
4
  export default class VariantEntries extends VariantAdapter<VariantHttpClient<ExportConfig>> {
4
5
  readonly config: ExportConfig;
5
6
  entriesDirPath: string;
6
7
  variantEntryBasePath: string;
8
+ protected progressManager: CLIProgressManager | null;
9
+ protected parentProgressManager: CLIProgressManager | null;
10
+ progress: any;
11
+ private processInitialized;
12
+ private totalVariantCount;
13
+ private processedVariantCount;
7
14
  constructor(config: ExportConfig);
15
+ /**
16
+ * Set parent progress manager for integration with entries module
17
+ */
18
+ setParentProgressManager(parentProgress: CLIProgressManager): void;
19
+ /**
20
+ * Update progress for a specific item
21
+ */
22
+ protected updateProgress(success: boolean, itemName: string, error?: string, processName?: string): void;
23
+ /**
24
+ * Complete the variant entries export process
25
+ */
26
+ completeExport(): void;
8
27
  /**
9
28
  * This function exports variant entries for a specific content type and locale.
10
29
  * @param options - The `exportVariantEntry` function takes in an `options` object with the following
@@ -45,6 +45,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
45
45
  const fs_1 = require("fs");
46
46
  const path_1 = require("path");
47
47
  const cli_utilities_1 = require("@contentstack/cli-utilities");
48
+ const constants_1 = require("../utils/constants");
48
49
  const variant_api_adapter_1 = __importStar(require("../utils/variant-api-adapter"));
49
50
  class VariantEntries extends variant_api_adapter_1.default {
50
51
  constructor(config) {
@@ -62,11 +63,44 @@ class VariantEntries extends variant_api_adapter_1.default {
62
63
  };
63
64
  super(Object.assign(config, conf));
64
65
  this.config = config;
66
+ this.progressManager = null;
67
+ this.parentProgressManager = null;
68
+ this.processInitialized = false;
69
+ this.totalVariantCount = 0;
70
+ this.processedVariantCount = 0;
65
71
  this.entriesDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.data), (0, cli_utilities_1.sanitizePath)(config.branchName || ''), (0, cli_utilities_1.sanitizePath)(config.modules.entries.dirName));
66
72
  if (this.config && this.config.context) {
67
73
  this.config.context.module = 'variant-entries';
68
74
  }
69
75
  }
76
+ /**
77
+ * Set parent progress manager for integration with entries module
78
+ */
79
+ setParentProgressManager(parentProgress) {
80
+ this.parentProgressManager = parentProgress;
81
+ this.progressManager = parentProgress;
82
+ this.progress = parentProgress;
83
+ }
84
+ /**
85
+ * Update progress for a specific item
86
+ */
87
+ updateProgress(success, itemName, error, processName) {
88
+ if (this.progress) {
89
+ this.progress.tick(success, itemName, error, processName);
90
+ }
91
+ }
92
+ /**
93
+ * Complete the variant entries export process
94
+ */
95
+ completeExport() {
96
+ if (this.processInitialized && this.progress) {
97
+ this.progress.completeProcess(constants_1.PROCESS_NAMES.VARIANT_ENTRIES, true);
98
+ cli_utilities_1.log.success(`Completed export of ${this.totalVariantCount} variant entries across all content types and locales`, this.config.context);
99
+ }
100
+ else if (this.totalVariantCount === 0) {
101
+ cli_utilities_1.log.info(`No variant entries found for export`, this.config.context);
102
+ }
103
+ }
70
104
  /**
71
105
  * This function exports variant entries for a specific content type and locale.
72
106
  * @param options - The `exportVariantEntry` function takes in an `options` object with the following
@@ -81,6 +115,8 @@ class VariantEntries extends variant_api_adapter_1.default {
81
115
  cli_utilities_1.log.debug('Initializing variant instance...', this.config.context);
82
116
  yield this.variantInstance.init();
83
117
  cli_utilities_1.log.debug('Variant instance initialized successfully', this.config.context);
118
+ let localVariantCount = 0; // Track variants found in this specific call
119
+ let processedEntries = 0;
84
120
  for (let index = 0; index < entries.length; index++) {
85
121
  const entry = entries[index];
86
122
  cli_utilities_1.log.debug(`Processing variant entries for entry: ${entry.title} (${entry.uid}) - ${index + 1}/${entries.length}`, this.config.context);
@@ -96,9 +132,28 @@ class VariantEntries extends variant_api_adapter_1.default {
96
132
  createDirIfNotExist: false,
97
133
  });
98
134
  cli_utilities_1.log.debug('Initialized FsUtility for variant entries', this.config.context);
135
+ let entryHasVariants = false;
136
+ let variantCount = 0;
99
137
  const callback = (variantEntries) => {
100
138
  cli_utilities_1.log.debug(`Callback received ${(variantEntries === null || variantEntries === void 0 ? void 0 : variantEntries.length) || 0} variant entries for entry: ${entry.uid}`, this.config.context);
101
139
  if (variantEntries === null || variantEntries === void 0 ? void 0 : variantEntries.length) {
140
+ cli_utilities_1.log.info(`Fetched ${variantEntries.length} variant entries for entry: ${entry.uid}`, this.config.context);
141
+ entryHasVariants = true;
142
+ variantCount = variantEntries.length;
143
+ localVariantCount += variantCount;
144
+ this.totalVariantCount += variantCount;
145
+ // Initialize progress ONLY when we find the first variants globally (lazy initialization)
146
+ if (!this.processInitialized && this.progress) {
147
+ this.progress.addProcess(constants_1.PROCESS_NAMES.VARIANT_ENTRIES, variantCount);
148
+ this.progress.startProcess(constants_1.PROCESS_NAMES.VARIANT_ENTRIES);
149
+ this.processInitialized = true;
150
+ cli_utilities_1.log.debug(`Initialized variant entries progress with first batch of ${variantCount} variants`, this.config.context);
151
+ }
152
+ // Update total as we discover more variants globally
153
+ if (this.processInitialized && this.progress) {
154
+ this.progress.updateProcessTotal(constants_1.PROCESS_NAMES.VARIANT_ENTRIES, this.totalVariantCount);
155
+ cli_utilities_1.log.debug(`Updated progress total to: ${this.totalVariantCount}`, this.config.context);
156
+ }
102
157
  if (!(0, fs_1.existsSync)(variantEntryBasePath)) {
103
158
  cli_utilities_1.log.debug(`Creating directory: ${variantEntryBasePath}`, this.config.context);
104
159
  (0, fs_1.mkdirSync)(variantEntryBasePath, { recursive: true });
@@ -127,13 +182,33 @@ class VariantEntries extends variant_api_adapter_1.default {
127
182
  else {
128
183
  cli_utilities_1.log.debug(`No variant entries directory created for entry: ${entry.uid}`, this.config.context);
129
184
  }
185
+ // After processing this entry, update progress for variants found
186
+ if (entryHasVariants && this.processInitialized) {
187
+ // Tick progress for each variant found in this entry
188
+ for (let i = 0; i < variantCount; i++) {
189
+ this.processedVariantCount++;
190
+ this.updateProgress(true, `Exported variant ${this.processedVariantCount}/${this.totalVariantCount} from ${entry.title || entry.uid}`, undefined, constants_1.PROCESS_NAMES.VARIANT_ENTRIES);
191
+ }
192
+ cli_utilities_1.log.debug(`Processed ${variantCount} variants for entry: ${entry.uid}, total processed: ${this.processedVariantCount}/${this.totalVariantCount}`, this.config.context);
193
+ }
194
+ processedEntries++;
130
195
  }
131
196
  catch (error) {
132
197
  cli_utilities_1.log.debug(`Error occurred while exporting variant entries for entry: ${entry.uid}`, this.config.context);
198
+ // Track progress for failed entry
199
+ if (this.processInitialized) {
200
+ this.updateProgress(false, `Failed to export variants for entry: ${entry.title || entry.uid}`, (error === null || error === void 0 ? void 0 : error.message) || 'Unknown error', constants_1.PROCESS_NAMES.VARIANT_ENTRIES);
201
+ }
133
202
  (0, cli_utilities_1.handleAndLogError)(error, Object.assign({}, this.config.context), `Error exporting variant entries of type '${entry.title} (${entry.uid})' locale '${locale}'`);
134
203
  }
135
204
  }
136
- cli_utilities_1.log.debug(`Completed variant entries export for content type: ${content_type_uid}, locale: ${locale}`, this.config.context);
205
+ if (localVariantCount > 0) {
206
+ cli_utilities_1.log.success(`Exported ${localVariantCount} variant entries across ${processedEntries} entries for ${content_type_uid}/${locale}`, this.config.context);
207
+ }
208
+ else {
209
+ cli_utilities_1.log.info(`No variant entries found for content type: ${content_type_uid}, locale: ${locale}`, this.config.context);
210
+ }
211
+ cli_utilities_1.log.debug(`Completed variant entries export for content type: ${content_type_uid}, locale: ${locale}. Local variants: ${localVariantCount}, Total variants so far: ${this.totalVariantCount}, Processed entries: ${processedEntries}`, this.config.context);
137
212
  });
138
213
  }
139
214
  }
@@ -8,9 +8,11 @@ export default class Attribute extends PersonalizationAdapter<ImportConfig> {
8
8
  private attributesUidMapper;
9
9
  private personalizeConfig;
10
10
  private attributeConfig;
11
+ private attributeData;
11
12
  constructor(config: ImportConfig);
12
13
  /**
13
14
  * The function asynchronously imports attributes from a JSON file and creates them in the system.
14
15
  */
15
16
  import(): Promise<void>;
17
+ private analyzeAttributes;
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 Attribute extends utils_1.PersonalizationAdapter {
17
18
  constructor(config) {
18
19
  const conf = {
@@ -28,7 +29,8 @@ class Attribute extends utils_1.PersonalizationAdapter {
28
29
  this.attrMapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.mapperDirPath), (0, cli_utilities_1.sanitizePath)(this.attributeConfig.dirName));
29
30
  this.attributesUidMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.attrMapperDirPath), 'uid-mapping.json');
30
31
  this.attributesUidMapper = {};
31
- this.config.context.module = 'attributes';
32
+ this.config.context.module = constants_1.MODULE_CONTEXTS.ATTRIBUTES;
33
+ this.attributeData = [];
32
34
  }
33
35
  /**
34
36
  * The function asynchronously imports attributes from a JSON file and creates them in the system.
@@ -36,48 +38,92 @@ class Attribute 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.attrMapperDirPath);
41
- cli_utilities_1.log.debug(`Created mapper directory: ${this.attrMapperDirPath}`, this.config.context);
42
- const { dirName, fileName } = this.attributeConfig;
43
- const attributesPath = (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 attributes file: ${attributesPath}`, this.config.context);
45
- if ((0, fs_1.existsSync)(attributesPath)) {
46
- try {
47
- const attributes = utils_1.fsUtil.readFile(attributesPath, true);
48
- cli_utilities_1.log.info(`Found ${attributes.length} attributes to import`, this.config.context);
49
- for (const attribute of attributes) {
50
- const { key, name, description, uid } = attribute;
51
- cli_utilities_1.log.debug(`Processing attribute: ${name} - ${attribute.__type}`, this.config.context);
52
- // skip creating preset attributes, as they are already present in the system
53
- if (attribute.__type === 'PRESET') {
54
- cli_utilities_1.log.debug(`Skipping preset attribute: ${name}`, this.config.context);
55
- continue;
56
- }
57
- try {
58
- cli_utilities_1.log.debug(`Creating custom attribute: ${name}`, this.config.context);
59
- const attributeRes = yield this.createAttribute({ key, name, description });
60
- //map old attribute uid to new attribute uid
61
- //mapper file is used to check whether attribute created or not before creating audience
62
- this.attributesUidMapper[uid] = (_a = attributeRes === null || attributeRes === void 0 ? void 0 : attributeRes.uid) !== null && _a !== void 0 ? _a : '';
63
- cli_utilities_1.log.debug(`Created attribute: ${uid} -> ${attributeRes === null || attributeRes === void 0 ? void 0 : attributeRes.uid}`, this.config.context);
64
- }
65
- catch (error) {
66
- (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create attribute: ${name}`);
67
- }
41
+ try {
42
+ cli_utilities_1.log.debug('Starting attributes import...', this.config.context);
43
+ const [canImport, attributesCount] = yield this.analyzeAttributes();
44
+ if (!canImport) {
45
+ cli_utilities_1.log.info('No attributes 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, 'attributes module (no data)', null, constants_1.PROCESS_NAMES.ATTRIBUTES);
68
49
  }
69
- utils_1.fsUtil.writeFile(this.attributesUidMapperPath, this.attributesUidMapper);
70
- cli_utilities_1.log.debug(`Saved ${Object.keys(this.attributesUidMapper).length} attribute mappings to: ${this.attributesUidMapperPath}`, this.config.context);
71
- cli_utilities_1.log.success('Attributes imported successfully', this.config.context);
50
+ return;
72
51
  }
73
- catch (error) {
74
- (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
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 attributes import', this.config.context);
57
+ this.parentProgressManager.updateProcessTotal(constants_1.PROCESS_NAMES.ATTRIBUTES, attributesCount);
75
58
  }
59
+ else {
60
+ progress = this.createSimpleProgress(constants_1.PROCESS_NAMES.ATTRIBUTES, attributesCount);
61
+ cli_utilities_1.log.debug('Created standalone progress manager for attributes import', this.config.context);
62
+ }
63
+ yield this.init();
64
+ yield utils_1.fsUtil.makeDirectory(this.attrMapperDirPath);
65
+ cli_utilities_1.log.debug(`Created mapper directory: ${this.attrMapperDirPath}`, this.config.context);
66
+ const { dirName, fileName } = this.attributeConfig;
67
+ cli_utilities_1.log.info(`Processing ${attributesCount} attributes`, this.config.context);
68
+ for (const attribute of this.attributeData) {
69
+ const { key, name, description, uid } = attribute;
70
+ if (!this.parentProgressManager) {
71
+ progress.updateStatus(constants_1.IMPORT_PROCESS_STATUS[constants_1.PROCESS_NAMES.ATTRIBUTES].CREATING);
72
+ }
73
+ cli_utilities_1.log.debug(`Processing attribute: ${name} - ${attribute.__type}`, this.config.context);
74
+ // skip creating preset attributes, as they are already present in the system
75
+ if (attribute.__type === 'PRESET') {
76
+ cli_utilities_1.log.debug(`Skipping preset attribute: ${name}`, this.config.context);
77
+ this.updateProgress(true, `attribute: ${name} (preset - skipped)`, undefined, constants_1.PROCESS_NAMES.ATTRIBUTES);
78
+ continue;
79
+ }
80
+ try {
81
+ cli_utilities_1.log.debug(`Creating custom attribute: ${name}`, this.config.context);
82
+ const attributeRes = yield this.createAttribute({ key, name, description });
83
+ //map old attribute uid to new attribute uid
84
+ //mapper file is used to check whether attribute created or not before creating audience
85
+ this.attributesUidMapper[uid] = (_a = attributeRes === null || attributeRes === void 0 ? void 0 : attributeRes.uid) !== null && _a !== void 0 ? _a : '';
86
+ this.updateProgress(true, `attribute: ${name}`, undefined, constants_1.PROCESS_NAMES.ATTRIBUTES);
87
+ cli_utilities_1.log.debug(`Created attribute: ${uid} -> ${attributeRes === null || attributeRes === void 0 ? void 0 : attributeRes.uid}`, this.config.context);
88
+ }
89
+ catch (error) {
90
+ this.updateProgress(false, `attribute: ${name}`, error === null || error === void 0 ? void 0 : error.message, constants_1.PROCESS_NAMES.ATTRIBUTES);
91
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create attribute: ${name}`);
92
+ }
93
+ }
94
+ utils_1.fsUtil.writeFile(this.attributesUidMapperPath, this.attributesUidMapper);
95
+ cli_utilities_1.log.debug(`Saved ${Object.keys(this.attributesUidMapper).length} attribute mappings`, this.config.context);
96
+ if (!this.parentProgressManager) {
97
+ this.completeProgress(true);
98
+ }
99
+ cli_utilities_1.log.success(`Attributes imported successfully! Total attributes: ${attributesCount} - personalization enabled`, this.config.context);
76
100
  }
77
- else {
78
- cli_utilities_1.log.warn(`Attributes file not found: ${attributesPath}`, this.config.context);
101
+ catch (error) {
102
+ if (!this.parentProgressManager) {
103
+ this.completeProgress(false, (error === null || error === void 0 ? void 0 : error.message) || 'Attributes import failed');
104
+ }
105
+ (0, cli_utilities_1.handleAndLogError)(error, this.config.context);
106
+ throw error;
79
107
  }
80
108
  });
81
109
  }
110
+ analyzeAttributes() {
111
+ return __awaiter(this, void 0, void 0, function* () {
112
+ return this.withLoadingSpinner('ATTRIBUTES: Analyzing import data...', () => __awaiter(this, void 0, void 0, function* () {
113
+ var _a;
114
+ const { dirName, fileName } = this.attributeConfig;
115
+ const attributesPath = (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));
116
+ cli_utilities_1.log.debug(`Checking for attributes file: ${attributesPath}`, this.config.context);
117
+ if (!(0, fs_1.existsSync)(attributesPath)) {
118
+ cli_utilities_1.log.warn(`Attributes file not found: ${attributesPath}`, this.config.context);
119
+ return [false, 0];
120
+ }
121
+ this.attributeData = utils_1.fsUtil.readFile(attributesPath, true);
122
+ const attributesCount = ((_a = this.attributeData) === null || _a === void 0 ? void 0 : _a.length) || 0;
123
+ cli_utilities_1.log.debug(`Found ${attributesCount} attributes to import`, this.config.context);
124
+ return [attributesCount > 0, attributesCount];
125
+ }));
126
+ });
127
+ }
82
128
  }
83
129
  exports.default = Attribute;
@@ -10,9 +10,11 @@ export default class Audiences extends PersonalizationAdapter<ImportConfig> {
10
10
  private personalizeConfig;
11
11
  private audienceConfig;
12
12
  attributeConfig: ImportConfig['modules']['personalize']['attributes'];
13
+ private audiences;
13
14
  constructor(config: ImportConfig);
14
15
  /**
15
16
  * The function asynchronously imports audiences from a JSON file and creates them in the system.
16
17
  */
17
18
  import(): Promise<void>;
19
+ private analyzeAudiences;
18
20
  }