@contentstack/cli-variants 1.3.2 → 2.0.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +139 -53
- 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 +180 -53
- package/lib/utils/variant-api-adapter.d.ts +28 -1
- package/lib/utils/variant-api-adapter.js +89 -32
- 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 +188 -75
- 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 +212 -76
- package/src/utils/variant-api-adapter.ts +137 -50
- package/tsconfig.json +1 -1
|
@@ -40,7 +40,7 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
40
40
|
}
|
|
41
41
|
init() {
|
|
42
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
-
var _a, _b, _c, _d
|
|
43
|
+
var _a, _b, _c, _d;
|
|
44
44
|
cli_utilities_1.log.debug('Initializing VariantHttpClient...', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
45
45
|
yield cli_utilities_1.authenticationHandler.getAuthDetails();
|
|
46
46
|
const token = cli_utilities_1.authenticationHandler.accessToken;
|
|
@@ -53,7 +53,6 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
53
53
|
cli_utilities_1.log.debug('Setting authtoken header', (_d = this.exportConfig) === null || _d === void 0 ? void 0 : _d.context);
|
|
54
54
|
this.apiClient.headers({ authtoken: token });
|
|
55
55
|
}
|
|
56
|
-
cli_utilities_1.log.debug('VariantHttpClient initialization completed', (_e = this.exportConfig) === null || _e === void 0 ? void 0 : _e.context);
|
|
57
56
|
});
|
|
58
57
|
}
|
|
59
58
|
variantEntry(options) {
|
|
@@ -171,28 +170,24 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
171
170
|
createVariantEntry(input, options, apiParams) {
|
|
172
171
|
return __awaiter(this, void 0, void 0, function* () {
|
|
173
172
|
var _a, _b;
|
|
174
|
-
const { reject, resolve, variantUid
|
|
173
|
+
const { reject, resolve, variantUid } = apiParams;
|
|
175
174
|
const variantConfig = this.config.modules.variantEntry;
|
|
176
175
|
const { locale = variantConfig.query.locale || 'en-us', variant_id, entry_uid, content_type_uid } = options;
|
|
177
|
-
log.debug(`Creating variant entry for content type: ${content_type_uid}, entry: ${entry_uid}, variant: ${variant_id}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
176
|
+
cli_utilities_1.log.debug(`Creating variant entry for content type: ${content_type_uid}, entry: ${entry_uid}, variant: ${variant_id}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
178
177
|
let endpoint = `content_types/${content_type_uid}/entries/${entry_uid}/variants/${variant_id}?locale=${locale}`;
|
|
179
178
|
const query = this.constructQuery((0, omit_1.default)(variantConfig.query, ['locale']));
|
|
180
179
|
if (query) {
|
|
181
180
|
endpoint = endpoint.concat(query);
|
|
182
181
|
}
|
|
183
|
-
log.debug(`Making API call to: ${endpoint}`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
182
|
+
cli_utilities_1.log.debug(`Making API call to: ${endpoint}`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
184
183
|
const onSuccess = (response) => {
|
|
185
|
-
|
|
186
|
-
log.debug(`Variant entry created successfully: ${variantUid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
187
|
-
resolve({ response, apiData: { variantUid, entryUid: entry_uid }, log });
|
|
184
|
+
resolve({ response, apiData: { variantUid, entryUid: entry_uid }, log: cli_utilities_1.log });
|
|
188
185
|
};
|
|
189
186
|
const onReject = (error) => {
|
|
190
|
-
var _a;
|
|
191
|
-
log.debug(`Failed to create variant entry: ${variantUid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
192
187
|
reject({
|
|
193
188
|
error,
|
|
194
189
|
apiData: { variantUid, entryUid: entry_uid },
|
|
195
|
-
log,
|
|
190
|
+
log: cli_utilities_1.log,
|
|
196
191
|
});
|
|
197
192
|
};
|
|
198
193
|
try {
|
|
@@ -222,23 +217,23 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
222
217
|
publishVariantEntry(input, options, apiParams) {
|
|
223
218
|
return __awaiter(this, void 0, void 0, function* () {
|
|
224
219
|
var _a, _b;
|
|
225
|
-
const { reject, resolve,
|
|
220
|
+
const { reject, resolve, variantUid } = apiParams;
|
|
226
221
|
const { entry_uid, content_type_uid } = options;
|
|
227
|
-
log.debug(`Publishing variant entry for content type: ${content_type_uid}, entry: ${entry_uid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
222
|
+
cli_utilities_1.log.debug(`Publishing variant entry for content type: ${content_type_uid}, entry: ${entry_uid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
228
223
|
let endpoint = `content_types/${content_type_uid}/entries/${entry_uid}/publish`;
|
|
229
|
-
log.debug(`Making API call to: ${endpoint}`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
224
|
+
cli_utilities_1.log.debug(`Making API call to: ${endpoint}`, (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
230
225
|
const onSuccess = (response) => {
|
|
231
226
|
var _a;
|
|
232
|
-
log.debug(`Variant entry published successfully: ${entry_uid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
233
|
-
resolve({ response, apiData: { entryUid: entry_uid, variantUid, locales: input.entry.locales }, log });
|
|
227
|
+
cli_utilities_1.log.debug(`Variant entry published successfully: ${entry_uid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
228
|
+
resolve({ response, apiData: { entryUid: entry_uid, variantUid, locales: input.entry.locales }, log: cli_utilities_1.log });
|
|
234
229
|
};
|
|
235
230
|
const onReject = (error) => {
|
|
236
231
|
var _a;
|
|
237
|
-
log.debug(`Failed to publish variant entry: ${entry_uid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
232
|
+
cli_utilities_1.log.debug(`Failed to publish variant entry: ${entry_uid}`, (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
238
233
|
reject({
|
|
239
234
|
error,
|
|
240
235
|
apiData: { entryUid: entry_uid, variantUid, locales: input.entry.locales },
|
|
241
|
-
log,
|
|
236
|
+
log: cli_utilities_1.log,
|
|
242
237
|
});
|
|
243
238
|
};
|
|
244
239
|
try {
|
|
@@ -275,9 +270,7 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
275
270
|
cli_utilities_1.log.debug(`API request failed with status: ${status}`, (_c = this.exportConfig) === null || _c === void 0 ? void 0 : _c.context);
|
|
276
271
|
// Refresh the access token if the response status is 401
|
|
277
272
|
yield cli_utilities_1.authenticationHandler.refreshAccessToken(res);
|
|
278
|
-
const errorMsg = (data === null || data === void 0 ? void 0 : data.errors)
|
|
279
|
-
? (0, error_helper_1.formatErrors)(data.errors)
|
|
280
|
-
: (data === null || data === void 0 ? void 0 : data.error_message) || (data === null || data === void 0 ? void 0 : data.message) || data;
|
|
273
|
+
const errorMsg = (data === null || data === void 0 ? void 0 : data.errors) ? (0, error_helper_1.formatErrors)(data.errors) : (data === null || data === void 0 ? void 0 : data.error_message) || (data === null || data === void 0 ? void 0 : data.message) || data;
|
|
281
274
|
cli_utilities_1.log.debug(`API error: ${errorMsg}`, (_d = this.exportConfig) === null || _d === void 0 ? void 0 : _d.context);
|
|
282
275
|
throw errorMsg;
|
|
283
276
|
});
|
|
@@ -287,38 +280,27 @@ exports.VariantHttpClient = VariantHttpClient;
|
|
|
287
280
|
class VariantManagementSDK extends adapter_helper_1.AdapterHelper {
|
|
288
281
|
init() {
|
|
289
282
|
return __awaiter(this, void 0, void 0, function* () {
|
|
290
|
-
var _a, _b;
|
|
291
|
-
cli_utilities_1.log.debug('Initializing VariantManagementSDK...', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
292
283
|
this.apiClient = yield (0, cli_utilities_1.managementSDKClient)(this.config);
|
|
293
|
-
cli_utilities_1.log.debug('VariantManagementSDK initialized successfully', (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
294
284
|
});
|
|
295
285
|
}
|
|
296
286
|
variantEntry(options) {
|
|
297
287
|
return __awaiter(this, void 0, void 0, function* () {
|
|
298
|
-
var _a;
|
|
299
|
-
cli_utilities_1.log.debug('VariantEntry method called (SDK placeholder implementation)', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
300
288
|
// TODO SDK implementation
|
|
301
289
|
return { entry: {} };
|
|
302
290
|
});
|
|
303
291
|
}
|
|
304
292
|
variantEntries(options) {
|
|
305
293
|
return __awaiter(this, void 0, void 0, function* () {
|
|
306
|
-
var _a;
|
|
307
|
-
cli_utilities_1.log.debug('VariantEntries method called (SDK placeholder implementation)', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
308
294
|
// TODO SDK implementation
|
|
309
295
|
return { entries: [{}] };
|
|
310
296
|
});
|
|
311
297
|
}
|
|
312
298
|
createVariantEntry(input, options, apiParams) {
|
|
313
|
-
var _a;
|
|
314
|
-
cli_utilities_1.log.debug('CreateVariantEntry method called (SDK placeholder implementation)', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
315
299
|
// FIXME placeholder
|
|
316
300
|
return Promise.resolve({});
|
|
317
301
|
}
|
|
318
302
|
handleVariantAPIRes(res) {
|
|
319
303
|
return __awaiter(this, void 0, void 0, function* () {
|
|
320
|
-
var _a;
|
|
321
|
-
cli_utilities_1.log.debug('HandleVariantAPIRes method called (SDK implementation)', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
322
304
|
return res.data;
|
|
323
305
|
});
|
|
324
306
|
}
|
|
@@ -337,6 +319,9 @@ exports.VariantManagementSDK = VariantManagementSDK;
|
|
|
337
319
|
class VariantAdapter {
|
|
338
320
|
constructor(config, options) {
|
|
339
321
|
var _a, _b, _c, _d;
|
|
322
|
+
this.progressManager = null;
|
|
323
|
+
this.parentProgressManager = null;
|
|
324
|
+
this.currentModuleName = '';
|
|
340
325
|
cli_utilities_1.log.debug('Initializing VariantAdapter...', (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.context);
|
|
341
326
|
if (config.httpClient) {
|
|
342
327
|
cli_utilities_1.log.debug('Using HTTP client variant instance', (_b = this.exportConfig) === null || _b === void 0 ? void 0 : _b.context);
|
|
@@ -351,6 +336,78 @@ class VariantAdapter {
|
|
|
351
336
|
this.messages = messages_1.default;
|
|
352
337
|
cli_utilities_1.log.debug('VariantAdapter initialized successfully', (_d = this.exportConfig) === null || _d === void 0 ? void 0 : _d.context);
|
|
353
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
|
+
}
|
|
354
411
|
}
|
|
355
412
|
exports.VariantAdapter = VariantAdapter;
|
|
356
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",
|
|
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.14.
|
|
30
|
+
"@contentstack/cli-utilities": "~1.14.1",
|
|
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
|
}
|
package/src/export/audiences.ts
CHANGED
|
@@ -1,73 +1,99 @@
|
|
|
1
1
|
import omit from 'lodash/omit';
|
|
2
2
|
import { resolve as pResolve } from 'node:path';
|
|
3
|
-
import { log, handleAndLogError } from '@contentstack/cli-utilities';
|
|
4
|
-
|
|
3
|
+
import { sanitizePath, log, handleAndLogError } from '@contentstack/cli-utilities';
|
|
4
|
+
import { PersonalizeConfig, ExportConfig, AudiencesConfig, AudienceStruct } from '../types';
|
|
5
5
|
import { fsUtil, PersonalizationAdapter } from '../utils';
|
|
6
|
-
import {
|
|
6
|
+
import { PROCESS_NAMES, MODULE_CONTEXTS, EXPORT_PROCESS_STATUS } from '../utils/constants';
|
|
7
7
|
|
|
8
8
|
export default class ExportAudiences extends PersonalizationAdapter<ExportConfig> {
|
|
9
9
|
private audiencesConfig: AudiencesConfig;
|
|
10
10
|
private audiencesFolderPath: string;
|
|
11
11
|
private audiences: Record<string, unknown>[];
|
|
12
|
+
public exportConfig: ExportConfig;
|
|
12
13
|
public personalizeConfig: PersonalizeConfig;
|
|
13
14
|
|
|
14
|
-
constructor(
|
|
15
|
+
constructor(exportConfig: ExportConfig) {
|
|
15
16
|
super({
|
|
16
17
|
config: exportConfig,
|
|
17
18
|
baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
|
|
18
19
|
headers: { 'X-Project-Uid': exportConfig.project_id },
|
|
19
20
|
});
|
|
21
|
+
this.exportConfig = exportConfig;
|
|
20
22
|
this.personalizeConfig = exportConfig.modules.personalize;
|
|
21
23
|
this.audiencesConfig = exportConfig.modules.audiences;
|
|
22
24
|
this.audiencesFolderPath = pResolve(
|
|
23
|
-
exportConfig.data,
|
|
24
|
-
exportConfig.branchName || '',
|
|
25
|
-
this.personalizeConfig.dirName,
|
|
26
|
-
this.audiencesConfig.dirName,
|
|
25
|
+
sanitizePath(exportConfig.data),
|
|
26
|
+
sanitizePath(exportConfig.branchName || ''),
|
|
27
|
+
sanitizePath(this.personalizeConfig.dirName),
|
|
28
|
+
sanitizePath(this.audiencesConfig.dirName),
|
|
27
29
|
);
|
|
28
30
|
this.audiences = [];
|
|
29
|
-
this.exportConfig.context.module =
|
|
31
|
+
this.exportConfig.context.module = MODULE_CONTEXTS.AUDIENCES;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
async start() {
|
|
33
35
|
try {
|
|
34
36
|
log.debug('Starting audiences export process...', this.exportConfig.context);
|
|
35
37
|
log.info('Starting audiences export', this.exportConfig.context);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
38
|
+
|
|
39
|
+
await this.withLoadingSpinner('AUDIENCES: 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 audiences directory at: ${this.audiencesFolderPath}`, this.exportConfig.context);
|
|
45
|
+
await fsUtil.makeDirectory(this.audiencesFolderPath);
|
|
46
|
+
log.debug('Audiences directory created successfully', this.exportConfig.context);
|
|
47
|
+
|
|
48
|
+
log.debug('Fetching audiences from personalization API...', this.exportConfig.context);
|
|
49
|
+
this.audiences = (await this.getAudiences()) as AudienceStruct[];
|
|
50
|
+
log.debug(`Fetched ${this.audiences?.length || 0} audiences`, this.exportConfig.context);
|
|
51
|
+
});
|
|
48
52
|
|
|
49
53
|
if (!this.audiences?.length) {
|
|
50
54
|
log.debug('No audiences found, completing export', this.exportConfig.context);
|
|
51
55
|
log.info('No Audiences found with the given project!', this.exportConfig.context);
|
|
52
56
|
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let progress: any;
|
|
60
|
+
|
|
61
|
+
if (this.parentProgressManager) {
|
|
62
|
+
progress = this.parentProgressManager;
|
|
63
|
+
this.progressManager = this.parentProgressManager;
|
|
64
|
+
progress.updateProcessTotal(PROCESS_NAMES.AUDIENCES, this.audiences.length);
|
|
53
65
|
} else {
|
|
54
|
-
|
|
55
|
-
this.sanitizeAttribs();
|
|
56
|
-
log.debug('Audiences sanitization completed', this.exportConfig.context);
|
|
57
|
-
|
|
58
|
-
const audiencesFilePath = pResolve(this.audiencesFolderPath, this.audiencesConfig.fileName);
|
|
59
|
-
log.debug(`Writing audiences to: ${audiencesFilePath}`, this.exportConfig.context);
|
|
60
|
-
fsUtil.writeFile(audiencesFilePath, this.audiences);
|
|
61
|
-
|
|
62
|
-
log.debug('Audiences export completed successfully', this.exportConfig.context);
|
|
63
|
-
log.success(
|
|
64
|
-
`Audiences exported successfully! Total audiences: ${this.audiences.length}`,
|
|
65
|
-
this.exportConfig.context,
|
|
66
|
-
);
|
|
67
|
-
return;
|
|
66
|
+
progress = this.createSimpleProgress(PROCESS_NAMES.AUDIENCES, this.audiences.length);
|
|
68
67
|
}
|
|
69
|
-
|
|
68
|
+
|
|
69
|
+
log.debug(`Processing ${this.audiences.length} audiences`, this.exportConfig.context);
|
|
70
|
+
progress.updateStatus(EXPORT_PROCESS_STATUS[PROCESS_NAMES.AUDIENCES].EXPORTING, PROCESS_NAMES.AUDIENCES);
|
|
71
|
+
|
|
72
|
+
this.sanitizeAttribs();
|
|
73
|
+
log.debug('Audiences sanitization completed', this.exportConfig.context);
|
|
74
|
+
|
|
75
|
+
// Write audiences to file
|
|
76
|
+
progress.updateStatus(EXPORT_PROCESS_STATUS[PROCESS_NAMES.AUDIENCES].EXPORTING, PROCESS_NAMES.AUDIENCES);
|
|
77
|
+
const audiencesFilePath = pResolve(
|
|
78
|
+
sanitizePath(this.audiencesFolderPath),
|
|
79
|
+
sanitizePath(this.audiencesConfig.fileName),
|
|
80
|
+
);
|
|
81
|
+
log.debug(`Writing audiences to: ${audiencesFilePath}`, this.exportConfig.context);
|
|
82
|
+
fsUtil.writeFile(audiencesFilePath, this.audiences);
|
|
83
|
+
|
|
84
|
+
// Complete progress only if we're managing our own progress
|
|
85
|
+
if (!this.parentProgressManager) {
|
|
86
|
+
this.completeProgress(true);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
log.debug('Audiences export completed successfully', this.exportConfig.context);
|
|
90
|
+
log.success(
|
|
91
|
+
`Audiences exported successfully! Total audiences: ${this.audiences.length}`,
|
|
92
|
+
this.exportConfig.context,
|
|
93
|
+
);
|
|
94
|
+
} catch (error: any) {
|
|
70
95
|
log.debug(`Error occurred during audiences export: ${error}`, this.exportConfig.context);
|
|
96
|
+
this.completeProgress(false, error?.message || 'Audiences export failed');
|
|
71
97
|
handleAndLogError(error, { ...this.exportConfig.context });
|
|
72
98
|
}
|
|
73
99
|
}
|
|
@@ -77,10 +103,30 @@ export default class ExportAudiences extends PersonalizationAdapter<ExportConfig
|
|
|
77
103
|
*/
|
|
78
104
|
sanitizeAttribs() {
|
|
79
105
|
log.debug(`Sanitizing ${this.audiences?.length || 0} audiences`, this.exportConfig.context);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
106
|
+
|
|
107
|
+
this.audiences =
|
|
108
|
+
this.audiences?.map((audience, index) => {
|
|
109
|
+
const sanitizedAudience = omit(audience, this.audiencesConfig.invalidKeys);
|
|
110
|
+
|
|
111
|
+
// Update progress for each processed audience
|
|
112
|
+
if (this.progressManager) {
|
|
113
|
+
const processName = this.parentProgressManager ? PROCESS_NAMES.AUDIENCES : undefined;
|
|
114
|
+
this.updateProgress(
|
|
115
|
+
true,
|
|
116
|
+
`audience ${index + 1}/${this.audiences.length}: ${
|
|
117
|
+
(audience as any).name || (audience as any).uid || 'unknown'
|
|
118
|
+
}`,
|
|
119
|
+
undefined,
|
|
120
|
+
processName,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return sanitizedAudience;
|
|
125
|
+
}) || [];
|
|
126
|
+
|
|
127
|
+
log.debug(
|
|
128
|
+
`Sanitization complete. Total audiences after sanitization: ${this.audiences.length}`,
|
|
129
|
+
this.exportConfig.context,
|
|
130
|
+
);
|
|
85
131
|
}
|
|
86
132
|
}
|