uql-orm 0.56.0 → 0.58.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 (110) hide show
  1. package/README.md +7 -9
  2. package/dist/browser/uql-browser.min.js +2 -2
  3. package/dist/browser/uql-browser.min.js.map +4 -4
  4. package/dist/cockroachdb/cockroachDialect.d.ts +5 -2
  5. package/dist/cockroachdb/cockroachDialect.js +2 -10
  6. package/dist/d1/d1SqliteDialect.d.ts +1 -0
  7. package/dist/d1/d1SqliteDialect.js +2 -0
  8. package/dist/dialect/abstractSqlDialect.d.ts +196 -33
  9. package/dist/dialect/abstractSqlDialect.js +410 -203
  10. package/dist/dialect/aliases.d.ts +10 -7
  11. package/dist/dialect/aliases.js +12 -7
  12. package/dist/dialect/hydrateColumn.d.ts +8 -2
  13. package/dist/dialect/hydrateColumn.js +33 -1
  14. package/dist/dialect/jsonSql.d.ts +13 -5
  15. package/dist/dialect/jsonSql.js +24 -7
  16. package/dist/dialect/mysqlLikeSqlDialect.d.ts +31 -3
  17. package/dist/dialect/mysqlLikeSqlDialect.js +57 -5
  18. package/dist/dialect/pgLikeSqlDialect.d.ts +20 -20
  19. package/dist/dialect/pgLikeSqlDialect.js +23 -48
  20. package/dist/dialect/pgVectorMetrics.d.ts +13 -0
  21. package/dist/dialect/pgVectorMetrics.js +17 -0
  22. package/dist/dialect/queryContext.d.ts +3 -7
  23. package/dist/dialect/queryContext.js +13 -8
  24. package/dist/dialect/queryJoins.d.ts +8 -4
  25. package/dist/dialect/queryJoins.js +26 -11
  26. package/dist/dialect/vectorSqlDialect.d.ts +2 -2
  27. package/dist/dialect/vectorSqlDialect.js +2 -3
  28. package/dist/entity/decorator/bag.d.ts +2 -2
  29. package/dist/entity/decorator/entity.d.ts +8 -9
  30. package/dist/entity/decorator/entity.js +6 -7
  31. package/dist/entity/decorator/members.d.ts +7 -6
  32. package/dist/entity/decorator/members.js +2 -1
  33. package/dist/entity/metadata/definition.d.ts +16 -11
  34. package/dist/entity/metadata/definition.js +54 -42
  35. package/dist/http/handler.d.ts +2 -2
  36. package/dist/http/handler.js +0 -1
  37. package/dist/maria/mariaDialect.d.ts +13 -6
  38. package/dist/maria/mariaDialect.js +29 -9
  39. package/dist/migrate/cli.d.ts +2 -3
  40. package/dist/migrate/cli.js +2 -2
  41. package/dist/migrate/codegen/entityCodeGenerator.js +6 -4
  42. package/dist/migrate/codegen/entityTypes.d.ts +1 -1
  43. package/dist/migrate/codegen/entityTypes.js +4 -3
  44. package/dist/migrate/codegen/indexDecoratorSource.d.ts +5 -4
  45. package/dist/migrate/codegen/indexDecoratorSource.js +17 -13
  46. package/dist/migrate/codegen/sourceLiteral.d.ts +2 -0
  47. package/dist/migrate/codegen/sourceLiteral.js +4 -0
  48. package/dist/migrate/ddl/index.d.ts +1 -5
  49. package/dist/migrate/ddl/index.js +14 -25
  50. package/dist/migrate/ddl/indexDdl.d.ts +11 -2
  51. package/dist/migrate/ddl/indexDdl.js +17 -1
  52. package/dist/migrate/ddl/mssqlIndexDdl.d.ts +10 -0
  53. package/dist/migrate/ddl/mssqlIndexDdl.js +10 -0
  54. package/dist/migrate/ddl/mysqlIndexDdl.d.ts +10 -17
  55. package/dist/migrate/ddl/mysqlIndexDdl.js +16 -27
  56. package/dist/migrate/ddl/pgIndexDdl.d.ts +18 -8
  57. package/dist/migrate/ddl/pgIndexDdl.js +29 -12
  58. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +3 -3
  59. package/dist/migrate/migrator.d.ts +4 -4
  60. package/dist/migrate/schemaGenerator.d.ts +8 -8
  61. package/dist/migrate/schemaGenerator.js +5 -7
  62. package/dist/migrate/schemaGeneratorAsync.d.ts +2 -3
  63. package/dist/mongo/mongoDialect.d.ts +31 -18
  64. package/dist/mongo/mongoDialect.js +146 -104
  65. package/dist/mongo/mongodbQuerier.d.ts +10 -17
  66. package/dist/mongo/mongodbQuerier.js +31 -106
  67. package/dist/mssql/mssqlDialect.d.ts +16 -0
  68. package/dist/mssql/mssqlDialect.js +26 -4
  69. package/dist/mysql/mysqlDialect.d.ts +2 -0
  70. package/dist/mysql/mysqlDialect.js +4 -0
  71. package/dist/querier/abstractQuerier.d.ts +20 -36
  72. package/dist/querier/abstractQuerier.js +35 -129
  73. package/dist/querier/abstractQuerierPool.d.ts +2 -2
  74. package/dist/querier/abstractSqlQuerier.d.ts +4 -17
  75. package/dist/querier/abstractSqlQuerier.js +40 -50
  76. package/dist/schema/canonicalType.js +4 -4
  77. package/dist/schema/indexDifferences.js +4 -4
  78. package/dist/schema/schemaASTBuilder.d.ts +3 -3
  79. package/dist/schema/schemaASTBuilder.js +32 -3
  80. package/dist/schema/schemaASTDiffer.js +5 -5
  81. package/dist/sqlite/sqliteDialect.d.ts +20 -1
  82. package/dist/sqlite/sqliteDialect.js +38 -7
  83. package/dist/turso/tursoDialect.d.ts +2 -0
  84. package/dist/turso/tursoDialect.js +2 -0
  85. package/dist/type/config.d.ts +3 -3
  86. package/dist/type/dialect.d.ts +4 -5
  87. package/dist/type/entity.d.ts +110 -69
  88. package/dist/type/migration.d.ts +7 -7
  89. package/dist/type/migratorDialect.d.ts +4 -0
  90. package/dist/type/querier.d.ts +6 -6
  91. package/dist/type/querierPool.d.ts +2 -2
  92. package/dist/type/query.d.ts +41 -72
  93. package/dist/type/query.js +10 -5
  94. package/dist/type/queryAggregate.d.ts +43 -34
  95. package/dist/type/queryAggregate.js +1 -1
  96. package/dist/type/queryWhere.d.ts +12 -9
  97. package/dist/type/universalQuerier.d.ts +4 -4
  98. package/dist/util/dialect.util.d.ts +4 -4
  99. package/dist/util/dialect.util.js +24 -15
  100. package/dist/util/field.util.d.ts +5 -0
  101. package/dist/util/field.util.js +19 -0
  102. package/dist/util/object.util.d.ts +2 -0
  103. package/dist/util/object.util.js +4 -0
  104. package/dist/util/relationQuery.util.d.ts +12 -65
  105. package/dist/util/relationQuery.util.js +27 -81
  106. package/dist/util/rowKey.util.d.ts +1 -11
  107. package/dist/util/rowKey.util.js +1 -13
  108. package/package.json +1 -1
  109. package/dist/querier/relationCount.d.ts +0 -16
  110. package/dist/querier/relationCount.js +0 -121
@@ -1,7 +1,23 @@
1
+ import { COCKROACH_VECTOR_METRICS, PG_VECTOR_METRICS } from '../../dialect/pgVectorMetrics.js';
1
2
  import { unsupportedVectorMetric } from '../../type/vector.js';
2
3
  import { IndexDdl } from './indexDdl.js';
4
+ /** `$text` computes its `TO_TSVECTOR` per row, which no index over the raw columns serves. */
5
+ const PG_INDEX_TYPE_HINTS = new Map([
6
+ ['fulltext', '. $text needs none there; name the columns it searches with $fields.'],
7
+ ]);
3
8
  /** `CREATE INDEX ... USING hnsw ("embedding" vector_cosine_ops) WITH (m = ...)`, pgvector's form. */
4
9
  export class PgIndexDdl extends IndexDdl {
10
+ /** Postgres 18's `pg_am`, with pgvector's two. */
11
+ indexTypes = new Set([
12
+ 'btree',
13
+ 'hash',
14
+ 'gin',
15
+ 'gist',
16
+ 'brin',
17
+ 'hnsw',
18
+ 'ivfflat',
19
+ ]);
20
+ indexTypeHints = PG_INDEX_TYPE_HINTS;
5
21
  indexFeatures = new Set([
6
22
  'expression',
7
23
  'partial',
@@ -10,20 +26,13 @@ export class PgIndexDdl extends IndexDdl {
10
26
  'include',
11
27
  'jsonPath',
12
28
  ]);
29
+ /** The metrics its vector index takes, each naming the operator class it is built with. */
30
+ vectorMetrics = PG_VECTOR_METRICS;
13
31
  /** pgvector's own index types; CockroachDB's native one widens this. */
14
32
  isVectorIndex(index) {
15
33
  return index.type === 'hnsw' || index.type === 'ivfflat';
16
34
  }
17
- /**
18
- * ` USING <method>`. `fulltext` is refused rather than compiled into a ` USING fulltext` the server
19
- * can only answer with a syntax error: `$text` computes its `TO_TSVECTOR` per row, which no index
20
- * over the raw columns serves.
21
- */
22
35
  indexAccessMethod(index) {
23
- if (index.type === 'fulltext') {
24
- throw new TypeError(`${this.dialect.dialectName} has no fulltext index (index "${index.name}"). $text needs none there; ` +
25
- 'name the columns it searches with $fields.');
26
- }
27
36
  return index.type ? ` USING ${index.type}` : '';
28
37
  }
29
38
  /**
@@ -37,7 +46,7 @@ export class PgIndexDdl extends IndexDdl {
37
46
  if (!this.isVectorIndex(index) || !index.distance) {
38
47
  return entry.opsClass ? ` ${entry.opsClass}` : '';
39
48
  }
40
- const metric = this.dialect.vectorMetrics.get(index.distance);
49
+ const metric = this.vectorMetrics.get(index.distance);
41
50
  if (!metric) {
42
51
  throw unsupportedVectorMetric(this.dialect.dialectName, index.distance, index.name);
43
52
  }
@@ -78,6 +87,13 @@ export class PgIndexDdl extends IndexDdl {
78
87
  */
79
88
  export class CockroachIndexDdl extends PgIndexDdl {
80
89
  indexFeatures = new Set(['expression', 'partial', 'include', 'jsonPath']);
90
+ /** v26.3 answers `hash` and `brin` "unimplemented", `ivfflat` "unrecognized"; `hnsw` builds its vector index. */
91
+ indexTypes = new Set(['btree', 'gin', 'gist', 'hnsw', 'vector']);
92
+ indexTypeHints = new Map([
93
+ ...PG_INDEX_TYPE_HINTS,
94
+ ['ivfflat', "; declare type: 'vector' instead"],
95
+ ]);
96
+ vectorMetrics = COCKROACH_VECTOR_METRICS;
81
97
  isNativeVectorIndex(index) {
82
98
  return index.type === 'vector';
83
99
  }
@@ -90,7 +106,8 @@ export class CockroachIndexDdl extends PgIndexDdl {
90
106
  indexAccessMethod(index) {
91
107
  return this.isNativeVectorIndex(index) ? '' : super.indexAccessMethod(index);
92
108
  }
93
- indexTuning(index) {
94
- return this.isNativeVectorIndex(index) ? '' : super.indexTuning(index);
109
+ /** None of pgvector's knobs: `WITH (m = 16)` answers "invalid storage parameter", `hnsw` included. */
110
+ indexTuning() {
111
+ return '';
95
112
  }
96
113
  }
@@ -13,8 +13,8 @@ export declare class MongoSchemaGenerator extends AbstractDialect implements Sch
13
13
  * defer and no order to respect: this is each collection and nothing more. `foreignKeys` is accepted
14
14
  * and ignored for the same reason.
15
15
  */
16
- generateCreateSchema(entities: readonly Type<unknown>[], options?: CreateSchemaOptions): string[];
17
- generateDropSchema(entities: readonly Type<unknown>[]): string[];
16
+ generateCreateSchema(entities: readonly Type<object>[], options?: CreateSchemaOptions): string[];
17
+ generateDropSchema(entities: readonly Type<object>[]): string[];
18
18
  private selected;
19
19
  /**
20
20
  * The indexes `@Field({ index })` declares, as the collection would hold them.
@@ -48,5 +48,5 @@ export declare class MongoSchemaGenerator extends AbstractDialect implements Sch
48
48
  ifNotExists?: boolean;
49
49
  }): string[];
50
50
  generateRenameTableSql(oldName: string, newName: string): string;
51
- diffSchema<E>(entity: Type<E>, currentTable: TableNode | undefined): SchemaDiff | undefined;
51
+ diffSchema(entity: Type<object>, currentTable: TableNode | undefined): SchemaDiff | undefined;
52
52
  }
@@ -1,4 +1,4 @@
1
- import type { DialectName, LoggingOptions, Migration, MigrationDefinition, MigrationResult, MigrationStorage, MigratorOptions, MongoQuerier, Querier, QuerierPool, SchemaDiff, SchemaGenerator, SchemaIntrospector, SyncOptions, Type } from '../type/index.js';
1
+ import type { DialectName, LoggingOptions, Migration, MigrationDefinition, MigrationResult, MigrationStorage, MigratorDialect, MigratorOptions, MongoQuerier, Querier, QuerierPool, SchemaDiff, SchemaGenerator, SchemaIntrospector, SyncOptions, Type } from '../type/index.js';
2
2
  import { LoggerWrapper } from '../util/index.js';
3
3
  import type { IMigrationBuilder } from './builder/types.js';
4
4
  /**
@@ -12,13 +12,13 @@ export declare class Migrator {
12
12
  get logger(): LoggerWrapper;
13
13
  set logger(value: LoggingOptions);
14
14
  private readonly _entities?;
15
- get entities(): Type<unknown>[];
15
+ get entities(): Type<object>[];
16
16
  readonly dialectName: DialectName;
17
17
  schemaGenerator?: SchemaGenerator;
18
18
  schemaIntrospector?: SchemaIntrospector;
19
19
  private readonly _defaultForeignKeyAction?;
20
20
  private _mongoSchemaLoadPromise?;
21
- constructor(pool: QuerierPool, options?: MigratorOptions);
21
+ constructor(pool: QuerierPool<Querier, MigratorDialect>, options?: MigratorOptions);
22
22
  /**
23
23
  * Loads MongoDB's schema generator on first use, so the optional `mongodb` peer loads only then. SQL
24
24
  * generators are set in the constructor (or via {@link setSchemaGenerator}).
@@ -89,7 +89,7 @@ export declare class Migrator {
89
89
  * {@link schemaIntrospector} so a caller that replaced it still wins.
90
90
  */
91
91
  private introspectClaimedSchemas;
92
- findEntityForTable(tableName: string): Promise<Type<unknown> | undefined>;
92
+ findEntityForTable(tableName: string): Promise<Type<object> | undefined>;
93
93
  /**
94
94
  * Applies the entity schema to the database: every registered entity, or the one `entity` names.
95
95
  *
@@ -1,8 +1,8 @@
1
- import { type AbstractDialect, AbstractSqlDialect } from '../dialect/index.js';
1
+ import type { AbstractSqlDialect } from '../dialect/index.js';
2
2
  import type { SchemaAST } from '../schema/schemaAST.js';
3
3
  import { type DiffOptions } from '../schema/schemaASTDiffer.js';
4
4
  import type { CanonicalType, ColumnNode, ForeignKeyAction, IndexNode, TableNode } from '../schema/types.js';
5
- import type { ColumnSchema, CreateSchemaOptions, DialectFeatures, DropSchemaOptions, EntityMeta, FieldMeta, FieldOptions, ForeignKeySchema, IndexSchema, NamingStrategy, SchemaDiff, SchemaGenerator, SqlDdlGenerator, Type } from '../type/index.js';
5
+ import type { ColumnSchema, CreateSchemaOptions, DialectFeatures, DropSchemaOptions, EntityMeta, FieldMeta, FieldOptions, ForeignKeySchema, IndexSchema, MigratorDialect, NamingStrategy, SchemaDiff, SchemaGenerator, SqlDdlGenerator, Type } from '../type/index.js';
6
6
  import type { FullColumnDefinition, TableDefinition } from './builder/types.js';
7
7
  import { type IndexDdl, type TableDdl } from './ddl/index.js';
8
8
  /**
@@ -46,7 +46,7 @@ export declare class SqlSchemaGenerator implements SqlDdlGenerator {
46
46
  protected columnSqlType(col: ColumnNode): string;
47
47
  protected canonicalTypeToSql(type: CanonicalType): string;
48
48
  /** The entity side as an AST, carrying this generator's default referential action. */
49
- buildAST(entities: readonly Type<unknown>[]): SchemaAST;
49
+ buildAST(entities: readonly Type<object>[]): SchemaAST;
50
50
  /**
51
51
  * Every `CREATE TABLE` for `entities`, then their foreign keys.
52
52
  *
@@ -56,14 +56,14 @@ export declare class SqlSchemaGenerator implements SqlDdlGenerator {
56
56
  * then `createForeignKeys()`). SQLite is the exception and keeps them inline: it cannot `ALTER` a
57
57
  * foreign key in, but it resolves targets lazily, so a forward reference is fine there.
58
58
  */
59
- generateCreateSchema(entities: readonly Type<unknown>[], options?: CreateSchemaOptions): string[];
59
+ generateCreateSchema(entities: readonly Type<object>[], options?: CreateSchemaOptions): string[];
60
60
  /**
61
61
  * One statement per distinct schema the tables being created live in, in first-seen order. Only
62
62
  * the tables actually being created, so a narrowed `only` does not declare namespaces it is not
63
63
  * about to fill. Empty on an engine without schemas, whose tables are never qualified.
64
64
  */
65
65
  private generateCreateSchemas;
66
- generateDropSchema(entities: readonly Type<unknown>[], options?: DropSchemaOptions): string[];
66
+ generateDropSchema(entities: readonly Type<object>[], options?: DropSchemaOptions): string[];
67
67
  /**
68
68
  * The tables of `entities` in dependency order, optionally narrowed to `only`. The AST always spans
69
69
  * every entity even when narrowed, so a relation pointing at a table outside the subset still
@@ -132,7 +132,7 @@ export declare class SqlSchemaGenerator implements SqlDdlGenerator {
132
132
  * longer disagree about what has changed. Only two things are this side's own: the entity becomes a
133
133
  * table node first, and types are compared as the *engine* would store them - see `normalizeType`.
134
134
  */
135
- diffSchema<E>(entity: Type<E>, currentTable: TableNode | undefined, desiredAst?: SchemaAST): SchemaDiff | undefined;
135
+ diffSchema(entity: Type<object>, currentTable: TableNode | undefined, desiredAst?: SchemaAST): SchemaDiff | undefined;
136
136
  /**
137
137
  * Indexes the entity declares that the table does not already have, in any shape.
138
138
  *
@@ -217,9 +217,9 @@ export declare class SqlSchemaGenerator implements SqlDdlGenerator {
217
217
  * other way and the table is created under one name and compared under another, which reports every
218
218
  * table of a project using a naming strategy as both missing and unexpected.
219
219
  */
220
- export declare function buildEntityAST(generator: Pick<SchemaGenerator, 'resolveTableAlias' | 'resolveSchema' | 'resolveColumnName'>, entities: readonly Type<unknown>[], defaultForeignKeyAction?: ForeignKeyAction): SchemaAST;
220
+ export declare function buildEntityAST(generator: Pick<SchemaGenerator, 'resolveTableAlias' | 'resolveSchema' | 'resolveColumnName'>, entities: readonly Type<object>[], defaultForeignKeyAction?: ForeignKeyAction): SchemaAST;
221
221
  /**
222
222
  * Synchronous factory for SQL schema generators only.
223
223
  * For MongoDB, use `createSchemaGeneratorAsync` from `./schemaGeneratorAsync.js` so the optional `mongodb` peer is not loaded at import time.
224
224
  */
225
- export declare function createSchemaGenerator(dialect: AbstractDialect, defaultForeignKeyAction?: ForeignKeyAction): SqlSchemaGenerator | undefined;
225
+ export declare function createSchemaGenerator(dialect: MigratorDialect, defaultForeignKeyAction?: ForeignKeyAction): SqlSchemaGenerator | undefined;
@@ -1,6 +1,5 @@
1
- import { AbstractSqlDialect } from '../dialect/index.js';
2
1
  import { getMeta, soleIdOf } from '../entity/index.js';
3
- import { areTypesEqual, canonicalToSql, engineType, fieldOptionsToCanonical, isVectorCategory, } from '../schema/canonicalType.js';
2
+ import { canonicalToSql, engineType, fieldOptionsToCanonical, isVectorCategory } from '../schema/canonicalType.js';
4
3
  import { indexSignature } from '../schema/indexDifferences.js';
5
4
  import { buildSchemaAST } from '../schema/schemaASTBuilder.js';
6
5
  import { diffRelationshipNodes, diffTable } from '../schema/schemaASTDiffer.js';
@@ -543,8 +542,10 @@ export class SqlSchemaGenerator {
543
542
  }
544
543
  statements.push(createSql);
545
544
  statements.push(...this.generateCommentStatements(table));
545
+ // A table created only if missing creates its indexes the same way, or re-creating a schema fails on the first.
546
+ const indexOptions = { ifNotExists: !!options.ifNotExists && this.features.indexIfNotExists };
546
547
  for (const idx of table.indexes) {
547
- statements.push(this.generateCreateIndexFromNode(idx));
548
+ statements.push(this.generateCreateIndexFromNode(idx, indexOptions));
548
549
  }
549
550
  return statements;
550
551
  }
@@ -726,8 +727,5 @@ export function buildEntityAST(generator, entities, defaultForeignKeyAction) {
726
727
  * For MongoDB, use `createSchemaGeneratorAsync` from `./schemaGeneratorAsync.js` so the optional `mongodb` peer is not loaded at import time.
727
728
  */
728
729
  export function createSchemaGenerator(dialect, defaultForeignKeyAction) {
729
- if (!(dialect instanceof AbstractSqlDialect)) {
730
- return undefined;
731
- }
732
- return new SqlSchemaGenerator(dialect, defaultForeignKeyAction);
730
+ return dialect.dialectName === 'mongodb' ? undefined : new SqlSchemaGenerator(dialect, defaultForeignKeyAction);
733
731
  }
@@ -1,8 +1,7 @@
1
- import type { AbstractDialect } from '../dialect/abstractDialect.js';
2
1
  import type { ForeignKeyAction } from '../schema/types.js';
3
- import type { SchemaGenerator } from '../type/index.js';
2
+ import type { MigratorDialect, SchemaGenerator } from '../type/index.js';
4
3
  /**
5
4
  * Async factory for schema generators. Use this for MongoDB so the optional peer
6
5
  * `mongodb` is only loaded when this path runs. SQL dialects delegate to {@link createSchemaGenerator}.
7
6
  */
8
- export declare function createSchemaGeneratorAsync(dialect: AbstractDialect, defaultForeignKeyAction?: ForeignKeyAction): Promise<SchemaGenerator | undefined>;
7
+ export declare function createSchemaGeneratorAsync(dialect: MigratorDialect, defaultForeignKeyAction?: ForeignKeyAction): Promise<SchemaGenerator | undefined>;
@@ -65,16 +65,18 @@ export declare class MongoDialect extends AbstractDialect {
65
65
  */
66
66
  private appendRelationLookup;
67
67
  /**
68
- * The correlated `$lookup` for one relation, as `temp`: through its junction for a ManyToMany, or
69
- * straight at the target otherwise. `tail` decides what the lookup leaves behind - a row to test
70
- * for existence, or a `$count` - so a filter and an ordering build the same stage.
68
+ * The correlated `$lookup` for the target rows of one relation `where` narrows, as `temp`: straight at
69
+ * the target, or for a many-to-many from inside its junction's rows. The caller's filter bypass is not
70
+ * passed down, as on the SQL dialects. `tail` decides what the lookup leaves behind - a row to test for
71
+ * existence, or a `$count` - so a filter and an ordering build the same stage.
71
72
  */
72
73
  private relationLookup;
73
74
  /**
74
- * ManyToMany counts/tests junction rows, so the target is reached from inside the junction's own
75
- * lookup - the junction's filters apply too, since a soft-deleted link is not a link.
75
+ * The junction a many-to-many reaches its targets through: the lookup keys matching a parent's rows of
76
+ * it, its own filters, since a soft-deleted link is not a link, and the field holding each target's id.
77
+ * Each end is one field matched against one `_id`, so both sides must be sole-keyed.
76
78
  */
77
- private junctionLookup;
79
+ private junctionOf;
78
80
  /**
79
81
  * Compares the looked-up row count, which is `[{ n: <count> }]` or `[]` when nothing matched - hence
80
82
  * the `$ifNull` fallback to 0, so `{ $size: 0 }` matches parents with no related row at all.
@@ -99,7 +101,7 @@ export declare class MongoDialect extends AbstractDialect {
99
101
  protected mapTableNameRow(row: {
100
102
  table_name: string;
101
103
  }): string;
102
- /** String operators → { pattern: (v) => regex, caseInsensitive } */
104
+ /** String operators -> { pattern: (v) => regex, caseInsensitive } */
103
105
  private static readonly REGEX_OP_MAP;
104
106
  /** MongoDB native operators - pass through as-is. */
105
107
  private static readonly NATIVE_OPS;
@@ -127,14 +129,30 @@ export declare class MongoDialect extends AbstractDialect {
127
129
  * per parent, and the `$set` that lifts the tally onto the document as the field the `$sort` then
128
130
  * orders by. A parent with no related row gets no lookup result at all, which is a zero.
129
131
  */
130
- sortCountStages<E extends Document>(entity: Type<E>, sort: QuerySortMap<E> | undefined, opts?: QueryOptions): {
132
+ sortCountStages<E extends Document>(entity: Type<E>, sort: QuerySortMap<E> | undefined): {
131
133
  readonly stages: MongoAggregationPipelineEntry<Document>[];
132
134
  readonly fields: string[];
133
135
  };
136
+ /** The correlated lookup counting a relation's rows, which `where` narrows, into `temp`. */
137
+ private tallyLookup;
138
+ /** The tally a lookup left in `temp`, which holds no row at all where nothing matched: a zero. */
139
+ private tally;
140
+ /**
141
+ * The lookups reading each to-many a query populates, and the tally of each `$count`, onto the fields
142
+ * its rows answer under, and the fields they parked a junction's pairings or a tally on taken back out.
143
+ * [The design](../../../../architecture/relations-in-one-statement.md).
144
+ */
145
+ private relationReadStages;
146
+ /**
147
+ * A to-many's rows as a lookup running their own read, whose filters, ordering and page apply per
148
+ * parent inside it. A many-to-many reads its targets, each once, by the ids its junction pairs the
149
+ * parent with, parked in a temporary field of the parent's.
150
+ */
151
+ private toManyLookup;
134
152
  /** Whether a `$sort` reads a relation, which is what forces the lookups to run before it. */
135
153
  sortsRelations<E extends Document>(entity: Type<E>, sort: QuerySortMap<E> | undefined): boolean;
136
154
  /**
137
- * Aggregate results are keyed by `$group`/`$agg` alias rather than by column, so an aggregate
155
+ * Aggregate results are keyed by `$group`/`$select` alias rather than by column, so an aggregate
138
156
  * `$sort` addresses those aliases as-is - the same reason the SQL dialects sort by alias there.
139
157
  */
140
158
  private aliasSort;
@@ -152,7 +170,7 @@ export declare class MongoDialect extends AbstractDialect {
152
170
  * Shared by the plain pipeline and the `$vectorSearch` one, which each used to spell the order out
153
171
  * for themselves and each got a different part of it wrong.
154
172
  */
155
- readStages<E extends Document>(entity: Type<E>, q: Query<E>, opts?: QueryOptions, extra?: MongoReadStages): MongoAggregationPipelineEntry<Document>[];
173
+ readStages<E extends Document>(entity: Type<E>, q: Query<E>, extra?: MongoReadStages): MongoAggregationPipelineEntry<Document>[];
156
174
  /**
157
175
  * `$distinct` as a `$group` on the columns the query projects - the same set a SQL dialect puts
158
176
  * after `SELECT DISTINCT` - and the `$replaceRoot` that lifts the grouped key back to the top
@@ -162,16 +180,11 @@ export declare class MongoDialect extends AbstractDialect {
162
180
  private distinctStages;
163
181
  /**
164
182
  * The scalar projection a narrowing query asks for, widened by what the pipeline itself produced:
165
- * the joined documents, and the `_id` a to-many fill groups children by. It goes last, after the
166
- * lookups have read the join keys - projecting any earlier is what used to leave `$populate`
167
- * empty, and is why the pipeline emitted no projection at all and returned every column.
183
+ * each populated relation and the tallies. It goes last, after the lookups have read the join keys -
184
+ * projecting any earlier is what used to leave `$populate` empty, and is why the pipeline emitted no
185
+ * projection at all and returned every column.
168
186
  */
169
187
  pipelineProjection<E extends Document>(entity: Type<E>, q: Query<E>): Record<string, 0 | 1> | undefined;
170
- /**
171
- * `$lookup`/`$unwind` stages for the joinable relations a query populates. Shared by the plain
172
- * aggregation pipeline and the `$vectorSearch` one, so relations load the same way in both.
173
- */
174
- relationStages<E extends Document>(entity: Type<E>, q: Query<E>, opts?: QueryOptions): MongoAggregationPipelineEntry<E>[];
175
188
  /**
176
189
  * The `$lookup`/`$unwind` pair for each relation joined below `parent`, its own relations nested
177
190
  * inside its pipeline and resolved before the projection that reads them.