@contentstack/cli-cm-import 1.16.6 → 1.17.1
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/README.md +33 -31
- package/lib/commands/cm/stacks/import.js +6 -1
- package/lib/config/index.js +41 -0
- package/lib/import/module-importer.js +5 -4
- package/lib/import/modules/content-types.js +5 -1
- package/lib/import/modules/entries.d.ts +10 -5
- package/lib/import/modules/entries.js +40 -3
- package/lib/import/modules/personalization.d.ts +11 -0
- package/lib/import/modules/personalization.js +50 -0
- package/lib/import/modules/variant-entries.d.ts +12 -0
- package/lib/import/modules/variant-entries.js +41 -0
- package/lib/types/default-config.d.ts +40 -0
- package/lib/types/import-config.d.ts +3 -1
- package/lib/types/index.d.ts +7 -1
- package/lib/types/marketplace-app.d.ts +1 -3
- package/lib/utils/import-config-handler.js +3 -1
- package/oclif.manifest.json +8 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import
|
|
|
47
47
|
$ csdx COMMAND
|
|
48
48
|
running command...
|
|
49
49
|
$ csdx (--version)
|
|
50
|
-
@contentstack/cli-cm-import/1.
|
|
50
|
+
@contentstack/cli-cm-import/1.17.1 linux-x64 node-v18.20.4
|
|
51
51
|
$ csdx --help [COMMAND]
|
|
52
52
|
USAGE
|
|
53
53
|
$ csdx COMMAND
|
|
@@ -71,21 +71,22 @@ USAGE
|
|
|
71
71
|
[--branch <value>] [--import-webhook-status disable|current]
|
|
72
72
|
|
|
73
73
|
FLAGS
|
|
74
|
-
-B, --branch=<value>
|
|
75
|
-
-a, --alias=<value>
|
|
76
|
-
-b, --backup-dir=<value>
|
|
77
|
-
-c, --config=<value>
|
|
78
|
-
-d, --data-dir=<value>
|
|
79
|
-
-k, --stack-api-key=<value>
|
|
80
|
-
-m, --module=<value>
|
|
81
|
-
-y, --yes
|
|
82
|
-
--exclude-global-modules
|
|
83
|
-
--import-webhook-status=<option>
|
|
84
|
-
|
|
85
|
-
--
|
|
86
|
-
--
|
|
87
|
-
--skip-
|
|
88
|
-
--skip-
|
|
74
|
+
-B, --branch=<value> [optional] branch name
|
|
75
|
+
-a, --alias=<value> alias of the management token
|
|
76
|
+
-b, --backup-dir=<value> [optional] backup directory name when using specific module
|
|
77
|
+
-c, --config=<value> [optional] path of config file
|
|
78
|
+
-d, --data-dir=<value> path and location where data is stored
|
|
79
|
+
-k, --stack-api-key=<value> API key of the target stack
|
|
80
|
+
-m, --module=<value> [optional] specific module name
|
|
81
|
+
-y, --yes [optional] Override marketplace prompts
|
|
82
|
+
--exclude-global-modules Excludes the branch-independent module from the import operation
|
|
83
|
+
--import-webhook-status=<option> [default: disable] [optional] Webhook state
|
|
84
|
+
<options: disable|current>
|
|
85
|
+
--personalize-project-name=<value> Personalize project name.
|
|
86
|
+
--replace-existing Replaces the existing module in the target stack.
|
|
87
|
+
--skip-app-recreation [optional] Skip private apps recreation if already exist
|
|
88
|
+
--skip-audit Skips the audit fix.
|
|
89
|
+
--skip-existing Skips the module exists warning messages.
|
|
89
90
|
|
|
90
91
|
DESCRIPTION
|
|
91
92
|
Import content from a stack
|
|
@@ -121,21 +122,22 @@ USAGE
|
|
|
121
122
|
[--branch <value>] [--import-webhook-status disable|current]
|
|
122
123
|
|
|
123
124
|
FLAGS
|
|
124
|
-
-B, --branch=<value>
|
|
125
|
-
-a, --alias=<value>
|
|
126
|
-
-b, --backup-dir=<value>
|
|
127
|
-
-c, --config=<value>
|
|
128
|
-
-d, --data-dir=<value>
|
|
129
|
-
-k, --stack-api-key=<value>
|
|
130
|
-
-m, --module=<value>
|
|
131
|
-
-y, --yes
|
|
132
|
-
--exclude-global-modules
|
|
133
|
-
--import-webhook-status=<option>
|
|
134
|
-
|
|
135
|
-
--
|
|
136
|
-
--
|
|
137
|
-
--skip-
|
|
138
|
-
--skip-
|
|
125
|
+
-B, --branch=<value> [optional] branch name
|
|
126
|
+
-a, --alias=<value> alias of the management token
|
|
127
|
+
-b, --backup-dir=<value> [optional] backup directory name when using specific module
|
|
128
|
+
-c, --config=<value> [optional] path of config file
|
|
129
|
+
-d, --data-dir=<value> path and location where data is stored
|
|
130
|
+
-k, --stack-api-key=<value> API key of the target stack
|
|
131
|
+
-m, --module=<value> [optional] specific module name
|
|
132
|
+
-y, --yes [optional] Override marketplace prompts
|
|
133
|
+
--exclude-global-modules Excludes the branch-independent module from the import operation
|
|
134
|
+
--import-webhook-status=<option> [default: disable] [optional] Webhook state
|
|
135
|
+
<options: disable|current>
|
|
136
|
+
--personalize-project-name=<value> Personalize project name.
|
|
137
|
+
--replace-existing Replaces the existing module in the target stack.
|
|
138
|
+
--skip-app-recreation [optional] Skip private apps recreation if already exist
|
|
139
|
+
--skip-audit Skips the audit fix.
|
|
140
|
+
--skip-existing Skips the module exists warning messages.
|
|
139
141
|
|
|
140
142
|
DESCRIPTION
|
|
141
143
|
Import content from a stack
|
|
@@ -17,6 +17,7 @@ class ImportCommand extends cli_command_1.Command {
|
|
|
17
17
|
let importConfig = await (0, utils_1.setupImportConfig)(flags);
|
|
18
18
|
// Note setting host to create cma client
|
|
19
19
|
importConfig.host = this.cmaHost;
|
|
20
|
+
importConfig.region = this.region;
|
|
20
21
|
importConfig.developerHubBaseUrl = this.developerHubUrl;
|
|
21
22
|
backupDir = importConfig.cliLogsPath || importConfig.backupDir;
|
|
22
23
|
const managementAPIClient = await (0, cli_utilities_1.managementSDKClient)(importConfig);
|
|
@@ -127,12 +128,16 @@ ImportCommand.flags = {
|
|
|
127
128
|
default: false,
|
|
128
129
|
description: 'Skips the module exists warning messages.',
|
|
129
130
|
}),
|
|
131
|
+
'personalize-project-name': cli_utilities_1.flags.string({
|
|
132
|
+
required: false,
|
|
133
|
+
description: 'Personalize project name.',
|
|
134
|
+
}),
|
|
130
135
|
'skip-audit': cli_utilities_1.flags.boolean({
|
|
131
136
|
description: 'Skips the audit fix.',
|
|
132
137
|
}),
|
|
133
138
|
'exclude-global-modules': cli_utilities_1.flags.boolean({
|
|
134
139
|
description: 'Excludes the branch-independent module from the import operation',
|
|
135
|
-
default: false
|
|
140
|
+
default: false,
|
|
136
141
|
}),
|
|
137
142
|
};
|
|
138
143
|
ImportCommand.aliases = ['cm:import'];
|
package/lib/config/index.js
CHANGED
|
@@ -33,9 +33,11 @@ const config = {
|
|
|
33
33
|
'marketplace-apps',
|
|
34
34
|
'global-fields',
|
|
35
35
|
'content-types',
|
|
36
|
+
'personalization',
|
|
36
37
|
'custom-roles',
|
|
37
38
|
'workflows',
|
|
38
39
|
'entries',
|
|
40
|
+
'variant-entries',
|
|
39
41
|
'labels',
|
|
40
42
|
'webhooks',
|
|
41
43
|
],
|
|
@@ -149,6 +151,45 @@ const config = {
|
|
|
149
151
|
dirName: 'taxonomies',
|
|
150
152
|
fileName: 'taxonomies.json',
|
|
151
153
|
},
|
|
154
|
+
personalization: {
|
|
155
|
+
baseURL: {
|
|
156
|
+
NA: 'https://personalization-api.contentstack.com',
|
|
157
|
+
},
|
|
158
|
+
importData: true,
|
|
159
|
+
dirName: 'personalization',
|
|
160
|
+
importOrder: ['attributes', 'audiences', 'events', 'experiences'],
|
|
161
|
+
project_id: '',
|
|
162
|
+
projects: {
|
|
163
|
+
dirName: 'projects',
|
|
164
|
+
fileName: 'projects.json',
|
|
165
|
+
},
|
|
166
|
+
attributes: {
|
|
167
|
+
dirName: 'attributes',
|
|
168
|
+
fileName: 'attributes.json',
|
|
169
|
+
},
|
|
170
|
+
audiences: {
|
|
171
|
+
dirName: 'audiences',
|
|
172
|
+
fileName: 'audiences.json',
|
|
173
|
+
},
|
|
174
|
+
events: {
|
|
175
|
+
dirName: 'events',
|
|
176
|
+
fileName: 'events.json',
|
|
177
|
+
},
|
|
178
|
+
experiences: {
|
|
179
|
+
dirName: 'experiences',
|
|
180
|
+
fileName: 'experiences.json',
|
|
181
|
+
thresholdTimer: 60000,
|
|
182
|
+
checkIntervalDuration: 10000,
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
variantEntry: {
|
|
186
|
+
dirName: 'variants',
|
|
187
|
+
fileName: 'index.json',
|
|
188
|
+
apiConcurrency: 5,
|
|
189
|
+
query: {
|
|
190
|
+
locale: 'en-us',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
152
193
|
},
|
|
153
194
|
languagesCode: [
|
|
154
195
|
'af-za',
|
|
@@ -19,8 +19,9 @@ class ModuleImporter {
|
|
|
19
19
|
}
|
|
20
20
|
async start() {
|
|
21
21
|
if (!this.importConfig.management_token) {
|
|
22
|
-
const
|
|
23
|
-
this.importConfig.stackName =
|
|
22
|
+
const stackDetails = await this.stackAPIClient.fetch();
|
|
23
|
+
this.importConfig.stackName = stackDetails.name;
|
|
24
|
+
this.importConfig.org_uid = stackDetails.org_uid;
|
|
24
25
|
}
|
|
25
26
|
if (this.importConfig.branchName) {
|
|
26
27
|
await (0, utils_1.validateBranch)(this.stackAPIClient, this.importConfig, this.importConfig.branchName);
|
|
@@ -39,7 +40,7 @@ class ModuleImporter {
|
|
|
39
40
|
// NOTE audit and fix the import content.
|
|
40
41
|
if (!this.importConfig.skipAudit &&
|
|
41
42
|
(!this.importConfig.moduleName ||
|
|
42
|
-
['content-types', 'global-fields', 'entries', 'extensions', 'workflows'].includes(this.importConfig.moduleName))) {
|
|
43
|
+
['content-types', 'global-fields', 'entries', 'extensions', 'workflows', 'custom-roles'].includes(this.importConfig.moduleName))) {
|
|
43
44
|
if (!(await this.auditImportData(logger))) {
|
|
44
45
|
return { noSuccessMsg: true };
|
|
45
46
|
}
|
|
@@ -118,7 +119,7 @@ class ModuleImporter {
|
|
|
118
119
|
}
|
|
119
120
|
else if (this.importConfig.modules.types.length) {
|
|
120
121
|
this.importConfig.modules.types
|
|
121
|
-
.filter((val) => ['content-types', 'global-fields', 'entries', 'extensions', 'workflows'].includes(val))
|
|
122
|
+
.filter((val) => ['content-types', 'global-fields', 'entries', 'extensions', 'workflows', 'custom-roles'].includes(val))
|
|
122
123
|
.forEach((val) => {
|
|
123
124
|
args.push('--modules', val);
|
|
124
125
|
});
|
|
@@ -44,6 +44,7 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
44
44
|
this.extPendingPath = path.join((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'extensions', 'pending_extensions.js');
|
|
45
45
|
}
|
|
46
46
|
async start() {
|
|
47
|
+
var _a;
|
|
47
48
|
/**
|
|
48
49
|
* read content type, check if it is necessary to read the entire dir
|
|
49
50
|
* Seed content types
|
|
@@ -60,11 +61,13 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
60
61
|
this.installedExtensions = ((await utils_1.fsUtil.readFile(this.marketplaceAppMapperPath)) || { extension_uid: {} }).extension_uid;
|
|
61
62
|
this.taxonomies = utils_1.fsUtil.readFile(this.taxonomiesPath);
|
|
62
63
|
await this.seedCTs();
|
|
64
|
+
if ((_a = this.createdCTs) === null || _a === void 0 ? void 0 : _a.length)
|
|
65
|
+
utils_1.fsUtil.writeFile(this.cTsSuccessPath, this.createdCTs);
|
|
63
66
|
(0, utils_1.log)(this.importConfig, 'Created content types', 'success');
|
|
64
67
|
await this.updateCTs();
|
|
65
68
|
(0, utils_1.log)(this.importConfig, 'Updated content types with references', 'success');
|
|
66
69
|
if (this.fieldRules.length > 0) {
|
|
67
|
-
|
|
70
|
+
utils_1.fsUtil.writeFile(path.join(this.cTsFolderPath, 'field_rules_uid.json'), this.fieldRules);
|
|
68
71
|
}
|
|
69
72
|
(0, utils_1.log)(this.importConfig, 'Updating the extensions...', 'success');
|
|
70
73
|
await this.updatePendingExtensions();
|
|
@@ -79,6 +82,7 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
79
82
|
}
|
|
80
83
|
async seedCTs() {
|
|
81
84
|
const onSuccess = ({ response: globalField, apiData: { content_type: { uid = null } = {} } = {} }) => {
|
|
85
|
+
this.createdCTs.push(uid);
|
|
82
86
|
(0, utils_1.log)(this.importConfig, `${uid} content type seeded`, 'info');
|
|
83
87
|
};
|
|
84
88
|
const onReject = ({ error, apiData: { content_type: { uid = null } = {} } = {} }) => {
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Contentstack Import
|
|
3
|
-
* Copyright (c) 2024 Contentstack LLC
|
|
4
|
-
* MIT Licensed
|
|
5
|
-
*/
|
|
6
1
|
import { ModuleClassParams } from '../../types';
|
|
7
2
|
import BaseClass, { ApiOptions } from './base-class';
|
|
8
3
|
export default class EntriesImport extends BaseClass {
|
|
@@ -38,8 +33,18 @@ export default class EntriesImport extends BaseClass {
|
|
|
38
33
|
taxonomies: Record<string, unknown>;
|
|
39
34
|
rteCTs: any;
|
|
40
35
|
rteCTsWithRef: any;
|
|
36
|
+
entriesForVariant: {
|
|
37
|
+
content_type: string;
|
|
38
|
+
locale: string;
|
|
39
|
+
entry_uid: string;
|
|
40
|
+
}[];
|
|
41
41
|
constructor({ importConfig, stackAPIClient }: ModuleClassParams);
|
|
42
42
|
start(): Promise<any>;
|
|
43
|
+
/**
|
|
44
|
+
* The function `createEntryDataForVariantEntry` writes the `entriesForVariant` data to a JSON file
|
|
45
|
+
* named `data-for-variant-entry.json`.
|
|
46
|
+
*/
|
|
47
|
+
createEntryDataForVariantEntry(): void;
|
|
43
48
|
disableMandatoryCTReferences(): Promise<void>;
|
|
44
49
|
/**
|
|
45
50
|
* @method serializeUpdateCTs
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
2
4
|
/* eslint-disable no-prototype-builtins */
|
|
3
5
|
/*!
|
|
4
6
|
* Contentstack Import
|
|
5
7
|
* Copyright (c) 2024 Contentstack LLC
|
|
6
8
|
* MIT Licensed
|
|
7
9
|
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
const tslib_1 = require("tslib");
|
|
10
10
|
const path = tslib_1.__importStar(require("path"));
|
|
11
|
+
const fs_1 = require("fs");
|
|
11
12
|
const lodash_1 = require("lodash");
|
|
12
13
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
13
14
|
const utils_1 = require("../../utils");
|
|
@@ -15,6 +16,7 @@ const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
|
15
16
|
class EntriesImport extends base_class_1.default {
|
|
16
17
|
constructor({ importConfig, stackAPIClient }) {
|
|
17
18
|
super({ importConfig, stackAPIClient });
|
|
19
|
+
this.entriesForVariant = [];
|
|
18
20
|
this.assetUidMapperPath = path.resolve((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'assets', 'uid-mapping.json');
|
|
19
21
|
this.assetUrlMapperPath = path.resolve((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'assets', 'url-mapping.json');
|
|
20
22
|
this.entriesMapperPath = path.resolve((0, cli_utilities_1.sanitizePath)(importConfig.data), 'mapper', 'entries');
|
|
@@ -107,12 +109,24 @@ class EntriesImport extends base_class_1.default {
|
|
|
107
109
|
}
|
|
108
110
|
(0, utils_1.log)(this.importConfig, 'All the entries have been published successfully', 'success');
|
|
109
111
|
}
|
|
112
|
+
this.createEntryDataForVariantEntry();
|
|
110
113
|
}
|
|
111
114
|
catch (error) {
|
|
115
|
+
this.createEntryDataForVariantEntry();
|
|
112
116
|
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
113
117
|
throw new Error('Error while importing entries');
|
|
114
118
|
}
|
|
115
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* The function `createEntryDataForVariantEntry` writes the `entriesForVariant` data to a JSON file
|
|
122
|
+
* named `data-for-variant-entry.json`.
|
|
123
|
+
*/
|
|
124
|
+
createEntryDataForVariantEntry() {
|
|
125
|
+
const filePath = path.join(this.entriesMapperPath, 'data-for-variant-entry.json');
|
|
126
|
+
if (!(0, lodash_1.isEmpty)(this.entriesForVariant)) {
|
|
127
|
+
(0, fs_1.writeFileSync)(filePath, JSON.stringify(this.entriesForVariant), { encoding: 'utf8' });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
116
130
|
async disableMandatoryCTReferences() {
|
|
117
131
|
const onSuccess = ({ response: contentType, apiData: { uid } }) => {
|
|
118
132
|
(0, utils_1.log)(this.importConfig, `${uid} content type references removed temporarily`, 'success');
|
|
@@ -238,6 +252,7 @@ class EntriesImport extends base_class_1.default {
|
|
|
238
252
|
const contentType = (0, lodash_1.find)(this.cTs, { uid: cTUid });
|
|
239
253
|
const onSuccess = ({ response, apiData: entry, additionalInfo }) => {
|
|
240
254
|
var _a, _b;
|
|
255
|
+
this.entriesForVariant.push({ content_type: cTUid, entry_uid: entry.uid, locale });
|
|
241
256
|
if ((_a = additionalInfo[entry.uid]) === null || _a === void 0 ? void 0 : _a.isLocalized) {
|
|
242
257
|
let oldUid = additionalInfo[entry.uid].entryOldUid;
|
|
243
258
|
(0, utils_1.log)(this.importConfig, `Localized entry: '${entry.title}' of content type ${cTUid} in locale ${locale}`, 'info');
|
|
@@ -264,7 +279,9 @@ class EntriesImport extends base_class_1.default {
|
|
|
264
279
|
const onReject = ({ error, apiData: entry, additionalInfo }) => {
|
|
265
280
|
var _a, _b;
|
|
266
281
|
const { title, uid } = entry;
|
|
267
|
-
//
|
|
282
|
+
// NOTE Remove from list if any entry import failed
|
|
283
|
+
(0, lodash_1.remove)(this.entriesForVariant, { locale, entry_uid: uid });
|
|
284
|
+
// NOTE: write existing entries into files to handler later
|
|
268
285
|
if (error.errorCode === 119) {
|
|
269
286
|
if (((_a = error === null || error === void 0 ? void 0 : error.errors) === null || _a === void 0 ? void 0 : _a.title) || ((_b = error === null || error === void 0 ? void 0 : error.errors) === null || _b === void 0 ? void 0 : _b.uid)) {
|
|
270
287
|
if (this.importConfig.replaceExisting) {
|
|
@@ -391,6 +408,8 @@ class EntriesImport extends base_class_1.default {
|
|
|
391
408
|
entriesReplaceFileHelper.writeIntoFile({ [entry.uid]: entry }, { mapKeyVal: true });
|
|
392
409
|
};
|
|
393
410
|
const onReject = ({ error, apiData: { uid, title } }) => {
|
|
411
|
+
// NOTE Remove from list if any entry import failed
|
|
412
|
+
(0, lodash_1.remove)(this.entriesForVariant, { locale, entry_uid: uid });
|
|
394
413
|
(0, utils_1.log)(this.importConfig, `${title} entry of content type ${cTUid} in locale ${locale} failed to replace`, 'error');
|
|
395
414
|
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
396
415
|
this.failedEntries.push({
|
|
@@ -503,6 +522,8 @@ class EntriesImport extends base_class_1.default {
|
|
|
503
522
|
(0, utils_1.log)(this.importConfig, `Updated entry: '${title}' of content type ${cTUid} in locale ${locale}`, 'info');
|
|
504
523
|
};
|
|
505
524
|
const onReject = ({ error, apiData: { uid, title } }) => {
|
|
525
|
+
// NOTE Remove from list if any entry import failed
|
|
526
|
+
(0, lodash_1.remove)(this.entriesForVariant, { locale, entry_uid: uid });
|
|
506
527
|
(0, utils_1.log)(this.importConfig, `${title} entry of content type ${cTUid} in locale ${locale} failed to update`, 'error');
|
|
507
528
|
(0, utils_1.log)(this.importConfig, (0, utils_1.formatError)(error), 'error');
|
|
508
529
|
this.failedEntries.push({
|
|
@@ -621,9 +642,21 @@ class EntriesImport extends base_class_1.default {
|
|
|
621
642
|
async removeAutoCreatedEntries() {
|
|
622
643
|
var _a, _b;
|
|
623
644
|
const onSuccess = ({ response, apiData: { entryUid } }) => {
|
|
645
|
+
var _a, _b;
|
|
646
|
+
// NOTE Remove entry from list
|
|
647
|
+
(0, lodash_1.remove)(this.entriesForVariant, {
|
|
648
|
+
entry_uid: entryUid,
|
|
649
|
+
locale: (_b = (_a = this.importConfig) === null || _a === void 0 ? void 0 : _a.master_locale) === null || _b === void 0 ? void 0 : _b.code,
|
|
650
|
+
});
|
|
624
651
|
(0, utils_1.log)(this.importConfig, `Auto created entry in master locale removed - entry uid ${entryUid} `, 'success');
|
|
625
652
|
};
|
|
626
653
|
const onReject = ({ error, apiData: { entryUid } }) => {
|
|
654
|
+
var _a, _b;
|
|
655
|
+
// NOTE Remove entry from list
|
|
656
|
+
(0, lodash_1.remove)(this.entriesForVariant, {
|
|
657
|
+
entry_uid: entryUid,
|
|
658
|
+
locale: (_b = (_a = this.importConfig) === null || _a === void 0 ? void 0 : _a.master_locale) === null || _b === void 0 ? void 0 : _b.code,
|
|
659
|
+
});
|
|
627
660
|
(0, utils_1.log)(this.importConfig, `Failed to remove auto created entry in master locale - entry uid ${entryUid} \n ${(0, utils_1.formatError)(error)}`, 'error');
|
|
628
661
|
};
|
|
629
662
|
return await this.makeConcurrentCall({
|
|
@@ -774,6 +807,10 @@ class EntriesImport extends base_class_1.default {
|
|
|
774
807
|
apiOptions.apiData = null;
|
|
775
808
|
return apiOptions;
|
|
776
809
|
}
|
|
810
|
+
if (requestObject.environments.length === 0 || requestObject.locales.length === 0) {
|
|
811
|
+
apiOptions.apiData = null;
|
|
812
|
+
return apiOptions;
|
|
813
|
+
}
|
|
777
814
|
apiOptions.apiData = requestObject;
|
|
778
815
|
return apiOptions;
|
|
779
816
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ImportConfig, ModuleClassParams } from '../../types';
|
|
2
|
+
export default class ImportPersonalization {
|
|
3
|
+
private config;
|
|
4
|
+
personalizeConfig: ImportConfig['modules']['personalization'];
|
|
5
|
+
constructor({ importConfig }: ModuleClassParams);
|
|
6
|
+
/**
|
|
7
|
+
* The `start` function in TypeScript asynchronously imports data based on a specified order using a
|
|
8
|
+
* module mapper.
|
|
9
|
+
*/
|
|
10
|
+
start(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cli_variants_1 = require("@contentstack/cli-variants");
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
class ImportPersonalization {
|
|
6
|
+
constructor({ importConfig }) {
|
|
7
|
+
this.config = importConfig;
|
|
8
|
+
this.personalizeConfig = importConfig.modules.personalization;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The `start` function in TypeScript asynchronously imports data based on a specified order using a
|
|
12
|
+
* module mapper.
|
|
13
|
+
*/
|
|
14
|
+
async start() {
|
|
15
|
+
try {
|
|
16
|
+
if (!this.personalizeConfig.baseURL[this.config.region.name]) {
|
|
17
|
+
(0, utils_1.log)(this.config, 'Skipping Personalize project import, personalize url is not set', 'info');
|
|
18
|
+
this.personalizeConfig.importData = false;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (this.config.management_token) {
|
|
22
|
+
(0, utils_1.log)(this.config, 'Skipping Personalize project import when using management token', 'info');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
await new cli_variants_1.Import.Project(this.config, utils_1.log).import();
|
|
26
|
+
if (this.personalizeConfig.importData) {
|
|
27
|
+
const moduleMapper = {
|
|
28
|
+
events: cli_variants_1.Import.Events,
|
|
29
|
+
audiences: cli_variants_1.Import.Audiences,
|
|
30
|
+
attributes: cli_variants_1.Import.Attribute,
|
|
31
|
+
experiences: cli_variants_1.Import.Experiences,
|
|
32
|
+
};
|
|
33
|
+
const order = this.personalizeConfig
|
|
34
|
+
.importOrder;
|
|
35
|
+
for (const module of order) {
|
|
36
|
+
const Module = moduleMapper[module];
|
|
37
|
+
await new Module(this.config, utils_1.log).import();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.personalizeConfig.importData = false; // Stop personalization import if project creation fails
|
|
43
|
+
(0, utils_1.log)(this.config, error, 'error');
|
|
44
|
+
if (!this.personalizeConfig.importData) {
|
|
45
|
+
(0, utils_1.log)(this.config, 'Skipping personalization migration...', 'warn');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.default = ImportPersonalization;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ImportConfig, ModuleClassParams } from '../../types';
|
|
2
|
+
export default class ImportVarientEntries {
|
|
3
|
+
private config;
|
|
4
|
+
personalization: ImportConfig['modules']['personalization'];
|
|
5
|
+
private projectMapperFilePath;
|
|
6
|
+
constructor({ importConfig }: ModuleClassParams);
|
|
7
|
+
/**
|
|
8
|
+
* The `start` function in TypeScript is an asynchronous method that conditionally imports data using
|
|
9
|
+
* helper methods and logs any errors encountered.
|
|
10
|
+
*/
|
|
11
|
+
start(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
5
|
+
const cli_variants_1 = require("@contentstack/cli-variants");
|
|
6
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
|
+
const utils_1 = require("../../utils");
|
|
8
|
+
class ImportVarientEntries {
|
|
9
|
+
constructor({ importConfig }) {
|
|
10
|
+
this.config = importConfig;
|
|
11
|
+
this.personalization = importConfig.modules.personalization;
|
|
12
|
+
this.projectMapperFilePath = path_1.default.resolve((0, cli_utilities_1.sanitizePath)(this.config.data), 'mapper', (0, cli_utilities_1.sanitizePath)(this.personalization.dirName), 'projects', 'projects.json');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The `start` function in TypeScript is an asynchronous method that conditionally imports data using
|
|
16
|
+
* helper methods and logs any errors encountered.
|
|
17
|
+
*/
|
|
18
|
+
async start() {
|
|
19
|
+
try {
|
|
20
|
+
const project = utils_1.fsUtil.readFile(this.projectMapperFilePath);
|
|
21
|
+
if (project && project.uid && this.personalization.importData) {
|
|
22
|
+
this.config.modules.personalization.project_id = project.uid;
|
|
23
|
+
const helpers = {
|
|
24
|
+
lookUpTerms: utils_1.lookUpTerms,
|
|
25
|
+
lookupAssets: utils_1.lookupAssets,
|
|
26
|
+
lookupEntries: utils_1.lookupEntries,
|
|
27
|
+
lookupExtension: utils_1.lookupExtension,
|
|
28
|
+
restoreJsonRteEntryRefs: utils_1.restoreJsonRteEntryRefs,
|
|
29
|
+
};
|
|
30
|
+
await new cli_variants_1.Import.VariantEntries(Object.assign(this.config, { helpers })).import();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
(0, utils_1.log)(this.config, 'Skipping entry variants import because no personalize project is linked.', 'info');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
(0, utils_1.log)(this.config, error, 'error');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.default = ImportVarientEntries;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Modules } from '.';
|
|
2
|
+
export interface AnyProperty {
|
|
3
|
+
[propName: string]: any;
|
|
4
|
+
}
|
|
2
5
|
export default interface DefaultConfig {
|
|
3
6
|
versioning: boolean;
|
|
4
7
|
host: string;
|
|
@@ -117,6 +120,43 @@ export default interface DefaultConfig {
|
|
|
117
120
|
fileName: string;
|
|
118
121
|
dependencies?: Modules[];
|
|
119
122
|
};
|
|
123
|
+
personalization: {
|
|
124
|
+
baseURL: Record<string, string>;
|
|
125
|
+
dirName: string;
|
|
126
|
+
importData: boolean;
|
|
127
|
+
importOrder: string[];
|
|
128
|
+
project_id?: string;
|
|
129
|
+
projects: {
|
|
130
|
+
dirName: string;
|
|
131
|
+
fileName: string;
|
|
132
|
+
};
|
|
133
|
+
attributes: {
|
|
134
|
+
dirName: string;
|
|
135
|
+
fileName: string;
|
|
136
|
+
};
|
|
137
|
+
audiences: {
|
|
138
|
+
dirName: string;
|
|
139
|
+
fileName: string;
|
|
140
|
+
};
|
|
141
|
+
events: {
|
|
142
|
+
dirName: string;
|
|
143
|
+
fileName: string;
|
|
144
|
+
};
|
|
145
|
+
experiences: {
|
|
146
|
+
dirName: string;
|
|
147
|
+
fileName: string;
|
|
148
|
+
thresholdTimer: number;
|
|
149
|
+
checkIntervalDuration: number;
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
variantEntry: {
|
|
153
|
+
dirName: string;
|
|
154
|
+
fileName: string;
|
|
155
|
+
apiConcurrency: number;
|
|
156
|
+
query: {
|
|
157
|
+
locale: string;
|
|
158
|
+
} & AnyProperty;
|
|
159
|
+
} & AnyProperty;
|
|
120
160
|
};
|
|
121
161
|
languagesCode: string[];
|
|
122
162
|
apis: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Modules } from '.';
|
|
1
|
+
import { Modules, Region } from '.';
|
|
2
2
|
import DefaultConfig from './default-config';
|
|
3
3
|
export interface ExternalConfig {
|
|
4
4
|
source_stack?: string;
|
|
@@ -49,6 +49,8 @@ export default interface ImportConfig extends DefaultConfig, ExternalConfig {
|
|
|
49
49
|
skipExisting?: boolean;
|
|
50
50
|
skipAudit?: boolean;
|
|
51
51
|
stackName?: string;
|
|
52
|
+
region: Region;
|
|
53
|
+
personalizeProjectName?: string;
|
|
52
54
|
'exclude-global-modules': false;
|
|
53
55
|
}
|
|
54
56
|
type branch = {
|
package/lib/types/index.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ export interface ContentStackManagementClient {
|
|
|
9
9
|
export interface PrintOptions {
|
|
10
10
|
color?: string;
|
|
11
11
|
}
|
|
12
|
+
export interface Region {
|
|
13
|
+
name: string;
|
|
14
|
+
cma: string;
|
|
15
|
+
cda: string;
|
|
16
|
+
uiHost: string;
|
|
17
|
+
}
|
|
12
18
|
export interface InquirePayload {
|
|
13
19
|
type: string;
|
|
14
20
|
name: string;
|
|
@@ -20,7 +26,7 @@ export interface User {
|
|
|
20
26
|
email: string;
|
|
21
27
|
authtoken: string;
|
|
22
28
|
}
|
|
23
|
-
export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies';
|
|
29
|
+
export type Modules = 'stack' | 'assets' | 'locales' | 'environments' | 'extensions' | 'webhooks' | 'global-fields' | 'entries' | 'content-types' | 'custom-roles' | 'workflows' | 'labels' | 'marketplace-apps' | 'taxonomies' | 'personalization' | 'variant-entries';
|
|
24
30
|
export type ModuleClassParams = {
|
|
25
31
|
stackAPIClient: ReturnType<ContentstackClient['stack']>;
|
|
26
32
|
importConfig: ImportConfig;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AnyProperty } from "./default-config";
|
|
1
2
|
type AppLocation = 'cs.cm.stack.config' | 'cs.cm.stack.dashboard' | 'cs.cm.stack.sidebar' | 'cs.cm.stack.custom_field' | 'cs.cm.stack.rte' | 'cs.cm.stack.asset_sidebar' | 'cs.org.config';
|
|
2
3
|
interface ExtensionMeta {
|
|
3
4
|
uid?: string;
|
|
@@ -21,9 +22,6 @@ interface LocationConfiguration {
|
|
|
21
22
|
base_url: string;
|
|
22
23
|
locations: Extension[];
|
|
23
24
|
}
|
|
24
|
-
interface AnyProperty {
|
|
25
|
-
[propName: string]: any;
|
|
26
|
-
}
|
|
27
25
|
type Manifest = {
|
|
28
26
|
uid: string;
|
|
29
27
|
name: string;
|
|
@@ -67,6 +67,7 @@ const setupConfig = async (importCmdFlags) => {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
config.isAuthenticated = (0, cli_utilities_1.isAuthenticated)();
|
|
70
|
+
config.auth_token = cli_utilities_1.configHandler.get('authtoken'); // TBD handle auth token in httpClient & sdk
|
|
70
71
|
//Note to support the old key
|
|
71
72
|
config.source_stack = config.apiKey;
|
|
72
73
|
config.skipAudit = importCmdFlags['skip-audit'];
|
|
@@ -75,7 +76,7 @@ const setupConfig = async (importCmdFlags) => {
|
|
|
75
76
|
config.skipPrivateAppRecreationIfExist = importCmdFlags['skip-app-recreation'];
|
|
76
77
|
if (importCmdFlags['branch']) {
|
|
77
78
|
config.branchName = importCmdFlags['branch'];
|
|
78
|
-
config.branchDir =
|
|
79
|
+
config.branchDir = config.contentDir;
|
|
79
80
|
}
|
|
80
81
|
if (importCmdFlags['module']) {
|
|
81
82
|
config.moduleName = importCmdFlags['module'];
|
|
@@ -88,6 +89,7 @@ const setupConfig = async (importCmdFlags) => {
|
|
|
88
89
|
config.target_stack = config.apiKey;
|
|
89
90
|
config.replaceExisting = importCmdFlags['replace-existing'];
|
|
90
91
|
config.skipExisting = importCmdFlags['skip-existing'];
|
|
92
|
+
config.personalizeProjectName = importCmdFlags['personalize-project-name'];
|
|
91
93
|
if (importCmdFlags['exclude-global-modules']) {
|
|
92
94
|
config['exclude-global-modules'] = importCmdFlags['exclude-global-modules'];
|
|
93
95
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.17.1",
|
|
3
3
|
"commands": {
|
|
4
4
|
"cm:stacks:import": {
|
|
5
5
|
"id": "cm:stacks:import",
|
|
@@ -144,6 +144,13 @@
|
|
|
144
144
|
"required": false,
|
|
145
145
|
"allowNo": false
|
|
146
146
|
},
|
|
147
|
+
"personalize-project-name": {
|
|
148
|
+
"name": "personalize-project-name",
|
|
149
|
+
"type": "option",
|
|
150
|
+
"description": "Personalize project name.",
|
|
151
|
+
"required": false,
|
|
152
|
+
"multiple": false
|
|
153
|
+
},
|
|
147
154
|
"skip-audit": {
|
|
148
155
|
"name": "skip-audit",
|
|
149
156
|
"type": "boolean",
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-import",
|
|
3
3
|
"description": "Contentstack CLI plugin to import content into stack",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.17.1",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-audit": "~1.
|
|
8
|
+
"@contentstack/cli-audit": "~1.7.0",
|
|
9
9
|
"@contentstack/cli-command": "~1.3.0",
|
|
10
|
-
"@contentstack/cli-utilities": "~1.7.
|
|
10
|
+
"@contentstack/cli-utilities": "~1.7.2",
|
|
11
11
|
"@contentstack/management": "~1.17.0",
|
|
12
|
+
"@contentstack/cli-variants": "0.0.1-alpha",
|
|
12
13
|
"@oclif/core": "^3.26.5",
|
|
13
14
|
"big-json": "^3.2.0",
|
|
14
15
|
"bluebird": "^3.7.2",
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
"nyc": "^15.1.0",
|
|
46
47
|
"oclif": "^3.8.1",
|
|
47
48
|
"rimraf": "^2.7.1",
|
|
48
|
-
"sinon": "^
|
|
49
|
+
"sinon": "^19.0.0",
|
|
49
50
|
"tmp": "^0.2.2",
|
|
50
51
|
"ts-node": "^10.9.1",
|
|
51
52
|
"typescript": "^4.9.3"
|