@contentstack/cli-variants 1.0.0 → 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.js +2 -1
- package/lib/export/audiences.js +2 -1
- package/lib/export/events.js +2 -1
- package/lib/export/experiences.js +3 -2
- package/lib/export/projects.js +2 -1
- package/lib/export/variant-entries.js +1 -1
- package/lib/import/attribute.js +2 -1
- package/lib/import/audiences.js +2 -1
- package/lib/import/events.js +2 -1
- package/lib/import/experiences.js +3 -2
- package/lib/import/project.js +3 -2
- package/lib/import/variant-entries.js +15 -9
- package/lib/messages/index.js +1 -1
- package/lib/types/personalization-api-adapter.d.ts +1 -1
- package/lib/types/variant-api-adapter.d.ts +3 -2
- package/lib/types/variant-entry.d.ts +0 -1
- package/lib/utils/attributes-helper.js +2 -2
- package/lib/utils/error-helper.js +6 -6
- package/lib/utils/logger.js +5 -4
- package/lib/utils/personalization-api-adapter.d.ts +2 -1
- package/lib/utils/personalization-api-adapter.js +54 -26
- package/lib/utils/variant-api-adapter.d.ts +5 -4
- package/lib/utils/variant-api-adapter.js +28 -10
- package/package.json +2 -2
- package/src/export/attributes.ts +6 -2
- package/src/export/audiences.ts +2 -1
- package/src/export/events.ts +2 -1
- package/src/export/experiences.ts +3 -2
- package/src/export/projects.ts +2 -1
- package/src/export/variant-entries.ts +1 -2
- package/src/import/attribute.ts +2 -2
- package/src/import/audiences.ts +2 -2
- package/src/import/events.ts +2 -2
- package/src/import/experiences.ts +3 -3
- package/src/import/project.ts +4 -4
- package/src/import/variant-entries.ts +22 -12
- package/src/messages/index.ts +1 -1
- package/src/types/personalization-api-adapter.ts +1 -1
- package/src/types/variant-api-adapter.ts +3 -1
- package/src/types/variant-entry.ts +0 -1
- package/src/utils/attributes-helper.ts +2 -2
- package/src/utils/error-helper.ts +6 -6
- package/src/utils/logger.ts +5 -4
- package/src/utils/personalization-api-adapter.ts +45 -22
- package/src/utils/variant-api-adapter.ts +19 -5
|
@@ -5,6 +5,7 @@ import { AdapterHelper } from './adapter-helper';
|
|
|
5
5
|
export declare class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> implements VariantInterface<C, HttpClient> {
|
|
6
6
|
baseURL: string;
|
|
7
7
|
constructor(config: APIConfig, options?: HttpClientOptions);
|
|
8
|
+
init(): Promise<void>;
|
|
8
9
|
variantEntry(options: VariantOptions): Promise<{
|
|
9
10
|
entry: {};
|
|
10
11
|
}>;
|
|
@@ -48,10 +49,10 @@ export declare class VariantHttpClient<C> extends AdapterHelper<C, HttpClient> i
|
|
|
48
49
|
* @returns The variant API response data.
|
|
49
50
|
* @throws If the API response status is not within the success range, an error message is thrown.
|
|
50
51
|
*/
|
|
51
|
-
handleVariantAPIRes(res: APIResponse): VariantEntryStruct | {
|
|
52
|
+
handleVariantAPIRes(res: APIResponse): Promise<VariantEntryStruct | {
|
|
52
53
|
entries: VariantEntryStruct[];
|
|
53
54
|
count: number;
|
|
54
|
-
} | string | any
|
|
55
|
+
} | string | any>;
|
|
55
56
|
}
|
|
56
57
|
export declare class VariantManagementSDK<T> extends AdapterHelper<T, ContentstackClient> implements VariantInterface<T, ContentstackClient> {
|
|
57
58
|
apiClient: ContentstackClient;
|
|
@@ -63,10 +64,10 @@ export declare class VariantManagementSDK<T> extends AdapterHelper<T, Contentsta
|
|
|
63
64
|
entries: {}[];
|
|
64
65
|
}>;
|
|
65
66
|
createVariantEntry(input: CreateVariantEntryDto, options: CreateVariantEntryOptions, apiParams: Record<string, any>): Promise<VariantEntryStruct | string | void>;
|
|
66
|
-
handleVariantAPIRes(res: APIResponse): VariantEntryStruct | {
|
|
67
|
+
handleVariantAPIRes(res: APIResponse): Promise<VariantEntryStruct | {
|
|
67
68
|
entries: VariantEntryStruct[];
|
|
68
69
|
count: number;
|
|
69
|
-
} | string
|
|
70
|
+
} | string>;
|
|
70
71
|
constructQuery(query: Record<string, any>): string | void;
|
|
71
72
|
delay(ms: number): Promise<void>;
|
|
72
73
|
}
|
|
@@ -37,6 +37,18 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
37
37
|
this.baseURL = ((_a = config.baseURL) === null || _a === void 0 ? void 0 : _a.includes('http')) ? `${config.baseURL}/v3` : `https://${config.baseURL}/v3`;
|
|
38
38
|
this.apiClient.baseUrl(this.baseURL);
|
|
39
39
|
}
|
|
40
|
+
init() {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
yield cli_utilities_1.authenticationHandler.getAuthDetails();
|
|
43
|
+
const token = cli_utilities_1.authenticationHandler.accessToken;
|
|
44
|
+
if (cli_utilities_1.authenticationHandler.isOauthEnabled) {
|
|
45
|
+
this.apiClient.headers({ authorization: token });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.apiClient.headers({ authtoken: token });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
40
52
|
variantEntry(options) {
|
|
41
53
|
return __awaiter(this, void 0, void 0, function* () {
|
|
42
54
|
// TODO single entry variant
|
|
@@ -99,7 +111,7 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
99
111
|
endpoint = endpoint.concat(query);
|
|
100
112
|
}
|
|
101
113
|
const data = yield this.apiClient.get(endpoint);
|
|
102
|
-
const response = this.handleVariantAPIRes(data);
|
|
114
|
+
const response = (yield this.handleVariantAPIRes(data));
|
|
103
115
|
if (callback) {
|
|
104
116
|
callback(response.entries);
|
|
105
117
|
}
|
|
@@ -205,14 +217,18 @@ class VariantHttpClient extends adapter_helper_1.AdapterHelper {
|
|
|
205
217
|
* @throws If the API response status is not within the success range, an error message is thrown.
|
|
206
218
|
*/
|
|
207
219
|
handleVariantAPIRes(res) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
220
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
221
|
+
const { status, data } = res;
|
|
222
|
+
if (status >= 200 && status < 300) {
|
|
223
|
+
return data;
|
|
224
|
+
}
|
|
225
|
+
// Refresh the access token if the response status is 401
|
|
226
|
+
yield cli_utilities_1.authenticationHandler.refreshAccessToken(res);
|
|
227
|
+
const errorMsg = (data === null || data === void 0 ? void 0 : data.errors)
|
|
228
|
+
? (0, error_helper_1.formatErrors)(data.errors)
|
|
229
|
+
: (data === null || data === void 0 ? void 0 : data.error_message) || (data === null || data === void 0 ? void 0 : data.message) || 'Something went wrong while processing entry variant request!';
|
|
230
|
+
throw errorMsg;
|
|
231
|
+
});
|
|
216
232
|
}
|
|
217
233
|
}
|
|
218
234
|
exports.VariantHttpClient = VariantHttpClient;
|
|
@@ -239,7 +255,9 @@ class VariantManagementSDK extends adapter_helper_1.AdapterHelper {
|
|
|
239
255
|
return Promise.resolve({});
|
|
240
256
|
}
|
|
241
257
|
handleVariantAPIRes(res) {
|
|
242
|
-
return
|
|
258
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
return res.data;
|
|
260
|
+
});
|
|
243
261
|
}
|
|
244
262
|
constructQuery(query) { }
|
|
245
263
|
delay(ms) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-variants",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Variants plugin",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"typescript": "^5.4.2"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@contentstack/cli-utilities": "^1.
|
|
33
|
+
"@contentstack/cli-utilities": "^1.8.0",
|
|
34
34
|
"lodash": "^4.17.21",
|
|
35
35
|
"mkdirp": "^1.0.4",
|
|
36
36
|
"winston": "^3.7.2"
|
package/src/export/attributes.ts
CHANGED
|
@@ -14,7 +14,7 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
|
|
|
14
14
|
super({
|
|
15
15
|
config: exportConfig,
|
|
16
16
|
baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
|
|
17
|
-
headers: {
|
|
17
|
+
headers: { 'X-Project-Uid': exportConfig.project_id },
|
|
18
18
|
});
|
|
19
19
|
this.personalizeConfig = exportConfig.modules.personalize;
|
|
20
20
|
this.attributesConfig = exportConfig.modules.attributes;
|
|
@@ -30,6 +30,7 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
|
|
|
30
30
|
async start() {
|
|
31
31
|
try {
|
|
32
32
|
log(this.exportConfig, 'Starting attributes export', 'info');
|
|
33
|
+
await this.init();
|
|
33
34
|
await fsUtil.makeDirectory(this.attributesFolderPath);
|
|
34
35
|
this.attributes = (await this.getAttributes()) as AttributeStruct[];
|
|
35
36
|
|
|
@@ -37,7 +38,10 @@ export default class ExportAttributes extends PersonalizationAdapter<ExportConfi
|
|
|
37
38
|
log(this.exportConfig, 'No Attributes found with the given project!', 'info');
|
|
38
39
|
} else {
|
|
39
40
|
this.sanitizeAttribs();
|
|
40
|
-
fsUtil.writeFile(
|
|
41
|
+
fsUtil.writeFile(
|
|
42
|
+
pResolve(sanitizePath(this.attributesFolderPath), sanitizePath(this.attributesConfig.fileName)),
|
|
43
|
+
this.attributes,
|
|
44
|
+
);
|
|
41
45
|
log(this.exportConfig, 'All the attributes have been exported successfully!', 'success');
|
|
42
46
|
}
|
|
43
47
|
} catch (error) {
|
package/src/export/audiences.ts
CHANGED
|
@@ -14,7 +14,7 @@ export default class ExportAudiences extends PersonalizationAdapter<ExportConfig
|
|
|
14
14
|
super({
|
|
15
15
|
config: exportConfig,
|
|
16
16
|
baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
|
|
17
|
-
headers: {
|
|
17
|
+
headers: { 'X-Project-Uid': exportConfig.project_id },
|
|
18
18
|
});
|
|
19
19
|
this.personalizeConfig = exportConfig.modules.personalize;
|
|
20
20
|
this.audiencesConfig = exportConfig.modules.audiences;
|
|
@@ -30,6 +30,7 @@ export default class ExportAudiences extends PersonalizationAdapter<ExportConfig
|
|
|
30
30
|
async start() {
|
|
31
31
|
try {
|
|
32
32
|
log(this.exportConfig, 'Starting audiences export', 'info');
|
|
33
|
+
await this.init();
|
|
33
34
|
await fsUtil.makeDirectory(this.audiencesFolderPath);
|
|
34
35
|
this.audiences = (await this.getAudiences()) as AudienceStruct[];
|
|
35
36
|
|
package/src/export/events.ts
CHANGED
|
@@ -14,7 +14,7 @@ export default class ExportEvents extends PersonalizationAdapter<ExportConfig> {
|
|
|
14
14
|
super({
|
|
15
15
|
config: exportConfig,
|
|
16
16
|
baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
|
|
17
|
-
headers: {
|
|
17
|
+
headers: { 'X-Project-Uid': exportConfig.project_id },
|
|
18
18
|
});
|
|
19
19
|
this.personalizeConfig = exportConfig.modules.personalize;
|
|
20
20
|
this.eventsConfig = exportConfig.modules.events;
|
|
@@ -30,6 +30,7 @@ export default class ExportEvents extends PersonalizationAdapter<ExportConfig> {
|
|
|
30
30
|
async start() {
|
|
31
31
|
try {
|
|
32
32
|
log(this.exportConfig, 'Starting events export', 'info');
|
|
33
|
+
await this.init();
|
|
33
34
|
await fsUtil.makeDirectory(this.eventsFolderPath);
|
|
34
35
|
this.events = (await this.getEvents()) as EventStruct[];
|
|
35
36
|
|
|
@@ -11,10 +11,10 @@ export default class ExportExperiences extends PersonalizationAdapter<ExportConf
|
|
|
11
11
|
super({
|
|
12
12
|
config: exportConfig,
|
|
13
13
|
baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
|
|
14
|
-
headers: {
|
|
14
|
+
headers: { 'X-Project-Uid': exportConfig.project_id },
|
|
15
15
|
cmaConfig: {
|
|
16
16
|
baseURL: exportConfig.region.cma + `/v3`,
|
|
17
|
-
headers: {
|
|
17
|
+
headers: { api_key: exportConfig.apiKey },
|
|
18
18
|
},
|
|
19
19
|
});
|
|
20
20
|
this.exportConfig = exportConfig;
|
|
@@ -33,6 +33,7 @@ export default class ExportExperiences extends PersonalizationAdapter<ExportConf
|
|
|
33
33
|
// loop through experiences and get content types attached to it
|
|
34
34
|
// write experiences in to a file
|
|
35
35
|
log(this.exportConfig, 'Starting experiences export', 'info');
|
|
36
|
+
await this.init();
|
|
36
37
|
await fsUtil.makeDirectory(this.experiencesFolderPath);
|
|
37
38
|
await fsUtil.makeDirectory(path.resolve(sanitizePath(this.experiencesFolderPath), 'versions'));
|
|
38
39
|
const experiences: Array<ExperienceStruct> = (await this.getExperiences()) || [];
|
package/src/export/projects.ts
CHANGED
|
@@ -11,7 +11,7 @@ export default class ExportProjects extends PersonalizationAdapter<ExportConfig>
|
|
|
11
11
|
super({
|
|
12
12
|
config: exportConfig,
|
|
13
13
|
baseURL: exportConfig.modules.personalize.baseURL[exportConfig.region.name],
|
|
14
|
-
headers: {
|
|
14
|
+
headers: { organization_uid: exportConfig.org_uid },
|
|
15
15
|
});
|
|
16
16
|
this.exportConfig = exportConfig;
|
|
17
17
|
this.personalizeConfig = exportConfig.modules.personalize;
|
|
@@ -26,6 +26,7 @@ export default class ExportProjects extends PersonalizationAdapter<ExportConfig>
|
|
|
26
26
|
async start() {
|
|
27
27
|
try {
|
|
28
28
|
log(this.exportConfig, 'Starting projects export', 'info');
|
|
29
|
+
await this.init();
|
|
29
30
|
await fsUtil.makeDirectory(this.projectFolderPath);
|
|
30
31
|
const project = await this.projects({ connectedStackApiKey: this.exportConfig.apiKey });
|
|
31
32
|
if (!project || project?.length < 1) {
|
|
@@ -19,7 +19,6 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Exp
|
|
|
19
19
|
headers: {
|
|
20
20
|
api_key: config.apiKey,
|
|
21
21
|
branch: config.branchName,
|
|
22
|
-
authtoken: config.auth_token,
|
|
23
22
|
organization_uid: config.org_uid,
|
|
24
23
|
'X-Project-Uid': config.project_id,
|
|
25
24
|
},
|
|
@@ -36,7 +35,7 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Exp
|
|
|
36
35
|
async exportVariantEntry(options: { locale: string; contentTypeUid: string; entries: Record<string, any>[] }) {
|
|
37
36
|
const variantEntry = this.config.modules.variantEntry;
|
|
38
37
|
const { entries, locale, contentTypeUid: content_type_uid } = options;
|
|
39
|
-
|
|
38
|
+
await this.variantInstance.init();
|
|
40
39
|
for (let index = 0; index < entries.length; index++) {
|
|
41
40
|
const entry = entries[index];
|
|
42
41
|
const variantEntryBasePath = join(sanitizePath(this.entriesDirPath), sanitizePath(content_type_uid), sanitizePath(locale), sanitizePath(variantEntry.dirName), sanitizePath(entry.uid));
|
package/src/import/attribute.ts
CHANGED
|
@@ -16,7 +16,7 @@ export default class Attribute extends PersonalizationAdapter<ImportConfig> {
|
|
|
16
16
|
const conf: APIConfig = {
|
|
17
17
|
config,
|
|
18
18
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
19
|
-
headers: { 'X-Project-Uid': config.modules.personalize.project_id
|
|
19
|
+
headers: { 'X-Project-Uid': config.modules.personalize.project_id },
|
|
20
20
|
};
|
|
21
21
|
super(Object.assign(config, conf));
|
|
22
22
|
this.personalizeConfig = this.config.modules.personalize;
|
|
@@ -36,7 +36,7 @@ export default class Attribute extends PersonalizationAdapter<ImportConfig> {
|
|
|
36
36
|
*/
|
|
37
37
|
async import() {
|
|
38
38
|
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Attributes' }), 'info');
|
|
39
|
-
|
|
39
|
+
await this.init();
|
|
40
40
|
await fsUtil.makeDirectory(this.attrMapperDirPath);
|
|
41
41
|
const { dirName, fileName } = this.attributeConfig;
|
|
42
42
|
const attributesPath = resolve(
|
package/src/import/audiences.ts
CHANGED
|
@@ -18,7 +18,7 @@ export default class Audiences extends PersonalizationAdapter<ImportConfig> {
|
|
|
18
18
|
const conf: APIConfig = {
|
|
19
19
|
config,
|
|
20
20
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
21
|
-
headers: { 'X-Project-Uid': config.modules.personalize.project_id
|
|
21
|
+
headers: { 'X-Project-Uid': config.modules.personalize.project_id },
|
|
22
22
|
};
|
|
23
23
|
super(Object.assign(config, conf));
|
|
24
24
|
this.personalizeConfig = this.config.modules.personalize;
|
|
@@ -44,7 +44,7 @@ export default class Audiences extends PersonalizationAdapter<ImportConfig> {
|
|
|
44
44
|
*/
|
|
45
45
|
async import() {
|
|
46
46
|
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Audiences' }), 'info');
|
|
47
|
-
|
|
47
|
+
await this.init();
|
|
48
48
|
await fsUtil.makeDirectory(this.audienceMapperDirPath);
|
|
49
49
|
const { dirName, fileName } = this.audienceConfig;
|
|
50
50
|
const audiencesPath = resolve(
|
package/src/import/events.ts
CHANGED
|
@@ -16,7 +16,7 @@ export default class Events extends PersonalizationAdapter<ImportConfig> {
|
|
|
16
16
|
const conf: APIConfig = {
|
|
17
17
|
config,
|
|
18
18
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
19
|
-
headers: { 'X-Project-Uid': config.modules.personalize.project_id
|
|
19
|
+
headers: { 'X-Project-Uid': config.modules.personalize.project_id },
|
|
20
20
|
};
|
|
21
21
|
super(Object.assign(config, conf));
|
|
22
22
|
this.personalizeConfig = this.config.modules.personalize;
|
|
@@ -36,7 +36,7 @@ export default class Events extends PersonalizationAdapter<ImportConfig> {
|
|
|
36
36
|
*/
|
|
37
37
|
async import() {
|
|
38
38
|
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Events' }), 'info');
|
|
39
|
-
|
|
39
|
+
await this.init();
|
|
40
40
|
await fsUtil.makeDirectory(this.eventMapperDirPath);
|
|
41
41
|
const { dirName, fileName } = this.eventsConfig;
|
|
42
42
|
const eventsPath = resolve(
|
|
@@ -45,10 +45,10 @@ export default class Experiences extends PersonalizationAdapter<ImportConfig> {
|
|
|
45
45
|
const conf: APIConfig = {
|
|
46
46
|
config,
|
|
47
47
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
48
|
-
headers: { 'X-Project-Uid': config.modules.personalize.project_id
|
|
48
|
+
headers: { 'X-Project-Uid': config.modules.personalize.project_id},
|
|
49
49
|
cmaConfig: {
|
|
50
50
|
baseURL: config.region.cma + `/v3`,
|
|
51
|
-
headers: {
|
|
51
|
+
headers: { api_key: config.apiKey },
|
|
52
52
|
},
|
|
53
53
|
};
|
|
54
54
|
super(Object.assign(config, conf));
|
|
@@ -107,7 +107,7 @@ export default class Experiences extends PersonalizationAdapter<ImportConfig> {
|
|
|
107
107
|
*/
|
|
108
108
|
async import() {
|
|
109
109
|
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Experiences' }), 'info');
|
|
110
|
-
|
|
110
|
+
await this.init();
|
|
111
111
|
await fsUtil.makeDirectory(this.expMapperDirPath);
|
|
112
112
|
|
|
113
113
|
if (existsSync(this.experiencesPath)) {
|
package/src/import/project.ts
CHANGED
|
@@ -10,7 +10,7 @@ export default class Project extends PersonalizationAdapter<ImportConfig> {
|
|
|
10
10
|
const conf: APIConfig = {
|
|
11
11
|
config,
|
|
12
12
|
baseURL: config.modules.personalize.baseURL[config.region.name],
|
|
13
|
-
headers: { organization_uid: config.org_uid
|
|
13
|
+
headers: { organization_uid: config.org_uid },
|
|
14
14
|
};
|
|
15
15
|
super(Object.assign(config, conf));
|
|
16
16
|
this.projectMapperFolderPath = pResolve(
|
|
@@ -29,7 +29,7 @@ export default class Project extends PersonalizationAdapter<ImportConfig> {
|
|
|
29
29
|
const personalize = this.config.modules.personalize;
|
|
30
30
|
const { dirName, fileName } = personalize.projects;
|
|
31
31
|
const projectPath = join(sanitizePath(this.config.data), sanitizePath(personalize.dirName), sanitizePath(dirName), sanitizePath(fileName));
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
if (existsSync(projectPath)) {
|
|
34
34
|
const projects = JSON.parse(readFileSync(projectPath, 'utf8')) as CreateProjectInput[];
|
|
35
35
|
|
|
@@ -38,7 +38,7 @@ export default class Project extends PersonalizationAdapter<ImportConfig> {
|
|
|
38
38
|
this.log(this.config, 'No project found!', 'info');
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
await this.init();
|
|
42
42
|
for (const project of projects) {
|
|
43
43
|
const createProject = async (newName: void | string): Promise<ProjectStruct> => {
|
|
44
44
|
return await this.createProject({
|
|
@@ -46,7 +46,7 @@ export default class Project extends PersonalizationAdapter<ImportConfig> {
|
|
|
46
46
|
description: project.description,
|
|
47
47
|
connectedStackApiKey: this.config.apiKey,
|
|
48
48
|
}).catch(async (error) => {
|
|
49
|
-
if (error
|
|
49
|
+
if (error.includes('personalization.PROJECTS.DUPLICATE_NAME') || error.includes('personalize.PROJECTS.DUPLICATE_NAME')) {
|
|
50
50
|
const projectName = await askProjectName('Copy Of ' + (newName || project.name));
|
|
51
51
|
return await createProject(projectName);
|
|
52
52
|
}
|
|
@@ -49,7 +49,6 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
49
49
|
headers: {
|
|
50
50
|
api_key: config.apiKey,
|
|
51
51
|
branch: config.branchName,
|
|
52
|
-
authtoken: config.auth_token,
|
|
53
52
|
organization_uid: config.org_uid,
|
|
54
53
|
'X-Project-Uid': config.modules.personalize.project_id,
|
|
55
54
|
},
|
|
@@ -138,7 +137,8 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
138
137
|
this.assetUidMapper = (fsUtil.readFile(assetUidMapperPath, true) || {}) as Record<string, any>;
|
|
139
138
|
this.assetUrlMapper = (fsUtil.readFile(assetUrlMapperPath, true) || {}) as Record<string, any>;
|
|
140
139
|
this.environments = (fsUtil.readFile(envPath, true) || {}) as Record<string, any>;
|
|
141
|
-
|
|
140
|
+
// set the token
|
|
141
|
+
await this.variantInstance.init();
|
|
142
142
|
for (const entriesForVariant of entriesForVariants) {
|
|
143
143
|
await this.importVariantEntries(entriesForVariant);
|
|
144
144
|
}
|
|
@@ -368,7 +368,7 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
368
368
|
* @param variantEntry - The entry variant to update.
|
|
369
369
|
*/
|
|
370
370
|
updateFileFields(variantEntry: VariantEntryStruct) {
|
|
371
|
-
const setValue = (currentObj: VariantEntryStruct, keys:
|
|
371
|
+
const setValue = (currentObj: VariantEntryStruct, keys: string[]) => {
|
|
372
372
|
if (!currentObj || keys.length === 0) return;
|
|
373
373
|
|
|
374
374
|
const [firstKey, ...restKeys] = keys;
|
|
@@ -380,7 +380,14 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
380
380
|
} else if (currentObj && typeof currentObj === 'object') {
|
|
381
381
|
if (firstKey in currentObj) {
|
|
382
382
|
if (keys.length === 1) {
|
|
383
|
-
|
|
383
|
+
// Check if the current property is already an object with uid and filename
|
|
384
|
+
const existingValue = currentObj[firstKey];
|
|
385
|
+
|
|
386
|
+
if (existingValue && typeof existingValue === 'object' && existingValue.uid) {
|
|
387
|
+
currentObj[firstKey] = { uid: existingValue.uid, filename: 'dummy.jpeg' };
|
|
388
|
+
} else {
|
|
389
|
+
currentObj[firstKey] = { uid: currentObj[firstKey], filename: 'dummy.jpeg' };
|
|
390
|
+
}
|
|
384
391
|
} else {
|
|
385
392
|
setValue(currentObj[firstKey], restKeys);
|
|
386
393
|
}
|
|
@@ -388,13 +395,12 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
388
395
|
}
|
|
389
396
|
};
|
|
390
397
|
|
|
391
|
-
const pathsToUpdate =
|
|
392
|
-
|
|
393
|
-
|
|
398
|
+
const pathsToUpdate =
|
|
399
|
+
variantEntry?._metadata?.references
|
|
400
|
+
?.filter((ref: any) => ref._content_type_uid === 'sys_assets')
|
|
401
|
+
.map((ref: any) => ref.path) || [];
|
|
394
402
|
|
|
395
|
-
|
|
396
|
-
pathsToUpdate.forEach((path: string) => setValue(variantEntry, path.split('.')));
|
|
397
|
-
}
|
|
403
|
+
pathsToUpdate.forEach((path: string) => setValue(variantEntry, path.split('.')));
|
|
398
404
|
}
|
|
399
405
|
|
|
400
406
|
/**
|
|
@@ -406,6 +412,11 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
406
412
|
*/
|
|
407
413
|
async publishVariantEntries(batch: VariantEntryStruct[], entryUid: string, content_type: string) {
|
|
408
414
|
const allPromise = [];
|
|
415
|
+
log(
|
|
416
|
+
this.config,
|
|
417
|
+
`Publishing variant entries for entry uid '${entryUid}' of Content Type '${content_type}'`,
|
|
418
|
+
'info',
|
|
419
|
+
);
|
|
409
420
|
for (let [, variantEntry] of entries(batch)) {
|
|
410
421
|
const variantEntryUID = variantEntry.uid;
|
|
411
422
|
const oldVariantUid = variantEntry._variant._uid || '';
|
|
@@ -446,11 +457,9 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
446
457
|
entry: {
|
|
447
458
|
environments,
|
|
448
459
|
locales,
|
|
449
|
-
publish_with_base_entry: false,
|
|
450
460
|
variants: [{ uid: newVariantUid, version: 1 }],
|
|
451
461
|
},
|
|
452
462
|
locale: variantEntry.locale,
|
|
453
|
-
version: 1,
|
|
454
463
|
};
|
|
455
464
|
|
|
456
465
|
const promise = this.variantInstance.publishVariantEntry(
|
|
@@ -470,6 +479,7 @@ export default class VariantEntries extends VariantAdapter<VariantHttpClient<Imp
|
|
|
470
479
|
allPromise.push(promise);
|
|
471
480
|
}
|
|
472
481
|
await Promise.allSettled(allPromise);
|
|
482
|
+
log(this.config, `Published variant entries for entry uid '${entryUid}' of Content Type '${content_type}'`, 'info');
|
|
473
483
|
}
|
|
474
484
|
|
|
475
485
|
/**
|
package/src/messages/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ const expImportMsg = {
|
|
|
23
23
|
UPDATING_CT_IN_EXP: 'Updating content types in experiences...',
|
|
24
24
|
UPDATED_CT_IN_EXP: 'Successfully updated content types in experiences!',
|
|
25
25
|
VALIDATE_VARIANT_AND_VARIANT_GRP: 'Validating variant group and variants creation...',
|
|
26
|
-
PERSONALIZE_JOB_FAILURE: 'Something went wrong
|
|
26
|
+
PERSONALIZE_JOB_FAILURE: 'Something went wrong! Failed to fetch some variant and variant groups.',
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const messages: typeof errors & typeof commonMsg & typeof migrationMsg & typeof variantEntry & typeof expImportMsg = {
|
|
@@ -206,5 +206,5 @@ export interface Personalization<T> extends AdapterHelperInterface<T, HttpClient
|
|
|
206
206
|
|
|
207
207
|
updateCTsInExperience(experience: UpdateExperienceInput, experienceUid: string): Promise<CMSExperienceStruct | void>;
|
|
208
208
|
|
|
209
|
-
handleVariantAPIRes(res: any): VariantAPIRes
|
|
209
|
+
handleVariantAPIRes(res: any): Promise<VariantAPIRes>;
|
|
210
210
|
}
|
|
@@ -42,6 +42,8 @@ export type VariantOptions = VariantsOption & {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
export interface VariantInterface<T, ApiClient> extends AdapterHelperInterface<T, ApiClient> {
|
|
45
|
+
init(): Promise<void>;
|
|
46
|
+
|
|
45
47
|
variantEntry(options: VariantOptions): Promise<{ entry: Record<string, any> }>;
|
|
46
48
|
|
|
47
49
|
variantEntries(options: VariantsOption): Promise<{ entries?: Record<string, any>[] | unknown[] } | void>;
|
|
@@ -52,5 +54,5 @@ export interface VariantInterface<T, ApiClient> extends AdapterHelperInterface<T
|
|
|
52
54
|
apiParams: Record<string, any>,
|
|
53
55
|
): Promise<VariantEntryStruct | string | void>;
|
|
54
56
|
|
|
55
|
-
handleVariantAPIRes(res: APIResponse): VariantEntryStruct | { entries: VariantEntryStruct[]; count: number } | string
|
|
57
|
+
handleVariantAPIRes(res: APIResponse): Promise<VariantEntryStruct | { entries: VariantEntryStruct[]; count: number } | string>;
|
|
56
58
|
}
|
|
@@ -12,8 +12,8 @@ export const lookUpAttributes = (attributeRules: Record<string, any>[], attribut
|
|
|
12
12
|
// Check if attribute reference exists in attributesUid
|
|
13
13
|
const attributeRef = rule.attribute?.ref;
|
|
14
14
|
const attributeType = rule.attribute['__type'];
|
|
15
|
-
// check if type is
|
|
16
|
-
if (attributeType === '
|
|
15
|
+
// check if type is CustomAttributeReference
|
|
16
|
+
if (attributeType === 'CustomAttributeReference') {
|
|
17
17
|
if (attributeRef && attributesUid.hasOwnProperty(attributeRef) && attributesUid[attributeRef]) {
|
|
18
18
|
rule.attribute.ref = attributesUid[attributeRef];
|
|
19
19
|
} else {
|
|
@@ -9,18 +9,18 @@ export function formatErrors(errors: any): string {
|
|
|
9
9
|
for (const errorKey in errors) {
|
|
10
10
|
const errorValue = errors[errorKey];
|
|
11
11
|
if (Array.isArray(errorValue)) {
|
|
12
|
-
errorMessages.push(...errorValue.map((error: any) => formatError(error)));
|
|
12
|
+
errorMessages.push(...errorValue.map((error: any) => formatError(errorKey, error)));
|
|
13
13
|
} else {
|
|
14
|
-
errorMessages.push(formatError(errorValue));
|
|
14
|
+
errorMessages.push(formatError(errorKey, errorValue));
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
return errorMessages.join(' ');
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function formatError(error: any): string {
|
|
22
|
-
if (typeof error === 'object') {
|
|
23
|
-
return Object.values(error).join(' ')
|
|
21
|
+
function formatError(errorKey: string, error: any): string {
|
|
22
|
+
if (typeof error === 'object' && error !== null) {
|
|
23
|
+
return `${errorKey}: ${Object.values(error).join(' ')}`;
|
|
24
24
|
}
|
|
25
|
-
return error
|
|
25
|
+
return `${errorKey}: ${error}`;
|
|
26
26
|
}
|
package/src/utils/logger.ts
CHANGED
|
@@ -51,9 +51,9 @@ let errorLogger: winston.Logger;
|
|
|
51
51
|
let successTransport;
|
|
52
52
|
let errorTransport;
|
|
53
53
|
|
|
54
|
-
function init(_logPath: string) {
|
|
54
|
+
function init(_logPath: string, module: string) {
|
|
55
55
|
if (!logger || !errorLogger) {
|
|
56
|
-
const logsDir = path.resolve(sanitizePath(_logPath), 'logs',
|
|
56
|
+
const logsDir = path.resolve(sanitizePath(_logPath), 'logs', sanitizePath(module));
|
|
57
57
|
// Create dir if doesn't already exist
|
|
58
58
|
mkdirp.sync(logsDir);
|
|
59
59
|
|
|
@@ -131,11 +131,12 @@ function init(_logPath: string) {
|
|
|
131
131
|
export const log = (config: ExportConfig | ImportConfig, message: any, type: 'info' | 'error' | 'success') => {
|
|
132
132
|
const logsPath = config.data;
|
|
133
133
|
// ignoring the type argument, as we are not using it to create a logfile anymore
|
|
134
|
+
const module = (config as ImportConfig)['backupDir'] ? 'import' : 'export';
|
|
134
135
|
if (type !== 'error') {
|
|
135
136
|
// removed type argument from init method
|
|
136
|
-
init(logsPath).log(message);
|
|
137
|
+
init(logsPath, module).log(message);
|
|
137
138
|
} else {
|
|
138
|
-
init(logsPath).error(message);
|
|
139
|
+
init(logsPath, module).error(message);
|
|
139
140
|
}
|
|
140
141
|
};
|
|
141
142
|
|