@nicia-ai/typegraph 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend/postgres/index.cjs +19 -19
- package/dist/backend/postgres/index.d.cts +5 -5
- package/dist/backend/postgres/index.d.ts +5 -5
- package/dist/backend/postgres/index.js +9 -9
- package/dist/backend/postgres/pglite.cjs +14 -14
- package/dist/backend/postgres/pglite.d.cts +2 -2
- package/dist/backend/postgres/pglite.d.ts +2 -2
- package/dist/backend/postgres/pglite.js +9 -9
- package/dist/backend/sqlite/index.cjs +17 -17
- package/dist/backend/sqlite/index.d.cts +11 -6
- package/dist/backend/sqlite/index.d.ts +11 -6
- package/dist/backend/sqlite/index.js +8 -8
- package/dist/backend/sqlite/libsql.cjs +13 -13
- package/dist/backend/sqlite/libsql.d.cts +2 -2
- package/dist/backend/sqlite/libsql.d.ts +2 -2
- package/dist/backend/sqlite/libsql.js +9 -9
- package/dist/backend/sqlite/local.cjs +16 -15
- package/dist/backend/sqlite/local.cjs.map +1 -1
- package/dist/backend/sqlite/local.d.cts +8 -2
- package/dist/backend/sqlite/local.d.ts +8 -2
- package/dist/backend/sqlite/local.js +11 -10
- package/dist/backend/sqlite/local.js.map +1 -1
- package/dist/{chunk-UP4QAJND.cjs → chunk-26HWIIVS.cjs} +65 -65
- package/dist/{chunk-UP4QAJND.cjs.map → chunk-26HWIIVS.cjs.map} +1 -1
- package/dist/{chunk-GPUNAJFH.js → chunk-2QA5EHEN.js} +3 -3
- package/dist/{chunk-GPUNAJFH.js.map → chunk-2QA5EHEN.js.map} +1 -1
- package/dist/{chunk-CUZGBWFT.js → chunk-3IRMLJEK.js} +3 -3
- package/dist/{chunk-CUZGBWFT.js.map → chunk-3IRMLJEK.js.map} +1 -1
- package/dist/{chunk-MRMD7S7E.js → chunk-3JLRHQ67.js} +7 -7
- package/dist/{chunk-MRMD7S7E.js.map → chunk-3JLRHQ67.js.map} +1 -1
- package/dist/{chunk-UPBXUOW7.cjs → chunk-4BXHVEFB.cjs} +15 -15
- package/dist/{chunk-UPBXUOW7.cjs.map → chunk-4BXHVEFB.cjs.map} +1 -1
- package/dist/{chunk-RU5BBUU2.cjs → chunk-4LBO6KIF.cjs} +70 -67
- package/dist/chunk-4LBO6KIF.cjs.map +1 -0
- package/dist/{chunk-HKN622O4.js → chunk-633N7DSE.js} +9 -5
- package/dist/chunk-633N7DSE.js.map +1 -0
- package/dist/{chunk-R2LA6MKR.cjs → chunk-7JGLPAFV.cjs} +8 -8
- package/dist/{chunk-R2LA6MKR.cjs.map → chunk-7JGLPAFV.cjs.map} +1 -1
- package/dist/{chunk-7KLVFWXR.js → chunk-AI3RNREM.js} +30 -4
- package/dist/chunk-AI3RNREM.js.map +1 -0
- package/dist/{chunk-SFNUHFON.js → chunk-ENDUY2CD.js} +4 -4
- package/dist/{chunk-SFNUHFON.js.map → chunk-ENDUY2CD.js.map} +1 -1
- package/dist/{chunk-7V335GHG.cjs → chunk-FLRCVI2G.cjs} +12 -2
- package/dist/chunk-FLRCVI2G.cjs.map +1 -0
- package/dist/{chunk-IE2TPFBT.js → chunk-FVIGJTS7.js} +3 -3
- package/dist/{chunk-IE2TPFBT.js.map → chunk-FVIGJTS7.js.map} +1 -1
- package/dist/{chunk-Q5ASTPM4.cjs → chunk-FWBVPATK.cjs} +19 -19
- package/dist/{chunk-Q5ASTPM4.cjs.map → chunk-FWBVPATK.cjs.map} +1 -1
- package/dist/{chunk-KGAJ5HFO.cjs → chunk-IE6GN7L3.cjs} +17 -17
- package/dist/{chunk-KGAJ5HFO.cjs.map → chunk-IE6GN7L3.cjs.map} +1 -1
- package/dist/{chunk-A4H6QMV4.js → chunk-IUIJJYPI.js} +14 -11
- package/dist/chunk-IUIJJYPI.js.map +1 -0
- package/dist/{chunk-BMDF2S7S.js → chunk-IX7RE7CG.js} +3 -3
- package/dist/{chunk-BMDF2S7S.js.map → chunk-IX7RE7CG.js.map} +1 -1
- package/dist/{chunk-G6P3OVDY.cjs → chunk-JIEJCTDS.cjs} +18 -2
- package/dist/chunk-JIEJCTDS.cjs.map +1 -0
- package/dist/{chunk-XTQHSOIC.cjs → chunk-K4N35E7B.cjs} +86 -86
- package/dist/{chunk-XTQHSOIC.cjs.map → chunk-K4N35E7B.cjs.map} +1 -1
- package/dist/{chunk-NZ5PMBTG.js → chunk-K5P5OZXS.js} +12 -3
- package/dist/chunk-K5P5OZXS.js.map +1 -0
- package/dist/{chunk-Y52UNT66.js → chunk-K5VREXMZ.js} +7 -7
- package/dist/{chunk-Y52UNT66.js.map → chunk-K5VREXMZ.js.map} +1 -1
- package/dist/chunk-LUHU4T2F.cjs +12 -0
- package/dist/{chunk-Q3ZZLU3O.cjs.map → chunk-LUHU4T2F.cjs.map} +1 -1
- package/dist/{chunk-Z36W5WUM.js → chunk-MAQJYNJR.js} +3 -3
- package/dist/{chunk-Z36W5WUM.js.map → chunk-MAQJYNJR.js.map} +1 -1
- package/dist/{chunk-N3VVQDMA.js → chunk-MXE2U3EX.js} +3 -3
- package/dist/{chunk-N3VVQDMA.js.map → chunk-MXE2U3EX.js.map} +1 -1
- package/dist/{chunk-3DTLDGIM.js → chunk-N2OEOGBB.js} +6 -6
- package/dist/{chunk-3DTLDGIM.js.map → chunk-N2OEOGBB.js.map} +1 -1
- package/dist/{chunk-OGUH56BB.js → chunk-R4JOBEJU.js} +4 -4
- package/dist/{chunk-OGUH56BB.js.map → chunk-R4JOBEJU.js.map} +1 -1
- package/dist/{chunk-HM6XMR3E.cjs → chunk-SGPXKJ4A.cjs} +18 -18
- package/dist/{chunk-HM6XMR3E.cjs.map → chunk-SGPXKJ4A.cjs.map} +1 -1
- package/dist/{chunk-MB363HT5.js → chunk-TQOYM4LN.js} +18 -3
- package/dist/chunk-TQOYM4LN.js.map +1 -0
- package/dist/{chunk-C2RWFIYP.cjs → chunk-UESTHN47.cjs} +34 -6
- package/dist/chunk-UESTHN47.cjs.map +1 -0
- package/dist/{chunk-4K6IHUW6.cjs → chunk-VFX3LC76.cjs} +14 -14
- package/dist/{chunk-4K6IHUW6.cjs.map → chunk-VFX3LC76.cjs.map} +1 -1
- package/dist/{chunk-F2Q76CQ4.cjs → chunk-WEMZM7J7.cjs} +11 -7
- package/dist/chunk-WEMZM7J7.cjs.map +1 -0
- package/dist/{chunk-ZYQEXGYC.cjs → chunk-WFCECD6Q.cjs} +84 -84
- package/dist/{chunk-ZYQEXGYC.cjs.map → chunk-WFCECD6Q.cjs.map} +1 -1
- package/dist/{chunk-VGU26WIU.cjs → chunk-YQGLVWB2.cjs} +4 -4
- package/dist/{chunk-VGU26WIU.cjs.map → chunk-YQGLVWB2.cjs.map} +1 -1
- package/dist/{ddl-D3o-RmsV.d.cts → ddl-BSFlbGQF.d.cts} +3 -3
- package/dist/{ddl-BwH00BB6.d.ts → ddl-EdkIiFVU.d.ts} +3 -3
- package/dist/graph-extension/index.cjs +19 -19
- package/dist/graph-extension/index.d.cts +1 -1
- package/dist/graph-extension/index.d.ts +1 -1
- package/dist/graph-extension/index.js +4 -4
- package/dist/{index-CapHwi1a.d.ts → index-DzeIiMO3.d.ts} +9 -1
- package/dist/{index-jPPexxM5.d.cts → index-Ln_KHTGA.d.cts} +9 -1
- package/dist/index.cjs +780 -515
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +314 -53
- package/dist/index.js.map +1 -1
- package/dist/indexes/index.cjs +18 -18
- package/dist/indexes/index.d.cts +4 -4
- package/dist/indexes/index.d.ts +4 -4
- package/dist/indexes/index.js +4 -4
- package/dist/interchange/index.cjs +7 -7
- package/dist/interchange/index.d.cts +3 -3
- package/dist/interchange/index.d.ts +3 -3
- package/dist/interchange/index.js +2 -2
- package/dist/{manager-BUugwCYz.d.ts → manager-BbdyNhkv.d.ts} +1 -1
- package/dist/{manager-DpIpn1HQ.d.cts → manager-wTDgjoXG.d.cts} +1 -1
- package/dist/{postgres-CQL9UIn2.d.cts → postgres-CK2ByP1q.d.cts} +1 -1
- package/dist/{postgres-CcRLaxz0.d.ts → postgres-ymXYC6Rr.d.ts} +1 -1
- package/dist/profiler/index.cjs +9 -9
- package/dist/profiler/index.d.cts +5 -5
- package/dist/profiler/index.d.ts +5 -5
- package/dist/profiler/index.js +2 -2
- package/dist/schema/index.cjs +31 -31
- package/dist/schema/index.d.cts +5 -5
- package/dist/schema/index.d.ts +5 -5
- package/dist/schema/index.js +8 -8
- package/dist/{sqlite-Rj3xu4It.d.cts → sqlite-DxH1lrwD.d.cts} +1 -1
- package/dist/{sqlite-CZDFUfHS.d.ts → sqlite-R8YGOqVQ.d.ts} +1 -1
- package/dist/{store-B43FpOVX.d.cts → store--z1Tmk7U.d.cts} +43 -3
- package/dist/{store-De0Y33wP.d.ts → store-CNKM334w.d.ts} +43 -3
- package/dist/{types-CmAT-Z47.d.ts → types-BBiDqJCU.d.ts} +2 -0
- package/dist/{types-B5GSeE3t.d.ts → types-CMvxx2kd.d.ts} +1 -1
- package/dist/{types-Bwlp_yvu.d.cts → types-D5B6Be5c.d.cts} +1 -1
- package/dist/{types-DXCSyxac.d.cts → types-dL-clxO3.d.cts} +2 -0
- package/dist/{where-CP4qGIHd.d.ts → where-CAo6wsBZ.d.ts} +1 -1
- package/dist/{where-2dsyYt3d.d.cts → where-bJjuOCeV.d.cts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-7KLVFWXR.js.map +0 -1
- package/dist/chunk-7V335GHG.cjs.map +0 -1
- package/dist/chunk-A4H6QMV4.js.map +0 -1
- package/dist/chunk-C2RWFIYP.cjs.map +0 -1
- package/dist/chunk-F2Q76CQ4.cjs.map +0 -1
- package/dist/chunk-G6P3OVDY.cjs.map +0 -1
- package/dist/chunk-HKN622O4.js.map +0 -1
- package/dist/chunk-MB363HT5.js.map +0 -1
- package/dist/chunk-NZ5PMBTG.js.map +0 -1
- package/dist/chunk-Q3ZZLU3O.cjs +0 -12
- package/dist/chunk-RU5BBUU2.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/backend/drizzle/schema/sqlite.ts","../src/backend/types.ts"],"names":["nodes","sqliteTable","text","integer","primaryKey","index","buildSqliteNodeIndexBuilders","edges","buildSqliteEdgeIndexBuilders","uniques","schemaVersions","uniqueIndex","sql"],"mappings":"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","file":"chunk-F2Q76CQ4.cjs","sourcesContent":["/**\n * Drizzle SQLite schema for TypeGraph.\n *\n * Provides table definitions that can be customized via the factory function.\n * Users import these tables into their Drizzle schema and use drizzle-kit\n * for migrations.\n *\n * @example\n * ```typescript\n * // Default table names\n * import { tables } from \"@nicia-ai/typegraph/sqlite\";\n *\n * // Custom table names\n * import { createSqliteTables } from \"@nicia-ai/typegraph/sqlite\";\n * const tables = createSqliteTables({\n * nodes: \"myapp_nodes\",\n * edges: \"myapp_edges\",\n * });\n * ```\n */\nimport { sql } from \"drizzle-orm\";\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\n\nimport {\n buildSqliteEdgeIndexBuilders,\n buildSqliteNodeIndexBuilders,\n type IndexDeclaration,\n} from \"../../../indexes\";\n\n/**\n * Table name configuration.\n */\nexport type SqliteTableNames = Readonly<{\n nodes: string;\n edges: string;\n uniques: string;\n schemaVersions: string;\n fulltext: string;\n indexMaterializations: string;\n contributionMaterializations: string;\n kindRemovals: string;\n reconciliationMarkers: string;\n}>;\n\n/**\n * Physical name of the legacy single shared embeddings table, dropped in\n * the cross-backend vector cutover (the clean cut of #157). Strategies now\n * own per-`(nodeKind, fieldPath)` typed storage. Retained only so the\n * one-time migration utility can address and drain the old table.\n */\nexport const LEGACY_EMBEDDINGS_TABLE_NAME = \"typegraph_node_embeddings\";\n\nexport type CreateSqliteTablesOptions = Readonly<{\n /**\n * Additional TypeGraph indexes to include in the Drizzle schema.\n *\n * These become first-class Drizzle indexes, so drizzle-kit migrations will\n * pick them up automatically.\n */\n indexes?: readonly IndexDeclaration[] | undefined;\n}>;\n\nconst DEFAULT_TABLE_NAMES: SqliteTableNames = {\n nodes: \"typegraph_nodes\",\n edges: \"typegraph_edges\",\n uniques: \"typegraph_node_uniques\",\n schemaVersions: \"typegraph_schema_versions\",\n fulltext: \"typegraph_node_fulltext\",\n indexMaterializations: \"typegraph_index_materializations\",\n contributionMaterializations: \"typegraph_contribution_materializations\",\n kindRemovals: \"typegraph_kind_removals\",\n reconciliationMarkers: \"typegraph_reconciliation_markers\",\n};\n\n/**\n * Creates SQLite table definitions with customizable table names.\n * Index names are derived from table names.\n */\nexport function createSqliteTables(\n names: Partial<SqliteTableNames> = {},\n options: CreateSqliteTablesOptions = {},\n) {\n const n: SqliteTableNames = { ...DEFAULT_TABLE_NAMES, ...names };\n const indexes = options.indexes ?? [];\n\n const nodes = sqliteTable(\n n.nodes,\n {\n graphId: text(\"graph_id\").notNull(),\n kind: text(\"kind\").notNull(),\n id: text(\"id\").notNull(),\n props: text(\"props\").notNull(),\n version: integer(\"version\").notNull().default(1),\n validFrom: text(\"valid_from\"),\n validTo: text(\"valid_to\"),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n deletedAt: text(\"deleted_at\"),\n },\n (t) => [\n primaryKey({ columns: [t.graphId, t.kind, t.id] }),\n index(`${n.nodes}_kind_idx`).on(t.graphId, t.kind),\n index(`${n.nodes}_kind_created_idx`).on(\n t.graphId,\n t.kind,\n t.deletedAt,\n t.createdAt,\n ),\n index(`${n.nodes}_deleted_idx`).on(t.graphId, t.deletedAt),\n index(`${n.nodes}_valid_idx`).on(t.graphId, t.validFrom, t.validTo),\n ...buildSqliteNodeIndexBuilders(t, indexes),\n ],\n );\n\n const edges = sqliteTable(\n n.edges,\n {\n graphId: text(\"graph_id\").notNull(),\n id: text(\"id\").notNull(),\n kind: text(\"kind\").notNull(),\n fromKind: text(\"from_kind\").notNull(),\n fromId: text(\"from_id\").notNull(),\n toKind: text(\"to_kind\").notNull(),\n toId: text(\"to_id\").notNull(),\n props: text(\"props\").notNull(),\n validFrom: text(\"valid_from\"),\n validTo: text(\"valid_to\"),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n deletedAt: text(\"deleted_at\"),\n },\n (t) => [\n primaryKey({ columns: [t.graphId, t.id] }),\n index(`${n.edges}_kind_idx`).on(t.graphId, t.kind),\n // Directional traversal index (outgoing): supports endpoint lookups\n // and extra filtering by edge kind / target kind.\n index(`${n.edges}_from_idx`).on(\n t.graphId,\n t.fromKind,\n t.fromId,\n t.kind,\n t.toKind,\n t.deletedAt,\n t.validTo,\n ),\n // Directional traversal index (incoming): mirrors from_idx for reverse traversals.\n index(`${n.edges}_to_idx`).on(\n t.graphId,\n t.toKind,\n t.toId,\n t.kind,\n t.fromKind,\n t.deletedAt,\n t.validTo,\n ),\n index(`${n.edges}_kind_created_idx`).on(\n t.graphId,\n t.kind,\n t.deletedAt,\n t.createdAt,\n ),\n index(`${n.edges}_deleted_idx`).on(t.graphId, t.deletedAt),\n index(`${n.edges}_valid_idx`).on(t.graphId, t.validFrom, t.validTo),\n index(`${n.edges}_cardinality_idx`).on(\n t.graphId,\n t.kind,\n t.fromKind,\n t.fromId,\n t.validTo,\n ),\n ...buildSqliteEdgeIndexBuilders(t, indexes),\n ],\n );\n\n const uniques = sqliteTable(\n n.uniques,\n {\n graphId: text(\"graph_id\").notNull(),\n nodeKind: text(\"node_kind\").notNull(),\n constraintName: text(\"constraint_name\").notNull(),\n key: text(\"key\").notNull(),\n nodeId: text(\"node_id\").notNull(),\n concreteKind: text(\"concrete_kind\").notNull(),\n deletedAt: text(\"deleted_at\"),\n },\n (t) => [\n primaryKey({\n columns: [t.graphId, t.nodeKind, t.constraintName, t.key],\n }),\n index(`${n.uniques}_node_idx`).on(t.graphId, t.concreteKind, t.nodeId),\n ],\n );\n\n const schemaVersions = sqliteTable(\n n.schemaVersions,\n {\n graphId: text(\"graph_id\").notNull(),\n version: integer(\"version\").notNull(),\n schemaHash: text(\"schema_hash\").notNull(),\n schemaDoc: text(\"schema_doc\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n isActive: integer(\"is_active\", { mode: \"boolean\" })\n .notNull()\n .default(false),\n },\n (t) => [\n primaryKey({ columns: [t.graphId, t.version] }),\n index(`${n.schemaVersions}_active_idx`).on(t.graphId, t.isActive),\n // Partial unique index enforcing the \"at most one active version\n // per graph\" invariant at the storage layer. Defense in depth\n // against buggy backend implementations or out-of-band writes.\n // Forces the deactivate-then-activate ordering used by\n // `commitSchemaVersion` and `setActiveVersion`.\n uniqueIndex(`${n.schemaVersions}_one_active_per_graph_idx`)\n .on(t.graphId)\n .where(sql`${t.isActive} = 1`),\n ],\n );\n\n /**\n * Per-deployment record of which declared indexes have been\n * materialized against this database. Owned and written by\n * `store.materializeIndexes()`. Keyed on `index_name` because SQL\n * index names are physical, database-global identifiers — `graphId`\n * is provenance, not identity.\n */\n const indexMaterializations = sqliteTable(\n n.indexMaterializations,\n {\n indexName: text(\"index_name\").notNull(),\n graphId: text(\"graph_id\").notNull(),\n entity: text(\"entity\").notNull(),\n kind: text(\"kind\").notNull(),\n signature: text(\"signature\").notNull(),\n schemaVersion: integer(\"schema_version\").notNull(),\n materializedAt: text(\"materialized_at\"),\n lastAttemptedAt: text(\"last_attempted_at\").notNull(),\n lastError: text(\"last_error\"),\n },\n (t) => [primaryKey({ columns: [t.indexName] })],\n );\n\n /**\n * Per-deployment record of extension kinds removed via\n * `store.removeKinds()` whose data has not yet been cleaned up by\n * `store.materializeRemovals()`. Keyed on `(graph_id, kind_name,\n * entity, schema_version)` — each remove operation is its own row.\n * `entity` separates a node and an edge that share a kind name; the\n * `schema_version` discriminator keeps a re-add-then-re-remove cycle\n * (Foo removed at v=N, re-added, then removed again at v=N+2) from\n * collapsing onto the prior row, where the COALESCE-on-failure rule\n * would preserve the earlier `removed_at` and silently skip the new\n * pending cleanup. `removed_at` is null until the data-cleanup pass\n * succeeds; the pending set is \"rows where removed_at IS NULL\".\n */\n const kindRemovals = sqliteTable(\n n.kindRemovals,\n {\n graphId: text(\"graph_id\").notNull(),\n kindName: text(\"kind_name\").notNull(),\n entity: text(\"entity\").notNull(),\n schemaVersion: integer(\"schema_version\").notNull(),\n removedAt: text(\"removed_at\"),\n lastAttemptedAt: text(\"last_attempted_at\").notNull(),\n lastError: text(\"last_error\"),\n },\n (t) => [\n primaryKey({\n columns: [t.graphId, t.kindName, t.entity, t.schemaVersion],\n }),\n ],\n );\n\n /**\n * Per-deployment high-water mark for the `materializeRemovals`\n * reconciliation walk. One row per `graph_id` carrying the schema\n * version up to which the historical \"did every removal land in\n * `kindRemovals`?\" walk has been verified. Lets subsequent calls\n * skip already-checked transitions instead of re-walking from\n * version 1 every time.\n */\n const reconciliationMarkers = sqliteTable(\n n.reconciliationMarkers,\n {\n graphId: text(\"graph_id\").notNull(),\n reconciledToVersion: integer(\"reconciled_to_version\").notNull(),\n },\n (t) => [primaryKey({ columns: [t.graphId] })],\n );\n\n /**\n * Per-deployment durable marker that a strategy-owned table\n * contribution (#129 — the FTS5 virtual table today) has been\n * materialized against this database (#135). Replaces the in-memory\n * per-backend `fulltextEnsured` latch with a queryable database fact.\n * Keyed on `(graph_id, logical_name, owner, table_name)`; `signature`\n * stays out of the key so same-identity drift is a loud error, not a\n * silent re-materialize. Same COALESCE-on-failure preservation rule\n * as `indexMaterializations`.\n */\n const contributionMaterializations = sqliteTable(\n n.contributionMaterializations,\n {\n graphId: text(\"graph_id\").notNull(),\n logicalName: text(\"logical_name\").notNull(),\n owner: text(\"owner\").notNull(),\n tableName: text(\"table_name\").notNull(),\n signature: text(\"signature\").notNull(),\n materializedAt: text(\"materialized_at\"),\n lastAttemptedAt: text(\"last_attempted_at\").notNull(),\n lastError: text(\"last_error\"),\n },\n (t) => [\n primaryKey({\n columns: [t.graphId, t.logicalName, t.owner, t.tableName],\n }),\n ],\n );\n\n return {\n nodes,\n edges,\n uniques,\n schemaVersions,\n indexMaterializations,\n contributionMaterializations,\n kindRemovals,\n reconciliationMarkers,\n /**\n * The fulltext storage is a FTS5 virtual table which Drizzle cannot\n * represent. DDL is emitted as raw SQL and operations query it via\n * `sql.raw()`.\n */\n fulltextTableName: n.fulltext,\n } as const;\n}\n\n/**\n * Default tables with standard TypeGraph table names.\n */\nexport const tables = createSqliteTables();\n\n/**\n * Convenience exports for default tables.\n */\nexport const { nodes, edges, uniques, schemaVersions } = tables;\n\n/**\n * Type representing the tables object returned by createSqliteTables.\n */\nexport type SqliteTables = ReturnType<typeof createSqliteTables>;\n","/**\n * Backend interface types for TypeGraph storage.\n *\n * The backend abstracts database operations, allowing different\n * SQL implementations (SQLite, PostgreSQL) behind a common interface.\n */\nimport { type SQL } from \"drizzle-orm\";\n\nimport {\n type IndexEntity,\n type KindEntity,\n type TemporalMode,\n} from \"../core/types\";\nimport { type SqlTableNames } from \"../query/compiler/schema\";\nimport { type FulltextStrategy } from \"../query/dialect/fulltext-strategy\";\nimport { type VectorStrategy } from \"../query/dialect/vector-strategy\";\nimport { type SerializedSchema } from \"../schema/types\";\nimport {\n type AnyPgDatabase,\n type AnySqliteDatabase,\n} from \"./drizzle/execution\";\n\n// ============================================================\n// Vector Search Types\n// ============================================================\n\n/**\n * Supported vector similarity metrics.\n */\nexport type VectorMetric = \"cosine\" | \"l2\" | \"inner_product\";\n\n/**\n * Supported vector index types.\n */\nexport type VectorIndexType = \"hnsw\" | \"ivfflat\" | \"none\";\n\n/**\n * Vector search capabilities.\n */\nexport type VectorCapabilities = Readonly<{\n /** Whether the backend supports vector operations */\n supported: boolean;\n /** Supported similarity metrics */\n metrics: readonly VectorMetric[];\n /** Supported index types */\n indexTypes: readonly VectorIndexType[];\n /** Maximum dimensions supported */\n maxDimensions: number;\n}>;\n\n// ============================================================\n// Fulltext Search Types\n// ============================================================\n\n/**\n * Query modes for fulltext search.\n *\n * - \"websearch\": Google-style syntax (quoted phrases, +required, -excluded).\n * Postgres: `websearch_to_tsquery`. SQLite: translated to FTS5 MATCH.\n * - \"phrase\": treats the whole query as a phrase.\n * Postgres: `phraseto_tsquery`. SQLite: FTS5 `\"...\"` phrase.\n * - \"plain\": splits on whitespace and ANDs terms.\n * Postgres: `plainto_tsquery`. SQLite: default FTS5 AND.\n * - \"raw\": dialect-native syntax passed through unchanged.\n */\nexport type FulltextQueryMode = \"websearch\" | \"phrase\" | \"plain\" | \"raw\";\n\n/**\n * Fulltext search capabilities declared by a backend.\n */\nexport type FulltextCapabilities = Readonly<{\n /** Whether the backend supports fulltext operations */\n supported: boolean;\n /**\n * Language / tokenizer names understood by this backend.\n * Postgres: installed regconfigs (english, simple, ...).\n * SQLite FTS5: tokenizer names (unicode61, porter, trigram).\n */\n languages: readonly string[];\n /** Whether phrase queries are supported. */\n phraseQueries: boolean;\n /** Whether prefix (`foo*`) queries are supported. */\n prefixQueries: boolean;\n /** Whether highlighting / snippets are supported. */\n highlighting: boolean;\n}>;\n\n// ============================================================\n// SQL Dialect & Capabilities\n// ============================================================\n\nimport { type SqlDialect } from \"../query/dialect/types\";\n\nexport type { SqlDialect } from \"../query/dialect/types\";\n\n/**\n * Backend capabilities that vary by dialect.\n */\nexport type BackendCapabilities = Readonly<{\n /** Whether the backend supports atomic transactions (D1 does not) */\n transactions: boolean;\n /** Vector search capabilities (undefined if not configured) */\n vector?: VectorCapabilities | undefined;\n /** Fulltext search capabilities (undefined if not configured) */\n fulltext?: FulltextCapabilities | undefined;\n}>;\n\n// ============================================================\n// Row Types (Database Records)\n// ============================================================\n\n/**\n * A row from the typegraph_nodes table.\n */\nexport type NodeRow = Readonly<{\n graph_id: string;\n kind: string;\n id: string;\n props: string; // JSON string\n version: number;\n valid_from: string | undefined;\n valid_to: string | undefined;\n created_at: string;\n updated_at: string;\n deleted_at: string | undefined;\n}>;\n\n/**\n * A row from the typegraph_edges table.\n */\nexport type EdgeRow = Readonly<{\n graph_id: string;\n id: string;\n kind: string;\n from_kind: string;\n from_id: string;\n to_kind: string;\n to_id: string;\n props: string; // JSON string\n valid_from: string | undefined;\n valid_to: string | undefined;\n created_at: string;\n updated_at: string;\n deleted_at: string | undefined;\n}>;\n\n/**\n * A row from the typegraph_node_uniques table.\n */\nexport type UniqueRow = Readonly<{\n graph_id: string;\n node_kind: string;\n constraint_name: string;\n key: string;\n node_id: string;\n concrete_kind: string;\n deleted_at: string | undefined;\n}>;\n\n/**\n * A row from the typegraph_schema_versions table.\n */\nexport type SchemaVersionRow = Readonly<{\n graph_id: string;\n version: number;\n schema_hash: string;\n schema_doc: string; // JSON string\n created_at: string;\n is_active: boolean;\n}>;\n\n// ============================================================\n// Insert Parameters\n// ============================================================\n\n/**\n * Parameters for inserting a node.\n */\nexport type InsertNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n validFrom?: string;\n validTo?: string;\n}>;\n\n/**\n * Parameters for updating a node.\n */\nexport type UpdateNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n validTo?: string;\n incrementVersion?: boolean;\n /** If true, clears deleted_at (un-deletes the node). Used by upsert. */\n clearDeleted?: boolean;\n}>;\n\n/**\n * Parameters for deleting a node (soft delete).\n */\nexport type DeleteNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n}>;\n\n/**\n * Parameters for inserting an edge.\n */\nexport type InsertEdgeParams = Readonly<{\n graphId: string;\n id: string;\n kind: string;\n fromKind: string;\n fromId: string;\n toKind: string;\n toId: string;\n props: Readonly<Record<string, unknown>>;\n validFrom?: string;\n validTo?: string;\n}>;\n\n/**\n * Parameters for updating an edge.\n */\nexport type UpdateEdgeParams = Readonly<{\n graphId: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n validTo?: string;\n clearDeleted?: boolean;\n}>;\n\n/**\n * Parameters for deleting an edge (soft delete).\n */\nexport type DeleteEdgeParams = Readonly<{\n graphId: string;\n id: string;\n}>;\n\n/**\n * Parameters for hard deleting a node (permanent removal).\n */\nexport type HardDeleteNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n}>;\n\n/**\n * Parameters for hard deleting an edge (permanent removal).\n */\nexport type HardDeleteEdgeParams = Readonly<{\n graphId: string;\n id: string;\n}>;\n\n// ============================================================\n// Embedding Parameters\n// ============================================================\n\n/**\n * Parameters for inserting or updating an embedding.\n *\n * `dimensions`, `metric`, and `indexType` together resolve the slot's\n * typed per-`(nodeKind, fieldPath)` storage (the strategy needs the fixed\n * dimension for the column type, and the metric/index type to address the\n * right ANN structure). The store populates them from the schema's\n * `embedding()` declaration via `getEmbeddingDimensions()` /\n * `getEmbeddingIndex()`; the backend constructs a `VectorSlot` from them\n * and stays graph-agnostic.\n */\nexport type UpsertEmbeddingParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n fieldPath: string;\n embedding: readonly number[];\n dimensions: number;\n metric: VectorMetric;\n indexType: VectorIndexType;\n}>;\n\n/**\n * Parameters for deleting an embedding.\n *\n * `dimensions` / `metric` / `indexType` mirror {@link UpsertEmbeddingParams}\n * so the backend can resolve the slot's typed per-`(nodeKind, fieldPath)`\n * storage and idempotently ensure it exists before the DELETE. That\n * matters because a delete can run before any embedding was ever written\n * (e.g. a node hard-deleted having never carried one), and on Postgres a\n * DELETE against a missing relation inside a transaction aborts the whole\n * transaction. The store populates them from the schema's `embedding()`\n * declaration, exactly as for upserts.\n */\nexport type DeleteEmbeddingParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n fieldPath: string;\n dimensions: number;\n metric: VectorMetric;\n indexType: VectorIndexType;\n}>;\n\n/**\n * Parameters for vector similarity search.\n */\nexport type VectorSearchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n fieldPath: string;\n queryEmbedding: readonly number[];\n metric: VectorMetric;\n /**\n * Fixed vector dimension `N` for the searched `(nodeKind, fieldPath)`\n * slot. The store populates it from the schema's `embedding()`\n * declaration via `getEmbeddingDimensions()`; the backend uses it to\n * construct the `VectorSlot` whose typed storage the strategy scans.\n */\n dimensions: number;\n /**\n * Index type materialized for this slot. `\"none\"` means brute-force\n * only; otherwise the strategy may route through its ANN structure.\n * The store populates it from `getEmbeddingIndex()`.\n */\n indexType: VectorIndexType;\n limit: number;\n minScore?: number;\n /**\n * HNSW search frontier for this query (pgvector `hnsw.ef_search`).\n * Sizes the dynamic candidate list the index scan maintains: higher\n * trades latency for recall. The floor for the over-fetch to fill its\n * candidate set is `efSearch >= limit`; ~2–4× is the high-recall\n * target. Applied transaction-locally (`SET LOCAL`) on the Postgres\n * HNSW path only. No-op on backends without an HNSW frontier knob\n * (sqlite-vec) and ignored — with a one-time warning — on Postgres\n * backends without transactions (e.g. `drizzle-orm/neon-http`).\n */\n efSearch?: number;\n}>;\n\n/**\n * Result from a vector similarity search.\n */\nexport type VectorSearchResult = Readonly<{\n nodeId: string;\n /**\n * Cosine metric returns similarity score (higher is better).\n * L2 and inner_product return raw distance (lower is better).\n */\n score: number;\n}>;\n\n/**\n * Parameters for creating a vector index.\n */\nexport type CreateVectorIndexParams = Readonly<{\n graphId: string;\n nodeKind: string;\n fieldPath: string;\n dimensions: number;\n metric: VectorMetric;\n indexType: VectorIndexType;\n /** Index-specific parameters */\n indexParams?: Readonly<{\n /** HNSW: max connections per layer */\n m?: number;\n /** HNSW: construction search depth */\n efConstruction?: number;\n /** IVFFlat: number of lists */\n lists?: number;\n }>;\n /**\n * Build the index without taking an `AccessExclusiveLock` on live\n * tables (Postgres `CREATE INDEX CONCURRENTLY`). Mirrors the\n * `concurrent` flag the relational DDL path uses inside\n * `materializeIndexes()`. Cannot be set inside a transaction —\n * callers (`materializeIndexes()`) run at top level. Backends that\n * don't have a CONCURRENTLY equivalent (SQLite) ignore this flag.\n */\n concurrent?: boolean;\n}>;\n\n/**\n * Parameters for dropping a vector index.\n */\nexport type DropVectorIndexParams = Readonly<{\n graphId: string;\n nodeKind: string;\n fieldPath: string;\n}>;\n\n// ============================================================\n// Fulltext Parameters\n// ============================================================\n\n/**\n * Parameters for inserting or updating a fulltext entry.\n *\n * One row per node. Callers concatenate the searchable fields into\n * `content` so a single MATCH query can find terms spread across fields.\n *\n * Note: `createFulltextIndex` / `dropFulltextIndex` were removed as\n * dead code in #PR_E. The fulltext table's canonical index (Postgres\n * GIN on `tsv`, SQLite FTS5 virtual table) is created with the table\n * itself by `bootstrapTables` per the active `FulltextStrategy`;\n * per-kind fulltext indexes are an \"advanced strategy\" surface that\n * doesn't fit the relational-style declaration model and is reserved\n * for future work.\n */\nexport type UpsertFulltextParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n content: string;\n language: string;\n}>;\n\n/**\n * Parameters for deleting a single fulltext entry.\n */\nexport type DeleteFulltextParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n}>;\n\n/**\n * A single row in a fulltext batch upsert.\n */\nexport type FulltextBatchRow = Readonly<{\n nodeId: string;\n content: string;\n language: string;\n}>;\n\n/**\n * Parameters for a batched fulltext upsert.\n *\n * Homogeneous: one graph, one node kind, many nodes. Duplicate `nodeId`\n * values within a single batch are deduplicated last-write-wins by the\n * builders before SQL generation — Postgres `ON CONFLICT` errors on\n * repeated conflict keys in one statement, and SQLite `DELETE + INSERT`\n * would create duplicate virtual-table rows otherwise.\n */\nexport type UpsertFulltextBatchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n rows: readonly FulltextBatchRow[];\n}>;\n\n/**\n * Parameters for a batched fulltext delete.\n */\nexport type DeleteFulltextBatchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeIds: readonly string[];\n}>;\n\n/**\n * Parameters for fulltext search.\n */\nexport type FulltextSearchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n /** The user-supplied query string. */\n query: string;\n /** How to parse `query`. Default: \"websearch\". */\n mode?: FulltextQueryMode;\n /**\n * Language override. Default: per-row language (as stored at insert time).\n * Postgres: passed as the regconfig to `to_tsquery` / `websearch_to_tsquery`.\n * SQLite: informational only (FTS5 tokenizer is fixed at table-create time).\n */\n language?: string;\n /** Max rows to return. */\n limit: number;\n /** Minimum rank to include (backend-dependent units). */\n minScore?: number;\n /** Whether to return a highlighted snippet per match. */\n includeSnippets?: boolean;\n}>;\n\n/**\n * Result from a fulltext search.\n *\n * Score semantics differ by backend; prefer `rank` (1-based) when fusing\n * with another source via RRF.\n */\nexport type FulltextSearchResult = Readonly<{\n nodeId: string;\n /**\n * Backend-native relevance score.\n * Postgres: `ts_rank_cd` (higher is better).\n * SQLite FTS5: negated `bm25()` (higher is better; FTS5 returns lower-is-better).\n */\n score: number;\n /** 1-based rank within the result set, suitable for RRF. */\n rank: number;\n /** Highlighted snippet of the content (if `includeSnippets` was set). */\n snippet?: string;\n}>;\n\n/**\n * Parameters for creating a fulltext index.\n *\n * The canonical index (Postgres GIN on `tsv`, SQLite FTS5 virtual table)\n * is created when the fulltext table itself is created. This is reserved\n * for advanced per-kind specializations.\n */\n\n// ============================================================\n// Index Materialization Status\n// ============================================================\n\n/**\n * Per-deployment record for a single declared index.\n *\n * Identified by `indexName` because SQL index names are physical,\n * database-global identifiers — `graphId` is provenance, not identity.\n * `materializedAt` is null until the first successful CREATE INDEX\n * completes; `lastAttemptedAt` is always set, even on failure.\n */\nexport type IndexMaterializationRow = Readonly<{\n indexName: string;\n graphId: string;\n entity: IndexEntity;\n kind: string;\n signature: string;\n schemaVersion: number;\n materializedAt: string | undefined;\n lastAttemptedAt: string;\n lastError: string | undefined;\n}>;\n\n/**\n * Parameters for upserting a materialization attempt.\n *\n * On success: pass `materializedAt` (ISO timestamp) and undefined `error`.\n * On failure: pass undefined `materializedAt` (preserve any existing\n * timestamp from a prior success) and the error message.\n */\nexport type RecordIndexMaterializationParams = Readonly<{\n indexName: string;\n graphId: string;\n entity: IndexEntity;\n kind: string;\n signature: string;\n schemaVersion: number;\n attemptedAt: string;\n /** ISO timestamp on success; undefined on failure (preserves existing). */\n materializedAt: string | undefined;\n /** Error message on failure; undefined on success (clears existing). */\n error: string | undefined;\n}>;\n\n// ============================================================\n// Contribution Materializations (#135 — durable strategy-owned\n// storage marker, sibling of index materializations)\n// ============================================================\n\n/**\n * Durable identity of a strategy-owned table contribution (#129),\n * scoped to a graph. This is the primary key of\n * `typegraph_contribution_materializations`.\n *\n * `logicalName` is the stable slot (\"fulltext\"); `owner` is the\n * producing strategy (\"tsvector\" / \"fts5\"); `tableName` is the resolved\n * physical name (custom per-deployment names must be distinguishable).\n * `graphId` is part of identity here — unlike the index status table\n * where the physical index name is database-global, two graphs can each\n * own a logically-identical fulltext contribution.\n */\nexport type ContributionMaterializationIdentity = Readonly<{\n graphId: string;\n logicalName: string;\n owner: string;\n tableName: string;\n}>;\n\n/**\n * Per-deployment record that a strategy-owned contribution has been\n * durably materialized against this database.\n *\n * `signature` is intentionally NOT part of the identity: a row with the\n * same identity but a different signature means \"materialized artifact\n * is stale/drifted\" — a loud error on the hot path, never a silent\n * re-materialize. `materializedAt` is undefined until the first\n * successful materialization; `lastAttemptedAt` is always set.\n */\nexport type ContributionMaterializationRow = Readonly<{\n graphId: string;\n logicalName: string;\n owner: string;\n tableName: string;\n signature: string;\n materializedAt: string | undefined;\n lastAttemptedAt: string;\n lastError: string | undefined;\n}>;\n\n/**\n * Parameters for upserting a contribution-materialization attempt.\n * Same success/failure contract as\n * {@link RecordIndexMaterializationParams}: on failure pass undefined\n * `materializedAt` so a prior successful timestamp is preserved via\n * COALESCE, and the error message.\n */\nexport type RecordContributionMaterializationParams = Readonly<{\n graphId: string;\n logicalName: string;\n owner: string;\n tableName: string;\n signature: string;\n attemptedAt: string;\n /** ISO timestamp on success; undefined on failure (preserves existing). */\n materializedAt: string | undefined;\n /** Error message on failure; undefined on success (clears existing). */\n error: string | undefined;\n}>;\n\n// ============================================================\n// Kind Removals (data-cleanup status)\n// ============================================================\n\n/**\n * One row of the per-deployment `typegraph_kind_removals` table:\n * a graph-extension kind that has been removed from the schema and whose\n * data may or may not have been cleaned up yet.\n */\nexport type KindRemovalRow = Readonly<{\n graphId: string;\n kindName: string;\n entity: KindEntity;\n schemaVersion: number;\n /** ISO timestamp when the data-cleanup pass succeeded; undefined while pending. */\n removedAt: string | undefined;\n lastAttemptedAt: string;\n lastError: string | undefined;\n}>;\n\n/**\n * Upsert payload for a kind-removal status row. On removal-commit:\n * pass `removedAt: undefined` (the pending state). On successful\n * data-cleanup: pass `removedAt` set and `error: undefined`. On\n * cleanup failure: pass `removedAt: undefined` (preserves any prior\n * timestamp from a partial success on a different replica) and the\n * error message.\n */\nexport type RecordKindRemovalParams = Readonly<{\n graphId: string;\n kindName: string;\n entity: KindEntity;\n schemaVersion: number;\n attemptedAt: string;\n /** ISO timestamp on success; undefined while pending or on failure. */\n removedAt: string | undefined;\n /** Error message on failure; undefined on success or while pending. */\n error: string | undefined;\n}>;\n\n// ============================================================\n// Query Types\n// ============================================================\n\n/**\n * Transaction options.\n */\nexport type TransactionOptions = Readonly<{\n /** Transaction isolation level (if supported) */\n isolationLevel?:\n | \"read_uncommitted\"\n | \"read_committed\"\n | \"repeatable_read\"\n | \"serializable\";\n}>;\n\n/**\n * A caller-owned, already-open Drizzle transaction handle that a\n * TypeGraph store can adopt so both layers commit/rollback together.\n *\n * The literal client the caller's transaction runs on — a `PgDatabase`\n * transaction (node-postgres / `neon-serverless` Pool) or a\n * `BaseSQLiteDatabase` connection. Async drivers obtain it from\n * `db.transaction(async (tx) => …)`; synchronous `better-sqlite3` (whose\n * driver rejects an `async` transaction callback) passes the connection\n * itself under an explicit `BEGIN`/`COMMIT`/`ROLLBACK`. Passing it to\n * {@link GraphBackend.adoptTransaction} threads that *literal* client\n * through TypeGraph's SQL, so graph writes and the caller's own\n * relational writes share one Postgres/SQLite transaction (#134).\n */\nexport type AdoptedTransaction = AnyPgDatabase | AnySqliteDatabase;\n\n// ============================================================\n// Backend Interface\n// ============================================================\n\n/**\n * Transaction backend — a backend scoped to a transaction.\n *\n * `commitSchemaVersion` and `setActiveVersion` are intentionally omitted:\n * the atomicity / CAS guarantees of those primitives depend on\n * dialect-specific write-locking (BEGIN IMMEDIATE on SQLite,\n * `pg_advisory_xact_lock` on Postgres) acquired by the top-level\n * backend wrappers, not the transaction itself. Calling them from a\n * user-supplied `backend.transaction(...)` callback would bypass that\n * locking and silently weaken the orphan-row crash window the primitive\n * exists to eliminate. Schema commits go through the top-level backend\n * methods only.\n */\nexport type TransactionBackend = Omit<\n GraphBackend,\n | \"transaction\"\n | \"adoptTransaction\"\n | \"close\"\n | \"refreshStatistics\"\n | \"commitSchemaVersion\"\n | \"setActiveVersion\"\n>;\n\n/**\n * The GraphBackend interface abstracts database operations.\n *\n * Implementations should provide:\n * - SQLite backend via better-sqlite3 or libsql\n * - PostgreSQL backend via pg or postgres\n */\nexport type GraphBackend = Readonly<{\n /** The SQL dialect */\n dialect: SqlDialect;\n /** Backend capabilities */\n capabilities: BackendCapabilities;\n /** Table names used by this backend (for query schema auto-derivation) */\n tableNames?: SqlTableNames | undefined;\n /**\n * Optional fulltext strategy override. When present, both the compiler\n * (for `$fulltext.matches()` in query builder) and backend-direct\n * search paths use this instead of the dialect's default strategy —\n * allowing a Postgres backend to ship pg_trgm, ParadeDB, pgroonga etc.\n * When absent, the dialect's default strategy is used.\n */\n fulltextStrategy?: FulltextStrategy | undefined;\n /**\n * Optional vector strategy this backend is wired with. The query\n * compiler reads it (via `compileQuery` options) to emit per-`(kind,\n * field)` relevance scans for `field.similarTo(...)` predicates, and\n * the index-materialization / removal paths read its deterministic\n * `tableName(...)` to address the right physical per-field storage.\n * `undefined` when the backend has no vector support (e.g. a generic\n * SQLite backend without sqlite-vec).\n */\n vectorStrategy?: VectorStrategy | undefined;\n\n // === Node Operations ===\n insertNode: (params: InsertNodeParams) => Promise<NodeRow>;\n insertNodeNoReturn?: (params: InsertNodeParams) => Promise<void>;\n insertNodesBatch?: (params: readonly InsertNodeParams[]) => Promise<void>;\n insertNodesBatchReturning?: (\n params: readonly InsertNodeParams[],\n ) => Promise<readonly NodeRow[]>;\n updateNode: (params: UpdateNodeParams) => Promise<NodeRow>;\n deleteNode: (params: DeleteNodeParams) => Promise<void>;\n hardDeleteNode: (params: HardDeleteNodeParams) => Promise<void>;\n getNode: (\n graphId: string,\n kind: string,\n id: string,\n ) => Promise<NodeRow | undefined>;\n getNodes?: (\n graphId: string,\n kind: string,\n ids: readonly string[],\n ) => Promise<readonly NodeRow[]>;\n\n // === Edge Operations ===\n insertEdge: (params: InsertEdgeParams) => Promise<EdgeRow>;\n insertEdgeNoReturn?: (params: InsertEdgeParams) => Promise<void>;\n insertEdgesBatch?: (params: readonly InsertEdgeParams[]) => Promise<void>;\n insertEdgesBatchReturning?: (\n params: readonly InsertEdgeParams[],\n ) => Promise<readonly EdgeRow[]>;\n updateEdge: (params: UpdateEdgeParams) => Promise<EdgeRow>;\n deleteEdge: (params: DeleteEdgeParams) => Promise<void>;\n hardDeleteEdge: (params: HardDeleteEdgeParams) => Promise<void>;\n getEdge: (graphId: string, id: string) => Promise<EdgeRow | undefined>;\n getEdges?: (\n graphId: string,\n ids: readonly string[],\n ) => Promise<readonly EdgeRow[]>;\n\n // === Edge Cardinality Operations ===\n countEdgesFrom: (params: CountEdgesFromParams) => Promise<number>;\n edgeExistsBetween: (params: EdgeExistsBetweenParams) => Promise<boolean>;\n\n // === Edge Query Operations ===\n findEdgesConnectedTo: (\n params: FindEdgesConnectedToParams,\n ) => Promise<readonly EdgeRow[]>;\n\n // === Collection Query Operations ===\n findNodesByKind: (\n params: FindNodesByKindParams,\n ) => Promise<readonly NodeRow[]>;\n countNodesByKind: (params: CountNodesByKindParams) => Promise<number>;\n findEdgesByKind: (\n params: FindEdgesByKindParams,\n ) => Promise<readonly EdgeRow[]>;\n countEdgesByKind: (params: CountEdgesByKindParams) => Promise<number>;\n\n // === Unique Constraint Operations ===\n insertUnique: (params: InsertUniqueParams) => Promise<void>;\n deleteUnique: (params: DeleteUniqueParams) => Promise<void>;\n checkUnique: (params: CheckUniqueParams) => Promise<UniqueRow | undefined>;\n checkUniqueBatch?: (\n params: CheckUniqueBatchParams,\n ) => Promise<readonly UniqueRow[]>;\n\n // === Schema Operations ===\n getActiveSchema: (graphId: string) => Promise<SchemaVersionRow | undefined>;\n getSchemaVersion: (\n graphId: string,\n version: number,\n ) => Promise<SchemaVersionRow | undefined>;\n /**\n * Atomically inserts a new schema version and activates it as a single\n * transactional unit, with optimistic compare-and-swap on the currently\n * active version.\n *\n * - If `expected.kind === \"active\"` and the actual active version\n * differs, throws `StaleVersionError` (caller should refetch and\n * retry).\n * - If a row already exists at `params.version` with the same\n * `schemaHash`, returns it idempotently — reactivating it if it was\n * left inactive by an earlier crashed commit.\n * - If a row already exists at `params.version` with a different\n * `schemaHash`, throws `SchemaContentConflictError`.\n *\n * Requires `capabilities.transactions === true`. On non-transactional\n * backends (e.g. Cloudflare D1, drizzle-orm/neon-http) this method\n * throws `ConfigurationError` rather than running with degraded\n * atomicity that would silently re-introduce the orphan-row crash\n * window the primitive exists to eliminate.\n */\n commitSchemaVersion: (\n params: CommitSchemaVersionParams,\n ) => Promise<SchemaVersionRow>;\n /**\n * Atomically flips the active schema pointer to an existing version,\n * with optimistic compare-and-swap on the currently active version.\n * Used by `rollbackSchema` and any other \"promote/demote existing\n * version\" workflow. Throws `StaleVersionError` on CAS mismatch and\n * `MigrationError` if the target version row does not exist.\n *\n * Same transactional requirements as `commitSchemaVersion`.\n */\n setActiveVersion: (params: SetActiveVersionParams) => Promise<void>;\n\n // === Embedding Operations (optional - depends on vector capabilities) ===\n upsertEmbedding?: (params: UpsertEmbeddingParams) => Promise<void>;\n deleteEmbedding?: (params: DeleteEmbeddingParams) => Promise<void>;\n vectorSearch?: (\n params: VectorSearchParams,\n ) => Promise<readonly VectorSearchResult[]>;\n createVectorIndex?: (params: CreateVectorIndexParams) => Promise<void>;\n dropVectorIndex?: (params: DropVectorIndexParams) => Promise<void>;\n\n // === Fulltext Operations (optional - depends on fulltext capabilities) ===\n upsertFulltext?: (params: UpsertFulltextParams) => Promise<void>;\n deleteFulltext?: (params: DeleteFulltextParams) => Promise<void>;\n /**\n * Batched variant of `upsertFulltext`. Optional — callers fall back to\n * per-row `upsertFulltext` when unset.\n */\n upsertFulltextBatch?: (params: UpsertFulltextBatchParams) => Promise<void>;\n /**\n * Batched variant of `deleteFulltext`. Optional — callers fall back to\n * per-row `deleteFulltext` when unset.\n */\n deleteFulltextBatch?: (params: DeleteFulltextBatchParams) => Promise<void>;\n fulltextSearch?: (\n params: FulltextSearchParams,\n ) => Promise<readonly FulltextSearchResult[]>;\n\n // === Index Materialization (used by store.materializeIndexes) ===\n /**\n * Idempotently ensure ONLY the `typegraph_index_materializations`\n * table exists — separate from `bootstrapTables` so that\n * `materializeIndexes` doesn't pull in the full base-table DDL set\n * just to access the status table.\n *\n * Why focused: `bootstrapTables` issues 20+ `CREATE TABLE / CREATE\n * INDEX IF NOT EXISTS` statements covering every base table. Two\n * concurrent calls (e.g. two replicas of the same `schema_doc` both\n * starting up and calling `materializeIndexes`) race on\n * Postgres SHARE locks and DEADLOCK. Restricting the ensure-step to\n * the single status table eliminates the cross-table race entirely\n * — concurrent `CREATE TABLE IF NOT EXISTS` for one specific table\n * is well-behaved on Postgres.\n */\n ensureIndexMaterializationsTable?: () => Promise<void>;\n\n /**\n * Look up a recorded materialization for a declared index by its\n * physical SQL index name. Returns `undefined` if no row exists.\n */\n getIndexMaterialization?: (\n indexName: string,\n ) => Promise<IndexMaterializationRow | undefined>;\n /**\n * Bulk variant of `getIndexMaterialization`: load every recorded\n * materialization whose `indexName` (status key) is in `statusKeys`,\n * in a single round-trip. Returned rows are unordered — callers index\n * by `indexName`. Optional; consumers fall back to per-key\n * `getIndexMaterialization` when unset.\n */\n getIndexMaterializations?: (\n statusKeys: readonly string[],\n ) => Promise<readonly IndexMaterializationRow[]>;\n /**\n * Upsert a materialization attempt — success or failure. Failure rows\n * preserve any prior `materializedAt` so the historical successful\n * timestamp survives across error windows.\n */\n recordIndexMaterialization?: (\n params: RecordIndexMaterializationParams,\n ) => Promise<void>;\n\n // === Contribution Materialization (#135 — durable strategy-owned\n // storage marker, sibling of the index status table) ===\n\n /**\n * Idempotently ensure ONLY the\n * `typegraph_contribution_materializations` table exists. Same\n * focused-bootstrap rationale as `ensureIndexMaterializationsTable`:\n * a single `CREATE TABLE IF NOT EXISTS` is concurrency-safe under\n * replica startup, where the full `bootstrapTables` set risks a\n * Postgres SHARE-lock deadlock.\n */\n ensureContributionMaterializationsTable?: () => Promise<void>;\n\n /**\n * Look up the durable materialization marker for one strategy-owned\n * contribution identity. Returns `undefined` when no row exists\n * (\"never initialized\").\n */\n getContributionMaterialization?: (\n identity: ContributionMaterializationIdentity,\n ) => Promise<ContributionMaterializationRow | undefined>;\n\n /**\n * Upsert a contribution-materialization attempt — success or failure.\n * Failure rows preserve any prior `materializedAt` via COALESCE so a\n * later failed re-attempt doesn't erase the historical success.\n */\n recordContributionMaterialization?: (\n params: RecordContributionMaterializationParams,\n ) => Promise<void>;\n\n /**\n * Resolve (once per backend instance, cached) and assert the durable\n * materialization markers for every `runtimeEnsure` contribution this\n * backend's strategy declares, for `graphId`. Throws\n * `StoreNotInitializedError` when a marker is missing, stale\n * (signature drift), or recorded a failed last attempt.\n *\n * This is the single read-side gate the fulltext hot-path wrappers\n * and `store.transaction()` consult. It performs ZERO DDL and ZERO\n * marker writes — initialization is the exclusive job of the async\n * boot path (`createStoreWithSchema` → `ensureRuntimeContributions`).\n */\n assertRuntimeContributionsInitialized?: (graphId: string) => Promise<void>;\n\n // === Kind Removal Status ===\n\n /**\n * Bootstraps the per-deployment `typegraph_kind_removals` table so\n * `store.removeKinds()` and `store.materializeRemovals()` can persist\n * removal status. Mirrors the focused-bootstrap rationale documented\n * on `ensureIndexMaterializationsTable` — the full `bootstrapTables`\n * touches every base table and risks Postgres SHARE-lock deadlock\n * under concurrent replica startup.\n */\n ensureKindRemovalsTable?: () => Promise<void>;\n\n /**\n * List graph-extension kind removals whose data-cleanup pass has not yet\n * succeeded for this `graphId`. Returns rows with\n * `removedAt: undefined`. Order is unspecified; callers materialize\n * one-at-a-time and don't depend on it.\n */\n getPendingKindRemovals?: (\n graphId: string,\n ) => Promise<readonly KindRemovalRow[]>;\n\n /**\n * List ALL kind-removal rows for a `graphId` — pending and completed.\n * Used by `materializeRemovals()` reconciliation to detect rows that\n * are missing entirely (the `removeKinds()` crash window) versus\n * already completed. Without this distinction the reconciler would\n * have to upsert every expected historical removal on every call,\n * churning `last_attempted_at` on rows that long since succeeded.\n * Order is unspecified.\n */\n getAllKindRemovals?: (graphId: string) => Promise<readonly KindRemovalRow[]>;\n\n /**\n * Upsert a kind-removal status row. `removedAt: undefined` records\n * the pending state at schema-commit time; `removedAt: <iso>`\n * marks the data cleanup successful. The COALESCE rule on `removedAt`\n * mirrors `recordIndexMaterialization` so a later failure doesn't\n * clobber the historical successful timestamp from another replica.\n */\n recordKindRemoval?: (params: RecordKindRemovalParams) => Promise<void>;\n\n // === Reconciliation Watermark ===\n\n /**\n * Bootstraps the per-deployment `typegraph_reconciliation_markers`\n * table so `materializeRemovals()` can persist reconciliation\n * progress. Same focused-bootstrap rationale as the other status\n * tables — full `bootstrapTables` risks Postgres SHARE-lock\n * deadlock under concurrent replica startup.\n */\n ensureReconciliationMarkersTable?: () => Promise<void>;\n\n // === Table Contributions (#129) ===\n\n /**\n * Materializes every contribution flagged `runtimeEnsure` — the\n * strategy-owned runtime tables (fulltext today) that drizzle-kit-\n * managed setups don't create. Called once after a successful schema\n * load. Deliberately scoped: base/drizzle-visible tables are\n * `runtimeEnsure: false`, so this does not regress startup into\n * broad DDL/probing across every table.\n *\n * The canonical durable-marker writer (#135): for each runtime\n * contribution it short-circuits when the marker already records a\n * matching signature, otherwise runs the idempotent `createDdl` and\n * records the marker (success or failure) keyed by `graphId`.\n */\n ensureRuntimeContributions?: (graphId: string) => Promise<void>;\n\n /**\n * Bootstraps the fulltext storage table the active `FulltextStrategy`\n * owns. Same focused-bootstrap rationale as the other `ensure*Table`\n * methods: idempotent and concurrency-safe under replica startup.\n *\n * Superseded by `ensureRuntimeContributions()` (#129); retained as\n * a thin back-compat wrapper for backends/callers predating #129. Not\n * machine-`@deprecated` because the manager still calls it as the\n * pre-#129 fallback. #135 removed the remaining hot-path callers and\n * routed this through the durable-marker writer.\n */\n ensureFulltextTable?: (graphId: string) => Promise<void>;\n\n /**\n * Read the high-water mark schema version for which\n * `materializeRemovals` reconciliation has already verified history\n * for `graphId`. Returns `undefined` when no marker has been\n * recorded yet. Used to skip already-checked transitions in the\n * recovery walk.\n */\n getReconciliationMarker?: (graphId: string) => Promise<number | undefined>;\n\n /**\n * Persist the reconciliation high-water mark for `graphId`. Called\n * after `materializeRemovals` completes a clean walk; subsequent\n * calls walk only versions newer than this marker. Idempotent\n * upsert by `graphId`.\n */\n setReconciliationMarker?: (graphId: string, version: number) => Promise<void>;\n\n // === Graph Lifecycle ===\n /**\n * Hard-deletes all data for a graph (nodes, edges, uniques, embeddings, schema versions).\n * Intended for import-replacement workflows. No hooks, no per-row logic.\n */\n clearGraph: (graphId: string) => Promise<void>;\n\n /**\n * Creates the base TypeGraph tables if they don't already exist.\n *\n * Called automatically by `createStoreWithSchema()` when a fresh database\n * is detected. Users who manage DDL themselves via `createStore()` never\n * hit this path.\n */\n bootstrapTables?: () => Promise<void>;\n\n /**\n * Refreshes the backend's query-planner statistics.\n *\n * Call this once after a large initial import or bulk backfill. Without\n * up-to-date statistics, the planner can pick suboptimal execution plans\n * — on PostgreSQL this is the difference between a 0.5ms and a 5ms\n * forward traversal; on SQLite it's the difference between 0.9ms and\n * 23ms fulltext search. Autovacuum / background statistics collection\n * will catch up eventually, but calling this explicitly after a bulk\n * load gives you correct latencies immediately.\n *\n * Implementations:\n * - SQLite runs `ANALYZE`, which populates `sqlite_stat1`\n * - PostgreSQL runs `ANALYZE` on the TypeGraph-managed tables\n *\n * Safe to call at any time; costs a few tens of milliseconds on the\n * sizes this library is designed for.\n */\n refreshStatistics: () => Promise<void>;\n\n // === Query Execution ===\n execute: <T>(query: SQL) => Promise<readonly T[]>;\n\n /** Execute pre-compiled SQL text with bound parameters. Available on sync SQLite and pg backends. */\n executeRaw?: <T>(\n sqlText: string,\n params: readonly unknown[],\n ) => Promise<readonly T[]>;\n\n /** Compile a Drizzle SQL object to { sql, params } without executing. */\n compileSql?: (\n query: SQL,\n ) => Readonly<{ sql: string; params: readonly unknown[] }>;\n\n /**\n * Execute a DDL statement that returns no rows (CREATE INDEX,\n * CREATE TABLE, ALTER TABLE, etc.). Separate from `executeRaw`\n * because some drivers (better-sqlite3) require `.run()` for DDL\n * and `.all()` for queries — the ambiguity can't be resolved by\n * inspecting the SQL string portably.\n *\n * Postgres path can use this for `CREATE INDEX CONCURRENTLY`, which\n * cannot run inside a transaction. Implementations must execute the\n * statement outside `transaction(...)`.\n */\n executeDdl?: (ddl: string) => Promise<void>;\n\n // === Transaction ===\n /**\n * `fn` receives the tx-scoped backend and the raw Drizzle handle\n * **bound to that same transaction** (`AdoptedTransaction`). The\n * store surfaces the second argument as `TransactionContext.sql` so\n * callers can write their own relational tables inside the\n * graph-owned transaction. Implementations MUST pass the *exact*\n * handle the tx-scoped backend writes through (the Postgres/libsql\n * tx handle; for better-sqlite3 / do-sqlite the bound connection),\n * never a fresh one.\n */\n transaction: <T>(\n fn: (tx: TransactionBackend, sql: AdoptedTransaction) => Promise<T>,\n options?: TransactionOptions,\n ) => Promise<T>;\n\n /**\n * Adopt a caller-owned, already-open transaction (#134).\n *\n * Returns a transaction-scoped backend bound to the *exact*\n * `externalTx` client, reusing this backend's already-resolved\n * schema/strategy config — no `createStoreWithSchema` / `evolve` /\n * `migrateSchema`, and **no DDL inside the caller's business\n * transaction**. The caller owns `BEGIN`/`COMMIT`/`ROLLBACK`; this\n * method neither opens nor closes a transaction. Async drivers\n * (node-postgres, `neon-serverless` Pool, libsql) wrap with\n * `db.transaction(async …)`; synchronous `better-sqlite3` must instead\n * issue explicit `BEGIN`/`COMMIT`/`ROLLBACK` (its driver rejects an\n * `async` transaction callback).\n *\n * Optional and presence-detected like the other capability-scoped\n * members: only the Drizzle Postgres/SQLite backends provide it.\n * Implementations MUST throw (not silently degrade) when\n * `capabilities.transactions` is `false` — a non-atomic fallback is\n * safe for graph-only writes but dangerous for cross-store flows,\n * where the caller's relational write *would* still commit.\n *\n * Fulltext stays safe by construction: the returned backend's\n * fulltext methods assert the durable materialization marker (a\n * cached SELECT, never DDL) at point of use and throw\n * `StoreNotInitializedError` on a missing/stale/failed marker rather\n * than migrating mid-transaction. Prefer booting the parent store via\n * `createStoreWithSchema` so that assertion is a warm-cache no-op.\n */\n adoptTransaction?: (externalTx: AdoptedTransaction) => TransactionBackend;\n\n // === Lifecycle ===\n close: () => Promise<void>;\n}>;\n\n// ============================================================\n// Managed Backend Helper\n// ============================================================\n\n/**\n * Wraps a GraphBackend with idempotent close that also runs a teardown\n * callback (e.g. closing the underlying database connection).\n */\nexport function wrapWithManagedClose(\n backend: GraphBackend,\n teardown: () => void | Promise<void>,\n): GraphBackend {\n let isClosed = false;\n return {\n ...backend,\n async close(): Promise<void> {\n if (isClosed) return;\n isClosed = true;\n await backend.close();\n await teardown();\n },\n };\n}\n\n/**\n * Runs `fn` inside a transaction when the backend supports one, falling\n * through to a direct invocation otherwise. Lets call sites benefit from\n * atomicity on backends that have transactions while staying functional\n * on backends that don't (Cloudflare D1, `drizzle-orm/neon-http` over\n * HTTP). The single-statement race window is already implicit on any\n * backend that reports `transactions: false`; callers that cannot\n * tolerate it must branch on the capability themselves.\n *\n * Pass `fallback` only when the toplevel backend method would recurse\n * — pass the operation-level backend so the no-tx path doesn't loop\n * back through the same toplevel method.\n */\nexport async function runOptionallyInTransaction<T>(\n backend: GraphBackend,\n fn: (target: GraphBackend | TransactionBackend) => Promise<T>,\n fallback?: GraphBackend | TransactionBackend,\n): Promise<T> {\n if (!backend.capabilities.transactions) {\n return fn(fallback ?? backend);\n }\n return backend.transaction((tx) => fn(tx));\n}\n\n// ============================================================\n// Additional Parameter Types\n// ============================================================\n\n/**\n * Parameters for inserting a unique constraint entry.\n */\nexport type InsertUniqueParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n key: string;\n nodeId: string;\n concreteKind: string;\n}>;\n\n/**\n * Parameters for deleting a unique constraint entry.\n */\nexport type DeleteUniqueParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n key: string;\n}>;\n\n/**\n * Parameters for checking a unique constraint.\n */\nexport type CheckUniqueParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n key: string;\n /** If true, also returns soft-deleted entries. Used by get-or-create operations. */\n includeDeleted?: boolean;\n}>;\n\n/**\n * Parameters for batch-checking unique constraints.\n */\nexport type CheckUniqueBatchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n keys: readonly string[];\n /** If true, also returns soft-deleted entries. Used by get-or-create operations. */\n includeDeleted?: boolean;\n}>;\n\n/**\n * Parameters for inserting a schema version.\n *\n * Used internally by backend implementations. Public callers go through\n * `commitSchemaVersion`, which handles the insert + activate atomically\n * with CAS guarantees.\n */\nexport type InsertSchemaParams = Readonly<{\n graphId: string;\n version: number;\n schemaHash: string;\n schemaDoc: SerializedSchema;\n isActive: boolean;\n}>;\n\n/**\n * The caller's claim about the currently-active schema version, used as\n * the optimistic compare-and-swap guard for `commitSchemaVersion`.\n *\n * - `{ kind: \"initial\" }` — caller is committing the first-ever version\n * for this graph and asserts no active version exists yet.\n * - `{ kind: \"active\", version: N }` — caller observed version N as\n * active and is committing version N+1 against that baseline. The\n * commit fails with `StaleVersionError` if some other writer has\n * advanced or rolled back the pointer in the meantime.\n *\n * Tagged-union form (rather than a magic `version: 0` sentinel) because\n * the two cases have materially different semantics: the initial path\n * skips the \"deactivate prior\" UPDATE, and the no-active-row state is\n * a *valid* expected state, not an out-of-band signal.\n */\nexport type CommitSchemaVersionExpected =\n | Readonly<{ kind: \"initial\" }>\n | Readonly<{ kind: \"active\"; version: number }>;\n\n/**\n * Parameters for `commitSchemaVersion`.\n */\nexport type CommitSchemaVersionParams = Readonly<{\n graphId: string;\n /** CAS guard — see `CommitSchemaVersionExpected`. */\n expected: CommitSchemaVersionExpected;\n /** The new version to insert and activate. */\n version: number;\n schemaHash: string;\n schemaDoc: SerializedSchema;\n}>;\n\n/**\n * Parameters for `setActiveVersion`.\n *\n * Flips the active pointer from `expected` to `version` for an existing\n * row. CAS prevents overwriting a concurrent rollback or commit.\n */\nexport type SetActiveVersionParams = Readonly<{\n graphId: string;\n /** CAS guard. Same semantics as `commitSchemaVersion.expected`. */\n expected: CommitSchemaVersionExpected;\n /** The version to mark active. Must already exist. */\n version: number;\n}>;\n\n/**\n * Parameters for counting edges from a source node.\n */\nexport type CountEdgesFromParams = Readonly<{\n graphId: string;\n edgeKind: string;\n fromKind: string;\n fromId: string;\n /** If true, only count edges where valid_to IS NULL */\n activeOnly?: boolean;\n}>;\n\n/**\n * Parameters for checking if an edge exists between two nodes.\n */\nexport type EdgeExistsBetweenParams = Readonly<{\n graphId: string;\n edgeKind: string;\n fromKind: string;\n fromId: string;\n toKind: string;\n toId: string;\n}>;\n\n/**\n * Parameters for finding edges connected to a node.\n */\nexport type FindEdgesConnectedToParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n}>;\n\n/**\n * Parameters for finding nodes by kind.\n */\nexport type FindNodesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n /** Max rows to return. */\n limit?: number;\n /** Offset. Present for backward compat; rebuild uses `after` instead. */\n offset?: number;\n /** If true, exclude deleted nodes. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n /**\n * Stable ordering for keyset pagination. Default: \"created_at\" (existing\n * behavior). Rebuild should use \"id\" for iteration that is stable under\n * concurrent writes and shared timestamps.\n */\n orderBy?: \"id\" | \"created_at\";\n /**\n * Keyset cursor. Returns rows strictly greater (by `orderBy`) than this\n * value. When `orderBy: \"id\"`, compared lexicographically. Mutually\n * exclusive with `offset` — callers pick one.\n */\n after?: string;\n}>;\n\n/**\n * Parameters for counting nodes by kind.\n */\nexport type CountNodesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n /** If true, exclude deleted nodes. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n}>;\n\n/**\n * Parameters for finding edges by kind.\n */\nexport type FindEdgesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n fromKind?: string;\n fromId?: string;\n toKind?: string;\n toId?: string;\n limit?: number;\n offset?: number;\n /** If true, exclude deleted edges. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n}>;\n\n/**\n * Parameters for counting edges by kind.\n */\nexport type CountEdgesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n fromKind?: string;\n fromId?: string;\n toKind?: string;\n toId?: string;\n /** If true, exclude deleted edges. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n}>;\n\n// ============================================================\n// Default Capabilities\n// ============================================================\n\n/**\n * Default capabilities for SQLite.\n */\nexport const SQLITE_CAPABILITIES: BackendCapabilities = {\n transactions: true, // SQLite supports transactions\n};\n\n/**\n * Default capabilities for PostgreSQL.\n */\nexport const POSTGRES_CAPABILITIES: BackendCapabilities = {\n transactions: true, // PostgreSQL supports transactions\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors/index.ts"],"names":[],"mappings":"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","file":"chunk-G6P3OVDY.cjs","sourcesContent":["/**\n * TypeGraph Error Hierarchy\n *\n * All errors extend TypeGraphError with:\n * - `code`: Machine-readable error code for programmatic handling\n * - `category`: Classification for error handling strategies\n * - `suggestion`: Optional recovery guidance for users\n * - `details`: Structured context about the error\n *\n * @example\n * ```typescript\n * try {\n * await store.nodes.Person.create({ name: \"\" });\n * } catch (error) {\n * if (isTypeGraphError(error)) {\n * console.error(error.toUserMessage());\n * if (isUserRecoverable(error)) {\n * // Show to user for correction\n * }\n * }\n * }\n * ```\n */\n\nimport type { KindEntity } from \"../core/types\";\n// Type-only import: `materialize-indexes.ts` value-imports\n// `ConfigurationError` from this file, but type-only imports are erased\n// at runtime so this back-edge does not create a value cycle.\nimport type { MaterializeIndexesResult } from \"../store/materialize-indexes\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/**\n * Error category for programmatic handling.\n *\n * - `user`: Caused by invalid input or incorrect usage. Recoverable by fixing input.\n * - `constraint`: Business rule or schema constraint violation. Recoverable by changing data.\n * - `system`: Internal error or infrastructure issue. May require investigation or retry.\n */\nexport type ErrorCategory = \"user\" | \"constraint\" | \"system\";\n\n/**\n * Options for TypeGraphError constructor.\n */\nexport type TypeGraphErrorOptions = Readonly<{\n /** Structured context about the error */\n details?: Record<string, unknown>;\n /** Error category for handling strategies */\n category: ErrorCategory;\n /** Recovery guidance for users */\n suggestion?: string;\n /** Underlying cause of the error */\n cause?: unknown;\n}>;\n\nfunction formatCause(cause: unknown): string {\n if (cause instanceof Error) {\n return cause.stack ?? cause.message;\n }\n if (typeof cause === \"string\") {\n return cause;\n }\n if (\n typeof cause === \"number\" ||\n typeof cause === \"boolean\" ||\n typeof cause === \"bigint\"\n ) {\n return String(cause);\n }\n if (typeof cause === \"symbol\") {\n return cause.description ?? \"Symbol\";\n }\n if (cause === undefined) {\n return \"Unknown cause\";\n }\n\n try {\n return JSON.stringify(cause);\n } catch (error) {\n return `Unserializable cause: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`;\n }\n}\n\n// ============================================================\n// Base Error\n// ============================================================\n\n/**\n * Base error class for all TypeGraph errors.\n *\n * Provides structured error information for both programmatic handling\n * and user-friendly messages.\n */\nexport class TypeGraphError extends Error {\n /** Machine-readable error code (e.g., \"VALIDATION_ERROR\") */\n readonly code: string;\n\n /** Error category for handling strategies */\n readonly category: ErrorCategory;\n\n /** Structured context about the error */\n readonly details: Readonly<Record<string, unknown>>;\n\n /** Recovery guidance for users */\n readonly suggestion?: string;\n\n constructor(message: string, code: string, options: TypeGraphErrorOptions) {\n super(message, options.cause ? { cause: options.cause } : undefined);\n this.name = \"TypeGraphError\";\n this.code = code;\n this.category = options.category;\n this.details = Object.freeze(options.details ?? {});\n if (options.suggestion !== undefined) {\n this.suggestion = options.suggestion;\n }\n }\n\n /**\n * Returns a user-friendly error message with suggestion if available.\n */\n toUserMessage(): string {\n if (this.suggestion) {\n return `${this.message}\\n\\nSuggestion: ${this.suggestion}`;\n }\n return this.message;\n }\n\n /**\n * Returns a detailed string representation for logging.\n */\n toLogString(): string {\n const lines = [\n `[${this.code}] ${this.message}`,\n ` Category: ${this.category}`,\n ];\n\n if (this.suggestion) {\n lines.push(` Suggestion: ${this.suggestion}`);\n }\n\n const detailKeys = Object.keys(this.details);\n if (detailKeys.length > 0) {\n lines.push(` Details: ${JSON.stringify(this.details)}`);\n }\n\n if (this.cause) {\n lines.push(` Cause: ${formatCause(this.cause)}`);\n }\n\n return lines.join(\"\\n\");\n }\n}\n\n// ============================================================\n// Validation Errors (category: \"user\")\n// ============================================================\n\n/**\n * Validation issue from Zod or custom validation.\n */\nexport type ValidationIssue = Readonly<{\n /** Path to the invalid field (e.g., \"address.city\") */\n path: string;\n /** Human-readable error message */\n message: string;\n /** Zod error code if from Zod validation */\n code?: string;\n}>;\n\n/**\n * Details for ValidationError.\n */\nexport type ValidationErrorDetails = Readonly<{\n /** Type of entity being validated */\n entityType?: KindEntity;\n /** Kind/type name of the entity */\n kind?: string;\n /** Operation being performed */\n operation?: \"create\" | \"update\";\n /** Entity ID if updating */\n id?: string;\n /** Individual validation issues */\n issues: readonly ValidationIssue[];\n}>;\n\n/**\n * Thrown when schema validation fails during node or edge operations.\n *\n * @example\n * ```typescript\n * try {\n * await store.nodes.Person.create({ email: \"invalid\" });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.log(error.details.issues);\n * // [{ path: \"email\", message: \"Invalid email\" }]\n * }\n * }\n * ```\n */\nexport class ValidationError extends TypeGraphError {\n declare readonly details: ValidationErrorDetails;\n\n constructor(\n message: string,\n details: ValidationErrorDetails,\n options?: { cause?: unknown; suggestion?: string },\n ) {\n const fieldList =\n details.issues.length > 0 ?\n details.issues.map((index) => index.path || \"(root)\").join(\", \")\n : \"unknown\";\n\n super(message, \"VALIDATION_ERROR\", {\n details,\n category: \"user\",\n suggestion:\n options?.suggestion ??\n `Check the following fields: ${fieldList}. See error.details.issues for specific validation failures.`,\n cause: options?.cause,\n });\n this.name = \"ValidationError\";\n }\n}\n\n// ============================================================\n// Not Found Errors (category: \"user\")\n// ============================================================\n\n/**\n * Thrown when a node is not found.\n *\n * @example\n * ```typescript\n * try {\n * await store.nodes.Person.get(\"nonexistent-id\");\n * } catch (error) {\n * if (error instanceof NodeNotFoundError) {\n * console.log(error.details.kind, error.details.id);\n * }\n * }\n * ```\n */\nexport class NodeNotFoundError extends TypeGraphError {\n constructor(kind: string, id: string, options?: { cause?: unknown }) {\n super(`Node not found: ${kind}/${id}`, \"NODE_NOT_FOUND\", {\n details: { kind, id },\n category: \"user\",\n suggestion: `Verify the node ID \"${id}\" exists and has not been deleted.`,\n cause: options?.cause,\n });\n this.name = \"NodeNotFoundError\";\n }\n}\n\n/**\n * Thrown when an edge is not found.\n */\nexport class EdgeNotFoundError extends TypeGraphError {\n constructor(kind: string, id: string, options?: { cause?: unknown }) {\n super(`Edge not found: ${kind}/${id}`, \"EDGE_NOT_FOUND\", {\n details: { kind, id },\n category: \"user\",\n suggestion: `Verify the edge ID \"${id}\" exists and has not been deleted.`,\n cause: options?.cause,\n });\n this.name = \"EdgeNotFoundError\";\n }\n}\n\n/**\n * Thrown when an operation references a kind that isn't registered on\n * the graph — `getNodeCollectionOrThrow` against an unknown kind, a\n * `materializeIndexes({ kinds })` filter naming a missing kind, an\n * extension referencing an unresolved endpoint, search facade typos,\n * etc. Carries the offending `kindName` and `entity` plus the host\n * `graphId` so logs are unambiguous when multiple stores share a\n * process.\n */\nexport class KindNotFoundError extends TypeGraphError {\n readonly kindName: string;\n readonly entity: KindEntity;\n\n constructor(\n kindName: string,\n entity: KindEntity,\n options?: Readonly<{\n graphId?: string;\n suggestion?: string;\n cause?: unknown;\n }>,\n ) {\n const where =\n options?.graphId === undefined ? \"\" : ` on graph \"${options.graphId}\"`;\n super(\n `${entity === \"node\" ? \"Node\" : \"Edge\"} kind \"${kindName}\" is not registered${where}.`,\n \"KIND_NOT_FOUND\",\n {\n details: {\n kindName,\n entity,\n ...(options?.graphId === undefined ?\n {}\n : { graphId: options.graphId }),\n },\n category: \"user\",\n suggestion:\n options?.suggestion ??\n \"Compile-time kinds come from defineGraph; extension kinds appear after store.evolve() returns. Check store.introspect() for the registered set.\",\n cause: options?.cause,\n },\n );\n this.name = \"KindNotFoundError\";\n this.kindName = kindName;\n this.entity = entity;\n }\n}\n\n/**\n * Thrown when a uniqueness constraint name is not found on a node kind.\n */\nexport class NodeConstraintNotFoundError extends TypeGraphError {\n constructor(\n constraintName: string,\n kind: string,\n options?: { cause?: unknown },\n ) {\n super(\n `Constraint not found: \"${constraintName}\" on node kind \"${kind}\"`,\n \"CONSTRAINT_NOT_FOUND\",\n {\n details: { constraintName, kind },\n category: \"user\",\n suggestion: `Verify the constraint name \"${constraintName}\" is defined in the unique constraints for \"${kind}\".`,\n cause: options?.cause,\n },\n );\n this.name = \"NodeConstraintNotFoundError\";\n }\n}\n\n// ============================================================\n// Constraint Errors (category: \"constraint\")\n// ============================================================\n\n/**\n * Thrown when edge endpoint node does not exist or is deleted.\n */\nexport class EndpointNotFoundError extends TypeGraphError {\n constructor(\n details: Readonly<{\n edgeKind: string;\n endpoint: \"from\" | \"to\";\n nodeKind: string;\n nodeId: string;\n }>,\n options?: { cause?: unknown },\n ) {\n super(\n `Endpoint node not found for edge \"${details.edgeKind}\": ${details.nodeKind}/${details.nodeId} (${details.endpoint})`,\n \"ENDPOINT_NOT_FOUND\",\n {\n details,\n category: \"constraint\",\n suggestion: `Ensure the ${details.endpoint} node exists before creating the edge.`,\n cause: options?.cause,\n },\n );\n this.name = \"EndpointNotFoundError\";\n }\n}\n\n/**\n * Thrown when edge endpoint has wrong node type.\n */\nexport class EndpointError extends TypeGraphError {\n constructor(\n details: Readonly<{\n edgeKind: string;\n endpoint: \"from\" | \"to\";\n actualKind: string;\n expectedKinds: readonly string[];\n }>,\n options?: { cause?: unknown },\n ) {\n const expected = details.expectedKinds.join(\" | \");\n super(\n `Invalid ${details.endpoint} endpoint for edge \"${details.edgeKind}\": got \"${details.actualKind}\", expected ${expected}`,\n \"ENDPOINT_ERROR\",\n {\n details,\n category: \"constraint\",\n suggestion: `Use a node of type ${expected} as the ${details.endpoint} endpoint.`,\n cause: options?.cause,\n },\n );\n this.name = \"EndpointError\";\n }\n}\n\n/**\n * Thrown when uniqueness constraint is violated.\n */\nexport class UniquenessError extends TypeGraphError {\n constructor(\n details: Readonly<{\n constraintName: string;\n kind: string;\n existingId: string;\n newId: string;\n fields: readonly string[];\n }>,\n options?: { cause?: unknown },\n ) {\n const fieldList = details.fields.join(\", \");\n super(\n `Uniqueness violation on \"${details.kind}\": constraint \"${details.constraintName}\" (fields: ${fieldList}) conflicts with existing node ${details.existingId}`,\n \"UNIQUENESS_VIOLATION\",\n {\n details,\n category: \"constraint\",\n suggestion: `Change the values for fields [${fieldList}] to be unique, or update the existing node ${details.existingId} instead.`,\n cause: options?.cause,\n },\n );\n this.name = \"UniquenessError\";\n }\n}\n\n/**\n * Thrown when cardinality constraint is violated.\n */\nexport class CardinalityError extends TypeGraphError {\n constructor(\n details: Readonly<{\n edgeKind: string;\n fromKind: string;\n fromId: string;\n cardinality: string;\n existingCount: number;\n }>,\n options?: { cause?: unknown },\n ) {\n super(\n `Cardinality violation: \"${details.edgeKind}\" from ${details.fromKind}/${details.fromId} allows \"${details.cardinality}\" but ${details.existingCount} edge(s) already exist`,\n \"CARDINALITY_ERROR\",\n {\n details,\n category: \"constraint\",\n suggestion:\n details.cardinality === \"one\" || details.cardinality === \"unique\" ?\n `Delete the existing edge before creating a new one, or use cardinality \"many\".`\n : `Check if the cardinality constraint \"${details.cardinality}\" is correct for your use case.`,\n cause: options?.cause,\n },\n );\n this.name = \"CardinalityError\";\n }\n}\n\n/**\n * Thrown when disjointness constraint is violated.\n *\n * Disjoint types cannot share the same ID - a node cannot be both\n * a Person and an Organization if they are declared disjoint.\n */\nexport class DisjointError extends TypeGraphError {\n constructor(\n details: Readonly<{\n nodeId: string;\n attemptedKind: string;\n conflictingKind: string;\n }>,\n options?: { cause?: unknown },\n ) {\n super(\n `Disjoint constraint violation: cannot create ${details.attemptedKind} with ID \"${details.nodeId}\" - conflicts with existing ${details.conflictingKind}`,\n \"DISJOINT_ERROR\",\n {\n details,\n category: \"constraint\",\n suggestion: `Use a different ID for the new ${details.attemptedKind} node, or delete the existing ${details.conflictingKind}/${details.nodeId} first.`,\n cause: options?.cause,\n },\n );\n this.name = \"DisjointError\";\n }\n}\n\n/**\n * Thrown when deletion is blocked due to existing edges (restrict behavior).\n */\nexport class RestrictedDeleteError extends TypeGraphError {\n constructor(\n details: Readonly<{\n nodeKind: string;\n nodeId: string;\n edgeCount: number;\n edgeKinds: readonly string[];\n }>,\n options?: { cause?: unknown },\n ) {\n const edgeList = details.edgeKinds.join(\", \");\n super(\n `Cannot delete ${details.nodeKind}/${details.nodeId}: ${details.edgeCount} connected edge(s) exist (${edgeList})`,\n \"RESTRICTED_DELETE\",\n {\n details,\n category: \"constraint\",\n suggestion: `Delete the connected edges first, or change onDelete behavior to \"cascade\" (auto-delete edges) or \"disconnect\" (soft-delete edges).`,\n cause: options?.cause,\n },\n );\n this.name = \"RestrictedDeleteError\";\n }\n}\n\n// ============================================================\n// Concurrency Errors (category: \"system\")\n// ============================================================\n\n/**\n * Thrown when optimistic locking detects a concurrent modification.\n *\n * This occurs when two operations try to update the same entity simultaneously.\n * The operation with the stale version fails.\n */\nexport class VersionConflictError extends TypeGraphError {\n constructor(\n details: Readonly<{\n kind: string;\n id: string;\n expectedVersion: number;\n actualVersion: number;\n }>,\n options?: { cause?: unknown },\n ) {\n super(\n `Version conflict on ${details.kind}/${details.id}: expected version ${details.expectedVersion}, found ${details.actualVersion}`,\n \"VERSION_CONFLICT\",\n {\n details,\n category: \"system\",\n suggestion: `Fetch the latest version of the entity and retry the operation. This error indicates concurrent modification.`,\n cause: options?.cause,\n },\n );\n this.name = \"VersionConflictError\";\n }\n}\n\n// ============================================================\n// Schema Errors (category: \"system\")\n// ============================================================\n\n/**\n * Thrown when the schema in code doesn't match the schema in the database.\n */\nexport class SchemaMismatchError extends TypeGraphError {\n constructor(\n details: Readonly<{\n graphId: string;\n expectedHash: string;\n actualHash: string;\n }>,\n options?: { cause?: unknown },\n ) {\n super(\n `Schema mismatch for graph \"${details.graphId}\": code schema differs from database schema`,\n \"SCHEMA_MISMATCH\",\n {\n details,\n category: \"system\",\n suggestion: `Run schema migration to update the database, or use createStoreWithSchema() for automatic migration.`,\n cause: options?.cause,\n },\n );\n this.name = \"SchemaMismatchError\";\n }\n}\n\n/**\n * Thrown when schema migration fails.\n */\nexport class MigrationError extends TypeGraphError {\n constructor(\n message: string,\n details: Readonly<{\n graphId: string;\n fromVersion: number;\n toVersion: number;\n reason?: string;\n }>,\n options?: { cause?: unknown },\n ) {\n super(message, \"MIGRATION_ERROR\", {\n details,\n category: \"system\",\n suggestion: `Review the schema changes and ensure they are backwards compatible, or implement a data migration.`,\n cause: options?.cause,\n });\n this.name = \"MigrationError\";\n }\n}\n\n/**\n * Thrown by `Store.evolve(extension, { eager })` when the schema\n * commit succeeded but the follow-on `materializeIndexes()` produced\n * one or more failed entries.\n *\n * Recovery: the schema commit is NOT rolled back. The new `Store` is\n * fully constructed and (when `options.ref` was supplied) `ref.current`\n * already points to it — the caller can read the new store via the ref\n * and decide how to handle the failed indexes (retry, skip, alert).\n * The full `MaterializeIndexesResult` is attached as `.materialization`.\n *\n * @example\n * ```ts\n * const ref = { current: store };\n * try {\n * await store.evolve(extension, { ref, eager: {} });\n * } catch (error) {\n * if (error instanceof EagerMaterializationError) {\n * // schema is committed; ref.current is the new store\n * log.warn(\n * { failed: error.failedIndexNames },\n * \"indexes did not materialize; will retry\",\n * );\n * await ref.current.materializeIndexes();\n * } else {\n * throw error;\n * }\n * }\n * ```\n */\nexport class EagerMaterializationError extends TypeGraphError {\n /**\n * The full materialization result, including successful and failed\n * entries. Same shape as `Store.materializeIndexes()` returns.\n */\n readonly materialization: MaterializeIndexesResult;\n\n constructor(materialization: MaterializeIndexesResult, graphId: string) {\n const names = collectFailedIndexNames(materialization);\n super(\n `Eager materialization failed for ${names.length} index(es) on graph \"${graphId}\": ${names.join(\", \")}. The schema commit succeeded; the new Store is available via the ref handle (when supplied) and the failed indexes can be retried via store.materializeIndexes().`,\n \"EAGER_MATERIALIZATION_FAILED\",\n {\n details: { graphId, failedIndexNames: names },\n category: \"system\",\n suggestion: `Inspect error.materialization for per-index errors. Each failure preserves any prior successful materialization timestamp; the schema is committed regardless.`,\n },\n );\n this.name = \"EagerMaterializationError\";\n this.materialization = materialization;\n }\n\n /**\n * Names of just the indexes that failed — derived from\n * `materialization.results` so the two views can never disagree.\n */\n get failedIndexNames(): readonly string[] {\n return collectFailedIndexNames(this.materialization);\n }\n}\n\nfunction collectFailedIndexNames(\n materialization: MaterializeIndexesResult,\n): readonly string[] {\n const names: string[] = [];\n for (const entry of materialization.results) {\n if (entry.status === \"failed\") names.push(entry.indexName);\n }\n return names;\n}\n\n/**\n * Thrown by `commitSchemaVersion` and `setActiveVersion` when the\n * caller's view of the active schema version is out of date — another\n * writer has already advanced it.\n *\n * Recovery: re-read the active version with `getActiveSchema(graphId)`,\n * recompute against the new baseline, and retry. This is a routine\n * concurrency signal, not a bug.\n *\n * `actual` is `0` when no active version exists yet (initial-commit race\n * where another writer initialized first).\n */\nexport class StaleVersionError extends TypeGraphError {\n declare readonly details: Readonly<{\n graphId: string;\n expected: number;\n actual: number;\n }>;\n\n constructor(\n details: Readonly<{\n graphId: string;\n expected: number;\n actual: number;\n }>,\n options?: { cause?: unknown },\n ) {\n super(\n `Schema version was advanced by another writer for graph \"${details.graphId}\": expected active version ${details.expected}, actual is ${details.actual}`,\n \"STALE_SCHEMA_VERSION\",\n {\n details,\n category: \"system\",\n suggestion: `Re-read the active schema version, recompute the new version against that baseline, and retry the commit.`,\n cause: options?.cause,\n },\n );\n this.name = \"StaleVersionError\";\n }\n}\n\n/**\n * Thrown by `commitSchemaVersion` when a row already exists at the\n * target version with a *different* schema hash — i.e. two writers\n * committed materially different schemas at the same version number.\n *\n * Distinct from `StaleVersionError`: this is not a refetch-and-retry\n * situation, it's a content disagreement that needs operator\n * intervention. Typically caused by inconsistent application\n * deployments writing schemas that hash differently.\n */\nexport class SchemaContentConflictError extends TypeGraphError {\n declare readonly details: Readonly<{\n graphId: string;\n version: number;\n existingHash: string;\n incomingHash: string;\n }>;\n\n constructor(\n details: Readonly<{\n graphId: string;\n version: number;\n existingHash: string;\n incomingHash: string;\n }>,\n options?: { cause?: unknown },\n ) {\n super(\n `Schema content conflict for graph \"${details.graphId}\" at version ${details.version}: existing hash ${details.existingHash} differs from incoming hash ${details.incomingHash}`,\n \"SCHEMA_CONTENT_CONFLICT\",\n {\n details,\n category: \"system\",\n suggestion: `Two writers committed different schemas at the same version. Reconcile the application deployments so they produce the same canonical schema, then retry.`,\n cause: options?.cause,\n },\n );\n this.name = \"SchemaContentConflictError\";\n }\n}\n\n// ============================================================\n// Configuration Errors (category: \"user\")\n// ============================================================\n\n/**\n * Thrown when graph configuration is invalid.\n *\n * This includes invalid schema definitions, ontology conflicts,\n * and other configuration issues detected at graph creation time.\n */\nexport class ConfigurationError extends TypeGraphError {\n constructor(\n message: string,\n details: Record<string, unknown> = {},\n options?: { cause?: unknown; suggestion?: string },\n ) {\n super(message, \"CONFIGURATION_ERROR\", {\n details,\n category: \"user\",\n suggestion:\n options?.suggestion ?? `Review your graph definition for errors.`,\n cause: options?.cause,\n });\n this.name = \"ConfigurationError\";\n }\n}\n\n/**\n * Why a store's strategy-owned storage is not usable on the current\n * connection. Drives the {@link StoreNotInitializedError} message and\n * is surfaced in `details.reason` for programmatic handling.\n *\n * - `missing`: no durable materialization marker exists — the database\n * was never initialized for this graph's runtime contributions.\n * - `stale`: a marker exists but its recorded signature no longer\n * matches the resolved contribution DDL (strategy swap or DDL drift).\n * The hot path refuses rather than silently re-materializing.\n * - `failed`: the most recent boot-time materialization attempt\n * recorded an error. Boot may retry; the hot path refuses.\n */\nexport type StoreNotInitializedReason = \"missing\" | \"stale\" | \"failed\";\n\nconst STORE_NOT_INITIALIZED_REASON_PHRASE: Readonly<\n Record<StoreNotInitializedReason, string>\n> = {\n missing: \"is not initialized\",\n stale: \"is stale (recorded materialization signature no longer matches)\",\n failed: \"failed its last initialization attempt\",\n};\n\n/**\n * Thrown when a fulltext-dependent operation runs against a connection\n * whose strategy-owned storage has not been durably materialized.\n *\n * `createStore()` is a synchronous, zero-I/O attach: it never creates\n * tables, repairs DDL, or writes materialization markers. The durable\n * marker is written exclusively by the async boot path\n * (`createStoreWithSchema`). When a fulltext read/write — or an\n * adopted/business transaction — observes no valid marker, it refuses\n * loudly here instead of lazily emitting DDL on the hot path.\n */\nexport class StoreNotInitializedError extends TypeGraphError {\n // `graphId`/`reason` are positional and required: both are\n // load-bearing for the message and for programmatic handling via\n // `details.reason`. Caller `details` merge on top.\n constructor(\n graphId: string,\n reason: StoreNotInitializedReason,\n options?: { cause?: unknown; details?: Record<string, unknown> },\n ) {\n super(\n `fulltext storage for graph \"${graphId}\" ${STORE_NOT_INITIALIZED_REASON_PHRASE[reason]}. ` +\n `Run createStoreWithSchema(graph, backend) during application boot, ` +\n `outside request handlers and adopted transactions, before using createStore().`,\n \"STORE_NOT_INITIALIZED\",\n {\n details: { graphId, reason, ...options?.details },\n category: \"user\",\n suggestion:\n \"Call createStoreWithSchema(graph, backend) once at application \" +\n \"startup. createStore() attaches to an already-initialized \" +\n \"database and does not materialize storage itself.\",\n cause: options?.cause,\n },\n );\n this.name = \"StoreNotInitializedError\";\n }\n}\n\n// ============================================================\n// Database Errors (category: \"system\")\n// ============================================================\n\n/**\n * Thrown when a database operation fails unexpectedly.\n *\n * This indicates a system-level failure in the database backend,\n * not a user-recoverable error.\n */\nexport class DatabaseOperationError extends TypeGraphError {\n constructor(\n message: string,\n details: Readonly<{ operation: string; entity: string }>,\n options?: { cause?: unknown },\n ) {\n super(message, \"DATABASE_OPERATION_ERROR\", {\n details,\n category: \"system\",\n suggestion: `This is a system-level database error. Check the database connection and retry the operation. If the problem persists, investigate the underlying cause.`,\n cause: options?.cause,\n });\n this.name = \"DatabaseOperationError\";\n }\n}\n\n// ============================================================\n// Vector / Embedding Errors (category: \"user\")\n// ============================================================\n\n/**\n * Thrown when an embedding field's declared dimension no longer matches the\n * dimension of its materialized per-field storage — i.e. a field's\n * `embedding(N)` was changed to `embedding(M)`. The stored vectors are invalid\n * under the new dimension and cannot be converted, only recomputed, so this is\n * a deliberate app-driven migration: call\n * `store.reembedVectorField(kind, fieldPath, ...)` to recreate the storage at\n * the new dimension and re-embed existing rows.\n */\nexport class EmbeddingDimensionChangedError extends TypeGraphError {\n constructor(\n message: string,\n details: Readonly<{\n kind: string;\n fieldPath: string;\n declaredDimensions?: number;\n storedDimensions?: number;\n }>,\n options?: { cause?: unknown },\n ) {\n super(message, \"EMBEDDING_DIMENSION_CHANGED\", {\n details,\n category: \"user\",\n suggestion: `Run store.reembedVectorField(\"${details.kind}\", \"${details.fieldPath}\", { embed }) to recreate the field's storage at the new dimension and re-embed existing rows.`,\n cause: options?.cause,\n });\n this.name = \"EmbeddingDimensionChangedError\";\n }\n}\n\n// ============================================================\n// Query Errors (category: \"system\")\n// ============================================================\n\n/**\n * Thrown when a query predicate cannot be compiled for the target database.\n */\nexport class UnsupportedPredicateError extends TypeGraphError {\n constructor(\n message: string,\n details: Readonly<Record<string, unknown>> = {},\n options?: { cause?: unknown; suggestion?: string },\n ) {\n super(message, \"UNSUPPORTED_PREDICATE\", {\n details,\n category: \"system\",\n suggestion:\n options?.suggestion ??\n `This predicate may not be supported by your database backend. Check the documentation for supported predicates.`,\n cause: options?.cause,\n });\n this.name = \"UnsupportedPredicateError\";\n }\n}\n\n// ============================================================\n// Compiler Errors (category: \"system\")\n// ============================================================\n\n/**\n * Thrown when a compiler invariant is violated.\n *\n * This indicates a bug in the query compiler — the compiler reached\n * a state that should be unreachable. These errors are not user-recoverable.\n */\nexport class CompilerInvariantError extends TypeGraphError {\n constructor(\n message: string,\n details?: Readonly<Record<string, unknown>>,\n options?: { cause?: unknown },\n ) {\n super(message, \"COMPILER_INVARIANT_ERROR\", {\n details: details ?? {},\n category: \"system\",\n suggestion: `This is an internal compiler error. Please report it as a bug with the query that triggered it.`,\n cause: options?.cause,\n });\n this.name = \"CompilerInvariantError\";\n }\n}\n\n// ============================================================\n// Lifecycle Errors (category: \"system\")\n// ============================================================\n\n/**\n * Thrown when an operation is attempted on a backend that has been disposed.\n *\n * This typically occurs during runtime teardown — for example, when a\n * Cloudflare Workers test runner resets Durable Object storage while\n * the TypeGraph backend still has queued operations.\n */\nexport class BackendDisposedError extends TypeGraphError {\n constructor(options?: { cause?: unknown }) {\n super(\n \"Backend has been disposed — the underlying database connection is no longer available\",\n \"BACKEND_DISPOSED\",\n {\n category: \"system\",\n suggestion:\n \"Ensure all store operations complete before calling backend.close(). \" +\n \"In test environments, await store teardown before resetting the database.\",\n cause: options?.cause,\n },\n );\n this.name = \"BackendDisposedError\";\n }\n}\n\n// ============================================================\n// Utility Functions\n// ============================================================\n\n/**\n * Type guard for TypeGraphError.\n *\n * @example\n * ```typescript\n * try {\n * await store.nodes.Person.create({});\n * } catch (error) {\n * if (isTypeGraphError(error)) {\n * console.log(error.code, error.category);\n * }\n * }\n * ```\n */\nexport function isTypeGraphError(error: unknown): error is TypeGraphError {\n return error instanceof TypeGraphError;\n}\n\n/**\n * Check if error is recoverable by user action (user or constraint error).\n *\n * User-recoverable errors can typically be resolved by:\n * - Fixing invalid input data\n * - Using different IDs or values\n * - Deleting conflicting data first\n *\n * @example\n * ```typescript\n * if (isUserRecoverable(error)) {\n * showErrorToUser(error.toUserMessage());\n * } else {\n * logAndAlertOps(error);\n * }\n * ```\n */\nexport function isUserRecoverable(error: unknown): boolean {\n if (!isTypeGraphError(error)) return false;\n return error.category === \"user\" || error.category === \"constraint\";\n}\n\n/**\n * Check if error indicates a system/infrastructure issue.\n *\n * System errors typically require:\n * - Retry logic (for transient failures)\n * - Investigation (for persistent failures)\n * - Ops team notification\n */\nexport function isSystemError(error: unknown): boolean {\n return isTypeGraphError(error) && error.category === \"system\";\n}\n\n/**\n * Check if error is a constraint violation.\n */\nexport function isConstraintError(error: unknown): boolean {\n return isTypeGraphError(error) && error.category === \"constraint\";\n}\n\n/**\n * Extract suggestion from error if available.\n */\nexport function getErrorSuggestion(error: unknown): string | undefined {\n return isTypeGraphError(error) ? error.suggestion : undefined;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/backend/drizzle/schema/sqlite.ts","../src/backend/types.ts"],"names":["nodes","edges","uniques","schemaVersions"],"mappings":"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","file":"chunk-HKN622O4.js","sourcesContent":["/**\n * Drizzle SQLite schema for TypeGraph.\n *\n * Provides table definitions that can be customized via the factory function.\n * Users import these tables into their Drizzle schema and use drizzle-kit\n * for migrations.\n *\n * @example\n * ```typescript\n * // Default table names\n * import { tables } from \"@nicia-ai/typegraph/sqlite\";\n *\n * // Custom table names\n * import { createSqliteTables } from \"@nicia-ai/typegraph/sqlite\";\n * const tables = createSqliteTables({\n * nodes: \"myapp_nodes\",\n * edges: \"myapp_edges\",\n * });\n * ```\n */\nimport { sql } from \"drizzle-orm\";\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\n\nimport {\n buildSqliteEdgeIndexBuilders,\n buildSqliteNodeIndexBuilders,\n type IndexDeclaration,\n} from \"../../../indexes\";\n\n/**\n * Table name configuration.\n */\nexport type SqliteTableNames = Readonly<{\n nodes: string;\n edges: string;\n uniques: string;\n schemaVersions: string;\n fulltext: string;\n indexMaterializations: string;\n contributionMaterializations: string;\n kindRemovals: string;\n reconciliationMarkers: string;\n}>;\n\n/**\n * Physical name of the legacy single shared embeddings table, dropped in\n * the cross-backend vector cutover (the clean cut of #157). Strategies now\n * own per-`(nodeKind, fieldPath)` typed storage. Retained only so the\n * one-time migration utility can address and drain the old table.\n */\nexport const LEGACY_EMBEDDINGS_TABLE_NAME = \"typegraph_node_embeddings\";\n\nexport type CreateSqliteTablesOptions = Readonly<{\n /**\n * Additional TypeGraph indexes to include in the Drizzle schema.\n *\n * These become first-class Drizzle indexes, so drizzle-kit migrations will\n * pick them up automatically.\n */\n indexes?: readonly IndexDeclaration[] | undefined;\n}>;\n\nconst DEFAULT_TABLE_NAMES: SqliteTableNames = {\n nodes: \"typegraph_nodes\",\n edges: \"typegraph_edges\",\n uniques: \"typegraph_node_uniques\",\n schemaVersions: \"typegraph_schema_versions\",\n fulltext: \"typegraph_node_fulltext\",\n indexMaterializations: \"typegraph_index_materializations\",\n contributionMaterializations: \"typegraph_contribution_materializations\",\n kindRemovals: \"typegraph_kind_removals\",\n reconciliationMarkers: \"typegraph_reconciliation_markers\",\n};\n\n/**\n * Creates SQLite table definitions with customizable table names.\n * Index names are derived from table names.\n */\nexport function createSqliteTables(\n names: Partial<SqliteTableNames> = {},\n options: CreateSqliteTablesOptions = {},\n) {\n const n: SqliteTableNames = { ...DEFAULT_TABLE_NAMES, ...names };\n const indexes = options.indexes ?? [];\n\n const nodes = sqliteTable(\n n.nodes,\n {\n graphId: text(\"graph_id\").notNull(),\n kind: text(\"kind\").notNull(),\n id: text(\"id\").notNull(),\n props: text(\"props\").notNull(),\n version: integer(\"version\").notNull().default(1),\n validFrom: text(\"valid_from\"),\n validTo: text(\"valid_to\"),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n deletedAt: text(\"deleted_at\"),\n },\n (t) => [\n primaryKey({ columns: [t.graphId, t.kind, t.id] }),\n index(`${n.nodes}_kind_idx`).on(t.graphId, t.kind),\n index(`${n.nodes}_kind_created_idx`).on(\n t.graphId,\n t.kind,\n t.deletedAt,\n t.createdAt,\n ),\n index(`${n.nodes}_deleted_idx`).on(t.graphId, t.deletedAt),\n index(`${n.nodes}_valid_idx`).on(t.graphId, t.validFrom, t.validTo),\n ...buildSqliteNodeIndexBuilders(t, indexes),\n ],\n );\n\n const edges = sqliteTable(\n n.edges,\n {\n graphId: text(\"graph_id\").notNull(),\n id: text(\"id\").notNull(),\n kind: text(\"kind\").notNull(),\n fromKind: text(\"from_kind\").notNull(),\n fromId: text(\"from_id\").notNull(),\n toKind: text(\"to_kind\").notNull(),\n toId: text(\"to_id\").notNull(),\n props: text(\"props\").notNull(),\n validFrom: text(\"valid_from\"),\n validTo: text(\"valid_to\"),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n deletedAt: text(\"deleted_at\"),\n },\n (t) => [\n primaryKey({ columns: [t.graphId, t.id] }),\n index(`${n.edges}_kind_idx`).on(t.graphId, t.kind),\n // Directional traversal index (outgoing): supports endpoint lookups\n // and extra filtering by edge kind / target kind.\n index(`${n.edges}_from_idx`).on(\n t.graphId,\n t.fromKind,\n t.fromId,\n t.kind,\n t.toKind,\n t.deletedAt,\n t.validTo,\n ),\n // Directional traversal index (incoming): mirrors from_idx for reverse traversals.\n index(`${n.edges}_to_idx`).on(\n t.graphId,\n t.toKind,\n t.toId,\n t.kind,\n t.fromKind,\n t.deletedAt,\n t.validTo,\n ),\n index(`${n.edges}_kind_created_idx`).on(\n t.graphId,\n t.kind,\n t.deletedAt,\n t.createdAt,\n ),\n index(`${n.edges}_deleted_idx`).on(t.graphId, t.deletedAt),\n index(`${n.edges}_valid_idx`).on(t.graphId, t.validFrom, t.validTo),\n index(`${n.edges}_cardinality_idx`).on(\n t.graphId,\n t.kind,\n t.fromKind,\n t.fromId,\n t.validTo,\n ),\n ...buildSqliteEdgeIndexBuilders(t, indexes),\n ],\n );\n\n const uniques = sqliteTable(\n n.uniques,\n {\n graphId: text(\"graph_id\").notNull(),\n nodeKind: text(\"node_kind\").notNull(),\n constraintName: text(\"constraint_name\").notNull(),\n key: text(\"key\").notNull(),\n nodeId: text(\"node_id\").notNull(),\n concreteKind: text(\"concrete_kind\").notNull(),\n deletedAt: text(\"deleted_at\"),\n },\n (t) => [\n primaryKey({\n columns: [t.graphId, t.nodeKind, t.constraintName, t.key],\n }),\n index(`${n.uniques}_node_idx`).on(t.graphId, t.concreteKind, t.nodeId),\n ],\n );\n\n const schemaVersions = sqliteTable(\n n.schemaVersions,\n {\n graphId: text(\"graph_id\").notNull(),\n version: integer(\"version\").notNull(),\n schemaHash: text(\"schema_hash\").notNull(),\n schemaDoc: text(\"schema_doc\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n isActive: integer(\"is_active\", { mode: \"boolean\" })\n .notNull()\n .default(false),\n },\n (t) => [\n primaryKey({ columns: [t.graphId, t.version] }),\n index(`${n.schemaVersions}_active_idx`).on(t.graphId, t.isActive),\n // Partial unique index enforcing the \"at most one active version\n // per graph\" invariant at the storage layer. Defense in depth\n // against buggy backend implementations or out-of-band writes.\n // Forces the deactivate-then-activate ordering used by\n // `commitSchemaVersion` and `setActiveVersion`.\n uniqueIndex(`${n.schemaVersions}_one_active_per_graph_idx`)\n .on(t.graphId)\n .where(sql`${t.isActive} = 1`),\n ],\n );\n\n /**\n * Per-deployment record of which declared indexes have been\n * materialized against this database. Owned and written by\n * `store.materializeIndexes()`. Keyed on `index_name` because SQL\n * index names are physical, database-global identifiers — `graphId`\n * is provenance, not identity.\n */\n const indexMaterializations = sqliteTable(\n n.indexMaterializations,\n {\n indexName: text(\"index_name\").notNull(),\n graphId: text(\"graph_id\").notNull(),\n entity: text(\"entity\").notNull(),\n kind: text(\"kind\").notNull(),\n signature: text(\"signature\").notNull(),\n schemaVersion: integer(\"schema_version\").notNull(),\n materializedAt: text(\"materialized_at\"),\n lastAttemptedAt: text(\"last_attempted_at\").notNull(),\n lastError: text(\"last_error\"),\n },\n (t) => [primaryKey({ columns: [t.indexName] })],\n );\n\n /**\n * Per-deployment record of extension kinds removed via\n * `store.removeKinds()` whose data has not yet been cleaned up by\n * `store.materializeRemovals()`. Keyed on `(graph_id, kind_name,\n * entity, schema_version)` — each remove operation is its own row.\n * `entity` separates a node and an edge that share a kind name; the\n * `schema_version` discriminator keeps a re-add-then-re-remove cycle\n * (Foo removed at v=N, re-added, then removed again at v=N+2) from\n * collapsing onto the prior row, where the COALESCE-on-failure rule\n * would preserve the earlier `removed_at` and silently skip the new\n * pending cleanup. `removed_at` is null until the data-cleanup pass\n * succeeds; the pending set is \"rows where removed_at IS NULL\".\n */\n const kindRemovals = sqliteTable(\n n.kindRemovals,\n {\n graphId: text(\"graph_id\").notNull(),\n kindName: text(\"kind_name\").notNull(),\n entity: text(\"entity\").notNull(),\n schemaVersion: integer(\"schema_version\").notNull(),\n removedAt: text(\"removed_at\"),\n lastAttemptedAt: text(\"last_attempted_at\").notNull(),\n lastError: text(\"last_error\"),\n },\n (t) => [\n primaryKey({\n columns: [t.graphId, t.kindName, t.entity, t.schemaVersion],\n }),\n ],\n );\n\n /**\n * Per-deployment high-water mark for the `materializeRemovals`\n * reconciliation walk. One row per `graph_id` carrying the schema\n * version up to which the historical \"did every removal land in\n * `kindRemovals`?\" walk has been verified. Lets subsequent calls\n * skip already-checked transitions instead of re-walking from\n * version 1 every time.\n */\n const reconciliationMarkers = sqliteTable(\n n.reconciliationMarkers,\n {\n graphId: text(\"graph_id\").notNull(),\n reconciledToVersion: integer(\"reconciled_to_version\").notNull(),\n },\n (t) => [primaryKey({ columns: [t.graphId] })],\n );\n\n /**\n * Per-deployment durable marker that a strategy-owned table\n * contribution (#129 — the FTS5 virtual table today) has been\n * materialized against this database (#135). Replaces the in-memory\n * per-backend `fulltextEnsured` latch with a queryable database fact.\n * Keyed on `(graph_id, logical_name, owner, table_name)`; `signature`\n * stays out of the key so same-identity drift is a loud error, not a\n * silent re-materialize. Same COALESCE-on-failure preservation rule\n * as `indexMaterializations`.\n */\n const contributionMaterializations = sqliteTable(\n n.contributionMaterializations,\n {\n graphId: text(\"graph_id\").notNull(),\n logicalName: text(\"logical_name\").notNull(),\n owner: text(\"owner\").notNull(),\n tableName: text(\"table_name\").notNull(),\n signature: text(\"signature\").notNull(),\n materializedAt: text(\"materialized_at\"),\n lastAttemptedAt: text(\"last_attempted_at\").notNull(),\n lastError: text(\"last_error\"),\n },\n (t) => [\n primaryKey({\n columns: [t.graphId, t.logicalName, t.owner, t.tableName],\n }),\n ],\n );\n\n return {\n nodes,\n edges,\n uniques,\n schemaVersions,\n indexMaterializations,\n contributionMaterializations,\n kindRemovals,\n reconciliationMarkers,\n /**\n * The fulltext storage is a FTS5 virtual table which Drizzle cannot\n * represent. DDL is emitted as raw SQL and operations query it via\n * `sql.raw()`.\n */\n fulltextTableName: n.fulltext,\n } as const;\n}\n\n/**\n * Default tables with standard TypeGraph table names.\n */\nexport const tables = createSqliteTables();\n\n/**\n * Convenience exports for default tables.\n */\nexport const { nodes, edges, uniques, schemaVersions } = tables;\n\n/**\n * Type representing the tables object returned by createSqliteTables.\n */\nexport type SqliteTables = ReturnType<typeof createSqliteTables>;\n","/**\n * Backend interface types for TypeGraph storage.\n *\n * The backend abstracts database operations, allowing different\n * SQL implementations (SQLite, PostgreSQL) behind a common interface.\n */\nimport { type SQL } from \"drizzle-orm\";\n\nimport {\n type IndexEntity,\n type KindEntity,\n type TemporalMode,\n} from \"../core/types\";\nimport { type SqlTableNames } from \"../query/compiler/schema\";\nimport { type FulltextStrategy } from \"../query/dialect/fulltext-strategy\";\nimport { type VectorStrategy } from \"../query/dialect/vector-strategy\";\nimport { type SerializedSchema } from \"../schema/types\";\nimport {\n type AnyPgDatabase,\n type AnySqliteDatabase,\n} from \"./drizzle/execution\";\n\n// ============================================================\n// Vector Search Types\n// ============================================================\n\n/**\n * Supported vector similarity metrics.\n */\nexport type VectorMetric = \"cosine\" | \"l2\" | \"inner_product\";\n\n/**\n * Supported vector index types.\n */\nexport type VectorIndexType = \"hnsw\" | \"ivfflat\" | \"none\";\n\n/**\n * Vector search capabilities.\n */\nexport type VectorCapabilities = Readonly<{\n /** Whether the backend supports vector operations */\n supported: boolean;\n /** Supported similarity metrics */\n metrics: readonly VectorMetric[];\n /** Supported index types */\n indexTypes: readonly VectorIndexType[];\n /** Maximum dimensions supported */\n maxDimensions: number;\n}>;\n\n// ============================================================\n// Fulltext Search Types\n// ============================================================\n\n/**\n * Query modes for fulltext search.\n *\n * - \"websearch\": Google-style syntax (quoted phrases, +required, -excluded).\n * Postgres: `websearch_to_tsquery`. SQLite: translated to FTS5 MATCH.\n * - \"phrase\": treats the whole query as a phrase.\n * Postgres: `phraseto_tsquery`. SQLite: FTS5 `\"...\"` phrase.\n * - \"plain\": splits on whitespace and ANDs terms.\n * Postgres: `plainto_tsquery`. SQLite: default FTS5 AND.\n * - \"raw\": dialect-native syntax passed through unchanged.\n */\nexport type FulltextQueryMode = \"websearch\" | \"phrase\" | \"plain\" | \"raw\";\n\n/**\n * Fulltext search capabilities declared by a backend.\n */\nexport type FulltextCapabilities = Readonly<{\n /** Whether the backend supports fulltext operations */\n supported: boolean;\n /**\n * Language / tokenizer names understood by this backend.\n * Postgres: installed regconfigs (english, simple, ...).\n * SQLite FTS5: tokenizer names (unicode61, porter, trigram).\n */\n languages: readonly string[];\n /** Whether phrase queries are supported. */\n phraseQueries: boolean;\n /** Whether prefix (`foo*`) queries are supported. */\n prefixQueries: boolean;\n /** Whether highlighting / snippets are supported. */\n highlighting: boolean;\n}>;\n\n// ============================================================\n// SQL Dialect & Capabilities\n// ============================================================\n\nimport { type SqlDialect } from \"../query/dialect/types\";\n\nexport type { SqlDialect } from \"../query/dialect/types\";\n\n/**\n * Backend capabilities that vary by dialect.\n */\nexport type BackendCapabilities = Readonly<{\n /** Whether the backend supports atomic transactions (D1 does not) */\n transactions: boolean;\n /** Vector search capabilities (undefined if not configured) */\n vector?: VectorCapabilities | undefined;\n /** Fulltext search capabilities (undefined if not configured) */\n fulltext?: FulltextCapabilities | undefined;\n}>;\n\n// ============================================================\n// Row Types (Database Records)\n// ============================================================\n\n/**\n * A row from the typegraph_nodes table.\n */\nexport type NodeRow = Readonly<{\n graph_id: string;\n kind: string;\n id: string;\n props: string; // JSON string\n version: number;\n valid_from: string | undefined;\n valid_to: string | undefined;\n created_at: string;\n updated_at: string;\n deleted_at: string | undefined;\n}>;\n\n/**\n * A row from the typegraph_edges table.\n */\nexport type EdgeRow = Readonly<{\n graph_id: string;\n id: string;\n kind: string;\n from_kind: string;\n from_id: string;\n to_kind: string;\n to_id: string;\n props: string; // JSON string\n valid_from: string | undefined;\n valid_to: string | undefined;\n created_at: string;\n updated_at: string;\n deleted_at: string | undefined;\n}>;\n\n/**\n * A row from the typegraph_node_uniques table.\n */\nexport type UniqueRow = Readonly<{\n graph_id: string;\n node_kind: string;\n constraint_name: string;\n key: string;\n node_id: string;\n concrete_kind: string;\n deleted_at: string | undefined;\n}>;\n\n/**\n * A row from the typegraph_schema_versions table.\n */\nexport type SchemaVersionRow = Readonly<{\n graph_id: string;\n version: number;\n schema_hash: string;\n schema_doc: string; // JSON string\n created_at: string;\n is_active: boolean;\n}>;\n\n// ============================================================\n// Insert Parameters\n// ============================================================\n\n/**\n * Parameters for inserting a node.\n */\nexport type InsertNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n validFrom?: string;\n validTo?: string;\n}>;\n\n/**\n * Parameters for updating a node.\n */\nexport type UpdateNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n validTo?: string;\n incrementVersion?: boolean;\n /** If true, clears deleted_at (un-deletes the node). Used by upsert. */\n clearDeleted?: boolean;\n}>;\n\n/**\n * Parameters for deleting a node (soft delete).\n */\nexport type DeleteNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n}>;\n\n/**\n * Parameters for inserting an edge.\n */\nexport type InsertEdgeParams = Readonly<{\n graphId: string;\n id: string;\n kind: string;\n fromKind: string;\n fromId: string;\n toKind: string;\n toId: string;\n props: Readonly<Record<string, unknown>>;\n validFrom?: string;\n validTo?: string;\n}>;\n\n/**\n * Parameters for updating an edge.\n */\nexport type UpdateEdgeParams = Readonly<{\n graphId: string;\n id: string;\n props: Readonly<Record<string, unknown>>;\n validTo?: string;\n clearDeleted?: boolean;\n}>;\n\n/**\n * Parameters for deleting an edge (soft delete).\n */\nexport type DeleteEdgeParams = Readonly<{\n graphId: string;\n id: string;\n}>;\n\n/**\n * Parameters for hard deleting a node (permanent removal).\n */\nexport type HardDeleteNodeParams = Readonly<{\n graphId: string;\n kind: string;\n id: string;\n}>;\n\n/**\n * Parameters for hard deleting an edge (permanent removal).\n */\nexport type HardDeleteEdgeParams = Readonly<{\n graphId: string;\n id: string;\n}>;\n\n// ============================================================\n// Embedding Parameters\n// ============================================================\n\n/**\n * Parameters for inserting or updating an embedding.\n *\n * `dimensions`, `metric`, and `indexType` together resolve the slot's\n * typed per-`(nodeKind, fieldPath)` storage (the strategy needs the fixed\n * dimension for the column type, and the metric/index type to address the\n * right ANN structure). The store populates them from the schema's\n * `embedding()` declaration via `getEmbeddingDimensions()` /\n * `getEmbeddingIndex()`; the backend constructs a `VectorSlot` from them\n * and stays graph-agnostic.\n */\nexport type UpsertEmbeddingParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n fieldPath: string;\n embedding: readonly number[];\n dimensions: number;\n metric: VectorMetric;\n indexType: VectorIndexType;\n}>;\n\n/**\n * Parameters for deleting an embedding.\n *\n * `dimensions` / `metric` / `indexType` mirror {@link UpsertEmbeddingParams}\n * so the backend can resolve the slot's typed per-`(nodeKind, fieldPath)`\n * storage and idempotently ensure it exists before the DELETE. That\n * matters because a delete can run before any embedding was ever written\n * (e.g. a node hard-deleted having never carried one), and on Postgres a\n * DELETE against a missing relation inside a transaction aborts the whole\n * transaction. The store populates them from the schema's `embedding()`\n * declaration, exactly as for upserts.\n */\nexport type DeleteEmbeddingParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n fieldPath: string;\n dimensions: number;\n metric: VectorMetric;\n indexType: VectorIndexType;\n}>;\n\n/**\n * Parameters for vector similarity search.\n */\nexport type VectorSearchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n fieldPath: string;\n queryEmbedding: readonly number[];\n metric: VectorMetric;\n /**\n * Fixed vector dimension `N` for the searched `(nodeKind, fieldPath)`\n * slot. The store populates it from the schema's `embedding()`\n * declaration via `getEmbeddingDimensions()`; the backend uses it to\n * construct the `VectorSlot` whose typed storage the strategy scans.\n */\n dimensions: number;\n /**\n * Index type materialized for this slot. `\"none\"` means brute-force\n * only; otherwise the strategy may route through its ANN structure.\n * The store populates it from `getEmbeddingIndex()`.\n */\n indexType: VectorIndexType;\n limit: number;\n minScore?: number;\n /**\n * HNSW search frontier for this query (pgvector `hnsw.ef_search`).\n * Sizes the dynamic candidate list the index scan maintains: higher\n * trades latency for recall. The floor for the over-fetch to fill its\n * candidate set is `efSearch >= limit`; ~2–4× is the high-recall\n * target. Applied transaction-locally (`SET LOCAL`) on the Postgres\n * HNSW path only. No-op on backends without an HNSW frontier knob\n * (sqlite-vec) and ignored — with a one-time warning — on Postgres\n * backends without transactions (e.g. `drizzle-orm/neon-http`).\n */\n efSearch?: number;\n}>;\n\n/**\n * Result from a vector similarity search.\n */\nexport type VectorSearchResult = Readonly<{\n nodeId: string;\n /**\n * Cosine metric returns similarity score (higher is better).\n * L2 and inner_product return raw distance (lower is better).\n */\n score: number;\n}>;\n\n/**\n * Parameters for creating a vector index.\n */\nexport type CreateVectorIndexParams = Readonly<{\n graphId: string;\n nodeKind: string;\n fieldPath: string;\n dimensions: number;\n metric: VectorMetric;\n indexType: VectorIndexType;\n /** Index-specific parameters */\n indexParams?: Readonly<{\n /** HNSW: max connections per layer */\n m?: number;\n /** HNSW: construction search depth */\n efConstruction?: number;\n /** IVFFlat: number of lists */\n lists?: number;\n }>;\n /**\n * Build the index without taking an `AccessExclusiveLock` on live\n * tables (Postgres `CREATE INDEX CONCURRENTLY`). Mirrors the\n * `concurrent` flag the relational DDL path uses inside\n * `materializeIndexes()`. Cannot be set inside a transaction —\n * callers (`materializeIndexes()`) run at top level. Backends that\n * don't have a CONCURRENTLY equivalent (SQLite) ignore this flag.\n */\n concurrent?: boolean;\n}>;\n\n/**\n * Parameters for dropping a vector index.\n */\nexport type DropVectorIndexParams = Readonly<{\n graphId: string;\n nodeKind: string;\n fieldPath: string;\n}>;\n\n// ============================================================\n// Fulltext Parameters\n// ============================================================\n\n/**\n * Parameters for inserting or updating a fulltext entry.\n *\n * One row per node. Callers concatenate the searchable fields into\n * `content` so a single MATCH query can find terms spread across fields.\n *\n * Note: `createFulltextIndex` / `dropFulltextIndex` were removed as\n * dead code in #PR_E. The fulltext table's canonical index (Postgres\n * GIN on `tsv`, SQLite FTS5 virtual table) is created with the table\n * itself by `bootstrapTables` per the active `FulltextStrategy`;\n * per-kind fulltext indexes are an \"advanced strategy\" surface that\n * doesn't fit the relational-style declaration model and is reserved\n * for future work.\n */\nexport type UpsertFulltextParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n content: string;\n language: string;\n}>;\n\n/**\n * Parameters for deleting a single fulltext entry.\n */\nexport type DeleteFulltextParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n}>;\n\n/**\n * A single row in a fulltext batch upsert.\n */\nexport type FulltextBatchRow = Readonly<{\n nodeId: string;\n content: string;\n language: string;\n}>;\n\n/**\n * Parameters for a batched fulltext upsert.\n *\n * Homogeneous: one graph, one node kind, many nodes. Duplicate `nodeId`\n * values within a single batch are deduplicated last-write-wins by the\n * builders before SQL generation — Postgres `ON CONFLICT` errors on\n * repeated conflict keys in one statement, and SQLite `DELETE + INSERT`\n * would create duplicate virtual-table rows otherwise.\n */\nexport type UpsertFulltextBatchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n rows: readonly FulltextBatchRow[];\n}>;\n\n/**\n * Parameters for a batched fulltext delete.\n */\nexport type DeleteFulltextBatchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeIds: readonly string[];\n}>;\n\n/**\n * Parameters for fulltext search.\n */\nexport type FulltextSearchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n /** The user-supplied query string. */\n query: string;\n /** How to parse `query`. Default: \"websearch\". */\n mode?: FulltextQueryMode;\n /**\n * Language override. Default: per-row language (as stored at insert time).\n * Postgres: passed as the regconfig to `to_tsquery` / `websearch_to_tsquery`.\n * SQLite: informational only (FTS5 tokenizer is fixed at table-create time).\n */\n language?: string;\n /** Max rows to return. */\n limit: number;\n /** Minimum rank to include (backend-dependent units). */\n minScore?: number;\n /** Whether to return a highlighted snippet per match. */\n includeSnippets?: boolean;\n}>;\n\n/**\n * Result from a fulltext search.\n *\n * Score semantics differ by backend; prefer `rank` (1-based) when fusing\n * with another source via RRF.\n */\nexport type FulltextSearchResult = Readonly<{\n nodeId: string;\n /**\n * Backend-native relevance score.\n * Postgres: `ts_rank_cd` (higher is better).\n * SQLite FTS5: negated `bm25()` (higher is better; FTS5 returns lower-is-better).\n */\n score: number;\n /** 1-based rank within the result set, suitable for RRF. */\n rank: number;\n /** Highlighted snippet of the content (if `includeSnippets` was set). */\n snippet?: string;\n}>;\n\n/**\n * Parameters for creating a fulltext index.\n *\n * The canonical index (Postgres GIN on `tsv`, SQLite FTS5 virtual table)\n * is created when the fulltext table itself is created. This is reserved\n * for advanced per-kind specializations.\n */\n\n// ============================================================\n// Index Materialization Status\n// ============================================================\n\n/**\n * Per-deployment record for a single declared index.\n *\n * Identified by `indexName` because SQL index names are physical,\n * database-global identifiers — `graphId` is provenance, not identity.\n * `materializedAt` is null until the first successful CREATE INDEX\n * completes; `lastAttemptedAt` is always set, even on failure.\n */\nexport type IndexMaterializationRow = Readonly<{\n indexName: string;\n graphId: string;\n entity: IndexEntity;\n kind: string;\n signature: string;\n schemaVersion: number;\n materializedAt: string | undefined;\n lastAttemptedAt: string;\n lastError: string | undefined;\n}>;\n\n/**\n * Parameters for upserting a materialization attempt.\n *\n * On success: pass `materializedAt` (ISO timestamp) and undefined `error`.\n * On failure: pass undefined `materializedAt` (preserve any existing\n * timestamp from a prior success) and the error message.\n */\nexport type RecordIndexMaterializationParams = Readonly<{\n indexName: string;\n graphId: string;\n entity: IndexEntity;\n kind: string;\n signature: string;\n schemaVersion: number;\n attemptedAt: string;\n /** ISO timestamp on success; undefined on failure (preserves existing). */\n materializedAt: string | undefined;\n /** Error message on failure; undefined on success (clears existing). */\n error: string | undefined;\n}>;\n\n// ============================================================\n// Contribution Materializations (#135 — durable strategy-owned\n// storage marker, sibling of index materializations)\n// ============================================================\n\n/**\n * Durable identity of a strategy-owned table contribution (#129),\n * scoped to a graph. This is the primary key of\n * `typegraph_contribution_materializations`.\n *\n * `logicalName` is the stable slot (\"fulltext\"); `owner` is the\n * producing strategy (\"tsvector\" / \"fts5\"); `tableName` is the resolved\n * physical name (custom per-deployment names must be distinguishable).\n * `graphId` is part of identity here — unlike the index status table\n * where the physical index name is database-global, two graphs can each\n * own a logically-identical fulltext contribution.\n */\nexport type ContributionMaterializationIdentity = Readonly<{\n graphId: string;\n logicalName: string;\n owner: string;\n tableName: string;\n}>;\n\n/**\n * Per-deployment record that a strategy-owned contribution has been\n * durably materialized against this database.\n *\n * `signature` is intentionally NOT part of the identity: a row with the\n * same identity but a different signature means \"materialized artifact\n * is stale/drifted\" — a loud error on the hot path, never a silent\n * re-materialize. `materializedAt` is undefined until the first\n * successful materialization; `lastAttemptedAt` is always set.\n */\nexport type ContributionMaterializationRow = Readonly<{\n graphId: string;\n logicalName: string;\n owner: string;\n tableName: string;\n signature: string;\n materializedAt: string | undefined;\n lastAttemptedAt: string;\n lastError: string | undefined;\n}>;\n\n/**\n * Parameters for upserting a contribution-materialization attempt.\n * Same success/failure contract as\n * {@link RecordIndexMaterializationParams}: on failure pass undefined\n * `materializedAt` so a prior successful timestamp is preserved via\n * COALESCE, and the error message.\n */\nexport type RecordContributionMaterializationParams = Readonly<{\n graphId: string;\n logicalName: string;\n owner: string;\n tableName: string;\n signature: string;\n attemptedAt: string;\n /** ISO timestamp on success; undefined on failure (preserves existing). */\n materializedAt: string | undefined;\n /** Error message on failure; undefined on success (clears existing). */\n error: string | undefined;\n}>;\n\n// ============================================================\n// Kind Removals (data-cleanup status)\n// ============================================================\n\n/**\n * One row of the per-deployment `typegraph_kind_removals` table:\n * a graph-extension kind that has been removed from the schema and whose\n * data may or may not have been cleaned up yet.\n */\nexport type KindRemovalRow = Readonly<{\n graphId: string;\n kindName: string;\n entity: KindEntity;\n schemaVersion: number;\n /** ISO timestamp when the data-cleanup pass succeeded; undefined while pending. */\n removedAt: string | undefined;\n lastAttemptedAt: string;\n lastError: string | undefined;\n}>;\n\n/**\n * Upsert payload for a kind-removal status row. On removal-commit:\n * pass `removedAt: undefined` (the pending state). On successful\n * data-cleanup: pass `removedAt` set and `error: undefined`. On\n * cleanup failure: pass `removedAt: undefined` (preserves any prior\n * timestamp from a partial success on a different replica) and the\n * error message.\n */\nexport type RecordKindRemovalParams = Readonly<{\n graphId: string;\n kindName: string;\n entity: KindEntity;\n schemaVersion: number;\n attemptedAt: string;\n /** ISO timestamp on success; undefined while pending or on failure. */\n removedAt: string | undefined;\n /** Error message on failure; undefined on success or while pending. */\n error: string | undefined;\n}>;\n\n// ============================================================\n// Query Types\n// ============================================================\n\n/**\n * Transaction options.\n */\nexport type TransactionOptions = Readonly<{\n /** Transaction isolation level (if supported) */\n isolationLevel?:\n | \"read_uncommitted\"\n | \"read_committed\"\n | \"repeatable_read\"\n | \"serializable\";\n}>;\n\n/**\n * A caller-owned, already-open Drizzle transaction handle that a\n * TypeGraph store can adopt so both layers commit/rollback together.\n *\n * The literal client the caller's transaction runs on — a `PgDatabase`\n * transaction (node-postgres / `neon-serverless` Pool) or a\n * `BaseSQLiteDatabase` connection. Async drivers obtain it from\n * `db.transaction(async (tx) => …)`; synchronous `better-sqlite3` (whose\n * driver rejects an `async` transaction callback) passes the connection\n * itself under an explicit `BEGIN`/`COMMIT`/`ROLLBACK`. Passing it to\n * {@link GraphBackend.adoptTransaction} threads that *literal* client\n * through TypeGraph's SQL, so graph writes and the caller's own\n * relational writes share one Postgres/SQLite transaction (#134).\n */\nexport type AdoptedTransaction = AnyPgDatabase | AnySqliteDatabase;\n\n// ============================================================\n// Backend Interface\n// ============================================================\n\n/**\n * Transaction backend — a backend scoped to a transaction.\n *\n * `commitSchemaVersion` and `setActiveVersion` are intentionally omitted:\n * the atomicity / CAS guarantees of those primitives depend on\n * dialect-specific write-locking (BEGIN IMMEDIATE on SQLite,\n * `pg_advisory_xact_lock` on Postgres) acquired by the top-level\n * backend wrappers, not the transaction itself. Calling them from a\n * user-supplied `backend.transaction(...)` callback would bypass that\n * locking and silently weaken the orphan-row crash window the primitive\n * exists to eliminate. Schema commits go through the top-level backend\n * methods only.\n */\nexport type TransactionBackend = Omit<\n GraphBackend,\n | \"transaction\"\n | \"adoptTransaction\"\n | \"close\"\n | \"refreshStatistics\"\n | \"commitSchemaVersion\"\n | \"setActiveVersion\"\n>;\n\n/**\n * The GraphBackend interface abstracts database operations.\n *\n * Implementations should provide:\n * - SQLite backend via better-sqlite3 or libsql\n * - PostgreSQL backend via pg or postgres\n */\nexport type GraphBackend = Readonly<{\n /** The SQL dialect */\n dialect: SqlDialect;\n /** Backend capabilities */\n capabilities: BackendCapabilities;\n /** Table names used by this backend (for query schema auto-derivation) */\n tableNames?: SqlTableNames | undefined;\n /**\n * Optional fulltext strategy override. When present, both the compiler\n * (for `$fulltext.matches()` in query builder) and backend-direct\n * search paths use this instead of the dialect's default strategy —\n * allowing a Postgres backend to ship pg_trgm, ParadeDB, pgroonga etc.\n * When absent, the dialect's default strategy is used.\n */\n fulltextStrategy?: FulltextStrategy | undefined;\n /**\n * Optional vector strategy this backend is wired with. The query\n * compiler reads it (via `compileQuery` options) to emit per-`(kind,\n * field)` relevance scans for `field.similarTo(...)` predicates, and\n * the index-materialization / removal paths read its deterministic\n * `tableName(...)` to address the right physical per-field storage.\n * `undefined` when the backend has no vector support (e.g. a generic\n * SQLite backend without sqlite-vec).\n */\n vectorStrategy?: VectorStrategy | undefined;\n\n // === Node Operations ===\n insertNode: (params: InsertNodeParams) => Promise<NodeRow>;\n insertNodeNoReturn?: (params: InsertNodeParams) => Promise<void>;\n insertNodesBatch?: (params: readonly InsertNodeParams[]) => Promise<void>;\n insertNodesBatchReturning?: (\n params: readonly InsertNodeParams[],\n ) => Promise<readonly NodeRow[]>;\n updateNode: (params: UpdateNodeParams) => Promise<NodeRow>;\n deleteNode: (params: DeleteNodeParams) => Promise<void>;\n hardDeleteNode: (params: HardDeleteNodeParams) => Promise<void>;\n getNode: (\n graphId: string,\n kind: string,\n id: string,\n ) => Promise<NodeRow | undefined>;\n getNodes?: (\n graphId: string,\n kind: string,\n ids: readonly string[],\n ) => Promise<readonly NodeRow[]>;\n\n // === Edge Operations ===\n insertEdge: (params: InsertEdgeParams) => Promise<EdgeRow>;\n insertEdgeNoReturn?: (params: InsertEdgeParams) => Promise<void>;\n insertEdgesBatch?: (params: readonly InsertEdgeParams[]) => Promise<void>;\n insertEdgesBatchReturning?: (\n params: readonly InsertEdgeParams[],\n ) => Promise<readonly EdgeRow[]>;\n updateEdge: (params: UpdateEdgeParams) => Promise<EdgeRow>;\n deleteEdge: (params: DeleteEdgeParams) => Promise<void>;\n hardDeleteEdge: (params: HardDeleteEdgeParams) => Promise<void>;\n getEdge: (graphId: string, id: string) => Promise<EdgeRow | undefined>;\n getEdges?: (\n graphId: string,\n ids: readonly string[],\n ) => Promise<readonly EdgeRow[]>;\n\n // === Edge Cardinality Operations ===\n countEdgesFrom: (params: CountEdgesFromParams) => Promise<number>;\n edgeExistsBetween: (params: EdgeExistsBetweenParams) => Promise<boolean>;\n\n // === Edge Query Operations ===\n findEdgesConnectedTo: (\n params: FindEdgesConnectedToParams,\n ) => Promise<readonly EdgeRow[]>;\n\n // === Collection Query Operations ===\n findNodesByKind: (\n params: FindNodesByKindParams,\n ) => Promise<readonly NodeRow[]>;\n countNodesByKind: (params: CountNodesByKindParams) => Promise<number>;\n findEdgesByKind: (\n params: FindEdgesByKindParams,\n ) => Promise<readonly EdgeRow[]>;\n countEdgesByKind: (params: CountEdgesByKindParams) => Promise<number>;\n\n // === Unique Constraint Operations ===\n insertUnique: (params: InsertUniqueParams) => Promise<void>;\n deleteUnique: (params: DeleteUniqueParams) => Promise<void>;\n checkUnique: (params: CheckUniqueParams) => Promise<UniqueRow | undefined>;\n checkUniqueBatch?: (\n params: CheckUniqueBatchParams,\n ) => Promise<readonly UniqueRow[]>;\n\n // === Schema Operations ===\n getActiveSchema: (graphId: string) => Promise<SchemaVersionRow | undefined>;\n getSchemaVersion: (\n graphId: string,\n version: number,\n ) => Promise<SchemaVersionRow | undefined>;\n /**\n * Atomically inserts a new schema version and activates it as a single\n * transactional unit, with optimistic compare-and-swap on the currently\n * active version.\n *\n * - If `expected.kind === \"active\"` and the actual active version\n * differs, throws `StaleVersionError` (caller should refetch and\n * retry).\n * - If a row already exists at `params.version` with the same\n * `schemaHash`, returns it idempotently — reactivating it if it was\n * left inactive by an earlier crashed commit.\n * - If a row already exists at `params.version` with a different\n * `schemaHash`, throws `SchemaContentConflictError`.\n *\n * Requires `capabilities.transactions === true`. On non-transactional\n * backends (e.g. Cloudflare D1, drizzle-orm/neon-http) this method\n * throws `ConfigurationError` rather than running with degraded\n * atomicity that would silently re-introduce the orphan-row crash\n * window the primitive exists to eliminate.\n */\n commitSchemaVersion: (\n params: CommitSchemaVersionParams,\n ) => Promise<SchemaVersionRow>;\n /**\n * Atomically flips the active schema pointer to an existing version,\n * with optimistic compare-and-swap on the currently active version.\n * Used by `rollbackSchema` and any other \"promote/demote existing\n * version\" workflow. Throws `StaleVersionError` on CAS mismatch and\n * `MigrationError` if the target version row does not exist.\n *\n * Same transactional requirements as `commitSchemaVersion`.\n */\n setActiveVersion: (params: SetActiveVersionParams) => Promise<void>;\n\n // === Embedding Operations (optional - depends on vector capabilities) ===\n upsertEmbedding?: (params: UpsertEmbeddingParams) => Promise<void>;\n deleteEmbedding?: (params: DeleteEmbeddingParams) => Promise<void>;\n vectorSearch?: (\n params: VectorSearchParams,\n ) => Promise<readonly VectorSearchResult[]>;\n createVectorIndex?: (params: CreateVectorIndexParams) => Promise<void>;\n dropVectorIndex?: (params: DropVectorIndexParams) => Promise<void>;\n\n // === Fulltext Operations (optional - depends on fulltext capabilities) ===\n upsertFulltext?: (params: UpsertFulltextParams) => Promise<void>;\n deleteFulltext?: (params: DeleteFulltextParams) => Promise<void>;\n /**\n * Batched variant of `upsertFulltext`. Optional — callers fall back to\n * per-row `upsertFulltext` when unset.\n */\n upsertFulltextBatch?: (params: UpsertFulltextBatchParams) => Promise<void>;\n /**\n * Batched variant of `deleteFulltext`. Optional — callers fall back to\n * per-row `deleteFulltext` when unset.\n */\n deleteFulltextBatch?: (params: DeleteFulltextBatchParams) => Promise<void>;\n fulltextSearch?: (\n params: FulltextSearchParams,\n ) => Promise<readonly FulltextSearchResult[]>;\n\n // === Index Materialization (used by store.materializeIndexes) ===\n /**\n * Idempotently ensure ONLY the `typegraph_index_materializations`\n * table exists — separate from `bootstrapTables` so that\n * `materializeIndexes` doesn't pull in the full base-table DDL set\n * just to access the status table.\n *\n * Why focused: `bootstrapTables` issues 20+ `CREATE TABLE / CREATE\n * INDEX IF NOT EXISTS` statements covering every base table. Two\n * concurrent calls (e.g. two replicas of the same `schema_doc` both\n * starting up and calling `materializeIndexes`) race on\n * Postgres SHARE locks and DEADLOCK. Restricting the ensure-step to\n * the single status table eliminates the cross-table race entirely\n * — concurrent `CREATE TABLE IF NOT EXISTS` for one specific table\n * is well-behaved on Postgres.\n */\n ensureIndexMaterializationsTable?: () => Promise<void>;\n\n /**\n * Look up a recorded materialization for a declared index by its\n * physical SQL index name. Returns `undefined` if no row exists.\n */\n getIndexMaterialization?: (\n indexName: string,\n ) => Promise<IndexMaterializationRow | undefined>;\n /**\n * Bulk variant of `getIndexMaterialization`: load every recorded\n * materialization whose `indexName` (status key) is in `statusKeys`,\n * in a single round-trip. Returned rows are unordered — callers index\n * by `indexName`. Optional; consumers fall back to per-key\n * `getIndexMaterialization` when unset.\n */\n getIndexMaterializations?: (\n statusKeys: readonly string[],\n ) => Promise<readonly IndexMaterializationRow[]>;\n /**\n * Upsert a materialization attempt — success or failure. Failure rows\n * preserve any prior `materializedAt` so the historical successful\n * timestamp survives across error windows.\n */\n recordIndexMaterialization?: (\n params: RecordIndexMaterializationParams,\n ) => Promise<void>;\n\n // === Contribution Materialization (#135 — durable strategy-owned\n // storage marker, sibling of the index status table) ===\n\n /**\n * Idempotently ensure ONLY the\n * `typegraph_contribution_materializations` table exists. Same\n * focused-bootstrap rationale as `ensureIndexMaterializationsTable`:\n * a single `CREATE TABLE IF NOT EXISTS` is concurrency-safe under\n * replica startup, where the full `bootstrapTables` set risks a\n * Postgres SHARE-lock deadlock.\n */\n ensureContributionMaterializationsTable?: () => Promise<void>;\n\n /**\n * Look up the durable materialization marker for one strategy-owned\n * contribution identity. Returns `undefined` when no row exists\n * (\"never initialized\").\n */\n getContributionMaterialization?: (\n identity: ContributionMaterializationIdentity,\n ) => Promise<ContributionMaterializationRow | undefined>;\n\n /**\n * Upsert a contribution-materialization attempt — success or failure.\n * Failure rows preserve any prior `materializedAt` via COALESCE so a\n * later failed re-attempt doesn't erase the historical success.\n */\n recordContributionMaterialization?: (\n params: RecordContributionMaterializationParams,\n ) => Promise<void>;\n\n /**\n * Resolve (once per backend instance, cached) and assert the durable\n * materialization markers for every `runtimeEnsure` contribution this\n * backend's strategy declares, for `graphId`. Throws\n * `StoreNotInitializedError` when a marker is missing, stale\n * (signature drift), or recorded a failed last attempt.\n *\n * This is the single read-side gate the fulltext hot-path wrappers\n * and `store.transaction()` consult. It performs ZERO DDL and ZERO\n * marker writes — initialization is the exclusive job of the async\n * boot path (`createStoreWithSchema` → `ensureRuntimeContributions`).\n */\n assertRuntimeContributionsInitialized?: (graphId: string) => Promise<void>;\n\n // === Kind Removal Status ===\n\n /**\n * Bootstraps the per-deployment `typegraph_kind_removals` table so\n * `store.removeKinds()` and `store.materializeRemovals()` can persist\n * removal status. Mirrors the focused-bootstrap rationale documented\n * on `ensureIndexMaterializationsTable` — the full `bootstrapTables`\n * touches every base table and risks Postgres SHARE-lock deadlock\n * under concurrent replica startup.\n */\n ensureKindRemovalsTable?: () => Promise<void>;\n\n /**\n * List graph-extension kind removals whose data-cleanup pass has not yet\n * succeeded for this `graphId`. Returns rows with\n * `removedAt: undefined`. Order is unspecified; callers materialize\n * one-at-a-time and don't depend on it.\n */\n getPendingKindRemovals?: (\n graphId: string,\n ) => Promise<readonly KindRemovalRow[]>;\n\n /**\n * List ALL kind-removal rows for a `graphId` — pending and completed.\n * Used by `materializeRemovals()` reconciliation to detect rows that\n * are missing entirely (the `removeKinds()` crash window) versus\n * already completed. Without this distinction the reconciler would\n * have to upsert every expected historical removal on every call,\n * churning `last_attempted_at` on rows that long since succeeded.\n * Order is unspecified.\n */\n getAllKindRemovals?: (graphId: string) => Promise<readonly KindRemovalRow[]>;\n\n /**\n * Upsert a kind-removal status row. `removedAt: undefined` records\n * the pending state at schema-commit time; `removedAt: <iso>`\n * marks the data cleanup successful. The COALESCE rule on `removedAt`\n * mirrors `recordIndexMaterialization` so a later failure doesn't\n * clobber the historical successful timestamp from another replica.\n */\n recordKindRemoval?: (params: RecordKindRemovalParams) => Promise<void>;\n\n // === Reconciliation Watermark ===\n\n /**\n * Bootstraps the per-deployment `typegraph_reconciliation_markers`\n * table so `materializeRemovals()` can persist reconciliation\n * progress. Same focused-bootstrap rationale as the other status\n * tables — full `bootstrapTables` risks Postgres SHARE-lock\n * deadlock under concurrent replica startup.\n */\n ensureReconciliationMarkersTable?: () => Promise<void>;\n\n // === Table Contributions (#129) ===\n\n /**\n * Materializes every contribution flagged `runtimeEnsure` — the\n * strategy-owned runtime tables (fulltext today) that drizzle-kit-\n * managed setups don't create. Called once after a successful schema\n * load. Deliberately scoped: base/drizzle-visible tables are\n * `runtimeEnsure: false`, so this does not regress startup into\n * broad DDL/probing across every table.\n *\n * The canonical durable-marker writer (#135): for each runtime\n * contribution it short-circuits when the marker already records a\n * matching signature, otherwise runs the idempotent `createDdl` and\n * records the marker (success or failure) keyed by `graphId`.\n */\n ensureRuntimeContributions?: (graphId: string) => Promise<void>;\n\n /**\n * Bootstraps the fulltext storage table the active `FulltextStrategy`\n * owns. Same focused-bootstrap rationale as the other `ensure*Table`\n * methods: idempotent and concurrency-safe under replica startup.\n *\n * Superseded by `ensureRuntimeContributions()` (#129); retained as\n * a thin back-compat wrapper for backends/callers predating #129. Not\n * machine-`@deprecated` because the manager still calls it as the\n * pre-#129 fallback. #135 removed the remaining hot-path callers and\n * routed this through the durable-marker writer.\n */\n ensureFulltextTable?: (graphId: string) => Promise<void>;\n\n /**\n * Read the high-water mark schema version for which\n * `materializeRemovals` reconciliation has already verified history\n * for `graphId`. Returns `undefined` when no marker has been\n * recorded yet. Used to skip already-checked transitions in the\n * recovery walk.\n */\n getReconciliationMarker?: (graphId: string) => Promise<number | undefined>;\n\n /**\n * Persist the reconciliation high-water mark for `graphId`. Called\n * after `materializeRemovals` completes a clean walk; subsequent\n * calls walk only versions newer than this marker. Idempotent\n * upsert by `graphId`.\n */\n setReconciliationMarker?: (graphId: string, version: number) => Promise<void>;\n\n // === Graph Lifecycle ===\n /**\n * Hard-deletes all data for a graph (nodes, edges, uniques, embeddings, schema versions).\n * Intended for import-replacement workflows. No hooks, no per-row logic.\n */\n clearGraph: (graphId: string) => Promise<void>;\n\n /**\n * Creates the base TypeGraph tables if they don't already exist.\n *\n * Called automatically by `createStoreWithSchema()` when a fresh database\n * is detected. Users who manage DDL themselves via `createStore()` never\n * hit this path.\n */\n bootstrapTables?: () => Promise<void>;\n\n /**\n * Refreshes the backend's query-planner statistics.\n *\n * Call this once after a large initial import or bulk backfill. Without\n * up-to-date statistics, the planner can pick suboptimal execution plans\n * — on PostgreSQL this is the difference between a 0.5ms and a 5ms\n * forward traversal; on SQLite it's the difference between 0.9ms and\n * 23ms fulltext search. Autovacuum / background statistics collection\n * will catch up eventually, but calling this explicitly after a bulk\n * load gives you correct latencies immediately.\n *\n * Implementations:\n * - SQLite runs `ANALYZE`, which populates `sqlite_stat1`\n * - PostgreSQL runs `ANALYZE` on the TypeGraph-managed tables\n *\n * Safe to call at any time; costs a few tens of milliseconds on the\n * sizes this library is designed for.\n */\n refreshStatistics: () => Promise<void>;\n\n // === Query Execution ===\n execute: <T>(query: SQL) => Promise<readonly T[]>;\n\n /** Execute pre-compiled SQL text with bound parameters. Available on sync SQLite and pg backends. */\n executeRaw?: <T>(\n sqlText: string,\n params: readonly unknown[],\n ) => Promise<readonly T[]>;\n\n /** Compile a Drizzle SQL object to { sql, params } without executing. */\n compileSql?: (\n query: SQL,\n ) => Readonly<{ sql: string; params: readonly unknown[] }>;\n\n /**\n * Execute a DDL statement that returns no rows (CREATE INDEX,\n * CREATE TABLE, ALTER TABLE, etc.). Separate from `executeRaw`\n * because some drivers (better-sqlite3) require `.run()` for DDL\n * and `.all()` for queries — the ambiguity can't be resolved by\n * inspecting the SQL string portably.\n *\n * Postgres path can use this for `CREATE INDEX CONCURRENTLY`, which\n * cannot run inside a transaction. Implementations must execute the\n * statement outside `transaction(...)`.\n */\n executeDdl?: (ddl: string) => Promise<void>;\n\n // === Transaction ===\n /**\n * `fn` receives the tx-scoped backend and the raw Drizzle handle\n * **bound to that same transaction** (`AdoptedTransaction`). The\n * store surfaces the second argument as `TransactionContext.sql` so\n * callers can write their own relational tables inside the\n * graph-owned transaction. Implementations MUST pass the *exact*\n * handle the tx-scoped backend writes through (the Postgres/libsql\n * tx handle; for better-sqlite3 / do-sqlite the bound connection),\n * never a fresh one.\n */\n transaction: <T>(\n fn: (tx: TransactionBackend, sql: AdoptedTransaction) => Promise<T>,\n options?: TransactionOptions,\n ) => Promise<T>;\n\n /**\n * Adopt a caller-owned, already-open transaction (#134).\n *\n * Returns a transaction-scoped backend bound to the *exact*\n * `externalTx` client, reusing this backend's already-resolved\n * schema/strategy config — no `createStoreWithSchema` / `evolve` /\n * `migrateSchema`, and **no DDL inside the caller's business\n * transaction**. The caller owns `BEGIN`/`COMMIT`/`ROLLBACK`; this\n * method neither opens nor closes a transaction. Async drivers\n * (node-postgres, `neon-serverless` Pool, libsql) wrap with\n * `db.transaction(async …)`; synchronous `better-sqlite3` must instead\n * issue explicit `BEGIN`/`COMMIT`/`ROLLBACK` (its driver rejects an\n * `async` transaction callback).\n *\n * Optional and presence-detected like the other capability-scoped\n * members: only the Drizzle Postgres/SQLite backends provide it.\n * Implementations MUST throw (not silently degrade) when\n * `capabilities.transactions` is `false` — a non-atomic fallback is\n * safe for graph-only writes but dangerous for cross-store flows,\n * where the caller's relational write *would* still commit.\n *\n * Fulltext stays safe by construction: the returned backend's\n * fulltext methods assert the durable materialization marker (a\n * cached SELECT, never DDL) at point of use and throw\n * `StoreNotInitializedError` on a missing/stale/failed marker rather\n * than migrating mid-transaction. Prefer booting the parent store via\n * `createStoreWithSchema` so that assertion is a warm-cache no-op.\n */\n adoptTransaction?: (externalTx: AdoptedTransaction) => TransactionBackend;\n\n // === Lifecycle ===\n close: () => Promise<void>;\n}>;\n\n// ============================================================\n// Managed Backend Helper\n// ============================================================\n\n/**\n * Wraps a GraphBackend with idempotent close that also runs a teardown\n * callback (e.g. closing the underlying database connection).\n */\nexport function wrapWithManagedClose(\n backend: GraphBackend,\n teardown: () => void | Promise<void>,\n): GraphBackend {\n let isClosed = false;\n return {\n ...backend,\n async close(): Promise<void> {\n if (isClosed) return;\n isClosed = true;\n await backend.close();\n await teardown();\n },\n };\n}\n\n/**\n * Runs `fn` inside a transaction when the backend supports one, falling\n * through to a direct invocation otherwise. Lets call sites benefit from\n * atomicity on backends that have transactions while staying functional\n * on backends that don't (Cloudflare D1, `drizzle-orm/neon-http` over\n * HTTP). The single-statement race window is already implicit on any\n * backend that reports `transactions: false`; callers that cannot\n * tolerate it must branch on the capability themselves.\n *\n * Pass `fallback` only when the toplevel backend method would recurse\n * — pass the operation-level backend so the no-tx path doesn't loop\n * back through the same toplevel method.\n */\nexport async function runOptionallyInTransaction<T>(\n backend: GraphBackend,\n fn: (target: GraphBackend | TransactionBackend) => Promise<T>,\n fallback?: GraphBackend | TransactionBackend,\n): Promise<T> {\n if (!backend.capabilities.transactions) {\n return fn(fallback ?? backend);\n }\n return backend.transaction((tx) => fn(tx));\n}\n\n// ============================================================\n// Additional Parameter Types\n// ============================================================\n\n/**\n * Parameters for inserting a unique constraint entry.\n */\nexport type InsertUniqueParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n key: string;\n nodeId: string;\n concreteKind: string;\n}>;\n\n/**\n * Parameters for deleting a unique constraint entry.\n */\nexport type DeleteUniqueParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n key: string;\n}>;\n\n/**\n * Parameters for checking a unique constraint.\n */\nexport type CheckUniqueParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n key: string;\n /** If true, also returns soft-deleted entries. Used by get-or-create operations. */\n includeDeleted?: boolean;\n}>;\n\n/**\n * Parameters for batch-checking unique constraints.\n */\nexport type CheckUniqueBatchParams = Readonly<{\n graphId: string;\n nodeKind: string;\n constraintName: string;\n keys: readonly string[];\n /** If true, also returns soft-deleted entries. Used by get-or-create operations. */\n includeDeleted?: boolean;\n}>;\n\n/**\n * Parameters for inserting a schema version.\n *\n * Used internally by backend implementations. Public callers go through\n * `commitSchemaVersion`, which handles the insert + activate atomically\n * with CAS guarantees.\n */\nexport type InsertSchemaParams = Readonly<{\n graphId: string;\n version: number;\n schemaHash: string;\n schemaDoc: SerializedSchema;\n isActive: boolean;\n}>;\n\n/**\n * The caller's claim about the currently-active schema version, used as\n * the optimistic compare-and-swap guard for `commitSchemaVersion`.\n *\n * - `{ kind: \"initial\" }` — caller is committing the first-ever version\n * for this graph and asserts no active version exists yet.\n * - `{ kind: \"active\", version: N }` — caller observed version N as\n * active and is committing version N+1 against that baseline. The\n * commit fails with `StaleVersionError` if some other writer has\n * advanced or rolled back the pointer in the meantime.\n *\n * Tagged-union form (rather than a magic `version: 0` sentinel) because\n * the two cases have materially different semantics: the initial path\n * skips the \"deactivate prior\" UPDATE, and the no-active-row state is\n * a *valid* expected state, not an out-of-band signal.\n */\nexport type CommitSchemaVersionExpected =\n | Readonly<{ kind: \"initial\" }>\n | Readonly<{ kind: \"active\"; version: number }>;\n\n/**\n * Parameters for `commitSchemaVersion`.\n */\nexport type CommitSchemaVersionParams = Readonly<{\n graphId: string;\n /** CAS guard — see `CommitSchemaVersionExpected`. */\n expected: CommitSchemaVersionExpected;\n /** The new version to insert and activate. */\n version: number;\n schemaHash: string;\n schemaDoc: SerializedSchema;\n}>;\n\n/**\n * Parameters for `setActiveVersion`.\n *\n * Flips the active pointer from `expected` to `version` for an existing\n * row. CAS prevents overwriting a concurrent rollback or commit.\n */\nexport type SetActiveVersionParams = Readonly<{\n graphId: string;\n /** CAS guard. Same semantics as `commitSchemaVersion.expected`. */\n expected: CommitSchemaVersionExpected;\n /** The version to mark active. Must already exist. */\n version: number;\n}>;\n\n/**\n * Parameters for counting edges from a source node.\n */\nexport type CountEdgesFromParams = Readonly<{\n graphId: string;\n edgeKind: string;\n fromKind: string;\n fromId: string;\n /** If true, only count edges where valid_to IS NULL */\n activeOnly?: boolean;\n}>;\n\n/**\n * Parameters for checking if an edge exists between two nodes.\n */\nexport type EdgeExistsBetweenParams = Readonly<{\n graphId: string;\n edgeKind: string;\n fromKind: string;\n fromId: string;\n toKind: string;\n toId: string;\n}>;\n\n/**\n * Parameters for finding edges connected to a node.\n */\nexport type FindEdgesConnectedToParams = Readonly<{\n graphId: string;\n nodeKind: string;\n nodeId: string;\n}>;\n\n/**\n * Parameters for finding nodes by kind.\n */\nexport type FindNodesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n /** Max rows to return. */\n limit?: number;\n /** Offset. Present for backward compat; rebuild uses `after` instead. */\n offset?: number;\n /** If true, exclude deleted nodes. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n /**\n * Stable ordering for keyset pagination. Default: \"created_at\" (existing\n * behavior). Rebuild should use \"id\" for iteration that is stable under\n * concurrent writes and shared timestamps.\n */\n orderBy?: \"id\" | \"created_at\";\n /**\n * Keyset cursor. Returns rows strictly greater (by `orderBy`) than this\n * value. When `orderBy: \"id\"`, compared lexicographically. Mutually\n * exclusive with `offset` — callers pick one.\n */\n after?: string;\n}>;\n\n/**\n * Parameters for counting nodes by kind.\n */\nexport type CountNodesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n /** If true, exclude deleted nodes. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n}>;\n\n/**\n * Parameters for finding edges by kind.\n */\nexport type FindEdgesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n fromKind?: string;\n fromId?: string;\n toKind?: string;\n toId?: string;\n limit?: number;\n offset?: number;\n /** If true, exclude deleted edges. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n}>;\n\n/**\n * Parameters for counting edges by kind.\n */\nexport type CountEdgesByKindParams = Readonly<{\n graphId: string;\n kind: string;\n fromKind?: string;\n fromId?: string;\n toKind?: string;\n toId?: string;\n /** If true, exclude deleted edges. Default true. */\n excludeDeleted?: boolean;\n /** Temporal mode for filtering by validity period. */\n temporalMode?: TemporalMode;\n /** Timestamp for \"current\" and \"asOf\" temporal modes. */\n asOf?: string;\n}>;\n\n// ============================================================\n// Default Capabilities\n// ============================================================\n\n/**\n * Default capabilities for SQLite.\n */\nexport const SQLITE_CAPABILITIES: BackendCapabilities = {\n transactions: true, // SQLite supports transactions\n};\n\n/**\n * Default capabilities for PostgreSQL.\n */\nexport const POSTGRES_CAPABILITIES: BackendCapabilities = {\n transactions: true, // PostgreSQL supports transactions\n};\n"]}
|