@contentstack/cli-variants 1.2.2 → 1.3.2
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.js +27 -10
- package/lib/export/audiences.js +28 -10
- package/lib/export/events.js +28 -10
- package/lib/export/experiences.js +48 -13
- package/lib/export/projects.js +24 -6
- package/lib/export/variant-entries.js +25 -4
- package/lib/import/attribute.d.ts +2 -3
- package/lib/import/attribute.js +16 -8
- package/lib/import/audiences.d.ts +2 -3
- package/lib/import/audiences.js +21 -8
- package/lib/import/events.d.ts +3 -4
- package/lib/import/events.js +16 -9
- package/lib/import/experiences.d.ts +2 -3
- package/lib/import/experiences.js +60 -17
- package/lib/import/project.d.ts +2 -3
- package/lib/import/project.js +11 -6
- package/lib/import/variant-entries.js +62 -25
- package/lib/types/export-config.d.ts +2 -1
- package/lib/types/utils.d.ts +11 -0
- package/lib/utils/attributes-helper.js +17 -1
- package/lib/utils/audiences-helper.js +37 -6
- package/lib/utils/events-helper.js +17 -4
- package/lib/utils/personalization-api-adapter.d.ts +2 -1
- package/lib/utils/personalization-api-adapter.js +119 -27
- package/lib/utils/variant-api-adapter.d.ts +4 -1
- package/lib/utils/variant-api-adapter.js +91 -17
- package/package.json +5 -2
- package/src/export/attributes.ts +34 -10
- package/src/export/audiences.ts +35 -7
- package/src/export/events.ts +35 -7
- package/src/export/experiences.ts +74 -24
- package/src/export/projects.ts +31 -7
- package/src/export/variant-entries.ts +47 -12
- package/src/import/attribute.ts +22 -9
- package/src/import/audiences.ts +28 -10
- package/src/import/events.ts +21 -10
- package/src/import/experiences.ts +74 -20
- package/src/import/project.ts +22 -8
- package/src/import/variant-entries.ts +116 -40
- package/src/types/export-config.ts +2 -1
- package/src/types/utils.ts +12 -0
- package/src/utils/attributes-helper.ts +21 -2
- package/src/utils/audiences-helper.ts +41 -1
- package/src/utils/events-helper.ts +19 -1
- package/src/utils/personalization-api-adapter.ts +95 -19
- package/src/utils/variant-api-adapter.ts +79 -8
package/lib/import/audiences.js
CHANGED
|
@@ -14,7 +14,7 @@ const fs_1 = require("fs");
|
|
|
14
14
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
16
|
class Audiences extends utils_1.PersonalizationAdapter {
|
|
17
|
-
constructor(config
|
|
17
|
+
constructor(config) {
|
|
18
18
|
const conf = {
|
|
19
19
|
config,
|
|
20
20
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
@@ -22,7 +22,6 @@ class Audiences extends utils_1.PersonalizationAdapter {
|
|
|
22
22
|
};
|
|
23
23
|
super(Object.assign(config, conf));
|
|
24
24
|
this.config = config;
|
|
25
|
-
this.log = log;
|
|
26
25
|
this.personalizeConfig = this.config.modules.personalize;
|
|
27
26
|
this.audienceConfig = this.personalizeConfig.audiences;
|
|
28
27
|
this.attributeConfig = this.personalizeConfig.attributes;
|
|
@@ -31,6 +30,7 @@ class Audiences extends utils_1.PersonalizationAdapter {
|
|
|
31
30
|
this.audiencesUidMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.audienceMapperDirPath), 'uid-mapping.json');
|
|
32
31
|
this.attributesMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.mapperDirPath), (0, cli_utilities_1.sanitizePath)(this.attributeConfig.dirName), 'uid-mapping.json');
|
|
33
32
|
this.audiencesUidMapper = {};
|
|
33
|
+
this.config.context.module = 'audiences';
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* The function asynchronously imports audiences from a JSON file and creates them in the system.
|
|
@@ -38,40 +38,53 @@ class Audiences extends utils_1.PersonalizationAdapter {
|
|
|
38
38
|
import() {
|
|
39
39
|
return __awaiter(this, void 0, void 0, function* () {
|
|
40
40
|
var _a, _b;
|
|
41
|
-
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Audiences' }), 'info');
|
|
42
41
|
yield this.init();
|
|
43
42
|
yield utils_1.fsUtil.makeDirectory(this.audienceMapperDirPath);
|
|
43
|
+
cli_utilities_1.log.debug(`Created mapper directory: ${this.audienceMapperDirPath}`, this.config.context);
|
|
44
44
|
const { dirName, fileName } = this.audienceConfig;
|
|
45
45
|
const audiencesPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(dirName), (0, cli_utilities_1.sanitizePath)(fileName));
|
|
46
|
+
cli_utilities_1.log.debug(`Checking for audiences file: ${audiencesPath}`, this.config.context);
|
|
46
47
|
if ((0, fs_1.existsSync)(audiencesPath)) {
|
|
47
48
|
try {
|
|
48
49
|
const audiences = utils_1.fsUtil.readFile(audiencesPath, true);
|
|
50
|
+
cli_utilities_1.log.info(`Found ${audiences.length} audiences to import`, this.config.context);
|
|
49
51
|
const attributesUid = utils_1.fsUtil.readFile(this.attributesMapperPath, true) || {};
|
|
52
|
+
cli_utilities_1.log.debug(`Loaded ${Object.keys(attributesUid).length} attribute mappings for audience processing`, this.config.context);
|
|
50
53
|
for (const audience of audiences) {
|
|
51
54
|
let { name, definition, description, uid } = audience;
|
|
55
|
+
cli_utilities_1.log.debug(`Processing audience: ${name} (${uid})`, this.config.context);
|
|
52
56
|
try {
|
|
53
57
|
//check whether reference attributes exists or not
|
|
54
58
|
if ((_a = definition.rules) === null || _a === void 0 ? void 0 : _a.length) {
|
|
59
|
+
cli_utilities_1.log.debug(`Processing ${definition.rules.length} definition rules for audience: ${name}`, this.config.context);
|
|
55
60
|
definition.rules = (0, utils_1.lookUpAttributes)(definition.rules, attributesUid);
|
|
61
|
+
cli_utilities_1.log.debug(`Processed definition rules, remaining rules: ${definition.rules.length}`, this.config.context);
|
|
56
62
|
}
|
|
63
|
+
else {
|
|
64
|
+
cli_utilities_1.log.debug(`No definition rules found for audience: ${name}`, this.config.context);
|
|
65
|
+
}
|
|
66
|
+
cli_utilities_1.log.debug(`Creating audience: ${name}`, this.config.context);
|
|
57
67
|
const audienceRes = yield this.createAudience({ definition, name, description });
|
|
58
68
|
//map old audience uid to new audience uid
|
|
59
69
|
//mapper file is used to check whether audience created or not before creating experience
|
|
60
70
|
this.audiencesUidMapper[uid] = (_b = audienceRes === null || audienceRes === void 0 ? void 0 : audienceRes.uid) !== null && _b !== void 0 ? _b : '';
|
|
71
|
+
cli_utilities_1.log.debug(`Created audience: ${uid} -> ${audienceRes === null || audienceRes === void 0 ? void 0 : audienceRes.uid}`, this.config.context);
|
|
61
72
|
}
|
|
62
73
|
catch (error) {
|
|
63
|
-
|
|
64
|
-
this.log(this.config, error, 'error');
|
|
74
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create audience: ${name} (${uid})`);
|
|
65
75
|
}
|
|
66
76
|
}
|
|
67
77
|
utils_1.fsUtil.writeFile(this.audiencesUidMapperPath, this.audiencesUidMapper);
|
|
68
|
-
|
|
78
|
+
cli_utilities_1.log.debug(`Saved ${Object.keys(this.audiencesUidMapper).length} audience mappings to: ${this.audiencesUidMapperPath}`, this.config.context);
|
|
79
|
+
cli_utilities_1.log.success('Audiences imported successfully', this.config.context);
|
|
69
80
|
}
|
|
70
81
|
catch (error) {
|
|
71
|
-
|
|
72
|
-
this.log(this.config, error, 'error');
|
|
82
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context);
|
|
73
83
|
}
|
|
74
84
|
}
|
|
85
|
+
else {
|
|
86
|
+
cli_utilities_1.log.warn(`Audiences file not found: ${audiencesPath}`, this.config.context);
|
|
87
|
+
}
|
|
75
88
|
});
|
|
76
89
|
}
|
|
77
90
|
}
|
package/lib/import/events.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { PersonalizationAdapter } from '../utils';
|
|
2
|
-
import { ImportConfig
|
|
2
|
+
import { ImportConfig } from '../types';
|
|
3
3
|
export default class Events extends PersonalizationAdapter<ImportConfig> {
|
|
4
4
|
readonly config: ImportConfig;
|
|
5
|
-
private readonly log;
|
|
6
5
|
private mapperDirPath;
|
|
7
6
|
private eventMapperDirPath;
|
|
8
7
|
private eventsUidMapperPath;
|
|
9
8
|
private eventsUidMapper;
|
|
10
9
|
private personalizeConfig;
|
|
11
10
|
private eventsConfig;
|
|
12
|
-
constructor(config: ImportConfig
|
|
11
|
+
constructor(config: ImportConfig);
|
|
13
12
|
/**
|
|
14
|
-
* The function asynchronously imports
|
|
13
|
+
* The function asynchronously imports events from a JSON file and creates them in the system.
|
|
15
14
|
*/
|
|
16
15
|
import(): Promise<void>;
|
|
17
16
|
}
|
package/lib/import/events.js
CHANGED
|
@@ -14,7 +14,7 @@ const fs_1 = require("fs");
|
|
|
14
14
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
16
|
class Events extends utils_1.PersonalizationAdapter {
|
|
17
|
-
constructor(config
|
|
17
|
+
constructor(config) {
|
|
18
18
|
const conf = {
|
|
19
19
|
config,
|
|
20
20
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
@@ -22,47 +22,54 @@ class Events extends utils_1.PersonalizationAdapter {
|
|
|
22
22
|
};
|
|
23
23
|
super(Object.assign(config, conf));
|
|
24
24
|
this.config = config;
|
|
25
|
-
this.log = log;
|
|
26
25
|
this.personalizeConfig = this.config.modules.personalize;
|
|
27
26
|
this.eventsConfig = this.personalizeConfig.events;
|
|
28
27
|
this.mapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName));
|
|
29
28
|
this.eventMapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.mapperDirPath), (0, cli_utilities_1.sanitizePath)(this.eventsConfig.dirName));
|
|
30
29
|
this.eventsUidMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.eventMapperDirPath), 'uid-mapping.json');
|
|
31
30
|
this.eventsUidMapper = {};
|
|
31
|
+
this.config.context.module = 'events';
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
* The function asynchronously imports
|
|
34
|
+
* The function asynchronously imports events from a JSON file and creates them in the system.
|
|
35
35
|
*/
|
|
36
36
|
import() {
|
|
37
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
38
|
var _a;
|
|
39
|
-
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Events' }), 'info');
|
|
40
39
|
yield this.init();
|
|
41
40
|
yield utils_1.fsUtil.makeDirectory(this.eventMapperDirPath);
|
|
41
|
+
cli_utilities_1.log.debug(`Created mapper directory: ${this.eventMapperDirPath}`, this.config.context);
|
|
42
42
|
const { dirName, fileName } = this.eventsConfig;
|
|
43
43
|
const eventsPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(dirName), (0, cli_utilities_1.sanitizePath)(fileName));
|
|
44
|
+
cli_utilities_1.log.debug(`Checking for events file: ${eventsPath}`, this.config.context);
|
|
44
45
|
if ((0, fs_1.existsSync)(eventsPath)) {
|
|
45
46
|
try {
|
|
46
47
|
const events = utils_1.fsUtil.readFile(eventsPath, true);
|
|
48
|
+
cli_utilities_1.log.info(`Found ${events.length} events to import`, this.config.context);
|
|
47
49
|
for (const event of events) {
|
|
48
50
|
const { key, description, uid } = event;
|
|
51
|
+
cli_utilities_1.log.debug(`Processing event: ${key} (${uid})`, this.config.context);
|
|
49
52
|
try {
|
|
53
|
+
cli_utilities_1.log.debug(`Creating event: ${key}`, this.config.context);
|
|
50
54
|
const eventsResponse = yield this.createEvents({ key, description });
|
|
51
55
|
this.eventsUidMapper[uid] = (_a = eventsResponse === null || eventsResponse === void 0 ? void 0 : eventsResponse.uid) !== null && _a !== void 0 ? _a : '';
|
|
56
|
+
cli_utilities_1.log.debug(`Created event: ${uid} -> ${eventsResponse === null || eventsResponse === void 0 ? void 0 : eventsResponse.uid}`, this.config.context);
|
|
52
57
|
}
|
|
53
58
|
catch (error) {
|
|
54
|
-
|
|
55
|
-
this.log(this.config, error, 'error');
|
|
59
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to create event: ${key} (${uid})`);
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
utils_1.fsUtil.writeFile(this.eventsUidMapperPath, this.eventsUidMapper);
|
|
59
|
-
|
|
63
|
+
cli_utilities_1.log.debug(`Saved ${Object.keys(this.eventsUidMapper).length} event mappings to: ${this.eventsUidMapperPath}`, this.config.context);
|
|
64
|
+
cli_utilities_1.log.success('Events imported successfully', this.config.context);
|
|
60
65
|
}
|
|
61
66
|
catch (error) {
|
|
62
|
-
|
|
63
|
-
this.log(this.config, error, 'error');
|
|
67
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context);
|
|
64
68
|
}
|
|
65
69
|
}
|
|
70
|
+
else {
|
|
71
|
+
cli_utilities_1.log.warn(`Events file not found: ${eventsPath}`, this.config.context);
|
|
72
|
+
}
|
|
66
73
|
});
|
|
67
74
|
}
|
|
68
75
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { PersonalizationAdapter } from '../utils';
|
|
2
|
-
import { ImportConfig, ExperienceStruct
|
|
2
|
+
import { ImportConfig, ExperienceStruct } from '../types';
|
|
3
3
|
export default class Experiences extends PersonalizationAdapter<ImportConfig> {
|
|
4
4
|
readonly config: ImportConfig;
|
|
5
|
-
private readonly log;
|
|
6
5
|
private createdCTs;
|
|
7
6
|
private mapperDirPath;
|
|
8
7
|
private cmsVariantPath;
|
|
@@ -30,7 +29,7 @@ export default class Experiences extends PersonalizationAdapter<ImportConfig> {
|
|
|
30
29
|
private personalizeConfig;
|
|
31
30
|
private audienceConfig;
|
|
32
31
|
private experienceConfig;
|
|
33
|
-
constructor(config: ImportConfig
|
|
32
|
+
constructor(config: ImportConfig);
|
|
34
33
|
/**
|
|
35
34
|
* The function asynchronously imports experiences from a JSON file and creates them in the system.
|
|
36
35
|
*/
|
|
@@ -30,7 +30,7 @@ const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
|
30
30
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
31
31
|
const utils_1 = require("../utils");
|
|
32
32
|
class Experiences extends utils_1.PersonalizationAdapter {
|
|
33
|
-
constructor(config
|
|
33
|
+
constructor(config) {
|
|
34
34
|
var _a, _b, _c, _d;
|
|
35
35
|
const conf = {
|
|
36
36
|
config,
|
|
@@ -43,7 +43,6 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
43
43
|
};
|
|
44
44
|
super(Object.assign(config, conf));
|
|
45
45
|
this.config = config;
|
|
46
|
-
this.log = log;
|
|
47
46
|
this.personalizeConfig = this.config.modules.personalize;
|
|
48
47
|
this.experiencesDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.experiences.dirName));
|
|
49
48
|
this.experiencesPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.experiencesDirPath), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.experiences.fileName));
|
|
@@ -72,6 +71,7 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
72
71
|
this.createdCTs = [];
|
|
73
72
|
this.audiencesUid = utils_1.fsUtil.readFile(this.audiencesMapperPath, true) || {};
|
|
74
73
|
this.eventsUid = utils_1.fsUtil.readFile(this.eventsMapperPath, true) || {};
|
|
74
|
+
this.config.context.module = 'experiences';
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
77
77
|
* The function asynchronously imports experiences from a JSON file and creates them in the system.
|
|
@@ -79,14 +79,17 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
79
79
|
import() {
|
|
80
80
|
return __awaiter(this, void 0, void 0, function* () {
|
|
81
81
|
var _a;
|
|
82
|
-
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Experiences' }), 'info');
|
|
83
82
|
yield this.init();
|
|
84
83
|
yield utils_1.fsUtil.makeDirectory(this.expMapperDirPath);
|
|
84
|
+
cli_utilities_1.log.debug(`Created mapper directory: ${this.expMapperDirPath}`, this.config.context);
|
|
85
85
|
if ((0, fs_1.existsSync)(this.experiencesPath)) {
|
|
86
|
+
cli_utilities_1.log.debug(`Loading experiences from: ${this.experiencesPath}`, this.config.context);
|
|
86
87
|
try {
|
|
87
88
|
const experiences = utils_1.fsUtil.readFile(this.experiencesPath, true);
|
|
89
|
+
cli_utilities_1.log.info(`Found ${experiences.length} experiences to import`, this.config.context);
|
|
88
90
|
for (const experience of experiences) {
|
|
89
91
|
const { uid } = experience, restExperienceData = __rest(experience, ["uid"]);
|
|
92
|
+
cli_utilities_1.log.debug(`Processing experience: ${uid}`, this.config.context);
|
|
90
93
|
//check whether reference audience exists or not that referenced in variations having __type equal to AudienceBasedVariation & targeting
|
|
91
94
|
let experienceReqObj = (0, utils_1.lookUpAudiences)(restExperienceData, this.audiencesUid);
|
|
92
95
|
//check whether events exists or not that referenced in metrics
|
|
@@ -94,40 +97,43 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
94
97
|
const expRes = (yield this.createExperience(experienceReqObj));
|
|
95
98
|
//map old experience uid to new experience uid
|
|
96
99
|
this.experiencesUidMapper[uid] = (_a = expRes === null || expRes === void 0 ? void 0 : expRes.uid) !== null && _a !== void 0 ? _a : '';
|
|
100
|
+
cli_utilities_1.log.debug(`Created experience: ${uid} -> ${expRes === null || expRes === void 0 ? void 0 : expRes.uid}`, this.config.context);
|
|
97
101
|
try {
|
|
98
102
|
// import versions of experience
|
|
99
103
|
yield this.importExperienceVersions(expRes, uid);
|
|
100
104
|
}
|
|
101
105
|
catch (error) {
|
|
102
|
-
|
|
103
|
-
this.log(this.config, error, 'error');
|
|
106
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context, `Failed to import experience versions for ${expRes.uid}`);
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
utils_1.fsUtil.writeFile(this.experiencesUidMapperPath, this.experiencesUidMapper);
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
cli_utilities_1.log.success('Experiences created successfully', this.config.context);
|
|
111
|
+
cli_utilities_1.log.info('Validating variant and variant group creation', this.config.context);
|
|
109
112
|
this.pendingVariantAndVariantGrpForExperience = (0, values_1.default)((0, cloneDeep_1.default)(this.experiencesUidMapper));
|
|
110
113
|
const jobRes = yield this.validateVariantGroupAndVariantsCreated();
|
|
111
114
|
utils_1.fsUtil.writeFile(this.cmsVariantPath, this.cmsVariants);
|
|
112
115
|
utils_1.fsUtil.writeFile(this.cmsVariantGroupPath, this.cmsVariantGroups);
|
|
113
116
|
if (jobRes) {
|
|
114
|
-
|
|
117
|
+
cli_utilities_1.log.success('Variant and variant groups created successfully', this.config.context);
|
|
115
118
|
}
|
|
116
119
|
else {
|
|
120
|
+
cli_utilities_1.log.error('Failed to create variants and variant groups', this.config.context);
|
|
117
121
|
this.personalizeConfig.importData = false;
|
|
118
122
|
}
|
|
119
123
|
if (this.personalizeConfig.importData) {
|
|
120
|
-
|
|
124
|
+
cli_utilities_1.log.info('Attaching content types to experiences', this.config.context);
|
|
121
125
|
yield this.attachCTsInExperience();
|
|
122
|
-
|
|
126
|
+
cli_utilities_1.log.success('Content types attached to experiences successfully', this.config.context);
|
|
123
127
|
}
|
|
124
128
|
yield this.createVariantIdMapper();
|
|
125
129
|
}
|
|
126
130
|
catch (error) {
|
|
127
|
-
|
|
128
|
-
this.log(this.config, error, 'error');
|
|
131
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context);
|
|
129
132
|
}
|
|
130
133
|
}
|
|
134
|
+
else {
|
|
135
|
+
cli_utilities_1.log.warn(`Experiences file not found: ${this.experiencesPath}`, this.config.context);
|
|
136
|
+
}
|
|
131
137
|
});
|
|
132
138
|
}
|
|
133
139
|
/**
|
|
@@ -135,11 +141,14 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
135
141
|
*/
|
|
136
142
|
importExperienceVersions(experience, oldExperienceUid) {
|
|
137
143
|
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
cli_utilities_1.log.debug(`Importing versions for experience: ${oldExperienceUid}`, this.config.context);
|
|
138
145
|
const versionsPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.experiencesDirPath), 'versions', `${(0, cli_utilities_1.sanitizePath)(oldExperienceUid)}.json`);
|
|
139
146
|
if (!(0, fs_1.existsSync)(versionsPath)) {
|
|
147
|
+
cli_utilities_1.log.debug(`No versions file found for experience: ${oldExperienceUid}`, this.config.context);
|
|
140
148
|
return;
|
|
141
149
|
}
|
|
142
150
|
const versions = utils_1.fsUtil.readFile(versionsPath, true);
|
|
151
|
+
cli_utilities_1.log.debug(`Found ${versions.length} versions for experience: ${oldExperienceUid}`, this.config.context);
|
|
143
152
|
const versionMap = {
|
|
144
153
|
ACTIVE: undefined,
|
|
145
154
|
DRAFT: undefined,
|
|
@@ -151,6 +160,7 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
151
160
|
versionReqObj = (0, utils_1.lookUpEvents)(version, this.eventsUid);
|
|
152
161
|
if (versionReqObj && versionReqObj.status) {
|
|
153
162
|
versionMap[versionReqObj.status] = versionReqObj;
|
|
163
|
+
cli_utilities_1.log.debug(`Mapped version with status: ${versionReqObj.status}`, this.config.context);
|
|
154
164
|
}
|
|
155
165
|
});
|
|
156
166
|
// Prioritize updating or creating versions based on the order: ACTIVE -> DRAFT -> PAUSE
|
|
@@ -160,26 +170,32 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
160
170
|
// Helper method to handle version update or creation logic
|
|
161
171
|
handleVersionUpdateOrCreate(experience, versionMap) {
|
|
162
172
|
return __awaiter(this, void 0, void 0, function* () {
|
|
173
|
+
cli_utilities_1.log.debug(`Handling version update/create for experience: ${experience.uid}`, this.config.context);
|
|
163
174
|
const { ACTIVE, DRAFT, PAUSE } = versionMap;
|
|
164
175
|
let latestVersionUsed = false;
|
|
165
176
|
if (ACTIVE) {
|
|
177
|
+
cli_utilities_1.log.debug(`Updating experience version to ACTIVE for: ${experience.uid}`, this.config.context);
|
|
166
178
|
yield this.updateExperienceVersion(experience.uid, experience.latestVersion, ACTIVE);
|
|
167
179
|
latestVersionUsed = true;
|
|
168
180
|
}
|
|
169
181
|
if (DRAFT) {
|
|
170
182
|
if (latestVersionUsed) {
|
|
183
|
+
cli_utilities_1.log.debug(`Creating new DRAFT version for: ${experience.uid}`, this.config.context);
|
|
171
184
|
yield this.createExperienceVersion(experience.uid, DRAFT);
|
|
172
185
|
}
|
|
173
186
|
else {
|
|
187
|
+
cli_utilities_1.log.debug(`Updating experience version to DRAFT for: ${experience.uid}`, this.config.context);
|
|
174
188
|
yield this.updateExperienceVersion(experience.uid, experience.latestVersion, DRAFT);
|
|
175
189
|
latestVersionUsed = true;
|
|
176
190
|
}
|
|
177
191
|
}
|
|
178
192
|
if (PAUSE) {
|
|
179
193
|
if (latestVersionUsed) {
|
|
194
|
+
cli_utilities_1.log.debug(`Creating new PAUSE version for: ${experience.uid}`, this.config.context);
|
|
180
195
|
yield this.createExperienceVersion(experience.uid, PAUSE);
|
|
181
196
|
}
|
|
182
197
|
else {
|
|
198
|
+
cli_utilities_1.log.debug(`Updating experience version to PAUSE for: ${experience.uid}`, this.config.context);
|
|
183
199
|
yield this.updateExperienceVersion(experience.uid, experience.latestVersion, PAUSE);
|
|
184
200
|
}
|
|
185
201
|
}
|
|
@@ -195,88 +211,115 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
195
211
|
validateVariantGroupAndVariantsCreated() {
|
|
196
212
|
return __awaiter(this, arguments, void 0, function* (retryCount = 0) {
|
|
197
213
|
var _a;
|
|
214
|
+
cli_utilities_1.log.debug(`Validating variant groups and variants creation - attempt ${retryCount + 1}/${this.maxValidateRetry}`, this.config.context);
|
|
198
215
|
try {
|
|
199
216
|
const promises = this.pendingVariantAndVariantGrpForExperience.map((expUid) => __awaiter(this, void 0, void 0, function* () {
|
|
200
217
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
218
|
+
cli_utilities_1.log.debug(`Checking experience: ${expUid}`, this.config.context);
|
|
201
219
|
const expRes = yield this.getExperience(expUid);
|
|
202
220
|
const variants = (_b = (_a = expRes === null || expRes === void 0 ? void 0 : expRes._cms) === null || _a === void 0 ? void 0 : _a.variants) !== null && _b !== void 0 ? _b : {};
|
|
203
221
|
if ((expRes === null || expRes === void 0 ? void 0 : expRes._cms) && ((_c = expRes === null || expRes === void 0 ? void 0 : expRes._cms) === null || _c === void 0 ? void 0 : _c.variantGroup) && Object.keys(variants).length > 0) {
|
|
222
|
+
cli_utilities_1.log.debug(`Found variants and variant group for experience: ${expUid}`, this.config.context);
|
|
204
223
|
this.cmsVariants[expUid] = (_e = (_d = expRes._cms) === null || _d === void 0 ? void 0 : _d.variants) !== null && _e !== void 0 ? _e : {};
|
|
205
224
|
this.cmsVariantGroups[expUid] = (_g = (_f = expRes._cms) === null || _f === void 0 ? void 0 : _f.variantGroup) !== null && _g !== void 0 ? _g : {};
|
|
206
225
|
return expUid; // Return the expUid for filtering later
|
|
207
226
|
}
|
|
227
|
+
else {
|
|
228
|
+
cli_utilities_1.log.debug(`Variants/variant group not ready for experience: ${expUid}`, this.config.context);
|
|
229
|
+
}
|
|
208
230
|
}));
|
|
209
231
|
yield Promise.all(promises);
|
|
210
232
|
retryCount++;
|
|
211
233
|
if ((_a = this.pendingVariantAndVariantGrpForExperience) === null || _a === void 0 ? void 0 : _a.length) {
|
|
212
234
|
if (retryCount !== this.maxValidateRetry) {
|
|
235
|
+
cli_utilities_1.log.debug(`Waiting ${this.expCheckIntervalDuration}ms before retry`, this.config.context);
|
|
213
236
|
yield this.delay(this.expCheckIntervalDuration);
|
|
214
237
|
// Filter out the processed elements
|
|
215
238
|
this.pendingVariantAndVariantGrpForExperience = this.pendingVariantAndVariantGrpForExperience.filter((uid) => !this.cmsVariants[uid]);
|
|
216
239
|
return this.validateVariantGroupAndVariantsCreated(retryCount);
|
|
217
240
|
}
|
|
218
241
|
else {
|
|
219
|
-
|
|
242
|
+
cli_utilities_1.log.error('Personalize job failed to create variants and variant groups', this.config.context);
|
|
243
|
+
cli_utilities_1.log.error(`Failed experiences: ${this.pendingVariantAndVariantGrpForExperience.join(', ')}`, this.config.context);
|
|
220
244
|
utils_1.fsUtil.writeFile(this.failedCmsExpPath, this.pendingVariantAndVariantGrpForExperience);
|
|
221
245
|
return false;
|
|
222
246
|
}
|
|
223
247
|
}
|
|
224
248
|
else {
|
|
249
|
+
cli_utilities_1.log.debug('All variant groups and variants created successfully', this.config.context);
|
|
225
250
|
return true;
|
|
226
251
|
}
|
|
227
252
|
}
|
|
228
253
|
catch (error) {
|
|
229
|
-
|
|
254
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context);
|
|
230
255
|
throw error;
|
|
231
256
|
}
|
|
232
257
|
});
|
|
233
258
|
}
|
|
234
259
|
attachCTsInExperience() {
|
|
235
260
|
return __awaiter(this, void 0, void 0, function* () {
|
|
261
|
+
cli_utilities_1.log.debug('Attaching content types to experiences', this.config.context);
|
|
236
262
|
try {
|
|
237
263
|
// Read the created content types from the file
|
|
238
264
|
this.createdCTs = utils_1.fsUtil.readFile(this.cTsSuccessPath, true);
|
|
239
265
|
if (!this.createdCTs) {
|
|
240
|
-
|
|
266
|
+
cli_utilities_1.log.debug('No Content types created, skipping following process', this.config.context);
|
|
241
267
|
return;
|
|
242
268
|
}
|
|
269
|
+
cli_utilities_1.log.debug(`Found ${this.createdCTs.length} created content types`, this.config.context);
|
|
243
270
|
const experienceCTsMap = utils_1.fsUtil.readFile(this.experienceCTsPath, true);
|
|
244
271
|
return yield Promise.allSettled(Object.entries(this.experiencesUidMapper).map((_a) => __awaiter(this, [_a], void 0, function* ([oldExpUid, newExpUid]) {
|
|
245
272
|
var _b;
|
|
246
273
|
if ((_b = experienceCTsMap[oldExpUid]) === null || _b === void 0 ? void 0 : _b.length) {
|
|
274
|
+
cli_utilities_1.log.debug(`Processing content types for experience: ${oldExpUid} -> ${newExpUid}`, this.config.context);
|
|
247
275
|
// Filter content types that were created
|
|
248
276
|
const updatedContentTypes = experienceCTsMap[oldExpUid].filter((ct) => this.createdCTs.includes(ct === null || ct === void 0 ? void 0 : ct.uid) && ct.status === 'linked');
|
|
249
277
|
if (updatedContentTypes === null || updatedContentTypes === void 0 ? void 0 : updatedContentTypes.length) {
|
|
278
|
+
cli_utilities_1.log.debug(`Attaching ${updatedContentTypes.length} content types to experience: ${newExpUid}`, this.config.context);
|
|
250
279
|
const { variant_groups: [variantGroup] = [] } = (yield this.getVariantGroup({ experienceUid: newExpUid })) || {};
|
|
251
280
|
variantGroup.content_types = updatedContentTypes;
|
|
252
281
|
// Update content types detail in the new experience asynchronously
|
|
253
282
|
return yield this.updateVariantGroup(variantGroup);
|
|
254
283
|
}
|
|
284
|
+
else {
|
|
285
|
+
cli_utilities_1.log.debug(`No valid content types found for experience: ${newExpUid}`, this.config.context);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
cli_utilities_1.log.debug(`No content types mapped for experience: ${oldExpUid}`, this.config.context);
|
|
255
290
|
}
|
|
256
291
|
})));
|
|
257
292
|
}
|
|
258
293
|
catch (error) {
|
|
259
|
-
|
|
260
|
-
this.log(this.config, error, 'error');
|
|
294
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context, 'Failed to attach content type with experience');
|
|
261
295
|
}
|
|
262
296
|
});
|
|
263
297
|
}
|
|
264
298
|
createVariantIdMapper() {
|
|
265
299
|
return __awaiter(this, void 0, void 0, function* () {
|
|
266
300
|
var _a;
|
|
301
|
+
cli_utilities_1.log.debug('Creating variant ID mapper', this.config.context);
|
|
267
302
|
try {
|
|
268
303
|
const experienceVariantIds = utils_1.fsUtil.readFile(this.experienceVariantsIdsPath, true) || [];
|
|
304
|
+
cli_utilities_1.log.debug(`Found ${experienceVariantIds.length} experience variant IDs to process`, this.config.context);
|
|
269
305
|
const variantUIDMapper = {};
|
|
270
306
|
for (let experienceVariantId of experienceVariantIds) {
|
|
271
307
|
const [experienceId, variantShortId, oldVariantId] = experienceVariantId.split('-');
|
|
272
308
|
const latestVariantId = (_a = this.cmsVariants[this.experiencesUidMapper[experienceId]]) === null || _a === void 0 ? void 0 : _a[variantShortId];
|
|
273
309
|
if (latestVariantId) {
|
|
274
310
|
variantUIDMapper[oldVariantId] = latestVariantId;
|
|
311
|
+
cli_utilities_1.log.debug(`Mapped variant ID: ${oldVariantId} -> ${latestVariantId}`, this.config.context);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
cli_utilities_1.log.warn(`Could not find variant ID mapping for: ${experienceVariantId}`, this.config.context);
|
|
275
315
|
}
|
|
276
316
|
}
|
|
317
|
+
cli_utilities_1.log.debug(`Created ${Object.keys(variantUIDMapper).length} variant ID mappings`, this.config.context);
|
|
277
318
|
utils_1.fsUtil.writeFile(this.variantUidMapperFilePath, variantUIDMapper);
|
|
319
|
+
cli_utilities_1.log.debug(`Variant ID mapper saved to: ${this.variantUidMapperFilePath}`, this.config.context);
|
|
278
320
|
}
|
|
279
321
|
catch (error) {
|
|
322
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.config.context, 'Failed to create variant ID mapper');
|
|
280
323
|
throw error;
|
|
281
324
|
}
|
|
282
325
|
});
|
package/lib/import/project.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { PersonalizationAdapter } from '../utils';
|
|
2
|
-
import { ImportConfig
|
|
2
|
+
import { ImportConfig } from '../types';
|
|
3
3
|
export default class Project extends PersonalizationAdapter<ImportConfig> {
|
|
4
4
|
readonly config: ImportConfig;
|
|
5
|
-
private readonly log;
|
|
6
5
|
private projectMapperFolderPath;
|
|
7
|
-
constructor(config: ImportConfig
|
|
6
|
+
constructor(config: ImportConfig);
|
|
8
7
|
/**
|
|
9
8
|
* The function asynchronously imports projects data from a file and creates projects based on the
|
|
10
9
|
* data.
|
package/lib/import/project.js
CHANGED
|
@@ -14,7 +14,7 @@ const fs_1 = require("fs");
|
|
|
14
14
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
16
|
class Project extends utils_1.PersonalizationAdapter {
|
|
17
|
-
constructor(config
|
|
17
|
+
constructor(config) {
|
|
18
18
|
const conf = {
|
|
19
19
|
config,
|
|
20
20
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
@@ -22,8 +22,8 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
22
22
|
};
|
|
23
23
|
super(Object.assign(config, conf));
|
|
24
24
|
this.config = config;
|
|
25
|
-
this.log = log;
|
|
26
25
|
this.projectMapperFolderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.config.modules.personalize.dirName), 'projects');
|
|
26
|
+
this.config.context.module = 'project';
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* The function asynchronously imports projects data from a file and creates projects based on the
|
|
@@ -34,16 +34,20 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
34
34
|
const personalize = this.config.modules.personalize;
|
|
35
35
|
const { dirName, fileName } = personalize.projects;
|
|
36
36
|
const projectPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(personalize.dirName), (0, cli_utilities_1.sanitizePath)(dirName), (0, cli_utilities_1.sanitizePath)(fileName));
|
|
37
|
+
cli_utilities_1.log.debug(`Checking for project file: ${projectPath}`, this.config.context);
|
|
37
38
|
if ((0, fs_1.existsSync)(projectPath)) {
|
|
38
39
|
const projects = JSON.parse((0, fs_1.readFileSync)(projectPath, 'utf8'));
|
|
40
|
+
cli_utilities_1.log.debug(`Loaded ${(projects === null || projects === void 0 ? void 0 : projects.length) || 0} projects from file`, this.config.context);
|
|
39
41
|
if (!projects || projects.length < 1) {
|
|
40
42
|
this.config.modules.personalize.importData = false; // Stop personalize import if stack not connected to any project
|
|
41
|
-
|
|
43
|
+
cli_utilities_1.log.warn('No projects found in file', this.config.context);
|
|
42
44
|
return;
|
|
43
45
|
}
|
|
44
46
|
yield this.init();
|
|
45
47
|
for (const project of projects) {
|
|
48
|
+
cli_utilities_1.log.debug(`Processing project: ${project.name}`, this.config.context);
|
|
46
49
|
const createProject = (newName) => __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
cli_utilities_1.log.debug(`Creating project with name: ${newName || project.name}`, this.config.context);
|
|
47
51
|
return yield this.createProject({
|
|
48
52
|
name: newName || project.name,
|
|
49
53
|
description: project.description,
|
|
@@ -51,10 +55,10 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
51
55
|
}).catch((error) => __awaiter(this, void 0, void 0, function* () {
|
|
52
56
|
if (error.includes('personalization.PROJECTS.DUPLICATE_NAME') ||
|
|
53
57
|
error.includes('personalize.PROJECTS.DUPLICATE_NAME')) {
|
|
58
|
+
cli_utilities_1.log.warn(`Project name already exists, generating new name`, this.config.context);
|
|
54
59
|
const projectName = yield (0, utils_1.askProjectName)('Copy Of ' + (newName || project.name));
|
|
55
60
|
return yield createProject(projectName);
|
|
56
61
|
}
|
|
57
|
-
this.log(this.config, this.$t(this.messages.CREATE_FAILURE, { module: 'Projects' }), 'error');
|
|
58
62
|
throw error;
|
|
59
63
|
}));
|
|
60
64
|
});
|
|
@@ -63,12 +67,13 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
63
67
|
this.config.modules.personalize.importData = true;
|
|
64
68
|
yield utils_1.fsUtil.makeDirectory(this.projectMapperFolderPath);
|
|
65
69
|
utils_1.fsUtil.writeFile((0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.projectMapperFolderPath), 'projects.json'), projectRes);
|
|
66
|
-
|
|
70
|
+
cli_utilities_1.log.success(`Project created successfully: ${projectRes.uid}`, this.config.context);
|
|
71
|
+
cli_utilities_1.log.debug(`Project data saved to: ${this.projectMapperFolderPath}/projects.json`, this.config.context);
|
|
67
72
|
}
|
|
68
73
|
}
|
|
69
74
|
else {
|
|
70
75
|
this.config.modules.personalize.importData = false; // Stop personalize import if stack not connected to any project
|
|
71
|
-
|
|
76
|
+
cli_utilities_1.log.warn(`Project file not found: ${projectPath}`, this.config.context);
|
|
72
77
|
}
|
|
73
78
|
});
|
|
74
79
|
}
|