@contentstack/cli-cm-import 1.1.0 → 1.2.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 +4 -3
- package/oclif.manifest.json +1 -1
- package/package.json +8 -7
- package/src/app.js +90 -106
- package/src/commands/cm/stacks/import.js +8 -1
- package/src/config/default.js +9 -4
- package/src/lib/import/assets.js +291 -296
- package/src/lib/import/content-types.js +171 -246
- package/src/lib/import/custom-roles.js +110 -93
- package/src/lib/import/entries.js +216 -174
- package/src/lib/import/environments.js +40 -50
- package/src/lib/import/extensions.js +35 -41
- package/src/lib/import/global-fields.js +56 -68
- package/src/lib/import/labels.js +62 -61
- package/src/lib/import/locales.js +61 -64
- package/src/lib/import/marketplace-apps.js +293 -290
- package/src/lib/import/webhooks.js +45 -51
- package/src/lib/import/workflows.js +72 -62
- package/src/lib/util/extensionsUidReplace.js +9 -9
- package/src/lib/util/fs.js +91 -12
- package/src/lib/util/index.js +39 -3
- package/src/lib/util/log.js +7 -5
- package/src/lib/util/login.js +2 -1
- package/src/lib/util/lookupReplaceAssets.js +22 -10
- package/src/lib/util/lookupReplaceEntries.js +60 -60
- package/src/lib/util/marketplace-app-helper.js +25 -6
|
@@ -4,108 +4,122 @@ const mkdirp = require('mkdirp');
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const chalk = require('chalk');
|
|
7
|
+
const { merge } = require('lodash');
|
|
7
8
|
|
|
8
9
|
const helper = require('../util/fs');
|
|
9
10
|
const { addlogs } = require('../util/log');
|
|
10
|
-
const
|
|
11
|
+
const { formatError } = require('../util');
|
|
11
12
|
let config = require('../../config/default');
|
|
13
|
+
const stack = require('../util/contentstack-management-sdk');
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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) || {};
|
|
15
|
+
module.exports = class ImportCustomRoles {
|
|
16
|
+
fails = [];
|
|
17
|
+
client = null;
|
|
18
|
+
labelUids = [];
|
|
19
|
+
customRolesUidMapper = {};
|
|
20
|
+
customRolesConfig = config.modules.customRoles;
|
|
21
|
+
|
|
22
|
+
constructor(credentialConfig) {
|
|
23
|
+
this.config = merge(config, credentialConfig);
|
|
24
|
+
this.client = stack.Client(this.config);
|
|
31
25
|
}
|
|
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
26
|
|
|
59
|
-
|
|
27
|
+
async start() {
|
|
28
|
+
const self = this;
|
|
29
|
+
addlogs(this.config, chalk.white('Migrating custom-roles'), 'success');
|
|
30
|
+
|
|
31
|
+
let customRolesFolderPath = path.resolve(this.config.data, this.customRolesConfig.dirName);
|
|
32
|
+
let customRolesMapperPath = path.resolve(this.config.data, 'mapper', 'custom-roles');
|
|
33
|
+
let entriesUidMapperFolderPath = path.resolve(this.config.data, 'mapper', 'entries');
|
|
34
|
+
let customRolesFailsPath = path.resolve(this.config.data, 'custom-roles', 'fails.json');
|
|
35
|
+
let environmentsUidMapperFolderPath = path.resolve(this.config.data, 'mapper', 'environments');
|
|
36
|
+
let customRolesUidMapperPath = path.resolve(this.config.data, 'mapper', 'custom-roles', 'uid-mapping.json');
|
|
37
|
+
let customRolesLocalesFilePath = path.resolve(
|
|
38
|
+
customRolesFolderPath,
|
|
39
|
+
this.customRolesConfig.customRolesLocalesFileName,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
self.customRoles = helper.readFileSync(path.resolve(customRolesFolderPath, this.customRolesConfig.fileName));
|
|
44
|
+
self.customRolesLocales = helper.readFileSync(customRolesLocalesFilePath);
|
|
45
|
+
// Mapper file paths.
|
|
46
|
+
|
|
47
|
+
if (fs.existsSync(customRolesMapperPath)) {
|
|
48
|
+
this.customRolesUidMapper = helper.readFileSync(customRolesUidMapperPath) || {};
|
|
49
|
+
}
|
|
60
50
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
51
|
+
mkdirp.sync(customRolesMapperPath);
|
|
52
|
+
|
|
53
|
+
if (!self.customRoles) {
|
|
54
|
+
addlogs(self.config, chalk.white('No custom-roles found'), 'error');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
self.customRolesUids = Object.keys(self.customRoles);
|
|
67
58
|
|
|
68
|
-
|
|
69
|
-
const customRole = self.customRoles[uid];
|
|
59
|
+
self.localesUidMap = await getLocalesUidMap(self.client, self.config, self.customRolesLocales);
|
|
70
60
|
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
61
|
+
if (fs.existsSync(environmentsUidMapperFolderPath)) {
|
|
62
|
+
self.environmentsUidMap = helper.readFileSync(
|
|
63
|
+
path.resolve(environmentsUidMapperFolderPath, 'uid-mapping.json'),
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (fs.existsSync(entriesUidMapperFolderPath)) {
|
|
67
|
+
self.entriesUidMap = helper.readFileSync(path.resolve(entriesUidMapperFolderPath, 'uid-mapping.json'));
|
|
74
68
|
}
|
|
75
69
|
|
|
76
|
-
|
|
77
|
-
customRole
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
branches: ['main'],
|
|
87
|
-
acl: { read: true }
|
|
88
|
-
});
|
|
70
|
+
for (const uid of self.customRolesUids) {
|
|
71
|
+
const customRole = self.customRoles[uid];
|
|
72
|
+
|
|
73
|
+
if (uid in self.customRolesUidMapper) {
|
|
74
|
+
addlogs(
|
|
75
|
+
self.config,
|
|
76
|
+
chalk.white(`The custom-role ${customRole.name} already exists. Skipping it to avoid duplicates!`),
|
|
77
|
+
'success',
|
|
78
|
+
);
|
|
79
|
+
continue;
|
|
89
80
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
customRole.rules.forEach((rule) => {
|
|
84
|
+
const transformUids = getTransformUidsFactory(rule);
|
|
85
|
+
rule = transformUids(rule, self.environmentsUidMap, self.localesUidMap, self.entriesUidMap);
|
|
86
|
+
});
|
|
87
|
+
// rules.branch is required to create custom roles.
|
|
88
|
+
const branchRuleExists = customRole.rules.find((rule) => rule.module === 'branch');
|
|
89
|
+
if (!branchRuleExists) {
|
|
90
|
+
customRole.rules.push({
|
|
91
|
+
module: 'branch',
|
|
92
|
+
branches: ['main'],
|
|
93
|
+
acl: { read: true },
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const role = await self.client
|
|
97
|
+
.stack({ api_key: self.config.target_stack, management_token: self.config.management_token })
|
|
98
|
+
.role()
|
|
99
|
+
.create({ role: customRole });
|
|
100
|
+
|
|
101
|
+
self.customRolesUidMapper[uid] = role;
|
|
102
|
+
helper.writeFileSync(customRolesUidMapperPath, self.customRolesUidMapper);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
self.fails.push(customRole);
|
|
105
|
+
|
|
106
|
+
if (error && error.errors && error.errors.name) {
|
|
107
|
+
addlogs(self.config, chalk.red(`custom-role: ${customRole.name} already exists`), 'error');
|
|
108
|
+
} else {
|
|
109
|
+
addlogs(self.config, chalk.red(`custom-role: ${customRole.name} failed`), 'error');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
addlogs(self.config, formatError(error), 'error');
|
|
101
113
|
}
|
|
102
114
|
}
|
|
115
|
+
addlogs(self.config, chalk.green('Custom-roles have been imported successfully!'), 'success');
|
|
116
|
+
} catch (error) {
|
|
117
|
+
helper.writeFileSync(customRolesFailsPath, self.fails);
|
|
118
|
+
addlogs(self.config, chalk.red('Custom-roles import failed'), 'error');
|
|
119
|
+
addlogs(self.config, formatError(error), 'error');
|
|
120
|
+
|
|
121
|
+
throw error;
|
|
103
122
|
}
|
|
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
123
|
}
|
|
110
124
|
};
|
|
111
125
|
|
|
@@ -122,17 +136,17 @@ const getTransformUidsFactory = (rule) => {
|
|
|
122
136
|
};
|
|
123
137
|
|
|
124
138
|
const environmentUidTransformer = (rule, environmentsUidMap) => {
|
|
125
|
-
rule.environments = rule.environments.map(env => environmentsUidMap[env]);
|
|
139
|
+
rule.environments = rule.environments.map((env) => environmentsUidMap[env]);
|
|
126
140
|
return rule;
|
|
127
141
|
};
|
|
128
142
|
|
|
129
143
|
const localeUidTransformer = (rule, environmentsUidMap, localesUidMap) => {
|
|
130
|
-
rule.locales = rule.locales.map(locale => localesUidMap[locale]);
|
|
144
|
+
rule.locales = rule.locales.map((locale) => localesUidMap[locale]);
|
|
131
145
|
return rule;
|
|
132
146
|
};
|
|
133
147
|
|
|
134
148
|
const entryUidTransformer = (rule, environmentsUidMap, localesUidMap, entriesUidMap) => {
|
|
135
|
-
rule.entries = rule.entries.map(entry => entriesUidMap[entry]);
|
|
149
|
+
rule.entries = rule.entries.map((entry) => entriesUidMap[entry]);
|
|
136
150
|
return rule;
|
|
137
151
|
};
|
|
138
152
|
|
|
@@ -141,10 +155,14 @@ const noopTransformer = (rule) => {
|
|
|
141
155
|
};
|
|
142
156
|
|
|
143
157
|
const getLocalesUidMap = async (client, config, sourceLocales) => {
|
|
144
|
-
const { items } = await client
|
|
158
|
+
const { items } = await client
|
|
159
|
+
.stack({ api_key: config.target_stack, management_token: config.management_token })
|
|
160
|
+
.locale()
|
|
161
|
+
.query()
|
|
162
|
+
.find();
|
|
145
163
|
const [targetLocalesMap, sourceLocalesMap] = [{}, {}];
|
|
146
164
|
|
|
147
|
-
items.forEach(locale => {
|
|
165
|
+
items.forEach((locale) => {
|
|
148
166
|
targetLocalesMap[locale.code] = locale.uid;
|
|
149
167
|
});
|
|
150
168
|
for (const key in sourceLocales) {
|
|
@@ -155,5 +173,4 @@ const getLocalesUidMap = async (client, config, sourceLocales) => {
|
|
|
155
173
|
localesUidMap[sourceLocalesMap[key]] = targetLocalesMap[key];
|
|
156
174
|
}
|
|
157
175
|
return localesUidMap;
|
|
158
|
-
}
|
|
159
|
-
module.exports = new ImportCustomRoles();
|
|
176
|
+
};
|