@contentstack/cli-utilities 1.11.0 → 1.12.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/lib/authentication-handler.js +15 -12
- package/lib/config-handler.d.ts +2 -0
- package/lib/config-handler.js +20 -0
- package/lib/constants/errorTypes.d.ts +10 -0
- package/lib/constants/errorTypes.js +13 -0
- package/lib/constants/logging.d.ts +15 -0
- package/lib/constants/logging.js +19 -0
- package/lib/interfaces/index.d.ts +35 -0
- package/lib/logger/cliErrorHandler.d.ts +64 -0
- package/lib/logger/cliErrorHandler.js +217 -0
- package/lib/logger/log.d.ts +23 -0
- package/lib/logger/log.js +52 -0
- package/lib/logger/logger.d.ts +57 -0
- package/lib/logger/logger.js +189 -0
- package/package.json +10 -10
|
@@ -49,13 +49,6 @@ class AuthenticationHandler {
|
|
|
49
49
|
}
|
|
50
50
|
async refreshAccessToken(error, maxRetryCount = 1) {
|
|
51
51
|
if (error.response && error.response.status) {
|
|
52
|
-
if (maxRetryCount >= 3) {
|
|
53
|
-
index_1.cliux.print('Max retry count reached, please login to proceed', {
|
|
54
|
-
color: 'yellow',
|
|
55
|
-
});
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
maxRetryCount++; // Increment for the next retry attempt
|
|
59
52
|
switch (error.response.status) {
|
|
60
53
|
case 401:
|
|
61
54
|
// NOTE: Refresh the token if the type is OAuth.
|
|
@@ -68,11 +61,24 @@ class AuthenticationHandler {
|
|
|
68
61
|
hostName = u.host;
|
|
69
62
|
}
|
|
70
63
|
hostName = hostName || region.cma;
|
|
71
|
-
await this.refreshToken(hostName);
|
|
72
|
-
|
|
64
|
+
const refreshed = await this.refreshToken(hostName);
|
|
65
|
+
if (refreshed) {
|
|
66
|
+
return this.refreshAccessToken(error, maxRetryCount); // Retry after refreshing the token
|
|
67
|
+
}
|
|
68
|
+
console.log('API(401) case error:-', error.response);
|
|
69
|
+
// For Basic Auth, exit immediately without retrying
|
|
70
|
+
return;
|
|
73
71
|
}
|
|
72
|
+
break;
|
|
74
73
|
case 429:
|
|
75
74
|
case 408:
|
|
75
|
+
if (maxRetryCount >= 3) {
|
|
76
|
+
index_1.cliux.print('Max retry count reached, please login to proceed', {
|
|
77
|
+
color: 'yellow',
|
|
78
|
+
});
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
maxRetryCount++; // Increment for the next retry attempt
|
|
76
82
|
// These cases require a wait, adding a delay before retrying
|
|
77
83
|
await new Promise((resolve) => setTimeout(resolve, 1000)); // wait for 1 second
|
|
78
84
|
return this.refreshAccessToken(error, maxRetryCount); // Retry
|
|
@@ -84,8 +90,6 @@ class AuthenticationHandler {
|
|
|
84
90
|
refreshToken(hostName) {
|
|
85
91
|
return new Promise((resolve) => {
|
|
86
92
|
if (this.authType === 'BASIC') {
|
|
87
|
-
// NOTE Handle basic auth 401 here
|
|
88
|
-
resolve(false);
|
|
89
93
|
index_1.cliux.print('Session timed out, please login to proceed', {
|
|
90
94
|
color: 'yellow',
|
|
91
95
|
});
|
|
@@ -106,7 +110,6 @@ class AuthenticationHandler {
|
|
|
106
110
|
});
|
|
107
111
|
}
|
|
108
112
|
else {
|
|
109
|
-
resolve(false);
|
|
110
113
|
index_1.cliux.print('You do not have the permissions to perform this action, please login to proceed', {
|
|
111
114
|
color: 'yellow',
|
|
112
115
|
});
|
package/lib/config-handler.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ declare class Config {
|
|
|
5
5
|
init(): Conf<Record<string, unknown>>;
|
|
6
6
|
importOldConfig(): void;
|
|
7
7
|
setOldConfigStoreData(data: any, _path?: string): void;
|
|
8
|
+
isConfigFileValid(configPath: string): boolean;
|
|
9
|
+
safeDeleteConfigIfInvalid(configFilePath: string): void;
|
|
8
10
|
removeOldConfigStoreFile(): void;
|
|
9
11
|
private getOldConfig;
|
|
10
12
|
private fallbackInit;
|
package/lib/config-handler.js
CHANGED
|
@@ -56,6 +56,22 @@ class Config {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
+
isConfigFileValid(configPath) {
|
|
60
|
+
try {
|
|
61
|
+
const content = (0, fs_1.readFileSync)(configPath, 'utf8');
|
|
62
|
+
JSON.parse(content);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
safeDeleteConfigIfInvalid(configFilePath) {
|
|
70
|
+
if ((0, fs_1.existsSync)(configFilePath) && !this.isConfigFileValid(configFilePath)) {
|
|
71
|
+
console.warn(chalk_1.default.yellow(`Warning: Detected corrupted config at ${configFilePath}. Removing...`));
|
|
72
|
+
(0, fs_1.unlinkSync)(configFilePath);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
59
75
|
removeOldConfigStoreFile() {
|
|
60
76
|
if ((0, fs_1.existsSync)(oldConfigPath)) {
|
|
61
77
|
(0, fs_1.unlinkSync)(oldConfigPath); // NOTE remove old configstore file
|
|
@@ -98,6 +114,7 @@ class Config {
|
|
|
98
114
|
try {
|
|
99
115
|
// NOTE reading current code base encrypted file if exist
|
|
100
116
|
const encryptionKey = this.getObfuscationKey();
|
|
117
|
+
this.safeDeleteConfigIfInvalid(oldConfigPath);
|
|
101
118
|
this.config = new conf_1.default({ configName: CONFIG_NAME, encryptionKey, cwd });
|
|
102
119
|
if ((_a = Object.keys(configData || {})) === null || _a === void 0 ? void 0 : _a.length) {
|
|
103
120
|
this.config.set(configData); // NOTE set config data if passed any
|
|
@@ -119,6 +136,7 @@ class Config {
|
|
|
119
136
|
};
|
|
120
137
|
try {
|
|
121
138
|
if (skip === false) {
|
|
139
|
+
this.safeDeleteConfigIfInvalid(oldConfigPath);
|
|
122
140
|
const config = new conf_1.default({ configName: CONFIG_NAME });
|
|
123
141
|
const oldConfigData = this.getConfigDataAndUnlinkConfigFile(config);
|
|
124
142
|
this.getEncryptedConfig(oldConfigData, true);
|
|
@@ -137,6 +155,7 @@ class Config {
|
|
|
137
155
|
getDecryptedConfig(configData) {
|
|
138
156
|
var _a;
|
|
139
157
|
try {
|
|
158
|
+
this.safeDeleteConfigIfInvalid(oldConfigPath);
|
|
140
159
|
this.config = new conf_1.default({ configName: CONFIG_NAME, cwd });
|
|
141
160
|
if ((_a = Object.keys(configData || {})) === null || _a === void 0 ? void 0 : _a.length) {
|
|
142
161
|
this.config.set(configData); // NOTE set config data if passed any
|
|
@@ -146,6 +165,7 @@ class Config {
|
|
|
146
165
|
// console.trace(error.message)
|
|
147
166
|
try {
|
|
148
167
|
const encryptionKey = this.getObfuscationKey();
|
|
168
|
+
this.safeDeleteConfigIfInvalid(oldConfigPath);
|
|
149
169
|
let config = new conf_1.default({ configName: CONFIG_NAME, encryptionKey, cwd });
|
|
150
170
|
const oldConfigData = this.getConfigDataAndUnlinkConfigFile(config);
|
|
151
171
|
this.getDecryptedConfig(oldConfigData); // NOTE NOTE reinitialize the config with old data and new decrypted file
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const ERROR_TYPES: {
|
|
2
|
+
readonly NETWORK: "NETWORK_ERROR";
|
|
3
|
+
readonly DATABASE: "DATABASE_ERROR";
|
|
4
|
+
readonly APPLICATION: "APPLICATION_ERROR";
|
|
5
|
+
readonly UNKNOWN: "UNKNOWN_ERROR";
|
|
6
|
+
readonly NORMALIZATION: "NORMALIZATION_ERROR";
|
|
7
|
+
readonly API_RESPONSE: "API_RESPONSE_DATA";
|
|
8
|
+
readonly API_ERROR: "API_ERROR";
|
|
9
|
+
readonly SERVER_ERROR: "SERVER_ERROR";
|
|
10
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ERROR_TYPES = void 0;
|
|
4
|
+
exports.ERROR_TYPES = {
|
|
5
|
+
NETWORK: 'NETWORK_ERROR',
|
|
6
|
+
DATABASE: 'DATABASE_ERROR',
|
|
7
|
+
APPLICATION: 'APPLICATION_ERROR',
|
|
8
|
+
UNKNOWN: 'UNKNOWN_ERROR',
|
|
9
|
+
NORMALIZATION: 'NORMALIZATION_ERROR',
|
|
10
|
+
API_RESPONSE: 'API_RESPONSE_DATA',
|
|
11
|
+
API_ERROR: 'API_ERROR',
|
|
12
|
+
SERVER_ERROR: 'SERVER_ERROR',
|
|
13
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const logLevels: {
|
|
2
|
+
readonly error: 0;
|
|
3
|
+
readonly warn: 1;
|
|
4
|
+
readonly info: 2;
|
|
5
|
+
readonly success: 2;
|
|
6
|
+
readonly debug: 3;
|
|
7
|
+
readonly verbose: 4;
|
|
8
|
+
};
|
|
9
|
+
export declare const levelColors: {
|
|
10
|
+
error: string;
|
|
11
|
+
warn: string;
|
|
12
|
+
success: string;
|
|
13
|
+
info: string;
|
|
14
|
+
debug: string;
|
|
15
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.levelColors = exports.logLevels = void 0;
|
|
4
|
+
exports.logLevels = {
|
|
5
|
+
error: 0,
|
|
6
|
+
warn: 1,
|
|
7
|
+
info: 2,
|
|
8
|
+
success: 2,
|
|
9
|
+
debug: 3,
|
|
10
|
+
verbose: 4
|
|
11
|
+
};
|
|
12
|
+
// 2. Create color mappings (for console only)
|
|
13
|
+
exports.levelColors = {
|
|
14
|
+
error: 'red',
|
|
15
|
+
warn: 'yellow',
|
|
16
|
+
success: 'green',
|
|
17
|
+
info: 'blue',
|
|
18
|
+
debug: 'white'
|
|
19
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logLevels } from "../constants/logging";
|
|
1
2
|
export interface IPromptOptions {
|
|
2
3
|
prompt?: string;
|
|
3
4
|
type?: 'normal' | 'mask' | 'hide' | 'single';
|
|
@@ -62,3 +63,37 @@ export interface Locale {
|
|
|
62
63
|
}
|
|
63
64
|
export interface CliUXPromptOptions extends IPromptOptions {
|
|
64
65
|
}
|
|
66
|
+
export interface LoggerConfig {
|
|
67
|
+
basePath: string;
|
|
68
|
+
processName?: string;
|
|
69
|
+
consoleLoggingEnabled?: boolean;
|
|
70
|
+
consoleLogLevel?: LogType;
|
|
71
|
+
logLevel?: LogType;
|
|
72
|
+
}
|
|
73
|
+
export interface PrintOptions {
|
|
74
|
+
bold?: boolean;
|
|
75
|
+
color?: string;
|
|
76
|
+
}
|
|
77
|
+
export type LogType = 'info' | 'warn' | 'error' | 'debug';
|
|
78
|
+
export type LogsType = LogType | PrintOptions | undefined;
|
|
79
|
+
export type MessageType = string | Error | Record<string, any> | Record<string, any>[];
|
|
80
|
+
export type LogLevel = keyof typeof logLevels;
|
|
81
|
+
export type ClassifiedError = {
|
|
82
|
+
type: string;
|
|
83
|
+
message: string;
|
|
84
|
+
error: Record<string, any>;
|
|
85
|
+
debug?: Record<string, any>;
|
|
86
|
+
meta?: Record<string, string | undefined>;
|
|
87
|
+
context?: string;
|
|
88
|
+
hidden?: boolean;
|
|
89
|
+
};
|
|
90
|
+
export type ErrorContext = {
|
|
91
|
+
operation?: string;
|
|
92
|
+
component?: string;
|
|
93
|
+
userId?: string;
|
|
94
|
+
requestId?: string;
|
|
95
|
+
email?: string;
|
|
96
|
+
sessionId?: string;
|
|
97
|
+
orgId?: string;
|
|
98
|
+
apiKey?: string;
|
|
99
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ClassifiedError, ErrorContext } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Handles errors in a CLI application by classifying, normalizing, and extracting
|
|
4
|
+
* relevant information for debugging and logging purposes.
|
|
5
|
+
*
|
|
6
|
+
* This class provides methods to:
|
|
7
|
+
* - Normalize unknown error types into standard `Error` objects.
|
|
8
|
+
* - Classify errors into predefined categories such as API errors, network errors,
|
|
9
|
+
* server errors, and more.
|
|
10
|
+
* - Extract detailed error payloads for logging, including HTTP request and response
|
|
11
|
+
* details when applicable.
|
|
12
|
+
* - Identify sensitive information in error messages to prevent accidental exposure.
|
|
13
|
+
* - Generate debug payloads for enhanced troubleshooting when debugging is enabled.
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This class is designed to handle a wide range of error types, including generic
|
|
17
|
+
* JavaScript errors, API errors, and custom error objects. It also supports
|
|
18
|
+
* optional debugging and context metadata for enhanced error reporting.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const errorHandler = new CLIErrorHandler(true);
|
|
23
|
+
*
|
|
24
|
+
* try {
|
|
25
|
+
* // Some operation that may throw an error
|
|
26
|
+
* } catch (error) {
|
|
27
|
+
* const classifiedError = errorHandler.classifyError(error, {
|
|
28
|
+
* operation: 'fetchData',
|
|
29
|
+
* component: 'DataService',
|
|
30
|
+
* });
|
|
31
|
+
* console.error(classifiedError);
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export default class CLIErrorHandler {
|
|
38
|
+
private isDebug;
|
|
39
|
+
constructor(isDebug?: boolean);
|
|
40
|
+
/**
|
|
41
|
+
* Classifies an error into a structured format for better handling and debugging.
|
|
42
|
+
*
|
|
43
|
+
* @param error - The error object to classify. Can be of any type.
|
|
44
|
+
* @param context - Optional additional context about the error, typically used to provide
|
|
45
|
+
* more information about where or why the error occurred.
|
|
46
|
+
*
|
|
47
|
+
* @returns A `ClassifiedError` object containing details about the error, including its type,
|
|
48
|
+
* message, payload, context, metadata, and whether it contains sensitive information.
|
|
49
|
+
* If the error is an API error or debugging is enabled, additional debug information
|
|
50
|
+
* is included.
|
|
51
|
+
*
|
|
52
|
+
* @throws This method handles its own errors and will return a `ClassifiedError` with type
|
|
53
|
+
* `ERROR_TYPES.NORMALIZATION` if it fails to normalize or classify the input error.
|
|
54
|
+
*/
|
|
55
|
+
classifyError(error: unknown, context?: ErrorContext): ClassifiedError;
|
|
56
|
+
private normalizeToError;
|
|
57
|
+
private isApiError;
|
|
58
|
+
private determineErrorType;
|
|
59
|
+
private extractErrorPayload;
|
|
60
|
+
private extractDebugPayload;
|
|
61
|
+
private extractMeta;
|
|
62
|
+
private containsSensitiveInfo;
|
|
63
|
+
}
|
|
64
|
+
export { CLIErrorHandler };
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLIErrorHandler = void 0;
|
|
4
|
+
const helpers_1 = require("../helpers");
|
|
5
|
+
const errorTypes_1 = require("../constants/errorTypes");
|
|
6
|
+
/**
|
|
7
|
+
* Handles errors in a CLI application by classifying, normalizing, and extracting
|
|
8
|
+
* relevant information for debugging and logging purposes.
|
|
9
|
+
*
|
|
10
|
+
* This class provides methods to:
|
|
11
|
+
* - Normalize unknown error types into standard `Error` objects.
|
|
12
|
+
* - Classify errors into predefined categories such as API errors, network errors,
|
|
13
|
+
* server errors, and more.
|
|
14
|
+
* - Extract detailed error payloads for logging, including HTTP request and response
|
|
15
|
+
* details when applicable.
|
|
16
|
+
* - Identify sensitive information in error messages to prevent accidental exposure.
|
|
17
|
+
* - Generate debug payloads for enhanced troubleshooting when debugging is enabled.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* This class is designed to handle a wide range of error types, including generic
|
|
21
|
+
* JavaScript errors, API errors, and custom error objects. It also supports
|
|
22
|
+
* optional debugging and context metadata for enhanced error reporting.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const errorHandler = new CLIErrorHandler(true);
|
|
27
|
+
*
|
|
28
|
+
* try {
|
|
29
|
+
* // Some operation that may throw an error
|
|
30
|
+
* } catch (error) {
|
|
31
|
+
* const classifiedError = errorHandler.classifyError(error, {
|
|
32
|
+
* operation: 'fetchData',
|
|
33
|
+
* component: 'DataService',
|
|
34
|
+
* });
|
|
35
|
+
* console.error(classifiedError);
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
class CLIErrorHandler {
|
|
42
|
+
constructor(isDebug = false) {
|
|
43
|
+
this.isDebug = isDebug;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Classifies an error into a structured format for better handling and debugging.
|
|
47
|
+
*
|
|
48
|
+
* @param error - The error object to classify. Can be of any type.
|
|
49
|
+
* @param context - Optional additional context about the error, typically used to provide
|
|
50
|
+
* more information about where or why the error occurred.
|
|
51
|
+
*
|
|
52
|
+
* @returns A `ClassifiedError` object containing details about the error, including its type,
|
|
53
|
+
* message, payload, context, metadata, and whether it contains sensitive information.
|
|
54
|
+
* If the error is an API error or debugging is enabled, additional debug information
|
|
55
|
+
* is included.
|
|
56
|
+
*
|
|
57
|
+
* @throws This method handles its own errors and will return a `ClassifiedError` with type
|
|
58
|
+
* `ERROR_TYPES.NORMALIZATION` if it fails to normalize or classify the input error.
|
|
59
|
+
*/
|
|
60
|
+
classifyError(error, context) {
|
|
61
|
+
try {
|
|
62
|
+
const normalized = this.normalizeToError(error);
|
|
63
|
+
const isApi = this.isApiError(normalized);
|
|
64
|
+
const type = this.determineErrorType(normalized);
|
|
65
|
+
const hidden = this.containsSensitiveInfo(normalized);
|
|
66
|
+
const result = {
|
|
67
|
+
type,
|
|
68
|
+
message: normalized.message || 'Unhandled error',
|
|
69
|
+
error: this.extractErrorPayload(normalized),
|
|
70
|
+
context: context ? JSON.stringify(context) : undefined,
|
|
71
|
+
meta: this.extractMeta(context),
|
|
72
|
+
hidden,
|
|
73
|
+
};
|
|
74
|
+
if (isApi || this.isDebug) {
|
|
75
|
+
result.debug = this.extractDebugPayload(normalized, context);
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
return {
|
|
81
|
+
type: errorTypes_1.ERROR_TYPES.NORMALIZATION,
|
|
82
|
+
message: 'Failed to normalize or classify error',
|
|
83
|
+
error: { message: String(e) },
|
|
84
|
+
context: context ? JSON.stringify(context) : undefined,
|
|
85
|
+
meta: this.extractMeta(context),
|
|
86
|
+
hidden: false,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
normalizeToError(error) {
|
|
91
|
+
if (!error)
|
|
92
|
+
return new Error('Unknown error occurred');
|
|
93
|
+
if (error instanceof Error)
|
|
94
|
+
return error;
|
|
95
|
+
if (typeof error === 'string')
|
|
96
|
+
return new Error(error);
|
|
97
|
+
if (typeof error === 'object') {
|
|
98
|
+
try {
|
|
99
|
+
const msg = error.message;
|
|
100
|
+
const err = new Error(msg || 'Unknown error');
|
|
101
|
+
Object.assign(err, error);
|
|
102
|
+
return err;
|
|
103
|
+
}
|
|
104
|
+
catch (_a) {
|
|
105
|
+
return new Error(JSON.stringify(error));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return new Error(String(error));
|
|
109
|
+
}
|
|
110
|
+
isApiError(error) {
|
|
111
|
+
return (error.isAxiosError ||
|
|
112
|
+
typeof error.status === 'number' ||
|
|
113
|
+
typeof error.statusText === 'string' ||
|
|
114
|
+
error.request !== undefined);
|
|
115
|
+
}
|
|
116
|
+
determineErrorType(error) {
|
|
117
|
+
var _a;
|
|
118
|
+
const status = error.status || ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status);
|
|
119
|
+
//Ignore 4XX errors
|
|
120
|
+
if (status >= 400 && status < 500) {
|
|
121
|
+
return errorTypes_1.ERROR_TYPES.API_ERROR;
|
|
122
|
+
}
|
|
123
|
+
//Server-side HTTP errors
|
|
124
|
+
if (status >= 500) {
|
|
125
|
+
return errorTypes_1.ERROR_TYPES.SERVER_ERROR;
|
|
126
|
+
}
|
|
127
|
+
//Network-related error
|
|
128
|
+
if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND' || error.code === 'ETIMEDOUT') {
|
|
129
|
+
return errorTypes_1.ERROR_TYPES.NETWORK;
|
|
130
|
+
}
|
|
131
|
+
//Database error
|
|
132
|
+
if (error.name === 'DatabaseError') {
|
|
133
|
+
return errorTypes_1.ERROR_TYPES.DATABASE;
|
|
134
|
+
}
|
|
135
|
+
//Axios errors without 4XX
|
|
136
|
+
if (error.isAxiosError) {
|
|
137
|
+
return errorTypes_1.ERROR_TYPES.NETWORK;
|
|
138
|
+
}
|
|
139
|
+
//Default
|
|
140
|
+
return errorTypes_1.ERROR_TYPES.APPLICATION;
|
|
141
|
+
}
|
|
142
|
+
extractErrorPayload(error) {
|
|
143
|
+
var _a, _b, _c, _d, _e, _f;
|
|
144
|
+
const code = error.code || error.errorCode;
|
|
145
|
+
const status = error.status || ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status);
|
|
146
|
+
const statusText = error.statusText || ((_b = error.response) === null || _b === void 0 ? void 0 : _b.statusText);
|
|
147
|
+
const method = ((_c = error.request) === null || _c === void 0 ? void 0 : _c.method) || ((_d = error.config) === null || _d === void 0 ? void 0 : _d.method) || 'UNKNOWN';
|
|
148
|
+
const url = ((_e = error.request) === null || _e === void 0 ? void 0 : _e.url) || ((_f = error.config) === null || _f === void 0 ? void 0 : _f.url);
|
|
149
|
+
const endpoint = url ? new URL(url, 'http://dummy').pathname : 'UNKNOWN';
|
|
150
|
+
const payload = {
|
|
151
|
+
name: error.name,
|
|
152
|
+
message: (0, helpers_1.formatError)(error),
|
|
153
|
+
code,
|
|
154
|
+
status,
|
|
155
|
+
statusText,
|
|
156
|
+
method,
|
|
157
|
+
endpoint,
|
|
158
|
+
};
|
|
159
|
+
if (this.isDebug) {
|
|
160
|
+
payload.stack = error.stack;
|
|
161
|
+
}
|
|
162
|
+
return payload;
|
|
163
|
+
}
|
|
164
|
+
extractDebugPayload(error, context) {
|
|
165
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
166
|
+
const method = ((_a = error.request) === null || _a === void 0 ? void 0 : _a.method) || ((_b = error.config) === null || _b === void 0 ? void 0 : _b.method);
|
|
167
|
+
const url = ((_c = error.request) === null || _c === void 0 ? void 0 : _c.url) || ((_d = error.config) === null || _d === void 0 ? void 0 : _d.url);
|
|
168
|
+
const status = error.status || ((_e = error.response) === null || _e === void 0 ? void 0 : _e.status);
|
|
169
|
+
const statusText = error.statusText || ((_f = error.response) === null || _f === void 0 ? void 0 : _f.statusText);
|
|
170
|
+
const data = error.data || ((_g = error.response) === null || _g === void 0 ? void 0 : _g.data) || error.errors || error.error;
|
|
171
|
+
return {
|
|
172
|
+
command: context === null || context === void 0 ? void 0 : context.operation,
|
|
173
|
+
module: context === null || context === void 0 ? void 0 : context.component,
|
|
174
|
+
request: {
|
|
175
|
+
method,
|
|
176
|
+
url,
|
|
177
|
+
headers: (_h = error.request) === null || _h === void 0 ? void 0 : _h.headers,
|
|
178
|
+
data: (_j = error.request) === null || _j === void 0 ? void 0 : _j.data,
|
|
179
|
+
},
|
|
180
|
+
response: {
|
|
181
|
+
status,
|
|
182
|
+
statusText,
|
|
183
|
+
data,
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
extractMeta(context) {
|
|
188
|
+
return {
|
|
189
|
+
email: context === null || context === void 0 ? void 0 : context.email,
|
|
190
|
+
sessionId: context === null || context === void 0 ? void 0 : context.sessionId,
|
|
191
|
+
userId: context === null || context === void 0 ? void 0 : context.userId,
|
|
192
|
+
apiKey: context === null || context === void 0 ? void 0 : context.apiKey,
|
|
193
|
+
orgId: context === null || context === void 0 ? void 0 : context.orgId,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
containsSensitiveInfo(error) {
|
|
197
|
+
try {
|
|
198
|
+
const content = `${error.message} ${error.stack || ''}`.toLowerCase();
|
|
199
|
+
return [
|
|
200
|
+
'password',
|
|
201
|
+
'token',
|
|
202
|
+
'secret',
|
|
203
|
+
'credentials',
|
|
204
|
+
'api_key',
|
|
205
|
+
'api-key',
|
|
206
|
+
'authorization',
|
|
207
|
+
'sessionid',
|
|
208
|
+
'email',
|
|
209
|
+
].some((term) => content.includes(term));
|
|
210
|
+
}
|
|
211
|
+
catch (_a) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
exports.default = CLIErrorHandler;
|
|
217
|
+
exports.CLIErrorHandler = CLIErrorHandler;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { default as Logger } from './logger';
|
|
2
|
+
import { CLIErrorHandler } from './cliErrorHandler';
|
|
3
|
+
import { ErrorContext } from '../interfaces';
|
|
4
|
+
declare const v2Logger: Logger;
|
|
5
|
+
declare const cliErrorHandler: CLIErrorHandler;
|
|
6
|
+
/**
|
|
7
|
+
* Handles and logs an error by classifying it and logging the relevant details.
|
|
8
|
+
*
|
|
9
|
+
* This function uses the `cliErrorHandler` to classify the provided error and logs
|
|
10
|
+
* the error details using `v2Logger`. If debug information is available, it logs
|
|
11
|
+
* additional debug details, including a stack trace if not already present.
|
|
12
|
+
*
|
|
13
|
+
* @param error - The error to be handled and logged. Can be of any type.
|
|
14
|
+
* @param context - Optional context information to assist in error classification
|
|
15
|
+
* and logging.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* - The error is always logged with its type, message, and other metadata.
|
|
19
|
+
* - If debug information is available, it is logged separately with a more specific
|
|
20
|
+
* debug type and additional details.
|
|
21
|
+
*/
|
|
22
|
+
declare function handleAndLogError(error: unknown, context?: ErrorContext): void;
|
|
23
|
+
export { v2Logger, cliErrorHandler, handleAndLogError };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleAndLogError = exports.cliErrorHandler = exports.v2Logger = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
6
|
+
const logger_1 = tslib_1.__importDefault(require("./logger"));
|
|
7
|
+
const cliErrorHandler_1 = require("./cliErrorHandler");
|
|
8
|
+
const v2Logger = new logger_1.default({ basePath: process.env.CS_CLI_LOG_PATH || path.join(process.cwd(), 'logs') });
|
|
9
|
+
exports.v2Logger = v2Logger;
|
|
10
|
+
const cliErrorHandler = new cliErrorHandler_1.CLIErrorHandler(true); // Enable debug mode for error classification
|
|
11
|
+
exports.cliErrorHandler = cliErrorHandler;
|
|
12
|
+
/**
|
|
13
|
+
* Handles and logs an error by classifying it and logging the relevant details.
|
|
14
|
+
*
|
|
15
|
+
* This function uses the `cliErrorHandler` to classify the provided error and logs
|
|
16
|
+
* the error details using `v2Logger`. If debug information is available, it logs
|
|
17
|
+
* additional debug details, including a stack trace if not already present.
|
|
18
|
+
*
|
|
19
|
+
* @param error - The error to be handled and logged. Can be of any type.
|
|
20
|
+
* @param context - Optional context information to assist in error classification
|
|
21
|
+
* and logging.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* - The error is always logged with its type, message, and other metadata.
|
|
25
|
+
* - If debug information is available, it is logged separately with a more specific
|
|
26
|
+
* debug type and additional details.
|
|
27
|
+
*/
|
|
28
|
+
function handleAndLogError(error, context) {
|
|
29
|
+
const classified = cliErrorHandler.classifyError(error, context);
|
|
30
|
+
// Always log the error
|
|
31
|
+
v2Logger.logError({
|
|
32
|
+
type: classified.type,
|
|
33
|
+
message: classified.message,
|
|
34
|
+
error: classified.error,
|
|
35
|
+
context: classified.context,
|
|
36
|
+
hidden: classified.hidden,
|
|
37
|
+
meta: classified.meta,
|
|
38
|
+
});
|
|
39
|
+
// Log debug information if available
|
|
40
|
+
if (classified.debug) {
|
|
41
|
+
v2Logger.logDebug({
|
|
42
|
+
type: `${classified.type}_DEBUG`,
|
|
43
|
+
message: `${classified.message} [DEBUG]`,
|
|
44
|
+
debug: Object.assign(Object.assign({}, classified.debug), {
|
|
45
|
+
// Ensure stack trace is included if not already there
|
|
46
|
+
stackTrace: classified.debug.stackTrace || classified.error.stack }),
|
|
47
|
+
context: classified.context,
|
|
48
|
+
meta: classified.meta,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.handleAndLogError = handleAndLogError;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as winston from 'winston';
|
|
2
|
+
import { LoggerConfig } from '../interfaces/index';
|
|
3
|
+
export default class Logger {
|
|
4
|
+
private loggers;
|
|
5
|
+
private config;
|
|
6
|
+
private sensitiveKeys;
|
|
7
|
+
constructor(config: LoggerConfig);
|
|
8
|
+
getLoggerInstance(level?: 'error' | 'info' | 'warn' | 'debug' | 'hidden'): winston.Logger;
|
|
9
|
+
private get loggerOptions();
|
|
10
|
+
private createLogger;
|
|
11
|
+
private isSensitiveKey;
|
|
12
|
+
private redactObject;
|
|
13
|
+
private redact;
|
|
14
|
+
private isLogEntry;
|
|
15
|
+
private shouldLog;
|
|
16
|
+
error(message: string, meta?: any): void;
|
|
17
|
+
warn(message: string, meta?: any): void;
|
|
18
|
+
info(message: string, meta?: any): void;
|
|
19
|
+
success(message: string, meta?: any): void;
|
|
20
|
+
debug(message: string, meta?: any): void;
|
|
21
|
+
logError(params: {
|
|
22
|
+
type: string;
|
|
23
|
+
message: string;
|
|
24
|
+
error: any;
|
|
25
|
+
context?: string;
|
|
26
|
+
hidden?: boolean;
|
|
27
|
+
meta?: Record<string, any>;
|
|
28
|
+
}): void;
|
|
29
|
+
logWarn(params: {
|
|
30
|
+
type: string;
|
|
31
|
+
message: string;
|
|
32
|
+
warn?: any;
|
|
33
|
+
context?: string;
|
|
34
|
+
meta?: Record<string, any>;
|
|
35
|
+
}): void;
|
|
36
|
+
logInfo(params: {
|
|
37
|
+
type: string;
|
|
38
|
+
message: string;
|
|
39
|
+
info?: any;
|
|
40
|
+
context?: string;
|
|
41
|
+
meta?: Record<string, any>;
|
|
42
|
+
}): void;
|
|
43
|
+
logSuccess(params: {
|
|
44
|
+
type: string;
|
|
45
|
+
message: string;
|
|
46
|
+
data?: any;
|
|
47
|
+
context?: string;
|
|
48
|
+
meta?: Record<string, any>;
|
|
49
|
+
}): void;
|
|
50
|
+
logDebug(params: {
|
|
51
|
+
type: string;
|
|
52
|
+
message: string;
|
|
53
|
+
debug?: any;
|
|
54
|
+
context?: string;
|
|
55
|
+
meta?: Record<string, any>;
|
|
56
|
+
}): void;
|
|
57
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const traverse_1 = tslib_1.__importDefault(require("traverse"));
|
|
5
|
+
const full_1 = require("klona/full");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const winston = tslib_1.__importStar(require("winston"));
|
|
8
|
+
const logging_1 = require("../constants/logging");
|
|
9
|
+
class Logger {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.sensitiveKeys = [
|
|
12
|
+
/authtoken/i,
|
|
13
|
+
/^email$/i,
|
|
14
|
+
/^password$/i,
|
|
15
|
+
/secret/i,
|
|
16
|
+
/token/i,
|
|
17
|
+
/api[-._]?key/i,
|
|
18
|
+
/management[-._]?token/i,
|
|
19
|
+
/sessionid/i,
|
|
20
|
+
/orgid/i,
|
|
21
|
+
];
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.loggers = {
|
|
24
|
+
error: this.getLoggerInstance('error'),
|
|
25
|
+
warn: this.getLoggerInstance('warn'),
|
|
26
|
+
info: this.getLoggerInstance('info'),
|
|
27
|
+
debug: this.getLoggerInstance('debug'),
|
|
28
|
+
success: this.getLoggerInstance('info'), // Map success to info
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
getLoggerInstance(level = 'info') {
|
|
32
|
+
const filePath = (0, path_1.normalize)(process.env.CS_CLI_LOG_PATH || this.config.basePath).replace(/^(\.\.(\/|\\|$))+/, '');
|
|
33
|
+
if (level === 'hidden') {
|
|
34
|
+
return this.createLogger('error', filePath);
|
|
35
|
+
}
|
|
36
|
+
return this.createLogger(level, filePath);
|
|
37
|
+
}
|
|
38
|
+
get loggerOptions() {
|
|
39
|
+
return {
|
|
40
|
+
filename: '',
|
|
41
|
+
maxFiles: 20,
|
|
42
|
+
tailable: true,
|
|
43
|
+
maxsize: 1000000,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
createLogger(level, filePath) {
|
|
47
|
+
return winston.createLogger({
|
|
48
|
+
levels: logging_1.logLevels,
|
|
49
|
+
level: level,
|
|
50
|
+
transports: [
|
|
51
|
+
new winston.transports.File(Object.assign(Object.assign({}, this.loggerOptions), { filename: `${filePath}/${level}.log`, format: winston.format.combine(winston.format.timestamp(), winston.format.json()) })),
|
|
52
|
+
new winston.transports.Console({
|
|
53
|
+
format: winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.printf((info) => {
|
|
54
|
+
const colorizer = winston.format.colorize();
|
|
55
|
+
const levelText = info.level.toUpperCase();
|
|
56
|
+
const timestamp = info.timestamp;
|
|
57
|
+
const message = info.message;
|
|
58
|
+
const meta = info.meta;
|
|
59
|
+
let fullLine = `[${timestamp}] ${levelText}: ${message}`;
|
|
60
|
+
if (meta && (info.level !== 'info' && info.level !== 'success')) {
|
|
61
|
+
const redactedMeta = this.isLogEntry(meta) ? JSON.stringify(this.redact(meta)) : JSON.stringify(this.redact(meta));
|
|
62
|
+
fullLine += ` - ${redactedMeta}`;
|
|
63
|
+
}
|
|
64
|
+
return colorizer.colorize(info.level, fullLine);
|
|
65
|
+
})),
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
isSensitiveKey(keyStr) {
|
|
71
|
+
return keyStr && typeof keyStr === 'string'
|
|
72
|
+
? this.sensitiveKeys.some((regex) => regex.test(keyStr))
|
|
73
|
+
: false;
|
|
74
|
+
}
|
|
75
|
+
redactObject(obj) {
|
|
76
|
+
const self = this;
|
|
77
|
+
(0, traverse_1.default)(obj).forEach(function redactor() {
|
|
78
|
+
if (this.key && self.isSensitiveKey(this.key)) {
|
|
79
|
+
this.update('[REDACTED]');
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
redact(info) {
|
|
84
|
+
try {
|
|
85
|
+
const copy = (0, full_1.klona)(info);
|
|
86
|
+
this.redactObject(copy);
|
|
87
|
+
const splat = copy[Symbol.for('splat')];
|
|
88
|
+
if (splat)
|
|
89
|
+
this.redactObject(splat);
|
|
90
|
+
return copy;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return info;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
isLogEntry(obj) {
|
|
97
|
+
return typeof obj === 'object' && 'level' in obj && 'message' in obj;
|
|
98
|
+
}
|
|
99
|
+
shouldLog(level, target) {
|
|
100
|
+
const configLevel = target === 'console' ? this.config.consoleLogLevel : this.config.logLevel;
|
|
101
|
+
const minLevel = configLevel ? logging_1.logLevels[configLevel] : 2; // default: info
|
|
102
|
+
const entryLevel = logging_1.logLevels[level];
|
|
103
|
+
return entryLevel <= minLevel;
|
|
104
|
+
}
|
|
105
|
+
/* === Public Log Methods === */
|
|
106
|
+
error(message, meta) {
|
|
107
|
+
if (this.shouldLog('error', 'console') || this.shouldLog('error', 'file')) {
|
|
108
|
+
this.loggers.error.error(message, meta);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
warn(message, meta) {
|
|
112
|
+
if (this.shouldLog('warn', 'console') || this.shouldLog('warn', 'file')) {
|
|
113
|
+
this.loggers.warn.warn(message, meta);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
info(message, meta) {
|
|
117
|
+
if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) {
|
|
118
|
+
this.loggers.info.info(message, meta);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
success(message, meta) {
|
|
122
|
+
if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) {
|
|
123
|
+
this.loggers.success.info(message, Object.assign(Object.assign({}, meta), { type: 'success' }));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
debug(message, meta) {
|
|
127
|
+
if (this.shouldLog('debug', 'console') || this.shouldLog('debug', 'file')) {
|
|
128
|
+
this.loggers.debug.debug(message, meta);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/* === Structured Logging === */
|
|
132
|
+
logError(params) {
|
|
133
|
+
const logPayload = {
|
|
134
|
+
level: logging_1.logLevels.error,
|
|
135
|
+
message: params.message,
|
|
136
|
+
timestamp: new Date(),
|
|
137
|
+
meta: Object.assign({ type: params.type, error: params.error, context: params.context }, params.meta),
|
|
138
|
+
};
|
|
139
|
+
const targetLevel = params.hidden ? 'debug' : 'error';
|
|
140
|
+
if (this.shouldLog(targetLevel, 'console') || this.shouldLog(targetLevel, 'file')) {
|
|
141
|
+
this.loggers[targetLevel].error(logPayload);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
logWarn(params) {
|
|
145
|
+
const logPayload = {
|
|
146
|
+
level: logging_1.logLevels.warn,
|
|
147
|
+
message: params.message,
|
|
148
|
+
timestamp: new Date(),
|
|
149
|
+
meta: Object.assign({ type: params.type, context: params.context }, params.meta),
|
|
150
|
+
};
|
|
151
|
+
if (this.shouldLog('warn', 'console') || this.shouldLog('warn', 'file')) {
|
|
152
|
+
this.loggers.warn.warn(logPayload);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
logInfo(params) {
|
|
156
|
+
const logPayload = {
|
|
157
|
+
level: logging_1.logLevels.info,
|
|
158
|
+
message: params.message,
|
|
159
|
+
timestamp: new Date(),
|
|
160
|
+
meta: Object.assign({ type: params.type, info: params.info, context: params.context }, params.meta),
|
|
161
|
+
};
|
|
162
|
+
if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) {
|
|
163
|
+
this.loggers.info.info(logPayload);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
logSuccess(params) {
|
|
167
|
+
const logPayload = {
|
|
168
|
+
level: logging_1.logLevels.success,
|
|
169
|
+
message: params.message,
|
|
170
|
+
timestamp: new Date(),
|
|
171
|
+
meta: Object.assign({ type: params.type, data: params.data, context: params.context }, params.meta),
|
|
172
|
+
};
|
|
173
|
+
if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) {
|
|
174
|
+
this.loggers.success.info(logPayload);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
logDebug(params) {
|
|
178
|
+
const logPayload = {
|
|
179
|
+
level: logging_1.logLevels.debug,
|
|
180
|
+
message: params.message,
|
|
181
|
+
timestamp: new Date(),
|
|
182
|
+
meta: Object.assign({ type: params.type, debug: params.debug, context: params.context }, params.meta),
|
|
183
|
+
};
|
|
184
|
+
if (this.shouldLog('debug', 'console') || this.shouldLog('debug', 'file')) {
|
|
185
|
+
this.loggers.debug.debug(logPayload);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
exports.default = Logger;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-utilities",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Utilities for contentstack projects",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -32,16 +32,16 @@
|
|
|
32
32
|
"author": "contentstack",
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@contentstack/management": "~1.
|
|
36
|
-
"@contentstack/marketplace-sdk": "^1.2.
|
|
37
|
-
"@oclif/core": "^4.
|
|
38
|
-
"axios": "^1.
|
|
35
|
+
"@contentstack/management": "~1.21.4",
|
|
36
|
+
"@contentstack/marketplace-sdk": "^1.2.8",
|
|
37
|
+
"@oclif/core": "^4.3.0",
|
|
38
|
+
"axios": "^1.9.0",
|
|
39
39
|
"chalk": "^4.1.2",
|
|
40
40
|
"cli-cursor": "^3.1.0",
|
|
41
41
|
"cli-progress": "^3.12.0",
|
|
42
42
|
"cli-table": "^0.3.11",
|
|
43
43
|
"conf": "^10.2.0",
|
|
44
|
-
"dotenv": "^16.
|
|
44
|
+
"dotenv": "^16.5.0",
|
|
45
45
|
"figures": "^3.2.0",
|
|
46
46
|
"inquirer": "8.2.6",
|
|
47
47
|
"inquirer-search-checkbox": "^1.0.0",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"mkdirp": "^1.0.4",
|
|
53
53
|
"open": "^8.4.2",
|
|
54
54
|
"ora": "^5.4.1",
|
|
55
|
-
"papaparse": "^5.5.
|
|
55
|
+
"papaparse": "^5.5.3",
|
|
56
56
|
"recheck": "~4.4.5",
|
|
57
57
|
"rxjs": "^6.6.7",
|
|
58
58
|
"traverse": "^0.6.11",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/chai": "^4.3.20",
|
|
67
|
-
"@types/inquirer": "^9.0.
|
|
67
|
+
"@types/inquirer": "^9.0.8",
|
|
68
68
|
"@types/mkdirp": "^1.0.2",
|
|
69
69
|
"@types/mocha": "^10.0.10",
|
|
70
70
|
"@types/node": "^14.18.63",
|
|
@@ -72,12 +72,12 @@
|
|
|
72
72
|
"@types/traverse": "^0.6.37",
|
|
73
73
|
"chai": "^4.5.0",
|
|
74
74
|
"eslint": "^8.57.1",
|
|
75
|
-
"eslint-config-oclif": "^6.0.
|
|
75
|
+
"eslint-config-oclif": "^6.0.62",
|
|
76
76
|
"eslint-config-oclif-typescript": "^3.1.14",
|
|
77
77
|
"fancy-test": "^2.0.42",
|
|
78
78
|
"mocha": "10.8.2",
|
|
79
79
|
"nyc": "^15.1.0",
|
|
80
|
-
"sinon": "^19.0.
|
|
80
|
+
"sinon": "^19.0.5",
|
|
81
81
|
"ts-node": "^10.9.2",
|
|
82
82
|
"typescript": "^4.9.5"
|
|
83
83
|
}
|