@contentstack/cli-cm-export 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,98 +4,106 @@
4
4
  * MIT Licensed
5
5
  */
6
6
 
7
- const mkdirp = require('mkdirp');
8
7
  const path = require('path');
9
8
  const chalk = require('chalk');
9
+ const mkdirp = require('mkdirp');
10
+ const { merge } = require('lodash');
10
11
 
11
- let helper = require('../util/helper');
12
- let { addlogs } = require('../util/log');
13
-
12
+ const helper = require('../util/helper');
13
+ const { addlogs } = require('../util/log');
14
+ const { formatError } = require('../util');
15
+ const config = require('../../config/default');
14
16
  const stack = require('../util/contentstack-management-sdk');
15
- let config = require('../../config/default');
16
- let workFlowConfig = config.modules.workflows;
17
- let client;
18
17
 
19
- function ExportWorkFlows() {
20
- this.workflows = {};
21
- }
18
+ module.exports = class ExportWorkFlows {
19
+ client;
20
+ config;
21
+ workflows = {};
22
+ workFlowConfig = config.modules.workflows;
23
+
24
+ constructor(credentialConfig) {
25
+ this.config = merge(config, credentialConfig);
26
+ }
22
27
 
23
- ExportWorkFlows.prototype.start = function (credentialConfig) {
24
- addlogs(config, 'Starting workflow export', 'success');
25
- this.workflows = {};
26
- let self = this;
27
- config = credentialConfig;
28
- client = stack.Client(config);
28
+ start() {
29
+ addlogs(this.config, 'Starting workflow export', 'success');
29
30
 
30
- let workflowsFolderPath = path.resolve(config.data, config.branchName || '', workFlowConfig.dirName);
31
- mkdirp.sync(workflowsFolderPath);
32
- return new Promise(function (resolve, reject) {
33
- return client
34
- .stack({ api_key: config.source_stack, management_token: config.management_token })
35
- .workflow()
36
- .fetchAll()
37
- .then(async (response) => {
38
- try {
39
- if (response.items.length) {
40
- await getWorkflowsData(self, response.items);
41
- addlogs(config, chalk.green('All the workflow have been exported successfully'), 'success');
31
+ const self = this;
32
+ this.client = stack.Client(this.config);
33
+ let workflowsFolderPath = path.resolve(this.config.data, this.config.branchName || '', this.workFlowConfig.dirName);
34
+
35
+ mkdirp.sync(workflowsFolderPath);
36
+
37
+ return new Promise(function (resolve, reject) {
38
+ return self.client
39
+ .stack({ api_key: self.config.source_stack, management_token: self.config.management_token })
40
+ .workflow()
41
+ .fetchAll()
42
+ .then(async (response) => {
43
+ try {
44
+ if (response.items.length) {
45
+ await self.getWorkflowsData(self, response.items);
46
+ addlogs(self.config, chalk.green('All the workflow have been exported successfully'), 'success');
47
+ }
48
+ if (!response.items.length) {
49
+ addlogs(self.config, 'No workflow were found in the Stack', 'success');
50
+ }
51
+ helper.writeFileSync(path.join(workflowsFolderPath, self.workFlowConfig.fileName), self.workflows);
52
+ resolve();
53
+ } catch (error) {
54
+ addlogs(self.config, formatError(error), 'error');
55
+ reject(error);
42
56
  }
43
- if (!response.items.length) {
44
- addlogs(config, 'No workflow were found in the Stack', 'success');
57
+ })
58
+ .catch(function (error) {
59
+ if (error.statusCode === 401) {
60
+ addlogs(
61
+ self.config,
62
+ chalk.red(
63
+ 'You are not allowed to export workflow, Unless you provide email and password in config',
64
+ 'error',
65
+ ),
66
+ );
67
+ return resolve();
45
68
  }
46
- helper.writeFile(path.join(workflowsFolderPath, workFlowConfig.fileName), self.workflows);
47
- return resolve();
48
- } catch (error) {
49
- return reject(error);
50
- }
51
- })
52
- .catch(function (error) {
53
- if (error.statusCode === 401) {
54
- addlogs(
55
- config,
56
- chalk.red(
57
- 'You are not allowed to export workflow, Unless you provide email and password in config',
58
- 'error',
59
- ),
60
- );
61
- return resolve();
62
- }
63
- addlogs(config, error, 'error');
64
- return resolve();
65
- });
66
- });
67
- };
69
+ addlogs(self.config, formatError(error), 'error');
70
+ resolve();
71
+ });
72
+ });
73
+ }
68
74
 
69
- const getWorkflowsData = async (self, workflows) => {
70
- try {
71
- for (const workflow of workflows) {
72
- addlogs(config, workflow.name + ' workflow was exported successfully', 'success');
73
- await getWorkflowRoles(workflow);
74
- self.workflows[workflow.uid] = workflow;
75
- let deleteItems = config.modules.workflows.invalidKeys;
76
- deleteItems.forEach((e) => delete workflow[e]);
75
+ async getWorkflowRoles(self, workflow) {
76
+ try {
77
+ for (const stage of workflow.workflow_stages) {
78
+ if (stage.SYS_ACL.roles.uids.length) {
79
+ for (let i = 0; i < stage.SYS_ACL.roles.uids.length; i++) {
80
+ const roleUid = stage.SYS_ACL.roles.uids[i];
81
+ const roleData = await self.client
82
+ .stack({ api_key: config.source_stack, management_token: config.management_token })
83
+ .role(roleUid)
84
+ .fetch({ include_rules: true, include_permissions: true });
85
+ stage.SYS_ACL.roles.uids[i] = roleData;
86
+ }
87
+ }
88
+ }
89
+ } catch (error) {
90
+ console.log('Error getting roles', error && error.message);
91
+ addlogs(self.config, 'Error fetching roles in export workflows task.', 'error');
92
+ throw new Error({ message: 'Error fetching roles in export workflows task.' });
77
93
  }
78
- } catch (error) {
79
- throw error;
80
94
  }
81
- };
82
95
 
83
- const getWorkflowRoles = async (workflow) => {
84
- try {
85
- for (const stage of workflow.workflow_stages) {
86
- if (stage.SYS_ACL.roles.uids.length) {
87
- for (let i = 0; i < stage.SYS_ACL.roles.uids.length; i++) {
88
- const roleUid = stage.SYS_ACL.roles.uids[i];
89
- const roleData = await client.stack({ api_key: config.source_stack, management_token: config.management_token }).role(roleUid).fetch({ include_rules: true, include_permissions: true });
90
- stage.SYS_ACL.roles.uids[i] = roleData;
91
- }
96
+ async getWorkflowsData(self, workflows) {
97
+ try {
98
+ for (const workflow of workflows) {
99
+ addlogs(self.config, workflow.name + ' workflow was exported successfully', 'success');
100
+ await self.getWorkflowRoles(self, workflow);
101
+ self.workflows[workflow.uid] = workflow;
102
+ let deleteItems = config.modules.workflows.invalidKeys;
103
+ deleteItems.forEach((e) => delete workflow[e]);
92
104
  }
105
+ } catch (error) {
106
+ throw error;
93
107
  }
94
- } catch (error) {
95
- console.log('Error getting roles', error && error.message);
96
- addlogs(config, 'Error fetching roles in export workflows task.', 'error');
97
- throw { message: 'Error fetching roles in export workflows task.' };
98
108
  }
99
109
  };
100
-
101
- module.exports = new ExportWorkFlows();
@@ -11,7 +11,7 @@ const helper = require('../util/helper');
11
11
  let _ = require('lodash');
12
12
  const { cliux } = require('@contentstack/cli-utilities');
13
13
 
14
- exports.configWithMToken = function (config, managementTokens, host, contentTypes, branchName, securedAssets, moduleName) {
14
+ exports.configWithMToken = async function (config, managementTokens, host, contentTypes, branchName, securedAssets, moduleName) {
15
15
  let externalConfig = require(config);
16
16
  defaultConfig.securedAssets = securedAssets;
17
17
  defaultConfig.management_token = managementTokens.token;
@@ -27,7 +27,7 @@ exports.configWithMToken = function (config, managementTokens, host, contentType
27
27
  }
28
28
  }
29
29
  defaultConfig = _.merge(defaultConfig, externalConfig);
30
- initial(defaultConfig);
30
+ await initial(defaultConfig);
31
31
  };
32
32
 
33
33
  exports.parameterWithMToken = async function (
@@ -87,10 +87,10 @@ exports.withoutParameterMToken = async (
87
87
  }
88
88
  defaultConfig.source_stack = stackUid;
89
89
  defaultConfig.data = pathOfExport;
90
- initial(defaultConfig);
90
+ await initial(defaultConfig);
91
91
  };
92
92
 
93
- exports.configWithAuthToken = function (config, _authToken, moduleName, host, contentTypes, branchName, securedAssets) {
93
+ exports.configWithAuthToken = async function (config, _authToken, moduleName, host, contentTypes, branchName, securedAssets) {
94
94
  let externalConfig = helper.readFile(path.resolve(config));
95
95
  defaultConfig.auth_token = _authToken;
96
96
  defaultConfig.host = host.cma;
@@ -105,7 +105,7 @@ exports.configWithAuthToken = function (config, _authToken, moduleName, host, co
105
105
  }
106
106
  }
107
107
  defaultConfig = _.merge(defaultConfig, externalConfig);
108
- initial(defaultConfig);
108
+ await initial(defaultConfig);
109
109
  };
110
110
 
111
111
  exports.parametersWithAuthToken = function (
@@ -133,8 +133,7 @@ exports.parametersWithAuthToken = function (
133
133
  defaultConfig.cdn = host.cda;
134
134
  defaultConfig.data = data;
135
135
  defaultConfig.securedAssets = securedAssets;
136
- var exportStart = initial(defaultConfig);
137
- exportStart
136
+ await initial(defaultConfig)
138
137
  .then(() => {
139
138
  return resolve();
140
139
  })
@@ -168,5 +167,5 @@ exports.withoutParametersWithAuthToken = async (
168
167
  defaultConfig.data = pathOfExport;
169
168
  defaultConfig.host = host.cma;
170
169
  defaultConfig.cdn = host.cda;
171
- initial(defaultConfig);
170
+ await initial(defaultConfig);
172
171
  };
@@ -7,8 +7,9 @@
7
7
  var fs = require('fs');
8
8
  var path = require('path');
9
9
  var mkdirp = require('mkdirp');
10
+ var bigJSON = require('big-json');
10
11
 
11
- exports.readFile = function (filePath, parse) {
12
+ exports.readFileSync = function (filePath, parse) {
12
13
  var data;
13
14
  parse = typeof parse === 'undefined' ? true : parse;
14
15
  filePath = path.resolve(filePath);
@@ -18,11 +19,91 @@ exports.readFile = function (filePath, parse) {
18
19
  return data;
19
20
  };
20
21
 
21
- exports.writeFile = function (filePath, data) {
22
+ // by default file type is json
23
+ exports.readFile = async (filePath, options = { type: 'json' }) => {
24
+ return new Promise((resolve, reject) => {
25
+ filePath = path.resolve(filePath);
26
+ fs.readFile(filePath, 'utf-8', (error, data) => {
27
+ if (error) {
28
+ reject(error);
29
+ } else {
30
+ if (options.type !== 'json') {
31
+ return resolve(data);
32
+ }
33
+ resolve(JSON.parse(data));
34
+ }
35
+ });
36
+ });
37
+ };
38
+
39
+ exports.makeDirectory = async function (path) {
40
+ if (!path) {
41
+ throw new Error('Invalid path to create directory');
42
+ }
43
+ return mkdirp(path);
44
+ };
45
+
46
+ exports.readLargeFile = function (filePath, opts = {}) {
47
+ if (typeof filePath !== 'string') {
48
+ return;
49
+ }
50
+ filePath = path.resolve(filePath);
51
+ if (fs.existsSync(filePath)) {
52
+ return new Promise((resolve, reject) => {
53
+ const readStream = fs.createReadStream(filePath, { encoding: 'utf-8' });
54
+ const parseStream = bigJSON.createParseStream();
55
+ parseStream.on('data', function (data) {
56
+ if (opts.type === 'array') {
57
+ return resolve(Object.values(data));
58
+ }
59
+ resolve(data);
60
+ });
61
+ parseStream.on('error', function (error) {
62
+ console.log('error', error);
63
+ reject(error);
64
+ });
65
+ readStream.pipe(parseStream);
66
+ });
67
+ }
68
+ };
69
+
70
+ exports.writeLargeFile = function (filePath, data) {
71
+ if (typeof filePath !== 'string' || typeof data !== 'object') {
72
+ return;
73
+ }
74
+ filePath = path.resolve(filePath);
75
+ return new Promise((resolve, reject) => {
76
+ const stringifyStream = bigJSON.createStringifyStream({
77
+ body: data,
78
+ });
79
+ var writeStream = fs.createWriteStream(filePath, 'utf-8');
80
+ stringifyStream.pipe(writeStream);
81
+ writeStream.on('finish', () => {
82
+ resolve();
83
+ });
84
+ writeStream.on('error', (error) => {
85
+ reject(error);
86
+ });
87
+ });
88
+ };
89
+
90
+ exports.writeFileSync = function (filePath, data) {
22
91
  data = typeof data === 'object' ? JSON.stringify(data) : data || '{}';
23
92
  fs.writeFileSync(filePath, data);
24
93
  };
25
94
 
95
+ exports.writeFile = function (filePath, data) {
96
+ return new Promise((resolve, reject) => {
97
+ data = typeof data === 'object' ? JSON.stringify(data) : data || '{}';
98
+ fs.writeFile(filePath, data, (error) => {
99
+ if (error) {
100
+ return reject(error);
101
+ }
102
+ resolve('done');
103
+ });
104
+ });
105
+ };
106
+
26
107
  exports.makeDirectory = function () {
27
108
  for (var key in arguments) {
28
109
  var dirname = path.resolve(arguments[key]);
@@ -6,8 +6,8 @@
6
6
 
7
7
  var _ = require('lodash');
8
8
  var defaultConfig = require('../../config/default');
9
- var { addlogs } = require('../util/log');
10
9
  const chalk = require('chalk');
10
+ const promiseLimit = require('promise-limit');
11
11
 
12
12
  exports.validateConfig = function (config) {
13
13
  if (!config.host || !config.cdn) {
@@ -43,3 +43,38 @@ exports.buildAppConfig = function (config) {
43
43
  config = _.merge(defaultConfig, config);
44
44
  return config;
45
45
  };
46
+
47
+ exports.formatError = function (error) {
48
+ try {
49
+ if (typeof error === 'string') {
50
+ error = JSON.parse(error);
51
+ } else {
52
+ error = JSON.parse(error.message);
53
+ }
54
+ } catch (e) {}
55
+ let message = error.errorMessage || error.error_message || error.message || error;
56
+ if (error.errors && Object.keys(error.errors).length > 0) {
57
+ Object.keys(error.errors).forEach((e) => {
58
+ let entity = e;
59
+ if (e === 'authorization') entity = 'Management Token';
60
+ if (e === 'api_key') entity = 'Stack API key';
61
+ if (e === 'uid') entity = 'Content Type';
62
+ if (e === 'access_token') entity = 'Delivery Token';
63
+ message += ' ' + [entity, error.errors[e]].join(' ');
64
+ });
65
+ }
66
+ return message;
67
+ };
68
+
69
+ exports.executeTask = function (tasks = [], handler, options) {
70
+ if (typeof handler !== 'function') {
71
+ throw new Error('Invalid handler');
72
+ }
73
+ const { concurrency = 1 } = options;
74
+ const limit = promiseLimit(concurrency);
75
+ return Promise.all(
76
+ tasks.map((task) => {
77
+ return limit(() => handler(task));
78
+ }),
79
+ );
80
+ };
@@ -11,7 +11,7 @@ var slice = Array.prototype.slice;
11
11
 
12
12
  const ansiRegexPattern = [
13
13
  '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
14
- '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
14
+ '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))',
15
15
  ].join('|');
16
16
 
17
17
  function returnString(args) {
@@ -20,14 +20,17 @@ function returnString(args) {
20
20
  returnStr = args
21
21
  .map(function (item) {
22
22
  if (item && typeof item === 'object') {
23
- return JSON.stringify(item).replace(/authtoken\":\"blt................/g, 'authtoken":"blt....');
23
+ try {
24
+ return JSON.stringify(item).replace(/authtoken\":\"blt................/g, 'authtoken":"blt....');
25
+ } catch (error) {}
26
+ return item;
24
27
  }
25
28
  return item;
26
29
  })
27
30
  .join(' ')
28
31
  .trim();
29
32
  }
30
- returnStr = returnStr.replace(new RegExp(ansiRegexPattern, 'g'), "").trim();
33
+ returnStr = returnStr.replace(new RegExp(ansiRegexPattern, 'g'), '').trim();
31
34
  return returnStr;
32
35
  }
33
36
  var myCustomLevels = {
@@ -1,5 +1,6 @@
1
+ let config = require('../../config/default');
1
2
  const sdk = require('./contentstack-management-sdk');
2
- const { HttpClient } = require('@contentstack/cli-utilities');
3
+ const { cliux, HttpClient, configHandler } = require('@contentstack/cli-utilities');
3
4
 
4
5
  const getInstalledExtensions = (config) => {
5
6
  const client = sdk.Client(config)
@@ -22,15 +23,13 @@ const getInstalledExtensions = (config) => {
22
23
  .then(({ items }) => resolve(items))
23
24
  .catch(reject)
24
25
  } else if (api_key && auth_token) {
26
+ const { cma } = configHandler.get('region') || {};
25
27
  const headers = {
26
28
  api_key,
27
29
  authtoken: auth_token
28
30
  }
29
31
  const httpClient = new HttpClient().headers(headers);
30
- const baseUrl = config.host.startsWith('http')
31
- ? config.host
32
- : `https://${config.host}/v3`;
33
- httpClient.get(`${baseUrl}/extensions/?include_marketplace_extensions=true`)
32
+ httpClient.get(`${cma}/v3/extensions/?include_marketplace_extensions=true`)
34
33
  .then(({ data: { extensions } }) => resolve(extensions))
35
34
  .catch(reject)
36
35
  } else {
@@ -39,4 +38,24 @@ const getInstalledExtensions = (config) => {
39
38
  })
40
39
  }
41
40
 
42
- module.exports = { getInstalledExtensions }
41
+ const getDeveloperHubUrl = async () => {
42
+ const { cma, name } = configHandler.get('region') || {};
43
+ let developerHubBaseUrl = config.developerHubUrls[cma];
44
+
45
+ if (!developerHubBaseUrl) {
46
+ developerHubBaseUrl = await cliux.inquire({
47
+ type: 'input',
48
+ name: 'name',
49
+ validate: (url) => {
50
+ if (!url) return "Developer-hub URL can't be empty.";
51
+
52
+ return true;
53
+ },
54
+ message: `Enter the developer-hub base URL for the ${name} region - `,
55
+ });
56
+ }
57
+
58
+ return developerHubBaseUrl.startsWith('http') ? developerHubBaseUrl : `https://${developerHubBaseUrl}`;
59
+ }
60
+
61
+ module.exports = { getInstalledExtensions, getDeveloperHubUrl }
@@ -8,12 +8,12 @@ const setupBranches = async (config, branch) => {
8
8
  throw new Error('Invalid config to setup the branch');
9
9
  }
10
10
  let branches = [];
11
- const headers = { api_key: config.source_stack }
11
+ const headers = { api_key: config.source_stack };
12
12
 
13
13
  if (config.auth_token) {
14
- headers['authtoken'] = config.auth_token
14
+ headers['authtoken'] = config.auth_token;
15
15
  } else if (config.management_token) {
16
- headers['authorization'] = config.management_token
16
+ headers['authorization'] = config.management_token;
17
17
  }
18
18
 
19
19
  if (typeof branch === 'string') {
@@ -29,14 +29,12 @@ const setupBranches = async (config, branch) => {
29
29
  }
30
30
  } else {
31
31
  try {
32
- const result = await HttpClient.create()
33
- .headers(headers)
34
- .get(`https://${config.host}/v3/stacks/branches`);
32
+ const result = await HttpClient.create().headers(headers).get(`https://${config.host}/v3/stacks/branches`);
35
33
 
36
34
  if (result && result.data && Array.isArray(result.data.branches) && result.data.branches.length > 0) {
37
35
  branches = result.data.branches;
38
36
  } else {
39
- branches.push('main');
37
+ return;
40
38
  }
41
39
  } catch (error) {
42
40
  return;