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,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ const execa = require('execa')
4
+ const fs = require('node:fs')
5
+
6
+ const existsSync = fs.existsSync
7
+ const stat = fs.promises.stat
8
+
9
+ // Hardcoded parameters
10
+ const esVersions = ['es5', 'es6', 'es2017', 'esnext']
11
+ const filesToTranspile = ['to-file-transport.ts']
12
+
13
+ async function transpile () {
14
+ process.chdir(__dirname)
15
+
16
+ for (const sourceFileName of filesToTranspile) {
17
+ const sourceStat = await stat(sourceFileName)
18
+
19
+ for (const esVersion of esVersions) {
20
+ const intermediateFileName = sourceFileName.replace(/\.ts$/, '.js')
21
+ const targetFileName = sourceFileName.replace(/\.ts$/, `.${esVersion}.cjs`)
22
+
23
+ const shouldTranspile = !existsSync(targetFileName) || (await stat(targetFileName)).mtimeMs < sourceStat.mtimeMs
24
+
25
+ if (shouldTranspile) {
26
+ await execa('tsc', ['--target', esVersion, '--module', 'commonjs', sourceFileName])
27
+ await execa('mv', [intermediateFileName, targetFileName])
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ transpile().catch(err => {
34
+ process.exitCode = 1
35
+ throw err
36
+ })
@@ -0,0 +1,15 @@
1
+ import pino from '../../..'
2
+ import { join } from 'node:path'
3
+
4
+ const transport = pino.transport({
5
+ target: join(__dirname, 'to-file-transport-with-transform.ts'),
6
+ options: {
7
+ destination: process.argv[2]
8
+ }
9
+ })
10
+ const logger = pino(transport)
11
+
12
+ logger.info('Hello')
13
+ logger.info('World')
14
+
15
+ process.exit(0)
@@ -0,0 +1,10 @@
1
+ import pino from '../../..'
2
+
3
+ const transport = pino.transport({
4
+ target: 'pino/file'
5
+ })
6
+ const logger = pino(transport)
7
+
8
+ logger.info('Hello')
9
+
10
+ process.exit(0)
@@ -0,0 +1,11 @@
1
+ import pino from '../../..'
2
+
3
+ const transport = pino.transport({
4
+ target: 'pino/file'
5
+ })
6
+ const logger = pino(transport)
7
+
8
+ transport.on('ready', function () {
9
+ logger.info('Hello')
10
+ process.exit(0)
11
+ })
@@ -0,0 +1,8 @@
1
+ import { join } from 'node:path'
2
+ import pino from '../../..'
3
+
4
+ const transport = pino.transport({
5
+ target: join(__dirname, 'transport-worker.ts')
6
+ })
7
+ const logger = pino(transport)
8
+ logger.info('Hello')
@@ -0,0 +1,8 @@
1
+ import pino from '../../..'
2
+
3
+ const transport = pino.transport({
4
+ target: 'pino/file',
5
+ options: { destination: '1' }
6
+ })
7
+ const logger = pino(transport)
8
+ logger.info('Hello')
@@ -0,0 +1,14 @@
1
+ import { Writable } from 'node:stream'
2
+
3
+ export default (): Writable => {
4
+ const myTransportStream = new Writable({
5
+ autoDestroy: true,
6
+ write (chunk, _enc, cb) {
7
+ console.log(chunk.toString())
8
+ cb()
9
+ },
10
+ defaultEncoding: 'utf8'
11
+ })
12
+
13
+ return myTransportStream
14
+ }
@@ -0,0 +1,364 @@
1
+ 'use strict'
2
+ /* eslint no-prototype-builtins: 0 */
3
+
4
+ const test = require('node:test')
5
+ const assert = require('node:assert')
6
+ const { hostname } = require('node:os')
7
+ const { join } = require('node:path')
8
+ const { readFile } = require('node:fs').promises
9
+ const tspl = require('@matteo.collina/tspl')
10
+
11
+ const { sink, match, once, watchFileCreated, file } = require('./helper')
12
+ const pino = require('../')
13
+
14
+ test('level formatter', async () => {
15
+ const stream = sink()
16
+ const logger = pino({
17
+ formatters: {
18
+ level (label, number) {
19
+ return {
20
+ log: {
21
+ level: label
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }, stream)
27
+
28
+ const o = once(stream, 'data')
29
+ logger.info('hello world')
30
+ match(await o, {
31
+ log: {
32
+ level: 'info'
33
+ }
34
+ })
35
+ })
36
+
37
+ test('bindings formatter', async () => {
38
+ const stream = sink()
39
+ const logger = pino({
40
+ formatters: {
41
+ bindings (bindings) {
42
+ return {
43
+ process: {
44
+ pid: bindings.pid
45
+ },
46
+ host: {
47
+ name: bindings.hostname
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }, stream)
53
+
54
+ const o = once(stream, 'data')
55
+ logger.info('hello world')
56
+ match(await o, {
57
+ process: {
58
+ pid: process.pid
59
+ },
60
+ host: {
61
+ name: hostname()
62
+ }
63
+ })
64
+ })
65
+
66
+ test('no bindings formatter', async () => {
67
+ const stream = sink()
68
+ const logger = pino({
69
+ formatters: {
70
+ bindings (bindings) {
71
+ return null
72
+ }
73
+ }
74
+ }, stream)
75
+
76
+ const o = once(stream, 'data')
77
+ logger.info('hello world')
78
+ const log = await o
79
+ assert.equal(log.hasOwnProperty('pid'), false)
80
+ assert.equal(log.hasOwnProperty('hostname'), false)
81
+ match(log, { msg: 'hello world' })
82
+ })
83
+
84
+ test('log formatter', async (t) => {
85
+ const plan = tspl(t, { plan: 1 })
86
+ const stream = sink()
87
+ const logger = pino({
88
+ formatters: {
89
+ log (obj) {
90
+ plan.equal(obj.hasOwnProperty('msg'), false)
91
+ return { hello: 'world', ...obj }
92
+ }
93
+ }
94
+ }, stream)
95
+
96
+ const o = once(stream, 'data')
97
+ logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
98
+ match(await o, {
99
+ hello: 'world',
100
+ foo: 'bar',
101
+ nested: { object: true }
102
+ })
103
+
104
+ await plan
105
+ })
106
+
107
+ test('Formatters combined', async () => {
108
+ const stream = sink()
109
+ const logger = pino({
110
+ formatters: {
111
+ level (label, number) {
112
+ return {
113
+ log: {
114
+ level: label
115
+ }
116
+ }
117
+ },
118
+ bindings (bindings) {
119
+ return {
120
+ process: {
121
+ pid: bindings.pid
122
+ },
123
+ host: {
124
+ name: bindings.hostname
125
+ }
126
+ }
127
+ },
128
+ log (obj) {
129
+ return { hello: 'world', ...obj }
130
+ }
131
+ }
132
+ }, stream)
133
+
134
+ const o = once(stream, 'data')
135
+ logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
136
+ match(await o, {
137
+ log: {
138
+ level: 'info'
139
+ },
140
+ process: {
141
+ pid: process.pid
142
+ },
143
+ host: {
144
+ name: hostname()
145
+ },
146
+ hello: 'world',
147
+ foo: 'bar',
148
+ nested: { object: true }
149
+ })
150
+ })
151
+
152
+ test('Formatters in child logger', async () => {
153
+ const stream = sink()
154
+ const logger = pino({
155
+ formatters: {
156
+ level (label, number) {
157
+ return {
158
+ log: {
159
+ level: label
160
+ }
161
+ }
162
+ },
163
+ bindings (bindings) {
164
+ return {
165
+ process: {
166
+ pid: bindings.pid
167
+ },
168
+ host: {
169
+ name: bindings.hostname
170
+ }
171
+ }
172
+ },
173
+ log (obj) {
174
+ return { hello: 'world', ...obj }
175
+ }
176
+ }
177
+ }, stream)
178
+
179
+ const child = logger.child({
180
+ foo: 'bar',
181
+ nested: { object: true }
182
+ }, {
183
+ formatters: {
184
+ bindings (bindings) {
185
+ return { ...bindings, faz: 'baz' }
186
+ }
187
+ }
188
+ })
189
+
190
+ const o = once(stream, 'data')
191
+ child.info('hello world')
192
+ match(await o, {
193
+ log: {
194
+ level: 'info'
195
+ },
196
+ process: {
197
+ pid: process.pid
198
+ },
199
+ host: {
200
+ name: hostname()
201
+ },
202
+ hello: 'world',
203
+ foo: 'bar',
204
+ nested: { object: true },
205
+ faz: 'baz'
206
+ })
207
+ })
208
+
209
+ test('Formatters without bindings in child logger', async () => {
210
+ const stream = sink()
211
+ const logger = pino({
212
+ formatters: {
213
+ level (label, number) {
214
+ return {
215
+ log: {
216
+ level: label
217
+ }
218
+ }
219
+ },
220
+ bindings (bindings) {
221
+ return {
222
+ process: {
223
+ pid: bindings.pid
224
+ },
225
+ host: {
226
+ name: bindings.hostname
227
+ }
228
+ }
229
+ },
230
+ log (obj) {
231
+ return { hello: 'world', ...obj }
232
+ }
233
+ }
234
+ }, stream)
235
+
236
+ const child = logger.child({
237
+ foo: 'bar',
238
+ nested: { object: true }
239
+ }, {
240
+ formatters: {
241
+ log (obj) {
242
+ return { other: 'stuff', ...obj }
243
+ }
244
+ }
245
+ })
246
+
247
+ const o = once(stream, 'data')
248
+ child.info('hello world')
249
+ match(await o, {
250
+ log: {
251
+ level: 'info'
252
+ },
253
+ process: {
254
+ pid: process.pid
255
+ },
256
+ host: {
257
+ name: hostname()
258
+ },
259
+ foo: 'bar',
260
+ other: 'stuff',
261
+ nested: { object: true }
262
+ })
263
+ })
264
+
265
+ test('elastic common schema format', async () => {
266
+ const stream = sink()
267
+ const ecs = {
268
+ formatters: {
269
+ level (label, number) {
270
+ return {
271
+ log: {
272
+ level: label,
273
+ logger: 'pino'
274
+ }
275
+ }
276
+ },
277
+ bindings (bindings) {
278
+ return {
279
+ process: {
280
+ pid: bindings.pid
281
+ },
282
+ host: {
283
+ name: bindings.hostname
284
+ }
285
+ }
286
+ },
287
+ log (obj) {
288
+ return { ecs: { version: '1.4.0' }, ...obj }
289
+ }
290
+ },
291
+ messageKey: 'message',
292
+ timestamp: () => `,"@timestamp":"${new Date(Date.now()).toISOString()}"`
293
+ }
294
+
295
+ const logger = pino({ ...ecs }, stream)
296
+
297
+ const o = once(stream, 'data')
298
+ logger.info({ foo: 'bar' }, 'hello world')
299
+ const log = await o
300
+ assert.equal(typeof log['@timestamp'], 'string')
301
+ match(log, {
302
+ log: { level: 'info', logger: 'pino' },
303
+ process: { pid: process.pid },
304
+ host: { name: hostname() },
305
+ ecs: { version: '1.4.0' },
306
+ foo: 'bar',
307
+ message: 'hello world'
308
+ })
309
+ })
310
+
311
+ test('formatter with transport', async (t) => {
312
+ const plan = tspl(t, { plan: 1 })
313
+ const destination = file()
314
+ const logger = pino({
315
+ formatters: {
316
+ log (obj) {
317
+ plan.equal(obj.hasOwnProperty('msg'), false)
318
+ return { hello: 'world', ...obj }
319
+ }
320
+ },
321
+ transport: {
322
+ targets: [
323
+ {
324
+ target: join(__dirname, 'fixtures', 'to-file-transport.js'),
325
+ options: { destination }
326
+ }
327
+ ]
328
+ }
329
+ })
330
+
331
+ logger.info({ foo: 'bar', nested: { object: true } }, 'hello world')
332
+ await watchFileCreated(destination)
333
+ const result = JSON.parse(await readFile(destination))
334
+ delete result.time
335
+ match(result, {
336
+ hello: 'world',
337
+ foo: 'bar',
338
+ nested: { object: true }
339
+ })
340
+ })
341
+
342
+ test('throws when custom level formatter is used with transport.targets', async () => {
343
+ assert.throws(
344
+ () => {
345
+ pino({
346
+ formatters: {
347
+ level (label) {
348
+ return label
349
+ }
350
+ },
351
+ transport: {
352
+ targets: [
353
+ {
354
+ target: 'pino/file',
355
+ options: { destination: 'foo.log' }
356
+ }
357
+ ]
358
+ }
359
+ }
360
+ )
361
+ },
362
+ Error('option.transport.targets do not allow custom level formatters')
363
+ )
364
+ })
@@ -0,0 +1,4 @@
1
+ import type { PathLike } from 'node:fs'
2
+
3
+ export declare function watchFileCreated (filename: PathLike): Promise<void>
4
+ export declare function watchForWrite (filename: PathLike, testString: string): Promise<void>
package/test/helper.js ADDED
@@ -0,0 +1,155 @@
1
+ 'use strict'
2
+
3
+ const crypto = require('node:crypto')
4
+ const { join } = require('node:path')
5
+ const os = require('node:os')
6
+ const { existsSync, readFileSync, statSync, unlinkSync } = require('node:fs')
7
+ const writer = require('flush-write-stream')
8
+ const split = require('split2')
9
+
10
+ const pid = process.pid
11
+ const hostname = os.hostname()
12
+ const { tmpdir } = os
13
+
14
+ const isWin = process.platform === 'win32'
15
+ const isYarnPnp = process.versions.pnp !== undefined
16
+
17
+ function getPathToNull () {
18
+ return isWin ? '\\\\.\\NUL' : '/dev/null'
19
+ }
20
+
21
+ function once (emitter, name) {
22
+ return new Promise((resolve, reject) => {
23
+ if (name !== 'error') emitter.once('error', reject)
24
+ emitter.once(name, (...args) => {
25
+ emitter.removeListener('error', reject)
26
+ resolve(...args)
27
+ })
28
+ })
29
+ }
30
+
31
+ function sink (func) {
32
+ const result = split((data) => {
33
+ try {
34
+ return JSON.parse(data)
35
+ } catch (err) {
36
+ console.log(err)
37
+ console.log(data)
38
+ }
39
+ })
40
+ if (func) result.pipe(writer.obj(func))
41
+ return result
42
+ }
43
+
44
+ function check (is, chunk, level, msg) {
45
+ is(new Date(chunk.time) <= new Date(), true, 'time is greater than Date.now()')
46
+ delete chunk.time
47
+ is(chunk.pid, pid)
48
+ is(chunk.hostname, hostname)
49
+ is(chunk.level, level)
50
+ is(chunk.msg, msg)
51
+ }
52
+
53
+ function sleep (ms) {
54
+ return new Promise((resolve) => {
55
+ setTimeout(resolve, ms)
56
+ })
57
+ }
58
+
59
+ function watchFileCreated (filename) {
60
+ return new Promise((resolve, reject) => {
61
+ const TIMEOUT = process.env.PINO_TEST_WAIT_WATCHFILE_TIMEOUT || 10000
62
+ const INTERVAL = 100
63
+ const threshold = TIMEOUT / INTERVAL
64
+ let counter = 0
65
+ const interval = setInterval(() => {
66
+ const exists = existsSync(filename)
67
+ // On some CI runs file is created but not filled
68
+ if (exists && statSync(filename).size !== 0) {
69
+ clearInterval(interval)
70
+ resolve()
71
+ } else if (counter <= threshold) {
72
+ counter++
73
+ } else {
74
+ clearInterval(interval)
75
+ reject(new Error(
76
+ `${filename} hasn't been created within ${TIMEOUT} ms. ` +
77
+ (exists ? 'File exist, but still empty.' : 'File not yet created.')
78
+ ))
79
+ }
80
+ }, INTERVAL)
81
+ })
82
+ }
83
+
84
+ function watchForWrite (filename, testString) {
85
+ return new Promise((resolve, reject) => {
86
+ const TIMEOUT = process.env.PINO_TEST_WAIT_WRITE_TIMEOUT || 10000
87
+ const INTERVAL = 100
88
+ const threshold = TIMEOUT / INTERVAL
89
+ let counter = 0
90
+ const interval = setInterval(() => {
91
+ if (readFileSync(filename).includes(testString)) {
92
+ clearInterval(interval)
93
+ resolve()
94
+ } else if (counter <= threshold) {
95
+ counter++
96
+ } else {
97
+ clearInterval(interval)
98
+ reject(new Error(`'${testString}' hasn't been written to ${filename} within ${TIMEOUT} ms.`))
99
+ }
100
+ }, INTERVAL)
101
+ })
102
+ }
103
+
104
+ let files = []
105
+
106
+ function file () {
107
+ const hash = crypto.randomBytes(12).toString('hex')
108
+ const file = join(tmpdir(), `pino-${pid}-${hash}`)
109
+ files.push(file)
110
+ return file
111
+ }
112
+
113
+ process.on('beforeExit', () => {
114
+ if (files.length === 0) return
115
+ for (const file of files) {
116
+ try {
117
+ unlinkSync(file)
118
+ } catch (e) {
119
+ }
120
+ }
121
+ files = []
122
+ })
123
+
124
+ /**
125
+ * match is a bare-bones object shape matcher. We should be able to replace
126
+ * this with `assert.partialDeepStrictEqual` when v22 is our minimum.
127
+ *
128
+ * @param {object} found
129
+ * @param {object} expected
130
+ */
131
+ function match (found, expected) {
132
+ for (const [key, value] of Object.entries(expected)) {
133
+ if (Object.prototype.toString.call(value) === '[object Object]') {
134
+ match(found[key], value)
135
+ continue
136
+ }
137
+ if (value !== found[key]) {
138
+ throw Error(`expected "${value}" but found "${found[key]}"`)
139
+ }
140
+ }
141
+ }
142
+
143
+ module.exports = {
144
+ check,
145
+ file,
146
+ getPathToNull,
147
+ isWin,
148
+ isYarnPnp,
149
+ match,
150
+ once,
151
+ sink,
152
+ sleep,
153
+ watchFileCreated,
154
+ watchForWrite
155
+ }