Browser (WASM)
Dynoxide compiles to WebAssembly and runs in the browser. The same engine that backs the native build runs against wa-sqlite - SQLite compiled to WASM - over a wasm-bindgen bridge, with the database persisted to OPFS, the browser's origin private file system. No server, no install, and nothing leaves the page.
Both backends issue the same SQL - the native and wasm code share one set of query builders - so a query fixed on one is fixed on both.
This is a preview. The wasm build isn't run against the conformance suite that backs the native build, so its correctness rests on its own tests for now. A build made with the wasm-sqlite feature exposes dynoxide::WASM_PREVIEW (true) so you can tell which path you're on.
What works
Create table, put, get, delete, query, and scan, over base tables and both secondary index types (GSI and LSI). Index maintenance is atomic with the base write, same as the native build.
What doesn't, yet
- TTL returns a typed
Unsupportederror - not wired up in the preview yet. - Streams are planned but not wired; the delivery mechanism is still being worked out.
TransactWriteItems, tags, table-setting updates, table stats, and bulk import return a preview "not yet implemented" error.
Build it
npm install then npm run build:wasm produces a self-contained dist/ (use build:wasm:dev to skip wasm-opt for a faster build):
npm install
npm run build:wasm
dist/ is three files, kept separate so the two .wasm cache independently of the JS bundle:
| File | Size | What |
|---|---|---|
dynoxide_bg.wasm |
~550 KB | the engine (release, wasm-opt) |
wa-sqlite.wasm |
~545 KB | SQLite (the synchronous build) |
dynoxide-worker.js |
~120 KB | the bundled Web Worker |
About 1.2 MB total. The .wasm files are immutable and cache well.
Drop it on static hosting
Put dist/ on any origin that's a secure context - HTTPS in production, or localhost for development. OPFS needs a secure context, but no COOP/COEP headers and no cross-origin isolation, so plain static hosting works.
That last part is the interesting bit. SQLite in the browser usually needs cross-origin isolation, because the common trick makes an async storage API look synchronous via SharedArrayBuffer. Dynoxide avoids that by running wa-sqlite's synchronous OPFS VFS inside a Web Worker, where synchronous file handles are available directly.
Run it
Spawn the bundle as a module Worker and drive it over postMessage. The two .wasm files must sit next to dynoxide-worker.js, which is where the build puts them.
The harness under harness/ in the repo is a working example - it loads the same bundled Worker a production consumer would:
npm run build:wasm
python3 -m http.server 8081
# then open http://localhost:8081/harness/
It runs a CRUD round-trip, a GSI write/query/scan, and an error-envelope check against the OPFS-backed database. Because it drives the shipping bundle rather than a parallel build, a green harness means the shipping artefact works.
For the full reference, see the WebAssembly section of the README.