@contentstack/cli-cm-export 0.1.1-beta.9 → 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/LICENSE +21 -0
- package/README.md +44 -29
- package/oclif.manifest.json +1 -1
- package/package.json +72 -68
- package/src/app.js +97 -104
- package/src/commands/cm/stacks/export.js +184 -0
- package/src/config/default.js +34 -59
- package/src/lib/export/assets.js +324 -223
- package/src/lib/export/content-types.js +72 -68
- package/src/lib/export/custom-roles.js +91 -0
- package/src/lib/export/entries.js +190 -135
- package/src/lib/export/environments.js +52 -47
- package/src/lib/export/extensions.js +50 -45
- package/src/lib/export/global-fields.js +17 -31
- package/src/lib/export/labels.js +52 -45
- package/src/lib/export/locales.js +74 -42
- package/src/lib/export/marketplace-apps.js +154 -0
- package/src/lib/export/stack.js +87 -47
- package/src/lib/export/webhooks.js +58 -50
- package/src/lib/export/workflows.js +85 -44
- package/src/lib/util/contentstack-management-sdk.js +26 -6
- package/src/lib/util/export-flags.js +140 -126
- package/src/lib/util/helper.js +20 -20
- package/src/lib/util/index.js +32 -19
- package/src/lib/util/log.js +109 -53
- package/src/lib/util/login.js +55 -40
- package/src/lib/util/marketplace-app-helper.js +42 -0
- package/src/lib/util/setup-branches.js +29 -38
- package/src/commands/cm/export.js +0 -142
- package/src/lib/util/request.js +0 -78
package/src/lib/util/login.js
CHANGED
|
@@ -7,55 +7,70 @@
|
|
|
7
7
|
* MIT Licensed
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
var chalk = require('chalk')
|
|
11
|
-
var {addlogs} = require('../util/log')
|
|
12
|
-
let stack = require('../util/contentstack-management-sdk')
|
|
13
|
-
let client
|
|
10
|
+
var chalk = require('chalk');
|
|
11
|
+
var { addlogs } = require('../util/log');
|
|
12
|
+
let stack = require('../util/contentstack-management-sdk');
|
|
13
|
+
let client;
|
|
14
14
|
|
|
15
|
-
module.exports.login = config => {
|
|
16
|
-
client = stack.Client(config)
|
|
15
|
+
module.exports.login = (config) => {
|
|
16
|
+
client = stack.Client(config);
|
|
17
17
|
return new Promise(function (resolve, reject) {
|
|
18
18
|
if (config.email && config.password) {
|
|
19
19
|
// eslint-disable-next-line no-console
|
|
20
|
-
console.log('Logging into Contentstack')
|
|
21
|
-
client
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
console.log('Logging into Contentstack');
|
|
21
|
+
client
|
|
22
|
+
.login({ email: config.email, password: config.password })
|
|
23
|
+
.then(function (response) {
|
|
24
|
+
// eslint-disable-next-line no-console
|
|
25
|
+
console.log(chalk.green('Contentstack account authenticated successfully!'));
|
|
26
|
+
config.authtoken = response.user.authtoken;
|
|
27
|
+
config.headers = {
|
|
28
|
+
api_key: config.source_stack,
|
|
29
|
+
access_token: config.access_token,
|
|
30
|
+
authtoken: config.authtoken,
|
|
31
|
+
'X-User-Agent': 'contentstack-export/v',
|
|
32
|
+
};
|
|
33
|
+
resolve(config);
|
|
34
|
+
})
|
|
35
|
+
.catch(function (error) {
|
|
36
|
+
reject(error);
|
|
37
|
+
});
|
|
36
38
|
} else if (!config.email && !config.password && config.source_stack && config.access_token) {
|
|
37
|
-
addlogs(
|
|
38
|
-
|
|
39
|
+
addlogs(
|
|
40
|
+
config,
|
|
41
|
+
chalk.yellow('Content types, entries, assets, labels, global fields, extensions modules will be exported'),
|
|
42
|
+
'success',
|
|
43
|
+
);
|
|
44
|
+
addlogs(
|
|
45
|
+
config,
|
|
46
|
+
chalk.yellow(
|
|
47
|
+
'Email, password, or management token is not set in the config, cannot export Webhook and label modules',
|
|
48
|
+
),
|
|
49
|
+
'success',
|
|
50
|
+
);
|
|
39
51
|
config.headers = {
|
|
40
52
|
api_key: config.source_stack,
|
|
41
53
|
access_token: config.access_token,
|
|
42
54
|
'X-User-Agent': 'contentstack-export/v',
|
|
43
|
-
}
|
|
44
|
-
resolve(config)
|
|
45
|
-
|
|
55
|
+
};
|
|
56
|
+
resolve(config);
|
|
57
|
+
// eslint-disable-next-line no-else-return
|
|
46
58
|
} else if (config.auth_token && !config.management_token) {
|
|
47
|
-
client
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
client
|
|
60
|
+
.stack({ api_key: config.source_stack, management_token: config.management_token })
|
|
61
|
+
.users()
|
|
62
|
+
.then(function () {
|
|
63
|
+
resolve();
|
|
64
|
+
})
|
|
65
|
+
.catch((error) => {
|
|
66
|
+
if (error.errors.api_key) {
|
|
67
|
+
return reject(error);
|
|
68
|
+
}
|
|
69
|
+
addlogs(config, error.errorMessage, 'error');
|
|
70
|
+
reject(error);
|
|
71
|
+
});
|
|
57
72
|
} else if (config.management_token) {
|
|
58
|
-
resolve()
|
|
73
|
+
resolve();
|
|
59
74
|
}
|
|
60
|
-
})
|
|
61
|
-
}
|
|
75
|
+
});
|
|
76
|
+
};
|
|
@@ -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 }
|
|
@@ -1,51 +1,42 @@
|
|
|
1
|
-
const mkdirp = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const
|
|
4
|
-
const
|
|
1
|
+
const mkdirp = require('mkdirp');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const helper = require('./helper');
|
|
4
|
+
const { HttpClient } = require('@contentstack/cli-utilities');
|
|
5
5
|
|
|
6
6
|
const setupBranches = async (config, branch) => {
|
|
7
|
-
if (typeof config !==
|
|
8
|
-
throw new Error(
|
|
7
|
+
if (typeof config !== 'object') {
|
|
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
12
|
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
branches.push(result.body.branch);
|
|
13
|
+
if (config.auth_token) {
|
|
14
|
+
headers['authtoken'] = config.auth_token
|
|
15
|
+
} else if (config.management_token) {
|
|
16
|
+
headers['authorization'] = config.management_token
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (typeof branch === 'string') {
|
|
20
|
+
// check branch exists
|
|
21
|
+
const result = await HttpClient.create()
|
|
22
|
+
.headers(headers)
|
|
23
|
+
.get(`https://${config.host}/v3/stacks/branches/${branch}`);
|
|
24
|
+
|
|
25
|
+
if (result && typeof result.data === 'object' && typeof result.data.branch === 'object') {
|
|
26
|
+
branches.push(result.data.branch);
|
|
27
27
|
} else {
|
|
28
|
-
throw new Error(
|
|
28
|
+
throw new Error('No branch found with the name ' + branch);
|
|
29
29
|
}
|
|
30
30
|
} else {
|
|
31
31
|
try {
|
|
32
|
-
const result = await
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
api_key: config.source_stack,
|
|
36
|
-
authtoken: config.auth_token,
|
|
37
|
-
},
|
|
38
|
-
});
|
|
32
|
+
const result = await HttpClient.create()
|
|
33
|
+
.headers(headers)
|
|
34
|
+
.get(`https://${config.host}/v3/stacks/branches`);
|
|
39
35
|
|
|
40
|
-
if (
|
|
41
|
-
result
|
|
42
|
-
result.body &&
|
|
43
|
-
Array.isArray(result.body.branches) &&
|
|
44
|
-
result.body.branches.length > 0
|
|
45
|
-
) {
|
|
46
|
-
branches = result.body.branches;
|
|
36
|
+
if (result && result.data && Array.isArray(result.data.branches) && result.data.branches.length > 0) {
|
|
37
|
+
branches = result.data.branches;
|
|
47
38
|
} else {
|
|
48
|
-
branches.push(
|
|
39
|
+
branches.push('main');
|
|
49
40
|
}
|
|
50
41
|
} catch (error) {
|
|
51
42
|
return;
|
|
@@ -54,7 +45,7 @@ const setupBranches = async (config, branch) => {
|
|
|
54
45
|
|
|
55
46
|
mkdirp.sync(config.data);
|
|
56
47
|
// create branch info file
|
|
57
|
-
helper.writeFile(path.join(config.data,
|
|
48
|
+
helper.writeFile(path.join(config.data, 'branches.json'), branches);
|
|
58
49
|
// add branches list in the
|
|
59
50
|
config.branches = branches;
|
|
60
51
|
};
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/* eslint-disable complexity */
|
|
2
|
-
const { Command, flags } = require('@contentstack/cli-command')
|
|
3
|
-
const { configWithMToken,
|
|
4
|
-
parameterWithMToken,
|
|
5
|
-
withoutParameterMToken,
|
|
6
|
-
configWithAuthToken,
|
|
7
|
-
parametersWithAuthToken,
|
|
8
|
-
withoutParametersWithAuthToken,
|
|
9
|
-
} = require('../../lib/util/export-flags')
|
|
10
|
-
const Configstore = require('configstore')
|
|
11
|
-
const credStore = new Configstore('contentstack_cli')
|
|
12
|
-
|
|
13
|
-
class ExportCommand extends Command {
|
|
14
|
-
async run() {
|
|
15
|
-
const exportCommandFlags = this.parse(ExportCommand).flags
|
|
16
|
-
const extConfig = exportCommandFlags.config
|
|
17
|
-
let sourceStack = exportCommandFlags['stack-uid']
|
|
18
|
-
const alias = exportCommandFlags['management-token-alias']
|
|
19
|
-
const authToken = exportCommandFlags['auth-token']
|
|
20
|
-
const securedAssets = exportCommandFlags['secured-assets']
|
|
21
|
-
const data = exportCommandFlags.data
|
|
22
|
-
const moduleName = exportCommandFlags.module
|
|
23
|
-
const contentTypes = exportCommandFlags['content-type']
|
|
24
|
-
const branchName = exportCommandFlags.branch;
|
|
25
|
-
let _authToken = credStore.get('authtoken')
|
|
26
|
-
let host = this.region
|
|
27
|
-
let cmaHost = host.cma.split('//')
|
|
28
|
-
let cdaHost = host.cda.split('//')
|
|
29
|
-
host.cma = cmaHost[1]
|
|
30
|
-
host.cda = cdaHost[1]
|
|
31
|
-
|
|
32
|
-
if (alias) {
|
|
33
|
-
let managementTokens = this.getToken(alias)
|
|
34
|
-
if (managementTokens) {
|
|
35
|
-
if (extConfig) {
|
|
36
|
-
configWithMToken(
|
|
37
|
-
extConfig,
|
|
38
|
-
managementTokens,
|
|
39
|
-
host,
|
|
40
|
-
contentTypes,
|
|
41
|
-
branchName,
|
|
42
|
-
securedAssets
|
|
43
|
-
)
|
|
44
|
-
} else if (data) {
|
|
45
|
-
parameterWithMToken(
|
|
46
|
-
managementTokens,
|
|
47
|
-
data,
|
|
48
|
-
moduleName,
|
|
49
|
-
host,
|
|
50
|
-
_authToken,
|
|
51
|
-
contentTypes,
|
|
52
|
-
branchName,
|
|
53
|
-
securedAssets
|
|
54
|
-
)
|
|
55
|
-
} else if (data === undefined && sourceStack === undefined) {
|
|
56
|
-
withoutParameterMToken(
|
|
57
|
-
managementTokens,
|
|
58
|
-
moduleName,
|
|
59
|
-
host,
|
|
60
|
-
_authToken,
|
|
61
|
-
contentTypes,
|
|
62
|
-
branchName,
|
|
63
|
-
securedAssets
|
|
64
|
-
)
|
|
65
|
-
} else {
|
|
66
|
-
this.log('Please provide a valid command. Run "csdx cm:export --help" command to view the command usage')
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
this.log(alias + ' management token is not present, please add managment token first')
|
|
70
|
-
}
|
|
71
|
-
} else if (authToken && _authToken) {
|
|
72
|
-
if (extConfig) {
|
|
73
|
-
configWithAuthToken(
|
|
74
|
-
extConfig,
|
|
75
|
-
_authToken,
|
|
76
|
-
moduleName,
|
|
77
|
-
host,
|
|
78
|
-
contentTypes,
|
|
79
|
-
branchName,
|
|
80
|
-
securedAssets
|
|
81
|
-
)
|
|
82
|
-
} else if (sourceStack && data) {
|
|
83
|
-
return parametersWithAuthToken(
|
|
84
|
-
_authToken,
|
|
85
|
-
sourceStack,
|
|
86
|
-
data,
|
|
87
|
-
moduleName,
|
|
88
|
-
host,
|
|
89
|
-
contentTypes,
|
|
90
|
-
branchName,
|
|
91
|
-
securedAssets
|
|
92
|
-
)
|
|
93
|
-
} else if (data === undefined && sourceStack === undefined) {
|
|
94
|
-
withoutParametersWithAuthToken(
|
|
95
|
-
_authToken,
|
|
96
|
-
moduleName,
|
|
97
|
-
host,
|
|
98
|
-
contentTypes,
|
|
99
|
-
branchName,
|
|
100
|
-
securedAssets
|
|
101
|
-
)
|
|
102
|
-
} else {
|
|
103
|
-
this.log('Please provide a valid command. Run "csdx cm:export --help" command to view the command usage')
|
|
104
|
-
}
|
|
105
|
-
} else {
|
|
106
|
-
this.log('Provide the alias for management token or auth token')
|
|
107
|
-
}
|
|
108
|
-
// return
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
ExportCommand.description = `Export content from a stack
|
|
113
|
-
...
|
|
114
|
-
Export content from one stack to another
|
|
115
|
-
`
|
|
116
|
-
ExportCommand.examples = [
|
|
117
|
-
'csdx cm:export -A',
|
|
118
|
-
'csdx cm:export -A -s <stack_ApiKey> -d <path/of/export/destination/dir>',
|
|
119
|
-
'csdx cm:export -A -c <path/to/config/dir>',
|
|
120
|
-
'csdx cm:export -A -m <single module name>',
|
|
121
|
-
'csdx cm:export -A --secured-assets',
|
|
122
|
-
'csdx cm:export -a <management_token_alias>',
|
|
123
|
-
'csdx cm:export -a <management_token_alias> -d <path/to/export/destination/dir>',
|
|
124
|
-
'csdx cm:export -a <management_token_alias> -c <path/to/config/file>',
|
|
125
|
-
'csdx cm:export -A -m <single module name>',
|
|
126
|
-
'csdx cm:export -A -m <single module name> -t <content type>',
|
|
127
|
-
'csdx cm:export -A -B [optional] branch name',
|
|
128
|
-
]
|
|
129
|
-
|
|
130
|
-
ExportCommand.flags = {
|
|
131
|
-
config: flags.string({ char: 'c', description: '[optional] path of the config' }),
|
|
132
|
-
'stack-uid': flags.string({ char: 's', description: 'API key of the source stack' }),
|
|
133
|
-
data: flags.string({ char: 'd', description: 'path or location to store the data' }),
|
|
134
|
-
'management-token-alias': flags.string({ char: 'a', description: 'alias of the management token' }),
|
|
135
|
-
'auth-token': flags.boolean({ char: 'A', description: 'to use auth token' }),
|
|
136
|
-
module: flags.string({ char: 'm', description: '[optional] specific module name' }),
|
|
137
|
-
'content-type': flags.string({ char: 't', description: '[optional] content type', multiple: true }),
|
|
138
|
-
branch: flags.string({ char: 'B', description: '[optional] branch name' }),
|
|
139
|
-
'secured-assets': flags.boolean({ description: '[optional] use when assets are secured' }),
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
module.exports = ExportCommand
|
package/src/lib/util/request.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Contentstack Export
|
|
3
|
-
* Copyright (c) 2019 Contentstack LLC
|
|
4
|
-
* MIT Licensed
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
var Bluebird = require('bluebird');
|
|
10
|
-
var request = Bluebird.promisify(require('request'));
|
|
11
|
-
//var pkg = require('../../package');
|
|
12
|
-
var app = require('../../app');
|
|
13
|
-
|
|
14
|
-
var MAX_RETRY_LIMIT = 8;
|
|
15
|
-
|
|
16
|
-
function validate(req) {
|
|
17
|
-
if (typeof req !== 'object') {
|
|
18
|
-
throw new Error(`Invalid params passed for request\n${JSON.stringify(arguments)}`);
|
|
19
|
-
}
|
|
20
|
-
if (typeof req.uri === 'undefined' && typeof req.url === 'undefined') {
|
|
21
|
-
throw new Error(`Missing uri in request!\n${JSON.stringify(req)}`);
|
|
22
|
-
}
|
|
23
|
-
if (typeof req.method === 'undefined') {
|
|
24
|
-
req.method = 'GET';
|
|
25
|
-
}
|
|
26
|
-
if (typeof req.json === 'undefined') {
|
|
27
|
-
req.json = true;
|
|
28
|
-
}
|
|
29
|
-
if (typeof req.headers === 'undefined') {
|
|
30
|
-
var config = app.getConfig();
|
|
31
|
-
req.headers = config.headers;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
var makeCall = module.exports = function(req, RETRY) {
|
|
36
|
-
return new Bluebird(function (resolve, reject) {
|
|
37
|
-
try {
|
|
38
|
-
validate(req);
|
|
39
|
-
if (typeof RETRY !== 'number') {
|
|
40
|
-
RETRY = 1;
|
|
41
|
-
} else if (RETRY > MAX_RETRY_LIMIT) {
|
|
42
|
-
return reject(new Error('Max retry limit exceeded!'));
|
|
43
|
-
}
|
|
44
|
-
// console.log(`${req.method.toUpperCase()}: ${req.uri || req.url}`);
|
|
45
|
-
return request(req).then(function (response) {
|
|
46
|
-
var timeDelay;
|
|
47
|
-
if (response.statusCode >= 200 && response.statusCode <= 399) {
|
|
48
|
-
return resolve(response);
|
|
49
|
-
} else if (response.statusCode === 429) {
|
|
50
|
-
timeDelay = Math.pow(Math.SQRT2, RETRY) * 100;
|
|
51
|
-
// console.log(`API rate limit exceeded.\nReceived ${response.statusCode} status\nBody ${JSON.stringify(response)}`);
|
|
52
|
-
console.log(`Retrying ${req.uri || req.url} with ${timeDelay} sec delay`);
|
|
53
|
-
return setTimeout(function (reqObj, retry) {
|
|
54
|
-
return makeCall(reqObj, retry)
|
|
55
|
-
.then(resolve)
|
|
56
|
-
.catch(reject);
|
|
57
|
-
}, timeDelay, req, RETRY);
|
|
58
|
-
} else if (response.statusCode >= 500) {
|
|
59
|
-
// retry, with delay
|
|
60
|
-
timeDelay = Math.pow(Math.SQRT2, RETRY) * 100;
|
|
61
|
-
// console.log(`Recevied ${response.statusCode} status\nBody ${JSON.stringify(response)}`);
|
|
62
|
-
console.log(`Retrying ${req.uri || req.url} with ${timeDelay} sec delay`);
|
|
63
|
-
RETRY++;
|
|
64
|
-
return setTimeout(function (req, RETRY) {
|
|
65
|
-
return makeCall(req, RETRY)
|
|
66
|
-
.then(resolve)
|
|
67
|
-
.catch(reject);
|
|
68
|
-
}, timeDelay, req, RETRY);
|
|
69
|
-
} else {
|
|
70
|
-
return reject(response);
|
|
71
|
-
}
|
|
72
|
-
}).catch(reject);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.log(error);
|
|
75
|
-
return reject(error);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
};
|