@aztec-labs/sqlite3mc-wasm 6.0.0-nightly.20260829
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/dest/index.js +81 -0
- package/dest/src/index.d.ts +33 -0
- package/dest/src/index.d.ts.map +1 -0
- package/package.json +79 -0
- package/src/index.ts +134 -0
- package/vendor/jswasm/SHA256SUMS +11 -0
- package/vendor/jswasm/sqlite3-opfs-async-proxy.js +792 -0
- package/vendor/jswasm/sqlite3-worker1-bundler-friendly.mjs +35 -0
- package/vendor/jswasm/sqlite3-worker1-promiser-bundler-friendly.mjs +176 -0
- package/vendor/jswasm/sqlite3-worker1-promiser.js +188 -0
- package/vendor/jswasm/sqlite3-worker1-promiser.mjs +176 -0
- package/vendor/jswasm/sqlite3-worker1.js +46 -0
- package/vendor/jswasm/sqlite3-worker1.mjs +35 -0
- package/vendor/jswasm/sqlite3.d.mts +7 -0
- package/vendor/jswasm/sqlite3.js +14500 -0
- package/vendor/jswasm/sqlite3.mjs +14464 -0
- package/vendor/jswasm/sqlite3.wasm +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# @aztec-labs/sqlite3mc-wasm
|
|
2
|
+
|
|
3
|
+
SQLite3 Multiple Ciphers v2.3.5 (based on SQLite 3.53.2) packaged as a WASM
|
|
4
|
+
module.
|
|
5
|
+
|
|
6
|
+
Upstream: https://github.com/utelle/SQLite3MultipleCiphers
|
|
7
|
+
|
|
8
|
+
Cipher schemes enabled: ChaCha20 (PRAGMA cipher = chacha20), SQLCipher v4,
|
|
9
|
+
AES-256, and others. See sqlite3mc upstream docs.
|
|
10
|
+
|
|
11
|
+
Usage: import sqlite3InitModule from @aztec-labs/sqlite3mc-wasm. API is identical
|
|
12
|
+
to @sqlite.org/sqlite-wasm; sqlite3mc is a strict superset.
|
|
13
|
+
|
|
14
|
+
License: sqlite3mc is MIT-licensed.
|
|
15
|
+
|
|
16
|
+
## How vendoring works
|
|
17
|
+
|
|
18
|
+
Upstream WASM/JS artifacts under `vendor/jswasm/` are fetched at build time. The committed state of the directory is:
|
|
19
|
+
|
|
20
|
+
| File | Why |
|
|
21
|
+
|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
|
|
22
|
+
| `.gitignore` | Allowlist that keeps the rest of `vendor/jswasm/` out of git |
|
|
23
|
+
| `SHA256SUMS` | Per-file integrity manifest. Pinned at vendoring time; verified at every build |
|
|
24
|
+
| `sqlite3.d.mts` | Locally-authored TypeScript declaration companion for the upstream `sqlite3.mjs`. Required by TS NodeNext module resolution. |
|
|
25
|
+
|
|
26
|
+
Everything else in `vendor/jswasm/` (the actual `.wasm`, `.mjs`, `.js`) is populated by `scripts/vendor.sh`, which is
|
|
27
|
+
invoked from `yarn-project/bootstrap.sh` before any package compiles. It downloads the upstream release zip, verifies
|
|
28
|
+
its SHA256 against the pinned value, extracts the WASM/JS files, and regenerates `SHA256SUMS`. On CI cache hits the
|
|
29
|
+
files come back via the build cache without re-fetching from upstream.
|
|
30
|
+
|
|
31
|
+
The pinned upstream version lives in `scripts/vendor.pin`:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
MC_VERSION=2.3.5
|
|
35
|
+
SQLITE_VERSION=3.53.2
|
|
36
|
+
SHA256=3d0d5ebe4c54a9a22012410726ecef711e4e3e15ec11dffddf09488c72a10670
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Verification (full chain)
|
|
40
|
+
|
|
41
|
+
Run from this package's root, after `scripts/vendor.sh ensure` has populated `vendor/jswasm/`.
|
|
42
|
+
|
|
43
|
+
### Step 1: zip matches the pinned SHA
|
|
44
|
+
|
|
45
|
+
The build script verifies this automatically. To check by hand:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
source scripts/vendor.pin
|
|
49
|
+
curl -sL "https://github.com/utelle/SQLite3MultipleCiphers/releases/download/v${MC_VERSION}/sqlite3mc-${MC_VERSION}-sqlite-${SQLITE_VERSION}-wasm.zip" \
|
|
50
|
+
| sha256sum
|
|
51
|
+
# Expected: matches $SHA256 from scripts/vendor.pin
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If this fails: upstream re-released the asset, or the artifact was tampered with in transit. Investigate before
|
|
55
|
+
trusting any subsequent check.
|
|
56
|
+
|
|
57
|
+
### Step 2: vendored files match the manifest
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd vendor/jswasm && sha256sum -c SHA256SUMS
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Expected output: every file reports `OK`.
|
|
64
|
+
|
|
65
|
+
If any file reports `FAILED`: the file's bytes differ from what was recorded at vendoring time. Either the file was
|
|
66
|
+
modified post-fetch (via pre-commit hooks, accidental edits, etc.), or `SHA256SUMS` itself was tampered with. Both
|
|
67
|
+
cases need investigation, the build should not be trusted.
|
|
68
|
+
|
|
69
|
+
### Step 3 (optional, stronger): independently re-derive SHA256SUMS from the zip
|
|
70
|
+
|
|
71
|
+
A reviewer who wants to prove `SHA256SUMS` itself wasn't tampered with can regenerate it from the upstream zip:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
source scripts/vendor.pin
|
|
75
|
+
curl -sL "https://github.com/utelle/SQLite3MultipleCiphers/releases/download/v${MC_VERSION}/sqlite3mc-${MC_VERSION}-sqlite-${SQLITE_VERSION}-wasm.zip" -o /tmp/sqlite3mc.zip
|
|
76
|
+
unzip -q /tmp/sqlite3mc.zip -d /tmp/sqlite3mc-check
|
|
77
|
+
|
|
78
|
+
# Compute per-file hashes from the extracted jswasm/
|
|
79
|
+
(cd /tmp/sqlite3mc-check/sqlite3mc-wasm-* && cd jswasm && sha256sum -- * | sort -k2) > /tmp/upstream-sums
|
|
80
|
+
|
|
81
|
+
# Compare against repo's SHA256SUMS, excluding our locally-authored d.mts
|
|
82
|
+
grep -v 'sqlite3\.d\.mts' vendor/jswasm/SHA256SUMS | sort -k2 > /tmp/repo-sums
|
|
83
|
+
diff /tmp/upstream-sums /tmp/repo-sums
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Expected: empty diff. Any output means either upstream files have been modified or `SHA256SUMS` claims different hashes
|
|
87
|
+
than the zip.
|
|
88
|
+
|
|
89
|
+
## Bumping the pinned version
|
|
90
|
+
|
|
91
|
+
1. Edit `scripts/vendor.pin` with the new `MC_VERSION`, `SQLITE_VERSION`, and the SHA256 of the new release zip (find
|
|
92
|
+
it in the upstream release notes or compute it: `curl -sL <url> | sha256sum`).
|
|
93
|
+
2. Run `scripts/vendor.sh` (no args). It fetches the new release, verifies the SHA, replaces `vendor/jswasm/`, and
|
|
94
|
+
regenerates `SHA256SUMS`.
|
|
95
|
+
3. Re-run kv-store tests to confirm compatibility: `yarn workspace @aztec-labs/kv-store test:browser`
|
|
96
|
+
4. Commit `scripts/vendor.pin` and `vendor/jswasm/SHA256SUMS` together.
|
|
97
|
+
|
|
98
|
+
To verify a candidate release before editing the pin file:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
scripts/vendor.sh <mc-version> <sqlite-version> <expected-sha256>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The 3-argument form overrides the pin file but does not modify it.
|
|
105
|
+
|
|
106
|
+
## Why `vendor/` is excluded from prettier
|
|
107
|
+
|
|
108
|
+
The repo's `.prettierignore` includes `sqlite3mc-wasm/vendor/`. Without this, pre-commit hooks would silently reformat
|
|
109
|
+
the upstream `.js` / `.mjs` files between fetch and the next commit (whitespace only, semantically identical, but
|
|
110
|
+
cryptographically different bytes), breaking the verification chain above.
|
|
111
|
+
|
|
112
|
+
If you see prettier formatting drift in this directory, the ignore entry is missing or misconfigured.
|
package/dest/index.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import vendoredInit from '../vendor/jswasm/sqlite3.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* Bundler-visible static reference to the wasm binary. Because the URL argument is a string literal, bundlers detect
|
|
4
|
+
* the expression, emit the wasm as an asset, and rewrite the URL, so the default `locateFile` below resolves to the
|
|
5
|
+
* emitted asset instead of guessing a path relative to the (relocated) output chunk at runtime.
|
|
6
|
+
*/ export const SQLITE3_WASM_URL = new URL('../vendor/jswasm/sqlite3.wasm', import.meta.url);
|
|
7
|
+
/**
|
|
8
|
+
* Initializes the sqlite3mc wasm module.
|
|
9
|
+
*
|
|
10
|
+
* With no options, the wasm is fetched from {@link SQLITE3_WASM_URL}, which bundlers rewrite to their emitted asset,
|
|
11
|
+
* so bundled consumers work by default. Pass `locateFile`, `wasmBinary`, or `instantiateWasm` to override.
|
|
12
|
+
*
|
|
13
|
+
* If loading the wasm fails (unreachable URL, HTTP error, corrupt bytes), the returned promise rejects with the cause.
|
|
14
|
+
* Exception: failures inside a caller-supplied `instantiateWasm` cannot be observed (Emscripten's hook contract has no
|
|
15
|
+
* error channel), so with a custom hook the promise never settles on failure.
|
|
16
|
+
*/ export default function sqlite3InitModule(options = {}) {
|
|
17
|
+
return new Promise((resolve, reject)=>{
|
|
18
|
+
const instantiateWasm = options.instantiateWasm ?? (options.wasmBinary ? wasmBinaryInstantiator(options.wasmBinary, reject) : urlInstantiator(options.locateFile ?? defaultLocateFile, reject));
|
|
19
|
+
const callOptions = {
|
|
20
|
+
...options,
|
|
21
|
+
instantiateWasm
|
|
22
|
+
};
|
|
23
|
+
installInitModuleState(callOptions);
|
|
24
|
+
// The vendored init consumes the installed state synchronously (its pre-js runs before the first await), so
|
|
25
|
+
// interleaved calls cannot observe each other's state. On instantiation failure the vendored promise never
|
|
26
|
+
// settles (the hook has no error channel), so the instantiators report failure through `reject` instead.
|
|
27
|
+
vendoredInit(callOptions).then(resolve, reject);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/** Builds an Emscripten `instantiateWasm` hook that instantiates the given bytes instead of fetching by URL. */ function wasmBinaryInstantiator(wasmBinary, onFailure) {
|
|
31
|
+
return (imports, onSuccess)=>{
|
|
32
|
+
void WebAssembly.instantiate(wasmBinary, imports).then(({ instance, module })=>onSuccess(instance, module), (error)=>onFailure(instantiationError('wasmBinary', error)));
|
|
33
|
+
return {};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Builds an Emscripten `instantiateWasm` hook that fetches and instantiates the wasm from the located URL, replacing
|
|
38
|
+
* the vendored fallback (which reports failures nowhere). Prefers streaming compilation, falling back to
|
|
39
|
+
* buffer-based instantiation when streaming is unavailable or fails (e.g. a server responding without the
|
|
40
|
+
* `application/wasm` MIME type, which `instantiateStreaming` rejects).
|
|
41
|
+
*/ function urlInstantiator(locate, onFailure) {
|
|
42
|
+
return (imports, onSuccess)=>{
|
|
43
|
+
const url = locate('sqlite3.wasm', '');
|
|
44
|
+
const streaming = WebAssembly.instantiateStreaming ? WebAssembly.instantiateStreaming(fetch(url, {
|
|
45
|
+
credentials: 'same-origin'
|
|
46
|
+
}), imports).catch(()=>fetchAndInstantiate(url, imports)) : fetchAndInstantiate(url, imports);
|
|
47
|
+
void streaming.then(({ instance, module })=>onSuccess(instance, module), (error)=>onFailure(instantiationError(url, error)));
|
|
48
|
+
return {};
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Fetches the wasm and instantiates it from a buffer, surfacing HTTP errors that streaming instantiation obscures. */ async function fetchAndInstantiate(url, imports) {
|
|
52
|
+
const response = await fetch(url, {
|
|
53
|
+
credentials: 'same-origin'
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`.trimEnd());
|
|
57
|
+
}
|
|
58
|
+
return WebAssembly.instantiate(await response.arrayBuffer(), imports);
|
|
59
|
+
}
|
|
60
|
+
function instantiationError(source, cause) {
|
|
61
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
62
|
+
return new Error(`sqlite3 wasm instantiation failed (${source}): ${detail}`, {
|
|
63
|
+
cause
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Installs the global state object the vendored module's pre-js binds its `Module.locateFile` and
|
|
68
|
+
* `Module.instantiateWasm` wrappers to.
|
|
69
|
+
*/ function installInitModuleState(options) {
|
|
70
|
+
const urlParams = globalThis.location?.href ? new URL(globalThis.location.href).searchParams : new URLSearchParams();
|
|
71
|
+
const debugModule = urlParams.has('sqlite3.debugModule') ? (...args)=>console.warn('sqlite3.debugModule:', ...args) : ()=>{};
|
|
72
|
+
globalThis.sqlite3InitModuleState = Object.assign(Object.create(null), {
|
|
73
|
+
debugModule,
|
|
74
|
+
wasmFilename: 'sqlite3.wasm',
|
|
75
|
+
emscriptenLocateFile: options.locateFile ?? defaultLocateFile,
|
|
76
|
+
emscriptenInstantiateWasm: options.instantiateWasm
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** Resolves the wasm to {@link SQLITE3_WASM_URL} so bundled consumers load the bundler-emitted asset by default. */ function defaultLocateFile(path, prefix) {
|
|
80
|
+
return path === 'sqlite3.wasm' ? SQLITE3_WASM_URL.href : new URL(path, prefix || import.meta.url).href;
|
|
81
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Sqlite3Static } from '@sqlite.org/sqlite-wasm';
|
|
2
|
+
export type { Database, SAHPoolUtil, Sqlite3Static } from '@sqlite.org/sqlite-wasm';
|
|
3
|
+
/**
|
|
4
|
+
* Bundler-visible static reference to the wasm binary. Because the URL argument is a string literal, bundlers detect
|
|
5
|
+
* the expression, emit the wasm as an asset, and rewrite the URL, so the default `locateFile` below resolves to the
|
|
6
|
+
* emitted asset instead of guessing a path relative to the (relocated) output chunk at runtime.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SQLITE3_WASM_URL: URL;
|
|
9
|
+
/**
|
|
10
|
+
* Emscripten module-loader options honored by {@link sqlite3InitModule}. Any further options are passed through to the
|
|
11
|
+
* vendored module unchanged.
|
|
12
|
+
*/
|
|
13
|
+
export interface Sqlite3InitOptions {
|
|
14
|
+
/** Resolves the URL from which a runtime asset (in practice always `sqlite3.wasm`) is fetched. */
|
|
15
|
+
locateFile?: (path: string, prefix: string) => string;
|
|
16
|
+
/** Pre-fetched wasm bytes. When set, the wasm is instantiated directly and never fetched by URL. */
|
|
17
|
+
wasmBinary?: BufferSource;
|
|
18
|
+
/** Custom wasm instantiation hook (standard Emscripten contract). Takes precedence over `wasmBinary`. */
|
|
19
|
+
instantiateWasm?: (imports: WebAssembly.Imports, onSuccess: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => object;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Initializes the sqlite3mc wasm module.
|
|
24
|
+
*
|
|
25
|
+
* With no options, the wasm is fetched from {@link SQLITE3_WASM_URL}, which bundlers rewrite to their emitted asset,
|
|
26
|
+
* so bundled consumers work by default. Pass `locateFile`, `wasmBinary`, or `instantiateWasm` to override.
|
|
27
|
+
*
|
|
28
|
+
* If loading the wasm fails (unreachable URL, HTTP error, corrupt bytes), the returned promise rejects with the cause.
|
|
29
|
+
* Exception: failures inside a caller-supplied `instantiateWasm` cannot be observed (Emscripten's hook contract has no
|
|
30
|
+
* error channel), so with a custom hook the promise never settles on failure.
|
|
31
|
+
*/
|
|
32
|
+
export default function sqlite3InitModule(options?: Sqlite3InitOptions): Promise<Sqlite3Static>;
|
|
33
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUk3RCxZQUFZLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVwRjs7OztHQUlHO0FBQ0gsZUFBTyxNQUFNLGdCQUFnQixLQUE0RCxDQUFDO0FBRTFGOzs7R0FHRztBQUNILE1BQU0sV0FBVyxrQkFBa0I7SUFDakMsa0dBQWtHO0lBQ2xHLFVBQVUsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxLQUFLLE1BQU0sQ0FBQztJQUN0RCxvR0FBb0c7SUFDcEcsVUFBVSxDQUFDLEVBQUUsWUFBWSxDQUFDO0lBQzFCLHlHQUF5RztJQUN6RyxlQUFlLENBQUMsRUFBRSxDQUNoQixPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU8sRUFDNUIsU0FBUyxFQUFFLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNLEtBQUssSUFBSSxLQUM1RSxNQUFNLENBQUM7SUFDWixDQUFDLEdBQUcsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDO0NBQ3hCO0FBRUQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sVUFBVSxpQkFBaUIsQ0FBQyxPQUFPLEdBQUUsa0JBQXVCLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQWNsRyJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAI7D,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAEpF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,KAA4D,CAAC;AAE1F;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,kGAAkG;IAClG,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,oGAAoG;IACpG,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,yGAAyG;IACzG,eAAe,CAAC,EAAE,CAChB,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,SAAS,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,KAAK,IAAI,KAC5E,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,aAAa,CAAC,CAclG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aztec-labs/sqlite3mc-wasm",
|
|
3
|
+
"version": "6.0.0-nightly.20260829",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dest/src/index.d.ts",
|
|
8
|
+
"import": "./dest/index.js"
|
|
9
|
+
},
|
|
10
|
+
"./vendor/jswasm/sqlite3.wasm": "./vendor/jswasm/sqlite3.wasm",
|
|
11
|
+
"./vendor/jswasm/sqlite3-opfs-async-proxy.js": "./vendor/jswasm/sqlite3-opfs-async-proxy.js"
|
|
12
|
+
},
|
|
13
|
+
"inherits": [
|
|
14
|
+
"../package.common.json",
|
|
15
|
+
"./package.local.json"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "yarn clean && ../scripts/tsc.sh",
|
|
19
|
+
"clean": "rm -rf ./dest .tsbuildinfo",
|
|
20
|
+
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
|
|
21
|
+
"build:dev": "../scripts/tsc.sh --watch",
|
|
22
|
+
"prepublishOnly": "./scripts/verify-pack.sh"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@jest/globals": "^30.0.0",
|
|
26
|
+
"@sqlite.org/sqlite-wasm": "3.50.4-build1",
|
|
27
|
+
"@typescript/native-preview": "7.0.0-dev.20260113.1",
|
|
28
|
+
"jest": "^30.0.0",
|
|
29
|
+
"ts-node": "^10.9.1",
|
|
30
|
+
"typescript": "^5.3.3"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"src",
|
|
34
|
+
"vendor",
|
|
35
|
+
"dest",
|
|
36
|
+
"!*.test.*"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.10"
|
|
40
|
+
},
|
|
41
|
+
"jest": {
|
|
42
|
+
"extensionsToTreatAsEsm": [
|
|
43
|
+
".ts"
|
|
44
|
+
],
|
|
45
|
+
"transform": {
|
|
46
|
+
"^.+\\.tsx?$": [
|
|
47
|
+
"@swc/jest",
|
|
48
|
+
{
|
|
49
|
+
"jsc": {
|
|
50
|
+
"parser": {
|
|
51
|
+
"syntax": "typescript",
|
|
52
|
+
"decorators": true
|
|
53
|
+
},
|
|
54
|
+
"transform": {
|
|
55
|
+
"decoratorVersion": "2022-03"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"moduleNameMapper": {
|
|
62
|
+
"^\\.\\./vendor/jswasm/(.*)$": "<rootDir>/../vendor/jswasm/$1",
|
|
63
|
+
"^(\\.{1,2}/.*)\\.[cm]?js$": "$1"
|
|
64
|
+
},
|
|
65
|
+
"reporters": [
|
|
66
|
+
"default"
|
|
67
|
+
],
|
|
68
|
+
"testTimeout": 120000,
|
|
69
|
+
"testRegex": "./src/.*\\.test\\.(js|mjs|ts)$",
|
|
70
|
+
"rootDir": "./src",
|
|
71
|
+
"setupFiles": [
|
|
72
|
+
"../../foundation/src/jest/setup.mjs"
|
|
73
|
+
],
|
|
74
|
+
"setupFilesAfterEnv": [
|
|
75
|
+
"../../foundation/src/jest/setupAfterEnv.mjs"
|
|
76
|
+
],
|
|
77
|
+
"testEnvironment": "../../foundation/src/jest/env.mjs"
|
|
78
|
+
}
|
|
79
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { Sqlite3Static } from '@sqlite.org/sqlite-wasm';
|
|
2
|
+
|
|
3
|
+
import vendoredInit from '../vendor/jswasm/sqlite3.mjs';
|
|
4
|
+
|
|
5
|
+
export type { Database, SAHPoolUtil, Sqlite3Static } from '@sqlite.org/sqlite-wasm';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Bundler-visible static reference to the wasm binary. Because the URL argument is a string literal, bundlers detect
|
|
9
|
+
* the expression, emit the wasm as an asset, and rewrite the URL, so the default `locateFile` below resolves to the
|
|
10
|
+
* emitted asset instead of guessing a path relative to the (relocated) output chunk at runtime.
|
|
11
|
+
*/
|
|
12
|
+
export const SQLITE3_WASM_URL = new URL('../vendor/jswasm/sqlite3.wasm', import.meta.url);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Emscripten module-loader options honored by {@link sqlite3InitModule}. Any further options are passed through to the
|
|
16
|
+
* vendored module unchanged.
|
|
17
|
+
*/
|
|
18
|
+
export interface Sqlite3InitOptions {
|
|
19
|
+
/** Resolves the URL from which a runtime asset (in practice always `sqlite3.wasm`) is fetched. */
|
|
20
|
+
locateFile?: (path: string, prefix: string) => string;
|
|
21
|
+
/** Pre-fetched wasm bytes. When set, the wasm is instantiated directly and never fetched by URL. */
|
|
22
|
+
wasmBinary?: BufferSource;
|
|
23
|
+
/** Custom wasm instantiation hook (standard Emscripten contract). Takes precedence over `wasmBinary`. */
|
|
24
|
+
instantiateWasm?: (
|
|
25
|
+
imports: WebAssembly.Imports,
|
|
26
|
+
onSuccess: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void,
|
|
27
|
+
) => object;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Initializes the sqlite3mc wasm module.
|
|
33
|
+
*
|
|
34
|
+
* With no options, the wasm is fetched from {@link SQLITE3_WASM_URL}, which bundlers rewrite to their emitted asset,
|
|
35
|
+
* so bundled consumers work by default. Pass `locateFile`, `wasmBinary`, or `instantiateWasm` to override.
|
|
36
|
+
*
|
|
37
|
+
* If loading the wasm fails (unreachable URL, HTTP error, corrupt bytes), the returned promise rejects with the cause.
|
|
38
|
+
* Exception: failures inside a caller-supplied `instantiateWasm` cannot be observed (Emscripten's hook contract has no
|
|
39
|
+
* error channel), so with a custom hook the promise never settles on failure.
|
|
40
|
+
*/
|
|
41
|
+
export default function sqlite3InitModule(options: Sqlite3InitOptions = {}): Promise<Sqlite3Static> {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const instantiateWasm =
|
|
44
|
+
options.instantiateWasm ??
|
|
45
|
+
(options.wasmBinary
|
|
46
|
+
? wasmBinaryInstantiator(options.wasmBinary, reject)
|
|
47
|
+
: urlInstantiator(options.locateFile ?? defaultLocateFile, reject));
|
|
48
|
+
const callOptions = { ...options, instantiateWasm };
|
|
49
|
+
installInitModuleState(callOptions);
|
|
50
|
+
// The vendored init consumes the installed state synchronously (its pre-js runs before the first await), so
|
|
51
|
+
// interleaved calls cannot observe each other's state. On instantiation failure the vendored promise never
|
|
52
|
+
// settles (the hook has no error channel), so the instantiators report failure through `reject` instead.
|
|
53
|
+
vendoredInit(callOptions).then(resolve, reject);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Builds an Emscripten `instantiateWasm` hook that instantiates the given bytes instead of fetching by URL. */
|
|
58
|
+
function wasmBinaryInstantiator(
|
|
59
|
+
wasmBinary: BufferSource,
|
|
60
|
+
onFailure: (error: Error) => void,
|
|
61
|
+
): Required<Sqlite3InitOptions>['instantiateWasm'] {
|
|
62
|
+
return (imports, onSuccess) => {
|
|
63
|
+
void WebAssembly.instantiate(wasmBinary, imports).then(
|
|
64
|
+
({ instance, module }) => onSuccess(instance, module),
|
|
65
|
+
error => onFailure(instantiationError('wasmBinary', error)),
|
|
66
|
+
);
|
|
67
|
+
return {};
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Builds an Emscripten `instantiateWasm` hook that fetches and instantiates the wasm from the located URL, replacing
|
|
73
|
+
* the vendored fallback (which reports failures nowhere). Prefers streaming compilation, falling back to
|
|
74
|
+
* buffer-based instantiation when streaming is unavailable or fails (e.g. a server responding without the
|
|
75
|
+
* `application/wasm` MIME type, which `instantiateStreaming` rejects).
|
|
76
|
+
*/
|
|
77
|
+
function urlInstantiator(
|
|
78
|
+
locate: (path: string, prefix: string) => string,
|
|
79
|
+
onFailure: (error: Error) => void,
|
|
80
|
+
): Required<Sqlite3InitOptions>['instantiateWasm'] {
|
|
81
|
+
return (imports, onSuccess) => {
|
|
82
|
+
const url = locate('sqlite3.wasm', '');
|
|
83
|
+
const streaming = WebAssembly.instantiateStreaming
|
|
84
|
+
? WebAssembly.instantiateStreaming(fetch(url, { credentials: 'same-origin' }), imports).catch(() =>
|
|
85
|
+
fetchAndInstantiate(url, imports),
|
|
86
|
+
)
|
|
87
|
+
: fetchAndInstantiate(url, imports);
|
|
88
|
+
void streaming.then(
|
|
89
|
+
({ instance, module }) => onSuccess(instance, module),
|
|
90
|
+
error => onFailure(instantiationError(url, error)),
|
|
91
|
+
);
|
|
92
|
+
return {};
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Fetches the wasm and instantiates it from a buffer, surfacing HTTP errors that streaming instantiation obscures. */
|
|
97
|
+
async function fetchAndInstantiate(
|
|
98
|
+
url: string,
|
|
99
|
+
imports: WebAssembly.Imports,
|
|
100
|
+
): Promise<WebAssembly.WebAssemblyInstantiatedSource> {
|
|
101
|
+
const response = await fetch(url, { credentials: 'same-origin' });
|
|
102
|
+
if (!response.ok) {
|
|
103
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`.trimEnd());
|
|
104
|
+
}
|
|
105
|
+
return WebAssembly.instantiate(await response.arrayBuffer(), imports);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function instantiationError(source: string, cause: unknown): Error {
|
|
109
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
110
|
+
return new Error(`sqlite3 wasm instantiation failed (${source}): ${detail}`, { cause });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Installs the global state object the vendored module's pre-js binds its `Module.locateFile` and
|
|
115
|
+
* `Module.instantiateWasm` wrappers to.
|
|
116
|
+
*/
|
|
117
|
+
function installInitModuleState(options: Sqlite3InitOptions): void {
|
|
118
|
+
const urlParams = globalThis.location?.href ? new URL(globalThis.location.href).searchParams : new URLSearchParams();
|
|
119
|
+
const debugModule = urlParams.has('sqlite3.debugModule')
|
|
120
|
+
? // eslint-disable-next-line no-console -- mirrors the vendored module's own console-based debug channel
|
|
121
|
+
(...args: unknown[]) => console.warn('sqlite3.debugModule:', ...args)
|
|
122
|
+
: () => {};
|
|
123
|
+
(globalThis as { sqlite3InitModuleState?: object }).sqlite3InitModuleState = Object.assign(Object.create(null), {
|
|
124
|
+
debugModule,
|
|
125
|
+
wasmFilename: 'sqlite3.wasm',
|
|
126
|
+
emscriptenLocateFile: options.locateFile ?? defaultLocateFile,
|
|
127
|
+
emscriptenInstantiateWasm: options.instantiateWasm,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Resolves the wasm to {@link SQLITE3_WASM_URL} so bundled consumers load the bundler-emitted asset by default. */
|
|
132
|
+
function defaultLocateFile(path: string, prefix: string): string {
|
|
133
|
+
return path === 'sqlite3.wasm' ? SQLITE3_WASM_URL.href : new URL(path, prefix || import.meta.url).href;
|
|
134
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
4ea2bcbd715b0d56089fc871ea241f8c5985d8669d1ddecaab4d56a8da806ce9 sqlite3-opfs-async-proxy.js
|
|
2
|
+
c043fcfadc1ded8e248ef032a27b6fcda4d66f9eee4b2a27acba02b85d17764f sqlite3-worker1-bundler-friendly.mjs
|
|
3
|
+
349fc2eb7eb4fbe8b6a14779b5144f7506d3b0e14bf6385062a11013cb63d5fe sqlite3-worker1-promiser-bundler-friendly.mjs
|
|
4
|
+
552fd74e051da915335eedfed5eb5c025103ad52dd3535e406ee0aabe8b43a57 sqlite3-worker1-promiser.js
|
|
5
|
+
4a73a2d1c105190ac8eb58572d5a4280f04baba0bae28d8e7a8fc33d9d23750b sqlite3-worker1-promiser.mjs
|
|
6
|
+
1bed25837f00f7b68943cfcabed62dfd202cae863a72af24a0d6487d7d7b0e61 sqlite3-worker1.js
|
|
7
|
+
aeeb5f492b283a00fe275bd667711031c72b5acc45b06483b527d62f6f9cc28b sqlite3-worker1.mjs
|
|
8
|
+
ed52a9f3ae2f29865ec5ba502302ef3df2ff70cb4a427733c721f2dda0a5effb sqlite3.d.mts
|
|
9
|
+
df462b605bf855e3415aace4e5db413fcde2234a7bf80a388b641405bdd45668 sqlite3.js
|
|
10
|
+
802291c5578f935da7138689fc73deddd1a0880c7082595d7498eeaa5f8126c3 sqlite3.mjs
|
|
11
|
+
e7600bc6d59b1459362c8c2d4686f733e26d58041b3cdc599929661ecfeb21ae sqlite3.wasm
|