@contentstack/cli-utilities 1.5.4 → 1.5.6

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/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import Logger from './logger';
1
2
  export { LoggerService } from './logger';
2
3
  export { default as cliux } from './cli-ux';
3
4
  export { default as CLIError } from './cli-error';
@@ -15,3 +16,4 @@ export * from './interfaces';
15
16
  export { Args, CommandHelp, Config, Errors, Flags, loadHelpClass, Help, HelpBase, HelpSection, HelpSectionRenderer, HelpSectionKeyValueTable, Hook, Interfaces, Parser, Plugin, run, toCached, tsPath, toStandardizedId, toConfiguredId, settings, Settings, flush, ux, execute, stderr, stdout, } from '@oclif/core';
16
17
  export { FlagInput, ArgInput } from '@oclif/core/lib/interfaces/parser';
17
18
  export { default as TablePrompt } from './inquirer-table-prompt';
19
+ export { Logger };
package/lib/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TablePrompt = exports.stdout = exports.stderr = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.tsPath = exports.toCached = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.authHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.LoggerService = void 0;
3
+ exports.Logger = exports.TablePrompt = exports.stdout = exports.stderr = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.tsPath = exports.toCached = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.authHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.LoggerService = void 0;
4
4
  const tslib_1 = require("tslib");
5
- var logger_1 = require("./logger");
6
- Object.defineProperty(exports, "LoggerService", { enumerable: true, get: function () { return logger_1.LoggerService; } });
5
+ const logger_1 = tslib_1.__importDefault(require("./logger"));
6
+ exports.Logger = logger_1.default;
7
+ var logger_2 = require("./logger");
8
+ Object.defineProperty(exports, "LoggerService", { enumerable: true, get: function () { return logger_2.LoggerService; } });
7
9
  var cli_ux_1 = require("./cli-ux");
8
10
  Object.defineProperty(exports, "cliux", { enumerable: true, get: function () { return tslib_1.__importDefault(cli_ux_1).default; } });
9
11
  var cli_error_1 = require("./cli-error");
package/lib/logger.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import winston from 'winston';
1
+ import winston, { LogEntry } from 'winston';
2
+ import { PrintOptions } from './index';
2
3
  export declare class LoggerService {
3
4
  name: string;
4
5
  data: object | null;
@@ -13,3 +14,68 @@ export declare class LoggerService {
13
14
  error(message: string, param?: any): Promise<any>;
14
15
  warn(message: string, param?: any): Promise<any>;
15
16
  }
17
+ export type LogType = 'info' | 'warn' | 'error' | 'debug';
18
+ export type LogsType = LogType | PrintOptions | undefined;
19
+ export type MessageType = string | Error | Record<string, any> | Record<string, any>[];
20
+ export default class Logger {
21
+ private logger;
22
+ private errorLogger;
23
+ private hiddenErrorLogger;
24
+ private config;
25
+ private sensitiveKeys;
26
+ /**
27
+ * The function returns an object with options for a file logger in the winston library.
28
+ * @returns an object of type `winston.transports.FileTransportOptions`.
29
+ */
30
+ get loggerOptions(): winston.transports.FileTransportOptions;
31
+ /**
32
+ * The constructor function initializes the class with a configuration object and creates logger
33
+ * instances.
34
+ * @param config - The `config` parameter is an object that contains various configuration options
35
+ * for the constructor. It is of type `Record<string, any>`, which means it can have any number of
36
+ * properties of any type.
37
+ */
38
+ constructor(config: Record<string, any>);
39
+ /**
40
+ * The function getLoggerInstance creates and returns a winston logger instance with specified log
41
+ * level and transports.
42
+ * @param {'error' | 'info' | 'hidden'} [level=info] - The `level` parameter is an optional parameter
43
+ * that specifies the logging level. It can have one of three values: 'error', 'info', or 'hidden'.
44
+ * The default value is 'info'.
45
+ * @returns an instance of the winston.Logger class.
46
+ */
47
+ getLoggerInstance(level?: 'error' | 'info' | 'hidden'): winston.Logger;
48
+ /**
49
+ * The function checks if a given key string matches any of the sensitive keys defined in an array.
50
+ * @param {string} keyStr - The parameter `keyStr` is a string that represents a key.
51
+ * @returns a boolean value. It returns true if the keyStr matches any of the regular expressions in
52
+ * the sensitiveKeys array, and false otherwise.
53
+ */
54
+ isSensitiveKey(keyStr: string): boolean;
55
+ /**
56
+ * The function redactObject takes an object as input and replaces any sensitive keys with the string
57
+ * '[REDACTED]'.
58
+ * @param {any} obj - The `obj` parameter is an object that you want to redact sensitive information
59
+ * from.
60
+ */
61
+ redactObject(obj: any): void;
62
+ /**
63
+ * The redact function takes an object, creates a copy of it, redacts sensitive information from the
64
+ * copy, and returns the redacted copy.
65
+ * @param {any} obj - The `obj` parameter is of type `any`, which means it can accept any type of
66
+ * value. It is the object that needs to be redacted.
67
+ * @returns The `redact` function is returning a copy of the `obj` parameter with certain properties
68
+ * redacted.
69
+ */
70
+ redact(obj: any): any;
71
+ /**
72
+ * The function checks if an object is a LogEntry by verifying if it has the properties 'level' and
73
+ * 'message'.
74
+ * @param {any} obj - The `obj` parameter is of type `any`, which means it can be any type of value.
75
+ * @returns a boolean value.
76
+ */
77
+ isLogEntry(obj: any): obj is LogEntry;
78
+ log(entry: LogEntry): void;
79
+ log(message: MessageType, logType: LogsType): void;
80
+ log(message: MessageType, logType: 'error', hidden: boolean): void;
81
+ }
package/lib/logger.js CHANGED
@@ -2,9 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LoggerService = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const traverse_1 = tslib_1.__importDefault(require("traverse"));
6
+ const full_1 = require("klona/full");
7
+ const path_1 = tslib_1.__importStar(require("path"));
5
8
  const winston_1 = tslib_1.__importDefault(require("winston"));
6
- const path_1 = tslib_1.__importDefault(require("path"));
7
- const message_handler_1 = tslib_1.__importDefault(require("./message-handler"));
9
+ const index_1 = require("./index");
8
10
  class LoggerService {
9
11
  static dateFormat() {
10
12
  return new Date(Date.now()).toUTCString();
@@ -14,7 +16,6 @@ class LoggerService {
14
16
  this.name = null;
15
17
  const logger = winston_1.default.createLogger({
16
18
  transports: [
17
- // new winston.transports.Console(),
18
19
  new winston_1.default.transports.File({
19
20
  filename: path_1.default.resolve(process.env.CS_CLI_LOG_PATH || `${pathToLog}/logs`, `${name}.log`),
20
21
  }),
@@ -28,21 +29,18 @@ class LoggerService {
28
29
  console.log('warning: failed to log the result');
29
30
  }
30
31
  // parse message
31
- info.message = message_handler_1.default.parse(info.message);
32
+ info.message = index_1.messageHandler.parse(info.message);
32
33
  let message = `${LoggerService.dateFormat()} : ${name}: ${info.level} : ${info.message}`;
33
34
  message = info.obj ? message + `:${stringifiedParam}` : message;
34
35
  message = this.data ? message + `:${JSON.stringify(this.data)}` : message;
35
36
  return message;
36
37
  })),
37
- // // level: (config.get('logger.level') as string) || 'error',
38
- // level: 'error',
39
- // silent: true
40
- // silent: config.get('logger.enabled') && process.env.CLI_ENV !== 'TEST' ? false : false,
41
38
  });
42
39
  this.logger = logger;
43
40
  }
44
41
  init(context) {
45
- this.name = (context && context.plugin && context.plugin.name) || 'cli';
42
+ var _a, _b;
43
+ this.name = (_b = (_a = context === null || context === void 0 ? void 0 : context.plugin) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'cli';
46
44
  }
47
45
  set loggerName(name) {
48
46
  this.name = name;
@@ -92,3 +90,152 @@ class LoggerService {
92
90
  }
93
91
  }
94
92
  exports.LoggerService = LoggerService;
93
+ /* The Logger class is a TypeScript class that provides logging functionality using the winston
94
+ library, with support for redacting sensitive information and different log levels. */
95
+ class Logger {
96
+ /**
97
+ * The function returns an object with options for a file logger in the winston library.
98
+ * @returns an object of type `winston.transports.FileTransportOptions`.
99
+ */
100
+ get loggerOptions() {
101
+ return {
102
+ filename: '',
103
+ maxFiles: 20,
104
+ tailable: true,
105
+ maxsize: 1000000,
106
+ };
107
+ }
108
+ /**
109
+ * The constructor function initializes the class with a configuration object and creates logger
110
+ * instances.
111
+ * @param config - The `config` parameter is an object that contains various configuration options
112
+ * for the constructor. It is of type `Record<string, any>`, which means it can have any number of
113
+ * properties of any type.
114
+ */
115
+ constructor(config) {
116
+ /* The `sensitiveKeys` array is used to store regular expressions that match sensitive keys. These
117
+ keys are used to redact sensitive information from log messages. When logging an object, any keys
118
+ that match the regular expressions in the `sensitiveKeys` array will be replaced with the string
119
+ '[REDACTED]'. This helps to prevent sensitive information from being logged or displayed. */
120
+ this.sensitiveKeys = [
121
+ /authtoken/i,
122
+ /^email$/,
123
+ /^password$/i,
124
+ /secret/i,
125
+ /token/i,
126
+ /api[-._]?key/i,
127
+ /management[-._]?token/i,
128
+ ];
129
+ this.config = config;
130
+ this.logger = this.getLoggerInstance();
131
+ this.errorLogger = this.getLoggerInstance('error');
132
+ this.hiddenErrorLogger = this.getLoggerInstance('hidden');
133
+ }
134
+ /**
135
+ * The function getLoggerInstance creates and returns a winston logger instance with specified log
136
+ * level and transports.
137
+ * @param {'error' | 'info' | 'hidden'} [level=info] - The `level` parameter is an optional parameter
138
+ * that specifies the logging level. It can have one of three values: 'error', 'info', or 'hidden'.
139
+ * The default value is 'info'.
140
+ * @returns an instance of the winston.Logger class.
141
+ */
142
+ getLoggerInstance(level = 'info') {
143
+ const filePath = (0, path_1.normalize)(process.env.CS_CLI_LOG_PATH || this.config.basePath).replace(/^(\.\.(\/|\\|$))+/, '');
144
+ const transports = [];
145
+ if (level !== 'hidden') {
146
+ transports.push(new winston_1.default.transports.Console({
147
+ format: winston_1.default.format.combine(winston_1.default.format.colorize({ all: true })),
148
+ }));
149
+ }
150
+ transports.push(new winston_1.default.transports.File(Object.assign(Object.assign({}, this.loggerOptions), { level: level === 'hidden' ? 'error' : level, filename: `${filePath}/${level === 'hidden' ? 'error' : level}.log` })));
151
+ return winston_1.default.createLogger({
152
+ levels: level === 'error' || level === 'hidden'
153
+ ? { error: 0 }
154
+ : {
155
+ warn: 1,
156
+ info: 2,
157
+ debug: 3,
158
+ },
159
+ level,
160
+ transports,
161
+ format: winston_1.default.format.combine(winston_1.default.format((info) => this.redact(info))(), winston_1.default.format.errors({ stack: level === 'hidden' }), // NOTE keep stack only for the hidden type
162
+ winston_1.default.format.simple(), winston_1.default.format.timestamp(), winston_1.default.format.metadata()),
163
+ });
164
+ }
165
+ /**
166
+ * The function checks if a given key string matches any of the sensitive keys defined in an array.
167
+ * @param {string} keyStr - The parameter `keyStr` is a string that represents a key.
168
+ * @returns a boolean value. It returns true if the keyStr matches any of the regular expressions in
169
+ * the sensitiveKeys array, and false otherwise.
170
+ */
171
+ isSensitiveKey(keyStr) {
172
+ if (keyStr) {
173
+ return this.sensitiveKeys.some((regex) => regex.test(keyStr));
174
+ }
175
+ }
176
+ /**
177
+ * The function redactObject takes an object as input and replaces any sensitive keys with the string
178
+ * '[REDACTED]'.
179
+ * @param {any} obj - The `obj` parameter is an object that you want to redact sensitive information
180
+ * from.
181
+ */
182
+ redactObject(obj) {
183
+ const self = this;
184
+ (0, traverse_1.default)(obj).forEach(function redactor() {
185
+ if (self.isSensitiveKey(this.key)) {
186
+ this.update('[REDACTED]');
187
+ }
188
+ });
189
+ }
190
+ /**
191
+ * The redact function takes an object, creates a copy of it, redacts sensitive information from the
192
+ * copy, and returns the redacted copy.
193
+ * @param {any} obj - The `obj` parameter is of type `any`, which means it can accept any type of
194
+ * value. It is the object that needs to be redacted.
195
+ * @returns The `redact` function is returning a copy of the `obj` parameter with certain properties
196
+ * redacted.
197
+ */
198
+ redact(obj) {
199
+ const copy = (0, full_1.klona)(obj);
200
+ this.redactObject(copy);
201
+ const splat = copy[Symbol.for('splat')];
202
+ this.redactObject(splat);
203
+ return copy;
204
+ }
205
+ /**
206
+ * The function checks if an object is a LogEntry by verifying if it has the properties 'level' and
207
+ * 'message'.
208
+ * @param {any} obj - The `obj` parameter is of type `any`, which means it can be any type of value.
209
+ * @returns a boolean value.
210
+ */
211
+ isLogEntry(obj) {
212
+ return typeof obj === 'object' && 'level' in obj && 'message' in obj;
213
+ }
214
+ log(entryOrMessage, logType, hidden) {
215
+ if (this.isLogEntry(entryOrMessage)) {
216
+ this.logger.log(entryOrMessage);
217
+ }
218
+ else {
219
+ switch (logType) {
220
+ case 'info':
221
+ case 'debug':
222
+ case 'warn':
223
+ this.logger.log(logType, entryOrMessage);
224
+ break;
225
+ case 'error':
226
+ if (hidden) {
227
+ this.hiddenErrorLogger.error(entryOrMessage);
228
+ }
229
+ else {
230
+ this.errorLogger.error(entryOrMessage);
231
+ this.hiddenErrorLogger.error(entryOrMessage);
232
+ }
233
+ break;
234
+ default:
235
+ index_1.cliux.print(entryOrMessage, logType || {});
236
+ break;
237
+ }
238
+ }
239
+ }
240
+ }
241
+ exports.default = Logger;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentstack/cli-utilities",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "Utilities for contentstack projects",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -32,9 +32,9 @@
32
32
  "author": "contentstack",
33
33
  "license": "MIT",
34
34
  "dependencies": {
35
- "@contentstack/management": "~1.10.2",
35
+ "@contentstack/management": "~1.12.0",
36
36
  "@oclif/core": "^2.9.3",
37
- "axios": "1.3.4",
37
+ "axios": "^1.6.0",
38
38
  "chalk": "^4.0.0",
39
39
  "cli-cursor": "^3.1.0",
40
40
  "cli-table": "^0.3.11",
@@ -44,11 +44,13 @@
44
44
  "inquirer": "8.2.4",
45
45
  "inquirer-search-checkbox": "^1.0.0",
46
46
  "inquirer-search-list": "^1.2.6",
47
- "mkdirp": "^1.0.4",
47
+ "klona": "^2.0.6",
48
48
  "lodash": "^4.17.15",
49
+ "mkdirp": "^1.0.4",
49
50
  "open": "^8.4.2",
50
51
  "ora": "^5.4.0",
51
52
  "rxjs": "^6.6.7",
53
+ "traverse": "^0.6.7",
52
54
  "unique-string": "^2.0.0",
53
55
  "uuid": "^9.0.0",
54
56
  "winston": "^3.7.2",
@@ -62,6 +64,7 @@
62
64
  "@types/mocha": "^8.2.2",
63
65
  "@types/node": "^14.14.32",
64
66
  "@types/sinon": "^10.0.2",
67
+ "@types/traverse": "^0.6.34",
65
68
  "chai": "^4.3.4",
66
69
  "eslint": "^8.18.0",
67
70
  "eslint-config-oclif": "^4.0.0",