@prisma-next/mongo-query-builder 0.5.0-dev.53 → 0.5.0-dev.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,147 +1,10 @@
1
1
  import { AggregateCommand, AnyMongoCommand, DeleteManyCommand, DeleteOneCommand, DeleteResult, DeleteResult as DeleteResult$1, FindOneAndDeleteCommand, FindOneAndUpdateCommand, InsertManyCommand, InsertManyResult, InsertManyResult as InsertManyResult$1, InsertOneCommand, InsertOneResult, InsertOneResult as InsertOneResult$1, MongoAggAccumulator, MongoAggExpr, MongoDensifyRange, MongoFieldShape, MongoFillOutput, MongoFilterExpr, MongoPipelineStage, MongoQueryPlan, MongoResultShape, MongoUpdatePipelineStage, MongoWindowField, UpdateManyCommand, UpdateOneCommand, UpdateResult, UpdateResult as UpdateResult$1 } from "@prisma-next/mongo-query-ast/execution";
2
- import { ExtractMongoCodecTypes, MongoContract, MongoContractWithTypeMaps, MongoModelDefinition, MongoTypeMaps } from "@prisma-next/mongo-contract";
2
+ import { ExtractMongoCodecTypes, ExtractMongoTypeMaps, InferModelRow, MongoContract, MongoContractWithTypeMaps, MongoModelDefinition, MongoTypeMaps } from "@prisma-next/mongo-contract";
3
3
  import { MongoValue } from "@prisma-next/mongo-value";
4
4
  import { ContractField } from "@prisma-next/contract/types";
5
5
 
6
- //#region src/types.d.ts
7
- interface DocField {
8
- readonly codecId: string;
9
- readonly nullable: boolean;
10
- }
11
- type NumericField = {
12
- readonly codecId: 'mongo/double@1';
13
- readonly nullable: false;
14
- };
15
- type NullableNumericField = {
16
- readonly codecId: 'mongo/double@1';
17
- readonly nullable: true;
18
- };
19
- type StringField = {
20
- readonly codecId: 'mongo/string@1';
21
- readonly nullable: false;
22
- };
23
- type ArrayField = {
24
- readonly codecId: 'mongo/array@1';
25
- readonly nullable: false;
26
- };
27
- type BooleanField = {
28
- readonly codecId: 'mongo/bool@1';
29
- readonly nullable: false;
30
- };
31
- type DateField = {
32
- readonly codecId: 'mongo/date@1';
33
- readonly nullable: false;
34
- };
35
- type NullableDocField = {
36
- readonly codecId: string;
37
- readonly nullable: true;
38
- };
39
- type LiteralValue<F extends DocField> = F extends StringField ? string : F extends NumericField ? number : F extends BooleanField ? boolean : F extends DateField ? Date : unknown;
40
- type DocShape = Record<string, DocField>;
41
- type ExtractCodecId<F> = F extends {
42
- type: {
43
- kind: 'scalar';
44
- codecId: infer C;
45
- };
46
- } ? C : F extends {
47
- codecId: infer C extends string;
48
- } ? C : string;
49
- type ModelToDocShape<TContract extends MongoContract, ModelName extends string & keyof TContract['models']> = { [K in keyof TContract['models'][ModelName]['fields'] & string]: {
50
- readonly codecId: ExtractCodecId<TContract['models'][ModelName]['fields'][K]>;
51
- readonly nullable: TContract['models'][ModelName]['fields'][K]['nullable'];
52
- } };
53
- type ResolveRow<Shape extends DocShape, CodecTypes extends Record<string, {
54
- readonly output: unknown;
55
- }>> = { -readonly [K in keyof Shape & string]: Shape[K]['codecId'] extends keyof CodecTypes ? Shape[K]['nullable'] extends true ? CodecTypes[Shape[K]['codecId']]['output'] | null : CodecTypes[Shape[K]['codecId']]['output'] : unknown };
56
- interface TypedAggExpr<F extends DocField> {
57
- readonly _field: F;
58
- readonly node: MongoAggExpr;
59
- }
60
- interface TypedAccumulatorExpr<F extends DocField> {
61
- readonly _field: F;
62
- readonly node: MongoAggAccumulator;
63
- }
64
- type ExtractDocShape<T extends Record<string, TypedAggExpr<DocField>>> = { [K in keyof T & string]: T[K]['_field'] };
65
- type SortSpec<S extends DocShape> = Partial<Record<keyof S & string, 1 | -1>>;
66
- type ProjectedShape<Shape extends DocShape, Spec extends Record<string, 1 | TypedAggExpr<DocField>>> = { [K in keyof Spec & string]: Spec[K] extends 1 ? K extends keyof Shape ? Shape[K] : DocField : Spec[K] extends TypedAggExpr<infer F> ? F : DocField } & ('_id' extends keyof Shape ? '_id' extends keyof Spec ? Record<keyof never, never> : Pick<Shape, '_id'> : Record<keyof never, never>);
67
- type GroupSpec = {
68
- _id: TypedAggExpr<DocField> | null;
69
- [key: string]: TypedAggExpr<DocField> | TypedAccumulatorExpr<DocField> | null;
70
- };
71
- type GroupedDocShape<Spec extends GroupSpec> = { [K in keyof Spec & string]: Spec[K] extends TypedAggExpr<infer F> ? F : Spec[K] extends TypedAccumulatorExpr<infer F> ? F : Spec[K] extends null ? {
72
- readonly codecId: 'mongo/null@1';
73
- readonly nullable: true;
74
- } : DocField };
75
- /**
76
- * Intentionally identity — full array element type extraction is deferred.
77
- * Used by `UnwoundShape` so the unwind result shape can be refined later
78
- * without changing the public API.
79
- */
80
- type UnwrapArrayDocField<F extends DocField> = F;
81
- type UnwoundShape<S extends DocShape, K$1 extends keyof S & string> = { [P in keyof S & string]: P extends K$1 ? UnwrapArrayDocField<S[P]> : S[P] };
82
- //#endregion
83
- //#region src/accumulator-helpers.d.ts
84
- declare const acc: {
85
- sum<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<F>;
86
- avg(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
87
- min<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
88
- readonly codecId: F["codecId"];
89
- readonly nullable: true;
90
- }>;
91
- max<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
92
- readonly codecId: F["codecId"];
93
- readonly nullable: true;
94
- }>;
95
- first<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
96
- readonly codecId: F["codecId"];
97
- readonly nullable: true;
98
- }>;
99
- last<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
100
- readonly codecId: F["codecId"];
101
- readonly nullable: true;
102
- }>;
103
- push(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<ArrayField>;
104
- addToSet(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<ArrayField>;
105
- count(): TypedAccumulatorExpr<NumericField>;
106
- stdDevPop(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
107
- stdDevSamp(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
108
- firstN(args: {
109
- input: TypedAggExpr<DocField>;
110
- n: TypedAggExpr<NumericField>;
111
- }): TypedAccumulatorExpr<ArrayField>;
112
- lastN(args: {
113
- input: TypedAggExpr<DocField>;
114
- n: TypedAggExpr<NumericField>;
115
- }): TypedAccumulatorExpr<ArrayField>;
116
- maxN(args: {
117
- input: TypedAggExpr<DocField>;
118
- n: TypedAggExpr<NumericField>;
119
- }): TypedAccumulatorExpr<ArrayField>;
120
- minN(args: {
121
- input: TypedAggExpr<DocField>;
122
- n: TypedAggExpr<NumericField>;
123
- }): TypedAccumulatorExpr<ArrayField>;
124
- top(args: {
125
- output: TypedAggExpr<DocField>;
126
- sortBy: Readonly<Record<string, 1 | -1>>;
127
- }): TypedAccumulatorExpr<DocField>;
128
- bottom(args: {
129
- output: TypedAggExpr<DocField>;
130
- sortBy: Readonly<Record<string, 1 | -1>>;
131
- }): TypedAccumulatorExpr<DocField>;
132
- topN(args: {
133
- output: TypedAggExpr<DocField>;
134
- sortBy: Readonly<Record<string, 1 | -1>>;
135
- n: TypedAggExpr<NumericField>;
136
- }): TypedAccumulatorExpr<ArrayField>;
137
- bottomN(args: {
138
- output: TypedAggExpr<DocField>;
139
- sortBy: Readonly<Record<string, 1 | -1>>;
140
- n: TypedAggExpr<NumericField>;
141
- }): TypedAccumulatorExpr<ArrayField>;
142
- };
143
- //#endregion
144
6
  //#region src/resolve-path.d.ts
7
+
145
8
  /**
146
9
  * Marker `DocField` variant representing a non-leaf (value-object) path in
147
10
  * a [NestedDocShape]. Extends `DocField` with a `fields` property carrying
@@ -163,6 +26,57 @@ interface ObjectField<N$1 extends NestedDocShape> extends DocField {
163
26
  readonly nullable: boolean;
164
27
  readonly fields: N$1;
165
28
  }
29
+ /**
30
+ * Marker `DocField` variant representing "an array of foreign-model rows"
31
+ * — the result of a `$lookup` whose foreign side was selected via the
32
+ * typed `col` accessor. `ModelName` is the literal foreign model name
33
+ * (e.g. `'User'`), preserved in the type so `ResolveRow` can resolve the
34
+ * field to `ResolveRow<ModelToDocShape<TC, ModelName>, …>[]` rather than
35
+ * the opaque `unknown[]` produced by the legacy `mongo/array@1` sentinel.
36
+ *
37
+ * Like `ObjectField`, the codec id is a purely type-level sentinel —
38
+ * there is no runtime codec entry for `'prisma/modelArray@1'`. The
39
+ * surrounding pipeline emits the standard `MongoLookupStage` whose
40
+ * runtime shape is unchanged; the marker exists solely to thread the
41
+ * foreign element type through the result-row resolver.
42
+ */
43
+ interface ModelArrayField<ModelName$1 extends string> extends DocField {
44
+ readonly codecId: 'prisma/modelArray@1';
45
+ readonly nullable: false;
46
+ readonly model: ModelName$1;
47
+ }
48
+ /**
49
+ * Phantom-symbol brand placed on `ModelToDocShape`'s output (and inherited
50
+ * through shape-extending stages like `addFields`, `match`, `lookup`) so
51
+ * `ResolveRow` can route value-object resolution through `InferModelRow`
52
+ * — which walks the contract's `valueObjects` registry and resolves
53
+ * nested types — instead of falling through the codec-lookup branch to
54
+ * `unknown`.
55
+ *
56
+ * The brand is keyed on a `unique symbol` rather than a string so it is
57
+ * invisible to every `keyof Shape & string` walk in the package
58
+ * (`SortSpec`, `ProjectedShape`, `GroupedDocShape`, the field accessor's
59
+ * `Object.keys` iteration, etc.). Field accessors do not surface a
60
+ * `__modelOrigin` autocomplete entry; sorts cannot key on it; projections
61
+ * cannot reference it.
62
+ *
63
+ * Shape-extending stages preserve the brand because intersection types
64
+ * (`Shape & NewFields`) carry through symbol-keyed properties. Shape-
65
+ * replacing stages (`replaceRoot`, `group`, `project`) construct fresh
66
+ * `DocShape`s from scratch, naturally dropping the brand — which is the
67
+ * intended behaviour, since those stages legitimately leave model
68
+ * territory.
69
+ */
70
+ declare const ModelOriginBrand: unique symbol;
71
+ type ModelOriginBrand = typeof ModelOriginBrand;
72
+ /**
73
+ * Brand carrier — a Shape whose row type should be resolved via
74
+ * `InferModelRow<TContract, ModelName>` rather than the per-field codec
75
+ * walk. Use as `ModelToDocShape<TC, ModelName> & ModelOriginBranded<ModelName>`.
76
+ */
77
+ type ModelOriginBranded<ModelName$1 extends string> = {
78
+ readonly [ModelOriginBrand]?: ModelName$1;
79
+ };
166
80
  /**
167
81
  * Document shape that carries nested value-object sub-shapes.
168
82
  *
@@ -255,7 +169,7 @@ type VONestedShape<TContract extends ContractHasValueObjects, VOName$1 extends s
255
169
  * literal field record collapses `keyof` to `string` and the result hover
256
170
  * degrades to `{ readonly [x: string]: any }`.
257
171
  */
258
- type ModelNestedShape<TContract extends MongoContract, ModelName extends string & keyof TContract['models']> = { readonly [K in keyof TContract['models'][ModelName]['fields'] & string]: TranslateField<TContract & ContractHasValueObjects, TContract['models'][ModelName]['fields'][K]> };
172
+ type ModelNestedShape<TContract extends MongoContract, ModelName$1 extends string & keyof TContract['models']> = { readonly [K in keyof TContract['models'][ModelName$1]['fields'] & string]: TranslateField<TContract & ContractHasValueObjects, TContract['models'][ModelName$1]['fields'][K]> };
259
173
  /**
260
174
  * Resolve a dot-path against a `NestedDocShape`. Returns:
261
175
  * - the leaf `DocField` when `Path` terminates on a scalar/array leaf,
@@ -297,6 +211,208 @@ type ValidPaths<N$1 extends NestedDocShape> = string extends keyof N$1 ? never :
297
211
  */
298
212
  type PathCompletions<N$1 extends NestedDocShape> = ValidPaths<N$1>;
299
213
  //#endregion
214
+ //#region src/types.d.ts
215
+ interface DocField {
216
+ readonly codecId: string;
217
+ readonly nullable: boolean;
218
+ }
219
+ type NumericField = {
220
+ readonly codecId: 'mongo/double@1';
221
+ readonly nullable: false;
222
+ };
223
+ type NullableNumericField = {
224
+ readonly codecId: 'mongo/double@1';
225
+ readonly nullable: true;
226
+ };
227
+ type StringField = {
228
+ readonly codecId: 'mongo/string@1';
229
+ readonly nullable: false;
230
+ };
231
+ type ArrayField = {
232
+ readonly codecId: 'mongo/array@1';
233
+ readonly nullable: false;
234
+ };
235
+ type BooleanField = {
236
+ readonly codecId: 'mongo/bool@1';
237
+ readonly nullable: false;
238
+ };
239
+ type DateField = {
240
+ readonly codecId: 'mongo/date@1';
241
+ readonly nullable: false;
242
+ };
243
+ type NullableDocField = {
244
+ readonly codecId: string;
245
+ readonly nullable: true;
246
+ };
247
+ type LiteralValue<F extends DocField> = F extends StringField ? string : F extends NumericField ? number : F extends BooleanField ? boolean : F extends DateField ? Date : unknown;
248
+ type DocShape = Record<string, DocField>;
249
+ type ExtractCodecId<F> = F extends {
250
+ type: {
251
+ kind: 'scalar';
252
+ codecId: infer C;
253
+ };
254
+ } ? C : F extends {
255
+ codecId: infer C extends string;
256
+ } ? C : string;
257
+ type ModelToDocShape<TContract extends MongoContract, ModelName$1 extends string & keyof TContract['models']> = { [K in keyof TContract['models'][ModelName$1]['fields'] & string]: {
258
+ readonly codecId: ExtractCodecId<TContract['models'][ModelName$1]['fields'][K]>;
259
+ readonly nullable: TContract['models'][ModelName$1]['fields'][K]['nullable'];
260
+ } } & ModelOriginBranded<ModelName$1>;
261
+ /**
262
+ * Per-field resolver. Walks `Shape`'s string keys, routing
263
+ * `ModelArrayField` (the lookup marker) through `InferModelRow` and
264
+ * everything else through the codec-lookup branch.
265
+ *
266
+ * Internal helper — public callers should use `ResolveRow`, which adds
267
+ * the model-origin brand detection on top.
268
+ */
269
+ type ResolveFields<Shape extends DocShape, CodecTypes extends Record<string, {
270
+ readonly output: unknown;
271
+ }>, TContract extends MongoContract> = { -readonly [K in keyof Shape & string]: Shape[K] extends ModelArrayField<infer ModelName> ? IsConcreteContract<TContract> extends true ? TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps> ? ModelName extends string & keyof TContract['models'] ? Array<InferModelRow<TContract, ModelName>> : unknown[] : unknown[] : unknown[] : Shape[K]['codecId'] extends keyof CodecTypes ? Shape[K]['nullable'] extends true ? CodecTypes[Shape[K]['codecId']]['output'] | null : CodecTypes[Shape[K]['codecId']]['output'] : unknown };
272
+ /**
273
+ * Resolve a `DocShape` to a concrete row object type.
274
+ *
275
+ * The optional `TContract` parameter exists so the resolver can:
276
+ *
277
+ * 1. Detect the `ModelOriginBrand` on `Shape` — the phantom symbol
278
+ * placed by `ModelToDocShape`. When present (and the contract has
279
+ * type maps), the row is resolved via `InferModelRow<TC, M>` from
280
+ * `@prisma-next/mongo-contract`, which walks scalar / valueObject /
281
+ * union field kinds (handling nested value-objects and `many: true`).
282
+ * This makes entry-point reads (`q.from('users').build()`) and
283
+ * shape-extending stages (`match`, `addFields`) resolve value-object
284
+ * fields to their concrete nested types instead of `unknown`.
285
+ *
286
+ * 2. Detect the per-field `ModelArrayField<ModelName>` marker produced
287
+ * by `lookup()` and resolve it to `Array<InferModelRow<TC, M>>` so
288
+ * lookup rows carry the same fully-typed foreign rows.
289
+ *
290
+ * When the contract is not threaded through (or lacks the type-map
291
+ * phantom), both branches fall back to `unknown` / `unknown[]` —
292
+ * preserving the legacy resolver shape for call sites that do not need
293
+ * model-row resolution.
294
+ */
295
+ /**
296
+ * Flatten an intersection `A & B` into a single object literal so callers
297
+ * (and `expectTypeOf().toEqualTypeOf<…>()`) see one homogeneous record
298
+ * rather than the intersection form. Vitest's strict equality check
299
+ * treats `A & B` as distinct from the structurally-equivalent flat
300
+ * record, even when assignability is bidirectional, so the
301
+ * `ResolveRow` brand-positive branch normalises its result through this.
302
+ */
303
+ type Flatten<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
304
+ /**
305
+ * Decide whether to route a brand-positive `ResolveRow` through
306
+ * `InferModelRow`. The default `MongoContract` (no concrete models)
307
+ * still satisfies `MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>`
308
+ * because the phantom key is optional, but `InferModelRow<MongoContract, …>`
309
+ * collapses to an empty/unknown row. Gate on the presence of the
310
+ * type-maps phantom: a concrete contract attaches concrete `TestTypeMaps`-
311
+ * shaped maps, while the default `MongoContract` has no phantom and
312
+ * `ExtractMongoTypeMaps` resolves to `never`.
313
+ */
314
+ type IsConcreteContract<TContract> = [ExtractMongoTypeMaps<TContract>] extends [never] ? false : true;
315
+ type ResolveRow<Shape extends DocShape, CodecTypes extends Record<string, {
316
+ readonly output: unknown;
317
+ }>, TContract extends MongoContract = MongoContract> = Shape extends {
318
+ readonly [ModelOriginBrand]?: infer ModelName extends string;
319
+ } ? IsConcreteContract<TContract> extends true ? TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps> ? ModelName extends string & keyof TContract['models'] ? Flatten<InferModelRow<TContract, ModelName> & Omit<ResolveFields<Shape, CodecTypes, TContract>, keyof InferModelRow<TContract, ModelName>>> : ResolveFields<Shape, CodecTypes, TContract> : ResolveFields<Shape, CodecTypes, TContract> : ResolveFields<Shape, CodecTypes, TContract> : ResolveFields<Shape, CodecTypes, TContract>;
320
+ interface TypedAggExpr<F extends DocField> {
321
+ readonly _field: F;
322
+ readonly node: MongoAggExpr;
323
+ }
324
+ interface TypedAccumulatorExpr<F extends DocField> {
325
+ readonly _field: F;
326
+ readonly node: MongoAggAccumulator;
327
+ }
328
+ type ExtractDocShape<T extends Record<string, TypedAggExpr<DocField>>> = { [K in keyof T & string]: T[K]['_field'] };
329
+ type SortSpec<S extends DocShape> = Partial<Record<keyof S & string, 1 | -1>>;
330
+ type ProjectedShape<Shape extends DocShape, Spec extends Record<string, 1 | TypedAggExpr<DocField>>> = { [K in keyof Spec & string]: Spec[K] extends 1 ? K extends keyof Shape ? Shape[K] : DocField : Spec[K] extends TypedAggExpr<infer F> ? F : DocField } & ('_id' extends keyof Shape ? '_id' extends keyof Spec ? Record<keyof never, never> : Pick<Shape, '_id'> : Record<keyof never, never>);
331
+ type GroupSpec = {
332
+ _id: TypedAggExpr<DocField> | null;
333
+ [key: string]: TypedAggExpr<DocField> | TypedAccumulatorExpr<DocField> | null;
334
+ };
335
+ type GroupedDocShape<Spec extends GroupSpec> = { [K in keyof Spec & string]: Spec[K] extends TypedAggExpr<infer F> ? F : Spec[K] extends TypedAccumulatorExpr<infer F> ? F : Spec[K] extends null ? {
336
+ readonly codecId: 'mongo/null@1';
337
+ readonly nullable: true;
338
+ } : DocField };
339
+ /**
340
+ * Intentionally identity — full array element type extraction is deferred.
341
+ * Used by `UnwoundShape` so the unwind result shape can be refined later
342
+ * without changing the public API.
343
+ */
344
+ type UnwrapArrayDocField<F extends DocField> = F;
345
+ /**
346
+ * `$unwind` reshapes the array slot but leaves the rest of the document
347
+ * structurally intact. The mapped iteration is keyed on `keyof S & string`,
348
+ * which discards the symbol-keyed `ModelOriginBrand` carried by
349
+ * model-rooted shapes. Preserve the brand explicitly so post-unwind
350
+ * `ResolveRow` still routes through `InferModelRow` and value-object
351
+ * fields keep their concrete nested types.
352
+ */
353
+ type UnwoundShape<S extends DocShape, K$1 extends keyof S & string> = { [P in keyof S & string]: P extends K$1 ? UnwrapArrayDocField<S[P]> : S[P] } & (S extends ModelOriginBranded<infer ModelName extends string> ? ModelOriginBranded<ModelName> : unknown);
354
+ //#endregion
355
+ //#region src/accumulator-helpers.d.ts
356
+ declare const acc: {
357
+ sum<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<F>;
358
+ avg(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
359
+ min<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
360
+ readonly codecId: F["codecId"];
361
+ readonly nullable: true;
362
+ }>;
363
+ max<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
364
+ readonly codecId: F["codecId"];
365
+ readonly nullable: true;
366
+ }>;
367
+ first<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
368
+ readonly codecId: F["codecId"];
369
+ readonly nullable: true;
370
+ }>;
371
+ last<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
372
+ readonly codecId: F["codecId"];
373
+ readonly nullable: true;
374
+ }>;
375
+ push(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<ArrayField>;
376
+ addToSet(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<ArrayField>;
377
+ count(): TypedAccumulatorExpr<NumericField>;
378
+ stdDevPop(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
379
+ stdDevSamp(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
380
+ firstN(args: {
381
+ input: TypedAggExpr<DocField>;
382
+ n: TypedAggExpr<NumericField>;
383
+ }): TypedAccumulatorExpr<ArrayField>;
384
+ lastN(args: {
385
+ input: TypedAggExpr<DocField>;
386
+ n: TypedAggExpr<NumericField>;
387
+ }): TypedAccumulatorExpr<ArrayField>;
388
+ maxN(args: {
389
+ input: TypedAggExpr<DocField>;
390
+ n: TypedAggExpr<NumericField>;
391
+ }): TypedAccumulatorExpr<ArrayField>;
392
+ minN(args: {
393
+ input: TypedAggExpr<DocField>;
394
+ n: TypedAggExpr<NumericField>;
395
+ }): TypedAccumulatorExpr<ArrayField>;
396
+ top(args: {
397
+ output: TypedAggExpr<DocField>;
398
+ sortBy: Readonly<Record<string, 1 | -1>>;
399
+ }): TypedAccumulatorExpr<DocField>;
400
+ bottom(args: {
401
+ output: TypedAggExpr<DocField>;
402
+ sortBy: Readonly<Record<string, 1 | -1>>;
403
+ }): TypedAccumulatorExpr<DocField>;
404
+ topN(args: {
405
+ output: TypedAggExpr<DocField>;
406
+ sortBy: Readonly<Record<string, 1 | -1>>;
407
+ n: TypedAggExpr<NumericField>;
408
+ }): TypedAccumulatorExpr<ArrayField>;
409
+ bottomN(args: {
410
+ output: TypedAggExpr<DocField>;
411
+ sortBy: Readonly<Record<string, 1 | -1>>;
412
+ n: TypedAggExpr<NumericField>;
413
+ }): TypedAccumulatorExpr<ArrayField>;
414
+ };
415
+ //#endregion
300
416
  //#region src/update-ops.d.ts
301
417
  /**
302
418
  * Per-field update operations produced by `Expression`'s update methods
@@ -520,6 +636,89 @@ type FieldAccessor<S extends DocShape, N$1 extends NestedDocShape = Record<strin
520
636
  */
521
637
  declare function createFieldAccessor<S extends DocShape, N$1 extends NestedDocShape = Record<string, never>>(): FieldAccessor<S, N$1>;
522
638
  //#endregion
639
+ //#region src/lookup-builder.d.ts
640
+ /**
641
+ * Resolved foreign-model name for a contract root. Looks `RootName` up
642
+ * through `TContract['roots']` and intersects the result back with
643
+ * `keyof TContract['models']` so it can be used as a `ModelName` index
644
+ * into `models`. Resolves to `never` when the root is not present (this
645
+ * surface should never be reachable through normal use because `from()`
646
+ * constrains its `R` parameter to `keyof TContract['roots']`).
647
+ */
648
+ type ModelOf<TContract extends MongoContract, RootName extends keyof TContract['roots'] & string> = TContract['roots'][RootName] & string & keyof TContract['models'];
649
+ /**
650
+ * Object returned by the user from the `on(...)` callback. Each side is
651
+ * a `LeafExpression` produced by property access on the corresponding
652
+ * `FieldAccessor` (`local._id`, `foreign.customerId`, etc.). Carrying
653
+ * `LeafExpression` rather than the broader `TypedAggExpr` is what makes
654
+ * non-leaf returns (e.g. `fn.toUpper(local._id)`) a compile-time error
655
+ * without per-field operator gating — `LeafExpression` carries `_path`,
656
+ * `TypedAggExpr` does not (see field-accessor.ts L47–L82).
657
+ */
658
+ interface LookupOnResult {
659
+ readonly local: LeafExpression<DocField>;
660
+ readonly foreign: LeafExpression<DocField>;
661
+ }
662
+ /**
663
+ * Marker brand on the captured spec returned by the `lookup(...)`
664
+ * callback. The phantom `_brand` literal lets `PipelineChain.lookup`
665
+ * accept the result of `from(...).on(...).as(...)` without exposing the
666
+ * internal field shape to user code, and prevents accidental
667
+ * construction of a malformed spec by hand.
668
+ */
669
+ type LookupResultBrand = 'mongo-query-builder/lookup-result@1';
670
+ /**
671
+ * Captured output of the inner `from(name).on(cb).as(name)` chain. The
672
+ * contract is consumed by `PipelineChain.lookup` to construct the
673
+ * `MongoLookupStage` (collection name comes from `models[ModelName]
674
+ * .storage.collection`) and to thread `ModelArrayField<ModelName>` into
675
+ * the resulting `Shape` so the resolver yields `Array<ForeignRow>`.
676
+ *
677
+ * Type parameters carry the foreign-root literal `RootName`, the
678
+ * resolved foreign model name `ModelName`, and the `As` literal so
679
+ * `PipelineChain.lookup`'s return type can encode the result-row
680
+ * promotion precisely.
681
+ */
682
+ interface LookupResult<RootName extends string, ModelName$1 extends string, As extends string> {
683
+ readonly _brand: LookupResultBrand;
684
+ readonly _root: RootName;
685
+ readonly _model: ModelName$1;
686
+ readonly _localField: string;
687
+ readonly _foreignField: string;
688
+ readonly _as: As;
689
+ }
690
+ /**
691
+ * Builder returned by `from(name).on(cb)`. Carries the foreign root /
692
+ * model literals plus the captured local / foreign paths, and exposes
693
+ * `.as(name)` to finalise the spec with the user-chosen field name.
694
+ */
695
+ interface LookupBuilderWithKey<RootName extends string, ModelName$1 extends string> {
696
+ as<As extends string>(name: As): LookupResult<RootName, ModelName$1, As>;
697
+ }
698
+ /**
699
+ * Builder returned by `from(name)`. Carries the foreign root / model
700
+ * literals and the local pipeline's `Shape` / nested shape so the
701
+ * `on(...)` callback's `local` and `foreign` accessors are typed
702
+ * narrowly.
703
+ *
704
+ * `on(cb)` runs the user's callback to capture the leaf paths and
705
+ * returns a `LookupBuilderWithKey` that exposes `.as(name)`.
706
+ */
707
+ interface LookupBuilder<TContract extends MongoContract, Shape extends DocShape, Nested extends Record<string, DocField>, RootName extends string, ModelName$1 extends string> {
708
+ on(cb: (local: FieldAccessor<Shape, Nested>, foreign: ModelName$1 extends keyof TContract['models'] & string ? FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>> : never) => LookupOnResult): LookupBuilderWithKey<RootName, ModelName$1>;
709
+ }
710
+ /**
711
+ * Type of the `from` callable passed to `PipelineChain.lookup`'s outer
712
+ * callback. The generic argument is inferred from a string-literal
713
+ * argument (the same pattern as `mongoQuery<TC>(...).from('orders')`),
714
+ * which grounds `RootName` into the returned `LookupBuilder` *before*
715
+ * the inner `on(...)` callback is type-checked. This sequential
716
+ * inference is what makes `foreign` resolve narrowly to the foreign
717
+ * model's `FieldAccessor` (verified in the R1.5 spike — see spec § Open
718
+ * Questions / Resolved decisions).
719
+ */
720
+ type LookupFrom<TContract extends MongoContract, Shape extends DocShape, Nested extends Record<string, DocField>> = <RootName extends keyof TContract['roots'] & string>(name: RootName) => LookupBuilder<TContract, Shape, Nested, RootName, ModelOf<TContract, RootName>>;
721
+ //#endregion
523
722
  //#region src/markers.d.ts
524
723
  /**
525
724
  * Phantom capability markers for `PipelineChain`.
@@ -578,9 +777,9 @@ interface PipelineChainState {
578
777
  * marker table (and rationale per row) in
579
778
  * `docs/architecture docs/adrs/ADR 201 - State-machine pattern for typed DSL builders.md`.
580
779
  */
581
- declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>, Shape extends DocShape, U extends UpdateEnabled = 'update-ok', F extends FindAndModifyEnabled = 'fam-ok', L extends LeadingMatch = 'leading', N$1 extends NestedDocShape = Record<string, never>> {
780
+ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>, Shape extends DocShape, U$1 extends UpdateEnabled = 'update-ok', F extends FindAndModifyEnabled = 'fam-ok', L extends LeadingMatch = 'leading', N$1 extends NestedDocShape = Record<string, never>> {
582
781
  #private;
583
- readonly __updateCompat: U;
782
+ readonly __updateCompat: U$1;
584
783
  readonly __findAndModifyCompat: F;
585
784
  readonly __leadingMatch: L;
586
785
  constructor(contract: TContract, state: PipelineChainState);
@@ -592,8 +791,8 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
592
791
  * `deconstructUpdateChain` can only peel leading `$match` stages into the
593
792
  * wire-command filter.
594
793
  */
595
- match(filter: MongoFilterExpr): PipelineChain<TContract, Shape, L extends 'leading' ? U : 'update-cleared', F, L, N$1>;
596
- match(fn: (fields: FieldAccessor<Shape, N$1>) => MongoFilterExpr): PipelineChain<TContract, Shape, L extends 'leading' ? U : 'update-cleared', F, L, N$1>;
794
+ match(filter: MongoFilterExpr): PipelineChain<TContract, Shape, L extends 'leading' ? U$1 : 'update-cleared', F, L, N$1>;
795
+ match(fn: (fields: FieldAccessor<Shape, N$1>) => MongoFilterExpr): PipelineChain<TContract, Shape, L extends 'leading' ? U$1 : 'update-cleared', F, L, N$1>;
597
796
  /**
598
797
  * `$sort`. Clears `UpdateEnabled` (`update` has no per-document sort) but
599
798
  * preserves `FindAndModifyEnabled` (`findAndModify` has a `sort` slot).
@@ -620,22 +819,21 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
620
819
  * preserved — newly added flat fields are reachable via property access
621
820
  * (`f.newField`) but do not themselves carry nested structure.
622
821
  */
623
- addFields<NewFields extends Record<string, TypedAggExpr<DocField>>>(fn: (fields: FieldAccessor<Shape, N$1>) => NewFields): PipelineChain<TContract, Shape & ExtractDocShape<NewFields>, U, 'fam-cleared', 'past-leading', N$1>;
822
+ addFields<NewFields extends Record<string, TypedAggExpr<DocField>>>(fn: (fields: FieldAccessor<Shape, N$1>) => NewFields): PipelineChain<TContract, Shape & ExtractDocShape<NewFields>, U$1, 'fam-cleared', 'past-leading', N$1>;
624
823
  /**
625
824
  * `$lookup`. Clears both markers — joins are not representable in either
626
825
  * the `update` or `findAndModify` wire commands. The original document's
627
826
  * nested-path shape `N` is preserved (the lookup adds a sidecar array
628
827
  * field; existing keys are untouched).
828
+ *
829
+ * The single callback receives a `from` callable that grounds the
830
+ * foreign-root literal sequentially before the inner `on(...)`
831
+ * callback is type-checked — see `lookup-builder.ts`. The resulting
832
+ * `Shape` gains the `As` key as a `ModelArrayField<ModelName>` so
833
+ * `ResolveRow` produces `Array<ForeignRow>` (with concrete leaf
834
+ * types) instead of the legacy `unknown[]`.
629
835
  */
630
- lookup<ForeignRoot extends keyof TContract['roots'] & string, As extends string>(options: {
631
- from: ForeignRoot;
632
- localField: keyof Shape & string;
633
- foreignField: string;
634
- as: As;
635
- }): PipelineChain<TContract, Shape & Record<As, {
636
- readonly codecId: 'mongo/array@1';
637
- readonly nullable: false;
638
- }>, 'update-cleared', 'fam-cleared', 'past-leading', N$1>;
836
+ lookup<RootName extends string, ModelName$1 extends string, As extends string>(fn: (from: LookupFrom<TContract, Shape, N$1>) => LookupResult<RootName, ModelName$1, As>): PipelineChain<TContract, Shape & Record<As, ModelArrayField<ModelName$1>>, 'update-cleared', 'fam-cleared', 'past-leading', N$1>;
639
837
  /**
640
838
  * `$project`. Preserves `UpdateEnabled` (representable as update-with-pipeline
641
839
  * `$project` / `$unset`); clears `FindAndModifyEnabled` (use `.project()` on
@@ -646,8 +844,8 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
646
844
  * fundamentally rewrites the document, so dot-paths into the *source*
647
845
  * document are no longer meaningful downstream.
648
846
  */
649
- project<K$1 extends keyof Shape & string>(...keys: K$1[]): PipelineChain<TContract, Pick<Shape, K$1 | ('_id' extends keyof Shape ? '_id' : never)>, U, 'fam-cleared', 'past-leading'>;
650
- project<Spec extends Record<string, 1 | TypedAggExpr<DocField>>>(fn: (fields: FieldAccessor<Shape, N$1>) => Spec): PipelineChain<TContract, ProjectedShape<Shape, Spec>, U, 'fam-cleared', 'past-leading'>;
847
+ project<K$1 extends keyof Shape & string>(...keys: K$1[]): PipelineChain<TContract, Pick<Shape, K$1 | ('_id' extends keyof Shape ? '_id' : never)>, U$1, 'fam-cleared', 'past-leading'>;
848
+ project<Spec extends Record<string, 1 | TypedAggExpr<DocField>>>(fn: (fields: FieldAccessor<Shape, N$1>) => Spec): PipelineChain<TContract, ProjectedShape<Shape, Spec>, U$1, 'fam-cleared', 'past-leading'>;
651
849
  /**
652
850
  * `$unwind`. Clears both markers — array unrolling produces multiple output
653
851
  * documents per input, incompatible with both single-document update and
@@ -670,7 +868,7 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
670
868
  * Nested path shape is reset — the replaced root has no relation to
671
869
  * the original document structure.
672
870
  */
673
- replaceRoot<NewShape extends DocShape>(fn: (fields: FieldAccessor<Shape, N$1>) => Expression<DocField> | TypedAggExpr<DocField>): PipelineChain<TContract, NewShape, U, 'fam-cleared', 'past-leading'>;
871
+ replaceRoot<NewShape extends DocShape>(fn: (fields: FieldAccessor<Shape, N$1>) => Expression<DocField> | TypedAggExpr<DocField>): PipelineChain<TContract, NewShape, U$1, 'fam-cleared', 'past-leading'>;
674
872
  count<Field extends string>(field: Field): PipelineChain<TContract, Record<Field, {
675
873
  readonly codecId: 'mongo/double@1';
676
874
  readonly nullable: false;
@@ -686,7 +884,7 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
686
884
  * `$redact`. Preserves `UpdateEnabled`; clears `FindAndModifyEnabled`.
687
885
  * Shape- and nested-path-preserving (the document tree is unchanged).
688
886
  */
689
- redact(fn: (fields: FieldAccessor<Shape, N$1>) => Expression<DocField> | TypedAggExpr<DocField>): PipelineChain<TContract, Shape, U, 'fam-cleared', 'past-leading', N$1>;
887
+ redact(fn: (fields: FieldAccessor<Shape, N$1>) => Expression<DocField> | TypedAggExpr<DocField>): PipelineChain<TContract, Shape, U$1, 'fam-cleared', 'past-leading', N$1>;
690
888
  /**
691
889
  * `$out` write terminal. Materialises the pipeline output into
692
890
  * `collection` (optionally in `db`), replacing any prior contents. Unlike
@@ -818,23 +1016,23 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
818
1016
  * runtime error is thrown as a defensive check (the type system should
819
1017
  * prevent this).
820
1018
  */
821
- findOneAndUpdate(this: PipelineChain<TContract, Shape, U, 'fam-ok', L, N$1>, updaterFn: (fields: FieldAccessor<Shape, N$1>) => UpdaterResult, opts?: {
1019
+ findOneAndUpdate(this: PipelineChain<TContract, Shape, U$1, 'fam-ok', L, N$1>, updaterFn: (fields: FieldAccessor<Shape, N$1>) => UpdaterResult, opts?: {
822
1020
  readonly upsert?: boolean;
823
1021
  readonly returnDocument?: 'before' | 'after';
824
- }): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>> | null, FindOneAndUpdateCommand>;
1022
+ }): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndUpdateCommand>;
825
1023
  /**
826
1024
  * Find a single document matching the accumulated pipeline and delete it.
827
1025
  * Same marker gating and deconstruction as `findOneAndUpdate`.
828
1026
  */
829
- findOneAndDelete(this: PipelineChain<TContract, Shape, U, 'fam-ok', L, N$1>): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>> | null, FindOneAndDeleteCommand>;
1027
+ findOneAndDelete(this: PipelineChain<TContract, Shape, U$1, 'fam-ok', L, N$1>): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndDeleteCommand>;
830
1028
  /**
831
1029
  * Materialise the chain as a `MongoQueryPlan` wrapping an `AggregateCommand`.
832
1030
  */
833
- build(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>>, AggregateCommand>;
1031
+ build(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract>, AggregateCommand>;
834
1032
  /**
835
1033
  * Alias for `build()` — surfaces the read intent at the call site.
836
1034
  */
837
- aggregate(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>>, AggregateCommand>;
1035
+ aggregate(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract>, AggregateCommand>;
838
1036
  }
839
1037
  //#endregion
840
1038
  //#region src/expression-helpers.d.ts
@@ -1016,14 +1214,14 @@ declare const fn: {
1016
1214
  * accidentally produce an unqualified write by forgetting to `.match(...)`
1017
1215
  * later in the chain. Bodies land in M2.
1018
1216
  */
1019
- declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>, ModelName extends keyof TContract['models'] & string> extends PipelineChain<TContract, ModelToDocShape<TContract, ModelName>, 'update-cleared', 'fam-cleared', 'leading', ModelNestedShape<TContract, ModelName>> {
1217
+ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>, ModelName$1 extends keyof TContract['models'] & string> extends PipelineChain<TContract, ModelToDocShape<TContract, ModelName$1>, 'update-cleared', 'fam-cleared', 'leading', ModelNestedShape<TContract, ModelName$1>> {
1020
1218
  #private;
1021
- constructor(ctx: BindingContext<TContract>, modelName: ModelName);
1219
+ constructor(ctx: BindingContext<TContract>, modelName: ModelName$1);
1022
1220
  /**
1023
1221
  * Bound model name. Exposed so type tests can assert the binding without
1024
1222
  * flipping into a pipeline. Not part of the public-API contract.
1025
1223
  */
1026
- get _modelName(): ModelName;
1224
+ get _modelName(): ModelName$1;
1027
1225
  /**
1028
1226
  * Begin accumulating a filter. Transitions to `FilteredCollection`.
1029
1227
  *
@@ -1033,8 +1231,8 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
1033
1231
  * Mongo — but `FilteredCollection` makes the accumulated filter
1034
1232
  * addressable for the write/find-and-modify terminals landing in M2/M3.
1035
1233
  */
1036
- match(filter: MongoFilterExpr): FilteredCollection<TContract, ModelName>;
1037
- match(fn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => MongoFilterExpr): FilteredCollection<TContract, ModelName>;
1234
+ match(filter: MongoFilterExpr): FilteredCollection<TContract, ModelName$1>;
1235
+ match(fn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => MongoFilterExpr): FilteredCollection<TContract, ModelName$1>;
1038
1236
  /**
1039
1237
  * Insert a single document. Document fields are passed straight through to
1040
1238
  * the wire `InsertOneCommand` — codec normalisation happens at the
@@ -1057,7 +1255,7 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
1057
1255
  * unqualified write by forgetting to `.match(...)` first. Pair with
1058
1256
  * `.match(...).updateMany(...)` for the filtered case.
1059
1257
  */
1060
- updateAll(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateManyCommand>;
1258
+ updateAll(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateManyCommand>;
1061
1259
  /**
1062
1260
  * Delete *every* document in the collection. See `updateAll` for the
1063
1261
  * rationale around the unqualified-write surface being limited to this
@@ -1074,7 +1272,7 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
1074
1272
  * new document derived from the filter equality fields plus the update
1075
1273
  * spec when no match is found; otherwise updates the matched document.
1076
1274
  */
1077
- upsertOne(filterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => MongoFilterExpr, updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateOneCommand>;
1275
+ upsertOne(filterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => MongoFilterExpr, updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateOneCommand>;
1078
1276
  }
1079
1277
  /**
1080
1278
  * State reached after one or more `.match(...)` calls on `CollectionHandle`.
@@ -1100,10 +1298,10 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
1100
1298
  * — those are insert or unqualified-write operations that are nonsense
1101
1299
  * after a filter has been applied.
1102
1300
  */
1103
- declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>, ModelName extends keyof TContract['models'] & string> extends PipelineChain<TContract, ModelToDocShape<TContract, ModelName>, 'update-cleared', 'fam-cleared', 'leading', ModelNestedShape<TContract, ModelName>> {
1301
+ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>, ModelName$1 extends keyof TContract['models'] & string> extends PipelineChain<TContract, ModelToDocShape<TContract, ModelName$1>, 'update-cleared', 'fam-cleared', 'leading', ModelNestedShape<TContract, ModelName$1>> {
1104
1302
  #private;
1105
- constructor(ctx: BindingContext<TContract>, modelName: ModelName, filters: ReadonlyArray<MongoFilterExpr>);
1106
- get _modelName(): ModelName;
1303
+ constructor(ctx: BindingContext<TContract>, modelName: ModelName$1, filters: ReadonlyArray<MongoFilterExpr>);
1304
+ get _modelName(): ModelName$1;
1107
1305
  /**
1108
1306
  * Accumulated filter list. Exposed for the M2/M3 write/find-and-modify
1109
1307
  * terminals to splat into wire-command `filter` slots; not part of the
@@ -1117,8 +1315,8 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
1117
1315
  * second `$match` stage), so the write/find-and-modify terminals see a
1118
1316
  * single authoritative filter expression.
1119
1317
  */
1120
- match(filter: MongoFilterExpr): FilteredCollection<TContract, ModelName>;
1121
- match(fn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => MongoFilterExpr): FilteredCollection<TContract, ModelName>;
1318
+ match(filter: MongoFilterExpr): FilteredCollection<TContract, ModelName$1>;
1319
+ match(fn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => MongoFilterExpr): FilteredCollection<TContract, ModelName$1>;
1122
1320
  /**
1123
1321
  * Update every matching document. `updaterFn` receives a `FieldAccessor`
1124
1322
  * and returns an array of `TypedUpdateOp` (e.g. `[f.amount.inc(1),
@@ -1126,14 +1324,14 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
1126
1324
  * update spec by `foldUpdateOps`, which throws on operator+path
1127
1325
  * collisions.
1128
1326
  */
1129
- updateMany(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateManyCommand>;
1327
+ updateMany(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateManyCommand>;
1130
1328
  /**
1131
1329
  * Update at most one matching document. The driver picks the document
1132
1330
  * (typically the first one matched by the underlying scan); no ordering
1133
1331
  * guarantee is implied — chain `.sort(...)` and use the M3
1134
1332
  * `.findOneAndUpdate(...)` terminal when ordering matters.
1135
1333
  */
1136
- updateOne(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateOneCommand>;
1334
+ updateOne(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateOneCommand>;
1137
1335
  /**
1138
1336
  * Delete every matching document.
1139
1337
  */
@@ -1149,7 +1347,7 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
1149
1347
  * `CollectionHandle.upsertOne(f => filter, updaterFn)` but reuses the
1150
1348
  * already-accumulated `.match(...)` filter chain.
1151
1349
  */
1152
- upsertOne(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateOneCommand>;
1350
+ upsertOne(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => UpdaterResult): MongoQueryPlan<UpdateResult$1, UpdateOneCommand>;
1153
1351
  /**
1154
1352
  * Find a single matching document and apply `updaterFn` to it.
1155
1353
  *
@@ -1157,15 +1355,15 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
1157
1355
  * `opts.returnDocument` (default `'after'`) controls whether the row
1158
1356
  * stream yields the document as it was before or after the update.
1159
1357
  */
1160
- findOneAndUpdate(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName>, ModelNestedShape<TContract, ModelName>>) => UpdaterResult, opts?: {
1358
+ findOneAndUpdate(updaterFn: (fields: FieldAccessor<ModelToDocShape<TContract, ModelName$1>, ModelNestedShape<TContract, ModelName$1>>) => UpdaterResult, opts?: {
1161
1359
  readonly upsert?: boolean;
1162
1360
  readonly returnDocument?: 'before' | 'after';
1163
- }): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName>, ExtractMongoCodecTypes<TContract>> | null, FindOneAndUpdateCommand>;
1361
+ }): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName$1>, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndUpdateCommand>;
1164
1362
  /**
1165
1363
  * Find a single matching document and delete it. Returns the deleted
1166
1364
  * document via the row stream.
1167
1365
  */
1168
- findOneAndDelete(): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName>, ExtractMongoCodecTypes<TContract>> | null, FindOneAndDeleteCommand>;
1366
+ findOneAndDelete(): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName$1>, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndDeleteCommand>;
1169
1367
  }
1170
1368
  /**
1171
1369
  * Bound execution context shared across the three state classes.
@@ -1203,5 +1401,5 @@ declare function contractModelToMongoResultShape(model: MongoModelDefinition, op
1203
1401
  readonly includeRelationNames?: readonly string[];
1204
1402
  }): MongoResultShape;
1205
1403
  //#endregion
1206
- export { type ArrayField, type BooleanField, CollectionHandle, type DateField, type DeleteResult, type DocField, type DocShape, type Expression, type ExtractDocShape, type FieldAccessor, FilteredCollection, type FindAndModifyEnabled, type GroupSpec, type GroupedDocShape, type InsertManyResult, type InsertOneResult, type LeafExpression, type LiteralValue, type ModelNestedShape, type ModelToDocShape, type NestedDocShape, type NullableDocField, type NullableNumericField, type NumericField, type ObjectExpression, type ObjectField, type PathCompletions, PipelineChain, type ProjectedShape, type QueryRoot, type ResolvePath, type ResolveRow, type SortSpec, type StringField, type TypedAccumulatorExpr, type TypedAggExpr, type TypedUpdateOp, type UnwoundShape, type UpdateEnabled, type UpdateResult, type UpdaterResult, type ValidPaths, acc, contractFieldToMongoFieldShape, contractModelToMongoResultShape, createFieldAccessor, fn, mongoQuery };
1404
+ export { type ArrayField, type BooleanField, CollectionHandle, type DateField, type DeleteResult, type DocField, type DocShape, type Expression, type ExtractDocShape, type FieldAccessor, FilteredCollection, type FindAndModifyEnabled, type GroupSpec, type GroupedDocShape, type InsertManyResult, type InsertOneResult, type LeafExpression, type LiteralValue, type LookupBuilder, type LookupBuilderWithKey, type LookupFrom, type LookupOnResult, type LookupResult, type ModelArrayField, type ModelNestedShape, type ModelOf, type ModelToDocShape, type NestedDocShape, type NullableDocField, type NullableNumericField, type NumericField, type ObjectExpression, type ObjectField, type PathCompletions, PipelineChain, type ProjectedShape, type QueryRoot, type ResolvePath, type ResolveRow, type SortSpec, type StringField, type TypedAccumulatorExpr, type TypedAggExpr, type TypedUpdateOp, type UnwoundShape, type UpdateEnabled, type UpdateResult, type UpdaterResult, type ValidPaths, acc, contractFieldToMongoFieldShape, contractModelToMongoResultShape, createFieldAccessor, fn, mongoQuery };
1207
1405
  //# sourceMappingURL=index.d.mts.map