@contentstack/cli-cm-clone 0.1.0-beta.6 → 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 +5 -5
- package/package.json +19 -13
- package/src/commands/cm/stacks/clone.js +249 -0
- package/src/lib/helpers/command-helpers.js +67 -0
- package/src/lib/util/abort-controller.js +49 -0
- package/src/lib/util/clone-handler.js +439 -190
- package/src/lib/util/contentstack-management-sdk.js +10 -11
- package/src/lib/util/log.js +32 -27
- package/src/commands/cm/stack-clone.js +0 -102
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
const contentstacksdk = require('@contentstack/management')
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.Client = function (config) {
|
|
1
|
+
const contentstacksdk = require('@contentstack/management');
|
|
5
2
|
|
|
3
|
+
exports.Client = function (config) {
|
|
6
4
|
const option = {
|
|
7
5
|
host: config.host,
|
|
8
6
|
authtoken: config.auth_token,
|
|
9
7
|
maxContentLength: 100000000,
|
|
10
8
|
maxBodyLength: 1000000000,
|
|
11
|
-
logHandler: (
|
|
12
|
-
|
|
9
|
+
logHandler: (_level, _data) => {
|
|
10
|
+
// empty log handler
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
13
|
|
|
14
14
|
if (config.target_stack) {
|
|
15
|
-
option.api_key = config.target_stack
|
|
15
|
+
option.api_key = config.target_stack;
|
|
16
16
|
}
|
|
17
17
|
if (config.source_stack) {
|
|
18
|
-
option.api_key = config.source_stack
|
|
18
|
+
option.api_key = config.source_stack;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
20
|
+
return contentstacksdk.client(option);
|
|
21
|
+
};
|
package/src/lib/util/log.js
CHANGED
|
@@ -9,15 +9,18 @@ var path = require('path');
|
|
|
9
9
|
var mkdirp = require('mkdirp');
|
|
10
10
|
var slice = Array.prototype.slice;
|
|
11
11
|
|
|
12
|
-
function returnString
|
|
12
|
+
function returnString(args) {
|
|
13
13
|
var returnStr = '';
|
|
14
14
|
if (args && args.length) {
|
|
15
|
-
returnStr = args
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
returnStr = args
|
|
16
|
+
.map(function (item) {
|
|
17
|
+
if (item && typeof item === 'object') {
|
|
18
|
+
return JSON.stringify(item);
|
|
19
|
+
}
|
|
20
|
+
return item;
|
|
21
|
+
})
|
|
22
|
+
.join(' ')
|
|
23
|
+
.trim();
|
|
21
24
|
}
|
|
22
25
|
return returnStr;
|
|
23
26
|
}
|
|
@@ -27,35 +30,37 @@ var myCustomLevels = {
|
|
|
27
30
|
error: 0,
|
|
28
31
|
warn: 1,
|
|
29
32
|
info: 2,
|
|
30
|
-
debug: 3
|
|
33
|
+
debug: 3,
|
|
31
34
|
},
|
|
32
35
|
colors: {
|
|
33
36
|
info: 'blue',
|
|
34
37
|
debug: 'green',
|
|
35
38
|
warn: 'yellow',
|
|
36
|
-
error: 'red'
|
|
37
|
-
}
|
|
39
|
+
error: 'red',
|
|
40
|
+
},
|
|
38
41
|
};
|
|
39
42
|
|
|
40
|
-
function init
|
|
41
|
-
var logsDir = path.resolve(_logPath, 'logs', 'import')
|
|
43
|
+
function init(_logPath, logfileName) {
|
|
44
|
+
var logsDir = path.resolve(_logPath, 'logs', 'import');
|
|
42
45
|
// Create dir if doesn't already exist
|
|
43
|
-
mkdirp.sync(logsDir)
|
|
46
|
+
mkdirp.sync(logsDir);
|
|
44
47
|
var logPath = path.join(logsDir, logfileName + '.log');
|
|
45
48
|
|
|
46
|
-
var transports = [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
var transports = [
|
|
50
|
+
new winston.transports.File({
|
|
51
|
+
filename: logPath,
|
|
52
|
+
maxFiles: 20,
|
|
53
|
+
maxsize: 1000000,
|
|
54
|
+
tailable: true,
|
|
55
|
+
json: true,
|
|
56
|
+
}),
|
|
57
|
+
];
|
|
53
58
|
|
|
54
|
-
transports.push(new
|
|
59
|
+
transports.push(new winston.transports.Console());
|
|
55
60
|
|
|
56
|
-
var logger =
|
|
61
|
+
var logger = winston.createLogger({
|
|
57
62
|
transports: transports,
|
|
58
|
-
levels: myCustomLevels.levels
|
|
63
|
+
levels: myCustomLevels.levels,
|
|
59
64
|
});
|
|
60
65
|
|
|
61
66
|
return {
|
|
@@ -86,14 +91,14 @@ function init (_logPath, logfileName) {
|
|
|
86
91
|
if (logString) {
|
|
87
92
|
logger.log('debug', logString);
|
|
88
93
|
}
|
|
89
|
-
}
|
|
94
|
+
},
|
|
90
95
|
};
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
exports.addlogs = async (config, message, type) => {
|
|
94
99
|
if (type !== 'error') {
|
|
95
|
-
init(config.oldPath, type).log(message)
|
|
100
|
+
init(config.oldPath, type).log(message);
|
|
96
101
|
} else {
|
|
97
|
-
init(config.oldPath, type).error(message)
|
|
102
|
+
init(config.oldPath, type).error(message);
|
|
98
103
|
}
|
|
99
|
-
}
|
|
104
|
+
};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
const {Command} = require('@contentstack/cli-command')
|
|
2
|
-
const Configstore = require('configstore')
|
|
3
|
-
const credStore = new Configstore('contentstack_cli')
|
|
4
|
-
const {CloneHandler} = require('../../lib/util/clone-handler')
|
|
5
|
-
let config = require('../../lib/util/dummyConfig.json')
|
|
6
|
-
const path = require('path')
|
|
7
|
-
const rimraf = require('rimraf')
|
|
8
|
-
let pathdir = path.join(__dirname.split('src')[0], 'contents')
|
|
9
|
-
const { readdirSync } = require('fs')
|
|
10
|
-
|
|
11
|
-
class StackCloneCommand extends Command {
|
|
12
|
-
async run() {
|
|
13
|
-
try {
|
|
14
|
-
await this.removeContentDirIfNotEmptyBeforeClone(pathdir) // NOTE remove if folder not empty before clone
|
|
15
|
-
|
|
16
|
-
this.registerCleanupOnInterrupt(pathdir)
|
|
17
|
-
let _authToken = credStore.get('authtoken')
|
|
18
|
-
if (_authToken && _authToken !== undefined) {
|
|
19
|
-
config.auth_token = _authToken
|
|
20
|
-
config.host = this.cmaHost
|
|
21
|
-
config.cdn = this.cdaHost
|
|
22
|
-
const cloneHandler = new CloneHandler(config)
|
|
23
|
-
await cloneHandler.start()
|
|
24
|
-
let successMessage = 'Stack cloning process have been completed successfully'
|
|
25
|
-
await this.cleanUp(pathdir, successMessage)
|
|
26
|
-
} else {
|
|
27
|
-
console.log("AuthToken is not present in local drive, Hence use 'csdx auth:login' command for login");
|
|
28
|
-
}
|
|
29
|
-
} catch (error) {
|
|
30
|
-
await this.cleanUp(pathdir)
|
|
31
|
-
// eslint-disable-next-line no-console
|
|
32
|
-
console.log(error.message || error)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async removeContentDirIfNotEmptyBeforeClone(dir) {
|
|
37
|
-
try {
|
|
38
|
-
const dirNotEmpty = readdirSync(dir).length
|
|
39
|
-
|
|
40
|
-
if (dirNotEmpty) {
|
|
41
|
-
await this.cleanUp(dir)
|
|
42
|
-
}
|
|
43
|
-
} catch (error) {
|
|
44
|
-
const omit = ['ENOENT'] // NOTE add emittable error codes in the array
|
|
45
|
-
|
|
46
|
-
if (!omit.includes(error.code)) {
|
|
47
|
-
console.log(error.message)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async cleanUp(pathDir, message) {
|
|
53
|
-
return new Promise(resolve => {
|
|
54
|
-
rimraf(pathDir, function (err) {
|
|
55
|
-
if (err)
|
|
56
|
-
throw err
|
|
57
|
-
if (message) {
|
|
58
|
-
// eslint-disable-next-line no-console
|
|
59
|
-
console.log(message)
|
|
60
|
-
}
|
|
61
|
-
resolve()
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
registerCleanupOnInterrupt(pathDir) {
|
|
67
|
-
const interrupt = ['SIGINT', 'SIGQUIT', 'SIGTERM']
|
|
68
|
-
const exceptions = ['unhandledRejection', 'uncaughtException']
|
|
69
|
-
|
|
70
|
-
const cleanUp = async (exitOrError = null) => {
|
|
71
|
-
// eslint-disable-next-line no-console
|
|
72
|
-
console.log('\nCleaning up')
|
|
73
|
-
await this.cleanUp(pathDir)
|
|
74
|
-
// eslint-disable-next-line no-console
|
|
75
|
-
console.log('done')
|
|
76
|
-
// eslint-disable-next-line no-process-exit
|
|
77
|
-
|
|
78
|
-
if (exitOrError instanceof Promise) {
|
|
79
|
-
exitOrError.catch(error => {
|
|
80
|
-
console.log(error && error.message || '')
|
|
81
|
-
})
|
|
82
|
-
} else if (exitOrError && exitOrError.message) {
|
|
83
|
-
console.log(exitOrError.message)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (exitOrError === true) process.exit()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
exceptions.forEach(event => process.on(event, cleanUp))
|
|
90
|
-
interrupt.forEach(signal => process.on(signal, () => cleanUp(true)))
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
StackCloneCommand.description = `Clone data (structure or content or both) of a stack into another stack
|
|
95
|
-
Use this plugin to automate the process of cloning a stack in a few steps.
|
|
96
|
-
`
|
|
97
|
-
|
|
98
|
-
StackCloneCommand.examples = [
|
|
99
|
-
'csdx cm:stack-clone',
|
|
100
|
-
]
|
|
101
|
-
|
|
102
|
-
module.exports = StackCloneCommand
|