@contentstack/cli-cm-import 1.8.1 → 1.8.3
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/import/modules/base-class.d.ts +2 -2
- package/lib/import/modules/content-types.js +5 -1
- package/lib/import/modules/entries.js +8 -2
- package/lib/import/modules/workflows.d.ts +1 -0
- package/lib/import/modules/workflows.js +43 -5
- package/lib/import/modules-js/content-types.d.ts +1 -0
- package/lib/import/modules-js/content-types.js +28 -1
- package/lib/import/modules-js/global-fields.js +0 -1
- package/lib/import/modules-js/workflows.d.ts +1 -0
- package/lib/import/modules-js/workflows.js +37 -4
- package/lib/utils/content-type-helper.d.ts +1 -0
- package/lib/utils/content-type-helper.js +26 -1
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
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.8.
|
|
50
|
+
@contentstack/cli-cm-import/1.8.3 linux-x64 node-v18.17.1
|
|
51
51
|
$ csdx --help [COMMAND]
|
|
52
52
|
USAGE
|
|
53
53
|
$ csdx COMMAND
|
|
@@ -9,8 +9,8 @@ export type ApiOptions = {
|
|
|
9
9
|
url?: string;
|
|
10
10
|
entity: ApiModuleType;
|
|
11
11
|
apiData?: Record<any, any> | any;
|
|
12
|
-
resolve: (value: any) => void;
|
|
13
|
-
reject: (error: any) => void;
|
|
12
|
+
resolve: (value: any) => Promise<void> | void;
|
|
13
|
+
reject: (error: any) => Promise<void> | void;
|
|
14
14
|
additionalInfo?: Record<any, any>;
|
|
15
15
|
includeParamOnCompletion?: boolean;
|
|
16
16
|
serializeData?: (input: ApiOptions) => any;
|
|
@@ -11,6 +11,7 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
11
11
|
const lodash_1 = require("lodash");
|
|
12
12
|
const utils_1 = require("../../utils");
|
|
13
13
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
14
|
+
const content_type_helper_1 = require("../../utils/content-type-helper");
|
|
14
15
|
class ContentTypesImport extends base_class_1.default {
|
|
15
16
|
constructor({ importConfig, stackAPIClient }) {
|
|
16
17
|
super({ importConfig, stackAPIClient });
|
|
@@ -134,8 +135,11 @@ class ContentTypesImport extends base_class_1.default {
|
|
|
134
135
|
serializeUpdateCTs(apiOptions) {
|
|
135
136
|
const { apiData: contentType } = apiOptions;
|
|
136
137
|
if (contentType.field_rules) {
|
|
138
|
+
contentType.field_rules = (0, content_type_helper_1.updateFieldRules)(contentType);
|
|
139
|
+
if (!contentType.field_rules.length) {
|
|
140
|
+
delete contentType.field_rules;
|
|
141
|
+
}
|
|
137
142
|
this.fieldRules.push(contentType.uid);
|
|
138
|
-
delete contentType.field_rules;
|
|
139
143
|
}
|
|
140
144
|
(0, utils_1.lookupExtension)(this.importConfig, contentType.schema, this.importConfig.preserveStackVersion, this.installedExtensions);
|
|
141
145
|
const contentTypePayload = this.stack.contentType(contentType.uid);
|
|
@@ -415,13 +415,19 @@ class EntriesImport extends base_class_1.default {
|
|
|
415
415
|
return;
|
|
416
416
|
}
|
|
417
417
|
for (let cTUid of cTsWithFieldRules) {
|
|
418
|
-
const
|
|
418
|
+
const cTs = utils_1.fsUtil.readFile(path.join(this.cTsPath, 'schema.json'));
|
|
419
|
+
const contentType = (0, lodash_1.find)(cTs, { uid: cTUid });
|
|
419
420
|
if (contentType.field_rules) {
|
|
420
421
|
let fieldRuleLength = contentType.field_rules.length;
|
|
422
|
+
const fieldDatatypeMap = {};
|
|
423
|
+
for (let i = 0; i < contentType.schema.length; i++) {
|
|
424
|
+
const field = contentType.schema[i].uid;
|
|
425
|
+
fieldDatatypeMap[field] = contentType.schema[i].data_type;
|
|
426
|
+
}
|
|
421
427
|
for (let k = 0; k < fieldRuleLength; k++) {
|
|
422
428
|
let fieldRuleConditionLength = contentType.field_rules[k].conditions.length;
|
|
423
429
|
for (let i = 0; i < fieldRuleConditionLength; i++) {
|
|
424
|
-
if (contentType.field_rules[k].conditions[i].operand_field === 'reference') {
|
|
430
|
+
if (fieldDatatypeMap[contentType.field_rules[k].conditions[i].operand_field] === 'reference') {
|
|
425
431
|
let fieldRulesValue = contentType.field_rules[k].conditions[i].value;
|
|
426
432
|
let fieldRulesArray = fieldRulesValue.split('.');
|
|
427
433
|
let updatedValue = [];
|
|
@@ -20,6 +20,7 @@ export default class ImportWorkflows extends BaseClass {
|
|
|
20
20
|
start(): Promise<void>;
|
|
21
21
|
getRoles(): Promise<void>;
|
|
22
22
|
importWorkflows(): Promise<void>;
|
|
23
|
+
updateNextAvailableStagesUid(workflow: Record<string, any>, newWorkflowStages: Record<string, any>[], oldWorkflowStages: Record<string, any>[]): Promise<import("@contentstack/management/types/stack/workflow").Workflow>;
|
|
23
24
|
/**
|
|
24
25
|
* @method serializeWorkflows
|
|
25
26
|
* @param {ApiOptions} apiOptions ApiOptions
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
5
|
-
const
|
|
6
|
-
const values_1 = tslib_1.__importDefault(require("lodash/values"));
|
|
5
|
+
const map_1 = tslib_1.__importDefault(require("lodash/map"));
|
|
7
6
|
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
8
|
-
const findIndex_1 = tslib_1.__importDefault(require("lodash/findIndex"));
|
|
9
7
|
const node_path_1 = require("node:path");
|
|
8
|
+
const values_1 = tslib_1.__importDefault(require("lodash/values"));
|
|
9
|
+
const filter_1 = tslib_1.__importDefault(require("lodash/filter"));
|
|
10
|
+
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
11
|
+
const cloneDeep_1 = tslib_1.__importDefault(require("lodash/cloneDeep"));
|
|
12
|
+
const findIndex_1 = tslib_1.__importDefault(require("lodash/findIndex"));
|
|
10
13
|
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
11
14
|
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
12
15
|
const utils_1 = require("../../utils");
|
|
@@ -66,19 +69,30 @@ class ImportWorkflows extends base_class_1.default {
|
|
|
66
69
|
.fetchAll()
|
|
67
70
|
.then((data) => data)
|
|
68
71
|
.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) {
|
|
72
|
+
for (const role of (roles === null || roles === void 0 ? void 0 : roles.items) || []) {
|
|
70
73
|
this.roleNameMap[role.name] = role.uid;
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
async importWorkflows() {
|
|
74
77
|
const apiContent = (0, values_1.default)(this.workflows);
|
|
78
|
+
const oldWorkflows = (0, cloneDeep_1.default)((0, values_1.default)(this.workflows));
|
|
75
79
|
//check and create custom roles if not exists
|
|
76
80
|
for (const workflow of (0, values_1.default)(this.workflows)) {
|
|
77
81
|
if (!this.workflowUidMapper.hasOwnProperty(workflow.uid)) {
|
|
78
82
|
await this.createCustomRoleIfNotExists(workflow);
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
|
-
const onSuccess = ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
|
|
85
|
+
const onSuccess = async ({ response, apiData: { uid, name } = { uid: null, name: '' } }) => {
|
|
86
|
+
var _a;
|
|
87
|
+
const oldWorkflowStages = (_a = (0, find_1.default)(oldWorkflows, { uid })) === null || _a === void 0 ? void 0 : _a.workflow_stages;
|
|
88
|
+
if (!(0, isEmpty_1.default)((0, filter_1.default)(oldWorkflowStages, ({ next_available_stages }) => !(0, isEmpty_1.default)(next_available_stages)))) {
|
|
89
|
+
let updateRresponse = await this.updateNextAvailableStagesUid(response, response.workflow_stages, oldWorkflowStages).catch((error) => {
|
|
90
|
+
(0, utils_1.log)(this.importConfig, `Workflow '${name}' update failed.`, 'error');
|
|
91
|
+
(0, utils_1.log)(this.importConfig, error, 'error');
|
|
92
|
+
});
|
|
93
|
+
if (updateRresponse)
|
|
94
|
+
response = updateRresponse;
|
|
95
|
+
}
|
|
82
96
|
this.createdWorkflows.push(response);
|
|
83
97
|
this.workflowUidMapper[uid] = response.uid;
|
|
84
98
|
(0, utils_1.log)(this.importConfig, `Workflow '${name}' imported successfully`, 'success');
|
|
@@ -114,6 +128,24 @@ class ImportWorkflows extends base_class_1.default {
|
|
|
114
128
|
concurrencyLimit: config_1.default.fetchConcurrency || 1,
|
|
115
129
|
}, undefined, false);
|
|
116
130
|
}
|
|
131
|
+
updateNextAvailableStagesUid(workflow, newWorkflowStages, oldWorkflowStages) {
|
|
132
|
+
newWorkflowStages = (0, map_1.default)(newWorkflowStages, (newStage, index) => {
|
|
133
|
+
const oldStage = oldWorkflowStages[index];
|
|
134
|
+
if (!(0, isEmpty_1.default)(oldStage.next_available_stages)) {
|
|
135
|
+
newStage.next_available_stages = (0, map_1.default)(oldStage.next_available_stages, (stageUid) => {
|
|
136
|
+
var _a, _b;
|
|
137
|
+
if (stageUid === '$all')
|
|
138
|
+
return stageUid;
|
|
139
|
+
const stageName = (_a = (0, find_1.default)(oldWorkflowStages, { uid: stageUid })) === null || _a === void 0 ? void 0 : _a.name;
|
|
140
|
+
return (_b = (0, find_1.default)(newWorkflowStages, { name: stageName })) === null || _b === void 0 ? void 0 : _b.uid;
|
|
141
|
+
}).filter((val) => val);
|
|
142
|
+
}
|
|
143
|
+
return newStage;
|
|
144
|
+
});
|
|
145
|
+
const updateWorkflow = this.stack.workflow(workflow.uid);
|
|
146
|
+
Object.assign(updateWorkflow, { workflow_stages: newWorkflowStages, name: workflow.name });
|
|
147
|
+
return updateWorkflow.update();
|
|
148
|
+
}
|
|
117
149
|
/**
|
|
118
150
|
* @method serializeWorkflows
|
|
119
151
|
* @param {ApiOptions} apiOptions ApiOptions
|
|
@@ -134,6 +166,12 @@ class ImportWorkflows extends base_class_1.default {
|
|
|
134
166
|
if (!workflow.branches) {
|
|
135
167
|
workflow.branches = ['main'];
|
|
136
168
|
}
|
|
169
|
+
for (const stage of workflow.workflow_stages) {
|
|
170
|
+
delete stage.uid;
|
|
171
|
+
if (!(0, isEmpty_1.default)(stage.next_available_stages)) {
|
|
172
|
+
stage.next_available_stages = ['$all'];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
137
175
|
apiOptions.apiData = workflow;
|
|
138
176
|
}
|
|
139
177
|
return apiOptions;
|
|
@@ -130,8 +130,11 @@ class ContentTypesImport {
|
|
|
130
130
|
return;
|
|
131
131
|
const requestObject = cloneDeep(this.requestOptions);
|
|
132
132
|
if (contentType.field_rules) {
|
|
133
|
+
contentType.field_rules = this.updateFieldRules(contentType);
|
|
134
|
+
if (!contentType.field_rules.length) {
|
|
135
|
+
delete contentType.field_rules;
|
|
136
|
+
}
|
|
133
137
|
this.fieldRules.push(contentType.uid);
|
|
134
|
-
delete contentType.field_rules;
|
|
135
138
|
}
|
|
136
139
|
lookupExtension(this.importConfig, contentType.schema, this.importConfig.preserveStackVersion, this.installedExtensions);
|
|
137
140
|
requestObject.json.content_type = contentType;
|
|
@@ -172,5 +175,29 @@ class ContentTypesImport {
|
|
|
172
175
|
this.titleToUIdMap.set(ct.uid, ct.title);
|
|
173
176
|
});
|
|
174
177
|
}
|
|
178
|
+
updateFieldRules(contentType) {
|
|
179
|
+
const fieldDataTypeMap = {};
|
|
180
|
+
for (let i = 0; i < contentType.schema.length; i++) {
|
|
181
|
+
const field = contentType.schema[i];
|
|
182
|
+
fieldDataTypeMap[field.uid] = field.data_type;
|
|
183
|
+
}
|
|
184
|
+
const fieldRules = [...contentType.field_rules];
|
|
185
|
+
let len = fieldRules.length;
|
|
186
|
+
// Looping backwards as we need to delete elements as we move.
|
|
187
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
188
|
+
const conditions = fieldRules[i].conditions;
|
|
189
|
+
let isReference = false;
|
|
190
|
+
for (let j = 0; j < conditions.length; j++) {
|
|
191
|
+
const field = conditions[j].operand_field;
|
|
192
|
+
if (fieldDataTypeMap[field] === 'reference') {
|
|
193
|
+
isReference = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (isReference) {
|
|
197
|
+
fieldRules.splice(i, 1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return fieldRules;
|
|
201
|
+
}
|
|
175
202
|
}
|
|
176
203
|
module.exports = ContentTypesImport;
|
|
@@ -71,7 +71,6 @@ 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;
|
|
75
74
|
let error = JSON.parse(err.message);
|
|
76
75
|
if (error.errors.title) {
|
|
77
76
|
// eslint-disable-next-line no-undef
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
* Copyright (c) 2019 Contentstack LLC
|
|
4
4
|
* MIT Licensed
|
|
5
5
|
*/
|
|
6
|
-
const mkdirp = require('mkdirp');
|
|
7
6
|
const fs = require('fs');
|
|
8
7
|
const path = require('path');
|
|
9
|
-
const Promise = require('bluebird');
|
|
10
8
|
const chalk = require('chalk');
|
|
11
|
-
const
|
|
9
|
+
const mkdirp = require('mkdirp');
|
|
10
|
+
const Promise = require('bluebird');
|
|
11
|
+
const { isEmpty, merge, filter, map, cloneDeep, find } = require('lodash');
|
|
12
12
|
let { default: config } = require('../../config');
|
|
13
13
|
const { fileHelper, log, formatError } = require('../../utils');
|
|
14
14
|
module.exports = class importWorkflows {
|
|
@@ -46,11 +46,16 @@ module.exports = class importWorkflows {
|
|
|
46
46
|
if (!self.workflowUidMapper.hasOwnProperty(workflowUid)) {
|
|
47
47
|
const roleNameMap = {};
|
|
48
48
|
const workflowStages = workflow.workflow_stages;
|
|
49
|
+
const oldWorkflowStages = cloneDeep(workflow.workflow_stages);
|
|
49
50
|
const roles = await self.stackAPIClient.role().fetchAll();
|
|
50
51
|
for (const role of roles.items) {
|
|
51
52
|
roleNameMap[role.name] = role.uid;
|
|
52
53
|
}
|
|
53
54
|
for (const stage of workflowStages) {
|
|
55
|
+
delete stage.uid;
|
|
56
|
+
if (!isEmpty(stage.next_available_stages)) {
|
|
57
|
+
stage.next_available_stages = ['$all'];
|
|
58
|
+
}
|
|
54
59
|
if (stage.SYS_ACL.users.uids.length && stage.SYS_ACL.users.uids[0] !== '$all') {
|
|
55
60
|
stage.SYS_ACL.users.uids = ['$all'];
|
|
56
61
|
}
|
|
@@ -94,7 +99,17 @@ module.exports = class importWorkflows {
|
|
|
94
99
|
return self.stackAPIClient
|
|
95
100
|
.workflow()
|
|
96
101
|
.create({ workflow })
|
|
97
|
-
.then(function (response) {
|
|
102
|
+
.then(async function (response) {
|
|
103
|
+
if (!isEmpty(filter(oldWorkflowStages, ({ next_available_stages }) => !isEmpty(next_available_stages)))) {
|
|
104
|
+
let updateRresponse = await self
|
|
105
|
+
.updateNextAvailableStagesUid(response, response.workflow_stages, oldWorkflowStages)
|
|
106
|
+
.catch((error) => {
|
|
107
|
+
log(self.config, `Workflow '${workflow.name}' update failed.`, 'error');
|
|
108
|
+
log(self.config, error, 'error');
|
|
109
|
+
});
|
|
110
|
+
if (updateRresponse)
|
|
111
|
+
response = updateRresponse;
|
|
112
|
+
}
|
|
98
113
|
self.workflowUidMapper[workflowUid] = response;
|
|
99
114
|
fileHelper.writeFileSync(workflowUidMapperPath, self.workflowUidMapper);
|
|
100
115
|
})
|
|
@@ -129,4 +144,22 @@ module.exports = class importWorkflows {
|
|
|
129
144
|
});
|
|
130
145
|
});
|
|
131
146
|
}
|
|
147
|
+
updateNextAvailableStagesUid(workflow, newWorkflowStages, oldWorkflowStages) {
|
|
148
|
+
newWorkflowStages = map(newWorkflowStages, (newStage, index) => {
|
|
149
|
+
const oldStage = oldWorkflowStages[index];
|
|
150
|
+
if (!isEmpty(oldStage.next_available_stages)) {
|
|
151
|
+
newStage.next_available_stages = map(oldStage.next_available_stages, (stageUid) => {
|
|
152
|
+
var _a, _b;
|
|
153
|
+
if (stageUid === '$all')
|
|
154
|
+
return stageUid;
|
|
155
|
+
const stageName = (_a = find(oldWorkflowStages, { uid: stageUid })) === null || _a === void 0 ? void 0 : _a.name;
|
|
156
|
+
return (_b = find(newWorkflowStages, { name: stageName })) === null || _b === void 0 ? void 0 : _b.uid;
|
|
157
|
+
}).filter((val) => val);
|
|
158
|
+
}
|
|
159
|
+
return newStage;
|
|
160
|
+
});
|
|
161
|
+
const updateWorkflow = this.stackAPIClient.workflow(workflow.uid);
|
|
162
|
+
Object.assign(updateWorkflow, { workflow_stages: newWorkflowStages, name: workflow.name });
|
|
163
|
+
return updateWorkflow.update();
|
|
164
|
+
}
|
|
132
165
|
};
|
|
@@ -49,3 +49,4 @@ export declare const suppressSchemaReference: (schema: any, flag: any) => void;
|
|
|
49
49
|
export declare const removeReferenceFields: (schema: any, flag: {
|
|
50
50
|
supressed: boolean;
|
|
51
51
|
}, stackAPIClient: any) => Promise<boolean | void>;
|
|
52
|
+
export declare const updateFieldRules: (contentType: any) => any[];
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* suppress mandatory fields
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.removeReferenceFields = exports.suppressSchemaReference = exports.schemaTemplate = void 0;
|
|
9
|
+
exports.updateFieldRules = exports.removeReferenceFields = exports.suppressSchemaReference = exports.schemaTemplate = void 0;
|
|
10
10
|
exports.schemaTemplate = {
|
|
11
11
|
content_type: {
|
|
12
12
|
title: 'Seed',
|
|
@@ -150,3 +150,28 @@ const removeReferenceFields = async function (schema, flag = { supressed: false
|
|
|
150
150
|
}
|
|
151
151
|
};
|
|
152
152
|
exports.removeReferenceFields = removeReferenceFields;
|
|
153
|
+
const updateFieldRules = function (contentType) {
|
|
154
|
+
const fieldDataTypeMap = {};
|
|
155
|
+
for (let i = 0; i < contentType.schema.length; i++) {
|
|
156
|
+
const field = contentType.schema[i];
|
|
157
|
+
fieldDataTypeMap[field.uid] = field.data_type;
|
|
158
|
+
}
|
|
159
|
+
const fieldRules = [...contentType.field_rules];
|
|
160
|
+
let len = fieldRules.length;
|
|
161
|
+
// Looping backwards as we need to delete elements as we move.
|
|
162
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
163
|
+
const conditions = fieldRules[i].conditions;
|
|
164
|
+
let isReference = false;
|
|
165
|
+
for (let j = 0; j < conditions.length; j++) {
|
|
166
|
+
const field = conditions[j].operand_field;
|
|
167
|
+
if (fieldDataTypeMap[field] === 'reference') {
|
|
168
|
+
isReference = true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (isReference) {
|
|
172
|
+
fieldRules.splice(i, 1);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return fieldRules;
|
|
176
|
+
};
|
|
177
|
+
exports.updateFieldRules = updateFieldRules;
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-import",
|
|
3
3
|
"description": "Contentstack CLI plugin to import content into stack",
|
|
4
|
-
"version": "1.8.
|
|
4
|
+
"version": "1.8.3",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-command": "~1.2.
|
|
9
|
-
"@contentstack/cli-utilities": "~1.5.
|
|
8
|
+
"@contentstack/cli-command": "~1.2.12",
|
|
9
|
+
"@contentstack/cli-utilities": "~1.5.2",
|
|
10
10
|
"@contentstack/management": "~1.10.0",
|
|
11
11
|
"@oclif/config": "^1.18.3",
|
|
12
12
|
"@oclif/core": "^2.9.3",
|