@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.
- package/dist/backend/postgres/index.cjs +178 -55
- package/dist/backend/postgres/index.cjs.map +1 -1
- package/dist/backend/postgres/index.d.cts +6 -7
- package/dist/backend/postgres/index.d.ts +6 -7
- package/dist/backend/postgres/index.js +151 -28
- package/dist/backend/postgres/index.js.map +1 -1
- package/dist/backend/sqlite/index.cjs +19 -17
- package/dist/backend/sqlite/index.d.cts +6 -7
- package/dist/backend/sqlite/index.d.ts +6 -7
- package/dist/backend/sqlite/index.js +9 -7
- package/dist/backend/sqlite/libsql.cjs +12 -10
- package/dist/backend/sqlite/libsql.cjs.map +1 -1
- package/dist/backend/sqlite/libsql.d.cts +4 -5
- package/dist/backend/sqlite/libsql.d.ts +4 -5
- package/dist/backend/sqlite/libsql.js +9 -7
- package/dist/backend/sqlite/libsql.js.map +1 -1
- package/dist/backend/sqlite/local.cjs +14 -12
- package/dist/backend/sqlite/local.cjs.map +1 -1
- package/dist/backend/sqlite/local.d.cts +4 -5
- package/dist/backend/sqlite/local.d.ts +4 -5
- package/dist/backend/sqlite/local.js +9 -7
- package/dist/backend/sqlite/local.js.map +1 -1
- package/dist/chunk-4BOWVUGQ.js +2029 -0
- package/dist/chunk-4BOWVUGQ.js.map +1 -0
- package/dist/{chunk-SUHW2UYL.cjs → chunk-7CDXX3QZ.cjs} +2 -2
- package/dist/chunk-7CDXX3QZ.cjs.map +1 -0
- package/dist/chunk-7V335GHG.cjs +112 -0
- package/dist/chunk-7V335GHG.cjs.map +1 -0
- package/dist/chunk-7W3KAMVQ.cjs +2678 -0
- package/dist/chunk-7W3KAMVQ.cjs.map +1 -0
- package/dist/chunk-CTHNVU6K.cjs +551 -0
- package/dist/chunk-CTHNVU6K.cjs.map +1 -0
- package/dist/chunk-D2GO3RBL.cjs +12 -0
- package/dist/chunk-D2GO3RBL.cjs.map +1 -0
- package/dist/{chunk-WFMTAEEN.js → chunk-DOTEN2FG.js} +81 -7
- package/dist/chunk-DOTEN2FG.js.map +1 -0
- package/dist/chunk-E5JZSEGJ.cjs +301 -0
- package/dist/chunk-E5JZSEGJ.cjs.map +1 -0
- package/dist/chunk-EG6TJ3I5.js +286 -0
- package/dist/chunk-EG6TJ3I5.js.map +1 -0
- package/dist/chunk-EJCDOA37.js +537 -0
- package/dist/chunk-EJCDOA37.js.map +1 -0
- package/dist/{chunk-UVZHTBZ5.cjs → chunk-EK6RJ373.cjs} +7 -150
- package/dist/chunk-EK6RJ373.cjs.map +1 -0
- package/dist/{chunk-GUTQTMOV.js → chunk-FPCOUJSL.js} +2 -2
- package/dist/chunk-FPCOUJSL.js.map +1 -0
- package/dist/{chunk-3JK66E3I.cjs → chunk-JTI5WT4P.cjs} +630 -59
- package/dist/chunk-JTI5WT4P.cjs.map +1 -0
- package/dist/chunk-LVCSL6A3.js +2626 -0
- package/dist/chunk-LVCSL6A3.js.map +1 -0
- package/dist/chunk-NHQWXSTS.js +10 -0
- package/dist/chunk-NHQWXSTS.js.map +1 -0
- package/dist/chunk-NZ5PMBTG.js +105 -0
- package/dist/chunk-NZ5PMBTG.js.map +1 -0
- package/dist/{chunk-5HVDOPZU.cjs → chunk-O2P3KAUT.cjs} +416 -93
- package/dist/chunk-O2P3KAUT.cjs.map +1 -0
- package/dist/{chunk-QOLTW7OZ.js → chunk-OJ6IQVZG.js} +151 -13
- package/dist/chunk-OJ6IQVZG.js.map +1 -0
- package/dist/{chunk-EYELZHKY.js → chunk-OOS2RKRH.js} +5 -140
- package/dist/chunk-OOS2RKRH.js.map +1 -0
- package/dist/chunk-RCAJZG67.cjs +2069 -0
- package/dist/chunk-RCAJZG67.cjs.map +1 -0
- package/dist/{chunk-O5PST6TB.cjs → chunk-W5MTHMTE.cjs} +83 -6
- package/dist/chunk-W5MTHMTE.cjs.map +1 -0
- package/dist/{chunk-EY4LBX3F.js → chunk-WI5VRP3X.js} +337 -26
- package/dist/chunk-WI5VRP3X.js.map +1 -0
- package/dist/chunk-WVQXAFP3.js +79 -0
- package/dist/chunk-WVQXAFP3.js.map +1 -0
- package/dist/chunk-X3244EKP.cjs +84 -0
- package/dist/chunk-X3244EKP.cjs.map +1 -0
- package/dist/{chunk-753F33CV.js → chunk-YZZBDCLV.js} +617 -44
- package/dist/chunk-YZZBDCLV.js.map +1 -0
- package/dist/{chunk-OVJ2BE5Q.cjs → chunk-ZEMNF3QK.cjs} +171 -33
- package/dist/chunk-ZEMNF3QK.cjs.map +1 -0
- package/dist/{ddl-B_H8JM-E.d.cts → ddl-B2jjLjpR.d.cts} +762 -99
- package/dist/{ddl-1tFIvt9V.d.ts → ddl-DpaeAKPp.d.ts} +762 -99
- package/dist/extension-types-D07e_NTw.d.cts +543 -0
- package/dist/extension-types-D07e_NTw.d.ts +543 -0
- package/dist/graph-extension/index.cjs +71 -0
- package/dist/graph-extension/index.cjs.map +1 -0
- package/dist/graph-extension/index.d.cts +278 -0
- package/dist/graph-extension/index.d.ts +278 -0
- package/dist/graph-extension/index.js +6 -0
- package/dist/graph-extension/index.js.map +1 -0
- package/dist/{index-DXkEXpNz.d.ts → index-CT6nvtxL.d.cts} +114 -5
- package/dist/{index-DXkEXpNz.d.cts → index-DQheiVQV.d.ts} +114 -5
- package/dist/index.cjs +2672 -901
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -10
- package/dist/index.d.ts +29 -10
- package/dist/index.js +2248 -598
- package/dist/index.js.map +1 -1
- package/dist/indexes/index.cjs +25 -23
- package/dist/indexes/index.d.cts +40 -22
- package/dist/indexes/index.d.ts +40 -22
- package/dist/indexes/index.js +5 -3
- package/dist/interchange/index.cjs +8 -7
- package/dist/interchange/index.cjs.map +1 -1
- package/dist/interchange/index.d.cts +5 -4
- package/dist/interchange/index.d.ts +5 -4
- package/dist/interchange/index.js +3 -2
- package/dist/interchange/index.js.map +1 -1
- package/dist/{manager-nIhmttD-.d.ts → manager-BKaPQbns.d.ts} +189 -6
- package/dist/{manager-Vkz28eAC.d.cts → manager-BpjBW1JK.d.cts} +189 -6
- package/dist/materialize-indexes-BB9N5uQl.d.cts +68 -0
- package/dist/materialize-indexes-BYpU2RKh.d.ts +68 -0
- package/dist/profiler/index.cjs +10 -8
- package/dist/profiler/index.cjs.map +1 -1
- package/dist/profiler/index.d.cts +8 -7
- package/dist/profiler/index.d.ts +8 -7
- package/dist/profiler/index.js +3 -1
- package/dist/profiler/index.js.map +1 -1
- package/dist/schema/index.cjs +43 -22
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +17 -8
- package/dist/schema/index.d.ts +17 -8
- package/dist/schema/index.js +9 -4
- package/dist/schema/index.js.map +1 -1
- package/dist/{sqlite-D0aceIe0.d.cts → sqlite-CU3j6rc7.d.ts} +837 -120
- package/dist/{sqlite-SUxbZqfy.d.ts → sqlite-Myo8e3Lr.d.cts} +837 -120
- package/dist/{store-U3i2tUch.d.ts → store-BAGuOHDh.d.cts} +659 -23
- package/dist/{store-CpvwTMxV.d.cts → store-De98Lod4.d.ts} +659 -23
- package/dist/types--0EslBx5.d.cts +2123 -0
- package/dist/{types-qYFZ9SqD.d.ts → types-BLmJq4wI.d.ts} +3 -2
- package/dist/types-BNWYZ-0-.d.ts +2123 -0
- package/dist/{types-yH4_p0XB.d.cts → types-CYga3lZp.d.cts} +3 -2
- package/dist/where-CluR73rs.d.ts +11 -0
- package/dist/where-m1uWsdua.d.cts +11 -0
- package/package.json +33 -73
- package/dist/ast-C8S37w1A.d.ts +0 -497
- package/dist/ast-dgLhLOg0.d.cts +0 -497
- package/dist/chunk-3JK66E3I.cjs.map +0 -1
- package/dist/chunk-3PPEHLGK.js +0 -1116
- package/dist/chunk-3PPEHLGK.js.map +0 -1
- package/dist/chunk-5HVDOPZU.cjs.map +0 -1
- package/dist/chunk-753F33CV.js.map +0 -1
- package/dist/chunk-EY4LBX3F.js.map +0 -1
- package/dist/chunk-EYELZHKY.js.map +0 -1
- package/dist/chunk-GFGVREHH.js +0 -1381
- package/dist/chunk-GFGVREHH.js.map +0 -1
- package/dist/chunk-GUTQTMOV.js.map +0 -1
- package/dist/chunk-LBORRUNJ.js +0 -135
- package/dist/chunk-LBORRUNJ.js.map +0 -1
- package/dist/chunk-O5PST6TB.cjs.map +0 -1
- package/dist/chunk-OLROXS2S.cjs +0 -147
- package/dist/chunk-OLROXS2S.cjs.map +0 -1
- package/dist/chunk-OVJ2BE5Q.cjs.map +0 -1
- package/dist/chunk-PAUN562Y.cjs +0 -1417
- package/dist/chunk-PAUN562Y.cjs.map +0 -1
- package/dist/chunk-PEE4EWXZ.cjs +0 -1131
- package/dist/chunk-PEE4EWXZ.cjs.map +0 -1
- package/dist/chunk-QOLTW7OZ.js.map +0 -1
- package/dist/chunk-SUHW2UYL.cjs.map +0 -1
- package/dist/chunk-UVZHTBZ5.cjs.map +0 -1
- package/dist/chunk-WFMTAEEN.js.map +0 -1
- package/dist/types-C-zfYDJB.d.ts +0 -159
- package/dist/types-CQx4iW5Y.d.cts +0 -159
- package/dist/types-Qk2l3IkQ.d.cts +0 -1254
- 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 };
|