@nicia-ai/typegraph 0.30.0 → 0.31.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.
Files changed (181) hide show
  1. package/README.md +39 -0
  2. package/dist/backend/postgres/index.cjs +19 -18
  3. package/dist/backend/postgres/index.d.cts +6 -6
  4. package/dist/backend/postgres/index.d.ts +6 -6
  5. package/dist/backend/postgres/index.js +9 -8
  6. package/dist/backend/postgres/pglite.cjs +13 -12
  7. package/dist/backend/postgres/pglite.cjs.map +1 -1
  8. package/dist/backend/postgres/pglite.d.cts +3 -3
  9. package/dist/backend/postgres/pglite.d.ts +3 -3
  10. package/dist/backend/postgres/pglite.js +9 -8
  11. package/dist/backend/postgres/pglite.js.map +1 -1
  12. package/dist/backend/sqlite/index.cjs +16 -16
  13. package/dist/backend/sqlite/index.d.cts +7 -7
  14. package/dist/backend/sqlite/index.d.ts +7 -7
  15. package/dist/backend/sqlite/index.js +7 -7
  16. package/dist/backend/sqlite/libsql.cjs +12 -12
  17. package/dist/backend/sqlite/libsql.d.cts +3 -3
  18. package/dist/backend/sqlite/libsql.d.ts +3 -3
  19. package/dist/backend/sqlite/libsql.js +8 -8
  20. package/dist/backend/sqlite/local.cjs +13 -13
  21. package/dist/backend/sqlite/local.d.cts +3 -3
  22. package/dist/backend/sqlite/local.d.ts +3 -3
  23. package/dist/backend/sqlite/local.js +8 -8
  24. package/dist/{chunk-AI3RNREM.js → chunk-2HZGWCB4.js} +94 -496
  25. package/dist/chunk-2HZGWCB4.js.map +1 -0
  26. package/dist/chunk-2YMGNYXY.js +40 -0
  27. package/dist/chunk-2YMGNYXY.js.map +1 -0
  28. package/dist/chunk-2ZY4K43M.js +90 -0
  29. package/dist/chunk-2ZY4K43M.js.map +1 -0
  30. package/dist/chunk-3EUKJEQ3.js +77 -0
  31. package/dist/chunk-3EUKJEQ3.js.map +1 -0
  32. package/dist/chunk-3JBJEYWE.cjs +604 -0
  33. package/dist/chunk-3JBJEYWE.cjs.map +1 -0
  34. package/dist/{chunk-IUIJJYPI.js → chunk-4A4GUZTQ.js} +6 -5
  35. package/dist/chunk-4A4GUZTQ.js.map +1 -0
  36. package/dist/{chunk-WEMZM7J7.cjs → chunk-54JVNOAQ.cjs} +5 -41
  37. package/dist/chunk-54JVNOAQ.cjs.map +1 -0
  38. package/dist/{chunk-IE6GN7L3.cjs → chunk-5CN7B4CZ.cjs} +17 -98
  39. package/dist/chunk-5CN7B4CZ.cjs.map +1 -0
  40. package/dist/{chunk-K4N35E7B.cjs → chunk-5DTPBFX5.cjs} +64 -63
  41. package/dist/chunk-5DTPBFX5.cjs.map +1 -0
  42. package/dist/chunk-6G35I3VW.cjs +40 -0
  43. package/dist/chunk-6G35I3VW.cjs.map +1 -0
  44. package/dist/{chunk-4BXHVEFB.cjs → chunk-6RMLO5O4.cjs} +6 -51
  45. package/dist/chunk-6RMLO5O4.cjs.map +1 -0
  46. package/dist/chunk-6SA7UIQJ.cjs +94 -0
  47. package/dist/chunk-6SA7UIQJ.cjs.map +1 -0
  48. package/dist/chunk-6ZR4QC3O.cjs +12 -0
  49. package/dist/{chunk-LUHU4T2F.cjs.map → chunk-6ZR4QC3O.cjs.map} +1 -1
  50. package/dist/chunk-73KASJGO.cjs +52 -0
  51. package/dist/chunk-73KASJGO.cjs.map +1 -0
  52. package/dist/chunk-A3W7QG7K.js +45 -0
  53. package/dist/chunk-A3W7QG7K.js.map +1 -0
  54. package/dist/{chunk-FWBVPATK.cjs → chunk-ASYQDPPU.cjs} +19 -19
  55. package/dist/{chunk-FWBVPATK.cjs.map → chunk-ASYQDPPU.cjs.map} +1 -1
  56. package/dist/{chunk-FVIGJTS7.js → chunk-ATTXBMAX.js} +4 -74
  57. package/dist/chunk-ATTXBMAX.js.map +1 -0
  58. package/dist/chunk-AW4A3P5A.cjs +51 -0
  59. package/dist/chunk-AW4A3P5A.cjs.map +1 -0
  60. package/dist/{chunk-WFCECD6Q.cjs → chunk-CIINW6PS.cjs} +73 -68
  61. package/dist/chunk-CIINW6PS.cjs.map +1 -0
  62. package/dist/{chunk-26HWIIVS.cjs → chunk-FLOI7QOT.cjs} +63 -62
  63. package/dist/chunk-FLOI7QOT.cjs.map +1 -0
  64. package/dist/{chunk-633N7DSE.js → chunk-GKFWM3DS.js} +4 -36
  65. package/dist/chunk-GKFWM3DS.js.map +1 -0
  66. package/dist/chunk-HTGDWIDE.cjs +89 -0
  67. package/dist/chunk-HTGDWIDE.cjs.map +1 -0
  68. package/dist/{chunk-R4JOBEJU.js → chunk-IJORSAC3.js} +4 -40
  69. package/dist/chunk-IJORSAC3.js.map +1 -0
  70. package/dist/{chunk-SGPXKJ4A.cjs → chunk-KTIEB7VH.cjs} +26 -16
  71. package/dist/chunk-KTIEB7VH.cjs.map +1 -0
  72. package/dist/chunk-LJLMDDCW.js +282 -0
  73. package/dist/chunk-LJLMDDCW.js.map +1 -0
  74. package/dist/{chunk-VFX3LC76.cjs → chunk-N2MBPTAF.cjs} +14 -14
  75. package/dist/{chunk-VFX3LC76.cjs.map → chunk-N2MBPTAF.cjs.map} +1 -1
  76. package/dist/{chunk-3IRMLJEK.js → chunk-O4VUR6SI.js} +3 -3
  77. package/dist/{chunk-3IRMLJEK.js.map → chunk-O4VUR6SI.js.map} +1 -1
  78. package/dist/chunk-RZ4DH4E7.cjs +15832 -0
  79. package/dist/chunk-RZ4DH4E7.cjs.map +1 -0
  80. package/dist/chunk-SAJSMR2B.js +35 -0
  81. package/dist/chunk-SAJSMR2B.js.map +1 -0
  82. package/dist/{chunk-4LBO6KIF.cjs → chunk-SFFJ2IKN.cjs} +60 -59
  83. package/dist/chunk-SFFJ2IKN.cjs.map +1 -0
  84. package/dist/{chunk-K5VREXMZ.js → chunk-STP7QVUB.js} +7 -6
  85. package/dist/chunk-STP7QVUB.js.map +1 -0
  86. package/dist/chunk-THX25XW6.js +590 -0
  87. package/dist/chunk-THX25XW6.js.map +1 -0
  88. package/dist/chunk-UIFEEPME.js +15787 -0
  89. package/dist/chunk-UIFEEPME.js.map +1 -0
  90. package/dist/{chunk-2QA5EHEN.js → chunk-UJ4V3YUQ.js} +3 -3
  91. package/dist/{chunk-2QA5EHEN.js.map → chunk-UJ4V3YUQ.js.map} +1 -1
  92. package/dist/{chunk-UESTHN47.cjs → chunk-V4IQYOQ4.cjs} +95 -507
  93. package/dist/chunk-V4IQYOQ4.cjs.map +1 -0
  94. package/dist/chunk-VMEWZU2N.cjs +287 -0
  95. package/dist/chunk-VMEWZU2N.cjs.map +1 -0
  96. package/dist/{chunk-N2OEOGBB.js → chunk-VZX2KSY3.js} +13 -8
  97. package/dist/chunk-VZX2KSY3.js.map +1 -0
  98. package/dist/{chunk-IX7RE7CG.js → chunk-WYTUF3QO.js} +3 -3
  99. package/dist/{chunk-IX7RE7CG.js.map → chunk-WYTUF3QO.js.map} +1 -1
  100. package/dist/{chunk-3JLRHQ67.js → chunk-XKJQQQVR.js} +6 -5
  101. package/dist/chunk-XKJQQQVR.js.map +1 -0
  102. package/dist/{chunk-ENDUY2CD.js → chunk-YCV72E6L.js} +23 -17
  103. package/dist/chunk-YCV72E6L.js.map +1 -0
  104. package/dist/{ddl-EdkIiFVU.d.ts → ddl-BJcPrB4L.d.ts} +3 -3
  105. package/dist/{ddl-BSFlbGQF.d.cts → ddl-CPZ7mB7X.d.cts} +3 -3
  106. package/dist/{extension-types-CwHV-Uk4.d.cts → extension-types-D1k0inWU.d.cts} +1 -1
  107. package/dist/{extension-types-CwHV-Uk4.d.ts → extension-types-D1k0inWU.d.ts} +1 -1
  108. package/dist/graph-extension/index.cjs +17 -17
  109. package/dist/graph-extension/index.d.cts +5 -16
  110. package/dist/graph-extension/index.d.ts +5 -16
  111. package/dist/graph-extension/index.js +2 -2
  112. package/dist/graph-merge/index.cjs +3822 -0
  113. package/dist/graph-merge/index.cjs.map +1 -0
  114. package/dist/graph-merge/index.d.cts +1191 -0
  115. package/dist/graph-merge/index.d.ts +1191 -0
  116. package/dist/graph-merge/index.js +3791 -0
  117. package/dist/graph-merge/index.js.map +1 -0
  118. package/dist/{index-DzeIiMO3.d.ts → index-BEK0VtNB.d.ts} +2 -2
  119. package/dist/{index-Ln_KHTGA.d.cts → index-C8sSTErx.d.cts} +2 -2
  120. package/dist/index.cjs +281 -15913
  121. package/dist/index.cjs.map +1 -1
  122. package/dist/index.d.cts +12 -11
  123. package/dist/index.d.ts +12 -11
  124. package/dist/index.js +23 -15790
  125. package/dist/index.js.map +1 -1
  126. package/dist/indexes/index.cjs +30 -26
  127. package/dist/indexes/index.d.cts +5 -5
  128. package/dist/indexes/index.d.ts +5 -5
  129. package/dist/indexes/index.js +6 -2
  130. package/dist/interchange/index.cjs +49 -592
  131. package/dist/interchange/index.cjs.map +1 -1
  132. package/dist/interchange/index.d.cts +5 -5
  133. package/dist/interchange/index.d.ts +5 -5
  134. package/dist/interchange/index.js +2 -588
  135. package/dist/interchange/index.js.map +1 -1
  136. package/dist/{manager-BbdyNhkv.d.ts → manager-By-WEd8M.d.ts} +3 -3
  137. package/dist/{manager-wTDgjoXG.d.cts → manager-Np7VVSlE.d.cts} +3 -3
  138. package/dist/{materialize-indexes-lkawaDor.d.ts → materialize-indexes-CAGhqPHQ.d.ts} +1 -1
  139. package/dist/{materialize-indexes-oanE3RU0.d.cts → materialize-indexes-DEYkU-wr.d.cts} +1 -1
  140. package/dist/{postgres-CK2ByP1q.d.cts → postgres-4J2tmauh.d.cts} +1 -1
  141. package/dist/{postgres-ymXYC6Rr.d.ts → postgres-BdIb7tS_.d.ts} +1 -1
  142. package/dist/profiler/index.d.cts +7 -7
  143. package/dist/profiler/index.d.ts +7 -7
  144. package/dist/result-DWo6mUVz.d.cts +37 -0
  145. package/dist/result-DWo6mUVz.d.ts +37 -0
  146. package/dist/schema/index.cjs +29 -28
  147. package/dist/schema/index.cjs.map +1 -1
  148. package/dist/schema/index.d.cts +7 -7
  149. package/dist/schema/index.d.ts +7 -7
  150. package/dist/schema/index.js +6 -5
  151. package/dist/schema/index.js.map +1 -1
  152. package/dist/{sqlite-DxH1lrwD.d.cts → sqlite-Gatk_iw_.d.cts} +1 -1
  153. package/dist/{sqlite-R8YGOqVQ.d.ts → sqlite-aM_PAz-O.d.ts} +1 -1
  154. package/dist/{store--z1Tmk7U.d.cts → store-DuCbdqsh.d.cts} +49 -49
  155. package/dist/{store-CNKM334w.d.ts → store-MloRPwb9.d.ts} +49 -49
  156. package/dist/{types-BBiDqJCU.d.ts → types-BKQljXom.d.ts} +16 -2
  157. package/dist/{types-dL-clxO3.d.cts → types-C1CYxWrL.d.cts} +16 -2
  158. package/dist/{types-D5B6Be5c.d.cts → types-DoByHGyU.d.cts} +2 -2
  159. package/dist/{types-CMvxx2kd.d.ts → types-K3vpaJAL.d.ts} +2 -2
  160. package/dist/{where-CAo6wsBZ.d.ts → where-Dt49bvo6.d.ts} +2 -2
  161. package/dist/{where-bJjuOCeV.d.cts → where-DydZjGOb.d.cts} +2 -2
  162. package/package.json +6 -1
  163. package/dist/chunk-26HWIIVS.cjs.map +0 -1
  164. package/dist/chunk-3JLRHQ67.js.map +0 -1
  165. package/dist/chunk-4BXHVEFB.cjs.map +0 -1
  166. package/dist/chunk-4LBO6KIF.cjs.map +0 -1
  167. package/dist/chunk-633N7DSE.js.map +0 -1
  168. package/dist/chunk-AI3RNREM.js.map +0 -1
  169. package/dist/chunk-ENDUY2CD.js.map +0 -1
  170. package/dist/chunk-FVIGJTS7.js.map +0 -1
  171. package/dist/chunk-IE6GN7L3.cjs.map +0 -1
  172. package/dist/chunk-IUIJJYPI.js.map +0 -1
  173. package/dist/chunk-K4N35E7B.cjs.map +0 -1
  174. package/dist/chunk-K5VREXMZ.js.map +0 -1
  175. package/dist/chunk-LUHU4T2F.cjs +0 -12
  176. package/dist/chunk-N2OEOGBB.js.map +0 -1
  177. package/dist/chunk-R4JOBEJU.js.map +0 -1
  178. package/dist/chunk-SGPXKJ4A.cjs.map +0 -1
  179. package/dist/chunk-UESTHN47.cjs.map +0 -1
  180. package/dist/chunk-WEMZM7J7.cjs.map +0 -1
  181. package/dist/chunk-WFCECD6Q.cjs.map +0 -1
@@ -0,0 +1,35 @@
1
+ // src/backend/types.ts
2
+ function wrapWithManagedClose(backend, teardown) {
3
+ let isClosed = false;
4
+ return {
5
+ ...backend,
6
+ async close() {
7
+ if (isClosed) return;
8
+ isClosed = true;
9
+ await backend.close();
10
+ await teardown();
11
+ }
12
+ };
13
+ }
14
+ async function runOptionallyInTransaction(backend, fn, fallback) {
15
+ if (!backend.capabilities.transactions) {
16
+ return fn(fallback ?? backend);
17
+ }
18
+ return backend.transaction((tx) => fn(tx));
19
+ }
20
+ var SQLITE_CAPABILITIES = {
21
+ transactions: true,
22
+ // SQLite supports transactions
23
+ windowFunctions: true
24
+ // SQLite has supported window functions since 3.25.0
25
+ };
26
+ var POSTGRES_CAPABILITIES = {
27
+ transactions: true,
28
+ // PostgreSQL supports transactions
29
+ windowFunctions: true
30
+ // PostgreSQL supports ROW_NUMBER() and related windows
31
+ };
32
+
33
+ export { POSTGRES_CAPABILITIES, SQLITE_CAPABILITIES, runOptionallyInTransaction, wrapWithManagedClose };
34
+ //# sourceMappingURL=chunk-SAJSMR2B.js.map
35
+ //# sourceMappingURL=chunk-SAJSMR2B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/backend/types.ts"],"names":[],"mappings":";AAkrCO,SAAS,oBAAA,CACd,SACA,QAAA,EACc;AACd,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,OAAO;AAAA,IACL,GAAG,OAAA;AAAA,IACH,MAAM,KAAA,GAAuB;AAC3B,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,MAAM,QAAQ,KAAA,EAAM;AACpB,MAAA,MAAM,QAAA,EAAS;AAAA,IACjB;AAAA,GACF;AACF;AAeA,eAAsB,0BAAA,CACpB,OAAA,EACA,EAAA,EACA,QAAA,EACY;AACZ,EAAA,IAAI,CAAC,OAAA,CAAQ,YAAA,CAAa,YAAA,EAAc;AACtC,IAAA,OAAO,EAAA,CAAG,YAAY,OAAO,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,QAAQ,WAAA,CAAY,CAAC,EAAA,KAAO,EAAA,CAAG,EAAE,CAAC,CAAA;AAC3C;AA0PO,IAAM,mBAAA,GAA2C;AAAA,EACtD,YAAA,EAAc,IAAA;AAAA;AAAA,EACd,eAAA,EAAiB;AAAA;AACnB;AAKO,IAAM,qBAAA,GAA6C;AAAA,EACxD,YAAA,EAAc,IAAA;AAAA;AAAA,EACd,eAAA,EAAiB;AAAA;AACnB","file":"chunk-SAJSMR2B.js","sourcesContent":["/**\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 /** Whether the backend supports SQL window functions such as ROW_NUMBER() */\n windowFunctions: 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 * Stable ordering for keyset pagination. Default: \"created_at\" (existing\n * behavior). Use \"id\" for iteration that is stable under shared `created_at`\n * timestamps — the offset path orders by the NON-unique `created_at`, so a\n * full enumeration must page by the unique `id` to avoid skipping a row at a\n * page boundary. Mirrors {@link FindNodesByKindParams.orderBy}.\n */\n orderBy?: \"id\" | \"created_at\";\n /**\n * Keyset cursor. Returns rows strictly greater (by `orderBy`) than this value.\n * When `orderBy: \"id\"`, compared lexicographically. Mutually exclusive with\n * `offset` — callers pick one. Mirrors {@link FindNodesByKindParams.after}.\n */\n after?: 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 windowFunctions: true, // SQLite has supported window functions since 3.25.0\n};\n\n/**\n * Default capabilities for PostgreSQL.\n */\nexport const POSTGRES_CAPABILITIES: BackendCapabilities = {\n transactions: true, // PostgreSQL supports transactions\n windowFunctions: true, // PostgreSQL supports ROW_NUMBER() and related windows\n};\n"]}
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkWFCECD6Q_cjs = require('./chunk-WFCECD6Q.cjs');
4
- var chunkWEMZM7J7_cjs = require('./chunk-WEMZM7J7.cjs');
3
+ var chunkCIINW6PS_cjs = require('./chunk-CIINW6PS.cjs');
4
+ var chunk54JVNOAQ_cjs = require('./chunk-54JVNOAQ.cjs');
5
+ var chunk6G35I3VW_cjs = require('./chunk-6G35I3VW.cjs');
5
6
  var chunkRP7YITHX_cjs = require('./chunk-RP7YITHX.cjs');
6
- var chunkUESTHN47_cjs = require('./chunk-UESTHN47.cjs');
7
+ var chunkV4IQYOQ4_cjs = require('./chunk-V4IQYOQ4.cjs');
7
8
  var chunkJIEJCTDS_cjs = require('./chunk-JIEJCTDS.cjs');
8
9
  var drizzleOrm = require('drizzle-orm');
9
10
  var sqliteCore = require('drizzle-orm/sqlite-core');
@@ -71,7 +72,7 @@ function resolveSqliteClient(db) {
71
72
  return sqliteClient;
72
73
  }
73
74
  function getOrCreatePreparedStatement(cache, sqliteClient, sqlText, cacheMax) {
74
- return chunkWFCECD6Q_cjs.getOrCreateLru(
75
+ return chunkCIINW6PS_cjs.getOrCreateLru(
75
76
  cache,
76
77
  sqlText,
77
78
  cacheMax,
@@ -107,7 +108,7 @@ function createSqliteExecutionAdapter(db, statementCacheMaxOrOptions = {}) {
107
108
  supportsCompiledExecution: sqliteClient !== void 0,
108
109
  transactionMode
109
110
  };
110
- const compile = (query) => chunkWFCECD6Q_cjs.compileQueryWithDialect(db, query, "SQLite");
111
+ const compile = (query) => chunkCIINW6PS_cjs.compileQueryWithDialect(db, query, "SQLite");
111
112
  if (sqliteClient !== void 0) {
112
113
  let executeCompiled2 = function(compiledQuery) {
113
114
  const preparedStatement = getOrCreatePreparedStatement(
@@ -178,11 +179,11 @@ var SQLITE_CHECK_UNIQUE_BATCH_CHUNK_SIZE = Math.max(
178
179
  1,
179
180
  SQLITE_MAX_BIND_PARAMETERS - CHECK_UNIQUE_BATCH_FIXED_PARAM_COUNT
180
181
  );
181
- var toNodeRow = chunkWFCECD6Q_cjs.createNodeRowMapper(chunkWFCECD6Q_cjs.SQLITE_ROW_MAPPER_CONFIG);
182
- var toEdgeRow = chunkWFCECD6Q_cjs.createEdgeRowMapper(chunkWFCECD6Q_cjs.SQLITE_ROW_MAPPER_CONFIG);
183
- var toUniqueRow = chunkWFCECD6Q_cjs.createUniqueRowMapper(chunkWFCECD6Q_cjs.SQLITE_ROW_MAPPER_CONFIG);
184
- var toSchemaVersionRow = chunkWFCECD6Q_cjs.createSchemaVersionRowMapper(
185
- chunkWFCECD6Q_cjs.SQLITE_ROW_MAPPER_CONFIG
182
+ var toNodeRow = chunkCIINW6PS_cjs.createNodeRowMapper(chunkCIINW6PS_cjs.SQLITE_ROW_MAPPER_CONFIG);
183
+ var toEdgeRow = chunkCIINW6PS_cjs.createEdgeRowMapper(chunkCIINW6PS_cjs.SQLITE_ROW_MAPPER_CONFIG);
184
+ var toUniqueRow = chunkCIINW6PS_cjs.createUniqueRowMapper(chunkCIINW6PS_cjs.SQLITE_ROW_MAPPER_CONFIG);
185
+ var toSchemaVersionRow = chunkCIINW6PS_cjs.createSchemaVersionRowMapper(
186
+ chunkCIINW6PS_cjs.SQLITE_ROW_MAPPER_CONFIG
186
187
  );
187
188
  var PENDING_FOREVER = new Promise(noop);
188
189
  function pendingForever() {
@@ -232,11 +233,11 @@ function throwSqliteTransactionsDisabled(message) {
232
233
  });
233
234
  }
234
235
  function buildSqliteCapabilities(options) {
235
- const base = options.transactionMode === "none" ? { ...chunkWEMZM7J7_cjs.SQLITE_CAPABILITIES, transactions: false } : chunkWEMZM7J7_cjs.SQLITE_CAPABILITIES;
236
+ const base = options.transactionMode === "none" ? { ...chunk6G35I3VW_cjs.SQLITE_CAPABILITIES, transactions: false } : chunk6G35I3VW_cjs.SQLITE_CAPABILITIES;
236
237
  return {
237
238
  ...base,
238
- fulltext: chunkUESTHN47_cjs.buildFulltextCapabilities(options.fulltextStrategy),
239
- ...options.vectorStrategy === void 0 ? {} : { vector: chunkUESTHN47_cjs.buildVectorCapabilities(options.vectorStrategy) }
239
+ fulltext: chunkV4IQYOQ4_cjs.buildFulltextCapabilities(options.fulltextStrategy),
240
+ ...options.vectorStrategy === void 0 ? {} : { vector: chunkV4IQYOQ4_cjs.buildVectorCapabilities(options.vectorStrategy) }
240
241
  };
241
242
  }
242
243
  function createSqliteOperationBackend(options) {
@@ -267,7 +268,7 @@ function createSqliteOperationBackend(options) {
267
268
  await db.run(query);
268
269
  });
269
270
  }
270
- const commonBackend = chunkWFCECD6Q_cjs.createCommonOperationBackend({
271
+ const commonBackend = chunkCIINW6PS_cjs.createCommonOperationBackend({
271
272
  batchConfig: {
272
273
  checkUniqueBatchChunkSize: SQLITE_CHECK_UNIQUE_BATCH_CHUNK_SIZE,
273
274
  edgeInsertBatchSize: SQLITE_EDGE_INSERT_BATCH_SIZE,
@@ -280,7 +281,7 @@ function createSqliteOperationBackend(options) {
280
281
  execGet,
281
282
  execRun
282
283
  },
283
- nowIso: chunkWFCECD6Q_cjs.nowIso,
284
+ nowIso: chunkCIINW6PS_cjs.nowIso,
284
285
  operationStrategy,
285
286
  rowMappers: {
286
287
  toEdgeRow,
@@ -306,19 +307,19 @@ function createSqliteOperationBackend(options) {
306
307
  }
307
308
  const vectorEmbeddingMethods = vectorStrategy === void 0 ? {} : {
308
309
  async upsertEmbedding(params) {
309
- const slot = chunkWFCECD6Q_cjs.vectorSlotFromParams(params);
310
+ const slot = chunkCIINW6PS_cjs.vectorSlotFromParams(params);
310
311
  await ensureVectorSlotStorage(slot);
311
- const statements = vectorStrategy.buildUpsert(slot, params, chunkWFCECD6Q_cjs.nowIso());
312
+ const statements = vectorStrategy.buildUpsert(slot, params, chunkCIINW6PS_cjs.nowIso());
312
313
  try {
313
314
  for (const statement of statements) {
314
315
  await execRun(statement);
315
316
  }
316
317
  } catch (error) {
317
- throw chunkWFCECD6Q_cjs.mapVectorWriteError(error, params);
318
+ throw chunkCIINW6PS_cjs.mapVectorWriteError(error, params);
318
319
  }
319
320
  },
320
321
  async deleteEmbedding(params) {
321
- const slot = chunkWFCECD6Q_cjs.vectorSlotFromParams(params);
322
+ const slot = chunkCIINW6PS_cjs.vectorSlotFromParams(params);
322
323
  await ensureVectorSlotStorage(slot);
323
324
  const statements = vectorStrategy.buildDelete(slot, params);
324
325
  for (const statement of statements) {
@@ -326,15 +327,15 @@ function createSqliteOperationBackend(options) {
326
327
  }
327
328
  },
328
329
  async vectorSearch(params) {
329
- chunkUESTHN47_cjs.assertVectorSearchLimit(params.limit);
330
- const slot = chunkWFCECD6Q_cjs.vectorSlotFromParams(params);
330
+ chunkV4IQYOQ4_cjs.assertVectorSearchLimit(params.limit);
331
+ const slot = chunkCIINW6PS_cjs.vectorSlotFromParams(params);
331
332
  await ensureVectorSlotStorage(slot);
332
333
  const query = vectorStrategy.buildSearch(slot, params);
333
334
  let rows;
334
335
  try {
335
336
  rows = await execAll(query);
336
337
  } catch (error) {
337
- throw chunkWFCECD6Q_cjs.mapVectorWriteError(error, params);
338
+ throw chunkCIINW6PS_cjs.mapVectorWriteError(error, params);
338
339
  }
339
340
  return rows.map((row) => ({
340
341
  nodeId: row.node_id,
@@ -353,7 +354,7 @@ function createSqliteOperationBackend(options) {
353
354
  ...vectorStrategy === void 0 ? {} : { vectorStrategy },
354
355
  async createVectorIndex(params) {
355
356
  if (vectorStrategy === void 0) return;
356
- const slot = chunkWFCECD6Q_cjs.vectorSlotFromCreateIndexParams(params);
357
+ const slot = chunkCIINW6PS_cjs.vectorSlotFromCreateIndexParams(params);
357
358
  await ensureVectorSlotStorage(slot);
358
359
  const indexStatement = vectorStrategy.buildCreateIndex?.(slot);
359
360
  if (indexStatement !== void 0) {
@@ -362,7 +363,7 @@ function createSqliteOperationBackend(options) {
362
363
  },
363
364
  async dropVectorIndex(params) {
364
365
  if (vectorStrategy === void 0) return;
365
- const slot = chunkWFCECD6Q_cjs.vectorSlotFromDropIndexParams(params);
366
+ const slot = chunkCIINW6PS_cjs.vectorSlotFromDropIndexParams(params);
366
367
  const dropStatement = vectorStrategy.buildDropIndex?.(slot);
367
368
  if (dropStatement === void 0) return;
368
369
  try {
@@ -373,7 +374,7 @@ function createSqliteOperationBackend(options) {
373
374
  },
374
375
  // === Fulltext Operations ===
375
376
  async upsertFulltext(params) {
376
- const timestamp = chunkWFCECD6Q_cjs.nowIso();
377
+ const timestamp = chunkCIINW6PS_cjs.nowIso();
377
378
  const statements = operationStrategy.buildUpsertFulltext(
378
379
  params,
379
380
  timestamp
@@ -390,7 +391,7 @@ function createSqliteOperationBackend(options) {
390
391
  },
391
392
  async upsertFulltextBatch(params) {
392
393
  if (params.rows.length === 0) return;
393
- const timestamp = chunkWFCECD6Q_cjs.nowIso();
394
+ const timestamp = chunkCIINW6PS_cjs.nowIso();
394
395
  const statements = operationStrategy.buildUpsertFulltextBatch(
395
396
  params,
396
397
  timestamp
@@ -411,7 +412,7 @@ function createSqliteOperationBackend(options) {
411
412
  const rows = await execAll(query);
412
413
  return rows.map((row, index) => ({
413
414
  nodeId: row.node_id,
414
- score: chunkWFCECD6Q_cjs.coerceNumericScore(row.score),
415
+ score: chunkCIINW6PS_cjs.coerceNumericScore(row.score),
415
416
  rank: index + 1,
416
417
  ...row.snippet === null ? {} : { snippet: row.snippet }
417
418
  }));
@@ -430,13 +431,13 @@ function createSqliteOperationBackend(options) {
430
431
  return operationBackend;
431
432
  }
432
433
  function createSqliteBackend(db, options = {}) {
433
- const tables2 = options.tables ?? chunkWEMZM7J7_cjs.tables;
434
- const fulltextStrategy = options.fulltext ?? chunkUESTHN47_cjs.fts5Strategy;
434
+ const tables2 = options.tables ?? chunk54JVNOAQ_cjs.tables;
435
+ const fulltextStrategy = options.fulltext ?? chunkV4IQYOQ4_cjs.fts5Strategy;
435
436
  const profileHints = options.executionProfile ?? {};
436
437
  const executionAdapter = createSqliteExecutionAdapter(db, { profileHints });
437
438
  const { isSync, transactionMode } = executionAdapter.profile;
438
439
  const vectorStrategy = options.vector;
439
- const vectorSlotLatch = vectorStrategy === void 0 ? void 0 : chunkWFCECD6Q_cjs.createVectorSlotLatch();
440
+ const vectorSlotLatch = vectorStrategy === void 0 ? void 0 : chunkCIINW6PS_cjs.createVectorSlotLatch();
440
441
  const capabilities = {
441
442
  ...buildSqliteCapabilities({
442
443
  fulltextStrategy,
@@ -451,7 +452,7 @@ function createSqliteBackend(db, options = {}) {
451
452
  fulltext: tables2.fulltextTableName,
452
453
  uniques: drizzleOrm.getTableName(tables2.uniques)
453
454
  };
454
- const operationStrategy = chunkWFCECD6Q_cjs.createSqliteOperationStrategy(
455
+ const operationStrategy = chunkCIINW6PS_cjs.createSqliteOperationStrategy(
455
456
  tables2,
456
457
  fulltextStrategy
457
458
  );
@@ -541,7 +542,7 @@ function createSqliteBackend(db, options = {}) {
541
542
  }
542
543
  const matTable = tables2.contributionMaterializations;
543
544
  async function ensureContributionMaterializationsTableImpl() {
544
- await db.run(drizzleOrm.sql.raw(chunkWFCECD6Q_cjs.generateSqliteCreateTableSQL(matTable)));
545
+ await db.run(drizzleOrm.sql.raw(chunkCIINW6PS_cjs.generateSqliteCreateTableSQL(matTable)));
545
546
  }
546
547
  async function getContributionMaterializationRow(identity) {
547
548
  const rows = await db.select().from(matTable).where(
@@ -554,16 +555,16 @@ function createSqliteBackend(db, options = {}) {
554
555
  );
555
556
  const row = rows[0];
556
557
  if (row === void 0) return void 0;
557
- return chunkWFCECD6Q_cjs.mapContributionMaterializationRow(
558
+ return chunkCIINW6PS_cjs.mapContributionMaterializationRow(
558
559
  row,
559
- chunkWFCECD6Q_cjs.SQLITE_CONTRIBUTION_MAT_TIMESTAMPS.decode
560
+ chunkCIINW6PS_cjs.SQLITE_CONTRIBUTION_MAT_TIMESTAMPS.decode
560
561
  );
561
562
  }
562
563
  async function recordContributionMaterializationRow(params) {
563
564
  await db.insert(matTable).values(
564
- chunkWFCECD6Q_cjs.buildContributionInsertValues(
565
+ chunkCIINW6PS_cjs.buildContributionInsertValues(
565
566
  params,
566
- chunkWFCECD6Q_cjs.SQLITE_CONTRIBUTION_MAT_TIMESTAMPS.encode
567
+ chunkCIINW6PS_cjs.SQLITE_CONTRIBUTION_MAT_TIMESTAMPS.encode
567
568
  )
568
569
  ).onConflictDoUpdate({
569
570
  target: [
@@ -572,13 +573,13 @@ function createSqliteBackend(db, options = {}) {
572
573
  matTable.owner,
573
574
  matTable.tableName
574
575
  ],
575
- set: chunkWFCECD6Q_cjs.buildContributionOnConflictSet(
576
+ set: chunkCIINW6PS_cjs.buildContributionOnConflictSet(
576
577
  matTable.materializedAt,
577
578
  params.materializedAt
578
579
  )
579
580
  });
580
581
  }
581
- const contributionMaterializer = chunkWFCECD6Q_cjs.createContributionMaterializer({
582
+ const contributionMaterializer = chunkCIINW6PS_cjs.createContributionMaterializer({
582
583
  dialect: "sqlite",
583
584
  fulltextStrategy,
584
585
  fulltextTableName: tables2.fulltextTableName,
@@ -598,12 +599,12 @@ function createSqliteBackend(db, options = {}) {
598
599
  tableNames,
599
600
  fulltextStrategy,
600
601
  vectorStrategy});
601
- return chunkWFCECD6Q_cjs.gateFulltext(txBackend, contributionMaterializer.assertInitialized);
602
+ return chunkCIINW6PS_cjs.gateFulltext(txBackend, contributionMaterializer.assertInitialized);
602
603
  }
603
604
  const backend = {
604
605
  ...operations,
605
606
  async bootstrapTables() {
606
- const statements = chunkWFCECD6Q_cjs.generateSqliteDDL(tables2, fulltextStrategy);
607
+ const statements = chunkCIINW6PS_cjs.generateSqliteDDL(tables2, fulltextStrategy);
607
608
  for (const statement of statements) {
608
609
  await db.run(drizzleOrm.sql.raw(statement));
609
610
  }
@@ -613,7 +614,7 @@ function createSqliteBackend(db, options = {}) {
613
614
  // uninitialized database throws `StoreNotInitializedError` rather
614
615
  // than self-healing (#135). Shared verbatim with the tx-scoped gate
615
616
  // via `gateFulltextMethods`.
616
- ...chunkWFCECD6Q_cjs.gateFulltextMethods(
617
+ ...chunkCIINW6PS_cjs.gateFulltextMethods(
617
618
  operations,
618
619
  contributionMaterializer.assertInitialized
619
620
  ),
@@ -622,7 +623,7 @@ function createSqliteBackend(db, options = {}) {
622
623
  },
623
624
  async ensureIndexMaterializationsTable() {
624
625
  await db.run(
625
- drizzleOrm.sql.raw(chunkWFCECD6Q_cjs.generateSqliteCreateTableSQL(tables2.indexMaterializations))
626
+ drizzleOrm.sql.raw(chunkCIINW6PS_cjs.generateSqliteCreateTableSQL(tables2.indexMaterializations))
626
627
  );
627
628
  },
628
629
  async getIndexMaterialization(indexName) {
@@ -630,26 +631,26 @@ function createSqliteBackend(db, options = {}) {
630
631
  const rows = await db.select().from(t).where(drizzleOrm.eq(t.indexName, indexName));
631
632
  const row = rows[0];
632
633
  if (row === void 0) return void 0;
633
- return chunkWFCECD6Q_cjs.mapMaterializationRow(row, chunkWFCECD6Q_cjs.SQLITE_INDEX_MAT_TIMESTAMPS.decode);
634
+ return chunkCIINW6PS_cjs.mapMaterializationRow(row, chunkCIINW6PS_cjs.SQLITE_INDEX_MAT_TIMESTAMPS.decode);
634
635
  },
635
636
  async getIndexMaterializations(statusKeys) {
636
637
  if (statusKeys.length === 0) return [];
637
638
  const t = tables2.indexMaterializations;
638
639
  const rows = await db.select().from(t).where(drizzleOrm.inArray(t.indexName, [...statusKeys]));
639
640
  return rows.map(
640
- (row) => chunkWFCECD6Q_cjs.mapMaterializationRow(row, chunkWFCECD6Q_cjs.SQLITE_INDEX_MAT_TIMESTAMPS.decode)
641
+ (row) => chunkCIINW6PS_cjs.mapMaterializationRow(row, chunkCIINW6PS_cjs.SQLITE_INDEX_MAT_TIMESTAMPS.decode)
641
642
  );
642
643
  },
643
644
  async recordIndexMaterialization(params) {
644
645
  const t = tables2.indexMaterializations;
645
646
  await db.insert(t).values(
646
- chunkWFCECD6Q_cjs.buildMaterializationInsertValues(
647
+ chunkCIINW6PS_cjs.buildMaterializationInsertValues(
647
648
  params,
648
- chunkWFCECD6Q_cjs.SQLITE_INDEX_MAT_TIMESTAMPS.encode
649
+ chunkCIINW6PS_cjs.SQLITE_INDEX_MAT_TIMESTAMPS.encode
649
650
  )
650
651
  ).onConflictDoUpdate({
651
652
  target: t.indexName,
652
- set: chunkWFCECD6Q_cjs.buildMaterializationOnConflictSet(
653
+ set: chunkCIINW6PS_cjs.buildMaterializationOnConflictSet(
653
654
  t.materializedAt,
654
655
  params.materializedAt
655
656
  )
@@ -668,37 +669,37 @@ function createSqliteBackend(db, options = {}) {
668
669
  await contributionMaterializer.assertInitialized(graphId);
669
670
  },
670
671
  async ensureKindRemovalsTable() {
671
- await db.run(drizzleOrm.sql.raw(chunkWFCECD6Q_cjs.generateSqliteCreateTableSQL(tables2.kindRemovals)));
672
+ await db.run(drizzleOrm.sql.raw(chunkCIINW6PS_cjs.generateSqliteCreateTableSQL(tables2.kindRemovals)));
672
673
  },
673
674
  async getPendingKindRemovals(graphId) {
674
675
  const t = tables2.kindRemovals;
675
676
  const rows = await db.select().from(t).where(drizzleOrm.and(drizzleOrm.eq(t.graphId, graphId), drizzleOrm.isNull(t.removedAt)));
676
677
  return rows.map(
677
- (row) => chunkWFCECD6Q_cjs.mapKindRemovalRow(row, chunkWFCECD6Q_cjs.SQLITE_KIND_REMOVAL_TIMESTAMPS.decode)
678
+ (row) => chunkCIINW6PS_cjs.mapKindRemovalRow(row, chunkCIINW6PS_cjs.SQLITE_KIND_REMOVAL_TIMESTAMPS.decode)
678
679
  );
679
680
  },
680
681
  async getAllKindRemovals(graphId) {
681
682
  const t = tables2.kindRemovals;
682
683
  const rows = await db.select().from(t).where(drizzleOrm.eq(t.graphId, graphId));
683
684
  return rows.map(
684
- (row) => chunkWFCECD6Q_cjs.mapKindRemovalRow(row, chunkWFCECD6Q_cjs.SQLITE_KIND_REMOVAL_TIMESTAMPS.decode)
685
+ (row) => chunkCIINW6PS_cjs.mapKindRemovalRow(row, chunkCIINW6PS_cjs.SQLITE_KIND_REMOVAL_TIMESTAMPS.decode)
685
686
  );
686
687
  },
687
688
  async recordKindRemoval(params) {
688
689
  const t = tables2.kindRemovals;
689
690
  await db.insert(t).values(
690
- chunkWFCECD6Q_cjs.buildKindRemovalInsertValues(
691
+ chunkCIINW6PS_cjs.buildKindRemovalInsertValues(
691
692
  params,
692
- chunkWFCECD6Q_cjs.SQLITE_KIND_REMOVAL_TIMESTAMPS.encode
693
+ chunkCIINW6PS_cjs.SQLITE_KIND_REMOVAL_TIMESTAMPS.encode
693
694
  )
694
695
  ).onConflictDoUpdate({
695
696
  target: [t.graphId, t.kindName, t.entity, t.schemaVersion],
696
- set: chunkWFCECD6Q_cjs.buildKindRemovalOnConflictSet(t.removedAt, params.removedAt)
697
+ set: chunkCIINW6PS_cjs.buildKindRemovalOnConflictSet(t.removedAt, params.removedAt)
697
698
  });
698
699
  },
699
700
  async ensureReconciliationMarkersTable() {
700
701
  await db.run(
701
- drizzleOrm.sql.raw(chunkWFCECD6Q_cjs.generateSqliteCreateTableSQL(tables2.reconciliationMarkers))
702
+ drizzleOrm.sql.raw(chunkCIINW6PS_cjs.generateSqliteCreateTableSQL(tables2.reconciliationMarkers))
702
703
  );
703
704
  },
704
705
  async ensureRuntimeContributions(graphId) {
@@ -757,7 +758,7 @@ function createSqliteBackend(db, options = {}) {
757
758
  db.run(drizzleOrm.sql`BEGIN`);
758
759
  try {
759
760
  const result = await fn(
760
- chunkWFCECD6Q_cjs.gateFulltext(
761
+ chunkCIINW6PS_cjs.gateFulltext(
761
762
  txBackend,
762
763
  contributionMaterializer.assertInitialized
763
764
  ),
@@ -789,7 +790,7 @@ function createSqliteBackend(db, options = {}) {
789
790
  "Cross-store atomicity is unavailable on this SQLite backend: transactions are disabled (transactionMode: 'none'). Adopting an external transaction here would let the caller's relational write commit with no way to roll back the graph write. Configure a driver that supports transactions (better-sqlite3, libsql, bun:sqlite)."
790
791
  );
791
792
  }
792
- chunkWFCECD6Q_cjs.assertAdoptedDialect(
793
+ chunkCIINW6PS_cjs.assertAdoptedDialect(
793
794
  externalTx,
794
795
  sqliteCore.BaseSQLiteDatabase,
795
796
  "sqlite"
@@ -815,10 +816,10 @@ function createTransactionBackend(options) {
815
816
  tableNames: options.tableNames,
816
817
  fulltextStrategy: options.fulltextStrategy,
817
818
  vectorStrategy: options.vectorStrategy,
818
- ...options.vectorStrategy === void 0 ? {} : { vectorSlotLatch: chunkWFCECD6Q_cjs.createVectorSlotLatch() }
819
+ ...options.vectorStrategy === void 0 ? {} : { vectorSlotLatch: chunkCIINW6PS_cjs.createVectorSlotLatch() }
819
820
  });
820
821
  }
821
822
 
822
823
  exports.createSqliteBackend = createSqliteBackend;
823
- //# sourceMappingURL=chunk-4LBO6KIF.cjs.map
824
- //# sourceMappingURL=chunk-4LBO6KIF.cjs.map
824
+ //# sourceMappingURL=chunk-SFFJ2IKN.cjs.map
825
+ //# sourceMappingURL=chunk-SFFJ2IKN.cjs.map