@xwxfox/foxdb 0.1.1 → 0.1.3

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,5 @@
1
- import { TSchema as TSchema6 } from "typebox";
2
- import { TObject as TObject2, TArray, TSchema as TSchema2, TProperties, TOptional as TOptional2, Static } from "typebox";
1
+ import { TSchema as TSchema10 } from "typebox";
2
+ import { TObject as TObject2, TArray, TSchema as TSchema2, TProperties, TOptional as TOptional2, TString as TString2, TLiteral as TLiteral2, Static } from "typebox";
3
3
  import { TObject, TString, TNumber, TInteger, TBoolean, TLiteral, TSchema, TOptional } from "typebox";
4
4
  /** @category Schema */
5
5
  type TScalarSchema = TString | TNumber | TInteger | TBoolean | TLiteral<string> | TLiteral<number> | TLiteral<boolean>;
@@ -53,7 +53,16 @@ interface TypedRelation<
53
53
  kind: K;
54
54
  as: A;
55
55
  }
56
- import { Database, Statement } from "bun:sqlite";
56
+ import { Database, SQLQueryBindings, Statement } from "bun:sqlite";
57
+ type SweepTask = () => void;
58
+ declare class TableScheduler {
59
+ private timers;
60
+ private timersByName;
61
+ private tasks;
62
+ schedule(name: string, intervalMs: number, task: SweepTask): void;
63
+ clear(name: string): void;
64
+ clearAll(): void;
65
+ }
57
66
  /**
58
67
  * prepared sqlite statement
59
68
  * @category Database
@@ -92,7 +101,10 @@ declare class BunDatabase {
92
101
  /** underlying bun:sqlite database */
93
102
  readonly db: Database;
94
103
  /** scheduler for table maintenance tasks */
95
- readonly scheduler;
104
+ readonly scheduler: TableScheduler;
105
+ private extensionStatus;
106
+ /** Tracks nesting depth of user-initiated transactions */
107
+ _txDepth: number;
96
108
  constructor(opts?: DatabaseOptions);
97
109
  /** execute ddl (create table, index, etc) */
98
110
  exec(sql: string): void;
@@ -106,8 +118,18 @@ declare class BunDatabase {
106
118
  prepare(sql: string): BunStatement;
107
119
  /** set synchronous pragma for bulk load or normal operation */
108
120
  setSynchronous(mode: "OFF" | "NORMAL" | "FULL" | "EXTRA"): void;
121
+ /**
122
+ * Drop one cached statement without finalizing it. Recovery path for
123
+ * holders (see QueryExecutor) whose cached object was finalized
124
+ * out-of-band: the shared entry may reference the same dead object, so
125
+ * it must go too, otherwise the next prepare() would hand the corpse
126
+ * right back.
127
+ */
128
+ dropCached(sql: string): void;
109
129
  /** clear the statement cache */
110
130
  clearCache(): void;
131
+ /** get stmt stats from extension. Returns [] if ran without --feature DEBUG_SQL_BUILDING */
132
+ getStmtStats(sql: string): unknown;
111
133
  }
112
134
  type JsonValue = null | boolean | number | string | JsonValue[] | {
113
135
  [key: string]: JsonValue;
@@ -293,8 +315,18 @@ type ScalarFilter<V> = unknown extends V ? {
293
315
  eq: V;
294
316
  } | {
295
317
  ne: V;
318
+ } | {
319
+ gt: V;
320
+ } | {
321
+ gte: V;
322
+ } | {
323
+ lt: V;
324
+ } | {
325
+ lte: V;
296
326
  } | {
297
327
  like: string;
328
+ } | {
329
+ between: [V, V];
298
330
  } | {
299
331
  in: V[];
300
332
  } | {
@@ -406,7 +438,7 @@ type ArrayFilter<V> = {
406
438
  */
407
439
  type WhereClause<T extends TSchema2 & {
408
440
  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>> } & {
441
+ }> = { [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> | SubTableScalarPath<T>)]? : PathValue<T, K> extends Array<infer Item> ? ArrayFilter<Item> : ScalarFilter<PathValue<T, K>> } & {
410
442
  AND?: WhereClause<T>[];
411
443
  OR?: WhereClause<T>[];
412
444
  NOT?: WhereClause<T>;
@@ -475,6 +507,54 @@ interface CursorPageResult<T> {
475
507
  type SelectableKeys<T extends TSchema2 & {
476
508
  properties: Record<string, TSchema2>;
477
509
  }> = ScalarKeys<T> | ObjectKeys<T> | PrimitiveArrayKeys<T> | JsonPath<T>;
510
+ type FilterableFields<T extends TSchema2 & {
511
+ properties: Record<string, TSchema2>;
512
+ }> = ScalarKeys<T> | ObjectKeys<T> | ScalarJsonPath<T> | SubTableScalarPath<T>;
513
+ /**
514
+ * Filterable fields excluding sub-table paths.
515
+ * Used when no sub-tables have been included via .include().
516
+ * @category Query Types
517
+ */
518
+ type FilterableFieldsBase<T extends TSchema2 & {
519
+ properties: Record<string, TSchema2>;
520
+ }> = ScalarKeys<T> | ObjectKeys<T> | ScalarJsonPath<T>;
521
+ /**
522
+ * Filterable fields that include ONLY sub-table paths for the specified tables.
523
+ * @internal
524
+ */
525
+ type IncludedSubTablePaths<
526
+ T extends TSchema2 & {
527
+ properties: Record<string, TSchema2>;
528
+ },
529
+ I extends string
530
+ > = Extract<SubTableScalarPath<T>, `${I}.${string}`>;
531
+ type FilterableForInclude<
532
+ T extends TSchema2 & {
533
+ properties: Record<string, TSchema2>;
534
+ },
535
+ I extends string | undefined
536
+ > = [I] extends [never] ? FilterableFieldsBase<T> : [I] extends [undefined] ? FilterableFieldsBase<T> : FilterableFieldsBase<T> | IncludedSubTablePaths<T, I & string>;
537
+ type FieldType<
538
+ T extends TSchema2 & {
539
+ properties: Record<string, TSchema2>;
540
+ },
541
+ P extends FilterableFields<T>
542
+ > = PathValue<T, P>;
543
+ type ArrayFilterableFields<T extends TSchema2 & {
544
+ properties: Record<string, TSchema2>;
545
+ }> = PrimitiveArrayKeys<T>;
546
+ type ArrayItemType<
547
+ T extends TSchema2 & {
548
+ properties: Record<string, TSchema2>;
549
+ },
550
+ P extends ArrayFilterableFields<T>
551
+ > = UnwrapOptional<T["properties"][P]> extends TArray<infer Item> ? Static<Item> : never;
552
+ type OrderableFields<T extends TSchema2 & {
553
+ properties: Record<string, TSchema2>;
554
+ }> = ScalarKeys<T> | ScalarJsonPath<T>;
555
+ type DistinctableFields<T extends TSchema2 & {
556
+ properties: Record<string, TSchema2>;
557
+ }> = ScalarKeys<T> | ScalarJsonPath<T>;
478
558
  interface FindOptions<T extends TSchema2 & {
479
559
  properties: Record<string, TSchema2>;
480
560
  }> extends PaginationOptions {
@@ -581,6 +661,39 @@ interface CompressionConfig {
581
661
  interface SoftDeleteConfig {
582
662
  column: string;
583
663
  }
664
+ /**
665
+ * Full-text search configuration for a table.
666
+ * - `true` indexes every TEXT column.
667
+ * - `{ columns }` indexes an explicit, type-checked column list.
668
+ * @category Schema
669
+ */
670
+ type FTSConfig = true | {
671
+ /** Columns to index. Omit to index all TEXT columns. */
672
+ columns?: readonly ColumnRef<string, TScalarSchema>[];
673
+ /** FTS5 tokenizer directive, e.g. "porter unicode61", "trigram". Default: "unicode61". */
674
+ tokenizer?: string;
675
+ /** FTS5 prefix-index sizes, e.g. [2, 3]. */
676
+ prefix?: readonly number[];
677
+ };
678
+ /** True when a table has FTS enabled. @internal */
679
+ type FTSEnabled<F> = [F] extends [undefined] ? false : [F] extends [never] ? false : true;
680
+ /** Union of flattened TEXT column names (top-level + nested `a__b`). @internal */
681
+ type FTSAllTextFields<T extends TSchema2 & {
682
+ properties: Record<string, TSchema2>;
683
+ }> = { [K in keyof ColumnRefs<T>] : ColumnRefs<T>[K] extends ColumnRef<infer N, infer S> ? S extends TString2 ? N : S extends TLiteral2<string> ? N : never : never }[keyof ColumnRefs<T>];
684
+ /** Names extracted from an explicit `{ columns }` FTS config. @internal */
685
+ type FTSConfiguredFields<F> = F extends {
686
+ columns: readonly (infer C)[];
687
+ } ? C extends ColumnRef<infer N, TScalarSchema> ? N : never : never;
688
+ /** The searchable field-name union for a table given its FTS config. @internal */
689
+ type FTSFields<
690
+ T extends TSchema2 & {
691
+ properties: Record<string, TSchema2>;
692
+ },
693
+ F
694
+ > = [F] extends [undefined] ? never : [F] extends [false] ? never : F extends {
695
+ columns: readonly ColumnRef<string, TScalarSchema>[];
696
+ } ? FTSConfiguredFields<F> : FTSAllTextFields<T>;
584
697
  type GeneratedColumnConfig = {
585
698
  [name: string]: {
586
699
  expr: string;
@@ -608,7 +721,8 @@ interface TableConfig<
608
721
  },
609
722
  PK extends string = string,
610
723
  TS extends TimestampConfig = undefined,
611
- G extends GeneratedColumnConfig | undefined = undefined
724
+ G extends GeneratedColumnConfig | undefined = undefined,
725
+ F extends FTSConfig | undefined = undefined
612
726
  > {
613
727
  schema: T;
614
728
  primaryKey: ColumnRef<PK>;
@@ -621,6 +735,9 @@ interface TableConfig<
621
735
  compression?: CompressionConfig;
622
736
  softDelete?: SoftDeleteConfig;
623
737
  generated?: G;
738
+ fts?: F;
739
+ /** Auto-index TEXT columns on sub-tables. Defaults to false. Set true to enable. */
740
+ autoIndex?: boolean;
624
741
  }
625
742
  /**
626
743
  * read-only metadata about the current database schema
@@ -638,7 +755,7 @@ interface MetaAccessors {
638
755
  * @category Relations
639
756
  */
640
757
  interface RelationEntry<
641
- Tables extends Record<string, TableConfig<any, any, any, any>>,
758
+ Tables extends Record<string, TableConfig<any, any, any, any, any>>,
642
759
  Owner extends keyof Tables,
643
760
  Target extends keyof Tables
644
761
  > {
@@ -650,7 +767,7 @@ interface RelationEntry<
650
767
  * @internal
651
768
  * @category Relations
652
769
  */
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]> };
770
+ type RelationsConfig<Tables extends Record<string, TableConfig<any, any, any, any, any>>> = { [K in keyof Tables & string]? : Array<{ [Target in keyof Tables & string] : RelationEntry<Tables, K, Target> }[keyof Tables & string]> };
654
771
  /**
655
772
  * @internal
656
773
  * @category Relations
@@ -667,7 +784,7 @@ type ScalarMergeNames<
667
784
  * @category Relations
668
785
  */
669
786
  type ScalarMergeType<
670
- Tables extends Record<string, TableConfig<any, any, any, any>>,
787
+ Tables extends Record<string, TableConfig<any, any, any, any, any>>,
671
788
  Rels extends readonly TypedRelation[],
672
789
  Owner extends string,
673
790
  Name extends string
@@ -681,7 +798,7 @@ type ScalarMergeType<
681
798
  * @category Relations
682
799
  */
683
800
  type ScalarMerge<
684
- Tables extends Record<string, TableConfig<any, any, any, any>>,
801
+ Tables extends Record<string, TableConfig<any, any, any, any, any>>,
685
802
  Rels extends readonly TypedRelation[],
686
803
  Owner extends string
687
804
  > = { [K in ScalarMergeNames<Rels, Owner>] : ScalarMergeType<Tables, Rels, Owner, K> };
@@ -703,7 +820,7 @@ type SubMergeNames<
703
820
  * @category Relations
704
821
  */
705
822
  type SubMergeType<
706
- Tables extends Record<string, TableConfig<any, any, any, any>>,
823
+ Tables extends Record<string, TableConfig<any, any, any, any, any>>,
707
824
  Rels extends readonly TypedRelation[],
708
825
  Owner extends string,
709
826
  Sub extends string,
@@ -719,7 +836,7 @@ type SubMergeType<
719
836
  * @category Relations
720
837
  */
721
838
  type SubMerge<
722
- Tables extends Record<string, TableConfig<any, any, any, any>>,
839
+ Tables extends Record<string, TableConfig<any, any, any, any, any>>,
723
840
  Rels extends readonly TypedRelation[],
724
841
  Owner extends string,
725
842
  Sub extends string
@@ -744,7 +861,7 @@ type Materialized<
744
861
  T extends TSchema2 & {
745
862
  properties: Record<string, TSchema2>;
746
863
  },
747
- Tables extends Record<string, TableConfig<any, any, any, any>>,
864
+ Tables extends Record<string, TableConfig<any, any, any, any, any>>,
748
865
  Rels extends readonly TypedRelation[],
749
866
  Owner extends string
750
867
  > = { [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>;
@@ -958,15 +1075,15 @@ type AggregationOp<T extends TSchema2 & {
958
1075
  } = TSchema2 & {
959
1076
  properties: Record<string, TSchema2>;
960
1077
  }> = {
961
- sum?: ScalarKeys<T> | ScalarJsonPath<T>;
1078
+ sum?: ScalarKeys<T> | ScalarJsonPath<T> | SubTableScalarPath<T>;
962
1079
  } | {
963
- count?: "*" | ScalarKeys<T> | ScalarJsonPath<T>;
1080
+ count?: "*" | ScalarKeys<T> | ScalarJsonPath<T> | SubTableScalarPath<T>;
964
1081
  } | {
965
- avg?: ScalarKeys<T> | ScalarJsonPath<T>;
1082
+ avg?: ScalarKeys<T> | ScalarJsonPath<T> | SubTableScalarPath<T>;
966
1083
  } | {
967
- min?: ScalarKeys<T> | ScalarJsonPath<T>;
1084
+ min?: ScalarKeys<T> | ScalarJsonPath<T> | SubTableScalarPath<T>;
968
1085
  } | {
969
- max?: ScalarKeys<T> | ScalarJsonPath<T>;
1086
+ max?: ScalarKeys<T> | ScalarJsonPath<T> | SubTableScalarPath<T>;
970
1087
  };
971
1088
  /** @category Query Types */
972
1089
  interface AggregateOptions<
@@ -980,6 +1097,13 @@ interface AggregateOptions<
980
1097
  aggregations: A;
981
1098
  having?: { [K in keyof A]? : ScalarFilter<unknown> };
982
1099
  includeDeleted?: boolean;
1100
+ /**
1101
+ * Aggregate over a sub-table (array relationship) instead of the main table.
1102
+ * Provide the field name of the sub-table (e.g. "PurchaseLineItems").
1103
+ * Column references in aggregations/where/groupBy are resolved against the
1104
+ * sub-table's item schema.
1105
+ */
1106
+ subTable?: string;
983
1107
  }
984
1108
  /** @internal */
985
1109
  type AggregationOpResult<
@@ -1060,7 +1184,7 @@ type ErrorPolicy = "throw" | "emit" | "emit-swallow" | "crash";
1060
1184
  * @category Setup
1061
1185
  */
1062
1186
  type UnlinkPolicy = true | "onlyGraceful" | "any" | false | undefined;
1063
- import { TSchema as TSchema5 } from "typebox";
1187
+ import { TSchema as TSchema8 } from "typebox";
1064
1188
  import { TSchema as TSchema3 } from "typebox";
1065
1189
  /** @category Schema */
1066
1190
  interface SubTableConfig {
@@ -1072,12 +1196,14 @@ interface TableDescriptor<
1072
1196
  },
1073
1197
  PK extends string,
1074
1198
  TS extends TimestampConfig = undefined,
1075
- G extends GeneratedColumnConfig | undefined = undefined
1076
- > extends TableConfig<T, PK, TS, G> {}
1199
+ G extends GeneratedColumnConfig | undefined = undefined,
1200
+ F extends FTSConfig | undefined = undefined
1201
+ > extends TableConfig<T, PK, TS, G, F> {}
1077
1202
  interface TableConfigShape<
1078
1203
  PK extends string,
1079
1204
  TS extends TimestampConfig,
1080
- G extends GeneratedColumnConfig | undefined = undefined
1205
+ G extends GeneratedColumnConfig | undefined = undefined,
1206
+ F extends FTSConfig | undefined = undefined
1081
1207
  > {
1082
1208
  primaryKey: ColumnRef<PK>;
1083
1209
  indexes?: IndexDefinition[];
@@ -1087,6 +1213,9 @@ interface TableConfigShape<
1087
1213
  compression?: CompressionConfig;
1088
1214
  softDelete?: SoftDeleteConfig;
1089
1215
  generated?: G;
1216
+ fts?: F;
1217
+ /** Auto-index TEXT columns on sub-tables. Defaults to false. Set true to enable. */
1218
+ autoIndex?: boolean;
1090
1219
  }
1091
1220
  /**
1092
1221
  * Describe a table schema + config for `createORM`.
@@ -1110,8 +1239,9 @@ declare function table<
1110
1239
  },
1111
1240
  PK extends string,
1112
1241
  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>;
1242
+ G extends GeneratedColumnConfig | undefined = undefined,
1243
+ const F extends FTSConfig | undefined = undefined
1244
+ >(schema: T, configure: (columns: ColumnRefs<T>) => TableConfigShape<PK, TS, G, F>): TableDescriptor<T, PK, TS, G, F>;
1115
1245
  /** @category Events */
1116
1246
  type Listener = (payload: unknown) => void;
1117
1247
  /**
@@ -1145,7 +1275,7 @@ interface LifecycleEventMap {
1145
1275
  * typed event listener api
1146
1276
  * @category Events
1147
1277
  */
1148
- interface ORMEvents<Tables extends Record<string, TableDescriptor<any, any, any, any>>> {
1278
+ interface ORMEvents<Tables extends Record<string, TableDescriptor<any, any, any, any, any>>> {
1149
1279
  /** listen to lifecycle events (start, ready, shutdown, exit, fail) */
1150
1280
  on<K extends (keyof LifecycleEventMap) & string>(event: K, listener: (payload: LifecycleEventMap[K]) => void): () => void;
1151
1281
  /** listen to table events (insert, update, findMany, etc) */
@@ -1170,6 +1300,18 @@ declare class EventBus {
1170
1300
  import { TSchema as TSchema4 } from "typebox";
1171
1301
  /** @category Advanced */
1172
1302
  type SqliteType = "TEXT" | "INTEGER" | "REAL" | "BLOB";
1303
+ /**
1304
+ * Pre-classified decode strategy for hydration.
1305
+ * Avoids per-value heuristic checks by knowing the column's type at schema time.
1306
+ */
1307
+ declare const enum ColDecode {
1308
+ /** Scalar string or number – pass through, no processing */
1309
+ Scalar = 0,
1310
+ /** JSON object/array stored as TEXT – always JSON.parse */
1311
+ Json = 1,
1312
+ /** Boolean stored as INTEGER – convert 0/1 to false/true */
1313
+ Bool = 2
1314
+ }
1173
1315
  /** @category Advanced */
1174
1316
  interface ColumnMeta {
1175
1317
  name: string;
@@ -1185,22 +1327,44 @@ interface ColumnMeta {
1185
1327
  generated?: boolean;
1186
1328
  /** Expression for generated columns */
1187
1329
  generatedExpr?: string;
1330
+ /** Pre-built getter function for flattenRow (set during introspectTable) */
1331
+ _get?: (obj: Record<string, unknown>) => unknown;
1332
+ /**
1333
+ * Pre-classified decode strategy for hydration.
1334
+ * Scalar=0 (no processing), Json=1 (JSON.parse), Bool=2 (v===1).
1335
+ */
1336
+ decode?: ColDecode;
1337
+ /**
1338
+ * If path.length <= 1, pre-stored target key for direct property assignment
1339
+ * (avoids branching in the hydration hot loop).
1340
+ */
1341
+ _targetKey?: string;
1188
1342
  }
1189
- /** @category Advanced */
1190
- interface SubTableMeta {
1191
- /** e.g. "lineItems" */
1343
+ type SubTableMetaCommon = {
1192
1344
  fieldName: string;
1193
- /** e.g. "sales__lineItems" */
1194
1345
  tableName: string;
1195
- /** Schema of a single item in the array */
1196
- itemSchema: TSchema4 & {
1197
- properties: Record<string, TSchema4>;
1198
- };
1199
- /** Columns of the sub-table row (owner PK is prepended automatically) */
1200
1346
  columns: ColumnMeta[];
1201
1347
  columnByName: Map<string, ColumnMeta>;
1202
1348
  columnByPath: Map<string, ColumnMeta>;
1203
- }
1349
+ /** Pre-built INSERT column SQL fragment, e.g. `"_owner_id", "_index", "col1", "col2"` */
1350
+ insertColsSql?: string;
1351
+ /** Pre-built INSERT value group fragment, e.g. `(?, ?, ?, ?)` */
1352
+ insertValueGroup?: string;
1353
+ /** Ordered column names for INSERT */
1354
+ insertColumnNames?: string[];
1355
+ };
1356
+ /** @category Advanced */
1357
+ type SubTableMeta = SubTableMetaCommon & ({
1358
+ isScalar: true;
1359
+ scalarType: SqliteType;
1360
+ itemSchema?: never;
1361
+ } | {
1362
+ isScalar?: false;
1363
+ scalarType?: never;
1364
+ itemSchema?: TSchema4 & {
1365
+ properties: Record<string, TSchema4>;
1366
+ };
1367
+ });
1204
1368
  /** @category Advanced */
1205
1369
  interface TableMeta {
1206
1370
  tableName: string;
@@ -1210,6 +1374,17 @@ interface TableMeta {
1210
1374
  columnByPath: Map<string, ColumnMeta>;
1211
1375
  /** Map from column name → ColumnMeta for O(1) resolution */
1212
1376
  columnByName: Map<string, ColumnMeta>;
1377
+ /** The PK column name of the parent table - used for sub-table filter SQL */
1378
+ primaryKey?: string;
1379
+ /** Non-generated columns - pre-filtered for flattenRow / INSERT / UPDATE */
1380
+ insertColumns: ColumnMeta[];
1381
+ /** Precomputed ordered column names for INSERT SQL */
1382
+ insertColumnNames: string[];
1383
+ /**
1384
+ * Pre-compiled fast hydration function (no codecs, no select/include filtering).
1385
+ * Populated by introspectTable. Use hydrateRowFastCompiled for the common path.
1386
+ */
1387
+ _hydrateFast?: (flat: Record<string, unknown>) => Record<string, unknown>;
1213
1388
  }
1214
1389
  /** @category Advanced */
1215
1390
  declare function introspectTable(tableName: string, schema: TSchema4 & {
@@ -1218,9 +1393,256 @@ declare function introspectTable(tableName: string, schema: TSchema4 & {
1218
1393
  name: string;
1219
1394
  expr: string;
1220
1395
  sqlType?: SqliteType;
1221
- }>): TableMeta;
1396
+ }>, primaryKey?: string): TableMeta;
1222
1397
  /** @category Advanced */
1223
- declare function buildCreateTableSQL(meta: TableMeta, primaryKey: string): string[];
1398
+ declare function buildCreateTableSQL(meta: TableMeta, primaryKey: string, autoIndex?: boolean, onDeleteBehavior?: "native" | "foxdb" | "none"): string[];
1399
+ import { TSchema as TSchema6 } from "typebox";
1400
+ /**
1401
+ * Runtime shape of any filter - independent of the column's value type
1402
+ */
1403
+ type FilterShape = {
1404
+ eq: unknown;
1405
+ } | {
1406
+ ne: unknown;
1407
+ } | {
1408
+ gt: unknown;
1409
+ } | {
1410
+ gte: unknown;
1411
+ } | {
1412
+ lt: unknown;
1413
+ } | {
1414
+ lte: unknown;
1415
+ } | {
1416
+ like: string;
1417
+ } | {
1418
+ between: [unknown, unknown];
1419
+ } | {
1420
+ in: readonly unknown[];
1421
+ } | {
1422
+ notIn: readonly unknown[];
1423
+ } | {
1424
+ isNull: true;
1425
+ } | {
1426
+ isNotNull: true;
1427
+ } | {
1428
+ arraySome: unknown;
1429
+ } | {
1430
+ arrayNot: unknown;
1431
+ } | {
1432
+ isEmpty: boolean;
1433
+ } | {
1434
+ fastArraySome: unknown;
1435
+ } | {
1436
+ fastArrayNot: unknown;
1437
+ } | {
1438
+ fastArrayIsEmpty: boolean;
1439
+ };
1440
+ interface WhereResult {
1441
+ sql: string;
1442
+ params: SQLQueryBindings[];
1443
+ }
1444
+ type ConditionNode = {
1445
+ type: "condition";
1446
+ field: string;
1447
+ filter: FilterShape;
1448
+ } | {
1449
+ type: "raw";
1450
+ sql: string;
1451
+ params: SQLQueryBindings[];
1452
+ } | {
1453
+ type: "and";
1454
+ children: ConditionNode[];
1455
+ } | {
1456
+ type: "or";
1457
+ children: ConditionNode[];
1458
+ } | {
1459
+ type: "not";
1460
+ child: ConditionNode;
1461
+ } | {
1462
+ type: "nested";
1463
+ field: string;
1464
+ children: ConditionNode[];
1465
+ };
1466
+ interface InternalBuilderState {
1467
+ nodes: ConditionNode[];
1468
+ orderBy: Array<{
1469
+ column: string;
1470
+ direction: "ASC" | "DESC";
1471
+ }>;
1472
+ limit: number | undefined;
1473
+ offset: number | undefined;
1474
+ select: string[] | undefined;
1475
+ include: string[] | undefined;
1476
+ includeDeleted: boolean;
1477
+ distinct: boolean;
1478
+ distinctOn: string[] | undefined;
1479
+ }
1480
+ interface AggregateBuilderState {
1481
+ aggregations: Record<string, {
1482
+ op: string;
1483
+ field: string;
1484
+ }>;
1485
+ groupBy: string[] | undefined;
1486
+ having: ConditionNode[];
1487
+ includeDeleted: boolean;
1488
+ }
1489
+ declare function buildWhereFromNodes(nodes: ConditionNode[], softDeleteColumn: string | undefined, meta: TableMeta | undefined): WhereResult;
1490
+ declare class FilterBuilder<
1491
+ TQuery extends TSchema6 & {
1492
+ properties: Record<string, TSchema6>;
1493
+ },
1494
+ TResult,
1495
+ I extends SubTableKeys<TQuery> | undefined = undefined
1496
+ > {
1497
+ private _executor?;
1498
+ private _asyncExecutor?;
1499
+ _nodes: ConditionNode[];
1500
+ private _orderByFields;
1501
+ private _limitValue;
1502
+ private _offsetValue;
1503
+ private _selectFields;
1504
+ private _includeFields;
1505
+ private _includeDeletedValue;
1506
+ private _distinctValue;
1507
+ private _distinctOnFields;
1508
+ constructor(_executor?: ((state: InternalBuilderState) => TResult) | undefined, _asyncExecutor?: ((state: InternalBuilderState) => Promise<TResult>) | undefined);
1509
+ private _assertExecutor;
1510
+ private _collectState;
1511
+ equals<P extends FilterableForInclude<TQuery, I>>(field: P, value: FieldType<TQuery, P>): this;
1512
+ notEquals<P extends FilterableForInclude<TQuery, I>>(field: P, value: FieldType<TQuery, P>): this;
1513
+ greaterThan<P extends FilterableForInclude<TQuery, I>>(field: P, value: FieldType<TQuery, P>): this;
1514
+ greaterThanOrEqual<P extends FilterableForInclude<TQuery, I>>(field: P, value: FieldType<TQuery, P>): this;
1515
+ lessThan<P extends FilterableForInclude<TQuery, I>>(field: P, value: FieldType<TQuery, P>): this;
1516
+ lessThanOrEqual<P extends FilterableForInclude<TQuery, I>>(field: P, value: FieldType<TQuery, P>): this;
1517
+ between<P extends FilterableForInclude<TQuery, I>>(field: P, min: FieldType<TQuery, P>, max: FieldType<TQuery, P>): this;
1518
+ like<P extends FilterableForInclude<TQuery, I>>(field: P, pattern: string): this;
1519
+ contains<P extends FilterableForInclude<TQuery, I>>(field: P, substring: string): this;
1520
+ startsWith<P extends FilterableForInclude<TQuery, I>>(field: P, prefix: string): this;
1521
+ endsWith<P extends FilterableForInclude<TQuery, I>>(field: P, suffix: string): this;
1522
+ in<P extends FilterableForInclude<TQuery, I>>(field: P, values: FieldType<TQuery, P>[]): this;
1523
+ notIn<P extends FilterableForInclude<TQuery, I>>(field: P, values: FieldType<TQuery, P>[]): this;
1524
+ isNull<P extends FilterableForInclude<TQuery, I>>(field: P): this;
1525
+ isNotNull<P extends FilterableForInclude<TQuery, I>>(field: P): this;
1526
+ arraySome<P extends ArrayFilterableFields<TQuery>>(field: P, value: ArrayItemType<TQuery, P>): this;
1527
+ arrayNone<P extends ArrayFilterableFields<TQuery>>(field: P, value: ArrayItemType<TQuery, P>): this;
1528
+ isEmpty<P extends ArrayFilterableFields<TQuery>>(field: P): this;
1529
+ isNotEmpty<P extends ArrayFilterableFields<TQuery>>(field: P): this;
1530
+ arrayEvery<P extends ArrayFilterableFields<TQuery>>(_field: P, _value: ArrayItemType<TQuery, P>): this;
1531
+ arrayContainsAll<P extends ArrayFilterableFields<TQuery>>(_field: P, _values: ArrayItemType<TQuery, P>[]): this;
1532
+ arrayLength<P extends ArrayFilterableFields<TQuery>>(_field: P, _op: "eq" | "ne" | "gt" | "gte" | "lt" | "lte", _value: number): this;
1533
+ nested<P extends FilterableForInclude<TQuery, I>>(field: P, callback: (q: FilterBuilder<TQuery, unknown>) => void): this;
1534
+ and(callback: (q: FilterBuilder<TQuery, unknown>) => void): this;
1535
+ or(callback: (q: FilterBuilder<TQuery, unknown>) => void): this;
1536
+ not(callback: (q: FilterBuilder<TQuery, unknown>) => void): this;
1537
+ raw(sql: string, params?: SQLQueryBindings[]): this;
1538
+ orderBy<P extends OrderableFields<TQuery>>(field: P, direction?: "ASC" | "DESC"): this;
1539
+ thenBy<P extends OrderableFields<TQuery>>(field: P, direction?: "ASC" | "DESC"): this;
1540
+ limit(n: number): this;
1541
+ offset(n: number): this;
1542
+ select<S extends SelectableKeys<TQuery>[]>(...fields: S): this;
1543
+ include<Inc extends SubTableKeys<TQuery>[]>(...relations: Inc): FilterBuilder<TQuery, TResult, Inc[number]>;
1544
+ distinct(): this;
1545
+ distinctOn<D extends DistinctableFields<TQuery>[]>(...fields: D): this;
1546
+ includeDeleted(): this;
1547
+ exec(): TResult;
1548
+ execAsync(): Promise<TResult>;
1549
+ execThrowable(): TResult;
1550
+ }
1551
+ declare class AggregateBuilder<TQuery extends TSchema6 & {
1552
+ properties: Record<string, TSchema6>;
1553
+ }> {
1554
+ private _executor;
1555
+ private _asyncExecutor?;
1556
+ private _aggregations;
1557
+ private _groupByFields;
1558
+ private _havingNodes;
1559
+ private _whereNodes;
1560
+ private _includeDeletedValue;
1561
+ constructor(_executor: (state: AggregateBuilderState) => Record<string, unknown>[], _asyncExecutor?: ((state: AggregateBuilderState) => Promise<Record<string, unknown>[]>) | undefined);
1562
+ sum(field: string, alias: string): this;
1563
+ count(field: string, alias: string): this;
1564
+ avg(field: string, alias: string): this;
1565
+ min(field: string, alias: string): this;
1566
+ max(field: string, alias: string): this;
1567
+ groupBy<G extends string[]>(...fields: G): this;
1568
+ having(callback: (q: FilterBuilder<TQuery, unknown>) => void): this;
1569
+ includeDeleted(): this;
1570
+ exec(): Record<string, unknown>[];
1571
+ execAsync(): Promise<Record<string, unknown>[]>;
1572
+ }
1573
+ import { TSchema as TSchema7 } from "typebox";
1574
+ declare function ftsTableName(tableName: string): string;
1575
+ declare function resolveFtsColumns(meta: TableMeta, fts: FTSConfig): string[];
1576
+ interface FtsSnippetSpec {
1577
+ field: string;
1578
+ open: string;
1579
+ close: string;
1580
+ ellipsis: string;
1581
+ tokens: number;
1582
+ }
1583
+ interface FtsHighlightSpec {
1584
+ field: string;
1585
+ open: string;
1586
+ close: string;
1587
+ }
1588
+ interface FtsSearchState {
1589
+ query: string;
1590
+ limit?: number;
1591
+ offset?: number;
1592
+ weightMap?: Record<string, number>;
1593
+ weights?: number[];
1594
+ snippets: FtsSnippetSpec[];
1595
+ highlights: FtsHighlightSpec[];
1596
+ includeDeleted: boolean;
1597
+ nodes: ConditionNode[];
1598
+ }
1599
+ type FtsResult<E> = E & {
1600
+ _score: number;
1601
+ _snippet: Record<string, string>;
1602
+ _highlight: Record<string, string>;
1603
+ };
1604
+ declare function buildFtsSearchSql(tableName: string, ftsColumns: string[], state: FtsSearchState, softDeleteColumn: string | undefined, meta: TableMeta): {
1605
+ sql: string;
1606
+ params: SQLQueryBindings[];
1607
+ snippetAliases: Array<{
1608
+ field: string;
1609
+ alias: string;
1610
+ }>;
1611
+ highlightAliases: Array<{
1612
+ field: string;
1613
+ alias: string;
1614
+ }>;
1615
+ };
1616
+ declare class FtsSearchBuilder<
1617
+ TQuery extends TSchema7 & {
1618
+ properties: Record<string, TSchema7>;
1619
+ },
1620
+ TEntity,
1621
+ FTS extends string
1622
+ > {
1623
+ private _exec;
1624
+ private _execAsync?;
1625
+ _state: FtsSearchState;
1626
+ constructor(query: string, _exec: (state: FtsSearchState) => FtsResult<TEntity>[], _execAsync?: ((state: FtsSearchState) => Promise<FtsResult<TEntity>[]>) | undefined);
1627
+ limit(n: number): this;
1628
+ offset(n: number): this;
1629
+ includeDeleted(): this;
1630
+ weight(field: FTS, w: number): this;
1631
+ weights(map: Partial<Record<FTS, number>>): this;
1632
+ snippet(field: FTS, opts?: {
1633
+ open?: string;
1634
+ close?: string;
1635
+ ellipsis?: string;
1636
+ tokens?: number;
1637
+ }): this;
1638
+ highlight(field: FTS, opts?: {
1639
+ open?: string;
1640
+ close?: string;
1641
+ }): this;
1642
+ where(cb: (q: FilterBuilder<TQuery, unknown>) => void): this;
1643
+ exec(): FtsResult<TEntity>[];
1644
+ execAsync(): Promise<FtsResult<TEntity>[]>;
1645
+ }
1224
1646
  interface BatchWriterOptions {
1225
1647
  maxBuffer?: number;
1226
1648
  flushIntervalMs?: number;
@@ -1236,7 +1658,7 @@ declare class BatchWriter<
1236
1658
  private readonly prepare;
1237
1659
  private readonly onFlush?;
1238
1660
  private timer?;
1239
- constructor(tableName: string, db: BunDatabase, opts: BatchWriterOptions, callbacks: {
1661
+ constructor(tableName: string, db: BunDatabase, opts: BatchWriterOptions | undefined, callbacks: {
1240
1662
  prepare: (row: TInput) => TRow;
1241
1663
  onFlush?: (rows: TRow[]) => void;
1242
1664
  });
@@ -1244,6 +1666,25 @@ declare class BatchWriter<
1244
1666
  flush(): void;
1245
1667
  close(): void;
1246
1668
  }
1669
+ declare class ReadScheduler {
1670
+ private workers;
1671
+ private workerStatus;
1672
+ private taskCounter;
1673
+ private readonly MAX_PENDING_TASKS;
1674
+ private readonly pendingTasks;
1675
+ private readonly overflowQueue;
1676
+ private overflowHead;
1677
+ private nextWorkerHint;
1678
+ private readonly columnCache;
1679
+ constructor(opts?: DatabaseOptions, workerCount?: number);
1680
+ private initWorkers;
1681
+ private dispatch;
1682
+ private dequeueOrIdle;
1683
+ exec<T = any>(sql: string, params?: any[]): Promise<T>;
1684
+ execWithCols<T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params: any[], columns: string[]): Promise<T[]>;
1685
+ private enqueue;
1686
+ terminate(): void;
1687
+ }
1247
1688
  /**
1248
1689
  * Typed repository for a single table. Every entry in your `tables` config
1249
1690
  * becomes one of these on the ORM object, fully typed to its schema.
@@ -1266,34 +1707,59 @@ declare class BatchWriter<
1266
1707
  * ```
1267
1708
  */
1268
1709
  declare class Repository<
1269
- TWrite extends TSchema5 & {
1270
- properties: Record<string, TSchema5>;
1710
+ TWrite extends TSchema8 & {
1711
+ properties: Record<string, TSchema8>;
1271
1712
  },
1272
- TQuery extends TSchema5 & {
1273
- properties: Record<string, TSchema5>;
1713
+ TQuery extends TSchema8 & {
1714
+ properties: Record<string, TSchema8>;
1274
1715
  },
1275
1716
  PK extends ScalarKeys<TWrite>,
1276
1717
  Mat = never,
1277
- TS = {}
1718
+ TS = {},
1719
+ FTS extends string = never
1278
1720
  > {
1279
1721
  readonly tableName: string;
1280
1722
  /** table metadata - columns, sub-tables, indexes */
1281
1723
  readonly meta: TableMeta;
1724
+ /**
1725
+ * Get the underlying SQLite table name for a sub-table by field name.
1726
+ * Returns undefined if the field is not a sub-table (array relationship).
1727
+ *
1728
+ * @example
1729
+ * ```ts
1730
+ * orm.purchases.getSubTableName("PurchaseLineItems")
1731
+ * // => "archivedPurchases__PurchaseLineItems"
1732
+ * ```
1733
+ */
1734
+ getSubTableName(fieldName: string): string | undefined;
1282
1735
  private readonly validator;
1283
1736
  private readonly db;
1284
1737
  private readonly descriptor;
1285
1738
  private _entityProto;
1286
1739
  private readonly _timestampNames;
1740
+ private readonly _hasTimestamps;
1741
+ private readonly _hasEviction;
1287
1742
  private _materialize?;
1288
1743
  private _materializeMany?;
1289
1744
  private _events?;
1290
1745
  private _executor;
1291
1746
  private readonly _codecs;
1747
+ private readonly _insertColsSql;
1748
+ private readonly _insertPlaceholders;
1749
+ private readonly _readScheduler?;
1750
+ private readonly _allColumnNames;
1751
+ private readonly _onDeleteBehavior;
1752
+ private readonly _ftsEnabled;
1753
+ private readonly _ftsTableName;
1754
+ private readonly _ftsColumns;
1755
+ private readonly _ftsColumnSet;
1756
+ private readonly _ftsInsertDirectSql;
1757
+ private readonly _ftsDeleteDirectSql;
1292
1758
  /** @internal */
1293
1759
  setEventBus(bus: EventBus): void;
1294
1760
  /** @internal */
1295
1761
  setMetricsHook(hook?: (meta: QueryMetrics) => void): void;
1296
- constructor(tableName: string, config: TableConfig<TWrite, PK & string, TimestampConfig, GeneratedColumnConfig | undefined>, db: BunDatabase);
1762
+ constructor(tableName: string, config: TableConfig<TWrite, PK & string, TimestampConfig, GeneratedColumnConfig | undefined, FTSConfig | undefined>, db: BunDatabase, readScheduler?: ReadScheduler, onDeleteBehavior?: "native" | "foxdb" | "none");
1297
1763
  /** Ensure PK is selected when include is requested */
1298
1764
  private _ensureSelectPk;
1299
1765
  /**
@@ -1303,8 +1769,10 @@ declare class Repository<
1303
1769
  private _fetchRows;
1304
1770
  /** Inject materializers after ORM two-pass init */
1305
1771
  setMaterializer(single: (record: Record<string, unknown>) => Record<string, unknown>, many: (records: Record<string, unknown>[]) => Record<string, unknown>[]): void;
1306
- /** Wrap raw data in an entity object */
1772
+ /** Wrap raw data in an entity object (with sub-table fields) */
1307
1773
  private _wrap;
1774
+ /** Wrap raw data in an entity object (without sub-table fields) */
1775
+ private _wrapNoSubs;
1308
1776
  /** Narrow a parsed schema value to a plain record for dynamic property access */
1309
1777
  private _record;
1310
1778
  /** Validate that a value is a valid SQLite scalar for use as a primary key */
@@ -1352,6 +1820,7 @@ declare class Repository<
1352
1820
  * ```
1353
1821
  */
1354
1822
  insert(data: InsertData<TWrite>): Entity<Infer<TQuery>, Mat, TS>;
1823
+ private _insertRow;
1355
1824
  /**
1356
1825
  * Insert many records in a single transaction.
1357
1826
  *
@@ -1426,139 +1895,142 @@ declare class Repository<
1426
1895
  findById(id: Infer<TQuery>[PK]): Entity<Infer<TQuery>, Mat, TS> | null;
1427
1896
  /** Internal findById without event emission - used by update() */
1428
1897
  private _findByIdRaw;
1898
+ /** Internal raw row fetch without hydration - used by update() */
1899
+ private _findFlatRow;
1429
1900
  /**
1430
1901
  * Find many records matching the given filters.
1902
+ * Legacy object-based API - use `findMany()` chain API for new code.
1431
1903
  *
1432
1904
  * @group Reading
1433
1905
  *
1434
1906
  * @example
1435
1907
  * ```ts
1436
- * const adults = orm.users.findMany({
1908
+ * const adults = orm.users.O_findMany({
1437
1909
  * where: { age: { gte: 18 } },
1438
1910
  * orderBy: { column: "name", direction: "ASC" },
1439
1911
  * limit: 10,
1440
1912
  * });
1441
- *
1442
- * // Include sub-tables
1443
- * const orders = orm.orders.findMany({ include: ["lineItems"] });
1444
1913
  * ```
1445
1914
  */
1446
- findMany<
1915
+ O_findMany<
1447
1916
  const S extends readonly SelectableKeys<TQuery>[],
1448
1917
  const I extends readonly SubTableKeys<TQuery>[]
1449
1918
  >(opts: FindOptions<TQuery> & {
1450
1919
  select: S;
1451
1920
  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> & {
1921
+ }): (SelectShape<TQuery, S> & { [K in I[number]] : SubTableItem<TQuery, K>[] })[];
1922
+ O_findMany<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1923
+ include: I;
1924
+ }): (Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] })[];
1925
+ O_findMany<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1454
1926
  select: S;
1455
- }): (SelectShape<TQuery, S> & TS)[];
1456
- findMany(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS>[];
1927
+ }): (SelectShape<TQuery, S>)[];
1928
+ O_findMany(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS>[];
1457
1929
  /**
1458
1930
  * Find many with total count - useful for pagination.
1931
+ * Legacy object-based API - use `findPage()` chain API for new code.
1459
1932
  *
1460
1933
  * @group Reading
1461
1934
  *
1462
1935
  * @example
1463
1936
  * ```ts
1464
- * const page = orm.users.findPage({
1937
+ * const page = orm.users.O_findPage({
1465
1938
  * where: { status: { eq: "active" } },
1466
1939
  * limit: 10,
1467
1940
  * offset: 0,
1468
1941
  * });
1469
- * // page.data - the records
1470
- * // page.total - total matching records
1471
- * // page.limit, page.offset - what you passed in
1472
1942
  * ```
1473
1943
  */
1474
- findPage<
1944
+ O_findPage<
1475
1945
  const S extends readonly SelectableKeys<TQuery>[],
1476
1946
  const I extends readonly SubTableKeys<TQuery>[]
1477
1947
  >(opts: FindOptions<TQuery> & {
1478
1948
  select: S;
1479
1949
  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> & {
1950
+ }): PageResult<SelectShape<TQuery, S> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
1951
+ O_findPage<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1952
+ include: I;
1953
+ }): PageResult<Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
1954
+ O_findPage<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1482
1955
  select: S;
1483
- }): PageResult<SelectShape<TQuery, S> & TS>;
1484
- findPage(opts?: FindOptions<TQuery>): PageResult<Entity<Infer<TQuery>, Mat, TS>>;
1956
+ }): PageResult<SelectShape<TQuery, S>>;
1957
+ O_findPage(opts?: FindOptions<TQuery>): PageResult<Entity<Infer<TQuery>, Mat, TS>>;
1485
1958
  /**
1486
1959
  * Cursor-based pagination (seek method). Avoids OFFSET degradation on
1487
1960
  * large tables by using a boundary value from the previous page.
1961
+ * Legacy object-based API - use `findCursorPage()` chain API for new code.
1488
1962
  *
1489
1963
  * @group Reading
1490
1964
  *
1491
1965
  * @example
1492
1966
  * ```ts
1493
- * const page = orm.orders.findCursorPage({
1494
- * orderBy: { column: "DocumentDate", direction: "DESC" },
1495
- * limit: 25,
1496
- * });
1497
- *
1498
- * const next = orm.orders.findCursorPage({
1967
+ * const page = orm.orders.O_findCursorPage({
1499
1968
  * orderBy: { column: "DocumentDate", direction: "DESC" },
1500
- * cursor: page.nextCursor!,
1501
1969
  * limit: 25,
1502
1970
  * });
1503
1971
  * ```
1504
1972
  */
1505
- findCursorPage(opts: {
1973
+ O_findCursorPage(opts: {
1506
1974
  where?: WhereClause<TQuery>;
1507
1975
  orderBy: OrderByClause<TQuery>;
1508
1976
  cursor?: CursorInput;
1509
1977
  limit?: number;
1510
1978
  }): CursorPageResult<Entity<Infer<TQuery>, Mat, TS>>;
1511
1979
  /**
1512
- * Find a single record matching the given filters. Equivalent to `findMany`
1513
- * with `limit: 1`, but returns the entity directly (or `null`).
1980
+ * Find a single record matching the given filters.
1981
+ * Legacy object-based API - use `findOne()` chain API for new code.
1514
1982
  *
1515
1983
  * @group Reading
1516
1984
  *
1517
1985
  * @example
1518
1986
  * ```ts
1519
- * const admin = orm.users.findOne({
1987
+ * const admin = orm.users.O_findOne({
1520
1988
  * where: { role: { eq: "admin" } },
1521
1989
  * });
1522
1990
  * ```
1523
1991
  */
1524
- findOne<
1992
+ O_findOne<
1525
1993
  const S extends readonly SelectableKeys<TQuery>[],
1526
1994
  const I extends readonly SubTableKeys<TQuery>[]
1527
1995
  >(opts: FindOptions<TQuery> & {
1528
1996
  select: S;
1529
1997
  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> & {
1998
+ }): (SelectShape<TQuery, S> & { [K in I[number]] : SubTableItem<TQuery, K>[] }) | null;
1999
+ O_findOne<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2000
+ include: I;
2001
+ }): (Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] }) | null;
2002
+ O_findOne<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1532
2003
  select: S;
1533
- }): (SelectShape<TQuery, S> & TS) | null;
1534
- findOne(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS> | null;
2004
+ }): (SelectShape<TQuery, S>) | null;
2005
+ O_findOne(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS> | null;
1535
2006
  /**
1536
2007
  * Iterate over records matching the given filters, yielding one row at a time.
1537
- * Sub-tables are hydrated in windows to keep memory stable.
2008
+ * Legacy object-based API - use `iterate()` chain API for new code.
1538
2009
  *
1539
2010
  * @group Reading
1540
2011
  *
1541
2012
  * @example
1542
2013
  * ```ts
1543
- * for (const user of orm.users.iterate({ where: { active: { eq: true } } })) {
2014
+ * for (const user of orm.users.O_iterate({ where: { active: { eq: true } } })) {
1544
2015
  * console.log(user.name);
1545
2016
  * }
1546
2017
  * ```
1547
2018
  */
1548
- iterate<
2019
+ O_iterate<
1549
2020
  const S extends readonly SelectableKeys<TQuery>[],
1550
2021
  const I extends readonly SubTableKeys<TQuery>[]
1551
2022
  >(opts: FindOptions<TQuery> & {
1552
2023
  select: S;
1553
2024
  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> & {
2025
+ }): Generator<SelectShape<TQuery, S> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
2026
+ O_iterate<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1556
2027
  include: I;
1557
2028
  }): Generator<Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>;
1558
- iterate<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2029
+ O_iterate<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
1559
2030
  select: S;
1560
- }): Generator<SelectShape<TQuery, S> & TS>;
1561
- iterate(opts?: FindOptions<TQuery>): Generator<Entity<Infer<TQuery>, Mat, TS>>;
2031
+ }): Generator<SelectShape<TQuery, S>>;
2032
+ O_iterate(opts?: FindOptions<TQuery>): Generator<Entity<Infer<TQuery>, Mat, TS>>;
2033
+ private _iterateImpl;
1562
2034
  private _hydrateWindow;
1563
2035
  /**
1564
2036
  * Find many with resolved relations (n+1 safe). If you have cross-table
@@ -1577,35 +2049,32 @@ declare class Repository<
1577
2049
  findManyMaterialized(opts?: FindOptions<TQuery>): Entity<Infer<TQuery>, Mat, TS>[];
1578
2050
  /**
1579
2051
  * Count records matching the given filters.
2052
+ * Legacy object-based API - use `count()` chain API for new code.
1580
2053
  *
1581
2054
  * @group Reading
1582
2055
  *
1583
2056
  * @example
1584
2057
  * ```ts
1585
- * const total = orm.users.count();
1586
- * const adults = orm.users.count({ age: { gte: 18 } });
2058
+ * const total = orm.users.O_count();
2059
+ * const adults = orm.users.O_count({ age: { gte: 18 } });
1587
2060
  * ```
1588
2061
  */
1589
- count(where?: WhereClause<TQuery>): number;
2062
+ O_count(where?: WhereClause<TQuery>): number;
1590
2063
  /**
1591
2064
  * Run aggregate queries (sum, count, avg, min, max) with optional
1592
2065
  * grouping and filtering.
2066
+ * Legacy object-based API - use `aggregate()` chain API for new code.
1593
2067
  *
1594
2068
  * @group Reading
1595
2069
  *
1596
2070
  * @example
1597
2071
  * ```ts
1598
- * orm.orders.aggregate({
2072
+ * orm.orders.O_aggregate({
1599
2073
  * aggregations: { total: { sum: "amount" } },
1600
2074
  * });
1601
- *
1602
- * orm.orders.aggregate({
1603
- * groupBy: ["status"],
1604
- * aggregations: { count: { count: "*" }, avgAmount: { avg: "amount" } },
1605
- * });
1606
2075
  * ```
1607
2076
  */
1608
- aggregate<
2077
+ O_aggregate<
1609
2078
  const A extends Record<string, AggregationOp<TQuery>>,
1610
2079
  const G extends readonly (ScalarKeys<TQuery> | ScalarJsonPath<TQuery>)[] | undefined = undefined
1611
2080
  >(opts: AggregateOptions<TQuery, A> & {
@@ -1614,12 +2083,13 @@ declare class Repository<
1614
2083
  /**
1615
2084
  * Run window function queries (rowNumber, rank, denseRank, lead, lag)
1616
2085
  * with partitioning and ordering.
2086
+ * Legacy object-based API - use `windowQuery()` chain API for new code.
1617
2087
  *
1618
2088
  * @group Reading
1619
2089
  *
1620
2090
  * @example
1621
2091
  * ```ts
1622
- * orm.orders.windowQuery({
2092
+ * orm.orders.O_windowQuery({
1623
2093
  * partitionBy: ["Status__Group"],
1624
2094
  * orderBy: [{ column: "DocumentDate", direction: "DESC" }],
1625
2095
  * select: {
@@ -1631,10 +2101,200 @@ declare class Repository<
1631
2101
  * });
1632
2102
  * ```
1633
2103
  */
1634
- windowQuery<const W extends Record<string, WindowFunction<TQuery>>>(opts: WindowQueryOptions<TQuery> & {
2104
+ O_windowQuery<const W extends Record<string, WindowFunction<TQuery>>>(opts: WindowQueryOptions<TQuery> & {
1635
2105
  select: W;
1636
2106
  }): WindowResult<TQuery, W>;
1637
2107
  /**
2108
+ * Async variant of O_findMany - executes on the worker thread pool.
2109
+ */
2110
+ O_findManyAsync<
2111
+ const S extends readonly SelectableKeys<TQuery>[],
2112
+ const I extends readonly SubTableKeys<TQuery>[]
2113
+ >(opts: FindOptions<TQuery> & {
2114
+ select: S;
2115
+ include: I;
2116
+ }): Promise<(SelectShape<TQuery, S> & { [K in I[number]] : SubTableItem<TQuery, K>[] })[]>;
2117
+ O_findManyAsync<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2118
+ include: I;
2119
+ }): Promise<(Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] })[]>;
2120
+ O_findManyAsync<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2121
+ select: S;
2122
+ }): Promise<(SelectShape<TQuery, S>)[]>;
2123
+ O_findManyAsync(opts?: FindOptions<TQuery>): Promise<Entity<Infer<TQuery>, Mat, TS>[]>;
2124
+ /**
2125
+ * Async variant of O_findOne - executes on the worker thread pool.
2126
+ */
2127
+ O_findOneAsync<
2128
+ const S extends readonly SelectableKeys<TQuery>[],
2129
+ const I extends readonly SubTableKeys<TQuery>[]
2130
+ >(opts: FindOptions<TQuery> & {
2131
+ select: S;
2132
+ include: I;
2133
+ }): Promise<(SelectShape<TQuery, S> & { [K in I[number]] : SubTableItem<TQuery, K>[] }) | null>;
2134
+ O_findOneAsync<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2135
+ include: I;
2136
+ }): Promise<(Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] }) | null>;
2137
+ O_findOneAsync<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2138
+ select: S;
2139
+ }): Promise<(SelectShape<TQuery, S>) | null>;
2140
+ O_findOneAsync(opts?: FindOptions<TQuery>): Promise<Entity<Infer<TQuery>, Mat, TS> | null>;
2141
+ /**
2142
+ * Async variant of O_findPage - executes on the worker thread pool.
2143
+ */
2144
+ O_findPageAsync<
2145
+ const S extends readonly SelectableKeys<TQuery>[],
2146
+ const I extends readonly SubTableKeys<TQuery>[]
2147
+ >(opts: FindOptions<TQuery> & {
2148
+ select: S;
2149
+ include: I;
2150
+ }): Promise<PageResult<SelectShape<TQuery, S> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>>;
2151
+ O_findPageAsync<const I extends readonly SubTableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2152
+ include: I;
2153
+ }): Promise<PageResult<Entity<Infer<TQuery>, Mat, TS> & { [K in I[number]] : SubTableItem<TQuery, K>[] }>>;
2154
+ O_findPageAsync<const S extends readonly SelectableKeys<TQuery>[]>(opts: FindOptions<TQuery> & {
2155
+ select: S;
2156
+ }): Promise<PageResult<SelectShape<TQuery, S>>>;
2157
+ O_findPageAsync(opts?: FindOptions<TQuery>): Promise<PageResult<Entity<Infer<TQuery>, Mat, TS>>>;
2158
+ /**
2159
+ * Async variant of O_findCursorPage - executes on the worker thread pool.
2160
+ */
2161
+ O_findCursorPageAsync(opts: {
2162
+ where?: WhereClause<TQuery>;
2163
+ orderBy: OrderByClause<TQuery>;
2164
+ cursor?: CursorInput;
2165
+ limit?: number;
2166
+ }): Promise<CursorPageResult<Entity<Infer<TQuery>, Mat, TS>>>;
2167
+ /**
2168
+ * Async variant of O_count - executes on the worker thread pool.
2169
+ */
2170
+ O_countAsync(where?: WhereClause<TQuery>): Promise<number>;
2171
+ /**
2172
+ * Async variant of O_aggregate - executes on the worker thread pool.
2173
+ */
2174
+ O_aggregateAsync<
2175
+ const A extends Record<string, AggregationOp<TQuery>>,
2176
+ const G extends readonly (ScalarKeys<TQuery> | ScalarJsonPath<TQuery>)[] | undefined = undefined
2177
+ >(opts: AggregateOptions<TQuery, A> & {
2178
+ groupBy?: G;
2179
+ }): Promise<AggregateResult<TQuery, A, G>>;
2180
+ /**
2181
+ * Async variant of O_windowQuery - executes on the worker thread pool.
2182
+ */
2183
+ O_windowQueryAsync<const W extends Record<string, WindowFunction<TQuery>>>(opts: WindowQueryOptions<TQuery> & {
2184
+ select: W;
2185
+ }): Promise<WindowResult<TQuery, W>>;
2186
+ /**
2187
+ * Async variant of findById - executes on the worker thread pool.
2188
+ */
2189
+ findByIdAsync(id: Infer<TQuery>[PK]): Promise<Entity<Infer<TQuery>, Mat, TS> | null>;
2190
+ /**
2191
+ * Async variant of findManyMaterialized - executes on the worker thread pool.
2192
+ */
2193
+ findManyMaterializedAsync(opts?: FindOptions<TQuery>): Promise<Entity<Infer<TQuery>, Mat, TS>[]>;
2194
+ /**
2195
+ * Async variant of raw - executes on the worker thread pool.
2196
+ */
2197
+ rawAsync<R = DBRow>(sql: string, ...params: DBValue[]): Promise<R[]>;
2198
+ /**
2199
+ * Start a chain filter query that returns many records.
2200
+ *
2201
+ * @group Reading - Chain API
2202
+ *
2203
+ * @example
2204
+ * ```ts
2205
+ * const adults = orm.users
2206
+ * .findMany()
2207
+ * .greaterThanOrEqual("age", 18)
2208
+ * .equals("active", true)
2209
+ * .orderBy("createdAt", "DESC")
2210
+ * .limit(10)
2211
+ * .exec();
2212
+ * ```
2213
+ */
2214
+ findMany(): FilterBuilder<TQuery, Entity<Infer<TQuery>, Mat, TS>[]>;
2215
+ /**
2216
+ * Start a chain filter query that returns a single record.
2217
+ *
2218
+ * @group Reading - Chain API
2219
+ *
2220
+ * @example
2221
+ * ```ts
2222
+ * const admin = orm.users
2223
+ * .findOne()
2224
+ * .equals("role", "admin")
2225
+ * .exec();
2226
+ * ```
2227
+ */
2228
+ findOne(): FilterBuilder<TQuery, Entity<Infer<TQuery>, Mat, TS> | null>;
2229
+ /**
2230
+ * Start a chain count query.
2231
+ *
2232
+ * @group Reading - Chain API
2233
+ *
2234
+ * @example
2235
+ * ```ts
2236
+ * const total = orm.users
2237
+ * .count()
2238
+ * .equals("active", true)
2239
+ * .exec();
2240
+ * ```
2241
+ */
2242
+ count(): FilterBuilder<TQuery, number>;
2243
+ /**
2244
+ * Start a chain paginated query.
2245
+ *
2246
+ * @group Reading - Chain API
2247
+ *
2248
+ * @example
2249
+ * ```ts
2250
+ * const page = orm.users
2251
+ * .findPage()
2252
+ * .equals("active", true)
2253
+ * .limit(10)
2254
+ * .offset(0)
2255
+ * .exec();
2256
+ * ```
2257
+ */
2258
+ findPage(): FilterBuilder<TQuery, PageResult<Entity<Infer<TQuery>, Mat, TS>>>;
2259
+ /**
2260
+ * Start a chain cursor-paginated query.
2261
+ *
2262
+ * @group Reading - Chain API
2263
+ *
2264
+ * @example
2265
+ * ```ts
2266
+ * const page = orm.orders
2267
+ * .findCursorPage()
2268
+ * .orderBy("id", "ASC")
2269
+ * .limit(25)
2270
+ * .exec();
2271
+ * ```
2272
+ */
2273
+ findCursorPage(): FilterBuilder<TQuery, CursorPageResult<Entity<Infer<TQuery>, Mat, TS>>>;
2274
+ /**
2275
+ * Start a chain aggregate query.
2276
+ *
2277
+ * @group Reading - Chain API
2278
+ *
2279
+ * @example
2280
+ * ```ts
2281
+ * const totals = orm.orders
2282
+ * .aggregate()
2283
+ * .sum("amount", "totalRevenue")
2284
+ * .count("*", "orderCount")
2285
+ * .groupBy("status")
2286
+ * .exec();
2287
+ * ```
2288
+ */
2289
+ aggregate(): AggregateBuilder<TQuery>;
2290
+ /**
2291
+ * Full-text search (FTS5). Present only on tables with `fts` enabled.
2292
+ * @group Reading - Chain API
2293
+ */
2294
+ search(query: string): FtsSearchBuilder<TQuery, Entity<Infer<TQuery>, Mat, TS>, FTS>;
2295
+ /** Convenience async full-text search. Present only on tables with `fts` enabled. */
2296
+ searchAsync(query: string): Promise<FtsResult<Entity<Infer<TQuery>, Mat, TS>>[]>;
2297
+ /**
1638
2298
  * Update a record - must include the primary key. Returns the updated
1639
2299
  * entity, or `null` if no record matched.
1640
2300
  *
@@ -1705,6 +2365,13 @@ declare class Repository<
1705
2365
  * ```
1706
2366
  */
1707
2367
  drop(): void;
2368
+ private _ftsIndexByPk;
2369
+ private _ftsDeleteByPk;
2370
+ private _ftsIndexByRowid;
2371
+ private _ftsDeleteByRowid;
2372
+ private _patchTouchesFts;
2373
+ private _ftsBindInsert;
2374
+ private _ftsBindDelete;
1708
2375
  private _hydrateOne;
1709
2376
  /**
1710
2377
  * Run raw SQL - escape hatch for queries the ORM doesn't support directly.
@@ -1720,7 +2387,7 @@ declare class Repository<
1720
2387
  */
1721
2388
  raw<R = DBRow>(sql: string, ...params: DBValue[]): R[];
1722
2389
  }
1723
- declare class RelationBuilder<Tables extends Record<string, TableDescriptor<any, any, any, any>>> {
2390
+ declare class RelationBuilder<Tables extends Record<string, TableDescriptor<any, any, any, any, any>>> {
1724
2391
  private readonly tables;
1725
2392
  private readonly relations;
1726
2393
  constructor(tables: Tables);
@@ -1750,13 +2417,13 @@ declare class RelationBuilder<Tables extends Record<string, TableDescriptor<any,
1750
2417
  build(): TypedRelation[];
1751
2418
  }
1752
2419
  /** @category Relations */
1753
- declare function createRelationBuilder<T extends Record<string, TableDescriptor<any, any, any, any>>>(tables: T): RelationBuilder<T>;
1754
- import { Static as Static2 } from "typebox";
1755
- declare const SchemaHashSchema: unknown;
1756
- declare const SchemaJSONSchema: unknown;
1757
- declare const TablesSchema: unknown;
1758
- declare const RelationsSchema: unknown;
1759
- declare const VersionSchema: unknown;
2420
+ declare function createRelationBuilder<T extends Record<string, TableDescriptor<any, any, any, any, any>>>(tables: T): RelationBuilder<T>;
2421
+ import { Static as Static2, TSchema as TSchema9 } from "typebox";
2422
+ declare const SchemaHashSchema: TSchema9;
2423
+ declare const SchemaJSONSchema: TSchema9;
2424
+ declare const TablesSchema: TSchema9;
2425
+ declare const RelationsSchema: TSchema9;
2426
+ declare const VersionSchema: TSchema9;
1760
2427
  type SchemaHash = Static2<typeof SchemaHashSchema>;
1761
2428
  type SchemaJSON = Static2<typeof SchemaJSONSchema>;
1762
2429
  type TablesList = Static2<typeof TablesSchema>;
@@ -1798,7 +2465,7 @@ declare class MetaStore {
1798
2465
  * @category Lifecycle
1799
2466
  */
1800
2467
  interface ORMContext<
1801
- T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
2468
+ T extends Record<string, TableDescriptor<any, any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any, any>>,
1802
2469
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1803
2470
  > {
1804
2471
  orm: foxdb<T, Rels>;
@@ -1816,7 +2483,7 @@ interface ORMContext<
1816
2483
  * @category Lifecycle
1817
2484
  */
1818
2485
  type LifecycleHook<
1819
- T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
2486
+ T extends Record<string, TableDescriptor<any, any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any, any>>,
1820
2487
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1821
2488
  > = (ctx: ORMContext<T, Rels>) => void | Promise<void>;
1822
2489
  /**
@@ -1824,7 +2491,7 @@ type LifecycleHook<
1824
2491
  * @category Lifecycle
1825
2492
  */
1826
2493
  declare class LifecycleManager<
1827
- T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
2494
+ T extends Record<string, TableDescriptor<any, any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any, any>>,
1828
2495
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1829
2496
  > {
1830
2497
  private startHooks;
@@ -1834,17 +2501,17 @@ declare class LifecycleManager<
1834
2501
  private _ready;
1835
2502
  private _shutdown;
1836
2503
  /** true after runReady completes */
1837
- get isReady();
2504
+ get isReady(): boolean;
1838
2505
  /** true after runShutdown completes */
1839
- get isShutdown();
2506
+ get isShutdown(): boolean;
1840
2507
  /** register a startup hook */
1841
- onStart(hook: LifecycleHook<T, Rels>);
2508
+ onStart(hook: LifecycleHook<T, Rels>): void;
1842
2509
  /** register a ready hook */
1843
- onReady(hook: LifecycleHook<T, Rels>);
2510
+ onReady(hook: LifecycleHook<T, Rels>): void;
1844
2511
  /** register a shutdown hook */
1845
- onShutdown(hook: LifecycleHook<T, Rels>);
2512
+ onShutdown(hook: LifecycleHook<T, Rels>): void;
1846
2513
  /** register an exit hook */
1847
- onExit(hook: LifecycleHook<T, Rels>);
2514
+ onExit(hook: LifecycleHook<T, Rels>): void;
1848
2515
  /** @internal */
1849
2516
  runStart(ctx: ORMContext<T, Rels>): void;
1850
2517
  /** @internal */
@@ -1869,6 +2536,15 @@ interface CreateORMBaseOptions {
1869
2536
  vacuumIntervalMs?: number;
1870
2537
  /** disable fsync during large initial loads */
1871
2538
  bulkLoadMode?: boolean;
2539
+ /** number of worker threads for async read queries (enables *Async methods) */
2540
+ asyncReaderPool?: number;
2541
+ /**
2542
+ * How sub-table foreign key deletions are handled.
2543
+ * - `"native"` (default): SQLite ON DELETE CASCADE - FK verification on INSERT.
2544
+ * - `"foxdb"`: No FK in DDL, foxdb handles cascading in application code - faster INSERTs.
2545
+ * - `"none"`: No FK, no cascade - sub-table rows become orphaned on parent delete.
2546
+ */
2547
+ onDeleteBehavior?: "native" | "foxdb" | "none";
1872
2548
  }
1873
2549
  /**
1874
2550
  * Options passed to `createORM`.
@@ -1899,7 +2575,7 @@ interface CreateORMBaseOptions {
1899
2575
  * ```
1900
2576
  */
1901
2577
  interface CreateORMOptions<
1902
- T extends Record<string, TableDescriptor<any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any>>,
2578
+ T extends Record<string, TableDescriptor<any, any, any, any, any>> = Record<string, TableDescriptor<any, any, any, any, any>>,
1903
2579
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
1904
2580
  > extends CreateORMBaseOptions {
1905
2581
  /** table schemas */
@@ -1950,7 +2626,7 @@ interface CreateORMOptions<
1950
2626
  *
1951
2627
  * Every key in your `tables` config becomes a fully typed **Repository**
1952
2628
  * with CRUD methods. The type definition below is a mapped type that
1953
- * transforms your schema config into the actual runtime API — TypeDoc
2629
+ * transforms your schema config into the actual runtime API - TypeDoc
1954
2630
  * cannot expand it, so see the example for how it works in practice.
1955
2631
  *
1956
2632
  * @see {@link Repository} for the full method reference
@@ -1965,7 +2641,7 @@ interface CreateORMOptions<
1965
2641
  * },
1966
2642
  * });
1967
2643
  *
1968
- * // ─── Every table key is a Repository ───
2644
+ * // --- Every table key is a Repository ---
1969
2645
  *
1970
2646
  * // Insert
1971
2647
  * orm.users.insert({ id: "u1", name: "alice" });
@@ -1984,7 +2660,7 @@ interface CreateORMOptions<
1984
2660
  * orm.users.deleteById("u1");
1985
2661
  * orm.users.deleteWhere({ status: { eq: "banned" } });
1986
2662
  *
1987
- * // ─── Framework methods (prefixed with _) ───
2663
+ * // --- Framework methods (prefixed with _) ---
1988
2664
  *
1989
2665
  * orm._transaction(() => {
1990
2666
  * orm.users.insert({ id: "t1", name: "txn" });
@@ -1995,11 +2671,11 @@ interface CreateORMOptions<
1995
2671
  * ```
1996
2672
  */
1997
2673
  type foxdb<
1998
- Tables extends Record<string, TableDescriptor<any, any, any, any>>,
2674
+ Tables extends Record<string, TableDescriptor<any, any, any, any, any>>,
1999
2675
  Rels extends readonly TypedRelation[] = readonly TypedRelation[]
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 } & {
2676
+ > = { [K in keyof Tables] : Tables[K] extends TableDescriptor<infer TWrite extends TSchema10 & {
2677
+ properties: Record<string, TSchema10>;
2678
+ }, infer PKName extends string, infer Timestamps, infer G extends GeneratedColumnConfig | undefined, infer F> ? FTSEnabled<F> extends true ? Repository<TWrite, QuerySchema<TWrite, G>, PKName extends ScalarKeys<TWrite> ? PKName : never, Materialized<TWrite, Tables, Rels, K & string>, TimestampShape<Timestamps>, FTSFields<TWrite, F> & string> : Omit<Repository<TWrite, QuerySchema<TWrite, G>, PKName extends ScalarKeys<TWrite> ? PKName : never, Materialized<TWrite, Tables, Rels, K & string>, TimestampShape<Timestamps>, never>, "search" | "searchAsync"> : never } & {
2003
2679
  /** run a transaction */
2004
2680
  _transaction<R>(fn: () => R): R;
2005
2681
  /** close the database */
@@ -2023,7 +2699,7 @@ type foxdb<
2023
2699
  };
2024
2700
  /** create a typed orm instance backed by sqlite */
2025
2701
  declare function createORM<
2026
- const T extends Record<string, TableDescriptor<any, any, any, any>>,
2702
+ const T extends Record<string, TableDescriptor<any, any, any, any, any>>,
2027
2703
  const Rels extends readonly TypedRelation[] = readonly TypedRelation[]
2028
2704
  >(opts: CreateORMOptions<T, Rels>): foxdb<T, Rels>;
2029
2705
  declare function migrate(opts: MigrateOptions): Promise<void>;
@@ -2133,4 +2809,4 @@ interface DesiredTable {
2133
2809
  declare function computeDiff(desired: DesiredTable[], actual: InspectorTable[]): SchemaDiff;
2134
2810
  /** @category Migration */
2135
2811
  declare function applySync(diff: SchemaDiff, db: BunDatabase, policy: SyncPolicy, desired: DesiredTable[]): void;
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 };
2812
+ export { AggregateBuilder, AggregateBuilderState, AggregateOptions, AggregationOp, ArrayFilterableFields, ArrayItemType, ArrayOfObjectProperties, BatchWriter, BatchWriterOptions, BroadOperation, BunDatabase, BunStatement, ColumnMeta, ColumnRef, ColumnRefs, ConditionNode, CreateORMBaseOptions, CreateORMOptions, DEFAULT_TIMESTAMP_NAMES, DatabaseOptions, DesiredTable, DistinctableFields, Entity, ErrorPolicy2 as ErrorPolicy, EventBus, FTSConfig, FTSEnabled, FTSFields, FieldType, FilterBuilder, FilterableFields, FindOptions, FtsHighlightSpec, FtsResult, FtsSearchBuilder, FtsSearchState, FtsSnippetSpec, GeneratedColumnConfig, IndexDefinition, Infer, InsertData, InspectorColumn, InspectorIndex, InspectorTable, InternalBuilderState, LifecycleEventMap, LifecycleHook, LifecycleManager, Listener, Materialized, MetaStore, MigrateOptions, Migration, ORMContext, ORMError, ORMErrorContext, ORMEvents, OrderByClause, OrderableFields, PageResult, QueryMetrics, QueryMetricsHook, RelationBuilder, RelationEntry, RelationsConfig, Repository, ScalarFilter, ScalarKeys, ScalarMerge, ScalarMergeNames, ScalarMergeType, ScalarPath, ScalarProperties, SchemaChange, SchemaDiff, SchemaJSON, SchemaJSONSchema, SqliteType, SubMerge, SubMergeNames, SubMergeType, SubTableConfig, SubTableKeys, SubTableMeta, SubTableScalarPath, SyncPolicy, TScalarSchema, TableConfig, TableConfigShape, TableDescriptor, TableEventOperation, TableEventPayload, TableMeta, TableOperation, TimestampConfig2 as TimestampNamesConfig, TimestampShape, TraceEntry, TypedRelation, UnlinkPolicy, UpdateData, UpsertOptions, WhereClause, applySync, buildCreateTableSQL, buildFtsSearchSql, buildWhereFromNodes, computeDiff, createMigration, createORM, createRelationBuilder, foxdb, ftsTableName, inspectAllTables, inspectSchema, introspectTable, migrate, raise, resolveFtsColumns, resolveTimestampNames, table, withTrace };