@contentstack/cli-cm-export 1.0.0 → 1.1.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 CHANGED
@@ -38,7 +38,7 @@ $ npm install -g @contentstack/cli-cm-export
38
38
  $ csdx COMMAND
39
39
  running command...
40
40
  $ csdx (-v|--version|version)
41
- @contentstack/cli-cm-export/1.0.0 linux-x64 node-v16.14.2
41
+ @contentstack/cli-cm-export/1.1.0 darwin-arm64 node-v16.17.0
42
42
  $ csdx --help [COMMAND]
43
43
  USAGE
44
44
  $ csdx COMMAND
@@ -83,5 +83,5 @@ EXAMPLES
83
83
  csdx cm:stacks:export --branch [optional] branch name
84
84
  ```
85
85
 
86
- _See code: [src/commands/cm/stacks/export.js](https://github.com/contentstack/cli/blob/v1.0.0/packages/contentstack-export/src/commands/cm/stacks/export.js)_
86
+ _See code: [src/commands/cm/stacks/export.js](https://github.com/contentstack/cli/blob/v1.1.0/packages/contentstack-export/src/commands/cm/stacks/export.js)_
87
87
  <!-- commandsstop -->
@@ -1 +1 @@
1
- {"version":"1.0.0","commands":{"cm:stacks:export":{"id":"cm:stacks:export","description":"Export content from a stack","usage":"cm:stacks:export [-c <value>] [-k <value>] [-d <value>] [-a <value>] [--module <value>] [--content-types <value>] [--branch <value>] [--secured-assets]","pluginName":"@contentstack/cli-cm-export","pluginType":"core","aliases":["cm:export"],"examples":["csdx cm:stacks:export --stack-api-key <stack_api_key> --data-dir <path/of/export/destination/dir>","csdx cm:stacks:export --config <path/to/config/dir>","csdx cm:stacks:export --alias <management_token_alias>","csdx cm:stacks:export --alias <management_token_alias> --data-dir <path/to/export/destination/dir>","csdx cm:stacks:export --alias <management_token_alias> --config <path/to/config/file>","csdx cm:stacks:export --module <single module name>","csdx cm:stacks:export --branch [optional] branch name"],"flags":{"config":{"name":"config","type":"option","char":"c","description":"[optional] path of the config"},"stack-uid":{"name":"stack-uid","type":"option","char":"s","description":"API key of the source stack","hidden":true},"stack-api-key":{"name":"stack-api-key","type":"option","char":"k","description":"API key of the source stack"},"data":{"name":"data","type":"option","description":"path or location to store the data","hidden":true},"data-dir":{"name":"data-dir","type":"option","char":"d","description":"path or location to store the data"},"alias":{"name":"alias","type":"option","char":"a","description":"alias of the management token"},"management-token-alias":{"name":"management-token-alias","type":"option","description":"alias of the management token","hidden":true},"auth-token":{"name":"auth-token","type":"boolean","char":"A","description":"to use auth token","hidden":true,"allowNo":false},"module":{"name":"module","type":"option","char":"m","description":"[optional] specific module name"},"content-types":{"name":"content-types","type":"option","char":"t","description":"[optional] content type"},"branch":{"name":"branch","type":"option","char":"B","description":"[optional] branch name"},"secured-assets":{"name":"secured-assets","type":"boolean","description":"[optional] use when assets are secured","allowNo":false}},"args":[]}}}
1
+ {"version":"1.1.0","commands":{"cm:stacks:export":{"id":"cm:stacks:export","description":"Export content from a stack","usage":"cm:stacks:export [-c <value>] [-k <value>] [-d <value>] [-a <value>] [--module <value>] [--content-types <value>] [--branch <value>] [--secured-assets]","pluginName":"@contentstack/cli-cm-export","pluginType":"core","aliases":["cm:export"],"examples":["csdx cm:stacks:export --stack-api-key <stack_api_key> --data-dir <path/of/export/destination/dir>","csdx cm:stacks:export --config <path/to/config/dir>","csdx cm:stacks:export --alias <management_token_alias>","csdx cm:stacks:export --alias <management_token_alias> --data-dir <path/to/export/destination/dir>","csdx cm:stacks:export --alias <management_token_alias> --config <path/to/config/file>","csdx cm:stacks:export --module <single module name>","csdx cm:stacks:export --branch [optional] branch name"],"flags":{"config":{"name":"config","type":"option","char":"c","description":"[optional] path of the config"},"stack-uid":{"name":"stack-uid","type":"option","char":"s","description":"API key of the source stack","hidden":true},"stack-api-key":{"name":"stack-api-key","type":"option","char":"k","description":"API key of the source stack"},"data":{"name":"data","type":"option","description":"path or location to store the data","hidden":true},"data-dir":{"name":"data-dir","type":"option","char":"d","description":"path or location to store the data"},"alias":{"name":"alias","type":"option","char":"a","description":"alias of the management token"},"management-token-alias":{"name":"management-token-alias","type":"option","description":"alias of the management token","hidden":true},"auth-token":{"name":"auth-token","type":"boolean","char":"A","description":"to use auth token","hidden":true,"allowNo":false},"module":{"name":"module","type":"option","char":"m","description":"[optional] specific module name"},"content-types":{"name":"content-types","type":"option","char":"t","description":"[optional] content type"},"branch":{"name":"branch","type":"option","char":"B","description":"[optional] branch name"},"secured-assets":{"name":"secured-assets","type":"boolean","description":"[optional] use when assets are secured","allowNo":false}},"args":[]}}}
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.0.0",
4
+ "version": "1.1.0",
5
5
  "author": "Contentstack",
6
6
  "bugs": "https://github.com/contentstack/cli/issues",
7
7
  "dependencies": {
8
- "@contentstack/cli-command": "^1.0.0",
9
- "@contentstack/cli-utilities": "^1.0.0",
8
+ "@contentstack/cli-command": "^1.0.1",
9
+ "@contentstack/cli-utilities": "^1.0.2",
10
10
  "@contentstack/management": "^1.3.0",
11
11
  "@oclif/command": "^1.8.16",
12
12
  "@oclif/config": "^1.18.3",
package/src/app.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /* eslint-disable no-redeclare */
2
- var util = require('./lib/util');
3
- var login = require('./lib/util/login');
4
- var { addlogs, unlinkFileLogger } = require('./lib/util/log');
5
- const setupBranches = require('./lib/util/setup-branches');
2
+ const _ = require('lodash');
3
+ const path = require('path');
6
4
  const chalk = require('chalk');
7
- let path = require('path');
8
- let _ = require('lodash');
5
+ const util = require('./lib/util');
6
+ const login = require('./lib/util/login');
7
+ const setupBranches = require('./lib/util/setup-branches');
8
+ const { addlogs, unlinkFileLogger } = require('./lib/util/log');
9
9
 
10
10
  exports.initial = async function (config) {
11
11
  return new Promise(async function (resolve, reject) {
@@ -17,7 +17,8 @@ exports.initial = async function (config) {
17
17
 
18
18
  const fetchBranchAndExport = async () => {
19
19
  await setupBranches(config, config.branchName);
20
- var types = config.modules.types;
20
+ let types = config.modules.types;
21
+
21
22
  if (Array.isArray(config.branches) && config.branches.length > 0) {
22
23
  for (let branch of config.branches) {
23
24
  config.branchName = branch.uid;
@@ -75,7 +76,7 @@ exports.initial = async function (config) {
75
76
  });
76
77
  };
77
78
 
78
- var singleExport = async (moduleName, types, config, branchName) => {
79
+ const singleExport = async (moduleName, types, config, branchName) => {
79
80
  try {
80
81
  if (types.indexOf(moduleName) > -1) {
81
82
  let iterateList;
@@ -86,10 +87,13 @@ var singleExport = async (moduleName, types, config, branchName) => {
86
87
  }
87
88
  iterateList.push(moduleName);
88
89
 
89
- for (let i = 0; i < iterateList.length; i++) {
90
- var exportedModule = require('./lib/export/' + iterateList[i]);
91
- const result = await exportedModule.start(config, branchName);
92
- if (result && iterateList[i] === 'stack') {
90
+ for (const element of iterateList) {
91
+ let exportedModule = require('./lib/export/' + element);
92
+ const result = await exportedModule.start(config, branchName)
93
+ .catch((error) => {
94
+ console.log(error && error.message)
95
+ });
96
+ if (result && element === 'stack') {
93
97
  let master_locale = {
94
98
  master_locale: { code: result.code },
95
99
  };
@@ -110,14 +114,16 @@ var singleExport = async (moduleName, types, config, branchName) => {
110
114
  }
111
115
  };
112
116
 
113
- var allExport = async (config, types, branchName) => {
114
- // eslint-disable-next-line no-async-promise-executor
117
+ const allExport = async (config, types, branchName) => {
115
118
  return new Promise(async (resolve, reject) => {
116
119
  try {
117
- for (let i = 0; i < types.length; i++) {
118
- let type = types[i];
119
- var exportedModule = require('./lib/export/' + type);
120
- const result = await exportedModule.start(config, branchName);
120
+ for (const type of types) {
121
+ const exportedModule = require('./lib/export/' + type);
122
+ const result = await exportedModule.start(config, branchName)
123
+ .catch((error) => {
124
+ console.log(error && error.message)
125
+ });
126
+
121
127
  if (result && type === 'stack') {
122
128
  let master_locale = { master_locale: { code: result.code } };
123
129
  config = _.merge(config, master_locale);
@@ -10,6 +10,7 @@ const {
10
10
  parametersWithAuthToken,
11
11
  withoutParametersWithAuthToken,
12
12
  } = require('../../../lib/util/export-flags');
13
+ const config = require('../../../config/default');
13
14
  const { configHandler } = require('@contentstack/cli-utilities');
14
15
 
15
16
  class ExportCommand extends Command {
@@ -32,6 +33,12 @@ class ExportCommand extends Command {
32
33
 
33
34
  if (alias) {
34
35
  let managementTokens = this.getToken(alias);
36
+
37
+ if (alias) {
38
+ const listOfTokens = configHandler.get('tokens');
39
+ config.management_token_data = listOfTokens[alias];
40
+ }
41
+
35
42
  if (managementTokens) {
36
43
  if (extConfig) {
37
44
  await configWithMToken(
@@ -1,6 +1,13 @@
1
1
  module.exports = {
2
2
  versioning: false,
3
3
  host: 'https://api.contentstack.io/v3',
4
+ developerHubUrls: {
5
+ // NOTE CDA url used as developer-hub url mapper to avoid conflict if user used any custom name
6
+ 'https://api.contentstack.io': 'https://developerhub-api.contentstack.com',
7
+ 'https://eu-api.contentstack.com': 'https://eu-developerhub-api.contentstack.com',
8
+ 'https://azure-na-api.contentstack.com': 'https://azure-na-developerhub-api.contentstack.com',
9
+ 'https://stag-api.csnonprod.com': 'https://stag-developerhub-api.csnonprod.com'
10
+ },
4
11
  // use below hosts for eu region
5
12
  // host:'https://eu-api.contentstack.com/v3',
6
13
  // use below hosts for azure-na region
@@ -15,15 +22,22 @@ module.exports = {
15
22
  'webhooks',
16
23
  'global-fields',
17
24
  'content-types',
25
+ 'custom-roles',
18
26
  'workflows',
19
27
  'entries',
20
28
  'labels',
29
+ 'marketplace-apps'
21
30
  ],
22
31
  locales: {
23
32
  dirName: 'locales',
24
33
  fileName: 'locales.json',
25
34
  requiredKeys: ['code', 'uid', 'name', 'fallback_locale'],
26
35
  },
36
+ customRoles: {
37
+ dirName: 'custom-roles',
38
+ fileName: 'custom-roles.json',
39
+ customRolesLocalesFileName: 'custom-roles-locales.json',
40
+ },
27
41
  environments: {
28
42
  dirName: 'environments',
29
43
  fileName: 'environments.json',
@@ -101,6 +115,10 @@ module.exports = {
101
115
  dependency: {
102
116
  entries: ['stack', 'locales', 'content-types'],
103
117
  },
118
+ marketplace_apps: {
119
+ dirName: 'marketplace_apps',
120
+ fileName: 'marketplace_apps.json'
121
+ }
104
122
  },
105
123
  languagesCode: [
106
124
  'af-za',
@@ -326,5 +344,5 @@ module.exports = {
326
344
  webhooks: '/webhooks/',
327
345
  stacks: '/stacks/',
328
346
  },
329
- preserveStackVersion: false,
347
+ preserveStackVersion: false
330
348
  };
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ const mkdirp = require('mkdirp');
4
+ const path = require('path');
5
+ const chalk = require('chalk');
6
+
7
+ const helper = require('../util/helper');
8
+ const { addlogs } = require('../util/log');
9
+
10
+ const stack = require('../util/contentstack-management-sdk');
11
+ let config = require('../../config/default');
12
+ const rolesConfig = config.modules.customRoles;
13
+
14
+ const EXISTING_ROLES = {
15
+ Admin: 1,
16
+ Developer: 1,
17
+ 'Content Manager': 1,
18
+ };
19
+
20
+ function ExportCustomRoles() {
21
+ this.client = null;
22
+ this.roles = {};
23
+ }
24
+
25
+ ExportCustomRoles.prototype.start = async function (credentialConfig) {
26
+ try {
27
+ addlogs(config, 'Starting roles export', 'success');
28
+ let self = this;
29
+ this.roles = {};
30
+ config = credentialConfig;
31
+ this.client = stack.Client(config);
32
+
33
+ const rolesFolderPath = path.resolve(config.data, config.branchName || '', rolesConfig.dirName);
34
+ mkdirp.sync(rolesFolderPath);
35
+
36
+ const roles = await this.client
37
+ .stack({ api_key: config.source_stack, management_token: config.management_token })
38
+ .role()
39
+ .fetchAll({ include_rules: true, include_permissions: true });
40
+
41
+ const customRoles = roles.items.filter(role => !EXISTING_ROLES[role.name]);
42
+
43
+ if (!customRoles.length) {
44
+ addlogs(config, 'No custom roles were found in the Stack', 'success');
45
+ return;
46
+ }
47
+
48
+ await getCustomRolesLocales(customRoles, path.join(rolesFolderPath, rolesConfig.customRolesLocalesFileName), this.client, config);
49
+ self.customRoles = {};
50
+ customRoles.forEach(role => {
51
+ addlogs(config, role.name + ' role was exported successfully', 'success');
52
+ self.customRoles[role.uid] = role;
53
+ });
54
+ helper.writeFile(path.join(rolesFolderPath, rolesConfig.fileName), self.customRoles);
55
+ addlogs(config, chalk.green('All the custom roles have been exported successfully'), 'success');
56
+ } catch (error) {
57
+ if (error.statusCode === 401) {
58
+ addlogs(config, chalk.red('You are not allowed to export roles, Unless you provide email and password in config'), 'error');
59
+ return;
60
+ }
61
+ addlogs(config, 'Error occurred in exporting roles. ' + error && error.message, 'error');
62
+ throw error;
63
+ }
64
+ };
65
+
66
+ async function getCustomRolesLocales(customRoles, customRolesLocalesFilepath, client, config) {
67
+ const localesMap = {};
68
+ for (const role of customRoles) {
69
+ const rulesLocales = role.rules.find(rule => rule.module === 'locale');
70
+ if (rulesLocales.locales && rulesLocales.locales.length) {
71
+ rulesLocales.locales.forEach(locale => {
72
+ localesMap[locale] = 1;
73
+ });
74
+ }
75
+ }
76
+
77
+ if (Object.keys(localesMap).length) {
78
+ const locales = await client.stack({ api_key: config.source_stack, management_token: config.management_token }).locale().query({}).find();
79
+ const sourceLocalesMap = {};
80
+ for (const locale of locales.items) {
81
+ sourceLocalesMap[locale.uid] = locale;
82
+ }
83
+ for (const locale in localesMap) {
84
+ delete sourceLocalesMap[locale]['stackHeaders'];
85
+ localesMap[locale] = sourceLocalesMap[locale];
86
+ }
87
+ helper.writeFile(customRolesLocalesFilepath, localesMap);
88
+ }
89
+ }
90
+
91
+ module.exports = new ExportCustomRoles();
@@ -0,0 +1,154 @@
1
+ /*!
2
+ * Contentstack Export
3
+ * Copyright (c) 2019 Contentstack LLC
4
+ * MIT Licensed
5
+ */
6
+ const _ = require('lodash')
7
+ const path = require('path');
8
+ const chalk = require('chalk');
9
+ const mkdirp = require('mkdirp');
10
+ const eachOf = require('async/eachOf');
11
+ const { cliux, configHandler, HttpClient, NodeCrypto } = require('@contentstack/cli-utilities');
12
+
13
+ let config = require('../../config/default');
14
+ const { writeFile } = require('../util/helper');
15
+ const { addlogs: log } = require('../util/log');
16
+ let stack = require('../util/contentstack-management-sdk');
17
+ const { getInstalledExtensions } = require('../util/marketplace-app-helper')
18
+
19
+ let client
20
+ let marketplaceAppConfig = config.modules.marketplace_apps;
21
+
22
+ function exportMarketplaceApps() {
23
+ this.marketplaceAppPath = null
24
+ this.developerHuBaseUrl = null
25
+ this.start = async (credentialConfig) => {
26
+ config = credentialConfig;
27
+ client = stack.Client(config);
28
+ this.developerHuBaseUrl = await this.getDeveloperHubUrl()
29
+
30
+ if (!config.auth_token) {
31
+ cliux.print('WARNING!!! To export Marketplace apps, you must be logged in. Please check csdx auth:login --help to log in', { color: 'yellow' })
32
+ return Promise.resolve()
33
+ }
34
+
35
+ log(credentialConfig, 'Starting marketplace app export', 'success');
36
+ this.marketplaceAppPath = path.resolve(
37
+ config.data, config.branchName || '',
38
+ marketplaceAppConfig.dirName
39
+ );
40
+ mkdirp.sync(this.marketplaceAppPath);
41
+
42
+ return this.exportInstalledExtensions()
43
+ }
44
+
45
+ this.exportInstalledExtensions = () => {
46
+ const self = this
47
+
48
+ return new Promise(async function (resolve, reject) {
49
+ getInstalledExtensions(config)
50
+ .then(async (items) => {
51
+ const installedApps = _.map(
52
+ _.filter(items, 'app_uid'),
53
+ ({ uid, title, app_uid, app_installation_uid, type }) => ({ title, uid, app_uid, app_installation_uid, type })
54
+ )
55
+ const headers = {
56
+ authtoken: config.auth_token,
57
+ organization_uid: config.org_uid
58
+ }
59
+ const httpClient = new HttpClient().headers(headers);
60
+ const nodeCrypto = new NodeCrypto()
61
+ const developerHubApps = await httpClient.get(`${self.developerHuBaseUrl}/apps`)
62
+ .then(({ data: { data } }) => data)
63
+ .catch(err => {
64
+ console.log(err)
65
+ }) || []
66
+
67
+ eachOf(_.uniqBy(installedApps, 'app_uid'), (app, _key, cb) => {
68
+ log(config, `Exporting ${app.title} app and it's config.`, 'success')
69
+ const listOfIndexToBeUpdated = _.map(
70
+ installedApps,
71
+ ({ app_uid }, index) => (app_uid === app.app_uid ? index : undefined)
72
+ ).filter(val => val !== undefined)
73
+
74
+ httpClient.get(`${self.developerHuBaseUrl}/installations/${app.app_installation_uid}/installationData`)
75
+ .then(({ data: result }) => {
76
+ const { data, error } = result
77
+ const developerHubApp = _.find(developerHubApps, { uid: app.app_uid })
78
+
79
+ _.forEach(listOfIndexToBeUpdated, (index, i) => {
80
+ if (developerHubApp) {
81
+ installedApps[index]['visibility'] = developerHubApp.visibility
82
+ installedApps[index]['manifest'] = _.pick(
83
+ developerHubApp,
84
+ ['name', 'description', 'icon', 'target_type', 'ui_location', 'webhook', 'oauth'] // NOTE keys can be passed to install new app in the developer hub
85
+ )
86
+ }
87
+
88
+ if (_.has(data, 'configuration') || _.has(data, 'server_configuration')) {
89
+ const { configuration, server_configuration } = data
90
+
91
+ if (!_.isEmpty(configuration)) {
92
+ installedApps[index]['configuration'] = nodeCrypto.encrypt(configuration)
93
+ }
94
+ if (!_.isEmpty(server_configuration)) {
95
+ installedApps[index]['server_configuration'] = nodeCrypto.encrypt(server_configuration)
96
+ }
97
+
98
+ if (i === 0) {
99
+ log(config, `Exported ${app.title} app and it's config.`, 'success')
100
+ }
101
+ } else if (error) {
102
+ console.log(error)
103
+ if (i === 0) {
104
+ log(config, `Error on exporting ${app.title} app and it's config.`, 'error')
105
+ }
106
+ }
107
+ })
108
+
109
+ cb()
110
+ })
111
+ .catch(err => {
112
+ console.log(err)
113
+ cb()
114
+ })
115
+ }, () => {
116
+ if (!_.isEmpty(installedApps)) {
117
+ writeFile(
118
+ path.join(self.marketplaceAppPath, marketplaceAppConfig.fileName),
119
+ installedApps
120
+ )
121
+
122
+ log(config, chalk.green('All the marketplace apps have been exported successfully'), 'success')
123
+ } else {
124
+ log(config, 'No marketplace apps found', 'success')
125
+ }
126
+
127
+ resolve()
128
+ })
129
+ }).catch(reject)
130
+ })
131
+ }
132
+
133
+ this.getDeveloperHubUrl = async () => {
134
+ const { cma, name } = configHandler.get('region') || {}
135
+ let developerHubBaseUrl = config.developerHubUrls[cma]
136
+
137
+ if (!developerHubBaseUrl) {
138
+ developerHubBaseUrl = await cliux.inquire({
139
+ type: 'input',
140
+ name: 'name',
141
+ validate: (url) => {
142
+ if (!url) return 'Developer-hub URL cant be empty.'
143
+
144
+ return true
145
+ },
146
+ message: `Enter the developer-hub base URL for the ${name} region - `,
147
+ })
148
+ }
149
+
150
+ return developerHubBaseUrl.startsWith('http') ? developerHubBaseUrl : `https://${developerHubBaseUrl}`
151
+ }
152
+ }
153
+
154
+ module.exports = new exportMarketplaceApps();
@@ -26,10 +26,25 @@ function ExportStack() {
26
26
  };
27
27
  }
28
28
 
29
- ExportStack.prototype.start = function (credentialConfig) {
29
+ ExportStack.prototype.start = async function (credentialConfig) {
30
30
  config = credentialConfig;
31
31
  client = stack.Client(config);
32
32
  const self = this
33
+
34
+ // NOTE get org uid
35
+ if (config.auth_token) {
36
+ const stack = await client
37
+ .stack({ api_key: config.source_stack, authtoken: config.auth_token })
38
+ .fetch()
39
+ .catch((error) => {
40
+ console.log(error)
41
+ })
42
+
43
+ if (stack && stack.org_uid) {
44
+ config.org_uid = stack.org_uid
45
+ }
46
+ }
47
+
33
48
  if (!config.preserveStackVersion && !config.hasOwnProperty('master_locale')) {
34
49
  const apiDetails = {
35
50
  limit: 100,
@@ -29,26 +29,25 @@ ExportWorkFlows.prototype.start = function (credentialConfig) {
29
29
 
30
30
  let workflowsFolderPath = path.resolve(config.data, config.branchName || '', workFlowConfig.dirName);
31
31
  mkdirp.sync(workflowsFolderPath);
32
- return new Promise(function (resolve) {
32
+ return new Promise(function (resolve, reject) {
33
33
  return client
34
34
  .stack({ api_key: config.source_stack, management_token: config.management_token })
35
35
  .workflow()
36
36
  .fetchAll()
37
- .then((response) => {
38
- if (response.items.length !== 0) {
39
- response.items.forEach(function (workflow) {
40
- addlogs(config, workflow.name + ' workflow was exported successfully', 'success');
41
- self.workflows[workflow.uid] = workflow;
42
- let deleteItems = config.modules.workflows.invalidKeys;
43
- deleteItems.forEach((e) => delete workflow[e]);
44
- });
45
- addlogs(config, chalk.green('All the workflow have been exported successfully'), 'success');
46
- }
47
- if (response.items.length === 0) {
48
- addlogs(config, 'No workflow were found in the Stack', 'success');
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');
42
+ }
43
+ if (!response.items.length) {
44
+ addlogs(config, 'No workflow were found in the Stack', 'success');
45
+ }
46
+ helper.writeFile(path.join(workflowsFolderPath, workFlowConfig.fileName), self.workflows);
47
+ return resolve();
48
+ } catch (error) {
49
+ return reject(error);
49
50
  }
50
- helper.writeFile(path.join(workflowsFolderPath, workFlowConfig.fileName), self.workflows);
51
- return resolve();
52
51
  })
53
52
  .catch(function (error) {
54
53
  if (error.statusCode === 401) {
@@ -67,4 +66,36 @@ ExportWorkFlows.prototype.start = function (credentialConfig) {
67
66
  });
68
67
  };
69
68
 
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]);
77
+ }
78
+ } catch (error) {
79
+ throw error;
80
+ }
81
+ };
82
+
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
+ }
92
+ }
93
+ }
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
+ }
99
+ };
100
+
70
101
  module.exports = new ExportWorkFlows();
@@ -0,0 +1,42 @@
1
+ const sdk = require('./contentstack-management-sdk');
2
+ const { HttpClient } = require('@contentstack/cli-utilities');
3
+
4
+ const getInstalledExtensions = (config) => {
5
+ const client = sdk.Client(config)
6
+
7
+ return new Promise((resolve, reject) => {
8
+ const queryRequestOptions = {
9
+ include_marketplace_extensions: true
10
+ }
11
+ const {
12
+ management_token_data: { apiKey: api_key, token: management_token } = { apiKey: config.source_stack },
13
+ auth_token
14
+ } = config || { management_token_data: {} }
15
+
16
+ if (api_key && management_token) {
17
+ client
18
+ .stack({ api_key, management_token })
19
+ .extension()
20
+ .query(queryRequestOptions)
21
+ .find()
22
+ .then(({ items }) => resolve(items))
23
+ .catch(reject)
24
+ } else if (api_key && auth_token) {
25
+ const headers = {
26
+ api_key,
27
+ authtoken: auth_token
28
+ }
29
+ 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`)
34
+ .then(({ data: { extensions } }) => resolve(extensions))
35
+ .catch(reject)
36
+ } else {
37
+ resolve([])
38
+ }
39
+ })
40
+ }
41
+
42
+ module.exports = { getInstalledExtensions }