@contentstack/cli-cm-export 1.6.1 → 1.7.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 +12 -2
- package/lib/export/modules/content-types.d.ts +15 -0
- package/lib/export/modules/content-types.js +72 -0
- package/lib/export/modules/custom-roles.d.ts +16 -0
- package/lib/export/modules/custom-roles.js +81 -0
- package/lib/export/modules/environments.d.ts +12 -0
- package/lib/export/modules/environments.js +64 -0
- package/lib/export/modules/extensions.d.ts +12 -0
- package/lib/export/modules/extensions.js +64 -0
- package/lib/export/modules/global-fields.d.ts +14 -0
- package/lib/export/modules/global-fields.js +59 -0
- package/lib/export/modules/labels.d.ts +12 -0
- package/lib/export/modules/labels.js +64 -0
- package/lib/export/modules/marketplace-apps.d.ts +18 -0
- package/lib/export/modules/marketplace-apps.js +119 -0
- package/lib/export/modules/webhooks.d.ts +12 -0
- package/lib/export/modules/webhooks.js +63 -0
- package/lib/export/modules-js/index.d.ts +2 -1
- package/lib/export/modules-js/index.js +3 -5
- package/lib/export/modules-js/marketplace-apps.d.ts +0 -1
- package/lib/export/modules-js/marketplace-apps.js +3 -22
- package/lib/types/export-config.d.ts +2 -0
- package/lib/types/index.d.ts +43 -0
- package/lib/utils/interactive.d.ts +1 -0
- package/lib/utils/interactive.js +15 -2
- package/lib/utils/marketplace-app-helper.d.ts +11 -1
- package/lib/utils/marketplace-app-helper.js +43 -11
- package/lib/utils/setup-branches.d.ts +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +5 -4
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.7.0 linux-x64 node-v18.17.0
|
|
52
52
|
$ csdx --help [COMMAND]
|
|
53
53
|
USAGE
|
|
54
54
|
$ csdx COMMAND
|
package/lib/config/index.js
CHANGED
|
@@ -60,7 +60,7 @@ const config = {
|
|
|
60
60
|
labels: {
|
|
61
61
|
dirName: 'labels',
|
|
62
62
|
fileName: 'labels.json',
|
|
63
|
-
invalidKeys: ['stackHeaders', '
|
|
63
|
+
invalidKeys: ['stackHeaders', 'urlPath', 'created_at', 'updated_at', 'created_by', 'updated_by'],
|
|
64
64
|
},
|
|
65
65
|
webhooks: {
|
|
66
66
|
dirName: 'webhooks',
|
|
@@ -368,7 +368,17 @@ const config = {
|
|
|
368
368
|
'xh',
|
|
369
369
|
'zu',
|
|
370
370
|
],
|
|
371
|
-
updatedModules: [
|
|
371
|
+
updatedModules: [
|
|
372
|
+
'assets',
|
|
373
|
+
'locales',
|
|
374
|
+
'extensions',
|
|
375
|
+
'marketplace-apps',
|
|
376
|
+
'labels',
|
|
377
|
+
'webhooks',
|
|
378
|
+
'custom-roles',
|
|
379
|
+
'global-fields',
|
|
380
|
+
'content-types',
|
|
381
|
+
],
|
|
372
382
|
apis: {
|
|
373
383
|
userSession: '/user-session/',
|
|
374
384
|
globalfields: '/global_fields/',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ExportConfig, ModuleClassParams } from '../../types';
|
|
2
|
+
import BaseClass from './base-class';
|
|
3
|
+
export default class ContentTypesExport extends BaseClass {
|
|
4
|
+
private stackAPIClient;
|
|
5
|
+
exportConfig: ExportConfig;
|
|
6
|
+
private qs;
|
|
7
|
+
private contentTypesConfig;
|
|
8
|
+
private contentTypesDirPath;
|
|
9
|
+
private contentTypes;
|
|
10
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
11
|
+
start(): Promise<void>;
|
|
12
|
+
getContentTypes(skip?: number): Promise<any>;
|
|
13
|
+
sanitizeAttribs(contentTypes: Record<string, unknown>[]): Record<string, unknown>[];
|
|
14
|
+
writeContentTypes(contentTypes: Record<string, unknown>[]): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
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 utils_1 = require("../../utils");
|
|
6
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
7
|
+
class ContentTypesExport extends base_class_1.default {
|
|
8
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
9
|
+
super({ exportConfig, stackAPIClient });
|
|
10
|
+
this.stackAPIClient = stackAPIClient;
|
|
11
|
+
this.contentTypesConfig = exportConfig.modules['content-types'];
|
|
12
|
+
this.qs = {
|
|
13
|
+
include_count: true,
|
|
14
|
+
asc: 'updated_at',
|
|
15
|
+
limit: this.contentTypesConfig.limit,
|
|
16
|
+
include_global_field_schema: true,
|
|
17
|
+
};
|
|
18
|
+
this.contentTypesDirPath = path.resolve(exportConfig.data, exportConfig.branchName || '', this.contentTypesConfig.dirName);
|
|
19
|
+
this.contentTypes = [];
|
|
20
|
+
}
|
|
21
|
+
async start() {
|
|
22
|
+
try {
|
|
23
|
+
(0, utils_1.log)(this.exportConfig, 'Starting content type export', 'success');
|
|
24
|
+
await utils_1.fsUtil.makeDirectory(this.contentTypesDirPath);
|
|
25
|
+
await this.getContentTypes();
|
|
26
|
+
await this.writeContentTypes(this.contentTypes);
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'Content type(s) exported successfully', 'success');
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export content types ${(0, utils_1.formatError)(error)}`, 'error');
|
|
31
|
+
throw new Error('Failed to export content types');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async getContentTypes(skip = 0) {
|
|
35
|
+
if (skip) {
|
|
36
|
+
this.qs.skip = skip;
|
|
37
|
+
}
|
|
38
|
+
const contentTypeSearchResponse = await this.stackAPIClient.contentType().query(this.qs).find();
|
|
39
|
+
if (Array.isArray(contentTypeSearchResponse.items) && contentTypeSearchResponse.items.length > 0) {
|
|
40
|
+
let updatedContentTypes = this.sanitizeAttribs(contentTypeSearchResponse.items);
|
|
41
|
+
this.contentTypes.push(...updatedContentTypes);
|
|
42
|
+
skip += this.contentTypesConfig.limit || 100;
|
|
43
|
+
if (skip >= contentTypeSearchResponse.count) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
return await this.getContentTypes(skip);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
(0, utils_1.log)(this.exportConfig, 'No content types returned for the given query', 'info');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
sanitizeAttribs(contentTypes) {
|
|
53
|
+
let updatedContentTypes = [];
|
|
54
|
+
contentTypes.forEach((contentType) => {
|
|
55
|
+
for (let key in contentType) {
|
|
56
|
+
if (this.contentTypesConfig.validKeys.indexOf(key) === -1) {
|
|
57
|
+
delete contentType[key];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
updatedContentTypes.push(contentType);
|
|
61
|
+
});
|
|
62
|
+
return updatedContentTypes;
|
|
63
|
+
}
|
|
64
|
+
async writeContentTypes(contentTypes) {
|
|
65
|
+
function write(contentType) {
|
|
66
|
+
return utils_1.fsUtil.writeFile(path.join(this.contentTypesDirPath, `${contentType.uid === 'schema' ? 'schema|1' : contentType.uid}.json`), contentType);
|
|
67
|
+
}
|
|
68
|
+
await (0, utils_1.executeTask)(contentTypes, write.bind(this), { concurrency: this.exportConfig.writeConcurrency });
|
|
69
|
+
return utils_1.fsUtil.writeFile(path.join(this.contentTypesDirPath, 'schema.json'), contentTypes);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.default = ContentTypesExport;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import BaseClass from './base-class';
|
|
2
|
+
import { ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ExportCustomRoles extends BaseClass {
|
|
4
|
+
private customRoles;
|
|
5
|
+
private existingRoles;
|
|
6
|
+
private customRolesConfig;
|
|
7
|
+
private sourceLocalesMap;
|
|
8
|
+
private localesMap;
|
|
9
|
+
rolesFolderPath: string;
|
|
10
|
+
customRolesLocalesFilepath: string;
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
12
|
+
start(): Promise<void>;
|
|
13
|
+
getCustomRoles(): Promise<void>;
|
|
14
|
+
getLocales(): Promise<void>;
|
|
15
|
+
getCustomRolesLocales(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const keys_1 = tslib_1.__importDefault(require("lodash/keys"));
|
|
5
|
+
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
6
|
+
const forEach_1 = tslib_1.__importDefault(require("lodash/forEach"));
|
|
7
|
+
const values_1 = tslib_1.__importDefault(require("lodash/values"));
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
10
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
11
|
+
const utils_1 = require("../../utils");
|
|
12
|
+
class ExportCustomRoles extends base_class_1.default {
|
|
13
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
14
|
+
super({ exportConfig, stackAPIClient });
|
|
15
|
+
this.customRoles = {};
|
|
16
|
+
this.customRolesConfig = config_1.default.modules.customRoles;
|
|
17
|
+
this.existingRoles = { Admin: 1, Developer: 1, 'Content Manager': 1 };
|
|
18
|
+
this.localesMap = {};
|
|
19
|
+
this.sourceLocalesMap = {};
|
|
20
|
+
}
|
|
21
|
+
async start() {
|
|
22
|
+
(0, utils_1.log)(this.exportConfig, 'Starting custom roles export', 'info');
|
|
23
|
+
this.rolesFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.customRolesConfig.dirName);
|
|
24
|
+
await utils_1.fsUtil.makeDirectory(this.rolesFolderPath);
|
|
25
|
+
this.customRolesLocalesFilepath = (0, node_path_1.resolve)(this.rolesFolderPath, this.customRolesConfig.customRolesLocalesFileName);
|
|
26
|
+
await this.getCustomRoles();
|
|
27
|
+
await this.getLocales();
|
|
28
|
+
await this.getCustomRolesLocales();
|
|
29
|
+
}
|
|
30
|
+
async getCustomRoles() {
|
|
31
|
+
const roles = await this.stack
|
|
32
|
+
.role()
|
|
33
|
+
.fetchAll({ include_rules: true, include_permissions: true })
|
|
34
|
+
.then((data) => data)
|
|
35
|
+
.catch((err) => (0, utils_1.log)(this.exportConfig, `Failed to fetch roles. ${(0, utils_1.formatError)(err)}`, 'error'));
|
|
36
|
+
const customRoles = roles.items.filter((role) => !this.existingRoles[role.name]);
|
|
37
|
+
if (!customRoles.length) {
|
|
38
|
+
(0, utils_1.log)(this.exportConfig, 'No custom roles were found in the Stack', 'info');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
customRoles.forEach((role) => {
|
|
42
|
+
(0, utils_1.log)(this.exportConfig, `'${role === null || role === void 0 ? void 0 : role.name}' role was exported successfully`, 'info');
|
|
43
|
+
this.customRoles[role.uid] = role;
|
|
44
|
+
});
|
|
45
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.rolesFolderPath, this.customRolesConfig.fileName), this.customRoles);
|
|
46
|
+
}
|
|
47
|
+
async getLocales() {
|
|
48
|
+
const locales = await this.stack
|
|
49
|
+
.locale()
|
|
50
|
+
.query({})
|
|
51
|
+
.find()
|
|
52
|
+
.then((data) => data)
|
|
53
|
+
.catch((err) => (0, utils_1.log)(this.exportConfig, `Failed to fetch locales. ${(0, utils_1.formatError)(err)}`, 'error'));
|
|
54
|
+
for (const locale of locales.items) {
|
|
55
|
+
this.sourceLocalesMap[locale.uid] = locale;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async getCustomRolesLocales() {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
for (const role of (0, values_1.default)(this.customRoles)) {
|
|
61
|
+
const customRole = role;
|
|
62
|
+
const rulesLocales = (0, find_1.default)(customRole.rules, (rule) => rule.module === 'locale');
|
|
63
|
+
if ((_a = rulesLocales === null || rulesLocales === void 0 ? void 0 : rulesLocales.locales) === null || _a === void 0 ? void 0 : _a.length) {
|
|
64
|
+
(0, forEach_1.default)(rulesLocales.locales, (locale) => {
|
|
65
|
+
this.localesMap[locale] = 1;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if ((_b = (0, keys_1.default)(this.localesMap)) === null || _b === void 0 ? void 0 : _b.length) {
|
|
70
|
+
for (const locale in this.localesMap) {
|
|
71
|
+
if (this.sourceLocalesMap[locale] !== undefined) {
|
|
72
|
+
const sourceLocale = this.sourceLocalesMap[locale];
|
|
73
|
+
sourceLocale === null || sourceLocale === void 0 ? true : delete sourceLocale.stackHeaders;
|
|
74
|
+
}
|
|
75
|
+
this.localesMap[locale] = this.sourceLocalesMap[locale];
|
|
76
|
+
}
|
|
77
|
+
utils_1.fsUtil.writeFile(this.customRolesLocalesFilepath, this.localesMap);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.default = ExportCustomRoles;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseClass from './base-class';
|
|
2
|
+
import { ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ExportEnvironments extends BaseClass {
|
|
4
|
+
private environments;
|
|
5
|
+
private environmentConfig;
|
|
6
|
+
environmentsFolderPath: string;
|
|
7
|
+
private qs;
|
|
8
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
getEnvironments(skip?: number): Promise<void>;
|
|
11
|
+
sanitizeAttribs(environments: Record<string, string>[]): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
|
|
6
|
+
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
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 ExportEnvironments extends base_class_1.default {
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
12
|
+
super({ exportConfig, stackAPIClient });
|
|
13
|
+
this.environments = {};
|
|
14
|
+
this.environmentConfig = config_1.default.modules.environments;
|
|
15
|
+
this.qs = { include_count: true };
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
(0, utils_1.log)(this.exportConfig, 'Starting environment export', 'info');
|
|
19
|
+
this.environmentsFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.environmentConfig.dirName);
|
|
20
|
+
await utils_1.fsUtil.makeDirectory(this.environmentsFolderPath);
|
|
21
|
+
await this.getEnvironments();
|
|
22
|
+
if (this.environments === undefined || (0, isEmpty_1.default)(this.environments)) {
|
|
23
|
+
(0, utils_1.log)(this.exportConfig, 'No environments found', 'info');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.environmentsFolderPath, this.environmentConfig.fileName), this.environments);
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'All the environments have been exported successfully!', 'success');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async getEnvironments(skip = 0) {
|
|
31
|
+
if (skip) {
|
|
32
|
+
this.qs.skip = skip;
|
|
33
|
+
}
|
|
34
|
+
await this.stack
|
|
35
|
+
.environment()
|
|
36
|
+
.query(this.qs)
|
|
37
|
+
.find()
|
|
38
|
+
.then(async (data) => {
|
|
39
|
+
const { items, count } = data;
|
|
40
|
+
if (items === null || items === void 0 ? void 0 : items.length) {
|
|
41
|
+
this.sanitizeAttribs(items);
|
|
42
|
+
skip += this.environmentConfig.limit || 100;
|
|
43
|
+
if (skip >= count) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
return await this.getEnvironments(skip);
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
.catch((error) => {
|
|
50
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export environments. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
51
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
sanitizeAttribs(environments) {
|
|
55
|
+
var _a;
|
|
56
|
+
for (let index = 0; index < (environments === null || environments === void 0 ? void 0 : environments.length); index++) {
|
|
57
|
+
const extUid = environments[index].uid;
|
|
58
|
+
const envName = (_a = environments[index]) === null || _a === void 0 ? void 0 : _a.name;
|
|
59
|
+
this.environments[extUid] = (0, omit_1.default)(environments[index], ['ACL']);
|
|
60
|
+
(0, utils_1.log)(this.exportConfig, `'${envName}' environment was exported successfully`, 'success');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.default = ExportEnvironments;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseClass from './base-class';
|
|
2
|
+
import { ExtensionsConfig, ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ExportExtensions extends BaseClass {
|
|
4
|
+
private extensionsFolderPath;
|
|
5
|
+
private extensions;
|
|
6
|
+
extensionConfig: ExtensionsConfig;
|
|
7
|
+
private qs;
|
|
8
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
getExtensions(skip?: number): Promise<void>;
|
|
11
|
+
sanitizeAttribs(extensions: Record<string, string>[]): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
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 ExportExtensions extends base_class_1.default {
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
12
|
+
super({ exportConfig, stackAPIClient });
|
|
13
|
+
this.extensions = {};
|
|
14
|
+
this.extensionConfig = config_1.default.modules.extensions;
|
|
15
|
+
this.qs = { include_count: true };
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
(0, utils_1.log)(this.exportConfig, 'Starting extension export', 'info');
|
|
19
|
+
this.extensionsFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.extensionConfig.dirName);
|
|
20
|
+
await utils_1.fsUtil.makeDirectory(this.extensionsFolderPath);
|
|
21
|
+
await this.getExtensions();
|
|
22
|
+
if (this.extensions === undefined || (0, isEmpty_1.default)(this.extensions)) {
|
|
23
|
+
(0, utils_1.log)(this.exportConfig, 'No extensions found', 'info');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.extensionsFolderPath, this.extensionConfig.fileName), this.extensions);
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'All the extensions have been exported successfully!', 'success');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async getExtensions(skip = 0) {
|
|
31
|
+
if (skip) {
|
|
32
|
+
this.qs.skip = skip;
|
|
33
|
+
}
|
|
34
|
+
await this.stack
|
|
35
|
+
.extension()
|
|
36
|
+
.query(this.qs)
|
|
37
|
+
.find()
|
|
38
|
+
.then(async (data) => {
|
|
39
|
+
const { items, count } = data;
|
|
40
|
+
if (items === null || items === void 0 ? void 0 : items.length) {
|
|
41
|
+
this.sanitizeAttribs(items);
|
|
42
|
+
skip += this.extensionConfig.limit || 100;
|
|
43
|
+
if (skip >= count) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
return await this.getExtensions(skip);
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
.catch((error) => {
|
|
50
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export extensions. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
51
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
sanitizeAttribs(extensions) {
|
|
55
|
+
var _a;
|
|
56
|
+
for (let index = 0; index < (extensions === null || extensions === void 0 ? void 0 : extensions.length); index++) {
|
|
57
|
+
const extUid = extensions[index].uid;
|
|
58
|
+
const extTitle = (_a = extensions[index]) === null || _a === void 0 ? void 0 : _a.title;
|
|
59
|
+
this.extensions[extUid] = (0, omit_1.default)(extensions[index], ['SYS_ACL']);
|
|
60
|
+
(0, utils_1.log)(this.exportConfig, `'${extTitle}' extension was exported successfully`, 'success');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.default = ExportExtensions;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ExportConfig, ModuleClassParams } from '../../types';
|
|
2
|
+
import BaseClass from './base-class';
|
|
3
|
+
export default class GlobalFieldsExport extends BaseClass {
|
|
4
|
+
private stackAPIClient;
|
|
5
|
+
exportConfig: ExportConfig;
|
|
6
|
+
private qs;
|
|
7
|
+
private globalFieldsConfig;
|
|
8
|
+
private globalFieldsDirPath;
|
|
9
|
+
private globalFields;
|
|
10
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
11
|
+
start(): Promise<void>;
|
|
12
|
+
getGlobalFields(skip?: number): Promise<any>;
|
|
13
|
+
sanitizeAttribs(globalFields: Record<string, string>[]): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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 utils_1 = require("../../utils");
|
|
6
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
7
|
+
class GlobalFieldsExport extends base_class_1.default {
|
|
8
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
9
|
+
super({ exportConfig, stackAPIClient });
|
|
10
|
+
this.stackAPIClient = stackAPIClient;
|
|
11
|
+
this.globalFieldsConfig = exportConfig.modules['global-fields'];
|
|
12
|
+
this.qs = {
|
|
13
|
+
skip: 0,
|
|
14
|
+
asc: 'updated_at',
|
|
15
|
+
include_count: true,
|
|
16
|
+
limit: this.globalFieldsConfig.limit,
|
|
17
|
+
};
|
|
18
|
+
this.globalFieldsDirPath = path.resolve(exportConfig.data, exportConfig.branchName || '', this.globalFieldsConfig.dirName);
|
|
19
|
+
this.globalFields = [];
|
|
20
|
+
}
|
|
21
|
+
async start() {
|
|
22
|
+
try {
|
|
23
|
+
(0, utils_1.log)(this.exportConfig, 'Starting global fields export', 'success');
|
|
24
|
+
await utils_1.fsUtil.makeDirectory(this.globalFieldsDirPath);
|
|
25
|
+
await this.getGlobalFields();
|
|
26
|
+
utils_1.fsUtil.writeFile(path.join(this.globalFieldsDirPath, this.globalFieldsConfig.fileName), this.globalFields);
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'Completed global fields export', 'success');
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export global fields. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
31
|
+
throw new Error('Failed to export global fields');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async getGlobalFields(skip = 0) {
|
|
35
|
+
if (skip) {
|
|
36
|
+
this.qs.skip = skip;
|
|
37
|
+
}
|
|
38
|
+
let globalFieldsFetchResponse = await this.stackAPIClient.globalField().query(this.qs).find();
|
|
39
|
+
if (Array.isArray(globalFieldsFetchResponse.items) && globalFieldsFetchResponse.items.length > 0) {
|
|
40
|
+
this.sanitizeAttribs(globalFieldsFetchResponse.items);
|
|
41
|
+
skip += this.globalFieldsConfig.limit || 100;
|
|
42
|
+
if (skip >= globalFieldsFetchResponse.count) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
return await this.getGlobalFields(skip);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
sanitizeAttribs(globalFields) {
|
|
49
|
+
globalFields.forEach((globalField) => {
|
|
50
|
+
for (let key in globalField) {
|
|
51
|
+
if (this.globalFieldsConfig.validKeys.indexOf(key) === -1) {
|
|
52
|
+
delete globalField[key];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
this.globalFields.push(globalField);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.default = GlobalFieldsExport;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseClass from './base-class';
|
|
2
|
+
import { ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ExportLabels extends BaseClass {
|
|
4
|
+
private labels;
|
|
5
|
+
private labelConfig;
|
|
6
|
+
labelsFolderPath: string;
|
|
7
|
+
private qs;
|
|
8
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
getLabels(skip?: number): Promise<void>;
|
|
11
|
+
sanitizeAttribs(labels: Record<string, string>[]): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
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 ExportLabels extends base_class_1.default {
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
12
|
+
super({ exportConfig, stackAPIClient });
|
|
13
|
+
this.labels = {};
|
|
14
|
+
this.labelConfig = config_1.default.modules.labels;
|
|
15
|
+
this.qs = { include_count: true };
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
(0, utils_1.log)(this.exportConfig, 'Starting labels export', 'info');
|
|
19
|
+
this.labelsFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.labelConfig.dirName);
|
|
20
|
+
await utils_1.fsUtil.makeDirectory(this.labelsFolderPath);
|
|
21
|
+
await this.getLabels();
|
|
22
|
+
if (this.labels === undefined || (0, isEmpty_1.default)(this.labels)) {
|
|
23
|
+
(0, utils_1.log)(this.exportConfig, 'No labels found', 'info');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.labelsFolderPath, this.labelConfig.fileName), this.labels);
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'All the labels have been exported successfully!', 'success');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async getLabels(skip = 0) {
|
|
31
|
+
if (skip) {
|
|
32
|
+
this.qs.skip = skip;
|
|
33
|
+
}
|
|
34
|
+
await this.stack
|
|
35
|
+
.label()
|
|
36
|
+
.query(this.qs)
|
|
37
|
+
.find()
|
|
38
|
+
.then(async (data) => {
|
|
39
|
+
const { items, count } = data;
|
|
40
|
+
if (items === null || items === void 0 ? void 0 : items.length) {
|
|
41
|
+
this.sanitizeAttribs(items);
|
|
42
|
+
skip += this.labelConfig.limit || 100;
|
|
43
|
+
if (skip >= count) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
return await this.getLabels(skip);
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
.catch((error) => {
|
|
50
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export labels. ${(0, utils_1.formatError)(error)}`, 'error');
|
|
51
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
sanitizeAttribs(labels) {
|
|
55
|
+
var _a;
|
|
56
|
+
for (let index = 0; index < (labels === null || labels === void 0 ? void 0 : labels.length); index++) {
|
|
57
|
+
const labelUid = labels[index].uid;
|
|
58
|
+
const labelName = (_a = labels[index]) === null || _a === void 0 ? void 0 : _a.name;
|
|
59
|
+
this.labels[labelUid] = (0, omit_1.default)(labels[index], this.labelConfig.invalidKeys);
|
|
60
|
+
(0, utils_1.log)(this.exportConfig, `'${labelName}' label was exported successfully`, 'success');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.default = ExportLabels;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NodeCrypto } from '@contentstack/cli-utilities';
|
|
2
|
+
import BaseClass from './base-class';
|
|
3
|
+
import { ModuleClassParams } from '../../types';
|
|
4
|
+
export default class ExportMarketplaceApps extends BaseClass {
|
|
5
|
+
private httpClient;
|
|
6
|
+
private marketplaceAppConfig;
|
|
7
|
+
private listOfApps;
|
|
8
|
+
private installedApps;
|
|
9
|
+
developerHubBaseUrl: string;
|
|
10
|
+
marketplaceAppPath: string;
|
|
11
|
+
nodeCrypto: NodeCrypto;
|
|
12
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
setHttpClient(): Promise<void>;
|
|
15
|
+
getAllStackSpecificApps(skip?: number): Promise<any>;
|
|
16
|
+
exportInstalledExtensions(): Promise<void>;
|
|
17
|
+
getAppConfigurations(index: number, appInstallation: any): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const map_1 = tslib_1.__importDefault(require("lodash/map"));
|
|
5
|
+
const has_1 = tslib_1.__importDefault(require("lodash/has"));
|
|
6
|
+
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
7
|
+
const entries_1 = tslib_1.__importDefault(require("lodash/entries"));
|
|
8
|
+
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
11
|
+
const config_1 = tslib_1.__importDefault(require("../../config"));
|
|
12
|
+
const utils_1 = require("../../utils");
|
|
13
|
+
const base_class_1 = tslib_1.__importDefault(require("./base-class"));
|
|
14
|
+
class ExportMarketplaceApps extends base_class_1.default {
|
|
15
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
16
|
+
super({ exportConfig, stackAPIClient });
|
|
17
|
+
this.httpClient = new cli_utilities_1.HttpClient();
|
|
18
|
+
this.marketplaceAppConfig = config_1.default.modules.marketplace_apps;
|
|
19
|
+
this.listOfApps = [];
|
|
20
|
+
this.installedApps = [];
|
|
21
|
+
}
|
|
22
|
+
async start() {
|
|
23
|
+
if (!(0, cli_utilities_1.isAuthenticated)()) {
|
|
24
|
+
cli_utilities_1.cliux.print('WARNING!!! To export Marketplace apps, you must be logged in. Please check csdx auth:login --help to log in', { color: 'yellow' });
|
|
25
|
+
return Promise.resolve();
|
|
26
|
+
}
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'Starting marketplace app export', 'info');
|
|
28
|
+
this.marketplaceAppPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.marketplaceAppConfig.dirName);
|
|
29
|
+
await utils_1.fsUtil.makeDirectory(this.marketplaceAppPath);
|
|
30
|
+
this.developerHubBaseUrl = this.exportConfig.developerHubBaseUrl || (await (0, utils_1.getDeveloperHubUrl)(this.exportConfig));
|
|
31
|
+
this.exportConfig.org_uid = await (0, utils_1.getOrgUid)(this.exportConfig);
|
|
32
|
+
await this.setHttpClient();
|
|
33
|
+
await this.getAllStackSpecificApps();
|
|
34
|
+
this.installedApps = this.listOfApps;
|
|
35
|
+
await this.exportInstalledExtensions();
|
|
36
|
+
}
|
|
37
|
+
async setHttpClient() {
|
|
38
|
+
if (!this.exportConfig.auth_token) {
|
|
39
|
+
this.httpClient = new cli_utilities_1.OauthDecorator(this.httpClient);
|
|
40
|
+
const headers = await this.httpClient.preHeadersCheck(this.exportConfig);
|
|
41
|
+
this.httpClient = this.httpClient.headers(headers);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.httpClient = new cli_utilities_1.HttpClientDecorator(this.httpClient);
|
|
45
|
+
this.httpClient.headers(this.exportConfig);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async getAllStackSpecificApps(skip = 0) {
|
|
49
|
+
const data = await (0, utils_1.getStackSpecificApps)({
|
|
50
|
+
developerHubBaseUrl: this.developerHubBaseUrl,
|
|
51
|
+
httpClient: this.httpClient,
|
|
52
|
+
config: this.exportConfig,
|
|
53
|
+
skip,
|
|
54
|
+
});
|
|
55
|
+
const { data: apps, count } = data;
|
|
56
|
+
if (!this.nodeCrypto && (0, find_1.default)(apps, (app) => (0, isEmpty_1.default)(app.configuration))) {
|
|
57
|
+
this.nodeCrypto = await (0, utils_1.createNodeCryptoInstance)(this.exportConfig);
|
|
58
|
+
}
|
|
59
|
+
const stackApps = (0, map_1.default)(apps, (app) => {
|
|
60
|
+
if ((0, has_1.default)(app, 'configuration')) {
|
|
61
|
+
app['configuration'] = this.nodeCrypto.encrypt(app.configuration);
|
|
62
|
+
}
|
|
63
|
+
return app;
|
|
64
|
+
});
|
|
65
|
+
this.listOfApps = [...this.listOfApps, ...stackApps];
|
|
66
|
+
if (count - (skip + 50) > 0) {
|
|
67
|
+
return await this.getAllStackSpecificApps(skip + 50);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async exportInstalledExtensions() {
|
|
71
|
+
if ((0, isEmpty_1.default)(this.installedApps)) {
|
|
72
|
+
(0, utils_1.log)(this.exportConfig, 'No marketplace apps found', 'info');
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
for (const [index, app] of (0, entries_1.default)(this.installedApps)) {
|
|
76
|
+
await this.getAppConfigurations(+index, app);
|
|
77
|
+
}
|
|
78
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.marketplaceAppPath, this.marketplaceAppConfig.fileName), this.installedApps);
|
|
79
|
+
(0, utils_1.log)(this.exportConfig, 'All the marketplace apps have been exported successfully', 'info');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async getAppConfigurations(index, appInstallation) {
|
|
83
|
+
var _a, _b;
|
|
84
|
+
const sdkClient = await (0, cli_utilities_1.managementSDKClient)({
|
|
85
|
+
host: this.developerHubBaseUrl.split('://').pop(),
|
|
86
|
+
});
|
|
87
|
+
const appName = (_a = appInstallation === null || appInstallation === void 0 ? void 0 : appInstallation.manifest) === null || _a === void 0 ? void 0 : _a.name;
|
|
88
|
+
(0, utils_1.log)(this.exportConfig, `Exporting ${appName} app and it's config.`, 'info');
|
|
89
|
+
await sdkClient
|
|
90
|
+
.organization(this.exportConfig.org_uid)
|
|
91
|
+
.app((_b = appInstallation === null || appInstallation === void 0 ? void 0 : appInstallation.manifest) === null || _b === void 0 ? void 0 : _b.uid)
|
|
92
|
+
.installation(appInstallation === null || appInstallation === void 0 ? void 0 : appInstallation.uid)
|
|
93
|
+
.installationData()
|
|
94
|
+
.then(async (result) => {
|
|
95
|
+
const { data, error } = result;
|
|
96
|
+
if ((0, has_1.default)(data, 'server_configuration')) {
|
|
97
|
+
if (!this.nodeCrypto && (0, has_1.default)(data, 'server_configuration')) {
|
|
98
|
+
this.nodeCrypto = await (0, utils_1.createNodeCryptoInstance)(this.exportConfig);
|
|
99
|
+
}
|
|
100
|
+
if (!(0, isEmpty_1.default)(data === null || data === void 0 ? void 0 : data.server_configuration)) {
|
|
101
|
+
this.installedApps[index]['server_configuration'] = this.nodeCrypto.encrypt(data.server_configuration);
|
|
102
|
+
(0, utils_1.log)(this.exportConfig, `Exported ${appName} app and it's config.`, 'success');
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
(0, utils_1.log)(this.exportConfig, `Exported ${appName} app`, 'success');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (error) {
|
|
109
|
+
(0, utils_1.log)(this.exportConfig, `Error on exporting ${appName} app and it's config.`, 'error');
|
|
110
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
.catch((error) => {
|
|
114
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export ${appName} app config ${(0, utils_1.formatError)(error)}`, 'error');
|
|
115
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.default = ExportMarketplaceApps;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseClass from './base-class';
|
|
2
|
+
import { ModuleClassParams } from '../../types';
|
|
3
|
+
export default class ExportWebhooks extends BaseClass {
|
|
4
|
+
private webhooks;
|
|
5
|
+
private webhookConfig;
|
|
6
|
+
webhooksFolderPath: string;
|
|
7
|
+
private qs;
|
|
8
|
+
constructor({ exportConfig, stackAPIClient }: ModuleClassParams);
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
getWebhooks(skip?: number): Promise<void>;
|
|
11
|
+
sanitizeAttribs(webhooks: Record<string, string>[]): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
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 ExportWebhooks extends base_class_1.default {
|
|
11
|
+
constructor({ exportConfig, stackAPIClient }) {
|
|
12
|
+
super({ exportConfig, stackAPIClient });
|
|
13
|
+
this.webhooks = {};
|
|
14
|
+
this.webhookConfig = config_1.default.modules.webhooks;
|
|
15
|
+
this.qs = { include_count: true, asc: 'updated_at' };
|
|
16
|
+
}
|
|
17
|
+
async start() {
|
|
18
|
+
(0, utils_1.log)(this.exportConfig, 'Starting webhooks export', 'info');
|
|
19
|
+
this.webhooksFolderPath = (0, node_path_1.resolve)(this.exportConfig.data, this.exportConfig.branchName || '', this.webhookConfig.dirName);
|
|
20
|
+
await utils_1.fsUtil.makeDirectory(this.webhooksFolderPath);
|
|
21
|
+
await this.getWebhooks();
|
|
22
|
+
if (this.webhooks === undefined || (0, isEmpty_1.default)(this.webhooks)) {
|
|
23
|
+
(0, utils_1.log)(this.exportConfig, 'No webhooks found', 'info');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
utils_1.fsUtil.writeFile((0, node_path_1.resolve)(this.webhooksFolderPath, this.webhookConfig.fileName), this.webhooks);
|
|
27
|
+
(0, utils_1.log)(this.exportConfig, 'All the webhooks have been exported successfully!', 'success');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async getWebhooks(skip = 0) {
|
|
31
|
+
if (skip) {
|
|
32
|
+
this.qs.skip = skip;
|
|
33
|
+
}
|
|
34
|
+
await this.stack
|
|
35
|
+
.webhook()
|
|
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
|
+
this.sanitizeAttribs(items);
|
|
41
|
+
skip += this.webhookConfig.limit || 100;
|
|
42
|
+
if (skip >= count) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
return await this.getWebhooks(skip);
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.catch(({ error }) => {
|
|
49
|
+
(0, utils_1.log)(this.exportConfig, `Failed to export webhooks.${(0, utils_1.formatError)(error)}`, 'error');
|
|
50
|
+
(0, utils_1.log)(this.exportConfig, error, 'error');
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
sanitizeAttribs(webhooks) {
|
|
54
|
+
var _a;
|
|
55
|
+
for (let index = 0; index < (webhooks === null || webhooks === void 0 ? void 0 : webhooks.length); index++) {
|
|
56
|
+
const webhookUid = webhooks[index].uid;
|
|
57
|
+
const webhookName = (_a = webhooks[index]) === null || _a === void 0 ? void 0 : _a.name;
|
|
58
|
+
this.webhooks[webhookUid] = (0, omit_1.default)(webhooks[index], ['SYS_ACL']);
|
|
59
|
+
(0, utils_1.log)(this.exportConfig, `'${webhookName}' webhook was exported successfully`, 'success');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.default = ExportWebhooks;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export = startModuleExport;
|
|
2
|
+
declare function startModuleExport(modulePayload: any): Promise<any>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
2
|
if (k2 === undefined) k2 = k;
|
|
4
3
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -22,12 +21,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
21
|
__setModuleDefault(result, mod);
|
|
23
22
|
return result;
|
|
24
23
|
};
|
|
25
|
-
var _a;
|
|
26
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
24
|
async function startModuleExport(modulePayload) {
|
|
25
|
+
var _a;
|
|
28
26
|
const { moduleName, exportConfig, stackAPIClient } = modulePayload;
|
|
29
|
-
const { default: ModuleRunner } = await (_a = `./${moduleName}`, Promise.resolve().then(() => __importStar(require(_a))));
|
|
27
|
+
const { default: ModuleRunner } = await (_a = `./${moduleName}.js`, Promise.resolve().then(() => __importStar(require(_a))));
|
|
30
28
|
const moduleRunner = new ModuleRunner(exportConfig, stackAPIClient);
|
|
31
29
|
return moduleRunner.start();
|
|
32
30
|
}
|
|
33
|
-
exports
|
|
31
|
+
module.exports = startModuleExport;
|
|
@@ -14,7 +14,6 @@ declare class ExportMarketplaceApps {
|
|
|
14
14
|
};
|
|
15
15
|
start(): Promise<void>;
|
|
16
16
|
getOrgUid(): Promise<void>;
|
|
17
|
-
createNodeCryptoInstance(): Promise<void>;
|
|
18
17
|
exportInstalledExtensions(): Promise<void>;
|
|
19
18
|
getAllStackSpecificApps(listOfApps?: any[], skip?: number): any;
|
|
20
19
|
getAppConfigurations(sdkClient: any, installedApps: any, [index, appInstallation]: [any, any]): Promise<void>;
|
|
@@ -11,7 +11,7 @@ const eachOf = require('async/eachOf');
|
|
|
11
11
|
const { cliux, HttpClient, NodeCrypto, managementSDKClient, HttpClientDecorator, OauthDecorator, isAuthenticated, } = require('@contentstack/cli-utilities');
|
|
12
12
|
const { default: config } = require('../../config');
|
|
13
13
|
const { formatError, log, fileHelper } = require('../../utils');
|
|
14
|
-
const { getDeveloperHubUrl } = require('../../utils');
|
|
14
|
+
const { getDeveloperHubUrl, createNodeCryptoInstance } = require('../../utils');
|
|
15
15
|
module.exports = class ExportMarketplaceApps {
|
|
16
16
|
constructor(credentialConfig) {
|
|
17
17
|
this.marketplaceAppPath = null;
|
|
@@ -24,7 +24,7 @@ module.exports = class ExportMarketplaceApps {
|
|
|
24
24
|
cliux.print('WARNING!!! To export Marketplace apps, you must be logged in. Please check csdx auth:login --help to log in', { color: 'yellow' });
|
|
25
25
|
return Promise.resolve();
|
|
26
26
|
}
|
|
27
|
-
this.developerHubBaseUrl = this.config.developerHubBaseUrl || (await getDeveloperHubUrl());
|
|
27
|
+
this.developerHubBaseUrl = this.config.developerHubBaseUrl || (await getDeveloperHubUrl(this.config));
|
|
28
28
|
await this.getOrgUid();
|
|
29
29
|
const httpClient = new HttpClient();
|
|
30
30
|
if (!this.config.auth_token) {
|
|
@@ -39,6 +39,7 @@ module.exports = class ExportMarketplaceApps {
|
|
|
39
39
|
log(this.config, 'Starting marketplace app export', 'success');
|
|
40
40
|
this.marketplaceAppPath = path.resolve(this.config.data, this.config.branchName || '', this.marketplaceAppConfig.dirName);
|
|
41
41
|
mkdirp.sync(this.marketplaceAppPath);
|
|
42
|
+
this.nodeCrypto = await createNodeCryptoInstance(config);
|
|
42
43
|
return this.exportInstalledExtensions();
|
|
43
44
|
}
|
|
44
45
|
async getOrgUid() {
|
|
@@ -54,26 +55,6 @@ module.exports = class ExportMarketplaceApps {
|
|
|
54
55
|
this.config.org_uid = tempStackData.org_uid;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
|
-
async createNodeCryptoInstance() {
|
|
58
|
-
const cryptoArgs = {};
|
|
59
|
-
if (this.config.forceStopMarketplaceAppsPrompt) {
|
|
60
|
-
cryptoArgs['encryptionKey'] = this.config.marketplaceAppEncryptionKey;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
cryptoArgs['encryptionKey'] = await cliux.inquire({
|
|
64
|
-
type: 'input',
|
|
65
|
-
name: 'name',
|
|
66
|
-
default: this.config.marketplaceAppEncryptionKey,
|
|
67
|
-
validate: (url) => {
|
|
68
|
-
if (!url)
|
|
69
|
-
return "Encryption key can't be empty.";
|
|
70
|
-
return true;
|
|
71
|
-
},
|
|
72
|
-
message: 'Enter marketplace app configurations encryption key',
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
this.nodeCrypto = new NodeCrypto(cryptoArgs);
|
|
76
|
-
}
|
|
77
58
|
async exportInstalledExtensions() {
|
|
78
59
|
const client = await managementSDKClient({ host: this.developerHubBaseUrl.split('://').pop() });
|
|
79
60
|
const installedApps = (await this.getAllStackSpecificApps()) || [];
|
package/lib/types/index.d.ts
CHANGED
|
@@ -41,5 +41,48 @@ export interface ExternalConfig extends ExportConfig {
|
|
|
41
41
|
email?: string;
|
|
42
42
|
password?: string;
|
|
43
43
|
}
|
|
44
|
+
export interface ExtensionsConfig {
|
|
45
|
+
dirName: string;
|
|
46
|
+
fileName: string;
|
|
47
|
+
dependencies?: Modules[];
|
|
48
|
+
limit?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface MarketplaceAppsConfig {
|
|
51
|
+
dirName: string;
|
|
52
|
+
fileName: string;
|
|
53
|
+
dependencies?: Modules[];
|
|
54
|
+
}
|
|
55
|
+
export interface EnvironmentConfig {
|
|
56
|
+
dirName: string;
|
|
57
|
+
fileName: string;
|
|
58
|
+
dependencies?: Modules[];
|
|
59
|
+
limit?: number;
|
|
60
|
+
}
|
|
61
|
+
export interface LabelConfig {
|
|
62
|
+
dirName: string;
|
|
63
|
+
fileName: string;
|
|
64
|
+
invalidKeys: string[];
|
|
65
|
+
dependencies?: Modules[];
|
|
66
|
+
limit?: number;
|
|
67
|
+
}
|
|
68
|
+
export interface WebhookConfig {
|
|
69
|
+
dirName: string;
|
|
70
|
+
fileName: string;
|
|
71
|
+
dependencies?: Modules[];
|
|
72
|
+
limit?: number;
|
|
73
|
+
}
|
|
74
|
+
export interface WorkflowConfig {
|
|
75
|
+
dirName: string;
|
|
76
|
+
fileName: string;
|
|
77
|
+
invalidKeys: string[];
|
|
78
|
+
dependencies?: Modules[];
|
|
79
|
+
limit?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface CustomRoleConfig {
|
|
82
|
+
dirName: string;
|
|
83
|
+
fileName: string;
|
|
84
|
+
customRolesLocalesFileName: string;
|
|
85
|
+
dependencies?: Modules[];
|
|
86
|
+
}
|
|
44
87
|
export { default as DefaultConfig } from './default-config';
|
|
45
88
|
export { default as ExportConfig } from './export-config';
|
|
@@ -4,3 +4,4 @@ export declare const askOTP: () => Promise<string>;
|
|
|
4
4
|
export declare const askUsername: () => Promise<string>;
|
|
5
5
|
export declare const askExportDir: () => Promise<string>;
|
|
6
6
|
export declare const askAPIKey: () => Promise<string>;
|
|
7
|
+
export declare const askDeveloperHub: (regionName: string) => Promise<string>;
|
package/lib/utils/interactive.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.askAPIKey = exports.askExportDir = exports.askUsername = exports.askOTP = exports.askOTPChannel = exports.askPassword = void 0;
|
|
3
|
+
exports.askDeveloperHub = exports.askAPIKey = exports.askExportDir = exports.askUsername = exports.askOTP = exports.askOTPChannel = exports.askPassword = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
6
|
const path = tslib_1.__importStar(require("path"));
|
|
@@ -62,10 +62,23 @@ const askExportDir = async () => {
|
|
|
62
62
|
};
|
|
63
63
|
exports.askExportDir = askExportDir;
|
|
64
64
|
const askAPIKey = async () => {
|
|
65
|
-
return cli_utilities_1.cliux.inquire({
|
|
65
|
+
return await cli_utilities_1.cliux.inquire({
|
|
66
66
|
type: 'input',
|
|
67
67
|
message: 'Enter the stack api key',
|
|
68
68
|
name: 'apiKey',
|
|
69
69
|
});
|
|
70
70
|
};
|
|
71
71
|
exports.askAPIKey = askAPIKey;
|
|
72
|
+
const askDeveloperHub = async (regionName) => {
|
|
73
|
+
return await cli_utilities_1.cliux.inquire({
|
|
74
|
+
type: 'input',
|
|
75
|
+
name: 'name',
|
|
76
|
+
validate: (url) => {
|
|
77
|
+
if (!url)
|
|
78
|
+
return "Developer-hub URL can't be empty.";
|
|
79
|
+
return true;
|
|
80
|
+
},
|
|
81
|
+
message: `Enter the developer-hub base URL for the ${regionName} region - `,
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
exports.askDeveloperHub = askDeveloperHub;
|
|
@@ -1 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { NodeCrypto, HttpClient } from '@contentstack/cli-utilities';
|
|
2
|
+
import { ExportConfig } from '../types';
|
|
3
|
+
export declare const getDeveloperHubUrl: (exportConfig: ExportConfig) => Promise<any>;
|
|
4
|
+
export declare function getOrgUid(config: ExportConfig): Promise<string>;
|
|
5
|
+
export declare function createNodeCryptoInstance(config: ExportConfig): Promise<NodeCrypto>;
|
|
6
|
+
export declare const getStackSpecificApps: (params: {
|
|
7
|
+
developerHubBaseUrl: string;
|
|
8
|
+
httpClient: HttpClient;
|
|
9
|
+
config: ExportConfig;
|
|
10
|
+
skip: number;
|
|
11
|
+
}) => Promise<any>;
|
|
@@ -1,23 +1,55 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDeveloperHubUrl = void 0;
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
exports.getStackSpecificApps = exports.createNodeCryptoInstance = exports.getOrgUid = exports.getDeveloperHubUrl = void 0;
|
|
4
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const interactive_1 = require("./interactive");
|
|
7
|
+
const getDeveloperHubUrl = async (exportConfig) => {
|
|
8
|
+
const { cma, name } = cli_utilities_1.configHandler.get('region') || {};
|
|
9
|
+
let developerHubBaseUrl = exportConfig === null || exportConfig === void 0 ? void 0 : exportConfig.developerHubUrls[cma];
|
|
9
10
|
if (!developerHubBaseUrl) {
|
|
10
|
-
developerHubBaseUrl = await
|
|
11
|
+
developerHubBaseUrl = await (0, interactive_1.askDeveloperHub)(name);
|
|
12
|
+
}
|
|
13
|
+
return developerHubBaseUrl.startsWith('http') ? developerHubBaseUrl : `https://${developerHubBaseUrl}`;
|
|
14
|
+
};
|
|
15
|
+
exports.getDeveloperHubUrl = getDeveloperHubUrl;
|
|
16
|
+
async function getOrgUid(config) {
|
|
17
|
+
const tempAPIClient = await (0, cli_utilities_1.managementSDKClient)({ host: config.host });
|
|
18
|
+
const tempStackData = await tempAPIClient
|
|
19
|
+
.stack({ api_key: config.source_stack })
|
|
20
|
+
.fetch()
|
|
21
|
+
.catch((error) => {
|
|
22
|
+
(0, utils_1.log)(this.config, (0, utils_1.formatError)(error), 'error');
|
|
23
|
+
});
|
|
24
|
+
return tempStackData === null || tempStackData === void 0 ? void 0 : tempStackData.org_uid;
|
|
25
|
+
}
|
|
26
|
+
exports.getOrgUid = getOrgUid;
|
|
27
|
+
async function createNodeCryptoInstance(config) {
|
|
28
|
+
const cryptoArgs = { encryptionKey: '' };
|
|
29
|
+
if (config.forceStopMarketplaceAppsPrompt) {
|
|
30
|
+
cryptoArgs['encryptionKey'] = config.marketplaceAppEncryptionKey;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
cryptoArgs['encryptionKey'] = await cli_utilities_1.cliux.inquire({
|
|
11
34
|
type: 'input',
|
|
12
35
|
name: 'name',
|
|
36
|
+
default: config.marketplaceAppEncryptionKey,
|
|
13
37
|
validate: (url) => {
|
|
14
38
|
if (!url)
|
|
15
|
-
return "
|
|
39
|
+
return "Encryption key can't be empty.";
|
|
16
40
|
return true;
|
|
17
41
|
},
|
|
18
|
-
message:
|
|
42
|
+
message: 'Enter marketplace app configurations encryption key',
|
|
19
43
|
});
|
|
20
44
|
}
|
|
21
|
-
return
|
|
45
|
+
return new cli_utilities_1.NodeCrypto(cryptoArgs);
|
|
46
|
+
}
|
|
47
|
+
exports.createNodeCryptoInstance = createNodeCryptoInstance;
|
|
48
|
+
const getStackSpecificApps = async (params) => {
|
|
49
|
+
const { developerHubBaseUrl, httpClient, config, skip } = params;
|
|
50
|
+
return httpClient
|
|
51
|
+
.get(`${developerHubBaseUrl}/installations?target_uids=${config.source_stack}&skip=${skip}`)
|
|
52
|
+
.then((data) => data.data)
|
|
53
|
+
.catch((error) => (0, utils_1.log)(config, `Failed to export marketplace-apps ${(0, utils_1.formatError)(error)}`, 'error'));
|
|
22
54
|
};
|
|
23
|
-
exports.
|
|
55
|
+
exports.getStackSpecificApps = getStackSpecificApps;
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
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.7.0",
|
|
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.11",
|
|
9
|
+
"@contentstack/cli-utilities": "^1.5.1",
|
|
10
10
|
"@oclif/command": "^1.8.16",
|
|
11
11
|
"@oclif/config": "^1.18.3",
|
|
12
|
-
"@oclif/core": "^2.3
|
|
12
|
+
"@oclif/core": "^2.9.3",
|
|
13
13
|
"async": "^3.2.4",
|
|
14
14
|
"big-json": "^3.2.0",
|
|
15
15
|
"bluebird": "^3.7.2",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"@oclif/test": "^1.2.6",
|
|
34
34
|
"@types/mkdirp": "^1.0.2",
|
|
35
35
|
"@types/progress-stream": "^2.0.2",
|
|
36
|
+
"@types/mkdirp": "^1.0.2",
|
|
36
37
|
"assert": "^2.0.0",
|
|
37
38
|
"chai": "^4.2.0",
|
|
38
39
|
"dotenv": "^16.0.1",
|