@xwxfox/foxdb 0.0.1 → 0.0.4
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/index.d.mts +768 -137
- package/dist/index.mjs +23 -19
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { TObject,
|
|
1
|
+
import { TSchema as TSchema6 } from "typebox";
|
|
2
|
+
import { TObject as TObject2, TArray, TSchema as TSchema2, TProperties, TOptional as TOptional2, Static } from "typebox";
|
|
3
|
+
import { TObject, TString, TNumber, TInteger, TBoolean, TLiteral, TSchema, TOptional } from "typebox";
|
|
3
4
|
/** @category Schema */
|
|
4
5
|
type TScalarSchema = TString | TNumber | TInteger | TBoolean | TLiteral<string> | TLiteral<number> | TLiteral<boolean>;
|
|
5
6
|
/**
|
|
@@ -14,11 +15,24 @@ interface ColumnRef<
|
|
|
14
15
|
readonly name: N;
|
|
15
16
|
readonly schema: S;
|
|
16
17
|
}
|
|
18
|
+
type UnwrapOptionalSchema<S extends TSchema> = S extends TOptional<infer U> ? U : S;
|
|
19
|
+
type IsScalarSchema<S extends TSchema> = S extends TString ? true : S extends TNumber ? true : S extends TInteger ? true : S extends TBoolean ? true : S extends TLiteral<string | number | boolean> ? true : false;
|
|
20
|
+
type NestedColumnKeys<T extends TSchema & {
|
|
21
|
+
properties: Record<string, TSchema>;
|
|
22
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptionalSchema<T["properties"][K]> extends TObject<infer P> ? { [K2 in keyof P & string] : IsScalarSchema<UnwrapOptionalSchema<P[K2]>> extends true ? `${K}__${K2}` : UnwrapOptionalSchema<P[K2]> extends TObject<infer P2> ? { [K3 in keyof P2 & string] : IsScalarSchema<UnwrapOptionalSchema<P2[K3]>> extends true ? `${K}__${K2}__${K3}` : never }[keyof P2 & string] : never }[keyof P & string] : never }[keyof T["properties"] & string];
|
|
23
|
+
type NestedColumnRef<
|
|
24
|
+
T extends TSchema & {
|
|
25
|
+
properties: Record<string, TSchema>;
|
|
26
|
+
},
|
|
27
|
+
N extends string
|
|
28
|
+
> = N extends `${infer K}__${infer K2}__${infer K3}` ? K extends keyof T["properties"] & string ? UnwrapOptionalSchema<T["properties"][K]> extends TObject<infer P> ? K2 extends keyof P & string ? UnwrapOptionalSchema<P[K2]> extends TObject<infer P2> ? K3 extends keyof P2 & string ? UnwrapOptionalSchema<P2[K3]> extends infer U ? U extends TScalarSchema ? ColumnRef<N, U> : never : never : never : never : never : never : never : N extends `${infer K}__${infer K2}` ? K extends keyof T["properties"] & string ? UnwrapOptionalSchema<T["properties"][K]> extends TObject<infer P> ? K2 extends keyof P & string ? UnwrapOptionalSchema<P[K2]> extends infer U ? U extends TScalarSchema ? ColumnRef<N, U> : never : never : never : never : never : never;
|
|
17
29
|
/**
|
|
18
30
|
* map of scalar columns to their typed refs
|
|
19
31
|
* @category Schema
|
|
20
32
|
*/
|
|
21
|
-
type ColumnRefs<T extends
|
|
33
|
+
type ColumnRefs<T extends TSchema & {
|
|
34
|
+
properties: Record<string, TSchema>;
|
|
35
|
+
}> = { readonly [K in keyof T["properties"] as T["properties"][K] extends TScalarSchema ? K : never] : T["properties"][K] extends TScalarSchema ? ColumnRef<K & string, T["properties"][K]> : never } & { readonly [K in NestedColumnKeys<T>] : NestedColumnRef<T, K> };
|
|
22
36
|
/**
|
|
23
37
|
* foxdb/src/typed-relation.ts
|
|
24
38
|
* Runtime + compile-time representation of a single relation.
|
|
@@ -39,20 +53,12 @@ interface TypedRelation<
|
|
|
39
53
|
kind: K;
|
|
40
54
|
as: A;
|
|
41
55
|
}
|
|
42
|
-
import { Database,
|
|
56
|
+
import { Database, Statement } from "bun:sqlite";
|
|
43
57
|
/**
|
|
44
58
|
* prepared sqlite statement
|
|
45
59
|
* @category Database
|
|
46
60
|
*/
|
|
47
|
-
|
|
48
|
-
run(...params: SQLQueryBindings[]): {
|
|
49
|
-
changes: number;
|
|
50
|
-
lastInsertRowid: number | bigint;
|
|
51
|
-
};
|
|
52
|
-
all(...params: SQLQueryBindings[]): unknown[];
|
|
53
|
-
get(...params: SQLQueryBindings[]): unknown;
|
|
54
|
-
finalize(): void;
|
|
55
|
-
}
|
|
61
|
+
type BunStatement = Statement;
|
|
56
62
|
/** @category Database */
|
|
57
63
|
interface DatabaseOptions {
|
|
58
64
|
/** Path to the SQLite file. Defaults to ":memory:" */
|
|
@@ -75,6 +81,8 @@ interface DatabaseOptions {
|
|
|
75
81
|
synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA";
|
|
76
82
|
/** PRAGMA mmap_size in bytes. 0 disables. Defaults to 256 MB. */
|
|
77
83
|
mmapSize?: number;
|
|
84
|
+
/** PRAGMA auto_vacuum level. "incremental" | "full" | false. Defaults to false. */
|
|
85
|
+
autoVacuum?: "incremental" | "full" | false;
|
|
78
86
|
}
|
|
79
87
|
/**
|
|
80
88
|
* sqlite database with statement caching and pragma tuning
|
|
@@ -83,6 +91,8 @@ interface DatabaseOptions {
|
|
|
83
91
|
declare class BunDatabase {
|
|
84
92
|
/** underlying bun:sqlite database */
|
|
85
93
|
readonly db: Database;
|
|
94
|
+
/** scheduler for table maintenance tasks */
|
|
95
|
+
readonly scheduler;
|
|
86
96
|
constructor(opts?: DatabaseOptions);
|
|
87
97
|
/** execute ddl (create table, index, etc) */
|
|
88
98
|
exec(sql: string): void;
|
|
@@ -94,46 +104,192 @@ declare class BunDatabase {
|
|
|
94
104
|
private readonly _stmtCache;
|
|
95
105
|
/** get or compile a prepared statement */
|
|
96
106
|
prepare(sql: string): BunStatement;
|
|
107
|
+
/** set synchronous pragma for bulk load or normal operation */
|
|
108
|
+
setSynchronous(mode: "OFF" | "NORMAL" | "FULL" | "EXTRA"): void;
|
|
97
109
|
/** clear the statement cache */
|
|
98
110
|
clearCache(): void;
|
|
99
111
|
}
|
|
112
|
+
type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
113
|
+
[key: string]: JsonValue;
|
|
114
|
+
};
|
|
115
|
+
type DBBinary = Uint8Array;
|
|
116
|
+
type DBScalar = string | number | boolean | bigint | null;
|
|
117
|
+
type DBValue = DBScalar | JsonValue | DBBinary;
|
|
118
|
+
type DBRow = Record<string, DBValue | undefined>;
|
|
119
|
+
/** @internal */
|
|
120
|
+
type UnwrapOptional<T> = T extends TOptional2<infer U> ? U : T;
|
|
121
|
+
/** @internal */
|
|
122
|
+
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
123
|
+
/** @internal */
|
|
124
|
+
type IsOptionalKey<
|
|
125
|
+
O,
|
|
126
|
+
K extends keyof O
|
|
127
|
+
> = {} extends Pick<O, K> ? true : false;
|
|
128
|
+
/** @internal */
|
|
129
|
+
type MergePath<
|
|
130
|
+
O,
|
|
131
|
+
P extends string
|
|
132
|
+
> = P extends `${infer K}.${infer Rest}` ? K extends keyof O ? IsOptionalKey<O, K> extends true ? { [k in K]? : MergePath<NonNullable<O[K]>, Rest> } : { [k in K] : MergePath<NonNullable<O[K]>, Rest> } : never : P extends keyof O ? IsOptionalKey<O, P> extends true ? { [k in P]? : O[P] } : { [k in P] : O[P] } : never;
|
|
133
|
+
/** @internal */
|
|
134
|
+
type SelectShape<
|
|
135
|
+
T extends TSchema2 & {
|
|
136
|
+
properties: Record<string, TSchema2>;
|
|
137
|
+
},
|
|
138
|
+
S extends readonly string[]
|
|
139
|
+
> = UnionToIntersection<S[number] extends infer P ? P extends string ? MergePath<Infer<T>, P> : never : never>;
|
|
140
|
+
/**
|
|
141
|
+
* scalar values sqlite can store natively
|
|
142
|
+
* @category Advanced
|
|
143
|
+
*/
|
|
144
|
+
type SqliteScalar = string | number | boolean | null | bigint;
|
|
100
145
|
/**
|
|
101
146
|
* @internal
|
|
102
147
|
* @category Advanced
|
|
103
148
|
*/
|
|
104
|
-
type ScalarProperties<P extends TProperties> = { [K in keyof P as P[K] extends TArray<infer _> ? never : K] : P[K] };
|
|
149
|
+
type ScalarProperties<P extends TProperties> = { [K in keyof P as P[K] extends TArray<infer _> ? never : P[K] extends TObject2 ? never : K] : P[K] };
|
|
105
150
|
/**
|
|
106
151
|
* @internal
|
|
107
152
|
* @category Advanced
|
|
108
153
|
*/
|
|
109
|
-
type ArrayOfObjectProperties<P extends TProperties> = { [K in keyof P as P[K] extends TArray<
|
|
154
|
+
type ArrayOfObjectProperties<P extends TProperties> = { [K in keyof P as P[K] extends TArray<{
|
|
155
|
+
properties: Record<string, TSchema2>;
|
|
156
|
+
}> ? K : never] : P[K] extends TArray<infer Item> ? Item : never };
|
|
110
157
|
/**
|
|
111
158
|
* column names that are scalar (not arrays or nested objects)
|
|
112
159
|
* @category Query Types
|
|
113
160
|
*/
|
|
114
|
-
type ScalarKeys<T extends
|
|
161
|
+
type ScalarKeys<T extends TSchema2 & {
|
|
162
|
+
properties: Record<string, TSchema2>;
|
|
163
|
+
}> = keyof ScalarProperties<T["properties"]> & string;
|
|
164
|
+
/** @internal */
|
|
165
|
+
type ObjectKeys<T extends TSchema2 & {
|
|
166
|
+
properties: Record<string, TSchema2>;
|
|
167
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends TObject2 ? K : never }[keyof T["properties"] & string];
|
|
168
|
+
/** @internal */
|
|
169
|
+
type PrimitiveArrayKeys<T extends TSchema2 & {
|
|
170
|
+
properties: Record<string, TSchema2>;
|
|
171
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends TArray<infer Item> ? Item extends TScalarSchema ? K : never : never }[keyof T["properties"] & string];
|
|
115
172
|
/**
|
|
116
173
|
* @internal
|
|
117
174
|
* @category Query Types
|
|
118
175
|
*/
|
|
119
|
-
type SubTableKeys<T extends
|
|
176
|
+
type SubTableKeys<T extends TSchema2 & {
|
|
177
|
+
properties: Record<string, TSchema2>;
|
|
178
|
+
}> = keyof ArrayOfObjectProperties<T["properties"]> & string;
|
|
120
179
|
/**
|
|
121
180
|
* @internal
|
|
122
181
|
* @category Advanced
|
|
123
182
|
*/
|
|
124
|
-
type SubTableScalarPath<T extends
|
|
183
|
+
type SubTableScalarPath<T extends TSchema2 & {
|
|
184
|
+
properties: Record<string, TSchema2>;
|
|
185
|
+
}> = { [K in SubTableKeys<T>] : T["properties"][K] extends TArray<infer Item> ? Item extends {
|
|
186
|
+
properties: Record<string, TSchema2>;
|
|
187
|
+
} ? `${K}.${ScalarKeys<Item>}` : never : never }[SubTableKeys<T>];
|
|
125
188
|
/**
|
|
126
189
|
* @internal
|
|
127
190
|
* @category Advanced
|
|
128
191
|
*/
|
|
129
|
-
type ScalarPath<T extends
|
|
192
|
+
type ScalarPath<T extends TSchema2 & {
|
|
193
|
+
properties: Record<string, TSchema2>;
|
|
194
|
+
}> = ScalarKeys<T> | SubTableScalarPath<T>;
|
|
195
|
+
/** @internal */
|
|
196
|
+
type JsonPathLevel1<T extends TSchema2 & {
|
|
197
|
+
properties: Record<string, TSchema2>;
|
|
198
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends {
|
|
199
|
+
properties: Record<string, TSchema2>;
|
|
200
|
+
} ? `${K}.${keyof UnwrapOptional<T["properties"][K]>["properties"] & string}` : never }[keyof T["properties"] & string];
|
|
201
|
+
/** @internal */
|
|
202
|
+
type JsonPathLevel2<T extends TSchema2 & {
|
|
203
|
+
properties: Record<string, TSchema2>;
|
|
204
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends {
|
|
205
|
+
properties: Record<string, TSchema2>;
|
|
206
|
+
} ? { [K2 in keyof UnwrapOptional<T["properties"][K]>["properties"] & string] : UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]> extends {
|
|
207
|
+
properties: Record<string, TSchema2>;
|
|
208
|
+
} ? `${K}.${K2}.${keyof UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"] & string}` : never }[keyof UnwrapOptional<T["properties"][K]>["properties"] & string] : never }[keyof T["properties"] & string];
|
|
209
|
+
/** @internal */
|
|
210
|
+
type JsonPathLevel3<T extends TSchema2 & {
|
|
211
|
+
properties: Record<string, TSchema2>;
|
|
212
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends {
|
|
213
|
+
properties: Record<string, TSchema2>;
|
|
214
|
+
} ? { [K2 in keyof UnwrapOptional<T["properties"][K]>["properties"] & string] : UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]> extends {
|
|
215
|
+
properties: Record<string, TSchema2>;
|
|
216
|
+
} ? { [K3 in keyof UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"] & string] : UnwrapOptional<UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"][K3]> extends {
|
|
217
|
+
properties: Record<string, TSchema2>;
|
|
218
|
+
} ? `${K}.${K2}.${K3}.${keyof UnwrapOptional<UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"][K3]>["properties"] & string}` : never }[keyof UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"] & string] : never }[keyof UnwrapOptional<T["properties"][K]>["properties"] & string] : never }[keyof T["properties"] & string];
|
|
219
|
+
/** @internal */
|
|
220
|
+
type JsonPath<T extends TSchema2 & {
|
|
221
|
+
properties: Record<string, TSchema2>;
|
|
222
|
+
}> = JsonPathLevel1<T> | JsonPathLevel2<T> | JsonPathLevel3<T>;
|
|
223
|
+
/** @internal */
|
|
224
|
+
type ScalarJsonPathLevel1<T extends TSchema2 & {
|
|
225
|
+
properties: Record<string, TSchema2>;
|
|
226
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends TObject2<infer P> ? { [K2 in keyof P & string] : UnwrapOptional<P[K2]> extends TScalarSchema ? `${K}.${K2}` : never }[keyof P & string] : never }[keyof T["properties"] & string];
|
|
227
|
+
/** @internal */
|
|
228
|
+
type ScalarJsonPathLevel2<T extends TSchema2 & {
|
|
229
|
+
properties: Record<string, TSchema2>;
|
|
230
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends TObject2<infer P> ? { [K2 in keyof P & string] : UnwrapOptional<P[K2]> extends TObject2<infer P2> ? { [K3 in keyof P2 & string] : UnwrapOptional<P2[K3]> extends TScalarSchema ? `${K}.${K2}.${K3}` : never }[keyof P2 & string] : never }[keyof P & string] : never }[keyof T["properties"] & string];
|
|
231
|
+
/** @internal */
|
|
232
|
+
type ScalarJsonPathLevel3<T extends TSchema2 & {
|
|
233
|
+
properties: Record<string, TSchema2>;
|
|
234
|
+
}> = { [K in keyof T["properties"] & string] : UnwrapOptional<T["properties"][K]> extends TObject2<infer P> ? { [K2 in keyof P & string] : UnwrapOptional<P[K2]> extends TObject2<infer P2> ? { [K3 in keyof P2 & string] : UnwrapOptional<P2[K3]> extends TObject2<infer P3> ? { [K4 in keyof P3 & string] : UnwrapOptional<P3[K4]> extends TScalarSchema ? `${K}.${K2}.${K3}.${K4}` : never }[keyof P3 & string] : never }[keyof P2 & string] : never }[keyof P & string] : never }[keyof T["properties"] & string];
|
|
235
|
+
/** @internal */
|
|
236
|
+
type ScalarJsonPath<T extends TSchema2 & {
|
|
237
|
+
properties: Record<string, TSchema2>;
|
|
238
|
+
}> = ScalarJsonPathLevel1<T> | ScalarJsonPathLevel2<T> | ScalarJsonPathLevel3<T>;
|
|
239
|
+
/** @internal */
|
|
240
|
+
type PathValue<
|
|
241
|
+
T extends TSchema2 & {
|
|
242
|
+
properties: Record<string, TSchema2>;
|
|
243
|
+
},
|
|
244
|
+
P extends string
|
|
245
|
+
> = P extends `${infer K}.${infer Rest}` ? UnwrapOptional<T["properties"][K]> extends {
|
|
246
|
+
properties: Record<string, TSchema2>;
|
|
247
|
+
} ? Rest extends `${infer K2}.${infer Rest2}` ? UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]> extends {
|
|
248
|
+
properties: Record<string, TSchema2>;
|
|
249
|
+
} ? Rest2 extends `${infer K3}.${infer Rest3}` ? UnwrapOptional<UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"][K3]> extends {
|
|
250
|
+
properties: Record<string, TSchema2>;
|
|
251
|
+
} ? UnwrapOptional<UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"][K3]>["properties"][Rest3] extends TSchema2 ? Static<UnwrapOptional<UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"][K3]>["properties"][Rest3]> : never : never : UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"][Rest2] extends TSchema2 ? Static<UnwrapOptional<UnwrapOptional<T["properties"][K]>["properties"][K2]>["properties"][Rest2]> : never : never : UnwrapOptional<T["properties"][K]>["properties"][Rest] extends TSchema2 ? Static<UnwrapOptional<T["properties"][K]>["properties"][Rest]> : never : never : P extends keyof T["properties"] ? Static<T["properties"][P]> : never;
|
|
130
252
|
/**
|
|
131
253
|
* the typescript type that matches a typebox schema
|
|
132
254
|
* @category Query Types
|
|
133
255
|
*/
|
|
134
|
-
type Infer<T extends
|
|
256
|
+
type Infer<T extends TSchema2> = Static<T>;
|
|
257
|
+
/**
|
|
258
|
+
* @internal
|
|
259
|
+
* @category Advanced
|
|
260
|
+
*/
|
|
261
|
+
type SubTableItem<
|
|
262
|
+
T extends TSchema2 & {
|
|
263
|
+
properties: Record<string, TSchema2>;
|
|
264
|
+
},
|
|
265
|
+
K extends SubTableKeys<T>
|
|
266
|
+
> = T["properties"][K] extends TArray<infer Item extends TSchema2> ? Static<Item> : never;
|
|
135
267
|
/** @category Query Types */
|
|
136
|
-
type ScalarFilter<V> =
|
|
268
|
+
type ScalarFilter<V> = unknown extends V ? {
|
|
269
|
+
eq: V;
|
|
270
|
+
} | {
|
|
271
|
+
ne: V;
|
|
272
|
+
} | {
|
|
273
|
+
gt: V;
|
|
274
|
+
} | {
|
|
275
|
+
gte: V;
|
|
276
|
+
} | {
|
|
277
|
+
lt: V;
|
|
278
|
+
} | {
|
|
279
|
+
lte: V;
|
|
280
|
+
} | {
|
|
281
|
+
like: string;
|
|
282
|
+
} | {
|
|
283
|
+
between: [V, V];
|
|
284
|
+
} | {
|
|
285
|
+
in: V[];
|
|
286
|
+
} | {
|
|
287
|
+
notIn: V[];
|
|
288
|
+
} | {
|
|
289
|
+
isNull: true;
|
|
290
|
+
} | {
|
|
291
|
+
isNotNull: true;
|
|
292
|
+
} : V extends string ? {
|
|
137
293
|
eq: V;
|
|
138
294
|
} | {
|
|
139
295
|
ne: V;
|
|
@@ -173,6 +329,14 @@ type ScalarFilter<V> = V extends string ? {
|
|
|
173
329
|
isNull: true;
|
|
174
330
|
} | {
|
|
175
331
|
isNotNull: true;
|
|
332
|
+
} : V extends object ? {
|
|
333
|
+
eq: V;
|
|
334
|
+
} | {
|
|
335
|
+
ne: V;
|
|
336
|
+
} | {
|
|
337
|
+
isNull: true;
|
|
338
|
+
} | {
|
|
339
|
+
isNotNull: true;
|
|
176
340
|
} : {
|
|
177
341
|
isNull: true;
|
|
178
342
|
} | {
|
|
@@ -198,13 +362,25 @@ type ScalarFilter<V> = V extends string ? {
|
|
|
198
362
|
* @category Query Types
|
|
199
363
|
* @category Query Types
|
|
200
364
|
*/
|
|
201
|
-
type WhereClause<T extends
|
|
365
|
+
type WhereClause<T extends TSchema2 & {
|
|
366
|
+
properties: Record<string, TSchema2>;
|
|
367
|
+
}> = { [K in ScalarKeys<T>]? : ScalarFilter<Static<T["properties"][K]>> } & { [K in ObjectKeys<T>]? : ScalarFilter<Static<T["properties"][K]>> } & { [K in JsonPath<T>]? : ScalarFilter<PathValue<T, K>> } & {
|
|
368
|
+
AND?: WhereClause<T>[];
|
|
369
|
+
OR?: WhereClause<T>[];
|
|
370
|
+
NOT?: WhereClause<T>;
|
|
371
|
+
_raw?: {
|
|
372
|
+
sql: string;
|
|
373
|
+
params: unknown[];
|
|
374
|
+
};
|
|
375
|
+
};
|
|
202
376
|
/**
|
|
203
377
|
* sort direction for queries
|
|
204
378
|
* @category Query Types
|
|
205
379
|
*/
|
|
206
|
-
type OrderByClause<T extends
|
|
207
|
-
|
|
380
|
+
type OrderByClause<T extends TSchema2 & {
|
|
381
|
+
properties: Record<string, TSchema2>;
|
|
382
|
+
}> = {
|
|
383
|
+
column: ScalarKeys<T> | ScalarJsonPath<T>;
|
|
208
384
|
direction?: "ASC" | "DESC";
|
|
209
385
|
};
|
|
210
386
|
/**
|
|
@@ -215,6 +391,18 @@ interface PaginationOptions {
|
|
|
215
391
|
limit?: number;
|
|
216
392
|
offset?: number;
|
|
217
393
|
}
|
|
394
|
+
interface Cursor {
|
|
395
|
+
column: string;
|
|
396
|
+
value: SqliteScalar;
|
|
397
|
+
}
|
|
398
|
+
interface CursorInput extends Cursor {
|
|
399
|
+
direction: "next" | "prev";
|
|
400
|
+
}
|
|
401
|
+
interface CursorPageResult<T> {
|
|
402
|
+
data: T[];
|
|
403
|
+
nextCursor: Cursor | null;
|
|
404
|
+
prevCursor: Cursor | null;
|
|
405
|
+
}
|
|
218
406
|
/**
|
|
219
407
|
* Options for `findMany`, `findPage`, and `findOne`.
|
|
220
408
|
*
|
|
@@ -241,22 +429,36 @@ interface PaginationOptions {
|
|
|
241
429
|
* @category Query Types
|
|
242
430
|
* @category Query Types
|
|
243
431
|
*/
|
|
244
|
-
|
|
432
|
+
/** @internal */
|
|
433
|
+
type SelectableKeys<T extends TSchema2 & {
|
|
434
|
+
properties: Record<string, TSchema2>;
|
|
435
|
+
}> = ScalarKeys<T> | ObjectKeys<T> | PrimitiveArrayKeys<T> | JsonPath<T>;
|
|
436
|
+
interface FindOptions<T extends TSchema2 & {
|
|
437
|
+
properties: Record<string, TSchema2>;
|
|
438
|
+
}> extends PaginationOptions {
|
|
245
439
|
where?: WhereClause<T>;
|
|
246
440
|
orderBy?: OrderByClause<T> | OrderByClause<T>[];
|
|
247
441
|
include?: SubTableKeys<T>[];
|
|
442
|
+
select?: SelectableKeys<T>[];
|
|
443
|
+
includeDeleted?: boolean;
|
|
444
|
+
distinct?: boolean;
|
|
445
|
+
distinctOn?: (ScalarKeys<T> | ScalarJsonPath<T>)[];
|
|
248
446
|
}
|
|
249
447
|
/**
|
|
250
448
|
* full record to insert
|
|
251
449
|
* @category Query Types
|
|
252
450
|
*/
|
|
253
|
-
type InsertData<T extends
|
|
451
|
+
type InsertData<T extends TSchema2 & {
|
|
452
|
+
properties: Record<string, TSchema2>;
|
|
453
|
+
}> = Infer<T>;
|
|
254
454
|
/**
|
|
255
455
|
* update payload - must include the primary key
|
|
256
456
|
* @category Query Types
|
|
257
457
|
*/
|
|
258
458
|
type UpdateData<
|
|
259
|
-
T extends
|
|
459
|
+
T extends TSchema2 & {
|
|
460
|
+
properties: Record<string, TSchema2>;
|
|
461
|
+
},
|
|
260
462
|
PK extends ScalarKeys<T>
|
|
261
463
|
> = Pick<Infer<T>, PK> & Partial<Omit<Infer<T>, PK>>;
|
|
262
464
|
/**
|
|
@@ -265,8 +467,14 @@ type UpdateData<
|
|
|
265
467
|
*/
|
|
266
468
|
interface IndexDefinition {
|
|
267
469
|
name?: string;
|
|
268
|
-
columns: ColumnRef<string, TScalarSchema>
|
|
470
|
+
columns: Array<ColumnRef<string, TScalarSchema> | {
|
|
471
|
+
name: string;
|
|
472
|
+
}>;
|
|
269
473
|
unique?: boolean;
|
|
474
|
+
where?: string;
|
|
475
|
+
include?: Array<ColumnRef<string, TScalarSchema> | {
|
|
476
|
+
name: string;
|
|
477
|
+
}>;
|
|
270
478
|
}
|
|
271
479
|
/**
|
|
272
480
|
* timestamp configuration for a table
|
|
@@ -318,10 +526,47 @@ type Entity<
|
|
|
318
526
|
* table descriptor passed to createORM
|
|
319
527
|
* @category Schema
|
|
320
528
|
*/
|
|
529
|
+
interface EvictionConfig {
|
|
530
|
+
maxRows?: number;
|
|
531
|
+
ttlColumn?: string;
|
|
532
|
+
ttlMs?: number;
|
|
533
|
+
lruColumn?: string;
|
|
534
|
+
}
|
|
535
|
+
interface CompressionConfig {
|
|
536
|
+
columns: ColumnRef<string, TScalarSchema>[];
|
|
537
|
+
algorithm: "gzip" | "none";
|
|
538
|
+
}
|
|
539
|
+
interface SoftDeleteConfig {
|
|
540
|
+
column: string;
|
|
541
|
+
}
|
|
542
|
+
type GeneratedColumnConfig = {
|
|
543
|
+
[name: string]: {
|
|
544
|
+
expr: string;
|
|
545
|
+
type: TSchema2;
|
|
546
|
+
};
|
|
547
|
+
};
|
|
548
|
+
type GeneratedColumnValues<C extends GeneratedColumnConfig> = { [K in keyof C & string] : Static<C[K]["type"]> };
|
|
549
|
+
type AugmentSchema<
|
|
550
|
+
T extends TSchema2 & {
|
|
551
|
+
properties: Record<string, TSchema2>;
|
|
552
|
+
},
|
|
553
|
+
G extends GeneratedColumnConfig
|
|
554
|
+
> = TObject2<T["properties"] & GeneratedColumnValues<G>>;
|
|
555
|
+
type QuerySchema<
|
|
556
|
+
T extends TSchema2 & {
|
|
557
|
+
properties: Record<string, TSchema2>;
|
|
558
|
+
},
|
|
559
|
+
G extends GeneratedColumnConfig | undefined
|
|
560
|
+
> = [G] extends [undefined] ? T : [G] extends [GeneratedColumnConfig] ? AugmentSchema<T, G> : T;
|
|
321
561
|
interface TableConfig<
|
|
322
|
-
T extends
|
|
562
|
+
T extends TSchema2 & {
|
|
563
|
+
properties: Record<string, TSchema2>;
|
|
564
|
+
} = TSchema2 & {
|
|
565
|
+
properties: Record<string, TSchema2>;
|
|
566
|
+
},
|
|
323
567
|
PK extends string = string,
|
|
324
|
-
TS extends TimestampConfig = undefined
|
|
568
|
+
TS extends TimestampConfig = undefined,
|
|
569
|
+
G extends GeneratedColumnConfig | undefined = undefined
|
|
325
570
|
> {
|
|
326
571
|
schema: T;
|
|
327
572
|
primaryKey: ColumnRef<PK>;
|
|
@@ -330,6 +575,10 @@ interface TableConfig<
|
|
|
330
575
|
indexes?: IndexDefinition[];
|
|
331
576
|
}>>;
|
|
332
577
|
timestamps?: TS;
|
|
578
|
+
eviction?: EvictionConfig;
|
|
579
|
+
compression?: CompressionConfig;
|
|
580
|
+
softDelete?: SoftDeleteConfig;
|
|
581
|
+
generated?: G;
|
|
333
582
|
}
|
|
334
583
|
/**
|
|
335
584
|
* read-only metadata about the current database schema
|
|
@@ -347,7 +596,7 @@ interface MetaAccessors {
|
|
|
347
596
|
* @category Relations
|
|
348
597
|
*/
|
|
349
598
|
interface RelationEntry<
|
|
350
|
-
Tables extends Record<string, TableConfig<any, any, any>>,
|
|
599
|
+
Tables extends Record<string, TableConfig<any, any, any, any>>,
|
|
351
600
|
Owner extends keyof Tables,
|
|
352
601
|
Target extends keyof Tables
|
|
353
602
|
> {
|
|
@@ -359,7 +608,7 @@ interface RelationEntry<
|
|
|
359
608
|
* @internal
|
|
360
609
|
* @category Relations
|
|
361
610
|
*/
|
|
362
|
-
type RelationsConfig<Tables extends Record<string, TableConfig<any, any, any>>> = { [K in keyof Tables & string]? : Array<{ [Target in keyof Tables & string] : RelationEntry<Tables, K, Target> }[keyof Tables & string]> };
|
|
611
|
+
type RelationsConfig<Tables extends Record<string, TableConfig<any, any, any, any>>> = { [K in keyof Tables & string]? : Array<{ [Target in keyof Tables & string] : RelationEntry<Tables, K, Target> }[keyof Tables & string]> };
|
|
363
612
|
/**
|
|
364
613
|
* @internal
|
|
365
614
|
* @category Relations
|
|
@@ -376,7 +625,7 @@ type ScalarMergeNames<
|
|
|
376
625
|
* @category Relations
|
|
377
626
|
*/
|
|
378
627
|
type ScalarMergeType<
|
|
379
|
-
Tables extends Record<string, TableConfig<any, any, any>>,
|
|
628
|
+
Tables extends Record<string, TableConfig<any, any, any, any>>,
|
|
380
629
|
Rels extends readonly TypedRelation[],
|
|
381
630
|
Owner extends string,
|
|
382
631
|
Name extends string
|
|
@@ -390,7 +639,7 @@ type ScalarMergeType<
|
|
|
390
639
|
* @category Relations
|
|
391
640
|
*/
|
|
392
641
|
type ScalarMerge<
|
|
393
|
-
Tables extends Record<string, TableConfig<any, any, any>>,
|
|
642
|
+
Tables extends Record<string, TableConfig<any, any, any, any>>,
|
|
394
643
|
Rels extends readonly TypedRelation[],
|
|
395
644
|
Owner extends string
|
|
396
645
|
> = { [K in ScalarMergeNames<Rels, Owner>] : ScalarMergeType<Tables, Rels, Owner, K> };
|
|
@@ -412,7 +661,7 @@ type SubMergeNames<
|
|
|
412
661
|
* @category Relations
|
|
413
662
|
*/
|
|
414
663
|
type SubMergeType<
|
|
415
|
-
Tables extends Record<string, TableConfig<any, any, any>>,
|
|
664
|
+
Tables extends Record<string, TableConfig<any, any, any, any>>,
|
|
416
665
|
Rels extends readonly TypedRelation[],
|
|
417
666
|
Owner extends string,
|
|
418
667
|
Sub extends string,
|
|
@@ -428,7 +677,7 @@ type SubMergeType<
|
|
|
428
677
|
* @category Relations
|
|
429
678
|
*/
|
|
430
679
|
type SubMerge<
|
|
431
|
-
Tables extends Record<string, TableConfig<any, any, any>>,
|
|
680
|
+
Tables extends Record<string, TableConfig<any, any, any, any>>,
|
|
432
681
|
Rels extends readonly TypedRelation[],
|
|
433
682
|
Owner extends string,
|
|
434
683
|
Sub extends string
|
|
@@ -450,8 +699,10 @@ type SubMerge<
|
|
|
450
699
|
* @category Relations
|
|
451
700
|
*/
|
|
452
701
|
type Materialized<
|
|
453
|
-
T extends
|
|
454
|
-
|
|
702
|
+
T extends TSchema2 & {
|
|
703
|
+
properties: Record<string, TSchema2>;
|
|
704
|
+
},
|
|
705
|
+
Tables extends Record<string, TableConfig<any, any, any, any>>,
|
|
455
706
|
Rels extends readonly TypedRelation[],
|
|
456
707
|
Owner extends string
|
|
457
708
|
> = { [K in keyof Infer<T>] : K extends string ? Infer<T>[K] extends Array<infer Item> ? Array<Item & SubMerge<Tables, Rels, Owner, K>> : Infer<T>[K] : Infer<T>[K] } & ScalarMerge<Tables, Rels, Owner>;
|
|
@@ -470,7 +721,9 @@ interface PageResult<T> {
|
|
|
470
721
|
* @category Query Types
|
|
471
722
|
*/
|
|
472
723
|
interface UpsertOptions<
|
|
473
|
-
T extends
|
|
724
|
+
T extends TSchema2 & {
|
|
725
|
+
properties: Record<string, TSchema2>;
|
|
726
|
+
},
|
|
474
727
|
PK extends ScalarKeys<T>
|
|
475
728
|
> {
|
|
476
729
|
data: InsertData<T>;
|
|
@@ -479,6 +732,35 @@ interface UpsertOptions<
|
|
|
479
732
|
update?: Array<ScalarKeys<T>>;
|
|
480
733
|
}
|
|
481
734
|
/**
|
|
735
|
+
* bulk conditional update
|
|
736
|
+
* @category Query Types
|
|
737
|
+
*/
|
|
738
|
+
interface UpdateWhereOptions<
|
|
739
|
+
T extends TSchema2 & {
|
|
740
|
+
properties: Record<string, TSchema2>;
|
|
741
|
+
},
|
|
742
|
+
PK extends ScalarKeys<T>
|
|
743
|
+
> {
|
|
744
|
+
where: WhereClause<T>;
|
|
745
|
+
data: Partial<Omit<Infer<T>, PK>>;
|
|
746
|
+
includeDeleted?: boolean;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* bulk upsert with conflict resolution
|
|
750
|
+
* @category Query Types
|
|
751
|
+
*/
|
|
752
|
+
interface UpsertManyOptions<
|
|
753
|
+
T extends TSchema2 & {
|
|
754
|
+
properties: Record<string, TSchema2>;
|
|
755
|
+
},
|
|
756
|
+
PK extends ScalarKeys<T>
|
|
757
|
+
> {
|
|
758
|
+
data: InsertData<T>[];
|
|
759
|
+
conflictTarget: PK | PK[];
|
|
760
|
+
/** columns to update on conflict - defaults to all non-pk columns */
|
|
761
|
+
update?: Array<ScalarKeys<T>>;
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
482
764
|
* a single migration step
|
|
483
765
|
* @category Migration
|
|
484
766
|
*/
|
|
@@ -584,11 +866,121 @@ interface SchemaDiff {
|
|
|
584
866
|
* @category Migration
|
|
585
867
|
*/
|
|
586
868
|
type SyncPolicy = "ignore" | "warn" | "error" | "auto" | ((diff: SchemaDiff, db: BunDatabase) => boolean | void);
|
|
869
|
+
/** @category Query Types */
|
|
870
|
+
type WindowFunction<T extends TSchema2 & {
|
|
871
|
+
properties: Record<string, TSchema2>;
|
|
872
|
+
}> = {
|
|
873
|
+
rowNumber: true;
|
|
874
|
+
} | {
|
|
875
|
+
rank: true;
|
|
876
|
+
} | {
|
|
877
|
+
denseRank: true;
|
|
878
|
+
} | {
|
|
879
|
+
lead: ScalarKeys<T> | ScalarJsonPath<T>;
|
|
880
|
+
offset?: number;
|
|
881
|
+
} | {
|
|
882
|
+
lag: ScalarKeys<T> | ScalarJsonPath<T>;
|
|
883
|
+
offset?: number;
|
|
884
|
+
};
|
|
885
|
+
/** @category Query Types */
|
|
886
|
+
interface WindowQueryOptions<T extends TSchema2 & {
|
|
887
|
+
properties: Record<string, TSchema2>;
|
|
888
|
+
}> {
|
|
889
|
+
partitionBy?: (ScalarKeys<T> | ScalarJsonPath<T>)[];
|
|
890
|
+
orderBy?: OrderByClause<T> | OrderByClause<T>[];
|
|
891
|
+
where?: WhereClause<T>;
|
|
892
|
+
limit?: number;
|
|
893
|
+
select: Record<string, WindowFunction<T>>;
|
|
894
|
+
}
|
|
895
|
+
/** @internal */
|
|
896
|
+
type WindowFunctionResult<
|
|
897
|
+
T extends TSchema2 & {
|
|
898
|
+
properties: Record<string, TSchema2>;
|
|
899
|
+
},
|
|
900
|
+
W extends WindowFunction<T>
|
|
901
|
+
> = W extends {
|
|
902
|
+
lead: infer C extends string;
|
|
903
|
+
} ? PathValue<T, C> | null : W extends {
|
|
904
|
+
lag: infer C extends string;
|
|
905
|
+
} ? PathValue<T, C> | null : number;
|
|
906
|
+
/** @category Query Types */
|
|
907
|
+
type WindowResult<
|
|
908
|
+
T extends TSchema2 & {
|
|
909
|
+
properties: Record<string, TSchema2>;
|
|
910
|
+
},
|
|
911
|
+
W extends Record<string, WindowFunction<T>>
|
|
912
|
+
> = Array<{ [K in keyof W] : WindowFunctionResult<T, W[K]> }>;
|
|
913
|
+
/** @category Query Types */
|
|
914
|
+
type AggregationOp<T extends TSchema2 & {
|
|
915
|
+
properties: Record<string, TSchema2>;
|
|
916
|
+
} = TSchema2 & {
|
|
917
|
+
properties: Record<string, TSchema2>;
|
|
918
|
+
}> = {
|
|
919
|
+
sum?: ScalarKeys<T> | ScalarJsonPath<T>;
|
|
920
|
+
} | {
|
|
921
|
+
count?: "*" | ScalarKeys<T> | ScalarJsonPath<T>;
|
|
922
|
+
} | {
|
|
923
|
+
avg?: ScalarKeys<T> | ScalarJsonPath<T>;
|
|
924
|
+
} | {
|
|
925
|
+
min?: ScalarKeys<T> | ScalarJsonPath<T>;
|
|
926
|
+
} | {
|
|
927
|
+
max?: ScalarKeys<T> | ScalarJsonPath<T>;
|
|
928
|
+
};
|
|
929
|
+
/** @category Query Types */
|
|
930
|
+
interface AggregateOptions<
|
|
931
|
+
T extends TSchema2 & {
|
|
932
|
+
properties: Record<string, TSchema2>;
|
|
933
|
+
},
|
|
934
|
+
A extends Record<string, AggregationOp<T>> = Record<string, AggregationOp<T>>
|
|
935
|
+
> {
|
|
936
|
+
where?: WhereClause<T>;
|
|
937
|
+
groupBy?: readonly (ScalarKeys<T> | ScalarJsonPath<T>)[];
|
|
938
|
+
aggregations: A;
|
|
939
|
+
having?: { [K in keyof A]? : ScalarFilter<unknown> };
|
|
940
|
+
includeDeleted?: boolean;
|
|
941
|
+
}
|
|
942
|
+
/** @internal */
|
|
943
|
+
type AggregationOpResult<
|
|
944
|
+
T extends TSchema2 & {
|
|
945
|
+
properties: Record<string, TSchema2>;
|
|
946
|
+
},
|
|
947
|
+
Op extends AggregationOp<T>
|
|
948
|
+
> = Op extends {
|
|
949
|
+
sum: string;
|
|
950
|
+
} ? number | null : Op extends {
|
|
951
|
+
count: string;
|
|
952
|
+
} ? number : Op extends {
|
|
953
|
+
avg: string;
|
|
954
|
+
} ? number | null : Op extends {
|
|
955
|
+
min: infer C extends string;
|
|
956
|
+
} ? PathValue<T, C> | null : Op extends {
|
|
957
|
+
max: infer C extends string;
|
|
958
|
+
} ? PathValue<T, C> | null : never;
|
|
959
|
+
/** @category Query Types */
|
|
960
|
+
type AggregateResult<
|
|
961
|
+
T extends TSchema2 & {
|
|
962
|
+
properties: Record<string, TSchema2>;
|
|
963
|
+
},
|
|
964
|
+
A extends Record<string, AggregationOp<T>>,
|
|
965
|
+
G extends readonly string[] | undefined = undefined
|
|
966
|
+
> = Array<{ [K in keyof A] : AggregationOpResult<T, A[K]> } & (G extends readonly string[] ? { [K in G[number]] : PathValue<T, K> } : {})>;
|
|
967
|
+
/** @category Observability */
|
|
968
|
+
interface QueryMetrics {
|
|
969
|
+
table: string;
|
|
970
|
+
operation: string;
|
|
971
|
+
sql: string;
|
|
972
|
+
durationMs: number;
|
|
973
|
+
rowCount: number;
|
|
974
|
+
}
|
|
975
|
+
/** @category Observability */
|
|
976
|
+
interface QueryMetricsHook {
|
|
977
|
+
onQuery: (meta: QueryMetrics) => void;
|
|
978
|
+
}
|
|
587
979
|
/**
|
|
588
980
|
* specific operations that can be listened to per table
|
|
589
981
|
* @category Events
|
|
590
982
|
*/
|
|
591
|
-
type TableOperation = "insert" | "insertMany" | "update" | "delete" | "deleteWhere" | "upsert" | "findById" | "findMany" | "findOne" | "findPage" | "count" | "flush";
|
|
983
|
+
type TableOperation = "insert" | "insertMany" | "update" | "updateWhere" | "delete" | "deleteWhere" | "upsert" | "upsertMany" | "findById" | "findMany" | "findOne" | "findPage" | "findCursorPage" | "iterate" | "count" | "flush" | "aggregate" | "windowQuery";
|
|
592
984
|
/**
|
|
593
985
|
* broad categories for event listening
|
|
594
986
|
* @category Events
|
|
@@ -626,7 +1018,58 @@ type ErrorPolicy = "throw" | "emit" | "emit-swallow" | "crash";
|
|
|
626
1018
|
* @category Setup
|
|
627
1019
|
*/
|
|
628
1020
|
type UnlinkPolicy = true | "onlyGraceful" | "any" | false | undefined;
|
|
629
|
-
import {
|
|
1021
|
+
import { TSchema as TSchema5 } from "typebox";
|
|
1022
|
+
import { TSchema as TSchema3 } from "typebox";
|
|
1023
|
+
/** @category Schema */
|
|
1024
|
+
interface SubTableConfig {
|
|
1025
|
+
indexes?: IndexDefinition[];
|
|
1026
|
+
}
|
|
1027
|
+
interface TableDescriptor<
|
|
1028
|
+
T extends TSchema3 & {
|
|
1029
|
+
properties: Record<string, TSchema3>;
|
|
1030
|
+
},
|
|
1031
|
+
PK extends string,
|
|
1032
|
+
TS extends TimestampConfig = undefined,
|
|
1033
|
+
G extends GeneratedColumnConfig | undefined = undefined
|
|
1034
|
+
> extends TableConfig<T, PK, TS, G> {}
|
|
1035
|
+
interface TableConfigShape<
|
|
1036
|
+
PK extends string,
|
|
1037
|
+
TS extends TimestampConfig,
|
|
1038
|
+
G extends GeneratedColumnConfig | undefined = undefined
|
|
1039
|
+
> {
|
|
1040
|
+
primaryKey: ColumnRef<PK>;
|
|
1041
|
+
indexes?: IndexDefinition[];
|
|
1042
|
+
subTables?: Partial<Record<string, SubTableConfig>>;
|
|
1043
|
+
timestamps?: TS;
|
|
1044
|
+
eviction?: EvictionConfig;
|
|
1045
|
+
compression?: CompressionConfig;
|
|
1046
|
+
softDelete?: SoftDeleteConfig;
|
|
1047
|
+
generated?: G;
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Describe a table schema + config for `createORM`.
|
|
1051
|
+
*
|
|
1052
|
+
* @example
|
|
1053
|
+
* ```ts
|
|
1054
|
+
* const UserSchema = Object({ id: String(), name: String(), email: String() });
|
|
1055
|
+
*
|
|
1056
|
+
* const users = table(UserSchema, (s) => ({
|
|
1057
|
+
* primaryKey: s.id,
|
|
1058
|
+
* indexes: [{ columns: [s.email], unique: true }],
|
|
1059
|
+
* timestamps: true, // adds createdAt / updatedAt
|
|
1060
|
+
* }));
|
|
1061
|
+
* ```
|
|
1062
|
+
* @category Schema
|
|
1063
|
+
* @category Schema
|
|
1064
|
+
*/
|
|
1065
|
+
declare function table<
|
|
1066
|
+
T extends TSchema3 & {
|
|
1067
|
+
properties: Record<string, TSchema3>;
|
|
1068
|
+
},
|
|
1069
|
+
PK extends string,
|
|
1070
|
+
TS extends TimestampConfig = undefined,
|
|
1071
|
+
G extends GeneratedColumnConfig | undefined = undefined
|
|
1072
|
+
>(schema: T, configure: (columns: ColumnRefs<T>) => TableConfigShape<PK, TS, G>): TableDescriptor<T, PK, TS, G>;
|
|
630
1073
|
/** @category Events */
|
|
631
1074
|
type Listener = (payload: unknown) => void;
|
|
632
1075
|
/**
|
|
@@ -660,7 +1103,7 @@ interface LifecycleEventMap {
|
|
|
660
1103
|
* typed event listener api
|
|
661
1104
|
* @category Events
|
|
662
1105
|
*/
|
|
663
|
-
interface ORMEvents<Tables extends Record<string,
|
|
1106
|
+
interface ORMEvents<Tables extends Record<string, TableDescriptor<any, any, any, any>>> {
|
|
664
1107
|
/** listen to lifecycle events (start, ready, shutdown, exit, fail) */
|
|
665
1108
|
on<K extends (keyof LifecycleEventMap) & string>(event: K, listener: (payload: LifecycleEventMap[K]) => void): () => void;
|
|
666
1109
|
/** listen to table events (insert, update, findMany, etc) */
|
|
@@ -682,7 +1125,7 @@ declare class EventBus {
|
|
|
682
1125
|
emit(event: string, payload: unknown): void;
|
|
683
1126
|
emitIf(event: string, payload: unknown): void;
|
|
684
1127
|
}
|
|
685
|
-
import {
|
|
1128
|
+
import { TSchema as TSchema4 } from "typebox";
|
|
686
1129
|
/** @category Advanced */
|
|
687
1130
|
type SqliteType = "TEXT" | "INTEGER" | "REAL" | "BLOB";
|
|
688
1131
|
/** @category Advanced */
|
|
@@ -692,6 +1135,14 @@ interface ColumnMeta {
|
|
|
692
1135
|
nullable: boolean;
|
|
693
1136
|
/** True if this is actually an `Optional` wrapper */
|
|
694
1137
|
optional: boolean;
|
|
1138
|
+
/** Path segments for flattened nested columns, e.g. ["Status", "Group"] */
|
|
1139
|
+
path?: string[];
|
|
1140
|
+
/** True if the underlying schema is a boolean (stored as INTEGER) */
|
|
1141
|
+
isBoolean?: boolean;
|
|
1142
|
+
/** True if this is a generated column */
|
|
1143
|
+
generated?: boolean;
|
|
1144
|
+
/** Expression for generated columns */
|
|
1145
|
+
generatedExpr?: string;
|
|
695
1146
|
}
|
|
696
1147
|
/** @category Advanced */
|
|
697
1148
|
interface SubTableMeta {
|
|
@@ -700,20 +1151,57 @@ interface SubTableMeta {
|
|
|
700
1151
|
/** e.g. "sales__lineItems" */
|
|
701
1152
|
tableName: string;
|
|
702
1153
|
/** Schema of a single item in the array */
|
|
703
|
-
itemSchema:
|
|
1154
|
+
itemSchema: TSchema4 & {
|
|
1155
|
+
properties: Record<string, TSchema4>;
|
|
1156
|
+
};
|
|
704
1157
|
/** Columns of the sub-table row (owner PK is prepended automatically) */
|
|
705
1158
|
columns: ColumnMeta[];
|
|
1159
|
+
columnByName: Map<string, ColumnMeta>;
|
|
1160
|
+
columnByPath: Map<string, ColumnMeta>;
|
|
706
1161
|
}
|
|
707
1162
|
/** @category Advanced */
|
|
708
1163
|
interface TableMeta {
|
|
709
1164
|
tableName: string;
|
|
710
1165
|
columns: ColumnMeta[];
|
|
711
1166
|
subTables: SubTableMeta[];
|
|
1167
|
+
/** Map from dotted path → ColumnMeta for O(1) resolution */
|
|
1168
|
+
columnByPath: Map<string, ColumnMeta>;
|
|
1169
|
+
/** Map from column name → ColumnMeta for O(1) resolution */
|
|
1170
|
+
columnByName: Map<string, ColumnMeta>;
|
|
712
1171
|
}
|
|
713
1172
|
/** @category Advanced */
|
|
714
|
-
declare function introspectTable(tableName: string, schema:
|
|
1173
|
+
declare function introspectTable(tableName: string, schema: TSchema4 & {
|
|
1174
|
+
properties: Record<string, TSchema4>;
|
|
1175
|
+
}, generated?: Array<{
|
|
1176
|
+
name: string;
|
|
1177
|
+
expr: string;
|
|
1178
|
+
sqlType?: SqliteType;
|
|
1179
|
+
}>): TableMeta;
|
|
715
1180
|
/** @category Advanced */
|
|
716
1181
|
declare function buildCreateTableSQL(meta: TableMeta, primaryKey: string): string[];
|
|
1182
|
+
interface BatchWriterOptions {
|
|
1183
|
+
maxBuffer?: number;
|
|
1184
|
+
flushIntervalMs?: number;
|
|
1185
|
+
}
|
|
1186
|
+
declare class BatchWriter<
|
|
1187
|
+
TInput,
|
|
1188
|
+
TRow extends Record<string, unknown>
|
|
1189
|
+
> {
|
|
1190
|
+
private buffer;
|
|
1191
|
+
private readonly maxBuffer;
|
|
1192
|
+
private readonly tableName;
|
|
1193
|
+
private readonly db;
|
|
1194
|
+
private readonly prepare;
|
|
1195
|
+
private readonly onFlush?;
|
|
1196
|
+
private timer?;
|
|
1197
|
+
constructor(tableName: string, db: BunDatabase, opts: BatchWriterOptions, callbacks: {
|
|
1198
|
+
prepare: (row: TInput) => TRow;
|
|
1199
|
+
onFlush?: (rows: TRow[]) => void;
|
|
1200
|
+
});
|
|
1201
|
+
insert(row: TInput): void;
|
|
1202
|
+
flush(): void;
|
|
1203
|
+
close(): void;
|
|
1204
|
+
}
|
|
717
1205
|
/**
|
|
718
1206
|
* Typed repository for a single table. Every entry in your `tables` config
|
|
719
1207
|
* becomes one of these on the ORM object, fully typed to its schema.
|
|
@@ -736,8 +1224,13 @@ declare function buildCreateTableSQL(meta: TableMeta, primaryKey: string): strin
|
|
|
736
1224
|
* ```
|
|
737
1225
|
*/
|
|
738
1226
|
declare class Repository<
|
|
739
|
-
|
|
740
|
-
|
|
1227
|
+
TWrite extends TSchema5 & {
|
|
1228
|
+
properties: Record<string, TSchema5>;
|
|
1229
|
+
},
|
|
1230
|
+
TQuery extends TSchema5 & {
|
|
1231
|
+
properties: Record<string, TSchema5>;
|
|
1232
|
+
},
|
|
1233
|
+
PK extends ScalarKeys<TWrite>,
|
|
741
1234
|
Mat = never,
|
|
742
1235
|
TS = {}
|
|
743
1236
|
> {
|
|
@@ -752,17 +1245,31 @@ declare class Repository<
|
|
|
752
1245
|
private _materialize?;
|
|
753
1246
|
private _materializeMany?;
|
|
754
1247
|
private _events?;
|
|
1248
|
+
private _executor;
|
|
1249
|
+
private readonly _codecs;
|
|
755
1250
|
/** @internal */
|
|
756
1251
|
setEventBus(bus: EventBus): void;
|
|
757
|
-
|
|
1252
|
+
/** @internal */
|
|
1253
|
+
setMetricsHook(hook?: (meta: QueryMetrics) => void): void;
|
|
1254
|
+
constructor(tableName: string, config: TableConfig<TWrite, PK & string, TimestampConfig, GeneratedColumnConfig | undefined>, db: BunDatabase);
|
|
1255
|
+
/** Ensure PK is selected when include is requested */
|
|
1256
|
+
private _ensureSelectPk;
|
|
1257
|
+
/**
|
|
1258
|
+
* Two-phase row fetch: first get PKs via index, then fetch full rows.
|
|
1259
|
+
* Avoids reading all columns for rows that don't match the WHERE clause.
|
|
1260
|
+
*/
|
|
1261
|
+
private _fetchRows;
|
|
758
1262
|
/** Inject materializers after ORM two-pass init */
|
|
759
1263
|
setMaterializer(single: (record: Record<string, unknown>) => Record<string, unknown>, many: (records: Record<string, unknown>[]) => Record<string, unknown>[]): void;
|
|
760
1264
|
/** Wrap raw data in an entity object */
|
|
761
1265
|
private _wrap;
|
|
762
1266
|
/** Narrow a parsed schema value to a plain record for dynamic property access */
|
|
763
1267
|
private _record;
|
|
1268
|
+
/** Validate that a value is a valid SQLite scalar for use as a primary key */
|
|
1269
|
+
private _assertPk;
|
|
764
1270
|
private _emit;
|
|
765
1271
|
private _migrate;
|
|
1272
|
+
private _runEviction;
|
|
766
1273
|
/**
|
|
767
1274
|
* Validate and coerce data against the schema. Throws on invalid input.
|
|
768
1275
|
*
|
|
@@ -774,7 +1281,7 @@ declare class Repository<
|
|
|
774
1281
|
* // user is typed as Infer<typeof UserSchema>
|
|
775
1282
|
* ```
|
|
776
1283
|
*/
|
|
777
|
-
parse(data: unknown): Infer<
|
|
1284
|
+
parse(data: unknown): Infer<TWrite>;
|
|
778
1285
|
/**
|
|
779
1286
|
* Type-guard - returns true if data matches the schema.
|
|
780
1287
|
*
|
|
@@ -787,7 +1294,7 @@ declare class Repository<
|
|
|
787
1294
|
* }
|
|
788
1295
|
* ```
|
|
789
1296
|
*/
|
|
790
|
-
check(data: unknown): data is Infer<
|
|
1297
|
+
check(data: unknown): data is Infer<TWrite>;
|
|
791
1298
|
/**
|
|
792
1299
|
* Insert a single record. Returns the inserted entity.
|
|
793
1300
|
*
|
|
@@ -802,7 +1309,7 @@ declare class Repository<
|
|
|
802
1309
|
* });
|
|
803
1310
|
* ```
|
|
804
1311
|
*/
|
|
805
|
-
insert(data: InsertData<
|
|
1312
|
+
insert(data: InsertData<TWrite>): Entity<Infer<TQuery>, Mat, TS>;
|
|
806
1313
|
/**
|
|
807
1314
|
* Insert many records in a single transaction.
|
|
808
1315
|
*
|
|
@@ -816,8 +1323,20 @@ declare class Repository<
|
|
|
816
1323
|
* ]);
|
|
817
1324
|
* ```
|
|
818
1325
|
*/
|
|
819
|
-
insertMany(records: InsertData<
|
|
820
|
-
|
|
1326
|
+
insertMany(records: InsertData<TWrite>[]): Entity<Infer<TQuery>, Mat, TS>[];
|
|
1327
|
+
/**
|
|
1328
|
+
* Create a batch writer for high-throughput insert streaming.
|
|
1329
|
+
*
|
|
1330
|
+
* @group Writing
|
|
1331
|
+
*
|
|
1332
|
+
* @example
|
|
1333
|
+
* ```ts
|
|
1334
|
+
* const writer = orm.users.createBatchWriter({ maxBuffer: 500 });
|
|
1335
|
+
* writer.insert({ id: "u1", name: "alice" });
|
|
1336
|
+
* writer.close();
|
|
1337
|
+
* ```
|
|
1338
|
+
*/
|
|
1339
|
+
createBatchWriter(opts?: BatchWriterOptions): BatchWriter<InsertData<TWrite>, Record<string, unknown>>;
|
|
821
1340
|
/**
|
|
822
1341
|
* Insert or update on conflict. If the record exists (by conflict target),
|
|
823
1342
|
* it updates the specified columns instead.
|
|
@@ -832,7 +1351,25 @@ declare class Repository<
|
|
|
832
1351
|
* });
|
|
833
1352
|
* ```
|
|
834
1353
|
*/
|
|
835
|
-
upsert(opts: UpsertOptions<
|
|
1354
|
+
upsert(opts: UpsertOptions<TWrite, PK>): Entity<Infer<TQuery>, Mat, TS>;
|
|
1355
|
+
/**
|
|
1356
|
+
* Bulk upsert with conflict resolution.
|
|
1357
|
+
* Sub-table rows are reconciled by deleting old rows and re-inserting.
|
|
1358
|
+
*
|
|
1359
|
+
* @group Writing
|
|
1360
|
+
*
|
|
1361
|
+
* @example
|
|
1362
|
+
* ```ts
|
|
1363
|
+
* orm.users.upsertMany({
|
|
1364
|
+
* data: [
|
|
1365
|
+
* { id: "u1", name: "alice" },
|
|
1366
|
+
* { id: "u2", name: "bob" },
|
|
1367
|
+
* ],
|
|
1368
|
+
* conflictTarget: "id",
|
|
1369
|
+
* });
|
|
1370
|
+
* ```
|
|
1371
|
+
*/
|
|
1372
|
+
upsertMany(opts: UpsertManyOptions<TWrite, PK>): number;
|
|
836
1373
|
/**
|
|
837
1374
|
* Find a record by its primary key.
|
|
838
1375
|
*
|
|
@@ -844,7 +1381,7 @@ declare class Repository<
|
|
|
844
1381
|
* if (user) console.log(user.name);
|
|
845
1382
|
* ```
|
|
846
1383
|
*/
|
|
847
|
-
findById(id: Infer<
|
|
1384
|
+
findById(id: Infer<TQuery>[PK]): Entity<Infer<TQuery>, Mat, TS> | null;
|
|
848
1385
|
/** Internal findById without event emission - used by update() */
|
|
849
1386
|
private _findByIdRaw;
|
|
850
1387
|
/**
|
|
@@ -864,7 +1401,17 @@ declare class Repository<
|
|
|
864
1401
|
* const orders = orm.orders.findMany({ include: ["lineItems"] });
|
|
865
1402
|
* ```
|
|
866
1403
|
*/
|
|
867
|
-
findMany
|
|
1404
|
+
findMany<
|
|
1405
|
+
const S extends readonly SelectableKeys<TQuery>[],
|
|
1406
|
+
const I extends readonly SubTableKeys<TQuery>[]
|
|
1407
|
+
>(opts: FindOptions<TQuery> & {
|
|
1408
|
+
select: S;
|
|
1409
|
+
include: I;
|
|
1410
|
+
}): (SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] })[];
|
|
1411
|
+
findMany<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
|
|
1412
|
+
select: S;
|
|
1413
|
+
}): (SelectShape<TQuery, S> & TS)[];
|
|
1414
|
+
findMany(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS>[];
|
|
868
1415
|
/**
|
|
869
1416
|
* Find many with total count - useful for pagination.
|
|
870
1417
|
*
|
|
@@ -882,7 +1429,43 @@ declare class Repository<
|
|
|
882
1429
|
* // page.limit, page.offset - what you passed in
|
|
883
1430
|
* ```
|
|
884
1431
|
*/
|
|
885
|
-
findPage
|
|
1432
|
+
findPage<
|
|
1433
|
+
const S extends readonly SelectableKeys<TQuery>[],
|
|
1434
|
+
const I extends readonly SubTableKeys<TQuery>[]
|
|
1435
|
+
>(opts: FindOptions<TQuery> & {
|
|
1436
|
+
select: S;
|
|
1437
|
+
include: I;
|
|
1438
|
+
}): PageResult<SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
|
|
1439
|
+
findPage<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
|
|
1440
|
+
select: S;
|
|
1441
|
+
}): PageResult<SelectShape<TQuery, S> & TS>;
|
|
1442
|
+
findPage(opts?: FindOptions<TQuery>): PageResult<Entity<Infer<TQuery>, Mat, TS>>;
|
|
1443
|
+
/**
|
|
1444
|
+
* Cursor-based pagination (seek method). Avoids OFFSET degradation on
|
|
1445
|
+
* large tables by using a boundary value from the previous page.
|
|
1446
|
+
*
|
|
1447
|
+
* @group Reading
|
|
1448
|
+
*
|
|
1449
|
+
* @example
|
|
1450
|
+
* ```ts
|
|
1451
|
+
* const page = orm.orders.findCursorPage({
|
|
1452
|
+
* orderBy: { column: "DocumentDate", direction: "DESC" },
|
|
1453
|
+
* limit: 25,
|
|
1454
|
+
* });
|
|
1455
|
+
*
|
|
1456
|
+
* const next = orm.orders.findCursorPage({
|
|
1457
|
+
* orderBy: { column: "DocumentDate", direction: "DESC" },
|
|
1458
|
+
* cursor: page.nextCursor!,
|
|
1459
|
+
* limit: 25,
|
|
1460
|
+
* });
|
|
1461
|
+
* ```
|
|
1462
|
+
*/
|
|
1463
|
+
findCursorPage(opts: {
|
|
1464
|
+
where?: WhereClause<TQuery>;
|
|
1465
|
+
orderBy: OrderByClause<TQuery>;
|
|
1466
|
+
cursor?: CursorInput;
|
|
1467
|
+
limit?: number;
|
|
1468
|
+
}): CursorPageResult<Entity<Infer<TQuery>, Mat, TS>>;
|
|
886
1469
|
/**
|
|
887
1470
|
* Find a single record matching the given filters. Equivalent to `findMany`
|
|
888
1471
|
* with `limit: 1`, but returns the entity directly (or `null`).
|
|
@@ -896,7 +1479,45 @@ declare class Repository<
|
|
|
896
1479
|
* });
|
|
897
1480
|
* ```
|
|
898
1481
|
*/
|
|
899
|
-
findOne
|
|
1482
|
+
findOne<
|
|
1483
|
+
const S extends readonly SelectableKeys<TQuery>[],
|
|
1484
|
+
const I extends readonly SubTableKeys<TQuery>[]
|
|
1485
|
+
>(opts: FindOptions<TQuery> & {
|
|
1486
|
+
select: S;
|
|
1487
|
+
include: I;
|
|
1488
|
+
}): (SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] }) | null;
|
|
1489
|
+
findOne<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
|
|
1490
|
+
select: S;
|
|
1491
|
+
}): (SelectShape<TQuery, S> & TS) | null;
|
|
1492
|
+
findOne(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS> | null;
|
|
1493
|
+
/**
|
|
1494
|
+
* Iterate over records matching the given filters, yielding one row at a time.
|
|
1495
|
+
* Sub-tables are hydrated in windows to keep memory stable.
|
|
1496
|
+
*
|
|
1497
|
+
* @group Reading
|
|
1498
|
+
*
|
|
1499
|
+
* @example
|
|
1500
|
+
* ```ts
|
|
1501
|
+
* for (const user of orm.users.iterate({ where: { active: { eq: true } } })) {
|
|
1502
|
+
* console.log(user.name);
|
|
1503
|
+
* }
|
|
1504
|
+
* ```
|
|
1505
|
+
*/
|
|
1506
|
+
iterate<
|
|
1507
|
+
const S extends readonly SelectableKeys<TQuery>[],
|
|
1508
|
+
const I extends readonly SubTableKeys<TQuery>[]
|
|
1509
|
+
>(opts: FindOptions<TQuery> & {
|
|
1510
|
+
select: S;
|
|
1511
|
+
include: I;
|
|
1512
|
+
}): Generator<SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
|
|
1513
|
+
iterate<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
|
|
1514
|
+
include: I;
|
|
1515
|
+
}): Generator<Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
|
|
1516
|
+
iterate<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
|
|
1517
|
+
select: S;
|
|
1518
|
+
}): Generator<SelectShape<TQuery, S> & TS>;
|
|
1519
|
+
iterate(opts?: FindOptions<TQuery>): Generator<Entity<Infer<TQuery>, Mat, TS>>;
|
|
1520
|
+
private _hydrateWindow;
|
|
900
1521
|
/**
|
|
901
1522
|
* Find many with resolved relations (n+1 safe). If you have cross-table
|
|
902
1523
|
* relations configured, this eagerly loads them in a single batch query.
|
|
@@ -911,7 +1532,7 @@ declare class Repository<
|
|
|
911
1532
|
* }
|
|
912
1533
|
* ```
|
|
913
1534
|
*/
|
|
914
|
-
findManyMaterialized(opts?: FindOptions<
|
|
1535
|
+
findManyMaterialized(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS>[];
|
|
915
1536
|
/**
|
|
916
1537
|
* Count records matching the given filters.
|
|
917
1538
|
*
|
|
@@ -923,7 +1544,54 @@ declare class Repository<
|
|
|
923
1544
|
* const adults = orm.users.count({ age: { gte: 18 } });
|
|
924
1545
|
* ```
|
|
925
1546
|
*/
|
|
926
|
-
count(where?: WhereClause<
|
|
1547
|
+
count(where?: WhereClause<TQuery>): number;
|
|
1548
|
+
/**
|
|
1549
|
+
* Run aggregate queries (sum, count, avg, min, max) with optional
|
|
1550
|
+
* grouping and filtering.
|
|
1551
|
+
*
|
|
1552
|
+
* @group Reading
|
|
1553
|
+
*
|
|
1554
|
+
* @example
|
|
1555
|
+
* ```ts
|
|
1556
|
+
* orm.orders.aggregate({
|
|
1557
|
+
* aggregations: { total: { sum: "amount" } },
|
|
1558
|
+
* });
|
|
1559
|
+
*
|
|
1560
|
+
* orm.orders.aggregate({
|
|
1561
|
+
* groupBy: ["status"],
|
|
1562
|
+
* aggregations: { count: { count: "*" }, avgAmount: { avg: "amount" } },
|
|
1563
|
+
* });
|
|
1564
|
+
* ```
|
|
1565
|
+
*/
|
|
1566
|
+
aggregate<
|
|
1567
|
+
const A extends Record<string, AggregationOp<TQuery>>,
|
|
1568
|
+
const G extends readonly (ScalarKeys<TQuery> | ScalarJsonPath<TQuery>)[] | undefined = undefined
|
|
1569
|
+
>(opts: AggregateOptions<TQuery, A> & {
|
|
1570
|
+
groupBy?: G;
|
|
1571
|
+
}): AggregateResult<TQuery, A, G>;
|
|
1572
|
+
/**
|
|
1573
|
+
* Run window function queries (rowNumber, rank, denseRank, lead, lag)
|
|
1574
|
+
* with partitioning and ordering.
|
|
1575
|
+
*
|
|
1576
|
+
* @group Reading
|
|
1577
|
+
*
|
|
1578
|
+
* @example
|
|
1579
|
+
* ```ts
|
|
1580
|
+
* orm.orders.windowQuery({
|
|
1581
|
+
* partitionBy: ["Status__Group"],
|
|
1582
|
+
* orderBy: [{ column: "DocumentDate", direction: "DESC" }],
|
|
1583
|
+
* select: {
|
|
1584
|
+
* rowNumber: { rowNumber: true },
|
|
1585
|
+
* rank: { rank: true },
|
|
1586
|
+
* leadTotal: { lead: "TotalTurnover", offset: 1 },
|
|
1587
|
+
* },
|
|
1588
|
+
* limit: 100,
|
|
1589
|
+
* });
|
|
1590
|
+
* ```
|
|
1591
|
+
*/
|
|
1592
|
+
windowQuery<const W extends Record<string, WindowFunction<TQuery>>>(opts: WindowQueryOptions<TQuery> & {
|
|
1593
|
+
select: W;
|
|
1594
|
+
}): WindowResult<TQuery, W>;
|
|
927
1595
|
/**
|
|
928
1596
|
* Update a record - must include the primary key. Returns the updated
|
|
929
1597
|
* entity, or `null` if no record matched.
|
|
@@ -935,7 +1603,22 @@ declare class Repository<
|
|
|
935
1603
|
* orm.users.update({ id: "u1", name: "alice smith" });
|
|
936
1604
|
* ```
|
|
937
1605
|
*/
|
|
938
|
-
update(data: UpdateData<
|
|
1606
|
+
update(data: UpdateData<TWrite, PK>): Entity<Infer<TQuery>, Mat, TS> | null;
|
|
1607
|
+
/**
|
|
1608
|
+
* Update multiple records matching the given filters.
|
|
1609
|
+
* Returns the number of rows changed.
|
|
1610
|
+
*
|
|
1611
|
+
* @group Writing
|
|
1612
|
+
*
|
|
1613
|
+
* @example
|
|
1614
|
+
* ```ts
|
|
1615
|
+
* orm.users.updateWhere({
|
|
1616
|
+
* where: { status: { eq: "pending" } },
|
|
1617
|
+
* data: { status: { group: "completed" } },
|
|
1618
|
+
* });
|
|
1619
|
+
* ```
|
|
1620
|
+
*/
|
|
1621
|
+
updateWhere(opts: UpdateWhereOptions<TWrite, PK>): number;
|
|
939
1622
|
/**
|
|
940
1623
|
* Delete a record by its primary key. Returns `true` if a record was deleted.
|
|
941
1624
|
*
|
|
@@ -946,7 +1629,7 @@ declare class Repository<
|
|
|
946
1629
|
* const deleted = orm.users.deleteById("u1");
|
|
947
1630
|
* ```
|
|
948
1631
|
*/
|
|
949
|
-
deleteById(id: Infer<
|
|
1632
|
+
deleteById(id: Infer<TWrite>[PK]): boolean;
|
|
950
1633
|
/**
|
|
951
1634
|
* Delete records matching the given filters. Returns the number of rows deleted.
|
|
952
1635
|
*
|
|
@@ -957,7 +1640,7 @@ declare class Repository<
|
|
|
957
1640
|
* const removed = orm.users.deleteWhere({ status: { eq: "banned" } });
|
|
958
1641
|
* ```
|
|
959
1642
|
*/
|
|
960
|
-
deleteWhere(where: WhereClause<
|
|
1643
|
+
deleteWhere(where: WhereClause<TQuery>): number;
|
|
961
1644
|
/**
|
|
962
1645
|
* Truncate the table and all sub-tables. Deletes all rows but keeps the schema.
|
|
963
1646
|
*
|
|
@@ -993,9 +1676,9 @@ declare class Repository<
|
|
|
993
1676
|
* );
|
|
994
1677
|
* ```
|
|
995
1678
|
*/
|
|
996
|
-
raw<R =
|
|
1679
|
+
raw<R = DBRow>(sql: string, ...params: DBValue[]): R[];
|
|
997
1680
|
}
|
|
998
|
-
declare class RelationBuilder<Tables extends Record<string,
|
|
1681
|
+
declare class RelationBuilder<Tables extends Record<string, TableDescriptor<any, any, any, any>>> {
|
|
999
1682
|
private readonly tables;
|
|
1000
1683
|
private readonly relations;
|
|
1001
1684
|
constructor(tables: Tables);
|
|
@@ -1025,16 +1708,14 @@ declare class RelationBuilder<Tables extends Record<string, TableConfig<any, any
|
|
|
1025
1708
|
build(): TypedRelation[];
|
|
1026
1709
|
}
|
|
1027
1710
|
/** @category Relations */
|
|
1028
|
-
declare function createRelationBuilder<T extends Record<string,
|
|
1711
|
+
declare function createRelationBuilder<T extends Record<string, TableDescriptor<any, any, any, any>>>(tables: T): RelationBuilder<T>;
|
|
1029
1712
|
import { Static as Static2 } from "typebox";
|
|
1030
1713
|
declare const SchemaHashSchema: unknown;
|
|
1031
|
-
/** @category Database */
|
|
1032
1714
|
declare const SchemaJSONSchema: unknown;
|
|
1033
1715
|
declare const TablesSchema: unknown;
|
|
1034
1716
|
declare const RelationsSchema: unknown;
|
|
1035
1717
|
declare const VersionSchema: unknown;
|
|
1036
1718
|
type SchemaHash = Static2<typeof SchemaHashSchema>;
|
|
1037
|
-
/** @category Database */
|
|
1038
1719
|
type SchemaJSON = Static2<typeof SchemaJSONSchema>;
|
|
1039
1720
|
type TablesList = Static2<typeof TablesSchema>;
|
|
1040
1721
|
type RelationsList = Static2<typeof RelationsSchema>;
|
|
@@ -1051,7 +1732,7 @@ declare class MetaStore {
|
|
|
1051
1732
|
private getRow;
|
|
1052
1733
|
private setRow;
|
|
1053
1734
|
private getValidatedJSON;
|
|
1054
|
-
private
|
|
1735
|
+
private validateAndSetJSON;
|
|
1055
1736
|
getString(key: string): string | null;
|
|
1056
1737
|
setString(key: string, value: string): void;
|
|
1057
1738
|
getJSON<T>(key: string): T | null;
|
|
@@ -1075,7 +1756,7 @@ declare class MetaStore {
|
|
|
1075
1756
|
* @category Lifecycle
|
|
1076
1757
|
*/
|
|
1077
1758
|
interface ORMContext<
|
|
1078
|
-
T extends Record<string,
|
|
1759
|
+
T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
|
|
1079
1760
|
Rels extends readonly TypedRelation[] = readonly TypedRelation[]
|
|
1080
1761
|
> {
|
|
1081
1762
|
orm: foxdb<T, Rels>;
|
|
@@ -1093,7 +1774,7 @@ interface ORMContext<
|
|
|
1093
1774
|
* @category Lifecycle
|
|
1094
1775
|
*/
|
|
1095
1776
|
type LifecycleHook<
|
|
1096
|
-
T extends Record<string,
|
|
1777
|
+
T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
|
|
1097
1778
|
Rels extends readonly TypedRelation[] = readonly TypedRelation[]
|
|
1098
1779
|
> = (ctx: ORMContext<T, Rels>) => void | Promise<void>;
|
|
1099
1780
|
/**
|
|
@@ -1101,7 +1782,7 @@ type LifecycleHook<
|
|
|
1101
1782
|
* @category Lifecycle
|
|
1102
1783
|
*/
|
|
1103
1784
|
declare class LifecycleManager<
|
|
1104
|
-
T extends Record<string,
|
|
1785
|
+
T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
|
|
1105
1786
|
Rels extends readonly TypedRelation[] = readonly TypedRelation[]
|
|
1106
1787
|
> {
|
|
1107
1788
|
private startHooks;
|
|
@@ -1142,6 +1823,10 @@ interface CreateORMBaseOptions {
|
|
|
1142
1823
|
busyTimeout?: number;
|
|
1143
1824
|
synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA";
|
|
1144
1825
|
mmapSize?: number;
|
|
1826
|
+
autoVacuum?: "incremental" | "full" | false;
|
|
1827
|
+
vacuumIntervalMs?: number;
|
|
1828
|
+
/** disable fsync during large initial loads */
|
|
1829
|
+
bulkLoadMode?: boolean;
|
|
1145
1830
|
}
|
|
1146
1831
|
/**
|
|
1147
1832
|
* Options passed to `createORM`.
|
|
@@ -1172,7 +1857,7 @@ interface CreateORMBaseOptions {
|
|
|
1172
1857
|
* ```
|
|
1173
1858
|
*/
|
|
1174
1859
|
interface CreateORMOptions<
|
|
1175
|
-
T extends Record<string,
|
|
1860
|
+
T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
|
|
1176
1861
|
Rels extends readonly TypedRelation[] = readonly TypedRelation[]
|
|
1177
1862
|
> extends CreateORMBaseOptions {
|
|
1178
1863
|
/** table schemas */
|
|
@@ -1215,6 +1900,8 @@ interface CreateORMOptions<
|
|
|
1215
1900
|
errorPolicy?: ErrorPolicy;
|
|
1216
1901
|
/** delete db files on exit */
|
|
1217
1902
|
unlinkDbFilesOnExit?: UnlinkPolicy;
|
|
1903
|
+
/** observability hooks */
|
|
1904
|
+
hooks?: QueryMetricsHook;
|
|
1218
1905
|
}
|
|
1219
1906
|
/**
|
|
1220
1907
|
* The ORM object returned by `createORM`.
|
|
@@ -1266,15 +1953,19 @@ interface CreateORMOptions<
|
|
|
1266
1953
|
* ```
|
|
1267
1954
|
*/
|
|
1268
1955
|
type foxdb<
|
|
1269
|
-
Tables extends Record<string,
|
|
1956
|
+
Tables extends Record<string, TableDescriptor<any, any, any, any>>,
|
|
1270
1957
|
Rels extends readonly TypedRelation[] = readonly TypedRelation[]
|
|
1271
|
-
> = { [K in keyof Tables] : Tables[K] extends
|
|
1958
|
+
> = { [K in keyof Tables] : Tables[K] extends TableDescriptor<infer TWrite extends TSchema6 & {
|
|
1959
|
+
properties: Record<string, TSchema6>;
|
|
1960
|
+
}, infer PKName extends string, infer Timestamps, infer G extends GeneratedColumnConfig | undefined> ? Repository<TWrite, QuerySchema<TWrite, G>, PKName extends ScalarKeys<TWrite> ? PKName : never, Materialized<TWrite, Tables, Rels, K & string>, TimestampShape<Timestamps>> : never } & {
|
|
1272
1961
|
/** run a transaction */
|
|
1273
1962
|
_transaction<R>(fn: () => R): R;
|
|
1274
1963
|
/** close the database */
|
|
1275
1964
|
_close(): void;
|
|
1276
1965
|
/** read-only metadata */
|
|
1277
1966
|
_meta: MetaAccessors;
|
|
1967
|
+
/** toggle bulk-load mode (disables synchronous fsync) */
|
|
1968
|
+
_setBulkLoadMode(enabled: boolean): void;
|
|
1278
1969
|
/** resolve relations for a single record */
|
|
1279
1970
|
_materialize<Owner extends keyof Tables & string>(ownerTable: Owner, record: Record<string, unknown>): Record<string, unknown>;
|
|
1280
1971
|
/** resolve relations for many records (n+1 safe) */
|
|
@@ -1290,69 +1981,9 @@ type foxdb<
|
|
|
1290
1981
|
};
|
|
1291
1982
|
/** create a typed orm instance backed by sqlite */
|
|
1292
1983
|
declare function createORM<
|
|
1293
|
-
const T extends Record<string,
|
|
1984
|
+
const T extends Record<string, TableDescriptor<any, any, any, any>>,
|
|
1294
1985
|
const Rels extends readonly TypedRelation[] = readonly TypedRelation[]
|
|
1295
1986
|
>(opts: CreateORMOptions<T, Rels>): foxdb<T, Rels>;
|
|
1296
|
-
import { TObject as TObject5 } from "typebox";
|
|
1297
|
-
/** @category Schema */
|
|
1298
|
-
interface SubTableConfig {
|
|
1299
|
-
indexes?: IndexDefinition[];
|
|
1300
|
-
}
|
|
1301
|
-
/** @category Schema */
|
|
1302
|
-
interface TableDescriptor<
|
|
1303
|
-
T extends TObject5,
|
|
1304
|
-
PK extends string,
|
|
1305
|
-
TS extends TimestampConfig = undefined
|
|
1306
|
-
> extends TableConfig<T, PK, TS> {}
|
|
1307
|
-
/** @category Schema */
|
|
1308
|
-
interface TableConfigShape<
|
|
1309
|
-
PK extends string,
|
|
1310
|
-
TS extends TimestampConfig
|
|
1311
|
-
> {
|
|
1312
|
-
primaryKey: ColumnRef<PK>;
|
|
1313
|
-
indexes?: IndexDefinition[];
|
|
1314
|
-
subTables?: Partial<Record<string, SubTableConfig>>;
|
|
1315
|
-
timestamps?: TS;
|
|
1316
|
-
}
|
|
1317
|
-
/**
|
|
1318
|
-
* Describe a table schema + config for `createORM`.
|
|
1319
|
-
*
|
|
1320
|
-
* @example
|
|
1321
|
-
* ```ts
|
|
1322
|
-
* const UserSchema = Object({ id: String(), name: String(), email: String() });
|
|
1323
|
-
*
|
|
1324
|
-
* const users = table(UserSchema, (s) => ({
|
|
1325
|
-
* primaryKey: s.id,
|
|
1326
|
-
* indexes: [{ columns: [s.email], unique: true }],
|
|
1327
|
-
* timestamps: true, // adds createdAt / updatedAt
|
|
1328
|
-
* }));
|
|
1329
|
-
* ```
|
|
1330
|
-
* @category Schema
|
|
1331
|
-
* @category Schema
|
|
1332
|
-
*/
|
|
1333
|
-
declare function table<
|
|
1334
|
-
T extends TObject5,
|
|
1335
|
-
PK extends string,
|
|
1336
|
-
const TS extends boolean
|
|
1337
|
-
>(schema: T, configure: (columns: ColumnRefs<T>) => TableConfigShape<PK, TS> & {
|
|
1338
|
-
timestamps: TS;
|
|
1339
|
-
}): TableDescriptor<T, PK, TS>;
|
|
1340
|
-
/** @category Schema */
|
|
1341
|
-
declare function table<
|
|
1342
|
-
T extends TObject5,
|
|
1343
|
-
PK extends string,
|
|
1344
|
-
const TS extends {
|
|
1345
|
-
createdAt?: string;
|
|
1346
|
-
updatedAt?: string;
|
|
1347
|
-
}
|
|
1348
|
-
>(schema: T, configure: (columns: ColumnRefs<T>) => TableConfigShape<PK, TS> & {
|
|
1349
|
-
timestamps: TS;
|
|
1350
|
-
}): TableDescriptor<T, PK, TS>;
|
|
1351
|
-
/** @category Schema */
|
|
1352
|
-
declare function table<
|
|
1353
|
-
T extends TObject5,
|
|
1354
|
-
PK extends string
|
|
1355
|
-
>(schema: T, configure: (columns: ColumnRefs<T>) => TableConfigShape<PK, undefined>): TableDescriptor<T, PK, undefined>;
|
|
1356
1987
|
declare function migrate(opts: MigrateOptions): Promise<void>;
|
|
1357
1988
|
/** @category Migration */
|
|
1358
1989
|
declare function createMigration(name: string, migrationsDir: string): string;
|
|
@@ -1460,4 +2091,4 @@ interface DesiredTable {
|
|
|
1460
2091
|
declare function computeDiff(desired: DesiredTable[], actual: InspectorTable[]): SchemaDiff;
|
|
1461
2092
|
/** @category Migration */
|
|
1462
2093
|
declare function applySync(diff: SchemaDiff, db: BunDatabase, policy: SyncPolicy, desired: DesiredTable[]): void;
|
|
1463
|
-
export { withTrace, table, resolveTimestampNames, raise, migrate, introspectTable, inspectSchema, inspectAllTables, foxdb, createRelationBuilder, createORM, createMigration, computeDiff, buildCreateTableSQL, applySync, WhereClause, UpsertOptions, UpdateData, UnlinkPolicy, TypedRelation, TraceEntry, TimestampShape, TimestampConfig2 as TimestampNamesConfig, TableOperation, TableMeta, TableEventPayload, TableEventOperation, TableDescriptor, TableConfigShape, TableConfig, TScalarSchema, SyncPolicy, SubTableScalarPath, SubTableMeta, SubTableKeys, SubTableConfig, SubMergeType, SubMergeNames, SubMerge, SqliteType, SchemaJSONSchema, SchemaJSON, SchemaDiff, SchemaChange, ScalarProperties, ScalarPath, ScalarMergeType, ScalarMergeNames, ScalarMerge, ScalarKeys, ScalarFilter, Repository, RelationsConfig, RelationEntry, RelationBuilder, PageResult, OrderByClause, ORMEvents, ORMErrorContext, ORMError, ORMContext, Migration, MigrateOptions, MetaStore, Materialized, Listener, LifecycleManager, LifecycleHook, LifecycleEventMap, InspectorTable, InspectorIndex, InspectorColumn, InsertData, Infer, IndexDefinition, FindOptions, EventBus, ErrorPolicy2 as ErrorPolicy, Entity, DesiredTable, DatabaseOptions, DEFAULT_TIMESTAMP_NAMES, CreateORMOptions, CreateORMBaseOptions, ColumnRefs, ColumnRef, ColumnMeta, BunStatement, BunDatabase, BroadOperation, ArrayOfObjectProperties };
|
|
2094
|
+
export { withTrace, table, resolveTimestampNames, raise, migrate, introspectTable, inspectSchema, inspectAllTables, foxdb, createRelationBuilder, createORM, createMigration, computeDiff, buildCreateTableSQL, applySync, WhereClause, UpsertOptions, UpdateData, UnlinkPolicy, TypedRelation, TraceEntry, TimestampShape, TimestampConfig2 as TimestampNamesConfig, TableOperation, TableMeta, TableEventPayload, TableEventOperation, TableDescriptor, TableConfigShape, TableConfig, TScalarSchema, SyncPolicy, SubTableScalarPath, SubTableMeta, SubTableKeys, SubTableConfig, SubMergeType, SubMergeNames, SubMerge, SqliteType, SchemaJSONSchema, SchemaJSON, SchemaDiff, SchemaChange, ScalarProperties, ScalarPath, ScalarMergeType, ScalarMergeNames, ScalarMerge, ScalarKeys, ScalarFilter, Repository, RelationsConfig, RelationEntry, RelationBuilder, QueryMetricsHook, QueryMetrics, PageResult, OrderByClause, ORMEvents, ORMErrorContext, ORMError, ORMContext, Migration, MigrateOptions, MetaStore, Materialized, Listener, LifecycleManager, LifecycleHook, LifecycleEventMap, InspectorTable, InspectorIndex, InspectorColumn, InsertData, Infer, IndexDefinition, GeneratedColumnConfig, FindOptions, EventBus, ErrorPolicy2 as ErrorPolicy, Entity, DesiredTable, DatabaseOptions, DEFAULT_TIMESTAMP_NAMES, CreateORMOptions, CreateORMBaseOptions, ColumnRefs, ColumnRef, ColumnMeta, BunStatement, BunDatabase, BroadOperation, BatchWriterOptions, BatchWriter, ArrayOfObjectProperties, AggregationOp, AggregateOptions };
|