@verdaccio/logger 6.0.0-6-next.11 → 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,41 @@
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
+
3
39
  ## 6.0.0-6-next.11
4
40
 
5
41
  ### 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), 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
- }, format = DEFAULT_LOG_FORMAT) {
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,27 +98,16 @@ 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');
110
+ let logger;
122
111
  let loggerConfig = options;
123
112
 
124
113
  if (!((_loggerConfig = loggerConfig) !== null && _loggerConfig !== void 0 && _loggerConfig.level)) {
@@ -135,44 +124,39 @@ function setup(options = DEFAULT_LOGGER_CONF) {
135
124
  debug('logging file enabled');
136
125
 
137
126
  const destination = _pino.default.destination(loggerConfig.path);
127
+ /* eslint-disable */
138
128
 
139
- process.on('SIGUSR2', () => destination.reopen()); // @ts-ignore
129
+ /* istanbul ignore next */
140
130
 
141
- exports.logger = logger = createLogger(pinoConfig, destination, loggerConfig.format); // @ts-ignore
142
- } else if (loggerConfig.type === 'rotating-file') {
143
- _core.warningUtils.emit(_core.warningUtils.Codes.VERWAR003);
144
131
 
145
- debug('logging stdout enabled'); // @ts-ignore
132
+ process.on('SIGUSR2', () => destination.reopen()); // @ts-ignore
146
133
 
147
- exports.logger = logger = createLogger(pinoConfig, _pino.default.destination(1), loggerConfig.format);
134
+ logger = createLogger({
135
+ level: loggerConfig.level,
136
+ path: loggerConfig.path,
137
+ colors: loggerConfig.colors
138
+ }, destination, loggerConfig.format);
139
+ return logger;
148
140
  } else {
149
141
  debug('logging stdout enabled'); // @ts-ignore
150
142
 
151
- exports.logger = logger = createLogger(pinoConfig, _pino.default.destination(1), loggerConfig.format);
143
+ logger = createLogger({
144
+ level: loggerConfig.level,
145
+ colors: loggerConfig.colors
146
+ }, _pino.default.destination(1), loggerConfig.format);
147
+ return logger;
152
148
  }
149
+ }
153
150
 
154
- if (isProd()) {
155
- // why only on prod? https://github.com/pinojs/pino/issues/920#issuecomment-710807667
156
- const finalHandler = _pino.default.final(logger, (err, finalLogger, event) => {
157
- finalLogger.info(`${event} caught`);
158
-
159
- if (err) {
160
- finalLogger.error(err, 'error caused exit');
161
- }
162
-
163
- process.exit(err ? 1 : 0);
164
- });
151
+ let logger;
152
+ exports.logger = logger;
165
153
 
166
- process.on('uncaughtException', err => finalHandler(err, 'uncaughtException'));
167
- process.on('unhandledRejection', err => finalHandler(err, 'unhandledRejection'));
168
- process.on('beforeExit', () => finalHandler(null, 'beforeExit'));
169
- process.on('exit', () => finalHandler(null, 'exit'));
170
- process.on('uncaughtException', err => finalHandler(err, 'uncaughtException'));
171
- process.on('SIGINT', () => finalHandler(null, 'SIGINT'));
172
- process.on('SIGQUIT', () => finalHandler(null, 'SIGQUIT'));
173
- process.on('SIGTERM', () => finalHandler(null, 'SIGTERM'));
154
+ function setup(options) {
155
+ if (typeof logger !== 'undefined') {
156
+ return logger;
174
157
  }
175
158
 
159
+ exports.logger = logger = prepareSetup(options);
176
160
  return logger;
177
161
  }
178
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","prettyPrintOptions","suppressFlushSyncWarning","format","_","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","loggerConfig","path","reopen","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 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 format: LogFormat = DEFAULT_LOG_FORMAT\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: LoggerConfigItem = DEFAULT_LOGGER_CONF) {\n debug('setup logger');\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 process.on('SIGUSR2', () => destination.reopen());\n // @ts-ignore\n logger = createLogger(pinoConfig, destination, loggerConfig.format);\n // @ts-ignore\n } else if (loggerConfig.type === 'rotating-file') {\n warningUtils.emit(warningUtils.Codes.VERWAR003);\n debug('logging stdout enabled');\n // @ts-ignore\n logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);\n } else {\n debug('logging stdout enabled');\n // @ts-ignore\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,56 +1,56 @@
1
1
  {
2
- "name": "@verdaccio/logger",
3
- "version": "6.0.0-6-next.11",
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.5",
34
- "@verdaccio/logger-prettify": "6.0.0-6-next.6",
35
- "pino-pretty": "7.6.0",
36
- "debug": "4.3.3",
37
- "lodash": "4.17.21",
38
- "pino": "7.6.4"
39
- },
40
- "devDependencies": {
41
- "@verdaccio/types": "11.0.0-6-next.11"
42
- },
43
- "funding": {
44
- "type": "opencollective",
45
- "url": "https://opencollective.com/verdaccio"
46
- },
47
- "scripts": {
48
- "clean": "rimraf ./build",
49
- "test": "cross-env NODE_ENV=test BABEL_ENV=test jest --runTestsByPath",
50
- "type-check": "tsc --noEmit -p tsconfig.build.json",
51
- "build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
52
- "build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
53
- "watch": "pnpm build:js -- --watch",
54
- "build": "cross-env BABEL_ENV=registry babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps"
55
- }
56
- }
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
- prettyPrintOptions = {
30
- // we hide warning since the prettifier should not be used in production
31
- // https://getpino.io/#/docs/pretty?id=prettifier-api
32
- suppressFlushSyncWarning: true,
33
- },
34
- format: LogFormat = DEFAULT_LOG_FORMAT
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,34 +100,20 @@ 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
- };
118
-
119
109
  export type LoggerConfig = LoggerConfigItem;
120
110
 
121
- export function setup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF) {
122
- debug('setup logger');
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
+ }>;
123
117
  let loggerConfig = options;
124
118
  if (!loggerConfig?.level) {
125
119
  loggerConfig = Object.assign(
@@ -134,40 +128,35 @@ export function setup(options: LoggerConfigItem = DEFAULT_LOGGER_CONF) {
134
128
  if (loggerConfig.type === 'file') {
135
129
  debug('logging file enabled');
136
130
  const destination = pino.destination(loggerConfig.path);
131
+ /* eslint-disable */
132
+ /* istanbul ignore next */
137
133
  process.on('SIGUSR2', () => destination.reopen());
138
134
  // @ts-ignore
139
- logger = createLogger(pinoConfig, destination, loggerConfig.format);
140
- // @ts-ignore
141
- } else if (loggerConfig.type === 'rotating-file') {
142
- warningUtils.emit(warningUtils.Codes.VERWAR003);
143
- debug('logging stdout enabled');
144
- // @ts-ignore
145
- logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);
135
+ logger = createLogger(
136
+ { level: loggerConfig.level, path: loggerConfig.path, colors: loggerConfig.colors },
137
+ destination,
138
+ loggerConfig.format
139
+ );
140
+ return logger;
146
141
  } else {
147
142
  debug('logging stdout enabled');
148
143
  // @ts-ignore
149
- logger = createLogger(pinoConfig, pino.destination(1), loggerConfig.format);
144
+ logger = createLogger(
145
+ { level: loggerConfig.level, colors: loggerConfig.colors },
146
+ pino.destination(1),
147
+ loggerConfig.format
148
+ );
149
+ return logger;
150
150
  }
151
+ }
151
152
 
152
- if (isProd()) {
153
- // why only on prod? https://github.com/pinojs/pino/issues/920#issuecomment-710807667
154
- const finalHandler = pino.final(logger, (err, finalLogger, event) => {
155
- finalLogger.info(`${event} caught`);
156
- if (err) {
157
- finalLogger.error(err, 'error caused exit');
158
- }
159
- process.exit(err ? 1 : 0);
160
- });
153
+ export let logger: Logger;
161
154
 
162
- process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));
163
- process.on('unhandledRejection', (err) => finalHandler(err as Error, 'unhandledRejection'));
164
- process.on('beforeExit', () => finalHandler(null, 'beforeExit'));
165
- process.on('exit', () => finalHandler(null, 'exit'));
166
- process.on('uncaughtException', (err) => finalHandler(err, 'uncaughtException'));
167
- process.on('SIGINT', () => finalHandler(null, 'SIGINT'));
168
- process.on('SIGQUIT', () => finalHandler(null, 'SIGQUIT'));
169
- process.on('SIGTERM', () => finalHandler(null, 'SIGTERM'));
155
+ export function setup(options: LoggerConfigItem) {
156
+ if (typeof logger !== 'undefined') {
157
+ return logger;
170
158
  }
171
159
 
160
+ logger = prepareSetup(options);
172
161
  return logger;
173
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,51 +1,115 @@
1
- import { logger, setup } from '../src';
2
-
3
- const mockWarningUtils = jest.fn();
4
-
5
- jest.mock('@verdaccio/core', () => {
6
- const original = jest.requireActual('@verdaccio/core');
7
- return {
8
- warningUtils: {
9
- ...original.warningUtils,
10
- emit: (...args) => {
11
- mockWarningUtils(...args);
12
- },
13
- },
14
- };
15
- });
1
+ import { readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { setTimeout } from 'timers/promises';
16
4
 
17
- describe('logger', () => {
18
- beforeEach(() => {
19
- jest.clearAllMocks();
20
- });
5
+ import { fileUtils } from '@verdaccio/core';
21
6
 
22
- test.skip('should write message logger', () => {
23
- jest.spyOn(process.stdout, 'write');
24
- setup([
25
- {
26
- level: 'info',
27
- },
28
- ]);
7
+ import { prepareSetup } from '../src';
8
+
9
+ async function readLogFile(path: string) {
10
+ await setTimeout(1000, 'resolved');
11
+ return readFile(path, 'utf8');
12
+ }
29
13
 
30
- logger.info({ packageName: 'test' }, `publishing or updating a new version for @{packageName}`);
31
- // FIXME: check expect
32
- // 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
+ });
33
53
  });
34
54
 
35
- test.skip('throw deprecation warning if multiple loggers configured', () => {
36
- setup([
37
- {
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,
38
63
  level: 'info',
39
- },
40
- {
41
- level: 'http',
42
- },
43
- ]);
44
- // 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
+ });
45
77
  });
46
78
 
47
- test('regression: do not throw deprecation warning if no logger config is provided', () => {
48
- setup();
49
- 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
+ });
50
114
  });
51
115
  });