Skip to content

Commit

Permalink
Merge pull request #1473 from contentstack/next-feature-update
Browse files Browse the repository at this point in the history
Variants changes
  • Loading branch information
shafeeqd959 authored Sep 5, 2024
2 parents b7d3593 + 3726f57 commit 536e219
Show file tree
Hide file tree
Showing 95 changed files with 4,967 additions and 2,505 deletions.
Empty file modified README.md
100755 → 100644
Empty file.
2,992 changes: 634 additions & 2,358 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/contentstack-bootstrap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"test:report": "nyc --reporter=lcov mocha \"test/**/*.test.js\""
},
"dependencies": {
"@contentstack/cli-cm-seed": "~1.7.9",
"@contentstack/cli-cm-seed": "~1.8.0",
"@contentstack/cli-command": "~1.3.0",
"@contentstack/cli-utilities": "~1.7.2",
"inquirer": "8.2.4",
Expand Down Expand Up @@ -73,4 +73,4 @@
}
},
"repository": "contentstack/cli"
}
}
2 changes: 1 addition & 1 deletion packages/contentstack-clone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ $ npm install -g @contentstack/cli-cm-clone
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-clone/1.10.7 darwin-arm64 node-v22.2.0
@contentstack/cli-cm-clone/1.11.0 darwin-arm64 node-v22.2.0
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
6 changes: 3 additions & 3 deletions packages/contentstack-clone/package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "@contentstack/cli-cm-clone",
"description": "Contentstack stack clone plugin",
"version": "1.10.7",
"version": "1.11.0",
"author": "Contentstack",
"bugs": "https://github.com/rohitmishra209/cli-cm-clone/issues",
"dependencies": {
"@colors/colors": "^1.5.0",
"@contentstack/cli-cm-export": "~1.11.7",
"@contentstack/cli-cm-import": "~1.16.7",
"@contentstack/cli-cm-export": "~1.12.0",
"@contentstack/cli-cm-import": "~1.17.0",
"@contentstack/cli-command": "~1.3.0",
"@contentstack/cli-utilities": "~1.7.2",
"async": "^3.2.4",
Expand Down
4 changes: 2 additions & 2 deletions packages/contentstack-command/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ export interface Region {
name: string;
cma: string;
cda: string;
uiHost: string;
developerHubUrl: string;
launchHubUrl: string;
personalizeUrl: string;
launchHubUrl: string;
uiHost: string;
}
2 changes: 1 addition & 1 deletion packages/contentstack-export/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $ npm install -g @contentstack/cli-cm-export
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-export/1.11.7 darwin-arm64 node-v22.2.0
@contentstack/cli-cm-export/1.12.0 darwin-arm64 node-v22.2.0
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
5 changes: 3 additions & 2 deletions packages/contentstack-export/package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "@contentstack/cli-cm-export",
"description": "Contentstack CLI plugin to export content from stack",
"version": "1.11.7",
"version": "1.12.0",
"author": "Contentstack",
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
"@contentstack/cli-command": "~1.3.0",
"@contentstack/cli-variants": "~0.0.1-alpha",
"@contentstack/cli-utilities": "~1.7.2",
"@oclif/core": "^3.26.5",
"async": "^3.2.4",
Expand Down Expand Up @@ -98,4 +99,4 @@
}
},
"repository": "https://github.com/contentstack/cli"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export default class ExportCommand extends Command {
let exportConfig = await setupExportConfig(flags);
// Note setting host to create cma client
exportConfig.host = this.cmaHost;
exportConfig.region = this.region;
exportConfig.developerHubBaseUrl = this.developerHubUrl;
exportDir = exportConfig.cliLogsPath || exportConfig.data || exportConfig.exportDir;
const managementAPIClient: ContentstackClient = await managementSDKClient(exportConfig);
Expand Down
84 changes: 83 additions & 1 deletion packages/contentstack-export/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const config: DefaultConfig = {
'content-types',
'custom-roles',
'workflows',
'personalization',
'entries',
'labels',
'marketplace-apps',
Expand Down Expand Up @@ -143,6 +144,47 @@ const config: DefaultConfig = {
dependencies: ['locales', 'content-types'],
exportVersions: false,
},
personalization: {
baseURL: {
NA: 'https://personalization-api.contentstack.com',
},
dirName: 'personalization',
exportOrder: ['attributes', 'audiences', 'events', 'experiences'],
projects: {
dirName: 'projects',
fileName: 'projects.json',
},
attributes: {
dirName: 'attributes',
fileName: 'attributes.json',
},
audiences: {
dirName: 'audiences',
fileName: 'audiences.json',
},
events: {
dirName: 'events',
fileName: 'events.json',
},
experiences: {
dirName: 'experiences',
fileName: 'experiences.json',
},
},
variantEntry: {
serveMockData: false,
dirName: 'variants',
fileName: 'index.json',
chunkFileSize: 1,
query: {
skip: 0,
limit: 100,
include_variant: false,
include_count: true,
include_publish_details: true,
},
mockDataPath: './variant-mock-data.json',
},
extensions: {
dirName: 'extensions',
fileName: 'extensions.json',
Expand All @@ -166,7 +208,46 @@ const config: DefaultConfig = {
dirName: 'taxonomies',
fileName: 'taxonomies.json',
invalidKeys: ['updated_at', 'created_by', 'updated_by', 'stackHeaders', 'urlPath', 'created_at'],
}
},
events: {
dirName: 'events',
fileName: 'events.json',
invalidKeys: [
'updatedAt',
'createdBy',
'updatedBy',
'_id',
'createdAt',
'createdByUserName',
'updatedByUserName',
],
},
audiences: {
dirName: 'audiences',
fileName: 'audiences.json',
invalidKeys: [
'updatedAt',
'createdBy',
'updatedBy',
'_id',
'createdAt',
'createdByUserName',
'updatedByUserName',
],
},
attributes: {
dirName: 'attributes',
fileName: 'attributes.json',
invalidKeys: [
'updatedAt',
'createdBy',
'updatedBy',
'_id',
'createdAt',
'createdByUserName',
'updatedByUserName',
],
},
},
languagesCode: [
'af-za',
Expand Down Expand Up @@ -393,6 +474,7 @@ const config: DefaultConfig = {
stacks: '/stacks/',
},
preserveStackVersion: false,
personalizationEnabled: false,
fetchConcurrency: 5,
writeConcurrency: 5,
developerHubBaseUrl: '',
Expand Down
63 changes: 54 additions & 9 deletions packages/contentstack-export/src/export/modules/entries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as path from 'path';
import { ContentstackClient, FsUtility } from '@contentstack/cli-utilities';
import { LogType, Export, ExportProjects } from '@contentstack/cli-variants';

import { log, formatError, fsUtil } from '../../utils';
import { ExportConfig, ModuleClassParams } from '../../types';
import BaseClass, { ApiOptions } from './base-class';
Expand All @@ -19,17 +21,24 @@ export default class EntriesExport extends BaseClass {
batchLimit?: number;
exportVersions: boolean;
};
private variantEntries!: any;
private entriesDirPath: string;
private localesFilePath: string;
private schemaFilePath: string;
private entriesFileHelper: FsUtility;
private projectInstance: ExportProjects;
public exportVariantEntry: boolean = false;

constructor({ exportConfig, stackAPIClient }: ModuleClassParams) {
super({ exportConfig, stackAPIClient });
this.stackAPIClient = stackAPIClient;
this.exportConfig = exportConfig;
this.entriesConfig = exportConfig.modules.entries;
this.entriesDirPath = path.resolve(sanitizePath(exportConfig.data), sanitizePath(exportConfig.branchName || ''), sanitizePath(this.entriesConfig.dirName));
this.entriesDirPath = path.resolve(
sanitizePath(exportConfig.data),
sanitizePath(exportConfig.branchName || ''),
sanitizePath(this.entriesConfig.dirName),
);
this.localesFilePath = path.resolve(
sanitizePath(exportConfig.data),
sanitizePath(exportConfig.branchName || ''),
Expand All @@ -42,6 +51,7 @@ export default class EntriesExport extends BaseClass {
sanitizePath(exportConfig.modules.content_types.dirName),
'schema.json',
);
this.projectInstance = new ExportProjects(this.exportConfig);
}

async start() {
Expand All @@ -53,13 +63,26 @@ export default class EntriesExport extends BaseClass {
log(this.exportConfig, 'No content types found to export entries', 'info');
return;
}

// NOTE Check if variant is enabled in specific stack
if (this.exportConfig.personalizationEnabled) {
let project_id;
try {
const project = await this.projectInstance.projects({ connectedStackApiKey: this.exportConfig.apiKey });

if (project && project[0]?.uid) {
project_id = project[0].uid;
this.exportVariantEntry = true;
}

this.variantEntries = new Export.VariantEntries(Object.assign(this.exportConfig, { project_id }));
} catch (error) {
log(this.exportConfig, `Failed to export variant entries ${error}`, 'error');
}
}

const entryRequestOptions = this.createRequestObjects(locales, contentTypes);
for (let entryRequestOption of entryRequestOptions) {
// log(
// this.exportConfig,
// `Starting export of entries of content type - ${entryRequestOption.contentType} locale - ${entryRequestOption.locale}`,
// 'info',
// );
await this.getEntries(entryRequestOption);
this.entriesFileHelper?.completeFile(true);
log(
Expand Down Expand Up @@ -119,7 +142,11 @@ export default class EntriesExport extends BaseClass {

if (Array.isArray(entriesSearchResponse.items) && entriesSearchResponse.items.length > 0) {
if (options.skip === 0) {
const entryBasePath = path.join(sanitizePath(this.entriesDirPath), sanitizePath(options.contentType), sanitizePath(options.locale));
const entryBasePath = path.join(
sanitizePath(this.entriesDirPath),
sanitizePath(options.contentType),
sanitizePath(options.locale),
);
await fsUtil.makeDirectory(entryBasePath);
this.entriesFileHelper = new FsUtility({
moduleName: 'entries',
Expand All @@ -132,14 +159,29 @@ export default class EntriesExport extends BaseClass {
}
this.entriesFileHelper.writeIntoFile(entriesSearchResponse.items, { mapKeyVal: true });
if (this.entriesConfig.exportVersions) {
let versionedEntryPath = path.join(sanitizePath(this.entriesDirPath), sanitizePath(options.contentType),sanitizePath(options.locale), 'versions');
let versionedEntryPath = path.join(
sanitizePath(this.entriesDirPath),
sanitizePath(options.contentType),
sanitizePath(options.locale),
'versions',
);
fsUtil.makeDirectory(versionedEntryPath);
await this.fetchEntriesVersions(entriesSearchResponse.items, {
locale: options.locale,
contentType: options.contentType,
versionedEntryPath,
});
}

// NOTE Export all base entry specific 'variant entries'
if (this.exportVariantEntry) {
await this.variantEntries.exportVariantEntry({
locale: options.locale,
contentTypeUid: options.contentType,
entries: entriesSearchResponse.items,
});
}

options.skip += this.entriesConfig.limit || 100;
if (options.skip >= entriesSearchResponse.count) {
return Promise.resolve(true);
Expand All @@ -153,7 +195,10 @@ export default class EntriesExport extends BaseClass {
options: { locale: string; contentType: string; versionedEntryPath: string },
): Promise<void> {
const onSuccess = ({ response, apiData: entry }: any) => {
fsUtil.writeFile(path.join(sanitizePath(options.versionedEntryPath), sanitizePath(`${entry.uid}.json`)), response);
fsUtil.writeFile(
path.join(sanitizePath(options.versionedEntryPath), sanitizePath(`${entry.uid}.json`)),
response,
);
log(
this.exportConfig,
`Exported versioned entries of type '${options.contentType}' locale '${options.locale}'`,
Expand Down
58 changes: 58 additions & 0 deletions packages/contentstack-export/src/export/modules/personalization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {
ExportProjects,
ExportExperiences,
ExportEvents,
ExportAttributes,
ExportAudiences,
AnyProperty,
} from '@contentstack/cli-variants';

import { log, formatError } from '../../utils';
import { ModuleClassParams, ExportConfig } from '../../types';

export default class ExportPersonalization {
public exportConfig: ExportConfig;
public personalizeConfig: { dirName: string; baseURL: Record<string, string> } & AnyProperty;
constructor({ exportConfig }: ModuleClassParams) {
this.exportConfig = exportConfig;
this.personalizeConfig = exportConfig.modules.personalization;
}

async start(): Promise<void> {
try {
if (!this.personalizeConfig.baseURL[this.exportConfig.region.name]) {
log(this.exportConfig, 'Skipping Personalize project export, personalize url is not set', 'info');
this.exportConfig.personalizationEnabled = false;
return;
}
if (this.exportConfig.management_token) {
log(this.exportConfig, 'Skipping Personalize project export when using management token', 'info');
this.exportConfig.personalizationEnabled = false;
return;
}
await new ExportProjects(this.exportConfig).start();
if (this.exportConfig.personalizationEnabled) {
const moduleMapper = {
events: new ExportEvents(this.exportConfig),
attributes: new ExportAttributes(this.exportConfig),
audiences: new ExportAudiences(this.exportConfig),
experiences: new ExportExperiences(this.exportConfig),
};

const order: (keyof typeof moduleMapper)[] = this.exportConfig.modules.personalization
.exportOrder as (keyof typeof moduleMapper)[];

for (const module of order) {
if (moduleMapper[module]) {
await moduleMapper[module].start();
} else {
log(this.exportConfig, `No implementation found for the module ${module}`, 'info');
}
}
}
} catch (error) {
this.exportConfig.personalizationEnabled = false;
log(this.exportConfig, error, 'error');
}
}
}
Loading

0 comments on commit 536e219

Please sign in to comment.