space-data-module-sdk 0.8.21 → 0.8.23

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.
@@ -0,0 +1,323 @@
1
+ // Controller for one FlatSQL I/O worker (opfsIoWorker.mjs): spawn, init,
2
+ // attach instance memories, pre-open, revoke, and supervise
3
+ // (docs/architecture/flatsql-partition-store.md §5.5, A7, A36, A38, A39).
4
+ //
5
+ // The engine worker owns these controllers: one writer I/O worker per writer,
6
+ // and 1-2 reader I/O workers (A7). Supervision (A36): when the I/O worker
7
+ // errors or exits, the controller completes every pending request with an
8
+ // error status (no guest thread stays blocked, and nothing throws in a guest),
9
+ // reports `onError`, and, with `restart: true`, starts a replacement over the
10
+ // same channel and re-attaches the live instance memories. Handles do not
11
+ // survive: the engine reopens from heads.
12
+ //
13
+ // Worker source: `workerUrl` when given (a module worker, or with
14
+ // `workerType: "classic"` the self-contained bundle from hostWorkerBundles.js
15
+ // spawned from a blob: URL; A39: the dashboard's single-file CSP allows only
16
+ // blob: workers), otherwise the packaged sibling `opfsIoWorker.mjs` (unbundled
17
+ // layouts and Node).
18
+
19
+ import {
20
+ SAB_IO_INSTANCE_REVOKED,
21
+ createSabIoChannelBuffer,
22
+ describeSabIoChannel,
23
+ failPendingSabIoRequests,
24
+ resetSabIoInstance,
25
+ revokeSabIoInstance,
26
+ } from "./sabIoChannel.js";
27
+ import { FLATSQL_IO_ERR_IO } from "./flatsqlIoContract.js";
28
+ import { NODE_BUILTIN_PREFIX } from "./nodeBuiltinSpecifier.js";
29
+
30
+ const IS_NODE =
31
+ typeof process !== "undefined" && !!process.release && process.release.name === "node";
32
+
33
+ export const FLATSQL_IO_WORKER_FILENAME = "opfsIoWorker.mjs";
34
+
35
+ /** Thrown when the I/O worker cannot start (asset missing, OPFS refused, ...). */
36
+ export class FlatsqlIoWorkerStartError extends Error {
37
+ constructor(message, cause) {
38
+ super(message);
39
+ this.name = "FlatsqlIoWorkerStartError";
40
+ if (cause !== undefined) this.cause = cause;
41
+ }
42
+ }
43
+
44
+ async function spawnWorker({ workerUrl, workerType }) {
45
+ if (IS_NODE) {
46
+ const specifier = NODE_BUILTIN_PREFIX + "worker_threads";
47
+ const { Worker } = await import(/* @vite-ignore */ /* webpackIgnore: true */ specifier);
48
+ const url = workerUrl ?? new URL(`./${FLATSQL_IO_WORKER_FILENAME}`, import.meta.url);
49
+ const worker = new Worker(url);
50
+ return {
51
+ raw: worker,
52
+ post: (message, transfer) => worker.postMessage(message, transfer),
53
+ onMessage: (fn) => worker.on("message", fn),
54
+ onError: (fn) => {
55
+ worker.on("error", fn);
56
+ worker.on("exit", (code) => fn(new Error(`I/O worker exited with code ${code}`), true));
57
+ },
58
+ terminate: () => worker.terminate(),
59
+ };
60
+ }
61
+ let worker;
62
+ if (workerUrl) {
63
+ worker =
64
+ workerType === "classic"
65
+ ? new Worker(workerUrl)
66
+ : new Worker(workerUrl, { type: "module" });
67
+ } else {
68
+ let packaged;
69
+ try {
70
+ packaged = new URL(`./${FLATSQL_IO_WORKER_FILENAME}`, import.meta.url);
71
+ } catch (error) {
72
+ throw new FlatsqlIoWorkerStartError(
73
+ "No packaged I/O worker anchor (this source was bundled without import.meta.url): " +
74
+ 'pass workerUrl, e.g. hostWorkerBundleUrl("flatsql-io") with workerType "classic".',
75
+ error,
76
+ );
77
+ }
78
+ worker = new Worker(packaged, { type: "module" });
79
+ }
80
+ return {
81
+ raw: worker,
82
+ post: (message, transfer) => worker.postMessage(message, transfer ?? []),
83
+ onMessage: (fn) => {
84
+ worker.onmessage = (event) => fn(event.data);
85
+ },
86
+ onError: (fn) => {
87
+ worker.onerror = (event) => {
88
+ event?.preventDefault?.();
89
+ fn(new Error(event?.message ?? "I/O worker error"), false);
90
+ };
91
+ worker.onmessageerror = () => fn(new Error("I/O worker message error"), false);
92
+ },
93
+ terminate: () => worker.terminate(),
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Start an I/O worker over a channel.
99
+ *
100
+ * @param {object} [options]
101
+ * @param {SharedArrayBuffer} [options.buffer] the channel; created when absent.
102
+ * @param {object} [options.channel] createSabIoChannelBuffer options when creating.
103
+ * @param {"opfs"|"memory"} [options.backend="opfs"]
104
+ * @param {"writer"|"reader"} [options.role="writer"]
105
+ * @param {number} [options.chunkBytes] write/read step (default 256 KiB).
106
+ * @param {"auto"|"atomics"|"message"} [options.doorbell="auto"]
107
+ * @param {{ buffer: SharedArrayBuffer, suffixes?: string[], write?: boolean }} [options.mirror]
108
+ * @param {string} [options.rootDirectory] OPFS directory every path is confined to.
109
+ * @param {"auto"|"shared"|"exclusive"} [options.handleMode="auto"]
110
+ * @param {number} [options.memoryMaxBytes] memory backend budget.
111
+ * @param {{ pattern: string, ms: number }} [options.openDelay] test hook.
112
+ * @param {{ name: string, ifAvailable?: boolean }} [options.lock] take this Web
113
+ * Lock inside the I/O worker before any handle opens (A37: the store lock
114
+ * `sdn-flatsql-store/<format>/<artifact-sha256>` lives exactly as long as the
115
+ * handles). With `ifAvailable`, start fails with `lockUnavailable: true` when
116
+ * another context holds it; otherwise start waits for it. `stop()` closes the
117
+ * handles, then releases the lock.
118
+ * @param {{ attempts: number, baseMs?: number }} [options.busyRetry] OPFS: retry
119
+ * a sync-handle creation refused by a previous holder, with backoff (A37).
120
+ * @param {string|URL} [options.workerUrl]
121
+ * @param {"module"|"classic"} [options.workerType="module"]
122
+ * @param {(error: Error, info: { restarted: boolean, failedRequests: number }) => void} [options.onError]
123
+ * @param {boolean} [options.restart=false] recreate a dead worker.
124
+ */
125
+ export async function createFlatsqlIoWorker(options = {}) {
126
+ const buffer = options.buffer ?? createSabIoChannelBuffer(options.channel ?? {});
127
+ const layout = describeSabIoChannel(buffer);
128
+ const attached = new Map();
129
+ const pending = new Map();
130
+ let nextRequestId = 1;
131
+ let worker = null;
132
+ let info = null;
133
+ let dead = false;
134
+ let stopping = false;
135
+ let restarts = 0;
136
+
137
+ const initMessage = {
138
+ t: "init",
139
+ buffer,
140
+ backend: options.backend ?? "opfs",
141
+ role: options.role ?? "writer",
142
+ chunkBytes: options.chunkBytes,
143
+ doorbell: options.doorbell ?? "auto",
144
+ mirror: options.mirror ?? null,
145
+ rootDirectory: options.rootDirectory,
146
+ handleMode: options.handleMode,
147
+ memoryMaxBytes: options.memoryMaxBytes,
148
+ openDelay: options.openDelay ?? null,
149
+ lock: options.lock ?? null,
150
+ busyRetry: options.busyRetry ?? null,
151
+ };
152
+
153
+ function request(message) {
154
+ const id = nextRequestId++;
155
+ return new Promise((resolve) => {
156
+ pending.set(id, resolve);
157
+ worker.post({ ...message, id });
158
+ });
159
+ }
160
+
161
+ async function start() {
162
+ const spawned = await spawnWorker(options);
163
+ worker = spawned;
164
+ dead = false;
165
+ let resolveReady;
166
+ const ready = new Promise((resolve) => {
167
+ resolveReady = resolve;
168
+ });
169
+ spawned.onMessage((message) => {
170
+ if (!message || worker !== spawned) return;
171
+ if (message.t === "ready") {
172
+ resolveReady(message);
173
+ return;
174
+ }
175
+ if (message.t === "attached") {
176
+ const resolve = pending.get(`attach:${message.instanceId}`);
177
+ pending.delete(`attach:${message.instanceId}`);
178
+ resolve?.(message.ok);
179
+ return;
180
+ }
181
+ if (message.id !== undefined && pending.has(message.id)) {
182
+ const resolve = pending.get(message.id);
183
+ pending.delete(message.id);
184
+ resolve(message);
185
+ }
186
+ });
187
+ spawned.onError((error, exited) => {
188
+ if (stopping || worker !== spawned) return;
189
+ if (!info) {
190
+ resolveReady({ ok: false, error: String(error?.message ?? error) });
191
+ return;
192
+ }
193
+ handleDeath(error, exited);
194
+ });
195
+ spawned.post(initMessage);
196
+ const result = await ready;
197
+ if (!result.ok) {
198
+ try {
199
+ spawned.terminate();
200
+ } catch {
201
+ // ignore
202
+ }
203
+ const error = new FlatsqlIoWorkerStartError(`I/O worker failed to start: ${result.error}`);
204
+ error.lockUnavailable = result.lockUnavailable === true;
205
+ throw error;
206
+ }
207
+ info = result.info;
208
+ for (const [instanceId, memory] of attached) {
209
+ await attachInternal(instanceId, memory);
210
+ }
211
+ return info;
212
+ }
213
+
214
+ function attachInternal(instanceId, memory) {
215
+ return new Promise((resolve) => {
216
+ pending.set(`attach:${instanceId}`, resolve);
217
+ worker.post({ t: "attach", instanceId, memory });
218
+ });
219
+ }
220
+
221
+ function handleDeath(error) {
222
+ if (dead) return;
223
+ dead = true;
224
+ try {
225
+ worker.terminate();
226
+ } catch {
227
+ // already gone
228
+ }
229
+ const failedRequests = failPendingSabIoRequests(buffer, FLATSQL_IO_ERR_IO);
230
+ for (const resolve of pending.values()) resolve({ ok: false, dead: true });
231
+ pending.clear();
232
+ const restart = options.restart === true;
233
+ try {
234
+ options.onError?.(error, { restarted: restart, failedRequests });
235
+ } catch {
236
+ // the hook never breaks supervision
237
+ }
238
+ if (restart) {
239
+ restarts += 1;
240
+ info = null;
241
+ start().catch((startError) => {
242
+ try {
243
+ options.onError?.(startError, { restarted: false, failedRequests: 0 });
244
+ } catch {
245
+ // ignore
246
+ }
247
+ });
248
+ }
249
+ }
250
+
251
+ await start();
252
+
253
+ return {
254
+ buffer,
255
+ get info() {
256
+ return info;
257
+ },
258
+ get dead() {
259
+ return dead;
260
+ },
261
+ get restarts() {
262
+ return restarts;
263
+ },
264
+ get worker() {
265
+ return worker?.raw ?? null;
266
+ },
267
+ /** Attach an instance's shared memory for direct transfers. */
268
+ async attachMemory(instanceId, memory) {
269
+ if (Atomics.load(layout.instances, instanceId) === SAB_IO_INSTANCE_REVOKED) {
270
+ resetSabIoInstance(buffer, instanceId);
271
+ }
272
+ attached.set(instanceId, memory);
273
+ return attachInternal(instanceId, memory);
274
+ },
275
+ detachMemory(instanceId) {
276
+ attached.delete(instanceId);
277
+ worker.post({ t: "detach", instanceId });
278
+ },
279
+ /**
280
+ * Revoke an instance (A36 step 2): resolves once the I/O worker has closed
281
+ * its handles; later requests from it complete with ACCESS.
282
+ */
283
+ async revoke(instanceId) {
284
+ attached.delete(instanceId);
285
+ await revokeSabIoInstance(buffer, instanceId);
286
+ },
287
+ /** Pre-open paths (A38, §5.5). Resolves to one status per path. */
288
+ async preopen(paths, flags) {
289
+ const reply = await request({ t: "preopen", paths, flags });
290
+ return reply.statuses ?? paths.map(() => FLATSQL_IO_ERR_IO);
291
+ },
292
+ releasePreopen(paths) {
293
+ worker.post({ t: "release-preopen", paths });
294
+ },
295
+ async stats() {
296
+ return request({ t: "stats" });
297
+ },
298
+ /** Drop the memory backend's contents (window store UI-state change). */
299
+ async reset() {
300
+ await request({ t: "reset" });
301
+ },
302
+ /** Remove every file below the OPFS root (tests, store wipe). */
303
+ async clear() {
304
+ return request({ t: "clear" });
305
+ },
306
+ /** Stop the loop and the worker. */
307
+ async stop() {
308
+ stopping = true;
309
+ if (!dead) {
310
+ await request({ t: "stop" });
311
+ }
312
+ try {
313
+ await worker.terminate();
314
+ } catch {
315
+ // ignore
316
+ }
317
+ },
318
+ /** Kill the worker without a clean stop (fault injection, A36 tests). */
319
+ kill() {
320
+ handleDeath(new Error("I/O worker killed"), true);
321
+ },
322
+ };
323
+ }
@@ -0,0 +1,11 @@
1
+ // GENERATED by scripts/build-host-worker-bundles.mjs. Do not edit.
2
+ // Self-contained classic-script worker bundles, spawned from blob: URLs
3
+ // (design A39). Rebuild after changing any file they bundle.
4
+
5
+ /** src/host/wasiThreadBrowserWorker.mjs, sha256 a6904554c3cb075acfd387fa1d867b2605db78f23b0b7ec34dc3a643ffa65549. */
6
+ export const WASI_THREAD_POOL_WORKER_BUNDLE = "(()=>{var ct=new TextDecoder,it=new TextEncoder,J=\"$bin\";function at(e){return e instanceof Uint8Array||e instanceof ArrayBuffer||ArrayBuffer.isView(e)}function ut(e){return e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}function z(e,t){if(e==null)return e??null;if(at(e)){let r=t.length;return t.push(ut(e)),{[J]:r}}return e instanceof Date?e.toISOString():typeof e==\"bigint\"?e.toString():Array.isArray(e)?e.map(r=>z(r,t)):typeof e==\"object\"?Object.fromEntries(Object.entries(e).filter(([,r])=>r!==void 0).map(([r,n])=>[r,z(n,t)])):e}function P(e,t){if(e==null)return e;if(Array.isArray(e))return e.map(r=>P(r,t));if(typeof e==\"object\"){let r=Object.keys(e);if(r.length===1&&r[0]===J){let n=e[J];if(!Number.isInteger(n)||n<0||n>=t.length)throw new RangeError(`Hostcall envelope references missing binary segment ${n}.`);return t[n]}return Object.fromEntries(r.map(n=>[n,P(e[n],t)]))}return e}function ee(e,t=[]){let r=it.encode(JSON.stringify(e??null)),n=4+r.length+4;for(let E of t)n+=4+E.length;let o=new Uint8Array(n),c=new DataView(o.buffer),a=0;c.setUint32(a,r.length,!0),a+=4,o.set(r,a),a+=r.length,c.setUint32(a,t.length,!0),a+=4;for(let E of t)c.setUint32(a,E.length,!0),a+=4,o.set(E,a),a+=E.length;return o}function W(e){if(!(e instanceof Uint8Array))throw new TypeError(\"Hostcall envelope must be a Uint8Array.\");if(e.length<8)throw new RangeError(\"Hostcall envelope is truncated.\");let t=new DataView(e.buffer,e.byteOffset,e.byteLength),r=0,n=t.getUint32(r,!0);if(r+=4,r+n+4>e.length)throw new RangeError(\"Hostcall envelope meta exceeds envelope bounds.\");let o=JSON.parse(ct.decode(e.subarray(r,r+n)));r+=n;let c=t.getUint32(r,!0);r+=4;let a=[];for(let E=0;E<c;E+=1){if(r+4>e.length)throw new RangeError(\"Hostcall envelope segment table is truncated.\");let d=t.getUint32(r,!0);if(r+=4,r+d>e.length)throw new RangeError(\"Hostcall envelope segment exceeds envelope bounds.\");a.push(e.subarray(r,r+d)),r+=d}return{meta:o,segments:a}}function fe(e){let{meta:t,segments:r}=W(e);return P(t,r)}var lt=new TextDecoder,re=\"space_data_module_host\",v=0,te=1,Br=Object.freeze([\"host.runtimeTarget\",\"host.listCapabilities\",\"host.listSupportedCapabilities\",\"host.listOperations\",\"host.hasCapability\",\"clock.now\",\"clock.monotonicNow\",\"clock.nowIso\",\"random.bytes\",\"schedule.parse\",\"schedule.matches\",\"schedule.next\",\"filesystem.resolvePath\"]);function ft(e,t){let r=String(e??\"\").trim();if(!r)throw new TypeError(`${t} is required.`);return r}function Ae(e){if(typeof e!=\"function\")throw new TypeError(\"getMemory must be a function returning WebAssembly.Memory.\");let t=e();if(!t||typeof t!=\"object\"||!(\"buffer\"in t))throw new TypeError(\"getMemory must return a WebAssembly.Memory-like object.\");let r=t.buffer;if(!(r instanceof ArrayBuffer||r instanceof SharedArrayBuffer))throw new TypeError(\"Hostcall memory buffer must be an ArrayBuffer or SharedArrayBuffer.\");return r}function _e(e,t,r,n){if(!Number.isInteger(t)||t<0)throw new RangeError(`${n} pointer must be a non-negative integer.`);if(!Number.isInteger(r)||r<0)throw new RangeError(`${n} length must be a non-negative integer.`);let o=Ae(e);if(t+r>o.byteLength)throw new RangeError(`${n} range exceeds guest memory bounds.`);return new Uint8Array(o,t,r)}function _t(e,t,r,n){if(!Number.isInteger(t)||t<0)throw new RangeError(\"Response pointer must be a non-negative integer.\");if(!Number.isInteger(n)||n<0)throw new RangeError(\"Response max length must be a non-negative integer.\");let o=r instanceof Uint8Array?r:new Uint8Array(r),c=Ae(e),a=Math.min(o.length,n);if(t+a>c.byteLength)throw new RangeError(\"Response range exceeds guest memory bounds.\");return new Uint8Array(c,t,a).set(o.subarray(0,a)),a}function Et(e){if(e.length===0)return null;let{meta:t,segments:r}=W(e);return P(t,r)}function Ee(e,t=null){return{name:e?.name??\"Error\",message:e?.message??String(e),code:e?.code??null,operation:e?.operation??t,capability:e?.capability??null}}function At(e){return e!==null&&typeof e==\"object\"&&typeof e.then==\"function\"}function de(e={}){let t=e.dispatch;if(typeof t!=\"function\")throw new TypeError(\"createHostcallBridge requires a dispatch function.\");let r=e.getMemory,n=ft(e.moduleName??re,\"Hostcall import module name\"),o=Number.isInteger(e.maxRequestBytes)?e.maxRequestBytes:16*1024*1024,c=Number.isInteger(e.maxResponseBytes)?e.maxResponseBytes:64*1024*1024,a=v,E={ok:!0,result:null},d=ee(E,[]);function p(s,i){let u=[],m=z(i,u),S=ee(m,u);if(S.length>c)throw new Error(`Hostcall response exceeds ${c} byte limit.`);a=s,E=i,d=S}function A(s,i,u,m){try{if(m>o)throw new Error(`Hostcall request exceeds ${o} byte limit.`);let S=lt.decode(_e(r,s,i,\"Operation\")),w=Et(_e(r,u,m,\"Payload\")),L=t(S,w);if(At(L))throw new Error(`Operation \"${S}\" returned a Promise. The synchronous hostcall ABI only supports synchronous operations.`);return p(v,{ok:!0,result:L===void 0?null:L}),v}catch(S){try{p(te,{ok:!1,error:Ee(S)})}catch(w){p(te,{ok:!1,error:Ee(w)})}return te}}function T(){return d.length}function f(s,i){return _t(r,s,d,i)}function _(){return p(v,{ok:!0,result:null}),v}function h(){return a}return{moduleName:n,imports:{[n]:{call:A,response_len:T,read_response:f,clear_response:_,last_status_code:h}},getLastEnvelope(){return structuredClone(E)},getLastResponseBytes(){return new Uint8Array(d)},getLastResponseEnvelope(){let{meta:s,segments:i}=W(d);return P(s,i)}}}var Cr=Object.freeze({READ:1,WRITE:2,CREATE:4,EXCL:8,TRUNC:16,DELETE_ON_CLOSE:32,PROBE:64,UNLINK:128,CREATE_PARENTS:256,UNLINK_IF_UNUSED:512,OPEN_DEFERRED:1024}),Nr=Object.freeze({OK:0,GENERIC:-1,NOENT:-2,ACCESS:-3,IO:-4,NOSPACE:-5,BADHANDLE:-6,BUSY:-7});var Dr=Object.freeze([\"flatsql_io_open\",\"flatsql_io_read\",\"flatsql_io_write\",\"flatsql_io_truncate\",\"flatsql_io_sync\",\"flatsql_io_size\",\"flatsql_io_close\"]),j=4096;var Fr=typeof TextDecoder==\"function\"?new TextDecoder(\"utf-8\",{fatal:!0}):null;function Se(e){let t=2166136261;for(let r=0;r<e.length;r+=1)t^=e[r],t=Math.imul(t,16777619);return t>>>0}var dt=1330201683,St=1,pt=0,yt=1,mt=2,ht=3,Rt=4,ye=5;var Ot=7;var It=9,Z=10,Tt=11;var gt=13,ge=64,me=ge*4;var wt=1;var xt=1,Lt=2,Bt=3,k=32767,V=0,we=1,he=2,bt=3,Ct=4,Nt=5,Dt=6,Ft=7,Mt=8,Ht=9,Re=10,xe=11,Ut=12,Pt=13,Qt=8,Le=9,ne=128,oe=0,vt=1,qt=2;var kt=4,Vt=0;var Yt=0,Gt=1,$t=1,q=2,X=3,Kt=4,zt=5,Wt=6,jt=7;var Ur=64*1024;var Oe=250,Xt=20;function Ie(){return typeof performance<\"u\"&&performance.now?performance.now():Date.now()}function Zt(e,t){return Math.ceil(e/t)*t}function Be(e){if(typeof SharedArrayBuffer!=\"function\"||!(e instanceof SharedArrayBuffer))throw new TypeError(\"The SAB I/O channel requires a SharedArrayBuffer (cross-origin isolation in browsers).\")}function Jt(e){Be(e);let t=new Int32Array(e,0,ge);if(t[pt]!==dt||t[yt]!==St)throw new TypeError(\"Not a SAB I/O channel buffer (bad magic or version).\");let r=t[mt],n=t[ht],o=t[Rt],c=t[Tt],a=Zt(me+o*4,64),E=new Int32Array(e,me,o),d=[];for(let p=0;p<r;p+=1){let A=a+p*n;d.push({index:p,base:A,i32:new Int32Array(e,A,ne/4),f64:new Float64Array(e,A,ne/8),data:new Uint8Array(e,A+ne,c)})}return{buffer:e,header:t,instances:E,slots:d,slotCount:r,slotBytes:n,dataBytes:c,maxInstances:o,channelId:t[gt]}}function er(e){return`sdm-sab-io-doorbell-${e}`}function tr(e,t){Atomics.add(e.header,ye,1),Atomics.notify(e.header,ye),Atomics.load(e.header,Ot)===wt&&t()?.postMessage(0)}function rr(e){let t=null;return{get(){return!t&&typeof BroadcastChannel==\"function\"&&(t=new BroadcastChannel(e)),t},close(){t?.close(),t=null}}}var nr=typeof TextEncoder==\"function\"?new TextEncoder:null;function or(){return(Math.random()*2147483646|0)+1}function sr(e,t){let r=(Atomics.add(e.header,It,1)>>>0)%e.slotCount;for(let n=0;n<e.slotCount;n+=1){let o=e.slots[(r+n)%e.slotCount];if(Atomics.compareExchange(o.i32,V,oe,vt)===oe)return Atomics.store(o.i32,we,t),o}return null}function Te(e,t){Atomics.store(t.i32,we,0),Atomics.store(t.i32,V,oe),Atomics.add(e.header,Z,1),Atomics.notify(e.header,Z)}function cr(e,t,r){let n=e.i32;n[Ct]=t,n[Nt]=r.instanceId??k,n[Dt]=r.handle??-1,n[Ft]=r.flags??0,n[Mt]=r.ptr??0,n[Ht]=r.len??0,n[Pt]=r.dataInSlot?Gt:Yt,n[xe]=0,e.f64[Qt]=r.offset??0,e.f64[Le]=0,r.path?(e.data.set(r.path,0),n[Re]=r.path.length):n[Re]=0}function ir(e){return Atomics.load(e.i32,xe)}function be(e={}){Be(e.buffer);let t=Jt(e.buffer),r=Number.isInteger(e.instanceId)?e.instanceId:k;if(r!==k&&(r<0||r>=t.maxInstances))throw new RangeError(`instanceId ${r} is outside 0..${t.maxInstances-1}.`);let n=typeof e.getMemory==\"function\"?e.getMemory:()=>null,o=Number.isFinite(e.spinMicros)?Math.max(0,e.spinMicros):Xt,c=or(),a=rr(er(t.channelId)),E=0;function d(){for(;;){let s=Atomics.load(t.header,Z),i=sr(t,c);if(i)return i;Atomics.wait(t.header,Z,s,Oe)}}function p(s,i,u){let m=Atomics.load(s.i32,he)+1|0||1;cr(s,i,u),Atomics.store(s.i32,Ut,Vt),Atomics.store(s.i32,he,m),Atomics.store(s.i32,V,qt),tr(t,a.get);let S=o>0?Ie()+o/1e3:0;for(;;){let w=Atomics.load(s.i32,V);if(w===kt&&Atomics.load(s.i32,bt)===m)break;S>0&&Ie()<S||Atomics.wait(s.i32,V,w,Oe)}return E+=1,{status:ir(s),result:s.f64[Le]}}function A(s,i){let u=d();try{return p(u,s,i)}finally{Te(t,u)}}function T(){return r!==k&&Atomics.load(t.instances,r)===xt}function f(){if(r===k)return!1;let s=Atomics.load(t.instances,r);return s===Lt||s===Bt}function _(s,i,u,m){let S=0;for(;S<u.length;){let w=Math.min(t.dataBytes,u.length-S),L=d(),b;try{s===X&&L.data.set(u.subarray(S,S+w),0),b=p(L,s,{instanceId:r,dataInSlot:!0,handle:i,ptr:0,len:w,offset:m+S}).status,s===q&&b>0&&u.set(L.data.subarray(0,b),S)}finally{Te(t,L)}if(b<0)return S>0&&s===q?S:b;if(S+=b,b<w)break}return S}function h(s,i){let u=n(),m=u?.buffer??u;return!m||s<0||i<0||s+i>m.byteLength?null:new Uint8Array(m,s,i)}return{instanceId:r,get requests(){return E},open(s,i){let u=typeof s==\"string\"?nr.encode(s):s;return!(u instanceof Uint8Array)||u.length===0?-1:u.length>Math.min(t.dataBytes,j)?-1:A($t,{instanceId:r,flags:i|0,path:u}).status},read(s,i,u,m){if(u===0)return 0;if(T())return A(q,{instanceId:r,handle:s,ptr:i,len:u,offset:m}).status;let S=h(i,u);return S?_(q,s,S,m):f()?-3:-1},write(s,i,u,m){if(u===0)return 0;if(T())return A(X,{instanceId:r,handle:s,ptr:i,len:u,offset:m}).status;let S=h(i,u);return S?_(X,s,S,m):f()?-3:-1},readInto(s,i,u){return i.length===0?0:_(q,s,i,u)},writeFrom(s,i,u){return i.length===0?0:_(X,s,i,u)},truncate(s,i){return A(Kt,{instanceId:r,handle:s,offset:i}).status},sync(s){return A(zt,{instanceId:r,handle:s}).status},size(s){let{status:i,result:u}=A(Wt,{instanceId:r,handle:s});return i<0?i:u},close(s){return A(jt,{instanceId:r,handle:s}).status},release(){a.close()}}}var ar=typeof TextEncoder==\"function\"?new TextEncoder:null;function ur(e){let t=2166136261;for(let r=0;r<e.length;r+=1)t^=e[r],t=Math.imul(t,16777619);return t|0}var Ce=new WeakMap;function Ne(e){let t=Ce.get(e);if(t)return t;let r=new Int32Array(e,0,16);if(r[0]!==1380795475||r[1]!==1)throw new TypeError(\"Not a SAB I/O mirror buffer.\");let n=r[2],o=r[3],c=r[4],a=64,E=a+n*32,d=E+n*c;return t={entries:n,entryBytes:o,maxPathBytes:c,i32:new Int32Array(e,a,n*32/4),f64:new Float64Array(e,a,n*32/8),paths:new Uint8Array(e,E,n*c),data:new Uint8Array(e,d,n*o)},Ce.set(e,t),t}function lr(e){return typeof e==\"string\"?ar.encode(e):e}function fr(e,t,r){let n=t*8;if(Atomics.load(e.i32,n+3)!==r.length)return!1;let o=t*e.maxPathBytes;for(let c=0;c<r.length;c+=1)if(e.paths[o+c]!==r[c])return!1;return!0}function _r(e,t,r){let n=(r>>>0)%e.entries;for(let o=0;o<e.entries;o+=1){let c=n*8,a=Atomics.load(e.i32,c+0);if(a===0)return-1;if((a===2||a===3)&&Atomics.load(e.i32,c+2)===r&&fr(e,n,t))return n;n=(n+1)%e.entries}return-1}function De(e,t){let r=Ne(e),n=lr(t);if(n.length>r.maxPathBytes)return-1;let o=_r(r,n,ur(n));return o<0?-1:Atomics.load(r.i32,o*(32/4)+0)===2?o:-1}function Fe(e,t,r,n){let o=Ne(e),c=t*(32/4),a=t*(32/8)+3,E=t*o.entryBytes;for(let d=0;d<64;d+=1){let p=Atomics.load(o.i32,c+1);if(p&1)continue;if(Atomics.load(o.i32,c+0)!==2)return-1;let A=o.f64[a],T=Atomics.load(o.i32,c+4),f;if(n>=A)f=0;else{let _=Math.min(r.length,A-n);n+_>T?f=-1:(r.set(o.data.subarray(E+n,E+n+_),0),f=_)}if(Atomics.load(o.i32,c+1)===p)return f}return-1}function Me(e=[\"/h.fsh\"]){let t=Array.from(e,String);return r=>{let n=String(r);for(let o of t)if(n.endsWith(o)||n===o.replace(/^\\//,\"\"))return!0;return!1}}var Er=\"flatsql-io\",N=Object.freeze({open:1,read:2,write:3,truncate:4,sync:5,size:6,close:7,mirrorRead:8}),He=24,Ue=16777215;function se(){return typeof performance<\"u\"&&performance.now?performance.now()*1e3:Date.now()*1e3}function Ar(e){if(!e?.buffer)return null;let t=new Int32Array(e.buffer,0,4),r=t[1],n=new Float64Array(e.buffer,16,r),o=new Uint8Array(e.buffer,16+r*8,r);return(c,a)=>{let E=Atomics.add(t,0,1);E<r&&(n[E]=se()-a,o[E]=c)}}function dr(e,t,r){if(!e||r<=0||r>j||t<0)return null;let n=e.buffer??e;return t+r>n.byteLength?null:new Uint8Array(n,t,r).slice()}function Sr(e={}){let t=e.getMemory;if(typeof t!=\"function\")throw new TypeError(\"createFlatsqlIoImports requires getMemory().\");let r=Array.isArray(e.provider)?e.provider:[e.provider];if(r.length===0||r.some(f=>!f||typeof f.open!=\"function\"))throw new TypeError(\"createFlatsqlIoImports requires at least one provider.\");if(r.length>127)throw new RangeError(\"At most 127 providers can be routed.\");let n=r.length>1,o=Ar(e.trace),c=e.mirror?.buffer??null,a=c?Me(e.mirror.suffixes??[\"/h.fsh\"]):null,E=new Map,d=new TextDecoder;function p(f){if(!n)return{provider:r[0],local:f};let _=f>>>He,h=r[_];return h?{provider:h,local:f&Ue}:null}function A(f,_,h){let s=o?se():0,i;try{i=h()}catch{i=_}return o&&o(f,s),i}return{env:{flatsql_io_open(f,_,h){return A(N.open,-1,()=>{let s=dr(t(),f,_);if(!s)return-1;let i=n?Se(s)%r.length:0,u=r[i].open(s,h|0);if(u<0)return u;if(n&&u>Ue)return-4;let m=n?i<<He|u:u;if(a){let S=d.decode(s);a(S)&&E.set(m,S)}return m})},flatsql_io_read(f,_,h,s){if(c&&E.has(f)){let i=o?se():0;try{let u=t(),m=u.buffer??u;if(_>=0&&h>=0&&_+h<=m.byteLength){let S=De(c,E.get(f));if(S>=0){let w=Fe(c,S,new Uint8Array(m,_,h),s);if(w>=0)return o&&o(N.mirrorRead,i),w}}}catch{}}return A(N.read,-4,()=>{let i=p(f);return i?i.provider.read(i.local,_,h,s):-6})},flatsql_io_write(f,_,h,s){return A(N.write,-4,()=>{let i=p(f);return i?i.provider.write(i.local,_,h,s):-6})},flatsql_io_truncate(f,_){return A(N.truncate,-4,()=>{let h=p(f);return h?h.provider.truncate(h.local,_):-6})},flatsql_io_sync(f){return A(N.sync,-4,()=>{let _=p(f);return _?_.provider.sync(_.local):-6})},flatsql_io_size(f){return A(N.size,-4,()=>{let _=p(f);return _?_.provider.size(_.local):-6})},flatsql_io_close(f){return A(N.close,-4,()=>{E.delete(f);let _=p(f);return _?_.provider.close(_.local):-6})}}}}function pr(e,{getMemory:t}){let r=Array.isArray(e.channels)?e.channels:[e.channel??e.buffer];if(r.length===0||r.some(c=>!(c instanceof SharedArrayBuffer)))throw new TypeError(\"A flatsql-io descriptor needs channels: SharedArrayBuffer[].\");let n=r.map(c=>be({buffer:c,instanceId:e.instanceId,getMemory:t}));return{imports:Sr({getMemory:t,provider:n,mirror:e.mirror,trace:e.trace}),close(){for(let c of n)c.release()}}}function Pe(e,t){let r=[],n=[];for(let o of e??[]){let c;if(typeof o==\"function\")c=o(t);else if(o&&o.provider===Er)c=pr(o,t);else if(o&&typeof o.factory==\"function\")c=o.factory({...t,config:o.config});else throw new TypeError(`Unresolvable extraImports entry ${JSON.stringify(o?.provider??o?.moduleUrl??typeof o)}; pass a factory function, a { provider: \"flatsql-io\" } descriptor, or (module workers) a { moduleUrl } descriptor.`);c&&c.imports&&typeof c.close==\"function\"?(r.push(c.imports),n.push(c.close)):c&&r.push(c)}return{fragments:r,close(){for(let o of n)try{o()}catch{}}}}function Qe(e,t){for(let r of t)for(let[n,o]of Object.entries(r??{}))e[n]={...e[n]??{},...o};return e}var Y=0,yr=1,mr=2,qe=4,ce=0,ve=1;var hr=0;var ie=qe*4,Rr=4*1024*1024;function Or(e){if(typeof SharedArrayBuffer!=\"function\"||!(e instanceof SharedArrayBuffer))throw new TypeError(\"SAB hostcall channel requires a SharedArrayBuffer (cross-origin isolation in browsers).\")}function ke(e={}){if(typeof SharedArrayBuffer!=\"function\")throw new Error(\"SharedArrayBuffer is unavailable; the async hostcall bridge requires it (browsers additionally require cross-origin isolation: COOP+COEP).\");let t=Number.isInteger(e.maxResponseBytes)?e.maxResponseBytes:Rr;if(t<=0)throw new RangeError(\"maxResponseBytes must be a positive integer.\");return new SharedArrayBuffer(ie+t)}function Ve(e={}){Or(e.buffer);let t=e.postRequest;if(typeof t!=\"function\")throw new TypeError(\"createSabHostcallClientDispatch requires a postRequest function.\");let r=Number.isFinite(e.timeoutMs)&&e.timeoutMs>0?e.timeoutMs:12e4,n=new Int32Array(e.buffer,0,qe),o=e.buffer.byteLength-ie;return function(a,E=null){if(Atomics.store(n,Y,ve),t({operation:a,params:E}),Atomics.wait(n,Y,ve,r)===\"timed-out\")throw Atomics.store(n,Y,ce),new Error(`Hostcall \"${a}\" timed out after ${r}ms waiting for the controlling thread.`);let p=Atomics.load(n,yr),A=Atomics.load(n,mr);if(A<0||A>o)throw Atomics.store(n,Y,ce),new RangeError(`Hostcall \"${a}\" response length ${A} exceeds channel capacity ${o}.`);let T=new Uint8Array(A);T.set(new Uint8Array(e.buffer,ie,A)),Atomics.store(n,Y,ce);let f=fe(T);if(p!==hr){let _=new Error(f?.message??`Hostcall \"${a}\" failed on the host thread.`);throw _.name=f?.name??\"Error\",_.code=f?.code??null,_.operation=f?.operation??a,_.capability=f?.capability??null,_}return f}}var ae=class extends Error{constructor(t){super(`WASI exit with code ${t}`),this.name=\"WasiExitError\",this.code=t}};function Ir(e,t,r,n){for(;;){let o=Atomics.load(e,t);if(r>n-o)return-1;if(Atomics.compareExchange(e,t,o,o+r)===o)return o}}function Ye(e={}){let t=e.processState,r=t?.args??e.args??[],n=t?.env??e.env??{},o=t?.input??new Uint8Array(e.stdinBytes??[]),c=e.logOutput===!0,a=e.performance??globalThis.performance??{now:()=>Date.now(),timeOrigin:0},E=e.crypto??globalThis.crypto??null,d=[],p=[],A=0,T=null;function f(l){T=l}function _(){return T}function h(){return new Uint8Array(T.buffer)}function s(){return new DataView(T.buffer)}let u=Object.entries(n).map(([l,y])=>`${l}=${y}`).map(l=>new TextEncoder().encode(l)),m=r.map(l=>new TextEncoder().encode(l));function S(l,y,O){let I;if(l===0)I=BigInt(Math.round((a.timeOrigin+a.now())*1e6));else if(l===1)I=BigInt(Math.round(a.now()*1e6));else return 28;return s().setBigUint64(O,I,!0),0}function w(l,y,O,I){if(l!==1&&l!==2)return 8;let R=l===1?d:p,g=0,M=s(),H=h();for(let U=0;U<O;U++){let K=y+U*8,D=M.getUint32(K,!0),x=M.getUint32(K+4,!0);if(t){let B=l===1?t.stdout:t.stderr,le=Ir(t.control,l,x,B.length);if(le<0)return 51;B.set(H.subarray(D,D+x),le)}else R.push(H.slice(D,D+x));g+=x}return M.setUint32(I,g,!0),0}function L(l,y,O,I){if(l!==0)return s().setUint32(I,0,!0),8;let R=s(),g=h(),M=0;for(let H=0;H<O;H+=1){let U=y+H*8,K=R.getUint32(U,!0),D=R.getUint32(U+4,!0),x,B;if(t)do x=Atomics.load(t.control,0),B=Math.min(D,o.length-x);while(Atomics.compareExchange(t.control,0,x,x+B)!==x);else x=A,B=Math.min(D,o.length-x),A+=B;if(B===0){if(x>=o.length)break;continue}g.set(o.subarray(x,x+B),K),M+=B}return R.setUint32(I,M,!0),0}function b(l){return l<=2?0:8}function Ke(l,y,O,I){return l<=2?70:8}function ze(l,y){if(l>2)return 8;let O=s();return O.setUint8(y,2),O.setUint16(y+2,0,!0),O.setBigUint64(y+8,0n,!0),O.setBigUint64(y+16,0n,!0),0}function We(l,y){return l<=2?0:8}function je(l,y){return 8}function Xe(l,y,O){return 8}function Ze(){return 8}function Je(l,y){let O=s();O.setUint32(l,u.length,!0);let I=0;for(let R of u)I+=R.length+1;return O.setUint32(y,I,!0),0}function et(l,y){let O=s(),I=h(),R=y;for(let g=0;g<u.length;g++)O.setUint32(l+g*4,R,!0),I.set(u[g],R),R+=u[g].length,I[R]=0,R+=1;return 0}function tt(l,y){let O=s();O.setUint32(l,m.length,!0);let I=0;for(let R of m)I+=R.length+1;return O.setUint32(y,I,!0),0}function rt(l,y){let O=s(),I=h(),R=y;for(let g=0;g<m.length;g++)O.setUint32(l+g*4,R,!0),I.set(m[g],R),R+=m[g].length,I[R]=0,R+=1;return 0}function nt(l,y){return E?.getRandomValues?(E.getRandomValues(h().subarray(l,l+y)),0):52}function ot(l){throw t&&(Atomics.store(t.control,4,l),Atomics.store(t.control,3,1)),c&&ue(),new ae(l)}function st(){return 0}function ue(){if(d.length>0){let l=$(d);if(c){let y=new TextDecoder().decode(l);y&&console.log(y)}d.length=0}if(p.length>0){let l=$(p);if(c){let y=new TextDecoder().decode(l);y&&console.warn(y)}p.length=0}}function $(l){let y=0;for(let R of l)y+=R.length;let O=new Uint8Array(y),I=0;for(let R of l)O.set(R,I),I+=R.length;return O}return{imports:{wasi_snapshot_preview1:{clock_time_get:S,fd_write:w,fd_read:L,fd_close:b,fd_seek:Ke,fd_fdstat_get:ze,fd_fdstat_set_flags:We,fd_prestat_get:je,fd_prestat_dir_name:Xe,path_open:Ze,environ_sizes_get:Je,environ_get:et,args_sizes_get:tt,args_get:rt,random_get:nt,proc_exit:ot,sched_yield:st}},setMemory:f,getMemory:_,flushOutput:ue,get stdout(){return t?t.stdout.slice(0,Atomics.load(t.control,1)):$(d)},get stderr(){return t?t.stderr.slice(0,Atomics.load(t.control,2)):$(p)}}}var Tr=\"sdm.thread-hostcall\";function gr(e){return WebAssembly.Module.imports(e).some(t=>t.module===re)}function wr(e){if(!e||typeof e!=\"object\")throw new Error(\"A threaded guest that imports space_data_module_host requires an owning hostcall channel.\");let t=String(e.channelName??\"\").trim(),r=String(e.token??\"\").trim();if(!t||!r)throw new Error(\"The owning thread-hostcall channel name and token are required.\");if(typeof BroadcastChannel!=\"function\")throw new Error(\"BroadcastChannel is required for nested pthread hostcalls.\");let n=ke({maxResponseBytes:e.maxResponseBytes}),o=new BroadcastChannel(t),c=1;return{dispatch:Ve({buffer:n,timeoutMs:e.timeoutMs,postRequest(E){o.postMessage({type:Tr,token:r,requestId:c++,buffer:n,...E})}}),close(){o.close()}}}function Ge({wasmModule:e,memory:t,hostcallChannel:r,processState:n,extraImports:o,workerIndex:c,tid:a}={}){let E=Ye({processState:n});E.setMemory(t);let d=null,p=null,A={...E.imports,env:{memory:t},wasi:{\"thread-spawn\":()=>-1}};if(gr(e)){p=wr(r);let f=de({dispatch:p.dispatch,getMemory:()=>d?.exports?.memory??t});Object.assign(A,f.imports)}let T=Pe(o,{memory:t,getMemory:()=>d?.exports?.memory??t,workerIndex:c??null,tid:a??null});return Qe(A,T.fragments),A.env.memory=t,{imports:A,instantiate(){return d=new WebAssembly.Instance(e,A),E.setMemory(d.exports.memory??t),d},close(){p?.close(),T.close()}}}async function $e(e){let t=[];for(let r of e??[])if(r&&typeof r.moduleUrl==\"string\"){let o=(await import(r.moduleUrl))[r.exportName??\"default\"];if(typeof o!=\"function\")throw new TypeError(`extraImports module ${r.moduleUrl} exports no factory \"${r.exportName??\"default\"}\".`);t.push({factory:o,config:r.config??null})}else t.push(r);return t}var G=null;self.onmessage=async e=>{let t=e.data??{};if(t.t===\"probe\"){try{let r=await $e(t.extraImports??[]);G=Ge({wasmModule:t.wasmModule,memory:t.memory,hostcallChannel:t.hostcallChannel??null,processState:t.processState,extraImports:r,workerIndex:t.workerIndex}),G.instantiate(),self.postMessage({t:\"ready\",ok:!0})}catch(r){G?.close(),G=null,self.postMessage({t:\"ready\",ok:!1,error:String(r?.message??r)})}return}if(t.t===\"run\"){try{G.instantiate().exports.wasi_thread_start(t.tid,t.startArg)}catch(r){r&&r.name===\"WasiExitError\"||(console.error(`[wasi-thread] guest thread ${t.tid} trapped:`,r),self.postMessage({t:\"error\",tid:t.tid,error:String(r?.message??r)}))}self.postMessage({t:\"exit\",tid:t.tid})}};})();\n";
7
+ export const WASI_THREAD_POOL_WORKER_BUNDLE_SHA256 = "a6904554c3cb075acfd387fa1d867b2605db78f23b0b7ec34dc3a643ffa65549";
8
+
9
+ /** src/host/opfsIoWorker.mjs, sha256 9b5cf50741217bd829e7f1ee4cbdbf3e6b6b8ecc20a700501adf0faf9ee429b1. */
10
+ export const FLATSQL_IO_WORKER_BUNDLE = "(()=>{var Nn=Object.freeze({READ:1,WRITE:2,CREATE:4,EXCL:8,TRUNC:16,DELETE_ON_CLOSE:32,PROBE:64,UNLINK:128,CREATE_PARENTS:256,UNLINK_IF_UNUSED:512,OPEN_DEFERRED:1024}),Cn=Object.freeze({OK:0,GENERIC:-1,NOENT:-2,ACCESS:-3,IO:-4,NOSPACE:-5,BADHANDLE:-6,BUSY:-7});var Fn=Object.freeze([\"flatsql_io_open\",\"flatsql_io_read\",\"flatsql_io_write\",\"flatsql_io_truncate\",\"flatsql_io_sync\",\"flatsql_io_size\",\"flatsql_io_close\"]),Ye=4096;function vt(t,{during:n}={}){if(!t)return-1;let r=typeof t.code==\"string\"?t.code:null;if(r)switch(r){case\"ENOENT\":case\"ENOTDIR\":return-2;case\"EACCES\":case\"EPERM\":case\"EROFS\":return-3;case\"ENOSPC\":case\"EDQUOT\":return-5;case\"EBADF\":return-4;case\"EEXIST\":return-1;case\"EBUSY\":case\"ETXTBSY\":return-7;case\"ENAMETOOLONG\":case\"EINVAL\":return-1;default:return-4}switch(t.name){case\"NotFoundError\":return-2;case\"NoModificationAllowedError\":return-7;case\"InvalidStateError\":return n===\"open\"?-7:-6;case\"QuotaExceededError\":return-5;case\"TypeMismatchError\":case\"SecurityError\":case\"NotAllowedError\":return-3;case\"InvalidModificationError\":return-7;case\"TypeError\":case\"RangeError\":return-1;default:return-4}}var N=class extends Error{constructor(n,r){super(r??`flatsql_io status ${n}`),this.name=\"FlatsqlIoStatusError\",this.status=n}};function V(t,n){return t&&typeof t.status==\"number\"&&t.status<0?t.status:vt(t,n)}function oe(t){if(typeof t!=\"string\"||t.length===0||t.includes(\"\\0\"))return-1;let n=[];for(let r of t.split(\"/\"))if(!(r===\"\"||r===\".\")){if(r===\"..\")return-3;n.push(r)}return n.length===0?-1:n}var Ve=typeof TextDecoder==\"function\"?new TextDecoder(\"utf-8\",{fatal:!0}):null;function Ge(t){if(!Ve||t.length===0||t.length>Ye)return-1;let n=t.buffer instanceof ArrayBuffer?t:new Uint8Array(t);try{return Ve.decode(n)}catch{return-1}}var Vt=1330201683,Yt=1,Gt=0,qt=1,Wt=2,$t=3,Kt=4,H=5,Ie=6,We=7,$e=8;var Xt=11,Ke=12,zt=13,Xe=64,qe=Xe*4;var ze=1,Ze=2;var se=0,Oe=1,Je=0,ae=1,ie=2,ce=3,je=32767,G=0;var Zt=2,Jt=3,et=4,tt=5,nt=6,rt=7,ot=8,st=9,at=10,jt=11,en=12,it=13,ct=8,tn=9,de=128;var _e=2,_t=3,nn=4;var rn=1;var ft=1,pe=1,fe=2,he=3,Re=4,Te=5,me=6,Le=7;var Mn=64*1024;function on(t,n){return Math.ceil(t/n)*n}function sn(t){if(typeof SharedArrayBuffer!=\"function\"||!(t instanceof SharedArrayBuffer))throw new TypeError(\"The SAB I/O channel requires a SharedArrayBuffer (cross-origin isolation in browsers).\")}function lt(t){sn(t);let n=new Int32Array(t,0,Xe);if(n[Gt]!==Vt||n[qt]!==Yt)throw new TypeError(\"Not a SAB I/O channel buffer (bad magic or version).\");let r=n[Wt],s=n[$t],f=n[Kt],a=n[Xt],l=on(qe+f*4,64),L=new Int32Array(t,qe,f),S=[];for(let p=0;p<r;p+=1){let T=l+p*s;S.push({index:p,base:T,i32:new Int32Array(t,T,de/4),f64:new Float64Array(t,T,de/8),data:new Uint8Array(t,T+de,a)})}return{buffer:t,header:n,instances:L,slots:S,slotCount:r,slotBytes:s,dataBytes:a,maxInstances:f,channelId:n[zt]}}function ut(t){return`sdm-sab-io-doorbell-${t}`}function an(t){return`sdm-sab-io-done-${t}`}var Qn=typeof TextEncoder==\"function\"?new TextEncoder:null;var Y=null;function cn(t){return typeof BroadcastChannel!=\"function\"?null:((!Y||Y.id!==t.channelId)&&(Y?.channel.close(),Y={id:t.channelId,channel:new BroadcastChannel(an(t.channelId))}),Y.channel)}function Et(t,n,r,s=0){n.f64[tn]=s,Atomics.store(n.i32,jt,r|0),Atomics.store(n.i32,Jt,Atomics.load(n.i32,Zt)),Atomics.store(n.i32,G,nn),Atomics.notify(n.i32,G),Atomics.load(n.i32,en)===rn&&cn(t)?.postMessage(n.index)}var _n=typeof TextEncoder==\"function\"?new TextEncoder:null;function St(t){let n=2166136261;for(let r=0;r<t.length;r+=1)n^=t[r],n=Math.imul(n,16777619);return n|0}var At=new WeakMap;function ye(t){let n=At.get(t);if(n)return n;let r=new Int32Array(t,0,16);if(r[0]!==1380795475||r[1]!==1)throw new TypeError(\"Not a SAB I/O mirror buffer.\");let s=r[2],f=r[3],a=r[4],l=64,L=l+s*32,S=L+s*a;return n={entries:s,entryBytes:f,maxPathBytes:a,i32:new Int32Array(t,l,s*32/4),f64:new Float64Array(t,l,s*32/8),paths:new Uint8Array(t,L,s*a),data:new Uint8Array(t,S,s*f)},At.set(t,n),n}function dt(t){return ye(t).entryBytes}function It(t){return typeof t==\"string\"?_n.encode(t):t}function fn(t,n,r){let s=n*8;if(Atomics.load(t.i32,s+3)!==r.length)return!1;let f=n*t.maxPathBytes;for(let a=0;a<r.length;a+=1)if(t.paths[f+a]!==r[a])return!1;return!0}function Ot(t,n,r){let s=(r>>>0)%t.entries;for(let f=0;f<t.entries;f+=1){let a=s*8,l=Atomics.load(t.i32,a+0);if(l===0)return-1;if((l===2||l===3)&&Atomics.load(t.i32,a+2)===r&&fn(t,s,n))return s;s=(s+1)%t.entries}return-1}function ln(t,n,r){let s=(r>>>0)%t.entries;for(let f=0;f<t.entries;f+=1){let a=s*8;if(Atomics.compareExchange(t.i32,a+0,0,1)===0)return t.paths.set(n,s*t.maxPathBytes),Atomics.store(t.i32,a+3,n.length),Atomics.store(t.i32,a+2,r),Atomics.store(t.i32,a+4,0),t.f64[s*(32/8)+3]=0,Atomics.store(t.i32,a+0,3),s;s=(s+1)%t.entries}return-1}function W(t,n,r,s,{truncateTo:f}={}){let a=ye(t),l=It(n);if(l.length>a.maxPathBytes)return!1;let L=St(l),S=Ot(a,l,L);if(S<0&&(S=ln(a,l,L)),S<0)return!1;let p=S*(32/4),T=S*(32/8)+3,A=S*a.entryBytes,c=Atomics.load(a.i32,p+0)===2;Atomics.add(a.i32,p+1,1);let E=c?a.f64[T]:0,d=c?Atomics.load(a.i32,p+4):0;if(c||a.data.fill(0,A,A+a.entryBytes),s.length>0&&r<a.entryBytes){let m=Math.min(a.entryBytes,r+s.length);r>d&&a.data.fill(0,A+d,A+r),a.data.set(s.subarray(0,m-r),A+r)}return s.length>0&&(E=Math.max(E,r+s.length)),f!==void 0&&(f<d&&a.data.fill(0,A+f,A+d),E=f),d=Math.min(E,a.entryBytes),a.f64[T]=E,Atomics.store(a.i32,p+4,d),Atomics.store(a.i32,p+0,2),Atomics.add(a.i32,p+1,1),!0}function we(t,n){let r=ye(t),s=It(n);if(s.length>r.maxPathBytes)return;let f=Ot(r,s,St(s));if(f<0)return;let a=f*(32/4);Atomics.add(r.i32,a+1,1),Atomics.store(r.i32,a+0,3),Atomics.store(r.i32,a+4,0),r.f64[f*(32/8)+3]=0,Atomics.add(r.i32,a+1,1)}function pt(t=[\"/h.fsh\"]){let n=Array.from(t,String);return r=>{let s=String(r);for(let f of n)if(s.endsWith(f)||s===f.replace(/^\\//,\"\"))return!0;return!1}}var Ce=256*1024,dn=50,In=8,Tt=250,mt=16777215,R=0,xe=1,Lt=2;function le(){return typeof performance<\"u\"&&performance.now?performance.now():Date.now()}function On(){if(typeof MessageChannel==\"function\"){let t=new MessageChannel,n=[];return t.port1.onmessage=()=>n.shift()?.(),t.port1.unref?.(),t.port2.unref?.(),()=>new Promise(r=>{n.push(r),t.port2.postMessage(0)})}return()=>new Promise(t=>setTimeout(t,0))}function yt(t={}){let n=lt(t.buffer),r=t.backend;if(!r||typeof r.openFile!=\"function\")throw new TypeError(\"createFlatsqlIoServer requires a backend with openFile().\");let s=Number.isInteger(t.chunkBytes)&&t.chunkBytes>0?t.chunkBytes:Ce,f=t.doorbell??\"auto\",a=f===\"message\"||f===\"auto\"&&typeof Atomics.waitAsync!=\"function\"?Oe:se,l=t.mirror??null,L=Number.isFinite(t.spinMicros)?Math.max(0,t.spinMicros):dn,S=typeof t.onEvent==\"function\"?t.onEvent:null,p=On(),T=new Map,A=new Map,c=new Map,E=new Map,d=new Map,m=[],y=new Set,x=1,F=!1,g=null,D=null,U=null,J=null,j=!1,w={served:0,opens:0,deferredOpens:0,parked:0,chunks:0,busy:0,revoked:0,sharedViewsRejected:!1,maxReady:0};function v(e){if(S)try{S(e)}catch{}}function ee(){if(a===se)Atomics.add(n.header,H,1),Atomics.notify(n.header,H);else{let e=D;D=null,e?.()}}async function Ft(e){if(a===se){let o=Atomics.waitAsync(n.header,H,e,Tt);o.async&&await o.value;return}Atomics.load(n.header,H)===e&&await new Promise(o=>{let _=setTimeout(()=>{D===u&&(D=null),o()},Tt),u=()=>{clearTimeout(_),o()};D=u})}function Ae(e,o){let u=(d.get(e)??Promise.resolve()).then(o,o),i=u.then(()=>{},()=>{});return d.set(e,i),i.then(()=>{d.get(e)===i&&d.delete(e)}),u}function gt(){for(let e=0;e<mt;e+=1){let o=x;if(x=x>=mt?1:x+1,!c.has(o))return o}return-1}function te(e,o,_){let u=gt();if(u<0)return-1;let i=(_&2)!==0,O={id:u,entry:e,instanceId:o,canWrite:i,canRead:!i||(_&1)!==0};c.set(u,O),e.refs+=1,_&32&&(e.deleteOnClose=!0);let I=E.get(o);return I||(I=new Set,E.set(o,I)),I.add(u),u}function ne(e){if(!(e.refs>0||e.pins>0)){if(A.get(e.path)===e&&A.delete(e.path),e.file){try{e.file.close()}catch{}e.file=null}e.deleteOnClose&&e.openStatus===0&&Ae(e.path,async()=>{try{await r.remove(e.path,e.components)}catch{}l&&l.write!==!1&&we(l.buffer,e.path)})}}function De(e){c.delete(e.id)&&(E.get(e.instanceId)?.delete(e.id),e.entry.refs-=1,ne(e.entry))}function Dt(e){return e===je?ae:e<0||e>=n.maxInstances?-1:Atomics.load(n.instances,e)}function Se(e){let o=Dt(e);return o===ie||o===ce}function Me(e){let{slot:o,ptr:_,len:u}=e;if(u<0||_<0)return null;if(e.dataMode===ft)return _+u>o.data.length?null:o.data.subarray(_,_+u);let i=T.get(e.instanceId),O=i?.buffer??i;return!O||_+u>O.byteLength?null:new Uint8Array(O,_,u)}function Qe(e){return(!J||J.length<e)&&(J=new Uint8Array(Math.max(e,s))),J.subarray(0,e)}function Pe(e,o,_){if(!j)try{return e.read(o,{at:_})}catch(O){if(!(O instanceof TypeError)||!(o.buffer instanceof SharedArrayBuffer))throw O;j=!0,w.sharedViewsRejected=!0,v({type:\"shared-views-rejected\"})}let u=Qe(o.length),i=e.read(u,{at:_});return o.set(u.subarray(0,i),0),i}function Mt(e,o,_){if(!j)try{return e.write(o,{at:_})}catch(i){if(!(i instanceof TypeError)||!(o.buffer instanceof SharedArrayBuffer))throw i;j=!0,w.sharedViewsRejected=!0,v({type:\"shared-views-rejected\"})}let u=Qe(o.length);return u.set(o,0),e.write(u,{at:_})}function h(e,o,_=0){y.delete(e.slot.index),w.served+=1,Atomics.add(n.header,Ke,1),Et(n,e.slot,o,_)}function Qt(e){let o=e.i32;return{slot:e,op:o[et],instanceId:o[tt],handleId:o[nt],flags:o[rt],ptr:o[ot],len:o[st],dataMode:o[it],pathLen:o[at],offset:e.f64[ct],done:0,phase:0}}function He(){let e=0;for(let o of n.slots)y.has(o.index)||Atomics.load(o.i32,G)===_e&&Atomics.compareExchange(o.i32,G,_e,_t)===_e&&(y.add(o.index),m.push(Qt(o)),e+=1);return m.length>w.maxReady&&(w.maxReady=m.length),e}function Ue(){for(let e=0;e<n.maxInstances;e+=1){if(Atomics.load(n.instances,e)!==ie)continue;let o=E.get(e);if(o){for(let _ of Array.from(o)){let u=c.get(_);u&&De(u)}E.delete(e)}T.delete(e),w.revoked+=1,Atomics.store(n.instances,e,ce),Atomics.notify(n.instances,e),v({type:\"revoked\",instanceId:e})}}function re(e,o){return w.parked+=1,o.waiters.push(e),Lt}function ke(e,o,_){if(e.opening=null,e.openStatus=o,e.file=_??null,o===0&&l&&l.write!==!1&&l.match(e.path)&&e.file)try{let i=e.file.getSize(),O=new Uint8Array(Math.min(i,dt(l.buffer)));O.length>0&&Pe(e.file,O,0),W(l.buffer,e.path,0,O,{truncateTo:i})}catch{}let u=e.waiters;e.waiters=[];for(let i of u)i.op===pe&&i.phase===1&&i.entry===e&&(o<0?i.result=o:Se(i.instanceId)?i.result=-3:i.result=te(e,i.instanceId,i.flags),i.phase=2),m.push(i);o<0&&e.refs===0&&e.pins===0&&A.get(e.path)===e?A.delete(e.path):o===0&&e.refs===0&&e.pins===0&&ne(e),ee()}function be(e,o){w.opens+=1,e.opening=Ae(e.path,async()=>{try{let _=await r.openFile(e.path,e.components,o);ke(e,0,_)}catch(_){ke(e,V(_,{during:\"open\"}),null)}})}function Pt(e){if(e.phase===2)return h(e,e.result),R;if(Se(e.instanceId))return h(e,-3),R;if(e.path===void 0){let I=e.slot.data.slice(0,Math.max(0,e.pathLen)),Q=Ge(I);if(typeof Q!=\"string\")return h(e,Q),R;let P=oe(Q);if(!Array.isArray(P))return h(e,P),R;e.path=P.join(\"/\"),e.components=P}let{path:o,components:_,flags:u}=e,i=A.get(o);if(u&704)return i?.opening?re(e,i):u&64?i&&i.openStatus===0?(h(e,0),R):ve(e,async()=>await r.exists(o,_)?0:-2):i&&i.refs>0?(w.busy+=1,h(e,-7),R):(i&&i.pins>0&&(i.pins=0,ne(i)),ve(e,async()=>(await r.remove(o,_),l&&l.write!==!1&&we(l.buffer,o),0)));if(i){if(i.opening){if(u&1024){w.deferredOpens+=1;let I=te(i,e.instanceId,u);return h(e,I),R}return re(e,i)}if(i.openStatus===0){if(u&8)return h(e,-1),R;if(u&16&&u&2)try{i.file.truncate(0),l&&l.write!==!1&&l.match(o)&&W(l.buffer,o,0,new Uint8Array(0),{truncateTo:0})}catch(Q){return h(e,V(Q)),R}let I=te(i,e.instanceId,u);return h(e,I),R}A.get(o)===i&&A.delete(o)}let O={path:o,components:_,file:null,opening:null,openStatus:0,refs:0,pins:0,deleteOnClose:!1,waiters:[]};if(A.set(o,O),be(O,u),u&1024){w.deferredOpens+=1;let I=te(O,e.instanceId,u);return h(e,I),R}return e.phase=1,e.entry=O,re(e,O)}function ve(e,o){return e.phase=2,Ae(e.path,async()=>{try{e.result=await o()}catch(_){e.result=V(_)}m.push(e),ee()}),w.parked+=1,Lt}function Ht(e){if(Se(e.instanceId))return h(e,-3),R;let o=c.get(e.handleId);if(!o)return h(e,-6),R;let _=o.entry;if(_.opening)return re(e,_);if(e.op===Le)return De(o),h(e,0),R;if(_.openStatus<0||!_.file)return h(e,_.openStatus<0?_.openStatus:-6),R;let u=_.file;try{switch(e.op){case fe:{if(!o.canRead)return h(e,-4),R;let i=Me(e);if(!i)return h(e,-1),R;let O=Math.min(s,e.len-e.done),I=Pe(u,i.subarray(e.done,e.done+O),e.offset+e.done);return w.chunks+=1,e.done+=I,I<O||e.done>=e.len?(h(e,e.done),R):xe}case he:{if(!o.canWrite)return h(e,-4),R;let i=Me(e);if(!i)return h(e,-1),R;let O=Math.min(s,e.len-e.done),I=i.subarray(e.done,e.done+O),Q=e.offset+e.done,P=Mt(u,I,Q);return w.chunks+=1,l&&l.write!==!1&&l.match(_.path)&&W(l.buffer,_.path,Q,I.subarray(0,P)),e.done+=P,P<O||e.done>=e.len?(h(e,e.done),R):xe}case Re:return o.canWrite?(u.truncate(e.offset),l&&l.write!==!1&&l.match(_.path)&&W(l.buffer,_.path,0,new Uint8Array(0),{truncateTo:e.offset}),h(e,0),R):(h(e,-4),R);case Te:return u.flush(),h(e,0),R;case me:return h(e,0,u.getSize()),R;default:return h(e,-1),R}}catch(i){let O=V(i);return h(e,e.done>0&&e.op===fe?e.done:O),R}}function Ut(e){try{return e.op===pe?Pt(e):e.op===fe||e.op===he||e.op===Re||e.op===Te||e.op===me||e.op===Le?Ht(e):(h(e,-1),R)}catch(o){return v({type:\"step-error\",error:o}),h(e,-4),R}}function kt(){let e=le();for(;m.length>0;){let o=m.shift();if(Ut(o)===xe&&m.push(o),Ue(),He(),le()-e>In)return!1}return!0}async function bt(){for(Atomics.store(n.header,We,a),Atomics.add(n.header,$e,1),Atomics.store(n.header,Ie,ze);F;){let e=Atomics.load(n.header,H);Ue(),He();let o=kt();if(!F)break;if(!o||m.length>0){await p();continue}if(L>0){let _=le()+L/1e3;for(;le()<_&&Atomics.load(n.header,H)===e;);if(Atomics.load(n.header,H)!==e)continue}await Ft(e)}}return{doorbellMode:a,stats:w,start(){return F||(F=!0,a===Oe&&typeof BroadcastChannel==\"function\"&&(U=new BroadcastChannel(ut(n.channelId)),U.onmessage=()=>{let e=D;D=null,e?.()}),g=bt().catch(e=>{throw v({type:\"loop-error\",error:e}),e})),g},async stop(){F=!1,ee();try{await g}catch{}U?.close(),U=null;for(let e of A.values())try{e.file?.close()}catch{}A.clear(),c.clear(),E.clear(),Atomics.store(n.header,Ie,Ze)},attachMemory(e,o){if(!Number.isInteger(e)||e<0||e>=n.maxInstances)return!1;let _=Atomics.load(n.instances,e);return _===ie||_===ce?!1:(T.set(e,o),Atomics.store(n.instances,e,ae),!0)},detachMemory(e){T.delete(e),Atomics.load(n.instances,e)===ae&&Atomics.store(n.instances,e,Je)},async preopen(e,o=7){let _=await Promise.all(e.map(async u=>{let i=oe(String(u));if(!Array.isArray(i))return i;let O=i.join(\"/\"),I=A.get(O);return I||(I={path:O,components:i,file:null,opening:null,openStatus:0,refs:0,pins:0,deleteOnClose:!1,waiters:[]},A.set(O,I),be(I,o&-1025)),I.pins+=1,I.opening&&await I.opening,I.openStatus<0?(I.pins=Math.max(0,I.pins-1),I.openStatus):0}));return ee(),_},releasePreopen(e){for(let o of e){let _=oe(String(o));if(!Array.isArray(_))continue;let u=A.get(_.join(\"/\"));u&&u.pins>0&&(u.pins-=1,ne(u))}},inventory(){return{files:Array.from(A.values()).map(e=>({path:e.path,refs:e.refs,pins:e.pins,opening:!!e.opening,openStatus:e.openStatus})),handles:c.size}}}}var vn=263;var Fe=class{constructor(){this.bytes=new Uint8Array(0),this.length=0}ensureCapacity(n,r){if(n<=this.bytes.length)return;let s=Math.max(64,this.bytes.length);for(;s<n;)s*=2;r.reserve(s-this.bytes.length);let f=new Uint8Array(s);f.set(this.bytes.subarray(0,this.length)),this.bytes=f}};function wt(t={}){let n=Number.isFinite(t.maxBytes)?t.maxBytes:1/0,r=new Map,s=new Set([\"\"]),f=0,a={reserve(S){if(f+S>n)throw new N(-5,\"memory store budget exhausted\");f+=S},release(S){f=Math.max(0,f-S)}};function l(S){return S.slice(0,-1).join(\"/\")}function L(S){let p=!1,T=()=>{if(p){let c=new Error(\"handle closed\");throw c.name=\"InvalidStateError\",c}let A=r.get(S);if(!A){let c=new Error(\"file removed\");throw c.name=\"NotFoundError\",c}return A};return{read(A,{at:c=0}={}){let E=T();if(c>=E.length)return 0;let d=Math.min(A.length,E.length-c);return A.set(E.bytes.subarray(c,c+d),0),d},write(A,{at:c=0}={}){let E=T(),d=c+A.length;return E.ensureCapacity(d,a),c>E.length&&E.bytes.fill(0,E.length,c),E.bytes.set(A,c),d>E.length&&(E.length=d),A.length},truncate(A){let c=T();A>c.length&&(c.ensureCapacity(A,a),c.bytes.fill(0,c.length,A)),c.length=A},flush(){T()},getSize(){return T().length},close(){p=!0}}}return{kind:\"memory\",openFile(S,p,T){let A=l(p);if(!s.has(A)){if(!(T&256)||!(T&4))throw new N(-2,`no directory ${A}`);for(let E=1;E<p.length;E+=1)s.add(p.slice(0,E).join(\"/\"))}if(s.has(S))throw new N(-3,`${S} is a directory`);let c=r.get(S);if(c&&T&8)throw new N(-1,`${S} exists`);if(c)T&16&&(c.length=0);else{if(!(T&4))throw new N(-2,`no file ${S}`);c=new Fe,r.set(S,c)}return L(S)},exists(S){return r.has(S)||s.has(S)},remove(S){let p=r.get(S);if(!p)throw new N(-2,`no file ${S}`);a.release(p.bytes.length),r.delete(S)},reset(){r.clear(),s.clear(),s.add(\"\"),f=0},usage(){return{files:r.size,allocatedBytes:f}},list(){return Array.from(r.keys()).sort()}}}var Ee=\"readwrite-unsafe\";function hn(t){let n=new Error(t);return n.name=\"NotFoundError\",n}function Bt(t){return new Promise(n=>setTimeout(n,t))}async function Rn(t,n=\".sdm-mode-probe\"){let r=null,s=null;try{let f=await t.getFileHandle(n,{create:!0});return r=await f.createSyncAccessHandle({mode:Ee}),r.mode!==Ee?{supported:!1,detail:\"mode option ignored\"}:(s=await f.createSyncAccessHandle({mode:Ee}),{supported:!0,detail:\"two readwrite-unsafe handles\"})}catch(f){return{supported:!1,detail:`${f?.name??\"Error\"}: ${f?.message??f}`}}finally{try{s?.close()}catch{}try{r?.close()}catch{}try{await t.removeEntry(n)}catch{}}}async function Tn(t,n=\".sdm-view-probe\"){let r=null;try{r=await(await t.getFileHandle(n,{create:!0})).createSyncAccessHandle();let f=new Uint8Array(new SharedArrayBuffer(16));f.fill(90);let a=r.write(f,{at:0}),l=new Uint8Array(new SharedArrayBuffer(16)),L=r.read(l,{at:0});return a===16&&L===16&&l[15]===90}catch{return!1}finally{try{r?.close()}catch{}try{await t.removeEntry(n)}catch{}}}function xt(t={}){let n=t.root??null,r=!1,s=null,f=t.handleMode??\"auto\",a=typeof t.openDelayMs==\"function\"?t.openDelayMs:null,l=new Map,L={attempts:Math.max(0,t.busyRetry?.attempts??0),baseMs:Math.max(1,t.busyRetry?.baseMs??10)};async function S(c){for(let E=0;;E+=1)try{return r?await c.createSyncAccessHandle({mode:Ee}):await c.createSyncAccessHandle()}catch(d){if(!(d?.name===\"NoModificationAllowedError\"||d?.name===\"InvalidStateError\")||E>=L.attempts)throw d;await Bt(L.baseMs*2**Math.min(E,8))}}async function p(){if(!n){if(typeof navigator>\"u\"||!navigator.storage?.getDirectory)throw new N(-1,\"OPFS is unavailable here\");if(n=await navigator.storage.getDirectory(),t.rootDirectory)for(let E of String(t.rootDirectory).split(\"/\").filter(Boolean))n=await n.getDirectoryHandle(E,{create:!0})}let c=await Rn(n);if(s=await Tn(n),f===\"shared\"&&!c.supported)throw new N(-1,`shared OPFS handle modes are unsupported here (${c.detail})`);return r=f!==\"exclusive\"&&c.supported,l.set(\"\",n),{sharedModes:r,sharedModesDetail:c.detail,sharedViews:s}}async function T(c,E){let d=c.join(\"/\"),m=l.get(d);if(m)return m;let y=n,x=\"\";for(let F of c){x=x?`${x}/${F}`:F;let g=l.get(x);if(g){y=g;continue}y=await y.getDirectoryHandle(F,{create:E}),l.set(x,y)}return y}async function A(c,E){try{return await c.getFileHandle(E)}catch(d){if(d?.name===\"NotFoundError\")return null;throw d}}return{kind:\"opfs\",init:p,get sharedModes(){return r},get sharedViews(){return s},async openFile(c,E,d){if(n||await p(),a){let U=a(c);U>0&&await Bt(U)}let m=(d&4)!==0,y=m&&(d&256)!==0,x=await T(E.slice(0,-1),y),F=E[E.length-1],g=null;if(d&8&&await A(x,F))throw new N(-1,`${c} exists`);g=await x.getFileHandle(F,{create:m});let D=await S(g);return d&16&&D.truncate(0),D},async exists(c,E){n||await p();let d;try{d=await T(E.slice(0,-1),!1)}catch(y){if(y?.name===\"NotFoundError\"||y?.name===\"TypeMismatchError\")return!1;throw y}let m=E[E.length-1];if(await A(d,m))return!0;try{return await d.getDirectoryHandle(m),!0}catch{return!1}},async remove(c,E){n||await p();let d;try{d=await T(E.slice(0,-1),!1)}catch(m){throw m?.name===\"TypeMismatchError\"?hn(c):m}await d.removeEntry(E[E.length-1])},async clear(){n||await p();for await(let c of n.keys())await n.removeEntry(c,{recursive:!0});l.clear(),l.set(\"\",n)}}}var Nt=\"node:\";var mn=typeof process<\"u\"&&!!process.release&&process.release.name===\"node\",B=null,M=null,Z=null;function Ln({name:t,ifAvailable:n=!1}){return typeof navigator>\"u\"||!navigator.locks?Promise.reject(new Error(\"Web Locks are unavailable in this context\")):new Promise((r,s)=>{navigator.locks.request(t,{mode:\"exclusive\",ifAvailable:n},f=>{if(!f){r(!1);return}return r(!0),new Promise(a=>{Z=a})}).catch(s)})}function ge(t){return`${t?.name??\"Error\"}: ${t?.message??String(t)}`}function yn(t){if(!t||!t.pattern||!(t.ms>0))return;let n=new RegExp(t.pattern);return r=>n.test(r)?t.ms:0}async function wn(t,n){let r=t.role===\"reader\"?\"reader\":\"writer\";if(t.lock?.name&&!await Ln(t.lock)){let l=new Error(`the store lock ${t.lock.name} is held by another context`);throw l.name=\"LockUnavailableError\",l}t.backend===\"memory\"?M=wt({maxBytes:t.memoryMaxBytes}):M=xt({rootDirectory:t.rootDirectory,handleMode:t.handleMode??\"auto\",openDelayMs:yn(t.openDelay),busyRetry:t.busyRetry??void 0});let s={backend:M.kind,role:r,lock:t.lock?.name??null};M.init&&Object.assign(s,await M.init());let f=t.mirror?.buffer?{buffer:t.mirror.buffer,match:pt(t.mirror.suffixes??[\"/h.fsh\"]),write:t.mirror.write??r===\"writer\"}:null;return B=yt({buffer:t.buffer,backend:M,chunkBytes:t.chunkBytes??Ce,doorbell:t.doorbell??\"auto\",mirror:f,onEvent(a){(a.type===\"loop-error\"||a.type===\"step-error\")&&n({t:\"event\",event:{type:a.type,error:ge(a.error)}})}}),s.doorbellMode=B.doorbellMode===1?\"message\":\"atomics\",B.start().catch(a=>{setTimeout(()=>{throw a},0)}),s}async function Ct(t,n){switch(t?.t){case\"init\":try{let r=await wn(t,n);n({t:\"ready\",ok:!0,info:r})}catch(r){Z?.(),Z=null,n({t:\"ready\",ok:!1,error:ge(r),lockUnavailable:r?.name===\"LockUnavailableError\"})}return;case\"attach\":n({t:\"attached\",instanceId:t.instanceId,ok:!!B?.attachMemory(t.instanceId,t.memory)});return;case\"detach\":B?.detachMemory(t.instanceId);return;case\"preopen\":{let r=B?await B.preopen(t.paths??[],t.flags):[];n({t:\"preopened\",id:t.id,statuses:r});return}case\"release-preopen\":B?.releasePreopen(t.paths??[]);return;case\"stats\":n({t:\"stats\",id:t.id,stats:B?{...B.stats}:null,inventory:B?B.inventory():null,usage:M?.usage?M.usage():null});return;case\"reset\":M?.reset?.(),n({t:\"reset\",id:t.id});return;case\"clear\":try{await M?.clear?.(),n({t:\"cleared\",id:t.id,ok:!0})}catch(r){n({t:\"cleared\",id:t.id,ok:!1,error:ge(r)})}return;case\"stop\":await B?.stop(),B=null,Z?.(),Z=null,n({t:\"stopped\",id:t.id});return;default:}}function Bn(){let t=n=>self.postMessage(n);self.onmessage=n=>{Ct(n.data,t)}}async function xn(){let t=Nt+\"worker_threads\",{parentPort:n}=await import(t);if(!n)return;let r=s=>n.postMessage(s);n.on(\"message\",s=>{Ct(s,r)})}mn?xn():typeof self<\"u\"&&typeof self.postMessage==\"function\"&&typeof window>\"u\"&&Bn();})();\n";
11
+ export const FLATSQL_IO_WORKER_BUNDLE_SHA256 = "9b5cf50741217bd829e7f1ee4cbdbf3e6b6b8ecc20a700501adf0faf9ee429b1";
@@ -0,0 +1,79 @@
1
+ // Self-contained worker bundles, spawned from blob: URLs (design A39).
2
+ //
3
+ // The shipped dashboard is one HTML file whose CSP allows `worker-src 'self'
4
+ // blob:` and whose single-file law forbids separate worker files. These
5
+ // bundles let it run the wasi-threads pool and the FlatSQL I/O worker anyway:
6
+ //
7
+ // import { hostWorkerBundleUrl } from "space-data-module-sdk/host/worker-bundles";
8
+ // await createWasiThreadSpawn({ ..., poolSize,
9
+ // browserWorkerUrl: hostWorkerBundleUrl("wasi-thread-pool"),
10
+ // browserWorkerType: "classic" });
11
+ // await createFlatsqlIoWorker({ ...,
12
+ // workerUrl: hostWorkerBundleUrl("flatsql-io"), workerType: "classic" });
13
+ //
14
+ // The sources are generated by scripts/build-host-worker-bundles.mjs (esbuild
15
+ // IIFE of src/host/wasiThreadBrowserWorker.mjs and src/host/opfsIoWorker.mjs).
16
+ // `{ moduleUrl }` extraImports need a module worker; the bundles serve the
17
+ // built-in `{ provider: "flatsql-io" }` descriptor.
18
+
19
+ import {
20
+ FLATSQL_IO_WORKER_BUNDLE,
21
+ FLATSQL_IO_WORKER_BUNDLE_SHA256,
22
+ WASI_THREAD_POOL_WORKER_BUNDLE,
23
+ WASI_THREAD_POOL_WORKER_BUNDLE_SHA256,
24
+ } from "./hostWorkerBundleSources.js";
25
+
26
+ export const HOST_WORKER_BUNDLES = Object.freeze({
27
+ "wasi-thread-pool": Object.freeze({
28
+ source: WASI_THREAD_POOL_WORKER_BUNDLE,
29
+ sha256: WASI_THREAD_POOL_WORKER_BUNDLE_SHA256,
30
+ }),
31
+ "flatsql-io": Object.freeze({
32
+ source: FLATSQL_IO_WORKER_BUNDLE,
33
+ sha256: FLATSQL_IO_WORKER_BUNDLE_SHA256,
34
+ }),
35
+ });
36
+
37
+ const urls = new Map();
38
+
39
+ function bundleFor(kind) {
40
+ const bundle = HOST_WORKER_BUNDLES[kind];
41
+ if (!bundle) {
42
+ throw new RangeError(
43
+ `Unknown host worker bundle "${kind}"; expected one of ${Object.keys(HOST_WORKER_BUNDLES).join(", ")}.`,
44
+ );
45
+ }
46
+ return bundle;
47
+ }
48
+
49
+ /** The classic-script source of a bundle. */
50
+ export function hostWorkerBundleSource(kind) {
51
+ return bundleFor(kind).source;
52
+ }
53
+
54
+ /**
55
+ * A blob: URL for a bundle (created once per kind and reused). Spawn it as a
56
+ * CLASSIC worker: `new Worker(url)`, or pass `browserWorkerType: "classic"` /
57
+ * `workerType: "classic"` to the SDK hosts.
58
+ */
59
+ export function hostWorkerBundleUrl(kind) {
60
+ const bundle = bundleFor(kind);
61
+ let url = urls.get(kind);
62
+ if (!url) {
63
+ url = URL.createObjectURL(new Blob([bundle.source], { type: "text/javascript" }));
64
+ urls.set(kind, url);
65
+ }
66
+ return url;
67
+ }
68
+
69
+ /** Revoke the blob URLs created by hostWorkerBundleUrl. */
70
+ export function revokeHostWorkerBundleUrls() {
71
+ for (const url of urls.values()) {
72
+ try {
73
+ URL.revokeObjectURL(url);
74
+ } catch {
75
+ // ignore
76
+ }
77
+ }
78
+ urls.clear();
79
+ }
package/src/host/index.js CHANGED
@@ -13,3 +13,12 @@ export * from "./providerAccessFixtureAdapter.js";
13
13
  export * from "./providerAccessEngineAdapter.js";
14
14
  export * from "./providerAccessTileStoreAdapter.js";
15
15
  export * from "./terrainSourceSeam.js";
16
+ // FlatSQL partition store host I/O (T9): SAB I/O channel, I/O workers, OPFS
17
+ // and memory backends, the Node sync-fs provider, and the wasi-threads host
18
+ // with an explicit pool size.
19
+ export * from "./flatsqlIo.js";
20
+ export * from "./nodeSyncFsIo.js";
21
+ export {
22
+ createWasiThreadSpawn,
23
+ isWasiThreadsModule,
24
+ } from "./wasiThreadHost.js";