import { defineConfig } from 'vite'; import { resolve } from 'node:path'; import { existsSync, mkdirSync, cpSync, readFileSync } from 'node:fs'; // Copy onnxruntime-web's .wasm files into public/ at config-load time so Vite serves them. const ortDist = resolve(__dirname, 'node_modules/onnxruntime-web/dist'); const publicOrt = resolve(__dirname, 'public/ort'); if (existsSync(ortDist) && !existsSync(publicOrt)) { mkdirSync(publicOrt, { recursive: true }); cpSync(ortDist, publicOrt, { recursive: true }); } // In vitest (VITEST env var is set), keep the real `fs` so Node tests can // use fs.readFileSync for the temp-file approach. In the Vite browser build // alias both `fs` and `node:fs` to our thin browser shim. const isTest = Boolean(process.env.VITEST); export default defineConfig({ server: { port: 5173, headers: { // Required for SharedArrayBuffer / multi-threaded WASM (COOP+COEP). // With numThreads=1 these aren't strictly needed, but harmless to set. 'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Embedder-Policy': 'require-corp', }, }, plugins: [ { // Intercept /ort/*.mjs requests and serve them as plain ESM before // Vite's transform middleware can block them (Vite 8 refuses to serve // JS/CSS from /public via the module pipeline, but onnxruntime-web // needs to dynamically import its threading shim from that path). name: 'ort-mjs-passthrough', enforce: 'pre', configureServer(server) { // Use unshift to insert BEFORE Vite's own middleware stack. server.middlewares.stack.unshift({ route: '', handle: (req: any, res: any, next: any) => { const url: string = req.url ?? ''; if (url.startsWith('/ort/') && (url.includes('.mjs') || url.includes('.wasm'))) { const clean = url.split('?')[0]; const filePath = resolve(__dirname, 'public' + clean); if (existsSync(filePath)) { const content = readFileSync(filePath); const mime = clean.endsWith('.mjs') ? 'application/javascript; charset=utf-8' : 'application/wasm'; res.setHeader('Content-Type', mime); res.setHeader('Cache-Control', 'no-cache'); res.end(content); return; } } next(); }, }); }, }, ], test: { environment: 'node' }, resolve: isTest ? {} : { alias: { // sentencepiece-js uses: var fs = require('fs') // Vite will resolve this alias for the browser bundle. fs: resolve(__dirname, 'src/sp-fs-shim.ts'), 'node:fs': resolve(__dirname, 'src/sp-fs-shim.ts'), }, }, });