UNPKG

esbuild-plugin-pino

Version:

An esbuild plugin to generate extra pino files for bundling

135 lines (131 loc) 4.91 kB
'use strict'; var promises = require('node:fs/promises'); var path = require('node:path'); function isStringArray(entryPoints) { if (Array.isArray(entryPoints) && entryPoints.some((entrypoint) => typeof entrypoint === "string")) return true; return false; } function transformToObject(entryPoints, outbase) { const separator = entryPoints[0].includes("\\") ? path.win32.sep : path.posix.sep; let tmpOutbase = ""; if (!outbase) { const hierarchy = entryPoints[0].split(separator); let i = 0; let nextOutbase = ""; do { tmpOutbase = nextOutbase; i++; nextOutbase = hierarchy.slice(0, i).join(separator); } while (entryPoints.every( (entrypoint) => entrypoint.startsWith(`${nextOutbase}${separator}`) )); } const newEntrypoints = {}; for (const entrypoint of entryPoints) { const destination = (tmpOutbase ? entrypoint.replace(`${tmpOutbase}${separator}`, "") : entrypoint).replace(/.(js|ts)$/, ""); newEntrypoints[destination] = entrypoint; } return newEntrypoints; } function transformToNewEntryPointsType(entryPoints) { const newEntrypointsType = []; for (const [key, value] of Object.entries(entryPoints)) { newEntrypointsType.push({ in: value, out: key }); } return newEntrypointsType; } function esbuildPluginPino({ transports = [] }) { return { name: "pino", async setup(currentBuild) { const pino = path.dirname(require.resolve("pino")); const threadStream = path.dirname(require.resolve("thread-stream")); const { entryPoints, outbase, outExtension } = currentBuild.initialOptions; const customEntrypoints = { "thread-stream-worker": path.join(threadStream, "lib/worker.js"), "pino-worker": path.join(pino, "lib/worker.js"), "pino-file": path.join(pino, "file.js") }; try { const pinoPipelineWorker = path.join(pino, "lib/worker-pipeline.js"); await promises.stat(pinoPipelineWorker); customEntrypoints["pino-pipeline-worker"] = pinoPipelineWorker; } catch (err) { } const transportsEntrypoints = Object.fromEntries( transports.map((transport) => [transport, require.resolve(transport)]) ); let newEntrypoints = []; if (isStringArray(entryPoints)) { newEntrypoints = transformToNewEntryPointsType({ ...transformToObject(entryPoints, outbase), ...customEntrypoints, ...transportsEntrypoints }); } else if (Array.isArray(entryPoints)) { newEntrypoints = [ ...entryPoints, ...transformToNewEntryPointsType({ ...customEntrypoints, ...transportsEntrypoints }) ]; } else { newEntrypoints = transformToNewEntryPointsType({ ...entryPoints, ...customEntrypoints, ...transportsEntrypoints }); } currentBuild.initialOptions.entryPoints = newEntrypoints; let pinoBundlerRan = false; currentBuild.onEnd(() => { pinoBundlerRan = false; }); currentBuild.onLoad({ filter: /pino\.js$/ }, async (args) => { if (pinoBundlerRan) return; pinoBundlerRan = true; const contents = await promises.readFile(args.path, "utf8"); let absoluteOutputPath = ""; const { outdir = "dist" } = currentBuild.initialOptions; if (path.isAbsolute(outdir)) { absoluteOutputPath = outdir.replace(/\\/g, "\\\\"); } else { const workingDir = currentBuild.initialOptions.absWorkingDir ? `"${currentBuild.initialOptions.absWorkingDir.replace(/\\/g, "\\\\")}"` : "process.cwd()"; absoluteOutputPath = `\${${workingDir}}\${require('path').sep}${currentBuild.initialOptions.outdir || "dist"}`; } const functionDeclaration = ` function pinoBundlerAbsolutePath(p) { try { return require('path').join(\`${absoluteOutputPath}\`.replace(/\\\\/g, '/'), p) } catch(e) { const f = new Function('p', 'return new URL(p, import.meta.url).pathname'); return f(p) } } `; let extension = ".js"; if (outExtension?.[".js"]) { extension = outExtension[".js"]; } const pinoOverrides = Object.keys({ ...customEntrypoints, ...transportsEntrypoints }).map( (id) => `'${id === "pino-file" ? "pino/file" : id}': pinoBundlerAbsolutePath('./${id}${extension}')` ).join(","); const globalThisDeclaration = ` globalThis.__bundlerPathsOverrides = { ...(globalThis.__bundlerPathsOverrides || {}), ${pinoOverrides}} `; const code = functionDeclaration + globalThisDeclaration; return { contents: code + contents }; }); } }; } module.exports = esbuildPluginPino;