@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
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
managementSDKClient,
|
|
10
10
|
authenticationHandler,
|
|
11
11
|
log,
|
|
12
|
+
CLIProgressManager,
|
|
13
|
+
configHandler,
|
|
12
14
|
} from '@contentstack/cli-utilities';
|
|
13
15
|
|
|
14
16
|
import {
|
|
@@ -39,23 +41,24 @@ export class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implement
|
|
|
39
41
|
super(config, options);
|
|
40
42
|
this.baseURL = config.baseURL?.includes('http') ? `${config.baseURL}/v3` : `https://${config.baseURL}/v3`;
|
|
41
43
|
this.apiClient.baseUrl(this.baseURL);
|
|
42
|
-
log.debug(`VariantHttpClient initialized with base URL: ${this.baseURL}`, this.exportConfig?.context
|
|
44
|
+
log.debug(`VariantHttpClient initialized with base URL: ${this.baseURL}`, this.exportConfig?.context);
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
async init(): Promise<void> {
|
|
46
|
-
log.debug('Initializing VariantHttpClient...', this.exportConfig?.context
|
|
48
|
+
log.debug('Initializing VariantHttpClient...', this.exportConfig?.context);
|
|
47
49
|
await authenticationHandler.getAuthDetails();
|
|
48
50
|
const token = authenticationHandler.accessToken;
|
|
49
|
-
log.debug(
|
|
50
|
-
|
|
51
|
+
log.debug(
|
|
52
|
+
`Authentication type: ${authenticationHandler.isOauthEnabled ? 'OAuth' : 'Token'}`,
|
|
53
|
+
this.exportConfig?.context,
|
|
54
|
+
);
|
|
51
55
|
if (authenticationHandler.isOauthEnabled) {
|
|
52
|
-
log.debug('Setting OAuth authorization header', this.exportConfig?.context
|
|
56
|
+
log.debug('Setting OAuth authorization header', this.exportConfig?.context);
|
|
53
57
|
this.apiClient.headers({ authorization: token });
|
|
54
58
|
} else {
|
|
55
|
-
log.debug('Setting authtoken header', this.exportConfig?.context
|
|
59
|
+
log.debug('Setting authtoken header', this.exportConfig?.context);
|
|
56
60
|
this.apiClient.headers({ authtoken: token });
|
|
57
61
|
}
|
|
58
|
-
log.debug('VariantHttpClient initialization completed', this.exportConfig?.context );
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
async variantEntry(options: VariantOptions) {
|
|
@@ -96,22 +99,28 @@ export class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implement
|
|
|
96
99
|
include_publish_details = variantConfig.query.include_publish_details || true,
|
|
97
100
|
} = options;
|
|
98
101
|
|
|
99
|
-
log.debug(
|
|
100
|
-
|
|
102
|
+
log.debug(
|
|
103
|
+
`Fetching variant entries for content type: ${content_type_uid}, entry: ${entry_uid}, locale: ${locale}`,
|
|
104
|
+
this.exportConfig?.context,
|
|
105
|
+
);
|
|
106
|
+
log.debug(
|
|
107
|
+
`Query parameters - skip: ${skip}, limit: ${limit}, include_variant: ${include_variant}, include_count: ${include_count}, include_publish_details: ${include_publish_details}`,
|
|
108
|
+
this.exportConfig?.context,
|
|
109
|
+
);
|
|
101
110
|
|
|
102
111
|
if (variantConfig.serveMockData && callback) {
|
|
103
|
-
log.debug('Using mock data for variant entries', this.exportConfig?.context
|
|
112
|
+
log.debug('Using mock data for variant entries', this.exportConfig?.context);
|
|
104
113
|
let data = [] as Record<string, any>[];
|
|
105
114
|
|
|
106
115
|
if (existsSync(variantConfig.mockDataPath)) {
|
|
107
|
-
log.debug(`Loading mock data from: ${variantConfig.mockDataPath}`, this.exportConfig?.context
|
|
116
|
+
log.debug(`Loading mock data from: ${variantConfig.mockDataPath}`, this.exportConfig?.context);
|
|
108
117
|
data = require(variantConfig.mockDataPath) as Record<string, any>[];
|
|
109
118
|
}
|
|
110
119
|
callback(data);
|
|
111
120
|
return;
|
|
112
121
|
}
|
|
113
122
|
if (!locale) {
|
|
114
|
-
log.debug('No locale provided, skipping variant entries fetch', this.exportConfig?.context
|
|
123
|
+
log.debug('No locale provided, skipping variant entries fetch', this.exportConfig?.context);
|
|
115
124
|
return;
|
|
116
125
|
}
|
|
117
126
|
|
|
@@ -153,19 +162,22 @@ export class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implement
|
|
|
153
162
|
endpoint = endpoint.concat(query);
|
|
154
163
|
}
|
|
155
164
|
|
|
156
|
-
log.debug(`Making API call to: ${endpoint}`, this.exportConfig?.context
|
|
165
|
+
log.debug(`Making API call to: ${endpoint}`, this.exportConfig?.context);
|
|
157
166
|
const data = await this.apiClient.get(endpoint);
|
|
158
167
|
const response = (await this.handleVariantAPIRes(data)) as { entries: VariantEntryStruct[]; count: number };
|
|
159
|
-
|
|
168
|
+
|
|
160
169
|
if (response?.entries?.length) {
|
|
161
|
-
log.debug(
|
|
170
|
+
log.debug(
|
|
171
|
+
`Received ${response.entries?.length} variant entries out of total ${response.count}`,
|
|
172
|
+
this.exportConfig?.context,
|
|
173
|
+
);
|
|
162
174
|
}
|
|
163
175
|
|
|
164
176
|
if (callback) {
|
|
165
|
-
log.debug('Executing callback with variant entries', this.exportConfig?.context
|
|
177
|
+
log.debug('Executing callback with variant entries', this.exportConfig?.context);
|
|
166
178
|
callback(response.entries);
|
|
167
179
|
} else {
|
|
168
|
-
log.debug('Adding variant entries to collection', this.exportConfig?.context
|
|
180
|
+
log.debug('Adding variant entries to collection', this.exportConfig?.context);
|
|
169
181
|
entries = entries.concat(response.entries);
|
|
170
182
|
}
|
|
171
183
|
|
|
@@ -206,12 +218,15 @@ export class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implement
|
|
|
206
218
|
options: CreateVariantEntryOptions,
|
|
207
219
|
apiParams: Record<string, any>,
|
|
208
220
|
): Promise<VariantEntryStruct | string | void> {
|
|
209
|
-
const { reject, resolve, variantUid
|
|
221
|
+
const { reject, resolve, variantUid } = apiParams;
|
|
210
222
|
const variantConfig = (this.config as ImportConfig).modules.variantEntry;
|
|
211
223
|
const { locale = variantConfig.query.locale || 'en-us', variant_id, entry_uid, content_type_uid } = options;
|
|
212
|
-
|
|
213
|
-
log.debug(
|
|
214
|
-
|
|
224
|
+
|
|
225
|
+
log.debug(
|
|
226
|
+
`Creating variant entry for content type: ${content_type_uid}, entry: ${entry_uid}, variant: ${variant_id}`,
|
|
227
|
+
this.exportConfig?.context,
|
|
228
|
+
);
|
|
229
|
+
|
|
215
230
|
let endpoint = `content_types/${content_type_uid}/entries/${entry_uid}/variants/${variant_id}?locale=${locale}`;
|
|
216
231
|
|
|
217
232
|
const query = this.constructQuery(omit(variantConfig.query, ['locale']));
|
|
@@ -220,14 +235,12 @@ export class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implement
|
|
|
220
235
|
endpoint = endpoint.concat(query);
|
|
221
236
|
}
|
|
222
237
|
|
|
223
|
-
log.debug(`Making API call to: ${endpoint}`, this.exportConfig?.context
|
|
238
|
+
log.debug(`Making API call to: ${endpoint}`, this.exportConfig?.context);
|
|
224
239
|
|
|
225
240
|
const onSuccess = (response: any) => {
|
|
226
|
-
log.debug(`Variant entry created successfully: ${variantUid}`, this.exportConfig?.context );
|
|
227
241
|
resolve({ response, apiData: { variantUid, entryUid: entry_uid }, log });
|
|
228
242
|
};
|
|
229
243
|
const onReject = (error: any) => {
|
|
230
|
-
log.debug(`Failed to create variant entry: ${variantUid}`, this.exportConfig?.context );
|
|
231
244
|
reject({
|
|
232
245
|
error,
|
|
233
246
|
apiData: { variantUid, entryUid: entry_uid },
|
|
@@ -263,14 +276,17 @@ export class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implement
|
|
|
263
276
|
options: PublishVariantEntryOptions,
|
|
264
277
|
apiParams: Record<string, any>,
|
|
265
278
|
) {
|
|
266
|
-
const { reject, resolve,
|
|
279
|
+
const { reject, resolve, variantUid } = apiParams;
|
|
267
280
|
const { entry_uid, content_type_uid } = options;
|
|
268
|
-
|
|
269
|
-
log.debug(
|
|
270
|
-
|
|
281
|
+
|
|
282
|
+
log.debug(
|
|
283
|
+
`Publishing variant entry for content type: ${content_type_uid}, entry: ${entry_uid}`,
|
|
284
|
+
this.exportConfig?.context,
|
|
285
|
+
);
|
|
286
|
+
|
|
271
287
|
let endpoint = `content_types/${content_type_uid}/entries/${entry_uid}/publish`;
|
|
272
288
|
|
|
273
|
-
log.debug(`Making API call to: ${endpoint}`, this.exportConfig?.context
|
|
289
|
+
log.debug(`Making API call to: ${endpoint}`, this.exportConfig?.context);
|
|
274
290
|
|
|
275
291
|
const onSuccess = (response: any) => {
|
|
276
292
|
log.debug(`Variant entry published successfully: ${entry_uid}`, this.exportConfig?.context );
|
|
@@ -310,22 +326,20 @@ export class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implement
|
|
|
310
326
|
res: APIResponse,
|
|
311
327
|
): Promise<VariantEntryStruct | { entries: VariantEntryStruct[]; count: number } | string | any> {
|
|
312
328
|
const { status, data } = res;
|
|
313
|
-
log.debug(`API response status: ${status}`, this.exportConfig?.context
|
|
329
|
+
log.debug(`API response status: ${status}`, this.exportConfig?.context);
|
|
314
330
|
|
|
315
331
|
if (status >= 200 && status < 300) {
|
|
316
|
-
log.debug('API request successful', this.exportConfig?.context
|
|
332
|
+
log.debug('API request successful', this.exportConfig?.context);
|
|
317
333
|
return data;
|
|
318
334
|
}
|
|
319
335
|
|
|
320
|
-
log.debug(`API request failed with status: ${status}`, this.exportConfig?.context
|
|
336
|
+
log.debug(`API request failed with status: ${status}`, this.exportConfig?.context);
|
|
321
337
|
// Refresh the access token if the response status is 401
|
|
322
338
|
await authenticationHandler.refreshAccessToken(res);
|
|
323
339
|
|
|
324
|
-
const errorMsg = data?.errors
|
|
325
|
-
? formatErrors(data.errors)
|
|
326
|
-
: data?.error_message || data?.message || data;
|
|
340
|
+
const errorMsg = data?.errors ? formatErrors(data.errors) : data?.error_message || data?.message || data;
|
|
327
341
|
|
|
328
|
-
log.debug(`API error: ${errorMsg}`, this.exportConfig?.context
|
|
342
|
+
log.debug(`API error: ${errorMsg}`, this.exportConfig?.context);
|
|
329
343
|
throw errorMsg;
|
|
330
344
|
}
|
|
331
345
|
}
|
|
@@ -338,19 +352,15 @@ export class VariantManagementSDK<T>
|
|
|
338
352
|
public exportConfig?: any;
|
|
339
353
|
|
|
340
354
|
async init(): Promise<void> {
|
|
341
|
-
log.debug('Initializing VariantManagementSDK...', this.exportConfig?.context );
|
|
342
355
|
this.apiClient = await managementSDKClient(this.config);
|
|
343
|
-
log.debug('VariantManagementSDK initialized successfully', this.exportConfig?.context );
|
|
344
356
|
}
|
|
345
357
|
|
|
346
358
|
async variantEntry(options: VariantOptions) {
|
|
347
|
-
log.debug('VariantEntry method called (SDK placeholder implementation)', this.exportConfig?.context );
|
|
348
359
|
// TODO SDK implementation
|
|
349
360
|
return { entry: {} };
|
|
350
361
|
}
|
|
351
362
|
|
|
352
363
|
async variantEntries(options: VariantsOption) {
|
|
353
|
-
log.debug('VariantEntries method called (SDK placeholder implementation)', this.exportConfig?.context );
|
|
354
364
|
// TODO SDK implementation
|
|
355
365
|
return { entries: [{}] };
|
|
356
366
|
}
|
|
@@ -360,7 +370,6 @@ export class VariantManagementSDK<T>
|
|
|
360
370
|
options: CreateVariantEntryOptions,
|
|
361
371
|
apiParams: Record<string, any>,
|
|
362
372
|
): Promise<VariantEntryStruct | string | void> {
|
|
363
|
-
log.debug('CreateVariantEntry method called (SDK placeholder implementation)', this.exportConfig?.context );
|
|
364
373
|
// FIXME placeholder
|
|
365
374
|
return Promise.resolve({} as VariantEntryStruct);
|
|
366
375
|
}
|
|
@@ -368,16 +377,15 @@ export class VariantManagementSDK<T>
|
|
|
368
377
|
async handleVariantAPIRes(
|
|
369
378
|
res: APIResponse,
|
|
370
379
|
): Promise<VariantEntryStruct | { entries: VariantEntryStruct[]; count: number } | string> {
|
|
371
|
-
log.debug('HandleVariantAPIRes method called (SDK implementation)', this.exportConfig?.context );
|
|
372
380
|
return res.data;
|
|
373
381
|
}
|
|
374
382
|
|
|
375
383
|
constructQuery(query: Record<string, any>): string | void {
|
|
376
|
-
log.debug('ConstructQuery method called (SDK placeholder implementation)', this.exportConfig?.context
|
|
384
|
+
log.debug('ConstructQuery method called (SDK placeholder implementation)', this.exportConfig?.context);
|
|
377
385
|
}
|
|
378
386
|
|
|
379
387
|
async delay(ms: number): Promise<void> {
|
|
380
|
-
log.debug(`Delay method called for ${ms}ms (SDK placeholder implementation)`, this.exportConfig?.context
|
|
388
|
+
log.debug(`Delay method called for ${ms}ms (SDK placeholder implementation)`, this.exportConfig?.context);
|
|
381
389
|
}
|
|
382
390
|
}
|
|
383
391
|
|
|
@@ -385,6 +393,9 @@ export class VariantAdapter<T> {
|
|
|
385
393
|
protected variantInstance;
|
|
386
394
|
public readonly messages: typeof messages;
|
|
387
395
|
public exportConfig?: any;
|
|
396
|
+
protected progressManager: CLIProgressManager | null = null;
|
|
397
|
+
protected parentProgressManager: CLIProgressManager | null = null;
|
|
398
|
+
protected currentModuleName: string = '';
|
|
388
399
|
|
|
389
400
|
constructor(config: ContentstackConfig & AnyProperty & AdapterType<T, ContentstackConfig>);
|
|
390
401
|
constructor(config: APIConfig & AdapterType<T, APIConfig & AnyProperty>, options?: HttpClientOptions);
|
|
@@ -392,21 +403,97 @@ export class VariantAdapter<T> {
|
|
|
392
403
|
config: APIConfig & AdapterType<T, (APIConfig & AnyProperty) | ContentstackConfig>,
|
|
393
404
|
options?: HttpClientOptions,
|
|
394
405
|
) {
|
|
395
|
-
log.debug('Initializing VariantAdapter...', this.exportConfig?.context
|
|
396
|
-
|
|
406
|
+
log.debug('Initializing VariantAdapter...', this.exportConfig?.context);
|
|
407
|
+
|
|
397
408
|
if (config.httpClient) {
|
|
398
|
-
log.debug('Using HTTP client variant instance', this.exportConfig?.context
|
|
409
|
+
log.debug('Using HTTP client variant instance', this.exportConfig?.context);
|
|
399
410
|
const { httpClient, Adapter, ...restConfig } = config;
|
|
400
411
|
this.variantInstance = new Adapter(restConfig, options);
|
|
401
412
|
} else {
|
|
402
|
-
log.debug('Using SDK variant instance', this.exportConfig?.context
|
|
413
|
+
log.debug('Using SDK variant instance', this.exportConfig?.context);
|
|
403
414
|
const { Adapter, ...restConfig } = config;
|
|
404
415
|
this.variantInstance = new Adapter(restConfig);
|
|
405
416
|
}
|
|
406
417
|
|
|
407
418
|
this.messages = messages;
|
|
408
|
-
log.debug('VariantAdapter initialized successfully', this.exportConfig?.context
|
|
419
|
+
log.debug('VariantAdapter initialized successfully', this.exportConfig?.context);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Set parent progress manager for sub-module integration
|
|
424
|
+
*/
|
|
425
|
+
public setParentProgressManager(parentProgress: CLIProgressManager): void {
|
|
426
|
+
this.parentProgressManager = parentProgress;
|
|
427
|
+
this.progressManager = parentProgress;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Create simple progress manager for single process tracking
|
|
432
|
+
*/
|
|
433
|
+
protected createSimpleProgress(moduleName: string, total?: number): CLIProgressManager {
|
|
434
|
+
this.currentModuleName = moduleName;
|
|
435
|
+
|
|
436
|
+
// If we have a parent progress manager, use it instead of creating a new one
|
|
437
|
+
if (this.parentProgressManager) {
|
|
438
|
+
this.progressManager = this.parentProgressManager;
|
|
439
|
+
return this.progressManager;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const logConfig = configHandler.get('log') || {};
|
|
443
|
+
const showConsoleLogs = logConfig.showConsoleLogs ?? false;
|
|
444
|
+
this.progressManager = CLIProgressManager.createSimple(moduleName, total, showConsoleLogs);
|
|
445
|
+
return this.progressManager;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Create nested progress manager for multi-process tracking
|
|
450
|
+
*/
|
|
451
|
+
protected createNestedProgress(moduleName: string): CLIProgressManager {
|
|
452
|
+
this.currentModuleName = moduleName;
|
|
453
|
+
|
|
454
|
+
// If we have a parent progress manager, use it instead of creating a new one
|
|
455
|
+
if (this.parentProgressManager) {
|
|
456
|
+
this.progressManager = this.parentProgressManager;
|
|
457
|
+
return this.progressManager;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const logConfig = configHandler.get('log') || {};
|
|
461
|
+
const showConsoleLogs = logConfig.showConsoleLogs ?? false;
|
|
462
|
+
this.progressManager = CLIProgressManager.createNested(moduleName, showConsoleLogs);
|
|
463
|
+
return this.progressManager;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Complete progress manager
|
|
468
|
+
*/
|
|
469
|
+
protected completeProgress(success: boolean = true, error?: string): void {
|
|
470
|
+
// Only complete progress if we own the progress manager (no parent)
|
|
471
|
+
if (!this.parentProgressManager) {
|
|
472
|
+
this.progressManager?.complete(success, error);
|
|
473
|
+
}
|
|
474
|
+
this.progressManager = null;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Execute action with loading spinner for initial setup tasks
|
|
479
|
+
*/
|
|
480
|
+
protected async withLoadingSpinner<T>(message: string, action: () => Promise<T>): Promise<T> {
|
|
481
|
+
const logConfig = configHandler.get('log') || {};
|
|
482
|
+
const showConsoleLogs = logConfig.showConsoleLogs ?? false;
|
|
483
|
+
|
|
484
|
+
if (showConsoleLogs) {
|
|
485
|
+
// If console logs are enabled, don't show spinner, just execute the action
|
|
486
|
+
return await action();
|
|
487
|
+
}
|
|
488
|
+
return await CLIProgressManager.withLoadingSpinner(message, action);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Update progress for a specific item
|
|
493
|
+
*/
|
|
494
|
+
protected updateProgress(success: boolean, itemName: string, error?: string, processName?: string): void {
|
|
495
|
+
this.progressManager?.tick(success, itemName, error, processName);
|
|
409
496
|
}
|
|
410
497
|
}
|
|
411
498
|
|
|
412
|
-
export default VariantAdapter;
|
|
499
|
+
export default VariantAdapter;
|
package/tsconfig.json
CHANGED