Files
infocom-systems-design/node_modules/pino-abstract-transport/index.js
2025-10-03 22:27:28 +03:00

129 lines
3.0 KiB
JavaScript

'use strict'
const metadata = Symbol.for('pino.metadata')
const split = require('split2')
const { Duplex } = require('readable-stream')
const { parentPort, workerData } = require('worker_threads')
function createDeferred () {
let resolve
let reject
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve
reject = _reject
})
promise.resolve = resolve
promise.reject = reject
return promise
}
module.exports = function build (fn, opts = {}) {
const waitForConfig = opts.expectPinoConfig === true && workerData?.workerData?.pinoWillSendConfig === true
const parseLines = opts.parse === 'lines'
const parseLine = typeof opts.parseLine === 'function' ? opts.parseLine : JSON.parse
const close = opts.close || defaultClose
const stream = split(function (line) {
let value
try {
value = parseLine(line)
} catch (error) {
this.emit('unknown', line, error)
return
}
if (value === null) {
this.emit('unknown', line, 'Null value ignored')
return
}
if (typeof value !== 'object') {
value = {
data: value,
time: Date.now()
}
}
if (stream[metadata]) {
stream.lastTime = value.time
stream.lastLevel = value.level
stream.lastObj = value
}
if (parseLines) {
return line
}
return value
}, { autoDestroy: true })
stream._destroy = function (err, cb) {
const promise = close(err, cb)
if (promise && typeof promise.then === 'function') {
promise.then(cb, cb)
}
}
if (opts.expectPinoConfig === true && workerData?.workerData?.pinoWillSendConfig !== true) {
setImmediate(() => {
stream.emit('error', new Error('This transport is not compatible with the current version of pino. Please upgrade pino to the latest version.'))
})
}
if (opts.metadata !== false) {
stream[metadata] = true
stream.lastTime = 0
stream.lastLevel = 0
stream.lastObj = null
}
if (waitForConfig) {
let pinoConfig = {}
const configReceived = createDeferred()
parentPort.on('message', function handleMessage (message) {
if (message.code === 'PINO_CONFIG') {
pinoConfig = message.config
configReceived.resolve()
parentPort.off('message', handleMessage)
}
})
Object.defineProperties(stream, {
levels: {
get () { return pinoConfig.levels }
},
messageKey: {
get () { return pinoConfig.messageKey }
},
errorKey: {
get () { return pinoConfig.errorKey }
}
})
return configReceived.then(finish)
}
return finish()
function finish () {
let res = fn(stream)
if (res && typeof res.catch === 'function') {
res.catch((err) => {
stream.destroy(err)
})
// set it to null to not retain a reference to the promise
res = null
} else if (opts.enablePipelining && res) {
return Duplex.from({ writable: stream, readable: res })
}
return stream
}
}
function defaultClose (err, cb) {
process.nextTick(cb, err)
}