@contentstack/cli-variants 0.0.1-alpha
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 +15 -0
- package/lib/export/attributes.js +62 -0
- package/lib/export/audiences.d.ts +15 -0
- package/lib/export/audiences.js +63 -0
- package/lib/export/events.d.ts +15 -0
- package/lib/export/events.js +63 -0
- package/lib/export/experiences.d.ts +9 -0
- package/lib/export/experiences.js +99 -0
- package/lib/export/index.d.ts +9 -0
- package/lib/export/index.js +21 -0
- package/lib/export/projects.d.ts +9 -0
- package/lib/export/projects.js +73 -0
- package/lib/export/variant-entries.d.ts +18 -0
- package/lib/export/variant-entries.js +109 -0
- package/lib/import/attribute.d.ts +17 -0
- package/lib/import/attribute.js +64 -0
- package/lib/import/audiences.d.ts +19 -0
- package/lib/import/audiences.js +71 -0
- package/lib/import/events.d.ts +17 -0
- package/lib/import/events.js +62 -0
- package/lib/import/experiences.d.ts +46 -0
- package/lib/import/experiences.js +214 -0
- package/lib/import/index.d.ts +14 -0
- package/lib/import/index.js +21 -0
- package/lib/import/project.d.ts +13 -0
- package/lib/import/project.js +74 -0
- package/lib/import/variant-entries.d.ts +98 -0
- package/lib/import/variant-entries.js +407 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +21 -0
- package/lib/messages/index.d.ts +35 -0
- package/lib/messages/index.js +55 -0
- package/lib/types/adapter-helper.d.ts +8 -0
- package/lib/types/adapter-helper.js +2 -0
- package/lib/types/content-types.d.ts +19 -0
- package/lib/types/content-types.js +2 -0
- package/lib/types/export-config.d.ts +264 -0
- package/lib/types/export-config.js +2 -0
- package/lib/types/import-config.d.ts +92 -0
- package/lib/types/import-config.js +2 -0
- package/lib/types/index.d.ts +8 -0
- package/lib/types/index.js +24 -0
- package/lib/types/personalization-api-adapter.d.ts +152 -0
- package/lib/types/personalization-api-adapter.js +2 -0
- package/lib/types/utils.d.ts +7 -0
- package/lib/types/utils.js +2 -0
- package/lib/types/variant-api-adapter.d.ts +49 -0
- package/lib/types/variant-api-adapter.js +2 -0
- package/lib/types/variant-entry.d.ts +47 -0
- package/lib/types/variant-entry.js +2 -0
- package/lib/utils/adapter-helper.d.ts +30 -0
- package/lib/utils/adapter-helper.js +95 -0
- package/lib/utils/attributes-helper.d.ts +7 -0
- package/lib/utils/attributes-helper.js +37 -0
- package/lib/utils/audiences-helper.d.ts +8 -0
- package/lib/utils/audiences-helper.js +49 -0
- package/lib/utils/error-helper.d.ts +6 -0
- package/lib/utils/error-helper.js +27 -0
- package/lib/utils/events-helper.d.ts +8 -0
- package/lib/utils/events-helper.js +27 -0
- package/lib/utils/helper.d.ts +4 -0
- package/lib/utils/helper.js +51 -0
- package/lib/utils/index.d.ts +9 -0
- package/lib/utils/index.js +25 -0
- package/lib/utils/logger.d.ts +3 -0
- package/lib/utils/logger.js +175 -0
- package/lib/utils/personalization-api-adapter.d.ts +73 -0
- package/lib/utils/personalization-api-adapter.js +184 -0
- package/lib/utils/variant-api-adapter.d.ts +79 -0
- package/lib/utils/variant-api-adapter.js +263 -0
- package/package.json +38 -0
- package/src/export/attributes.ts +55 -0
- package/src/export/audiences.ts +57 -0
- package/src/export/events.ts +57 -0
- package/src/export/experiences.ts +80 -0
- package/src/export/index.ts +11 -0
- package/src/export/projects.ts +45 -0
- package/src/export/variant-entries.ts +88 -0
- package/src/import/attribute.ts +60 -0
- package/src/import/audiences.ts +69 -0
- package/src/import/events.ts +58 -0
- package/src/import/experiences.ts +224 -0
- package/src/import/index.ts +16 -0
- package/src/import/project.ts +71 -0
- package/src/import/variant-entries.ts +483 -0
- package/src/index.ts +5 -0
- package/src/messages/index.ts +63 -0
- package/src/types/adapter-helper.ts +10 -0
- package/src/types/content-types.ts +41 -0
- package/src/types/export-config.ts +292 -0
- package/src/types/import-config.ts +95 -0
- package/src/types/index.ts +8 -0
- package/src/types/personalization-api-adapter.ts +197 -0
- package/src/types/utils.ts +8 -0
- package/src/types/variant-api-adapter.ts +56 -0
- package/src/types/variant-entry.ts +61 -0
- package/src/utils/adapter-helper.ts +79 -0
- package/src/utils/attributes-helper.ts +31 -0
- package/src/utils/audiences-helper.ts +50 -0
- package/src/utils/error-helper.ts +26 -0
- package/src/utils/events-helper.ts +26 -0
- package/src/utils/helper.ts +34 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/logger.ts +160 -0
- package/src/utils/personalization-api-adapter.ts +188 -0
- package/src/utils/variant-api-adapter.ts +326 -0
- package/test/unit/export/variant-entries.test.ts +80 -0
- package/test/unit/import/variant-entries.test.ts +200 -0
- package/test/unit/mock/contents/content_types/CT-1.json +7 -0
- package/test/unit/mock/contents/entries/CT-1/en-us/variants/E-1/9b0da6xd7et72y-6gv7he23.json +12 -0
- package/test/unit/mock/contents/entries/CT-1/en-us/variants/E-1/index.json +3 -0
- package/test/unit/mock/contents/entries/CT-1/en-us/variants/E-2/9b0da6xd7et72y-6gv7he23.json +12 -0
- package/test/unit/mock/contents/entries/CT-1/en-us/variants/E-2/index.json +3 -0
- package/test/unit/mock/contents/mapper/assets/uid-mapping.json +6 -0
- package/test/unit/mock/contents/mapper/assets/url-mapping.json +6 -0
- package/test/unit/mock/contents/mapper/entries/data-for-variant-entry.json +6 -0
- package/test/unit/mock/contents/mapper/entries/empty-data/data-for-variant-entry.json +1 -0
- package/test/unit/mock/contents/mapper/entries/uid-mapping.json +6 -0
- package/test/unit/mock/contents/mapper/marketplace_apps/uid-mapping.json +3 -0
- package/test/unit/mock/contents/mapper/personalization/experiences/variants-uid-mapping.json +5 -0
- package/test/unit/mock/contents/mapper/taxonomies/terms/success.json +1 -0
- package/test/unit/mock/export-config.json +48 -0
- package/test/unit/mock/import-config.json +63 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import omit from 'lodash/omit';
|
|
2
|
+
import { resolve as pResolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { formatError, fsUtil, PersonalizationAdapter, log } from '../utils';
|
|
5
|
+
import { PersonalizationConfig, ExportConfig, EventStruct, EventsConfig } from '../types';
|
|
6
|
+
|
|
7
|
+
export default class ExportEvents extends PersonalizationAdapter<ExportConfig> {
|
|
8
|
+
private eventsConfig: EventsConfig;
|
|
9
|
+
private eventsFolderPath: string;
|
|
10
|
+
private events: Record<string, unknown>[];
|
|
11
|
+
public personalizationConfig: PersonalizationConfig;
|
|
12
|
+
|
|
13
|
+
constructor(readonly exportConfig: ExportConfig) {
|
|
14
|
+
super({
|
|
15
|
+
config: exportConfig,
|
|
16
|
+
baseURL: exportConfig.modules.personalization.baseURL[exportConfig.region.name],
|
|
17
|
+
headers: { authtoken: exportConfig.auth_token, 'X-Project-Uid': exportConfig.project_id },
|
|
18
|
+
});
|
|
19
|
+
this.personalizationConfig = exportConfig.modules.personalization;
|
|
20
|
+
this.eventsConfig = exportConfig.modules.events;
|
|
21
|
+
this.eventsFolderPath = pResolve(
|
|
22
|
+
exportConfig.data,
|
|
23
|
+
exportConfig.branchName || '',
|
|
24
|
+
this.personalizationConfig.dirName,
|
|
25
|
+
this.eventsConfig.dirName,
|
|
26
|
+
);
|
|
27
|
+
this.events = [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async start() {
|
|
31
|
+
try {
|
|
32
|
+
log(this.exportConfig, 'Starting events export', 'info');
|
|
33
|
+
await fsUtil.makeDirectory(this.eventsFolderPath);
|
|
34
|
+
this.events = (await this.getEvents()) as EventStruct[];
|
|
35
|
+
|
|
36
|
+
if (!this.events?.length) {
|
|
37
|
+
log(this.exportConfig, 'No Events found with the given project!', 'info');
|
|
38
|
+
return;
|
|
39
|
+
} else {
|
|
40
|
+
this.sanitizeAttribs();
|
|
41
|
+
fsUtil.writeFile(pResolve(this.eventsFolderPath, this.eventsConfig.fileName), this.events);
|
|
42
|
+
log(this.exportConfig, 'All the events have been exported successfully!', 'success');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
log(this.exportConfig, `Failed to export events!`, 'error');
|
|
47
|
+
log(this.config, error, 'error');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* function to remove invalid keys from event object
|
|
53
|
+
*/
|
|
54
|
+
sanitizeAttribs() {
|
|
55
|
+
this.events = this.events?.map((event) => omit(event, this.eventsConfig.invalidKeys)) || [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import { sanitizePath } from '@contentstack/cli-utilities';
|
|
3
|
+
import { PersonalizationConfig, ExportConfig, ExperienceStruct } from '../types';
|
|
4
|
+
import { formatError, fsUtil, log, PersonalizationAdapter } from '../utils';
|
|
5
|
+
|
|
6
|
+
export default class ExportExperiences extends PersonalizationAdapter<ExportConfig> {
|
|
7
|
+
private experiencesFolderPath: string;
|
|
8
|
+
public exportConfig: ExportConfig;
|
|
9
|
+
public personalizationConfig: PersonalizationConfig;
|
|
10
|
+
constructor(exportConfig: ExportConfig) {
|
|
11
|
+
super({
|
|
12
|
+
config: exportConfig,
|
|
13
|
+
baseURL: exportConfig.modules.personalization.baseURL[exportConfig.region.name],
|
|
14
|
+
headers: { authtoken: exportConfig.auth_token, 'X-Project-Uid': exportConfig.project_id },
|
|
15
|
+
cmaConfig: {
|
|
16
|
+
baseURL: exportConfig.region.cma + `/v3`,
|
|
17
|
+
headers: { authtoken: exportConfig.auth_token, api_key: exportConfig.apiKey },
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
this.exportConfig = exportConfig;
|
|
21
|
+
this.personalizationConfig = exportConfig.modules.personalization;
|
|
22
|
+
this.experiencesFolderPath = path.resolve(
|
|
23
|
+
sanitizePath(exportConfig.data),
|
|
24
|
+
sanitizePath(exportConfig.branchName || ''),
|
|
25
|
+
sanitizePath(this.personalizationConfig.dirName),
|
|
26
|
+
'experiences',
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async start() {
|
|
31
|
+
try {
|
|
32
|
+
// get all experiences
|
|
33
|
+
// loop through experiences and get content types attached to it
|
|
34
|
+
// write experiences in to a file
|
|
35
|
+
log(this.exportConfig, 'Starting experiences export', 'info');
|
|
36
|
+
await fsUtil.makeDirectory(this.experiencesFolderPath);
|
|
37
|
+
const experiences: Array<ExperienceStruct> = (await this.getExperiences()) || [];
|
|
38
|
+
if (!experiences || experiences?.length < 1) {
|
|
39
|
+
log(this.exportConfig, 'No Experiences found with the give project', 'info');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
fsUtil.writeFile(path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences.json'), experiences);
|
|
43
|
+
|
|
44
|
+
const experienceToVariantsStrList: Array<string> = [];
|
|
45
|
+
const experienceToContentTypesMap: Record<string, string[]> = {};
|
|
46
|
+
for (let experience of experiences) {
|
|
47
|
+
// create id mapper for experience to variants
|
|
48
|
+
let variants = experience?._cms?.variants ?? {};
|
|
49
|
+
Object.keys(variants).forEach((variantShortId: string) => {
|
|
50
|
+
const experienceToVariantsStr = `${experience.uid}-${variantShortId}-${variants[variantShortId]}`;
|
|
51
|
+
experienceToVariantsStrList.push(experienceToVariantsStr);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
// fetch content of experience
|
|
56
|
+
const { variant_groups: [variantGroup] = [] } =
|
|
57
|
+
(await this.getVariantGroup({ experienceUid: experience.uid })) || {};
|
|
58
|
+
if (variantGroup?.content_types?.length) {
|
|
59
|
+
experienceToContentTypesMap[experience.uid] = variantGroup.content_types;
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
log(this.exportConfig, `Failed to fetch content types of experience ${experience.name}`, 'error');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
fsUtil.writeFile(
|
|
66
|
+
path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences-variants-ids.json'),
|
|
67
|
+
experienceToVariantsStrList,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
fsUtil.writeFile(
|
|
71
|
+
path.resolve(sanitizePath(this.experiencesFolderPath), 'experiences-content-types.json'),
|
|
72
|
+
experienceToContentTypesMap,
|
|
73
|
+
);
|
|
74
|
+
log(this.exportConfig, 'All the experiences have been exported successfully!', 'success');
|
|
75
|
+
} catch (error) {
|
|
76
|
+
log(this.exportConfig, `Failed to export experiences!`, 'error');
|
|
77
|
+
log(this.config, error, 'error');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { default as ExportProjects } from './projects';
|
|
2
|
+
export { default as ExportExperiences } from './experiences';
|
|
3
|
+
import VariantEntries from './variant-entries';
|
|
4
|
+
export { default as ExportEvents } from './events';
|
|
5
|
+
export { default as ExportAudiences } from './audiences';
|
|
6
|
+
export { default as ExportAttributes } from './attributes';
|
|
7
|
+
|
|
8
|
+
// NOTE Acting as namespace to avoid the same class name conflicts in other modules
|
|
9
|
+
export const Export = {
|
|
10
|
+
VariantEntries,
|
|
11
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import { sanitizePath } from '@contentstack/cli-utilities';
|
|
3
|
+
import { ExportConfig, PersonalizationConfig } from '../types';
|
|
4
|
+
import { PersonalizationAdapter, log, fsUtil, formatError } from '../utils';
|
|
5
|
+
|
|
6
|
+
export default class ExportProjects extends PersonalizationAdapter<ExportConfig> {
|
|
7
|
+
private projectFolderPath: string;
|
|
8
|
+
public exportConfig: ExportConfig;
|
|
9
|
+
public personalizationConfig: PersonalizationConfig;
|
|
10
|
+
constructor(exportConfig: ExportConfig) {
|
|
11
|
+
super({
|
|
12
|
+
config: exportConfig,
|
|
13
|
+
baseURL: exportConfig.modules.personalization.baseURL[exportConfig.region.name],
|
|
14
|
+
headers: { authtoken: exportConfig.auth_token, organization_uid: exportConfig.org_uid },
|
|
15
|
+
});
|
|
16
|
+
this.exportConfig = exportConfig;
|
|
17
|
+
this.personalizationConfig = exportConfig.modules.personalization;
|
|
18
|
+
this.projectFolderPath = path.resolve(
|
|
19
|
+
sanitizePath(exportConfig.data),
|
|
20
|
+
sanitizePath(exportConfig.branchName || ''),
|
|
21
|
+
sanitizePath(this.personalizationConfig.dirName),
|
|
22
|
+
'projects',
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async start() {
|
|
27
|
+
try {
|
|
28
|
+
log(this.exportConfig, 'Starting projects export', 'info');
|
|
29
|
+
await fsUtil.makeDirectory(this.projectFolderPath);
|
|
30
|
+
const project = await this.projects({ connectedStackApiKey: this.exportConfig.apiKey });
|
|
31
|
+
if (!project || project?.length < 1) {
|
|
32
|
+
log(this.exportConfig, 'No Personalization Project connected with the given stack', 'info');
|
|
33
|
+
this.exportConfig.personalizationEnabled = false;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.exportConfig.personalizationEnabled = true;
|
|
37
|
+
this.exportConfig.project_id = project[0]?.uid;
|
|
38
|
+
fsUtil.writeFile(path.resolve(sanitizePath(this.projectFolderPath), 'projects.json'), project);
|
|
39
|
+
log(this.exportConfig, 'Project exported successfully!', 'success');
|
|
40
|
+
} catch (error) {
|
|
41
|
+
log(this.exportConfig, `Failed to export projects!`, 'error');
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
import { FsUtility, sanitizePath } from '@contentstack/cli-utilities';
|
|
4
|
+
|
|
5
|
+
import { APIConfig, AdapterType, ExportConfig, LogType } from '../types';
|
|
6
|
+
import VariantAdapter, { VariantHttpClient } from '../utils/variant-api-adapter';
|
|
7
|
+
import { fsUtil, log } from '../utils';
|
|
8
|
+
|
|
9
|
+
export default class VariantEntries extends VariantAdapter<VariantHttpClient<ExportConfig>> {
|
|
10
|
+
public entriesDirPath: string;
|
|
11
|
+
public variantEntryBasePath!: string;
|
|
12
|
+
|
|
13
|
+
constructor(readonly config: ExportConfig) {
|
|
14
|
+
const conf: APIConfig & AdapterType<VariantHttpClient<ExportConfig>, APIConfig> = {
|
|
15
|
+
config,
|
|
16
|
+
httpClient: true,
|
|
17
|
+
baseURL: config.host,
|
|
18
|
+
Adapter: VariantHttpClient<ExportConfig>,
|
|
19
|
+
headers: {
|
|
20
|
+
api_key: config.apiKey,
|
|
21
|
+
branch: config.branchName,
|
|
22
|
+
authtoken: config.auth_token,
|
|
23
|
+
organization_uid: config.org_uid,
|
|
24
|
+
'X-Project-Uid': config.project_id,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
super(Object.assign(config, conf));
|
|
28
|
+
this.entriesDirPath = resolve(sanitizePath(config.data), sanitizePath(config.branchName || ''), sanitizePath(config.modules.entries.dirName));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* This function exports variant entries for a specific content type and locale.
|
|
33
|
+
* @param options - The `exportVariantEntry` function takes in an `options` object with the following
|
|
34
|
+
* properties:
|
|
35
|
+
*/
|
|
36
|
+
async exportVariantEntry(options: { locale: string; contentTypeUid: string; entries: Record<string, any>[] }) {
|
|
37
|
+
const variantEntry = this.config.modules.variantEntry;
|
|
38
|
+
const { entries, locale, contentTypeUid: content_type_uid } = options;
|
|
39
|
+
|
|
40
|
+
for (let index = 0; index < entries.length; index++) {
|
|
41
|
+
const entry = entries[index];
|
|
42
|
+
const variantEntryBasePath = join(sanitizePath(this.entriesDirPath), sanitizePath(content_type_uid), sanitizePath(locale), sanitizePath(variantEntry.dirName), sanitizePath(entry.uid));
|
|
43
|
+
const variantEntriesFs = new FsUtility({
|
|
44
|
+
isArray: true,
|
|
45
|
+
keepMetadata: false,
|
|
46
|
+
moduleName: 'variant-entry',
|
|
47
|
+
basePath: variantEntryBasePath,
|
|
48
|
+
indexFileName: variantEntry.fileName,
|
|
49
|
+
chunkFileSize: variantEntry.chunkFileSize || 1,
|
|
50
|
+
createDirIfNotExist: false,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const callback = (variantEntries: Record<string, any>[]) => {
|
|
54
|
+
if (variantEntries?.length) {
|
|
55
|
+
if (!existsSync(variantEntryBasePath)) {
|
|
56
|
+
mkdirSync(variantEntryBasePath, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
variantEntriesFs.writeIntoFile(variantEntries);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
await this.variantInstance.variantEntries({
|
|
64
|
+
callback,
|
|
65
|
+
getAllData: true,
|
|
66
|
+
content_type_uid,
|
|
67
|
+
entry_uid: entry.uid,
|
|
68
|
+
locale,
|
|
69
|
+
});
|
|
70
|
+
if (existsSync(variantEntryBasePath)) {
|
|
71
|
+
variantEntriesFs.completeFile(true);
|
|
72
|
+
log(
|
|
73
|
+
this.config,
|
|
74
|
+
`Exported variant entries of type '${entry.title} (${entry.uid})' locale '${locale}'`,
|
|
75
|
+
'info',
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
log(
|
|
80
|
+
this.config,
|
|
81
|
+
`Error exporting variant entries of type '${entry.title} (${entry.uid})' locale '${locale}'`,
|
|
82
|
+
'error',
|
|
83
|
+
);
|
|
84
|
+
log(this.config, error, 'error');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { sanitizePath } from '@contentstack/cli-utilities';
|
|
4
|
+
import { PersonalizationAdapter, fsUtil } from '../utils';
|
|
5
|
+
import { APIConfig, AttributeStruct, ImportConfig, LogType } from '../types';
|
|
6
|
+
|
|
7
|
+
export default class Attribute extends PersonalizationAdapter<ImportConfig> {
|
|
8
|
+
private mapperDirPath: string;
|
|
9
|
+
private attrMapperDirPath: string;
|
|
10
|
+
private attributesUidMapperPath: string;
|
|
11
|
+
private attributesUidMapper: Record<string, unknown>;
|
|
12
|
+
private personalizationConfig: ImportConfig['modules']['personalization'];
|
|
13
|
+
private attributeConfig: ImportConfig['modules']['personalization']['attributes'];
|
|
14
|
+
|
|
15
|
+
constructor(public readonly config: ImportConfig, private readonly log: LogType = console.log) {
|
|
16
|
+
const conf: APIConfig = {
|
|
17
|
+
config,
|
|
18
|
+
baseURL: config.modules.personalization.baseURL[config.region.name],
|
|
19
|
+
headers: { 'X-Project-Uid': config.modules.personalization.project_id, authtoken: config.auth_token },
|
|
20
|
+
};
|
|
21
|
+
super(Object.assign(config, conf));
|
|
22
|
+
this.personalizationConfig = this.config.modules.personalization;
|
|
23
|
+
this.attributeConfig = this.personalizationConfig.attributes;
|
|
24
|
+
this.mapperDirPath = resolve(sanitizePath(this.config.backupDir), 'mapper', sanitizePath(this.personalizationConfig.dirName));
|
|
25
|
+
this.attrMapperDirPath = resolve(sanitizePath(this.mapperDirPath), sanitizePath(this.attributeConfig.dirName));
|
|
26
|
+
this.attributesUidMapperPath = resolve(sanitizePath(this.attrMapperDirPath), 'uid-mapping.json');
|
|
27
|
+
this.attributesUidMapper = {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The function asynchronously imports attributes from a JSON file and creates them in the system.
|
|
32
|
+
*/
|
|
33
|
+
async import() {
|
|
34
|
+
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Attributes' }), 'info');
|
|
35
|
+
|
|
36
|
+
await fsUtil.makeDirectory(this.attrMapperDirPath);
|
|
37
|
+
const { dirName, fileName } = this.attributeConfig;
|
|
38
|
+
const attributesPath = resolve(sanitizePath(this.config.data), sanitizePath(this.personalizationConfig.dirName), sanitizePath(dirName), sanitizePath(fileName));
|
|
39
|
+
|
|
40
|
+
if (existsSync(attributesPath)) {
|
|
41
|
+
try {
|
|
42
|
+
const attributes = fsUtil.readFile(attributesPath, true) as AttributeStruct[];
|
|
43
|
+
|
|
44
|
+
for (const attribute of attributes) {
|
|
45
|
+
const { key, name, description, uid } = attribute;
|
|
46
|
+
const attributeRes = await this.createAttribute({ key, name, description });
|
|
47
|
+
//map old attribute uid to new attribute uid
|
|
48
|
+
//mapper file is used to check whether attribute created or not before creating audience
|
|
49
|
+
this.attributesUidMapper[uid] = attributeRes?.uid ?? '';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fsUtil.writeFile(this.attributesUidMapperPath, this.attributesUidMapper);
|
|
53
|
+
this.log(this.config, this.$t(this.messages.CREATE_SUCCESS, { module: 'Attributes' }), 'info');
|
|
54
|
+
} catch (error) {
|
|
55
|
+
this.log(this.config, this.$t(this.messages.CREATE_FAILURE, { module: 'Attributes' }), 'error');
|
|
56
|
+
this.log(this.config, error, 'error');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { sanitizePath } from '@contentstack/cli-utilities';
|
|
4
|
+
import { APIConfig, AudienceStruct, ImportConfig, LogType } from '../types';
|
|
5
|
+
import { PersonalizationAdapter, fsUtil, lookUpAttributes } from '../utils';
|
|
6
|
+
|
|
7
|
+
export default class Audiences extends PersonalizationAdapter<ImportConfig> {
|
|
8
|
+
private mapperDirPath: string;
|
|
9
|
+
private audienceMapperDirPath: string;
|
|
10
|
+
private attributesMapperPath: string;
|
|
11
|
+
private audiencesUidMapperPath: string;
|
|
12
|
+
private audiencesUidMapper: Record<string, unknown>;
|
|
13
|
+
private personalizationConfig: ImportConfig['modules']['personalization'];
|
|
14
|
+
private audienceConfig: ImportConfig['modules']['personalization']['audiences'];
|
|
15
|
+
public attributeConfig: ImportConfig['modules']['personalization']['attributes'];
|
|
16
|
+
|
|
17
|
+
constructor(public readonly config: ImportConfig, private readonly log: LogType = console.log) {
|
|
18
|
+
const conf: APIConfig = {
|
|
19
|
+
config,
|
|
20
|
+
baseURL: config.modules.personalization.baseURL[config.region.name],
|
|
21
|
+
headers: { 'X-Project-Uid': config.modules.personalization.project_id, authtoken: config.auth_token },
|
|
22
|
+
};
|
|
23
|
+
super(Object.assign(config, conf));
|
|
24
|
+
this.personalizationConfig = this.config.modules.personalization;
|
|
25
|
+
this.audienceConfig = this.personalizationConfig.audiences;
|
|
26
|
+
this.attributeConfig = this.personalizationConfig.attributes;
|
|
27
|
+
this.mapperDirPath = resolve(sanitizePath(this.config.backupDir), 'mapper', sanitizePath(this.personalizationConfig.dirName));
|
|
28
|
+
this.audienceMapperDirPath = resolve(sanitizePath(this.mapperDirPath), sanitizePath(this.audienceConfig.dirName));
|
|
29
|
+
this.audiencesUidMapperPath = resolve(sanitizePath(this.audienceMapperDirPath), 'uid-mapping.json');
|
|
30
|
+
this.attributesMapperPath = resolve(sanitizePath(this.mapperDirPath), sanitizePath(this.attributeConfig.dirName), 'uid-mapping.json');
|
|
31
|
+
this.audiencesUidMapper = {};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The function asynchronously imports audiences from a JSON file and creates them in the system.
|
|
36
|
+
*/
|
|
37
|
+
async import() {
|
|
38
|
+
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Audiences' }), 'info');
|
|
39
|
+
|
|
40
|
+
await fsUtil.makeDirectory(this.audienceMapperDirPath);
|
|
41
|
+
const { dirName, fileName } = this.audienceConfig;
|
|
42
|
+
const audiencesPath = resolve(sanitizePath(this.config.data), sanitizePath(this.personalizationConfig.dirName), sanitizePath(dirName), sanitizePath(fileName));
|
|
43
|
+
|
|
44
|
+
if (existsSync(audiencesPath)) {
|
|
45
|
+
try {
|
|
46
|
+
const audiences = fsUtil.readFile(audiencesPath, true) as AudienceStruct[];
|
|
47
|
+
const attributesUid = (fsUtil.readFile(this.attributesMapperPath, true) as Record<string, string>) || {};
|
|
48
|
+
|
|
49
|
+
for (const audience of audiences) {
|
|
50
|
+
let { name, definition, description, uid } = audience;
|
|
51
|
+
//check whether reference attributes exists or not
|
|
52
|
+
if (definition.rules?.length) {
|
|
53
|
+
definition.rules = lookUpAttributes(definition.rules, attributesUid);
|
|
54
|
+
}
|
|
55
|
+
const audienceRes = await this.createAudience({ definition, name, description });
|
|
56
|
+
//map old audience uid to new audience uid
|
|
57
|
+
//mapper file is used to check whether audience created or not before creating experience
|
|
58
|
+
this.audiencesUidMapper[uid] = audienceRes?.uid ?? '';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fsUtil.writeFile(this.audiencesUidMapperPath, this.audiencesUidMapper);
|
|
62
|
+
this.log(this.config, this.$t(this.messages.CREATE_SUCCESS, { module: 'Audiences' }), 'info');
|
|
63
|
+
} catch (error) {
|
|
64
|
+
this.log(this.config, this.$t(this.messages.CREATE_FAILURE, { module: 'Audiences' }), 'error');
|
|
65
|
+
this.log(this.config, error, 'error');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { sanitizePath } from '@contentstack/cli-utilities';
|
|
4
|
+
import { PersonalizationAdapter, fsUtil } from '../utils';
|
|
5
|
+
import { APIConfig, EventStruct, ImportConfig, LogType } from '../types';
|
|
6
|
+
|
|
7
|
+
export default class Events extends PersonalizationAdapter<ImportConfig> {
|
|
8
|
+
private mapperDirPath: string;
|
|
9
|
+
private eventMapperDirPath: string;
|
|
10
|
+
private eventsUidMapperPath: string;
|
|
11
|
+
private eventsUidMapper: Record<string, unknown>;
|
|
12
|
+
private personalizationConfig: ImportConfig['modules']['personalization'];
|
|
13
|
+
private eventsConfig: ImportConfig['modules']['personalization']['events'];
|
|
14
|
+
|
|
15
|
+
constructor(public readonly config: ImportConfig, private readonly log: LogType = console.log) {
|
|
16
|
+
const conf: APIConfig = {
|
|
17
|
+
config,
|
|
18
|
+
baseURL: config.modules.personalization.baseURL[config.region.name],
|
|
19
|
+
headers: { 'X-Project-Uid': config.modules.personalization.project_id, authtoken: config.auth_token },
|
|
20
|
+
};
|
|
21
|
+
super(Object.assign(config, conf));
|
|
22
|
+
this.personalizationConfig = this.config.modules.personalization;
|
|
23
|
+
this.eventsConfig = this.personalizationConfig.events;
|
|
24
|
+
this.mapperDirPath = resolve(sanitizePath(this.config.backupDir), 'mapper', sanitizePath(this.personalizationConfig.dirName));
|
|
25
|
+
this.eventMapperDirPath = resolve(sanitizePath(this.mapperDirPath), sanitizePath(this.eventsConfig.dirName));
|
|
26
|
+
this.eventsUidMapperPath = resolve(sanitizePath(this.eventMapperDirPath), 'uid-mapping.json');
|
|
27
|
+
this.eventsUidMapper = {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The function asynchronously imports attributes from a JSON file and creates them in the system.
|
|
32
|
+
*/
|
|
33
|
+
async import() {
|
|
34
|
+
this.log(this.config, this.$t(this.messages.IMPORT_MSG, { module: 'Events' }), 'info');
|
|
35
|
+
|
|
36
|
+
await fsUtil.makeDirectory(this.eventMapperDirPath);
|
|
37
|
+
const { dirName, fileName } = this.eventsConfig;
|
|
38
|
+
const eventsPath = resolve(sanitizePath(this.config.data), sanitizePath(this.personalizationConfig.dirName), sanitizePath(dirName), sanitizePath(fileName));
|
|
39
|
+
|
|
40
|
+
if (existsSync(eventsPath)) {
|
|
41
|
+
try {
|
|
42
|
+
const events = fsUtil.readFile(eventsPath, true) as EventStruct[];
|
|
43
|
+
|
|
44
|
+
for (const event of events) {
|
|
45
|
+
const { key, description, uid } = event;
|
|
46
|
+
const eventsResponse = await this.createEvents({ key, description });
|
|
47
|
+
this.eventsUidMapper[uid] = eventsResponse?.uid ?? '';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fsUtil.writeFile(this.eventsUidMapperPath, this.eventsUidMapper);
|
|
51
|
+
this.log(this.config, this.$t(this.messages.CREATE_SUCCESS, { module: 'Events' }), 'info');
|
|
52
|
+
} catch (error) {
|
|
53
|
+
this.log(this.config, this.$t(this.messages.CREATE_FAILURE, { module: 'Events' }), 'error');
|
|
54
|
+
this.log(this.config, error, 'error');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|