UNPKG

@chialab/esbuild-rna

Version:

A framework for esbuild plugins with transform and emit capabilities.

141 lines (128 loc) 4.29 kB
import { Buffer } from 'buffer'; import crypto from 'crypto'; import path from 'path'; /** * Create an empty metafile object. * @returns {import('esbuild').Metafile} */ export function createEmptyMetafile() { return { inputs: {}, outputs: {} }; } /** * Create an hash for the given buffer. * @param {Buffer|Uint8Array|string} buffer The buffer input. * @returns A buffer hash. */ export function createFileHash(buffer) { const hash = crypto.createHash('sha1'); hash.update(Buffer.from(buffer)); return hash.digest('hex').substring(0, 8); } /** * @param {string} path * @param {Buffer} contents * @returns {import('esbuild').OutputFile} */ export function createOutputFile(path, contents) { return { path, contents, hash: createFileHash(contents), get text() { return contents.toString(); }, }; } /** * @param {import('esbuild').OutputFile[]} [outputFiles] * @param {import('esbuild').Metafile} [metafile] * @returns {import('./Build.js').Result} */ export function createResult(outputFiles, metafile = createEmptyMetafile()) { return { errors: [], warnings: [], dependencies: {}, outputFiles, metafile, mangleCache: {}, }; } /** * Merge esbuild results into a single object * that collects all inputs and outputs references, errors and warnings. * This is useful when running multiple builds in separated process. * @param {import('./Build.js').Result} context * @param {import('esbuild').BuildResult & { dependencies?: Record<string, string[]> }} result */ export function assignToResult(context, result) { context.errors.push(...result.errors); context.warnings.push(...result.warnings); if (context.outputFiles || result.outputFiles) { const outputFiles = (context.outputFiles = context.outputFiles || []); outputFiles.push(...(result.outputFiles || [])); } const contextMeta = (context.metafile = context.metafile || createEmptyMetafile()); const resultMeta = result.metafile || createEmptyMetafile(); contextMeta.inputs = { ...contextMeta.inputs, ...resultMeta.inputs, }; contextMeta.outputs = { ...contextMeta.outputs, ...resultMeta.outputs, }; /** * @type {Record<string, string[]>} */ const dependencies = (context.dependencies = context.dependencies || {}); if (typeof result.dependencies === 'object') { for (const out of Object.entries(result.dependencies)) { const entryPoint = out[0]; const list = (dependencies[entryPoint] = dependencies[entryPoint] || []); out[1].forEach((dep) => { if (!list.includes(dep)) { list.push(dep); } }); } } } /** * @param {import('./Build.js').Result} result * @param {string} from * @param {string} to * @returns {import('./Build.js').Result} */ export function remapResult(result, from, to) { const resultMeta = result.metafile || createEmptyMetafile(); const inputs = resultMeta.inputs; const outputs = resultMeta.outputs; return { errors: result.errors, warnings: result.warnings, outputFiles: result.outputFiles, dependencies: result.dependencies, metafile: { inputs: Object.keys(inputs).reduce((acc, input) => { const newPath = path.relative(to, path.resolve(from, input)); acc[newPath] = inputs[input]; return acc; }, /** @type {import('esbuild').Metafile['inputs']} */ ({})), outputs: Object.keys(outputs).reduce((acc, output) => { const newPath = path.relative(to, path.resolve(from, output)); acc[newPath] = outputs[output]; return acc; }, /** @type {import('esbuild').Metafile['outputs']} */ ({})), }, mangleCache: result.mangleCache, }; } /** * Check if a plugin is already part of the list. * @param {import('esbuild').Plugin[]} plugins The plugins list. * @param {string} name The of the plugin to check. */ export function hasPlugin(plugins, name) { return plugins.some((plg) => plg.name === name); }