fsqlite-wasm
fsqlite-wasm is the Rust crate that produces FrankenSQLite's browser-facing
WebAssembly package.
The intended npm artifact is published as @frankensqlite/core and exposes the
generated wasm-bindgen glue plus the FrankenDB API implemented in
src/lib.rs. Builds that enable the prepared-statements
feature also export FrankenPreparedStatement.
Package Build
Build the primary browser ES module package into target/fsqlite-wasm-pkg/:
Choose a different output directory or wasm-pack target:
FSQLITE_WASM_TARGET=bundler
FSQLITE_WASM_TARGET=nodejs
The helper script:
- runs
wasm-pack build - uses the workspace size-optimized
releaseprofile (opt-level = "z", LTO, one codegen unit, stripped symbols, aborting panics) - runs
wasm-optexplicitly after wasm-bindgen output, with Rust's bulk-memory and nontrapping-float feature flags enabled, then keeps the optimized output only when it is no larger after gzip, without leaving a rejected optimizer side artifact in the package directory - normalizes the generated
package.jsonto the@frankensqlite/corepackage name - copies README/license files into the output package
- validates the generated
.wasm,.js, and.d.tsartifacts exist - can build a minimum-feature core package with
FSQLITE_WASM_NO_DEFAULT_FEATURES=1 - can opt into SQLite image import/export bindings with
FSQLITE_WASM_FEATURES=backup - can opt into multi-statement batch execution with
FSQLITE_WASM_FEATURES=batch-execution - can opt into JavaScript
Dateparameter coercion withFSQLITE_WASM_FEATURES=date-params - can opt into JavaScript convenience APIs with
FSQLITE_WASM_FEATURES=api-extras - can opt into browser memory-policy constructors and parser glue with
FSQLITE_WASM_FEATURES=memory-options - can opt into the reusable prepared-statement wrapper with
FSQLITE_WASM_FEATURES=prepared-statements - can enable opt-in diagnostics such as
FSQLITE_WASM_FEATURES=diagnostics,tracing,panic-hook - can make optimizer availability explicit with
FSQLITE_WASM_WASM_OPT(required,auto, ordisabled) - can postprocess an existing wasm-bindgen output directory without invoking
wasm-packor cargo by settingFSQLITE_WASM_PACKAGE_ONLY=1 - can refuse local
wasm-packexecution withFSQLITE_WASM_FORBID_LOCAL_BUILD=1, which is useful for agent runs where cargo-shaped work must happen throughrch - strips caller-location file/line/column detail from release/profiling builds
by default with
-Zlocation-detail=none - emits
twiggy-top.txtbefore enforcing the gzip budget whentwiggyis available, or requires it withFSQLITE_WASM_TWIGGY=required, so over-budget failures retain a size-attribution artifact - writes
frankensqlite_wasm_bg.wasm.gzand enforces the 800 KB core gzip budget by default (FSQLITE_WASM_MAX_GZIP_BYTES=0disables the guard) - writes
size-report.jsonwith the raw wasm bytes, gzipped wasm bytes, wasm-opt retention decision, size budgets, and final npm tarball bytes - runs
npm packso the result is ready for registry or local install testing - enforces a packed tarball size budget of 2 MiB by default (
FSQLITE_WASM_MAX_PACKED_BYTES=0disables the guard)
The default crate feature set is intentionally empty so the core browser
package does not carry crash-reporting or diagnostics glue. Minimum-core release
wasm builds compile tracing at error level only and strip caller-location
detail to keep metadata out of the core download. The default browser package
leaves FrankenSQLite-specific observability PRAGMAs and browser-facing
introspection exports out of the core transfer. Enable the diagnostics feature
when a build needs parseSql(), db.path, db.explain(),
prepared-statement explain(), prepared-statement metadata getters (stmt.sql,
stmt.columnCount, stmt.columnNames()), db.memoryStats(),
PRAGMA fsqlite.jit_stats,
PRAGMA fsqlite.cache_stats, PRAGMA fsqlite.txn_stats, lineage, SSI,
JavaScript NaN coercion warnings, or diagnostic error recovery fields such as
transient, userRecoverable, and suggestion, query-result changes
placeholders, richer JavaScript value-type descriptions in error messages, or
other debug/advisor surfaces. Diagnostics builds that also enable
memory-options retain the expanded out-of-memory advisory text with memory
knob names; the default core package uses a compact out-of-memory message.
Default JavaScript errors still include code, sqliteCode, extendedCode,
and message; default parameterized execution stays available through
executeWithParams() and queryWithParams(). Enable the batch-execution
feature when a package needs FrankenDB.executeBatch() for multi-statement SQL
strings. Enable the api-extras feature when a package needs the duplicate
static constructor FrankenDB.open() or the generic db.pragma() helper. Enable
the date-params feature when a package needs JavaScript Date parameters to
coerce to ISO 8601 SQLite TEXT; the minimum core accepts explicit string
timestamps and omits Date-specific glue. Enable
the memory-options feature when a package needs
FrankenDB.openWithOptions(), memory sizing options, or the option parser.
Enable backup,memory-options together when a package needs
FrankenDB.importWithOptions(). Enable the prepared-statements feature when a
package needs db.prepare() and the FrankenPreparedStatement wrapper with
reusable execute() / query() methods. The tracing feature is also opt-in
because it restores warning-level tracing and pulls in extra browser logging
glue. The panic-hook feature is available for browser crash reports when a
larger diagnostic package is acceptable:
FSQLITE_WASM_FEATURES=diagnostics,tracing,panic-hook
The backup feature is separate from diagnostics. Enable it when the browser
package needs FrankenDB.import() or db.export() for SQLite image
round-trips. FrankenDB.importWithOptions() additionally requires
memory-options. The minimum core package omits those backup bindings and keeps
the common in-memory constructor/execute/query surface.
The batch-execution feature is separate from diagnostics. Enable it when the
package needs FrankenDB.executeBatch() for semicolon-delimited multi-statement
scripts. The minimum core package keeps one-shot execute() and
executeWithParams() available and omits the batch wrapper.
The api-extras feature is separate from diagnostics. Enable it when the
package needs convenience wrappers such as FrankenDB.open() or db.pragma().
The minimum core package keeps the constructor plus execute() / query() and
omits those duplicate helper exports.
The date-params feature is separate from diagnostics. Enable it when browser
callers want to pass JavaScript Date values directly to parameterized SQL.
The minimum core package keeps string timestamps as the explicit date/time input
shape and omits Date instanceof / toISOString() glue.
The prepared-statements feature is separate from diagnostics. Enable it when
the package needs FrankenDB.prepare() and the exported
FrankenPreparedStatement class. The minimum core package omits that wrapper
and keeps parameterized one-shot SQL available through executeWithParams() and
queryWithParams().
The row-arrays feature restores positional result.rowArrays for consumers
that need array-indexed rows in addition to the default labeled result.rows
objects. The minimum core package omits rowArrays to avoid carrying duplicate
row materialization glue.
Size Budgets
All release packages must emit the raw .wasm, a gzipped .wasm.gz, and a
Twiggy top report in CI. The helper also writes size-report.json so CI and
manual runs preserve the exact wasm-opt decision, raw/gzip bytes, active
budgets, Twiggy report path, and packed archive size next to the package
artifacts. Twiggy runs before the gzip-budget failure path, so an over-budget
core package can still be diagnosed from the same output directory. The core
package budget is enforced against the gzipped WebAssembly artifact because that
is the browser transfer shape.
| Feature combo | Build command | Gzip budget |
|---|---|---|
| Minimum core | FSQLITE_WASM_NO_DEFAULT_FEATURES=1 FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
800000 bytes |
| Default core | FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
800000 bytes |
| Batch execution | FSQLITE_WASM_FEATURES=batch-execution FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
800000 bytes unless the release owner intentionally raises FSQLITE_WASM_MAX_GZIP_BYTES |
| Date parameters | FSQLITE_WASM_FEATURES=date-params FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
800000 bytes unless the release owner intentionally raises FSQLITE_WASM_MAX_GZIP_BYTES |
| API extras | FSQLITE_WASM_FEATURES=api-extras FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
800000 bytes unless the release owner intentionally raises FSQLITE_WASM_MAX_GZIP_BYTES |
| Memory options | FSQLITE_WASM_FEATURES=memory-options FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
800000 bytes unless the release owner intentionally raises FSQLITE_WASM_MAX_GZIP_BYTES |
| Diagnostics | FSQLITE_WASM_FEATURES=diagnostics,tracing FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
800000 bytes unless the release owner intentionally raises FSQLITE_WASM_MAX_GZIP_BYTES |
| Extension bundle | FSQLITE_WASM_FEATURES=extensions FSQLITE_WASM_TWIGGY=required ./scripts/build_fsqlite_wasm_package.sh |
report-only until each extension has its own tracked budget; set FSQLITE_WASM_MAX_GZIP_BYTES=0 for exploratory measurement |
Manual measurement should use the package helper so the post-bindgen wasm-opt
flags and gzip-based artifact selection match CI:
FSQLITE_WASM_TWIGGY=required
When a remote rch build or CI job has already produced a wasm-bindgen package
directory, agents can run the package checks without re-entering cargo:
FSQLITE_WASM_FORBID_LOCAL_BUILD=1 \
FSQLITE_WASM_PACKAGE_ONLY=1 \
FSQLITE_WASM_WASM_OPT=disabled \
FSQLITE_WASM_TWIGGY=disabled \
FSQLITE_WASM_MAX_GZIP_BYTES=0 \
Package-only mode refuses settings that affect the earlier cargo or wasm-pack
build, not postprocessing: FSQLITE_WASM_TARGET, FSQLITE_WASM_MODE,
FSQLITE_WASM_SCOPE, FSQLITE_WASM_PROFILE,
FSQLITE_WASM_STRIP_LOCATION_DETAIL, FSQLITE_WASM_FEATURES, and
FSQLITE_WASM_NO_DEFAULT_FEATURES. Build the desired target/profile/feature set
first, then point the helper at that output directory. Because package-only mode
cannot know which Rust flags produced the prebuilt .wasm, size-report.json
sets stripLocationDetail to null for package-only runs.
Expected Package Contents
frankensqlite_wasm_bg.wasmfrankensqlite_wasm.jsfrankensqlite_wasm.d.tssnippets/README.mdLICENSE
Import Example
import init, { FrankenDB } from "@frankensqlite/core";
await init();
const db = new FrankenDB(":memory:");
db.execute("CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT)");
db.execute("INSERT INTO users(name) VALUES('Ada')");
const result = db.query("SELECT id, name FROM users ORDER BY id");
console.log(result.rows);
WASM Memory Management
FrankenSQLite's WASM package runs inside the browser's WebAssembly linear
memory, so the hard upper bound remains 4 GiB for the whole module. The
database-specific knobs exposed by the memory-options feature let you budget
FrankenSQLite's own heap usage inside that ceiling. Enable
FSQLITE_WASM_FEATURES=memory-options for FrankenDB.openWithOptions(), or
FSQLITE_WASM_FEATURES=backup,memory-options for the backup import variant:
const db = FrankenDB.openWithOptions(":memory:", {
pageBufferMax: 256,
memory: {
initialPages: 4,
growthChunkPages: 1,
maxPages: 512,
},
});
pageBufferMaxcaps the pager's page-buffer pool in pages.memory.initialPages,memory.growthChunkPages, andmemory.maxPagesexpress the same policy in WebAssembly pages (64 KiBeach). The byte-level aliasesmemory.initialReserveBytes,memory.growthChunkBytes, andmemory.maxBytesremain available when callers want exact byte counts.memory.maxPages/memory.maxBytesact as a hard cap for trackedMemoryVfsheap usage. When the engine crosses that cap, operations fail with a structured out-of-memory error instead of trapping through anunreachable.- With
FSQLITE_WASM_FEATURES=diagnostics,memory-options,memory.warnAtPercentderives a warning threshold from the tracked max,memory.warningThresholdBytesaccepts exact byte thresholds, andmemory.onWarningfires once with the same byte-level and page-oriented payload asdb.memoryStats(). - Diagnostic builds also expose
db.memoryStats()and emit page-cache pressure advisory fields:pageCachePressureLevel,pageCachePressureBudgetBytes,recommendedPageBufferMaxPages,recommendedPageBufferMaxBytes, andtrackedHeadroomBytes. These let the JS side decide when to ratchetpageBufferMaxdown before the tracked heap reaches its hard cap.
Diagnostic builds can call db.memoryStats() at any point to inspect tracked
heap bytes, page-cache resident bytes, page-cache capacity, growth events,
current linear-memory size/pages (when running under wasm32), and the derived
page-cache pressure recommendation. Configured warning thresholds are reported
when diagnostics,memory-options are enabled together.