{"version":3,"sources":["../src/backend/sqlite/local.ts"],"names":["createRequire","tables","CURRENT_BASE_SCHEMA_VERSION","CompilerInvariantError","generateSqliteMigrationSQL","isSqliteMissingEdgeMatchIdentityColumnError","getTableName","quoteDdlIdentifier","planSqliteEdgeMatchIdentityAdoption","isSqliteDuplicateEdgeMatchIdentityColumnError","Database","ConfigurationError","DEFAULT_LOCAL_SQLITE_PRAGMAS","assertNoLegacyTransactionCapability","drizzle","createSqliteBackend","sqliteVecStrategy","wrapWithManagedClose","markBundledRootAutocommitEligible"],"mappings":"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","file":"chunk-ZRIXU33S.cjs","sourcesContent":["/**\n * Local SQLite backend using better-sqlite3.\n *\n * This module depends on the `better-sqlite3` native addon and should only\n * be imported in Node.js environments. For bundler-friendly SQLite DDL\n * generation and Drizzle backend creation, import from `@nicia-ai/typegraph/adapters/drizzle/sqlite`.\n *\n * @example In-memory database (default)\n * ```typescript\n * import { createLocalSqliteBackend } from \"@nicia-ai/typegraph/adapters/drizzle/sqlite/local\";\n *\n * const { backend, db } = createLocalSqliteBackend();\n * const store = createStore(graph, backend);\n * ```\n *\n * @example File-based database for persistent local development\n * ```typescript\n * import { createLocalSqliteBackend } from \"@nicia-ai/typegraph/adapters/drizzle/sqlite/local\";\n *\n * const { backend, db } = createLocalSqliteBackend({ path: \"./dev.db\" });\n * const store = createStore(graph, backend);\n * ```\n */\nimport { createRequire } from \"node:module\";\n\nimport Database from \"better-sqlite3\";\nimport { getTableName } from \"drizzle-orm\";\nimport {\n  type BetterSQLite3Database,\n  drizzle,\n} from \"drizzle-orm/better-sqlite3\";\n\nimport { CompilerInvariantError, ConfigurationError } from \"../../errors\";\nimport { type FulltextStrategy } from \"../../query/dialect/fulltext-strategy\";\nimport { sqliteVecStrategy } from \"../../query/dialect/vector/sqlite-vec-strategy\";\nimport {\n  isSqliteDuplicateEdgeMatchIdentityColumnError,\n  isSqliteMissingEdgeMatchIdentityColumnError,\n} from \"../../utils/sql-errors\";\nimport { markBundledRootAutocommitEligible } from \"../capabilities/autocommit-single-statement\";\nimport { wrapWithManagedClose } from \"../derive-backend\";\nimport { CURRENT_BASE_SCHEMA_VERSION } from \"../drizzle/base-schema\";\nimport {\n  generateSqliteMigrationSQL,\n  planSqliteEdgeMatchIdentityAdoption,\n  quoteDdlIdentifier,\n} from \"../drizzle/ddl\";\nimport { type AnySqliteDatabase } from \"../drizzle/execution\";\nexport type { AnySqliteDatabase } from \"../drizzle/execution\";\nimport { assertNoLegacyTransactionCapability } from \"../capabilities/declarations\";\nimport {\n  createSqliteBackend,\n  type SqliteTables,\n  tables as defaultTables,\n} from \"../drizzle/sqlite\";\nimport {\n  DEFAULT_LOCAL_SQLITE_PRAGMAS,\n  type LocalSqliteJournalMode,\n  type LocalSqlitePragmaOptions,\n  type LocalSqliteSynchronousMode,\n} from \"./local-options\";\n\nexport {\n  DEFAULT_LOCAL_SQLITE_PRAGMAS,\n  type LocalSqliteJournalMode,\n  type LocalSqlitePragmaOptions,\n  type LocalSqliteSynchronousMode,\n} from \"./local-options\";\nimport {\n  type AdapterBackend,\n  type BundledBackendCapabilityOverrides,\n  type SchemaProvisioning,\n} from \"../types\";\nexport type { BundledBackendCapabilityOverrides } from \"../types\";\nexport type {\n  ContributionDiagnostic,\n  ContributionDiagnosticState,\n  ContributionRepairEntry,\n  ContributionRepairResult,\n} from \"../types\";\n\nconst nodeRequire = createRequire(import.meta.url);\n\nfunction installLocalSqliteBaseSchema(\n  sqlite: Database.Database,\n  tables: SqliteTables,\n  fulltextStrategy: FulltextStrategy | false | undefined,\n): void {\n  // v2 (the fences relation) and v3 (the recorded-relations' and recorded\n  // identity-assertions relation's `since_idx` indexes) need no adoption\n  // logic beyond what `generateSqliteMigrationSQL` already emits: a\n  // brand-new relation or index is fully covered by its own `CREATE TABLE\n  // IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS`, on both a fresh database\n  // and one that already has every OTHER base table or index. Only v1's\n  // edge-match-identity `ADD COLUMN` migration — handled by the catch block\n  // below — needed runtime introspection this synchronous path writes by\n  // hand instead of running `BaseSchemaLifecycle`'s async state machine.\n  if (CURRENT_BASE_SCHEMA_VERSION !== 3) {\n    throw new CompilerInvariantError(\n      \"The synchronous managed SQLite installation path only implements base-schema v1 through v3 adoption.\",\n      { currentVersion: CURRENT_BASE_SCHEMA_VERSION },\n    );\n  }\n  const installationSql = generateSqliteMigrationSQL(tables, fulltextStrategy);\n  try {\n    sqlite.exec(installationSql);\n  } catch (error) {\n    if (!isSqliteMissingEdgeMatchIdentityColumnError(error)) throw error;\n    const edgeTableName = getTableName(tables.edges);\n    for (let attempt = 0; attempt < 3; attempt += 1) {\n      const rows = sqlite\n        .prepare(`PRAGMA table_info(${quoteDdlIdentifier(edgeTableName)})`)\n        .all() as readonly Readonly<{ name?: unknown }>[];\n      const columns = new Set(\n        rows.flatMap((row) => (typeof row.name === \"string\" ? [row.name] : [])),\n      );\n      const adoptionSql = planSqliteEdgeMatchIdentityAdoption(\n        edgeTableName,\n        columns,\n      );\n      try {\n        sqlite.exec([...adoptionSql, installationSql].join(\"\\n\"));\n        return;\n      } catch (repairError) {\n        if (\n          attempt === 2 ||\n          !isSqliteDuplicateEdgeMatchIdentityColumnError(repairError)\n        ) {\n          throw repairError;\n        }\n      }\n    }\n    throw new CompilerInvariantError(\n      \"Local SQLite match-identity adoption exhausted its retry loop without returning or throwing.\",\n    );\n  }\n}\n\n// ============================================================\n// Native Addon Helpers\n// ============================================================\n\ntype NodeModuleVersionMismatch = Readonly<{\n  compiled: number;\n  required: number;\n}>;\n\nfunction getUnknownErrorMessage(error: unknown): string {\n  if (error instanceof Error) return error.message;\n  return String(error);\n}\n\nfunction parseNodeModuleVersionMismatchMessage(\n  message: string,\n): NodeModuleVersionMismatch | undefined {\n  const regexp =\n    /NODE_MODULE_VERSION (?<compiled>\\d+)[\\s\\S]*?NODE_MODULE_VERSION (?<required>\\d+)/;\n  const match = regexp.exec(message);\n  if (!match?.groups) return undefined;\n\n  const compiled = Number(match.groups[\"compiled\"]);\n  const required = Number(match.groups[\"required\"]);\n\n  if (!Number.isFinite(compiled) || !Number.isFinite(required))\n    return undefined;\n\n  return { compiled, required };\n}\n\nfunction createDatabase(path: string): Database.Database {\n  try {\n    return new Database(path);\n  } catch (error) {\n    const message = getUnknownErrorMessage(error);\n    const mismatch = parseNodeModuleVersionMismatchMessage(message);\n    if (!mismatch) throw error;\n\n    throw new ConfigurationError(\n      [\n        \"Failed to load better-sqlite3 native addon.\",\n        `It was compiled for NODE_MODULE_VERSION ${mismatch.compiled}, but this Node.js runtime requires ${mismatch.required}.`,\n        \"This usually happens after switching Node versions without rebuilding native dependencies.\",\n        \"Rebuild with: pnpm rebuild better-sqlite3 (or npm rebuild better-sqlite3).\",\n      ].join(\" \"),\n      {\n        nodeVersion: process.version,\n        nodeModuleVersion: process.versions.modules,\n        compiledNodeModuleVersion: mismatch.compiled,\n        requiredNodeModuleVersion: mismatch.required,\n      },\n      { cause: error },\n    );\n  }\n}\n\n// ============================================================\n// Types\n// ============================================================\n\nconst LOCAL_SQLITE_JOURNAL_MODES: readonly LocalSqliteJournalMode[] = [\n  \"wal\",\n  \"delete\",\n  \"truncate\",\n  \"persist\",\n  \"memory\",\n  \"off\",\n];\n\nconst LOCAL_SQLITE_SYNCHRONOUS_MODES: readonly LocalSqliteSynchronousMode[] = [\n  \"off\",\n  \"normal\",\n  \"full\",\n  \"extra\",\n];\n\nconst SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES = 2_147_483_647;\n\nfunction applyConnectionPragmas(\n  sqlite: Database.Database,\n  pragmas: LocalSqlitePragmaOptions | false | undefined,\n): void {\n  if (pragmas === false) return;\n  const resolved: Required<LocalSqlitePragmaOptions> = {\n    ...DEFAULT_LOCAL_SQLITE_PRAGMAS,\n    ...pragmas,\n  };\n\n  // Runtime guards mirror the compile-time unions: pragma values are spliced\n  // into pragma statements, so reject anything outside the allowlists rather\n  // than forwarding it to SQLite.\n  if (!LOCAL_SQLITE_JOURNAL_MODES.includes(resolved.journalMode)) {\n    throw new ConfigurationError(\n      `Invalid journalMode pragma: ${resolved.journalMode}. ` +\n        `Expected one of: ${LOCAL_SQLITE_JOURNAL_MODES.join(\", \")}.`,\n      { journalMode: resolved.journalMode },\n    );\n  }\n  if (!LOCAL_SQLITE_SYNCHRONOUS_MODES.includes(resolved.synchronous)) {\n    throw new ConfigurationError(\n      `Invalid synchronous pragma: ${resolved.synchronous}. ` +\n        `Expected one of: ${LOCAL_SQLITE_SYNCHRONOUS_MODES.join(\", \")}.`,\n      { synchronous: resolved.synchronous },\n    );\n  }\n  if (\n    !Number.isSafeInteger(resolved.busyTimeoutMs) ||\n    resolved.busyTimeoutMs < 0\n  ) {\n    throw new ConfigurationError(\n      `Invalid busyTimeoutMs pragma: ${String(resolved.busyTimeoutMs)}. ` +\n        \"Expected a non-negative integer number of milliseconds.\",\n      { busyTimeoutMs: resolved.busyTimeoutMs },\n    );\n  }\n  if (\n    resolved.cacheSizeKib !== undefined &&\n    (!Number.isSafeInteger(resolved.cacheSizeKib) || resolved.cacheSizeKib >= 0)\n  ) {\n    throw new ConfigurationError(\n      `Invalid cacheSizeKib pragma: ${String(resolved.cacheSizeKib)}. ` +\n        \"Expected a negative safe integer — SQLite's own cache_size pragma \" +\n        \"interprets a positive value as a page count, not KiB, so a caller \" +\n        'who passes e.g. 131072 meaning \"131072 KiB\" silently gets ' +\n        \"131072 pages (~512MiB at the default 4KiB page size) instead.\",\n      { cacheSizeKib: resolved.cacheSizeKib },\n    );\n  }\n  if (\n    resolved.mmapSizeBytes !== undefined &&\n    (!Number.isSafeInteger(resolved.mmapSizeBytes) ||\n      resolved.mmapSizeBytes < 0)\n  ) {\n    throw new ConfigurationError(\n      `Invalid mmapSizeBytes pragma: ${String(resolved.mmapSizeBytes)}. ` +\n        \"Expected a non-negative safe integer number of bytes.\",\n      { mmapSizeBytes: resolved.mmapSizeBytes },\n    );\n  }\n  if (\n    resolved.walAutocheckpointPages !== undefined &&\n    (!Number.isSafeInteger(resolved.walAutocheckpointPages) ||\n      resolved.walAutocheckpointPages < 0 ||\n      resolved.walAutocheckpointPages > SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES)\n  ) {\n    throw new ConfigurationError(\n      `Invalid walAutocheckpointPages pragma: ${String(resolved.walAutocheckpointPages)}. ` +\n        `Expected an integer between 0 and ${SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES} ` +\n        \"WAL pages (0 disables automatic checkpointing entirely).\",\n      { walAutocheckpointPages: resolved.walAutocheckpointPages },\n    );\n  }\n\n  // \":memory:\" databases always journal in memory; SQLite answers the WAL\n  // request with \"memory\" instead of erroring, so no special-casing needed.\n  sqlite.pragma(`journal_mode = ${resolved.journalMode}`);\n  sqlite.pragma(`synchronous = ${resolved.synchronous}`);\n  sqlite.pragma(`busy_timeout = ${resolved.busyTimeoutMs}`);\n  if (resolved.cacheSizeKib !== undefined) {\n    sqlite.pragma(`cache_size = ${resolved.cacheSizeKib}`);\n  }\n  if (resolved.mmapSizeBytes !== undefined) {\n    sqlite.pragma(`mmap_size = ${resolved.mmapSizeBytes}`);\n  }\n  if (resolved.walAutocheckpointPages !== undefined) {\n    sqlite.pragma(`wal_autocheckpoint = ${resolved.walAutocheckpointPages}`);\n  }\n}\n\n/**\n * Options for creating a local SQLite backend.\n */\nexport type LocalSqliteBackendOptions = Readonly<{\n  schemaProvisioning?: SchemaProvisioning;\n  /**\n   * Path to the SQLite database file.\n   * Defaults to \":memory:\" for an in-memory database.\n   */\n  path?: string;\n\n  /**\n   * Connection pragmas applied at open. Defaults to\n   * {@link DEFAULT_LOCAL_SQLITE_PRAGMAS} (WAL, `synchronous=NORMAL`, 5s busy\n   * timeout, and SQLite's own tiny built-in page cache / disabled mmap\n   * left untouched). Individual values merge over the defaults; pass\n   * `false` to skip pragma configuration entirely and keep the driver\n   * defaults (rollback journal, `synchronous=FULL`, and better-sqlite3's\n   * own 5s busy timeout from its `timeout` constructor option). Set\n   * `cacheSizeKib`/`mmapSizeBytes` explicitly once a database's working\n   * set is known to exceed SQLite's 2MiB default cache — otherwise every\n   * query pays a fresh disk read per page past that tiny working set. Set\n   * `walAutocheckpointPages` explicitly for a bulk-insert-heavy workload —\n   * SQLite's own default checkpoints every ~4MiB of WAL growth, which gets\n   * more expensive as the database file grows over a large load.\n   */\n  pragmas?: LocalSqlitePragmaOptions | false;\n\n  /**\n   * Custom table definitions.\n   * Defaults to standard TypeGraph table names.\n   */\n  tables?: SqliteTables;\n\n  /**\n   * Override the fulltext strategy. Defaults to `fts5Strategy` (SQLite's\n   * built-in FTS5 virtual table). Pass `false` to disable fulltext support\n   * entirely — the backend then advertises no `capabilities.fulltext` and\n   * omits the fulltext CRUD/search methods, and the managed installation\n   * never creates the fulltext table. Forwarded to both the installation\n   * DDL and `createSqliteBackend`.\n   */\n  fulltext?: FulltextStrategy | false;\n\n  /**\n   * Override specific backend capabilities — e.g. to simulate an engine-level\n   * gap like missing SQL window functions in tests. Forwarded to\n   * createSqliteBackend.\n   */\n  capabilities?: BundledBackendCapabilityOverrides;\n}>;\n\n/**\n * Result of creating a local SQLite backend.\n */\nexport type LocalSqliteBackendResult = Readonly<{\n  /**\n   * The GraphBackend instance for use with createStore.\n   */\n  backend: AdapterBackend<AnySqliteDatabase>;\n\n  /**\n   * The underlying Drizzle database instance.\n   * Useful for direct SQL access or cleanup.\n   */\n  db: BetterSQLite3Database;\n}>;\n\n// ============================================================\n// Factory Function\n// ============================================================\n\n/**\n * Creates a SQLite backend with minimal configuration.\n *\n * This is a convenience function for local development and testing.\n * It handles database creation, schema migration, and backend setup.\n *\n * For production deployments or custom configurations, use createSqliteBackend\n * directly with your own Drizzle database instance.\n *\n * @param options - Configuration options\n * @returns Backend and database instances\n *\n * @example In-memory database (default)\n * ```typescript\n * const { backend } = createLocalSqliteBackend();\n * const store = createStore(graph, backend);\n * ```\n *\n * @example File-based database\n * ```typescript\n * const { backend, db } = createLocalSqliteBackend({ path: \"./data.db\" });\n * const store = createStore(graph, backend);\n * ```\n */\nexport function createLocalSqliteBackend(\n  options: LocalSqliteBackendOptions = {},\n): LocalSqliteBackendResult {\n  assertNoLegacyTransactionCapability(options.capabilities);\n  const path = options.path ?? \":memory:\";\n  const tables = options.tables ?? defaultTables;\n\n  const sqlite = createDatabase(path);\n  try {\n    applyConnectionPragmas(sqlite, options.pragmas);\n\n    // Best-effort: load sqlite-vec so embedding fields are persisted to\n    // per-`(kind, field)` `vec0` storage. Without it, nodes with\n    // `embedding()` fields validate and insert but their vectors are silently\n    // dropped. When the user has installed sqlite-vec as a peer dep we load\n    // it and wire the strategy; otherwise we proceed without vector support.\n    const hasSqliteVec = tryLoadSqliteVec(sqlite);\n\n    const db = drizzle(sqlite);\n\n    // The managed factory owns a complete fresh installation, including the\n    // deployment-wide base-schema marker consumed by verified/runtime-only\n    // entrypoints. Raw generateSqliteDDL intentionally omits that marker.\n    installLocalSqliteBaseSchema(sqlite, tables, options.fulltext);\n\n    const backend = createSqliteBackend(db, {\n      ...(options.schemaProvisioning === undefined ?\n        {}\n      : { schemaProvisioning: options.schemaProvisioning }),\n      executionProfile: {\n        isSync: true,\n      },\n      tables,\n      ...(hasSqliteVec ? { vector: sqliteVecStrategy } : {}),\n      ...(options.fulltext === undefined ? {} : { fulltext: options.fulltext }),\n      capabilities: {\n        ...options.capabilities,\n        graphAnalytics: {\n          supported:\n            options.capabilities?.graphAnalytics?.supported ??\n            options.capabilities?.execution?.interactiveTransactions !== false,\n          mathFunctions:\n            options.capabilities?.graphAnalytics?.mathFunctions ?? true,\n        },\n      },\n    });\n    const managedBackend = wrapWithManagedClose(backend, () => {\n      sqlite.close();\n    });\n\n    return { backend: markBundledRootAutocommitEligible(managedBackend), db };\n  } catch (error) {\n    try {\n      sqlite.close();\n    } catch {\n      // Preserve the provisioning error; a cleanup failure is secondary.\n    }\n    throw error;\n  }\n}\n\nfunction tryLoadSqliteVec(sqlite: Database.Database): boolean {\n  try {\n    // `sqlite-vec` is an optional peer dep; resolved via createRequire so\n    // bundlers don't mark it as a hard import. Node resolves the package\n    // only when it's actually installed.\n    const module_: unknown = nodeRequire(\"sqlite-vec\");\n    if (\n      typeof module_ === \"object\" &&\n      module_ !== null &&\n      \"load\" in module_ &&\n      typeof module_.load === \"function\"\n    ) {\n      (module_ as { load: (db: Database.Database) => void }).load(sqlite);\n      return true;\n    }\n    return false;\n  } catch {\n    return false;\n  }\n}\nexport type { GraphIdentityConfig } from \"../../core/define-graph\";\n"]}