@contentstack/cli-cm-import 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/README.md +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +4 -4
- package/src/app.js +3 -3
- package/src/config/default.js +18 -2
- package/src/lib/import/assets.js +8 -10
- package/src/lib/import/content-types.js +22 -7
- package/src/lib/import/custom-roles.js +159 -0
- package/src/lib/import/entries.js +31 -11
- package/src/lib/import/global-fields.js +16 -3
- package/src/lib/import/locales.js +1 -0
- package/src/lib/import/marketplace-apps.js +440 -0
- package/src/lib/import/workflows.js +41 -11
- package/src/lib/util/extensionsUidReplace.js +18 -3
- package/src/lib/util/lookupReplaceAssets.js +99 -8
- package/src/lib/util/lookupReplaceEntries.js +43 -42
- package/src/lib/util/marketplace-app-helper.js +38 -0
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ $ npm install -g @contentstack/cli-cm-import
|
|
|
37
37
|
$ csdx COMMAND
|
|
38
38
|
running command...
|
|
39
39
|
$ csdx (-v|--version|version)
|
|
40
|
-
@contentstack/cli-cm-import/1.
|
|
40
|
+
@contentstack/cli-cm-import/1.1.0 darwin-arm64 node-v16.17.0
|
|
41
41
|
$ csdx --help [COMMAND]
|
|
42
42
|
USAGE
|
|
43
43
|
$ csdx COMMAND
|
|
@@ -88,5 +88,5 @@ EXAMPLES
|
|
|
88
88
|
csdx cm:stacks:import --branch <branch name>
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
_See code: [src/commands/cm/stacks/import.js](https://github.com/contentstack/cli/blob/v1.
|
|
91
|
+
_See code: [src/commands/cm/stacks/import.js](https://github.com/contentstack/cli/blob/v1.1.0/packages/contentstack-import/src/commands/cm/stacks/import.js)_
|
|
92
92
|
<!-- commandsstop -->
|
package/oclif.manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.
|
|
1
|
+
{"version":"1.1.0","commands":{"cm:stacks:import":{"id":"cm:stacks:import","description":"Import script for importing the content into the new stack\n...\nOnce you export content from the source stack, import it to your destination stack by using the cm:stacks:import command.\n","usage":"cm:stacks:import [-c <value>] [-k <value>] [-d <value>] [-a <value>] [--module <value>] [--backup-dir <value>] [--branch <value>] [--import-webhook-status disable|current]","pluginName":"@contentstack/cli-cm-import","pluginType":"core","aliases":["cm:import"],"examples":["csdx cm:stacks:import --stack-api-key <stack_api_key> --data-dir <path/of/export/destination/dir>","csdx cm:stacks:import --config <path/of/config/dir>","csdx cm:stacks:import --module <single module name>","csdx cm:stacks:import --module <single module name> --backup-dir <backup dir>","csdx cm:stacks:import --alias <management_token_alias>","csdx cm:stacks:import --alias <management_token_alias> --data-dir <path/of/export/destination/dir>","csdx cm:stacks:import --alias <management_token_alias> --config <path/of/config/file>","csdx cm:stacks:import --branch <branch name>"],"flags":{"config":{"name":"config","type":"option","char":"c","description":"[optional] path of config file"},"stack-uid":{"name":"stack-uid","type":"option","char":"s","description":"API key of the target stack","hidden":true},"stack-api-key":{"name":"stack-api-key","type":"option","char":"k","description":"API key of the target stack"},"data":{"name":"data","type":"option","description":"path and location where data is stored","hidden":true},"data-dir":{"name":"data-dir","type":"option","char":"d","description":"path and location where data is stored"},"alias":{"name":"alias","type":"option","char":"a","description":"alias of the management token"},"management-token-alias":{"name":"management-token-alias","type":"option","description":"alias of the management token","hidden":true},"auth-token":{"name":"auth-token","type":"boolean","char":"A","description":"to use auth token","hidden":true,"allowNo":false},"module":{"name":"module","type":"option","char":"m","description":"[optional] specific module name"},"backup-dir":{"name":"backup-dir","type":"option","char":"b","description":"[optional] backup directory name when using specific module"},"branch":{"name":"branch","type":"option","char":"B","description":"[optional] branch name"},"import-webhook-status":{"name":"import-webhook-status","type":"option","description":"Webhook state","required":false,"options":["disable","current"],"default":"disable"}},"args":[]}}}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
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.1.0",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-command": "^1.0.
|
|
8
|
+
"@contentstack/cli-command": "^1.0.1",
|
|
9
9
|
"@contentstack/management": "^1.3.0",
|
|
10
|
-
"@contentstack/cli-utilities": "^1.0.
|
|
11
|
-
"@contentstack/cli-cm-export": "^1.
|
|
10
|
+
"@contentstack/cli-utilities": "^1.0.2",
|
|
11
|
+
"@contentstack/cli-cm-export": "^1.1.0",
|
|
12
12
|
"@oclif/command": "^1.8.16",
|
|
13
13
|
"@oclif/config": "^1.18.3",
|
|
14
14
|
"bluebird": "3.5.1",
|
package/src/app.js
CHANGED
|
@@ -91,7 +91,7 @@ let singleImport = async (moduleName, types, config) => {
|
|
|
91
91
|
if (moduleName === 'content-types') {
|
|
92
92
|
let ctPath = path.resolve(config.data, config.modules.content_types.dirName);
|
|
93
93
|
let fieldPath = path.join(ctPath + '/field_rules_uid.json');
|
|
94
|
-
if (fieldPath
|
|
94
|
+
if (fieldPath) {
|
|
95
95
|
await util.field_rules_update(config, ctPath);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -139,9 +139,9 @@ let allImport = async (config, types) => {
|
|
|
139
139
|
config,
|
|
140
140
|
chalk.green(
|
|
141
141
|
'The data of the ' +
|
|
142
|
-
config.sourceStackName +
|
|
142
|
+
(config.sourceStackName || config.source_stack) +
|
|
143
143
|
' stack has been imported into ' +
|
|
144
|
-
config.destinationStackName +
|
|
144
|
+
(config.destinationStackName || config.target_stack) +
|
|
145
145
|
' stack successfully!',
|
|
146
146
|
),
|
|
147
147
|
'success',
|
package/src/config/default.js
CHANGED
|
@@ -8,24 +8,38 @@ module.exports = {
|
|
|
8
8
|
// not passing `locale` will migrate all the locales present
|
|
9
9
|
// locales: ['fr-fr'],
|
|
10
10
|
host: 'https://api.contentstack.io/v3',
|
|
11
|
+
extensionHost: 'https://app.contentstack.com',
|
|
12
|
+
developerHubUrls: {
|
|
13
|
+
'https://api.contentstack.io': 'https://developerhub-api.contentstack.com',
|
|
14
|
+
'https://eu-api.contentstack.com': 'https://eu-developerhub-api.contentstack.com',
|
|
15
|
+
'https://azure-na-api.contentstack.com': 'https://azure-na-developerhub-api.contentstack.com',
|
|
16
|
+
'https://stag-api.csnonprod.com': 'https://stag-developerhub-api.csnonprod.com'
|
|
17
|
+
},
|
|
11
18
|
modules: {
|
|
12
19
|
types: [
|
|
13
20
|
'locales',
|
|
14
21
|
'environments',
|
|
15
22
|
'assets',
|
|
16
23
|
'extensions',
|
|
24
|
+
'marketplace-apps',
|
|
17
25
|
'global-fields',
|
|
18
26
|
'content-types',
|
|
19
27
|
'workflows',
|
|
20
28
|
'entries',
|
|
21
29
|
'labels',
|
|
22
30
|
'webhooks',
|
|
31
|
+
'custom-roles',
|
|
23
32
|
],
|
|
24
33
|
locales: {
|
|
25
34
|
dirName: 'locales',
|
|
26
35
|
fileName: 'locales.json',
|
|
27
36
|
requiredKeys: ['code', 'uid', 'name', 'fallback_locale'],
|
|
28
37
|
},
|
|
38
|
+
customRoles: {
|
|
39
|
+
dirName: 'custom-roles',
|
|
40
|
+
fileName: 'custom-roles.json',
|
|
41
|
+
customRolesLocalesFileName: 'custom-roles-locales.json',
|
|
42
|
+
},
|
|
29
43
|
environments: {
|
|
30
44
|
dirName: 'environments',
|
|
31
45
|
fileName: 'environments.json',
|
|
@@ -74,7 +88,6 @@ module.exports = {
|
|
|
74
88
|
limit: 50,
|
|
75
89
|
assetBatchLimit: 5,
|
|
76
90
|
},
|
|
77
|
-
|
|
78
91
|
globalfields: {
|
|
79
92
|
dirName: 'global_fields',
|
|
80
93
|
fileName: 'globalfields.json',
|
|
@@ -85,6 +98,10 @@ module.exports = {
|
|
|
85
98
|
dirName: 'stack',
|
|
86
99
|
fileName: 'stack.json',
|
|
87
100
|
},
|
|
101
|
+
marketplace_apps: {
|
|
102
|
+
dirName: 'marketplace_apps',
|
|
103
|
+
fileName: 'marketplace_apps.json'
|
|
104
|
+
}
|
|
88
105
|
},
|
|
89
106
|
languagesCode: [
|
|
90
107
|
'af-za',
|
|
@@ -296,7 +313,6 @@ module.exports = {
|
|
|
296
313
|
'xh',
|
|
297
314
|
'zu',
|
|
298
315
|
],
|
|
299
|
-
|
|
300
316
|
apis: {
|
|
301
317
|
userSession: '/user-session/',
|
|
302
318
|
locales: '/locales/',
|
package/src/lib/import/assets.js
CHANGED
|
@@ -418,22 +418,20 @@ importAssets.prototype = {
|
|
|
418
418
|
i--;
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
|
-
this.findBranches(tree, coll);
|
|
421
|
+
this.findBranches(tree, _.keys(tree), coll);
|
|
422
422
|
return tree;
|
|
423
423
|
},
|
|
424
|
-
findBranches: function (
|
|
424
|
+
findBranches: function (tree, branches, coll) {
|
|
425
425
|
let self = this;
|
|
426
|
-
_.forEach(
|
|
426
|
+
_.forEach(branches, (branch) => {
|
|
427
427
|
for (let j = 0; j < coll.length; j++) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
branch
|
|
431
|
-
|
|
432
|
-
self.findBranches(branch[parent_uid], coll);
|
|
433
|
-
--j;
|
|
428
|
+
if (branch === coll[j].parent_uid) {
|
|
429
|
+
let childUid = coll[j].uid;
|
|
430
|
+
tree[branch][childUid] = {};
|
|
431
|
+
self.findBranches(tree[branch], [childUid], coll);
|
|
434
432
|
}
|
|
435
433
|
}
|
|
436
|
-
})
|
|
434
|
+
});
|
|
437
435
|
},
|
|
438
436
|
publish: function (assetUid, assetObject) {
|
|
439
437
|
let self = this;
|
|
@@ -14,10 +14,11 @@ let chalk = require('chalk');
|
|
|
14
14
|
|
|
15
15
|
let helper = require('../util/fs');
|
|
16
16
|
let { addlogs } = require('../util/log');
|
|
17
|
+
let config = require('../../config/default');
|
|
17
18
|
let supress = require('../util/extensionsUidReplace');
|
|
18
19
|
let sdkInstance = require('../util/contentstack-management-sdk');
|
|
20
|
+
const { getInstalledExtensions } = require('../util/marketplace-app-helper')
|
|
19
21
|
|
|
20
|
-
let config = require('../../config/default');
|
|
21
22
|
let reqConcurrency = config.concurrency;
|
|
22
23
|
let requestLimit = config.rateLimit;
|
|
23
24
|
let contentTypeConfig = config.modules.content_types;
|
|
@@ -40,10 +41,11 @@ function importContentTypes() {
|
|
|
40
41
|
this.requestOptions = {
|
|
41
42
|
json: {},
|
|
42
43
|
};
|
|
44
|
+
this.installedExtensions = []
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
importContentTypes.prototype = {
|
|
46
|
-
start: function (credentialConfig) {
|
|
48
|
+
start: async function (credentialConfig) {
|
|
47
49
|
addlogs(config, 'Migrating contenttypes', 'success');
|
|
48
50
|
let self = this;
|
|
49
51
|
config = credentialConfig;
|
|
@@ -52,6 +54,7 @@ importContentTypes.prototype = {
|
|
|
52
54
|
globalFieldsFolderPath = path.resolve(config.data, globalFieldConfig.dirName);
|
|
53
55
|
contentTypesFolderPath = path.resolve(config.data, contentTypeConfig.dirName);
|
|
54
56
|
mapperFolderPath = path.join(config.data, 'mapper', 'content_types');
|
|
57
|
+
const appMapperFolderPath = path.join(config.data, 'mapper', 'marketplace_apps');
|
|
55
58
|
globalFieldMapperFolderPath = helper.readFile(path.join(config.data, 'mapper', 'global_fields', 'success.json'));
|
|
56
59
|
globalFieldPendingPath = helper.readFile(
|
|
57
60
|
path.join(config.data, 'mapper', 'global_fields', 'pending_global_fields.js'),
|
|
@@ -59,6 +62,7 @@ importContentTypes.prototype = {
|
|
|
59
62
|
globalFieldUpdateFile = path.join(config.data, 'mapper', 'global_fields', 'success.json');
|
|
60
63
|
fileNames = fs.readdirSync(path.join(contentTypesFolderPath));
|
|
61
64
|
self.globalfields = helper.readFile(path.resolve(globalFieldsFolderPath, globalFieldConfig.fileName));
|
|
65
|
+
|
|
62
66
|
for (let index in fileNames) {
|
|
63
67
|
if (skipFiles.indexOf(fileNames[index]) === -1) {
|
|
64
68
|
self.contentTypes.push(helper.readFile(path.join(contentTypesFolderPath, fileNames[index])));
|
|
@@ -74,6 +78,15 @@ importContentTypes.prototype = {
|
|
|
74
78
|
if (fs.existsSync(path.join(mapperFolderPath, 'success.json'))) {
|
|
75
79
|
self.createdContentTypeUids = helper.readFile(path.join(mapperFolderPath, 'success.json')) || [];
|
|
76
80
|
}
|
|
81
|
+
|
|
82
|
+
if (fs.existsSync(path.join(appMapperFolderPath, 'marketplace-apps.json'))) {
|
|
83
|
+
self.installedExtensions = helper.readFile(path.join(appMapperFolderPath, 'marketplace-apps.json')) || {};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (_.isEmpty(self.installedExtensions)) {
|
|
87
|
+
self.installedExtensions = await getInstalledExtensions(config)
|
|
88
|
+
}
|
|
89
|
+
|
|
77
90
|
self.contentTypeUids = _.difference(self.contentTypeUids, self.createdContentTypeUids);
|
|
78
91
|
self.uidToTitleMap = self.mapUidToTitle(self.contentTypes);
|
|
79
92
|
// remove content types, already created
|
|
@@ -182,13 +195,14 @@ importContentTypes.prototype = {
|
|
|
182
195
|
updateContentTypes: function (contentType) {
|
|
183
196
|
let self = this;
|
|
184
197
|
return new Promise(function (resolve, reject) {
|
|
185
|
-
setTimeout(function () {
|
|
198
|
+
setTimeout(async function () {
|
|
186
199
|
let requestObject = _.cloneDeep(self.requestOptions);
|
|
187
200
|
if (contentType.field_rules) {
|
|
188
201
|
field_rules_ct.push(contentType.uid);
|
|
189
202
|
delete contentType.field_rules;
|
|
190
203
|
}
|
|
191
|
-
|
|
204
|
+
|
|
205
|
+
supress(contentType.schema, config.preserveStackVersion, self.installedExtensions);
|
|
192
206
|
requestObject.json.content_type = contentType;
|
|
193
207
|
let contentTypeResponse = stack.contentType(contentType.uid);
|
|
194
208
|
Object.assign(contentTypeResponse, _.cloneDeep(contentType));
|
|
@@ -209,9 +223,10 @@ importContentTypes.prototype = {
|
|
|
209
223
|
let self = this;
|
|
210
224
|
return new Promise(function (resolve, reject) {
|
|
211
225
|
// eslint-disable-next-line no-undef
|
|
212
|
-
return Promise.map(globalFieldPendingPath, function (globalfield) {
|
|
226
|
+
return Promise.map(globalFieldPendingPath, async function (globalfield) {
|
|
213
227
|
let Obj = _.find(self.globalfields, { uid: globalfield });
|
|
214
|
-
|
|
228
|
+
|
|
229
|
+
supress(Obj.schema, config.preserveStackVersion, self.installedExtensions);
|
|
215
230
|
let globalFieldObj = stack.globalField(globalfield);
|
|
216
231
|
Object.assign(globalFieldObj, _.cloneDeep(Obj));
|
|
217
232
|
return globalFieldObj
|
|
@@ -245,7 +260,7 @@ importContentTypes.prototype = {
|
|
|
245
260
|
result[ct.uid] = ct.title;
|
|
246
261
|
});
|
|
247
262
|
return result;
|
|
248
|
-
}
|
|
263
|
+
}
|
|
249
264
|
};
|
|
250
265
|
|
|
251
266
|
module.exports = new importContentTypes();
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const mkdirp = require('mkdirp');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
|
|
8
|
+
const helper = require('../util/fs');
|
|
9
|
+
const { addlogs } = require('../util/log');
|
|
10
|
+
const stack = require('../util/contentstack-management-sdk');
|
|
11
|
+
let config = require('../../config/default');
|
|
12
|
+
|
|
13
|
+
const customRolesConfig = config.modules.customRoles;
|
|
14
|
+
let customRolesFolderPath;
|
|
15
|
+
// Mapper file paths variables.
|
|
16
|
+
let customRolesMapperPath;
|
|
17
|
+
let customRolesUidMapperPath;
|
|
18
|
+
let customRolesSuccessPath;
|
|
19
|
+
let customRolesFailsPath;
|
|
20
|
+
let environmentsUidMapperFolderPath;
|
|
21
|
+
let entriesUidMapperFolderPath;
|
|
22
|
+
let customRolesLocalesFilePath;
|
|
23
|
+
|
|
24
|
+
function ImportCustomRoles() {
|
|
25
|
+
this.fails = [];
|
|
26
|
+
this.customRolesUidMapper = {};
|
|
27
|
+
this.labelUids = [];
|
|
28
|
+
this.client = null;
|
|
29
|
+
if (fs.existsSync(customRolesMapperPath)) {
|
|
30
|
+
this.customRolesUidMapper = helper.readFile(customRolesUidMapperPath) || {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
ImportCustomRoles.prototype.start = async function(credentialConfig) {
|
|
35
|
+
let self = this;
|
|
36
|
+
try {
|
|
37
|
+
config = credentialConfig;
|
|
38
|
+
this.client = stack.Client(config);
|
|
39
|
+
addlogs(config, chalk.white('Migrating custom-roles'), 'success');
|
|
40
|
+
customRolesFolderPath = path.resolve(config.data, customRolesConfig.dirName);
|
|
41
|
+
self.customRoles = helper.readFile(path.resolve(customRolesFolderPath, customRolesConfig.fileName));
|
|
42
|
+
customRolesLocalesFilePath = path.resolve(customRolesFolderPath, customRolesConfig.customRolesLocalesFileName);
|
|
43
|
+
self.customRolesLocales = helper.readFile(customRolesLocalesFilePath);
|
|
44
|
+
// Mapper file paths.
|
|
45
|
+
customRolesMapperPath = path.resolve(config.data, 'mapper', 'custom-roles');
|
|
46
|
+
customRolesUidMapperPath = path.resolve(config.data, 'mapper', 'custom-roles', 'uid-mapping.json');
|
|
47
|
+
customRolesSuccessPath = path.resolve(config.data, 'custom-roles', 'success.json');
|
|
48
|
+
customRolesFailsPath = path.resolve(config.data, 'custom-roles', 'fails.json');
|
|
49
|
+
environmentsUidMapperFolderPath = path.resolve(config.data, 'mapper', 'environments');
|
|
50
|
+
entriesUidMapperFolderPath = path.resolve(config.data, 'mapper', 'entries');
|
|
51
|
+
mkdirp.sync(customRolesMapperPath);
|
|
52
|
+
|
|
53
|
+
if (!self.customRoles) {
|
|
54
|
+
addlogs(config, chalk.white('No custom-roles found'), 'error');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
self.customRolesUids = Object.keys(self.customRoles);
|
|
58
|
+
|
|
59
|
+
self.localesUidMap = await getLocalesUidMap(this.client, config, self.customRolesLocales);
|
|
60
|
+
|
|
61
|
+
if (fs.existsSync(environmentsUidMapperFolderPath)) {
|
|
62
|
+
self.environmentsUidMap = helper.readFile(path.resolve(environmentsUidMapperFolderPath, 'uid-mapping.json'));
|
|
63
|
+
}
|
|
64
|
+
if (fs.existsSync(entriesUidMapperFolderPath)) {
|
|
65
|
+
self.entriesUidMap = helper.readFile(path.resolve(entriesUidMapperFolderPath, 'uid-mapping.json'));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (const uid of self.customRolesUids) {
|
|
69
|
+
const customRole = self.customRoles[uid];
|
|
70
|
+
|
|
71
|
+
if (uid in self.customRolesUidMapper) {
|
|
72
|
+
addlogs(config, chalk.white(`The custom-role ${customRole.name} already exists. Skipping it to avoid duplicates!`), 'success');
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
customRole.rules.forEach(rule => {
|
|
78
|
+
const transformUids = getTransformUidsFactory(rule);
|
|
79
|
+
rule = transformUids(rule, self.environmentsUidMap, self.localesUidMap, self.entriesUidMap);
|
|
80
|
+
});
|
|
81
|
+
// rules.branch is required to create custom roles.
|
|
82
|
+
const branchRuleExists = customRole.rules.find(rule => rule.module === 'branch');
|
|
83
|
+
if (!branchRuleExists) {
|
|
84
|
+
customRole.rules.push({
|
|
85
|
+
module: 'branch',
|
|
86
|
+
branches: ['main'],
|
|
87
|
+
acl: { read: true }
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const role = await this.client.stack({ api_key: config.target_stack, management_token: config.management_token })
|
|
91
|
+
.role().create({ role: customRole });
|
|
92
|
+
|
|
93
|
+
self.customRolesUidMapper[uid] = role;
|
|
94
|
+
helper.writeFile(customRolesUidMapperPath, self.customRolesUidMapper);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
self.fails.push(customRole);
|
|
97
|
+
if (error && error.errors && error.errors.name) {
|
|
98
|
+
addlogs(config, chalk.red(`custom-role: ${customRole.name} already exists`), 'error');
|
|
99
|
+
} else {
|
|
100
|
+
addlogs(config, chalk.red(`custom-role: ${customRole.name} failed`), 'error');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
addlogs(config, chalk.green('Custom-roles have been imported successfully!'), 'success');
|
|
105
|
+
} catch (error) {
|
|
106
|
+
helper.writeFile(customRolesFailsPath, self.fails);
|
|
107
|
+
addlogs(config, chalk.red('Custom-roles import failed'), 'error');
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const getTransformUidsFactory = (rule) => {
|
|
113
|
+
if (rule.module === 'environment') {
|
|
114
|
+
return environmentUidTransformer;
|
|
115
|
+
} else if (rule.module === 'locale') {
|
|
116
|
+
return localeUidTransformer;
|
|
117
|
+
} else if (rule.module === 'entry') {
|
|
118
|
+
return entryUidTransformer;
|
|
119
|
+
} else {
|
|
120
|
+
return noopTransformer;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const environmentUidTransformer = (rule, environmentsUidMap) => {
|
|
125
|
+
rule.environments = rule.environments.map(env => environmentsUidMap[env]);
|
|
126
|
+
return rule;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const localeUidTransformer = (rule, environmentsUidMap, localesUidMap) => {
|
|
130
|
+
rule.locales = rule.locales.map(locale => localesUidMap[locale]);
|
|
131
|
+
return rule;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const entryUidTransformer = (rule, environmentsUidMap, localesUidMap, entriesUidMap) => {
|
|
135
|
+
rule.entries = rule.entries.map(entry => entriesUidMap[entry]);
|
|
136
|
+
return rule;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const noopTransformer = (rule) => {
|
|
140
|
+
return rule;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const getLocalesUidMap = async (client, config, sourceLocales) => {
|
|
144
|
+
const { items } = await client.stack({ api_key: config.target_stack, management_token: config.management_token }).locale().query().find();
|
|
145
|
+
const [targetLocalesMap, sourceLocalesMap] = [{}, {}];
|
|
146
|
+
|
|
147
|
+
items.forEach(locale => {
|
|
148
|
+
targetLocalesMap[locale.code] = locale.uid;
|
|
149
|
+
});
|
|
150
|
+
for (const key in sourceLocales) {
|
|
151
|
+
sourceLocalesMap[sourceLocales[key].code] = key;
|
|
152
|
+
}
|
|
153
|
+
const localesUidMap = {};
|
|
154
|
+
for (const key in sourceLocalesMap) {
|
|
155
|
+
localesUidMap[sourceLocalesMap[key]] = targetLocalesMap[key];
|
|
156
|
+
}
|
|
157
|
+
return localesUidMap;
|
|
158
|
+
}
|
|
159
|
+
module.exports = new ImportCustomRoles();
|
|
@@ -10,16 +10,18 @@ const _ = require('lodash');
|
|
|
10
10
|
const mkdirp = require('mkdirp');
|
|
11
11
|
const chalk = require('chalk');
|
|
12
12
|
|
|
13
|
+
const util = require('../util');
|
|
13
14
|
const helper = require('../util/fs');
|
|
14
15
|
const { addlogs } = require('../util/log');
|
|
15
|
-
const lookupReplaceAssets = require('../util/lookupReplaceAssets');
|
|
16
|
-
const lookupReplaceEntries = require('../util/lookupReplaceEntries');
|
|
17
16
|
const suppress = require('../util/supress-mandatory-fields');
|
|
18
|
-
const extension_suppress = require('../util/extensionsUidReplace');
|
|
19
|
-
const util = require('../util');
|
|
20
|
-
let config = util.getConfig();
|
|
21
17
|
const stack = require('../util/contentstack-management-sdk');
|
|
18
|
+
const extension_suppress = require('../util/extensionsUidReplace');
|
|
19
|
+
const lookupReplaceAssets = require('../util/lookupReplaceAssets');
|
|
20
|
+
const lookupReplaceEntries = require('../util/lookupReplaceEntries');
|
|
21
|
+
const { getInstalledExtensions } = require('../util/marketplace-app-helper')
|
|
22
|
+
|
|
22
23
|
let client;
|
|
24
|
+
let config = util.getConfig();
|
|
23
25
|
|
|
24
26
|
let reqConcurrency = config.concurrency;
|
|
25
27
|
let eConfig = config.modules.entries;
|
|
@@ -56,6 +58,7 @@ function importEntries() {
|
|
|
56
58
|
|
|
57
59
|
createdEntriesWOUidPath = path.join(entryMapperPath, 'created-entries-wo-uid.json');
|
|
58
60
|
failedWOPath = path.join(entryMapperPath, 'failedWO.json');
|
|
61
|
+
|
|
59
62
|
// Object of Schemas, referred to by their content type uid
|
|
60
63
|
this.ctSchemas = {};
|
|
61
64
|
// Array of content type uids, that have reference fields
|
|
@@ -76,6 +79,8 @@ function importEntries() {
|
|
|
76
79
|
this.success = [];
|
|
77
80
|
// Entries that failed to get created OR updated
|
|
78
81
|
this.fails = [];
|
|
82
|
+
// List of installed extensions to replace uid
|
|
83
|
+
this.installedExtensions = []
|
|
79
84
|
|
|
80
85
|
let files = fs.readdirSync(ctPath);
|
|
81
86
|
this.environment = helper.readFile(environmentPath);
|
|
@@ -108,6 +113,16 @@ importEntries.prototype = {
|
|
|
108
113
|
masterLanguage = config.master_locale;
|
|
109
114
|
addlogs(config, 'Migrating entries', 'success');
|
|
110
115
|
let languages = helper.readFile(lPath);
|
|
116
|
+
const appMapperFolderPath = path.join(config.data, 'mapper', 'marketplace_apps');
|
|
117
|
+
|
|
118
|
+
if (fs.existsSync(path.join(appMapperFolderPath, 'marketplace-apps.json'))) {
|
|
119
|
+
self.installedExtensions = helper.readFile(path.join(appMapperFolderPath, 'marketplace-apps.json')) || {};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (_.isEmpty(self.installedExtensions)) {
|
|
123
|
+
self.installedExtensions = await getInstalledExtensions(config)
|
|
124
|
+
}
|
|
125
|
+
|
|
111
126
|
return new Promise(function (resolve, reject) {
|
|
112
127
|
let langs = [masterLanguage.code];
|
|
113
128
|
for (let i in languages) {
|
|
@@ -248,6 +263,7 @@ importEntries.prototype = {
|
|
|
248
263
|
mappedAssetUids,
|
|
249
264
|
mappedAssetUrls,
|
|
250
265
|
eLangFolderPath,
|
|
266
|
+
self.installedExtensions
|
|
251
267
|
);
|
|
252
268
|
}
|
|
253
269
|
}
|
|
@@ -694,7 +710,7 @@ importEntries.prototype = {
|
|
|
694
710
|
// it should be spelled as suppressFields
|
|
695
711
|
addlogs(config, chalk.white('Suppressing content type fields...'), 'success');
|
|
696
712
|
let self = this;
|
|
697
|
-
return new Promise(function (resolve, reject) {
|
|
713
|
+
return new Promise(async function (resolve, reject) {
|
|
698
714
|
let modifiedSchemas = [];
|
|
699
715
|
let suppressedSchemas = [];
|
|
700
716
|
|
|
@@ -750,7 +766,7 @@ importEntries.prototype = {
|
|
|
750
766
|
}
|
|
751
767
|
|
|
752
768
|
// Replace extensions with new UID
|
|
753
|
-
extension_suppress(contentTypeSchema.schema, config.preserveStackVersion);
|
|
769
|
+
extension_suppress(contentTypeSchema.schema, config.preserveStackVersion, self.installedExtensions);
|
|
754
770
|
}
|
|
755
771
|
}
|
|
756
772
|
|
|
@@ -834,7 +850,8 @@ importEntries.prototype = {
|
|
|
834
850
|
});
|
|
835
851
|
},
|
|
836
852
|
unSuppressFields: function () {
|
|
837
|
-
|
|
853
|
+
let self = this;
|
|
854
|
+
return new Promise(async function (resolve, reject) {
|
|
838
855
|
let modifiedSchemas = helper.readFile(modifiedSchemaPath);
|
|
839
856
|
let modifiedSchemasUids = [];
|
|
840
857
|
let updatedExtensionUidsSchemas = [];
|
|
@@ -844,7 +861,8 @@ importEntries.prototype = {
|
|
|
844
861
|
if (_contentTypeSchema.field_rules) {
|
|
845
862
|
delete _contentTypeSchema.field_rules;
|
|
846
863
|
}
|
|
847
|
-
|
|
864
|
+
|
|
865
|
+
extension_suppress(_contentTypeSchema.schema, config.preserveStackVersion, self.installedExtensions);
|
|
848
866
|
updatedExtensionUidsSchemas.push(_contentTypeSchema);
|
|
849
867
|
}
|
|
850
868
|
}
|
|
@@ -1314,7 +1332,9 @@ importEntries.prototype = {
|
|
|
1314
1332
|
|
|
1315
1333
|
if (entryRefs.length > 0) {
|
|
1316
1334
|
entryRefs.forEach((entryRef) => {
|
|
1317
|
-
entry[entryRef.uid]
|
|
1335
|
+
if (!_.isEmpty(entry[entryRef.uid]) && entry[entryRef.uid].children) {
|
|
1336
|
+
entry[entryRef.uid].children.splice(entryRef.index, 0, entryRef.value);
|
|
1337
|
+
}
|
|
1318
1338
|
});
|
|
1319
1339
|
}
|
|
1320
1340
|
}
|
|
@@ -1447,7 +1467,7 @@ importEntries.prototype = {
|
|
|
1447
1467
|
}
|
|
1448
1468
|
|
|
1449
1469
|
return jsonRteChild;
|
|
1450
|
-
}
|
|
1470
|
+
}
|
|
1451
1471
|
};
|
|
1452
1472
|
|
|
1453
1473
|
module.exports = new importEntries();
|
|
@@ -9,13 +9,14 @@ let fs = require('fs');
|
|
|
9
9
|
let path = require('path');
|
|
10
10
|
let Promise = require('bluebird');
|
|
11
11
|
let chalk = require('chalk');
|
|
12
|
-
const {isEmpty} = require('lodash');
|
|
12
|
+
const { isEmpty } = require('lodash');
|
|
13
13
|
|
|
14
14
|
let helper = require('../util/fs');
|
|
15
15
|
let { addlogs } = require('../util/log');
|
|
16
16
|
let extension_supress = require('../util/extensionsUidReplace');
|
|
17
17
|
let removeReferenceFields = require('../util/removeReferenceFields');
|
|
18
18
|
const stack = require('../util/contentstack-management-sdk');
|
|
19
|
+
const { getInstalledExtensions } = require('../util/marketplace-app-helper');
|
|
19
20
|
|
|
20
21
|
let config = require('../../config/default');
|
|
21
22
|
let reqConcurrency = config.concurrency;
|
|
@@ -39,10 +40,11 @@ function importGlobalFields() {
|
|
|
39
40
|
headers: config.headers,
|
|
40
41
|
method: 'POST',
|
|
41
42
|
};
|
|
43
|
+
this.installedExtensions = [];
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
importGlobalFields.prototype = {
|
|
45
|
-
start: function (credential) {
|
|
47
|
+
start: async function (credential) {
|
|
46
48
|
addlogs(config, chalk.white('Migrating global-fields'), 'success');
|
|
47
49
|
let self = this;
|
|
48
50
|
config = credential;
|
|
@@ -53,6 +55,8 @@ importGlobalFields.prototype = {
|
|
|
53
55
|
globalFieldsPending = path.resolve(config.data, 'mapper', 'global_fields', 'pending_global_fields.js');
|
|
54
56
|
globalfieldsFailsPath = path.resolve(config.data, 'mapper', 'global_fields', 'fails.json');
|
|
55
57
|
self.globalfields = helper.readFile(path.resolve(globalfieldsFolderPath, globalfieldsConfig.fileName));
|
|
58
|
+
const appMapperFolderPath = path.join(config.data, 'mapper', 'marketplace_apps');
|
|
59
|
+
|
|
56
60
|
if (fs.existsSync(globalfieldsUidMapperPath)) {
|
|
57
61
|
self.snipUidMapper = helper.readFile(globalfieldsUidMapperPath);
|
|
58
62
|
self.snipUidMapper = this.snipUidMapper || {};
|
|
@@ -61,6 +65,15 @@ importGlobalFields.prototype = {
|
|
|
61
65
|
if (!fs.existsSync(globalfieldsMapperPath)) {
|
|
62
66
|
mkdirp.sync(globalfieldsMapperPath);
|
|
63
67
|
}
|
|
68
|
+
|
|
69
|
+
if (fs.existsSync(path.join(appMapperFolderPath, 'marketplace-apps.json'))) {
|
|
70
|
+
self.installedExtensions = helper.readFile(path.join(appMapperFolderPath, 'marketplace-apps.json')) || {};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (isEmpty(self.installedExtensions)) {
|
|
74
|
+
self.installedExtensions = await getInstalledExtensions(config);
|
|
75
|
+
}
|
|
76
|
+
|
|
64
77
|
client = stack.Client(config);
|
|
65
78
|
return new Promise(function (resolve, reject) {
|
|
66
79
|
if (self.globalfields === undefined || isEmpty(self.globalfields)) {
|
|
@@ -76,7 +89,7 @@ importGlobalFields.prototype = {
|
|
|
76
89
|
supressed: false,
|
|
77
90
|
};
|
|
78
91
|
let snip = self.globalfields[snipUid];
|
|
79
|
-
extension_supress(snip.schema);
|
|
92
|
+
extension_supress(snip.schema, config.preserveStackVersion, self.installedExtensions);
|
|
80
93
|
removeReferenceFields(snip.schema, flag);
|
|
81
94
|
|
|
82
95
|
if (flag.supressed) {
|
|
@@ -46,6 +46,7 @@ importLanguages.prototype = {
|
|
|
46
46
|
langFailsPath = path.resolve(config.data, 'mapper', 'languages', 'fails.json');
|
|
47
47
|
mkdirp.sync(langMapperPath);
|
|
48
48
|
self.languages = helper.readFile(path.resolve(langFolderPath, langConfig.fileName));
|
|
49
|
+
|
|
49
50
|
if (fs.existsSync(langUidMapperPath)) {
|
|
50
51
|
self.langUidMapper = helper.readFile(langUidMapperPath);
|
|
51
52
|
self.langUidMapper = self.langUidMapper || {};
|