@contentstack/cli-variants 0.0.1-alpha → 1.1.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.
- package/lib/export/attributes.d.ts +2 -2
- package/lib/export/attributes.js +5 -4
- package/lib/export/audiences.d.ts +2 -2
- package/lib/export/audiences.js +5 -4
- package/lib/export/events.d.ts +2 -2
- package/lib/export/events.js +5 -4
- package/lib/export/experiences.d.ts +2 -2
- package/lib/export/experiences.js +20 -5
- package/lib/export/projects.d.ts +2 -2
- package/lib/export/projects.js +9 -6
- package/lib/export/variant-entries.js +1 -1
- package/lib/import/attribute.d.ts +1 -1
- package/lib/import/attribute.js +21 -10
- package/lib/import/audiences.d.ts +2 -2
- package/lib/import/audiences.js +21 -14
- package/lib/import/events.d.ts +1 -1
- package/lib/import/events.js +15 -8
- package/lib/import/experiences.d.ts +12 -5
- package/lib/import/experiences.js +86 -21
- package/lib/import/project.js +12 -11
- package/lib/import/variant-entries.d.ts +1 -1
- package/lib/import/variant-entries.js +28 -22
- package/lib/messages/index.d.ts +1 -1
- package/lib/messages/index.js +3 -2
- package/lib/types/export-config.d.ts +3 -3
- package/lib/types/import-config.d.ts +1 -1
- package/lib/types/personalization-api-adapter.d.ts +14 -1
- package/lib/types/variant-api-adapter.d.ts +3 -2
- package/lib/types/variant-entry.d.ts +2 -3
- package/lib/utils/attributes-helper.js +2 -2
- package/lib/utils/audiences-helper.js +14 -3
- package/lib/utils/error-helper.js +6 -6
- package/lib/utils/logger.js +5 -4
- package/lib/utils/personalization-api-adapter.d.ts +6 -2
- package/lib/utils/personalization-api-adapter.js +90 -23
- package/lib/utils/variant-api-adapter.d.ts +5 -4
- package/lib/utils/variant-api-adapter.js +29 -10
- package/package.json +2 -2
- package/src/export/attributes.ts +11 -7
- package/src/export/audiences.ts +7 -6
- package/src/export/events.ts +7 -6
- package/src/export/experiences.ts +24 -7
- package/src/export/projects.ts +11 -8
- package/src/export/variant-entries.ts +1 -2
- package/src/import/attribute.ts +31 -13
- package/src/import/audiences.ts +37 -19
- package/src/import/events.ts +25 -11
- package/src/import/experiences.ts +120 -30
- package/src/import/project.ts +13 -13
- package/src/import/variant-entries.ts +70 -37
- package/src/messages/index.ts +3 -2
- package/src/types/export-config.ts +3 -3
- package/src/types/import-config.ts +1 -1
- package/src/types/personalization-api-adapter.ts +14 -1
- package/src/types/variant-api-adapter.ts +3 -1
- package/src/types/variant-entry.ts +2 -3
- package/src/utils/attributes-helper.ts +2 -2
- package/src/utils/audiences-helper.ts +12 -2
- package/src/utils/error-helper.ts +6 -6
- package/src/utils/logger.ts +5 -4
- package/src/utils/personalization-api-adapter.ts +71 -18
- package/src/utils/variant-api-adapter.ts +21 -7
|
@@ -34,22 +34,22 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
34
34
|
var _a, _b, _c, _d;
|
|
35
35
|
const conf = {
|
|
36
36
|
config,
|
|
37
|
-
baseURL: config.modules.
|
|
38
|
-
headers: { 'X-Project-Uid': config.modules.
|
|
37
|
+
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
38
|
+
headers: { 'X-Project-Uid': config.modules.personalize.project_id },
|
|
39
39
|
cmaConfig: {
|
|
40
40
|
baseURL: config.region.cma + `/v3`,
|
|
41
|
-
headers: {
|
|
41
|
+
headers: { api_key: config.apiKey },
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
44
|
super(Object.assign(config, conf));
|
|
45
45
|
this.config = config;
|
|
46
46
|
this.log = log;
|
|
47
|
-
this.
|
|
48
|
-
this.experiencesDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.
|
|
49
|
-
this.experiencesPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.experiencesDirPath), (0, cli_utilities_1.sanitizePath)(this.
|
|
50
|
-
this.experienceConfig = this.
|
|
51
|
-
this.audienceConfig = this.
|
|
52
|
-
this.mapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.
|
|
47
|
+
this.personalizeConfig = this.config.modules.personalize;
|
|
48
|
+
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
|
+
this.experiencesPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.experiencesDirPath), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.experiences.fileName));
|
|
50
|
+
this.experienceConfig = this.personalizeConfig.experiences;
|
|
51
|
+
this.audienceConfig = this.personalizeConfig.audiences;
|
|
52
|
+
this.mapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName));
|
|
53
53
|
this.expMapperDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.mapperDirPath), (0, cli_utilities_1.sanitizePath)(this.experienceConfig.dirName));
|
|
54
54
|
this.experiencesUidMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.expMapperDirPath), 'uid-mapping.json');
|
|
55
55
|
this.cmsVariantGroupPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.expMapperDirPath), 'cms-variant-groups.json');
|
|
@@ -59,7 +59,7 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
59
59
|
this.failedCmsExpPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.expMapperDirPath), 'failed-cms-experience.json');
|
|
60
60
|
this.failedCmsExpPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.expMapperDirPath), 'failed-cms-experience.json');
|
|
61
61
|
this.experienceCTsPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.experiencesDirPath), 'experiences-content-types.json');
|
|
62
|
-
this.experienceVariantsIdsPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(this.
|
|
62
|
+
this.experienceVariantsIdsPath = (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.experienceConfig.dirName), 'experiences-variants-ids.json');
|
|
63
63
|
this.variantUidMapperFilePath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.expMapperDirPath), 'variants-uid-mapping.json');
|
|
64
64
|
this.experiencesUidMapper = {};
|
|
65
65
|
this.cmsVariantGroups = {};
|
|
@@ -70,6 +70,8 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
70
70
|
this.pendingVariantAndVariantGrpForExperience = [];
|
|
71
71
|
this.cTsSuccessPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', 'content_types', 'success.json');
|
|
72
72
|
this.createdCTs = [];
|
|
73
|
+
this.audiencesUid = utils_1.fsUtil.readFile(this.audiencesMapperPath, true) || {};
|
|
74
|
+
this.eventsUid = utils_1.fsUtil.readFile(this.eventsMapperPath, true) || {};
|
|
73
75
|
}
|
|
74
76
|
/**
|
|
75
77
|
* The function asynchronously imports experiences from a JSON file and creates them in the system.
|
|
@@ -78,21 +80,28 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
78
80
|
return __awaiter(this, void 0, void 0, function* () {
|
|
79
81
|
var _a;
|
|
80
82
|
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Experiences' }), 'info');
|
|
83
|
+
yield this.init();
|
|
81
84
|
yield utils_1.fsUtil.makeDirectory(this.expMapperDirPath);
|
|
82
85
|
if ((0, fs_1.existsSync)(this.experiencesPath)) {
|
|
83
86
|
try {
|
|
84
87
|
const experiences = utils_1.fsUtil.readFile(this.experiencesPath, true);
|
|
85
|
-
const audiencesUid = utils_1.fsUtil.readFile(this.audiencesMapperPath, true) || {};
|
|
86
|
-
const eventsUid = utils_1.fsUtil.readFile(this.eventsMapperPath, true) || {};
|
|
87
88
|
for (const experience of experiences) {
|
|
88
89
|
const { uid } = experience, restExperienceData = __rest(experience, ["uid"]);
|
|
89
90
|
//check whether reference audience exists or not that referenced in variations having __type equal to AudienceBasedVariation & targeting
|
|
90
|
-
let experienceReqObj = (0, utils_1.lookUpAudiences)(restExperienceData, audiencesUid);
|
|
91
|
+
let experienceReqObj = (0, utils_1.lookUpAudiences)(restExperienceData, this.audiencesUid);
|
|
91
92
|
//check whether events exists or not that referenced in metrics
|
|
92
|
-
experienceReqObj = (0, utils_1.lookUpEvents)(experienceReqObj, eventsUid);
|
|
93
|
-
const expRes = yield this.createExperience(experienceReqObj);
|
|
93
|
+
experienceReqObj = (0, utils_1.lookUpEvents)(experienceReqObj, this.eventsUid);
|
|
94
|
+
const expRes = (yield this.createExperience(experienceReqObj));
|
|
94
95
|
//map old experience uid to new experience uid
|
|
95
96
|
this.experiencesUidMapper[uid] = (_a = expRes === null || expRes === void 0 ? void 0 : expRes.uid) !== null && _a !== void 0 ? _a : '';
|
|
97
|
+
try {
|
|
98
|
+
// import versions of experience
|
|
99
|
+
yield this.importExperienceVersions(expRes, uid);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
this.log(this.config, `Error while importing experience versions of ${expRes.uid}`, 'error');
|
|
103
|
+
this.log(this.config, error, 'error');
|
|
104
|
+
}
|
|
96
105
|
}
|
|
97
106
|
utils_1.fsUtil.writeFile(this.experiencesUidMapperPath, this.experiencesUidMapper);
|
|
98
107
|
this.log(this.config, this.$t(this.messages.CREATE_SUCCESS, { module: 'Experiences' }), 'info');
|
|
@@ -103,9 +112,10 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
103
112
|
utils_1.fsUtil.writeFile(this.cmsVariantGroupPath, this.cmsVariantGroups);
|
|
104
113
|
if (jobRes)
|
|
105
114
|
this.log(this.config, this.$t(this.messages.CREATE_SUCCESS, { module: 'Variant & Variant groups' }), 'info');
|
|
106
|
-
if (this.
|
|
115
|
+
if (this.personalizeConfig.importData) {
|
|
107
116
|
this.log(this.config, this.messages.UPDATING_CT_IN_EXP, 'info');
|
|
108
117
|
yield this.attachCTsInExperience();
|
|
118
|
+
this.log(this.config, this.messages.UPDATED_CT_IN_EXP, 'info');
|
|
109
119
|
}
|
|
110
120
|
yield this.createVariantIdMapper();
|
|
111
121
|
}
|
|
@@ -117,9 +127,64 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
117
127
|
});
|
|
118
128
|
}
|
|
119
129
|
/**
|
|
120
|
-
* function
|
|
121
|
-
|
|
122
|
-
|
|
130
|
+
* function import experience versions from a JSON file and creates them in the project.
|
|
131
|
+
*/
|
|
132
|
+
importExperienceVersions(experience, oldExperienceUid) {
|
|
133
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
const versionsPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.experiencesDirPath), 'versions', `${(0, cli_utilities_1.sanitizePath)(oldExperienceUid)}.json`);
|
|
135
|
+
if (!(0, fs_1.existsSync)(versionsPath)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const versions = utils_1.fsUtil.readFile(versionsPath, true);
|
|
139
|
+
const versionMap = {
|
|
140
|
+
ACTIVE: undefined,
|
|
141
|
+
DRAFT: undefined,
|
|
142
|
+
PAUSE: undefined,
|
|
143
|
+
};
|
|
144
|
+
// Process each version and map them by status
|
|
145
|
+
versions.forEach((version) => {
|
|
146
|
+
let versionReqObj = (0, utils_1.lookUpAudiences)(version, this.audiencesUid);
|
|
147
|
+
versionReqObj = (0, utils_1.lookUpEvents)(version, this.eventsUid);
|
|
148
|
+
if (versionReqObj && versionReqObj.status) {
|
|
149
|
+
versionMap[versionReqObj.status] = versionReqObj;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
// Prioritize updating or creating versions based on the order: ACTIVE -> DRAFT -> PAUSE
|
|
153
|
+
return yield this.handleVersionUpdateOrCreate(experience, versionMap);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// Helper method to handle version update or creation logic
|
|
157
|
+
handleVersionUpdateOrCreate(experience, versionMap) {
|
|
158
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
159
|
+
const { ACTIVE, DRAFT, PAUSE } = versionMap;
|
|
160
|
+
let latestVersionUsed = false;
|
|
161
|
+
if (ACTIVE) {
|
|
162
|
+
yield this.updateExperienceVersion(experience.uid, experience.latestVersion, ACTIVE);
|
|
163
|
+
latestVersionUsed = true;
|
|
164
|
+
}
|
|
165
|
+
if (DRAFT) {
|
|
166
|
+
if (latestVersionUsed) {
|
|
167
|
+
yield this.createExperienceVersion(experience.uid, DRAFT);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
yield this.updateExperienceVersion(experience.uid, experience.latestVersion, DRAFT);
|
|
171
|
+
latestVersionUsed = true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (PAUSE) {
|
|
175
|
+
if (latestVersionUsed) {
|
|
176
|
+
yield this.createExperienceVersion(experience.uid, PAUSE);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
yield this.updateExperienceVersion(experience.uid, experience.latestVersion, PAUSE);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* function to validate if all variant groups and variants have been created using personalize background job
|
|
186
|
+
* store the variant groups data in mapper/personalize/experiences/cms-variant-groups.json and the variants data
|
|
187
|
+
* in mapper/personalize/experiences/cms-variants.json. If not, invoke validateVariantGroupAndVariantsCreated after some delay.
|
|
123
188
|
* @param retryCount Counter to track the number of times the function has been called
|
|
124
189
|
* @returns
|
|
125
190
|
*/
|
|
@@ -146,7 +211,7 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
146
211
|
return this.validateVariantGroupAndVariantsCreated(retryCount);
|
|
147
212
|
}
|
|
148
213
|
else {
|
|
149
|
-
this.log(this.config, this.messages.
|
|
214
|
+
this.log(this.config, this.messages.PERSONALIZE_JOB_FAILURE, 'error');
|
|
150
215
|
utils_1.fsUtil.writeFile(this.failedCmsExpPath, this.pendingVariantAndVariantGrpForExperience);
|
|
151
216
|
return false;
|
|
152
217
|
}
|
|
@@ -174,7 +239,7 @@ class Experiences extends utils_1.PersonalizationAdapter {
|
|
|
174
239
|
var _b;
|
|
175
240
|
if ((_b = experienceCTsMap[oldExpUid]) === null || _b === void 0 ? void 0 : _b.length) {
|
|
176
241
|
// Filter content types that were created
|
|
177
|
-
const updatedContentTypes = experienceCTsMap[oldExpUid].filter((ct) => this.createdCTs.includes(ct === null || ct === void 0 ? void 0 : ct.uid));
|
|
242
|
+
const updatedContentTypes = experienceCTsMap[oldExpUid].filter((ct) => this.createdCTs.includes(ct === null || ct === void 0 ? void 0 : ct.uid) && ct.status === 'linked');
|
|
178
243
|
if (updatedContentTypes === null || updatedContentTypes === void 0 ? void 0 : updatedContentTypes.length) {
|
|
179
244
|
const { variant_groups: [variantGroup] = [] } = (yield this.getVariantGroup({ experienceUid: newExpUid })) || {};
|
|
180
245
|
variantGroup.content_types = updatedContentTypes;
|
package/lib/import/project.js
CHANGED
|
@@ -17,13 +17,13 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
17
17
|
constructor(config, log = console.log) {
|
|
18
18
|
const conf = {
|
|
19
19
|
config,
|
|
20
|
-
baseURL: config.modules.
|
|
21
|
-
headers: { organization_uid: config.org_uid
|
|
20
|
+
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
21
|
+
headers: { organization_uid: config.org_uid },
|
|
22
22
|
};
|
|
23
23
|
super(Object.assign(config, conf));
|
|
24
24
|
this.config = config;
|
|
25
25
|
this.log = log;
|
|
26
|
-
this.projectMapperFolderPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.config.modules.
|
|
26
|
+
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');
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* The function asynchronously imports projects data from a file and creates projects based on the
|
|
@@ -31,16 +31,17 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
31
31
|
*/
|
|
32
32
|
import() {
|
|
33
33
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
const
|
|
35
|
-
const { dirName, fileName } =
|
|
36
|
-
const projectPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.data), (0, cli_utilities_1.sanitizePath)(
|
|
34
|
+
const personalize = this.config.modules.personalize;
|
|
35
|
+
const { dirName, fileName } = personalize.projects;
|
|
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
37
|
if ((0, fs_1.existsSync)(projectPath)) {
|
|
38
38
|
const projects = JSON.parse((0, fs_1.readFileSync)(projectPath, 'utf8'));
|
|
39
39
|
if (!projects || projects.length < 1) {
|
|
40
|
-
this.config.modules.
|
|
40
|
+
this.config.modules.personalize.importData = false; // Stop personalize import if stack not connected to any project
|
|
41
41
|
this.log(this.config, 'No project found!', 'info');
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
+
yield this.init();
|
|
44
45
|
for (const project of projects) {
|
|
45
46
|
const createProject = (newName) => __awaiter(this, void 0, void 0, function* () {
|
|
46
47
|
return yield this.createProject({
|
|
@@ -48,7 +49,7 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
48
49
|
description: project.description,
|
|
49
50
|
connectedStackApiKey: this.config.apiKey,
|
|
50
51
|
}).catch((error) => __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
if (error
|
|
52
|
+
if (error.includes('personalization.PROJECTS.DUPLICATE_NAME') || error.includes('personalize.PROJECTS.DUPLICATE_NAME')) {
|
|
52
53
|
const projectName = yield (0, utils_1.askProjectName)('Copy Of ' + (newName || project.name));
|
|
53
54
|
return yield createProject(projectName);
|
|
54
55
|
}
|
|
@@ -57,15 +58,15 @@ class Project extends utils_1.PersonalizationAdapter {
|
|
|
57
58
|
}));
|
|
58
59
|
});
|
|
59
60
|
const projectRes = yield createProject(this.config.personalizeProjectName);
|
|
60
|
-
this.config.modules.
|
|
61
|
-
this.config.modules.
|
|
61
|
+
this.config.modules.personalize.project_id = projectRes.uid;
|
|
62
|
+
this.config.modules.personalize.importData = true;
|
|
62
63
|
yield utils_1.fsUtil.makeDirectory(this.projectMapperFolderPath);
|
|
63
64
|
utils_1.fsUtil.writeFile((0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.projectMapperFolderPath), 'projects.json'), projectRes);
|
|
64
65
|
this.log(this.config, `Project Created Successfully: ${projectRes.uid}`, 'info');
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
else {
|
|
68
|
-
this.config.modules.
|
|
69
|
+
this.config.modules.personalize.importData = false; // Stop personalize import if stack not connected to any project
|
|
69
70
|
this.log(this.config, 'No project found!', 'info');
|
|
70
71
|
}
|
|
71
72
|
});
|
|
@@ -8,7 +8,7 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
8
8
|
entriesMapperPath: string;
|
|
9
9
|
variantEntryBasePath: string;
|
|
10
10
|
variantIdList: Record<string, unknown>;
|
|
11
|
-
|
|
11
|
+
personalizeConfig: ImportConfig['modules']['personalize'];
|
|
12
12
|
taxonomies: Record<string, unknown>;
|
|
13
13
|
assetUrlMapper: Record<string, any>;
|
|
14
14
|
assetUidMapper: Record<string, any>;
|
|
@@ -56,15 +56,14 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
56
56
|
headers: {
|
|
57
57
|
api_key: config.apiKey,
|
|
58
58
|
branch: config.branchName,
|
|
59
|
-
authtoken: config.auth_token,
|
|
60
59
|
organization_uid: config.org_uid,
|
|
61
|
-
'X-Project-Uid': config.modules.
|
|
60
|
+
'X-Project-Uid': config.modules.personalize.project_id,
|
|
62
61
|
},
|
|
63
62
|
};
|
|
64
63
|
super(Object.assign((0, omit_1.default)(config, ['helpers']), conf));
|
|
65
64
|
this.config = config;
|
|
66
65
|
this.entriesMapperPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.backupDir), (0, cli_utilities_1.sanitizePath)(config.branchName || ''), 'mapper', 'entries');
|
|
67
|
-
this.
|
|
66
|
+
this.personalizeConfig = this.config.modules.personalize;
|
|
68
67
|
this.entriesDirPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(config.backupDir), (0, cli_utilities_1.sanitizePath)(config.branchName || ''), (0, cli_utilities_1.sanitizePath)(config.modules.entries.dirName));
|
|
69
68
|
this.failedVariantPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.entriesMapperPath), 'failed-entry-variants.json');
|
|
70
69
|
this.failedVariantEntries = new Map();
|
|
@@ -80,7 +79,7 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
80
79
|
import() {
|
|
81
80
|
return __awaiter(this, void 0, void 0, function* () {
|
|
82
81
|
const filePath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.entriesMapperPath), 'data-for-variant-entry.json');
|
|
83
|
-
const variantIdPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.
|
|
82
|
+
const variantIdPath = (0, path_1.resolve)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.dirName), (0, cli_utilities_1.sanitizePath)(this.personalizeConfig.experiences.dirName), 'variants-uid-mapping.json');
|
|
84
83
|
if (!(0, fs_1.existsSync)(filePath)) {
|
|
85
84
|
(0, utils_1.log)(this.config, this.messages.IMPORT_ENTRY_NOT_FOUND, 'info');
|
|
86
85
|
return;
|
|
@@ -114,6 +113,8 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
114
113
|
this.assetUidMapper = (utils_1.fsUtil.readFile(assetUidMapperPath, true) || {});
|
|
115
114
|
this.assetUrlMapper = (utils_1.fsUtil.readFile(assetUrlMapperPath, true) || {});
|
|
116
115
|
this.environments = (utils_1.fsUtil.readFile(envPath, true) || {});
|
|
116
|
+
// set the token
|
|
117
|
+
yield this.variantInstance.init();
|
|
117
118
|
for (const entriesForVariant of entriesForVariants) {
|
|
118
119
|
yield this.importVariantEntries(entriesForVariant);
|
|
119
120
|
}
|
|
@@ -184,21 +185,21 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
184
185
|
log(this.config, error, 'error');
|
|
185
186
|
};
|
|
186
187
|
// NOTE Find new variant Id by old Id
|
|
187
|
-
const
|
|
188
|
+
const variantId = this.variantIdList[variantEntry._variant._uid];
|
|
188
189
|
// NOTE Replace all the relation data UID's
|
|
189
190
|
variantEntry = this.handleVariantEntryRelationalData(contentType, variantEntry);
|
|
190
191
|
const changeSet = this.serializeChangeSet(variantEntry);
|
|
191
192
|
const createVariantReq = Object.assign({ _variant: variantEntry._variant }, changeSet);
|
|
192
|
-
if (
|
|
193
|
+
if (variantId) {
|
|
193
194
|
const promise = this.variantInstance.createVariantEntry(createVariantReq, {
|
|
194
195
|
locale,
|
|
195
196
|
entry_uid: entryUid,
|
|
196
|
-
variant_id,
|
|
197
|
+
variant_id: variantId,
|
|
197
198
|
content_type_uid: content_type,
|
|
198
199
|
}, {
|
|
199
200
|
reject: onReject.bind(this),
|
|
200
201
|
resolve: onSuccess.bind(this),
|
|
201
|
-
variantUid:
|
|
202
|
+
variantUid: variantId,
|
|
202
203
|
log: utils_1.log,
|
|
203
204
|
});
|
|
204
205
|
allPromise.push(promise);
|
|
@@ -291,7 +292,7 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
291
292
|
* @param variantEntry - The entry variant to update.
|
|
292
293
|
*/
|
|
293
294
|
updateFileFields(variantEntry) {
|
|
294
|
-
var _a;
|
|
295
|
+
var _a, _b;
|
|
295
296
|
const setValue = (currentObj, keys) => {
|
|
296
297
|
if (!currentObj || keys.length === 0)
|
|
297
298
|
return;
|
|
@@ -304,7 +305,14 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
304
305
|
else if (currentObj && typeof currentObj === 'object') {
|
|
305
306
|
if (firstKey in currentObj) {
|
|
306
307
|
if (keys.length === 1) {
|
|
307
|
-
|
|
308
|
+
// Check if the current property is already an object with uid and filename
|
|
309
|
+
const existingValue = currentObj[firstKey];
|
|
310
|
+
if (existingValue && typeof existingValue === 'object' && existingValue.uid) {
|
|
311
|
+
currentObj[firstKey] = { uid: existingValue.uid, filename: 'dummy.jpeg' };
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
currentObj[firstKey] = { uid: currentObj[firstKey], filename: 'dummy.jpeg' };
|
|
315
|
+
}
|
|
308
316
|
}
|
|
309
317
|
else {
|
|
310
318
|
setValue(currentObj[firstKey], restKeys);
|
|
@@ -312,10 +320,8 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
312
320
|
}
|
|
313
321
|
}
|
|
314
322
|
};
|
|
315
|
-
const pathsToUpdate = (_a = variantEntry === null || variantEntry === void 0 ? void 0 : variantEntry._metadata) === null || _a === void 0 ? void 0 : _a.references.filter((ref) => ref._content_type_uid === 'sys_assets').map((ref) => ref.path);
|
|
316
|
-
|
|
317
|
-
pathsToUpdate.forEach((path) => setValue(variantEntry, path.split('.')));
|
|
318
|
-
}
|
|
323
|
+
const pathsToUpdate = ((_b = (_a = variantEntry === null || variantEntry === void 0 ? void 0 : variantEntry._metadata) === null || _a === void 0 ? void 0 : _a.references) === null || _b === void 0 ? void 0 : _b.filter((ref) => ref._content_type_uid === 'sys_assets').map((ref) => ref.path)) || [];
|
|
324
|
+
pathsToUpdate.forEach((path) => setValue(variantEntry, path.split('.')));
|
|
319
325
|
}
|
|
320
326
|
/**
|
|
321
327
|
* Publishes variant entries in batch for a given entry UID and content type.
|
|
@@ -328,16 +334,17 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
328
334
|
return __awaiter(this, void 0, void 0, function* () {
|
|
329
335
|
var _a;
|
|
330
336
|
const allPromise = [];
|
|
337
|
+
(0, utils_1.log)(this.config, `Publishing variant entries for entry uid '${entryUid}' of Content Type '${content_type}'`, 'info');
|
|
331
338
|
for (let [, variantEntry] of (0, entries_1.default)(batch)) {
|
|
332
|
-
const
|
|
333
|
-
const oldVariantUid = variantEntry.
|
|
339
|
+
const variantEntryUID = variantEntry.uid;
|
|
340
|
+
const oldVariantUid = variantEntry._variant._uid || '';
|
|
334
341
|
const newVariantUid = this.variantIdList[oldVariantUid];
|
|
335
342
|
if (!newVariantUid) {
|
|
336
|
-
(0, utils_1.log)(this.config, `${this.messages.VARIANT_ID_NOT_FOUND}. Skipping entry variant publish
|
|
343
|
+
(0, utils_1.log)(this.config, `${this.messages.VARIANT_ID_NOT_FOUND}. Skipping entry variant publish`, 'info');
|
|
337
344
|
continue;
|
|
338
345
|
}
|
|
339
|
-
if (this.failedVariantEntries.has(
|
|
340
|
-
(0, utils_1.log)(this.config, `${this.messages.VARIANT_UID_NOT_FOUND}. Skipping entry variant publish for ${
|
|
346
|
+
if (this.failedVariantEntries.has(variantEntryUID)) {
|
|
347
|
+
(0, utils_1.log)(this.config, `${this.messages.VARIANT_UID_NOT_FOUND}. Skipping entry variant publish for ${variantEntryUID}`, 'info');
|
|
341
348
|
continue;
|
|
342
349
|
}
|
|
343
350
|
if ((_a = this.environments) === null || _a === void 0 ? void 0 : _a.length) {
|
|
@@ -359,11 +366,9 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
359
366
|
entry: {
|
|
360
367
|
environments,
|
|
361
368
|
locales,
|
|
362
|
-
publish_with_base_entry: false,
|
|
363
369
|
variants: [{ uid: newVariantUid, version: 1 }],
|
|
364
370
|
},
|
|
365
371
|
locale: variantEntry.locale,
|
|
366
|
-
version: 1,
|
|
367
372
|
};
|
|
368
373
|
const promise = this.variantInstance.publishVariantEntry(publishReq, {
|
|
369
374
|
entry_uid: entryUid,
|
|
@@ -372,11 +377,12 @@ class VariantEntries extends variant_api_adapter_1.default {
|
|
|
372
377
|
reject: onReject.bind(this),
|
|
373
378
|
resolve: onSuccess.bind(this),
|
|
374
379
|
log: utils_1.log,
|
|
375
|
-
variantUid,
|
|
380
|
+
variantUid: newVariantUid,
|
|
376
381
|
});
|
|
377
382
|
allPromise.push(promise);
|
|
378
383
|
}
|
|
379
384
|
yield Promise.allSettled(allPromise);
|
|
385
|
+
(0, utils_1.log)(this.config, `Published variant entries for entry uid '${entryUid}' of Content Type '${content_type}'`, 'info');
|
|
380
386
|
});
|
|
381
387
|
}
|
|
382
388
|
/**
|
package/lib/messages/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ declare const expImportMsg: {
|
|
|
17
17
|
UPDATING_CT_IN_EXP: string;
|
|
18
18
|
UPDATED_CT_IN_EXP: string;
|
|
19
19
|
VALIDATE_VARIANT_AND_VARIANT_GRP: string;
|
|
20
|
-
|
|
20
|
+
PERSONALIZE_JOB_FAILURE: string;
|
|
21
21
|
};
|
|
22
22
|
declare const messages: typeof errors & typeof commonMsg & typeof migrationMsg & typeof variantEntry & typeof expImportMsg;
|
|
23
23
|
/**
|
package/lib/messages/index.js
CHANGED
|
@@ -27,7 +27,7 @@ const expImportMsg = {
|
|
|
27
27
|
UPDATING_CT_IN_EXP: 'Updating content types in experiences...',
|
|
28
28
|
UPDATED_CT_IN_EXP: 'Successfully updated content types in experiences!',
|
|
29
29
|
VALIDATE_VARIANT_AND_VARIANT_GRP: 'Validating variant group and variants creation...',
|
|
30
|
-
|
|
30
|
+
PERSONALIZE_JOB_FAILURE: 'Something went wrong! Failed to fetch some variant and variant groups.',
|
|
31
31
|
};
|
|
32
32
|
const messages = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, errors), commonMsg), migrationMsg), variantEntry), expImportMsg);
|
|
33
33
|
/**
|
|
@@ -46,7 +46,8 @@ function $t(msg, args) {
|
|
|
46
46
|
return '';
|
|
47
47
|
for (const key of Object.keys(args)) {
|
|
48
48
|
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
49
|
-
|
|
49
|
+
const placeholder = `{${escapedKey}}`;
|
|
50
|
+
msg = msg.split(placeholder).join(args[key]);
|
|
50
51
|
}
|
|
51
52
|
return msg;
|
|
52
53
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Therefore, we are duplicating the following types from the export.
|
|
5
5
|
*/
|
|
6
6
|
import { AnyProperty } from './utils';
|
|
7
|
-
export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies' | '
|
|
7
|
+
export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies' | 'personalize';
|
|
8
8
|
export type branch = {
|
|
9
9
|
uid: string;
|
|
10
10
|
source: string;
|
|
@@ -131,7 +131,7 @@ export interface DefaultConfig {
|
|
|
131
131
|
include_publish_details: boolean;
|
|
132
132
|
} & AnyProperty;
|
|
133
133
|
} & AnyProperty;
|
|
134
|
-
|
|
134
|
+
personalize: {
|
|
135
135
|
dirName: string;
|
|
136
136
|
baseURL: Record<string, string>;
|
|
137
137
|
} & AnyProperty;
|
|
@@ -243,7 +243,7 @@ export interface ExportConfig extends DefaultConfig {
|
|
|
243
243
|
personalizationHost?: string;
|
|
244
244
|
region: any;
|
|
245
245
|
}
|
|
246
|
-
export interface
|
|
246
|
+
export interface PersonalizeConfig {
|
|
247
247
|
dirName: string;
|
|
248
248
|
baseURL: Record<string, string>;
|
|
249
249
|
}
|
|
@@ -112,6 +112,18 @@ export type ExperienceStruct = {
|
|
|
112
112
|
};
|
|
113
113
|
content_types?: string[];
|
|
114
114
|
} & AnyProperty;
|
|
115
|
+
export interface CreateExperienceVersionInput {
|
|
116
|
+
name: string;
|
|
117
|
+
__type: string;
|
|
118
|
+
description: string;
|
|
119
|
+
targeting?: ExpTargeting;
|
|
120
|
+
variations: ExpVariations[];
|
|
121
|
+
variationSplit?: string;
|
|
122
|
+
metrics?: ExpMetric[];
|
|
123
|
+
status: string;
|
|
124
|
+
metadata?: object;
|
|
125
|
+
variants: Array<ExpVariations>;
|
|
126
|
+
}
|
|
115
127
|
export interface CreateExperienceInput {
|
|
116
128
|
name: string;
|
|
117
129
|
__type: string;
|
|
@@ -122,6 +134,7 @@ export interface CreateExperienceInput {
|
|
|
122
134
|
metrics?: ExpMetric[];
|
|
123
135
|
status: string;
|
|
124
136
|
metadata?: object;
|
|
137
|
+
variants?: Array<ExpVariations>;
|
|
125
138
|
}
|
|
126
139
|
export interface UpdateExperienceInput {
|
|
127
140
|
contentTypes: string[];
|
|
@@ -147,6 +160,6 @@ export interface Personalization<T> extends AdapterHelperInterface<T, HttpClient
|
|
|
147
160
|
createExperience(experience: CreateExperienceInput): Promise<ExperienceStruct | void>;
|
|
148
161
|
getCTsFromExperience(experienceUid: string): Promise<CMSExperienceStruct | void>;
|
|
149
162
|
updateCTsInExperience(experience: UpdateExperienceInput, experienceUid: string): Promise<CMSExperienceStruct | void>;
|
|
150
|
-
handleVariantAPIRes(res: any): VariantAPIRes
|
|
163
|
+
handleVariantAPIRes(res: any): Promise<VariantAPIRes>;
|
|
151
164
|
}
|
|
152
165
|
export {};
|
|
@@ -35,6 +35,7 @@ export type VariantOptions = VariantsOption & {
|
|
|
35
35
|
variant_uid: string;
|
|
36
36
|
};
|
|
37
37
|
export interface VariantInterface<T, ApiClient> extends AdapterHelperInterface<T, ApiClient> {
|
|
38
|
+
init(): Promise<void>;
|
|
38
39
|
variantEntry(options: VariantOptions): Promise<{
|
|
39
40
|
entry: Record<string, any>;
|
|
40
41
|
}>;
|
|
@@ -42,8 +43,8 @@ export interface VariantInterface<T, ApiClient> extends AdapterHelperInterface<T
|
|
|
42
43
|
entries?: Record<string, any>[] | unknown[];
|
|
43
44
|
} | void>;
|
|
44
45
|
createVariantEntry(input: CreateVariantEntryDto, options: CreateVariantEntryOptions, apiParams: Record<string, any>): Promise<VariantEntryStruct | string | void>;
|
|
45
|
-
handleVariantAPIRes(res: APIResponse): VariantEntryStruct | {
|
|
46
|
+
handleVariantAPIRes(res: APIResponse): Promise<VariantEntryStruct | {
|
|
46
47
|
entries: VariantEntryStruct[];
|
|
47
48
|
count: number;
|
|
48
|
-
} | string
|
|
49
|
+
} | string>;
|
|
49
50
|
}
|
|
@@ -2,11 +2,11 @@ import { AnyProperty } from './utils';
|
|
|
2
2
|
export type VariantEntryStruct = {
|
|
3
3
|
uid: string;
|
|
4
4
|
title: string;
|
|
5
|
-
variant_id: string;
|
|
6
5
|
locale: string;
|
|
7
6
|
_version: number;
|
|
8
7
|
_variant: {
|
|
9
|
-
|
|
8
|
+
_uid: string;
|
|
9
|
+
_instance_uid: string;
|
|
10
10
|
_change_set: string[];
|
|
11
11
|
_base_entry_version: number;
|
|
12
12
|
};
|
|
@@ -36,7 +36,6 @@ export type PublishVariantEntryDto = {
|
|
|
36
36
|
entry: {
|
|
37
37
|
environments: string[];
|
|
38
38
|
locales: string[];
|
|
39
|
-
publish_with_base_entry: boolean;
|
|
40
39
|
variants: {
|
|
41
40
|
uid: string;
|
|
42
41
|
version?: number;
|
|
@@ -15,8 +15,8 @@ const lookUpAttributes = (attributeRules, attributesUid) => {
|
|
|
15
15
|
// Check if attribute reference exists in attributesUid
|
|
16
16
|
const attributeRef = (_a = rule.attribute) === null || _a === void 0 ? void 0 : _a.ref;
|
|
17
17
|
const attributeType = rule.attribute['__type'];
|
|
18
|
-
// check if type is
|
|
19
|
-
if (attributeType === '
|
|
18
|
+
// check if type is CustomAttributeReference
|
|
19
|
+
if (attributeType === 'CustomAttributeReference') {
|
|
20
20
|
if (attributeRef && attributesUid.hasOwnProperty(attributeRef) && attributesUid[attributeRef]) {
|
|
21
21
|
rule.attribute.ref = attributesUid[attributeRef];
|
|
22
22
|
}
|
|
@@ -24,7 +24,7 @@ function updateAudiences(audiences, audiencesUid) {
|
|
|
24
24
|
* @returns
|
|
25
25
|
*/
|
|
26
26
|
const lookUpAudiences = (experience, audiencesUid) => {
|
|
27
|
-
var _a, _b, _c, _d, _e, _f;
|
|
27
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
28
28
|
// Update experience variations
|
|
29
29
|
if ((_a = experience === null || experience === void 0 ? void 0 : experience.variations) === null || _a === void 0 ? void 0 : _a.length) {
|
|
30
30
|
for (let index = experience.variations.length - 1; index >= 0; index--) {
|
|
@@ -37,8 +37,19 @@ const lookUpAudiences = (experience, audiencesUid) => {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
else if (experience.variants) {
|
|
41
|
+
for (let index = experience.variants.length - 1; index >= 0; index--) {
|
|
42
|
+
const expVariations = experience.variants[index];
|
|
43
|
+
if (expVariations['__type'] === 'SegmentedVariant' && ((_c = expVariations === null || expVariations === void 0 ? void 0 : expVariations.audiences) === null || _c === void 0 ? void 0 : _c.length)) {
|
|
44
|
+
updateAudiences(expVariations.audiences, audiencesUid);
|
|
45
|
+
if (!expVariations.audiences.length) {
|
|
46
|
+
experience.variants.splice(index, 1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (((_d = experience === null || experience === void 0 ? void 0 : experience.targeting) === null || _d === void 0 ? void 0 : _d.hasOwnProperty('audience')) && ((_g = (_f = (_e = experience === null || experience === void 0 ? void 0 : experience.targeting) === null || _e === void 0 ? void 0 : _e.audience) === null || _f === void 0 ? void 0 : _f.audiences) === null || _g === void 0 ? void 0 : _g.length)) {
|
|
52
|
+
// Update targeting audiences
|
|
42
53
|
updateAudiences(experience.targeting.audience.audiences, audiencesUid);
|
|
43
54
|
if (!experience.targeting.audience.audiences.length) {
|
|
44
55
|
experience.targeting = {};
|
|
@@ -11,17 +11,17 @@ function formatErrors(errors) {
|
|
|
11
11
|
for (const errorKey in errors) {
|
|
12
12
|
const errorValue = errors[errorKey];
|
|
13
13
|
if (Array.isArray(errorValue)) {
|
|
14
|
-
errorMessages.push(...errorValue.map((error) => formatError(error)));
|
|
14
|
+
errorMessages.push(...errorValue.map((error) => formatError(errorKey, error)));
|
|
15
15
|
}
|
|
16
16
|
else {
|
|
17
|
-
errorMessages.push(formatError(errorValue));
|
|
17
|
+
errorMessages.push(formatError(errorKey, errorValue));
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
return errorMessages.join(' ');
|
|
21
21
|
}
|
|
22
|
-
function formatError(error) {
|
|
23
|
-
if (typeof error === 'object') {
|
|
24
|
-
return Object.values(error).join(' ')
|
|
22
|
+
function formatError(errorKey, error) {
|
|
23
|
+
if (typeof error === 'object' && error !== null) {
|
|
24
|
+
return `${errorKey}: ${Object.values(error).join(' ')}`;
|
|
25
25
|
}
|
|
26
|
-
return
|
|
26
|
+
return `${errorKey}: ${error}`;
|
|
27
27
|
}
|