@contentstack/cli-variants 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/export/attributes.js +27 -10
  2. package/lib/export/audiences.js +28 -10
  3. package/lib/export/events.js +28 -10
  4. package/lib/export/experiences.js +48 -13
  5. package/lib/export/projects.js +24 -6
  6. package/lib/export/variant-entries.js +25 -4
  7. package/lib/import/attribute.d.ts +2 -3
  8. package/lib/import/attribute.js +16 -8
  9. package/lib/import/audiences.d.ts +2 -3
  10. package/lib/import/audiences.js +21 -8
  11. package/lib/import/events.d.ts +3 -4
  12. package/lib/import/events.js +16 -9
  13. package/lib/import/experiences.d.ts +2 -3
  14. package/lib/import/experiences.js +60 -17
  15. package/lib/import/project.d.ts +2 -3
  16. package/lib/import/project.js +11 -6
  17. package/lib/import/variant-entries.js +62 -25
  18. package/lib/types/export-config.d.ts +2 -1
  19. package/lib/types/utils.d.ts +11 -0
  20. package/lib/utils/attributes-helper.js +17 -1
  21. package/lib/utils/audiences-helper.js +37 -6
  22. package/lib/utils/events-helper.js +17 -4
  23. package/lib/utils/personalization-api-adapter.d.ts +2 -1
  24. package/lib/utils/personalization-api-adapter.js +119 -27
  25. package/lib/utils/variant-api-adapter.d.ts +4 -1
  26. package/lib/utils/variant-api-adapter.js +91 -17
  27. package/package.json +5 -2
  28. package/src/export/attributes.ts +34 -10
  29. package/src/export/audiences.ts +35 -7
  30. package/src/export/events.ts +35 -7
  31. package/src/export/experiences.ts +74 -24
  32. package/src/export/projects.ts +31 -7
  33. package/src/export/variant-entries.ts +47 -12
  34. package/src/import/attribute.ts +22 -9
  35. package/src/import/audiences.ts +28 -10
  36. package/src/import/events.ts +21 -10
  37. package/src/import/experiences.ts +74 -20
  38. package/src/import/project.ts +22 -8
  39. package/src/import/variant-entries.ts +116 -40
  40. package/src/types/export-config.ts +2 -1
  41. package/src/types/utils.ts +12 -0
  42. package/src/utils/attributes-helper.ts +21 -2
  43. package/src/utils/audiences-helper.ts +41 -1
  44. package/src/utils/events-helper.ts +19 -1
  45. package/src/utils/personalization-api-adapter.ts +95 -19
  46. package/src/utils/variant-api-adapter.ts +79 -8
@@ -1,7 +1,7 @@
1
1
  import omit from 'lodash/omit';
2
2
  import { resolve as pResolve } from 'node:path';
3
- import { sanitizePath } from '@contentstack/cli-utilities';
4
- import { formatError, fsUtil, PersonalizationAdapter, log } from '../utils';
3
+ import { sanitizePath, log, handleAndLogError } from '@contentstack/cli-utilities';
4
+ import {fsUtil, PersonalizationAdapter } from '../utils';
5
5
  import { PersonalizeConfig, ExportConfig, AttributesConfig, AttributeStruct } from '../types';
6
6
 
7
7
  export default class ExportAttributes extends PersonalizationAdapter<ExportConfig> {
@@ -16,6 +16,7 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
16
16
  baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
17
17
  headers: { 'X-Project-Uid': exportConfig.project_id },
18
18
  });
19
+ this.exportConfig = exportConfig;
19
20
  this.personalizeConfig = exportConfig.modules.personalize;
20
21
  this.attributesConfig = exportConfig.modules.attributes;
21
22
  this.attributesFolderPath = pResolve(
@@ -25,28 +26,46 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
25
26
  sanitizePath(this.attributesConfig.dirName),
26
27
  );
27
28
  this.attributes = [];
29
+ this.exportConfig.context.module = 'attributes';
28
30
  }
29
31
 
30
32
  async start() {
31
33
  try {
32
- log(this.exportConfig, 'Starting attributes export', 'info');
34
+ log.info('Starting attributes export', this.exportConfig.context);
35
+
36
+ log.debug('Initializing personalization adapter...', this.exportConfig.context);
33
37
  await this.init();
38
+ log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
39
+
40
+ log.debug(`Creating attributes directory at: ${this.attributesFolderPath}`, this.exportConfig.context);
34
41
  await fsUtil.makeDirectory(this.attributesFolderPath);
42
+ log.debug('Attributes directory created successfully', this.exportConfig.context);
43
+
44
+ log.debug('Fetching attributes from personalization API...', this.exportConfig.context);
35
45
  this.attributes = (await this.getAttributes()) as AttributeStruct[];
46
+ log.debug(`Fetched ${this.attributes?.length || 0} attributes`, this.exportConfig.context);
36
47
 
37
48
  if (!this.attributes?.length) {
38
- log(this.exportConfig, 'No Attributes found with the given project!', 'info');
49
+ log.debug('No attributes found, completing export', this.exportConfig.context);
50
+ log.info('No Attributes found with the given project!', this.exportConfig.context);
39
51
  } else {
52
+ log.debug(`Processing ${this.attributes.length} attributes`, this.exportConfig.context);
40
53
  this.sanitizeAttribs();
41
- fsUtil.writeFile(
42
- pResolve(sanitizePath(this.attributesFolderPath), sanitizePath(this.attributesConfig.fileName)),
43
- this.attributes,
54
+ log.debug('Attributes sanitization completed', this.exportConfig.context);
55
+
56
+ const attributesFilePath = pResolve(sanitizePath(this.attributesFolderPath), sanitizePath(this.attributesConfig.fileName));
57
+ log.debug(`Writing attributes to: ${attributesFilePath}`, this.exportConfig.context);
58
+ fsUtil.writeFile(attributesFilePath, this.attributes);
59
+
60
+ log.debug('Attributes export completed successfully', this.exportConfig.context);
61
+ log.success(
62
+ `Attributes exported successfully! Total attributes: ${this.attributes.length}`,
63
+ this.exportConfig.context,
44
64
  );
45
- log(this.exportConfig, 'All the attributes have been exported successfully!', 'success');
46
65
  }
47
66
  } catch (error) {
48
- log(this.exportConfig, `Failed to export attributes!`, 'error');
49
- log(this.config, error, 'error');
67
+ log.debug(`Error occurred during attributes export: ${error}`, this.exportConfig.context);
68
+ handleAndLogError(error, { ...this.exportConfig.context });
50
69
  }
51
70
  }
52
71
 
@@ -54,6 +73,11 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
54
73
  * function to remove invalid keys from attributes object
55
74
  */
56
75
  sanitizeAttribs() {
76
+ log.debug(`Sanitizing ${this.attributes?.length || 0} attributes`, this.exportConfig.context);
77
+ log.debug(`Invalid keys to remove: ${JSON.stringify(this.attributesConfig.invalidKeys)}`, this.exportConfig.context);
78
+
57
79
  this.attributes = this.attributes?.map((audience) => omit(audience, this.attributesConfig.invalidKeys)) || [];
80
+
81
+ log.debug(`Sanitization complete. Total attributes after sanitization: ${this.attributes.length}`, this.exportConfig.context);
58
82
  }
59
83
  }
@@ -1,7 +1,8 @@
1
1
  import omit from 'lodash/omit';
2
2
  import { resolve as pResolve } from 'node:path';
3
+ import { log, handleAndLogError } from '@contentstack/cli-utilities';
3
4
 
4
- import { formatError, fsUtil, PersonalizationAdapter, log } from '../utils';
5
+ import { fsUtil, PersonalizationAdapter } from '../utils';
5
6
  import { PersonalizeConfig, ExportConfig, AudienceStruct, AudiencesConfig } from '../types';
6
7
 
7
8
  export default class ExportAudiences extends PersonalizationAdapter<ExportConfig> {
@@ -25,27 +26,49 @@ export default class ExportAudiences extends PersonalizationAdapter<ExportConfig
25
26
  this.audiencesConfig.dirName,
26
27
  );
27
28
  this.audiences = [];
29
+ this.exportConfig.context.module = 'audiences';
28
30
  }
29
31
 
30
32
  async start() {
31
33
  try {
32
- log(this.exportConfig, 'Starting audiences export', 'info');
34
+ log.debug('Starting audiences export process...', this.exportConfig.context);
35
+ log.info('Starting audiences export', this.exportConfig.context);
36
+
37
+ log.debug('Initializing personalization adapter...', this.exportConfig.context);
33
38
  await this.init();
39
+ log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
40
+
41
+ log.debug(`Creating audiences directory at: ${this.audiencesFolderPath}`, this.exportConfig.context);
34
42
  await fsUtil.makeDirectory(this.audiencesFolderPath);
43
+ log.debug('Audiences directory created successfully', this.exportConfig.context);
44
+
45
+ log.debug('Fetching audiences from personalization API...', this.exportConfig.context);
35
46
  this.audiences = (await this.getAudiences()) as AudienceStruct[];
47
+ log.debug(`Fetched ${this.audiences?.length || 0} audiences`, this.exportConfig.context);
36
48
 
37
49
  if (!this.audiences?.length) {
38
- log(this.exportConfig, 'No Audiences found with the given project!', 'info');
50
+ log.debug('No audiences found, completing export', this.exportConfig.context);
51
+ log.info('No Audiences found with the given project!', this.exportConfig.context);
39
52
  return;
40
53
  } else {
54
+ log.debug(`Processing ${this.audiences.length} audiences`, this.exportConfig.context);
41
55
  this.sanitizeAttribs();
42
- fsUtil.writeFile(pResolve(this.audiencesFolderPath, this.audiencesConfig.fileName), this.audiences);
43
- log(this.exportConfig, 'All the audiences have been exported successfully!', 'success');
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
+ );
44
67
  return;
45
68
  }
46
69
  } catch (error) {
47
- log(this.exportConfig, `Failed to export audiences!`, 'error');
48
- log(this.config, error, 'error');
70
+ log.debug(`Error occurred during audiences export: ${error}`, this.exportConfig.context);
71
+ handleAndLogError(error, { ...this.exportConfig.context });
49
72
  }
50
73
  }
51
74
 
@@ -53,6 +76,11 @@ export default class ExportAudiences extends PersonalizationAdapter<ExportConfig
53
76
  * function to remove invalid keys from audience object
54
77
  */
55
78
  sanitizeAttribs() {
79
+ log.debug(`Sanitizing ${this.audiences?.length || 0} audiences`, this.exportConfig.context);
80
+ log.debug(`Invalid keys to remove: ${JSON.stringify(this.audiencesConfig.invalidKeys)}`, this.exportConfig.context);
81
+
56
82
  this.audiences = this.audiences?.map((audience) => omit(audience, this.audiencesConfig.invalidKeys)) || [];
83
+
84
+ log.debug(`Sanitization complete. Total audiences after sanitization: ${this.audiences.length}`, this.exportConfig.context);
57
85
  }
58
86
  }
@@ -1,7 +1,8 @@
1
1
  import omit from 'lodash/omit';
2
2
  import { resolve as pResolve } from 'node:path';
3
+ import { log, handleAndLogError } from '@contentstack/cli-utilities';
3
4
 
4
- import { formatError, fsUtil, PersonalizationAdapter, log } from '../utils';
5
+ import { fsUtil, PersonalizationAdapter } from '../utils';
5
6
  import { PersonalizeConfig, ExportConfig, EventStruct, EventsConfig } from '../types';
6
7
 
7
8
  export default class ExportEvents extends PersonalizationAdapter<ExportConfig> {
@@ -25,27 +26,49 @@ export default class ExportEvents extends PersonalizationAdapter<ExportConfig> {
25
26
  this.eventsConfig.dirName,
26
27
  );
27
28
  this.events = [];
29
+ this.exportConfig.context.module = 'events';
28
30
  }
29
31
 
30
32
  async start() {
31
33
  try {
32
- log(this.exportConfig, 'Starting events export', 'info');
34
+ log.debug('Starting events export process...', this.exportConfig.context);
35
+ log.info('Starting events export', this.exportConfig.context);
36
+
37
+ log.debug('Initializing personalization adapter...', this.exportConfig.context);
33
38
  await this.init();
39
+ log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
40
+
41
+ log.debug(`Creating events directory at: ${this.eventsFolderPath}`, this.exportConfig.context);
34
42
  await fsUtil.makeDirectory(this.eventsFolderPath);
43
+ log.debug('Events directory created successfully', this.exportConfig.context);
44
+
45
+ log.debug('Fetching events from personalization API...', this.exportConfig.context);
35
46
  this.events = (await this.getEvents()) as EventStruct[];
47
+ log.debug(`Fetched ${this.events?.length || 0} events`, this.exportConfig.context);
36
48
 
37
49
  if (!this.events?.length) {
38
- log(this.exportConfig, 'No Events found with the given project!', 'info');
50
+ log.debug('No events found, completing export', this.exportConfig.context);
51
+ log.info('No Events found with the given project!', this.exportConfig.context);
39
52
  return;
40
53
  } else {
54
+ log.debug(`Processing ${this.events.length} events`, this.exportConfig.context);
41
55
  this.sanitizeAttribs();
42
- fsUtil.writeFile(pResolve(this.eventsFolderPath, this.eventsConfig.fileName), this.events);
43
- log(this.exportConfig, 'All the events have been exported successfully!', 'success');
56
+ log.debug('Events sanitization completed', this.exportConfig.context);
57
+
58
+ const eventsFilePath = pResolve(this.eventsFolderPath, this.eventsConfig.fileName);
59
+ log.debug(`Writing events to: ${eventsFilePath}`, this.exportConfig.context);
60
+ fsUtil.writeFile(eventsFilePath, this.events);
61
+
62
+ log.debug('Events export completed successfully', this.exportConfig.context);
63
+ log.success(
64
+ `Events exported successfully! Total events: ${this.events.length}`,
65
+ this.exportConfig.context,
66
+ );
44
67
  return;
45
68
  }
46
69
  } catch (error) {
47
- log(this.exportConfig, `Failed to export events!`, 'error');
48
- log(this.config, error, 'error');
70
+ log.debug(`Error occurred during events export: ${error}`, this.exportConfig.context);
71
+ handleAndLogError(error, { ...this.exportConfig.context });
49
72
  }
50
73
  }
51
74
 
@@ -53,6 +76,11 @@ export default class ExportEvents extends PersonalizationAdapter<ExportConfig> {
53
76
  * function to remove invalid keys from event object
54
77
  */
55
78
  sanitizeAttribs() {
79
+ log.debug(`Sanitizing ${this.events?.length || 0} events`, this.exportConfig.context);
80
+ log.debug(`Invalid keys to remove: ${JSON.stringify(this.eventsConfig.invalidKeys)}`, this.exportConfig.context);
81
+
56
82
  this.events = this.events?.map((event) => omit(event, this.eventsConfig.invalidKeys)) || [];
83
+
84
+ log.debug(`Sanitization complete. Total events after sanitization: ${this.events.length}`, this.exportConfig.context);
57
85
  }
58
86
  }
@@ -1,7 +1,7 @@
1
1
  import * as path from 'path';
2
- import { sanitizePath } from '@contentstack/cli-utilities';
2
+ import { sanitizePath, log, handleAndLogError } from '@contentstack/cli-utilities';
3
3
  import { PersonalizeConfig, ExportConfig, ExperienceStruct } from '../types';
4
- import { formatError, fsUtil, log, PersonalizationAdapter } from '../utils';
4
+ import { fsUtil, PersonalizationAdapter } from '../utils';
5
5
 
6
6
  export default class ExportExperiences extends PersonalizationAdapter<ExportConfig> {
7
7
  private experiencesFolderPath: string;
@@ -25,6 +25,7 @@ export default class ExportExperiences extends PersonalizationAdapter<ExportConf
25
25
  sanitizePath(this.personalizeConfig.dirName),
26
26
  'experiences',
27
27
  );
28
+ this.exportConfig.context.module = 'experiences';
28
29
  }
29
30
 
30
31
  async start() {
@@ -32,66 +33,115 @@ export default class ExportExperiences extends PersonalizationAdapter<ExportConf
32
33
  // get all experiences
33
34
  // loop through experiences and get content types attached to it
34
35
  // write experiences in to a file
35
- log(this.exportConfig, 'Starting experiences export', 'info');
36
+ log.debug('Starting experiences export process...', this.exportConfig.context);
37
+ log.info('Starting experiences export', this.exportConfig.context);
38
+
39
+ log.debug('Initializing personalization adapter...', this.exportConfig.context);
36
40
  await this.init();
41
+ log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
42
+
43
+ log.debug(`Creating experiences directory at: ${this.experiencesFolderPath}`, this.exportConfig.context);
37
44
  await fsUtil.makeDirectory(this.experiencesFolderPath);
38
- await fsUtil.makeDirectory(path.resolve(sanitizePath(this.experiencesFolderPath), 'versions'));
45
+ log.debug('Experiences directory created successfully', this.exportConfig.context);
46
+
47
+ const versionsDirPath = path.resolve(sanitizePath(this.experiencesFolderPath), 'versions');
48
+ log.debug(`Creating versions directory at: ${versionsDirPath}`, this.exportConfig.context);
49
+ await fsUtil.makeDirectory(versionsDirPath);
50
+ log.debug('Versions directory created successfully', this.exportConfig.context);
51
+
52
+ log.debug('Fetching experiences from personalization API...', this.exportConfig.context);
39
53
  const experiences: Array<ExperienceStruct> = (await this.getExperiences()) || [];
54
+ log.debug(`Fetched ${experiences?.length || 0} experiences`, this.exportConfig.context);
55
+
40
56
  if (!experiences || experiences?.length < 1) {
41
- log(this.exportConfig, 'No Experiences found with the give project', 'info');
57
+ log.debug('No experiences found, completing export', this.exportConfig.context);
58
+ log.info('No Experiences found with the given project!', this.exportConfig.context);
42
59
  return;
43
60
  }
44
- fsUtil.writeFile(path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences.json'), experiences);
61
+
62
+ const experiencesFilePath = path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences.json');
63
+ log.debug(`Writing experiences to: ${experiencesFilePath}`, this.exportConfig.context);
64
+ fsUtil.writeFile(experiencesFilePath, experiences);
45
65
 
46
66
  const experienceToVariantsStrList: Array<string> = [];
47
67
  const experienceToContentTypesMap: Record<string, string[]> = {};
68
+
69
+ log.debug(`Processing ${experiences.length} experiences for variants and content types`, this.exportConfig.context);
70
+
48
71
  for (let experience of experiences) {
72
+ log.debug(`Processing experience: ${experience.name} (${experience.uid})`, this.exportConfig.context);
73
+
49
74
  // create id mapper for experience to variants
50
75
  let variants = experience?._cms?.variants ?? {};
76
+ log.debug(`Found ${Object.keys(variants).length} variants for experience: ${experience.name}`, this.exportConfig.context);
77
+
51
78
  Object.keys(variants).forEach((variantShortId: string) => {
52
79
  const experienceToVariantsStr = `${experience.uid}-${variantShortId}-${variants[variantShortId]}`;
53
80
  experienceToVariantsStrList.push(experienceToVariantsStr);
81
+ log.debug(`Added variant mapping: ${experienceToVariantsStr}`, this.exportConfig.context);
54
82
  });
55
83
 
56
84
  try {
57
85
  // fetch versions of experience
86
+ log.debug(`Fetching versions for experience: ${experience.name}`, this.exportConfig.context);
58
87
  const experienceVersions = (await this.getExperienceVersions(experience.uid)) || [];
88
+ log.debug(`Fetched ${experienceVersions.length} versions for experience: ${experience.name}`, this.exportConfig.context);
89
+
59
90
  if (experienceVersions.length > 0) {
60
- fsUtil.writeFile(
61
- path.resolve(sanitizePath(this.experiencesFolderPath), 'versions', `${experience.uid}.json`),
62
- experienceVersions,
63
- );
91
+ const versionsFilePath = path.resolve(sanitizePath(this.experiencesFolderPath), 'versions', `${experience.uid}.json`);
92
+ log.debug(`Writing experience versions to: ${versionsFilePath}`, this.exportConfig.context);
93
+ fsUtil.writeFile(versionsFilePath, experienceVersions);
64
94
  } else {
65
- log(this.exportConfig, `No versions found for experience ${experience.name}`, 'info');
95
+ log.debug(`No versions found for experience: ${experience.name}`, this.exportConfig.context);
96
+ log.info(
97
+ `No versions found for experience '${experience.name}'`,
98
+ this.exportConfig.context,
99
+ );
66
100
  }
67
101
  } catch (error) {
68
- log(this.exportConfig, `Failed to fetch versions of experience ${experience.name}`, 'error');
102
+ log.debug(`Error occurred while fetching versions for experience: ${experience.name}`, this.exportConfig.context);
103
+ handleAndLogError(
104
+ error,
105
+ {...this.exportConfig.context},
106
+ `Failed to fetch versions of experience ${experience.name}`
107
+ );
69
108
  }
70
109
 
71
110
  try {
72
111
  // fetch content of experience
112
+ log.debug(`Fetching variant group for experience: ${experience.name}`, this.exportConfig.context);
73
113
  const { variant_groups: [variantGroup] = [] } =
74
114
  (await this.getVariantGroup({ experienceUid: experience.uid })) || {};
115
+
75
116
  if (variantGroup?.content_types?.length) {
117
+ log.debug(`Found ${variantGroup.content_types.length} content types for experience: ${experience.name}`, this.exportConfig.context);
76
118
  experienceToContentTypesMap[experience.uid] = variantGroup.content_types;
119
+ } else {
120
+ log.debug(`No content types found for experience: ${experience.name}`, this.exportConfig.context);
77
121
  }
78
122
  } catch (error) {
79
- log(this.exportConfig, `Failed to fetch content types of experience ${experience.name}`, 'error');
123
+ log.debug(`Error occurred while fetching content types for experience: ${experience.name}`, this.exportConfig.context);
124
+ handleAndLogError(
125
+ error,
126
+ {...this.exportConfig.context},
127
+ `Failed to fetch content types of experience ${experience.name}`
128
+ );
80
129
  }
81
130
  }
82
- fsUtil.writeFile(
83
- path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences-variants-ids.json'),
84
- experienceToVariantsStrList,
85
- );
131
+
132
+ const variantsIdsFilePath = path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences-variants-ids.json');
133
+ log.debug(`Writing experience variants mapping to: ${variantsIdsFilePath}`, this.exportConfig.context);
134
+ fsUtil.writeFile(variantsIdsFilePath, experienceToVariantsStrList);
86
135
 
87
- fsUtil.writeFile(
88
- path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences-content-types.json'),
89
- experienceToContentTypesMap,
90
- );
91
- log(this.exportConfig, 'All the experiences have been exported successfully!', 'success');
136
+ const contentTypesFilePath = path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences-content-types.json');
137
+ log.debug(`Writing experience content types mapping to: ${contentTypesFilePath}`, this.exportConfig.context);
138
+ fsUtil.writeFile(contentTypesFilePath, experienceToContentTypesMap);
139
+
140
+ log.debug('Experiences export completed successfully', this.exportConfig.context);
141
+ log.success('Experiences exported successfully!', this.exportConfig.context);
92
142
  } catch (error) {
93
- log(this.exportConfig, `Failed to export experiences!`, 'error');
94
- log(this.config, error, 'error');
143
+ log.debug(`Error occurred during experiences export: ${error}`, this.exportConfig.context);
144
+ handleAndLogError(error, {...this.exportConfig.context});
95
145
  }
96
146
  }
97
147
  }
@@ -1,7 +1,7 @@
1
1
  import * as path from 'path';
2
- import { sanitizePath } from '@contentstack/cli-utilities';
2
+ import { sanitizePath, log } from '@contentstack/cli-utilities';
3
3
  import { ExportConfig, PersonalizeConfig } from '../types';
4
- import { PersonalizationAdapter, log, fsUtil, formatError } from '../utils';
4
+ import { PersonalizationAdapter, fsUtil, } from '../utils';
5
5
 
6
6
  export default class ExportProjects extends PersonalizationAdapter<ExportConfig> {
7
7
  private projectFolderPath: string;
@@ -21,26 +21,50 @@ export default class ExportProjects extends PersonalizationAdapter<ExportConfig>
21
21
  sanitizePath(this.personalizeConfig.dirName),
22
22
  'projects',
23
23
  );
24
+ this.exportConfig.context.module = 'projects';
24
25
  }
25
26
 
26
27
  async start() {
27
28
  try {
28
- log(this.exportConfig, 'Starting projects export', 'info');
29
+ log.debug('Starting projects export process...', this.exportConfig.context);
30
+ log.info(`Starting projects export`, this.exportConfig.context);
31
+
32
+ log.debug('Initializing personalization adapter...', this.exportConfig.context);
29
33
  await this.init();
34
+ log.debug('Personalization adapter initialized successfully', this.exportConfig.context);
35
+
36
+ log.debug(`Creating projects directory at: ${this.projectFolderPath}`, this.exportConfig.context);
30
37
  await fsUtil.makeDirectory(this.projectFolderPath);
38
+ log.debug('Projects directory created successfully', this.exportConfig.context);
39
+
40
+ log.debug(`Fetching projects for stack API key: ${this.exportConfig.apiKey}`, this.exportConfig.context);
31
41
  const project = await this.projects({ connectedStackApiKey: this.exportConfig.apiKey });
42
+ log.debug(`Fetched ${project?.length || 0} projects`, this.exportConfig.context);
43
+
32
44
  if (!project || project?.length < 1) {
33
- log(this.exportConfig, 'No Personalize Project connected with the given stack', 'info');
45
+ log.debug('No projects found, disabling personalization', this.exportConfig.context);
46
+ log.info(`No Personalize Project connected with the given stack`, this.exportConfig.context);
34
47
  this.exportConfig.personalizationEnabled = false;
35
48
  return;
36
49
  }
50
+
51
+ log.debug(`Found ${project.length} projects, enabling personalization`, this.exportConfig.context);
37
52
  this.exportConfig.personalizationEnabled = true;
38
53
  this.exportConfig.project_id = project[0]?.uid;
39
- fsUtil.writeFile(path.resolve(sanitizePath(this.projectFolderPath), 'projects.json'), project);
40
- log(this.exportConfig, 'Project exported successfully!', 'success');
54
+ log.debug(`Set project ID: ${project[0]?.uid}`, this.exportConfig.context);
55
+
56
+ const projectsFilePath = path.resolve(sanitizePath(this.projectFolderPath), 'projects.json');
57
+ log.debug(`Writing projects data to: ${projectsFilePath}`, this.exportConfig.context);
58
+ fsUtil.writeFile(projectsFilePath, project);
59
+
60
+ log.debug('Projects export completed successfully', this.exportConfig.context);
61
+ log.success(`Projects exported successfully!`, this.exportConfig.context);
41
62
  } catch (error) {
42
63
  if (error !== 'Forbidden') {
43
- log(this.exportConfig, `Failed to export projects!`, 'error');
64
+ log.debug(`Error occurred during projects export: ${error}`, this.exportConfig.context);
65
+ log.error('Failed to export projects!', this.exportConfig.context);
66
+ } else {
67
+ log.debug('Projects export forbidden, likely due to permissions', this.exportConfig.context);
44
68
  }
45
69
  throw error;
46
70
  }
@@ -1,10 +1,9 @@
1
1
  import { existsSync, mkdirSync } from 'fs';
2
2
  import { join, resolve } from 'path';
3
- import { FsUtility, sanitizePath } from '@contentstack/cli-utilities';
3
+ import { FsUtility, sanitizePath, log, handleAndLogError } from '@contentstack/cli-utilities';
4
4
 
5
- import { APIConfig, AdapterType, ExportConfig, LogType } from '../types';
5
+ import { APIConfig, AdapterType, ExportConfig } from '../types';
6
6
  import VariantAdapter, { VariantHttpClient } from '../utils/variant-api-adapter';
7
- import { fsUtil, log } from '../utils';
8
7
 
9
8
  export default class VariantEntries extends VariantAdapter<VariantHttpClient<ExportConfig>> {
10
9
  public entriesDirPath: string;
@@ -24,7 +23,14 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Exp
24
23
  },
25
24
  };
26
25
  super(Object.assign(config, conf));
27
- this.entriesDirPath = resolve(sanitizePath(config.data), sanitizePath(config.branchName || ''), sanitizePath(config.modules.entries.dirName));
26
+ this.entriesDirPath = resolve(
27
+ sanitizePath(config.data),
28
+ sanitizePath(config.branchName || ''),
29
+ sanitizePath(config.modules.entries.dirName),
30
+ );
31
+ if (this.config && this.config.context) {
32
+ this.config.context.module = 'variant-entries';
33
+ }
28
34
  }
29
35
 
30
36
  /**
@@ -35,10 +41,27 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Exp
35
41
  async exportVariantEntry(options: { locale: string; contentTypeUid: string; entries: Record<string, any>[] }) {
36
42
  const variantEntry = this.config.modules.variantEntry;
37
43
  const { entries, locale, contentTypeUid: content_type_uid } = options;
44
+
45
+ log.debug(`Starting variant entries export for content type: ${content_type_uid}, locale: ${locale}`, this.config.context);
46
+ log.debug(`Processing ${entries.length} entries for variant export`, this.config.context);
47
+
48
+ log.debug('Initializing variant instance...', this.config.context);
38
49
  await this.variantInstance.init();
50
+ log.debug('Variant instance initialized successfully', this.config.context);
51
+
39
52
  for (let index = 0; index < entries.length; index++) {
40
53
  const entry = entries[index];
41
- const variantEntryBasePath = join(sanitizePath(this.entriesDirPath), sanitizePath(content_type_uid), sanitizePath(locale), sanitizePath(variantEntry.dirName), sanitizePath(entry.uid));
54
+ log.debug(`Processing variant entries for entry: ${entry.title} (${entry.uid}) - ${index + 1}/${entries.length}`, this.config.context);
55
+
56
+ const variantEntryBasePath = join(
57
+ sanitizePath(this.entriesDirPath),
58
+ sanitizePath(content_type_uid),
59
+ sanitizePath(locale),
60
+ sanitizePath(variantEntry.dirName),
61
+ sanitizePath(entry.uid),
62
+ );
63
+ log.debug(`Variant entry base path: ${variantEntryBasePath}`, this.config.context);
64
+
42
65
  const variantEntriesFs = new FsUtility({
43
66
  isArray: true,
44
67
  keepMetadata: false,
@@ -48,17 +71,24 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Exp
48
71
  chunkFileSize: variantEntry.chunkFileSize || 1,
49
72
  createDirIfNotExist: false,
50
73
  });
74
+ log.debug('Initialized FsUtility for variant entries', this.config.context);
51
75
 
52
76
  const callback = (variantEntries: Record<string, any>[]) => {
77
+ log.debug(`Callback received ${variantEntries?.length || 0} variant entries for entry: ${entry.uid}`, this.config.context);
53
78
  if (variantEntries?.length) {
54
79
  if (!existsSync(variantEntryBasePath)) {
80
+ log.debug(`Creating directory: ${variantEntryBasePath}`, this.config.context);
55
81
  mkdirSync(variantEntryBasePath, { recursive: true });
56
82
  }
83
+ log.debug(`Writing ${variantEntries.length} variant entries to file`, this.config.context);
57
84
  variantEntriesFs.writeIntoFile(variantEntries);
85
+ } else {
86
+ log.debug(`No variant entries found for entry: ${entry.uid}`, this.config.context);
58
87
  }
59
88
  };
60
89
 
61
90
  try {
91
+ log.debug(`Fetching variant entries for entry: ${entry.uid}`, this.config.context);
62
92
  await this.variantInstance.variantEntries({
63
93
  callback,
64
94
  getAllData: true,
@@ -66,22 +96,27 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Exp
66
96
  entry_uid: entry.uid,
67
97
  locale,
68
98
  });
99
+
69
100
  if (existsSync(variantEntryBasePath)) {
101
+ log.debug(`Completing file for entry: ${entry.uid}`, this.config.context);
70
102
  variantEntriesFs.completeFile(true);
71
- log(
72
- this.config,
103
+ log.info(
73
104
  `Exported variant entries of type '${entry.title} (${entry.uid})' locale '${locale}'`,
74
- 'info',
105
+ this.config.context,
75
106
  );
107
+ } else {
108
+ log.debug(`No variant entries directory created for entry: ${entry.uid}`, this.config.context);
76
109
  }
77
110
  } catch (error) {
78
- log(
79
- this.config,
111
+ log.debug(`Error occurred while exporting variant entries for entry: ${entry.uid}`, this.config.context);
112
+ handleAndLogError(
113
+ error,
114
+ { ...this.config.context },
80
115
  `Error exporting variant entries of type '${entry.title} (${entry.uid})' locale '${locale}'`,
81
- 'error',
82
116
  );
83
- log(this.config, error, 'error');
84
117
  }
85
118
  }
119
+
120
+ log.debug(`Completed variant entries export for content type: ${content_type_uid}, locale: ${locale}`, this.config.context);
86
121
  }
87
122
  }