import { cp, mkdir, rm, readdir, readFile, writeFile } from 'node:fs/promises'; import { createHash } from 'node:crypto'; import { build } from 'esbuild'; const root = new URL('../', import.meta.url); const dist = new URL('dist/', root); await rm(dist, { recursive: true, force: true }); await mkdir(new URL('vendor/', dist), { recursive: true }); for (const file of ['index.html', 'styles.css', 'src', 'models']) { await cp(new URL(file, root), new URL(file, dist), { recursive: true }); } const onnx = new URL('node_modules/onnxruntime-web/dist/', root); for (const name of await readdir(onnx)) { if (/^ort-wasm-simd-threaded(?:\.(?:jsep|asyncify|jspi))?\.(?:mjs|wasm)$/.test(name)) { await cp(new URL(name, onnx), new URL(`vendor/${name}`, dist)); } } await build({ entryPoints: ['src/app.js', 'src/worker.js', 'src/runtime.js'], absWorkingDir: root.pathname, outdir: 'dist/src', bundle: true, minify: true, format: 'esm', platform: 'browser', target: ['es2022'], }); const version = createHash('sha256') .update(await readFile(new URL('src/app.js', dist))) .update(await readFile(new URL('src/worker.js', dist))) .digest('hex').slice(0, 12); const html = await readFile(new URL('index.html', dist), 'utf8'); await writeFile(new URL('index.html', dist), html.replace('src="./src/app.js"', `src="./src/app.js?v=${version}"`)); await mkdir(new URL('vendor/licenses/', dist), { recursive: true }); for (const [folder, name] of [ ['@huggingface/transformers', 'transformers'], ['@huggingface/tokenizers', 'tokenizers'], ['@huggingface/jinja', 'jinja'], ]) await cp(new URL(`node_modules/${folder}/LICENSE`, root), new URL(`vendor/licenses/${name}.txt`, dist)); await cp(new URL('third-party/licenses/onnxruntime.txt', root), new URL('vendor/licenses/onnxruntime.txt', dist)); await cp(new URL('THIRD_PARTY_NOTICES.md', root), new URL('vendor/THIRD_PARTY_NOTICES.md', dist)); console.log('Built dist/ with local Transformers.js and WebAssembly assets.');