@contentstack/cli-cm-export 1.7.0 → 1.8.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 +1 -1
- package/lib/config/index.js +4 -0
- package/lib/export/modules/base-class.d.ts +2 -1
- package/lib/export/modules/base-class.js +1 -0
- package/lib/export/modules/entries.d.ts +26 -0
- package/lib/export/modules/entries.js +167 -0
- package/lib/export/modules/locales.js +2 -1
- package/lib/export/modules/stack.d.ts +12 -0
- package/lib/export/modules/stack.js +91 -0
- package/lib/export/modules/webhooks.js +1 -1
- package/lib/export/modules/workflows.d.ts +14 -0
- package/lib/export/modules/workflows.js +81 -0
- package/lib/export/modules-js/entries.js +2 -1
- package/lib/export/modules-js/stack.js +2 -2
- package/lib/types/default-config.d.ts +1 -0
- package/lib/types/export-config.d.ts +1 -0
- package/lib/types/index.d.ts +6 -0
- package/oclif.manifest.json +1 -1
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ $ npm install -g @contentstack/cli-cm-export
|
|
|
48
48
|
$ csdx COMMAND
|
|
49
49
|
running command...
|
|
50
50
|
$ csdx (--version)
|
|
51
|
-
@contentstack/cli-cm-export/1.
|
|
51
|
+
@contentstack/cli-cm-export/1.8.1 linux-x64 node-v18.17.1
|
|
52
52
|
$ csdx --help [COMMAND]
|
|
53
53
|
USAGE
|
|
54
54
|
$ csdx COMMAND
|
package/lib/config/index.js
CHANGED
|
@@ -137,6 +137,7 @@ const config = {
|
|
|
137
137
|
// total no of entries fetched in each content type in a single call
|
|
138
138
|
limit: 100,
|
|
139
139
|
dependencies: ['locales', 'content-types'],
|
|
140
|
+
exportVersions: false,
|
|
140
141
|
},
|
|
141
142
|
extensions: {
|
|
142
143
|
dirName: 'extensions',
|
|
@@ -378,6 +379,9 @@ const config = {
|
|
|
378
379
|
'custom-roles',
|
|
379
380
|
'global-fields',
|
|
380
381
|
'content-types',
|
|
382
|
+
'entries',
|
|
383
|
+
'workflows',
|
|
384
|
+
'stack',
|
|
381
385
|
],
|
|
382
386
|
apis: {
|
|
383
387
|
userSession: '/user-session/',
|
|
@@ -18,11 +18,12 @@ export type EnvType = {
|
|
|
18
18
|
export type CustomPromiseHandlerInput = {
|
|
19
19
|
index: number;
|
|
20
20
|
batchIndex: number;
|
|
21
|
+
element?: Record<string, any>;
|
|
21
22
|
apiParams?: ApiOptions;
|
|
22
23
|
isLastRequest: boolean;
|
|
23
24
|
};
|
|
24
25
|
export type CustomPromiseHandler = (input: CustomPromiseHandlerInput) => Promise<any>;
|
|
25
|
-
export type ApiModuleType = 'stack' | 'asset' | 'assets' | 'entry' | 'entries' | 'content-type' | 'content-types' | 'stacks' | 'download-asset';
|
|
26
|
+
export type ApiModuleType = 'stack' | 'asset' | 'assets' | 'entry' | 'entries' | 'content-type' | 'content-types' | 'stacks' | 'versioned-entries' | 'download-asset';
|
|
26
27
|
export default abstract class BaseClass {
|
|
27
28
|
readonly client: any;
|
|
28
29
|
exportConfig: ExportConfig;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ExportConfig, ModuleClassParams } from '../../types';
|
|
2
|
+
import BaseClass, { ApiOptions } from './base-class';
|
|
3
|
+
export default class EntriesExport extends BaseClass {
|
|
4
|
+
private stackAPIClient;
|
|
5
|
+
exportConfig: ExportConfig;
|
|
6
|
+
private entriesConfig;
|
|
7
|
+
private entriesDirPath;
|
|
8
|
+
private localesFilePath;
|
|
9
|
+
private schemaFilePath;
|
|
10
|
+
private entriesFileHelper;
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
12
|
+
start(): Promise<void>;
|
|
13
|
+
createRequestObjects(locales: Array<Record<string, unknown>>, contentTypes: Array<Record<string, unknown>>): Array<Record<string, any>>;
|
|
14
|
+
getEntries(options: Record<string, any>): Promise<any>;
|
|
15
|
+
fetchEntriesVersions(entries: any, options: {
|
|
16
|
+
locale: string;
|
|
17
|
+
contentType: string;
|
|
18
|
+
versionedEntryPath: string;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
entryVersionHandler({ apiParams, element: entry, }: {
|
|
21
|
+
apiParams: ApiOptions;
|
|
22
|
+
element: Record<string, string>;
|
|
23
|
+
isLastRequest: boolean;
|
|
24
|
+
}): Promise<unknown>;
|
|
25
|
+
getEntryByVersion(options: any, entry: Record<string, any>, entries?: Array<Record<string, any>>): Promise<any[]>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const path = tslib_1.__importStar(require("path"));
|
|
5
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
|
+
const utils_1 = require("../../utils");
|
|
7
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
8
|
+
class EntriesExport extends base_class_1.default {
|
|
9
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
10
|
+
super({ exportConfig, stackAPIClient });
|
|
11
|
+
this.stackAPIClient = stackAPIClient;
|
|
12
|
+
this.exportConfig = exportConfig;
|
|
13
|
+
this.entriesConfig = exportConfig.modules.entries;
|
|
14
|
+
this.entriesDirPath = path.resolve(exportConfig.data, exportConfig.branchName || '', this.entriesConfig.dirName);
|
|
15
|
+
this.localesFilePath = path.resolve(exportConfig.data, exportConfig.branchName || '', exportConfig.modules.locales.dirName, exportConfig.modules.locales.fileName);
|
|
16
|
+
this.schemaFilePath = path.resolve(exportConfig.data, exportConfig.branchName || '', exportConfig.modules.content_types.dirName, 'schema.json');
|
|
17
|
+
}
|
|
18
|
+
async start() {
|
|
19
|
+
var _a;
|
|
20
|
+
try {
|
|
21
|
+
(0, utils_1.log)(this.exportConfig, 'Starting entries export', 'info');
|
|
22
|
+
const locales = utils_1.fsUtil.readFile(this.localesFilePath);
|
|
23
|
+
const contentTypes = utils_1.fsUtil.readFile(this.schemaFilePath);
|
|
24
|
+
if (contentTypes.length === 0) {
|
|
25
|
+
(0, utils_1.log)(this.exportConfig, 'No content types found to export entries', 'info');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const entryRequestOptions = this.createRequestObjects(locales, contentTypes);
|
|
29
|
+
for (let entryRequestOption of entryRequestOptions) {
|
|
30
|
+
(0, utils_1.log)(this.exportConfig, `Starting export of entries of content type - ${entryRequestOption.contentType} locale - ${entryRequestOption.locale}`, 'info');
|
|
31
|
+
await this.getEntries(entryRequestOption);
|
|
32
|
+
(_a = this.entriesFileHelper) === null || _a === void 0 ? void 0 : _a.completeFile(true);
|
|
33
|
+
(0, utils_1.log)(this.exportConfig, `Exported entries of type '${entryRequestOption.contentType}' locale '${entryRequestOption.locale}'`, 'success');
|
|
34
|
+
}
|
|
35
|
+
(0, utils_1.log)(this.exportConfig, 'Entries exported successfully', 'success');
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export entries ${(0, utils_1.formatError)(error)}`, 'error');
|
|
39
|
+
throw new Error('Failed to export entries');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
createRequestObjects(locales, contentTypes) {
|
|
43
|
+
let requestObjects = [];
|
|
44
|
+
contentTypes.forEach((contentType) => {
|
|
45
|
+
if (Object.keys(locales).length !== 0) {
|
|
46
|
+
for (let locale in locales) {
|
|
47
|
+
requestObjects.push({
|
|
48
|
+
contentType: contentType.uid,
|
|
49
|
+
locale: locales[locale].code,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
requestObjects.push({
|
|
54
|
+
contentType: contentType.uid,
|
|
55
|
+
locale: this.exportConfig.master_locale.code,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
return requestObjects;
|
|
59
|
+
}
|
|
60
|
+
async getEntries(options) {
|
|
61
|
+
options.skip = options.skip || 0;
|
|
62
|
+
let requestObject = {
|
|
63
|
+
locale: options.locale,
|
|
64
|
+
skip: options.skip,
|
|
65
|
+
limit: this.entriesConfig.limit,
|
|
66
|
+
include_count: true,
|
|
67
|
+
include_publish_details: true,
|
|
68
|
+
query: {
|
|
69
|
+
locale: options.locale,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
const entriesSearchResponse = await this.stackAPIClient
|
|
73
|
+
.contentType(options.contentType)
|
|
74
|
+
.entry()
|
|
75
|
+
.query(requestObject)
|
|
76
|
+
.find();
|
|
77
|
+
if (Array.isArray(entriesSearchResponse.items) && entriesSearchResponse.items.length > 0) {
|
|
78
|
+
if (options.skip === 0) {
|
|
79
|
+
const entryBasePath = path.join(this.entriesDirPath, options.contentType, options.locale);
|
|
80
|
+
await utils_1.fsUtil.makeDirectory(entryBasePath);
|
|
81
|
+
this.entriesFileHelper = new cli_utilities_1.FsUtility({
|
|
82
|
+
moduleName: 'entries',
|
|
83
|
+
indexFileName: 'index.json',
|
|
84
|
+
basePath: entryBasePath,
|
|
85
|
+
chunkFileSize: this.entriesConfig.chunkFileSize,
|
|
86
|
+
keepMetadata: false,
|
|
87
|
+
omitKeys: this.entriesConfig.invalidKeys,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
this.entriesFileHelper.writeIntoFile(entriesSearchResponse.items, { mapKeyVal: true });
|
|
91
|
+
if (this.entriesConfig.exportVersions) {
|
|
92
|
+
let versionedEntryPath = path.join(this.entriesDirPath, options.contentType, options.locale, 'versions');
|
|
93
|
+
utils_1.fsUtil.makeDirectory(versionedEntryPath);
|
|
94
|
+
await this.fetchEntriesVersions(entriesSearchResponse.items, {
|
|
95
|
+
locale: options.locale,
|
|
96
|
+
contentType: options.contentType,
|
|
97
|
+
versionedEntryPath,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
options.skip += this.entriesConfig.limit || 100;
|
|
101
|
+
if (options.skip >= entriesSearchResponse.count) {
|
|
102
|
+
return Promise.resolve(true);
|
|
103
|
+
}
|
|
104
|
+
return await this.getEntries(options);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async fetchEntriesVersions(entries, options) {
|
|
108
|
+
const onSuccess = ({ response, apiData: entry }) => {
|
|
109
|
+
utils_1.fsUtil.writeFile(path.join(options.versionedEntryPath, `${entry.uid}.json`), response);
|
|
110
|
+
(0, utils_1.log)(this.exportConfig, `Exported versioned entries of type '${options.contentType}' locale '${options.locale}'`, 'success');
|
|
111
|
+
};
|
|
112
|
+
const onReject = ({ error, apiData: { uid } = undefined }) => {
|
|
113
|
+
(0, utils_1.log)(this.exportConfig, `failed to export versions of entry ${uid}`, 'error');
|
|
114
|
+
(0, utils_1.log)(this.exportConfig, (0, utils_1.formatError)(error), 'error');
|
|
115
|
+
};
|
|
116
|
+
return await this.makeConcurrentCall({
|
|
117
|
+
apiBatches: [entries],
|
|
118
|
+
module: 'versioned-entries',
|
|
119
|
+
totalCount: entries.length,
|
|
120
|
+
concurrencyLimit: this.entriesConfig.batchLimit,
|
|
121
|
+
apiParams: {
|
|
122
|
+
module: 'versioned-entries',
|
|
123
|
+
queryParam: options,
|
|
124
|
+
resolve: onSuccess,
|
|
125
|
+
reject: onReject,
|
|
126
|
+
},
|
|
127
|
+
}, this.entryVersionHandler.bind(this));
|
|
128
|
+
}
|
|
129
|
+
async entryVersionHandler({ apiParams, element: entry, }) {
|
|
130
|
+
return new Promise(async (resolve, reject) => {
|
|
131
|
+
return await this.getEntryByVersion(apiParams.queryParam, entry)
|
|
132
|
+
.then((response) => {
|
|
133
|
+
apiParams.resolve({
|
|
134
|
+
response,
|
|
135
|
+
apiData: entry,
|
|
136
|
+
});
|
|
137
|
+
resolve(true);
|
|
138
|
+
})
|
|
139
|
+
.catch((error) => {
|
|
140
|
+
apiParams.reject({
|
|
141
|
+
error,
|
|
142
|
+
apiData: entry,
|
|
143
|
+
});
|
|
144
|
+
reject(true);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async getEntryByVersion(options, entry, entries = []) {
|
|
149
|
+
const queryRequestObject = {
|
|
150
|
+
locale: options.locale,
|
|
151
|
+
except: {
|
|
152
|
+
BASE: this.entriesConfig.invalidKeys,
|
|
153
|
+
},
|
|
154
|
+
version: entry._version,
|
|
155
|
+
};
|
|
156
|
+
const entryResponse = await this.stackAPIClient
|
|
157
|
+
.contentType(options.contentType)
|
|
158
|
+
.entry(entry.uid)
|
|
159
|
+
.fetch(queryRequestObject);
|
|
160
|
+
entries.push(entryResponse);
|
|
161
|
+
if (--entry._version > 0) {
|
|
162
|
+
return await this.getEntryByVersion(options, entry, entries);
|
|
163
|
+
}
|
|
164
|
+
return entries;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.default = EntriesExport;
|
|
@@ -51,12 +51,13 @@ class LocaleExport extends base_class_1.default {
|
|
|
51
51
|
}
|
|
52
52
|
sanitizeAttribs(locales) {
|
|
53
53
|
locales.forEach((locale) => {
|
|
54
|
+
var _a, _b;
|
|
54
55
|
for (let key in locale) {
|
|
55
56
|
if (this.localeConfig.requiredKeys.indexOf(key) === -1) {
|
|
56
57
|
delete locale[key];
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
if (locale.code === this.exportConfig.master_locale.code) {
|
|
60
|
+
if ((locale === null || locale === void 0 ? void 0 : locale.code) === ((_b = (_a = this.exportConfig) === null || _a === void 0 ? void 0 : _a.master_locale) === null || _b === void 0 ? void 0 : _b.code)) {
|
|
60
61
|
this.masterLocale[locale.uid] = locale;
|
|
61
62
|
}
|
|
62
63
|
else {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseClass from './base-class';
|
|
2
|
+
import { ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ExportStack extends BaseClass {
|
|
4
|
+
private stackConfig;
|
|
5
|
+
private stackFolderPath;
|
|
6
|
+
private qs;
|
|
7
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
8
|
+
start(): Promise<void>;
|
|
9
|
+
getStack(): Promise<any>;
|
|
10
|
+
getLocales(skip?: number): Promise<any>;
|
|
11
|
+
exportStack(): Promise<any>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
|
+
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
8
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
class ExportStack extends base_class_1.default {
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
12
|
+
super({ exportConfig, stackAPIClient });
|
|
13
|
+
this.stackConfig = config_1.default.modules.stack;
|
|
14
|
+
this.qs = { include_count: true };
|
|
15
|
+
this.stackFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.stackConfig.dirName);
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
if ((0, cli_utilities_1.isAuthenticated)()) {
|
|
19
|
+
const stackData = await this.getStack();
|
|
20
|
+
if (stackData === null || stackData === void 0 ? void 0 : stackData.org_uid) {
|
|
21
|
+
this.exportConfig.org_uid = stackData.org_uid;
|
|
22
|
+
this.exportConfig.sourceStackName = stackData.name;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!this.exportConfig.preserveStackVersion && !this.exportConfig.hasOwnProperty('master_locale')) {
|
|
26
|
+
//fetch master locale details
|
|
27
|
+
return this.getLocales();
|
|
28
|
+
}
|
|
29
|
+
else if (this.exportConfig.preserveStackVersion) {
|
|
30
|
+
return this.exportStack();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async getStack() {
|
|
34
|
+
const tempAPIClient = await (0, cli_utilities_1.managementSDKClient)({ host: this.exportConfig.host });
|
|
35
|
+
return await tempAPIClient
|
|
36
|
+
.stack({ api_key: this.exportConfig.source_stack })
|
|
37
|
+
.fetch()
|
|
38
|
+
.catch((error) => {
|
|
39
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export stack. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async getLocales(skip = 0) {
|
|
43
|
+
if (skip) {
|
|
44
|
+
this.qs.skip = skip;
|
|
45
|
+
}
|
|
46
|
+
return await this.stack
|
|
47
|
+
.locale()
|
|
48
|
+
.query(this.qs)
|
|
49
|
+
.find()
|
|
50
|
+
.then(async (data) => {
|
|
51
|
+
const { items, count } = data;
|
|
52
|
+
if (items === null || items === void 0 ? void 0 : items.length) {
|
|
53
|
+
skip += this.stackConfig.limit || 100;
|
|
54
|
+
const masterLocalObj = (0, find_1.default)(items, (locale) => {
|
|
55
|
+
if (locale.fallback_locale === null) {
|
|
56
|
+
return locale;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
if (masterLocalObj) {
|
|
60
|
+
return masterLocalObj;
|
|
61
|
+
}
|
|
62
|
+
else if (skip >= count) {
|
|
63
|
+
(0, utils_1.log)(this.exportConfig, 'Master locale not found', 'error');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return await this.getLocales(skip);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
.catch((error) => {
|
|
72
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export locales. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
73
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
async exportStack() {
|
|
77
|
+
(0, utils_1.log)(this.exportConfig, 'Exporting stack details', 'success');
|
|
78
|
+
await utils_1.fsUtil.makeDirectory(this.stackFolderPath);
|
|
79
|
+
return this.stack
|
|
80
|
+
.fetch()
|
|
81
|
+
.then((resp) => {
|
|
82
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.stackFolderPath, this.stackConfig.fileName), resp);
|
|
83
|
+
(0, utils_1.log)(this.exportConfig, 'Exported stack details successfully!', 'success');
|
|
84
|
+
return resp;
|
|
85
|
+
})
|
|
86
|
+
.catch((error) => {
|
|
87
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export stack. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.default = ExportStack;
|
|
@@ -45,7 +45,7 @@ class ExportWebhooks extends base_class_1.default {
|
|
|
45
45
|
return await this.getWebhooks(skip);
|
|
46
46
|
}
|
|
47
47
|
})
|
|
48
|
-
.catch((
|
|
48
|
+
.catch((error) => {
|
|
49
49
|
(0, utils_1.log)(this.exportConfig, `Failed to export webhooks.${(0, utils_1.formatError)(error)}`, 'error');
|
|
50
50
|
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
51
51
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import BaseClass from './base-class';
|
|
2
|
+
import { ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ExportWorkFlows extends BaseClass {
|
|
4
|
+
private workflows;
|
|
5
|
+
private workflowConfig;
|
|
6
|
+
webhooksFolderPath: string;
|
|
7
|
+
private qs;
|
|
8
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
getWorkflows(skip?: number): Promise<void>;
|
|
11
|
+
sanitizeAttribs(workflows: Record<string, string>[]): Promise<void>;
|
|
12
|
+
getWorkflowRoles(workflow: Record<string, any>): Promise<void>;
|
|
13
|
+
getRoles(roleUid: number): Promise<any>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
|
|
5
|
+
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
8
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
class ExportWorkFlows extends base_class_1.default {
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
12
|
+
super({ exportConfig, stackAPIClient });
|
|
13
|
+
this.workflows = {};
|
|
14
|
+
this.workflowConfig = config_1.default.modules.workflows;
|
|
15
|
+
this.qs = { include_count: true };
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
(0, utils_1.log)(this.exportConfig, 'Starting workflows export', 'info');
|
|
19
|
+
this.webhooksFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.workflowConfig.dirName);
|
|
20
|
+
await utils_1.fsUtil.makeDirectory(this.webhooksFolderPath);
|
|
21
|
+
await this.getWorkflows();
|
|
22
|
+
if (this.workflows === undefined || (0, isEmpty_1.default)(this.workflows)) {
|
|
23
|
+
(0, utils_1.log)(this.exportConfig, 'No workflows found', 'info');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.webhooksFolderPath, this.workflowConfig.fileName), this.workflows);
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'All the workflows have been exported successfully!', 'success');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async getWorkflows(skip = 0) {
|
|
31
|
+
if (skip) {
|
|
32
|
+
this.qs.skip = skip;
|
|
33
|
+
}
|
|
34
|
+
await this.stack
|
|
35
|
+
.workflow()
|
|
36
|
+
.fetchAll(this.qs)
|
|
37
|
+
.then(async (data) => {
|
|
38
|
+
const { items, count } = data;
|
|
39
|
+
if (items === null || items === void 0 ? void 0 : items.length) {
|
|
40
|
+
await this.sanitizeAttribs(items);
|
|
41
|
+
skip += this.workflowConfig.limit || 100;
|
|
42
|
+
if (skip >= count) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
return await this.getWorkflows(skip);
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.catch((error) => {
|
|
49
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export workflows.${(0, utils_1.formatError)(error)}`, 'error');
|
|
50
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async sanitizeAttribs(workflows) {
|
|
54
|
+
var _a;
|
|
55
|
+
for (let index = 0; index < (workflows === null || workflows === void 0 ? void 0 : workflows.length); index++) {
|
|
56
|
+
await this.getWorkflowRoles(workflows[index]);
|
|
57
|
+
const workflowUid = workflows[index].uid;
|
|
58
|
+
const workflowName = ((_a = workflows[index]) === null || _a === void 0 ? void 0 : _a.name) || '';
|
|
59
|
+
this.workflows[workflowUid] = (0, omit_1.default)(workflows[index], this.workflowConfig.invalidKeys);
|
|
60
|
+
(0, utils_1.log)(this.exportConfig, `'${workflowName}' workflow was exported successfully`, 'success');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async getWorkflowRoles(workflow) {
|
|
64
|
+
var _a, _b, _c;
|
|
65
|
+
for (const stage of workflow === null || workflow === void 0 ? void 0 : workflow.workflow_stages) {
|
|
66
|
+
for (let i = 0; i < ((_c = (_b = (_a = stage === null || stage === void 0 ? void 0 : stage.SYS_ACL) === null || _a === void 0 ? void 0 : _a.roles) === null || _b === void 0 ? void 0 : _b.uids) === null || _c === void 0 ? void 0 : _c.length); i++) {
|
|
67
|
+
const roleUid = stage.SYS_ACL.roles.uids[i];
|
|
68
|
+
const roleData = await this.getRoles(roleUid);
|
|
69
|
+
stage.SYS_ACL.roles.uids[i] = roleData;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async getRoles(roleUid) {
|
|
74
|
+
return await this.stack
|
|
75
|
+
.role(roleUid)
|
|
76
|
+
.fetch({ include_rules: true, include_permissions: true })
|
|
77
|
+
.then((data) => data)
|
|
78
|
+
.catch((err) => (0, utils_1.log)(this.exportConfig, `Failed to fetch roles.${(0, utils_1.formatError)(err)}`, 'error'));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.default = ExportWorkFlows;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const chalk = require('chalk');
|
|
3
|
+
const { values } = require('lodash');
|
|
3
4
|
const { executeTask, formatError, fileHelper, log } = require('../../utils');
|
|
4
5
|
class EntriesExport {
|
|
5
6
|
constructor(exportConfig, stackAPIClient) {
|
|
@@ -31,7 +32,7 @@ class EntriesExport {
|
|
|
31
32
|
log(this.exportConfig, `Exported entries of type '${requestOption.content_type}' locale '${requestOption.locale}'`, 'success');
|
|
32
33
|
if (this.exportConfig.versioning) {
|
|
33
34
|
log(this.exportConfig, `Started export versioned entries of type '${requestOption.content_type}' locale '${requestOption.locale}'`, 'info');
|
|
34
|
-
for (let entry of entries) {
|
|
35
|
+
for (let entry of values(entries)) {
|
|
35
36
|
const versionedEntries = await this.getEntryByVersion(Object.assign(Object.assign({}, requestOption), { uid: entry.uid }), entry._version);
|
|
36
37
|
let versionedEntryPath = path.join(this.entriesRootPath, requestOption.locale, requestOption.content_type, entry.uid);
|
|
37
38
|
await fileHelper.makeDirectory(versionedEntryPath);
|
|
@@ -44,8 +44,8 @@ class ExportStack {
|
|
|
44
44
|
}
|
|
45
45
|
else if (self.config.preserveStackVersion) {
|
|
46
46
|
log(self.config, 'Exporting stack details', 'success');
|
|
47
|
-
let stackFolderPath = path.resolve(self.config.data, stackConfig.dirName);
|
|
48
|
-
let stackContentsFile = path.resolve(stackFolderPath, stackConfig.fileName);
|
|
47
|
+
let stackFolderPath = path.resolve(self.config.data, this.stackConfig.dirName);
|
|
48
|
+
let stackContentsFile = path.resolve(stackFolderPath, this.stackConfig.fileName);
|
|
49
49
|
mkdirp.sync(stackFolderPath);
|
|
50
50
|
return new Promise((resolve, reject) => {
|
|
51
51
|
return self.stackAPIClient
|
package/lib/types/index.d.ts
CHANGED
|
@@ -84,5 +84,11 @@ export interface CustomRoleConfig {
|
|
|
84
84
|
customRolesLocalesFileName: string;
|
|
85
85
|
dependencies?: Modules[];
|
|
86
86
|
}
|
|
87
|
+
export interface StackConfig {
|
|
88
|
+
dirName: string;
|
|
89
|
+
fileName: string;
|
|
90
|
+
dependencies?: Modules[];
|
|
91
|
+
limit?: number;
|
|
92
|
+
}
|
|
87
93
|
export { default as DefaultConfig } from './default-config';
|
|
88
94
|
export { default as ExportConfig } from './export-config';
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-export",
|
|
3
3
|
"description": "Contentstack CLI plugin to export content from stack",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.8.1",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-command": "
|
|
9
|
-
"@contentstack/cli-utilities": "
|
|
8
|
+
"@contentstack/cli-command": "~1.2.12",
|
|
9
|
+
"@contentstack/cli-utilities": "~1.5.2",
|
|
10
10
|
"@oclif/command": "^1.8.16",
|
|
11
11
|
"@oclif/config": "^1.18.3",
|
|
12
12
|
"@oclif/core": "^2.9.3",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"winston": "^3.7.2"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@contentstack/cli-auth": "
|
|
30
|
-
"@contentstack/cli-config": "
|
|
31
|
-
"@contentstack/cli-dev-dependencies": "
|
|
29
|
+
"@contentstack/cli-auth": "~1.3.13",
|
|
30
|
+
"@contentstack/cli-config": "~1.4.11",
|
|
31
|
+
"@contentstack/cli-dev-dependencies": "~1.2.3",
|
|
32
32
|
"@oclif/plugin-help": "^5.1.19",
|
|
33
33
|
"@oclif/test": "^1.2.6",
|
|
34
34
|
"@types/mkdirp": "^1.0.2",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"lint": "eslint src/**/*.ts",
|
|
63
63
|
"format": "eslint src/**/*.ts --fix",
|
|
64
64
|
"test:integration": "INTEGRATION_TEST=true mocha --config ./test/.mocharc.js --forbid-only \"test/run.test.js\"",
|
|
65
|
+
"test:integration:report": "INTEGRATION_TEST=true nyc --extension .js mocha --forbid-only \"test/run.test.js\"",
|
|
65
66
|
"test:unit": "mocha --forbid-only \"test/unit/*.test.ts\""
|
|
66
67
|
},
|
|
67
68
|
"engines": {
|