/** * Leaf module for node:sqlite native binding access. * * This file MUST have no imports that transitively reach back to any CLEO * module that participates in the agent-resolver → dispatch-trace → * extraction-gate → graph-auto-populate → memory-sqlite → sqlite.ts cycle * (see T1325/T1331). Only node builtins are imported below this line. * * ## Why this exists * * `sqlite.ts` previously declared `let _DatabaseSyncCtor = null` at module * scope. When Vitest eagerly traces the dynamic `import('../memory/dispatch-trace.js')` * in `agent-resolver.ts`, it re-enters `sqlite.ts` before the module finishes * initializing. Because `let` declarations in ESM are hoisted (TDZ) but not yet * initialized at re-entry, any access to `_DatabaseSyncCtor` throws * `Cannot access '_DatabaseSyncCtor' before initialization`. * * The v2 fix moved the constructor cache into this leaf module. The v3 fix * (T1331) goes further: `openNativeDatabase` itself now lives here so that * `sqlite.ts` has ZERO value-binding imports from `sqlite-native.ts` at module * scope. `sqlite.ts` only re-exports this module's symbols — re-exports are * live-binding getters (Vite transforms them as property accessors, not `const` * bindings), so they cannot be in TDZ during module initialization. * * ## Invariant (updated T9024) * * Modules imported here MUST NOT have live bindings that participate in the * agent-resolver TDZ cycle. Node builtins (fs, os, path, module) are always * safe. `sqlite-pragmas.ts` is now also safe (confirmed T9024): its only * import is `import type { DatabaseSync } from 'node:sqlite'` — a type-only * import erased at runtime, so it never enters the live binding graph. All * other CLEO modules remain forbidden here. * * @module sqlite-native * @task T1331 * @epic T1323 */ import type { DatabaseSync as _DatabaseSyncType } from 'node:sqlite'; /** Re-exported DatabaseSync type for consumers of this leaf module. */ export type DatabaseSync = _DatabaseSyncType; /** * Returns the node:sqlite DatabaseSync constructor, loading it on first call. * * Uses `createRequire` rather than a top-level `import` because Vitest/Vite * cannot resolve `node:sqlite` as an ESM import (it strips the `node:` prefix * in some environments). The constructor is memoized after the first call. * * This function is safe to call from module initialization code in `sqlite.ts` * and any other consumer because this leaf module has no CLEO imports and * therefore cannot participate in a circular-import cycle. * * @returns The DatabaseSync class constructor from node:sqlite. */ export declare function getDbSyncConstructor(): new (...args: ConstructorParameters) => DatabaseSync; /** * Open a node:sqlite DatabaseSync with CLEO standard pragmas. * * This function lives in the leaf module (zero CLEO imports) so that callers * in the agent-resolver cycle can reach it without triggering a TDZ on any * Vite SSR binding. `sqlite.ts` re-exports this symbol — callers that already * import from `sqlite.js` continue to work unchanged. * * CRITICAL: WAL mode is verified, not just requested. If another process holds * an EXCLUSIVE lock in DELETE mode, PRAGMA journal_mode=WAL silently returns * 'delete'. This caused data loss (T5173) when concurrent processes opened * the same database — writes were silently dropped under lock contention. * * Under vitest, {@link assertVitestSafePath} blocks any open against a * path outside an isolated test root. See that function's doc for opt-outs. * * @param path - Absolute path to the SQLite database file. * @param options - Optional open settings. * @returns An open DatabaseSync instance with WAL and busy_timeout applied. * @task T1331 */ export declare function openNativeDatabase(path: string, options?: { readonly?: boolean; timeout?: number; enableWal?: boolean; allowExtension?: boolean; }): DatabaseSync; //# sourceMappingURL=sqlite-native.d.ts.map