@xwxfox/foxdb 0.0.1 → 0.1.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/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
- import { TObject as TObject2, TArray, TSchema, TProperties, Static } from "typebox";
2
- import { TObject, TString, TNumber, TInteger, TBoolean, TLiteral } from "typebox";
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 TObject> = { 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 };
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, SQLQueryBindings } from "bun:sqlite";
56
+ import { Database, Statement } from "bun:sqlite";
43
57
  /**
44
58
  * prepared sqlite statement
45
59
  * @category Database
46
60
  */
47
- interface BunStatement {
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<TObject2> ? K : never] : P[K] extends TArray<infer Item> ? Item : never };
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 TObject2> = keyof ScalarProperties<T["properties"]> & string;
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 TObject2> = keyof ArrayOfObjectProperties<T["properties"]> & string;
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 TObject2> = { [K in SubTableKeys<T>] : T["properties"][K] extends TArray<infer Item> ? Item extends TObject2 ? `${K}.${ScalarKeys<Item>}` : never : never }[SubTableKeys<T>];
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 TObject2> = ScalarKeys<T> | SubTableScalarPath<T>;
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 TSchema> = Static<T>;
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> = V extends string ? {
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,11 +329,57 @@ 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
  } | {
179
343
  isNotNull: true;
180
344
  };
345
+ /** @category Query Types */
346
+ type ArrayFilter<V> = {
347
+ /** matches if at least one element in the array equals this value */
348
+ arraySome?: V;
349
+ /** matches if no element in the array equals this value */
350
+ arrayNot?: V;
351
+ /** matches if the array is empty (length 0 or NULL) */
352
+ isEmpty?: boolean;
353
+ /**
354
+ * HIGH PERFORMANCE: matches if at least one element in the array equals this value.
355
+ * Uses string-based matching which is significantly faster than JSON parsing but
356
+ * sensitive to JSON formatting/whitespace.
357
+ */
358
+ fastArraySome?: V;
359
+ /**
360
+ * HIGH PERFORMANCE: matches if no element in the array equals this value.
361
+ * Uses string-based matching which is significantly faster than JSON parsing but
362
+ * sensitive to JSON formatting/whitespace.
363
+ */
364
+ fastArrayNot?: V;
365
+ /**
366
+ * HIGH PERFORMANCE: matches if the array is empty ('[]' or NULL).
367
+ * Significantly faster than isEmpty and can be indexed with a standard index.
368
+ */
369
+ fastArrayIsEmpty?: boolean;
370
+ /** matches if the entire array equals this value */
371
+ eq?: V[];
372
+ /** matches if the entire array does not equal this value */
373
+ ne?: V[];
374
+ /** matches if the column is NULL */
375
+ isNull?: true;
376
+ /** matches if the column is NOT NULL */
377
+ isNotNull?: true;
378
+ /** matches if the entire array is in the list of arrays */
379
+ in?: V[][];
380
+ /** matches if the entire array is not in the list of arrays */
381
+ notIn?: V[][];
382
+ };
181
383
  /**
182
384
  * Where filters for queries - only scalar columns are filterable.
183
385
  *
@@ -187,6 +389,10 @@ type ScalarFilter<V> = V extends string ? {
187
389
  * orm.users.findMany({ where: { name: { like: "%alice%" } } });
188
390
  * orm.users.findMany({ where: { email: { in: ["a@x.com", "b@x.com"] } } });
189
391
  *
392
+ * // Array filters
393
+ * orm.users.findMany({ where: { tags: { arraySome: "typescript" } } });
394
+ * orm.users.findMany({ where: { scores: { isEmpty: true } } });
395
+ *
190
396
  * // Number filters
191
397
  * orm.users.findMany({ where: { age: { gte: 18, lte: 65 } } });
192
398
  * orm.products.findMany({ where: { price: { between: [10, 100] } } });
@@ -198,13 +404,25 @@ type ScalarFilter<V> = V extends string ? {
198
404
  * @category Query Types
199
405
  * @category Query Types
200
406
  */
201
- type WhereClause<T extends TObject2> = { [K in ScalarKeys<T>]? : ScalarFilter<Static<T["properties"][K]>> };
407
+ type WhereClause<T extends TSchema2 & {
408
+ properties: Record<string, TSchema2>;
409
+ }> = { [K in ScalarKeys<T>]? : ScalarFilter<Static<T["properties"][K]>> } & { [K in ObjectKeys<T>]? : ScalarFilter<Static<T["properties"][K]>> } & { [K in PrimitiveArrayKeys<T>]? : ArrayFilter<Static<UnwrapOptional<T["properties"][K]> extends TArray<infer Item> ? Item : never>> } & { [K in JsonPath<T>]? : PathValue<T, K> extends Array<infer Item> ? ArrayFilter<Item> : ScalarFilter<PathValue<T, K>> } & {
410
+ AND?: WhereClause<T>[];
411
+ OR?: WhereClause<T>[];
412
+ NOT?: WhereClause<T>;
413
+ _raw?: {
414
+ sql: string;
415
+ params: unknown[];
416
+ };
417
+ };
202
418
  /**
203
419
  * sort direction for queries
204
420
  * @category Query Types
205
421
  */
206
- type OrderByClause<T extends TObject2> = {
207
- column: ScalarKeys<T>;
422
+ type OrderByClause<T extends TSchema2 & {
423
+ properties: Record<string, TSchema2>;
424
+ }> = {
425
+ column: ScalarKeys<T> | ScalarJsonPath<T>;
208
426
  direction?: "ASC" | "DESC";
209
427
  };
210
428
  /**
@@ -215,6 +433,18 @@ interface PaginationOptions {
215
433
  limit?: number;
216
434
  offset?: number;
217
435
  }
436
+ interface Cursor {
437
+ column: string;
438
+ value: SqliteScalar;
439
+ }
440
+ interface CursorInput extends Cursor {
441
+ direction: "next" | "prev";
442
+ }
443
+ interface CursorPageResult<T> {
444
+ data: T[];
445
+ nextCursor: Cursor | null;
446
+ prevCursor: Cursor | null;
447
+ }
218
448
  /**
219
449
  * Options for `findMany`, `findPage`, and `findOne`.
220
450
  *
@@ -241,22 +471,36 @@ interface PaginationOptions {
241
471
  * @category Query Types
242
472
  * @category Query Types
243
473
  */
244
- interface FindOptions<T extends TObject2> extends PaginationOptions {
474
+ /** @internal */
475
+ type SelectableKeys<T extends TSchema2 & {
476
+ properties: Record<string, TSchema2>;
477
+ }> = ScalarKeys<T> | ObjectKeys<T> | PrimitiveArrayKeys<T> | JsonPath<T>;
478
+ interface FindOptions<T extends TSchema2 & {
479
+ properties: Record<string, TSchema2>;
480
+ }> extends PaginationOptions {
245
481
  where?: WhereClause<T>;
246
482
  orderBy?: OrderByClause<T> | OrderByClause<T>[];
247
483
  include?: SubTableKeys<T>[];
484
+ select?: SelectableKeys<T>[];
485
+ includeDeleted?: boolean;
486
+ distinct?: boolean;
487
+ distinctOn?: (ScalarKeys<T> | ScalarJsonPath<T>)[];
248
488
  }
249
489
  /**
250
490
  * full record to insert
251
491
  * @category Query Types
252
492
  */
253
- type InsertData<T extends TObject2> = Infer<T>;
493
+ type InsertData<T extends TSchema2 & {
494
+ properties: Record<string, TSchema2>;
495
+ }> = Infer<T>;
254
496
  /**
255
497
  * update payload - must include the primary key
256
498
  * @category Query Types
257
499
  */
258
500
  type UpdateData<
259
- T extends TObject2,
501
+ T extends TSchema2 & {
502
+ properties: Record<string, TSchema2>;
503
+ },
260
504
  PK extends ScalarKeys<T>
261
505
  > = Pick<Infer<T>, PK> & Partial<Omit<Infer<T>, PK>>;
262
506
  /**
@@ -265,8 +509,14 @@ type UpdateData<
265
509
  */
266
510
  interface IndexDefinition {
267
511
  name?: string;
268
- columns: ColumnRef<string, TScalarSchema>[];
512
+ columns: Array<ColumnRef<string, TScalarSchema> | {
513
+ name: string;
514
+ }>;
269
515
  unique?: boolean;
516
+ where?: string;
517
+ include?: Array<ColumnRef<string, TScalarSchema> | {
518
+ name: string;
519
+ }>;
270
520
  }
271
521
  /**
272
522
  * timestamp configuration for a table
@@ -318,10 +568,47 @@ type Entity<
318
568
  * table descriptor passed to createORM
319
569
  * @category Schema
320
570
  */
571
+ interface EvictionConfig {
572
+ maxRows?: number;
573
+ ttlColumn?: string;
574
+ ttlMs?: number;
575
+ lruColumn?: string;
576
+ }
577
+ interface CompressionConfig {
578
+ columns: ColumnRef<string, TScalarSchema>[];
579
+ algorithm: "gzip" | "none";
580
+ }
581
+ interface SoftDeleteConfig {
582
+ column: string;
583
+ }
584
+ type GeneratedColumnConfig = {
585
+ [name: string]: {
586
+ expr: string;
587
+ type: TSchema2;
588
+ };
589
+ };
590
+ type GeneratedColumnValues<C extends GeneratedColumnConfig> = { [K in keyof C & string] : Static<C[K]["type"]> };
591
+ type AugmentSchema<
592
+ T extends TSchema2 & {
593
+ properties: Record<string, TSchema2>;
594
+ },
595
+ G extends GeneratedColumnConfig
596
+ > = TObject2<T["properties"] & GeneratedColumnValues<G>>;
597
+ type QuerySchema<
598
+ T extends TSchema2 & {
599
+ properties: Record<string, TSchema2>;
600
+ },
601
+ G extends GeneratedColumnConfig | undefined
602
+ > = [G] extends [undefined] ? T : [G] extends [GeneratedColumnConfig] ? AugmentSchema<T, G> : T;
321
603
  interface TableConfig<
322
- T extends TObject2 = TObject2,
604
+ T extends TSchema2 & {
605
+ properties: Record<string, TSchema2>;
606
+ } = TSchema2 & {
607
+ properties: Record<string, TSchema2>;
608
+ },
323
609
  PK extends string = string,
324
- TS extends TimestampConfig = undefined
610
+ TS extends TimestampConfig = undefined,
611
+ G extends GeneratedColumnConfig | undefined = undefined
325
612
  > {
326
613
  schema: T;
327
614
  primaryKey: ColumnRef<PK>;
@@ -330,6 +617,10 @@ interface TableConfig<
330
617
  indexes?: IndexDefinition[];
331
618
  }>>;
332
619
  timestamps?: TS;
620
+ eviction?: EvictionConfig;
621
+ compression?: CompressionConfig;
622
+ softDelete?: SoftDeleteConfig;
623
+ generated?: G;
333
624
  }
334
625
  /**
335
626
  * read-only metadata about the current database schema
@@ -347,7 +638,7 @@ interface MetaAccessors {
347
638
  * @category Relations
348
639
  */
349
640
  interface RelationEntry<
350
- Tables extends Record<string, TableConfig<any, any, any>>,
641
+ Tables extends Record<string, TableConfig<any, any, any, any>>,
351
642
  Owner extends keyof Tables,
352
643
  Target extends keyof Tables
353
644
  > {
@@ -359,7 +650,7 @@ interface RelationEntry<
359
650
  * @internal
360
651
  * @category Relations
361
652
  */
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]> };
653
+ 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
654
  /**
364
655
  * @internal
365
656
  * @category Relations
@@ -376,7 +667,7 @@ type ScalarMergeNames<
376
667
  * @category Relations
377
668
  */
378
669
  type ScalarMergeType<
379
- Tables extends Record<string, TableConfig<any, any, any>>,
670
+ Tables extends Record<string, TableConfig<any, any, any, any>>,
380
671
  Rels extends readonly TypedRelation[],
381
672
  Owner extends string,
382
673
  Name extends string
@@ -390,7 +681,7 @@ type ScalarMergeType<
390
681
  * @category Relations
391
682
  */
392
683
  type ScalarMerge<
393
- Tables extends Record<string, TableConfig<any, any, any>>,
684
+ Tables extends Record<string, TableConfig<any, any, any, any>>,
394
685
  Rels extends readonly TypedRelation[],
395
686
  Owner extends string
396
687
  > = { [K in ScalarMergeNames<Rels, Owner>] : ScalarMergeType<Tables, Rels, Owner, K> };
@@ -412,7 +703,7 @@ type SubMergeNames<
412
703
  * @category Relations
413
704
  */
414
705
  type SubMergeType<
415
- Tables extends Record<string, TableConfig<any, any, any>>,
706
+ Tables extends Record<string, TableConfig<any, any, any, any>>,
416
707
  Rels extends readonly TypedRelation[],
417
708
  Owner extends string,
418
709
  Sub extends string,
@@ -428,7 +719,7 @@ type SubMergeType<
428
719
  * @category Relations
429
720
  */
430
721
  type SubMerge<
431
- Tables extends Record<string, TableConfig<any, any, any>>,
722
+ Tables extends Record<string, TableConfig<any, any, any, any>>,
432
723
  Rels extends readonly TypedRelation[],
433
724
  Owner extends string,
434
725
  Sub extends string
@@ -450,8 +741,10 @@ type SubMerge<
450
741
  * @category Relations
451
742
  */
452
743
  type Materialized<
453
- T extends TObject2,
454
- Tables extends Record<string, TableConfig<any, any, any>>,
744
+ T extends TSchema2 & {
745
+ properties: Record<string, TSchema2>;
746
+ },
747
+ Tables extends Record<string, TableConfig<any, any, any, any>>,
455
748
  Rels extends readonly TypedRelation[],
456
749
  Owner extends string
457
750
  > = { [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 +763,9 @@ interface PageResult<T> {
470
763
  * @category Query Types
471
764
  */
472
765
  interface UpsertOptions<
473
- T extends TObject2,
766
+ T extends TSchema2 & {
767
+ properties: Record<string, TSchema2>;
768
+ },
474
769
  PK extends ScalarKeys<T>
475
770
  > {
476
771
  data: InsertData<T>;
@@ -479,6 +774,35 @@ interface UpsertOptions<
479
774
  update?: Array<ScalarKeys<T>>;
480
775
  }
481
776
  /**
777
+ * bulk conditional update
778
+ * @category Query Types
779
+ */
780
+ interface UpdateWhereOptions<
781
+ T extends TSchema2 & {
782
+ properties: Record<string, TSchema2>;
783
+ },
784
+ PK extends ScalarKeys<T>
785
+ > {
786
+ where: WhereClause<T>;
787
+ data: Partial<Omit<Infer<T>, PK>>;
788
+ includeDeleted?: boolean;
789
+ }
790
+ /**
791
+ * bulk upsert with conflict resolution
792
+ * @category Query Types
793
+ */
794
+ interface UpsertManyOptions<
795
+ T extends TSchema2 & {
796
+ properties: Record<string, TSchema2>;
797
+ },
798
+ PK extends ScalarKeys<T>
799
+ > {
800
+ data: InsertData<T>[];
801
+ conflictTarget: PK | PK[];
802
+ /** columns to update on conflict - defaults to all non-pk columns */
803
+ update?: Array<ScalarKeys<T>>;
804
+ }
805
+ /**
482
806
  * a single migration step
483
807
  * @category Migration
484
808
  */
@@ -584,11 +908,121 @@ interface SchemaDiff {
584
908
  * @category Migration
585
909
  */
586
910
  type SyncPolicy = "ignore" | "warn" | "error" | "auto" | ((diff: SchemaDiff, db: BunDatabase) => boolean | void);
911
+ /** @category Query Types */
912
+ type WindowFunction<T extends TSchema2 & {
913
+ properties: Record<string, TSchema2>;
914
+ }> = {
915
+ rowNumber: true;
916
+ } | {
917
+ rank: true;
918
+ } | {
919
+ denseRank: true;
920
+ } | {
921
+ lead: ScalarKeys<T> | ScalarJsonPath<T>;
922
+ offset?: number;
923
+ } | {
924
+ lag: ScalarKeys<T> | ScalarJsonPath<T>;
925
+ offset?: number;
926
+ };
927
+ /** @category Query Types */
928
+ interface WindowQueryOptions<T extends TSchema2 & {
929
+ properties: Record<string, TSchema2>;
930
+ }> {
931
+ partitionBy?: (ScalarKeys<T> | ScalarJsonPath<T>)[];
932
+ orderBy?: OrderByClause<T> | OrderByClause<T>[];
933
+ where?: WhereClause<T>;
934
+ limit?: number;
935
+ select: Record<string, WindowFunction<T>>;
936
+ }
937
+ /** @internal */
938
+ type WindowFunctionResult<
939
+ T extends TSchema2 & {
940
+ properties: Record<string, TSchema2>;
941
+ },
942
+ W extends WindowFunction<T>
943
+ > = W extends {
944
+ lead: infer C extends string;
945
+ } ? PathValue<T, C> | null : W extends {
946
+ lag: infer C extends string;
947
+ } ? PathValue<T, C> | null : number;
948
+ /** @category Query Types */
949
+ type WindowResult<
950
+ T extends TSchema2 & {
951
+ properties: Record<string, TSchema2>;
952
+ },
953
+ W extends Record<string, WindowFunction<T>>
954
+ > = Array<{ [K in keyof W] : WindowFunctionResult<T, W[K]> }>;
955
+ /** @category Query Types */
956
+ type AggregationOp<T extends TSchema2 & {
957
+ properties: Record<string, TSchema2>;
958
+ } = TSchema2 & {
959
+ properties: Record<string, TSchema2>;
960
+ }> = {
961
+ sum?: ScalarKeys<T> | ScalarJsonPath<T>;
962
+ } | {
963
+ count?: "*" | ScalarKeys<T> | ScalarJsonPath<T>;
964
+ } | {
965
+ avg?: ScalarKeys<T> | ScalarJsonPath<T>;
966
+ } | {
967
+ min?: ScalarKeys<T> | ScalarJsonPath<T>;
968
+ } | {
969
+ max?: ScalarKeys<T> | ScalarJsonPath<T>;
970
+ };
971
+ /** @category Query Types */
972
+ interface AggregateOptions<
973
+ T extends TSchema2 & {
974
+ properties: Record<string, TSchema2>;
975
+ },
976
+ A extends Record<string, AggregationOp<T>> = Record<string, AggregationOp<T>>
977
+ > {
978
+ where?: WhereClause<T>;
979
+ groupBy?: readonly (ScalarKeys<T> | ScalarJsonPath<T>)[];
980
+ aggregations: A;
981
+ having?: { [K in keyof A]? : ScalarFilter<unknown> };
982
+ includeDeleted?: boolean;
983
+ }
984
+ /** @internal */
985
+ type AggregationOpResult<
986
+ T extends TSchema2 & {
987
+ properties: Record<string, TSchema2>;
988
+ },
989
+ Op extends AggregationOp<T>
990
+ > = Op extends {
991
+ sum: string;
992
+ } ? number | null : Op extends {
993
+ count: string;
994
+ } ? number : Op extends {
995
+ avg: string;
996
+ } ? number | null : Op extends {
997
+ min: infer C extends string;
998
+ } ? PathValue<T, C> | null : Op extends {
999
+ max: infer C extends string;
1000
+ } ? PathValue<T, C> | null : never;
1001
+ /** @category Query Types */
1002
+ type AggregateResult<
1003
+ T extends TSchema2 & {
1004
+ properties: Record<string, TSchema2>;
1005
+ },
1006
+ A extends Record<string, AggregationOp<T>>,
1007
+ G extends readonly string[] | undefined = undefined
1008
+ > = Array<{ [K in keyof A] : AggregationOpResult<T, A[K]> } & (G extends readonly string[] ? { [K in G[number]] : PathValue<T, K> } : {})>;
1009
+ /** @category Observability */
1010
+ interface QueryMetrics {
1011
+ table: string;
1012
+ operation: string;
1013
+ sql: string;
1014
+ durationMs: number;
1015
+ rowCount: number;
1016
+ }
1017
+ /** @category Observability */
1018
+ interface QueryMetricsHook {
1019
+ onQuery: (meta: QueryMetrics) => void;
1020
+ }
587
1021
  /**
588
1022
  * specific operations that can be listened to per table
589
1023
  * @category Events
590
1024
  */
591
- type TableOperation = "insert" | "insertMany" | "update" | "delete" | "deleteWhere" | "upsert" | "findById" | "findMany" | "findOne" | "findPage" | "count" | "flush";
1025
+ type TableOperation = "insert" | "insertMany" | "update" | "updateWhere" | "delete" | "deleteWhere" | "upsert" | "upsertMany" | "findById" | "findMany" | "findOne" | "findPage" | "findCursorPage" | "iterate" | "count" | "flush" | "aggregate" | "windowQuery";
592
1026
  /**
593
1027
  * broad categories for event listening
594
1028
  * @category Events
@@ -626,7 +1060,58 @@ type ErrorPolicy = "throw" | "emit" | "emit-swallow" | "crash";
626
1060
  * @category Setup
627
1061
  */
628
1062
  type UnlinkPolicy = true | "onlyGraceful" | "any" | false | undefined;
629
- import { TObject as TObject4 } from "typebox";
1063
+ import { TSchema as TSchema5 } from "typebox";
1064
+ import { TSchema as TSchema3 } from "typebox";
1065
+ /** @category Schema */
1066
+ interface SubTableConfig {
1067
+ indexes?: IndexDefinition[];
1068
+ }
1069
+ interface TableDescriptor<
1070
+ T extends TSchema3 & {
1071
+ properties: Record<string, TSchema3>;
1072
+ },
1073
+ PK extends string,
1074
+ TS extends TimestampConfig = undefined,
1075
+ G extends GeneratedColumnConfig | undefined = undefined
1076
+ > extends TableConfig<T, PK, TS, G> {}
1077
+ interface TableConfigShape<
1078
+ PK extends string,
1079
+ TS extends TimestampConfig,
1080
+ G extends GeneratedColumnConfig | undefined = undefined
1081
+ > {
1082
+ primaryKey: ColumnRef<PK>;
1083
+ indexes?: IndexDefinition[];
1084
+ subTables?: Partial<Record<string, SubTableConfig>>;
1085
+ timestamps?: TS;
1086
+ eviction?: EvictionConfig;
1087
+ compression?: CompressionConfig;
1088
+ softDelete?: SoftDeleteConfig;
1089
+ generated?: G;
1090
+ }
1091
+ /**
1092
+ * Describe a table schema + config for `createORM`.
1093
+ *
1094
+ * @example
1095
+ * ```ts
1096
+ * const UserSchema = Object({ id: String(), name: String(), email: String() });
1097
+ *
1098
+ * const users = table(UserSchema, (s) => ({
1099
+ * primaryKey: s.id,
1100
+ * indexes: [{ columns: [s.email], unique: true }],
1101
+ * timestamps: true, // adds createdAt / updatedAt
1102
+ * }));
1103
+ * ```
1104
+ * @category Schema
1105
+ * @category Schema
1106
+ */
1107
+ declare function table<
1108
+ T extends TSchema3 & {
1109
+ properties: Record<string, TSchema3>;
1110
+ },
1111
+ PK extends string,
1112
+ TS extends TimestampConfig = undefined,
1113
+ G extends GeneratedColumnConfig | undefined = undefined
1114
+ >(schema: T, configure: (columns: ColumnRefs<T>) => TableConfigShape<PK, TS, G>): TableDescriptor<T, PK, TS, G>;
630
1115
  /** @category Events */
631
1116
  type Listener = (payload: unknown) => void;
632
1117
  /**
@@ -660,7 +1145,7 @@ interface LifecycleEventMap {
660
1145
  * typed event listener api
661
1146
  * @category Events
662
1147
  */
663
- interface ORMEvents<Tables extends Record<string, TableConfig<any, any, any>>> {
1148
+ interface ORMEvents<Tables extends Record<string, TableDescriptor<any, any, any, any>>> {
664
1149
  /** listen to lifecycle events (start, ready, shutdown, exit, fail) */
665
1150
  on<K extends (keyof LifecycleEventMap) & string>(event: K, listener: (payload: LifecycleEventMap[K]) => void): () => void;
666
1151
  /** listen to table events (insert, update, findMany, etc) */
@@ -682,7 +1167,7 @@ declare class EventBus {
682
1167
  emit(event: string, payload: unknown): void;
683
1168
  emitIf(event: string, payload: unknown): void;
684
1169
  }
685
- import { TObject as TObject3 } from "typebox";
1170
+ import { TSchema as TSchema4 } from "typebox";
686
1171
  /** @category Advanced */
687
1172
  type SqliteType = "TEXT" | "INTEGER" | "REAL" | "BLOB";
688
1173
  /** @category Advanced */
@@ -692,6 +1177,14 @@ interface ColumnMeta {
692
1177
  nullable: boolean;
693
1178
  /** True if this is actually an `Optional` wrapper */
694
1179
  optional: boolean;
1180
+ /** Path segments for flattened nested columns, e.g. ["Status", "Group"] */
1181
+ path?: string[];
1182
+ /** True if the underlying schema is a boolean (stored as INTEGER) */
1183
+ isBoolean?: boolean;
1184
+ /** True if this is a generated column */
1185
+ generated?: boolean;
1186
+ /** Expression for generated columns */
1187
+ generatedExpr?: string;
695
1188
  }
696
1189
  /** @category Advanced */
697
1190
  interface SubTableMeta {
@@ -700,20 +1193,57 @@ interface SubTableMeta {
700
1193
  /** e.g. "sales__lineItems" */
701
1194
  tableName: string;
702
1195
  /** Schema of a single item in the array */
703
- itemSchema: TObject3;
1196
+ itemSchema: TSchema4 & {
1197
+ properties: Record<string, TSchema4>;
1198
+ };
704
1199
  /** Columns of the sub-table row (owner PK is prepended automatically) */
705
1200
  columns: ColumnMeta[];
1201
+ columnByName: Map<string, ColumnMeta>;
1202
+ columnByPath: Map<string, ColumnMeta>;
706
1203
  }
707
1204
  /** @category Advanced */
708
1205
  interface TableMeta {
709
1206
  tableName: string;
710
1207
  columns: ColumnMeta[];
711
1208
  subTables: SubTableMeta[];
1209
+ /** Map from dotted path → ColumnMeta for O(1) resolution */
1210
+ columnByPath: Map<string, ColumnMeta>;
1211
+ /** Map from column name → ColumnMeta for O(1) resolution */
1212
+ columnByName: Map<string, ColumnMeta>;
712
1213
  }
713
1214
  /** @category Advanced */
714
- declare function introspectTable(tableName: string, schema: TObject3): TableMeta;
1215
+ declare function introspectTable(tableName: string, schema: TSchema4 & {
1216
+ properties: Record<string, TSchema4>;
1217
+ }, generated?: Array<{
1218
+ name: string;
1219
+ expr: string;
1220
+ sqlType?: SqliteType;
1221
+ }>): TableMeta;
715
1222
  /** @category Advanced */
716
1223
  declare function buildCreateTableSQL(meta: TableMeta, primaryKey: string): string[];
1224
+ interface BatchWriterOptions {
1225
+ maxBuffer?: number;
1226
+ flushIntervalMs?: number;
1227
+ }
1228
+ declare class BatchWriter<
1229
+ TInput,
1230
+ TRow extends Record<string, unknown>
1231
+ > {
1232
+ private buffer;
1233
+ private readonly maxBuffer;
1234
+ private readonly tableName;
1235
+ private readonly db;
1236
+ private readonly prepare;
1237
+ private readonly onFlush?;
1238
+ private timer?;
1239
+ constructor(tableName: string, db: BunDatabase, opts: BatchWriterOptions, callbacks: {
1240
+ prepare: (row: TInput) => TRow;
1241
+ onFlush?: (rows: TRow[]) => void;
1242
+ });
1243
+ insert(row: TInput): void;
1244
+ flush(): void;
1245
+ close(): void;
1246
+ }
717
1247
  /**
718
1248
  * Typed repository for a single table. Every entry in your `tables` config
719
1249
  * becomes one of these on the ORM object, fully typed to its schema.
@@ -736,8 +1266,13 @@ declare function buildCreateTableSQL(meta: TableMeta, primaryKey: string): strin
736
1266
  * ```
737
1267
  */
738
1268
  declare class Repository<
739
- T extends TObject4,
740
- PK extends ScalarKeys<T>,
1269
+ TWrite extends TSchema5 & {
1270
+ properties: Record<string, TSchema5>;
1271
+ },
1272
+ TQuery extends TSchema5 & {
1273
+ properties: Record<string, TSchema5>;
1274
+ },
1275
+ PK extends ScalarKeys<TWrite>,
741
1276
  Mat = never,
742
1277
  TS = {}
743
1278
  > {
@@ -752,17 +1287,31 @@ declare class Repository<
752
1287
  private _materialize?;
753
1288
  private _materializeMany?;
754
1289
  private _events?;
1290
+ private _executor;
1291
+ private readonly _codecs;
755
1292
  /** @internal */
756
1293
  setEventBus(bus: EventBus): void;
757
- constructor(tableName: string, config: TableConfig<T, PK>, db: BunDatabase);
1294
+ /** @internal */
1295
+ setMetricsHook(hook?: (meta: QueryMetrics) => void): void;
1296
+ constructor(tableName: string, config: TableConfig<TWrite, PK & string, TimestampConfig, GeneratedColumnConfig | undefined>, db: BunDatabase);
1297
+ /** Ensure PK is selected when include is requested */
1298
+ private _ensureSelectPk;
1299
+ /**
1300
+ * Two-phase row fetch: first get PKs via index, then fetch full rows.
1301
+ * Avoids reading all columns for rows that don't match the WHERE clause.
1302
+ */
1303
+ private _fetchRows;
758
1304
  /** Inject materializers after ORM two-pass init */
759
1305
  setMaterializer(single: (record: Record<string, unknown>) => Record<string, unknown>, many: (records: Record<string, unknown>[]) => Record<string, unknown>[]): void;
760
1306
  /** Wrap raw data in an entity object */
761
1307
  private _wrap;
762
1308
  /** Narrow a parsed schema value to a plain record for dynamic property access */
763
1309
  private _record;
1310
+ /** Validate that a value is a valid SQLite scalar for use as a primary key */
1311
+ private _assertPk;
764
1312
  private _emit;
765
1313
  private _migrate;
1314
+ private _runEviction;
766
1315
  /**
767
1316
  * Validate and coerce data against the schema. Throws on invalid input.
768
1317
  *
@@ -774,7 +1323,7 @@ declare class Repository<
774
1323
  * // user is typed as Infer<typeof UserSchema>
775
1324
  * ```
776
1325
  */
777
- parse(data: unknown): Infer<T>;
1326
+ parse(data: unknown): Infer<TWrite>;
778
1327
  /**
779
1328
  * Type-guard - returns true if data matches the schema.
780
1329
  *
@@ -787,7 +1336,7 @@ declare class Repository<
787
1336
  * }
788
1337
  * ```
789
1338
  */
790
- check(data: unknown): data is Infer<T>;
1339
+ check(data: unknown): data is Infer<TWrite>;
791
1340
  /**
792
1341
  * Insert a single record. Returns the inserted entity.
793
1342
  *
@@ -802,7 +1351,7 @@ declare class Repository<
802
1351
  * });
803
1352
  * ```
804
1353
  */
805
- insert(data: InsertData<T>): Entity<Infer<T>, Mat, TS>;
1354
+ insert(data: InsertData<TWrite>): Entity<Infer<TQuery>, Mat, TS>;
806
1355
  /**
807
1356
  * Insert many records in a single transaction.
808
1357
  *
@@ -816,8 +1365,20 @@ declare class Repository<
816
1365
  * ]);
817
1366
  * ```
818
1367
  */
819
- insertMany(records: InsertData<T>[]): Entity<Infer<T>, Mat, TS>[];
820
- private _insertParsed;
1368
+ insertMany(records: InsertData<TWrite>[]): Entity<Infer<TQuery>, Mat, TS>[];
1369
+ /**
1370
+ * Create a batch writer for high-throughput insert streaming.
1371
+ *
1372
+ * @group Writing
1373
+ *
1374
+ * @example
1375
+ * ```ts
1376
+ * const writer = orm.users.createBatchWriter({ maxBuffer: 500 });
1377
+ * writer.insert({ id: "u1", name: "alice" });
1378
+ * writer.close();
1379
+ * ```
1380
+ */
1381
+ createBatchWriter(opts?: BatchWriterOptions): BatchWriter<InsertData<TWrite>, Record<string, unknown>>;
821
1382
  /**
822
1383
  * Insert or update on conflict. If the record exists (by conflict target),
823
1384
  * it updates the specified columns instead.
@@ -832,7 +1393,25 @@ declare class Repository<
832
1393
  * });
833
1394
  * ```
834
1395
  */
835
- upsert(opts: UpsertOptions<T, PK>): Entity<Infer<T>, Mat, TS>;
1396
+ upsert(opts: UpsertOptions<TWrite, PK>): Entity<Infer<TQuery>, Mat, TS>;
1397
+ /**
1398
+ * Bulk upsert with conflict resolution.
1399
+ * Sub-table rows are reconciled by deleting old rows and re-inserting.
1400
+ *
1401
+ * @group Writing
1402
+ *
1403
+ * @example
1404
+ * ```ts
1405
+ * orm.users.upsertMany({
1406
+ * data: [
1407
+ * { id: "u1", name: "alice" },
1408
+ * { id: "u2", name: "bob" },
1409
+ * ],
1410
+ * conflictTarget: "id",
1411
+ * });
1412
+ * ```
1413
+ */
1414
+ upsertMany(opts: UpsertManyOptions<TWrite, PK>): number;
836
1415
  /**
837
1416
  * Find a record by its primary key.
838
1417
  *
@@ -844,7 +1423,7 @@ declare class Repository<
844
1423
  * if (user) console.log(user.name);
845
1424
  * ```
846
1425
  */
847
- findById(id: Infer<T>[PK]): Entity<Infer<T>, Mat, TS> | null;
1426
+ findById(id: Infer<TQuery>[PK]): Entity<Infer<TQuery>, Mat, TS> | null;
848
1427
  /** Internal findById without event emission - used by update() */
849
1428
  private _findByIdRaw;
850
1429
  /**
@@ -864,7 +1443,17 @@ declare class Repository<
864
1443
  * const orders = orm.orders.findMany({ include: ["lineItems"] });
865
1444
  * ```
866
1445
  */
867
- findMany(opts?: FindOptions<T>): Entity<Infer<T>, Mat, TS>[];
1446
+ findMany<
1447
+ const S extends readonly SelectableKeys<TQuery>[],
1448
+ const I extends readonly SubTableKeys<TQuery>[]
1449
+ >(opts: FindOptions<TQuery> & {
1450
+ select: S;
1451
+ include: I;
1452
+ }): (SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] })[];
1453
+ findMany<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1454
+ select: S;
1455
+ }): (SelectShape<TQuery, S> & TS)[];
1456
+ findMany(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS>[];
868
1457
  /**
869
1458
  * Find many with total count - useful for pagination.
870
1459
  *
@@ -882,7 +1471,43 @@ declare class Repository<
882
1471
  * // page.limit, page.offset - what you passed in
883
1472
  * ```
884
1473
  */
885
- findPage(opts?: FindOptions<T>): PageResult<Entity<Infer<T>, Mat, TS>>;
1474
+ findPage<
1475
+ const S extends readonly SelectableKeys<TQuery>[],
1476
+ const I extends readonly SubTableKeys<TQuery>[]
1477
+ >(opts: FindOptions<TQuery> & {
1478
+ select: S;
1479
+ include: I;
1480
+ }): PageResult<SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
1481
+ findPage<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1482
+ select: S;
1483
+ }): PageResult<SelectShape<TQuery, S> & TS>;
1484
+ findPage(opts?: FindOptions<TQuery>): PageResult<Entity<Infer<TQuery>, Mat, TS>>;
1485
+ /**
1486
+ * Cursor-based pagination (seek method). Avoids OFFSET degradation on
1487
+ * large tables by using a boundary value from the previous page.
1488
+ *
1489
+ * @group Reading
1490
+ *
1491
+ * @example
1492
+ * ```ts
1493
+ * const page = orm.orders.findCursorPage({
1494
+ * orderBy: { column: "DocumentDate", direction: "DESC" },
1495
+ * limit: 25,
1496
+ * });
1497
+ *
1498
+ * const next = orm.orders.findCursorPage({
1499
+ * orderBy: { column: "DocumentDate", direction: "DESC" },
1500
+ * cursor: page.nextCursor!,
1501
+ * limit: 25,
1502
+ * });
1503
+ * ```
1504
+ */
1505
+ findCursorPage(opts: {
1506
+ where?: WhereClause<TQuery>;
1507
+ orderBy: OrderByClause<TQuery>;
1508
+ cursor?: CursorInput;
1509
+ limit?: number;
1510
+ }): CursorPageResult<Entity<Infer<TQuery>, Mat, TS>>;
886
1511
  /**
887
1512
  * Find a single record matching the given filters. Equivalent to `findMany`
888
1513
  * with `limit: 1`, but returns the entity directly (or `null`).
@@ -896,7 +1521,45 @@ declare class Repository<
896
1521
  * });
897
1522
  * ```
898
1523
  */
899
- findOne(opts?: FindOptions<T>): Entity<Infer<T>, Mat, TS> | null;
1524
+ findOne<
1525
+ const S extends readonly SelectableKeys<TQuery>[],
1526
+ const I extends readonly SubTableKeys<TQuery>[]
1527
+ >(opts: FindOptions<TQuery> & {
1528
+ select: S;
1529
+ include: I;
1530
+ }): (SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] }) | null;
1531
+ findOne<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1532
+ select: S;
1533
+ }): (SelectShape<TQuery, S> & TS) | null;
1534
+ findOne(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS> | null;
1535
+ /**
1536
+ * Iterate over records matching the given filters, yielding one row at a time.
1537
+ * Sub-tables are hydrated in windows to keep memory stable.
1538
+ *
1539
+ * @group Reading
1540
+ *
1541
+ * @example
1542
+ * ```ts
1543
+ * for (const user of orm.users.iterate({ where: { active: { eq: true } } })) {
1544
+ * console.log(user.name);
1545
+ * }
1546
+ * ```
1547
+ */
1548
+ iterate<
1549
+ const S extends readonly SelectableKeys<TQuery>[],
1550
+ const I extends readonly SubTableKeys<TQuery>[]
1551
+ >(opts: FindOptions<TQuery> & {
1552
+ select: S;
1553
+ include: I;
1554
+ }): Generator<SelectShape<TQuery, S> & TS & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
1555
+ iterate<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1556
+ include: I;
1557
+ }): Generator<Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
1558
+ iterate<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1559
+ select: S;
1560
+ }): Generator<SelectShape<TQuery, S> & TS>;
1561
+ iterate(opts?: FindOptions<TQuery>): Generator<Entity<Infer<TQuery>, Mat, TS>>;
1562
+ private _hydrateWindow;
900
1563
  /**
901
1564
  * Find many with resolved relations (n+1 safe). If you have cross-table
902
1565
  * relations configured, this eagerly loads them in a single batch query.
@@ -911,7 +1574,7 @@ declare class Repository<
911
1574
  * }
912
1575
  * ```
913
1576
  */
914
- findManyMaterialized(opts?: FindOptions<T>): Entity<Infer<T>, Mat, TS>[];
1577
+ findManyMaterialized(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS>[];
915
1578
  /**
916
1579
  * Count records matching the given filters.
917
1580
  *
@@ -923,7 +1586,54 @@ declare class Repository<
923
1586
  * const adults = orm.users.count({ age: { gte: 18 } });
924
1587
  * ```
925
1588
  */
926
- count(where?: WhereClause<T>): number;
1589
+ count(where?: WhereClause<TQuery>): number;
1590
+ /**
1591
+ * Run aggregate queries (sum, count, avg, min, max) with optional
1592
+ * grouping and filtering.
1593
+ *
1594
+ * @group Reading
1595
+ *
1596
+ * @example
1597
+ * ```ts
1598
+ * orm.orders.aggregate({
1599
+ * aggregations: { total: { sum: "amount" } },
1600
+ * });
1601
+ *
1602
+ * orm.orders.aggregate({
1603
+ * groupBy: ["status"],
1604
+ * aggregations: { count: { count: "*" }, avgAmount: { avg: "amount" } },
1605
+ * });
1606
+ * ```
1607
+ */
1608
+ aggregate<
1609
+ const A extends Record<string, AggregationOp<TQuery>>,
1610
+ const G extends readonly (ScalarKeys<TQuery> | ScalarJsonPath<TQuery>)[] | undefined = undefined
1611
+ >(opts: AggregateOptions<TQuery, A> & {
1612
+ groupBy?: G;
1613
+ }): AggregateResult<TQuery, A, G>;
1614
+ /**
1615
+ * Run window function queries (rowNumber, rank, denseRank, lead, lag)
1616
+ * with partitioning and ordering.
1617
+ *
1618
+ * @group Reading
1619
+ *
1620
+ * @example
1621
+ * ```ts
1622
+ * orm.orders.windowQuery({
1623
+ * partitionBy: ["Status__Group"],
1624
+ * orderBy: [{ column: "DocumentDate", direction: "DESC" }],
1625
+ * select: {
1626
+ * rowNumber: { rowNumber: true },
1627
+ * rank: { rank: true },
1628
+ * leadTotal: { lead: "TotalTurnover", offset: 1 },
1629
+ * },
1630
+ * limit: 100,
1631
+ * });
1632
+ * ```
1633
+ */
1634
+ windowQuery<const W extends Record<string, WindowFunction<TQuery>>>(opts: WindowQueryOptions<TQuery> & {
1635
+ select: W;
1636
+ }): WindowResult<TQuery, W>;
927
1637
  /**
928
1638
  * Update a record - must include the primary key. Returns the updated
929
1639
  * entity, or `null` if no record matched.
@@ -935,7 +1645,22 @@ declare class Repository<
935
1645
  * orm.users.update({ id: "u1", name: "alice smith" });
936
1646
  * ```
937
1647
  */
938
- update(data: UpdateData<T, PK>): Entity<Infer<T>, Mat, TS> | null;
1648
+ update(data: UpdateData<TWrite, PK>): Entity<Infer<TQuery>, Mat, TS> | null;
1649
+ /**
1650
+ * Update multiple records matching the given filters.
1651
+ * Returns the number of rows changed.
1652
+ *
1653
+ * @group Writing
1654
+ *
1655
+ * @example
1656
+ * ```ts
1657
+ * orm.users.updateWhere({
1658
+ * where: { status: { eq: "pending" } },
1659
+ * data: { status: { group: "completed" } },
1660
+ * });
1661
+ * ```
1662
+ */
1663
+ updateWhere(opts: UpdateWhereOptions<TWrite, PK>): number;
939
1664
  /**
940
1665
  * Delete a record by its primary key. Returns `true` if a record was deleted.
941
1666
  *
@@ -946,7 +1671,7 @@ declare class Repository<
946
1671
  * const deleted = orm.users.deleteById("u1");
947
1672
  * ```
948
1673
  */
949
- deleteById(id: Infer<T>[PK]): boolean;
1674
+ deleteById(id: Infer<TWrite>[PK]): boolean;
950
1675
  /**
951
1676
  * Delete records matching the given filters. Returns the number of rows deleted.
952
1677
  *
@@ -957,7 +1682,7 @@ declare class Repository<
957
1682
  * const removed = orm.users.deleteWhere({ status: { eq: "banned" } });
958
1683
  * ```
959
1684
  */
960
- deleteWhere(where: WhereClause<T>): number;
1685
+ deleteWhere(where: WhereClause<TQuery>): number;
961
1686
  /**
962
1687
  * Truncate the table and all sub-tables. Deletes all rows but keeps the schema.
963
1688
  *
@@ -993,9 +1718,9 @@ declare class Repository<
993
1718
  * );
994
1719
  * ```
995
1720
  */
996
- raw<R = unknown>(sql: string, ...params: unknown[]): R[];
1721
+ raw<R = DBRow>(sql: string, ...params: DBValue[]): R[];
997
1722
  }
998
- declare class RelationBuilder<Tables extends Record<string, TableConfig<any, any, any>>> {
1723
+ declare class RelationBuilder<Tables extends Record<string, TableDescriptor<any, any, any, any>>> {
999
1724
  private readonly tables;
1000
1725
  private readonly relations;
1001
1726
  constructor(tables: Tables);
@@ -1025,16 +1750,14 @@ declare class RelationBuilder<Tables extends Record<string, TableConfig<any, any
1025
1750
  build(): TypedRelation[];
1026
1751
  }
1027
1752
  /** @category Relations */
1028
- declare function createRelationBuilder<T extends Record<string, TableConfig<any, any, any>>>(tables: T): RelationBuilder<T>;
1753
+ declare function createRelationBuilder<T extends Record<string, TableDescriptor<any, any, any, any>>>(tables: T): RelationBuilder<T>;
1029
1754
  import { Static as Static2 } from "typebox";
1030
1755
  declare const SchemaHashSchema: unknown;
1031
- /** @category Database */
1032
1756
  declare const SchemaJSONSchema: unknown;
1033
1757
  declare const TablesSchema: unknown;
1034
1758
  declare const RelationsSchema: unknown;
1035
1759
  declare const VersionSchema: unknown;
1036
1760
  type SchemaHash = Static2<typeof SchemaHashSchema>;
1037
- /** @category Database */
1038
1761
  type SchemaJSON = Static2<typeof SchemaJSONSchema>;
1039
1762
  type TablesList = Static2<typeof TablesSchema>;
1040
1763
  type RelationsList = Static2<typeof RelationsSchema>;
@@ -1051,7 +1774,7 @@ declare class MetaStore {
1051
1774
  private getRow;
1052
1775
  private setRow;
1053
1776
  private getValidatedJSON;
1054
- private setValidatedJSON;
1777
+ private validateAndSetJSON;
1055
1778
  getString(key: string): string | null;
1056
1779
  setString(key: string, value: string): void;
1057
1780
  getJSON<T>(key: string): T | null;
@@ -1075,7 +1798,7 @@ declare class MetaStore {
1075
1798
  * @category Lifecycle
1076
1799
  */
1077
1800
  interface ORMContext<
1078
- T extends Record<string, TableConfig<any, any, any>> = Record<string, TableConfig<any, any, any>>,
1801
+ T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
1079
1802
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1080
1803
  > {
1081
1804
  orm: foxdb<T, Rels>;
@@ -1093,7 +1816,7 @@ interface ORMContext<
1093
1816
  * @category Lifecycle
1094
1817
  */
1095
1818
  type LifecycleHook<
1096
- T extends Record<string, TableConfig<any, any, any>> = Record<string, TableConfig<any, any, any>>,
1819
+ T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
1097
1820
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1098
1821
  > = (ctx: ORMContext<T, Rels>) => void | Promise<void>;
1099
1822
  /**
@@ -1101,7 +1824,7 @@ type LifecycleHook<
1101
1824
  * @category Lifecycle
1102
1825
  */
1103
1826
  declare class LifecycleManager<
1104
- T extends Record<string, TableConfig<any, any, any>> = Record<string, TableConfig<any, any, any>>,
1827
+ T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
1105
1828
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1106
1829
  > {
1107
1830
  private startHooks;
@@ -1142,6 +1865,10 @@ interface CreateORMBaseOptions {
1142
1865
  busyTimeout?: number;
1143
1866
  synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA";
1144
1867
  mmapSize?: number;
1868
+ autoVacuum?: "incremental" | "full" | false;
1869
+ vacuumIntervalMs?: number;
1870
+ /** disable fsync during large initial loads */
1871
+ bulkLoadMode?: boolean;
1145
1872
  }
1146
1873
  /**
1147
1874
  * Options passed to `createORM`.
@@ -1172,7 +1899,7 @@ interface CreateORMBaseOptions {
1172
1899
  * ```
1173
1900
  */
1174
1901
  interface CreateORMOptions<
1175
- T extends Record<string, TableConfig<any, any, any>> = Record<string, TableConfig<any, any, any>>,
1902
+ T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
1176
1903
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1177
1904
  > extends CreateORMBaseOptions {
1178
1905
  /** table schemas */
@@ -1215,6 +1942,8 @@ interface CreateORMOptions<
1215
1942
  errorPolicy?: ErrorPolicy;
1216
1943
  /** delete db files on exit */
1217
1944
  unlinkDbFilesOnExit?: UnlinkPolicy;
1945
+ /** observability hooks */
1946
+ hooks?: QueryMetricsHook;
1218
1947
  }
1219
1948
  /**
1220
1949
  * The ORM object returned by `createORM`.
@@ -1266,15 +1995,19 @@ interface CreateORMOptions<
1266
1995
  * ```
1267
1996
  */
1268
1997
  type foxdb<
1269
- Tables extends Record<string, TableConfig<any, any, any>>,
1998
+ Tables extends Record<string, TableDescriptor<any, any, any, any>>,
1270
1999
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1271
- > = { [K in keyof Tables] : Tables[K] extends TableConfig<infer T, infer PK, infer TS> ? Repository<T, PK extends ScalarKeys<T> ? PK : never, Materialized<T, Tables, Rels, K & string>, TimestampShape<TS>> : never } & {
2000
+ > = { [K in keyof Tables] : Tables[K] extends TableDescriptor<infer TWrite extends TSchema6 & {
2001
+ properties: Record<string, TSchema6>;
2002
+ }, 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
2003
  /** run a transaction */
1273
2004
  _transaction<R>(fn: () => R): R;
1274
2005
  /** close the database */
1275
2006
  _close(): void;
1276
2007
  /** read-only metadata */
1277
2008
  _meta: MetaAccessors;
2009
+ /** toggle bulk-load mode (disables synchronous fsync) */
2010
+ _setBulkLoadMode(enabled: boolean): void;
1278
2011
  /** resolve relations for a single record */
1279
2012
  _materialize<Owner extends keyof Tables & string>(ownerTable: Owner, record: Record<string, unknown>): Record<string, unknown>;
1280
2013
  /** resolve relations for many records (n+1 safe) */
@@ -1290,69 +2023,9 @@ type foxdb<
1290
2023
  };
1291
2024
  /** create a typed orm instance backed by sqlite */
1292
2025
  declare function createORM<
1293
- const T extends Record<string, TableConfig<any, any, any>>,
2026
+ const T extends Record<string, TableDescriptor<any, any, any, any>>,
1294
2027
  const Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1295
2028
  >(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
2029
  declare function migrate(opts: MigrateOptions): Promise<void>;
1357
2030
  /** @category Migration */
1358
2031
  declare function createMigration(name: string, migrationsDir: string): string;
@@ -1460,4 +2133,4 @@ interface DesiredTable {
1460
2133
  declare function computeDiff(desired: DesiredTable[], actual: InspectorTable[]): SchemaDiff;
1461
2134
  /** @category Migration */
1462
2135
  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 };
2136
+ 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 };