@prisma-next/mongo-query-builder 0.5.0-dev.6 → 0.5.0-dev.61
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/README.md +28 -0
- package/dist/index.d.mts +390 -183
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +176 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -7
- package/src/builder.ts +56 -31
- package/src/exports/index.ts +13 -0
- package/src/lookup-builder.ts +272 -0
- package/src/pipeline-result-shape.ts +15 -0
- package/src/query.ts +0 -1
- package/src/resolve-path.ts +54 -0
- package/src/result-shape.ts +63 -0
- package/src/state-classes.ts +12 -3
- package/src/types.ts +110 -9
package/dist/index.d.mts
CHANGED
|
@@ -1,146 +1,10 @@
|
|
|
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, MongoFillOutput, MongoFilterExpr, MongoPipelineStage, MongoQueryPlan, MongoUpdatePipelineStage, MongoWindowField, UpdateManyCommand, UpdateOneCommand, UpdateResult, UpdateResult as UpdateResult$1 } from "@prisma-next/mongo-query-ast/execution";
|
|
2
|
-
import { ExtractMongoCodecTypes, MongoContract, MongoContractWithTypeMaps, MongoTypeMaps } from "@prisma-next/mongo-contract";
|
|
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, ExtractMongoTypeMaps, InferModelRow, MongoContract, MongoContractWithTypeMaps, MongoModelDefinition, MongoTypeMaps } from "@prisma-next/mongo-contract";
|
|
3
3
|
import { MongoValue } from "@prisma-next/mongo-value";
|
|
4
|
+
import { ContractField } from "@prisma-next/contract/types";
|
|
4
5
|
|
|
5
|
-
//#region src/types.d.ts
|
|
6
|
-
interface DocField {
|
|
7
|
-
readonly codecId: string;
|
|
8
|
-
readonly nullable: boolean;
|
|
9
|
-
}
|
|
10
|
-
type NumericField = {
|
|
11
|
-
readonly codecId: 'mongo/double@1';
|
|
12
|
-
readonly nullable: false;
|
|
13
|
-
};
|
|
14
|
-
type NullableNumericField = {
|
|
15
|
-
readonly codecId: 'mongo/double@1';
|
|
16
|
-
readonly nullable: true;
|
|
17
|
-
};
|
|
18
|
-
type StringField = {
|
|
19
|
-
readonly codecId: 'mongo/string@1';
|
|
20
|
-
readonly nullable: false;
|
|
21
|
-
};
|
|
22
|
-
type ArrayField = {
|
|
23
|
-
readonly codecId: 'mongo/array@1';
|
|
24
|
-
readonly nullable: false;
|
|
25
|
-
};
|
|
26
|
-
type BooleanField = {
|
|
27
|
-
readonly codecId: 'mongo/bool@1';
|
|
28
|
-
readonly nullable: false;
|
|
29
|
-
};
|
|
30
|
-
type DateField = {
|
|
31
|
-
readonly codecId: 'mongo/date@1';
|
|
32
|
-
readonly nullable: false;
|
|
33
|
-
};
|
|
34
|
-
type NullableDocField = {
|
|
35
|
-
readonly codecId: string;
|
|
36
|
-
readonly nullable: true;
|
|
37
|
-
};
|
|
38
|
-
type LiteralValue<F extends DocField> = F extends StringField ? string : F extends NumericField ? number : F extends BooleanField ? boolean : F extends DateField ? Date : unknown;
|
|
39
|
-
type DocShape = Record<string, DocField>;
|
|
40
|
-
type ExtractCodecId<F> = F extends {
|
|
41
|
-
type: {
|
|
42
|
-
kind: 'scalar';
|
|
43
|
-
codecId: infer C;
|
|
44
|
-
};
|
|
45
|
-
} ? C : F extends {
|
|
46
|
-
codecId: infer C extends string;
|
|
47
|
-
} ? C : string;
|
|
48
|
-
type ModelToDocShape<TContract extends MongoContract, ModelName extends string & keyof TContract['models']> = { [K in keyof TContract['models'][ModelName]['fields'] & string]: {
|
|
49
|
-
readonly codecId: ExtractCodecId<TContract['models'][ModelName]['fields'][K]>;
|
|
50
|
-
readonly nullable: TContract['models'][ModelName]['fields'][K]['nullable'];
|
|
51
|
-
} };
|
|
52
|
-
type ResolveRow<Shape extends DocShape, CodecTypes extends Record<string, {
|
|
53
|
-
readonly output: unknown;
|
|
54
|
-
}>> = { -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 };
|
|
55
|
-
interface TypedAggExpr<F extends DocField> {
|
|
56
|
-
readonly _field: F;
|
|
57
|
-
readonly node: MongoAggExpr;
|
|
58
|
-
}
|
|
59
|
-
interface TypedAccumulatorExpr<F extends DocField> {
|
|
60
|
-
readonly _field: F;
|
|
61
|
-
readonly node: MongoAggAccumulator;
|
|
62
|
-
}
|
|
63
|
-
type ExtractDocShape<T extends Record<string, TypedAggExpr<DocField>>> = { [K in keyof T & string]: T[K]['_field'] };
|
|
64
|
-
type SortSpec<S extends DocShape> = Partial<Record<keyof S & string, 1 | -1>>;
|
|
65
|
-
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>);
|
|
66
|
-
type GroupSpec = {
|
|
67
|
-
_id: TypedAggExpr<DocField> | null;
|
|
68
|
-
[key: string]: TypedAggExpr<DocField> | TypedAccumulatorExpr<DocField> | null;
|
|
69
|
-
};
|
|
70
|
-
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 ? {
|
|
71
|
-
readonly codecId: 'mongo/null@1';
|
|
72
|
-
readonly nullable: true;
|
|
73
|
-
} : DocField };
|
|
74
|
-
/**
|
|
75
|
-
* Intentionally identity — full array element type extraction is deferred.
|
|
76
|
-
* Used by `UnwoundShape` so the unwind result shape can be refined later
|
|
77
|
-
* without changing the public API.
|
|
78
|
-
*/
|
|
79
|
-
type UnwrapArrayDocField<F extends DocField> = F;
|
|
80
|
-
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] };
|
|
81
|
-
//#endregion
|
|
82
|
-
//#region src/accumulator-helpers.d.ts
|
|
83
|
-
declare const acc: {
|
|
84
|
-
sum<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<F>;
|
|
85
|
-
avg(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
|
|
86
|
-
min<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
|
|
87
|
-
readonly codecId: F["codecId"];
|
|
88
|
-
readonly nullable: true;
|
|
89
|
-
}>;
|
|
90
|
-
max<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
|
|
91
|
-
readonly codecId: F["codecId"];
|
|
92
|
-
readonly nullable: true;
|
|
93
|
-
}>;
|
|
94
|
-
first<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
|
|
95
|
-
readonly codecId: F["codecId"];
|
|
96
|
-
readonly nullable: true;
|
|
97
|
-
}>;
|
|
98
|
-
last<F extends DocField>(expr: TypedAggExpr<F>): TypedAccumulatorExpr<{
|
|
99
|
-
readonly codecId: F["codecId"];
|
|
100
|
-
readonly nullable: true;
|
|
101
|
-
}>;
|
|
102
|
-
push(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<ArrayField>;
|
|
103
|
-
addToSet(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<ArrayField>;
|
|
104
|
-
count(): TypedAccumulatorExpr<NumericField>;
|
|
105
|
-
stdDevPop(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
|
|
106
|
-
stdDevSamp(expr: TypedAggExpr<DocField>): TypedAccumulatorExpr<NullableNumericField>;
|
|
107
|
-
firstN(args: {
|
|
108
|
-
input: TypedAggExpr<DocField>;
|
|
109
|
-
n: TypedAggExpr<NumericField>;
|
|
110
|
-
}): TypedAccumulatorExpr<ArrayField>;
|
|
111
|
-
lastN(args: {
|
|
112
|
-
input: TypedAggExpr<DocField>;
|
|
113
|
-
n: TypedAggExpr<NumericField>;
|
|
114
|
-
}): TypedAccumulatorExpr<ArrayField>;
|
|
115
|
-
maxN(args: {
|
|
116
|
-
input: TypedAggExpr<DocField>;
|
|
117
|
-
n: TypedAggExpr<NumericField>;
|
|
118
|
-
}): TypedAccumulatorExpr<ArrayField>;
|
|
119
|
-
minN(args: {
|
|
120
|
-
input: TypedAggExpr<DocField>;
|
|
121
|
-
n: TypedAggExpr<NumericField>;
|
|
122
|
-
}): TypedAccumulatorExpr<ArrayField>;
|
|
123
|
-
top(args: {
|
|
124
|
-
output: TypedAggExpr<DocField>;
|
|
125
|
-
sortBy: Readonly<Record<string, 1 | -1>>;
|
|
126
|
-
}): TypedAccumulatorExpr<DocField>;
|
|
127
|
-
bottom(args: {
|
|
128
|
-
output: TypedAggExpr<DocField>;
|
|
129
|
-
sortBy: Readonly<Record<string, 1 | -1>>;
|
|
130
|
-
}): TypedAccumulatorExpr<DocField>;
|
|
131
|
-
topN(args: {
|
|
132
|
-
output: TypedAggExpr<DocField>;
|
|
133
|
-
sortBy: Readonly<Record<string, 1 | -1>>;
|
|
134
|
-
n: TypedAggExpr<NumericField>;
|
|
135
|
-
}): TypedAccumulatorExpr<ArrayField>;
|
|
136
|
-
bottomN(args: {
|
|
137
|
-
output: TypedAggExpr<DocField>;
|
|
138
|
-
sortBy: Readonly<Record<string, 1 | -1>>;
|
|
139
|
-
n: TypedAggExpr<NumericField>;
|
|
140
|
-
}): TypedAccumulatorExpr<ArrayField>;
|
|
141
|
-
};
|
|
142
|
-
//#endregion
|
|
143
6
|
//#region src/resolve-path.d.ts
|
|
7
|
+
|
|
144
8
|
/**
|
|
145
9
|
* Marker `DocField` variant representing a non-leaf (value-object) path in
|
|
146
10
|
* a [NestedDocShape]. Extends `DocField` with a `fields` property carrying
|
|
@@ -162,6 +26,57 @@ interface ObjectField<N$1 extends NestedDocShape> extends DocField {
|
|
|
162
26
|
readonly nullable: boolean;
|
|
163
27
|
readonly fields: N$1;
|
|
164
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
|
+
};
|
|
165
80
|
/**
|
|
166
81
|
* Document shape that carries nested value-object sub-shapes.
|
|
167
82
|
*
|
|
@@ -254,7 +169,7 @@ type VONestedShape<TContract extends ContractHasValueObjects, VOName$1 extends s
|
|
|
254
169
|
* literal field record collapses `keyof` to `string` and the result hover
|
|
255
170
|
* degrades to `{ readonly [x: string]: any }`.
|
|
256
171
|
*/
|
|
257
|
-
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]> };
|
|
258
173
|
/**
|
|
259
174
|
* Resolve a dot-path against a `NestedDocShape`. Returns:
|
|
260
175
|
* - the leaf `DocField` when `Path` terminates on a scalar/array leaf,
|
|
@@ -296,6 +211,208 @@ type ValidPaths<N$1 extends NestedDocShape> = string extends keyof N$1 ? never :
|
|
|
296
211
|
*/
|
|
297
212
|
type PathCompletions<N$1 extends NestedDocShape> = ValidPaths<N$1>;
|
|
298
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
|
|
299
416
|
//#region src/update-ops.d.ts
|
|
300
417
|
/**
|
|
301
418
|
* Per-field update operations produced by `Expression`'s update methods
|
|
@@ -519,6 +636,89 @@ type FieldAccessor<S extends DocShape, N$1 extends NestedDocShape = Record<strin
|
|
|
519
636
|
*/
|
|
520
637
|
declare function createFieldAccessor<S extends DocShape, N$1 extends NestedDocShape = Record<string, never>>(): FieldAccessor<S, N$1>;
|
|
521
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
|
|
522
722
|
//#region src/markers.d.ts
|
|
523
723
|
/**
|
|
524
724
|
* Phantom capability markers for `PipelineChain`.
|
|
@@ -551,6 +751,7 @@ interface PipelineChainState {
|
|
|
551
751
|
readonly collection: string;
|
|
552
752
|
readonly stages: ReadonlyArray<MongoPipelineStage>;
|
|
553
753
|
readonly storageHash: string;
|
|
754
|
+
readonly modelName?: string;
|
|
554
755
|
}
|
|
555
756
|
/**
|
|
556
757
|
* The pipeline state in the query-builder state machine.
|
|
@@ -576,9 +777,9 @@ interface PipelineChainState {
|
|
|
576
777
|
* marker table (and rationale per row) in
|
|
577
778
|
* `docs/architecture docs/adrs/ADR 201 - State-machine pattern for typed DSL builders.md`.
|
|
578
779
|
*/
|
|
579
|
-
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>> {
|
|
580
781
|
#private;
|
|
581
|
-
readonly __updateCompat: U;
|
|
782
|
+
readonly __updateCompat: U$1;
|
|
582
783
|
readonly __findAndModifyCompat: F;
|
|
583
784
|
readonly __leadingMatch: L;
|
|
584
785
|
constructor(contract: TContract, state: PipelineChainState);
|
|
@@ -590,8 +791,8 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
|
|
|
590
791
|
* `deconstructUpdateChain` can only peel leading `$match` stages into the
|
|
591
792
|
* wire-command filter.
|
|
592
793
|
*/
|
|
593
|
-
match(filter: MongoFilterExpr): PipelineChain<TContract, Shape, L extends 'leading' ? U : 'update-cleared', F, L, N$1>;
|
|
594
|
-
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>;
|
|
595
796
|
/**
|
|
596
797
|
* `$sort`. Clears `UpdateEnabled` (`update` has no per-document sort) but
|
|
597
798
|
* preserves `FindAndModifyEnabled` (`findAndModify` has a `sort` slot).
|
|
@@ -618,22 +819,21 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
|
|
|
618
819
|
* preserved — newly added flat fields are reachable via property access
|
|
619
820
|
* (`f.newField`) but do not themselves carry nested structure.
|
|
620
821
|
*/
|
|
621
|
-
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>;
|
|
622
823
|
/**
|
|
623
824
|
* `$lookup`. Clears both markers — joins are not representable in either
|
|
624
825
|
* the `update` or `findAndModify` wire commands. The original document's
|
|
625
826
|
* nested-path shape `N` is preserved (the lookup adds a sidecar array
|
|
626
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[]`.
|
|
627
835
|
*/
|
|
628
|
-
lookup<
|
|
629
|
-
from: ForeignRoot;
|
|
630
|
-
localField: keyof Shape & string;
|
|
631
|
-
foreignField: string;
|
|
632
|
-
as: As;
|
|
633
|
-
}): PipelineChain<TContract, Shape & Record<As, {
|
|
634
|
-
readonly codecId: 'mongo/array@1';
|
|
635
|
-
readonly nullable: false;
|
|
636
|
-
}>, '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>;
|
|
637
837
|
/**
|
|
638
838
|
* `$project`. Preserves `UpdateEnabled` (representable as update-with-pipeline
|
|
639
839
|
* `$project` / `$unset`); clears `FindAndModifyEnabled` (use `.project()` on
|
|
@@ -644,8 +844,8 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
|
|
|
644
844
|
* fundamentally rewrites the document, so dot-paths into the *source*
|
|
645
845
|
* document are no longer meaningful downstream.
|
|
646
846
|
*/
|
|
647
|
-
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'>;
|
|
648
|
-
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'>;
|
|
649
849
|
/**
|
|
650
850
|
* `$unwind`. Clears both markers — array unrolling produces multiple output
|
|
651
851
|
* documents per input, incompatible with both single-document update and
|
|
@@ -668,7 +868,7 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
|
|
|
668
868
|
* Nested path shape is reset — the replaced root has no relation to
|
|
669
869
|
* the original document structure.
|
|
670
870
|
*/
|
|
671
|
-
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'>;
|
|
672
872
|
count<Field extends string>(field: Field): PipelineChain<TContract, Record<Field, {
|
|
673
873
|
readonly codecId: 'mongo/double@1';
|
|
674
874
|
readonly nullable: false;
|
|
@@ -684,7 +884,7 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
|
|
|
684
884
|
* `$redact`. Preserves `UpdateEnabled`; clears `FindAndModifyEnabled`.
|
|
685
885
|
* Shape- and nested-path-preserving (the document tree is unchanged).
|
|
686
886
|
*/
|
|
687
|
-
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>;
|
|
688
888
|
/**
|
|
689
889
|
* `$out` write terminal. Materialises the pipeline output into
|
|
690
890
|
* `collection` (optionally in `db`), replacing any prior contents. Unlike
|
|
@@ -816,23 +1016,23 @@ declare class PipelineChain<TContract extends MongoContractWithTypeMaps<MongoCon
|
|
|
816
1016
|
* runtime error is thrown as a defensive check (the type system should
|
|
817
1017
|
* prevent this).
|
|
818
1018
|
*/
|
|
819
|
-
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?: {
|
|
820
1020
|
readonly upsert?: boolean;
|
|
821
1021
|
readonly returnDocument?: 'before' | 'after';
|
|
822
|
-
}): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract
|
|
1022
|
+
}): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndUpdateCommand>;
|
|
823
1023
|
/**
|
|
824
1024
|
* Find a single document matching the accumulated pipeline and delete it.
|
|
825
1025
|
* Same marker gating and deconstruction as `findOneAndUpdate`.
|
|
826
1026
|
*/
|
|
827
|
-
findOneAndDelete(this: PipelineChain<TContract, Shape, U, 'fam-ok', L, N$1>): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract
|
|
1027
|
+
findOneAndDelete(this: PipelineChain<TContract, Shape, U$1, 'fam-ok', L, N$1>): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndDeleteCommand>;
|
|
828
1028
|
/**
|
|
829
1029
|
* Materialise the chain as a `MongoQueryPlan` wrapping an `AggregateCommand`.
|
|
830
1030
|
*/
|
|
831
|
-
build(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract
|
|
1031
|
+
build(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract>, AggregateCommand>;
|
|
832
1032
|
/**
|
|
833
1033
|
* Alias for `build()` — surfaces the read intent at the call site.
|
|
834
1034
|
*/
|
|
835
|
-
aggregate(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract
|
|
1035
|
+
aggregate(): MongoQueryPlan<ResolveRow<Shape, ExtractMongoCodecTypes<TContract>, TContract>, AggregateCommand>;
|
|
836
1036
|
}
|
|
837
1037
|
//#endregion
|
|
838
1038
|
//#region src/expression-helpers.d.ts
|
|
@@ -1014,14 +1214,14 @@ declare const fn: {
|
|
|
1014
1214
|
* accidentally produce an unqualified write by forgetting to `.match(...)`
|
|
1015
1215
|
* later in the chain. Bodies land in M2.
|
|
1016
1216
|
*/
|
|
1017
|
-
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>> {
|
|
1018
1218
|
#private;
|
|
1019
|
-
constructor(ctx: BindingContext<TContract>, modelName: ModelName);
|
|
1219
|
+
constructor(ctx: BindingContext<TContract>, modelName: ModelName$1);
|
|
1020
1220
|
/**
|
|
1021
1221
|
* Bound model name. Exposed so type tests can assert the binding without
|
|
1022
1222
|
* flipping into a pipeline. Not part of the public-API contract.
|
|
1023
1223
|
*/
|
|
1024
|
-
get _modelName(): ModelName;
|
|
1224
|
+
get _modelName(): ModelName$1;
|
|
1025
1225
|
/**
|
|
1026
1226
|
* Begin accumulating a filter. Transitions to `FilteredCollection`.
|
|
1027
1227
|
*
|
|
@@ -1031,8 +1231,8 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
|
|
|
1031
1231
|
* Mongo — but `FilteredCollection` makes the accumulated filter
|
|
1032
1232
|
* addressable for the write/find-and-modify terminals landing in M2/M3.
|
|
1033
1233
|
*/
|
|
1034
|
-
match(filter: MongoFilterExpr): FilteredCollection<TContract, ModelName>;
|
|
1035
|
-
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>;
|
|
1036
1236
|
/**
|
|
1037
1237
|
* Insert a single document. Document fields are passed straight through to
|
|
1038
1238
|
* the wire `InsertOneCommand` — codec normalisation happens at the
|
|
@@ -1055,7 +1255,7 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
|
|
|
1055
1255
|
* unqualified write by forgetting to `.match(...)` first. Pair with
|
|
1056
1256
|
* `.match(...).updateMany(...)` for the filtered case.
|
|
1057
1257
|
*/
|
|
1058
|
-
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>;
|
|
1059
1259
|
/**
|
|
1060
1260
|
* Delete *every* document in the collection. See `updateAll` for the
|
|
1061
1261
|
* rationale around the unqualified-write surface being limited to this
|
|
@@ -1072,7 +1272,7 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
|
|
|
1072
1272
|
* new document derived from the filter equality fields plus the update
|
|
1073
1273
|
* spec when no match is found; otherwise updates the matched document.
|
|
1074
1274
|
*/
|
|
1075
|
-
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>;
|
|
1076
1276
|
}
|
|
1077
1277
|
/**
|
|
1078
1278
|
* State reached after one or more `.match(...)` calls on `CollectionHandle`.
|
|
@@ -1098,10 +1298,10 @@ declare class CollectionHandle<TContract extends MongoContractWithTypeMaps<Mongo
|
|
|
1098
1298
|
* — those are insert or unqualified-write operations that are nonsense
|
|
1099
1299
|
* after a filter has been applied.
|
|
1100
1300
|
*/
|
|
1101
|
-
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>> {
|
|
1102
1302
|
#private;
|
|
1103
|
-
constructor(ctx: BindingContext<TContract>, modelName: ModelName, filters: ReadonlyArray<MongoFilterExpr>);
|
|
1104
|
-
get _modelName(): ModelName;
|
|
1303
|
+
constructor(ctx: BindingContext<TContract>, modelName: ModelName$1, filters: ReadonlyArray<MongoFilterExpr>);
|
|
1304
|
+
get _modelName(): ModelName$1;
|
|
1105
1305
|
/**
|
|
1106
1306
|
* Accumulated filter list. Exposed for the M2/M3 write/find-and-modify
|
|
1107
1307
|
* terminals to splat into wire-command `filter` slots; not part of the
|
|
@@ -1115,8 +1315,8 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
|
|
|
1115
1315
|
* second `$match` stage), so the write/find-and-modify terminals see a
|
|
1116
1316
|
* single authoritative filter expression.
|
|
1117
1317
|
*/
|
|
1118
|
-
match(filter: MongoFilterExpr): FilteredCollection<TContract, ModelName>;
|
|
1119
|
-
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>;
|
|
1120
1320
|
/**
|
|
1121
1321
|
* Update every matching document. `updaterFn` receives a `FieldAccessor`
|
|
1122
1322
|
* and returns an array of `TypedUpdateOp` (e.g. `[f.amount.inc(1),
|
|
@@ -1124,14 +1324,14 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
|
|
|
1124
1324
|
* update spec by `foldUpdateOps`, which throws on operator+path
|
|
1125
1325
|
* collisions.
|
|
1126
1326
|
*/
|
|
1127
|
-
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>;
|
|
1128
1328
|
/**
|
|
1129
1329
|
* Update at most one matching document. The driver picks the document
|
|
1130
1330
|
* (typically the first one matched by the underlying scan); no ordering
|
|
1131
1331
|
* guarantee is implied — chain `.sort(...)` and use the M3
|
|
1132
1332
|
* `.findOneAndUpdate(...)` terminal when ordering matters.
|
|
1133
1333
|
*/
|
|
1134
|
-
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>;
|
|
1135
1335
|
/**
|
|
1136
1336
|
* Delete every matching document.
|
|
1137
1337
|
*/
|
|
@@ -1147,7 +1347,7 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
|
|
|
1147
1347
|
* `CollectionHandle.upsertOne(f => filter, updaterFn)` but reuses the
|
|
1148
1348
|
* already-accumulated `.match(...)` filter chain.
|
|
1149
1349
|
*/
|
|
1150
|
-
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>;
|
|
1151
1351
|
/**
|
|
1152
1352
|
* Find a single matching document and apply `updaterFn` to it.
|
|
1153
1353
|
*
|
|
@@ -1155,15 +1355,15 @@ declare class FilteredCollection<TContract extends MongoContractWithTypeMaps<Mon
|
|
|
1155
1355
|
* `opts.returnDocument` (default `'after'`) controls whether the row
|
|
1156
1356
|
* stream yields the document as it was before or after the update.
|
|
1157
1357
|
*/
|
|
1158
|
-
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?: {
|
|
1159
1359
|
readonly upsert?: boolean;
|
|
1160
1360
|
readonly returnDocument?: 'before' | 'after';
|
|
1161
|
-
}): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName>, ExtractMongoCodecTypes<TContract
|
|
1361
|
+
}): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName$1>, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndUpdateCommand>;
|
|
1162
1362
|
/**
|
|
1163
1363
|
* Find a single matching document and delete it. Returns the deleted
|
|
1164
1364
|
* document via the row stream.
|
|
1165
1365
|
*/
|
|
1166
|
-
findOneAndDelete(): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName>, ExtractMongoCodecTypes<TContract
|
|
1366
|
+
findOneAndDelete(): MongoQueryPlan<ResolveRow<ModelToDocShape<TContract, ModelName$1>, ExtractMongoCodecTypes<TContract>, TContract> | null, FindOneAndDeleteCommand>;
|
|
1167
1367
|
}
|
|
1168
1368
|
/**
|
|
1169
1369
|
* Bound execution context shared across the three state classes.
|
|
@@ -1194,5 +1394,12 @@ declare function mongoQuery<TContract extends MongoContractWithTypeMaps<MongoCon
|
|
|
1194
1394
|
contractJson: unknown;
|
|
1195
1395
|
}): QueryRoot<TContract>;
|
|
1196
1396
|
//#endregion
|
|
1197
|
-
|
|
1397
|
+
//#region src/result-shape.d.ts
|
|
1398
|
+
declare function contractFieldToMongoFieldShape(field: ContractField): MongoFieldShape;
|
|
1399
|
+
declare function contractModelToMongoResultShape(model: MongoModelDefinition, options?: {
|
|
1400
|
+
readonly selection?: readonly string[];
|
|
1401
|
+
readonly includeRelationNames?: readonly string[];
|
|
1402
|
+
}): MongoResultShape;
|
|
1403
|
+
//#endregion
|
|
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 };
|
|
1198
1405
|
//# sourceMappingURL=index.d.mts.map
|