@contentstack/cli-cm-import 1.7.1 → 1.8.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 +1 -1
- package/lib/config/index.js +2 -0
- package/lib/import/module-importer.js +15 -0
- package/lib/import/modules/base-class.d.ts +1 -1
- package/lib/import/modules/base-class.js +31 -1
- package/lib/import/modules/content-types.js +1 -1
- package/lib/import/modules/entries.d.ts +93 -0
- package/lib/import/modules/entries.js +536 -0
- package/lib/import/modules/marketplace-apps.d.ts +5 -2
- package/lib/import/modules/marketplace-apps.js +21 -16
- package/lib/import/modules/workflows.d.ts +41 -0
- package/lib/import/modules/workflows.js +209 -0
- package/lib/import/modules-js/custom-roles.js +1 -1
- package/lib/import/modules-js/entries.js +13 -7
- package/lib/import/modules-js/environments.js +1 -1
- package/lib/import/modules-js/extensions.js +1 -1
- package/lib/import/modules-js/global-fields.js +2 -4
- package/lib/import/modules-js/marketplace-apps.d.ts +6 -4
- package/lib/import/modules-js/marketplace-apps.js +19 -15
- package/lib/import/modules-js/workflows.js +2 -2
- package/lib/types/default-config.d.ts +1 -0
- package/lib/utils/asset-helper.d.ts +1 -1
- package/lib/utils/backup-handler.js +10 -1
- package/lib/utils/entries-helper.d.ts +4 -1
- package/lib/utils/entries-helper.js +322 -2
- package/lib/utils/file-helper.d.ts +1 -0
- package/lib/utils/file-helper.js +5 -1
- package/lib/utils/import-config-handler.js +1 -1
- package/lib/utils/index.d.ts +2 -2
- package/lib/utils/index.js +4 -1
- package/oclif.manifest.json +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import BaseClass, { ApiOptions } from './base-class';
|
|
2
|
+
import { ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ImportWorkflows extends BaseClass {
|
|
4
|
+
private mapperDirPath;
|
|
5
|
+
private workflowsFolderPath;
|
|
6
|
+
private workflowUidMapperPath;
|
|
7
|
+
private createdWorkflowsPath;
|
|
8
|
+
private failedWorkflowsPath;
|
|
9
|
+
private workflowsConfig;
|
|
10
|
+
private workflows;
|
|
11
|
+
private workflowUidMapper;
|
|
12
|
+
private createdWorkflows;
|
|
13
|
+
private failedWebhooks;
|
|
14
|
+
private roleNameMap;
|
|
15
|
+
constructor({ importConfig, stackAPIClient }: ModuleClassParams);
|
|
16
|
+
/**
|
|
17
|
+
* @method start
|
|
18
|
+
* @returns {Promise<void>} Promise<void>
|
|
19
|
+
*/
|
|
20
|
+
start(): Promise<void>;
|
|
21
|
+
getRoles(): Promise<void>;
|
|
22
|
+
importWorkflows(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* @method serializeWorkflows
|
|
25
|
+
* @param {ApiOptions} apiOptions ApiOptions
|
|
26
|
+
* @returns {ApiOptions} ApiOptions
|
|
27
|
+
*/
|
|
28
|
+
serializeWorkflows(apiOptions: ApiOptions): ApiOptions;
|
|
29
|
+
createCustomRoleIfNotExists(workflow: Record<string, any>): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* @method serializeCustomRoles
|
|
32
|
+
* @param {ApiOptions} apiOptions ApiOptions
|
|
33
|
+
* @returns {ApiOptions} ApiOptions
|
|
34
|
+
*/
|
|
35
|
+
serializeCustomRoles(apiOptions: ApiOptions): ApiOptions;
|
|
36
|
+
updateRoleData(params: {
|
|
37
|
+
workflowUid: string;
|
|
38
|
+
stageIndex: number;
|
|
39
|
+
roleData: any;
|
|
40
|
+
}): void;
|
|
41
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
5
|
+
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
6
|
+
const values_1 = tslib_1.__importDefault(require("lodash/values"));
|
|
7
|
+
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
8
|
+
const findIndex_1 = tslib_1.__importDefault(require("lodash/findIndex"));
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
11
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
12
|
+
const utils_1 = require("../../utils");
|
|
13
|
+
class ImportWorkflows extends base_class_1.default {
|
|
14
|
+
constructor({ importConfig, stackAPIClient }) {
|
|
15
|
+
super({ importConfig, stackAPIClient });
|
|
16
|
+
this.workflowsConfig = config_1.default.modules.workflows;
|
|
17
|
+
this.mapperDirPath = (0, node_path_1.join)(this.importConfig.backupDir, 'mapper', 'workflows');
|
|
18
|
+
this.workflowsFolderPath = (0, node_path_1.join)(this.importConfig.backupDir, this.workflowsConfig.dirName);
|
|
19
|
+
this.workflowUidMapperPath = (0, node_path_1.join)(this.mapperDirPath, 'uid-mapping.json');
|
|
20
|
+
this.createdWorkflowsPath = (0, node_path_1.join)(this.mapperDirPath, 'success.json');
|
|
21
|
+
this.failedWorkflowsPath = (0, node_path_1.join)(this.mapperDirPath, 'fails.json');
|
|
22
|
+
this.workflows = {};
|
|
23
|
+
this.failedWebhooks = [];
|
|
24
|
+
this.createdWorkflows = [];
|
|
25
|
+
this.workflowUidMapper = {};
|
|
26
|
+
this.roleNameMap = {};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @method start
|
|
30
|
+
* @returns {Promise<void>} Promise<void>
|
|
31
|
+
*/
|
|
32
|
+
async start() {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
(0, utils_1.log)(this.importConfig, 'Migrating workflows', 'info');
|
|
35
|
+
//Step1 check folder exists or not
|
|
36
|
+
if (utils_1.fileHelper.fileExistsSync(this.workflowsFolderPath)) {
|
|
37
|
+
this.workflows = utils_1.fsUtil.readFile((0, node_path_1.join)(this.workflowsFolderPath, this.workflowsConfig.fileName), true);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
(0, utils_1.log)(this.importConfig, `No such file or directory - '${this.workflowsFolderPath}'`, 'error');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
//create workflows in mapper directory
|
|
44
|
+
await utils_1.fsUtil.makeDirectory(this.mapperDirPath);
|
|
45
|
+
this.workflowUidMapper = utils_1.fileHelper.fileExistsSync(this.workflowUidMapperPath)
|
|
46
|
+
? utils_1.fsUtil.readFile((0, node_path_1.join)(this.workflowUidMapperPath), true)
|
|
47
|
+
: {};
|
|
48
|
+
if (this.workflows === undefined || (0, isEmpty_1.default)(this.workflows)) {
|
|
49
|
+
(0, utils_1.log)(this.importConfig, 'No Workflow Found', 'info');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
//fetch all roles
|
|
53
|
+
await this.getRoles();
|
|
54
|
+
await this.importWorkflows();
|
|
55
|
+
if ((_a = this.createdWorkflows) === null || _a === void 0 ? void 0 : _a.length) {
|
|
56
|
+
utils_1.fsUtil.writeFile(this.createdWorkflowsPath, this.createdWorkflows);
|
|
57
|
+
}
|
|
58
|
+
if ((_b = this.failedWebhooks) === null || _b === void 0 ? void 0 : _b.length) {
|
|
59
|
+
utils_1.fsUtil.writeFile(this.failedWorkflowsPath, this.failedWebhooks);
|
|
60
|
+
}
|
|
61
|
+
(0, utils_1.log)(this.importConfig, 'Workflows have been imported successfully!', 'success');
|
|
62
|
+
}
|
|
63
|
+
async getRoles() {
|
|
64
|
+
const roles = await this.stack
|
|
65
|
+
.role()
|
|
66
|
+
.fetchAll()
|
|
67
|
+
.then((data) => data)
|
|
68
|
+
.catch((err) => (0, utils_1.log)(this.importConfig, `Failed to fetch roles. ${(0, utils_1.formatError)(err)}`, 'error'));
|
|
69
|
+
for (const role of roles === null || roles === void 0 ? void 0 : roles.items) {
|
|
70
|
+
this.roleNameMap[role.name] = role.uid;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async importWorkflows() {
|
|
74
|
+
const apiContent = (0, values_1.default)(this.workflows);
|
|
75
|
+
//check and create custom roles if not exists
|
|
76
|
+
for (const workflow of (0, values_1.default)(this.workflows)) {
|
|
77
|
+
if (!this.workflowUidMapper.hasOwnProperty(workflow.uid)) {
|
|
78
|
+
await this.createCustomRoleIfNotExists(workflow);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
|
|
82
|
+
this.createdWorkflows.push(response);
|
|
83
|
+
this.workflowUidMapper[uid] = response.uid;
|
|
84
|
+
(0, utils_1.log)(this.importConfig, `Workflow '${name}' imported successfully`, 'success');
|
|
85
|
+
utils_1.fsUtil.writeFile(this.workflowUidMapperPath, this.workflowUidMapper);
|
|
86
|
+
};
|
|
87
|
+
const onReject = ({ error, apiData }) => {
|
|
88
|
+
var _a;
|
|
89
|
+
const err = (error === null || error === void 0 ? void 0 : error.message) ? JSON.parse(error.message) : error;
|
|
90
|
+
const { name } = apiData;
|
|
91
|
+
if ((_a = err === null || err === void 0 ? void 0 : err.errors) === null || _a === void 0 ? void 0 : _a.name) {
|
|
92
|
+
(0, utils_1.log)(this.importConfig, `Workflow '${name}' already exists`, 'info');
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.failedWebhooks.push(apiData);
|
|
96
|
+
if (error.errors['workflow_stages.0.users']) {
|
|
97
|
+
(0, utils_1.log)(this.importConfig, "Failed to import Workflows as you've specified certain roles in the Stage transition and access rules section. We currently don't import roles to the stack.", 'error');
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
(0, utils_1.log)(this.importConfig, `Workflow '${name}' failed to be import. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
await this.makeConcurrentCall({
|
|
105
|
+
apiContent,
|
|
106
|
+
processName: 'create workflows',
|
|
107
|
+
apiParams: {
|
|
108
|
+
serializeData: this.serializeWorkflows.bind(this),
|
|
109
|
+
reject: onReject,
|
|
110
|
+
resolve: onSuccess,
|
|
111
|
+
entity: 'create-workflows',
|
|
112
|
+
includeParamOnCompletion: true,
|
|
113
|
+
},
|
|
114
|
+
concurrencyLimit: config_1.default.fetchConcurrency || 1,
|
|
115
|
+
}, undefined, false);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @method serializeWorkflows
|
|
119
|
+
* @param {ApiOptions} apiOptions ApiOptions
|
|
120
|
+
* @returns {ApiOptions} ApiOptions
|
|
121
|
+
*/
|
|
122
|
+
serializeWorkflows(apiOptions) {
|
|
123
|
+
let { apiData: workflow } = apiOptions;
|
|
124
|
+
if (this.workflowUidMapper.hasOwnProperty(workflow.uid)) {
|
|
125
|
+
(0, utils_1.log)(this.importConfig, `Workflow '${workflow.name}' already exists. Skipping it to avoid duplicates!`, 'info');
|
|
126
|
+
apiOptions.entity = undefined;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
if (workflow.admin_users !== undefined) {
|
|
130
|
+
(0, utils_1.log)(this.importConfig, chalk_1.default.yellow('We are skipping import of `Workflow superuser(s)` from workflow'), 'info');
|
|
131
|
+
delete workflow.admin_users;
|
|
132
|
+
}
|
|
133
|
+
// One branch is required to create workflow.
|
|
134
|
+
if (!workflow.branches) {
|
|
135
|
+
workflow.branches = ['main'];
|
|
136
|
+
}
|
|
137
|
+
apiOptions.apiData = workflow;
|
|
138
|
+
}
|
|
139
|
+
return apiOptions;
|
|
140
|
+
}
|
|
141
|
+
async createCustomRoleIfNotExists(workflow) {
|
|
142
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
143
|
+
const onSuccess = ({ response, apiData, additionalInfo: { workflowUid, stageIndex } }) => {
|
|
144
|
+
const { name } = apiData;
|
|
145
|
+
this.updateRoleData({ workflowUid, stageIndex, roleData: apiData });
|
|
146
|
+
this.roleNameMap[name] = response === null || response === void 0 ? void 0 : response.uid;
|
|
147
|
+
};
|
|
148
|
+
const onReject = ({ error, apiData: { name } = { name: '' } }) => {
|
|
149
|
+
(0, utils_1.log)(this.importConfig, `Failed to create custom roles '${name}'.${(0, utils_1.formatError)(error)}`, 'error');
|
|
150
|
+
};
|
|
151
|
+
const workflowStages = workflow.workflow_stages;
|
|
152
|
+
let stageIndex = 0;
|
|
153
|
+
for (const stage of workflowStages) {
|
|
154
|
+
if (((_c = (_b = (_a = stage === null || stage === void 0 ? void 0 : stage.SYS_ACL) === null || _a === void 0 ? void 0 : _a.users) === null || _b === void 0 ? void 0 : _b.uids) === null || _c === void 0 ? void 0 : _c.length) && ((_e = (_d = stage === null || stage === void 0 ? void 0 : stage.SYS_ACL) === null || _d === void 0 ? void 0 : _d.users) === null || _e === void 0 ? void 0 : _e.uids[0]) !== '$all') {
|
|
155
|
+
stage.SYS_ACL.users.uids = ['$all'];
|
|
156
|
+
}
|
|
157
|
+
if ((_h = (_g = (_f = stage === null || stage === void 0 ? void 0 : stage.SYS_ACL) === null || _f === void 0 ? void 0 : _f.roles) === null || _g === void 0 ? void 0 : _g.uids) === null || _h === void 0 ? void 0 : _h.length) {
|
|
158
|
+
const apiContent = stage.SYS_ACL.roles.uids;
|
|
159
|
+
await this.makeConcurrentCall({
|
|
160
|
+
apiContent,
|
|
161
|
+
processName: 'create custom role',
|
|
162
|
+
apiParams: {
|
|
163
|
+
serializeData: this.serializeCustomRoles.bind(this),
|
|
164
|
+
reject: onReject,
|
|
165
|
+
resolve: onSuccess,
|
|
166
|
+
entity: 'create-custom-role',
|
|
167
|
+
includeParamOnCompletion: true,
|
|
168
|
+
additionalInfo: { workflowUid: workflow.uid, stageIndex },
|
|
169
|
+
},
|
|
170
|
+
concurrencyLimit: config_1.default.fetchConcurrency || 1,
|
|
171
|
+
}, undefined, false);
|
|
172
|
+
}
|
|
173
|
+
stageIndex++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* @method serializeCustomRoles
|
|
178
|
+
* @param {ApiOptions} apiOptions ApiOptions
|
|
179
|
+
* @returns {ApiOptions} ApiOptions
|
|
180
|
+
*/
|
|
181
|
+
serializeCustomRoles(apiOptions) {
|
|
182
|
+
let { apiData: roleData, additionalInfo: { workflowUid, stageIndex }, } = apiOptions;
|
|
183
|
+
if (!this.roleNameMap[roleData.name]) {
|
|
184
|
+
// rules.branch is required to create custom roles.
|
|
185
|
+
const branchRuleExists = (0, find_1.default)(roleData.rules, (rule) => rule.module === 'branch');
|
|
186
|
+
if (!branchRuleExists) {
|
|
187
|
+
roleData.rules.push({
|
|
188
|
+
module: 'branch',
|
|
189
|
+
branches: ['main'],
|
|
190
|
+
acl: { read: true },
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
apiOptions = roleData;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
apiOptions.entity = undefined;
|
|
197
|
+
this.updateRoleData({ workflowUid, stageIndex, roleData });
|
|
198
|
+
}
|
|
199
|
+
return apiOptions;
|
|
200
|
+
}
|
|
201
|
+
updateRoleData(params) {
|
|
202
|
+
const { workflowUid, stageIndex, roleData } = params;
|
|
203
|
+
const workflowStage = this.workflows[workflowUid].workflow_stages;
|
|
204
|
+
const roles = workflowStage[stageIndex].SYS_ACL.roles.uids;
|
|
205
|
+
const index = (0, findIndex_1.default)(roles, ['uid', roleData.uid]);
|
|
206
|
+
roles[index >= 0 ? index : roles.length] = this.roleNameMap[roleData.name];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.default = ImportWorkflows;
|
|
@@ -74,7 +74,7 @@ module.exports = class ImportCustomRoles {
|
|
|
74
74
|
catch (error) {
|
|
75
75
|
self.fails.push(customRole);
|
|
76
76
|
if (((error && error.errors && error.errors.name) || '').includes('is not a unique.')) {
|
|
77
|
-
log(self.config, `custom-role ${customRole.name} already exists`, 'info');
|
|
77
|
+
log(self.config, `custom-role '${customRole.name}' already exists`, 'info');
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
80
80
|
if (!(error && error.errors && error.errors.name)) {
|
|
@@ -324,12 +324,12 @@ module.exports = class ImportEntries {
|
|
|
324
324
|
}
|
|
325
325
|
})
|
|
326
326
|
.catch((error) => {
|
|
327
|
-
if (error.hasOwnProperty('
|
|
327
|
+
if (error.hasOwnProperty('errorCode') && error.errorCode === 119) {
|
|
328
328
|
if (error.errors.title) {
|
|
329
329
|
log(this.config, 'Entry ' + eUid + ' already exist, skip to avoid creating a duplicate entry', 'error');
|
|
330
330
|
}
|
|
331
331
|
else {
|
|
332
|
-
log(this.config, `Failed to create an entry ${eUid} ${formatError(error)}`, 'error');
|
|
332
|
+
log(this.config, `Failed to create an entry '${eUid}' ${formatError(error)} Title of the failed entry: '${entries[eUid].title}'`, 'error');
|
|
333
333
|
}
|
|
334
334
|
self.createdEntriesWOUid.push({
|
|
335
335
|
content_type: ctUid,
|
|
@@ -342,7 +342,7 @@ module.exports = class ImportEntries {
|
|
|
342
342
|
}
|
|
343
343
|
// TODO: if status code: 422, check the reason
|
|
344
344
|
// 429 for rate limit
|
|
345
|
-
log(this.config, `Failed to create an entry ${eUid} ${formatError(error)}`, 'error');
|
|
345
|
+
log(this.config, `Failed to create an entry '${eUid}' ${formatError(error)}. Title of the failed entry: '${entries[eUid].title}'`, 'error');
|
|
346
346
|
self.fails.push({
|
|
347
347
|
content_type: ctUid,
|
|
348
348
|
locale: lang,
|
|
@@ -394,7 +394,13 @@ module.exports = class ImportEntries {
|
|
|
394
394
|
return resolve();
|
|
395
395
|
})
|
|
396
396
|
.catch((error) => {
|
|
397
|
-
|
|
397
|
+
var _a, _b;
|
|
398
|
+
let title = (_b = JSON.parse(((_a = error === null || error === void 0 ? void 0 : error.request) === null || _a === void 0 ? void 0 : _a.data) || "{}").entry) === null || _b === void 0 ? void 0 : _b.title;
|
|
399
|
+
addlogs(this.config, chalk.red("Failed to create entries in '" +
|
|
400
|
+
lang +
|
|
401
|
+
"' language. " +
|
|
402
|
+
'Title of the failed entry: ' +
|
|
403
|
+
`'${title || ""}'`), 'error');
|
|
398
404
|
return reject(error);
|
|
399
405
|
});
|
|
400
406
|
});
|
|
@@ -473,7 +479,7 @@ module.exports = class ImportEntries {
|
|
|
473
479
|
return _entry;
|
|
474
480
|
}
|
|
475
481
|
catch (error) {
|
|
476
|
-
addlogs(this.config, `Failed to update the entry ${uid} references while reposting ${formatError(error)}`, 'error');
|
|
482
|
+
addlogs(this.config, `Failed to update the entry '${uid}' references while reposting ${formatError(error)}`, 'error');
|
|
477
483
|
}
|
|
478
484
|
});
|
|
479
485
|
log(this.config, 'Starting the reposting process for entries');
|
|
@@ -544,7 +550,7 @@ module.exports = class ImportEntries {
|
|
|
544
550
|
})
|
|
545
551
|
.catch((error) => {
|
|
546
552
|
// error while updating entries with references
|
|
547
|
-
addlogs(this.config, `Failed re-post entries of content type ${ctUid} locale ${lang}`, 'error');
|
|
553
|
+
addlogs(this.config, `Failed re-post entries of content type '${ctUid}' locale '${lang}'`, 'error');
|
|
548
554
|
addlogs(this.config, formatError(error), 'error');
|
|
549
555
|
// throw error;
|
|
550
556
|
});
|
|
@@ -620,7 +626,7 @@ module.exports = class ImportEntries {
|
|
|
620
626
|
})
|
|
621
627
|
.catch((_error) => {
|
|
622
628
|
addlogs(this.config, formatError(_error), 'error');
|
|
623
|
-
reject(`Failed suppress content type ${schema.uid} reference fields`);
|
|
629
|
+
reject(`Failed suppress content type '${schema.uid}' reference fields`);
|
|
624
630
|
});
|
|
625
631
|
// update 5 content types at a time
|
|
626
632
|
}, {
|
|
@@ -67,7 +67,7 @@ module.exports = class ImportEnvironments {
|
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
69
|
// the environment has already been created
|
|
70
|
-
log(config, `The environment ${env.name} already exists. Skipping it to avoid duplicates!`, 'success');
|
|
70
|
+
log(config, `The environment '${env.name}' already exists. Skipping it to avoid duplicates!`, 'success');
|
|
71
71
|
}
|
|
72
72
|
}, { concurrency: self.fetchConcurrency })
|
|
73
73
|
.then(function () {
|
|
@@ -59,7 +59,7 @@ module.exports = class ImportExtensions {
|
|
|
59
59
|
log(self.config, `Extension '${ext.title}' already exists`, 'error');
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
|
-
log(self.config, "Extension: '" + ext.title + "' failed to
|
|
62
|
+
log(self.config, "Extension: '" + ext.title + "' failed to import" + formatError(error), 'error');
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
}
|
|
@@ -71,13 +71,14 @@ module.exports = class ImportGlobalFields {
|
|
|
71
71
|
log(self.config, chalk.green('Global field ' + global_field_uid + ' created successfully'), 'success');
|
|
72
72
|
})
|
|
73
73
|
.catch(function (err) {
|
|
74
|
+
console.log;
|
|
74
75
|
let error = JSON.parse(err.message);
|
|
75
76
|
if (error.errors.title) {
|
|
76
77
|
// eslint-disable-next-line no-undef
|
|
77
78
|
log(self.config, `Globalfield '${snip.uid} already exists'`, 'error');
|
|
78
79
|
}
|
|
79
80
|
else {
|
|
80
|
-
log(self.config, chalk.red(`Globalfield failed to import ${formatError(error)}`), 'error');
|
|
81
|
+
log(self.config, chalk.red(`Globalfield '${snip.title}' failed to import. ${formatError(error)}`), 'error');
|
|
81
82
|
}
|
|
82
83
|
self.fails.push(snip);
|
|
83
84
|
});
|
|
@@ -96,10 +97,7 @@ module.exports = class ImportGlobalFields {
|
|
|
96
97
|
return resolve();
|
|
97
98
|
})
|
|
98
99
|
.catch(function (err) {
|
|
99
|
-
// error while importing globalfields
|
|
100
100
|
let error = JSON.parse(err);
|
|
101
|
-
// error while importing globalfields
|
|
102
|
-
log(self.config, err, 'error');
|
|
103
101
|
fileHelper.writeFileSync(globalfieldsFailsPath, self.fails);
|
|
104
102
|
log(self.config, `Globalfields import failed. ${formatError(err)}`, 'error');
|
|
105
103
|
return reject(error);
|
|
@@ -3,7 +3,7 @@ declare class ImportMarketplaceApps {
|
|
|
3
3
|
constructor(importConfig: any, stackAPIClient: any);
|
|
4
4
|
client: any;
|
|
5
5
|
httpClient: any;
|
|
6
|
-
|
|
6
|
+
appOriginalName: any;
|
|
7
7
|
appUidMapping: {};
|
|
8
8
|
appNameMapping: {};
|
|
9
9
|
marketplaceApps: any[];
|
|
@@ -42,10 +42,12 @@ declare class ImportMarketplaceApps {
|
|
|
42
42
|
getAppName(name: any, appSuffix?: number): any;
|
|
43
43
|
/**
|
|
44
44
|
* @method installApps
|
|
45
|
-
*
|
|
46
|
-
* @
|
|
45
|
+
*
|
|
46
|
+
* @param {Record<string, any>} app
|
|
47
|
+
* @param {Record<string, any>[]} installedApps
|
|
48
|
+
* @returns {Promise<void>}
|
|
47
49
|
*/
|
|
48
|
-
installApps(app:
|
|
50
|
+
installApps(app: Record<string, any>, installedApps: Record<string, any>[]): Promise<void>;
|
|
49
51
|
makeRedirectUrlCall(response: any, appName: any): Promise<void>;
|
|
50
52
|
ifAppAlreadyExist(app: any, currentStackApp: any): Promise<any>;
|
|
51
53
|
confirmToCloseProcess(installation: any): Promise<void>;
|
|
@@ -62,7 +62,7 @@ module.exports = class ImportMarketplaceApps {
|
|
|
62
62
|
.catch((error) => {
|
|
63
63
|
console.log(error);
|
|
64
64
|
});
|
|
65
|
-
if (tempStackData
|
|
65
|
+
if (tempStackData === null || tempStackData === void 0 ? void 0 : tempStackData.org_uid) {
|
|
66
66
|
this.config.org_uid = tempStackData.org_uid;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -131,25 +131,26 @@ module.exports = class ImportMarketplaceApps {
|
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
async generateUidMapper() {
|
|
134
|
+
var _a, _b;
|
|
134
135
|
const listOfNewMeta = [];
|
|
135
136
|
const listOfOldMeta = [];
|
|
136
|
-
const
|
|
137
|
-
const allInstalledApps = await getAllStackSpecificApps(this.developerHubBaseUrl, this.httpClient, this.config);
|
|
137
|
+
const extensionUidMap = {};
|
|
138
|
+
const allInstalledApps = (await getAllStackSpecificApps(this.developerHubBaseUrl, this.httpClient, this.config)) || [];
|
|
138
139
|
for (const app of this.marketplaceApps) {
|
|
139
|
-
listOfOldMeta.push(..._.map(app
|
|
140
|
+
listOfOldMeta.push(..._.map((_a = app === null || app === void 0 ? void 0 : app.ui_location) === null || _a === void 0 ? void 0 : _a.locations, 'meta').flat());
|
|
140
141
|
}
|
|
141
142
|
for (const app of allInstalledApps) {
|
|
142
|
-
listOfNewMeta.push(..._.map(app
|
|
143
|
+
listOfNewMeta.push(..._.map((_b = app === null || app === void 0 ? void 0 : app.ui_location) === null || _b === void 0 ? void 0 : _b.locations, 'meta').flat());
|
|
143
144
|
}
|
|
144
145
|
for (const { extension_uid, name, path, uid, data_type } of _.filter(listOfOldMeta, 'name')) {
|
|
145
146
|
const meta = _.find(listOfNewMeta, { name, path }) ||
|
|
146
147
|
_.find(listOfNewMeta, { name: this.appNameMapping[name], path }) ||
|
|
147
148
|
_.find(listOfNewMeta, { name, uid, data_type });
|
|
148
149
|
if (meta) {
|
|
149
|
-
|
|
150
|
+
extensionUidMap[extension_uid] = meta.extension_uid;
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
|
-
return
|
|
153
|
+
return extensionUidMap;
|
|
153
154
|
}
|
|
154
155
|
/**
|
|
155
156
|
* @method handleAllPrivateAppsCreationProcess
|
|
@@ -166,10 +167,10 @@ module.exports = class ImportMarketplaceApps {
|
|
|
166
167
|
for (let app of privateApps) {
|
|
167
168
|
// NOTE keys can be passed to install new app in the developer hub
|
|
168
169
|
app.manifest = _.pick(app.manifest, ['uid', 'name', 'description', 'icon', 'target_type', 'webhook', 'oauth']);
|
|
169
|
-
this.
|
|
170
|
+
this.appOriginalName = app.manifest.name;
|
|
170
171
|
await this.createPrivateApps(Object.assign({ oauth: app.oauth, webhook: app.webhook, ui_location: app.ui_location }, app.manifest));
|
|
171
172
|
}
|
|
172
|
-
this.
|
|
173
|
+
this.appOriginalName = undefined;
|
|
173
174
|
}
|
|
174
175
|
async getConfirmationToCreateApps(privateApps) {
|
|
175
176
|
if (!this.config.forceStopMarketplaceAppsPrompt) {
|
|
@@ -184,7 +185,8 @@ module.exports = class ImportMarketplaceApps {
|
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
async createPrivateApps(app, uidCleaned = false, appSuffix = 1) {
|
|
187
|
-
|
|
188
|
+
var _a;
|
|
189
|
+
let locations = (_a = app === null || app === void 0 ? void 0 : app.ui_location) === null || _a === void 0 ? void 0 : _a.locations;
|
|
188
190
|
if (!uidCleaned && !_.isEmpty(locations)) {
|
|
189
191
|
app.ui_location.locations = this.updateManifestUILocations(locations, 'uid');
|
|
190
192
|
}
|
|
@@ -223,7 +225,7 @@ module.exports = class ImportMarketplaceApps {
|
|
|
223
225
|
// NOTE new app installation
|
|
224
226
|
log(this.config, `${response.name} app created successfully.!`, 'success');
|
|
225
227
|
this.appUidMapping[app.uid] = response.uid;
|
|
226
|
-
this.appNameMapping[this.
|
|
228
|
+
this.appNameMapping[this.appOriginalName] = response.name;
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
async handleNameConflict(app, appSuffix) {
|
|
@@ -254,8 +256,8 @@ module.exports = class ImportMarketplaceApps {
|
|
|
254
256
|
location.meta = _.map(location.meta, (meta) => {
|
|
255
257
|
if (meta.name) {
|
|
256
258
|
const name = `${_.first(_.split(meta.name, '◈'))}◈${appSuffix}`;
|
|
257
|
-
if (!this.appNameMapping[this.
|
|
258
|
-
this.appNameMapping[this.
|
|
259
|
+
if (!this.appNameMapping[this.appOriginalName]) {
|
|
260
|
+
this.appNameMapping[this.appOriginalName] = name;
|
|
259
261
|
}
|
|
260
262
|
meta.name = name;
|
|
261
263
|
}
|
|
@@ -274,8 +276,10 @@ module.exports = class ImportMarketplaceApps {
|
|
|
274
276
|
}
|
|
275
277
|
/**
|
|
276
278
|
* @method installApps
|
|
277
|
-
*
|
|
278
|
-
* @
|
|
279
|
+
*
|
|
280
|
+
* @param {Record<string, any>} app
|
|
281
|
+
* @param {Record<string, any>[]} installedApps
|
|
282
|
+
* @returns {Promise<void>}
|
|
279
283
|
*/
|
|
280
284
|
async installApps(app, installedApps) {
|
|
281
285
|
let updateParam;
|
|
@@ -101,13 +101,13 @@ module.exports = class importWorkflows {
|
|
|
101
101
|
.catch(function (error) {
|
|
102
102
|
self.fails.push(workflow);
|
|
103
103
|
if (error.errors.name) {
|
|
104
|
-
log(self.config, `workflow ${workflow.name} already exist`, 'error');
|
|
104
|
+
log(self.config, `workflow '${workflow.name}' already exist`, 'error');
|
|
105
105
|
}
|
|
106
106
|
else if (error.errors['workflow_stages.0.users']) {
|
|
107
107
|
log(self.config, "Failed to import Workflows as you've specified certain roles in the Stage transition and access rules section. We currently don't import roles to the stack.", 'error');
|
|
108
108
|
}
|
|
109
109
|
else {
|
|
110
|
-
log(self.config, `
|
|
110
|
+
log(self.config, `Workflow '${workflow.name}' failed.`, 'error');
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
113
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import Bluebird from 'bluebird';
|
|
2
2
|
import { ImportConfig } from 'src/types';
|
|
3
3
|
export declare const uploadAssetHelper: (config: ImportConfig, req: any, fsPath: string, RETRY?: number) => Bluebird<unknown>;
|
|
4
|
-
export declare const lookupAssets: (data:
|
|
4
|
+
export declare const lookupAssets: (data: Record<string, any>, mappedAssetUids: Record<string, any>, mappedAssetUrls: Record<string, any>, assetUidMapperPath: string, installedExtensions: Record<string, any>[]) => any;
|
|
@@ -3,12 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const path = tslib_1.__importStar(require("path"));
|
|
5
5
|
const ncp_1 = tslib_1.__importDefault(require("ncp"));
|
|
6
|
+
const index_1 = require("./index");
|
|
6
7
|
function setupBackupDir(importConfig) {
|
|
7
8
|
return new Promise(async (resolve, reject) => {
|
|
8
9
|
if (importConfig.hasOwnProperty('useBackedupDir')) {
|
|
9
10
|
return resolve(importConfig.useBackedupDir);
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
+
//NOTE: If the backup folder's directory is provided, create it at that location; otherwise, the default path (working directory).
|
|
13
|
+
let backupDirPath = path.join(process.cwd(), '_backup_' + Math.floor(Math.random() * 1000));
|
|
14
|
+
if (importConfig.createBackupDir) {
|
|
15
|
+
if (index_1.fileHelper.fileExistsSync(importConfig.createBackupDir)) {
|
|
16
|
+
index_1.fileHelper.removeDirSync(importConfig.createBackupDir);
|
|
17
|
+
}
|
|
18
|
+
index_1.fileHelper.makeDirectory(importConfig.createBackupDir);
|
|
19
|
+
backupDirPath = importConfig.createBackupDir;
|
|
20
|
+
}
|
|
12
21
|
const limit = importConfig.backupConcurrency || 16;
|
|
13
22
|
if (path.isAbsolute(importConfig.contentDir)) {
|
|
14
23
|
return (0, ncp_1.default)(importConfig.contentDir, backupDirPath, { limit }, (error) => {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Entries lookup
|
|
3
3
|
*/
|
|
4
|
-
export declare const lookupEntries: (data: any, mappedUids: string
|
|
4
|
+
export declare const lookupEntries: (data: any, mappedUids: Record<string, any>, uidMapperPath: string) => any;
|
|
5
|
+
export declare const removeUidsFromJsonRteFields: (entry: Record<string, any>, ctSchema: Record<string, any>[]) => Record<string, any>;
|
|
6
|
+
export declare const removeEntryRefsFromJSONRTE: (entry: Record<string, any>, ctSchema: Record<string, any>[]) => Record<string, any>;
|
|
7
|
+
export declare const restoreJsonRteEntryRefs: (entry: Record<string, any>, sourceStackEntry: any, ctSchema: any, { mappedAssetUids, mappedAssetUrls }: any) => Record<string, any>;
|