chalk-config 0.0.1-security → 2.14.7

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.

Potentially problematic release.


This version of chalk-config might be problematic. Click here for more details.

Files changed (200) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +8 -0
  3. package/.github/dependabot.yml +13 -0
  4. package/.github/workflows/bench.yml +61 -0
  5. package/.github/workflows/ci.yml +88 -0
  6. package/.github/workflows/lock-threads.yml +30 -0
  7. package/.github/workflows/target-main.yml +23 -0
  8. package/.nojekyll +0 -0
  9. package/.prettierignore +1 -0
  10. package/.taprc.yaml +8 -0
  11. package/CNAME +1 -0
  12. package/CONTRIBUTING.md +30 -0
  13. package/LICENSE +21 -0
  14. package/README.md +159 -3
  15. package/SECURITY.md +68 -0
  16. package/benchmarks/basic.bench.js +95 -0
  17. package/benchmarks/child-child.bench.js +52 -0
  18. package/benchmarks/child-creation.bench.js +73 -0
  19. package/benchmarks/child.bench.js +62 -0
  20. package/benchmarks/deep-object.bench.js +88 -0
  21. package/benchmarks/formatters.bench.js +50 -0
  22. package/benchmarks/internal/custom-levels.js +67 -0
  23. package/benchmarks/internal/just-pino-heavy.bench.js +76 -0
  24. package/benchmarks/internal/just-pino.bench.js +182 -0
  25. package/benchmarks/internal/parent-vs-child.bench.js +75 -0
  26. package/benchmarks/internal/redact.bench.js +86 -0
  27. package/benchmarks/long-string.bench.js +81 -0
  28. package/benchmarks/multi-arg.bench.js +193 -0
  29. package/benchmarks/multistream.js +98 -0
  30. package/benchmarks/object.bench.js +82 -0
  31. package/benchmarks/utils/generate-benchmark-doc.js +36 -0
  32. package/benchmarks/utils/runbench.js +138 -0
  33. package/benchmarks/utils/wrap-log-level.js +55 -0
  34. package/bin.js +6 -0
  35. package/browser.js +484 -0
  36. package/build/sync-version.js +10 -0
  37. package/docs/api.md +1487 -0
  38. package/docs/asynchronous.md +40 -0
  39. package/docs/benchmarks.md +55 -0
  40. package/docs/browser.md +227 -0
  41. package/docs/bundling.md +40 -0
  42. package/docs/child-loggers.md +95 -0
  43. package/docs/ecosystem.md +84 -0
  44. package/docs/help.md +345 -0
  45. package/docs/lts.md +64 -0
  46. package/docs/pretty.md +35 -0
  47. package/docs/redaction.md +135 -0
  48. package/docs/transports.md +1238 -0
  49. package/docs/web.md +269 -0
  50. package/docsify/sidebar.md +26 -0
  51. package/examples/basic.js +43 -0
  52. package/examples/transport.js +68 -0
  53. package/favicon-16x16.png +0 -0
  54. package/favicon-32x32.png +0 -0
  55. package/favicon.ico +0 -0
  56. package/file.js +12 -0
  57. package/inc-version.sh +42 -0
  58. package/index.html +55 -0
  59. package/lib/caller.js +30 -0
  60. package/lib/constants.js +28 -0
  61. package/lib/deprecations.js +8 -0
  62. package/lib/levels.js +241 -0
  63. package/lib/meta.js +3 -0
  64. package/lib/multistream.js +188 -0
  65. package/lib/proto.js +234 -0
  66. package/lib/redaction.js +118 -0
  67. package/lib/symbols.js +74 -0
  68. package/lib/time.js +11 -0
  69. package/lib/tools.js +394 -0
  70. package/lib/transport-stream.js +56 -0
  71. package/lib/transport.js +167 -0
  72. package/lib/worker.js +194 -0
  73. package/lib/writer.js +42 -0
  74. package/package.json +118 -3
  75. package/pino-banner.png +0 -0
  76. package/pino-logo-hire.png +0 -0
  77. package/pino-tree.png +0 -0
  78. package/pino.d.ts +889 -0
  79. package/pino.js +236 -0
  80. package/pretty-demo.png +0 -0
  81. package/test/basic.test.js +874 -0
  82. package/test/broken-pipe.test.js +57 -0
  83. package/test/browser-child.test.js +132 -0
  84. package/test/browser-disabled.test.js +87 -0
  85. package/test/browser-early-console-freeze.test.js +12 -0
  86. package/test/browser-levels.test.js +241 -0
  87. package/test/browser-serializers.test.js +352 -0
  88. package/test/browser-timestamp.test.js +88 -0
  89. package/test/browser-transmit.test.js +417 -0
  90. package/test/browser.test.js +659 -0
  91. package/test/complex-objects.test.js +34 -0
  92. package/test/crlf.test.js +32 -0
  93. package/test/custom-levels.test.js +253 -0
  94. package/test/error.test.js +398 -0
  95. package/test/errorKey.test.js +34 -0
  96. package/test/escaping.test.js +91 -0
  97. package/test/esm/esm.mjs +12 -0
  98. package/test/esm/index.test.js +34 -0
  99. package/test/esm/named-exports.mjs +27 -0
  100. package/test/exit.test.js +77 -0
  101. package/test/fixtures/broken-pipe/basic.js +9 -0
  102. package/test/fixtures/broken-pipe/destination.js +10 -0
  103. package/test/fixtures/broken-pipe/syncfalse.js +12 -0
  104. package/test/fixtures/console-transport.js +13 -0
  105. package/test/fixtures/default-exit.js +8 -0
  106. package/test/fixtures/destination-exit.js +8 -0
  107. package/test/fixtures/eval/index.js +13 -0
  108. package/test/fixtures/eval/node_modules/14-files.js +3 -0
  109. package/test/fixtures/eval/node_modules/2-files.js +3 -0
  110. package/test/fixtures/eval/node_modules/file1.js +5 -0
  111. package/test/fixtures/eval/node_modules/file10.js +5 -0
  112. package/test/fixtures/eval/node_modules/file11.js +5 -0
  113. package/test/fixtures/eval/node_modules/file12.js +5 -0
  114. package/test/fixtures/eval/node_modules/file13.js +5 -0
  115. package/test/fixtures/eval/node_modules/file14.js +11 -0
  116. package/test/fixtures/eval/node_modules/file2.js +5 -0
  117. package/test/fixtures/eval/node_modules/file3.js +5 -0
  118. package/test/fixtures/eval/node_modules/file4.js +5 -0
  119. package/test/fixtures/eval/node_modules/file5.js +5 -0
  120. package/test/fixtures/eval/node_modules/file6.js +5 -0
  121. package/test/fixtures/eval/node_modules/file7.js +5 -0
  122. package/test/fixtures/eval/node_modules/file8.js +5 -0
  123. package/test/fixtures/eval/node_modules/file9.js +5 -0
  124. package/test/fixtures/noop-transport.js +10 -0
  125. package/test/fixtures/pretty/null-prototype.js +8 -0
  126. package/test/fixtures/stdout-hack-protection.js +11 -0
  127. package/test/fixtures/syncfalse-child.js +6 -0
  128. package/test/fixtures/syncfalse-exit.js +9 -0
  129. package/test/fixtures/syncfalse-flush-exit.js +10 -0
  130. package/test/fixtures/syncfalse.js +6 -0
  131. package/test/fixtures/syntax-error-esm.mjs +2 -0
  132. package/test/fixtures/to-file-transport-with-transform.js +20 -0
  133. package/test/fixtures/to-file-transport.js +13 -0
  134. package/test/fixtures/to-file-transport.mjs +8 -0
  135. package/test/fixtures/transport/index.js +12 -0
  136. package/test/fixtures/transport/package.json +5 -0
  137. package/test/fixtures/transport-exit-immediately-with-async-dest.js +16 -0
  138. package/test/fixtures/transport-exit-immediately.js +11 -0
  139. package/test/fixtures/transport-exit-on-ready.js +12 -0
  140. package/test/fixtures/transport-main.js +9 -0
  141. package/test/fixtures/transport-many-lines.js +29 -0
  142. package/test/fixtures/transport-string-stdout.js +9 -0
  143. package/test/fixtures/transport-transform.js +21 -0
  144. package/test/fixtures/transport-uses-pino-config.js +33 -0
  145. package/test/fixtures/transport-with-on-exit.js +12 -0
  146. package/test/fixtures/transport-worker-data.js +19 -0
  147. package/test/fixtures/transport-worker.js +15 -0
  148. package/test/fixtures/transport-wrong-export-type.js +3 -0
  149. package/test/fixtures/ts/to-file-transport-with-transform.ts +18 -0
  150. package/test/fixtures/ts/to-file-transport.ts +11 -0
  151. package/test/fixtures/ts/transpile.cjs +36 -0
  152. package/test/fixtures/ts/transport-exit-immediately-with-async-dest.ts +15 -0
  153. package/test/fixtures/ts/transport-exit-immediately.ts +10 -0
  154. package/test/fixtures/ts/transport-exit-on-ready.ts +11 -0
  155. package/test/fixtures/ts/transport-main.ts +8 -0
  156. package/test/fixtures/ts/transport-string-stdout.ts +8 -0
  157. package/test/fixtures/ts/transport-worker.ts +14 -0
  158. package/test/formatters.test.js +355 -0
  159. package/test/helper.d.ts +4 -0
  160. package/test/helper.js +128 -0
  161. package/test/hooks.test.js +118 -0
  162. package/test/http.test.js +242 -0
  163. package/test/internals/version.test.js +15 -0
  164. package/test/is-level-enabled.test.js +185 -0
  165. package/test/jest/basic.spec.js +10 -0
  166. package/test/levels.test.js +772 -0
  167. package/test/metadata.test.js +106 -0
  168. package/test/mixin-merge-strategy.test.js +55 -0
  169. package/test/mixin.test.js +218 -0
  170. package/test/multistream.test.js +673 -0
  171. package/test/pkg/index.js +46 -0
  172. package/test/pkg/pkg.config.json +17 -0
  173. package/test/pkg/pkg.test.js +56 -0
  174. package/test/redact.test.js +847 -0
  175. package/test/serializers.test.js +253 -0
  176. package/test/stdout-protection.test.js +39 -0
  177. package/test/syncfalse.test.js +188 -0
  178. package/test/timestamp.test.js +121 -0
  179. package/test/transport/big.test.js +43 -0
  180. package/test/transport/bundlers-support.test.js +97 -0
  181. package/test/transport/caller.test.js +23 -0
  182. package/test/transport/core.test.js +644 -0
  183. package/test/transport/core.test.ts +236 -0
  184. package/test/transport/core.transpiled.test.ts +112 -0
  185. package/test/transport/module-link.test.js +239 -0
  186. package/test/transport/pipeline.test.js +135 -0
  187. package/test/transport/repl.test.js +14 -0
  188. package/test/transport/syncTrue.test.js +55 -0
  189. package/test/transport/syncfalse.test.js +68 -0
  190. package/test/transport/targets.test.js +44 -0
  191. package/test/transport/uses-pino-config.test.js +167 -0
  192. package/test/transport-stream.test.js +26 -0
  193. package/test/types/pino-import.test-d.ts +29 -0
  194. package/test/types/pino-multistream.test-d.ts +28 -0
  195. package/test/types/pino-top-export.test-d.ts +35 -0
  196. package/test/types/pino-transport.test-d.ts +145 -0
  197. package/test/types/pino-type-only.test-d.ts +64 -0
  198. package/test/types/pino.test-d.ts +468 -0
  199. package/test/types/pino.ts +78 -0
  200. package/tsconfig.json +14 -0
@@ -0,0 +1,118 @@
1
+ 'use strict'
2
+
3
+ const fastRedact = require('fast-redact')
4
+ const { redactFmtSym, wildcardFirstSym } = require('./symbols')
5
+ const { rx, validator } = fastRedact
6
+
7
+ const validate = validator({
8
+ ERR_PATHS_MUST_BE_STRINGS: () => 'pino – redacted paths must be strings',
9
+ ERR_INVALID_PATH: (s) => `pino – redact paths array contains an invalid path (${s})`
10
+ })
11
+
12
+ const CENSOR = '[Redacted]'
13
+ const strict = false // TODO should this be configurable?
14
+
15
+ function redaction (opts, serialize) {
16
+ const { paths, censor } = handle(opts)
17
+
18
+ const shape = paths.reduce((o, str) => {
19
+ rx.lastIndex = 0
20
+ const first = rx.exec(str)
21
+ const next = rx.exec(str)
22
+
23
+ // ns is the top-level path segment, brackets + quoting removed.
24
+ let ns = first[1] !== undefined
25
+ ? first[1].replace(/^(?:"|'|`)(.*)(?:"|'|`)$/, '$1')
26
+ : first[0]
27
+
28
+ if (ns === '*') {
29
+ ns = wildcardFirstSym
30
+ }
31
+
32
+ // top level key:
33
+ if (next === null) {
34
+ o[ns] = null
35
+ return o
36
+ }
37
+
38
+ // path with at least two segments:
39
+ // if ns is already redacted at the top level, ignore lower level redactions
40
+ if (o[ns] === null) {
41
+ return o
42
+ }
43
+
44
+ const { index } = next
45
+ const nextPath = `${str.substr(index, str.length - 1)}`
46
+
47
+ o[ns] = o[ns] || []
48
+
49
+ // shape is a mix of paths beginning with literal values and wildcard
50
+ // paths [ "a.b.c", "*.b.z" ] should reduce to a shape of
51
+ // { "a": [ "b.c", "b.z" ], *: [ "b.z" ] }
52
+ // note: "b.z" is in both "a" and * arrays because "a" matches the wildcard.
53
+ // (* entry has wildcardFirstSym as key)
54
+ if (ns !== wildcardFirstSym && o[ns].length === 0) {
55
+ // first time ns's get all '*' redactions so far
56
+ o[ns].push(...(o[wildcardFirstSym] || []))
57
+ }
58
+
59
+ if (ns === wildcardFirstSym) {
60
+ // new * path gets added to all previously registered literal ns's.
61
+ Object.keys(o).forEach(function (k) {
62
+ if (o[k]) {
63
+ o[k].push(nextPath)
64
+ }
65
+ })
66
+ }
67
+
68
+ o[ns].push(nextPath)
69
+ return o
70
+ }, {})
71
+
72
+ // the redactor assigned to the format symbol key
73
+ // provides top level redaction for instances where
74
+ // an object is interpolated into the msg string
75
+ const result = {
76
+ [redactFmtSym]: fastRedact({ paths, censor, serialize, strict })
77
+ }
78
+
79
+ const topCensor = (...args) => {
80
+ return typeof censor === 'function' ? serialize(censor(...args)) : serialize(censor)
81
+ }
82
+
83
+ return [...Object.keys(shape), ...Object.getOwnPropertySymbols(shape)].reduce((o, k) => {
84
+ // top level key:
85
+ if (shape[k] === null) {
86
+ o[k] = (value) => topCensor(value, [k])
87
+ } else {
88
+ const wrappedCensor = typeof censor === 'function'
89
+ ? (value, path) => {
90
+ return censor(value, [k, ...path])
91
+ }
92
+ : censor
93
+ o[k] = fastRedact({
94
+ paths: shape[k],
95
+ censor: wrappedCensor,
96
+ serialize,
97
+ strict
98
+ })
99
+ }
100
+ return o
101
+ }, result)
102
+ }
103
+
104
+ function handle (opts) {
105
+ if (Array.isArray(opts)) {
106
+ opts = { paths: opts, censor: CENSOR }
107
+ validate(opts)
108
+ return opts
109
+ }
110
+ let { paths, censor = CENSOR, remove } = opts
111
+ if (Array.isArray(paths) === false) { throw Error('pino – redact must contain an array of strings') }
112
+ if (remove === true) censor = undefined
113
+ validate({ paths, censor })
114
+
115
+ return { paths, censor }
116
+ }
117
+
118
+ module.exports = redaction
package/lib/symbols.js ADDED
@@ -0,0 +1,74 @@
1
+ 'use strict'
2
+
3
+ const setLevelSym = Symbol('pino.setLevel')
4
+ const getLevelSym = Symbol('pino.getLevel')
5
+ const levelValSym = Symbol('pino.levelVal')
6
+ const levelCompSym = Symbol('pino.levelComp')
7
+ const useLevelLabelsSym = Symbol('pino.useLevelLabels')
8
+ const useOnlyCustomLevelsSym = Symbol('pino.useOnlyCustomLevels')
9
+ const mixinSym = Symbol('pino.mixin')
10
+
11
+ const lsCacheSym = Symbol('pino.lsCache')
12
+ const chindingsSym = Symbol('pino.chindings')
13
+
14
+ const asJsonSym = Symbol('pino.asJson')
15
+ const writeSym = Symbol('pino.write')
16
+ const redactFmtSym = Symbol('pino.redactFmt')
17
+
18
+ const timeSym = Symbol('pino.time')
19
+ const timeSliceIndexSym = Symbol('pino.timeSliceIndex')
20
+ const streamSym = Symbol('pino.stream')
21
+ const stringifySym = Symbol('pino.stringify')
22
+ const stringifySafeSym = Symbol('pino.stringifySafe')
23
+ const stringifiersSym = Symbol('pino.stringifiers')
24
+ const endSym = Symbol('pino.end')
25
+ const formatOptsSym = Symbol('pino.formatOpts')
26
+ const messageKeySym = Symbol('pino.messageKey')
27
+ const errorKeySym = Symbol('pino.errorKey')
28
+ const nestedKeySym = Symbol('pino.nestedKey')
29
+ const nestedKeyStrSym = Symbol('pino.nestedKeyStr')
30
+ const mixinMergeStrategySym = Symbol('pino.mixinMergeStrategy')
31
+ const msgPrefixSym = Symbol('pino.msgPrefix')
32
+
33
+ const wildcardFirstSym = Symbol('pino.wildcardFirst')
34
+
35
+ // public symbols, no need to use the same pino
36
+ // version for these
37
+ const serializersSym = Symbol.for('pino.serializers')
38
+ const formattersSym = Symbol.for('pino.formatters')
39
+ const hooksSym = Symbol.for('pino.hooks')
40
+ const needsMetadataGsym = Symbol.for('pino.metadata')
41
+
42
+ module.exports = {
43
+ setLevelSym,
44
+ getLevelSym,
45
+ levelValSym,
46
+ levelCompSym,
47
+ useLevelLabelsSym,
48
+ mixinSym,
49
+ lsCacheSym,
50
+ chindingsSym,
51
+ asJsonSym,
52
+ writeSym,
53
+ serializersSym,
54
+ redactFmtSym,
55
+ timeSym,
56
+ timeSliceIndexSym,
57
+ streamSym,
58
+ stringifySym,
59
+ stringifySafeSym,
60
+ stringifiersSym,
61
+ endSym,
62
+ formatOptsSym,
63
+ messageKeySym,
64
+ errorKeySym,
65
+ nestedKeySym,
66
+ wildcardFirstSym,
67
+ needsMetadataGsym,
68
+ useOnlyCustomLevelsSym,
69
+ formattersSym,
70
+ hooksSym,
71
+ nestedKeyStrSym,
72
+ mixinMergeStrategySym,
73
+ msgPrefixSym
74
+ }
package/lib/time.js ADDED
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const nullTime = () => ''
4
+
5
+ const epochTime = () => `,"time":${Date.now()}`
6
+
7
+ const unixTime = () => `,"time":${Math.round(Date.now() / 1000.0)}`
8
+
9
+ const isoTime = () => `,"time":"${new Date(Date.now()).toISOString()}"` // using Date.now() for testability
10
+
11
+ module.exports = { nullTime, epochTime, unixTime, isoTime }
package/lib/tools.js ADDED
@@ -0,0 +1,394 @@
1
+ 'use strict'
2
+
3
+ /* eslint no-prototype-builtins: 0 */
4
+
5
+ const format = require('quick-format-unescaped')
6
+ const { mapHttpRequest, mapHttpResponse } = require('pino-std-serializers')
7
+ const SonicBoom = require('sonic-boom')
8
+ const onExit = require('on-exit-leak-free')
9
+ const {
10
+ lsCacheSym,
11
+ chindingsSym,
12
+ writeSym,
13
+ serializersSym,
14
+ formatOptsSym,
15
+ endSym,
16
+ stringifiersSym,
17
+ stringifySym,
18
+ stringifySafeSym,
19
+ wildcardFirstSym,
20
+ nestedKeySym,
21
+ formattersSym,
22
+ messageKeySym,
23
+ errorKeySym,
24
+ nestedKeyStrSym,
25
+ msgPrefixSym
26
+ } = require('./symbols')
27
+ const { isMainThread } = require('worker_threads')
28
+ const transport = require('./transport')
29
+
30
+ function noop () {
31
+ }
32
+
33
+ function genLog (level, hook) {
34
+ if (!hook) return LOG
35
+
36
+ return function hookWrappedLog (...args) {
37
+ hook.call(this, args, LOG, level)
38
+ }
39
+
40
+ function LOG (o, ...n) {
41
+ if (typeof o === 'object') {
42
+ let msg = o
43
+ if (o !== null) {
44
+ if (o.method && o.headers && o.socket) {
45
+ o = mapHttpRequest(o)
46
+ } else if (typeof o.setHeader === 'function') {
47
+ o = mapHttpResponse(o)
48
+ }
49
+ }
50
+ let formatParams
51
+ if (msg === null && n.length === 0) {
52
+ formatParams = [null]
53
+ } else {
54
+ msg = n.shift()
55
+ formatParams = n
56
+ }
57
+ // We do not use a coercive check for `msg` as it is
58
+ // measurably slower than the explicit checks.
59
+ if (typeof this[msgPrefixSym] === 'string' && msg !== undefined && msg !== null) {
60
+ msg = this[msgPrefixSym] + msg
61
+ }
62
+ this[writeSym](o, format(msg, formatParams, this[formatOptsSym]), level)
63
+ } else {
64
+ let msg = o === undefined ? n.shift() : o
65
+
66
+ // We do not use a coercive check for `msg` as it is
67
+ // measurably slower than the explicit checks.
68
+ if (typeof this[msgPrefixSym] === 'string' && msg !== undefined && msg !== null) {
69
+ msg = this[msgPrefixSym] + msg
70
+ }
71
+ this[writeSym](null, format(msg, n, this[formatOptsSym]), level)
72
+ }
73
+ }
74
+ }
75
+
76
+ // magically escape strings for json
77
+ // relying on their charCodeAt
78
+ // everything below 32 needs JSON.stringify()
79
+ // 34 and 92 happens all the time, so we
80
+ // have a fast case for them
81
+ function asString (str) {
82
+ let result = ''
83
+ let last = 0
84
+ let found = false
85
+ let point = 255
86
+ const l = str.length
87
+ if (l > 100) {
88
+ return JSON.stringify(str)
89
+ }
90
+ for (var i = 0; i < l && point >= 32; i++) {
91
+ point = str.charCodeAt(i)
92
+ if (point === 34 || point === 92) {
93
+ result += str.slice(last, i) + '\\'
94
+ last = i
95
+ found = true
96
+ }
97
+ }
98
+ if (!found) {
99
+ result = str
100
+ } else {
101
+ result += str.slice(last)
102
+ }
103
+ return point < 32 ? JSON.stringify(str) : '"' + result + '"'
104
+ }
105
+
106
+ function asJson (obj, msg, num, time) {
107
+ const stringify = this[stringifySym]
108
+ const stringifySafe = this[stringifySafeSym]
109
+ const stringifiers = this[stringifiersSym]
110
+ const end = this[endSym]
111
+ const chindings = this[chindingsSym]
112
+ const serializers = this[serializersSym]
113
+ const formatters = this[formattersSym]
114
+ const messageKey = this[messageKeySym]
115
+ const errorKey = this[errorKeySym]
116
+ let data = this[lsCacheSym][num] + time
117
+
118
+ // we need the child bindings added to the output first so instance logged
119
+ // objects can take precedence when JSON.parse-ing the resulting log line
120
+ data = data + chindings
121
+
122
+ let value
123
+ if (formatters.log) {
124
+ obj = formatters.log(obj)
125
+ }
126
+ const wildcardStringifier = stringifiers[wildcardFirstSym]
127
+ let propStr = ''
128
+ for (const key in obj) {
129
+ value = obj[key]
130
+ if (Object.prototype.hasOwnProperty.call(obj, key) && value !== undefined) {
131
+ if (serializers[key]) {
132
+ value = serializers[key](value)
133
+ } else if (key === errorKey && serializers.err) {
134
+ value = serializers.err(value)
135
+ }
136
+
137
+ const stringifier = stringifiers[key] || wildcardStringifier
138
+
139
+ switch (typeof value) {
140
+ case 'undefined':
141
+ case 'function':
142
+ continue
143
+ case 'number':
144
+ /* eslint no-fallthrough: "off" */
145
+ if (Number.isFinite(value) === false) {
146
+ value = null
147
+ }
148
+ // this case explicitly falls through to the next one
149
+ case 'boolean':
150
+ if (stringifier) value = stringifier(value)
151
+ break
152
+ case 'string':
153
+ value = (stringifier || asString)(value)
154
+ break
155
+ default:
156
+ value = (stringifier || stringify)(value, stringifySafe)
157
+ }
158
+ if (value === undefined) continue
159
+ const strKey = asString(key)
160
+ propStr += ',' + strKey + ':' + value
161
+ }
162
+ }
163
+
164
+ let msgStr = ''
165
+ if (msg !== undefined) {
166
+ value = serializers[messageKey] ? serializers[messageKey](msg) : msg
167
+ const stringifier = stringifiers[messageKey] || wildcardStringifier
168
+
169
+ switch (typeof value) {
170
+ case 'function':
171
+ break
172
+ case 'number':
173
+ /* eslint no-fallthrough: "off" */
174
+ if (Number.isFinite(value) === false) {
175
+ value = null
176
+ }
177
+ // this case explicitly falls through to the next one
178
+ case 'boolean':
179
+ if (stringifier) value = stringifier(value)
180
+ msgStr = ',"' + messageKey + '":' + value
181
+ break
182
+ case 'string':
183
+ value = (stringifier || asString)(value)
184
+ msgStr = ',"' + messageKey + '":' + value
185
+ break
186
+ default:
187
+ value = (stringifier || stringify)(value, stringifySafe)
188
+ msgStr = ',"' + messageKey + '":' + value
189
+ }
190
+ }
191
+
192
+ if (this[nestedKeySym] && propStr) {
193
+ // place all the obj properties under the specified key
194
+ // the nested key is already formatted from the constructor
195
+ return data + this[nestedKeyStrSym] + propStr.slice(1) + '}' + msgStr + end
196
+ } else {
197
+ return data + propStr + msgStr + end
198
+ }
199
+ }
200
+
201
+ function asChindings (instance, bindings) {
202
+ let value
203
+ let data = instance[chindingsSym]
204
+ const stringify = instance[stringifySym]
205
+ const stringifySafe = instance[stringifySafeSym]
206
+ const stringifiers = instance[stringifiersSym]
207
+ const wildcardStringifier = stringifiers[wildcardFirstSym]
208
+ const serializers = instance[serializersSym]
209
+ const formatter = instance[formattersSym].bindings
210
+ bindings = formatter(bindings)
211
+
212
+ for (const key in bindings) {
213
+ value = bindings[key]
214
+ const valid = key !== 'level' &&
215
+ key !== 'serializers' &&
216
+ key !== 'formatters' &&
217
+ key !== 'customLevels' &&
218
+ bindings.hasOwnProperty(key) &&
219
+ value !== undefined
220
+ if (valid === true) {
221
+ value = serializers[key] ? serializers[key](value) : value
222
+ value = (stringifiers[key] || wildcardStringifier || stringify)(value, stringifySafe)
223
+ if (value === undefined) continue
224
+ data += ',"' + key + '":' + value
225
+ }
226
+ }
227
+ return data
228
+ }
229
+
230
+ function hasBeenTampered (stream) {
231
+ return stream.write !== stream.constructor.prototype.write
232
+ }
233
+
234
+ const hasNodeCodeCoverage = process.env.NODE_V8_COVERAGE || process.env.V8_COVERAGE
235
+
236
+ function buildSafeSonicBoom (opts) {
237
+ const stream = new SonicBoom(opts)
238
+ stream.on('error', filterBrokenPipe)
239
+ // If we are sync: false, we must flush on exit
240
+ // We must disable this if there is node code coverage due to
241
+ // https://github.com/nodejs/node/issues/49344#issuecomment-1741776308.
242
+ if (!hasNodeCodeCoverage && !opts.sync && isMainThread) {
243
+ onExit.register(stream, autoEnd)
244
+
245
+ stream.on('close', function () {
246
+ onExit.unregister(stream)
247
+ })
248
+ }
249
+ return stream
250
+
251
+ function filterBrokenPipe (err) {
252
+ // Impossible to replicate across all operating systems
253
+ /* istanbul ignore next */
254
+ if (err.code === 'EPIPE') {
255
+ // If we get EPIPE, we should stop logging here
256
+ // however we have no control to the consumer of
257
+ // SonicBoom, so we just overwrite the write method
258
+ stream.write = noop
259
+ stream.end = noop
260
+ stream.flushSync = noop
261
+ stream.destroy = noop
262
+ return
263
+ }
264
+ stream.removeListener('error', filterBrokenPipe)
265
+ stream.emit('error', err)
266
+ }
267
+ }
268
+
269
+ function autoEnd (stream, eventName) {
270
+ // This check is needed only on some platforms
271
+ /* istanbul ignore next */
272
+ if (stream.destroyed) {
273
+ return
274
+ }
275
+
276
+ if (eventName === 'beforeExit') {
277
+ // We still have an event loop, let's use it
278
+ stream.flush()
279
+ stream.on('drain', function () {
280
+ stream.end()
281
+ })
282
+ } else {
283
+ // For some reason istanbul is not detecting this, but it's there
284
+ /* istanbul ignore next */
285
+ // We do not have an event loop, so flush synchronously
286
+ stream.flushSync()
287
+ }
288
+ }
289
+
290
+ function createArgsNormalizer (defaultOptions) {
291
+ return function normalizeArgs (instance, caller, opts = {}, stream) {
292
+ // support stream as a string
293
+ if (typeof opts === 'string') {
294
+ stream = buildSafeSonicBoom({ dest: opts })
295
+ opts = {}
296
+ } else if (typeof stream === 'string') {
297
+ if (opts && opts.transport) {
298
+ throw Error('only one of option.transport or stream can be specified')
299
+ }
300
+ stream = buildSafeSonicBoom({ dest: stream })
301
+ } else if (opts instanceof SonicBoom || opts.writable || opts._writableState) {
302
+ stream = opts
303
+ opts = {}
304
+ } else if (opts.transport) {
305
+ if (opts.transport instanceof SonicBoom || opts.transport.writable || opts.transport._writableState) {
306
+ throw Error('option.transport do not allow stream, please pass to option directly. e.g. pino(transport)')
307
+ }
308
+ if (opts.transport.targets && opts.transport.targets.length && opts.formatters && typeof opts.formatters.level === 'function') {
309
+ throw Error('option.transport.targets do not allow custom level formatters')
310
+ }
311
+
312
+ let customLevels
313
+ if (opts.customLevels) {
314
+ customLevels = opts.useOnlyCustomLevels ? opts.customLevels : Object.assign({}, opts.levels, opts.customLevels)
315
+ }
316
+ stream = transport({ caller, ...opts.transport, levels: customLevels })
317
+ }
318
+ opts = Object.assign({}, defaultOptions, opts)
319
+ opts.serializers = Object.assign({}, defaultOptions.serializers, opts.serializers)
320
+ opts.formatters = Object.assign({}, defaultOptions.formatters, opts.formatters)
321
+
322
+ if (opts.prettyPrint) {
323
+ throw new Error('prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)')
324
+ }
325
+
326
+ const { enabled, onChild } = opts
327
+ if (enabled === false) opts.level = 'silent'
328
+ if (!onChild) opts.onChild = noop
329
+ if (!stream) {
330
+ if (!hasBeenTampered(process.stdout)) {
331
+ // If process.stdout.fd is undefined, it means that we are running
332
+ // in a worker thread. Let's assume we are logging to file descriptor 1.
333
+ stream = buildSafeSonicBoom({ fd: process.stdout.fd || 1 })
334
+ } else {
335
+ stream = process.stdout
336
+ }
337
+ }
338
+ return { opts, stream }
339
+ }
340
+ }
341
+
342
+ function stringify (obj, stringifySafeFn) {
343
+ try {
344
+ return JSON.stringify(obj)
345
+ } catch (_) {
346
+ try {
347
+ const stringify = stringifySafeFn || this[stringifySafeSym]
348
+ return stringify(obj)
349
+ } catch (_) {
350
+ return '"[unable to serialize, circular reference is too complex to analyze]"'
351
+ }
352
+ }
353
+ }
354
+
355
+ function buildFormatters (level, bindings, log) {
356
+ return {
357
+ level,
358
+ bindings,
359
+ log
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Convert a string integer file descriptor to a proper native integer
365
+ * file descriptor.
366
+ *
367
+ * @param {string} destination The file descriptor string to attempt to convert.
368
+ *
369
+ * @returns {Number}
370
+ */
371
+ function normalizeDestFileDescriptor (destination) {
372
+ const fd = Number(destination)
373
+ if (typeof destination === 'string' && Number.isFinite(fd)) {
374
+ return fd
375
+ }
376
+ // destination could be undefined if we are in a worker
377
+ if (destination === undefined) {
378
+ // This is stdout in UNIX systems
379
+ return 1
380
+ }
381
+ return destination
382
+ }
383
+
384
+ module.exports = {
385
+ noop,
386
+ buildSafeSonicBoom,
387
+ asChindings,
388
+ asJson,
389
+ genLog,
390
+ createArgsNormalizer,
391
+ stringify,
392
+ buildFormatters,
393
+ normalizeDestFileDescriptor
394
+ }
@@ -0,0 +1,56 @@
1
+ 'use strict'
2
+
3
+ const { realImport, realRequire } = require('real-require')
4
+
5
+ module.exports = loadTransportStreamBuilder
6
+
7
+ /**
8
+ * Loads & returns a function to build transport streams
9
+ * @param {string} target
10
+ * @returns {Promise<function(object): Promise<import('node:stream').Writable>>}
11
+ * @throws {Error} In case the target module does not export a function
12
+ */
13
+ async function loadTransportStreamBuilder (target) {
14
+ let fn
15
+ try {
16
+ const toLoad = target.startsWith('file://') ? target : 'file://' + target
17
+
18
+ if (toLoad.endsWith('.ts') || toLoad.endsWith('.cts')) {
19
+ // TODO: add support for the TSM modules loader ( https://github.com/lukeed/tsm ).
20
+ if (process[Symbol.for('ts-node.register.instance')]) {
21
+ realRequire('ts-node/register')
22
+ } else if (process.env && process.env.TS_NODE_DEV) {
23
+ realRequire('ts-node-dev')
24
+ }
25
+ // TODO: Support ES imports once tsc, tap & ts-node provide better compatibility guarantees.
26
+ fn = realRequire(decodeURIComponent(target))
27
+ } else {
28
+ fn = (await realImport(toLoad))
29
+ }
30
+ } catch (error) {
31
+ // See this PR for details: https://github.com/pinojs/thread-stream/pull/34
32
+ if ((error.code === 'ENOTDIR' || error.code === 'ERR_MODULE_NOT_FOUND')) {
33
+ fn = realRequire(target)
34
+ } else if (error.code === undefined || error.code === 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING') {
35
+ // When bundled with pkg, an undefined error is thrown when called with realImport
36
+ // When bundled with pkg and using node v20, an ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING error is thrown when called with realImport
37
+ // More info at: https://github.com/pinojs/thread-stream/issues/143
38
+ try {
39
+ fn = realRequire(decodeURIComponent(target))
40
+ } catch {
41
+ throw error
42
+ }
43
+ } else {
44
+ throw error
45
+ }
46
+ }
47
+
48
+ // Depending on how the default export is performed, and on how the code is
49
+ // transpiled, we may find cases of two nested "default" objects.
50
+ // See https://github.com/pinojs/pino/issues/1243#issuecomment-982774762
51
+ if (typeof fn === 'object') fn = fn.default
52
+ if (typeof fn === 'object') fn = fn.default
53
+ if (typeof fn !== 'function') throw Error('exported worker is not a function')
54
+
55
+ return fn
56
+ }