@verdaccio/logger 6.0.0-6-next.9 → 6.0.0-6-next.12

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/CHANGELOG.md CHANGED
@@ -1,5 +1,80 @@
1
1
  # @verdaccio/logger
2
2
 
3
+ ## 6.0.0-6-next.12
4
+
5
+ ### Major Changes
6
+
7
+ - 292c0a37: feat!: replace deprecated request dependency by got
8
+
9
+ This is a big refactoring of the core, fetching dependencies, improve code, more tests and better stability. This is essential for the next release, will take some time but would allow modularize more the core.
10
+
11
+ ## Notes
12
+
13
+ - Remove deprecated `request` by other `got`, retry improved, custom Agent ( got does not include it built-in)
14
+ - Remove `async` dependency from storage (used by core) it was linked with proxy somehow safe to remove now
15
+ - Refactor with promises instead callback wherever is possible
16
+ - ~Document the API~
17
+ - Improve testing, integration tests
18
+ - Bugfix
19
+ - Clean up old validations
20
+ - Improve performance
21
+
22
+ ## 💥 Breaking changes
23
+
24
+ - Plugin API methods were callbacks based are returning promises, this will break current storage plugins, check documentation for upgrade.
25
+ - Write Tarball, Read Tarball methods parameters change, a new set of options like `AbortController` signals are being provided to the `addAbortSignal` can be internally used with Streams when a request is aborted. eg: `addAbortSignal(signal, fs.createReadStream(pathName));`
26
+ - `@verdaccio/streams` stream abort support is legacy is being deprecated removed
27
+ - Remove AWS and Google Cloud packages for future refactoring [#2574](https://github.com/verdaccio/verdaccio/pull/2574).
28
+
29
+ - a3a209b5: feat: migrate to pino.js 8
30
+
31
+ ### Patch Changes
32
+
33
+ - Updated dependencies [292c0a37]
34
+ - Updated dependencies [a3a209b5]
35
+ - Updated dependencies [00d1d2a1]
36
+ - @verdaccio/core@6.0.0-6-next.6
37
+ - @verdaccio/logger-prettify@6.0.0-6-next.7
38
+
39
+ ## 6.0.0-6-next.11
40
+
41
+ ### Major Changes
42
+
43
+ - 82cb0f2b: feat!: config.logs throw an error, logging config not longer accept array or logs property
44
+
45
+ ### 💥 Breaking change
46
+
47
+ This is valid
48
+
49
+ ```yaml
50
+ log: { type: stdout, format: pretty, level: http }
51
+ ```
52
+
53
+ This is invalid
54
+
55
+ ```yaml
56
+ logs: { type: stdout, format: pretty, level: http }
57
+ ```
58
+
59
+ or
60
+
61
+ ```yaml
62
+ logs:
63
+ - [{ type: stdout, format: pretty, level: http }]
64
+ ```
65
+
66
+ ### Patch Changes
67
+
68
+ - Updated dependencies [82cb0f2b]
69
+ - Updated dependencies [5167bb52]
70
+ - @verdaccio/core@6.0.0-6-next.5
71
+
72
+ ## 6.0.0-6-next.10
73
+
74
+ ### Patch Changes
75
+
76
+ - b78f3525: Fix re-opening log files using SIGUSR2
77
+
3
78
  ## 6.0.0-6-next.9
4
79
 
5
80
  ### Major Changes
package/build/index.js CHANGED
@@ -15,6 +15,12 @@ Object.defineProperty(exports, "logger", {
15
15
  return _logger.logger;
16
16
  }
17
17
  });
18
+ Object.defineProperty(exports, "prepareSetup", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _logger.prepareSetup;
22
+ }
23
+ });
18
24
  Object.defineProperty(exports, "setup", {
19
25
  enumerable: true,
20
26
  get: function () {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA","sourcesContent":["export { setup, createLogger, logger } from './logger';\n"],"file":"index.js"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export { setup, createLogger, logger, prepareSetup } from './logger';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA"}
package/build/logger.js CHANGED
@@ -4,52 +4,46 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.createLogger = createLogger;
7
- exports.getLogger = getLogger;
8
7
  exports.logger = void 0;
8
+ exports.prepareSetup = prepareSetup;
9
9
  exports.setup = setup;
10
10
 
11
- var _debug = _interopRequireDefault(require("debug"));
11
+ var _colorette = require("colorette");
12
12
 
13
- var _lodash = _interopRequireDefault(require("lodash"));
13
+ var _debug = _interopRequireDefault(require("debug"));
14
14
 
15
15
  var _pino = _interopRequireDefault(require("pino"));
16
16
 
17
- var _core = require("@verdaccio/core");
18
-
19
- var _loggerPrettify = _interopRequireWildcard(require("@verdaccio/logger-prettify"));
20
-
21
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
22
-
23
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
+ var _loggerPrettify = require("@verdaccio/logger-prettify");
24
18
 
25
19
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
20
 
21
+ // <reference types="node" />
27
22
  const debug = (0, _debug.default)('verdaccio:logger');
28
- let logger;
29
- exports.logger = logger;
30
23
 
31
24
  function isProd() {
32
25
  return process.env.NODE_ENV === 'production';
33
26
  }
34
27
 
28
+ function hasColors(colors) {
29
+ if (colors) {
30
+ return _colorette.isColorSupported;
31
+ }
32
+
33
+ return typeof colors === 'undefined' ? true : colors;
34
+ }
35
+
35
36
  const DEFAULT_LOG_FORMAT = isProd() ? 'json' : 'pretty';
36
37
 
37
38
  function createLogger(options = {
38
39
  level: 'http'
39
- }, destination = _pino.default.destination(1), format = DEFAULT_LOG_FORMAT, prettyPrintOptions = {
40
- // we hide warning since the prettifier should not be used in production
41
- // https://getpino.io/#/docs/pretty?id=prettifier-api
42
- suppressFlushSyncWarning: true
43
- }) {
44
- if (_lodash.default.isNil(format)) {
45
- format = DEFAULT_LOG_FORMAT;
46
- }
47
-
40
+ }, // eslint-disable-next-line no-undef
41
+ destination = _pino.default.destination(1), format = DEFAULT_LOG_FORMAT) {
42
+ debug('setup logger');
48
43
  let pinoConfig = {
49
44
  customLevels: {
50
45
  http: 25
51
46
  },
52
- ...options,
53
47
  level: options.level,
54
48
  serializers: {
55
49
  err: _pino.default.stdSerializers.err,
@@ -59,21 +53,24 @@ function createLogger(options = {
59
53
  };
60
54
  debug('has prettifier? %o', !isProd()); // pretty logs are not allowed in production for performance reasons
61
55
 
62
- if ((format === DEFAULT_LOG_FORMAT || format !== 'json') && isProd() === false) {
56
+ if (['pretty-timestamped', 'pretty'].includes(format) && isProd() === false) {
63
57
  pinoConfig = Object.assign({}, pinoConfig, {
64
- prettifier: _loggerPrettify.default,
65
- // more info
66
- // https://github.com/pinojs/pino-pretty/issues/37
67
- prettyPrint: {
68
- levelFirst: true,
69
- prettyStamp: format === 'pretty-timestamped',
70
- ...prettyPrintOptions
58
+ transport: {
59
+ target: '@verdaccio/logger-prettify',
60
+ options: {
61
+ // string or 1 (file descriptor for process.stdout)
62
+ destination: options.path || 1,
63
+ colors: hasColors(options.colors),
64
+ prettyStamp: format === 'pretty-timestamped'
65
+ }
71
66
  }
72
67
  });
73
68
  } else {
74
- pinoConfig = Object.assign({}, pinoConfig, {
69
+ pinoConfig = { ...pinoConfig,
75
70
  // more info
76
71
  // https://github.com/pinojs/pino/blob/v7.1.0/docs/api.md#hooks-object
72
+ // TODO: improve typings here
73
+ // @ts-ignore
77
74
  hooks: {
78
75
  logMethod(inputArgs, method) {
79
76
  const [templateObject, message, ...otherArgs] = inputArgs;
@@ -84,10 +81,13 @@ function createLogger(options = {
84
81
  }
85
82
 
86
83
  }
87
- });
84
+ };
88
85
  }
89
86
 
90
87
  const logger = (0, _pino.default)(pinoConfig, destination);
88
+ /* eslint-disable */
89
+
90
+ /* istanbul ignore next */
91
91
 
92
92
  if (process.env.DEBUG) {
93
93
  logger.on('level-change', (lvl, val, prevLvl, prevVal) => {
@@ -98,37 +98,17 @@ function createLogger(options = {
98
98
  return logger;
99
99
  }
100
100
 
101
- function getLogger() {
102
- if (_lodash.default.isNil(logger)) {
103
- // FIXME: not sure about display here a warning
104
- _core.warningUtils.emit(_core.warningUtils.Codes.VERWAR002);
105
-
106
- return;
107
- }
108
-
109
- return logger;
110
- }
111
-
112
101
  const DEFAULT_LOGGER_CONF = {
113
102
  type: 'stdout',
114
103
  format: 'pretty',
115
104
  level: 'http'
116
105
  };
117
106
 
118
- function setup(options = DEFAULT_LOGGER_CONF) {
107
+ function prepareSetup(options = DEFAULT_LOGGER_CONF) {
119
108
  var _loggerConfig;
120
109
 
121
- debug('setup logger');
122
- const isLegacyConf = Array.isArray(options);
123
-
124
- if (isLegacyConf) {
125
- _core.warningUtils.emit(_core.warningUtils.Codes.VERDEP002);
126
- } // verdaccio 5 does not allow multiple logger configuration
127
- // backward compatible, pick only the first option
128
- // next major will thrown an error
129
-
130
-
131
- let loggerConfig = isLegacyConf ? options[0] : options;
110
+ let logger;
111
+ let loggerConfig = options;
132
112
 
133
113
  if (!((_loggerConfig = loggerConfig) !== null && _loggerConfig !== void 0 && _loggerConfig.level)) {
134
114
  loggerConfig = Object.assign({}, {
@@ -142,39 +122,41 @@ function setup(options = DEFAULT_LOGGER_CONF) {
142
122
 
143
123
  if (loggerConfig.type === 'file') {
144
124
  debug('logging file enabled');
145
- exports.logger = logger = createLogger(pinoConfig, _pino.default.destination(loggerConfig.path), loggerConfig.format);
146
- } else if (loggerConfig.type === 'rotating-file') {
147
- _core.warningUtils.emit(_core.warningUtils.Codes.VERWAR003);
148
125
 
149
- debug('logging stdout enabled');
150
- exports.logger = logger = createLogger(pinoConfig, _pino.default.destination(1), loggerConfig.format);
151
- } else {
152
- debug('logging stdout enabled');
153
- exports.logger = logger = createLogger(pinoConfig, _pino.default.destination(1), loggerConfig.format);
154
- }
126
+ const destination = _pino.default.destination(loggerConfig.path);
127
+ /* eslint-disable */
155
128
 
156
- if (isProd()) {
157
- // why only on prod? https://github.com/pinojs/pino/issues/920#issuecomment-710807667
158
- const finalHandler = _pino.default.final(logger, (err, finalLogger, event) => {
159
- finalLogger.info(`${event} caught`);
129
+ /* istanbul ignore next */
160
130
 
161
- if (err) {
162
- finalLogger.error(err, 'error caused exit');
163
- }
164
131
 
165
- process.exit(err ? 1 : 0);
166
- });
132
+ process.on('SIGUSR2', () => destination.reopen()); // @ts-ignore
133
+
134
+ logger = createLogger({
135
+ level: loggerConfig.level,
136
+ path: loggerConfig.path,
137
+ colors: loggerConfig.colors
138
+ }, destination, loggerConfig.format);
139
+ return logger;
140
+ } else {
141
+ debug('logging stdout enabled'); // @ts-ignore
142
+
143
+ logger = createLogger({
144
+ level: loggerConfig.level,
145
+ colors: loggerConfig.colors
146
+ }, _pino.default.destination(1), loggerConfig.format);
147
+ return logger;
148
+ }
149
+ }
150
+
151
+ let logger;
152
+ exports.logger = logger;
167
153
 
168
- process.on('uncaughtException', err => finalHandler(err, 'uncaughtException'));
169
- process.on('unhandledRejection', err => finalHandler(err, 'unhandledRejection'));
170
- process.on('beforeExit', () => finalHandler(null, 'beforeExit'));
171
- process.on('exit', () => finalHandler(null, 'exit'));
172
- process.on('uncaughtException', err => finalHandler(err, 'uncaughtException'));
173
- process.on('SIGINT', () => finalHandler(null, 'SIGINT'));
174
- process.on('SIGQUIT', () => finalHandler(null, 'SIGQUIT'));
175
- process.on('SIGTERM', () => finalHandler(null, 'SIGTERM'));
154
+ function setup(options) {
155
+ if (typeof logger !== 'undefined') {
156
+ return logger;
176
157
  }
177
158
 
159
+ exports.logger = logger = prepareSetup(options);
178
160
  return logger;
179
161
  }
180
162
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts"],"names":["debug","logger","isProd","process","env","NODE_ENV","DEFAULT_LOG_FORMAT","createLogger","options","level","destination","pino","format","prettyPrintOptions","suppressFlushSyncWarning","_","isNil","pinoConfig","customLevels","http","serializers","err","stdSerializers","req","res","Object","assign","prettifier","prettyPrint","levelFirst","prettyStamp","hooks","logMethod","inputArgs","method","templateObject","message","otherArgs","templateVars","getOwnPropertyNames","length","apply","hydratedMessage","DEBUG","on","lvl","val","prevLvl","prevVal","getLogger","warningUtils","emit","Codes","VERWAR002","DEFAULT_LOGGER_CONF","type","setup","isLegacyConf","Array","isArray","VERDEP002","loggerConfig","path","VERWAR003","finalHandler","final","finalLogger","event","info","error","exit"],"mappings":"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","sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\nimport pino from 'pino';\n\nimport { warningUtils } from '@verdaccio/core';\nimport prettifier, { fillInMsgTemplate } from '@verdaccio/logger-prettify';\n\nconst debug = buildDebug('verdaccio:logger');\n\nexport let logger;\n\nfunction isProd() {\n return process.env.NODE_ENV === 'production';\n}\n\nconst DEFAULT_LOG_FORMAT = isProd() ? 'json' : 'pretty';\n\nexport type LogPlugin = {\n dest: string;\n options?: any[];\n};\n\nexport type LogType = 'file' | 'stdout';\nexport type LogFormat = 'json' | 'pretty-timestamped' | 'pretty';\n\nexport function createLogger(\n options = { level: 'http' },\n destination = pino.destination(1),\n format: LogFormat = DEFAULT_LOG_FORMAT,\n prettyPrintOptions = {\n // we hide warning since the prettifier should not be used in production\n // https://getpino.io/#/docs/pretty?id=prettifier-api\n suppressFlushSyncWarning: true,\n }\n) {\n if (_.isNil(format)) {\n format = DEFAULT_LOG_FORMAT;\n }\n\n let pinoConfig = {\n customLevels: {\n http: 25,\n },\n ...options,\n level: options.level,\n serializers: {\n err: pino.stdSerializers.err,\n req: pino.stdSerializers.req,\n res: pino.stdSerializers.res,\n },\n };\n\n debug('has prettifier? %o', !isProd());\n // pretty logs are not allowed in production for performance reasons\n if ((format === DEFAULT_LOG_FORMAT || format !== 'json') && isProd() === false) {\n pinoConfig = Object.assign({}, pinoConfig, {\n prettifier,\n // more info\n // https://github.com/pinojs/pino-pretty/issues/37\n prettyPrint: {\n levelFirst: true,\n prettyStamp: format === 'pretty-timestamped',\n ...prettyPrintOptions,\n },\n });\n } else {\n pinoConfig = Object.assign({}, pinoConfig, {\n // more info\n // https://github.com/pinojs/pino/blob/v7.1.0/docs/api.md#hooks-object\n hooks: {\n logMethod(inputArgs, method) {\n const [templateObject, message, ...otherArgs] = inputArgs;\n const templateVars =\n !!templateObject && typeof templateObject === 'object'\n ? Object.getOwnPropertyNames(templateObject)\n : [];\n if (!message || !templateVars.length) return method.apply(this, inputArgs);\n const hydratedMessage = fillInMsgTemplate(message, templateObject, false);\n return method.apply(this, [templateObject, hydratedMessage, ...otherArgs]);\n },\n },\n });\n }\n const logger = pino(pinoConfig, destination);\n\n if (process.env.DEBUG) {\n logger.on('level-change', (lvl, val, prevLvl, prevVal) => {\n debug('%s (%d) was changed to %s (%d)', lvl, val, prevLvl, prevVal);\n });\n }\n\n return logger;\n}\n\nexport function getLogger() {\n if (_.isNil(logger)) {\n // FIXME: not sure about display here a warning\n warningUtils.emit(warningUtils.Codes.VERWAR002);\n return;\n }\n\n return logger;\n}\n\nconst DEFAULT_LOGGER_CONF: LoggerConfigItem = {\n type: 'stdout',\n format: 'pretty',\n level: 'http',\n};\n\nexport type LoggerConfigItem = {\n type?: LogType;\n plugin?: LogPlugin;\n format?: LogFormat;\n path?: string;\n level?: string;\n};\n\nexport type LoggerConfig = LoggerConfigItem[];\n\nexport function setup(options: LoggerConfig | LoggerConfigItem = DEFAULT_LOGGER_CONF) {\n debug('setup logger');\n const isLegacyConf = Array.isArray(options);\n if (isLegacyConf) {\n warningUtils.emit(warningUtils.Codes.VERDEP002);\n }\n\n // verdaccio 5 does not allow multiple logger configuration\n // backward compatible, pick only the first option\n // next major will thrown an error\n let loggerConfig = isLegacyConf ? options[0] : options;\n if (!loggerConfig?.level) {\n loggerConfig = Object.assign(\n {},\n {\n level: 'http',\n },\n loggerConfig\n );\n }\n const pinoConfig = { level: loggerConfig.level };\n if (loggerConfig.type === 'file') {\n debug('logging file enabled');\n logger = createLogger(pinoConfig, pino.destination(loggerConfig.path), loggerConfig.format);\n } else if (loggerConfig.type === 'rotating-file') {\n warningUtils.emit(warningUtils.Codes.VERWAR003);\n debug('logging stdout enabled');\n logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);\n } else {\n debug('logging stdout enabled');\n logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);\n }\n\n if (isProd()) {\n // why only on prod? https://github.com/pinojs/pino/issues/920#issuecomment-710807667\n const finalHandler = pino.final(logger, (err, finalLogger, event) => {\n finalLogger.info(`${event} caught`);\n if (err) {\n finalLogger.error(err, 'error caused exit');\n }\n process.exit(err ? 1 : 0);\n });\n\n process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));\n process.on('unhandledRejection', (err) => finalHandler(err as Error, 'unhandledRejection'));\n process.on('beforeExit', () => finalHandler(null, 'beforeExit'));\n process.on('exit', () => finalHandler(null, 'exit'));\n process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));\n process.on('SIGINT', () => finalHandler(null, 'SIGINT'));\n process.on('SIGQUIT', () => finalHandler(null, 'SIGQUIT'));\n process.on('SIGTERM', () => finalHandler(null, 'SIGTERM'));\n }\n\n return logger;\n}\n"],"file":"logger.js"}
1
+ {"version":3,"file":"logger.js","names":["debug","buildDebug","isProd","process","env","NODE_ENV","hasColors","colors","isColorSupported","DEFAULT_LOG_FORMAT","createLogger","options","level","destination","pino","format","pinoConfig","customLevels","http","serializers","err","stdSerializers","req","res","includes","Object","assign","transport","target","path","prettyStamp","hooks","logMethod","inputArgs","method","templateObject","message","otherArgs","templateVars","getOwnPropertyNames","length","apply","hydratedMessage","fillInMsgTemplate","logger","DEBUG","on","lvl","val","prevLvl","prevVal","DEFAULT_LOGGER_CONF","type","prepareSetup","loggerConfig","reopen","setup"],"sources":["../src/logger.ts"],"sourcesContent":["// <reference types=\"node\" />\nimport { isColorSupported } from 'colorette';\nimport buildDebug from 'debug';\nimport pino, { Logger } from 'pino';\n\nimport { fillInMsgTemplate } from '@verdaccio/logger-prettify';\nimport { LoggerConfigItem, LoggerFormat } from '@verdaccio/types';\n\nconst debug = buildDebug('verdaccio:logger');\n\nfunction isProd() {\n return process.env.NODE_ENV === 'production';\n}\n\nfunction hasColors(colors: boolean | undefined) {\n if (colors) {\n return isColorSupported;\n }\n return typeof colors === 'undefined' ? true : colors;\n}\n\nconst DEFAULT_LOG_FORMAT = isProd() ? 'json' : 'pretty';\n\nexport type LogPlugin = {\n dest: string;\n options?: any[];\n};\n\ntype LoggerOptions = { level?: string; path?: string; colors?: boolean; sync?: boolean };\n\nexport function createLogger(\n options: LoggerOptions = { level: 'http' },\n // eslint-disable-next-line no-undef\n destination: NodeJS.WritableStream = pino.destination(1),\n format: LoggerFormat = DEFAULT_LOG_FORMAT\n) {\n debug('setup logger');\n let pinoConfig = {\n customLevels: {\n http: 25,\n },\n level: options.level,\n serializers: {\n err: pino.stdSerializers.err,\n req: pino.stdSerializers.req,\n res: pino.stdSerializers.res,\n },\n };\n\n debug('has prettifier? %o', !isProd());\n // pretty logs are not allowed in production for performance reasons\n if (['pretty-timestamped', 'pretty'].includes(format) && isProd() === false) {\n pinoConfig = Object.assign({}, pinoConfig, {\n transport: {\n target: '@verdaccio/logger-prettify',\n options: {\n // string or 1 (file descriptor for process.stdout)\n destination: options.path || 1,\n colors: hasColors(options.colors),\n prettyStamp: format === 'pretty-timestamped',\n },\n },\n });\n } else {\n pinoConfig = {\n ...pinoConfig,\n // more info\n // https://github.com/pinojs/pino/blob/v7.1.0/docs/api.md#hooks-object\n // TODO: improve typings here\n // @ts-ignore\n hooks: {\n logMethod(\n inputArgs: [any, any, ...any[]],\n method: {\n apply: (arg0: { logMethod: (inputArgs: any, method: any) => any }, arg1: any[]) => any;\n }\n ) {\n const [templateObject, message, ...otherArgs] = inputArgs;\n const templateVars =\n !!templateObject && typeof templateObject === 'object'\n ? Object.getOwnPropertyNames(templateObject)\n : [];\n if (!message || !templateVars.length) return method.apply(this, inputArgs);\n const hydratedMessage = fillInMsgTemplate(message, templateObject, false);\n return method.apply(this, [templateObject, hydratedMessage, ...otherArgs]);\n },\n },\n };\n }\n const logger = pino(pinoConfig, destination);\n\n /* eslint-disable */\n /* istanbul ignore next */\n if (process.env.DEBUG) {\n logger.on('level-change', (lvl, val, prevLvl, prevVal) => {\n debug('%s (%d) was changed to %s (%d)', lvl, val, prevLvl, prevVal);\n });\n }\n\n return logger;\n}\n\nconst DEFAULT_LOGGER_CONF: LoggerConfigItem = {\n type: 'stdout',\n format: 'pretty',\n level: 'http',\n};\n\nexport type LoggerConfig = LoggerConfigItem;\n\nexport function prepareSetup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF) {\n let logger: Logger<{\n customLevels: { http: number };\n level: string | undefined;\n serializers: { err: any; req: any; res: any };\n }>;\n let loggerConfig = options;\n if (!loggerConfig?.level) {\n loggerConfig = Object.assign(\n {},\n {\n level: 'http',\n },\n loggerConfig\n );\n }\n const pinoConfig = { level: loggerConfig.level };\n if (loggerConfig.type === 'file') {\n debug('logging file enabled');\n const destination = pino.destination(loggerConfig.path);\n /* eslint-disable */\n /* istanbul ignore next */\n process.on('SIGUSR2', () => destination.reopen());\n // @ts-ignore\n logger = createLogger(\n { level: loggerConfig.level, path: loggerConfig.path, colors: loggerConfig.colors },\n destination,\n loggerConfig.format\n );\n return logger;\n } else {\n debug('logging stdout enabled');\n // @ts-ignore\n logger = createLogger(\n { level: loggerConfig.level, colors: loggerConfig.colors },\n pino.destination(1),\n loggerConfig.format\n );\n return logger;\n }\n}\n\nexport let logger: Logger;\n\nexport function setup(options: LoggerConfigItem) {\n if (typeof logger !== 'undefined') {\n return logger;\n }\n\n logger = prepareSetup(options);\n return logger;\n}\n"],"mappings":"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"}
package/jest.config.js CHANGED
@@ -1,5 +1,10 @@
1
1
  const config = require('../../jest/config');
2
2
 
3
3
  module.exports = Object.assign({}, config, {
4
- verbose: true,
4
+ coverageThreshold: {
5
+ global: {
6
+ // FIXME: increase to 90
7
+ lines: 39,
8
+ },
9
+ },
5
10
  });
package/package.json CHANGED
@@ -1,55 +1,56 @@
1
1
  {
2
- "name": "@verdaccio/logger",
3
- "version": "6.0.0-6-next.9",
4
- "description": "logger",
5
- "main": "./build/index.js",
6
- "types": "build/index.d.ts",
7
- "author": {
8
- "name": "Juan Picado",
9
- "email": "juanpicado19@gmail.com"
10
- },
11
- "repository": {
12
- "type": "https",
13
- "url": "https://github.com/verdaccio/verdaccio"
14
- },
15
- "license": "MIT",
16
- "homepage": "https://verdaccio.org",
17
- "keywords": [
18
- "private",
19
- "package",
20
- "repository",
21
- "registry",
22
- "enterprise",
23
- "modules",
24
- "proxy",
25
- "server",
26
- "verdaccio"
27
- ],
28
- "engines": {
29
- "node": ">=14",
30
- "npm": ">=6"
31
- },
32
- "dependencies": {
33
- "@verdaccio/core": "6.0.0-6-next.4",
34
- "@verdaccio/logger-prettify": "6.0.0-6-next.6",
35
- "debug": "4.3.3",
36
- "lodash": "4.17.21",
37
- "pino": "7.6.3"
38
- },
39
- "devDependencies": {
40
- "@verdaccio/types": "11.0.0-6-next.10"
41
- },
42
- "funding": {
43
- "type": "opencollective",
44
- "url": "https://opencollective.com/verdaccio"
45
- },
46
- "scripts": {
47
- "clean": "rimraf ./build",
48
- "test": "cross-env NODE_ENV=test BABEL_ENV=test jest --runTestsByPath",
49
- "type-check": "tsc --noEmit -p tsconfig.build.json",
50
- "build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
51
- "build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
52
- "watch": "pnpm build:js -- --watch",
53
- "build": "cross-env BABEL_ENV=registry babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps"
54
- }
55
- }
2
+ "name": "@verdaccio/logger",
3
+ "version": "6.0.0-6-next.12",
4
+ "description": "logger",
5
+ "main": "./build/index.js",
6
+ "types": "build/index.d.ts",
7
+ "author": {
8
+ "name": "Juan Picado",
9
+ "email": "juanpicado19@gmail.com"
10
+ },
11
+ "repository": {
12
+ "type": "https",
13
+ "url": "https://github.com/verdaccio/verdaccio"
14
+ },
15
+ "license": "MIT",
16
+ "homepage": "https://verdaccio.org",
17
+ "keywords": [
18
+ "private",
19
+ "package",
20
+ "repository",
21
+ "registry",
22
+ "enterprise",
23
+ "modules",
24
+ "proxy",
25
+ "server",
26
+ "verdaccio"
27
+ ],
28
+ "engines": {
29
+ "node": ">=14",
30
+ "npm": ">=6"
31
+ },
32
+ "dependencies": {
33
+ "@verdaccio/core": "6.0.0-6-next.6",
34
+ "@verdaccio/logger-prettify": "6.0.0-6-next.7",
35
+ "debug": "4.3.4",
36
+ "colorette": "2.0.7",
37
+ "pino": "8.4.1"
38
+ },
39
+ "devDependencies": {
40
+ "@verdaccio/types": "11.0.0-6-next.13"
41
+ },
42
+ "funding": {
43
+ "type": "opencollective",
44
+ "url": "https://opencollective.com/verdaccio"
45
+ },
46
+ "scripts": {
47
+ "clean": "rimraf ./build",
48
+ "test": "cross-env TZ=utc jest",
49
+ "type-check": "tsc --noEmit -p tsconfig.build.json",
50
+ "build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
51
+ "build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
52
+ "watch": "pnpm build:js -- --watch",
53
+ "build": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps"
54
+ },
55
+ "readme": "# @verdaccio/logger\n\n[![backers](https://opencollective.com/verdaccio/tiers/backer/badge.svg?label=Backer&color=brightgreen)](https://opencollective.com/verdaccio)\n[![stackshare](https://img.shields.io/badge/Follow%20on-StackShare-blue.svg?logo=stackshare&style=flat)](https://stackshare.io/verdaccio)\n[![MIT](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)\n[![Crowdin](https://d322cqt584bo4o.cloudfront.net/verdaccio/localized.svg)](https://crowdin.com/project/verdaccio)\n[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/verdaccio/verdaccio)](https://www.tickgit.com/browse?repo=github.com/verdaccio/verdaccio)\n\n[![Twitter followers](https://img.shields.io/twitter/follow/verdaccio_npm.svg?style=social&label=Follow)](https://twitter.com/verdaccio_npm)\n[![Github](https://img.shields.io/github/stars/verdaccio/verdaccio.svg?style=social&label=Stars)](https://github.com/verdaccio/verdaccio/stargazers)\n\n## Donations\n\nVerdaccio is run by **volunteers**; nobody is working full-time on it. If you find this project to be useful and would like to support its development, consider making a donation - **your logo might end up in this readme.** 😉\n\n**[Donate](https://opencollective.com/verdaccio)** 💵👍🏻 starting from _\\$1/month_ or just one single contribution.\n\n## Report a vulnerability\n\nIf you want to report a security vulnerability, please follow the steps which we have defined for you in our [security policy](https://github.com/verdaccio/verdaccio/security/policy).\n\n## Open Collective Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio#sponsor)]\n\n[![sponsor](https://opencollective.com/verdaccio/sponsor/0/avatar.svg)](https://opencollective.com/verdaccio/sponsor/0/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/1/avatar.svg)](https://opencollective.com/verdaccio/sponsor/1/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/2/avatar.svg)](https://opencollective.com/verdaccio/sponsor/2/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/3/avatar.svg)](https://opencollective.com/verdaccio/sponsor/3/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/4/avatar.svg)](https://opencollective.com/verdaccio/sponsor/4/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/5/avatar.svg)](https://opencollective.com/verdaccio/sponsor/5/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/6/avatar.svg)](https://opencollective.com/verdaccio/sponsor/6/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/7/avatar.svg)](https://opencollective.com/verdaccio/sponsor/7/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.svg)](https://opencollective.com/verdaccio/sponsor/8/website)\n[![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.svg)](https://opencollective.com/verdaccio/sponsor/9/website)\n\n## Open Collective Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/verdaccio#backer)]\n\n[![backers](https://opencollective.com/verdaccio/backers.svg?width=890)](https://opencollective.com/verdaccio#backers)\n\n## Special Thanks\n\nThanks to the following companies to help us to achieve our goals providing free open source licenses.\n\n[![jetbrain](assets/thanks/jetbrains/logo.png)](https://www.jetbrains.com/)\n[![crowdin](assets/thanks/crowdin/logo.png)](https://crowdin.com/)\n[![balsamiq](assets/thanks/balsamiq/logo.jpg)](https://balsamiq.com/)\n\n## Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n\n[![contributors](https://opencollective.com/verdaccio/contributors.svg?width=890&button=true)](../../graphs/contributors)\n\n### FAQ / Contact / Troubleshoot\n\nIf you have any issue you can try the following options, do no desist to ask or check our issues database, perhaps someone has asked already what you are looking for.\n\n- [Blog](https://verdaccio.org/blog/)\n- [Donations](https://opencollective.com/verdaccio)\n- [Reporting an issue](https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#reporting-a-bug)\n- [Running discussions](https://github.com/verdaccio/verdaccio/issues?q=is%3Aissue+is%3Aopen+label%3Adiscuss)\n- [Chat](http://chat.verdaccio.org/)\n- [Logos](https://verdaccio.org/docs/en/logo)\n- [Docker Examples](https://github.com/verdaccio/docker-examples)\n- [FAQ](https://github.com/verdaccio/verdaccio/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20)\n\n### License\n\nVerdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)\n\nThe Verdaccio documentation and logos (excluding /thanks, e.g., .md, .png, .sketch) files within the /assets folder) is\n[Creative Commons licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE-docs).\n"
56
+ }
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export { setup, createLogger, logger } from './logger';
1
+ export { setup, createLogger, logger, prepareSetup } from './logger';
package/src/logger.ts CHANGED
@@ -1,18 +1,24 @@
1
+ // <reference types="node" />
2
+ import { isColorSupported } from 'colorette';
1
3
  import buildDebug from 'debug';
2
- import _ from 'lodash';
3
- import pino from 'pino';
4
+ import pino, { Logger } from 'pino';
4
5
 
5
- import { warningUtils } from '@verdaccio/core';
6
- import prettifier, { fillInMsgTemplate } from '@verdaccio/logger-prettify';
6
+ import { fillInMsgTemplate } from '@verdaccio/logger-prettify';
7
+ import { LoggerConfigItem, LoggerFormat } from '@verdaccio/types';
7
8
 
8
9
  const debug = buildDebug('verdaccio:logger');
9
10
 
10
- export let logger;
11
-
12
11
  function isProd() {
13
12
  return process.env.NODE_ENV === 'production';
14
13
  }
15
14
 
15
+ function hasColors(colors: boolean | undefined) {
16
+ if (colors) {
17
+ return isColorSupported;
18
+ }
19
+ return typeof colors === 'undefined' ? true : colors;
20
+ }
21
+
16
22
  const DEFAULT_LOG_FORMAT = isProd() ? 'json' : 'pretty';
17
23
 
18
24
  export type LogPlugin = {
@@ -20,28 +26,19 @@ export type LogPlugin = {
20
26
  options?: any[];
21
27
  };
22
28
 
23
- export type LogType = 'file' | 'stdout';
24
- export type LogFormat = 'json' | 'pretty-timestamped' | 'pretty';
29
+ type LoggerOptions = { level?: string; path?: string; colors?: boolean; sync?: boolean };
25
30
 
26
31
  export function createLogger(
27
- options = { level: 'http' },
28
- destination = pino.destination(1),
29
- format: LogFormat = DEFAULT_LOG_FORMAT,
30
- prettyPrintOptions = {
31
- // we hide warning since the prettifier should not be used in production
32
- // https://getpino.io/#/docs/pretty?id=prettifier-api
33
- suppressFlushSyncWarning: true,
34
- }
32
+ options: LoggerOptions = { level: 'http' },
33
+ // eslint-disable-next-line no-undef
34
+ destination: NodeJS.WritableStream = pino.destination(1),
35
+ format: LoggerFormat = DEFAULT_LOG_FORMAT
35
36
  ) {
36
- if (_.isNil(format)) {
37
- format = DEFAULT_LOG_FORMAT;
38
- }
39
-
37
+ debug('setup logger');
40
38
  let pinoConfig = {
41
39
  customLevels: {
42
40
  http: 25,
43
41
  },
44
- ...options,
45
42
  level: options.level,
46
43
  serializers: {
47
44
  err: pino.stdSerializers.err,
@@ -52,23 +49,32 @@ export function createLogger(
52
49
 
53
50
  debug('has prettifier? %o', !isProd());
54
51
  // pretty logs are not allowed in production for performance reasons
55
- if ((format === DEFAULT_LOG_FORMAT || format !== 'json') && isProd() === false) {
52
+ if (['pretty-timestamped', 'pretty'].includes(format) && isProd() === false) {
56
53
  pinoConfig = Object.assign({}, pinoConfig, {
57
- prettifier,
58
- // more info
59
- // https://github.com/pinojs/pino-pretty/issues/37
60
- prettyPrint: {
61
- levelFirst: true,
62
- prettyStamp: format === 'pretty-timestamped',
63
- ...prettyPrintOptions,
54
+ transport: {
55
+ target: '@verdaccio/logger-prettify',
56
+ options: {
57
+ // string or 1 (file descriptor for process.stdout)
58
+ destination: options.path || 1,
59
+ colors: hasColors(options.colors),
60
+ prettyStamp: format === 'pretty-timestamped',
61
+ },
64
62
  },
65
63
  });
66
64
  } else {
67
- pinoConfig = Object.assign({}, pinoConfig, {
65
+ pinoConfig = {
66
+ ...pinoConfig,
68
67
  // more info
69
68
  // https://github.com/pinojs/pino/blob/v7.1.0/docs/api.md#hooks-object
69
+ // TODO: improve typings here
70
+ // @ts-ignore
70
71
  hooks: {
71
- logMethod(inputArgs, method) {
72
+ logMethod(
73
+ inputArgs: [any, any, ...any[]],
74
+ method: {
75
+ apply: (arg0: { logMethod: (inputArgs: any, method: any) => any }, arg1: any[]) => any;
76
+ }
77
+ ) {
72
78
  const [templateObject, message, ...otherArgs] = inputArgs;
73
79
  const templateVars =
74
80
  !!templateObject && typeof templateObject === 'object'
@@ -79,10 +85,12 @@ export function createLogger(
79
85
  return method.apply(this, [templateObject, hydratedMessage, ...otherArgs]);
80
86
  },
81
87
  },
82
- });
88
+ };
83
89
  }
84
90
  const logger = pino(pinoConfig, destination);
85
91
 
92
+ /* eslint-disable */
93
+ /* istanbul ignore next */
86
94
  if (process.env.DEBUG) {
87
95
  logger.on('level-change', (lvl, val, prevLvl, prevVal) => {
88
96
  debug('%s (%d) was changed to %s (%d)', lvl, val, prevLvl, prevVal);
@@ -92,43 +100,21 @@ export function createLogger(
92
100
  return logger;
93
101
  }
94
102
 
95
- export function getLogger() {
96
- if (_.isNil(logger)) {
97
- // FIXME: not sure about display here a warning
98
- warningUtils.emit(warningUtils.Codes.VERWAR002);
99
- return;
100
- }
101
-
102
- return logger;
103
- }
104
-
105
103
  const DEFAULT_LOGGER_CONF: LoggerConfigItem = {
106
104
  type: 'stdout',
107
105
  format: 'pretty',
108
106
  level: 'http',
109
107
  };
110
108
 
111
- export type LoggerConfigItem = {
112
- type?: LogType;
113
- plugin?: LogPlugin;
114
- format?: LogFormat;
115
- path?: string;
116
- level?: string;
117
- };
109
+ export type LoggerConfig = LoggerConfigItem;
118
110
 
119
- export type LoggerConfig = LoggerConfigItem[];
120
-
121
- export function setup(options: LoggerConfig | LoggerConfigItem = DEFAULT_LOGGER_CONF) {
122
- debug('setup logger');
123
- const isLegacyConf = Array.isArray(options);
124
- if (isLegacyConf) {
125
- warningUtils.emit(warningUtils.Codes.VERDEP002);
126
- }
127
-
128
- // verdaccio 5 does not allow multiple logger configuration
129
- // backward compatible, pick only the first option
130
- // next major will thrown an error
131
- let loggerConfig = isLegacyConf ? options[0] : options;
111
+ export function prepareSetup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF) {
112
+ let logger: Logger<{
113
+ customLevels: { http: number };
114
+ level: string | undefined;
115
+ serializers: { err: any; req: any; res: any };
116
+ }>;
117
+ let loggerConfig = options;
132
118
  if (!loggerConfig?.level) {
133
119
  loggerConfig = Object.assign(
134
120
  {},
@@ -141,35 +127,36 @@ export function setup(options: LoggerConfig | LoggerConfigItem = DEFAULT_LOGGER_
141
127
  const pinoConfig = { level: loggerConfig.level };
142
128
  if (loggerConfig.type === 'file') {
143
129
  debug('logging file enabled');
144
- logger = createLogger(pinoConfig, pino.destination(loggerConfig.path), loggerConfig.format);
145
- } else if (loggerConfig.type === 'rotating-file') {
146
- warningUtils.emit(warningUtils.Codes.VERWAR003);
147
- debug('logging stdout enabled');
148
- logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);
130
+ const destination = pino.destination(loggerConfig.path);
131
+ /* eslint-disable */
132
+ /* istanbul ignore next */
133
+ process.on('SIGUSR2', () => destination.reopen());
134
+ // @ts-ignore
135
+ logger = createLogger(
136
+ { level: loggerConfig.level, path: loggerConfig.path, colors: loggerConfig.colors },
137
+ destination,
138
+ loggerConfig.format
139
+ );
140
+ return logger;
149
141
  } else {
150
142
  debug('logging stdout enabled');
151
- logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);
143
+ // @ts-ignore
144
+ logger = createLogger(
145
+ { level: loggerConfig.level, colors: loggerConfig.colors },
146
+ pino.destination(1),
147
+ loggerConfig.format
148
+ );
149
+ return logger;
152
150
  }
151
+ }
153
152
 
154
- if (isProd()) {
155
- // why only on prod? https://github.com/pinojs/pino/issues/920#issuecomment-710807667
156
- const finalHandler = pino.final(logger, (err, finalLogger, event) => {
157
- finalLogger.info(`${event} caught`);
158
- if (err) {
159
- finalLogger.error(err, 'error caused exit');
160
- }
161
- process.exit(err ? 1 : 0);
162
- });
153
+ export let logger: Logger;
163
154
 
164
- process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));
165
- process.on('unhandledRejection', (err) => finalHandler(err as Error, 'unhandledRejection'));
166
- process.on('beforeExit', () => finalHandler(null, 'beforeExit'));
167
- process.on('exit', () => finalHandler(null, 'exit'));
168
- process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));
169
- process.on('SIGINT', () => finalHandler(null, 'SIGINT'));
170
- process.on('SIGQUIT', () => finalHandler(null, 'SIGQUIT'));
171
- process.on('SIGTERM', () => finalHandler(null, 'SIGTERM'));
155
+ export function setup(options: LoggerConfigItem) {
156
+ if (typeof logger !== 'undefined') {
157
+ return logger;
172
158
  }
173
159
 
160
+ logger = prepareSetup(options);
174
161
  return logger;
175
162
  }
@@ -0,0 +1,20 @@
1
+ import { Writable } from 'stream';
2
+
3
+ import { createLogger } from '../src';
4
+
5
+ describe('logger test', () => {
6
+ describe('json format', () => {
7
+ test('should write json to a stream', () => {
8
+ const stream = new Writable({
9
+ write(chunk, encoding, callback) {
10
+ expect(JSON.parse(chunk.toString())).toEqual(
11
+ expect.objectContaining({ level: 30, msg: 'test' })
12
+ );
13
+ callback();
14
+ },
15
+ });
16
+ const logger = createLogger({ level: 'http' }, stream, 'json');
17
+ logger.info('test');
18
+ });
19
+ });
20
+ });
@@ -1,53 +1,115 @@
1
- import { warningUtils } from '@verdaccio/core';
2
-
3
- import { logger, setup } from '../src';
4
-
5
- const mockWarningUtils = jest.fn();
6
-
7
- jest.mock('@verdaccio/core', () => {
8
- const original = jest.requireActual('@verdaccio/core');
9
- return {
10
- warningUtils: {
11
- ...original.warningUtils,
12
- emit: (...args) => {
13
- mockWarningUtils(...args);
14
- },
15
- },
16
- };
17
- });
1
+ import { readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { setTimeout } from 'timers/promises';
18
4
 
19
- describe('logger', () => {
20
- beforeEach(() => {
21
- jest.clearAllMocks();
22
- });
5
+ import { fileUtils } from '@verdaccio/core';
23
6
 
24
- test.skip('should write message logger', () => {
25
- jest.spyOn(process.stdout, 'write');
26
- setup([
27
- {
28
- level: 'info',
29
- },
30
- ]);
7
+ import { prepareSetup } from '../src';
8
+
9
+ async function readLogFile(path: string) {
10
+ await setTimeout(1000, 'resolved');
11
+ return readFile(path, 'utf8');
12
+ }
31
13
 
32
- logger.info({ packageName: 'test' }, `publishing or updating a new version for @{packageName}`);
33
- // FIXME: check expect
34
- // expect(spyOn).toHaveBeenCalledTimes(2);
14
+ async function createLogFile() {
15
+ const folder = await fileUtils.createTempFolder('logger-1');
16
+ const file = join(folder, 'logger.log');
17
+ return file;
18
+ }
19
+
20
+ const defaultOptions = {
21
+ format: 'json',
22
+ level: 'http',
23
+ colors: false,
24
+ };
25
+
26
+ describe('logger test', () => {
27
+ describe('basic', () => {
28
+ test('should include default level', async () => {
29
+ const file = await createLogFile();
30
+ const logger = prepareSetup({ type: 'file', path: file, colors: false });
31
+ logger.info({ packageName: 'test' }, `testing @{packageName}`);
32
+ // Note: this should not be logged
33
+ logger.debug(`this should not be logged`);
34
+ // Note: this should not be logged
35
+ logger.trace(`this should not be logged`);
36
+ logger.error(`this should logged`);
37
+ const content = await readLogFile(file);
38
+ expect(content).toBe('info --- testing test \nerror--- this should logged \n');
39
+ });
40
+
41
+ test('should include all logging level', async () => {
42
+ const file = await createLogFile();
43
+ const logger = prepareSetup({ type: 'file', level: 'trace', path: file, colors: false });
44
+ logger.info({ packageName: 'test' }, `testing @{packageName}`);
45
+ logger.debug(`this should not be logged`);
46
+ logger.trace(`this should not be logged`);
47
+ logger.error(`this should logged`);
48
+ const content = await readLogFile(file);
49
+ expect(content).toBe(
50
+ 'info --- testing test \ndebug--- this should not be logged \ntrace--- this should not be logged \nerror--- this should logged \n'
51
+ );
52
+ });
35
53
  });
36
54
 
37
- test('throw deprecation warning if multiple loggers configured', () => {
38
- setup([
39
- {
55
+ describe('json format', () => {
56
+ test('should log into a file with json format', async () => {
57
+ const file = await createLogFile();
58
+ const logger = prepareSetup({
59
+ ...defaultOptions,
60
+ format: 'json',
61
+ type: 'file',
62
+ path: file,
40
63
  level: 'info',
41
- },
42
- {
43
- level: 'http',
44
- },
45
- ]);
46
- expect(mockWarningUtils).toHaveBeenCalledWith(warningUtils.Codes.VERDEP002);
64
+ });
65
+ logger.info(
66
+ { packageName: 'test' },
67
+ `publishing or updating a new version for @{packageName}`
68
+ );
69
+ const content = await readLogFile(file);
70
+ expect(JSON.parse(content)).toEqual(
71
+ expect.objectContaining({
72
+ level: 30,
73
+ msg: 'publishing or updating a new version for test',
74
+ })
75
+ );
76
+ });
47
77
  });
48
78
 
49
- test('regression: do not throw deprecation warning if no logger config is provided', () => {
50
- setup();
51
- expect(mockWarningUtils).not.toHaveBeenCalled();
79
+ describe('pretty format', () => {
80
+ test('should log into a file with pretty', async () => {
81
+ const file = await createLogFile();
82
+ const logger = prepareSetup({
83
+ format: 'pretty',
84
+ type: 'file',
85
+ path: file,
86
+ level: 'trace',
87
+ colors: false,
88
+ });
89
+ logger.info(
90
+ { packageName: 'test' },
91
+ `publishing or updating a new version for @{packageName}`
92
+ );
93
+ const content = await readLogFile(file);
94
+ expect(content).toEqual('info --- publishing or updating a new version for test \n');
95
+ });
96
+
97
+ test('should log into a file with pretty-timestamped', async () => {
98
+ const file = await createLogFile();
99
+ const logger = prepareSetup({
100
+ format: 'pretty-timestamped',
101
+ type: 'file',
102
+ path: file,
103
+ level: 'trace',
104
+ colors: false,
105
+ });
106
+ logger.info(
107
+ { packageName: 'test' },
108
+ `publishing or updating a new version for @{packageName}`
109
+ );
110
+ const content = await readLogFile(file);
111
+ // TODO: we might want mock time for testing
112
+ expect(content).toMatch('info --- publishing or updating a new version for test \n');
113
+ });
52
114
  });
53
115
  });