/** * Bridge the FlatSQL seven-import host I/O contract onto sdn-js's EXISTING * persistence stores. * * FlatSQL 1.4.0 registers its own sqlite3_vfs over seven offset-addressed * imports (`flatsql_io_open/read/write/truncate/sync/size/close`). The engine * is one binary with no runtime detection in it; the difference between a * WasmEdge preopen and a browser IndexedDB store lives entirely here, in the * host shim. See flatsql docs/STORAGE-DURABILITY.md §6. * * `LocalFlatSqlPersistenceStore` is a FLAT key -> bytes store: no path_open, * no seek, no partial write. flatsql's `createChunkedStoreBackend` gives it * pread/pwrite semantics by addressing fixed-size page groups * (`#`, plus a `#meta` length record), so a flush costs * O(dirty chunks) rather than O(file) and the browser reads and writes the same * byte ranges the POSIX lane does. Not "the browser rewrites everything" — the * same algorithm over a different transport. * * THE ONE ASYMMETRY, stated plainly. IndexedDB and the desktop HTTP store are * asynchronous; a wasm import cannot await. So durability is an explicit * awaited step at the JS boundary: * * await io.hydrate(path); // BEFORE opening the database * ...engine runs fully synchronously... * db.flushIndex(); // engine appends + records the mark * await io.flush(); // bytes become durable HERE * * Query results are identical to the native lane in every case; only the moment * bytes land differs, and it is awaited rather than assumed. * * IMPORTANT — one engine per JS context. flatsql's initFlatSQL() rebinds its * module-level wasm instance on every call, so the I/O backend must be * installed ONCE at shared-init time. That is why this module exports a ROUTER: * several stores can coexist behind one wasm instance by owning disjoint path * prefixes. */ import type { LocalFlatSqlPersistenceStore } from './local-flatsql.js'; /** Status codes the seven imports may return. Values, never throws. */ export declare const FLATSQL_IO_ERR_NOENT = -2; export declare const FLATSQL_IO_ERR_ACCESS = -3; export declare const FLATSQL_IO_ERR_BADHANDLE = -6; /** Engine state codes (flatsql_open_state and friends). */ export declare const FLATSQL_STATE_OK = 0; export declare const FLATSQL_STATE_ABSENT = -1; export declare const FLATSQL_STATE_VERSION_MISMATCH = -2; export declare const FLATSQL_STATE_CORRUPT = -3; export declare const FLATSQL_STATE_TORN = -4; export declare const FLATSQL_STATE_NO_FILESYSTEM = -5; export declare function describeFlatSqlStateCode(code: number): string; /** The synchronous backend shape flatsql's loaders expect. */ export interface FlatSqlIoBackend { open(path: string, flags: number): number; read(handle: number, dst: Uint8Array, offset: number): number; write(handle: number, src: Uint8Array, offset: number): number; truncate(handle: number, size: number): number; sync(handle: number): number; size(handle: number): number; close(handle: number): number; hydrate(path: string): Promise; flush(): Promise; drop(path: string): Promise; } export interface FlatSqlIoStoreOptions { /** Page-group size. 64 KiB by default: 16 SQLite pages per store value. */ chunkBytes?: number; /** Key namespace inside the store. */ prefix?: string; /** Paths already known to exist (skips a probe round trip on boot). */ knownPaths?: string[]; } /** * Back the seven imports with one sdn-js persistence store. * * `MemoryFlatSqlPersistenceStore` is a legitimate backend here, not a stub: it * survives engine teardown within a process and is exactly what the ephemeral * lane should do. What it cannot do is survive the process, and the test matrix * asserts that documented behaviour rather than skipping it. */ export declare function createFlatSqlIoStoreBackend(store: LocalFlatSqlPersistenceStore, options?: FlatSqlIoStoreOptions): FlatSqlIoBackend; /** * Dispatch the seven imports to several backends by path prefix. * * There is exactly one wasm instance per JS context, so there is exactly one * import object. A router is how more than one store gets to be durable at the * same time without a second engine — which "use FlatSQL only" forbids anyway. */ export declare class FlatSqlIoRouter implements FlatSqlIoBackend { private readonly entries; private readonly fallback; private readonly handles; private nextHandle; constructor(fallback?: FlatSqlIoBackend); /** Longest-prefix wins, so a specific mount beats a general one. */ register(prefix: string, backend: FlatSqlIoBackend): this; backendFor(path: string): FlatSqlIoBackend; open(path: string, flags: number): number; private entry; read(handle: number, dst: Uint8Array, offset: number): number; write(handle: number, src: Uint8Array, offset: number): number; truncate(handle: number, size: number): number; sync(handle: number): number; size(handle: number): number; close(handle: number): number; hydrate(path: string): Promise; /** * Flush EVERY mounted backend. Correct for a whole-context shutdown and * wrong for a single store's checkpoint: one node's ingest must not force * another mount's transport to run (and fail — an unavailable IndexedDB * mount registered by a different store would throw here). Per-store * checkpoints use `flushFor(path)`. */ flush(): Promise; /** Flush only the backend that owns `path` — the per-store checkpoint. */ flushFor(path: string): Promise; drop(path: string): Promise; } /** * Every file a durable FlatSQL database occupies in the backend namespace: * the index, the arena, and SQLite's rollback journal (journalMode TRUNCATE — * WAL needs xShmMap, which no wasm lane provides). The journal is listed * because a crash between `write` and `sync` leaves a HOT journal, and an open * that cannot see it silently skips the rollback it exists for. */ export declare function flatSqlDurablePaths(dbPath: string): string[]; /** Hydrate every file a database needs, before any synchronous engine call. */ export declare function hydrateFlatSqlDatabase(io: Pick, dbPath: string): Promise; export interface DurableOpenResult { db: TDatabase; /** Raw code from flatsql_open_state. */ stateCode: number; /** Records restored (0 when a re-derivation was needed). */ restored: number; /** True when the persisted index could not be trusted and was rebuilt. */ rederived: boolean; } /** * The durable-state surface the flatsql wasm artifact exports and its published * `wasm/index.d.ts` still does not declare (`openDatabase`, `openState`, * `reindexAll`, `flushIndex`, `flushedOffset`, `isDiskBacked`, `streamPath` — * present on both `wasm/index.js` and `wasm/standalone.js` since 1.4.0). * Declared structurally here so callers type the calls they make instead of * casting the engine away; drop it when upstream types them. */ export interface DurableFlatSqlDatabase { openState(): number; reindexAll(): number; flushIndex(): number; flushedOffset(): number; isDiskBacked(): boolean; } /** `FlatSQL.openDatabase` — same gap, same reason. */ export interface DurableFlatSqlOpener { openDatabase(schema: string, dbName: string, path: string, journalMode?: number): TDatabase; } type DurableDatabase = Pick; /** * The boot sequence, in one place so every caller performs it identically: * open state, and on ANY negative code fall back to a full re-derivation from * the stream. Every negative code is recoverable and the worst case is exactly * the behaviour hosts have today — so a failure here is a cost, never a loss. */ export declare function restoreFlatSqlState(db: TDatabase): DurableOpenResult; export {}; //# sourceMappingURL=flatsql-io-store.d.ts.map