import { readFile } from 'node:fs/promises'; import { spawn } from 'node:child_process'; /** * gitRevParse spawns a git rev-parse command and reports its stdout * in a resolved promise or a rejected error on completion, * depending on the exit code. */ const gitRevParse = (rev) => new Promise((resolve, reject) => { let commit = '', err = ''; const proc = spawn('git', ['rev-parse', '--short', rev]); proc.stdout.on('data', (data) => commit += data.toString().trim()); proc.stderr.on('data', (data) => err += err.toString()); proc.on('close', (code) => code === 0 ? resolve(commit) : reject(err)); }); /** * replaceOnCopyPlugin is an esbuild plugin. it loads files as utf-8 text * and replaces certain placeholders with their values computed on plugin setup. * the fileFilter is a regexp matching names or extensions of the files to process, * passed to esbuild's onLoad as is. * * the following placeholders are replaced: * * #[PKG_VERSION]# -> npm package version * #[GIT_COMMIT]# -> short git commit at current HEAD */ export const replaceOnCopyPlugin = (fileFilter) => { return { name: 'replace-on-copy', setup(build) { const appVersion = process.env.npm_package_version; const gitHeadCommit = gitRevParse('HEAD'); build.onLoad({filter: fileFilter}, async (args) => { const gitCommitHash = await gitHeadCommit; let text = await readFile(args.path, 'utf8'); text = text.replaceAll('#[PKG_VERSION]#', appVersion); text = text.replaceAll('#[GIT_COMMIT]#', gitCommitHash); return { contents: text, loader: 'copy', } }); } } }