uql-orm 0.61.0 → 0.63.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/browser/uql-browser.min.js.map +1 -1
- package/dist/bunSql/bunSql.util.d.ts +15 -15
- package/dist/bunSql/bunSql.util.js +22 -35
- package/dist/bunSql/bunSqlQuerier.d.ts +2 -2
- package/dist/bunSql/bunSqlQuerier.js +3 -3
- package/dist/bunSql/bunSqlQuerierPool.d.ts +1 -13
- package/dist/bunSql/bunSqlQuerierPool.js +3 -34
- package/dist/d1/d1Querier.d.ts +12 -4
- package/dist/d1/d1Querier.js +6 -11
- package/dist/d1/d1QuerierPool.d.ts +7 -3
- package/dist/d1/d1QuerierPool.js +5 -3
- package/dist/dialect/abstractSqlDialect.d.ts +12 -7
- package/dist/dialect/abstractSqlDialect.js +51 -50
- package/dist/dialect/mysqlLikeSqlDialect.js +1 -1
- package/dist/dialect/pgLikeSqlDialect.d.ts +1 -0
- package/dist/dialect/pgLikeSqlDialect.js +8 -7
- package/dist/dialect/queryContext.d.ts +5 -6
- package/dist/dialect/queryContext.js +8 -8
- package/dist/entity/decorator/entity.d.ts +6 -10
- package/dist/entity/decorator/entity.js +4 -8
- package/dist/entity/decorator/members.d.ts +3 -2
- package/dist/entity/decorator/members.js +1 -0
- package/dist/entity/metadata/definition.d.ts +2 -2
- package/dist/entity/metadata/definition.js +23 -26
- package/dist/libsql/libsqlDialect.d.ts +1 -1
- package/dist/libsql/libsqlDialect.js +1 -1
- package/dist/libsql/libsqlQuerierPool.d.ts +18 -9
- package/dist/libsql/libsqlQuerierPool.js +32 -20
- package/dist/migrate/builder/migrationBuilder.js +3 -5
- package/dist/migrate/builder/tableBuilder.js +2 -4
- package/dist/migrate/builder/types.d.ts +11 -3
- package/dist/migrate/codegen/index.d.ts +1 -1
- package/dist/migrate/codegen/index.js +1 -1
- package/dist/migrate/codegen/indexDecoratorSource.d.ts +1 -1
- package/dist/migrate/codegen/indexDecoratorSource.js +4 -6
- package/dist/migrate/codegen/migrationFile.d.ts +0 -4
- package/dist/migrate/codegen/migrationFile.js +0 -2
- package/dist/migrate/generator/definitionToNode.d.ts +8 -5
- package/dist/migrate/generator/definitionToNode.js +13 -4
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +2 -0
- package/dist/migrate/generator/mongoSchemaGenerator.js +6 -1
- package/dist/migrate/schemaGenerator.d.ts +5 -3
- package/dist/migrate/schemaGenerator.js +9 -2
- package/dist/mongo/mongoDialect.js +1 -1
- package/dist/mssql/mssqlDialect.js +3 -5
- package/dist/querier/abstractSharedHandleQuerierPool.d.ts +5 -5
- package/dist/querier/abstractSharedHandleQuerierPool.js +5 -5
- package/dist/schema/schemaASTBuilder.d.ts +6 -1
- package/dist/schema/schemaASTBuilder.js +17 -16
- package/dist/sqlite/abstractSqliteQuerier.d.ts +11 -28
- package/dist/sqlite/abstractSqliteQuerier.js +14 -33
- package/dist/sqlite/bunSqliteAdapter.bun.d.ts +5 -4
- package/dist/sqlite/bunSqliteAdapter.bun.js +1 -1
- package/dist/sqlite/hranaQuerier.d.ts +6 -4
- package/dist/sqlite/hranaQuerier.js +4 -13
- package/dist/sqlite/index.d.ts +0 -1
- package/dist/sqlite/index.js +0 -1
- package/dist/sqlite/localSqliteQuerierPool.d.ts +14 -5
- package/dist/sqlite/nodeSqliteAdapter.d.ts +3 -4
- package/dist/sqlite/nodeSqliteAdapter.js +3 -6
- package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -3
- package/dist/sqlite/nodeSqliteQuerierPool.js +3 -1
- package/dist/sqlite/sqliteDialect.d.ts +1 -1
- package/dist/sqlite/sqliteDialect.js +1 -1
- package/dist/sqlite/sqlitePragmas.d.ts +2 -11
- package/dist/sqlite/sqlitePragmas.js +1 -1
- package/dist/sqlite/sqliteQuerier.d.ts +29 -10
- package/dist/sqlite/sqliteQuerier.js +26 -4
- package/dist/sqlite/sqliteQuerierPool.d.ts +7 -3
- package/dist/sqlite/sqliteQuerierPool.js +12 -8
- package/dist/turso/index.d.ts +1 -0
- package/dist/turso/index.js +1 -0
- package/dist/turso/local.d.ts +1 -1
- package/dist/turso/local.js +1 -1
- package/dist/turso/tursoDialect.d.ts +4 -9
- package/dist/turso/tursoDialect.js +4 -12
- package/dist/turso/tursoLocalDialect.d.ts +10 -0
- package/dist/turso/tursoLocalDialect.js +13 -0
- package/dist/turso/tursoLocalQuerierPool.d.ts +8 -13
- package/dist/turso/tursoLocalQuerierPool.js +6 -5
- package/dist/turso/tursoQuerierPool.d.ts +15 -30
- package/dist/turso/tursoQuerierPool.js +13 -23
- package/dist/turso/tursoSessionQuerier.d.ts +57 -0
- package/dist/turso/tursoSessionQuerier.js +50 -0
- package/dist/type/dialect.d.ts +15 -6
- package/dist/type/entity.d.ts +108 -73
- package/dist/type/migration.d.ts +9 -2
- package/dist/type/query.d.ts +3 -3
- package/dist/type/queryLock.d.ts +7 -7
- package/dist/type/queryLock.js +8 -6
- package/dist/type/queryRaw.d.ts +30 -30
- package/dist/type/queryRaw.js +14 -9
- package/dist/util/ddlExpression.util.d.ts +8 -13
- package/dist/util/ddlExpression.util.js +14 -23
- package/dist/util/dialect.util.d.ts +1 -1
- package/dist/util/dialect.util.js +3 -4
- package/dist/util/field.util.d.ts +1 -1
- package/dist/util/raw.d.ts +24 -17
- package/dist/util/raw.js +46 -17
- package/dist/util/wideNumber.d.ts +2 -2
- package/dist/util/wideNumber.js +2 -2
- package/package.json +2 -2
- package/dist/sqlite/hranaQuerierPool.d.ts +0 -20
- package/dist/sqlite/hranaQuerierPool.js +0 -26
- package/dist/turso/tursoLocalQuerier.d.ts +0 -24
- package/dist/turso/tursoLocalQuerier.js +0 -20
package/dist/type/entity.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EnumValues, ForeignKeyAction, IndexType } from '../schema/types.js';
|
|
2
2
|
import type { FilterOptions } from './query.js';
|
|
3
|
-
import type { QueryRaw } from './queryRaw.js';
|
|
3
|
+
import type { ColumnRef, QueryRaw } from './queryRaw.js';
|
|
4
|
+
import type { QueryWhere } from './queryWhere.js';
|
|
4
5
|
import type { Except, IsMany, Json, Scalar, Type, Unpacked } from './utility.js';
|
|
5
6
|
import type { VectorDistance, VectorIndexOptions, VectorIndexType } from './vector.js';
|
|
6
7
|
/**
|
|
@@ -299,7 +300,9 @@ export type TypeFor<V, T = NonNullable<V>> = IsJsonColumn<T> extends true ? Json
|
|
|
299
300
|
* live there behind an `@internal` tag and a "do not set this" note, which is a comment standing in
|
|
300
301
|
* for a type boundary.
|
|
301
302
|
*/
|
|
302
|
-
export type FieldMeta<V = TsTypeOf<FieldType>> = FieldOptions<V> & {
|
|
303
|
+
export type FieldMeta<V = TsTypeOf<FieldType>> = Except<FieldOptions<V>, 'computed'> & {
|
|
304
|
+
/** {@link FieldOptions.computed}, a callback resolved to the SQL it returns. */
|
|
305
|
+
readonly computed?: QueryRaw;
|
|
303
306
|
/**
|
|
304
307
|
* Set by `defineField` when the field gave `references` but no `type`, so schema generation resolves
|
|
305
308
|
* the column from the referenced primary key rather than from whatever ended up in `type`. That is
|
|
@@ -317,7 +320,7 @@ export type FieldMeta<V = TsTypeOf<FieldType>> = FieldOptions<V> & {
|
|
|
317
320
|
* and what a default is has to be that value, checked the same way the declared `type` is. `Scalar` by
|
|
318
321
|
* default, for the places that handle a field without knowing which one it is.
|
|
319
322
|
*/
|
|
320
|
-
export type FieldOptions<V = TsTypeOf<FieldType
|
|
323
|
+
export type FieldOptions<V = TsTypeOf<FieldType>, E = unknown> = {
|
|
321
324
|
readonly name?: string;
|
|
322
325
|
readonly isId?: true;
|
|
323
326
|
readonly type?: FieldType;
|
|
@@ -365,9 +368,9 @@ export type FieldOptions<V = TsTypeOf<FieldType>> = {
|
|
|
365
368
|
* expression will do. With `stored`, it becomes a real column - `GENERATED ALWAYS AS (...) STORED` -
|
|
366
369
|
* which the engine keeps up to date, so it can be indexed and read like any other.
|
|
367
370
|
*
|
|
368
|
-
* @example `@Field({ type: String, computed: raw
|
|
371
|
+
* @example `@Field({ type: String, computed: (user) => raw`${user.first} || ' ' || ${user.last}`, stored: true })`
|
|
369
372
|
*/
|
|
370
|
-
readonly computed?:
|
|
373
|
+
readonly computed?: EntitySql<E>;
|
|
371
374
|
/**
|
|
372
375
|
* Whether {@link FieldOptions.computed} is a column the database keeps, rather than an expression
|
|
373
376
|
* spliced into each statement. The dial to flip after profiling: `$select`, `$where` and `$sort`
|
|
@@ -466,9 +469,9 @@ export type TsTypeOf<T> = T extends StringConstructor ? string : T extends Numbe
|
|
|
466
469
|
* `@Field({ references: () => Company })` would silently downgrade a `uuid` key to TEXT on every
|
|
467
470
|
* column pointing at it.
|
|
468
471
|
*/
|
|
469
|
-
export type FieldOptionsFor<V> = (FieldOptions<NonNullable<V
|
|
472
|
+
export type FieldOptionsFor<V, E = unknown> = (FieldOptions<NonNullable<V>, E> & {
|
|
470
473
|
readonly type: TypeFor<V>;
|
|
471
|
-
}) | (FieldOptions<NonNullable<V
|
|
474
|
+
}) | (FieldOptions<NonNullable<V>, E> & {
|
|
472
475
|
readonly references: EntityGetter;
|
|
473
476
|
readonly type?: TypeFor<V>;
|
|
474
477
|
});
|
|
@@ -592,6 +595,38 @@ type RelationOptionsThroughOwner<E, O> = Pick<RelationOptions<E, O>, 'entity' |
|
|
|
592
595
|
export type KeyMap<E> = {
|
|
593
596
|
readonly [K in keyof E]-?: K;
|
|
594
597
|
};
|
|
598
|
+
/**
|
|
599
|
+
* The fields of `E` as {@link ColumnRef}s, for SQL that names them: `refs(User)` in a statement, the
|
|
600
|
+
* callback's parameter in a definition. Keyed over a type parameter constrained to `keyof E`, as
|
|
601
|
+
* {@link KeyMap} is over `keyof E`, which keeps each ref linked to its field for rename.
|
|
602
|
+
*/
|
|
603
|
+
export type RefMap<E, F extends keyof E = FieldKey<E>> = {
|
|
604
|
+
readonly [K in F]-?: ColumnRef<K & string>;
|
|
605
|
+
};
|
|
606
|
+
/**
|
|
607
|
+
* SQL a definition writes: `raw`, or a callback reading the entity's fields off its refs. The callback is
|
|
608
|
+
* declared as a method, bivariant in its refs, so one typed for its entity still fits where the entity is
|
|
609
|
+
* erased: the registry, which resolves it.
|
|
610
|
+
*/
|
|
611
|
+
export type EntitySql<E> = QueryRaw | {
|
|
612
|
+
sql(refs: RefMap<E>): QueryRaw;
|
|
613
|
+
}['sql'];
|
|
614
|
+
/**
|
|
615
|
+
* A predicate DDL carries, over the entity's own fields: a relation, full-text search and a sub-query
|
|
616
|
+
* have nothing a `CHECK` or a partial index can hold. An intersection rather than `Except`, which would
|
|
617
|
+
* remap the keys and lose each one's link to its field.
|
|
618
|
+
*/
|
|
619
|
+
export type EntityPredicate<E> = QueryWhere<E> & {
|
|
620
|
+
readonly [K in RelationKey<E>]?: never;
|
|
621
|
+
} & {
|
|
622
|
+
readonly $text?: never;
|
|
623
|
+
readonly $exists?: never;
|
|
624
|
+
readonly $nexists?: never;
|
|
625
|
+
};
|
|
626
|
+
/** A definition's predicate: an {@link EntityPredicate}, or {@link EntitySql} for what one cannot say. */
|
|
627
|
+
export type EntityWhere<E> = EntityPredicate<E> | EntitySql<E>;
|
|
628
|
+
/** A definition's predicate as metadata keeps it, a callback resolved to its SQL, for the schema build to compile. */
|
|
629
|
+
export type EntityWhereMeta<E> = EntityPredicate<E> | QueryRaw;
|
|
595
630
|
export type RelationReferences = {
|
|
596
631
|
readonly local: string;
|
|
597
632
|
readonly foreign: string;
|
|
@@ -632,41 +667,24 @@ export type IndexTypeOptions = {
|
|
|
632
667
|
distance?: never;
|
|
633
668
|
};
|
|
634
669
|
/**
|
|
635
|
-
* One entry
|
|
636
|
-
* when the entry needs more
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
* @Index((post) => [{ column: post.
|
|
643
|
-
* @Index((post) => [post.data], { type: 'gin' }) // JSONB containment
|
|
644
|
-
* ```
|
|
645
|
-
*
|
|
646
|
-
* `C` is the entity's `FieldKey` on the `@Index`/`defineEntity` paths, where the decorated class says
|
|
647
|
-
* which columns exist, and `E` the entity itself, which is what checks a JSON entry's path. Both
|
|
648
|
-
* default to the unchecked form for the migration builder's `table.index(...)`, which names raw
|
|
649
|
-
* table columns with no entity in scope.
|
|
650
|
-
*/
|
|
651
|
-
export type IndexColumnInput<C extends string = string, E = unknown> = C | QueryRaw | IndexColumnOptions<C> | IndexJsonColumnOptions<C, E>;
|
|
652
|
-
/**
|
|
653
|
-
* The JSON entries, whose `path` is checked against the payload of the column the same entry names -
|
|
654
|
-
* a mapped union, one arm per JSON field, so `{ column: 'kind', jsonPath: { path: 'thema.color' } }`
|
|
655
|
-
* cannot compile. It matters more here than anywhere else in the index API: a path that is merely
|
|
656
|
-
* *misspelled* still builds a perfectly valid index, one no query will ever match, and nothing at
|
|
657
|
-
* runtime can tell that from the index you meant.
|
|
658
|
-
*
|
|
659
|
-
* `jsonArray`'s path is the array's own, so on a column that *is* the array (`Json<string[]>`) it
|
|
660
|
-
* resolves to `never` and the property can only be omitted, which is exactly the truth.
|
|
661
|
-
*
|
|
662
|
-
* Falls back to the unchecked shape only where there is no entity to check against - the migration
|
|
663
|
-
* builder. An entity with no JSON field at all offers no arm, which is also the truth.
|
|
670
|
+
* One index entry as the migration builder takes it: a column name, `raw` for an expression, or an object
|
|
671
|
+
* when the entry needs more. An entity's entries are this too, which is what `normalizeIndexColumn` reads.
|
|
672
|
+
*/
|
|
673
|
+
export type IndexColumnInput = string | QueryRaw | EntityIndexColumn;
|
|
674
|
+
/**
|
|
675
|
+
* One entry of an entity's index, read off its refs: a column, `raw` for an expression, or an object when
|
|
676
|
+
* the entry needs more, a JSON entry's path checked against its column.
|
|
677
|
+
* @example `@Index((post) => [post.tenantId, { column: post.createdAt, order: 'desc' }, raw`lower(${post.email})`])`
|
|
664
678
|
*/
|
|
665
|
-
type
|
|
666
|
-
|
|
667
|
-
|
|
679
|
+
export type EntityIndexColumnInput<E> = QueryRaw | IndexColumnOptions | IndexJsonColumnOptions<E>;
|
|
680
|
+
/**
|
|
681
|
+
* The JSON entries, one arm per JSON field, each `path` checked against the payload of the column its own
|
|
682
|
+
* entry names: a misspelled path still builds a valid index that no query matches. On a column that is
|
|
683
|
+
* the array (`Json<string[]>`), `jsonArray`'s path resolves to `never`, so it can only be omitted.
|
|
684
|
+
*/
|
|
685
|
+
type IndexJsonColumnOptions<E> = {
|
|
668
686
|
[K in JsonColumnKey<E>]: IndexColumnPlainModifiers & {
|
|
669
|
-
readonly column: K
|
|
687
|
+
readonly column: ColumnRef<K & string>;
|
|
670
688
|
} & ({
|
|
671
689
|
readonly jsonPath: WithCheckedPath<IndexJsonPath, E, K>;
|
|
672
690
|
readonly jsonArray?: never;
|
|
@@ -682,7 +700,7 @@ type IndexJsonColumnOptions<C extends string, E> = unknown extends E ? IndexColu
|
|
|
682
700
|
* subject is that column.
|
|
683
701
|
*/
|
|
684
702
|
type JsonColumnKey<E> = {
|
|
685
|
-
readonly [K in keyof E]-?:
|
|
703
|
+
readonly [K in keyof E]-?: IsJsonColumn<NonNullable<E[K]>> extends true ? K : never;
|
|
686
704
|
}[Key<E>];
|
|
687
705
|
/** The payload a path is checked against: the column's own brand, or that of the documents it holds. */
|
|
688
706
|
type JsonColumnPayload<V> = IsJson<NonNullable<V>> extends true ? UnwrapJson<NonNullable<V>> : JsonPayload<V>;
|
|
@@ -762,15 +780,19 @@ export type IndexJsonArray = {
|
|
|
762
780
|
};
|
|
763
781
|
/** The modifiers that do not name a JSON path, and so need no entity to be checked against. */
|
|
764
782
|
type IndexColumnPlainModifiers = Except<IndexColumnModifiers, 'jsonPath' | 'jsonArray'>;
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
783
|
+
/**
|
|
784
|
+
* An entity's entry with plain modifiers. `jsonPath` and `jsonArray` are `never` here, since a JSON entry
|
|
785
|
+
* would otherwise match this shape too, its path unchecked.
|
|
786
|
+
*/
|
|
787
|
+
type IndexColumnOptions = IndexColumnPlainModifiers & {
|
|
788
|
+
/** A column read off the refs, or `raw` for an expression. */
|
|
789
|
+
readonly column: QueryRaw;
|
|
768
790
|
readonly jsonPath?: never;
|
|
769
791
|
readonly jsonArray?: never;
|
|
770
792
|
};
|
|
771
793
|
/**
|
|
772
|
-
* One index entry, normalized:
|
|
773
|
-
*
|
|
794
|
+
* One index entry, normalized: every authored shape reduces to this before any dialect or generator sees
|
|
795
|
+
* it, so rendering never re-parses the sugar.
|
|
774
796
|
*/
|
|
775
797
|
export type IndexColumnSchema = IndexColumnModifiers & {
|
|
776
798
|
/** A column name, or raw SQL when {@link expression} is set. */
|
|
@@ -778,18 +800,26 @@ export type IndexColumnSchema = IndexColumnModifiers & {
|
|
|
778
800
|
/** Whether {@link column} is an expression to emit as-is rather than an identifier to quote. */
|
|
779
801
|
readonly expression?: boolean;
|
|
780
802
|
};
|
|
803
|
+
/**
|
|
804
|
+
* One index entry as entity metadata keeps it: a member, or an expression left unrendered until the
|
|
805
|
+
* schema is built, where the dialect and the naming strategy resolve what it references. Rendered, it
|
|
806
|
+
* is an {@link IndexColumnSchema}.
|
|
807
|
+
*/
|
|
808
|
+
export type EntityIndexColumn = IndexColumnModifiers & {
|
|
809
|
+
readonly column: string | QueryRaw;
|
|
810
|
+
};
|
|
781
811
|
/**
|
|
782
812
|
* An index as stored in entity metadata: authored options with the columns normalized.
|
|
783
813
|
*/
|
|
784
|
-
export type EntityIndexMeta = {
|
|
814
|
+
export type EntityIndexMeta<E = object> = {
|
|
785
815
|
/** The indexed columns, in order. */
|
|
786
|
-
columns: readonly
|
|
816
|
+
columns: readonly EntityIndexColumn[];
|
|
787
817
|
/** Custom index name */
|
|
788
818
|
name?: string;
|
|
789
819
|
/** Whether index is unique; omit or `false` for a non-unique index (default). */
|
|
790
820
|
unique?: boolean;
|
|
791
|
-
/** Partial index
|
|
792
|
-
where?:
|
|
821
|
+
/** Partial index predicate, compiled when the schema is built. */
|
|
822
|
+
where?: EntityWhereMeta<E>;
|
|
793
823
|
/**
|
|
794
824
|
* Extra columns stored in the index but not part of its key, so a query reading only these is
|
|
795
825
|
* answered from the index alone. Postgres-wire only (`INCLUDE`).
|
|
@@ -826,9 +856,9 @@ export type EntityMeta<E> = {
|
|
|
826
856
|
[key: string]: RelationMeta | undefined;
|
|
827
857
|
};
|
|
828
858
|
/** Composite indexes defined via @Index decorator */
|
|
829
|
-
indexes?: EntityIndexMeta[];
|
|
830
|
-
/** `CHECK` constraints,
|
|
831
|
-
checks?:
|
|
859
|
+
indexes?: EntityIndexMeta<E>[];
|
|
860
|
+
/** `CHECK` constraints, compiled when the schema is built. */
|
|
861
|
+
checks?: EntityCheckMeta<E>[];
|
|
832
862
|
/** Lifecycle hooks registered via @BeforeInsert, @AfterUpdate, etc. */
|
|
833
863
|
hooks?: Partial<Record<HookEvent, HookRegistration[]>>;
|
|
834
864
|
/**
|
|
@@ -840,13 +870,21 @@ export type EntityMeta<E> = {
|
|
|
840
870
|
processedAt?: number;
|
|
841
871
|
};
|
|
842
872
|
/**
|
|
843
|
-
* A table-level `CHECK
|
|
844
|
-
*
|
|
873
|
+
* A table-level `CHECK`: a predicate over the entity's fields, or SQL reading them off refs. A value in
|
|
874
|
+
* either is written as its literal, since DDL has no placeholder to bind one into.
|
|
875
|
+
*
|
|
876
|
+
* @example `{ where: { balance: { $gte: 0 } } }`
|
|
877
|
+
* @example `{ where: (wallet) => raw`${wallet.spent} <= ${wallet.balance}` }`
|
|
845
878
|
*/
|
|
846
|
-
export type CheckOptions = {
|
|
879
|
+
export type CheckOptions<E = unknown> = {
|
|
847
880
|
/** Derived from the table and the constraint's position when absent. */
|
|
848
881
|
readonly name?: string;
|
|
849
|
-
readonly
|
|
882
|
+
readonly where: EntityWhere<E>;
|
|
883
|
+
};
|
|
884
|
+
/** A `CHECK` as entity metadata keeps it, its callback resolved. */
|
|
885
|
+
export type EntityCheckMeta<E = object> = {
|
|
886
|
+
readonly name?: string;
|
|
887
|
+
readonly where: EntityWhereMeta<E>;
|
|
850
888
|
};
|
|
851
889
|
/**
|
|
852
890
|
* An entity's members as the registry takes them, keyed by plain strings - what a decorator bag, an
|
|
@@ -860,7 +898,7 @@ export type EntityMembers = {
|
|
|
860
898
|
};
|
|
861
899
|
/** An entity's fields as `defineEntity` takes them, keyed like every entity map (see `QuerySelect`). */
|
|
862
900
|
type EntityFieldOptions<E, F extends keyof E = FieldKey<E>> = {
|
|
863
|
-
readonly [K in F]?: FieldOptionsFor<E[K]>;
|
|
901
|
+
readonly [K in F]?: FieldOptionsFor<E[K], E>;
|
|
864
902
|
};
|
|
865
903
|
/**
|
|
866
904
|
* An entity's relations as `defineEntity` takes them. Keyed over every member rather than `RelationKey<E>`:
|
|
@@ -897,7 +935,7 @@ export type EntityOptions<E = unknown> = {
|
|
|
897
935
|
readonly relations?: EntityRelationOptions<E>;
|
|
898
936
|
readonly indexes?: readonly EntityIndexInput<E>[];
|
|
899
937
|
/** Table-level `CHECK` constraints. See {@link CheckOptions}. */
|
|
900
|
-
readonly checks?: readonly CheckOptions[];
|
|
938
|
+
readonly checks?: readonly CheckOptions<E>[];
|
|
901
939
|
/** Each lifecycle event and the methods it runs, read off the key map: `{ beforeInsert: (post) => [post.stamp] }`. */
|
|
902
940
|
readonly hooks?: Partial<Record<HookEvent, (keys: KeyMap<E>) => readonly MethodKey<E>[]>>;
|
|
903
941
|
};
|
|
@@ -906,28 +944,25 @@ export type EntityOptions<E = unknown> = {
|
|
|
906
944
|
* and through {@link EntityIndexOptions} `@Index` and `defineEntity`. `Except` (not plain `Omit`) keeps
|
|
907
945
|
* `type`/`distance` a discriminated pair: omitting `distance` on a vector index type is a compile error.
|
|
908
946
|
*/
|
|
909
|
-
export type IndexOptions = Except<EntityIndexMeta, 'columns' | '
|
|
910
|
-
/**
|
|
911
|
-
readonly
|
|
912
|
-
/**
|
|
913
|
-
* Partial-index predicate. `raw` with no interpolation, like an index expression: this is DDL, so
|
|
914
|
-
* there is no placeholder for a bound value. A bare string is the older spelling and still works.
|
|
915
|
-
*/
|
|
916
|
-
readonly where?: string | QueryRaw;
|
|
947
|
+
export type IndexOptions = Except<EntityIndexMeta, 'columns' | 'where'> & {
|
|
948
|
+
/** Partial-index predicate, as `raw` with no interpolation: the migration builder has no entity to compile one against. */
|
|
949
|
+
readonly where?: QueryRaw;
|
|
917
950
|
};
|
|
918
951
|
/**
|
|
919
|
-
* {@link IndexOptions} on an entity, whose stored columns are read off its
|
|
952
|
+
* {@link IndexOptions} on an entity, whose stored columns are read off its refs, `(post) => [post.slug]`,
|
|
920
953
|
* so they are checked against it and follow a rename. The migration builder names raw columns instead.
|
|
921
954
|
*/
|
|
922
|
-
export type EntityIndexOptions<E> = Except<IndexOptions, 'include'> & {
|
|
923
|
-
readonly include?: (
|
|
955
|
+
export type EntityIndexOptions<E> = Except<IndexOptions, 'include' | 'where'> & {
|
|
956
|
+
readonly include?: (refs: RefMap<E>) => readonly ColumnRef<FieldKey<E>>[];
|
|
957
|
+
/** Partial-index predicate. See {@link EntityWhere}. */
|
|
958
|
+
readonly where?: EntityWhere<E>;
|
|
924
959
|
};
|
|
925
960
|
/**
|
|
926
|
-
* An index as authored on an entity, before `defineIndex` reads its columns off the
|
|
961
|
+
* An index as authored on an entity, before `defineIndex` reads its columns off the refs. Only the
|
|
927
962
|
* member lists are callbacks: TypeScript never checks a callback's returned literal for excess properties,
|
|
928
963
|
* so the options stay a literal of their own, where `uniqe: true` is a compile error.
|
|
929
964
|
*/
|
|
930
965
|
export type EntityIndexInput<E> = EntityIndexOptions<E> & {
|
|
931
|
-
readonly columns: (
|
|
966
|
+
readonly columns: (refs: RefMap<E>) => readonly EntityIndexColumnInput<E>[];
|
|
932
967
|
};
|
|
933
968
|
export {};
|
package/dist/type/migration.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { VectorCast } from '../dialect/vectorCast.js';
|
|
2
|
-
import type { FullColumnDefinition, TableDefinition } from '../migrate/builder/types.js';
|
|
2
|
+
import type { FullColumnDefinition, IndexDefinition, TableDefinition } from '../migrate/builder/types.js';
|
|
3
3
|
import type { IndexFacet } from '../schema/indexDifferences.js';
|
|
4
4
|
import type { SchemaAST } from '../schema/schemaAST.js';
|
|
5
5
|
import type { ColumnNode, ForeignKeyAction, IndexNode, IndexType, TableNode } from '../schema/types.js';
|
|
6
|
-
import type { EntityMeta, FieldOptions, IndexColumnSchema, LoggingOptions, Querier, SqlQuerier, Type, VectorIndexOptions } from './index.js';
|
|
6
|
+
import type { EntityMeta, EntityWhereMeta, FieldOptions, IndexColumnSchema, LoggingOptions, Querier, SqlQuerier, Type, VectorIndexOptions } from './index.js';
|
|
7
7
|
/**
|
|
8
8
|
* Defines a migration using a simple object literal. `Q` is `MongoQuerier` for a MongoDB migration.
|
|
9
9
|
*/
|
|
@@ -295,6 +295,11 @@ export interface SchemaGenerator {
|
|
|
295
295
|
* Get the SQL type for a field based on its options
|
|
296
296
|
*/
|
|
297
297
|
getSqlType(fieldOptions: FieldOptions): string;
|
|
298
|
+
/**
|
|
299
|
+
* The text of SQL an entity declares - a check, a stored computed column, an index expression or
|
|
300
|
+
* predicate - rendered for this engine, which is what building an entity's schema needs from it.
|
|
301
|
+
*/
|
|
302
|
+
compileDdl(sql: EntityWhereMeta<object>, entity: Type<object>): string;
|
|
298
303
|
/**
|
|
299
304
|
* Compare an entity with a database table node and return the differences.
|
|
300
305
|
*
|
|
@@ -361,6 +366,8 @@ export interface SqlDdlGenerator extends SchemaGenerator {
|
|
|
361
366
|
generateAddForeignKeySql(tableName: string, foreignKey: ForeignKeySchema): string;
|
|
362
367
|
/** Generate DROP FOREIGN KEY statement */
|
|
363
368
|
generateDropForeignKeySql(tableName: string, constraintName: string): string;
|
|
369
|
+
/** CREATE INDEX from a builder's {@link IndexDefinition}, its SQL rendered for this engine. */
|
|
370
|
+
generateCreateIndexFromDefinition(tableName: string, index: IndexDefinition): string;
|
|
364
371
|
}
|
|
365
372
|
/**
|
|
366
373
|
* Interface for introspecting the current database schema
|
package/dist/type/query.d.ts
CHANGED
|
@@ -90,7 +90,7 @@ export interface UqlContext {
|
|
|
90
90
|
* A filter's `$where` fragment: a plain fragment, or a function of the ambient {@link UqlContext}.
|
|
91
91
|
* Return `undefined` when the condition can't resolve (see {@link FilterOptions.onMissing}).
|
|
92
92
|
*/
|
|
93
|
-
export type
|
|
93
|
+
export type FilterWhere<E> = QueryWhere<E> | ((context: UqlContext | undefined) => QueryWhere<E> | undefined);
|
|
94
94
|
/**
|
|
95
95
|
* What to do when a filter's condition returns `undefined`. `skip` omits it (convenience filters);
|
|
96
96
|
* `throw` fails closed (the default for `security` filters).
|
|
@@ -100,7 +100,7 @@ export type FilterOnMissing = 'skip' | 'throw';
|
|
|
100
100
|
* Authoring shape for `@Entity({ filters })` / `@Filter` / `defineFilter`.
|
|
101
101
|
*/
|
|
102
102
|
export type FilterOptions<E = unknown> = {
|
|
103
|
-
readonly
|
|
103
|
+
readonly where: FilterWhere<E>;
|
|
104
104
|
/** Applied to every query unless bypassed via `QueryOptions.filters`. Defaults to `true`. */
|
|
105
105
|
readonly default?: boolean;
|
|
106
106
|
/**
|
|
@@ -108,7 +108,7 @@ export type FilterOptions<E = unknown> = {
|
|
|
108
108
|
* AND-merged so a client `$where` on the same field can't override it.
|
|
109
109
|
*/
|
|
110
110
|
readonly security?: boolean;
|
|
111
|
-
/** What to do when
|
|
111
|
+
/** What to do when {@link where} returns `undefined`. Defaults to `skip`, or `throw` for `security`. */
|
|
112
112
|
readonly onMissing?: FilterOnMissing;
|
|
113
113
|
};
|
|
114
114
|
/**
|
package/dist/type/queryLock.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
declare const QUERY_LOCK_WAITS: readonly ['
|
|
1
|
+
declare const QUERY_LOCK_WAITS: readonly ['nowait', 'skip'];
|
|
2
2
|
/**
|
|
3
|
-
* What to do about a row someone else already holds. `block` (
|
|
4
|
-
* fails the statement at once; `skip` leaves the row out of the result, which is what makes a
|
|
3
|
+
* What to do about a row someone else already holds. `block` (what `true` asks for) waits for them;
|
|
4
|
+
* `nowait` fails the statement at once; `skip` leaves the row out of the result, which is what makes a
|
|
5
5
|
* work-queue possible: each worker takes rows nobody else has.
|
|
6
6
|
*/
|
|
7
|
-
export type QueryLockWait = (typeof QUERY_LOCK_WAITS)[number];
|
|
7
|
+
export type QueryLockWait = 'block' | (typeof QUERY_LOCK_WAITS)[number];
|
|
8
8
|
/**
|
|
9
|
-
* `true` takes the lock and waits for anyone holding the rows;
|
|
10
|
-
*
|
|
9
|
+
* `true` takes the lock and waits for anyone holding the rows; `$wait` chooses what to do instead of
|
|
10
|
+
* waiting. `false` takes none, so a query built conditionally needs no branch.
|
|
11
11
|
*/
|
|
12
12
|
export type QueryLock = boolean | {
|
|
13
|
-
readonly wait
|
|
13
|
+
readonly $wait: (typeof QUERY_LOCK_WAITS)[number];
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* The wait policy this lock resolves to, or `undefined` when there is no lock. An unknown policy
|
package/dist/type/queryLock.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const QUERY_LOCK_WAITS = ['
|
|
1
|
+
const QUERY_LOCK_WAITS = ['nowait', 'skip'];
|
|
2
2
|
function isOneOf(vals, val) {
|
|
3
3
|
return vals.includes(val);
|
|
4
4
|
}
|
|
@@ -8,12 +8,14 @@ function isOneOf(vals, val) {
|
|
|
8
8
|
* the SQL it would have produced.
|
|
9
9
|
*/
|
|
10
10
|
export function parseQueryLock(lock) {
|
|
11
|
-
if (lock
|
|
11
|
+
if (!lock) {
|
|
12
12
|
return undefined;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
throw new TypeError(`unknown $lock wait policy: ${String(wait)}`);
|
|
14
|
+
if (lock === true) {
|
|
15
|
+
return 'block';
|
|
17
16
|
}
|
|
18
|
-
|
|
17
|
+
if (!isOneOf(QUERY_LOCK_WAITS, lock.$wait)) {
|
|
18
|
+
throw new TypeError(`unknown $lock wait policy: ${String(lock.$wait)}`);
|
|
19
|
+
}
|
|
20
|
+
return lock.$wait;
|
|
19
21
|
}
|
package/dist/type/queryRaw.d.ts
CHANGED
|
@@ -1,43 +1,36 @@
|
|
|
1
1
|
import type { QueryContext, QueryDialect } from './dialect.js';
|
|
2
|
-
import type {
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* the prefix.
|
|
14
|
-
*/
|
|
15
|
-
prefix?: string;
|
|
2
|
+
import type { Type } from './utility.js';
|
|
3
|
+
/** What a `raw` callback receives. See {@link QueryRawFn}. */
|
|
4
|
+
export type QueryRawRenderOptions = {
|
|
5
|
+
/** The dialect rendering the SQL. */
|
|
6
|
+
dialect: QueryDialect;
|
|
7
|
+
/** The alias of the table in scope, unescaped; empty where there is none. */
|
|
8
|
+
prefix: string;
|
|
9
|
+
/** {@link prefix} escaped, with its trailing dot. */
|
|
10
|
+
escapedPrefix: string;
|
|
11
|
+
/** The query context the SQL is written into. */
|
|
12
|
+
ctx: QueryContext;
|
|
16
13
|
/**
|
|
17
|
-
*
|
|
14
|
+
* The entity being rendered, which a ref read off a definition's map resolves its column against: a
|
|
15
|
+
* computed field's own, or the one whose schema is built. Absent where a statement renders SQL.
|
|
18
16
|
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* the query context.
|
|
22
|
-
*/
|
|
23
|
-
ctx?: QueryContext;
|
|
17
|
+
entity?: Type<unknown>;
|
|
24
18
|
};
|
|
19
|
+
/** {@link QueryRawRenderOptions} as the callers along the way fill them in, every one still optional. */
|
|
20
|
+
export type QueryRawFnOptions = Partial<QueryRawRenderOptions>;
|
|
25
21
|
/**
|
|
26
22
|
* A `raw` callback: write into `ctx`, or return a string or number to have it appended. Anything else
|
|
27
23
|
* it returns is ignored, which is why the return type is `unknown` rather than `void | Scalar` - the
|
|
28
24
|
* latter rejected `({ ctx }) => ctx.append(...)`, the form every computed field is written in, because
|
|
29
25
|
* TypeScript's "returning a value where void is expected" allowance does not apply to a union.
|
|
30
|
-
*
|
|
31
|
-
* `Required`, and the parameter not optional, because the one place that calls it (`getRawValue`)
|
|
32
|
-
* passes all four every time.
|
|
33
26
|
*/
|
|
34
|
-
export type QueryRawFn = (opts:
|
|
27
|
+
export type QueryRawFn = (opts: QueryRawRenderOptions) => unknown;
|
|
35
28
|
export declare const RAW_VALUE: unique symbol;
|
|
36
29
|
export declare const RAW_ALIAS: unique symbol;
|
|
37
30
|
export declare class QueryRaw {
|
|
38
|
-
readonly [RAW_VALUE]:
|
|
31
|
+
readonly [RAW_VALUE]: QueryRawFn;
|
|
39
32
|
readonly [RAW_ALIAS]?: string;
|
|
40
|
-
constructor(value:
|
|
33
|
+
constructor(value: QueryRawFn, alias?: string);
|
|
41
34
|
/** The same expression under an alias, for a `$select` projection. */
|
|
42
35
|
as(alias: string): QueryRaw;
|
|
43
36
|
/**
|
|
@@ -45,9 +38,16 @@ export declare class QueryRaw {
|
|
|
45
38
|
* business, which is what lets a `raw` tagged template resolve an interpolated fragment without
|
|
46
39
|
* the dialect having to expose a method for it.
|
|
47
40
|
*
|
|
48
|
-
* The alias is not emitted here: it
|
|
49
|
-
*
|
|
50
|
-
* it around this call.
|
|
41
|
+
* The alias is not emitted here: it names a `$select` projection, which writes it after the term,
|
|
42
|
+
* and anywhere else it would land mid-expression.
|
|
51
43
|
*/
|
|
52
|
-
render(opts:
|
|
44
|
+
render(opts: QueryRawRenderOptions): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A field of an entity as SQL, read off `refs(Entity)` or a definition's refs: interpolated into `raw`, it
|
|
48
|
+
* renders as the field's column. Its `key` is how an index tells a column from an expression.
|
|
49
|
+
*/
|
|
50
|
+
export declare class ColumnRef<K extends string = string> extends QueryRaw {
|
|
51
|
+
readonly key: K;
|
|
52
|
+
constructor(key: K, value: QueryRawFn);
|
|
53
53
|
}
|
package/dist/type/queryRaw.js
CHANGED
|
@@ -16,19 +16,24 @@ export class QueryRaw {
|
|
|
16
16
|
* business, which is what lets a `raw` tagged template resolve an interpolated fragment without
|
|
17
17
|
* the dialect having to expose a method for it.
|
|
18
18
|
*
|
|
19
|
-
* The alias is not emitted here: it
|
|
20
|
-
*
|
|
21
|
-
* it around this call.
|
|
19
|
+
* The alias is not emitted here: it names a `$select` projection, which writes it after the term,
|
|
20
|
+
* and anywhere else it would land mid-expression.
|
|
22
21
|
*/
|
|
23
22
|
render(opts) {
|
|
24
|
-
const
|
|
25
|
-
if (typeof value !== 'function') {
|
|
26
|
-
opts.ctx.append(opts.prefix + String(value));
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const emitted = value(opts);
|
|
23
|
+
const emitted = this[RAW_VALUE](opts);
|
|
30
24
|
if (typeof emitted === 'string' || (typeof emitted === 'number' && !Number.isNaN(emitted))) {
|
|
31
25
|
opts.ctx.append(String(emitted));
|
|
32
26
|
}
|
|
33
27
|
}
|
|
34
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* A field of an entity as SQL, read off `refs(Entity)` or a definition's refs: interpolated into `raw`, it
|
|
31
|
+
* renders as the field's column. Its `key` is how an index tells a column from an expression.
|
|
32
|
+
*/
|
|
33
|
+
export class ColumnRef extends QueryRaw {
|
|
34
|
+
key;
|
|
35
|
+
constructor(key, value) {
|
|
36
|
+
super(value);
|
|
37
|
+
this.key = key;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import { type IndexColumnInput, type IndexColumnSchema, QueryRaw } from '../type/index.js';
|
|
1
|
+
import { type EntityIndexColumn, type IndexColumnInput, type IndexColumnSchema, QueryRaw } from '../type/index.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* for the callback form and no placeholder a `CREATE` statement could bind a value into.
|
|
6
|
-
*
|
|
7
|
-
* `what` names the thing being declared, so the error says which one the caller got wrong.
|
|
3
|
+
* Reduces an authored index entry to the form metadata keeps, so a column, an expression and an options
|
|
4
|
+
* object reach the schema as one: a column read off the refs as its key, any other `raw` as it is.
|
|
8
5
|
*/
|
|
9
|
-
export declare function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
export declare function normalizeIndexColumn(entry: IndexColumnInput): IndexColumnSchema;
|
|
6
|
+
export declare function normalizeIndexColumn(entry: IndexColumnInput): EntityIndexColumn;
|
|
7
|
+
/** An index entry as the schema holds it, its expression rendered to text by `render`. */
|
|
8
|
+
export declare function renderIndexColumn(entry: EntityIndexColumn, render: (sql: QueryRaw) => string): IndexColumnSchema;
|
|
9
|
+
/** What an unnamed index's name is built from: each entry's column, or `expr<n>` for an expression, which has none. */
|
|
10
|
+
export declare function indexNameParts(entries: readonly EntityIndexColumn[]): string[];
|
|
@@ -1,27 +1,18 @@
|
|
|
1
|
-
import { QueryRaw,
|
|
2
|
-
export function ddlText(value, what) {
|
|
3
|
-
if (!(value instanceof QueryRaw)) {
|
|
4
|
-
return value;
|
|
5
|
-
}
|
|
6
|
-
const sql = value[RAW_VALUE];
|
|
7
|
-
if (typeof sql !== 'string') {
|
|
8
|
-
throw new TypeError(`${what} needs raw() with no interpolation, not a function or a bound value`);
|
|
9
|
-
}
|
|
10
|
-
return sql;
|
|
11
|
-
}
|
|
1
|
+
import { ColumnRef, QueryRaw, } from '../type/index.js';
|
|
12
2
|
/**
|
|
13
|
-
* Reduces an authored index entry to
|
|
14
|
-
*
|
|
3
|
+
* Reduces an authored index entry to the form metadata keeps, so a column, an expression and an options
|
|
4
|
+
* object reach the schema as one: a column read off the refs as its key, any other `raw` as it is.
|
|
15
5
|
*/
|
|
16
6
|
export function normalizeIndexColumn(entry) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
7
|
+
const { column, ...modifiers } = typeof entry === 'string' || entry instanceof QueryRaw ? { column: entry } : entry;
|
|
8
|
+
return { ...modifiers, column: column instanceof ColumnRef ? column.key : column };
|
|
9
|
+
}
|
|
10
|
+
/** An index entry as the schema holds it, its expression rendered to text by `render`. */
|
|
11
|
+
export function renderIndexColumn(entry, render) {
|
|
12
|
+
const { column } = entry;
|
|
13
|
+
return column instanceof QueryRaw ? { ...entry, column: render(column), expression: true } : { ...entry, column };
|
|
14
|
+
}
|
|
15
|
+
/** What an unnamed index's name is built from: each entry's column, or `expr<n>` for an expression, which has none. */
|
|
16
|
+
export function indexNameParts(entries) {
|
|
17
|
+
return entries.map((entry, at) => (typeof entry.column === 'string' ? entry.column : `expr${at}`));
|
|
27
18
|
}
|
|
@@ -83,7 +83,7 @@ export declare function findVectorSort<E>(sort: QuerySortMap<E> | undefined): {
|
|
|
83
83
|
* The vector index declared on `key`, if any. Answers both "is there an ANN index to tune here" and
|
|
84
84
|
* "which kind", which decide the name Atlas is queried by and the setting Postgres is tuned with.
|
|
85
85
|
*/
|
|
86
|
-
export declare function findVectorIndex<E>(meta: EntityMeta<E>, key: string): EntityIndexMeta | undefined;
|
|
86
|
+
export declare function findVectorIndex<E>(meta: EntityMeta<E>, key: string): EntityIndexMeta<E> | undefined;
|
|
87
87
|
/**
|
|
88
88
|
* Whether a `$where` filters by vector distance anywhere in its tree, `$and`/`$or`/`$not` included.
|
|
89
89
|
* What tells Postgres that an HNSW scan needs to iterate rather than return one candidate list.
|