pino-testkit 10.4.5

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.
Files changed (196) hide show
  1. package/.nojekyll +0 -0
  2. package/.prettierignore +1 -0
  3. package/CNAME +1 -0
  4. package/CONTRIBUTING.md +30 -0
  5. package/LICENSE +21 -0
  6. package/README.md +175 -0
  7. package/SECURITY.md +87 -0
  8. package/benchmarks/basic.bench.js +95 -0
  9. package/benchmarks/child-child.bench.js +52 -0
  10. package/benchmarks/child-creation.bench.js +73 -0
  11. package/benchmarks/child.bench.js +62 -0
  12. package/benchmarks/deep-object.bench.js +88 -0
  13. package/benchmarks/formatters.bench.js +50 -0
  14. package/benchmarks/internal/custom-levels.js +67 -0
  15. package/benchmarks/internal/just-pino-heavy.bench.js +76 -0
  16. package/benchmarks/internal/just-pino.bench.js +182 -0
  17. package/benchmarks/internal/parent-vs-child.bench.js +75 -0
  18. package/benchmarks/internal/redact.bench.js +86 -0
  19. package/benchmarks/long-string.bench.js +81 -0
  20. package/benchmarks/multi-arg.bench.js +193 -0
  21. package/benchmarks/multistream.js +98 -0
  22. package/benchmarks/object.bench.js +82 -0
  23. package/benchmarks/utils/generate-benchmark-doc.js +36 -0
  24. package/benchmarks/utils/runbench.js +138 -0
  25. package/benchmarks/utils/wrap-log-level.js +55 -0
  26. package/bin.js +6 -0
  27. package/browser.js +547 -0
  28. package/build/sync-version.js +25 -0
  29. package/docs/api.md +1593 -0
  30. package/docs/asynchronous.md +40 -0
  31. package/docs/benchmarks.md +55 -0
  32. package/docs/browser.md +278 -0
  33. package/docs/bundling.md +40 -0
  34. package/docs/child-loggers.md +95 -0
  35. package/docs/diagnostics.md +16 -0
  36. package/docs/ecosystem.md +86 -0
  37. package/docs/help.md +345 -0
  38. package/docs/lts.md +64 -0
  39. package/docs/pretty.md +35 -0
  40. package/docs/redaction.md +135 -0
  41. package/docs/transports.md +1376 -0
  42. package/docs/web.md +309 -0
  43. package/eslint.config.js +28 -0
  44. package/examples/basic.js +43 -0
  45. package/examples/transport.js +68 -0
  46. package/favicon.ico +0 -0
  47. package/file.js +12 -0
  48. package/inc-version.sh +42 -0
  49. package/index.html +55 -0
  50. package/lib/caller.js +30 -0
  51. package/lib/constants.js +28 -0
  52. package/lib/contract.js +8 -0
  53. package/lib/deprecations.js +8 -0
  54. package/lib/levels.js +241 -0
  55. package/lib/meta.js +3 -0
  56. package/lib/multistream.js +203 -0
  57. package/lib/proto.js +256 -0
  58. package/lib/redaction.js +114 -0
  59. package/lib/symbols.js +74 -0
  60. package/lib/time.js +39 -0
  61. package/lib/tools.js +427 -0
  62. package/lib/transport-stream.js +56 -0
  63. package/lib/transport.js +289 -0
  64. package/lib/worker.js +194 -0
  65. package/package.json +119 -0
  66. package/pino.d.ts +908 -0
  67. package/pino.js +240 -0
  68. package/test/basic.test.js +886 -0
  69. package/test/broken-pipe.test.js +59 -0
  70. package/test/browser-child.test.js +132 -0
  71. package/test/browser-disabled.test.js +87 -0
  72. package/test/browser-early-console-freeze.test.js +12 -0
  73. package/test/browser-is-level-enabled.test.js +101 -0
  74. package/test/browser-levels.test.js +241 -0
  75. package/test/browser-serializers.test.js +352 -0
  76. package/test/browser-timestamp.test.js +88 -0
  77. package/test/browser-transmit.test.js +417 -0
  78. package/test/browser.test.js +698 -0
  79. package/test/complex-objects.test.js +36 -0
  80. package/test/crlf.test.js +34 -0
  81. package/test/custom-levels.test.js +267 -0
  82. package/test/diagnostics.test.js +107 -0
  83. package/test/error-key.test.js +37 -0
  84. package/test/error.test.js +403 -0
  85. package/test/escaping.test.js +93 -0
  86. package/test/esm/esm.mjs +14 -0
  87. package/test/esm/index.test.js +21 -0
  88. package/test/esm/named-exports.mjs +29 -0
  89. package/test/exit.test.js +79 -0
  90. package/test/fixtures/broken-pipe/basic.js +9 -0
  91. package/test/fixtures/broken-pipe/destination.js +10 -0
  92. package/test/fixtures/broken-pipe/syncfalse.js +12 -0
  93. package/test/fixtures/console-transport.js +13 -0
  94. package/test/fixtures/crashing-transport.js +13 -0
  95. package/test/fixtures/default-exit.js +8 -0
  96. package/test/fixtures/destination-exit.js +8 -0
  97. package/test/fixtures/eval/index.js +13 -0
  98. package/test/fixtures/eval/node_modules/14-files.js +3 -0
  99. package/test/fixtures/eval/node_modules/2-files.js +3 -0
  100. package/test/fixtures/eval/node_modules/file1.js +5 -0
  101. package/test/fixtures/eval/node_modules/file10.js +5 -0
  102. package/test/fixtures/eval/node_modules/file11.js +5 -0
  103. package/test/fixtures/eval/node_modules/file12.js +5 -0
  104. package/test/fixtures/eval/node_modules/file13.js +5 -0
  105. package/test/fixtures/eval/node_modules/file14.js +11 -0
  106. package/test/fixtures/eval/node_modules/file2.js +5 -0
  107. package/test/fixtures/eval/node_modules/file3.js +5 -0
  108. package/test/fixtures/eval/node_modules/file4.js +5 -0
  109. package/test/fixtures/eval/node_modules/file5.js +5 -0
  110. package/test/fixtures/eval/node_modules/file6.js +5 -0
  111. package/test/fixtures/eval/node_modules/file7.js +5 -0
  112. package/test/fixtures/eval/node_modules/file8.js +5 -0
  113. package/test/fixtures/eval/node_modules/file9.js +5 -0
  114. package/test/fixtures/noop-transport.js +10 -0
  115. package/test/fixtures/pretty/null-prototype.js +8 -0
  116. package/test/fixtures/stdout-hack-protection.js +11 -0
  117. package/test/fixtures/syncfalse-child.js +6 -0
  118. package/test/fixtures/syncfalse-exit.js +9 -0
  119. package/test/fixtures/syncfalse-flush-exit.js +10 -0
  120. package/test/fixtures/syncfalse.js +6 -0
  121. package/test/fixtures/syntax-error-esm.mjs +2 -0
  122. package/test/fixtures/to-file-transport-with-transform.js +20 -0
  123. package/test/fixtures/to-file-transport.js +13 -0
  124. package/test/fixtures/to-file-transport.mjs +8 -0
  125. package/test/fixtures/transport/index.js +12 -0
  126. package/test/fixtures/transport/package.json +5 -0
  127. package/test/fixtures/transport-exit-immediately-with-async-dest.js +16 -0
  128. package/test/fixtures/transport-exit-immediately.js +11 -0
  129. package/test/fixtures/transport-exit-on-ready.js +12 -0
  130. package/test/fixtures/transport-invalid-node-options.js +26 -0
  131. package/test/fixtures/transport-main.js +9 -0
  132. package/test/fixtures/transport-many-lines.js +29 -0
  133. package/test/fixtures/transport-preload-main.mjs +13 -0
  134. package/test/fixtures/transport-preload.mjs +13 -0
  135. package/test/fixtures/transport-string-stdout.js +9 -0
  136. package/test/fixtures/transport-transform.js +21 -0
  137. package/test/fixtures/transport-uses-pino-config.js +33 -0
  138. package/test/fixtures/transport-with-on-exit.js +12 -0
  139. package/test/fixtures/transport-worker-data.js +19 -0
  140. package/test/fixtures/transport-worker-name.js +24 -0
  141. package/test/fixtures/transport-worker.js +15 -0
  142. package/test/fixtures/transport-wrong-export-type.js +3 -0
  143. package/test/fixtures/ts/to-file-transport-native.mts +15 -0
  144. package/test/fixtures/ts/to-file-transport-with-transform.ts +18 -0
  145. package/test/fixtures/ts/to-file-transport.ts +11 -0
  146. package/test/fixtures/ts/transpile.cjs +36 -0
  147. package/test/fixtures/ts/transport-exit-immediately-with-async-dest.ts +15 -0
  148. package/test/fixtures/ts/transport-exit-immediately.ts +10 -0
  149. package/test/fixtures/ts/transport-exit-on-ready.ts +11 -0
  150. package/test/fixtures/ts/transport-main.ts +8 -0
  151. package/test/fixtures/ts/transport-string-stdout.ts +8 -0
  152. package/test/fixtures/ts/transport-worker.ts +14 -0
  153. package/test/formatters.test.js +364 -0
  154. package/test/helper.d.ts +4 -0
  155. package/test/helper.js +155 -0
  156. package/test/hooks.test.js +114 -0
  157. package/test/http.test.js +214 -0
  158. package/test/internals/version.test.js +17 -0
  159. package/test/is-level-enabled.test.js +179 -0
  160. package/test/jest/basic.spec.js +10 -0
  161. package/test/levels.test.js +810 -0
  162. package/test/metadata.test.js +120 -0
  163. package/test/mixin-merge-strategy.test.js +57 -0
  164. package/test/mixin.test.js +241 -0
  165. package/test/multistream.test.js +729 -0
  166. package/test/redact.test.js +893 -0
  167. package/test/serializers.test.js +257 -0
  168. package/test/stdout-protection.test.js +41 -0
  169. package/test/syncfalse.test.js +186 -0
  170. package/test/timestamp-nano.test.js +37 -0
  171. package/test/timestamp.test.js +124 -0
  172. package/test/transport/big.test.js +42 -0
  173. package/test/transport/bundlers-support.test.js +99 -0
  174. package/test/transport/caller.test.js +24 -0
  175. package/test/transport/core.test.js +733 -0
  176. package/test/transport/core.transpiled.test.ts +114 -0
  177. package/test/transport/crash.test.js +36 -0
  178. package/test/transport/module-link.test.js +241 -0
  179. package/test/transport/native-type-stripping.test.mjs +151 -0
  180. package/test/transport/node-options.test.js +116 -0
  181. package/test/transport/pipeline.test.js +137 -0
  182. package/test/transport/preload.test.js +54 -0
  183. package/test/transport/repl.test.js +15 -0
  184. package/test/transport/sync-false.test.js +67 -0
  185. package/test/transport/sync-true.test.js +57 -0
  186. package/test/transport/targets.test.js +48 -0
  187. package/test/transport/uses-pino-config.test.js +166 -0
  188. package/test/transport-stream.test.js +40 -0
  189. package/test/types/pino-import.test-d.cts +30 -0
  190. package/test/types/pino-multistream.test-d.ts +28 -0
  191. package/test/types/pino-top-export.test-d.ts +34 -0
  192. package/test/types/pino-transport.test-d.ts +156 -0
  193. package/test/types/pino-type-only.test-d.ts +75 -0
  194. package/test/types/pino.test-d.ts +683 -0
  195. package/test/types/pino.ts +91 -0
  196. package/tsconfig.json +14 -0
@@ -0,0 +1,683 @@
1
+ import { IncomingMessage, ServerResponse } from 'http'
2
+ import { mock } from 'node:test'
3
+ import { Socket } from 'net'
4
+ import { expectError, expectType } from 'tsd'
5
+ import pino, { LogFn, LoggerOptions } from '../../'
6
+ import Logger = pino.Logger
7
+
8
+ const log = pino()
9
+ const info = log.info
10
+ const error = log.error
11
+
12
+ info('hello world')
13
+ error('this is at error level')
14
+
15
+ // primitive types
16
+ info('simple string')
17
+ info(true)
18
+ info(42)
19
+ info(3.14)
20
+ info(null)
21
+ info(undefined)
22
+
23
+ // object types
24
+ info({ a: 1, b: '2' })
25
+ info(new Error())
26
+ info(new Date())
27
+ info([])
28
+ info(new Map())
29
+ info(new Set())
30
+
31
+ // placeholder messages
32
+ info('Hello %s', 'world')
33
+ info('The answer is %d', 42)
34
+ info('The object is %o', { a: 1, b: '2' })
35
+ info('The json is %j', { a: 1, b: '2' })
36
+ info('The object is %O', { a: 1, b: '2' })
37
+ info('The answer is %d and the question is %s with %o', 42, 'unknown', {
38
+ correct: 'order',
39
+ })
40
+ info('Missing placeholder is fine %s')
41
+
42
+ // %s placeholder supports all primitive types
43
+ info('Boolean %s', true)
44
+ info('Boolean %s', false)
45
+ info('Number %s', 123)
46
+ info('Number %s', 3.14)
47
+ info('BigInt %s', BigInt(123))
48
+ info('Null %s', null)
49
+ info('Undefined %s', undefined)
50
+ info('Symbol %s', Symbol('test'))
51
+ info('String %s', 'hello')
52
+
53
+ // %s placeholder with multiple primitives
54
+ info('Multiple primitives %s %s %s', true, 42, 'world')
55
+ info(
56
+ 'All primitive types %s %s %s %s %s %s %s',
57
+ 'string',
58
+ 123,
59
+ true,
60
+ BigInt(123),
61
+ null,
62
+ undefined,
63
+ Symbol('test')
64
+ )
65
+ declare const errorOrString: string | Error
66
+ info(errorOrString)
67
+
68
+ // %o placeholder supports primitives too (except undefined)
69
+ info('Boolean %o', true)
70
+ info('Boolean %o', false)
71
+ info('Number %o', 123)
72
+ info('Number %o', 3.14)
73
+ info('BigInt %o', BigInt(123))
74
+ info('Null %o', null)
75
+ info('Symbol %o', Symbol('test'))
76
+ info('String %o', 'hello')
77
+
78
+ // placeholder messages type errors
79
+ expectError(info('The answer is %d', 'not a number'))
80
+ expectError(
81
+ info(
82
+ 'The answer is %d and the question is %s with %o',
83
+ 'unknown',
84
+ { incorrect: 'order' },
85
+ 42
86
+ )
87
+ )
88
+ expectError(info('Extra message %s', 'after placeholder', 'not allowed'))
89
+
90
+ // object types with messages
91
+ info({ obj: 42 }, 'hello world')
92
+ info({ obj: 42, b: 2 }, 'hello world')
93
+ info({ obj: { aa: 'bbb' } }, 'another')
94
+ info({ a: 1, b: '2' }, 'hello world with %s', 'extra data')
95
+
96
+ // Extra message after placeholder
97
+ expectError(info({ a: 1, b: '2' }, 'hello world with %d', 2, 'extra'))
98
+
99
+ // metadata with messages type passes, because of custom toString method
100
+ // We can't detect if the object has a custom toString method that returns a string
101
+ info({ a: 1, b: '2' }, 'hello world with %s', {})
102
+
103
+ // metadata after message
104
+ expectError(info('message', { a: 1, b: '2' }))
105
+
106
+ // multiple strings without placeholder
107
+ expectError(info('string1', 'string2'))
108
+ expectError(info('string1', 'string2', 'string3'))
109
+
110
+ setImmediate(info, 'after setImmediate')
111
+ error(new Error('an error'))
112
+
113
+ const writeSym = pino.symbols.writeSym
114
+
115
+ const testUniqSymbol = {
116
+ [pino.symbols.needsMetadataGsym]: true,
117
+ }[pino.symbols.needsMetadataGsym]
118
+
119
+ const log2: pino.Logger = pino({
120
+ name: 'myapp',
121
+ safe: true,
122
+ serializers: {
123
+ req: pino.stdSerializers.req,
124
+ res: pino.stdSerializers.res,
125
+ err: pino.stdSerializers.err,
126
+ },
127
+ })
128
+
129
+ pino({
130
+ write (o) {},
131
+ })
132
+
133
+ pino({
134
+ mixin () {
135
+ return { customName: 'unknown', customId: 111 }
136
+ },
137
+ })
138
+
139
+ pino({
140
+ mixin: () => ({ customName: 'unknown', customId: 111 }),
141
+ })
142
+
143
+ pino({
144
+ mixin: (context: object) => ({ customName: 'unknown', customId: 111 }),
145
+ })
146
+
147
+ pino({
148
+ mixin: (context: object, level: number) => ({
149
+ customName: 'unknown',
150
+ customId: 111,
151
+ }),
152
+ })
153
+
154
+ pino({
155
+ redact: { paths: [], censor: 'SECRET' },
156
+ })
157
+
158
+ pino({
159
+ redact: { paths: [], censor: () => 'SECRET' },
160
+ })
161
+
162
+ pino({
163
+ redact: { paths: [], censor: (value) => value },
164
+ })
165
+
166
+ pino({
167
+ redact: { paths: [], censor: (value, path) => path.join() },
168
+ })
169
+
170
+ pino({
171
+ redact: {
172
+ paths: [],
173
+ censor: (value): string => 'SECRET',
174
+ },
175
+ })
176
+
177
+ expectError(
178
+ pino({
179
+ redact: { paths: [], censor: (value: string) => value },
180
+ })
181
+ )
182
+
183
+ pino({
184
+ depthLimit: 1,
185
+ })
186
+
187
+ pino({
188
+ edgeLimit: 1,
189
+ })
190
+
191
+ pino({
192
+ browser: {
193
+ write (o) {},
194
+ },
195
+ })
196
+
197
+ pino({
198
+ browser: {
199
+ write: {
200
+ info (o) {},
201
+ error (o) {},
202
+ },
203
+ serialize: true,
204
+ asObject: true,
205
+ transmit: {
206
+ level: 'fatal',
207
+ send: (level, logEvent) => {
208
+ level
209
+ logEvent.bindings
210
+ logEvent.level
211
+ logEvent.ts
212
+ logEvent.messages
213
+ },
214
+ },
215
+ disabled: false,
216
+ },
217
+ })
218
+
219
+ pino({
220
+ browser: {
221
+ asObjectBindingsOnly: true,
222
+ },
223
+ })
224
+
225
+ pino({}, undefined)
226
+
227
+ pino({ base: null })
228
+ if ('pino' in log) console.log(`pino version: ${log.pino}`)
229
+
230
+ expectType<void>(log.flush())
231
+ log.flush((err?: Error) => undefined)
232
+ log.child({ a: 'property' }).info('hello child!')
233
+ log.level = 'error'
234
+ log.info('nope')
235
+ const child = log.child({ foo: 'bar' })
236
+ child.info('nope again')
237
+ child.level = 'info'
238
+ child.info('hooray')
239
+ log.info('nope nope nope')
240
+ log.child({ foo: 'bar' }, { level: 'debug' }).debug('debug!')
241
+ child.bindings()
242
+ const customSerializers = {
243
+ test () {
244
+ return 'this is my serializer'
245
+ },
246
+ }
247
+ pino()
248
+ .child({}, { serializers: customSerializers })
249
+ .info({ test: 'should not show up' })
250
+ const child2 = log.child({ father: true })
251
+ const childChild = child2.child({ baby: true })
252
+ const childRedacted = pino().child({}, { redact: ['path'] })
253
+ childRedacted.info({
254
+ msg: 'logged with redacted properties',
255
+ path: 'Not shown',
256
+ })
257
+ const childAnotherRedacted = pino().child(
258
+ {},
259
+ {
260
+ redact: {
261
+ paths: ['anotherPath'],
262
+ censor: 'Not the log you\re looking for',
263
+ },
264
+ }
265
+ )
266
+ childAnotherRedacted.info({
267
+ msg: 'another logged with redacted properties',
268
+ anotherPath: 'Not shown',
269
+ })
270
+
271
+ log.level = 'info'
272
+ if (log.levelVal === 30) {
273
+ console.log('logger level is `info`')
274
+ }
275
+
276
+ const listener = (lvl: any, val: any, prevLvl: any, prevVal: any) => {
277
+ console.log(lvl, val, prevLvl, prevVal)
278
+ }
279
+ log.on('level-change', (lvl, val, prevLvl, prevVal, logger) => {
280
+ console.log(lvl, val, prevLvl, prevVal)
281
+ })
282
+ log.level = 'trace'
283
+ log.removeListener('level-change', listener)
284
+ log.level = 'info'
285
+
286
+ pino.levels.values.error === 50
287
+ pino.levels.labels[50] === 'error'
288
+
289
+ const logstderr: pino.Logger = pino(process.stderr)
290
+ logstderr.error('on stderr instead of stdout')
291
+
292
+ log.useLevelLabels = true
293
+ log.info('lol')
294
+ log.level === 'info'
295
+ const isEnabled: boolean = log.isLevelEnabled('info')
296
+
297
+ const redacted = pino({
298
+ redact: ['path'],
299
+ })
300
+
301
+ redacted.info({
302
+ msg: 'logged with redacted properties',
303
+ path: 'Not shown',
304
+ })
305
+
306
+ const anotherRedacted = pino({
307
+ redact: {
308
+ paths: ['anotherPath'],
309
+ censor: 'Not the log you\re looking for',
310
+ },
311
+ })
312
+
313
+ anotherRedacted.info({
314
+ msg: 'another logged with redacted properties',
315
+ anotherPath: 'Not shown',
316
+ })
317
+
318
+ const withTimeFn = pino({
319
+ timestamp: pino.stdTimeFunctions.isoTime,
320
+ })
321
+
322
+ const withRFC3339TimeFn = pino({
323
+ timestamp: pino.stdTimeFunctions.isoTimeNano,
324
+ })
325
+
326
+ const withNestedKey = pino({
327
+ nestedKey: 'payload',
328
+ })
329
+
330
+ const withHooks = pino({
331
+ hooks: {
332
+ logMethod (args, method, level) {
333
+ expectType<pino.Logger>(this)
334
+ return method.apply(this, args)
335
+ },
336
+ streamWrite (s) {
337
+ expectType<string>(s)
338
+ return s.replaceAll('secret-key', 'xxx')
339
+ },
340
+ },
341
+ })
342
+
343
+ // Properties/types imported from pino-std-serializers
344
+ const wrappedErrSerializer = pino.stdSerializers.wrapErrorSerializer(
345
+ (err: pino.SerializedError) => {
346
+ return { ...err, newProp: 'foo' }
347
+ }
348
+ )
349
+ const wrappedReqSerializer = pino.stdSerializers.wrapRequestSerializer(
350
+ (req: pino.SerializedRequest) => {
351
+ return { ...req, newProp: 'foo' }
352
+ }
353
+ )
354
+ const wrappedResSerializer = pino.stdSerializers.wrapResponseSerializer(
355
+ (res: pino.SerializedResponse) => {
356
+ return { ...res, newProp: 'foo' }
357
+ }
358
+ )
359
+
360
+ const socket = new Socket()
361
+ const incomingMessage = new IncomingMessage(socket)
362
+ const serverResponse = new ServerResponse(incomingMessage)
363
+
364
+ const mappedHttpRequest: { req: pino.SerializedRequest } =
365
+ pino.stdSerializers.mapHttpRequest(incomingMessage)
366
+ const mappedHttpResponse: { res: pino.SerializedResponse } =
367
+ pino.stdSerializers.mapHttpResponse(serverResponse)
368
+
369
+ const serializedErr: pino.SerializedError = pino.stdSerializers.err(
370
+ new Error()
371
+ )
372
+ const serializedReq: pino.SerializedRequest =
373
+ pino.stdSerializers.req(incomingMessage)
374
+ const serializedRes: pino.SerializedResponse =
375
+ pino.stdSerializers.res(serverResponse)
376
+
377
+ /**
378
+ * Destination static method
379
+ */
380
+ const destinationViaDefaultArgs = pino.destination()
381
+ const destinationViaStrFileDescriptor = pino.destination('/log/path')
382
+ const destinationViaNumFileDescriptor = pino.destination(2)
383
+ const destinationViaStream = pino.destination(process.stdout)
384
+ const destinationViaOptionsObject = pino.destination({
385
+ dest: '/log/path',
386
+ sync: false,
387
+ })
388
+
389
+ pino(destinationViaDefaultArgs)
390
+ pino({ name: 'my-logger' }, destinationViaDefaultArgs)
391
+ pino(destinationViaStrFileDescriptor)
392
+ pino({ name: 'my-logger' }, destinationViaStrFileDescriptor)
393
+ pino(destinationViaNumFileDescriptor)
394
+ pino({ name: 'my-logger' }, destinationViaNumFileDescriptor)
395
+ pino(destinationViaStream)
396
+ pino({ name: 'my-logger' }, destinationViaStream)
397
+ pino(destinationViaOptionsObject)
398
+ pino({ name: 'my-logger' }, destinationViaOptionsObject)
399
+
400
+ try {
401
+ throw new Error('Some error')
402
+ } catch (err) {
403
+ log.error(err)
404
+ }
405
+
406
+ interface StrictShape {
407
+ activity: string;
408
+ err?: unknown;
409
+ }
410
+
411
+ info<StrictShape>({
412
+ activity: 'Required property',
413
+ })
414
+
415
+ const logLine: pino.LogDescriptor = {
416
+ level: 20,
417
+ msg: 'A log message',
418
+ time: new Date().getTime(),
419
+ aCustomProperty: true,
420
+ }
421
+
422
+ interface CustomLogger extends pino.Logger {
423
+ customMethod(msg: string, ...args: unknown[]): void;
424
+ }
425
+
426
+ const serializerFunc: pino.SerializerFn = () => {}
427
+ const writeFunc: pino.WriteFn = () => {}
428
+
429
+ interface CustomBaseLogger extends pino.BaseLogger {
430
+ child(): CustomBaseLogger;
431
+ }
432
+
433
+ const customBaseLogger: CustomBaseLogger = {
434
+ level: 'info',
435
+ fatal () {},
436
+ error () {},
437
+ warn () {},
438
+ info () {},
439
+ debug () {},
440
+ trace () {},
441
+ silent () {},
442
+ child () {
443
+ return this
444
+ },
445
+ msgPrefix: 'prefix',
446
+ }
447
+
448
+ // custom levels
449
+ const log3 = pino({ customLevels: { myLevel: 100 } })
450
+ expectError(log3.log())
451
+ log3.level = 'myLevel'
452
+ log3.myLevel('')
453
+ log3.child({}).myLevel('')
454
+
455
+ log3.on('level-change', (lvl, val, prevLvl, prevVal, instance) => {
456
+ instance.myLevel('foo')
457
+ })
458
+
459
+ const clog3 = log3.child({}, { customLevels: { childLevel: 120 } })
460
+ // child inherit parent
461
+ clog3.myLevel('')
462
+ // child itself
463
+ clog3.childLevel('')
464
+ const cclog3 = clog3.child({}, { customLevels: { childLevel2: 130 } })
465
+ // child inherit root
466
+ cclog3.myLevel('')
467
+ // child inherit parent
468
+ cclog3.childLevel('')
469
+ // child itself
470
+ cclog3.childLevel2('')
471
+
472
+ const ccclog3 = clog3.child({})
473
+ expectError(ccclog3.nonLevel(''))
474
+
475
+ const withChildCallback = pino({
476
+ onChild: (child: Logger) => {},
477
+ })
478
+ withChildCallback.onChild = (child: Logger) => {}
479
+
480
+ pino({
481
+ crlf: true,
482
+ })
483
+
484
+ const customLevels = { foo: 99, bar: 42 }
485
+
486
+ const customLevelLogger = pino({ customLevels })
487
+
488
+ type CustomLevelLogger = typeof customLevelLogger
489
+ type CustomLevelLoggerLevels = pino.Level | keyof typeof customLevels
490
+
491
+ const fn = (logger: Pick<CustomLevelLogger, CustomLevelLoggerLevels>) => {}
492
+
493
+ const customLevelChildLogger = customLevelLogger.child({ name: 'child' })
494
+
495
+ fn(customLevelChildLogger) // missing foo typing
496
+
497
+ // unknown option
498
+ expectError(
499
+ pino({
500
+ hello: 'world',
501
+ })
502
+ )
503
+
504
+ // unknown option
505
+ expectError(
506
+ pino({
507
+ hello: 'world',
508
+ customLevels: {
509
+ log: 30,
510
+ },
511
+ })
512
+ )
513
+
514
+ function dangerous () {
515
+ throw Error('foo')
516
+ }
517
+
518
+ try {
519
+ dangerous()
520
+ } catch (err) {
521
+ log.error(err)
522
+ }
523
+
524
+ try {
525
+ dangerous()
526
+ } catch (err) {
527
+ log.error({ err })
528
+ }
529
+
530
+ const bLogger = pino({
531
+ customLevels: {
532
+ log: 5,
533
+ },
534
+ level: 'log',
535
+ transport: {
536
+ target: 'pino-pretty',
537
+ options: {
538
+ colorize: true,
539
+ },
540
+ },
541
+ })
542
+
543
+ // Test that we can properly extract parameters from the log fn type
544
+ type LogParam = Parameters<LogFn>
545
+ const [param1, param2, param3, param4]: LogParam = [
546
+ { multiple: 'params' },
547
+ 'should',
548
+ 'be',
549
+ 'accepted',
550
+ ]
551
+
552
+ expectType<unknown>(param1)
553
+ expectType<string>(param2)
554
+ expectType<unknown>(param3)
555
+ expectType<unknown>(param4)
556
+
557
+ const logger = mock.fn<LogFn>()
558
+ logger.mock.calls[0].arguments[1]?.includes('I should be able to get params')
559
+
560
+ const hooks: LoggerOptions['hooks'] = {
561
+ logMethod (this, parameters, method) {
562
+ if (parameters.length >= 2) {
563
+ const [parameter1, parameter2, ...remainingParameters] = parameters
564
+ if (typeof parameter1 === 'string') {
565
+ return method.apply(this, [
566
+ parameter2,
567
+ parameter1,
568
+ ...remainingParameters,
569
+ ])
570
+ }
571
+ return method.apply(this, [parameter2])
572
+ }
573
+
574
+ return method.apply(this, parameters)
575
+ },
576
+ }
577
+
578
+ expectType<Logger<'log'>>(
579
+ pino({
580
+ customLevels: {
581
+ log: 5,
582
+ },
583
+ level: 'log',
584
+ transport: {
585
+ target: 'pino-pretty',
586
+ options: {
587
+ colorize: true,
588
+ },
589
+ },
590
+ })
591
+ )
592
+
593
+ const parentLogger1 = pino(
594
+ {
595
+ customLevels: { myLevel: 90 },
596
+ onChild: (child) => {
597
+ const a = child.myLevel
598
+ },
599
+ },
600
+ process.stdout
601
+ )
602
+ parentLogger1.onChild = (child) => {
603
+ child.myLevel('')
604
+ }
605
+
606
+ const childLogger1 = parentLogger1.child({})
607
+ childLogger1.myLevel('')
608
+ expectError(childLogger1.doesntExist(''))
609
+
610
+ const parentLogger2 = pino({}, process.stdin)
611
+ expectError(
612
+ (parentLogger2.onChild = (child) => {
613
+ const b = child.doesntExist
614
+ })
615
+ )
616
+
617
+ const childLogger2 = parentLogger2.child({})
618
+ expectError(childLogger2.doesntExist)
619
+
620
+ expectError(
621
+ pino(
622
+ {
623
+ onChild: (child) => {
624
+ const a = child.doesntExist
625
+ },
626
+ },
627
+ process.stdout
628
+ )
629
+ )
630
+
631
+ const pinoWithoutLevelsSorting = pino({})
632
+ const pinoWithDescSortingLevels = pino({ levelComparison: 'DESC' })
633
+ const pinoWithAscSortingLevels = pino({ levelComparison: 'ASC' })
634
+ const pinoWithCustomSortingLevels = pino({ levelComparison: () => false })
635
+ // with wrong level comparison direction
636
+ expectError(pino({ levelComparison: 'SOME' }), process.stdout)
637
+ // with wrong level comparison type
638
+ expectError(pino({ levelComparison: 123 }), process.stdout)
639
+ // with wrong custom level comparison return type
640
+ expectError(pino({ levelComparison: () => null }), process.stdout)
641
+ expectError(pino({ levelComparison: () => 1 }), process.stdout)
642
+ expectError(pino({ levelComparison: () => 'string' }), process.stdout)
643
+
644
+ const customLevelsOnlyOpts = {
645
+ useOnlyCustomLevels: true,
646
+ customLevels: {
647
+ customDebug: 10,
648
+ info: 20, // to make sure the default names are also available for override
649
+ customNetwork: 30,
650
+ customError: 40,
651
+ },
652
+ level: 'customDebug',
653
+ } satisfies LoggerOptions
654
+
655
+ const loggerWithCustomLevelOnly = pino(customLevelsOnlyOpts)
656
+ loggerWithCustomLevelOnly.customDebug('test3')
657
+ loggerWithCustomLevelOnly.info('test4')
658
+ loggerWithCustomLevelOnly.customError('test5')
659
+ loggerWithCustomLevelOnly.customNetwork('test6')
660
+
661
+ expectError(loggerWithCustomLevelOnly.fatal('test'))
662
+ expectError(loggerWithCustomLevelOnly.error('test'))
663
+ expectError(loggerWithCustomLevelOnly.warn('test'))
664
+ expectError(loggerWithCustomLevelOnly.debug('test'))
665
+ expectError(loggerWithCustomLevelOnly.trace('test'))
666
+
667
+ // Module extension
668
+ declare module '../../' {
669
+ interface LogFnFields {
670
+ bannedField?: never;
671
+ typeCheckedField?: string;
672
+ }
673
+ }
674
+
675
+ info({ typeCheckedField: 'bar' })
676
+ expectError(info({ bannedField: 'bar' }))
677
+ expectError(info({ typeCheckedField: 123 }))
678
+
679
+ const someGenericFunction = <T extends string | number | symbol = never>(
680
+ arg: Record<T, unknown>
681
+ ) => {
682
+ info(arg)
683
+ }