/** * Browser-side shim for `fs` — used only in the Vite browser build. * * sentencepiece-js calls `fs.readFileSync(path)` internally (line 122 of its * dist) to read the .model bytes before writing them into its Emscripten * virtual FS. In the browser there is no real filesystem, so we maintain a * small in-process registry keyed by virtual path strings. * * Usage (in tokenizer.ts browser path): * import { registerBytes } from './sp-fs-shim'; * registerBytes('needle.model', modelBytes); * await spp.load('needle.model'); // sentencepiece-js calls readFileSync('needle.model') → shim */ // Use a globalThis-anchored registry so that even if Vite's CJS/ESM interop // causes two evaluations of this module (once for sentencepiece-js's // `require('fs')` alias, once for tokenizer.ts's `import('./sp-fs-shim')`), // both see the same Map. // eslint-disable-next-line @typescript-eslint/no-explicit-any const _g = globalThis as any; if (!_g.__sp_fs_registry__) { _g.__sp_fs_registry__ = new Map(); } const _registry: Map = _g.__sp_fs_registry__; /** * Register `bytes` under `path` so that `readFileSync(path)` returns them. * Call this before `spp.load(path)`. */ export function registerBytes(path: string, bytes: Uint8Array): void { _registry.set(path, bytes); } /** * Drop-in replacement for `fs.readFileSync(path)` used by sentencepiece-js. * Returns the Uint8Array that was previously registered via `registerBytes`. */ export function readFileSync(path: string): Uint8Array { const bytes = _registry.get(path); if (!bytes) { throw new Error( `sp-fs-shim: no bytes registered for "${path}". ` + 'Call registerBytes(path, bytes) before spp.load(path).', ); } return bytes; } // Default export mirrors the shape that sentencepiece-js sees after // _interopNamespace wraps the CJS `require('fs')` result. export default { readFileSync };