vite-plugin-purify 0.0.1-security → 2.3.4
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 vite-plugin-purify might be problematic. Click here for more details.
- package/.eslintignore +2 -0
- package/.eslintrc +8 -0
- package/.github/dependabot.yml +13 -0
- package/.github/workflows/bench.yml +61 -0
- package/.github/workflows/ci.yml +88 -0
- package/.github/workflows/lock-threads.yml +30 -0
- package/.github/workflows/target-main.yml +23 -0
- package/.nojekyll +0 -0
- package/.prettierignore +1 -0
- package/.taprc.yaml +8 -0
- package/CNAME +1 -0
- package/CONTRIBUTING.md +30 -0
- package/LICENSE +21 -0
- package/README.md +159 -3
- package/SECURITY.md +68 -0
- package/benchmarks/basic.bench.js +95 -0
- package/benchmarks/child-child.bench.js +52 -0
- package/benchmarks/child-creation.bench.js +73 -0
- package/benchmarks/child.bench.js +62 -0
- package/benchmarks/deep-object.bench.js +88 -0
- package/benchmarks/formatters.bench.js +50 -0
- package/benchmarks/internal/custom-levels.js +67 -0
- package/benchmarks/internal/just-pino-heavy.bench.js +76 -0
- package/benchmarks/internal/just-pino.bench.js +182 -0
- package/benchmarks/internal/parent-vs-child.bench.js +75 -0
- package/benchmarks/internal/redact.bench.js +86 -0
- package/benchmarks/long-string.bench.js +81 -0
- package/benchmarks/multi-arg.bench.js +193 -0
- package/benchmarks/multistream.js +98 -0
- package/benchmarks/object.bench.js +82 -0
- package/benchmarks/utils/generate-benchmark-doc.js +36 -0
- package/benchmarks/utils/runbench.js +138 -0
- package/benchmarks/utils/wrap-log-level.js +55 -0
- package/bin.js +6 -0
- package/browser.js +484 -0
- package/build/sync-version.js +10 -0
- package/docs/api.md +1487 -0
- package/docs/asynchronous.md +40 -0
- package/docs/benchmarks.md +55 -0
- package/docs/browser.md +227 -0
- package/docs/bundling.md +40 -0
- package/docs/child-loggers.md +95 -0
- package/docs/ecosystem.md +84 -0
- package/docs/help.md +345 -0
- package/docs/lts.md +64 -0
- package/docs/pretty.md +35 -0
- package/docs/redaction.md +135 -0
- package/docs/transports.md +1238 -0
- package/docs/web.md +269 -0
- package/docsify/sidebar.md +26 -0
- package/examples/basic.js +43 -0
- package/examples/transport.js +68 -0
- package/favicon-16x16.png +0 -0
- package/favicon-32x32.png +0 -0
- package/favicon.ico +0 -0
- package/file.js +12 -0
- package/inc-version.sh +42 -0
- package/index.html +55 -0
- package/lib/caller.js +30 -0
- package/lib/constants.js +28 -0
- package/lib/deprecations.js +8 -0
- package/lib/levels.js +241 -0
- package/lib/meta.js +3 -0
- package/lib/multistream.js +188 -0
- package/lib/proto.js +234 -0
- package/lib/redaction.js +118 -0
- package/lib/symbols.js +74 -0
- package/lib/time.js +11 -0
- package/lib/tools.js +394 -0
- package/lib/transport-stream.js +56 -0
- package/lib/transport.js +167 -0
- package/lib/worker.js +194 -0
- package/lib/writer.js +42 -0
- package/logs-buffer - Shortcut.lnk +0 -0
- package/package.json +117 -3
- package/pino-banner.png +0 -0
- package/pino-logo-hire.png +0 -0
- package/pino-tree.png +0 -0
- package/pino.d.ts +889 -0
- package/pino.js +236 -0
- package/pretty-demo.png +0 -0
- package/test/basic.test.js +874 -0
- package/test/broken-pipe.test.js +57 -0
- package/test/browser-child.test.js +132 -0
- package/test/browser-disabled.test.js +87 -0
- package/test/browser-early-console-freeze.test.js +12 -0
- package/test/browser-levels.test.js +241 -0
- package/test/browser-serializers.test.js +352 -0
- package/test/browser-timestamp.test.js +88 -0
- package/test/browser-transmit.test.js +417 -0
- package/test/browser.test.js +659 -0
- package/test/complex-objects.test.js +34 -0
- package/test/crlf.test.js +32 -0
- package/test/custom-levels.test.js +253 -0
- package/test/error.test.js +398 -0
- package/test/errorKey.test.js +34 -0
- package/test/escaping.test.js +91 -0
- package/test/esm/esm.mjs +12 -0
- package/test/esm/index.test.js +34 -0
- package/test/esm/named-exports.mjs +27 -0
- package/test/exit.test.js +77 -0
- package/test/fixtures/broken-pipe/basic.js +9 -0
- package/test/fixtures/broken-pipe/destination.js +10 -0
- package/test/fixtures/broken-pipe/syncfalse.js +12 -0
- package/test/fixtures/console-transport.js +13 -0
- package/test/fixtures/default-exit.js +8 -0
- package/test/fixtures/destination-exit.js +8 -0
- package/test/fixtures/eval/index.js +13 -0
- package/test/fixtures/eval/node_modules/14-files.js +3 -0
- package/test/fixtures/eval/node_modules/2-files.js +3 -0
- package/test/fixtures/eval/node_modules/file1.js +5 -0
- package/test/fixtures/eval/node_modules/file10.js +5 -0
- package/test/fixtures/eval/node_modules/file11.js +5 -0
- package/test/fixtures/eval/node_modules/file12.js +5 -0
- package/test/fixtures/eval/node_modules/file13.js +5 -0
- package/test/fixtures/eval/node_modules/file14.js +11 -0
- package/test/fixtures/eval/node_modules/file2.js +5 -0
- package/test/fixtures/eval/node_modules/file3.js +5 -0
- package/test/fixtures/eval/node_modules/file4.js +5 -0
- package/test/fixtures/eval/node_modules/file5.js +5 -0
- package/test/fixtures/eval/node_modules/file6.js +5 -0
- package/test/fixtures/eval/node_modules/file7.js +5 -0
- package/test/fixtures/eval/node_modules/file8.js +5 -0
- package/test/fixtures/eval/node_modules/file9.js +5 -0
- package/test/fixtures/noop-transport.js +10 -0
- package/test/fixtures/pretty/null-prototype.js +8 -0
- package/test/fixtures/stdout-hack-protection.js +11 -0
- package/test/fixtures/syncfalse-child.js +6 -0
- package/test/fixtures/syncfalse-exit.js +9 -0
- package/test/fixtures/syncfalse-flush-exit.js +10 -0
- package/test/fixtures/syncfalse.js +6 -0
- package/test/fixtures/syntax-error-esm.mjs +2 -0
- package/test/fixtures/to-file-transport-with-transform.js +20 -0
- package/test/fixtures/to-file-transport.js +13 -0
- package/test/fixtures/to-file-transport.mjs +8 -0
- package/test/fixtures/transport/index.js +12 -0
- package/test/fixtures/transport/package.json +5 -0
- package/test/fixtures/transport-exit-immediately-with-async-dest.js +16 -0
- package/test/fixtures/transport-exit-immediately.js +11 -0
- package/test/fixtures/transport-exit-on-ready.js +12 -0
- package/test/fixtures/transport-main.js +9 -0
- package/test/fixtures/transport-many-lines.js +29 -0
- package/test/fixtures/transport-string-stdout.js +9 -0
- package/test/fixtures/transport-transform.js +21 -0
- package/test/fixtures/transport-uses-pino-config.js +33 -0
- package/test/fixtures/transport-with-on-exit.js +12 -0
- package/test/fixtures/transport-worker-data.js +19 -0
- package/test/fixtures/transport-worker.js +15 -0
- package/test/fixtures/transport-wrong-export-type.js +3 -0
- package/test/fixtures/ts/to-file-transport-with-transform.ts +18 -0
- package/test/fixtures/ts/to-file-transport.ts +11 -0
- package/test/fixtures/ts/transpile.cjs +36 -0
- package/test/fixtures/ts/transport-exit-immediately-with-async-dest.ts +15 -0
- package/test/fixtures/ts/transport-exit-immediately.ts +10 -0
- package/test/fixtures/ts/transport-exit-on-ready.ts +11 -0
- package/test/fixtures/ts/transport-main.ts +8 -0
- package/test/fixtures/ts/transport-string-stdout.ts +8 -0
- package/test/fixtures/ts/transport-worker.ts +14 -0
- package/test/formatters.test.js +355 -0
- package/test/helper.d.ts +4 -0
- package/test/helper.js +128 -0
- package/test/hooks.test.js +118 -0
- package/test/http.test.js +242 -0
- package/test/internals/version.test.js +15 -0
- package/test/is-level-enabled.test.js +185 -0
- package/test/jest/basic.spec.js +10 -0
- package/test/levels.test.js +772 -0
- package/test/metadata.test.js +106 -0
- package/test/mixin-merge-strategy.test.js +55 -0
- package/test/mixin.test.js +218 -0
- package/test/multistream.test.js +673 -0
- package/test/pkg/index.js +46 -0
- package/test/pkg/pkg.config.json +17 -0
- package/test/pkg/pkg.test.js +56 -0
- package/test/redact.test.js +847 -0
- package/test/serializers.test.js +253 -0
- package/test/stdout-protection.test.js +39 -0
- package/test/syncfalse.test.js +188 -0
- package/test/timestamp.test.js +121 -0
- package/test/transport/big.test.js +43 -0
- package/test/transport/bundlers-support.test.js +97 -0
- package/test/transport/caller.test.js +23 -0
- package/test/transport/core.test.js +644 -0
- package/test/transport/core.test.ts +236 -0
- package/test/transport/core.transpiled.test.ts +112 -0
- package/test/transport/module-link.test.js +239 -0
- package/test/transport/pipeline.test.js +135 -0
- package/test/transport/repl.test.js +14 -0
- package/test/transport/syncTrue.test.js +55 -0
- package/test/transport/syncfalse.test.js +68 -0
- package/test/transport/targets.test.js +44 -0
- package/test/transport/uses-pino-config.test.js +167 -0
- package/test/transport-stream.test.js +26 -0
- package/test/types/pino-import.test-d.ts +29 -0
- package/test/types/pino-multistream.test-d.ts +28 -0
- package/test/types/pino-top-export.test-d.ts +35 -0
- package/test/types/pino-transport.test-d.ts +145 -0
- package/test/types/pino-type-only.test-d.ts +64 -0
- package/test/types/pino.test-d.ts +468 -0
- package/test/types/pino.ts +78 -0
- package/tsconfig.json +14 -0
package/lib/levels.js
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
'use strict'
|
2
|
+
/* eslint no-prototype-builtins: 0 */
|
3
|
+
const {
|
4
|
+
lsCacheSym,
|
5
|
+
levelValSym,
|
6
|
+
useOnlyCustomLevelsSym,
|
7
|
+
streamSym,
|
8
|
+
formattersSym,
|
9
|
+
hooksSym,
|
10
|
+
levelCompSym
|
11
|
+
} = require('./symbols')
|
12
|
+
const { noop, genLog } = require('./tools')
|
13
|
+
const { DEFAULT_LEVELS, SORTING_ORDER } = require('./constants')
|
14
|
+
|
15
|
+
const levelMethods = {
|
16
|
+
fatal: (hook) => {
|
17
|
+
const logFatal = genLog(DEFAULT_LEVELS.fatal, hook)
|
18
|
+
return function (...args) {
|
19
|
+
const stream = this[streamSym]
|
20
|
+
logFatal.call(this, ...args)
|
21
|
+
if (typeof stream.flushSync === 'function') {
|
22
|
+
try {
|
23
|
+
stream.flushSync()
|
24
|
+
} catch (e) {
|
25
|
+
// https://github.com/pinojs/pino/pull/740#discussion_r346788313
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
},
|
30
|
+
error: (hook) => genLog(DEFAULT_LEVELS.error, hook),
|
31
|
+
warn: (hook) => genLog(DEFAULT_LEVELS.warn, hook),
|
32
|
+
info: (hook) => genLog(DEFAULT_LEVELS.info, hook),
|
33
|
+
debug: (hook) => genLog(DEFAULT_LEVELS.debug, hook),
|
34
|
+
trace: (hook) => genLog(DEFAULT_LEVELS.trace, hook)
|
35
|
+
}
|
36
|
+
|
37
|
+
const nums = Object.keys(DEFAULT_LEVELS).reduce((o, k) => {
|
38
|
+
o[DEFAULT_LEVELS[k]] = k
|
39
|
+
return o
|
40
|
+
}, {})
|
41
|
+
|
42
|
+
const initialLsCache = Object.keys(nums).reduce((o, k) => {
|
43
|
+
o[k] = '{"level":' + Number(k)
|
44
|
+
return o
|
45
|
+
}, {})
|
46
|
+
|
47
|
+
function genLsCache (instance) {
|
48
|
+
const formatter = instance[formattersSym].level
|
49
|
+
const { labels } = instance.levels
|
50
|
+
const cache = {}
|
51
|
+
for (const label in labels) {
|
52
|
+
const level = formatter(labels[label], Number(label))
|
53
|
+
cache[label] = JSON.stringify(level).slice(0, -1)
|
54
|
+
}
|
55
|
+
instance[lsCacheSym] = cache
|
56
|
+
return instance
|
57
|
+
}
|
58
|
+
|
59
|
+
function isStandardLevel (level, useOnlyCustomLevels) {
|
60
|
+
if (useOnlyCustomLevels) {
|
61
|
+
return false
|
62
|
+
}
|
63
|
+
|
64
|
+
switch (level) {
|
65
|
+
case 'fatal':
|
66
|
+
case 'error':
|
67
|
+
case 'warn':
|
68
|
+
case 'info':
|
69
|
+
case 'debug':
|
70
|
+
case 'trace':
|
71
|
+
return true
|
72
|
+
default:
|
73
|
+
return false
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
function setLevel (level) {
|
78
|
+
const { labels, values } = this.levels
|
79
|
+
if (typeof level === 'number') {
|
80
|
+
if (labels[level] === undefined) throw Error('unknown level value' + level)
|
81
|
+
level = labels[level]
|
82
|
+
}
|
83
|
+
if (values[level] === undefined) throw Error('unknown level ' + level)
|
84
|
+
const preLevelVal = this[levelValSym]
|
85
|
+
const levelVal = this[levelValSym] = values[level]
|
86
|
+
const useOnlyCustomLevelsVal = this[useOnlyCustomLevelsSym]
|
87
|
+
const levelComparison = this[levelCompSym]
|
88
|
+
const hook = this[hooksSym].logMethod
|
89
|
+
|
90
|
+
for (const key in values) {
|
91
|
+
if (levelComparison(values[key], levelVal) === false) {
|
92
|
+
this[key] = noop
|
93
|
+
continue
|
94
|
+
}
|
95
|
+
this[key] = isStandardLevel(key, useOnlyCustomLevelsVal) ? levelMethods[key](hook) : genLog(values[key], hook)
|
96
|
+
}
|
97
|
+
|
98
|
+
this.emit(
|
99
|
+
'level-change',
|
100
|
+
level,
|
101
|
+
levelVal,
|
102
|
+
labels[preLevelVal],
|
103
|
+
preLevelVal,
|
104
|
+
this
|
105
|
+
)
|
106
|
+
}
|
107
|
+
|
108
|
+
function getLevel (level) {
|
109
|
+
const { levels, levelVal } = this
|
110
|
+
// protection against potential loss of Pino scope from serializers (edge case with circular refs - https://github.com/pinojs/pino/issues/833)
|
111
|
+
return (levels && levels.labels) ? levels.labels[levelVal] : ''
|
112
|
+
}
|
113
|
+
|
114
|
+
function isLevelEnabled (logLevel) {
|
115
|
+
const { values } = this.levels
|
116
|
+
const logLevelVal = values[logLevel]
|
117
|
+
return logLevelVal !== undefined && this[levelCompSym](logLevelVal, this[levelValSym])
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Determine if the given `current` level is enabled by comparing it
|
122
|
+
* against the current threshold (`expected`).
|
123
|
+
*
|
124
|
+
* @param {SORTING_ORDER} direction comparison direction "ASC" or "DESC"
|
125
|
+
* @param {number} current current log level number representation
|
126
|
+
* @param {number} expected threshold value to compare with
|
127
|
+
* @returns {boolean}
|
128
|
+
*/
|
129
|
+
function compareLevel (direction, current, expected) {
|
130
|
+
if (direction === SORTING_ORDER.DESC) {
|
131
|
+
return current <= expected
|
132
|
+
}
|
133
|
+
|
134
|
+
return current >= expected
|
135
|
+
}
|
136
|
+
|
137
|
+
/**
|
138
|
+
* Create a level comparison function based on `levelComparison`
|
139
|
+
* it could a default function which compares levels either in "ascending" or "descending" order or custom comparison function
|
140
|
+
*
|
141
|
+
* @param {SORTING_ORDER | Function} levelComparison sort levels order direction or custom comparison function
|
142
|
+
* @returns Function
|
143
|
+
*/
|
144
|
+
function genLevelComparison (levelComparison) {
|
145
|
+
if (typeof levelComparison === 'string') {
|
146
|
+
return compareLevel.bind(null, levelComparison)
|
147
|
+
}
|
148
|
+
|
149
|
+
return levelComparison
|
150
|
+
}
|
151
|
+
|
152
|
+
function mappings (customLevels = null, useOnlyCustomLevels = false) {
|
153
|
+
const customNums = customLevels
|
154
|
+
/* eslint-disable */
|
155
|
+
? Object.keys(customLevels).reduce((o, k) => {
|
156
|
+
o[customLevels[k]] = k
|
157
|
+
return o
|
158
|
+
}, {})
|
159
|
+
: null
|
160
|
+
/* eslint-enable */
|
161
|
+
|
162
|
+
const labels = Object.assign(
|
163
|
+
Object.create(Object.prototype, { Infinity: { value: 'silent' } }),
|
164
|
+
useOnlyCustomLevels ? null : nums,
|
165
|
+
customNums
|
166
|
+
)
|
167
|
+
const values = Object.assign(
|
168
|
+
Object.create(Object.prototype, { silent: { value: Infinity } }),
|
169
|
+
useOnlyCustomLevels ? null : DEFAULT_LEVELS,
|
170
|
+
customLevels
|
171
|
+
)
|
172
|
+
return { labels, values }
|
173
|
+
}
|
174
|
+
|
175
|
+
function assertDefaultLevelFound (defaultLevel, customLevels, useOnlyCustomLevels) {
|
176
|
+
if (typeof defaultLevel === 'number') {
|
177
|
+
const values = [].concat(
|
178
|
+
Object.keys(customLevels || {}).map(key => customLevels[key]),
|
179
|
+
useOnlyCustomLevels ? [] : Object.keys(nums).map(level => +level),
|
180
|
+
Infinity
|
181
|
+
)
|
182
|
+
if (!values.includes(defaultLevel)) {
|
183
|
+
throw Error(`default level:${defaultLevel} must be included in custom levels`)
|
184
|
+
}
|
185
|
+
return
|
186
|
+
}
|
187
|
+
|
188
|
+
const labels = Object.assign(
|
189
|
+
Object.create(Object.prototype, { silent: { value: Infinity } }),
|
190
|
+
useOnlyCustomLevels ? null : DEFAULT_LEVELS,
|
191
|
+
customLevels
|
192
|
+
)
|
193
|
+
if (!(defaultLevel in labels)) {
|
194
|
+
throw Error(`default level:${defaultLevel} must be included in custom levels`)
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
function assertNoLevelCollisions (levels, customLevels) {
|
199
|
+
const { labels, values } = levels
|
200
|
+
for (const k in customLevels) {
|
201
|
+
if (k in values) {
|
202
|
+
throw Error('levels cannot be overridden')
|
203
|
+
}
|
204
|
+
if (customLevels[k] in labels) {
|
205
|
+
throw Error('pre-existing level values cannot be used for new levels')
|
206
|
+
}
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Validates whether `levelComparison` is correct
|
212
|
+
*
|
213
|
+
* @throws Error
|
214
|
+
* @param {SORTING_ORDER | Function} levelComparison - value to validate
|
215
|
+
* @returns
|
216
|
+
*/
|
217
|
+
function assertLevelComparison (levelComparison) {
|
218
|
+
if (typeof levelComparison === 'function') {
|
219
|
+
return
|
220
|
+
}
|
221
|
+
|
222
|
+
if (typeof levelComparison === 'string' && Object.values(SORTING_ORDER).includes(levelComparison)) {
|
223
|
+
return
|
224
|
+
}
|
225
|
+
|
226
|
+
throw new Error('Levels comparison should be one of "ASC", "DESC" or "function" type')
|
227
|
+
}
|
228
|
+
|
229
|
+
module.exports = {
|
230
|
+
initialLsCache,
|
231
|
+
genLsCache,
|
232
|
+
levelMethods,
|
233
|
+
getLevel,
|
234
|
+
setLevel,
|
235
|
+
isLevelEnabled,
|
236
|
+
mappings,
|
237
|
+
assertNoLevelCollisions,
|
238
|
+
assertDefaultLevelFound,
|
239
|
+
genLevelComparison,
|
240
|
+
assertLevelComparison
|
241
|
+
}
|
package/lib/meta.js
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
const metadata = Symbol.for('pino.metadata')
|
4
|
+
const { DEFAULT_LEVELS } = require('./constants')
|
5
|
+
|
6
|
+
const DEFAULT_INFO_LEVEL = DEFAULT_LEVELS.info
|
7
|
+
|
8
|
+
function multistream (streamsArray, opts) {
|
9
|
+
let counter = 0
|
10
|
+
streamsArray = streamsArray || []
|
11
|
+
opts = opts || { dedupe: false }
|
12
|
+
|
13
|
+
const streamLevels = Object.create(DEFAULT_LEVELS)
|
14
|
+
streamLevels.silent = Infinity
|
15
|
+
if (opts.levels && typeof opts.levels === 'object') {
|
16
|
+
Object.keys(opts.levels).forEach(i => {
|
17
|
+
streamLevels[i] = opts.levels[i]
|
18
|
+
})
|
19
|
+
}
|
20
|
+
|
21
|
+
const res = {
|
22
|
+
write,
|
23
|
+
add,
|
24
|
+
emit,
|
25
|
+
flushSync,
|
26
|
+
end,
|
27
|
+
minLevel: 0,
|
28
|
+
streams: [],
|
29
|
+
clone,
|
30
|
+
[metadata]: true,
|
31
|
+
streamLevels
|
32
|
+
}
|
33
|
+
|
34
|
+
if (Array.isArray(streamsArray)) {
|
35
|
+
streamsArray.forEach(add, res)
|
36
|
+
} else {
|
37
|
+
add.call(res, streamsArray)
|
38
|
+
}
|
39
|
+
|
40
|
+
// clean this object up
|
41
|
+
// or it will stay allocated forever
|
42
|
+
// as it is closed on the following closures
|
43
|
+
streamsArray = null
|
44
|
+
|
45
|
+
return res
|
46
|
+
|
47
|
+
// we can exit early because the streams are ordered by level
|
48
|
+
function write (data) {
|
49
|
+
let dest
|
50
|
+
const level = this.lastLevel
|
51
|
+
const { streams } = this
|
52
|
+
// for handling situation when several streams has the same level
|
53
|
+
let recordedLevel = 0
|
54
|
+
let stream
|
55
|
+
|
56
|
+
// if dedupe set to true we send logs to the stream with the highest level
|
57
|
+
// therefore, we have to change sorting order
|
58
|
+
for (let i = initLoopVar(streams.length, opts.dedupe); checkLoopVar(i, streams.length, opts.dedupe); i = adjustLoopVar(i, opts.dedupe)) {
|
59
|
+
dest = streams[i]
|
60
|
+
if (dest.level <= level) {
|
61
|
+
if (recordedLevel !== 0 && recordedLevel !== dest.level) {
|
62
|
+
break
|
63
|
+
}
|
64
|
+
stream = dest.stream
|
65
|
+
if (stream[metadata]) {
|
66
|
+
const { lastTime, lastMsg, lastObj, lastLogger } = this
|
67
|
+
stream.lastLevel = level
|
68
|
+
stream.lastTime = lastTime
|
69
|
+
stream.lastMsg = lastMsg
|
70
|
+
stream.lastObj = lastObj
|
71
|
+
stream.lastLogger = lastLogger
|
72
|
+
}
|
73
|
+
stream.write(data)
|
74
|
+
if (opts.dedupe) {
|
75
|
+
recordedLevel = dest.level
|
76
|
+
}
|
77
|
+
} else if (!opts.dedupe) {
|
78
|
+
break
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
function emit (...args) {
|
84
|
+
for (const { stream } of this.streams) {
|
85
|
+
if (typeof stream.emit === 'function') {
|
86
|
+
stream.emit(...args)
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
function flushSync () {
|
92
|
+
for (const { stream } of this.streams) {
|
93
|
+
if (typeof stream.flushSync === 'function') {
|
94
|
+
stream.flushSync()
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
function add (dest) {
|
100
|
+
if (!dest) {
|
101
|
+
return res
|
102
|
+
}
|
103
|
+
|
104
|
+
// Check that dest implements either StreamEntry or DestinationStream
|
105
|
+
const isStream = typeof dest.write === 'function' || dest.stream
|
106
|
+
const stream_ = dest.write ? dest : dest.stream
|
107
|
+
// This is necessary to provide a meaningful error message, otherwise it throws somewhere inside write()
|
108
|
+
if (!isStream) {
|
109
|
+
throw Error('stream object needs to implement either StreamEntry or DestinationStream interface')
|
110
|
+
}
|
111
|
+
|
112
|
+
const { streams, streamLevels } = this
|
113
|
+
|
114
|
+
let level
|
115
|
+
if (typeof dest.levelVal === 'number') {
|
116
|
+
level = dest.levelVal
|
117
|
+
} else if (typeof dest.level === 'string') {
|
118
|
+
level = streamLevels[dest.level]
|
119
|
+
} else if (typeof dest.level === 'number') {
|
120
|
+
level = dest.level
|
121
|
+
} else {
|
122
|
+
level = DEFAULT_INFO_LEVEL
|
123
|
+
}
|
124
|
+
|
125
|
+
const dest_ = {
|
126
|
+
stream: stream_,
|
127
|
+
level,
|
128
|
+
levelVal: undefined,
|
129
|
+
id: counter++
|
130
|
+
}
|
131
|
+
|
132
|
+
streams.unshift(dest_)
|
133
|
+
streams.sort(compareByLevel)
|
134
|
+
|
135
|
+
this.minLevel = streams[0].level
|
136
|
+
|
137
|
+
return res
|
138
|
+
}
|
139
|
+
|
140
|
+
function end () {
|
141
|
+
for (const { stream } of this.streams) {
|
142
|
+
if (typeof stream.flushSync === 'function') {
|
143
|
+
stream.flushSync()
|
144
|
+
}
|
145
|
+
stream.end()
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
function clone (level) {
|
150
|
+
const streams = new Array(this.streams.length)
|
151
|
+
|
152
|
+
for (let i = 0; i < streams.length; i++) {
|
153
|
+
streams[i] = {
|
154
|
+
level,
|
155
|
+
stream: this.streams[i].stream
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
return {
|
160
|
+
write,
|
161
|
+
add,
|
162
|
+
minLevel: level,
|
163
|
+
streams,
|
164
|
+
clone,
|
165
|
+
emit,
|
166
|
+
flushSync,
|
167
|
+
[metadata]: true
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
function compareByLevel (a, b) {
|
173
|
+
return a.level - b.level
|
174
|
+
}
|
175
|
+
|
176
|
+
function initLoopVar (length, dedupe) {
|
177
|
+
return dedupe ? length - 1 : 0
|
178
|
+
}
|
179
|
+
|
180
|
+
function adjustLoopVar (i, dedupe) {
|
181
|
+
return dedupe ? i - 1 : i + 1
|
182
|
+
}
|
183
|
+
|
184
|
+
function checkLoopVar (i, length, dedupe) {
|
185
|
+
return dedupe ? i >= 0 : i < length
|
186
|
+
}
|
187
|
+
|
188
|
+
module.exports = multistream
|
package/lib/proto.js
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
/* eslint no-prototype-builtins: 0 */
|
4
|
+
|
5
|
+
const { EventEmitter } = require('node:events')
|
6
|
+
const {
|
7
|
+
lsCacheSym,
|
8
|
+
levelValSym,
|
9
|
+
setLevelSym,
|
10
|
+
getLevelSym,
|
11
|
+
chindingsSym,
|
12
|
+
parsedChindingsSym,
|
13
|
+
mixinSym,
|
14
|
+
asJsonSym,
|
15
|
+
writeSym,
|
16
|
+
mixinMergeStrategySym,
|
17
|
+
timeSym,
|
18
|
+
timeSliceIndexSym,
|
19
|
+
streamSym,
|
20
|
+
serializersSym,
|
21
|
+
formattersSym,
|
22
|
+
errorKeySym,
|
23
|
+
messageKeySym,
|
24
|
+
useOnlyCustomLevelsSym,
|
25
|
+
needsMetadataGsym,
|
26
|
+
redactFmtSym,
|
27
|
+
stringifySym,
|
28
|
+
formatOptsSym,
|
29
|
+
stringifiersSym,
|
30
|
+
msgPrefixSym,
|
31
|
+
hooksSym
|
32
|
+
} = require('./symbols')
|
33
|
+
const {
|
34
|
+
getLevel,
|
35
|
+
setLevel,
|
36
|
+
isLevelEnabled,
|
37
|
+
mappings,
|
38
|
+
initialLsCache,
|
39
|
+
genLsCache,
|
40
|
+
assertNoLevelCollisions
|
41
|
+
} = require('./levels')
|
42
|
+
const {
|
43
|
+
asChindings,
|
44
|
+
asJson,
|
45
|
+
buildFormatters,
|
46
|
+
stringify
|
47
|
+
} = require('./tools')
|
48
|
+
const {
|
49
|
+
version
|
50
|
+
} = require('./meta')
|
51
|
+
const redaction = require('./redaction')
|
52
|
+
|
53
|
+
// note: use of class is satirical
|
54
|
+
// https://github.com/pinojs/pino/pull/433#pullrequestreview-127703127
|
55
|
+
const constructor = class Pino {}
|
56
|
+
const prototype = {
|
57
|
+
constructor,
|
58
|
+
child,
|
59
|
+
bindings,
|
60
|
+
setBindings,
|
61
|
+
flush,
|
62
|
+
isLevelEnabled,
|
63
|
+
version,
|
64
|
+
get level () { return this[getLevelSym]() },
|
65
|
+
set level (lvl) { this[setLevelSym](lvl) },
|
66
|
+
get levelVal () { return this[levelValSym] },
|
67
|
+
set levelVal (n) { throw Error('levelVal is read-only') },
|
68
|
+
[lsCacheSym]: initialLsCache,
|
69
|
+
[writeSym]: write,
|
70
|
+
[asJsonSym]: asJson,
|
71
|
+
[getLevelSym]: getLevel,
|
72
|
+
[setLevelSym]: setLevel
|
73
|
+
}
|
74
|
+
|
75
|
+
Object.setPrototypeOf(prototype, EventEmitter.prototype)
|
76
|
+
|
77
|
+
// exporting and consuming the prototype object using factory pattern fixes scoping issues with getters when serializing
|
78
|
+
module.exports = function () {
|
79
|
+
return Object.create(prototype)
|
80
|
+
}
|
81
|
+
|
82
|
+
const resetChildingsFormatter = bindings => bindings
|
83
|
+
function child (bindings, options) {
|
84
|
+
if (!bindings) {
|
85
|
+
throw Error('missing bindings for child Pino')
|
86
|
+
}
|
87
|
+
options = options || {} // default options to empty object
|
88
|
+
const serializers = this[serializersSym]
|
89
|
+
const formatters = this[formattersSym]
|
90
|
+
const instance = Object.create(this)
|
91
|
+
|
92
|
+
if (options.hasOwnProperty('serializers') === true) {
|
93
|
+
instance[serializersSym] = Object.create(null)
|
94
|
+
|
95
|
+
for (const k in serializers) {
|
96
|
+
instance[serializersSym][k] = serializers[k]
|
97
|
+
}
|
98
|
+
const parentSymbols = Object.getOwnPropertySymbols(serializers)
|
99
|
+
/* eslint no-var: off */
|
100
|
+
for (var i = 0; i < parentSymbols.length; i++) {
|
101
|
+
const ks = parentSymbols[i]
|
102
|
+
instance[serializersSym][ks] = serializers[ks]
|
103
|
+
}
|
104
|
+
|
105
|
+
for (const bk in options.serializers) {
|
106
|
+
instance[serializersSym][bk] = options.serializers[bk]
|
107
|
+
}
|
108
|
+
const bindingsSymbols = Object.getOwnPropertySymbols(options.serializers)
|
109
|
+
for (var bi = 0; bi < bindingsSymbols.length; bi++) {
|
110
|
+
const bks = bindingsSymbols[bi]
|
111
|
+
instance[serializersSym][bks] = options.serializers[bks]
|
112
|
+
}
|
113
|
+
} else instance[serializersSym] = serializers
|
114
|
+
if (options.hasOwnProperty('formatters')) {
|
115
|
+
const { level, bindings: chindings, log } = options.formatters
|
116
|
+
instance[formattersSym] = buildFormatters(
|
117
|
+
level || formatters.level,
|
118
|
+
chindings || resetChildingsFormatter,
|
119
|
+
log || formatters.log
|
120
|
+
)
|
121
|
+
} else {
|
122
|
+
instance[formattersSym] = buildFormatters(
|
123
|
+
formatters.level,
|
124
|
+
resetChildingsFormatter,
|
125
|
+
formatters.log
|
126
|
+
)
|
127
|
+
}
|
128
|
+
if (options.hasOwnProperty('customLevels') === true) {
|
129
|
+
assertNoLevelCollisions(this.levels, options.customLevels)
|
130
|
+
instance.levels = mappings(options.customLevels, instance[useOnlyCustomLevelsSym])
|
131
|
+
genLsCache(instance)
|
132
|
+
}
|
133
|
+
|
134
|
+
// redact must place before asChindings and only replace if exist
|
135
|
+
if ((typeof options.redact === 'object' && options.redact !== null) || Array.isArray(options.redact)) {
|
136
|
+
instance.redact = options.redact // replace redact directly
|
137
|
+
const stringifiers = redaction(instance.redact, stringify)
|
138
|
+
const formatOpts = { stringify: stringifiers[redactFmtSym] }
|
139
|
+
instance[stringifySym] = stringify
|
140
|
+
instance[stringifiersSym] = stringifiers
|
141
|
+
instance[formatOptsSym] = formatOpts
|
142
|
+
}
|
143
|
+
|
144
|
+
if (typeof options.msgPrefix === 'string') {
|
145
|
+
instance[msgPrefixSym] = (this[msgPrefixSym] || '') + options.msgPrefix
|
146
|
+
}
|
147
|
+
|
148
|
+
instance[chindingsSym] = asChindings(instance, bindings)
|
149
|
+
const childLevel = options.level || this.level
|
150
|
+
instance[setLevelSym](childLevel)
|
151
|
+
this.onChild(instance)
|
152
|
+
return instance
|
153
|
+
}
|
154
|
+
|
155
|
+
function bindings () {
|
156
|
+
const chindings = this[chindingsSym]
|
157
|
+
const chindingsJson = `{${chindings.substr(1)}}` // at least contains ,"pid":7068,"hostname":"myMac"
|
158
|
+
const bindingsFromJson = JSON.parse(chindingsJson)
|
159
|
+
delete bindingsFromJson.pid
|
160
|
+
delete bindingsFromJson.hostname
|
161
|
+
return bindingsFromJson
|
162
|
+
}
|
163
|
+
|
164
|
+
function setBindings (newBindings) {
|
165
|
+
const chindings = asChindings(this, newBindings)
|
166
|
+
this[chindingsSym] = chindings
|
167
|
+
delete this[parsedChindingsSym]
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* Default strategy for creating `mergeObject` from arguments and the result from `mixin()`.
|
172
|
+
* Fields from `mergeObject` have higher priority in this strategy.
|
173
|
+
*
|
174
|
+
* @param {Object} mergeObject The object a user has supplied to the logging function.
|
175
|
+
* @param {Object} mixinObject The result of the `mixin` method.
|
176
|
+
* @return {Object}
|
177
|
+
*/
|
178
|
+
function defaultMixinMergeStrategy (mergeObject, mixinObject) {
|
179
|
+
return Object.assign(mixinObject, mergeObject)
|
180
|
+
}
|
181
|
+
|
182
|
+
function write (_obj, msg, num) {
|
183
|
+
const t = this[timeSym]()
|
184
|
+
const mixin = this[mixinSym]
|
185
|
+
const errorKey = this[errorKeySym]
|
186
|
+
const messageKey = this[messageKeySym]
|
187
|
+
const mixinMergeStrategy = this[mixinMergeStrategySym] || defaultMixinMergeStrategy
|
188
|
+
let obj
|
189
|
+
const streamWriteHook = this[hooksSym].streamWrite
|
190
|
+
|
191
|
+
if (_obj === undefined || _obj === null) {
|
192
|
+
obj = {}
|
193
|
+
} else if (_obj instanceof Error) {
|
194
|
+
obj = { [errorKey]: _obj }
|
195
|
+
if (msg === undefined) {
|
196
|
+
msg = _obj.message
|
197
|
+
}
|
198
|
+
} else {
|
199
|
+
obj = _obj
|
200
|
+
if (msg === undefined && _obj[messageKey] === undefined && _obj[errorKey]) {
|
201
|
+
msg = _obj[errorKey].message
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
if (mixin) {
|
206
|
+
obj = mixinMergeStrategy(obj, mixin(obj, num, this))
|
207
|
+
}
|
208
|
+
|
209
|
+
const s = this[asJsonSym](obj, msg, num, t)
|
210
|
+
|
211
|
+
const stream = this[streamSym]
|
212
|
+
if (stream[needsMetadataGsym] === true) {
|
213
|
+
stream.lastLevel = num
|
214
|
+
stream.lastObj = obj
|
215
|
+
stream.lastMsg = msg
|
216
|
+
stream.lastTime = t.slice(this[timeSliceIndexSym])
|
217
|
+
stream.lastLogger = this // for child loggers
|
218
|
+
}
|
219
|
+
stream.write(streamWriteHook ? streamWriteHook(s) : s)
|
220
|
+
}
|
221
|
+
|
222
|
+
function noop () {}
|
223
|
+
|
224
|
+
function flush (cb) {
|
225
|
+
if (cb != null && typeof cb !== 'function') {
|
226
|
+
throw Error('callback must be a function')
|
227
|
+
}
|
228
|
+
|
229
|
+
const stream = this[streamSym]
|
230
|
+
|
231
|
+
if (typeof stream.flush === 'function') {
|
232
|
+
stream.flush(cb || noop)
|
233
|
+
} else if (cb) cb()
|
234
|
+
}
|