@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.
- 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 +2 -2
- 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
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
import { AdapterHelper } from './adapter-helper';
|
|
2
|
-
import { HttpClient } from '@contentstack/cli-utilities';
|
|
2
|
+
import { HttpClient, CLIProgressManager } from '@contentstack/cli-utilities';
|
|
3
3
|
import { ProjectStruct, Personalization, GetProjectsParams, CreateProjectInput, CreateAttributeInput, APIConfig, GetVariantGroupInput, EventStruct, AudienceStruct, AttributeStruct, CreateAudienceInput, CreateEventInput, CreateExperienceInput, ExperienceStruct, UpdateExperienceInput, CMSExperienceStruct, VariantAPIRes, APIResponse, VariantGroupStruct, VariantGroup, CreateExperienceVersionInput, ExportConfig } from '../types';
|
|
4
4
|
export declare class PersonalizationAdapter<T> extends AdapterHelper<T, HttpClient> implements Personalization<T> {
|
|
5
5
|
exportConfig?: ExportConfig;
|
|
6
|
+
protected progressManager: CLIProgressManager | null;
|
|
7
|
+
protected parentProgressManager: CLIProgressManager | null;
|
|
8
|
+
protected currentModuleName: string;
|
|
9
|
+
protected cachedData: any[] | null;
|
|
6
10
|
constructor(options: APIConfig);
|
|
11
|
+
/**
|
|
12
|
+
* Set parent progress manager for sub-module integration
|
|
13
|
+
*/
|
|
14
|
+
setParentProgressManager(parentProgress: CLIProgressManager): void;
|
|
15
|
+
/**
|
|
16
|
+
* Set cached data to avoid redundant API calls
|
|
17
|
+
*/
|
|
18
|
+
setCachedData(data: any[]): void;
|
|
19
|
+
/**
|
|
20
|
+
* Create simple progress manager for single process tracking
|
|
21
|
+
*/
|
|
22
|
+
protected createSimpleProgress(moduleName: string, total?: number): CLIProgressManager;
|
|
23
|
+
/**
|
|
24
|
+
* Create nested progress manager for multi-process tracking
|
|
25
|
+
*/
|
|
26
|
+
protected createNestedProgress(moduleName: string): CLIProgressManager;
|
|
27
|
+
/**
|
|
28
|
+
* Complete progress manager
|
|
29
|
+
*/
|
|
30
|
+
protected completeProgress(success?: boolean, error?: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Execute action with loading spinner for initial setup tasks
|
|
33
|
+
*/
|
|
34
|
+
protected withLoadingSpinner<T>(message: string, action: () => Promise<T>): Promise<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Update progress for a specific item
|
|
37
|
+
*/
|
|
38
|
+
protected updateProgress(success: boolean, itemName: string, error?: string, processName?: string): void;
|
|
39
|
+
static printFinalSummary(): void;
|
|
7
40
|
init(): Promise<void>;
|
|
8
41
|
projects(options: GetProjectsParams): Promise<ProjectStruct[]>;
|
|
9
42
|
/**
|
|
@@ -28,45 +28,149 @@ class PersonalizationAdapter extends adapter_helper_1.AdapterHelper {
|
|
|
28
28
|
constructor(options) {
|
|
29
29
|
var _a;
|
|
30
30
|
super(options);
|
|
31
|
+
this.progressManager = null;
|
|
32
|
+
this.parentProgressManager = null; // Add parent progress manager
|
|
33
|
+
this.currentModuleName = '';
|
|
34
|
+
this.cachedData = null; // Add cached data property
|
|
31
35
|
cli_utilities_1.log.debug('PersonalizationAdapter initialized', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
32
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Set parent progress manager for sub-module integration
|
|
39
|
+
*/
|
|
40
|
+
setParentProgressManager(parentProgress) {
|
|
41
|
+
this.parentProgressManager = parentProgress;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Set cached data to avoid redundant API calls
|
|
45
|
+
*/
|
|
46
|
+
setCachedData(data) {
|
|
47
|
+
var _a;
|
|
48
|
+
this.cachedData = data;
|
|
49
|
+
cli_utilities_1.log.debug(`Cached data set with ${(data === null || data === void 0 ? void 0 : data.length) || 0} items`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create simple progress manager for single process tracking
|
|
53
|
+
*/
|
|
54
|
+
createSimpleProgress(moduleName, total) {
|
|
55
|
+
var _a;
|
|
56
|
+
this.currentModuleName = moduleName;
|
|
57
|
+
// If we have a parent progress manager, use it instead of creating a new one
|
|
58
|
+
if (this.parentProgressManager) {
|
|
59
|
+
this.progressManager = this.parentProgressManager;
|
|
60
|
+
return this.progressManager;
|
|
61
|
+
}
|
|
62
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
63
|
+
const showConsoleLogs = (_a = logConfig.showConsoleLogs) !== null && _a !== void 0 ? _a : false;
|
|
64
|
+
this.progressManager = cli_utilities_1.CLIProgressManager.createSimple(moduleName, total, showConsoleLogs);
|
|
65
|
+
return this.progressManager;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create nested progress manager for multi-process tracking
|
|
69
|
+
*/
|
|
70
|
+
createNestedProgress(moduleName) {
|
|
71
|
+
var _a;
|
|
72
|
+
this.currentModuleName = moduleName;
|
|
73
|
+
// If we have a parent progress manager, use it instead of creating a new one
|
|
74
|
+
if (this.parentProgressManager) {
|
|
75
|
+
this.progressManager = this.parentProgressManager;
|
|
76
|
+
return this.progressManager;
|
|
77
|
+
}
|
|
78
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
79
|
+
const showConsoleLogs = (_a = logConfig.showConsoleLogs) !== null && _a !== void 0 ? _a : false;
|
|
80
|
+
this.progressManager = cli_utilities_1.CLIProgressManager.createNested(moduleName, showConsoleLogs);
|
|
81
|
+
return this.progressManager;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Complete progress manager
|
|
85
|
+
*/
|
|
86
|
+
completeProgress(success = true, error) {
|
|
87
|
+
var _a;
|
|
88
|
+
// Only complete progress if we own the progress manager (no parent)
|
|
89
|
+
if (!this.parentProgressManager) {
|
|
90
|
+
(_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.complete(success, error);
|
|
91
|
+
}
|
|
92
|
+
this.progressManager = null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Execute action with loading spinner for initial setup tasks
|
|
96
|
+
*/
|
|
97
|
+
withLoadingSpinner(message, action) {
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
var _a;
|
|
100
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
101
|
+
const showConsoleLogs = (_a = logConfig.showConsoleLogs) !== null && _a !== void 0 ? _a : false;
|
|
102
|
+
if (showConsoleLogs) {
|
|
103
|
+
// If console logs are enabled, don't show spinner, just execute the action
|
|
104
|
+
return yield action();
|
|
105
|
+
}
|
|
106
|
+
return yield cli_utilities_1.CLIProgressManager.withLoadingSpinner(message, action);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Update progress for a specific item
|
|
111
|
+
*/
|
|
112
|
+
updateProgress(success, itemName, error, processName) {
|
|
113
|
+
if (this.parentProgressManager) {
|
|
114
|
+
this.parentProgressManager.tick(success, itemName, error, processName);
|
|
115
|
+
}
|
|
116
|
+
else if (this.progressManager) {
|
|
117
|
+
this.progressManager.tick(success, itemName, error, processName);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
static printFinalSummary() {
|
|
121
|
+
cli_utilities_1.CLIProgressManager.printGlobalSummary();
|
|
122
|
+
}
|
|
33
123
|
init() {
|
|
34
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
cli_utilities_1.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
125
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
126
|
+
try {
|
|
127
|
+
cli_utilities_1.log.debug('Initializing personalization adapter...', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
128
|
+
yield cli_utilities_1.authenticationHandler.getAuthDetails();
|
|
129
|
+
const token = cli_utilities_1.authenticationHandler.accessToken;
|
|
130
|
+
cli_utilities_1.log.debug(`Authentication type: ${cli_utilities_1.authenticationHandler.isOauthEnabled ? 'OAuth' : 'Token'}`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
131
|
+
if (cli_utilities_1.authenticationHandler.isOauthEnabled) {
|
|
132
|
+
cli_utilities_1.log.debug('Setting OAuth authorization header', (_c = this.exportConfig) === null || _c === void 0 ? void 0 : _c.context);
|
|
133
|
+
this.apiClient.headers({ authorization: token });
|
|
134
|
+
if (this.adapterConfig.cmaConfig) {
|
|
135
|
+
cli_utilities_1.log.debug('Setting OAuth authorization header for CMA client', (_d = this.exportConfig) === null || _d === void 0 ? void 0 : _d.context);
|
|
136
|
+
(_e = this.cmaAPIClient) === null || _e === void 0 ? void 0 : _e.headers({ authorization: token });
|
|
137
|
+
}
|
|
46
138
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
139
|
+
else {
|
|
140
|
+
cli_utilities_1.log.debug('Setting authtoken header', (_f = this.exportConfig) === null || _f === void 0 ? void 0 : _f.context);
|
|
141
|
+
this.apiClient.headers({ authtoken: token });
|
|
142
|
+
if (this.adapterConfig.cmaConfig) {
|
|
143
|
+
cli_utilities_1.log.debug('Setting authtoken header for CMA client', (_g = this.exportConfig) === null || _g === void 0 ? void 0 : _g.context);
|
|
144
|
+
(_h = this.cmaAPIClient) === null || _h === void 0 ? void 0 : _h.headers({ authtoken: token });
|
|
145
|
+
}
|
|
54
146
|
}
|
|
147
|
+
cli_utilities_1.log.debug('Personalization adapter initialization completed', (_j = this.exportConfig) === null || _j === void 0 ? void 0 : _j.context);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
cli_utilities_1.log.debug(`Personalization adapter initialization failed: ${error}`, (_k = this.exportConfig) === null || _k === void 0 ? void 0 : _k.context);
|
|
55
151
|
}
|
|
56
|
-
cli_utilities_1.log.debug('Personalization adapter initialization completed', (_j = this.exportConfig) === null || _j === void 0 ? void 0 : _j.context);
|
|
57
152
|
});
|
|
58
153
|
}
|
|
59
154
|
projects(options) {
|
|
60
155
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
156
|
var _a, _b, _c;
|
|
62
|
-
cli_utilities_1.log.debug(`Fetching projects for stack API key: ${options.connectedStackApiKey}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
63
157
|
yield this.init();
|
|
64
158
|
const getProjectEndPoint = `/projects?connectedStackApiKey=${options.connectedStackApiKey}`;
|
|
65
|
-
cli_utilities_1.log.debug(`Making API call to: ${getProjectEndPoint}`, (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
159
|
+
cli_utilities_1.log.debug(`Making API call to: ${getProjectEndPoint}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
160
|
+
try {
|
|
161
|
+
const data = yield this.apiClient.get(getProjectEndPoint);
|
|
162
|
+
const result = (yield this.handleVariantAPIRes(data));
|
|
163
|
+
cli_utilities_1.log.debug(`Fetched ${(result === null || result === void 0 ? void 0 : result.length) || 0} projects`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
164
|
+
// Update progress for each project fetched
|
|
165
|
+
result === null || result === void 0 ? void 0 : result.forEach((project) => {
|
|
166
|
+
this.updateProgress(true, `project: ${project.name || project.uid}`, undefined, 'Projects');
|
|
167
|
+
});
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
cli_utilities_1.log.debug(`Failed to fetch projects: ${error}`, (_c = this.exportConfig) === null || _c === void 0 ? void 0 : _c.context);
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
70
174
|
});
|
|
71
175
|
}
|
|
72
176
|
/**
|
|
@@ -110,13 +214,23 @@ class PersonalizationAdapter extends adapter_helper_1.AdapterHelper {
|
|
|
110
214
|
}
|
|
111
215
|
getExperiences() {
|
|
112
216
|
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
-
var _a, _b;
|
|
217
|
+
var _a, _b, _c;
|
|
114
218
|
cli_utilities_1.log.debug('Fetching experiences from personalization API', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
115
219
|
const getExperiencesEndPoint = `/experiences`;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
220
|
+
try {
|
|
221
|
+
const data = yield this.apiClient.get(getExperiencesEndPoint);
|
|
222
|
+
const result = (yield this.handleVariantAPIRes(data));
|
|
223
|
+
cli_utilities_1.log.debug(`Fetched ${(result === null || result === void 0 ? void 0 : result.length) || 0} experiences`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
224
|
+
// Update progress for each experience fetched
|
|
225
|
+
result === null || result === void 0 ? void 0 : result.forEach((experience) => {
|
|
226
|
+
this.updateProgress(true, `experience: ${experience.name || experience.uid}`, undefined, 'Experiences');
|
|
227
|
+
});
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
cli_utilities_1.log.debug(`Failed to fetch experiences: ${error}`, (_c = this.exportConfig) === null || _c === void 0 ? void 0 : _c.context);
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
120
234
|
});
|
|
121
235
|
}
|
|
122
236
|
getExperience(experienceUid) {
|
|
@@ -154,7 +268,7 @@ class PersonalizationAdapter extends adapter_helper_1.AdapterHelper {
|
|
|
154
268
|
const createExperiencesVersionsEndPoint = `/experiences/${experienceUid}/versions`;
|
|
155
269
|
const data = yield this.apiClient.post(createExperiencesVersionsEndPoint, input);
|
|
156
270
|
const result = (yield this.handleVariantAPIRes(data));
|
|
157
|
-
cli_utilities_1.log.
|
|
271
|
+
cli_utilities_1.log.debug(`Experience version created successfully for: ${experienceUid}`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
158
272
|
return result;
|
|
159
273
|
});
|
|
160
274
|
}
|
|
@@ -213,32 +327,45 @@ class PersonalizationAdapter extends adapter_helper_1.AdapterHelper {
|
|
|
213
327
|
}
|
|
214
328
|
getEvents() {
|
|
215
329
|
return __awaiter(this, void 0, void 0, function* () {
|
|
216
|
-
var _a, _b;
|
|
330
|
+
var _a, _b, _c;
|
|
217
331
|
cli_utilities_1.log.debug('Fetching events from personalization API', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
332
|
+
try {
|
|
333
|
+
const data = yield this.apiClient.get('/events');
|
|
334
|
+
const result = (yield this.handleVariantAPIRes(data));
|
|
335
|
+
cli_utilities_1.log.debug(`Fetched ${(result === null || result === void 0 ? void 0 : result.length) || 0} events`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
cli_utilities_1.log.debug(`Failed to fetch events: ${error}`, (_c = this.exportConfig) === null || _c === void 0 ? void 0 : _c.context);
|
|
340
|
+
// Return empty array instead of throwing to prevent spinner from hanging
|
|
341
|
+
throw error;
|
|
342
|
+
}
|
|
222
343
|
});
|
|
223
344
|
}
|
|
224
345
|
createEvents(event) {
|
|
225
346
|
return __awaiter(this, void 0, void 0, function* () {
|
|
226
|
-
var _a
|
|
227
|
-
cli_utilities_1.log.debug(`Creating event: ${event.key}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
347
|
+
var _a;
|
|
228
348
|
const data = yield this.apiClient.post('/events', event);
|
|
229
349
|
const result = (yield this.handleVariantAPIRes(data));
|
|
230
|
-
cli_utilities_1.log.info(`Event created successfully: ${result === null || result === void 0 ? void 0 : result.uid}`, (
|
|
350
|
+
cli_utilities_1.log.info(`Event created successfully: ${result === null || result === void 0 ? void 0 : result.uid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
231
351
|
return result;
|
|
232
352
|
});
|
|
233
353
|
}
|
|
234
354
|
getAudiences() {
|
|
235
355
|
return __awaiter(this, void 0, void 0, function* () {
|
|
236
|
-
var _a, _b;
|
|
356
|
+
var _a, _b, _c;
|
|
237
357
|
cli_utilities_1.log.debug('Fetching audiences from personalization API', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
358
|
+
try {
|
|
359
|
+
const data = yield this.apiClient.get('/audiences');
|
|
360
|
+
const result = (yield this.handleVariantAPIRes(data));
|
|
361
|
+
cli_utilities_1.log.debug(`Fetched ${(result === null || result === void 0 ? void 0 : result.length) || 0} audiences`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
362
|
+
return result;
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
cli_utilities_1.log.debug(`Failed to fetch audiences: ${error}`, (_c = this.exportConfig) === null || _c === void 0 ? void 0 : _c.context);
|
|
366
|
+
// Return empty array instead of throwing to prevent spinner from hanging
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
242
369
|
});
|
|
243
370
|
}
|
|
244
371
|
getAttributes() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HttpClient, HttpClientOptions, ContentstackClient, ContentstackConfig } from '@contentstack/cli-utilities';
|
|
1
|
+
import { HttpClient, HttpClientOptions, ContentstackClient, ContentstackConfig, CLIProgressManager } from '@contentstack/cli-utilities';
|
|
2
2
|
import { APIConfig, AdapterType, AnyProperty, ExportConfig, VariantOptions, VariantsOption, VariantInterface, VariantEntryStruct, CreateVariantEntryDto, CreateVariantEntryOptions, APIResponse, PublishVariantEntryDto, PublishVariantEntryOptions } from '../types';
|
|
3
3
|
import messages from '../messages';
|
|
4
4
|
import { AdapterHelper } from './adapter-helper';
|
|
@@ -77,7 +77,34 @@ export declare class VariantAdapter<T> {
|
|
|
77
77
|
protected variantInstance: T;
|
|
78
78
|
readonly messages: typeof messages;
|
|
79
79
|
exportConfig?: any;
|
|
80
|
+
protected progressManager: CLIProgressManager | null;
|
|
81
|
+
protected parentProgressManager: CLIProgressManager | null;
|
|
82
|
+
protected currentModuleName: string;
|
|
80
83
|
constructor(config: ContentstackConfig & AnyProperty & AdapterType<T, ContentstackConfig>);
|
|
81
84
|
constructor(config: APIConfig & AdapterType<T, APIConfig & AnyProperty>, options?: HttpClientOptions);
|
|
85
|
+
/**
|
|
86
|
+
* Set parent progress manager for sub-module integration
|
|
87
|
+
*/
|
|
88
|
+
setParentProgressManager(parentProgress: CLIProgressManager): void;
|
|
89
|
+
/**
|
|
90
|
+
* Create simple progress manager for single process tracking
|
|
91
|
+
*/
|
|
92
|
+
protected createSimpleProgress(moduleName: string, total?: number): CLIProgressManager;
|
|
93
|
+
/**
|
|
94
|
+
* Create nested progress manager for multi-process tracking
|
|
95
|
+
*/
|
|
96
|
+
protected createNestedProgress(moduleName: string): CLIProgressManager;
|
|
97
|
+
/**
|
|
98
|
+
* Complete progress manager
|
|
99
|
+
*/
|
|
100
|
+
protected completeProgress(success?: boolean, error?: string): void;
|
|
101
|
+
/**
|
|
102
|
+
* Execute action with loading spinner for initial setup tasks
|
|
103
|
+
*/
|
|
104
|
+
protected withLoadingSpinner<T>(message: string, action: () => Promise<T>): Promise<T>;
|
|
105
|
+
/**
|
|
106
|
+
* Update progress for a specific item
|
|
107
|
+
*/
|
|
108
|
+
protected updateProgress(success: boolean, itemName: string, error?: string, processName?: string): void;
|
|
82
109
|
}
|
|
83
110
|
export default VariantAdapter;
|
|
@@ -319,6 +319,9 @@ exports.VariantManagementSDK = VariantManagementSDK;
|
|
|
319
319
|
class VariantAdapter {
|
|
320
320
|
constructor(config, options) {
|
|
321
321
|
var _a, _b, _c, _d;
|
|
322
|
+
this.progressManager = null;
|
|
323
|
+
this.parentProgressManager = null;
|
|
324
|
+
this.currentModuleName = '';
|
|
322
325
|
cli_utilities_1.log.debug('Initializing VariantAdapter...', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
323
326
|
if (config.httpClient) {
|
|
324
327
|
cli_utilities_1.log.debug('Using HTTP client variant instance', (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
@@ -333,6 +336,78 @@ class VariantAdapter {
|
|
|
333
336
|
this.messages = messages_1.default;
|
|
334
337
|
cli_utilities_1.log.debug('VariantAdapter initialized successfully', (_d = this.exportConfig) === null || _d === void 0 ? void 0 : _d.context);
|
|
335
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Set parent progress manager for sub-module integration
|
|
341
|
+
*/
|
|
342
|
+
setParentProgressManager(parentProgress) {
|
|
343
|
+
this.parentProgressManager = parentProgress;
|
|
344
|
+
this.progressManager = parentProgress;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Create simple progress manager for single process tracking
|
|
348
|
+
*/
|
|
349
|
+
createSimpleProgress(moduleName, total) {
|
|
350
|
+
var _a;
|
|
351
|
+
this.currentModuleName = moduleName;
|
|
352
|
+
// If we have a parent progress manager, use it instead of creating a new one
|
|
353
|
+
if (this.parentProgressManager) {
|
|
354
|
+
this.progressManager = this.parentProgressManager;
|
|
355
|
+
return this.progressManager;
|
|
356
|
+
}
|
|
357
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
358
|
+
const showConsoleLogs = (_a = logConfig.showConsoleLogs) !== null && _a !== void 0 ? _a : false;
|
|
359
|
+
this.progressManager = cli_utilities_1.CLIProgressManager.createSimple(moduleName, total, showConsoleLogs);
|
|
360
|
+
return this.progressManager;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Create nested progress manager for multi-process tracking
|
|
364
|
+
*/
|
|
365
|
+
createNestedProgress(moduleName) {
|
|
366
|
+
var _a;
|
|
367
|
+
this.currentModuleName = moduleName;
|
|
368
|
+
// If we have a parent progress manager, use it instead of creating a new one
|
|
369
|
+
if (this.parentProgressManager) {
|
|
370
|
+
this.progressManager = this.parentProgressManager;
|
|
371
|
+
return this.progressManager;
|
|
372
|
+
}
|
|
373
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
374
|
+
const showConsoleLogs = (_a = logConfig.showConsoleLogs) !== null && _a !== void 0 ? _a : false;
|
|
375
|
+
this.progressManager = cli_utilities_1.CLIProgressManager.createNested(moduleName, showConsoleLogs);
|
|
376
|
+
return this.progressManager;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Complete progress manager
|
|
380
|
+
*/
|
|
381
|
+
completeProgress(success = true, error) {
|
|
382
|
+
var _a;
|
|
383
|
+
// Only complete progress if we own the progress manager (no parent)
|
|
384
|
+
if (!this.parentProgressManager) {
|
|
385
|
+
(_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.complete(success, error);
|
|
386
|
+
}
|
|
387
|
+
this.progressManager = null;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Execute action with loading spinner for initial setup tasks
|
|
391
|
+
*/
|
|
392
|
+
withLoadingSpinner(message, action) {
|
|
393
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
394
|
+
var _a;
|
|
395
|
+
const logConfig = cli_utilities_1.configHandler.get('log') || {};
|
|
396
|
+
const showConsoleLogs = (_a = logConfig.showConsoleLogs) !== null && _a !== void 0 ? _a : false;
|
|
397
|
+
if (showConsoleLogs) {
|
|
398
|
+
// If console logs are enabled, don't show spinner, just execute the action
|
|
399
|
+
return yield action();
|
|
400
|
+
}
|
|
401
|
+
return yield cli_utilities_1.CLIProgressManager.withLoadingSpinner(message, action);
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Update progress for a specific item
|
|
406
|
+
*/
|
|
407
|
+
updateProgress(success, itemName, error, processName) {
|
|
408
|
+
var _a;
|
|
409
|
+
(_a = this.progressManager) === null || _a === void 0 ? void 0 : _a.tick(success, itemName, error, processName);
|
|
410
|
+
}
|
|
336
411
|
}
|
|
337
412
|
exports.VariantAdapter = VariantAdapter;
|
|
338
413
|
exports.default = VariantAdapter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-variants",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
4
|
"description": "Variants plugin",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"typescript": "^5.8.3"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@contentstack/cli-utilities": "~1.
|
|
30
|
+
"@contentstack/cli-utilities": "~1.15.0",
|
|
31
31
|
"@oclif/core": "^4.3.0",
|
|
32
32
|
"@oclif/plugin-help": "^6.2.28",
|
|
33
33
|
"lodash": "^4.17.21",
|
package/src/export/attributes.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import omit from 'lodash/omit';
|
|
2
2
|
import { resolve as pResolve } from 'node:path';
|
|
3
3
|
import { sanitizePath, log, handleAndLogError } from '@contentstack/cli-utilities';
|
|
4
|
-
import {fsUtil, PersonalizationAdapter } from '../utils';
|
|
5
4
|
import { PersonalizeConfig, ExportConfig, AttributesConfig, AttributeStruct } from '../types';
|
|
5
|
+
import { fsUtil, PersonalizationAdapter } from '../utils';
|
|
6
|
+
import { PROCESS_NAMES, MODULE_CONTEXTS, EXPORT_PROCESS_STATUS } from '../utils/constants';
|
|
6
7
|
|
|
7
8
|
export default class ExportAttributes extends PersonalizationAdapter<ExportConfig> {
|
|
8
9
|
private attributesConfig: AttributesConfig;
|
|
9
10
|
private attributesFolderPath: string;
|
|
10
11
|
private attributes: Record<string, unknown>[];
|
|
12
|
+
public exportConfig: ExportConfig;
|
|
11
13
|
public personalizeConfig: PersonalizeConfig;
|
|
12
14
|
|
|
13
|
-
constructor(
|
|
15
|
+
constructor(exportConfig: ExportConfig) {
|
|
14
16
|
super({
|
|
15
17
|
config: exportConfig,
|
|
16
18
|
baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
|
|
@@ -26,45 +28,73 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
|
|
|
26
28
|
sanitizePath(this.attributesConfig.dirName),
|
|
27
29
|
);
|
|
28
30
|
this.attributes = [];
|
|
29
|
-
this.exportConfig.context.module =
|
|
31
|
+
this.exportConfig.context.module = MODULE_CONTEXTS.ATTRIBUTES;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
async start() {
|
|
33
35
|
try {
|
|
34
36
|
log.info('Starting attributes export', this.exportConfig.context);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
await this.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
|
|
38
|
+
// Initial setup with loading spinner
|
|
39
|
+
await this.withLoadingSpinner('ATTRIBUTES: Initializing export and fetching data...', async () => {
|
|
40
|
+
log.debug('Initializing personalization adapter...', this.exportConfig.context);
|
|
41
|
+
await this.init();
|
|
42
|
+
log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
|
|
43
|
+
|
|
44
|
+
log.debug(`Creating attributes directory at: ${this.attributesFolderPath}`, this.exportConfig.context);
|
|
45
|
+
await fsUtil.makeDirectory(this.attributesFolderPath);
|
|
46
|
+
log.debug('Attributes directory created successfully', this.exportConfig.context);
|
|
47
|
+
log.debug('Fetching attributes from personalization API...', this.exportConfig.context);
|
|
48
|
+
this.attributes = (await this.getAttributes()) as AttributeStruct[];
|
|
49
|
+
log.debug(`Fetched ${this.attributes?.length || 0} attributes`, this.exportConfig.context);
|
|
50
|
+
});
|
|
47
51
|
|
|
48
52
|
if (!this.attributes?.length) {
|
|
49
53
|
log.debug('No attributes found, completing export', this.exportConfig.context);
|
|
50
54
|
log.info('No Attributes found with the given project!', this.exportConfig.context);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let progress: any;
|
|
59
|
+
|
|
60
|
+
if (this.parentProgressManager) {
|
|
61
|
+
// Use parent progress manager - we're part of the personalize modules process
|
|
62
|
+
progress = this.parentProgressManager;
|
|
63
|
+
this.progressManager = this.parentProgressManager;
|
|
64
|
+
|
|
65
|
+
progress.updateProcessTotal(PROCESS_NAMES.ATTRIBUTES, this.attributes.length);
|
|
51
66
|
} else {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)
|
|
67
|
+
progress = this.createSimpleProgress(PROCESS_NAMES.ATTRIBUTES, this.attributes.length);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
log.debug(`Processing ${this.attributes.length} attributes`, this.exportConfig.context);
|
|
71
|
+
|
|
72
|
+
progress.updateStatus(EXPORT_PROCESS_STATUS[PROCESS_NAMES.ATTRIBUTES].EXPORTING, PROCESS_NAMES.ATTRIBUTES);
|
|
73
|
+
|
|
74
|
+
this.sanitizeAttribs();
|
|
75
|
+
log.debug('Attributes sanitization completed', this.exportConfig.context);
|
|
76
|
+
|
|
77
|
+
progress.updateStatus(EXPORT_PROCESS_STATUS[PROCESS_NAMES.ATTRIBUTES].EXPORTING, PROCESS_NAMES.ATTRIBUTES);
|
|
78
|
+
const attributesFilePath = pResolve(
|
|
79
|
+
sanitizePath(this.attributesFolderPath),
|
|
80
|
+
sanitizePath(this.attributesConfig.fileName),
|
|
81
|
+
);
|
|
82
|
+
log.debug(`Writing attributes to: ${attributesFilePath}`, this.exportConfig.context);
|
|
83
|
+
fsUtil.writeFile(attributesFilePath, this.attributes);
|
|
84
|
+
|
|
85
|
+
// Complete progress only if we're managing our own progress
|
|
86
|
+
if (!this.parentProgressManager) {
|
|
87
|
+
this.completeProgress(true);
|
|
65
88
|
}
|
|
66
|
-
|
|
89
|
+
|
|
90
|
+
log.debug('Attributes export completed successfully', this.exportConfig.context);
|
|
91
|
+
log.success(
|
|
92
|
+
`Attributes exported successfully! Total attributes: ${this.attributes.length}`,
|
|
93
|
+
this.exportConfig.context,
|
|
94
|
+
);
|
|
95
|
+
} catch (error: any) {
|
|
67
96
|
log.debug(`Error occurred during attributes export: ${error}`, this.exportConfig.context);
|
|
97
|
+
this.completeProgress(false, error?.message || 'Attributes export failed');
|
|
68
98
|
handleAndLogError(error, { ...this.exportConfig.context });
|
|
69
99
|
}
|
|
70
100
|
}
|
|
@@ -74,10 +104,30 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
|
|
|
74
104
|
*/
|
|
75
105
|
sanitizeAttribs() {
|
|
76
106
|
log.debug(`Sanitizing ${this.attributes?.length || 0} attributes`, this.exportConfig.context);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
107
|
+
|
|
108
|
+
this.attributes =
|
|
109
|
+
this.attributes?.map((attribute, index) => {
|
|
110
|
+
const sanitizedAttribute = omit(attribute, this.attributesConfig.invalidKeys);
|
|
111
|
+
|
|
112
|
+
// Update progress for each processed attribute
|
|
113
|
+
if (this.progressManager) {
|
|
114
|
+
const processName = this.parentProgressManager ? PROCESS_NAMES.ATTRIBUTES : undefined;
|
|
115
|
+
this.updateProgress(
|
|
116
|
+
true,
|
|
117
|
+
`attribute ${index + 1}/${this.attributes.length}: ${
|
|
118
|
+
(attribute as any)?.name || (attribute as any)?.uid || 'unknown'
|
|
119
|
+
}`,
|
|
120
|
+
undefined,
|
|
121
|
+
processName,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return sanitizedAttribute;
|
|
126
|
+
}) || [];
|
|
127
|
+
|
|
128
|
+
log.debug(
|
|
129
|
+
`Sanitization complete. Total attributes after sanitization: ${this.attributes.length}`,
|
|
130
|
+
this.exportConfig.context,
|
|
131
|
+
);
|
|
82
132
|
}
|
|
83
133
|
}
|