@nicia-ai/typegraph 0.24.1 → 0.25.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 (159) hide show
  1. package/dist/backend/postgres/index.cjs +178 -55
  2. package/dist/backend/postgres/index.cjs.map +1 -1
  3. package/dist/backend/postgres/index.d.cts +6 -7
  4. package/dist/backend/postgres/index.d.ts +6 -7
  5. package/dist/backend/postgres/index.js +151 -28
  6. package/dist/backend/postgres/index.js.map +1 -1
  7. package/dist/backend/sqlite/index.cjs +19 -17
  8. package/dist/backend/sqlite/index.d.cts +6 -7
  9. package/dist/backend/sqlite/index.d.ts +6 -7
  10. package/dist/backend/sqlite/index.js +9 -7
  11. package/dist/backend/sqlite/libsql.cjs +12 -10
  12. package/dist/backend/sqlite/libsql.cjs.map +1 -1
  13. package/dist/backend/sqlite/libsql.d.cts +4 -5
  14. package/dist/backend/sqlite/libsql.d.ts +4 -5
  15. package/dist/backend/sqlite/libsql.js +9 -7
  16. package/dist/backend/sqlite/libsql.js.map +1 -1
  17. package/dist/backend/sqlite/local.cjs +14 -12
  18. package/dist/backend/sqlite/local.cjs.map +1 -1
  19. package/dist/backend/sqlite/local.d.cts +4 -5
  20. package/dist/backend/sqlite/local.d.ts +4 -5
  21. package/dist/backend/sqlite/local.js +9 -7
  22. package/dist/backend/sqlite/local.js.map +1 -1
  23. package/dist/chunk-4BOWVUGQ.js +2029 -0
  24. package/dist/chunk-4BOWVUGQ.js.map +1 -0
  25. package/dist/{chunk-SUHW2UYL.cjs → chunk-7CDXX3QZ.cjs} +2 -2
  26. package/dist/chunk-7CDXX3QZ.cjs.map +1 -0
  27. package/dist/chunk-7V335GHG.cjs +112 -0
  28. package/dist/chunk-7V335GHG.cjs.map +1 -0
  29. package/dist/chunk-7W3KAMVQ.cjs +2678 -0
  30. package/dist/chunk-7W3KAMVQ.cjs.map +1 -0
  31. package/dist/chunk-CTHNVU6K.cjs +551 -0
  32. package/dist/chunk-CTHNVU6K.cjs.map +1 -0
  33. package/dist/chunk-D2GO3RBL.cjs +12 -0
  34. package/dist/chunk-D2GO3RBL.cjs.map +1 -0
  35. package/dist/{chunk-WFMTAEEN.js → chunk-DOTEN2FG.js} +81 -7
  36. package/dist/chunk-DOTEN2FG.js.map +1 -0
  37. package/dist/chunk-E5JZSEGJ.cjs +301 -0
  38. package/dist/chunk-E5JZSEGJ.cjs.map +1 -0
  39. package/dist/chunk-EG6TJ3I5.js +286 -0
  40. package/dist/chunk-EG6TJ3I5.js.map +1 -0
  41. package/dist/chunk-EJCDOA37.js +537 -0
  42. package/dist/chunk-EJCDOA37.js.map +1 -0
  43. package/dist/{chunk-UVZHTBZ5.cjs → chunk-EK6RJ373.cjs} +7 -150
  44. package/dist/chunk-EK6RJ373.cjs.map +1 -0
  45. package/dist/{chunk-GUTQTMOV.js → chunk-FPCOUJSL.js} +2 -2
  46. package/dist/chunk-FPCOUJSL.js.map +1 -0
  47. package/dist/{chunk-3JK66E3I.cjs → chunk-JTI5WT4P.cjs} +630 -59
  48. package/dist/chunk-JTI5WT4P.cjs.map +1 -0
  49. package/dist/chunk-LVCSL6A3.js +2626 -0
  50. package/dist/chunk-LVCSL6A3.js.map +1 -0
  51. package/dist/chunk-NHQWXSTS.js +10 -0
  52. package/dist/chunk-NHQWXSTS.js.map +1 -0
  53. package/dist/chunk-NZ5PMBTG.js +105 -0
  54. package/dist/chunk-NZ5PMBTG.js.map +1 -0
  55. package/dist/{chunk-5HVDOPZU.cjs → chunk-O2P3KAUT.cjs} +416 -93
  56. package/dist/chunk-O2P3KAUT.cjs.map +1 -0
  57. package/dist/{chunk-QOLTW7OZ.js → chunk-OJ6IQVZG.js} +151 -13
  58. package/dist/chunk-OJ6IQVZG.js.map +1 -0
  59. package/dist/{chunk-EYELZHKY.js → chunk-OOS2RKRH.js} +5 -140
  60. package/dist/chunk-OOS2RKRH.js.map +1 -0
  61. package/dist/chunk-RCAJZG67.cjs +2069 -0
  62. package/dist/chunk-RCAJZG67.cjs.map +1 -0
  63. package/dist/{chunk-O5PST6TB.cjs → chunk-W5MTHMTE.cjs} +83 -6
  64. package/dist/chunk-W5MTHMTE.cjs.map +1 -0
  65. package/dist/{chunk-EY4LBX3F.js → chunk-WI5VRP3X.js} +337 -26
  66. package/dist/chunk-WI5VRP3X.js.map +1 -0
  67. package/dist/chunk-WVQXAFP3.js +79 -0
  68. package/dist/chunk-WVQXAFP3.js.map +1 -0
  69. package/dist/chunk-X3244EKP.cjs +84 -0
  70. package/dist/chunk-X3244EKP.cjs.map +1 -0
  71. package/dist/{chunk-753F33CV.js → chunk-YZZBDCLV.js} +617 -44
  72. package/dist/chunk-YZZBDCLV.js.map +1 -0
  73. package/dist/{chunk-OVJ2BE5Q.cjs → chunk-ZEMNF3QK.cjs} +171 -33
  74. package/dist/chunk-ZEMNF3QK.cjs.map +1 -0
  75. package/dist/{ddl-B_H8JM-E.d.cts → ddl-B2jjLjpR.d.cts} +762 -99
  76. package/dist/{ddl-1tFIvt9V.d.ts → ddl-DpaeAKPp.d.ts} +762 -99
  77. package/dist/extension-types-D07e_NTw.d.cts +543 -0
  78. package/dist/extension-types-D07e_NTw.d.ts +543 -0
  79. package/dist/graph-extension/index.cjs +71 -0
  80. package/dist/graph-extension/index.cjs.map +1 -0
  81. package/dist/graph-extension/index.d.cts +278 -0
  82. package/dist/graph-extension/index.d.ts +278 -0
  83. package/dist/graph-extension/index.js +6 -0
  84. package/dist/graph-extension/index.js.map +1 -0
  85. package/dist/{index-DXkEXpNz.d.ts → index-CT6nvtxL.d.cts} +114 -5
  86. package/dist/{index-DXkEXpNz.d.cts → index-DQheiVQV.d.ts} +114 -5
  87. package/dist/index.cjs +2672 -901
  88. package/dist/index.cjs.map +1 -1
  89. package/dist/index.d.cts +29 -10
  90. package/dist/index.d.ts +29 -10
  91. package/dist/index.js +2248 -598
  92. package/dist/index.js.map +1 -1
  93. package/dist/indexes/index.cjs +25 -23
  94. package/dist/indexes/index.d.cts +40 -22
  95. package/dist/indexes/index.d.ts +40 -22
  96. package/dist/indexes/index.js +5 -3
  97. package/dist/interchange/index.cjs +8 -7
  98. package/dist/interchange/index.cjs.map +1 -1
  99. package/dist/interchange/index.d.cts +5 -4
  100. package/dist/interchange/index.d.ts +5 -4
  101. package/dist/interchange/index.js +3 -2
  102. package/dist/interchange/index.js.map +1 -1
  103. package/dist/{manager-nIhmttD-.d.ts → manager-BKaPQbns.d.ts} +189 -6
  104. package/dist/{manager-Vkz28eAC.d.cts → manager-BpjBW1JK.d.cts} +189 -6
  105. package/dist/materialize-indexes-BB9N5uQl.d.cts +68 -0
  106. package/dist/materialize-indexes-BYpU2RKh.d.ts +68 -0
  107. package/dist/profiler/index.cjs +10 -8
  108. package/dist/profiler/index.cjs.map +1 -1
  109. package/dist/profiler/index.d.cts +8 -7
  110. package/dist/profiler/index.d.ts +8 -7
  111. package/dist/profiler/index.js +3 -1
  112. package/dist/profiler/index.js.map +1 -1
  113. package/dist/schema/index.cjs +43 -22
  114. package/dist/schema/index.cjs.map +1 -1
  115. package/dist/schema/index.d.cts +17 -8
  116. package/dist/schema/index.d.ts +17 -8
  117. package/dist/schema/index.js +9 -4
  118. package/dist/schema/index.js.map +1 -1
  119. package/dist/{sqlite-D0aceIe0.d.cts → sqlite-CU3j6rc7.d.ts} +837 -120
  120. package/dist/{sqlite-SUxbZqfy.d.ts → sqlite-Myo8e3Lr.d.cts} +837 -120
  121. package/dist/{store-U3i2tUch.d.ts → store-BAGuOHDh.d.cts} +659 -23
  122. package/dist/{store-CpvwTMxV.d.cts → store-De98Lod4.d.ts} +659 -23
  123. package/dist/types--0EslBx5.d.cts +2123 -0
  124. package/dist/{types-qYFZ9SqD.d.ts → types-BLmJq4wI.d.ts} +3 -2
  125. package/dist/types-BNWYZ-0-.d.ts +2123 -0
  126. package/dist/{types-yH4_p0XB.d.cts → types-CYga3lZp.d.cts} +3 -2
  127. package/dist/where-CluR73rs.d.ts +11 -0
  128. package/dist/where-m1uWsdua.d.cts +11 -0
  129. package/package.json +33 -73
  130. package/dist/ast-C8S37w1A.d.ts +0 -497
  131. package/dist/ast-dgLhLOg0.d.cts +0 -497
  132. package/dist/chunk-3JK66E3I.cjs.map +0 -1
  133. package/dist/chunk-3PPEHLGK.js +0 -1116
  134. package/dist/chunk-3PPEHLGK.js.map +0 -1
  135. package/dist/chunk-5HVDOPZU.cjs.map +0 -1
  136. package/dist/chunk-753F33CV.js.map +0 -1
  137. package/dist/chunk-EY4LBX3F.js.map +0 -1
  138. package/dist/chunk-EYELZHKY.js.map +0 -1
  139. package/dist/chunk-GFGVREHH.js +0 -1381
  140. package/dist/chunk-GFGVREHH.js.map +0 -1
  141. package/dist/chunk-GUTQTMOV.js.map +0 -1
  142. package/dist/chunk-LBORRUNJ.js +0 -135
  143. package/dist/chunk-LBORRUNJ.js.map +0 -1
  144. package/dist/chunk-O5PST6TB.cjs.map +0 -1
  145. package/dist/chunk-OLROXS2S.cjs +0 -147
  146. package/dist/chunk-OLROXS2S.cjs.map +0 -1
  147. package/dist/chunk-OVJ2BE5Q.cjs.map +0 -1
  148. package/dist/chunk-PAUN562Y.cjs +0 -1417
  149. package/dist/chunk-PAUN562Y.cjs.map +0 -1
  150. package/dist/chunk-PEE4EWXZ.cjs +0 -1131
  151. package/dist/chunk-PEE4EWXZ.cjs.map +0 -1
  152. package/dist/chunk-QOLTW7OZ.js.map +0 -1
  153. package/dist/chunk-SUHW2UYL.cjs.map +0 -1
  154. package/dist/chunk-UVZHTBZ5.cjs.map +0 -1
  155. package/dist/chunk-WFMTAEEN.js.map +0 -1
  156. package/dist/types-C-zfYDJB.d.ts +0 -159
  157. package/dist/types-CQx4iW5Y.d.cts +0 -159
  158. package/dist/types-Qk2l3IkQ.d.cts +0 -1254
  159. package/dist/types-Qk2l3IkQ.d.ts +0 -1254
@@ -0,0 +1,2123 @@
1
+ import { z } from 'zod';
2
+ import { N as NodeType, d as EdgeType, U as UniquenessScope, C as Collation, D as DeleteBehavior, e as KindAnnotations, f as Cardinality, g as EndpointExistence, T as TemporalMode, G as GraphExtension, I as IndexEntity, K as KindEntity, a as NullCheckOp, A as AnyEdgeType } from './extension-types-D07e_NTw.cjs';
3
+ import { SQL } from 'drizzle-orm';
4
+
5
+ /** Brand key for MetaEdge */
6
+ declare const META_EDGE_BRAND: "__metaEdge";
7
+ /**
8
+ * How a meta-edge affects queries and validation.
9
+ */
10
+ type InferenceType = "subsumption" | "hierarchy" | "substitution" | "constraint" | "composition" | "association" | "none";
11
+ /**
12
+ * Properties of a meta-edge.
13
+ */
14
+ type MetaEdgeProperties = Readonly<{
15
+ transitive: boolean;
16
+ symmetric: boolean;
17
+ reflexive: boolean;
18
+ inverse: string | undefined;
19
+ inference: InferenceType;
20
+ description: string | undefined;
21
+ }>;
22
+ /**
23
+ * A meta-edge definition.
24
+ *
25
+ * Meta-edges represent type-level relationships (between kinds),
26
+ * not instance-level relationships (between nodes).
27
+ */
28
+ type MetaEdge<K extends string = string> = Readonly<{
29
+ [META_EDGE_BRAND]: true;
30
+ name: K;
31
+ properties: MetaEdgeProperties;
32
+ }>;
33
+ /**
34
+ * A relation in the ontology (instance of meta-edge between types).
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // Podcast subClassOf Media
39
+ * subClassOf(Podcast, Media)
40
+ *
41
+ * // Person equivalentTo schema:Person
42
+ * equivalentTo(Person, "https://schema.org/Person")
43
+ * ```
44
+ */
45
+ type OntologyRelation = Readonly<{
46
+ metaEdge: MetaEdge;
47
+ from: NodeType | EdgeType | string;
48
+ to: NodeType | EdgeType | string;
49
+ }>;
50
+ /**
51
+ * Checks if a value is a MetaEdge.
52
+ */
53
+ declare function isMetaEdge(value: unknown): value is MetaEdge;
54
+
55
+ declare const MAX_JSON_POINTER_DEPTH: 5;
56
+ type JsonPointer = string & {
57
+ readonly __jsonPointer: unique symbol;
58
+ };
59
+ type JsonPointerSegment = string | number;
60
+ type JsonPointerSegments = readonly JsonPointerSegment[];
61
+ type Depth = 0 | 1 | 2 | 3 | 4 | 5;
62
+ interface DepthDecrementMap {
63
+ 0: 0;
64
+ 1: 0;
65
+ 2: 1;
66
+ 3: 2;
67
+ 4: 3;
68
+ 5: 4;
69
+ }
70
+ type Decrement<Current extends Depth> = DepthDecrementMap[Current];
71
+ type NonNegativeIntegerString = Exclude<`${bigint}`, `-${string}`>;
72
+ type ObjectPointerKey<T> = Exclude<Extract<keyof T, string>, NonNegativeIntegerString>;
73
+ type EncodeTilde<S extends string> = S extends `${infer Head}~${infer Tail}` ? `${EncodeTilde<Head>}~0${EncodeTilde<Tail>}` : S;
74
+ type EncodeSlash<S extends string> = S extends `${infer Head}/${infer Tail}` ? `${EncodeSlash<Head>}~1${EncodeSlash<Tail>}` : S;
75
+ type EncodePointerSegment<S extends string> = EncodeSlash<EncodeTilde<S>>;
76
+ type DecodePointerSegment<S extends string> = S extends `${infer Head}~1${infer Tail}` ? `${DecodePointerSegment<Head>}/${DecodePointerSegment<Tail>}` : S extends `${infer Head}~0${infer Tail}` ? `${DecodePointerSegment<Head>}~${DecodePointerSegment<Tail>}` : S;
77
+ type PointerForArray<T, Current extends Depth> = `/${NonNegativeIntegerString}` | (Current extends 1 ? never : `/${NonNegativeIntegerString}${JsonPointerFor<T, Decrement<Current>>}`);
78
+ type PointerForObject<T, Current extends Depth> = {
79
+ [K in ObjectPointerKey<T>]: `/${EncodePointerSegment<K>}` | (Current extends 1 ? never : `/${EncodePointerSegment<K>}${JsonPointerFor<T[K], Decrement<Current>>}`);
80
+ }[ObjectPointerKey<T>];
81
+ type JsonPointerFor<T, Current extends Depth = 5> = "" | (Current extends 0 ? "" : T extends readonly (infer U)[] ? PointerForArray<U, Current> : never) | (Current extends 0 ? "" : T extends Record<string, unknown> ? PointerForObject<T, Current> : never);
82
+ type PointerSegmentsForArray<T, Current extends Depth> = readonly [number] | (Current extends 1 ? readonly [number] : readonly [number, ...JsonPointerSegmentsFor<T, Decrement<Current>>]);
83
+ type PointerSegmentsForObject<T, Current extends Depth> = {
84
+ [K in ObjectPointerKey<T>]: readonly [K] | (Current extends 1 ? readonly [K] : readonly [K, ...JsonPointerSegmentsFor<T[K], Decrement<Current>>]);
85
+ }[ObjectPointerKey<T>];
86
+ type JsonPointerSegmentsFor<T, Current extends Depth = 5> = readonly [] | (Current extends 0 ? readonly [] : T extends readonly (infer U)[] ? PointerSegmentsForArray<U, Current> : never) | (Current extends 0 ? readonly [] : T extends Record<string, unknown> ? PointerSegmentsForObject<T, Current> : never);
87
+ type JsonPointerInput<T> = JsonPointerFor<T> | JsonPointerSegmentsFor<T> | JsonPointer;
88
+ type ResolveJsonPointer<T, Pointer extends string> = Pointer extends "" ? T : Pointer extends `/${infer Head}/${infer Tail}` ? ResolveJsonPointer<ResolvePointerSegment<T, DecodePointerSegment<Head>>, `/${Tail}`> : Pointer extends `/${infer Head}` ? ResolvePointerSegment<T, DecodePointerSegment<Head>> : unknown;
89
+ type ResolvePointerSegment<T, Segment extends string> = T extends readonly (infer U)[] ? Segment extends NonNegativeIntegerString ? U : unknown : T extends Record<string, unknown> ? Segment extends keyof T ? Segment extends NonNegativeIntegerString ? unknown : T[Segment] : unknown : unknown;
90
+ type ResolveJsonPointerSegments<T, Segments extends readonly JsonPointerSegment[]> = Segments extends readonly [] ? T : Segments extends readonly [infer Head, ...infer Tail] ? ResolveJsonPointerSegments<ResolvePointerSegment<T, SegmentToString<Head>>, Extract<Tail, readonly JsonPointerSegment[]>> : unknown;
91
+ type SegmentToString<Segment> = Segment extends number ? `${Segment}` : Segment extends string ? Segment : string;
92
+ declare function jsonPointer(segments: JsonPointerSegments): JsonPointer;
93
+ declare function normalizeJsonPointer<T>(input: JsonPointerInput<T>): JsonPointer;
94
+ declare function parseJsonPointer(pointer: JsonPointer): readonly string[];
95
+ declare function joinJsonPointers(base: JsonPointer | undefined, relative: JsonPointer): JsonPointer;
96
+
97
+ /**
98
+ * SQL Schema Configuration for Query Compilation
99
+ *
100
+ * Provides table and column identifiers that the query compiler uses.
101
+ * This allows the compiler to work with custom table names instead of
102
+ * hard-coded defaults.
103
+ */
104
+
105
+ /**
106
+ * Table names for TypeGraph SQL schema.
107
+ *
108
+ * Carries every customizable physical-table name the backend exposes,
109
+ * including the secondary tables (`uniques`) that the query compiler
110
+ * itself doesn't reference but `materializeRemovals` and other
111
+ * cleanup paths need to address by name. Backends without a
112
+ * `uniques` table (custom embeddings-only stores) leave it as the
113
+ * default — the cleanup path is a no-op for kinds with no unique
114
+ * rows.
115
+ */
116
+ type SqlTableNames = Readonly<{
117
+ /** Nodes table name (default: "typegraph_nodes") */
118
+ nodes: string;
119
+ /** Edges table name (default: "typegraph_edges") */
120
+ edges: string;
121
+ /** Node embeddings table name (default: "typegraph_node_embeddings") */
122
+ embeddings: string;
123
+ /** Node fulltext table name (default: "typegraph_node_fulltext") */
124
+ fulltext: string;
125
+ /** Node uniques table name (default: "typegraph_node_uniques") */
126
+ uniques: string;
127
+ }>;
128
+ /**
129
+ * SQL schema configuration for query compilation.
130
+ * Contains table identifiers and utility methods for generating SQL references.
131
+ */
132
+ type SqlSchema = Readonly<{
133
+ /** Table names */
134
+ tables: SqlTableNames;
135
+ /** Get a SQL reference to the nodes table */
136
+ nodesTable: SQL;
137
+ /** Get a SQL reference to the edges table */
138
+ edgesTable: SQL;
139
+ /** Get a SQL reference to the embeddings table */
140
+ embeddingsTable: SQL;
141
+ /** Get a SQL reference to the fulltext table */
142
+ fulltextTable: SQL;
143
+ }>;
144
+ /**
145
+ * Creates a SqlSchema configuration from table names.
146
+ *
147
+ * Table names are validated to ensure they are valid SQL identifiers.
148
+ * This prevents SQL injection and ensures compatibility across databases.
149
+ *
150
+ * @param names - Optional custom table names (defaults to standard names)
151
+ * @returns SqlSchema configuration for query compilation
152
+ * @throws Error if any table name is invalid
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * // Use default table names
157
+ * const schema = createSqlSchema();
158
+ *
159
+ * // Use custom table names
160
+ * const schema = createSqlSchema({
161
+ * nodes: "myapp_nodes",
162
+ * edges: "myapp_edges",
163
+ * embeddings: "myapp_embeddings",
164
+ * });
165
+ * ```
166
+ */
167
+ declare function createSqlSchema(names?: Partial<SqlTableNames>): SqlSchema;
168
+ /**
169
+ * Default SqlSchema using standard TypeGraph table names.
170
+ */
171
+ declare const DEFAULT_SQL_SCHEMA: SqlSchema;
172
+
173
+ /**
174
+ * Fulltext Strategy — pluggable DDL + SQL generation for a dialect's
175
+ * fulltext stack. A strategy owns every SQL statement that touches its
176
+ * backing table: DDL, upsert (single + batch), delete (single + batch),
177
+ * MATCH condition, rank expression, and snippet expression.
178
+ *
179
+ * A dialect picks one as its default; `createPostgresBackend` /
180
+ * `createSqliteBackend` accept an override for alternate Postgres stacks
181
+ * (pg_trgm, ParadeDB/pg_search, pgroonga) to swap the entire fulltext
182
+ * pipeline without forking TypeGraph.
183
+ */
184
+
185
+ /**
186
+ * A pluggable fulltext implementation. Each strategy is expected to be
187
+ * self-contained: given a table name, a query string, and a parse mode,
188
+ * it emits every SQL statement the compiler and backend need — DDL,
189
+ * reads, and writes. No out-of-band conventions across layers.
190
+ */
191
+ interface FulltextStrategy {
192
+ /** Human-readable identifier used in error messages and telemetry. */
193
+ readonly name: string;
194
+ /**
195
+ * Parse modes this strategy can translate. Callers validate against
196
+ * this list before emitting SQL; a mode outside the set means the
197
+ * strategy rejects the query at compile time.
198
+ */
199
+ readonly supportedModes: readonly FulltextQueryMode[];
200
+ /**
201
+ * Whether the strategy can emit a per-row highlighted snippet. When
202
+ * false, `snippetExpression` returns a literal `NULL` so callers can
203
+ * leave the `snippet` column in place without a branch.
204
+ */
205
+ readonly supportsSnippets: boolean;
206
+ /**
207
+ * Whether the strategy supports prefix queries (`foo*`). Used to
208
+ * populate `BackendCapabilities.fulltext.prefixQueries`. A strategy
209
+ * may support prefix queries via dedicated syntax without advertising
210
+ * "raw" mode (and vice-versa).
211
+ */
212
+ readonly supportsPrefix: boolean;
213
+ /**
214
+ * Whether a per-query `language` override is honored. Postgres' tsvector
215
+ * accepts any installed regconfig at query time; SQLite FTS5's tokenizer
216
+ * is fixed at table-create time, so the override is silently ignored.
217
+ * Callers may surface a warning when the user passes `language` to a
218
+ * strategy that doesn't honor it.
219
+ */
220
+ readonly supportsLanguageOverride: boolean;
221
+ /**
222
+ * Languages / tokenizer names understood by the strategy. Advisory — a
223
+ * runtime backend like Postgres may accept other installed regconfigs.
224
+ * Used to populate `BackendCapabilities.fulltext.languages`.
225
+ */
226
+ readonly languages: readonly string[];
227
+ /**
228
+ * Emits the WHERE-side MATCH expression.
229
+ *
230
+ * @example
231
+ * tsvector: `"typegraph_node_fulltext"."tsv" @@ websearch_to_tsquery('english', 'cats')`
232
+ * fts5: `"typegraph_node_fulltext" MATCH '"cats"'`
233
+ */
234
+ matchCondition(tableName: string, query: string, mode: FulltextQueryMode, language?: string): SQL;
235
+ /**
236
+ * Emits the relevance expression. Higher values = more relevant. The
237
+ * compiler orders by this expression DESC, and both builder and
238
+ * backend-direct paths use the same form so their top-k results agree.
239
+ */
240
+ rankExpression(tableName: string, query: string, mode: FulltextQueryMode, language?: string): SQL;
241
+ /**
242
+ * Emits a per-row highlighted snippet expression, or `NULL` when
243
+ * `supportsSnippets` is false. Snippet markup is `<mark>…</mark>` in
244
+ * both shipped strategies so consumers can apply one stylesheet.
245
+ */
246
+ snippetExpression(tableName: string, query: string, mode: FulltextQueryMode, language?: string): SQL;
247
+ /**
248
+ * DDL statements to create the backing table and any supporting
249
+ * indexes. Idempotent (`CREATE ... IF NOT EXISTS`). Called once from
250
+ * `bootstrapTables()` on a fresh database.
251
+ */
252
+ generateDdl(tableName: string): readonly string[];
253
+ /**
254
+ * Emits the statements that upsert a single fulltext row. Returns one
255
+ * or more statements — some backends (SQLite FTS5) cannot emulate
256
+ * upsert in a single statement and need DELETE + INSERT.
257
+ */
258
+ buildUpsert(tableName: string, params: UpsertFulltextParams, timestamp: string): readonly SQL[];
259
+ /**
260
+ * Emits the statements that upsert many fulltext rows at once. Input
261
+ * rows are expected to be de-duplicated last-write-wins by the
262
+ * strategy if the underlying SQL statement cannot tolerate duplicate
263
+ * conflict keys. Returns `[]` when `params.rows` is empty.
264
+ */
265
+ buildBatchUpsert(tableName: string, params: UpsertFulltextBatchParams, timestamp: string): readonly SQL[];
266
+ /**
267
+ * Emits the statements that delete a single fulltext row. Normally a
268
+ * single PK-scoped DELETE, but strategies that maintain auxiliary
269
+ * indexes (delete-triggered external stores, ParadeDB-style secondary
270
+ * structures) may need more.
271
+ */
272
+ buildDelete(tableName: string, params: DeleteFulltextParams): readonly SQL[];
273
+ /**
274
+ * Emits the statements that delete many fulltext rows at once. Returns
275
+ * `[]` when `params.nodeIds` is empty.
276
+ */
277
+ buildBatchDelete(tableName: string, params: DeleteFulltextBatchParams): readonly SQL[];
278
+ }
279
+ declare const tsvectorStrategy: FulltextStrategy;
280
+ declare const fts5Strategy: FulltextStrategy;
281
+
282
+ /**
283
+ * JSON Schema type (subset used by Zod toJSONSchema).
284
+ *
285
+ * This is a simplified version - the actual JSON Schema has many more properties.
286
+ */
287
+ type JsonSchema = Readonly<{
288
+ $schema?: string;
289
+ type?: string | readonly string[];
290
+ properties?: Record<string, JsonSchema>;
291
+ required?: readonly string[];
292
+ items?: JsonSchema;
293
+ additionalProperties?: boolean | JsonSchema;
294
+ enum?: readonly unknown[];
295
+ const?: unknown;
296
+ anyOf?: readonly JsonSchema[];
297
+ oneOf?: readonly JsonSchema[];
298
+ allOf?: readonly JsonSchema[];
299
+ not?: JsonSchema;
300
+ description?: string;
301
+ default?: unknown;
302
+ minimum?: number;
303
+ maximum?: number;
304
+ minLength?: number;
305
+ maxLength?: number;
306
+ pattern?: string;
307
+ format?: string;
308
+ [key: string]: unknown;
309
+ }>;
310
+ /**
311
+ * Serialized representation of a meta-edge.
312
+ */
313
+ type SerializedMetaEdge = Readonly<{
314
+ name: string;
315
+ transitive: boolean;
316
+ symmetric: boolean;
317
+ reflexive: boolean;
318
+ inverse: string | undefined;
319
+ inference: InferenceType;
320
+ description: string | undefined;
321
+ }>;
322
+ /**
323
+ * Serialized representation of an ontology relation.
324
+ */
325
+ type SerializedOntologyRelation = Readonly<{
326
+ metaEdge: string;
327
+ from: string;
328
+ to: string;
329
+ }>;
330
+ /**
331
+ * Precomputed closures stored in the schema for fast runtime lookup.
332
+ */
333
+ type SerializedClosures = Readonly<{
334
+ subClassAncestors: Record<string, readonly string[]>;
335
+ subClassDescendants: Record<string, readonly string[]>;
336
+ broaderClosure: Record<string, readonly string[]>;
337
+ narrowerClosure: Record<string, readonly string[]>;
338
+ equivalenceSets: Record<string, readonly string[]>;
339
+ disjointPairs: readonly string[];
340
+ partOfClosure: Record<string, readonly string[]>;
341
+ hasPartClosure: Record<string, readonly string[]>;
342
+ iriToKind: Record<string, string>;
343
+ edgeInverses: Record<string, string>;
344
+ edgeImplicationsClosure: Record<string, readonly string[]>;
345
+ edgeImplyingClosure: Record<string, readonly string[]>;
346
+ }>;
347
+ /**
348
+ * Complete serialized ontology section.
349
+ */
350
+ type SerializedOntology = Readonly<{
351
+ metaEdges: Record<string, SerializedMetaEdge>;
352
+ relations: readonly SerializedOntologyRelation[];
353
+ closures: SerializedClosures;
354
+ }>;
355
+ /**
356
+ * Serialized representation of a uniqueness constraint.
357
+ */
358
+ type SerializedUniqueConstraint = Readonly<{
359
+ name: string;
360
+ fields: readonly string[];
361
+ where: string | undefined;
362
+ scope: UniquenessScope;
363
+ collation: Collation;
364
+ }>;
365
+ /**
366
+ * Serialized representation of a node kind.
367
+ */
368
+ type SerializedNodeDef = Readonly<{
369
+ kind: string;
370
+ properties: JsonSchema;
371
+ uniqueConstraints: readonly SerializedUniqueConstraint[];
372
+ onDelete: DeleteBehavior;
373
+ description: string | undefined;
374
+ annotations?: KindAnnotations;
375
+ }>;
376
+ /**
377
+ * Serialized representation of an edge kind.
378
+ */
379
+ type SerializedEdgeDef = Readonly<{
380
+ kind: string;
381
+ fromKinds: readonly string[];
382
+ toKinds: readonly string[];
383
+ properties: JsonSchema;
384
+ cardinality: Cardinality;
385
+ endpointExistence: EndpointExistence;
386
+ description: string | undefined;
387
+ annotations?: KindAnnotations;
388
+ }>;
389
+ /**
390
+ * Complete serialized schema document.
391
+ *
392
+ * This is the format stored in the schema_doc column of
393
+ * typegraph_schema_versions. The type is kept explicit rather than
394
+ * inferred from the Zod schema so that downstream code sees the
395
+ * precise literal union types (DeleteBehavior, TemporalMode, etc.)
396
+ * instead of the broader `string` type that Zod's passthrough schema uses.
397
+ */
398
+ type SerializedSchema = Readonly<{
399
+ graphId: string;
400
+ version: number;
401
+ generatedAt: string;
402
+ nodes: Record<string, SerializedNodeDef>;
403
+ edges: Record<string, SerializedEdgeDef>;
404
+ ontology: SerializedOntology;
405
+ defaults: Readonly<{
406
+ onNodeDelete: DeleteBehavior;
407
+ temporalMode: TemporalMode;
408
+ }>;
409
+ /**
410
+ * Index declarations attached to the graph.
411
+ *
412
+ * Omitted entirely when the graph never declared the slice — legacy
413
+ * schemas hash byte-identically to before `indexes` existed. Each
414
+ * entry carries an `origin` discriminator: `"compile-time"` is the
415
+ * default and is omitted from the canonical form (see `serializer.ts`);
416
+ * only `"runtime"` is emitted explicitly.
417
+ */
418
+ indexes?: readonly IndexDeclaration[];
419
+ /**
420
+ * Graph extension, when this schema was produced from a graph that
421
+ * had been merged with one. The loader uses this value (and only
422
+ * this value) to rebuild extension-kind Zod validators on restart —
423
+ * the merged `nodes` / `edges` / `ontology` maps above carry the
424
+ * JSON-Schema-shaped views for diff machinery and human-readable
425
+ * reporting, but they cannot reconstruct Zod alone.
426
+ *
427
+ * Omitted entirely on graphs that have never been extended — legacy
428
+ * schemas hash byte-identically.
429
+ */
430
+ extension?: GraphExtension;
431
+ /**
432
+ * Soft-deprecated node and edge kind names. Set by
433
+ * `store.deprecateKinds(...)`; cleared by `store.undeprecateKinds(...)`.
434
+ * Surfaces in introspection but does not affect reads, writes, or
435
+ * queries. Omitted entirely when empty so legacy schemas hash
436
+ * byte-identically.
437
+ */
438
+ deprecatedKinds?: readonly string[];
439
+ }>;
440
+ /**
441
+ * A schema hash for detecting changes.
442
+ *
443
+ * We hash the schema content (excluding version and generatedAt)
444
+ * to detect if the schema has actually changed.
445
+ */
446
+ type SchemaHash = string;
447
+
448
+ /**
449
+ * SQL Dialect Abstraction Layer
450
+ *
451
+ * Provides a unified interface for dialect-specific SQL generation.
452
+ * Implementing a new dialect (MySQL, SQL Server, etc.) requires
453
+ * implementing this interface.
454
+ */
455
+
456
+ /**
457
+ * Supported SQL dialects.
458
+ */
459
+ type SqlDialect = "sqlite" | "postgres";
460
+
461
+ /**
462
+ * Backend interface types for TypeGraph storage.
463
+ *
464
+ * The backend abstracts database operations, allowing different
465
+ * SQL implementations (SQLite, PostgreSQL) behind a common interface.
466
+ */
467
+
468
+ /**
469
+ * Supported vector similarity metrics.
470
+ */
471
+ type VectorMetric = "cosine" | "l2" | "inner_product";
472
+ /**
473
+ * Supported vector index types.
474
+ */
475
+ type VectorIndexType = "hnsw" | "ivfflat" | "none";
476
+ /**
477
+ * Vector search capabilities.
478
+ */
479
+ type VectorCapabilities = Readonly<{
480
+ /** Whether the backend supports vector operations */
481
+ supported: boolean;
482
+ /** Supported similarity metrics */
483
+ metrics: readonly VectorMetric[];
484
+ /** Supported index types */
485
+ indexTypes: readonly VectorIndexType[];
486
+ /** Maximum dimensions supported */
487
+ maxDimensions: number;
488
+ }>;
489
+ /**
490
+ * Query modes for fulltext search.
491
+ *
492
+ * - "websearch": Google-style syntax (quoted phrases, +required, -excluded).
493
+ * Postgres: `websearch_to_tsquery`. SQLite: translated to FTS5 MATCH.
494
+ * - "phrase": treats the whole query as a phrase.
495
+ * Postgres: `phraseto_tsquery`. SQLite: FTS5 `"..."` phrase.
496
+ * - "plain": splits on whitespace and ANDs terms.
497
+ * Postgres: `plainto_tsquery`. SQLite: default FTS5 AND.
498
+ * - "raw": dialect-native syntax passed through unchanged.
499
+ */
500
+ type FulltextQueryMode = "websearch" | "phrase" | "plain" | "raw";
501
+ /**
502
+ * Fulltext search capabilities declared by a backend.
503
+ */
504
+ type FulltextCapabilities = Readonly<{
505
+ /** Whether the backend supports fulltext operations */
506
+ supported: boolean;
507
+ /**
508
+ * Language / tokenizer names understood by this backend.
509
+ * Postgres: installed regconfigs (english, simple, ...).
510
+ * SQLite FTS5: tokenizer names (unicode61, porter, trigram).
511
+ */
512
+ languages: readonly string[];
513
+ /** Whether phrase queries are supported. */
514
+ phraseQueries: boolean;
515
+ /** Whether prefix (`foo*`) queries are supported. */
516
+ prefixQueries: boolean;
517
+ /** Whether highlighting / snippets are supported. */
518
+ highlighting: boolean;
519
+ }>;
520
+
521
+ /**
522
+ * Backend capabilities that vary by dialect.
523
+ */
524
+ type BackendCapabilities = Readonly<{
525
+ /** Whether the backend supports JSONB type (vs TEXT for JSON) */
526
+ jsonb: boolean;
527
+ /** Whether the backend supports partial indexes */
528
+ partialIndexes: boolean;
529
+ /** Whether the backend supports GIN indexes for JSON */
530
+ ginIndexes: boolean;
531
+ /** Whether the backend supports CTE (WITH) queries */
532
+ cte: boolean;
533
+ /** Whether the backend supports RETURNING clause */
534
+ returning: boolean;
535
+ /** Whether the backend supports atomic transactions (D1 does not) */
536
+ transactions: boolean;
537
+ /** Vector search capabilities (undefined if not configured) */
538
+ vector?: VectorCapabilities | undefined;
539
+ /** Fulltext search capabilities (undefined if not configured) */
540
+ fulltext?: FulltextCapabilities | undefined;
541
+ }>;
542
+ /**
543
+ * A row from the typegraph_nodes table.
544
+ */
545
+ type NodeRow = Readonly<{
546
+ graph_id: string;
547
+ kind: string;
548
+ id: string;
549
+ props: string;
550
+ version: number;
551
+ valid_from: string | undefined;
552
+ valid_to: string | undefined;
553
+ created_at: string;
554
+ updated_at: string;
555
+ deleted_at: string | undefined;
556
+ }>;
557
+ /**
558
+ * A row from the typegraph_edges table.
559
+ */
560
+ type EdgeRow = Readonly<{
561
+ graph_id: string;
562
+ id: string;
563
+ kind: string;
564
+ from_kind: string;
565
+ from_id: string;
566
+ to_kind: string;
567
+ to_id: string;
568
+ props: string;
569
+ valid_from: string | undefined;
570
+ valid_to: string | undefined;
571
+ created_at: string;
572
+ updated_at: string;
573
+ deleted_at: string | undefined;
574
+ }>;
575
+ /**
576
+ * A row from the typegraph_node_uniques table.
577
+ */
578
+ type UniqueRow = Readonly<{
579
+ graph_id: string;
580
+ node_kind: string;
581
+ constraint_name: string;
582
+ key: string;
583
+ node_id: string;
584
+ concrete_kind: string;
585
+ deleted_at: string | undefined;
586
+ }>;
587
+ /**
588
+ * A row from the typegraph_schema_versions table.
589
+ */
590
+ type SchemaVersionRow = Readonly<{
591
+ graph_id: string;
592
+ version: number;
593
+ schema_hash: string;
594
+ schema_doc: string;
595
+ created_at: string;
596
+ is_active: boolean;
597
+ }>;
598
+ /**
599
+ * A row from the typegraph_node_embeddings table.
600
+ */
601
+ type EmbeddingRow = Readonly<{
602
+ graph_id: string;
603
+ node_kind: string;
604
+ node_id: string;
605
+ field_path: string;
606
+ embedding: readonly number[];
607
+ dimensions: number;
608
+ created_at: string;
609
+ updated_at: string;
610
+ }>;
611
+ /**
612
+ * Parameters for inserting a node.
613
+ */
614
+ type InsertNodeParams = Readonly<{
615
+ graphId: string;
616
+ kind: string;
617
+ id: string;
618
+ props: Readonly<Record<string, unknown>>;
619
+ validFrom?: string;
620
+ validTo?: string;
621
+ }>;
622
+ /**
623
+ * Parameters for updating a node.
624
+ */
625
+ type UpdateNodeParams = Readonly<{
626
+ graphId: string;
627
+ kind: string;
628
+ id: string;
629
+ props: Readonly<Record<string, unknown>>;
630
+ validTo?: string;
631
+ incrementVersion?: boolean;
632
+ /** If true, clears deleted_at (un-deletes the node). Used by upsert. */
633
+ clearDeleted?: boolean;
634
+ }>;
635
+ /**
636
+ * Parameters for deleting a node (soft delete).
637
+ */
638
+ type DeleteNodeParams = Readonly<{
639
+ graphId: string;
640
+ kind: string;
641
+ id: string;
642
+ }>;
643
+ /**
644
+ * Parameters for inserting an edge.
645
+ */
646
+ type InsertEdgeParams = Readonly<{
647
+ graphId: string;
648
+ id: string;
649
+ kind: string;
650
+ fromKind: string;
651
+ fromId: string;
652
+ toKind: string;
653
+ toId: string;
654
+ props: Readonly<Record<string, unknown>>;
655
+ validFrom?: string;
656
+ validTo?: string;
657
+ }>;
658
+ /**
659
+ * Parameters for updating an edge.
660
+ */
661
+ type UpdateEdgeParams = Readonly<{
662
+ graphId: string;
663
+ id: string;
664
+ props: Readonly<Record<string, unknown>>;
665
+ validTo?: string;
666
+ clearDeleted?: boolean;
667
+ }>;
668
+ /**
669
+ * Parameters for deleting an edge (soft delete).
670
+ */
671
+ type DeleteEdgeParams = Readonly<{
672
+ graphId: string;
673
+ id: string;
674
+ }>;
675
+ /**
676
+ * Parameters for hard deleting a node (permanent removal).
677
+ */
678
+ type HardDeleteNodeParams = Readonly<{
679
+ graphId: string;
680
+ kind: string;
681
+ id: string;
682
+ }>;
683
+ /**
684
+ * Parameters for hard deleting an edge (permanent removal).
685
+ */
686
+ type HardDeleteEdgeParams = Readonly<{
687
+ graphId: string;
688
+ id: string;
689
+ }>;
690
+ /**
691
+ * Parameters for inserting or updating an embedding.
692
+ */
693
+ type UpsertEmbeddingParams = Readonly<{
694
+ graphId: string;
695
+ nodeKind: string;
696
+ nodeId: string;
697
+ fieldPath: string;
698
+ embedding: readonly number[];
699
+ dimensions: number;
700
+ }>;
701
+ /**
702
+ * Parameters for deleting an embedding.
703
+ */
704
+ type DeleteEmbeddingParams = Readonly<{
705
+ graphId: string;
706
+ nodeKind: string;
707
+ nodeId: string;
708
+ fieldPath: string;
709
+ }>;
710
+ /**
711
+ * Parameters for vector similarity search.
712
+ */
713
+ type VectorSearchParams = Readonly<{
714
+ graphId: string;
715
+ nodeKind: string;
716
+ fieldPath: string;
717
+ queryEmbedding: readonly number[];
718
+ metric: VectorMetric;
719
+ limit: number;
720
+ minScore?: number;
721
+ }>;
722
+ /**
723
+ * Result from a vector similarity search.
724
+ */
725
+ type VectorSearchResult = Readonly<{
726
+ nodeId: string;
727
+ /**
728
+ * Cosine metric returns similarity score (higher is better).
729
+ * L2 and inner_product return raw distance (lower is better).
730
+ */
731
+ score: number;
732
+ }>;
733
+ /**
734
+ * Parameters for creating a vector index.
735
+ */
736
+ type CreateVectorIndexParams = Readonly<{
737
+ graphId: string;
738
+ nodeKind: string;
739
+ fieldPath: string;
740
+ dimensions: number;
741
+ metric: VectorMetric;
742
+ indexType: VectorIndexType;
743
+ /** Index-specific parameters */
744
+ indexParams?: Readonly<{
745
+ /** HNSW: max connections per layer */
746
+ m?: number;
747
+ /** HNSW: construction search depth */
748
+ efConstruction?: number;
749
+ /** IVFFlat: number of lists */
750
+ lists?: number;
751
+ }>;
752
+ /**
753
+ * Build the index without taking an `AccessExclusiveLock` on live
754
+ * tables (Postgres `CREATE INDEX CONCURRENTLY`). Mirrors the
755
+ * `concurrent` flag the relational DDL path uses inside
756
+ * `materializeIndexes()`. Cannot be set inside a transaction —
757
+ * callers (`materializeIndexes()`) run at top level. Backends that
758
+ * don't have a CONCURRENTLY equivalent (SQLite) ignore this flag.
759
+ */
760
+ concurrent?: boolean;
761
+ }>;
762
+ /**
763
+ * Parameters for dropping a vector index.
764
+ */
765
+ type DropVectorIndexParams = Readonly<{
766
+ graphId: string;
767
+ nodeKind: string;
768
+ fieldPath: string;
769
+ }>;
770
+ /**
771
+ * Parameters for inserting or updating a fulltext entry.
772
+ *
773
+ * One row per node. Callers concatenate the searchable fields into
774
+ * `content` so a single MATCH query can find terms spread across fields.
775
+ *
776
+ * Note: `createFulltextIndex` / `dropFulltextIndex` were removed as
777
+ * dead code in #PR_E. The fulltext table's canonical index (Postgres
778
+ * GIN on `tsv`, SQLite FTS5 virtual table) is created with the table
779
+ * itself by `bootstrapTables` per the active `FulltextStrategy`;
780
+ * per-kind fulltext indexes are an "advanced strategy" surface that
781
+ * doesn't fit the relational-style declaration model and is reserved
782
+ * for future work.
783
+ */
784
+ type UpsertFulltextParams = Readonly<{
785
+ graphId: string;
786
+ nodeKind: string;
787
+ nodeId: string;
788
+ content: string;
789
+ language: string;
790
+ }>;
791
+ /**
792
+ * Parameters for deleting a single fulltext entry.
793
+ */
794
+ type DeleteFulltextParams = Readonly<{
795
+ graphId: string;
796
+ nodeKind: string;
797
+ nodeId: string;
798
+ }>;
799
+ /**
800
+ * A single row in a fulltext batch upsert.
801
+ */
802
+ type FulltextBatchRow = Readonly<{
803
+ nodeId: string;
804
+ content: string;
805
+ language: string;
806
+ }>;
807
+ /**
808
+ * Parameters for a batched fulltext upsert.
809
+ *
810
+ * Homogeneous: one graph, one node kind, many nodes. Duplicate `nodeId`
811
+ * values within a single batch are deduplicated last-write-wins by the
812
+ * builders before SQL generation — Postgres `ON CONFLICT` errors on
813
+ * repeated conflict keys in one statement, and SQLite `DELETE + INSERT`
814
+ * would create duplicate virtual-table rows otherwise.
815
+ */
816
+ type UpsertFulltextBatchParams = Readonly<{
817
+ graphId: string;
818
+ nodeKind: string;
819
+ rows: readonly FulltextBatchRow[];
820
+ }>;
821
+ /**
822
+ * Parameters for a batched fulltext delete.
823
+ */
824
+ type DeleteFulltextBatchParams = Readonly<{
825
+ graphId: string;
826
+ nodeKind: string;
827
+ nodeIds: readonly string[];
828
+ }>;
829
+ /**
830
+ * Parameters for fulltext search.
831
+ */
832
+ type FulltextSearchParams = Readonly<{
833
+ graphId: string;
834
+ nodeKind: string;
835
+ /** The user-supplied query string. */
836
+ query: string;
837
+ /** How to parse `query`. Default: "websearch". */
838
+ mode?: FulltextQueryMode;
839
+ /**
840
+ * Language override. Default: per-row language (as stored at insert time).
841
+ * Postgres: passed as the regconfig to `to_tsquery` / `websearch_to_tsquery`.
842
+ * SQLite: informational only (FTS5 tokenizer is fixed at table-create time).
843
+ */
844
+ language?: string;
845
+ /** Max rows to return. */
846
+ limit: number;
847
+ /** Minimum rank to include (backend-dependent units). */
848
+ minScore?: number;
849
+ /** Whether to return a highlighted snippet per match. */
850
+ includeSnippets?: boolean;
851
+ }>;
852
+ /**
853
+ * Result from a fulltext search.
854
+ *
855
+ * Score semantics differ by backend; prefer `rank` (1-based) when fusing
856
+ * with another source via RRF.
857
+ */
858
+ type FulltextSearchResult = Readonly<{
859
+ nodeId: string;
860
+ /**
861
+ * Backend-native relevance score.
862
+ * Postgres: `ts_rank_cd` (higher is better).
863
+ * SQLite FTS5: negated `bm25()` (higher is better; FTS5 returns lower-is-better).
864
+ */
865
+ score: number;
866
+ /** 1-based rank within the result set, suitable for RRF. */
867
+ rank: number;
868
+ /** Highlighted snippet of the content (if `includeSnippets` was set). */
869
+ snippet?: string;
870
+ }>;
871
+ /**
872
+ * Parameters for creating a fulltext index.
873
+ *
874
+ * The canonical index (Postgres GIN on `tsv`, SQLite FTS5 virtual table)
875
+ * is created when the fulltext table itself is created. This is reserved
876
+ * for advanced per-kind specializations.
877
+ */
878
+ /**
879
+ * Per-deployment record for a single declared index.
880
+ *
881
+ * Identified by `indexName` because SQL index names are physical,
882
+ * database-global identifiers — `graphId` is provenance, not identity.
883
+ * `materializedAt` is null until the first successful CREATE INDEX
884
+ * completes; `lastAttemptedAt` is always set, even on failure.
885
+ */
886
+ type IndexMaterializationRow = Readonly<{
887
+ indexName: string;
888
+ graphId: string;
889
+ entity: IndexEntity;
890
+ kind: string;
891
+ signature: string;
892
+ schemaVersion: number;
893
+ materializedAt: string | undefined;
894
+ lastAttemptedAt: string;
895
+ lastError: string | undefined;
896
+ }>;
897
+ /**
898
+ * Parameters for upserting a materialization attempt.
899
+ *
900
+ * On success: pass `materializedAt` (ISO timestamp) and undefined `error`.
901
+ * On failure: pass undefined `materializedAt` (preserve any existing
902
+ * timestamp from a prior success) and the error message.
903
+ */
904
+ type RecordIndexMaterializationParams = Readonly<{
905
+ indexName: string;
906
+ graphId: string;
907
+ entity: IndexEntity;
908
+ kind: string;
909
+ signature: string;
910
+ schemaVersion: number;
911
+ attemptedAt: string;
912
+ /** ISO timestamp on success; undefined on failure (preserves existing). */
913
+ materializedAt: string | undefined;
914
+ /** Error message on failure; undefined on success (clears existing). */
915
+ error: string | undefined;
916
+ }>;
917
+ /**
918
+ * One row of the per-deployment `typegraph_kind_removals` table:
919
+ * a graph-extension kind that has been removed from the schema and whose
920
+ * data may or may not have been cleaned up yet.
921
+ */
922
+ type KindRemovalRow = Readonly<{
923
+ graphId: string;
924
+ kindName: string;
925
+ entity: KindEntity;
926
+ schemaVersion: number;
927
+ /** ISO timestamp when the data-cleanup pass succeeded; undefined while pending. */
928
+ removedAt: string | undefined;
929
+ lastAttemptedAt: string;
930
+ lastError: string | undefined;
931
+ }>;
932
+ /**
933
+ * Upsert payload for a kind-removal status row. On removal-commit:
934
+ * pass `removedAt: undefined` (the pending state). On successful
935
+ * data-cleanup: pass `removedAt` set and `error: undefined`. On
936
+ * cleanup failure: pass `removedAt: undefined` (preserves any prior
937
+ * timestamp from a partial success on a different replica) and the
938
+ * error message.
939
+ */
940
+ type RecordKindRemovalParams = Readonly<{
941
+ graphId: string;
942
+ kindName: string;
943
+ entity: KindEntity;
944
+ schemaVersion: number;
945
+ attemptedAt: string;
946
+ /** ISO timestamp on success; undefined while pending or on failure. */
947
+ removedAt: string | undefined;
948
+ /** Error message on failure; undefined on success or while pending. */
949
+ error: string | undefined;
950
+ }>;
951
+ /**
952
+ * Transaction options.
953
+ */
954
+ type TransactionOptions = Readonly<{
955
+ /** Transaction isolation level (if supported) */
956
+ isolationLevel?: "read_uncommitted" | "read_committed" | "repeatable_read" | "serializable";
957
+ }>;
958
+ /**
959
+ * Transaction backend — a backend scoped to a transaction.
960
+ *
961
+ * `commitSchemaVersion` and `setActiveVersion` are intentionally omitted:
962
+ * the atomicity / CAS guarantees of those primitives depend on
963
+ * dialect-specific write-locking (BEGIN IMMEDIATE on SQLite,
964
+ * `pg_advisory_xact_lock` on Postgres) acquired by the top-level
965
+ * backend wrappers, not the transaction itself. Calling them from a
966
+ * user-supplied `backend.transaction(...)` callback would bypass that
967
+ * locking and silently weaken the orphan-row crash window the primitive
968
+ * exists to eliminate. Schema commits go through the top-level backend
969
+ * methods only.
970
+ */
971
+ type TransactionBackend = Omit<GraphBackend, "transaction" | "close" | "refreshStatistics" | "commitSchemaVersion" | "setActiveVersion">;
972
+ /**
973
+ * The GraphBackend interface abstracts database operations.
974
+ *
975
+ * Implementations should provide:
976
+ * - SQLite backend via better-sqlite3 or libsql
977
+ * - PostgreSQL backend via pg or postgres
978
+ */
979
+ type GraphBackend = Readonly<{
980
+ /** The SQL dialect */
981
+ dialect: SqlDialect;
982
+ /** Backend capabilities */
983
+ capabilities: BackendCapabilities;
984
+ /** Table names used by this backend (for query schema auto-derivation) */
985
+ tableNames?: SqlTableNames | undefined;
986
+ /**
987
+ * Optional fulltext strategy override. When present, both the compiler
988
+ * (for `$fulltext.matches()` in query builder) and backend-direct
989
+ * search paths use this instead of the dialect's default strategy —
990
+ * allowing a Postgres backend to ship pg_trgm, ParadeDB, pgroonga etc.
991
+ * When absent, the dialect's default strategy is used.
992
+ */
993
+ fulltextStrategy?: FulltextStrategy | undefined;
994
+ insertNode: (params: InsertNodeParams) => Promise<NodeRow>;
995
+ insertNodeNoReturn?: (params: InsertNodeParams) => Promise<void>;
996
+ insertNodesBatch?: (params: readonly InsertNodeParams[]) => Promise<void>;
997
+ insertNodesBatchReturning?: (params: readonly InsertNodeParams[]) => Promise<readonly NodeRow[]>;
998
+ updateNode: (params: UpdateNodeParams) => Promise<NodeRow>;
999
+ deleteNode: (params: DeleteNodeParams) => Promise<void>;
1000
+ hardDeleteNode: (params: HardDeleteNodeParams) => Promise<void>;
1001
+ getNode: (graphId: string, kind: string, id: string) => Promise<NodeRow | undefined>;
1002
+ getNodes?: (graphId: string, kind: string, ids: readonly string[]) => Promise<readonly NodeRow[]>;
1003
+ insertEdge: (params: InsertEdgeParams) => Promise<EdgeRow>;
1004
+ insertEdgeNoReturn?: (params: InsertEdgeParams) => Promise<void>;
1005
+ insertEdgesBatch?: (params: readonly InsertEdgeParams[]) => Promise<void>;
1006
+ insertEdgesBatchReturning?: (params: readonly InsertEdgeParams[]) => Promise<readonly EdgeRow[]>;
1007
+ updateEdge: (params: UpdateEdgeParams) => Promise<EdgeRow>;
1008
+ deleteEdge: (params: DeleteEdgeParams) => Promise<void>;
1009
+ hardDeleteEdge: (params: HardDeleteEdgeParams) => Promise<void>;
1010
+ getEdge: (graphId: string, id: string) => Promise<EdgeRow | undefined>;
1011
+ getEdges?: (graphId: string, ids: readonly string[]) => Promise<readonly EdgeRow[]>;
1012
+ countEdgesFrom: (params: CountEdgesFromParams) => Promise<number>;
1013
+ edgeExistsBetween: (params: EdgeExistsBetweenParams) => Promise<boolean>;
1014
+ findEdgesConnectedTo: (params: FindEdgesConnectedToParams) => Promise<readonly EdgeRow[]>;
1015
+ findNodesByKind: (params: FindNodesByKindParams) => Promise<readonly NodeRow[]>;
1016
+ countNodesByKind: (params: CountNodesByKindParams) => Promise<number>;
1017
+ findEdgesByKind: (params: FindEdgesByKindParams) => Promise<readonly EdgeRow[]>;
1018
+ countEdgesByKind: (params: CountEdgesByKindParams) => Promise<number>;
1019
+ insertUnique: (params: InsertUniqueParams) => Promise<void>;
1020
+ deleteUnique: (params: DeleteUniqueParams) => Promise<void>;
1021
+ checkUnique: (params: CheckUniqueParams) => Promise<UniqueRow | undefined>;
1022
+ checkUniqueBatch?: (params: CheckUniqueBatchParams) => Promise<readonly UniqueRow[]>;
1023
+ getActiveSchema: (graphId: string) => Promise<SchemaVersionRow | undefined>;
1024
+ getSchemaVersion: (graphId: string, version: number) => Promise<SchemaVersionRow | undefined>;
1025
+ /**
1026
+ * Atomically inserts a new schema version and activates it as a single
1027
+ * transactional unit, with optimistic compare-and-swap on the currently
1028
+ * active version.
1029
+ *
1030
+ * - If `expected.kind === "active"` and the actual active version
1031
+ * differs, throws `StaleVersionError` (caller should refetch and
1032
+ * retry).
1033
+ * - If a row already exists at `params.version` with the same
1034
+ * `schemaHash`, returns it idempotently — reactivating it if it was
1035
+ * left inactive by an earlier crashed commit.
1036
+ * - If a row already exists at `params.version` with a different
1037
+ * `schemaHash`, throws `SchemaContentConflictError`.
1038
+ *
1039
+ * Requires `capabilities.transactions === true`. On non-transactional
1040
+ * backends (e.g. Cloudflare D1, drizzle-orm/neon-http) this method
1041
+ * throws `ConfigurationError` rather than running with degraded
1042
+ * atomicity that would silently re-introduce the orphan-row crash
1043
+ * window the primitive exists to eliminate.
1044
+ */
1045
+ commitSchemaVersion: (params: CommitSchemaVersionParams) => Promise<SchemaVersionRow>;
1046
+ /**
1047
+ * Atomically flips the active schema pointer to an existing version,
1048
+ * with optimistic compare-and-swap on the currently active version.
1049
+ * Used by `rollbackSchema` and any other "promote/demote existing
1050
+ * version" workflow. Throws `StaleVersionError` on CAS mismatch and
1051
+ * `MigrationError` if the target version row does not exist.
1052
+ *
1053
+ * Same transactional requirements as `commitSchemaVersion`.
1054
+ */
1055
+ setActiveVersion: (params: SetActiveVersionParams) => Promise<void>;
1056
+ upsertEmbedding?: (params: UpsertEmbeddingParams) => Promise<void>;
1057
+ deleteEmbedding?: (params: DeleteEmbeddingParams) => Promise<void>;
1058
+ getEmbedding?: (graphId: string, nodeKind: string, nodeId: string, fieldPath: string) => Promise<EmbeddingRow | undefined>;
1059
+ vectorSearch?: (params: VectorSearchParams) => Promise<readonly VectorSearchResult[]>;
1060
+ createVectorIndex?: (params: CreateVectorIndexParams) => Promise<void>;
1061
+ dropVectorIndex?: (params: DropVectorIndexParams) => Promise<void>;
1062
+ upsertFulltext?: (params: UpsertFulltextParams) => Promise<void>;
1063
+ deleteFulltext?: (params: DeleteFulltextParams) => Promise<void>;
1064
+ /**
1065
+ * Batched variant of `upsertFulltext`. Optional — callers fall back to
1066
+ * per-row `upsertFulltext` when unset.
1067
+ */
1068
+ upsertFulltextBatch?: (params: UpsertFulltextBatchParams) => Promise<void>;
1069
+ /**
1070
+ * Batched variant of `deleteFulltext`. Optional — callers fall back to
1071
+ * per-row `deleteFulltext` when unset.
1072
+ */
1073
+ deleteFulltextBatch?: (params: DeleteFulltextBatchParams) => Promise<void>;
1074
+ fulltextSearch?: (params: FulltextSearchParams) => Promise<readonly FulltextSearchResult[]>;
1075
+ /**
1076
+ * Idempotently ensure ONLY the `typegraph_index_materializations`
1077
+ * table exists — separate from `bootstrapTables` so that
1078
+ * `materializeIndexes` doesn't pull in the full base-table DDL set
1079
+ * just to access the status table.
1080
+ *
1081
+ * Why focused: `bootstrapTables` issues 20+ `CREATE TABLE / CREATE
1082
+ * INDEX IF NOT EXISTS` statements covering every base table. Two
1083
+ * concurrent calls (e.g. two replicas of the same `schema_doc` both
1084
+ * starting up and calling `materializeIndexes`) race on
1085
+ * Postgres SHARE locks and DEADLOCK. Restricting the ensure-step to
1086
+ * the single status table eliminates the cross-table race entirely
1087
+ * — concurrent `CREATE TABLE IF NOT EXISTS` for one specific table
1088
+ * is well-behaved on Postgres.
1089
+ */
1090
+ ensureIndexMaterializationsTable?: () => Promise<void>;
1091
+ /**
1092
+ * Look up a recorded materialization for a declared index by its
1093
+ * physical SQL index name. Returns `undefined` if no row exists.
1094
+ */
1095
+ getIndexMaterialization?: (indexName: string) => Promise<IndexMaterializationRow | undefined>;
1096
+ /**
1097
+ * Bulk variant of `getIndexMaterialization`: load every recorded
1098
+ * materialization whose `indexName` (status key) is in `statusKeys`,
1099
+ * in a single round-trip. Returned rows are unordered — callers index
1100
+ * by `indexName`. Optional; consumers fall back to per-key
1101
+ * `getIndexMaterialization` when unset.
1102
+ */
1103
+ getIndexMaterializations?: (statusKeys: readonly string[]) => Promise<readonly IndexMaterializationRow[]>;
1104
+ /**
1105
+ * Upsert a materialization attempt — success or failure. Failure rows
1106
+ * preserve any prior `materializedAt` so the historical successful
1107
+ * timestamp survives across error windows.
1108
+ */
1109
+ recordIndexMaterialization?: (params: RecordIndexMaterializationParams) => Promise<void>;
1110
+ /**
1111
+ * Bootstraps the per-deployment `typegraph_kind_removals` table so
1112
+ * `store.removeKinds()` and `store.materializeRemovals()` can persist
1113
+ * removal status. Mirrors the focused-bootstrap rationale documented
1114
+ * on `ensureIndexMaterializationsTable` — the full `bootstrapTables`
1115
+ * touches every base table and risks Postgres SHARE-lock deadlock
1116
+ * under concurrent replica startup.
1117
+ */
1118
+ ensureKindRemovalsTable?: () => Promise<void>;
1119
+ /**
1120
+ * List graph-extension kind removals whose data-cleanup pass has not yet
1121
+ * succeeded for this `graphId`. Returns rows with
1122
+ * `removedAt: undefined`. Order is unspecified; callers materialize
1123
+ * one-at-a-time and don't depend on it.
1124
+ */
1125
+ getPendingKindRemovals?: (graphId: string) => Promise<readonly KindRemovalRow[]>;
1126
+ /**
1127
+ * List ALL kind-removal rows for a `graphId` — pending and completed.
1128
+ * Used by `materializeRemovals()` reconciliation to detect rows that
1129
+ * are missing entirely (the `removeKinds()` crash window) versus
1130
+ * already completed. Without this distinction the reconciler would
1131
+ * have to upsert every expected historical removal on every call,
1132
+ * churning `last_attempted_at` on rows that long since succeeded.
1133
+ * Order is unspecified.
1134
+ */
1135
+ getAllKindRemovals?: (graphId: string) => Promise<readonly KindRemovalRow[]>;
1136
+ /**
1137
+ * Upsert a kind-removal status row. `removedAt: undefined` records
1138
+ * the pending state at schema-commit time; `removedAt: <iso>`
1139
+ * marks the data cleanup successful. The COALESCE rule on `removedAt`
1140
+ * mirrors `recordIndexMaterialization` so a later failure doesn't
1141
+ * clobber the historical successful timestamp from another replica.
1142
+ */
1143
+ recordKindRemoval?: (params: RecordKindRemovalParams) => Promise<void>;
1144
+ /**
1145
+ * Bootstraps the per-deployment `typegraph_reconciliation_markers`
1146
+ * table so `materializeRemovals()` can persist reconciliation
1147
+ * progress. Same focused-bootstrap rationale as the other status
1148
+ * tables — full `bootstrapTables` risks Postgres SHARE-lock
1149
+ * deadlock under concurrent replica startup.
1150
+ */
1151
+ ensureReconciliationMarkersTable?: () => Promise<void>;
1152
+ /**
1153
+ * Read the high-water mark schema version for which
1154
+ * `materializeRemovals` reconciliation has already verified history
1155
+ * for `graphId`. Returns `undefined` when no marker has been
1156
+ * recorded yet. Used to skip already-checked transitions in the
1157
+ * recovery walk.
1158
+ */
1159
+ getReconciliationMarker?: (graphId: string) => Promise<number | undefined>;
1160
+ /**
1161
+ * Persist the reconciliation high-water mark for `graphId`. Called
1162
+ * after `materializeRemovals` completes a clean walk; subsequent
1163
+ * calls walk only versions newer than this marker. Idempotent
1164
+ * upsert by `graphId`.
1165
+ */
1166
+ setReconciliationMarker?: (graphId: string, version: number) => Promise<void>;
1167
+ /**
1168
+ * Hard-deletes all data for a graph (nodes, edges, uniques, embeddings, schema versions).
1169
+ * Intended for import-replacement workflows. No hooks, no per-row logic.
1170
+ */
1171
+ clearGraph: (graphId: string) => Promise<void>;
1172
+ /**
1173
+ * Creates the base TypeGraph tables if they don't already exist.
1174
+ *
1175
+ * Called automatically by `createStoreWithSchema()` when a fresh database
1176
+ * is detected. Users who manage DDL themselves via `createStore()` never
1177
+ * hit this path.
1178
+ */
1179
+ bootstrapTables?: () => Promise<void>;
1180
+ /**
1181
+ * Refreshes the backend's query-planner statistics.
1182
+ *
1183
+ * Call this once after a large initial import or bulk backfill. Without
1184
+ * up-to-date statistics, the planner can pick suboptimal execution plans
1185
+ * — on PostgreSQL this is the difference between a 0.5ms and a 5ms
1186
+ * forward traversal; on SQLite it's the difference between 0.9ms and
1187
+ * 23ms fulltext search. Autovacuum / background statistics collection
1188
+ * will catch up eventually, but calling this explicitly after a bulk
1189
+ * load gives you correct latencies immediately.
1190
+ *
1191
+ * Implementations:
1192
+ * - SQLite runs `ANALYZE`, which populates `sqlite_stat1`
1193
+ * - PostgreSQL runs `ANALYZE` on the TypeGraph-managed tables
1194
+ *
1195
+ * Safe to call at any time; costs a few tens of milliseconds on the
1196
+ * sizes this library is designed for.
1197
+ */
1198
+ refreshStatistics: () => Promise<void>;
1199
+ execute: <T>(query: SQL) => Promise<readonly T[]>;
1200
+ /** Execute pre-compiled SQL text with bound parameters. Available on sync SQLite and pg backends. */
1201
+ executeRaw?: <T>(sqlText: string, params: readonly unknown[]) => Promise<readonly T[]>;
1202
+ /** Compile a Drizzle SQL object to { sql, params } without executing. */
1203
+ compileSql?: (query: SQL) => Readonly<{
1204
+ sql: string;
1205
+ params: readonly unknown[];
1206
+ }>;
1207
+ /**
1208
+ * Execute a DDL statement that returns no rows (CREATE INDEX,
1209
+ * CREATE TABLE, ALTER TABLE, etc.). Separate from `executeRaw`
1210
+ * because some drivers (better-sqlite3) require `.run()` for DDL
1211
+ * and `.all()` for queries — the ambiguity can't be resolved by
1212
+ * inspecting the SQL string portably.
1213
+ *
1214
+ * Postgres path can use this for `CREATE INDEX CONCURRENTLY`, which
1215
+ * cannot run inside a transaction. Implementations must execute the
1216
+ * statement outside `transaction(...)`.
1217
+ */
1218
+ executeDdl?: (ddl: string) => Promise<void>;
1219
+ transaction: <T>(fn: (tx: TransactionBackend) => Promise<T>, options?: TransactionOptions) => Promise<T>;
1220
+ close: () => Promise<void>;
1221
+ }>;
1222
+ /**
1223
+ * Parameters for inserting a unique constraint entry.
1224
+ */
1225
+ type InsertUniqueParams = Readonly<{
1226
+ graphId: string;
1227
+ nodeKind: string;
1228
+ constraintName: string;
1229
+ key: string;
1230
+ nodeId: string;
1231
+ concreteKind: string;
1232
+ }>;
1233
+ /**
1234
+ * Parameters for deleting a unique constraint entry.
1235
+ */
1236
+ type DeleteUniqueParams = Readonly<{
1237
+ graphId: string;
1238
+ nodeKind: string;
1239
+ constraintName: string;
1240
+ key: string;
1241
+ }>;
1242
+ /**
1243
+ * Parameters for checking a unique constraint.
1244
+ */
1245
+ type CheckUniqueParams = Readonly<{
1246
+ graphId: string;
1247
+ nodeKind: string;
1248
+ constraintName: string;
1249
+ key: string;
1250
+ /** If true, also returns soft-deleted entries. Used by get-or-create operations. */
1251
+ includeDeleted?: boolean;
1252
+ }>;
1253
+ /**
1254
+ * Parameters for batch-checking unique constraints.
1255
+ */
1256
+ type CheckUniqueBatchParams = Readonly<{
1257
+ graphId: string;
1258
+ nodeKind: string;
1259
+ constraintName: string;
1260
+ keys: readonly string[];
1261
+ /** If true, also returns soft-deleted entries. Used by get-or-create operations. */
1262
+ includeDeleted?: boolean;
1263
+ }>;
1264
+ /**
1265
+ * The caller's claim about the currently-active schema version, used as
1266
+ * the optimistic compare-and-swap guard for `commitSchemaVersion`.
1267
+ *
1268
+ * - `{ kind: "initial" }` — caller is committing the first-ever version
1269
+ * for this graph and asserts no active version exists yet.
1270
+ * - `{ kind: "active", version: N }` — caller observed version N as
1271
+ * active and is committing version N+1 against that baseline. The
1272
+ * commit fails with `StaleVersionError` if some other writer has
1273
+ * advanced or rolled back the pointer in the meantime.
1274
+ *
1275
+ * Tagged-union form (rather than a magic `version: 0` sentinel) because
1276
+ * the two cases have materially different semantics: the initial path
1277
+ * skips the "deactivate prior" UPDATE, and the no-active-row state is
1278
+ * a *valid* expected state, not an out-of-band signal.
1279
+ */
1280
+ type CommitSchemaVersionExpected = Readonly<{
1281
+ kind: "initial";
1282
+ }> | Readonly<{
1283
+ kind: "active";
1284
+ version: number;
1285
+ }>;
1286
+ /**
1287
+ * Parameters for `commitSchemaVersion`.
1288
+ */
1289
+ type CommitSchemaVersionParams = Readonly<{
1290
+ graphId: string;
1291
+ /** CAS guard — see `CommitSchemaVersionExpected`. */
1292
+ expected: CommitSchemaVersionExpected;
1293
+ /** The new version to insert and activate. */
1294
+ version: number;
1295
+ schemaHash: string;
1296
+ schemaDoc: SerializedSchema;
1297
+ }>;
1298
+ /**
1299
+ * Parameters for `setActiveVersion`.
1300
+ *
1301
+ * Flips the active pointer from `expected` to `version` for an existing
1302
+ * row. CAS prevents overwriting a concurrent rollback or commit.
1303
+ */
1304
+ type SetActiveVersionParams = Readonly<{
1305
+ graphId: string;
1306
+ /** CAS guard. Same semantics as `commitSchemaVersion.expected`. */
1307
+ expected: CommitSchemaVersionExpected;
1308
+ /** The version to mark active. Must already exist. */
1309
+ version: number;
1310
+ }>;
1311
+ /**
1312
+ * Parameters for counting edges from a source node.
1313
+ */
1314
+ type CountEdgesFromParams = Readonly<{
1315
+ graphId: string;
1316
+ edgeKind: string;
1317
+ fromKind: string;
1318
+ fromId: string;
1319
+ /** If true, only count edges where valid_to IS NULL */
1320
+ activeOnly?: boolean;
1321
+ }>;
1322
+ /**
1323
+ * Parameters for checking if an edge exists between two nodes.
1324
+ */
1325
+ type EdgeExistsBetweenParams = Readonly<{
1326
+ graphId: string;
1327
+ edgeKind: string;
1328
+ fromKind: string;
1329
+ fromId: string;
1330
+ toKind: string;
1331
+ toId: string;
1332
+ }>;
1333
+ /**
1334
+ * Parameters for finding edges connected to a node.
1335
+ */
1336
+ type FindEdgesConnectedToParams = Readonly<{
1337
+ graphId: string;
1338
+ nodeKind: string;
1339
+ nodeId: string;
1340
+ }>;
1341
+ /**
1342
+ * Parameters for finding nodes by kind.
1343
+ */
1344
+ type FindNodesByKindParams = Readonly<{
1345
+ graphId: string;
1346
+ kind: string;
1347
+ /** Max rows to return. */
1348
+ limit?: number;
1349
+ /** Offset. Present for backward compat; rebuild uses `after` instead. */
1350
+ offset?: number;
1351
+ /** If true, exclude deleted nodes. Default true. */
1352
+ excludeDeleted?: boolean;
1353
+ /** Temporal mode for filtering by validity period. */
1354
+ temporalMode?: TemporalMode;
1355
+ /** Timestamp for "current" and "asOf" temporal modes. */
1356
+ asOf?: string;
1357
+ /**
1358
+ * Stable ordering for keyset pagination. Default: "created_at" (existing
1359
+ * behavior). Rebuild should use "id" for iteration that is stable under
1360
+ * concurrent writes and shared timestamps.
1361
+ */
1362
+ orderBy?: "id" | "created_at";
1363
+ /**
1364
+ * Keyset cursor. Returns rows strictly greater (by `orderBy`) than this
1365
+ * value. When `orderBy: "id"`, compared lexicographically. Mutually
1366
+ * exclusive with `offset` — callers pick one.
1367
+ */
1368
+ after?: string;
1369
+ }>;
1370
+ /**
1371
+ * Parameters for counting nodes by kind.
1372
+ */
1373
+ type CountNodesByKindParams = Readonly<{
1374
+ graphId: string;
1375
+ kind: string;
1376
+ /** If true, exclude deleted nodes. Default true. */
1377
+ excludeDeleted?: boolean;
1378
+ /** Temporal mode for filtering by validity period. */
1379
+ temporalMode?: TemporalMode;
1380
+ /** Timestamp for "current" and "asOf" temporal modes. */
1381
+ asOf?: string;
1382
+ }>;
1383
+ /**
1384
+ * Parameters for finding edges by kind.
1385
+ */
1386
+ type FindEdgesByKindParams = Readonly<{
1387
+ graphId: string;
1388
+ kind: string;
1389
+ fromKind?: string;
1390
+ fromId?: string;
1391
+ toKind?: string;
1392
+ toId?: string;
1393
+ limit?: number;
1394
+ offset?: number;
1395
+ /** If true, exclude deleted edges. Default true. */
1396
+ excludeDeleted?: boolean;
1397
+ /** Temporal mode for filtering by validity period. */
1398
+ temporalMode?: TemporalMode;
1399
+ /** Timestamp for "current" and "asOf" temporal modes. */
1400
+ asOf?: string;
1401
+ }>;
1402
+ /**
1403
+ * Parameters for counting edges by kind.
1404
+ */
1405
+ type CountEdgesByKindParams = Readonly<{
1406
+ graphId: string;
1407
+ kind: string;
1408
+ fromKind?: string;
1409
+ fromId?: string;
1410
+ toKind?: string;
1411
+ toId?: string;
1412
+ /** If true, exclude deleted edges. Default true. */
1413
+ excludeDeleted?: boolean;
1414
+ /** Temporal mode for filtering by validity period. */
1415
+ temporalMode?: TemporalMode;
1416
+ /** Timestamp for "current" and "asOf" temporal modes. */
1417
+ asOf?: string;
1418
+ }>;
1419
+
1420
+ /**
1421
+ * Query AST types.
1422
+ *
1423
+ * Defines the abstract syntax tree for TypeGraph queries.
1424
+ * This portable representation can be compiled to SQL (today)
1425
+ * or other query languages (Cypher, SPARQL) in the future.
1426
+ */
1427
+
1428
+ /**
1429
+ * A field reference in a predicate.
1430
+ */
1431
+ type FieldRef = Readonly<{
1432
+ __type: "field_ref";
1433
+ alias: string;
1434
+ path: readonly string[];
1435
+ jsonPointer?: JsonPointer | undefined;
1436
+ valueType?: ValueType | undefined;
1437
+ elementType?: ValueType | undefined;
1438
+ }>;
1439
+ /**
1440
+ * A literal value in a predicate.
1441
+ */
1442
+ type LiteralValue = Readonly<{
1443
+ __type: "literal";
1444
+ value: string | number | boolean;
1445
+ valueType?: ValueType | undefined;
1446
+ }>;
1447
+ /**
1448
+ * A parameter reference for prepared queries.
1449
+ *
1450
+ * Used in place of a literal value to create parameterized queries
1451
+ * that can be executed multiple times with different bindings.
1452
+ */
1453
+ type ParameterRef = Readonly<{
1454
+ __type: "parameter";
1455
+ name: string;
1456
+ valueType?: ValueType | undefined;
1457
+ }>;
1458
+ /**
1459
+ * Supported value types for predicates.
1460
+ */
1461
+ type ValueType = "string" | "number" | "boolean" | "date" | "array" | "object" | "embedding" | "unknown";
1462
+ /**
1463
+ * Comparison operators.
1464
+ */
1465
+ type ComparisonOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn";
1466
+ /**
1467
+ * String operators.
1468
+ */
1469
+ type StringOp = "contains" | "startsWith" | "endsWith" | "like" | "ilike";
1470
+ /**
1471
+ * A comparison predicate.
1472
+ */
1473
+ type ComparisonPredicate = Readonly<{
1474
+ __type: "comparison";
1475
+ op: ComparisonOp;
1476
+ left: FieldRef;
1477
+ right: LiteralValue | LiteralValue[] | ParameterRef;
1478
+ }>;
1479
+ /**
1480
+ * A string predicate.
1481
+ */
1482
+ type StringPredicate = Readonly<{
1483
+ __type: "string_op";
1484
+ op: StringOp;
1485
+ field: FieldRef;
1486
+ pattern: string | ParameterRef;
1487
+ }>;
1488
+ /**
1489
+ * A null check predicate.
1490
+ */
1491
+ type NullPredicate = Readonly<{
1492
+ __type: "null_check";
1493
+ op: NullCheckOp;
1494
+ field: FieldRef;
1495
+ }>;
1496
+ /**
1497
+ * A between predicate.
1498
+ */
1499
+ type BetweenPredicate = Readonly<{
1500
+ __type: "between";
1501
+ field: FieldRef;
1502
+ lower: LiteralValue | ParameterRef;
1503
+ upper: LiteralValue | ParameterRef;
1504
+ }>;
1505
+ /**
1506
+ * Array operators.
1507
+ */
1508
+ type ArrayOp = "contains" | "containsAll" | "containsAny" | "isEmpty" | "isNotEmpty" | "lengthEq" | "lengthGt" | "lengthGte" | "lengthLt" | "lengthLte";
1509
+ /**
1510
+ * An array predicate.
1511
+ */
1512
+ type ArrayPredicate = Readonly<{
1513
+ __type: "array_op";
1514
+ op: ArrayOp;
1515
+ field: FieldRef;
1516
+ values?: readonly LiteralValue[];
1517
+ length?: number;
1518
+ }>;
1519
+ /**
1520
+ * Object operators.
1521
+ */
1522
+ type ObjectOp = "hasKey" | "hasPath" | "pathEquals" | "pathContains" | "pathIsNull" | "pathIsNotNull";
1523
+ /**
1524
+ * An object/JSON predicate.
1525
+ */
1526
+ type ObjectPredicate = Readonly<{
1527
+ __type: "object_op";
1528
+ op: ObjectOp;
1529
+ field: FieldRef;
1530
+ pointer: JsonPointer;
1531
+ value?: LiteralValue;
1532
+ valueType?: ValueType;
1533
+ elementType?: ValueType;
1534
+ }>;
1535
+ /**
1536
+ * Logical AND predicate.
1537
+ */
1538
+ type AndPredicate = Readonly<{
1539
+ __type: "and";
1540
+ predicates: readonly PredicateExpression[];
1541
+ }>;
1542
+ /**
1543
+ * Logical OR predicate.
1544
+ */
1545
+ type OrPredicate = Readonly<{
1546
+ __type: "or";
1547
+ predicates: readonly PredicateExpression[];
1548
+ }>;
1549
+ /**
1550
+ * Logical NOT predicate.
1551
+ */
1552
+ type NotPredicate = Readonly<{
1553
+ __type: "not";
1554
+ predicate: PredicateExpression;
1555
+ }>;
1556
+ /**
1557
+ * An aggregate comparison predicate (for HAVING clauses).
1558
+ */
1559
+ type AggregateComparisonPredicate = Readonly<{
1560
+ __type: "aggregate_comparison";
1561
+ op: ComparisonOp;
1562
+ aggregate: AggregateExpr;
1563
+ value: LiteralValue;
1564
+ }>;
1565
+ /**
1566
+ * An EXISTS subquery predicate.
1567
+ * Tests whether the subquery returns any rows.
1568
+ */
1569
+ type ExistsSubquery = Readonly<{
1570
+ __type: "exists";
1571
+ subquery: QueryAst;
1572
+ negated: boolean;
1573
+ }>;
1574
+ /**
1575
+ * An IN subquery predicate.
1576
+ * Tests whether a field value is in the subquery results.
1577
+ */
1578
+ type InSubquery = Readonly<{
1579
+ __type: "in_subquery";
1580
+ field: FieldRef;
1581
+ subquery: QueryAst;
1582
+ negated: boolean;
1583
+ }>;
1584
+ /**
1585
+ * Vector similarity metric types.
1586
+ */
1587
+ type VectorMetricType = "cosine" | "l2" | "inner_product";
1588
+ /**
1589
+ * A vector similarity predicate.
1590
+ * Finds nodes with embeddings similar to the query embedding.
1591
+ *
1592
+ * This predicate affects query execution by:
1593
+ * - Joining with the embeddings table
1594
+ * - Adding ORDER BY distance (ascending)
1595
+ * - Applying LIMIT (top k results)
1596
+ * - Optionally filtering by minimum score
1597
+ */
1598
+ type VectorSimilarityPredicate = Readonly<{
1599
+ __type: "vector_similarity";
1600
+ /** The embedding field reference */
1601
+ field: FieldRef;
1602
+ /** The query embedding to compare against */
1603
+ queryEmbedding: readonly number[];
1604
+ /** Similarity metric to use */
1605
+ metric: VectorMetricType;
1606
+ /** Maximum number of results to return */
1607
+ limit: number;
1608
+ /** Optional minimum similarity score (0-1 for cosine) */
1609
+ minScore?: number;
1610
+ }>;
1611
+
1612
+ /**
1613
+ * A fulltext MATCH predicate.
1614
+ *
1615
+ * Finds nodes whose combined searchable content matches the query. Affects
1616
+ * query execution by joining with the fulltext table, adding an ORDER BY
1617
+ * on relevance rank (descending), and applying a LIMIT (top k).
1618
+ */
1619
+ type FulltextMatchPredicate = Readonly<{
1620
+ __type: "fulltext_match";
1621
+ /**
1622
+ * Reserved for forward compatibility with per-field fulltext dispatch.
1623
+ * Today only `field.alias` is consumed: the MATCH always targets the
1624
+ * combined `content` column, so `field.path` is a synthetic
1625
+ * `["$fulltext"]` marker rather than a real props path. Future
1626
+ * strategies (per-field indexes, `setweight()`-style boosts) can use
1627
+ * the full `FieldRef` without breaking the AST shape.
1628
+ */
1629
+ field: FieldRef;
1630
+ /** The user-supplied query string. */
1631
+ query: string;
1632
+ /** Parse mode for the query string. Default: "websearch". */
1633
+ mode: FulltextQueryMode;
1634
+ /** Language override for query parsing. */
1635
+ language?: string;
1636
+ /** Maximum number of results to return. */
1637
+ limit: number;
1638
+ /** Minimum relevance to include (backend-native units). */
1639
+ minScore?: number;
1640
+ }>;
1641
+ /**
1642
+ * Fusion options for hybrid (vector + fulltext) queries.
1643
+ *
1644
+ * Shared between:
1645
+ * - Query-builder path: `QueryBuilder.fuseWith()` stores this on `QueryAst`.
1646
+ * - Store path: `store.search.hybrid(kind, { fusion })` accepts the same shape.
1647
+ *
1648
+ * Only applied when the query contains both a vector and a fulltext
1649
+ * predicate. Defaults (when omitted): RRF with k=60 and equal weights.
1650
+ */
1651
+ type HybridFusionOptions = Readonly<{
1652
+ /** RRF is the only currently supported fusion method. */
1653
+ method?: "rrf";
1654
+ /** RRF constant. The classic value is 60. */
1655
+ k?: number;
1656
+ /** Per-source weights. Default: { vector: 1, fulltext: 1 }. */
1657
+ weights?: Readonly<{
1658
+ vector?: number;
1659
+ fulltext?: number;
1660
+ }>;
1661
+ }>;
1662
+ /**
1663
+ * All predicate expression types.
1664
+ */
1665
+ type PredicateExpression = ComparisonPredicate | StringPredicate | NullPredicate | BetweenPredicate | ArrayPredicate | ObjectPredicate | AndPredicate | OrPredicate | NotPredicate | AggregateComparisonPredicate | ExistsSubquery | InSubquery | VectorSimilarityPredicate | FulltextMatchPredicate;
1666
+ /**
1667
+ * The starting point of a query (the FROM clause).
1668
+ */
1669
+ type QueryStart = Readonly<{
1670
+ alias: string;
1671
+ kinds: readonly string[];
1672
+ includeSubClasses: boolean;
1673
+ }>;
1674
+ /**
1675
+ * Direction of edge traversal.
1676
+ */
1677
+ type TraversalDirection = "out" | "in";
1678
+ /**
1679
+ * Traversal ontology expansion behavior.
1680
+ *
1681
+ * - `"none"` — follow only the exact edge kind specified
1682
+ * - `"implying"` — also follow edge kinds that imply the specified kind (subClassOf)
1683
+ * - `"inverse"` — also follow the ontological inverse edge kind (inverseOf)
1684
+ * - `"all"` — follow both implying and inverse expansions
1685
+ */
1686
+ type TraversalExpansion = "none" | "implying" | "inverse" | "all";
1687
+ /**
1688
+ * Cycle handling policy for recursive traversals.
1689
+ */
1690
+ type RecursiveCyclePolicy = "prevent" | "allow";
1691
+ /**
1692
+ * Variable-length traversal specification for recursive graph traversals.
1693
+ */
1694
+ type VariableLengthSpec = Readonly<{
1695
+ /** Minimum number of hops before including results (default: 1) */
1696
+ minDepth: number;
1697
+ /** Maximum number of hops (-1 = unlimited, default: -1) */
1698
+ maxDepth: number;
1699
+ /**
1700
+ * Cycle handling mode.
1701
+ *
1702
+ * - "prevent": Track visited nodes per path and reject revisits
1703
+ * - "allow": Skip cycle checks (faster, may revisit nodes)
1704
+ */
1705
+ cyclePolicy: RecursiveCyclePolicy;
1706
+ /** Optional column alias for projected traversal path array */
1707
+ pathAlias?: string;
1708
+ /** Optional column alias for projected traversal depth */
1709
+ depthAlias?: string;
1710
+ }>;
1711
+ /**
1712
+ * A traversal step in the query.
1713
+ */
1714
+ type Traversal = Readonly<{
1715
+ edgeAlias: string;
1716
+ edgeKinds: readonly string[];
1717
+ /**
1718
+ * Edge kinds traversed in the opposite direction.
1719
+ *
1720
+ * Populated when query options request inverse/symmetric expansion.
1721
+ */
1722
+ inverseEdgeKinds?: readonly string[];
1723
+ direction: TraversalDirection;
1724
+ nodeAlias: string;
1725
+ nodeKinds: readonly string[];
1726
+ joinFromAlias: string;
1727
+ joinEdgeField: "from_id" | "to_id";
1728
+ /** If true, use LEFT JOIN instead of INNER JOIN (optional match) */
1729
+ optional: boolean;
1730
+ /** Variable-length traversal configuration (for recursive CTEs) */
1731
+ variableLength?: VariableLengthSpec;
1732
+ }>;
1733
+ /**
1734
+ * Supported aggregate functions.
1735
+ */
1736
+ type AggregateFunction = "count" | "countDistinct" | "sum" | "avg" | "min" | "max";
1737
+ /**
1738
+ * An aggregate expression.
1739
+ */
1740
+ type AggregateExpr = Readonly<{
1741
+ __type: "aggregate";
1742
+ function: AggregateFunction;
1743
+ field: FieldRef;
1744
+ }>;
1745
+ /**
1746
+ * A GROUP BY specification.
1747
+ */
1748
+ type GroupBySpec = Readonly<{
1749
+ fields: readonly FieldRef[];
1750
+ }>;
1751
+ /**
1752
+ * A projected field in the SELECT clause.
1753
+ * Can be either a direct field reference or an aggregate expression.
1754
+ */
1755
+ type ProjectedField = Readonly<{
1756
+ outputName: string;
1757
+ source: FieldRef | AggregateExpr;
1758
+ /** Override the CTE alias for this field (used for edge fields in node CTEs) */
1759
+ cteAlias?: string;
1760
+ }>;
1761
+ /**
1762
+ * The projection (SELECT) clause.
1763
+ */
1764
+ type Projection = Readonly<{
1765
+ fields: readonly ProjectedField[];
1766
+ }>;
1767
+ /**
1768
+ * A selectively projected field for optimized queries.
1769
+ *
1770
+ * Used when the select callback only accesses specific fields,
1771
+ * allowing the compiler to generate optimized SQL that fetches
1772
+ * only those fields instead of the full props blob.
1773
+ */
1774
+ type SelectiveField = Readonly<{
1775
+ /** The alias (node or edge) this field belongs to */
1776
+ alias: string;
1777
+ /** The field name (e.g., "email", "name", "id") */
1778
+ field: string;
1779
+ /** The output column name in the result (e.g., "p_email") */
1780
+ outputName: string;
1781
+ /** True if this is a system field (id, kind, etc.), false for props */
1782
+ isSystemField: boolean;
1783
+ /**
1784
+ * Optional value type for props fields.
1785
+ *
1786
+ * When present, the compiler can use type-aware JSON extraction
1787
+ * (e.g. numeric/date casts) to better match predicate compilation
1788
+ * and enable expression index coverage.
1789
+ */
1790
+ valueType?: ValueType | undefined;
1791
+ }>;
1792
+ /**
1793
+ * Null ordering preference.
1794
+ */
1795
+ type NullOrdering = "first" | "last";
1796
+ /**
1797
+ * Sort direction.
1798
+ */
1799
+ type SortDirection = "asc" | "desc";
1800
+ /**
1801
+ * An ordering specification.
1802
+ */
1803
+ type OrderSpec = Readonly<{
1804
+ field: FieldRef;
1805
+ direction: SortDirection;
1806
+ nulls?: NullOrdering;
1807
+ }>;
1808
+ /**
1809
+ * A predicate applied to a specific node or edge alias.
1810
+ */
1811
+ type NodePredicate = Readonly<{
1812
+ targetAlias: string;
1813
+ /** Whether this predicate targets a node or edge. Defaults to "node". */
1814
+ targetType?: KindEntity;
1815
+ expression: PredicateExpression;
1816
+ }>;
1817
+ /**
1818
+ * Temporal query options.
1819
+ */
1820
+ type TemporalOptions = Readonly<{
1821
+ mode: TemporalMode;
1822
+ asOf?: string;
1823
+ }>;
1824
+ /**
1825
+ * The complete query AST.
1826
+ */
1827
+ type QueryAst = Readonly<{
1828
+ /** The graph ID this query is for (used for subqueries) */
1829
+ graphId?: string;
1830
+ start: QueryStart;
1831
+ traversals: readonly Traversal[];
1832
+ predicates: readonly NodePredicate[];
1833
+ projection: Projection;
1834
+ temporalMode: TemporalOptions;
1835
+ orderBy?: readonly OrderSpec[];
1836
+ limit?: number;
1837
+ offset?: number;
1838
+ /** GROUP BY specification for aggregate queries */
1839
+ groupBy?: GroupBySpec;
1840
+ /** HAVING clause - predicates applied after GROUP BY */
1841
+ having?: PredicateExpression;
1842
+ /**
1843
+ * Selective fields for optimized queries.
1844
+ * When present, the compiler generates SQL that only fetches these specific
1845
+ * fields instead of the full props blob, enabling covered index usage.
1846
+ */
1847
+ selectiveFields?: readonly SelectiveField[];
1848
+ /** Fusion options for hybrid queries. Ignored unless both predicates present. */
1849
+ fusion?: HybridFusionOptions;
1850
+ }>;
1851
+ /**
1852
+ * Set operation types for combining queries.
1853
+ */
1854
+ type SetOperationType = "union" | "unionAll" | "intersect" | "except";
1855
+ /**
1856
+ * A set operation combining two queries.
1857
+ */
1858
+ type SetOperation = Readonly<{
1859
+ __type: "set_operation";
1860
+ operator: SetOperationType;
1861
+ left: ComposableQuery;
1862
+ right: ComposableQuery;
1863
+ orderBy?: readonly OrderSpec[];
1864
+ limit?: number;
1865
+ offset?: number;
1866
+ }>;
1867
+ /**
1868
+ * A composable query - either a base query or a set operation.
1869
+ */
1870
+ type ComposableQuery = QueryAst | SetOperation;
1871
+
1872
+ type IndexScope =
1873
+ /**
1874
+ * Prefix index keys with `(graph_id, kind)` (nodes) or `(graph_id, kind)` (edges).
1875
+ *
1876
+ * This matches TypeGraph queries which always filter on `graph_id` and `kind`
1877
+ * (often as `IN (...)` due to ontology expansion).
1878
+ */
1879
+ "graphAndKind"
1880
+ /**
1881
+ * Prefix index keys with `graph_id` only.
1882
+ */
1883
+ | "graph"
1884
+ /**
1885
+ * Do not prefix index keys with TypeGraph system columns.
1886
+ */
1887
+ | "none";
1888
+ type IndexWhereOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn";
1889
+ type IndexWhereExpression = Readonly<{
1890
+ __type: "index_where_and";
1891
+ predicates: readonly IndexWhereExpression[];
1892
+ }> | Readonly<{
1893
+ __type: "index_where_or";
1894
+ predicates: readonly IndexWhereExpression[];
1895
+ }> | Readonly<{
1896
+ __type: "index_where_not";
1897
+ predicate: IndexWhereExpression;
1898
+ }> | Readonly<{
1899
+ __type: "index_where_comparison";
1900
+ left: IndexWhereOperand;
1901
+ op: IndexWhereOp;
1902
+ right: IndexWhereLiteral | readonly IndexWhereLiteral[];
1903
+ }> | Readonly<{
1904
+ __type: "index_where_null_check";
1905
+ operand: IndexWhereOperand;
1906
+ op: NullCheckOp;
1907
+ }>;
1908
+ type IndexWhereOperand = Readonly<{
1909
+ __type: "index_operand_system";
1910
+ column: SystemColumnName;
1911
+ valueType: ValueType | undefined;
1912
+ }> | Readonly<{
1913
+ __type: "index_operand_prop";
1914
+ field: string;
1915
+ valueType: ValueType | undefined;
1916
+ }>;
1917
+ type IndexWhereLiteral = Readonly<{
1918
+ __type: "index_where_literal";
1919
+ value: string | number | boolean;
1920
+ valueType: ValueType;
1921
+ }>;
1922
+ type IndexWhereComparableValue<T> = NonNullable<T> extends string ? string : NonNullable<T> extends number ? number : NonNullable<T> extends boolean ? boolean : NonNullable<T> extends Date ? Date | string : never;
1923
+ type IndexWhereFieldBuilder<T> = Readonly<{
1924
+ eq: (value: IndexWhereComparableValue<T>) => IndexWhereExpression;
1925
+ neq: (value: IndexWhereComparableValue<T>) => IndexWhereExpression;
1926
+ gt: (value: IndexWhereComparableValue<T>) => IndexWhereExpression;
1927
+ gte: (value: IndexWhereComparableValue<T>) => IndexWhereExpression;
1928
+ lt: (value: IndexWhereComparableValue<T>) => IndexWhereExpression;
1929
+ lte: (value: IndexWhereComparableValue<T>) => IndexWhereExpression;
1930
+ in: (values: readonly IndexWhereComparableValue<T>[]) => IndexWhereExpression;
1931
+ notIn: (values: readonly IndexWhereComparableValue<T>[]) => IndexWhereExpression;
1932
+ isNull: () => IndexWhereExpression;
1933
+ isNotNull: () => IndexWhereExpression;
1934
+ }>;
1935
+ type NodeIndexWhereBuilder<N extends NodeType> = Readonly<{
1936
+ graphId: IndexWhereFieldBuilder<string>;
1937
+ kind: IndexWhereFieldBuilder<string>;
1938
+ id: IndexWhereFieldBuilder<string>;
1939
+ deletedAt: IndexWhereFieldBuilder<string | undefined>;
1940
+ validFrom: IndexWhereFieldBuilder<string | undefined>;
1941
+ validTo: IndexWhereFieldBuilder<string | undefined>;
1942
+ createdAt: IndexWhereFieldBuilder<string>;
1943
+ updatedAt: IndexWhereFieldBuilder<string>;
1944
+ version: IndexWhereFieldBuilder<number>;
1945
+ } & {
1946
+ [K in keyof z.infer<N["schema"]>]-?: IndexWhereFieldBuilder<z.infer<N["schema"]>[K]>;
1947
+ }>;
1948
+ type EdgeIndexWhereBuilder<E extends AnyEdgeType> = Readonly<{
1949
+ graphId: IndexWhereFieldBuilder<string>;
1950
+ kind: IndexWhereFieldBuilder<string>;
1951
+ id: IndexWhereFieldBuilder<string>;
1952
+ fromKind: IndexWhereFieldBuilder<string>;
1953
+ fromId: IndexWhereFieldBuilder<string>;
1954
+ toKind: IndexWhereFieldBuilder<string>;
1955
+ toId: IndexWhereFieldBuilder<string>;
1956
+ deletedAt: IndexWhereFieldBuilder<string | undefined>;
1957
+ validFrom: IndexWhereFieldBuilder<string | undefined>;
1958
+ validTo: IndexWhereFieldBuilder<string | undefined>;
1959
+ createdAt: IndexWhereFieldBuilder<string>;
1960
+ updatedAt: IndexWhereFieldBuilder<string>;
1961
+ } & {
1962
+ [K in keyof z.infer<E["schema"]>]-?: IndexWhereFieldBuilder<z.infer<E["schema"]>[K]>;
1963
+ }>;
1964
+ type IndexWhereInput<Builder> = IndexWhereExpression | ((where: Builder) => IndexWhereExpression);
1965
+ type NonEmptyJsonPointerFor<T> = Exclude<JsonPointerFor<T>, "">;
1966
+ type NonEmptyJsonPointerSegmentsFor<T> = Exclude<JsonPointerSegmentsFor<T>, readonly []>;
1967
+ type IndexFieldInput<T> = (keyof T & string) | NonEmptyJsonPointerFor<T> | NonEmptyJsonPointerSegmentsFor<T> | JsonPointer;
1968
+ type NodeIndexConfig<N extends NodeType> = Readonly<{
1969
+ fields: readonly [
1970
+ IndexFieldInput<z.infer<N["schema"]>>,
1971
+ ...IndexFieldInput<z.infer<N["schema"]>>[]
1972
+ ];
1973
+ coveringFields?: readonly IndexFieldInput<z.infer<N["schema"]>>[] | undefined;
1974
+ unique?: boolean | undefined;
1975
+ name?: string | undefined;
1976
+ scope?: IndexScope | undefined;
1977
+ where?: IndexWhereInput<NodeIndexWhereBuilder<N>> | undefined;
1978
+ }>;
1979
+ type EdgeIndexDirection = "out" | "in" | "none";
1980
+ type EdgeIndexConfig<E extends AnyEdgeType> = Readonly<{
1981
+ fields: readonly [
1982
+ IndexFieldInput<z.infer<E["schema"]>>,
1983
+ ...IndexFieldInput<z.infer<E["schema"]>>[]
1984
+ ];
1985
+ coveringFields?: readonly IndexFieldInput<z.infer<E["schema"]>>[] | undefined;
1986
+ unique?: boolean | undefined;
1987
+ name?: string | undefined;
1988
+ scope?: IndexScope | undefined;
1989
+ /**
1990
+ * Optional direction hint to prefix edge indexes with the join key that
1991
+ * TypeGraph traversal queries use (`from_id` for out, `to_id` for in).
1992
+ */
1993
+ direction?: EdgeIndexDirection | undefined;
1994
+ where?: IndexWhereInput<EdgeIndexWhereBuilder<E>> | undefined;
1995
+ }>;
1996
+ /**
1997
+ * Where an index declaration originated.
1998
+ *
1999
+ * - `compile-time`: declared via `defineNodeIndex` / `defineEdgeIndex` and
2000
+ * threaded through `defineGraph({ indexes })`. This is the default and is
2001
+ * omitted from the canonical schema document so legacy graphs hash
2002
+ * byte-identically.
2003
+ * - `runtime`: produced by a graph extension. Always emitted explicitly
2004
+ * so the loader can re-route the declaration through the extension
2005
+ * compiler on restart.
2006
+ */
2007
+ type IndexOrigin = "compile-time" | "runtime";
2008
+ /**
2009
+ * Common shape shared by node and edge index declarations.
2010
+ *
2011
+ * `IndexDeclaration` is the canonical, JSON-serializable representation of
2012
+ * an index that flows through `GraphDef.indexes` and
2013
+ * `SerializedSchema.indexes`. It carries everything the DDL compiler and
2014
+ * the Drizzle schema factories need to generate index SQL — the same
2015
+ * value can come from a typed builder (`defineNodeIndex` /
2016
+ * `defineEdgeIndex`) or be reconstructed from a graph extension on
2017
+ * restart.
2018
+ */
2019
+ type IndexDeclarationBase = Readonly<{
2020
+ /** Unique index name (used in DDL and as the diffing identity key). */
2021
+ name: string;
2022
+ /**
2023
+ * Where this declaration originated.
2024
+ *
2025
+ * `undefined` is the canonical representation of `"compile-time"` —
2026
+ * the default origin is omitted from the serialized form so legacy
2027
+ * graphs (no `indexes` slice) hash byte-identically with new graphs
2028
+ * that declare only compile-time indexes.
2029
+ */
2030
+ origin?: IndexOrigin;
2031
+ fields: readonly JsonPointer[];
2032
+ fieldValueTypes: readonly (ValueType | undefined)[];
2033
+ coveringFields: readonly JsonPointer[];
2034
+ coveringFieldValueTypes: readonly (ValueType | undefined)[];
2035
+ unique: boolean;
2036
+ scope: IndexScope;
2037
+ where: IndexWhereExpression | undefined;
2038
+ }>;
2039
+ type NodeIndexDeclaration = IndexDeclarationBase & Readonly<{
2040
+ entity: "node";
2041
+ kind: string;
2042
+ }>;
2043
+ type EdgeIndexDeclaration = IndexDeclarationBase & Readonly<{
2044
+ entity: "edge";
2045
+ kind: string;
2046
+ direction: EdgeIndexDirection;
2047
+ }>;
2048
+ /**
2049
+ * Distance metric for vector similarity. Mirrors `EmbeddingMetric` from
2050
+ * `core/embedding.ts` (re-exported here as part of the index surface).
2051
+ */
2052
+ type VectorIndexMetric = "cosine" | "l2" | "inner_product";
2053
+ /**
2054
+ * Vector index implementation. `none` is a declarative opt-out: the
2055
+ * declaration carries shape metadata for tooling but `materializeIndexes`
2056
+ * skips the DDL.
2057
+ */
2058
+ type VectorIndexImplementation = "hnsw" | "ivfflat" | "none";
2059
+ /**
2060
+ * Vector-index parameters. Concrete defaults are applied at the
2061
+ * `embedding(...)` brand boundary; this carries them onto the
2062
+ * declaration so the materializer / signature / drift detection have
2063
+ * everything they need without re-resolving from the brand.
2064
+ */
2065
+ type VectorIndexParams = Readonly<{
2066
+ /** HNSW: max connections per layer. */
2067
+ m: number;
2068
+ /** HNSW: build-time search depth. */
2069
+ efConstruction: number;
2070
+ /** IVFFlat: number of inverted lists. `undefined` when not IVFFlat. */
2071
+ lists: number | undefined;
2072
+ }>;
2073
+ /**
2074
+ * Vector index declaration. Auto-derived from `embedding()` brands at
2075
+ * `defineGraph()` time and explicitly buildable via `defineVectorIndex`.
2076
+ *
2077
+ * Identity key is `(kind, fieldPath)` — v1 allows at most one vector
2078
+ * index per (kind, field) pair. The `name` field is generated
2079
+ * deterministically from this tuple plus the metric so consumers don't
2080
+ * accidentally collide vector index names with relational indexes.
2081
+ *
2082
+ * `unique` / `scope` / `where` from the relational base are NOT
2083
+ * supported on vector — pgvector / sqlite-vec don't implement them.
2084
+ */
2085
+ type VectorIndexDeclaration = Readonly<{
2086
+ entity: "vector";
2087
+ /** Index name (also the physical identity key in the materialization status table). */
2088
+ name: string;
2089
+ origin?: IndexOrigin;
2090
+ /** Node kind the embedding lives on. */
2091
+ kind: string;
2092
+ /** JSON-pointer-style field path for the embedding inside the node's props. */
2093
+ fieldPath: string;
2094
+ /** Embedding dimensionality. */
2095
+ dimensions: number;
2096
+ /** Distance metric. */
2097
+ metric: VectorIndexMetric;
2098
+ /** Index implementation. */
2099
+ indexType: VectorIndexImplementation;
2100
+ /** Concrete index parameters. */
2101
+ indexParams: VectorIndexParams;
2102
+ }>;
2103
+ /**
2104
+ * Relational subset of `IndexDeclaration` — the variants that emit
2105
+ * `CREATE INDEX` DDL via `generateIndexDDL`. Used to narrow input
2106
+ * types in the relational DDL / serializer / migration code paths
2107
+ * that don't apply to vector indexes (which use a different
2108
+ * materialization primitive on the backend).
2109
+ */
2110
+ type RelationalIndexDeclaration = NodeIndexDeclaration | EdgeIndexDeclaration;
2111
+ /**
2112
+ * A serializable index declaration that flows through `GraphDef.indexes`
2113
+ * and `SerializedSchema.indexes`.
2114
+ *
2115
+ * Discriminated by `entity`. Everything is JSON round-trippable so a
2116
+ * declaration produced by `defineNodeIndex` and a declaration
2117
+ * reconstructed from a stored schema document compile to byte-identical
2118
+ * SQL.
2119
+ */
2120
+ type IndexDeclaration = RelationalIndexDeclaration | VectorIndexDeclaration;
2121
+ type SystemColumnName = "graph_id" | "kind" | "id" | "from_kind" | "from_id" | "to_kind" | "to_id" | "deleted_at" | "valid_from" | "valid_to" | "created_at" | "updated_at" | "version";
2122
+
2123
+ export { type JsonPointerFor as $, type AggregateExpr as A, type BackendCapabilities as B, type FieldRef as C, type ComparisonOp as D, type EdgeIndexConfig as E, type FulltextStrategy as F, type GraphBackend as G, type AggregateComparisonPredicate as H, type IndexDeclaration as I, type JsonPointer as J, type CommitSchemaVersionExpected as K, type CommitSchemaVersionParams as L, type MetaEdge as M, type NodeIndexConfig as N, type OntologyRelation as O, DEFAULT_SQL_SCHEMA as P, type QueryAst as Q, type RelationalIndexDeclaration as R, type SerializedNodeDef as S, type DeleteFulltextBatchParams as T, type FulltextBatchRow as U, type VectorIndexDeclaration as V, type FulltextCapabilities as W, type FulltextQueryMode as X, type FulltextSearchParams as Y, type FulltextSearchResult as Z, type HybridFusionOptions as _, type EdgeIndexDeclaration as a, type JsonPointerInput as a0, type JsonPointerSegment as a1, type JsonPointerSegments as a2, type JsonPointerSegmentsFor as a3, MAX_JSON_POINTER_DEPTH as a4, type MetaEdgeProperties as a5, type OrderSpec as a6, type ParameterRef as a7, type ResolveJsonPointer as a8, type ResolveJsonPointerSegments as a9, type NodeRow as aA, type SelectiveField as aB, type ComposableQuery as aC, type SetOperationType as aD, type SetOperation as aE, type VectorMetric as aF, type SetActiveVersionParams as aa, type SortDirection as ab, type SqlSchema as ac, type SqlTableNames as ad, type TransactionBackend as ae, type TraversalExpansion as af, type UpsertFulltextBatchParams as ag, type VectorCapabilities as ah, createSqlSchema as ai, fts5Strategy as aj, isMetaEdge as ak, joinJsonPointers as al, jsonPointer as am, normalizeJsonPointer as an, parseJsonPointer as ao, tsvectorStrategy as ap, type ValueType as aq, type PredicateExpression as ar, type VectorMetricType as as, type Traversal as at, type NodePredicate as au, type ProjectedField as av, type GroupBySpec as aw, type RecursiveCyclePolicy as ax, type TraversalDirection as ay, type EdgeRow as az, type NodeIndexDeclaration as b, type IndexWhereExpression as c, type SerializedEdgeDef as d, type SerializedMetaEdge as e, type SerializedOntologyRelation as f, type SerializedClosures as g, type SerializedSchema as h, type SchemaHash as i, type JsonSchema as j, type SerializedOntology as k, type SerializedUniqueConstraint as l, type SqlDialect as m, type EdgeIndexDirection as n, type EdgeIndexWhereBuilder as o, type IndexOrigin as p, type IndexScope as q, type IndexWhereFieldBuilder as r, type IndexWhereInput as s, type NodeIndexWhereBuilder as t, type SystemColumnName as u, type VectorIndexImplementation as v, type VectorIndexMetric as w, type VectorIndexParams as x, type SchemaVersionRow as y, type InferenceType as z };