@contentstack/cli-migration 1.5.1 → 1.5.2
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/package.json +2 -2
- package/src/commands/cm/stacks/migration.js +8 -16
- package/src/services/content-types.js +6 -6
- package/src/utils/error-helper.js +80 -36
- package/src/utils/index.js +0 -1
- package/src/utils/logger.js +4 -4
- package/src/utils/migration-logger.js +20 -0
- package/src/utils/error-handler.js +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-migration",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"author": "@contentstack",
|
|
5
5
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
6
6
|
"dependencies": {
|
|
@@ -66,4 +66,4 @@
|
|
|
66
66
|
"cm:migration": "O-MGRTN"
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
}
|
|
69
|
+
}
|
|
@@ -12,6 +12,7 @@ const { Parser } = require('../../../modules');
|
|
|
12
12
|
const { ActionList } = require('../../../actions');
|
|
13
13
|
const fs = require('fs');
|
|
14
14
|
const chalk = require('chalk');
|
|
15
|
+
const isEmpty = require('lodash/isEmpty');
|
|
15
16
|
const {
|
|
16
17
|
printFlagDeprecation,
|
|
17
18
|
managementSDKClient,
|
|
@@ -24,8 +25,6 @@ const { ApiError, SchemaValidator, MigrationError, FieldValidator } = require('.
|
|
|
24
25
|
|
|
25
26
|
// Utils
|
|
26
27
|
const { map: _map, constants, safePromise, errorHelper } = require('../../../utils');
|
|
27
|
-
const { success } = require('../../../utils/logger');
|
|
28
|
-
|
|
29
28
|
// Properties
|
|
30
29
|
const { get, set, getMapInstance, resetMapInstance } = _map;
|
|
31
30
|
const {
|
|
@@ -134,6 +133,10 @@ class MigrationCommand extends Command {
|
|
|
134
133
|
} else {
|
|
135
134
|
await this.execSingleFile(filePath, mapInstance);
|
|
136
135
|
}
|
|
136
|
+
const errLogPath = `${process.cwd()}/migration-logs`;
|
|
137
|
+
if (fs.existsSync(errLogPath)) {
|
|
138
|
+
this.log(`The log has been stored at: `, errLogPath);
|
|
139
|
+
}
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
async execSingleFile(filePath, mapInstance) {
|
|
@@ -160,21 +163,11 @@ class MigrationCommand extends Command {
|
|
|
160
163
|
|
|
161
164
|
const listr = new Listr(tasks);
|
|
162
165
|
|
|
163
|
-
await listr.run()
|
|
164
|
-
this.handleErrors(error);
|
|
165
|
-
// When the process is child, send error message to parent
|
|
166
|
-
if (process.send) process.send({ errorOccurred: true });
|
|
167
|
-
});
|
|
166
|
+
await listr.run();
|
|
168
167
|
requests.splice(0, requests.length);
|
|
169
168
|
} catch (error) {
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
this.log(error.message);
|
|
173
|
-
} else if (error.errorMessage) {
|
|
174
|
-
this.log(error.errorMessage);
|
|
175
|
-
} else {
|
|
176
|
-
this.log(error);
|
|
177
|
-
}
|
|
169
|
+
errorHelper(error, filePath);
|
|
170
|
+
if (process.send) process.send({ errorOccurred: true });
|
|
178
171
|
}
|
|
179
172
|
}
|
|
180
173
|
|
|
@@ -186,7 +179,6 @@ class MigrationCommand extends Command {
|
|
|
186
179
|
for (const element of files) {
|
|
187
180
|
const file = element;
|
|
188
181
|
if (extname(file) === '.js') {
|
|
189
|
-
success(chalk`{white Executing file:} {grey {bold ${file}}}`);
|
|
190
182
|
// eslint-disable-next-line no-await-in-loop
|
|
191
183
|
await this.execSingleFile(pathValidator(resolve(filePath, file)), mapInstance);
|
|
192
184
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const Base = require('../modules/base');
|
|
6
6
|
// Utils
|
|
7
|
-
const { map: _map, safePromise, successHandler, errorHandler, constants } = require('../utils');
|
|
7
|
+
const { map: _map, safePromise, successHandler, errorHandler, constants, errorHelper } = require('../utils');
|
|
8
8
|
// Map methods
|
|
9
9
|
const { get, getMapInstance, getDataWithAction } = _map;
|
|
10
10
|
const mapInstance = getMapInstance();
|
|
@@ -23,7 +23,7 @@ class ContentTypeService {
|
|
|
23
23
|
|
|
24
24
|
const [err, result] = await safePromise(this.stackSDKInstance.contentType(id).fetch());
|
|
25
25
|
if (err) {
|
|
26
|
-
|
|
26
|
+
errorHelper(err);
|
|
27
27
|
this.base.dispatch(callsite, id, err, 'apiError');
|
|
28
28
|
throw err;
|
|
29
29
|
}
|
|
@@ -36,7 +36,7 @@ class ContentTypeService {
|
|
|
36
36
|
const data = getDataWithAction(id, mapInstance, action);
|
|
37
37
|
const [err, result] = await safePromise(this.stackSDKInstance.contentType().create(data));
|
|
38
38
|
if (err) {
|
|
39
|
-
|
|
39
|
+
errorHelper(err);
|
|
40
40
|
this.base.dispatch(callsite, id, err, 'apiError');
|
|
41
41
|
throw err;
|
|
42
42
|
}
|
|
@@ -51,7 +51,7 @@ class ContentTypeService {
|
|
|
51
51
|
const method = 'PUT';
|
|
52
52
|
const [err, result] = await safePromise(data.update());
|
|
53
53
|
if (err) {
|
|
54
|
-
|
|
54
|
+
errorHelper(err);
|
|
55
55
|
this.base.dispatch(callsite, data.uid, err, 'apiError');
|
|
56
56
|
throw err;
|
|
57
57
|
}
|
|
@@ -66,7 +66,7 @@ class ContentTypeService {
|
|
|
66
66
|
const [err, result] = await safePromise(this.stackSDKInstance.contentType(id).delete());
|
|
67
67
|
|
|
68
68
|
if (err) {
|
|
69
|
-
|
|
69
|
+
errorHelper(err);
|
|
70
70
|
this.base.dispatch(callsite, id, err, 'apiError');
|
|
71
71
|
throw err;
|
|
72
72
|
}
|
|
@@ -306,7 +306,7 @@ class ContentTypeService {
|
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
// Handling both the scenarios
|
|
309
|
-
if (
|
|
309
|
+
if (found === 0 || (against && found === 1)) {
|
|
310
310
|
isValid = false;
|
|
311
311
|
}
|
|
312
312
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const { highlight } = require('cardinal');
|
|
2
2
|
const { keys } = Object;
|
|
3
3
|
const chalk = require('chalk');
|
|
4
|
-
const isEmpty = require('lodash/isEmpty')
|
|
5
|
-
|
|
4
|
+
const isEmpty = require('lodash/isEmpty');
|
|
5
|
+
const MigrationLogger = require('./migration-logger');
|
|
6
|
+
const fs = require('fs');
|
|
6
7
|
const { readFile } = require('./fs-helper');
|
|
7
8
|
const groupBy = require('./group-by');
|
|
8
9
|
|
|
@@ -19,43 +20,86 @@ const getLineWithContext = (lines, lineNumber, context) => {
|
|
|
19
20
|
};
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
function removeSpecialCharacter(str) {
|
|
24
|
+
return str.replace(/\u001b\[\d+m/g, '');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = (errors, filePath) => {
|
|
28
|
+
const logger = new MigrationLogger(process.cwd());
|
|
29
|
+
|
|
23
30
|
const errorsByFile = groupBy(errors, 'file');
|
|
24
31
|
const messages = [];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const context = 2;
|
|
35
|
-
const { before, line, after } = getLineWithContext(lines, callsite.line, context);
|
|
36
|
-
|
|
37
|
-
const beforeLines = before.map((_line) => chalk`${_line}\n`);
|
|
38
|
-
const afterLines = after.map((_line) => chalk`${_line}\n`);
|
|
39
|
-
const highlightedLine = chalk`{bold ${line}}\n`;
|
|
40
|
-
|
|
41
|
-
const formattedCode = beforeLines + highlightedLine + afterLines;
|
|
42
|
-
if (error.payload.apiError) {
|
|
43
|
-
return chalk`{red Line ${String(callsite.line)}:} {bold ${error.payload.apiError.message}}\n${formattedCode}`;
|
|
44
|
-
}
|
|
45
|
-
if (error.message) {
|
|
46
|
-
return chalk`{red Line ${String(callsite.line)}:} {bold ${error.message}}\n${formattedCode}`;
|
|
47
|
-
}
|
|
48
|
-
return chalk`{red Line ${String(callsite.line)}:} {bold something went wrong here.}\n${formattedCode}`;
|
|
49
|
-
})
|
|
50
|
-
.join('\n');
|
|
51
|
-
|
|
52
|
-
messages.push(`${fileErrorsMessage}${errorMessages}`);
|
|
53
|
-
}
|
|
54
|
-
if (isEmpty(messages) && errors !== undefined && isEmpty(errorsByFile)) {
|
|
55
|
-
console.error('Migration error---', errors);
|
|
32
|
+
if (filePath) {
|
|
33
|
+
if (errors.request) {
|
|
34
|
+
errors.data = errors.request?.data;
|
|
35
|
+
delete errors.request;
|
|
36
|
+
}
|
|
37
|
+
if (errors.message) {
|
|
38
|
+
delete errors.message;
|
|
39
|
+
}
|
|
40
|
+
logger.log('error', { [filePath]: errors });
|
|
56
41
|
} else {
|
|
57
|
-
|
|
42
|
+
for (const file of keys(errorsByFile)) {
|
|
43
|
+
const errorLogs = {};
|
|
44
|
+
errorLogs[file] = {};
|
|
45
|
+
const fileContents = readFile(file);
|
|
46
|
+
const highlightedCode = highlight(fileContents, { linenos: true });
|
|
47
|
+
const lines = highlightedCode.split('\n');
|
|
48
|
+
|
|
49
|
+
const fileErrorsMessage = chalk`{red Errors in ${file}}\n\n`;
|
|
50
|
+
errorLogs[file].fileErrorsMessage = fileErrorsMessage.replace(/\u001b\[\d+m/g, '');
|
|
51
|
+
const errorMessages = errorsByFile[file]
|
|
52
|
+
.map((error) => {
|
|
53
|
+
const callsite = error.meta.callsite;
|
|
54
|
+
const context = 2;
|
|
55
|
+
let { before, line, after } = getLineWithContext(lines, callsite.line, context);
|
|
56
|
+
|
|
57
|
+
const beforeLines = before.map((_line) => chalk`${_line}\n`);
|
|
58
|
+
const afterLines = after.map((_line) => chalk`${_line}\n`);
|
|
59
|
+
const highlightedLine = chalk`{bold ${line}}\n`;
|
|
60
|
+
|
|
61
|
+
before = removeSpecialCharacter(before.join('\n'));
|
|
62
|
+
after = removeSpecialCharacter(after.join('\n'));
|
|
63
|
+
line = removeSpecialCharacter(line);
|
|
64
|
+
errorLogs[file].lines = { before, line, after };
|
|
65
|
+
if (error.request) {
|
|
66
|
+
error.data = error.request?.data;
|
|
67
|
+
delete error.request;
|
|
68
|
+
}
|
|
69
|
+
if (error.message) {
|
|
70
|
+
delete error.message;
|
|
71
|
+
}
|
|
72
|
+
const formattedCode = beforeLines + highlightedLine + afterLines;
|
|
73
|
+
if (error.payload?.apiError) {
|
|
74
|
+
errorLogs[file].apiError = true;
|
|
75
|
+
errorLogs[file].errorCode = error.payload.apiError.errorCode;
|
|
76
|
+
errorLogs[file].errors = error.payload.apiError.errors;
|
|
77
|
+
errorLogs[file].data = error.data;
|
|
78
|
+
}
|
|
79
|
+
if (error.message && !error.payload.apiError) {
|
|
80
|
+
errorLogs[file].apiError = false;
|
|
81
|
+
errorLogs[file].error = error.message;
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
.join('\n');
|
|
85
|
+
|
|
86
|
+
messages.push(`${fileErrorsMessage}${errorMessages}`);
|
|
87
|
+
logger.log('error', errorLogs);
|
|
88
|
+
}
|
|
89
|
+
if (errors?.request) {
|
|
90
|
+
errors.data = errors.request?.data;
|
|
91
|
+
delete errors.request;
|
|
92
|
+
}
|
|
93
|
+
if (errors?.message) {
|
|
94
|
+
delete errors.message;
|
|
95
|
+
}
|
|
96
|
+
if (isEmpty(messages) && errors !== undefined && isEmpty(errorsByFile)) {
|
|
97
|
+
logger.log('error', { errors: errors });
|
|
98
|
+
console.log(chalk`{bold.red Migration unsuccessful}`);
|
|
99
|
+
} else {
|
|
100
|
+
logger.log('error', { error: messages.join('\n') });
|
|
101
|
+
}
|
|
58
102
|
}
|
|
59
103
|
// eslint-disable-next-line
|
|
60
|
-
console.log(chalk`{bold.red Migration unsuccessful}`);
|
|
104
|
+
// console.log(chalk`{bold.red Migration unsuccessful}`);
|
|
61
105
|
};
|
package/src/utils/index.js
CHANGED
|
@@ -11,7 +11,6 @@ module.exports = {
|
|
|
11
11
|
safePromise: require('./safe-promise'),
|
|
12
12
|
getConfig: require('./get-config'),
|
|
13
13
|
successHandler: require('./success-handler'),
|
|
14
|
-
errorHandler: require('./error-handler'),
|
|
15
14
|
getCallsite: require('./callsite'),
|
|
16
15
|
errorHelper: require('./error-helper'),
|
|
17
16
|
groupBy: require('./group-by'),
|
package/src/utils/logger.js
CHANGED
|
@@ -36,7 +36,7 @@ function init(logFileName) {
|
|
|
36
36
|
const logPath = pathValidator(join(logsDir, logFileName + '.log'));
|
|
37
37
|
const logger = createLogger({
|
|
38
38
|
format: combine(colorize(), label({ label: 'Migration' }), customFormat),
|
|
39
|
-
transports: [new transports.File({ filename: logPath })
|
|
39
|
+
transports: [new transports.File({ filename: logPath })],
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
let args;
|
|
@@ -54,9 +54,9 @@ function init(logFileName) {
|
|
|
54
54
|
logString && logger.log('warn', logString);
|
|
55
55
|
},
|
|
56
56
|
error: function () {
|
|
57
|
-
args = slice.call(arguments);
|
|
58
|
-
logString = getString(args);
|
|
59
|
-
logString && logger.log('error', logString);
|
|
57
|
+
// args = slice.call(arguments);
|
|
58
|
+
// logString = getString(args);
|
|
59
|
+
// logString && logger.log('error', logString);
|
|
60
60
|
},
|
|
61
61
|
debug: function () {
|
|
62
62
|
args = slice.call(arguments);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const winston = require('winston');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
module.exports = class MigrationLogger {
|
|
4
|
+
constructor(filePath) {
|
|
5
|
+
this.filePath = path.join(filePath, 'migration-logs');
|
|
6
|
+
this.logger = winston.createLogger({
|
|
7
|
+
levels: { error: 1 },
|
|
8
|
+
transports: [
|
|
9
|
+
new winston.transports.File({
|
|
10
|
+
level: 'error',
|
|
11
|
+
filename: path.join(this.filePath, 'error.logs'),
|
|
12
|
+
format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
|
|
13
|
+
}),
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
log(level, message) {
|
|
18
|
+
this.logger.log('error', message);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { error } = require('./logger');
|
|
4
|
-
const { errorMessageHandler } = require('./constants');
|
|
5
|
-
|
|
6
|
-
module.exports = (data, type, method, err) => {
|
|
7
|
-
if (data && type && method) {
|
|
8
|
-
error(`Error occurred while ${errorMessageHandler[method]} ${type}: ${data}.`);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (err.errorMessage) {
|
|
12
|
-
error(err.errorMessage);
|
|
13
|
-
}
|
|
14
|
-
if (err instanceof Error && err && err.message && err.stack) {
|
|
15
|
-
error(err.message);
|
|
16
|
-
// error(err.stack)
|
|
17
|
-
} else {
|
|
18
|
-
error(err);
|
|
19
|
-
}
|
|
20
|
-
// throw new Error(err);
|
|
21
|
-
};
|