uql-orm 0.65.1 → 0.67.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.
Files changed (193) hide show
  1. package/dist/browser/querier/httpQuerier.js +1 -8
  2. package/dist/browser/uql-browser.min.js.map +5 -5
  3. package/dist/bunSql/bunSql.util.d.ts +2 -6
  4. package/dist/bunSql/bunSql.util.js +2 -6
  5. package/dist/bunSql/bunSqlQuerier.d.ts +2 -5
  6. package/dist/bunSql/bunSqlQuerier.js +2 -5
  7. package/dist/cockroachdb/cockroachDialect.d.ts +4 -13
  8. package/dist/cockroachdb/cockroachDialect.js +4 -13
  9. package/dist/context/context.browser.js +2 -10
  10. package/dist/context/context.d.ts +4 -17
  11. package/dist/context/context.js +4 -17
  12. package/dist/dialect/abstractDialect.d.ts +4 -19
  13. package/dist/dialect/abstractDialect.js +2 -20
  14. package/dist/dialect/abstractSqlDialect.d.ts +47 -212
  15. package/dist/dialect/abstractSqlDialect.js +68 -222
  16. package/dist/dialect/aliases.d.ts +2 -12
  17. package/dist/dialect/aliases.js +4 -12
  18. package/dist/dialect/hydrateColumn.d.ts +2 -6
  19. package/dist/dialect/hydrateColumn.js +3 -13
  20. package/dist/dialect/jsonArrayElemMatchUtils.d.ts +1 -7
  21. package/dist/dialect/jsonArrayElemMatchUtils.js +1 -7
  22. package/dist/dialect/jsonSql.d.ts +6 -27
  23. package/dist/dialect/jsonSql.js +6 -27
  24. package/dist/dialect/mergeSqlDialect.d.ts +4 -22
  25. package/dist/dialect/mergeSqlDialect.js +4 -22
  26. package/dist/dialect/mysqlLikeSqlDialect.d.ts +11 -37
  27. package/dist/dialect/mysqlLikeSqlDialect.js +35 -51
  28. package/dist/dialect/pgLikeSqlDialect.d.ts +8 -22
  29. package/dist/dialect/pgLikeSqlDialect.js +36 -39
  30. package/dist/dialect/queryContext.d.ts +4 -22
  31. package/dist/dialect/queryContext.js +4 -22
  32. package/dist/dialect/queryJoins.d.ts +3 -12
  33. package/dist/dialect/queryJoins.js +3 -12
  34. package/dist/dialect/vectorCast.d.ts +2 -12
  35. package/dist/dialect/vectorCast.js +3 -19
  36. package/dist/dialect/vectorSqlDialect.d.ts +8 -38
  37. package/dist/dialect/vectorSqlDialect.js +7 -38
  38. package/dist/entity/decorator/bag.d.ts +6 -19
  39. package/dist/entity/decorator/bag.js +6 -22
  40. package/dist/entity/decorator/entity.d.ts +5 -10
  41. package/dist/entity/decorator/entity.js +2 -7
  42. package/dist/entity/decorator/members.d.ts +10 -31
  43. package/dist/entity/decorator/members.js +3 -12
  44. package/dist/entity/metadata/definition.d.ts +5 -21
  45. package/dist/entity/metadata/definition.js +69 -91
  46. package/dist/http/handler.d.ts +2 -14
  47. package/dist/index.d.ts +3 -1
  48. package/dist/index.js +3 -1
  49. package/dist/libsql/libsqlDialect.d.ts +1 -8
  50. package/dist/libsql/libsqlDialect.js +1 -8
  51. package/dist/maria/mariaDialect.d.ts +3 -5
  52. package/dist/maria/mariaDialect.js +5 -5
  53. package/dist/maria/mariadbQuerier.js +2 -2
  54. package/dist/maria/mariadbQuerierPool.js +1 -6
  55. package/dist/migrate/builder/migrationBuilder.js +3 -19
  56. package/dist/migrate/builder/splitSqlStatements.d.ts +1 -14
  57. package/dist/migrate/builder/splitSqlStatements.js +2 -22
  58. package/dist/migrate/builder/types.d.ts +2 -15
  59. package/dist/migrate/cli-config.js +2 -11
  60. package/dist/migrate/cli.js +2 -7
  61. package/dist/migrate/codegen/entityCodeGenerator.d.ts +0 -15
  62. package/dist/migrate/codegen/entityCodeGenerator.js +15 -44
  63. package/dist/migrate/codegen/fieldOptionsSource.d.ts +1 -8
  64. package/dist/migrate/codegen/fieldOptionsSource.js +3 -22
  65. package/dist/migrate/ddl/indexDdl.d.ts +2 -5
  66. package/dist/migrate/ddl/indexDdl.js +2 -5
  67. package/dist/migrate/ddl/pgIndexDdl.d.ts +3 -13
  68. package/dist/migrate/ddl/pgIndexDdl.js +3 -13
  69. package/dist/migrate/generator/definitionToNode.d.ts +2 -9
  70. package/dist/migrate/generator/definitionToNode.js +3 -17
  71. package/dist/migrate/generator/indexNodeToSchema.d.ts +2 -3
  72. package/dist/migrate/generator/indexNodeToSchema.js +2 -3
  73. package/dist/migrate/generator/mongoCommand.d.ts +1 -8
  74. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -8
  75. package/dist/migrate/generator/mongoSchemaGenerator.js +1 -8
  76. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +6 -26
  77. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +9 -41
  78. package/dist/migrate/introspection/baseSqlIntrospector.js +0 -1
  79. package/dist/migrate/introspection/mongoIntrospector.d.ts +3 -1
  80. package/dist/migrate/introspection/mongoIntrospector.js +48 -46
  81. package/dist/migrate/introspection/mssqlIntrospector.d.ts +4 -4
  82. package/dist/migrate/introspection/mssqlIntrospector.js +18 -27
  83. package/dist/migrate/introspection/mysqlIntrospector.d.ts +7 -2
  84. package/dist/migrate/introspection/mysqlIntrospector.js +16 -14
  85. package/dist/migrate/introspection/postgresIntrospector.d.ts +24 -9
  86. package/dist/migrate/introspection/postgresIntrospector.js +68 -59
  87. package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -1
  88. package/dist/migrate/introspection/sqliteIntrospector.js +8 -10
  89. package/dist/migrate/migrator.d.ts +9 -53
  90. package/dist/migrate/migrator.js +32 -65
  91. package/dist/migrate/schemaGenerator.d.ts +20 -66
  92. package/dist/migrate/schemaGenerator.js +32 -93
  93. package/dist/mongo/mongoDialect.d.ts +21 -53
  94. package/dist/mongo/mongoDialect.js +25 -70
  95. package/dist/mongo/mongodbQuerier.d.ts +5 -8
  96. package/dist/mongo/mongodbQuerier.js +31 -65
  97. package/dist/mssql/mssqlDialect.d.ts +8 -34
  98. package/dist/mssql/mssqlDialect.js +37 -51
  99. package/dist/mssql/mssqlQuerier.d.ts +37 -4
  100. package/dist/mssql/mssqlQuerier.js +2 -2
  101. package/dist/mssql/mssqlWireTypes.d.ts +2 -14
  102. package/dist/mssql/mssqlWireTypes.js +2 -14
  103. package/dist/nestjs/uqlModule.js +2 -7
  104. package/dist/pglite/pgliteQuerier.d.ts +1 -9
  105. package/dist/pglite/pgliteQuerierPool.d.ts +4 -26
  106. package/dist/pglite/pgliteQuerierPool.js +3 -18
  107. package/dist/postgres/abstractPgQuerierPool.d.ts +1 -8
  108. package/dist/postgres/abstractPgQuerierPool.js +1 -8
  109. package/dist/postgres/pgNumericTypes.d.ts +3 -26
  110. package/dist/postgres/pgNumericTypes.js +3 -26
  111. package/dist/postgres/postgresDialect.d.ts +4 -10
  112. package/dist/postgres/postgresDialect.js +4 -10
  113. package/dist/querier/abstractQuerier.d.ts +35 -103
  114. package/dist/querier/abstractQuerier.js +105 -201
  115. package/dist/querier/abstractSharedHandleQuerierPool.d.ts +3 -17
  116. package/dist/querier/abstractSharedHandleQuerierPool.js +3 -17
  117. package/dist/querier/abstractSqlQuerier.d.ts +15 -36
  118. package/dist/querier/abstractSqlQuerier.js +49 -131
  119. package/dist/schema/canonicalType.d.ts +3 -21
  120. package/dist/schema/canonicalType.js +22 -67
  121. package/dist/schema/dependencyGraph.d.ts +2 -8
  122. package/dist/schema/dependencyGraph.js +2 -32
  123. package/dist/schema/index.d.ts +1 -25
  124. package/dist/schema/index.js +0 -26
  125. package/dist/schema/indexColumns.d.ts +1 -8
  126. package/dist/schema/indexColumns.js +1 -8
  127. package/dist/schema/indexDifferences.d.ts +7 -40
  128. package/dist/schema/indexDifferences.js +6 -31
  129. package/dist/schema/schemaAST.d.ts +8 -175
  130. package/dist/schema/schemaAST.js +13 -365
  131. package/dist/schema/schemaASTBuilder.d.ts +2 -24
  132. package/dist/schema/schemaASTBuilder.js +6 -41
  133. package/dist/schema/schemaASTDiffer.d.ts +6 -46
  134. package/dist/schema/schemaASTDiffer.js +8 -56
  135. package/dist/schema/types.d.ts +5 -61
  136. package/dist/schema/types.js +3 -6
  137. package/dist/sqlite/abstractSqliteQuerier.d.ts +1 -8
  138. package/dist/sqlite/localSqliteQuerierPool.d.ts +1 -7
  139. package/dist/sqlite/localSqliteQuerierPool.js +1 -7
  140. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -7
  141. package/dist/sqlite/nodeSqliteQuerierPool.js +2 -7
  142. package/dist/sqlite/sqliteDialect.d.ts +5 -20
  143. package/dist/sqlite/sqliteDialect.js +29 -35
  144. package/dist/turso/tursoDialect.d.ts +4 -6
  145. package/dist/turso/tursoDialect.js +4 -6
  146. package/dist/turso/tursoLocalQuerierPool.d.ts +1 -7
  147. package/dist/turso/tursoLocalQuerierPool.js +1 -7
  148. package/dist/turso/tursoQuerierPool.d.ts +2 -6
  149. package/dist/turso/tursoQuerierPool.js +2 -6
  150. package/dist/turso/tursoSessionQuerier.d.ts +1 -7
  151. package/dist/turso/tursoSessionQuerier.js +1 -7
  152. package/dist/type/dialect.d.ts +42 -94
  153. package/dist/type/dialect.js +3 -13
  154. package/dist/type/entity.d.ts +189 -551
  155. package/dist/type/entity.js +26 -9
  156. package/dist/type/logger.d.ts +2 -14
  157. package/dist/type/migration.d.ts +9 -38
  158. package/dist/type/querier.d.ts +9 -28
  159. package/dist/type/querierPool.d.ts +4 -26
  160. package/dist/type/query.d.ts +28 -78
  161. package/dist/type/query.js +2 -7
  162. package/dist/type/queryAggregate.d.ts +18 -98
  163. package/dist/type/queryRaw.d.ts +1 -8
  164. package/dist/type/queryRaw.js +1 -8
  165. package/dist/type/queryWhere.d.ts +13 -61
  166. package/dist/type/universalQuerier.d.ts +18 -105
  167. package/dist/type/utility.d.ts +12 -24
  168. package/dist/type/vector.d.ts +8 -38
  169. package/dist/type/vector.js +1 -1
  170. package/dist/type/wire.d.ts +2 -5
  171. package/dist/util/dialect.util.d.ts +9 -27
  172. package/dist/util/dialect.util.js +10 -27
  173. package/dist/util/field.util.d.ts +5 -37
  174. package/dist/util/field.util.js +7 -50
  175. package/dist/util/fieldOption.util.d.ts +7 -15
  176. package/dist/util/fieldOption.util.js +1 -1
  177. package/dist/util/filters.util.d.ts +2 -5
  178. package/dist/util/filters.util.js +2 -5
  179. package/dist/util/logger.d.ts +2 -6
  180. package/dist/util/logger.js +2 -6
  181. package/dist/util/object.util.d.ts +2 -6
  182. package/dist/util/object.util.js +1 -5
  183. package/dist/util/raw.d.ts +3 -23
  184. package/dist/util/relationQuery.util.d.ts +3 -14
  185. package/dist/util/relationQuery.util.js +3 -14
  186. package/dist/util/rowKey.util.d.ts +2 -10
  187. package/dist/util/rowKey.util.js +2 -10
  188. package/dist/util/sql.util.d.ts +6 -37
  189. package/dist/util/sql.util.js +13 -73
  190. package/dist/util/sqlLiteral.d.ts +2 -13
  191. package/dist/util/sqlLiteral.js +8 -13
  192. package/dist/util/string.util.js +0 -2
  193. package/package.json +4 -4
@@ -1,10 +1,4 @@
1
- /**
2
- * SqlQueryContext is an implementation of the QueryContext interface specifically for SQL-based dialects.
3
- * It follows the "Accumulator" or "Builder" pattern to construct SQL queries and their corresponding parameters.
4
- *
5
- * This pattern solves the problem of building complex SQL strings while safely managing parameterized values,
6
- * preventing SQL injection and handling dialect-specific parameter placeholders (e.g., '?' for MySQL, '$n' for PostgreSQL).
7
- */
1
+ /** A SQL statement being built: its text, and the values it binds, placeholders numbered by the dialect. */
8
2
  export class SqlQueryContext {
9
3
  dialect;
10
4
  statement;
@@ -13,14 +7,8 @@ export class SqlQueryContext {
13
7
  params;
14
8
  tableAliases = new Set();
15
9
  /**
16
- * @param dialect The SQL dialect used to determine how values should be formatted as placeholders.
17
- * @param params An existing values array to bind into instead of a fresh one - shared by a
18
- * fragment context built via {@link AbstractSqlDialect.buildFragment}, so a bound value's
19
- * placeholder is numbered correctly against the real query from the moment it's added, rather
20
- * than needing to be reconciled after the fact.
21
- * @param statement The context this one renders a fragment of, which owns the claimed aliases: a
22
- * fragment is part of one statement, so its aliases have to be unique across the whole of it.
23
- * @param inlineValues See {@link QueryContext.inlineValues}; a fragment takes its statement's.
10
+ * `params` and `statement` are a fragment's parent's, so a value numbers against the whole statement and
11
+ * an alias is unique across it; a fragment inlines values where its statement does.
24
12
  */
25
13
  constructor(dialect, params = [], statement, inlineValues = false) {
26
14
  this.dialect = dialect;
@@ -51,13 +39,7 @@ export class SqlQueryContext {
51
39
  this.sqlChunks.push(this.dialect.addValue(this, value));
52
40
  return this;
53
41
  }
54
- /**
55
- * Pushes values to the parameters list without appending placeholders to the SQL.
56
- * This is useful when the placeholder is already present in the SQL string or handled elsewhere.
57
- *
58
- * @param values The values to be added to the parameters.
59
- * @returns The current context instance for method chaining.
60
- */
42
+ /** Binds values whose placeholders the SQL already carries. */
61
43
  pushValue(...values) {
62
44
  this.params.push(...values.map((v) => this.dialect.normalizeValue(v)));
63
45
  return this;
@@ -35,11 +35,8 @@ export type QuerySortOptions = {
35
35
  readonly distinct?: boolean;
36
36
  };
37
37
  /**
38
- * What the statement joins, from the whole query rather than from `$populate` alone: ordering by a
39
- * related column needs that relation joined just as much as selecting it does. The two sources meet
40
- * here, so the columns, the `ORDER BY` and the row lock cannot disagree about what is in the
41
- * statement. `$sort` contributes to-one relations only; the rest is rejected where it is rendered.
42
- * `claimAlias` names each join's table, parents first.
38
+ * What the statement joins, from `$populate` and from a `$sort` by a to-one relation's field, so the
39
+ * columns, the `ORDER BY` and the lock agree. `claimAlias` names each join's table, parents first.
43
40
  */
44
41
  export declare function resolveQueryJoins<E>(meta: EntityMeta<E>, q: Query<E>, claimAlias?: (path: string) => string): QueryJoins;
45
42
  /**
@@ -50,13 +47,7 @@ export declare function resolveQueryJoins<E>(meta: EntityMeta<E>, q: Query<E>, c
50
47
  export declare function hasRequiredJoin<E>(meta: EntityMeta<E>, q: Query<E>): boolean;
51
48
  /** Whether a statement aggregates a relation's rows: a to-many off its own row, or off a row it joins. */
52
49
  export declare function aggregatesRelations<E>(meta: EntityMeta<E>, q: Query<E>): boolean;
53
- /**
54
- * The join an ordering may address at `path`, with the relation's own sort map, or why it may not.
55
- * Every backend answers this the same way - a to-many has no single value to order by, a relation
56
- * sort is a map of that relation's fields, and the path has to be joined - so it is answered once
57
- * here rather than per dialect, where the three checks had already drifted apart twice. Only the
58
- * remedy for an unjoined path is the dialect's business, which is what `unjoinable` says.
59
- */
50
+ /** The join a sort may address at `path` with the relation's own sort map, or why it may not; `unjoinable` is the dialect's remedy. */
60
51
  export declare function resolveSortableJoin(relation: RelationMeta, path: string, value: unknown, joins: QueryJoins, unjoinable: string): {
61
52
  readonly join: QueryJoin;
62
53
  readonly sort: QuerySortMap<object>;
@@ -2,11 +2,8 @@ import { getMeta, relationOf } from '../entity/index.js';
2
2
  import { getKeys, getRelationRequestSummary, isToManyRelation, parseRelationAtKey } from '../util/index.js';
3
3
  export const NO_JOINS = new Map();
4
4
  /**
5
- * What the statement joins, from the whole query rather than from `$populate` alone: ordering by a
6
- * related column needs that relation joined just as much as selecting it does. The two sources meet
7
- * here, so the columns, the `ORDER BY` and the row lock cannot disagree about what is in the
8
- * statement. `$sort` contributes to-one relations only; the rest is rejected where it is rendered.
9
- * `claimAlias` names each join's table, parents first.
5
+ * What the statement joins, from `$populate` and from a `$sort` by a to-one relation's field, so the
6
+ * columns, the `ORDER BY` and the lock agree. `claimAlias` names each join's table, parents first.
10
7
  */
11
8
  export function resolveQueryJoins(meta, q, claimAlias = (path) => path) {
12
9
  if (!q.$populate && !q.$sort) {
@@ -91,13 +88,7 @@ function addSortJoins(joins, claimAlias, meta, sort, parent) {
91
88
  addSortJoins(joins, claimAlias, join.meta, value, join);
92
89
  }
93
90
  }
94
- /**
95
- * The join an ordering may address at `path`, with the relation's own sort map, or why it may not.
96
- * Every backend answers this the same way - a to-many has no single value to order by, a relation
97
- * sort is a map of that relation's fields, and the path has to be joined - so it is answered once
98
- * here rather than per dialect, where the three checks had already drifted apart twice. Only the
99
- * remedy for an unjoined path is the dialect's business, which is what `unjoinable` says.
100
- */
91
+ /** The join a sort may address at `path` with the relation's own sort map, or why it may not; `unjoinable` is the dialect's remedy. */
101
92
  export function resolveSortableJoin(relation, path, value, joins, unjoinable) {
102
93
  if (isToManyRelation(relation)) {
103
94
  throw new TypeError(`cannot $sort by '${path}': a parent has many of them, so there is no single value to order by. Sort the relation's own rows inside $populate instead.`);
@@ -16,17 +16,7 @@ export declare function resolveVectorCast(field: {
16
16
  */
17
17
  export declare function toSparsevecLiteral(values: readonly unknown[]): string;
18
18
  /**
19
- * The inverse of the two literals above. pgvector hands a vector column back as **text**, so a read
20
- * that did not parse it returned a string from a field whose declared type is `number[]`: invisible
21
- * to the compiler, and invisible to any mocked test, because a mock returns the array the entity
22
- * promises. It surfaces only as arithmetic quietly producing nonsense on real rows.
23
- *
24
- * Driven by `cast`, never by the shape of the text, so this is the exact mirror of the write side:
25
- * a `sparsevec` column is read as `{1:1,3:2}/3` because that is what it was written as, and a dense
26
- * one as `[1,2,3]`. Both return the dense array the field type promises, whichever width the column
27
- * has. Sniffing the string instead would guess at a type the caller already knows.
28
- *
29
- * Returns `undefined` when the text does not match the column's own format, so a caller can keep the
30
- * raw value rather than replace it with something invented.
19
+ * A vector column's text as the dense array its field promises (pgvector returns text), read by `cast`
20
+ * as it was written, `{1:1,3:2}/3` or `[1,2,3]`; `undefined` where the text matches neither.
31
21
  */
32
22
  export declare function parseVectorLiteral(raw: string, cast: VectorCast): number[] | undefined;
@@ -24,18 +24,8 @@ export function toSparsevecLiteral(values) {
24
24
  return `{${pairs}}/${values.length}`;
25
25
  }
26
26
  /**
27
- * The inverse of the two literals above. pgvector hands a vector column back as **text**, so a read
28
- * that did not parse it returned a string from a field whose declared type is `number[]`: invisible
29
- * to the compiler, and invisible to any mocked test, because a mock returns the array the entity
30
- * promises. It surfaces only as arithmetic quietly producing nonsense on real rows.
31
- *
32
- * Driven by `cast`, never by the shape of the text, so this is the exact mirror of the write side:
33
- * a `sparsevec` column is read as `{1:1,3:2}/3` because that is what it was written as, and a dense
34
- * one as `[1,2,3]`. Both return the dense array the field type promises, whichever width the column
35
- * has. Sniffing the string instead would guess at a type the caller already knows.
36
- *
37
- * Returns `undefined` when the text does not match the column's own format, so a caller can keep the
38
- * raw value rather than replace it with something invented.
27
+ * A vector column's text as the dense array its field promises (pgvector returns text), read by `cast`
28
+ * as it was written, `{1:1,3:2}/3` or `[1,2,3]`; `undefined` where the text matches neither.
39
29
  */
40
30
  export function parseVectorLiteral(raw, cast) {
41
31
  const text = raw.trim();
@@ -63,13 +53,7 @@ function parseSparse(text) {
63
53
  }
64
54
  return dense;
65
55
  }
66
- /**
67
- * `[1,0,2]`, whatever width the column has.
68
- *
69
- * A dense literal is valid JSON by construction, so parsing it as JSON is both stricter and cheaper
70
- * than splitting: `[1,,2]` throws here, where `split(',').map(Number)` would have turned the hole
71
- * into a 0.
72
- */
56
+ /** `[1,0,2]`, parsed as the JSON it is, which refuses a hole `split` would read as 0. */
73
57
  function parseDense(text) {
74
58
  if (!text.startsWith('[') || !text.endsWith(']'))
75
59
  return undefined;
@@ -1,48 +1,23 @@
1
- import type { EntityIndexMeta, EntityMeta, FieldOptions, Query, QueryContext, QueryVectorSearch, VectorDistance, VectorMetric } from '../type/index.js';
1
+ import type { EntityIndexMeta, EntityMeta, FieldOptions, Query, QueryContext, QueryVectorSearch, SqlDialectFeatures, VectorDistance, VectorMetric } from '../type/index.js';
2
2
  import { AbstractDialect } from './abstractDialect.js';
3
3
  import type { VectorCast } from './vectorCast.js';
4
4
  /**
5
- * Vector similarity search for SQL dialects: the `ORDER BY <distance>` expression, its projection as
6
- * a named score, and the index metadata the schema generator reads.
7
- *
8
- * A layer of its own because it is nearly self-contained - it needs only `escapeId` from the SQL
9
- * dialect above it - unlike the JSON operators, which are woven into the generic comparison
10
- * machinery (`neExpr`, `numericCast`, `formatIn`, ...) and belong with it.
11
- *
12
- * A dialect declares which metrics it has, and how it spells each, in {@link vectorMetrics}. Both
13
- * shapes live in that one map - an operator (`"col" <=> $1`, Postgres/CockroachDB) or a function call
14
- * (`VEC_DISTANCE_COSINE(col, ?)`, MariaDB/SQLite) - so {@link appendVectorSort} is written once and an
15
- * engine with no vector search at all is simply the empty map.
5
+ * Vector search for the SQL dialects: the distance a `$sort` ranks by and projects, and the ANN tuning.
6
+ * Each dialect lists its metrics in {@link vectorMetrics}, an operator or a function; empty means no search.
16
7
  */
17
8
  export declare abstract class VectorSqlDialect extends AbstractDialect {
18
9
  readonly vectorExtension: string | undefined;
10
+ abstract readonly features: SqlDialectFeatures;
19
11
  /**
20
- * Whether {@link vectorTuningStatements} only applies inside a transaction. `SET LOCAL` does
21
- * nothing outside one, so the querier - the only layer that knows whether a transaction is open -
22
- * refuses instead of running a tuning that would silently not apply.
23
- */
24
- readonly vectorTuningNeedsTransaction: boolean;
25
- /**
26
- * `SET`s that widen an ANN index's search for one query, run before it on the same connection.
27
- *
28
- * Keyed off `$sort` rather than a `$where` `$near`, because the ANN index is what ranks: pgvector
29
- * reaches for HNSW on an `ORDER BY distance LIMIT`, while a bare distance predicate scans whatever
30
- * the planner picks. Tuning a query that never touches the index would set a knob for nothing.
31
- *
32
- * Empty by default: SQLite, libSQL and Turso compute every distance, so there is no candidate list
33
- * to widen, and a field with no ANN index has nothing to tune either.
12
+ * `SET`s widening an ANN index's search for one query, run before it on its connection. Keyed off `$sort`,
13
+ * since the index is what ranks. Empty where every distance is computed anyway.
34
14
  */
35
15
  vectorTuningStatements<E>(_meta: EntityMeta<E>, _q: Query<E>): readonly string[];
36
16
  /** The `$sort` key carrying a vector search, if the query ranks by one. */
37
17
  protected vectorSortKey<E>(q: Query<E>): string | undefined;
38
18
  /**
39
- * The ANN index `$candidates` would tune for this query, and nothing when there is none to tune -
40
- * no `$candidates`, no vector ranking, or a field with no ANN index on it. One place, so the two
41
- * dialects that act on it cannot disagree about when tuning applies.
42
- *
43
- * Validates here rather than at each emitter because the number is spelled into the statement
44
- * rather than bound: `SET LOCAL hnsw.ef_search = $1` is not a thing either engine accepts. `/http`
45
- * casts client JSON straight to `Query`, so `'abc'` and `null` both reach this.
19
+ * The ANN index `$candidates` tunes for the query, or nothing to tune. Checked here, since the number is
20
+ * spelled into a `SET` rather than bound, and `/http` input is untyped.
46
21
  */
47
22
  protected tunedVectorIndex<E>(meta: EntityMeta<E>, q: Query<E>): EntityIndexMeta | undefined;
48
23
  /**
@@ -67,11 +42,6 @@ export declare abstract class VectorSqlDialect extends AbstractDialect {
67
42
  * dialect needing a conversion around it (`$1::vector`, `VEC_FromText(?)`) declares it once.
68
43
  */
69
44
  protected appendVectorValue(ctx: QueryContext, value: readonly unknown[], _field?: FieldOptions): void;
70
- /**
71
- * Whether this engine has pgvector's narrower vector types (`halfvec`, `sparsevec`) or only the one.
72
- * Declared by the dialect that has them rather than looked up in a table keyed by dialect name.
73
- */
74
- protected readonly hasNarrowVectorTypes: boolean;
75
45
  /**
76
46
  * The vector type this dialect actually has for a declared one, so the cast follows the column
77
47
  * rather than naming a type the engine does not define.
@@ -3,35 +3,14 @@ import { findVectorIndex, findVectorSort } from '../util/dialect.util.js';
3
3
  import { entityName } from '../util/object.util.js';
4
4
  import { AbstractDialect } from './abstractDialect.js';
5
5
  /**
6
- * Vector similarity search for SQL dialects: the `ORDER BY <distance>` expression, its projection as
7
- * a named score, and the index metadata the schema generator reads.
8
- *
9
- * A layer of its own because it is nearly self-contained - it needs only `escapeId` from the SQL
10
- * dialect above it - unlike the JSON operators, which are woven into the generic comparison
11
- * machinery (`neExpr`, `numericCast`, `formatIn`, ...) and belong with it.
12
- *
13
- * A dialect declares which metrics it has, and how it spells each, in {@link vectorMetrics}. Both
14
- * shapes live in that one map - an operator (`"col" <=> $1`, Postgres/CockroachDB) or a function call
15
- * (`VEC_DISTANCE_COSINE(col, ?)`, MariaDB/SQLite) - so {@link appendVectorSort} is written once and an
16
- * engine with no vector search at all is simply the empty map.
6
+ * Vector search for the SQL dialects: the distance a `$sort` ranks by and projects, and the ANN tuning.
7
+ * Each dialect lists its metrics in {@link vectorMetrics}, an operator or a function; empty means no search.
17
8
  */
18
9
  export class VectorSqlDialect extends AbstractDialect {
19
10
  vectorExtension = undefined;
20
11
  /**
21
- * Whether {@link vectorTuningStatements} only applies inside a transaction. `SET LOCAL` does
22
- * nothing outside one, so the querier - the only layer that knows whether a transaction is open -
23
- * refuses instead of running a tuning that would silently not apply.
24
- */
25
- vectorTuningNeedsTransaction = false;
26
- /**
27
- * `SET`s that widen an ANN index's search for one query, run before it on the same connection.
28
- *
29
- * Keyed off `$sort` rather than a `$where` `$near`, because the ANN index is what ranks: pgvector
30
- * reaches for HNSW on an `ORDER BY distance LIMIT`, while a bare distance predicate scans whatever
31
- * the planner picks. Tuning a query that never touches the index would set a knob for nothing.
32
- *
33
- * Empty by default: SQLite, libSQL and Turso compute every distance, so there is no candidate list
34
- * to widen, and a field with no ANN index has nothing to tune either.
12
+ * `SET`s widening an ANN index's search for one query, run before it on its connection. Keyed off `$sort`,
13
+ * since the index is what ranks. Empty where every distance is computed anyway.
35
14
  */
36
15
  vectorTuningStatements(_meta, _q) {
37
16
  return [];
@@ -41,13 +20,8 @@ export class VectorSqlDialect extends AbstractDialect {
41
20
  return findVectorSort(q.$sort)?.key;
42
21
  }
43
22
  /**
44
- * The ANN index `$candidates` would tune for this query, and nothing when there is none to tune -
45
- * no `$candidates`, no vector ranking, or a field with no ANN index on it. One place, so the two
46
- * dialects that act on it cannot disagree about when tuning applies.
47
- *
48
- * Validates here rather than at each emitter because the number is spelled into the statement
49
- * rather than bound: `SET LOCAL hnsw.ef_search = $1` is not a thing either engine accepts. `/http`
50
- * casts client JSON straight to `Query`, so `'abc'` and `null` both reach this.
23
+ * The ANN index `$candidates` tunes for the query, or nothing to tune. Checked here, since the number is
24
+ * spelled into a `SET` rather than bound, and `/http` input is untyped.
51
25
  */
52
26
  tunedVectorIndex(meta, q) {
53
27
  const candidates = q.$candidates;
@@ -83,17 +57,12 @@ export class VectorSqlDialect extends AbstractDialect {
83
57
  appendVectorValue(ctx, value, _field) {
84
58
  ctx.addValue(`[${value.join(',')}]`);
85
59
  }
86
- /**
87
- * Whether this engine has pgvector's narrower vector types (`halfvec`, `sparsevec`) or only the one.
88
- * Declared by the dialect that has them rather than looked up in a table keyed by dialect name.
89
- */
90
- hasNarrowVectorTypes = false;
91
60
  /**
92
61
  * The vector type this dialect actually has for a declared one, so the cast follows the column
93
62
  * rather than naming a type the engine does not define.
94
63
  */
95
64
  supportedVectorType(cast) {
96
- return this.hasNarrowVectorTypes ? cast : 'vector';
65
+ return this.features.narrowVectorTypes ? cast : 'vector';
97
66
  }
98
67
  /**
99
68
  * The distance a vector `$sort` projects, which the projection names after `$project`. Delegates to
@@ -1,11 +1,7 @@
1
1
  import type { FieldOptions, HookEvent, RelationRegistration, Type } from '../../type/index.js';
2
2
  /**
3
- * What the member decorators record for one class, waiting for `@Entity()` or `defineEntity` to drain
4
- * it into the metadata registry. Member decorators receive no class reference under the standard
5
- * decorator spec, so this object is the only channel between them and the class decorator that does.
6
- *
7
- * The writable counterpart of `EntityMembers`, which is what registration reads: this one is written
8
- * into member by member, so every map is present and none of them is readonly.
3
+ * What the member decorators record for one class, until `@Entity()` or `defineEntity` drains it: the
4
+ * only channel from a member decorator to its class. The writable counterpart of `EntityMembers`.
9
5
  */
10
6
  export type MemberRegistrations = {
11
7
  readonly fields: Record<string, FieldOptions>;
@@ -13,13 +9,8 @@ export type MemberRegistrations = {
13
9
  readonly hooks: Partial<Record<HookEvent, string[]>>;
14
10
  };
15
11
  /**
16
- * The calling class's own registrations, created on first use.
17
- *
18
- * Deliberately holds **only** this class's members: inheritance is resolved later by walking the class
19
- * prototype chain, not by reading through the metadata object's. tsc chains a subclass's metadata to its
20
- * parent's and SWC does not, so anything built on that chain would work under one compiler and quietly
21
- * lose inherited fields under the other. Keeping each bag to its own members also means a parent's map
22
- * is never shared with its subclasses, and hooks cannot be registered twice.
12
+ * The class's own registrations, created on first use, never read through a parent's: inheritance walks
13
+ * the class chain, since not every compiler chains decorator metadata.
23
14
  */
24
15
  export declare function memberRegistrations(metadata: DecoratorMetadata): MemberRegistrations;
25
16
  /**
@@ -28,11 +19,7 @@ export declare function memberRegistrations(metadata: DecoratorMetadata): Member
28
19
  */
29
20
  export declare function drainRegistrations(metadata: DecoratorMetadata | undefined): MemberRegistrations | undefined;
30
21
  /**
31
- * The registrations a class made for itself.
32
- *
33
- * @remarks Only usable once the class is fully defined, which is why `@Entity()` reads
34
- * `context.metadata` instead: TypeScript attaches `Symbol.metadata` to the class *after* its class
35
- * decorators return. Ancestors are always fully defined by then, so this is how inherited members are
36
- * collected.
22
+ * The registrations a class made for itself, readable once it is fully defined: `@Entity()` reads
23
+ * `context.metadata` instead, since the class gets `Symbol.metadata` after its decorators return.
37
24
  */
38
25
  export declare function ownRegistrations(entity: Type<unknown>): MemberRegistrations | undefined;
@@ -1,26 +1,14 @@
1
1
  /**
2
- * Polyfill `Symbol.metadata`, which no runtime we support defines yet (checked on Node 24 and Bun
3
- * 1.3): TypeScript's decorator emit reads it to decide whether to build the metadata object at all, so
4
- * without this every `context.metadata` is `undefined` and field registration is silently dropped
5
- * rather than failing.
6
- *
7
- * `Symbol.for`, not `Symbol()`, so a duplicated copy of this module (HMR, federated bundles, ESM+CJS
8
- * dual-loading) lands on the same symbol, and so it agrees with the key esbuild and SWC fall back to
9
- * (`Symbol.metadata ?? Symbol.for('Symbol.metadata')`). Assigned through a widened alias because the
10
- * lib declares the property `readonly`; when a runtime does define it, `??=` leaves it alone.
2
+ * Polyfills `Symbol.metadata`, without which TypeScript builds no `context.metadata` and every field is
3
+ * silently dropped. `Symbol.for`, the key esbuild and SWC fall back to, so duplicated modules agree.
11
4
  */
12
5
  const symbolCtor = Symbol;
13
6
  symbolCtor.metadata ??= Symbol.for('Symbol.metadata');
14
7
  /** Where member registrations live on the per-class metadata object. */
15
8
  const registrations = Symbol.for('uql-orm/entity/decoratorMembers');
16
9
  /**
17
- * The calling class's own registrations, created on first use.
18
- *
19
- * Deliberately holds **only** this class's members: inheritance is resolved later by walking the class
20
- * prototype chain, not by reading through the metadata object's. tsc chains a subclass's metadata to its
21
- * parent's and SWC does not, so anything built on that chain would work under one compiler and quietly
22
- * lose inherited fields under the other. Keeping each bag to its own members also means a parent's map
23
- * is never shared with its subclasses, and hooks cannot be registered twice.
10
+ * The class's own registrations, created on first use, never read through a parent's: inheritance walks
11
+ * the class chain, since not every compiler chains decorator metadata.
24
12
  */
25
13
  export function memberRegistrations(metadata) {
26
14
  if (!Object.hasOwn(metadata, registrations)) {
@@ -41,12 +29,8 @@ export function drainRegistrations(metadata) {
41
29
  return own;
42
30
  }
43
31
  /**
44
- * The registrations a class made for itself.
45
- *
46
- * @remarks Only usable once the class is fully defined, which is why `@Entity()` reads
47
- * `context.metadata` instead: TypeScript attaches `Symbol.metadata` to the class *after* its class
48
- * decorators return. Ancestors are always fully defined by then, so this is how inherited members are
49
- * collected.
32
+ * The registrations a class made for itself, readable once it is fully defined: `@Entity()` reads
33
+ * `context.metadata` instead, since the class gets `Symbol.metadata` after its decorators return.
50
34
  */
51
35
  export function ownRegistrations(entity) {
52
36
  const metadata = Object.getOwnPropertyDescriptor(entity, Symbol.metadata)?.value;
@@ -1,20 +1,15 @@
1
- import type { EntityIndexColumnInput, EntityIndexOptions, EntityOptions, FilterOptions, RefMap, Type } from '../../type/index.js';
1
+ import type { EntityIndexColumnInput, EntityIndexOptions, EntityOptions, FilterName, FilterOptions, RefMap, Type } from '../../type/index.js';
2
2
  /**
3
- * Marks a class as an entity and finalizes its metadata.
4
- *
5
- * @remarks Takes the registrations from `context.metadata` rather than from the class. Member
6
- * decorators have already run by the time a class decorator does, but TypeScript defines
7
- * `Symbol.metadata` on the class *after* the class decorators return, so reading `entity[Symbol.metadata]`
8
- * here would find only what the base class left behind. `defineEntity` reads it off the class instead,
9
- * which is correct for the imperative path because it runs later still.
3
+ * Marks a class as an entity and finalizes its metadata, draining `context.metadata`: the class gets
4
+ * `Symbol.metadata` only after its decorators return.
10
5
  */
11
- export declare function Entity<E>(opts?: EntityOptions<E>): (entity: Type<E>, context?: ClassDecoratorContext) => void;
6
+ export declare function Entity<E>(opts?: NoInfer<EntityOptions<E>>): (entity: Type<E>, context?: ClassDecoratorContext) => void;
12
7
  /**
13
8
  * Registers a named `$where` filter, applied to every query unless bypassed via `QueryOptions.filters`.
14
9
  *
15
10
  * @example `@Filter('active', { where: { status: 'active' }, default: false })`
16
11
  */
17
- export declare function Filter<E>(name: string, opts: FilterOptions<E>): (entity: Type<E>) => void;
12
+ export declare function Filter<E, N extends string>(name: FilterName<N>, opts: FilterOptions<E>): (entity: Type<E>) => void;
18
13
  /**
19
14
  * Declares a composite index, its columns read off the entity's refs, so `@Index((user) => [user.nope])`
20
15
  * does not compile and a rename reaches every column. Stacks, so several may sit above one class.
@@ -3,13 +3,8 @@ import { drainRegistrations } from './bag.js';
3
3
  // The class-level decorators. Unlike the member ones they receive the class, so each is a direct call
4
4
  // into the registry with no bag in between.
5
5
  /**
6
- * Marks a class as an entity and finalizes its metadata.
7
- *
8
- * @remarks Takes the registrations from `context.metadata` rather than from the class. Member
9
- * decorators have already run by the time a class decorator does, but TypeScript defines
10
- * `Symbol.metadata` on the class *after* the class decorators return, so reading `entity[Symbol.metadata]`
11
- * here would find only what the base class left behind. `defineEntity` reads it off the class instead,
12
- * which is correct for the imperative path because it runs later still.
6
+ * Marks a class as an entity and finalizes its metadata, draining `context.metadata`: the class gets
7
+ * `Symbol.metadata` only after its decorators return.
13
8
  */
14
9
  export function Entity(opts) {
15
10
  return (entity, context) => {
@@ -1,15 +1,7 @@
1
- import type { EntityGetter, FieldOptions, FieldType, IdValue, NamedIdKey, RelationManyToManyOptions, RelationManyToOneOptions, RelationOneToManyOptions, RelationOneToOneOptions, TsTypeOf } from '../../type/index.js';
1
+ import type { EntityGetter, FieldOptions, FieldType, HasCompositeKey, IdValue, NamedIdKey, RejectKeys, RelationManyToManyOptions, RelationManyToOneOptions, RelationOneToManyOptions, RelationOneToOneOptions, TsTypeOf } from '../../type/index.js';
2
2
  import type { RejectIncompatible } from '../../util/index.js';
3
3
  /** A member decorator that also constrains the property it may be applied to, on a class `O`. */
4
4
  type MemberDecorator<V, O = unknown> = (value: undefined, context: ClassFieldDecoratorContext<O, V>) => void;
5
- /**
6
- * Maps any option the type does not declare to `never`, turning a typo into a compile error.
7
- *
8
- * Needed because the decorators capture their options as a naked type parameter, and TypeScript
9
- * skips excess-property checking on one of those: `@Field({ nulable: true })` compiled and was
10
- * silently ignored. Resolves to `unknown` - an inert intersection member - when there are none.
11
- */
12
- type RejectUnknown<O, Known> = [Exclude<keyof O, keyof Known>] extends [never] ? unknown : Record<Exclude<keyof O, keyof Known> & string, never>;
13
5
  /**
14
6
  * The property type a set of field options describes: the declared `type`, narrowed by `enum` to the
15
7
  * values that type admits (so `enum: [2]` stays off a `String`), or else the referenced key's own type,
@@ -21,32 +13,23 @@ type DeclaredValue<O> = O extends {
21
13
  readonly enum: infer E extends readonly unknown[];
22
14
  } ? EnumValue<Extract<E[number], TsTypeOf<T>>, TsTypeOf<T>> : TsTypeOf<T> : O extends {
23
15
  readonly references: EntityGetter<infer E>;
24
- } ? IdValue<E> : never;
25
- /**
26
- * The enum's members, or a named complaint when they widened.
27
- *
28
- * `['a', 'b']` without `as const` infers `string[]`, whose member type is the field's own type and
29
- * so narrows nothing - the check would be silently off. Resolving to a type no property can hold
30
- * makes that a compile error that says why, rather than a decoration.
31
- */
16
+ } ? HasCompositeKey<E> extends true ? {
17
+ readonly __compositeKeyNeedsAColumnPerKey: true;
18
+ } : IdValue<E> : never;
19
+ /** The enum's members, or a named complaint where they widened for lack of `as const`, which would check nothing. */
32
20
  type EnumValue<Members, Declared> = Declared extends Members ? {
33
21
  readonly __enumNeedsAsConst: true;
34
22
  } : Members;
35
23
  /**
36
- * Declares a persisted field.
37
- *
38
- * `@Field({ type: String })` on a `number` property is a compile error rather than a silent TEXT column,
39
- * which is what makes the now-mandatory `type` worth stating.
40
- *
24
+ * Declares a persisted field, its `type` checked against the property's.
41
25
  * @example `@Field({ type: String }) name?: string;`
42
- * @example `@Field({ references: () => User }) userId?: string;` (where `User.id` is a `uuid`)
43
- * @example `@Field({ type: Number, computed: (line) => raw`${line.qty} * ${line.price}` }) total?: number;`
26
+ * @example `@Field({ references: () => User }) userId?: string;`
44
27
  */
45
28
  export declare function Field<This, O extends FieldOptions<DeclaredValue<O>, This> & ({
46
29
  type: FieldType;
47
30
  } | {
48
31
  references: EntityGetter;
49
- }) & RejectUnknown<O, FieldOptions> & RejectIncompatible<O>>(opts: O): MemberDecorator<DeclaredValue<O> | undefined, This>;
32
+ }) & RejectKeys<Exclude<keyof O, keyof FieldOptions>> & RejectIncompatible<O>>(opts: O): MemberDecorator<DeclaredValue<O> | undefined, This>;
50
33
  /**
51
34
  * A key the type level cannot name, reported on each `@Id` that leaves it unnamed. Where no `idKey`
52
35
  * brand and no conventional name applies, `IdKey` falls back to every field, and `IdValue`,
@@ -58,16 +41,12 @@ type KeyIsNamed<This> = [NamedIdKey<This>] extends [never] ? {
58
41
  /** {@link MemberDecorator} that also constrains the class, which is where a key is named. */
59
42
  type IdDecorator<V> = <This>(value: undefined, context: ClassFieldDecoratorContext<This, V> & KeyIsNamed<This>) => void;
60
43
  /**
61
- * Declares the primary key, checked the same way as `@Field` and additionally against the class:
62
- * a key not named `id`, `_id` or `uuid` has to be named by the `idKey` brand.
63
- *
64
- * @example `@Id({ type: Number }) id?: number;`
44
+ * Declares the primary key, checked like `@Field`; a key not named `id`, `_id` or `uuid` needs the `idKey` brand.
65
45
  * @example `@Id({ type: 'uuid', onInsert: uuidv7 }) id?: string;`
66
- * @example `[idKey]?: 'pk';` beside `@Id({ type: Number }) pk?: number;`
67
46
  */
68
47
  export declare function Id<O extends FieldOptions<DeclaredValue<O>> & {
69
48
  type: FieldType;
70
- } & RejectUnknown<O, FieldOptions> & RejectIncompatible<O> & {
49
+ } & RejectKeys<Exclude<keyof O, keyof FieldOptions>> & RejectIncompatible<O> & {
71
50
  readonly nullable?: false;
72
51
  }>(opts: O): IdDecorator<DeclaredValue<O> | undefined>;
73
52
  /**
@@ -1,14 +1,9 @@
1
1
  import { relationRegistration } from '../metadata/definition.js';
2
2
  import { memberRegistrations } from './bag.js';
3
3
  /**
4
- * Declares a persisted field.
5
- *
6
- * `@Field({ type: String })` on a `number` property is a compile error rather than a silent TEXT column,
7
- * which is what makes the now-mandatory `type` worth stating.
8
- *
4
+ * Declares a persisted field, its `type` checked against the property's.
9
5
  * @example `@Field({ type: String }) name?: string;`
10
- * @example `@Field({ references: () => User }) userId?: string;` (where `User.id` is a `uuid`)
11
- * @example `@Field({ type: Number, computed: (line) => raw`${line.qty} * ${line.price}` }) total?: number;`
6
+ * @example `@Field({ references: () => User }) userId?: string;`
12
7
  */
13
8
  export function Field(opts) {
14
9
  return (_value, context) => {
@@ -16,12 +11,8 @@ export function Field(opts) {
16
11
  };
17
12
  }
18
13
  /**
19
- * Declares the primary key, checked the same way as `@Field` and additionally against the class:
20
- * a key not named `id`, `_id` or `uuid` has to be named by the `idKey` brand.
21
- *
22
- * @example `@Id({ type: Number }) id?: number;`
14
+ * Declares the primary key, checked like `@Field`; a key not named `id`, `_id` or `uuid` needs the `idKey` brand.
23
15
  * @example `@Id({ type: 'uuid', onInsert: uuidv7 }) id?: string;`
24
- * @example `[idKey]?: 'pk';` beside `@Id({ type: Number }) pk?: number;`
25
16
  */
26
17
  export function Id(opts) {
27
18
  return (_value, context) => {
@@ -1,4 +1,4 @@
1
- import type { EntityData, EntityIndexInput, EntityMembers, EntityMeta, EntityOptions, FieldMeta, FieldOptions, FilterOptions, HookEvent, IdKey, RelationKey, RelationMeta, RelationOptions, RelationRegistration, Type, WrittenId } from '../../type/index.js';
1
+ import type { EntityData, EntityIndexInput, EntityMembers, EntityMeta, EntityOptions, FieldMeta, FieldOptions, FilterName, FilterOptions, HookEvent, IdKey, RelationKey, RelationMeta, RelationOptions, RelationRegistration, Type, WrittenId } from '../../type/index.js';
2
2
  export declare function defineField<E>(entity: Type<E>, key: string, opts?: FieldOptions): EntityMeta<E>;
3
3
  export declare function defineId<E>(entity: Type<E>, key: string, opts: FieldOptions): EntityMeta<E>;
4
4
  /** `T` is the relation's target, independent of the owner `E`. */
@@ -15,7 +15,7 @@ export declare function defineHook<E>(entity: Type<E>, methodName: string, event
15
15
  * sugar are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
16
16
  */
17
17
  export declare function defineIndex<E>(entity: Type<E>, index: EntityIndexInput<E>): EntityMeta<E>;
18
- export declare function defineFilter<E>(entity: Type<E>, name: string, opts: FilterOptions<E>): EntityMeta<E>;
18
+ export declare function defineFilter<E, N extends string>(entity: Type<E>, name: FilterName<N>, opts: FilterOptions<E>): EntityMeta<E>;
19
19
  /**
20
20
  * Feeds fields, relations and hooks into the `define*` primitives, so the decorators and the imperative
21
21
  * API converge on one registration path before anything is finalized.
@@ -39,25 +39,9 @@ export declare function soleIdOf<E>(meta: EntityMeta<E>, what: string): IdKey<E>
39
39
  export declare function fieldOf<E>(meta: EntityMeta<E>, key: string): FieldMeta;
40
40
  /** The relation `key` names, for a caller that took `key` from the metadata itself. */
41
41
  export declare function relationOf<E>(meta: EntityMeta<E>, key: RelationKey<E>): RelationMeta;
42
- /**
43
- * Whether the caller named every column of the row's primary key, so {@link idOf} can name the row.
44
- *
45
- * `!= null` rather than falsiness: `0` and an empty string are ids a row can legitimately carry, and
46
- * reading them as "no id" is how a write of that row turned into a second insert. Distinct from
47
- * "does the row carry this column", which an insert asks of `undefined` alone because that is what
48
- * decides whether the column appears in its `VALUES` list at all.
49
- */
42
+ /** Whether the row names every column of its primary key, `0` and `''` included. */
50
43
  export declare function namesKey<E>(meta: EntityMeta<E>, row: EntityData<E>): boolean;
51
- /**
52
- * A row's primary key: the value itself for a single key, an object carrying every key for a
53
- * composite - which is {@link WrittenId}, and reads as the {@link EntityId} a `$where` takes.
54
- *
55
- * What a settled write names its rows by, and what a write hands back. Naming a composite row by one
56
- * of its columns would address every row agreeing on that one.
57
- *
58
- * `WrittenId` does not reduce for an unresolved `E`, so which branch this entity is in cannot be
59
- * proven here, only checked - which is what `ids.length` does.
60
- */
44
+ /** A row's primary key: its value, or a map of every column on a composite, checked at run time. */
61
45
  export declare function idOf<E>(meta: EntityMeta<E>, row: EntityData<E>): WrittenId<E>;
62
46
  /**
63
47
  * Forgets an entity, and reports whether there was one - for a registry that grows at runtime, where a
@@ -71,6 +55,6 @@ export declare function getMeta<E>(entity: Type<E>): EntityMeta<E>;
71
55
  /**
72
56
  * The foreign keys an entity holds: each owning to-one's columns, and each `@Field({ references })` no
73
57
  * relation joins on, as the many-to-one it describes, once its target has registered a key. What the
74
- * schema build constrains and a junction joins by, read once the relations holding them are settled.
58
+ * schema build constrains and a junction joins by, settling the relations holding them first.
75
59
  */
76
60
  export declare function foreignKeysOf<E>(meta: EntityMeta<E>): RelationMeta[];