@contentstack/cli-variants 1.3.3 → 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.
- package/lib/export/attributes.d.ts +2 -2
- package/lib/export/attributes.js +51 -23
- package/lib/export/audiences.d.ts +2 -2
- package/lib/export/audiences.js +50 -24
- package/lib/export/events.d.ts +2 -2
- package/lib/export/events.js +52 -24
- package/lib/export/experiences.js +87 -54
- package/lib/export/projects.d.ts +3 -2
- package/lib/export/projects.js +55 -63
- package/lib/export/variant-entries.d.ts +19 -0
- package/lib/export/variant-entries.js +76 -1
- package/lib/import/attribute.d.ts +2 -0
- package/lib/import/attribute.js +83 -37
- package/lib/import/audiences.d.ts +2 -0
- package/lib/import/audiences.js +85 -41
- package/lib/import/events.d.ts +3 -1
- package/lib/import/events.js +86 -30
- package/lib/import/experiences.d.ts +2 -0
- package/lib/import/experiences.js +93 -39
- package/lib/import/project.d.ts +2 -0
- package/lib/import/project.js +81 -22
- package/lib/import/variant-entries.d.ts +10 -0
- package/lib/import/variant-entries.js +132 -47
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/types/export-config.d.ts +0 -2
- package/lib/types/import-config.d.ts +0 -1
- package/lib/types/utils.d.ts +1 -1
- package/lib/utils/constants.d.ts +91 -0
- package/lib/utils/constants.js +93 -0
- package/lib/utils/personalization-api-adapter.d.ts +34 -1
- package/lib/utils/personalization-api-adapter.js +171 -44
- package/lib/utils/variant-api-adapter.d.ts +28 -1
- package/lib/utils/variant-api-adapter.js +75 -0
- package/package.json +1 -1
- package/src/export/attributes.ts +84 -34
- package/src/export/audiences.ts +87 -41
- package/src/export/events.ts +84 -41
- package/src/export/experiences.ts +155 -83
- package/src/export/projects.ts +71 -39
- package/src/export/variant-entries.ts +136 -12
- package/src/import/attribute.ts +105 -49
- package/src/import/audiences.ts +110 -54
- package/src/import/events.ts +104 -41
- package/src/import/experiences.ts +140 -62
- package/src/import/project.ts +108 -38
- package/src/import/variant-entries.ts +179 -65
- package/src/index.ts +2 -1
- package/src/types/export-config.ts +0 -2
- package/src/types/import-config.ts +0 -1
- package/src/types/utils.ts +1 -1
- package/src/utils/constants.ts +98 -0
- package/src/utils/personalization-api-adapter.ts +202 -66
- package/src/utils/variant-api-adapter.ts +82 -1
- package/tsconfig.json +1 -1
package/lib/export/projects.js
CHANGED
|
@@ -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
|
|
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.
|
|
58
|
-
this.
|
|
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(
|
|
66
|
-
|
|
67
|
-
yield this.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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(
|
|
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
|
-
|
|
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 = (
|
|
84
|
-
cli_utilities_1.log.debug(`Set project ID: ${(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/lib/import/attribute.js
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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
|
}
|