import {build} from 'esbuild'; import {cp, mkdir, readdir, rm, stat} from 'node:fs/promises'; import {join, resolve} from 'node:path'; const root = process.cwd(); const publicRoot = join(root, 'public'); const assetRoot = join(publicRoot, 'tts', 'piper-wasm-v1'); const onnxSource = join(root, 'node_modules', 'onnxruntime-web', 'dist'); const piperSource = join(root, 'node_modules', '@diffusionstudio', 'piper-wasm', 'build'); const piperWasm = join(piperSource, 'piper_phonemize.wasm'); const piperData = join(piperSource, 'piper_phonemize.data'); await rm(assetRoot, {recursive: true, force: true}); await mkdir(join(assetRoot, 'onnx'), {recursive: true}); await mkdir(join(assetRoot, 'piper'), {recursive: true}); const wasmFiles = (await readdir(onnxSource)) .filter(name => name.endsWith('.wasm')); if (wasmFiles.length === 0) throw new Error('ONNX Runtime WebAssembly files are missing'); for (const file of wasmFiles) { await cp(join(onnxSource, file), join(assetRoot, 'onnx', file)); } for (const file of [piperWasm, piperData]) { const fileStat = await stat(file).catch(() => null); if (!fileStat?.isFile() || fileStat.size === 0) throw new Error(`Missing Piper WebAssembly asset: ${file}`); await cp(file, join(assetRoot, 'piper', file.split('/').at(-1))); } await build({ entryPoints: [resolve(root, 'piper-runtime.js')], outfile: join(publicRoot, 'piper-runtime.js'), bundle: true, format: 'iife', platform: 'browser', target: ['es2022'], external: ['fs', 'path'], sourcemap: false, legalComments: 'none', }); await build({ entryPoints: [resolve(root, 'piper-worker.js')], outfile: join(assetRoot, 'piper-worker.js'), bundle: true, format: 'iife', platform: 'browser', target: ['es2022'], external: ['fs', 'path'], sourcemap: false, legalComments: 'none', }); console.log(`Piper browser assets prepared at ${assetRoot}`);