@prisma-next/mongo-query-builder 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +23 -30
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +10 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -9
- package/src/builder.ts +2 -2
- package/src/lookup-builder.ts +17 -11
- package/src/query.ts +7 -2
- package/src/resolve-path.ts +12 -21
- package/src/state-classes.ts +11 -8
- package/src/types.ts +7 -6
package/package.json
CHANGED
|
@@ -1,33 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/mongo-query-builder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "Type-safe MongoDB query builder (reads, writes, find-and-modify, pipeline-terminal writes) with document shape tracking",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/contract": "0.
|
|
10
|
-
"@prisma-next/mongo-contract": "0.
|
|
11
|
-
"@prisma-next/mongo-query-ast": "0.
|
|
12
|
-
"@prisma-next/mongo-value": "0.
|
|
13
|
-
"@prisma-next/utils": "0.
|
|
9
|
+
"@prisma-next/contract": "0.12.0",
|
|
10
|
+
"@prisma-next/mongo-contract": "0.12.0",
|
|
11
|
+
"@prisma-next/mongo-query-ast": "0.12.0",
|
|
12
|
+
"@prisma-next/mongo-value": "0.12.0",
|
|
13
|
+
"@prisma-next/utils": "0.12.0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@prisma-next/tsconfig": "0.
|
|
17
|
-
"@prisma-next/tsdown": "0.
|
|
16
|
+
"@prisma-next/tsconfig": "0.12.0",
|
|
17
|
+
"@prisma-next/tsdown": "0.12.0",
|
|
18
18
|
"tsdown": "0.22.0",
|
|
19
19
|
"typescript": "5.9.3",
|
|
20
20
|
"vitest": "4.1.6"
|
|
21
21
|
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"typescript": ">=5.9"
|
|
24
|
+
},
|
|
25
|
+
"peerDependenciesMeta": {
|
|
26
|
+
"typescript": {
|
|
27
|
+
"optional": true
|
|
28
|
+
}
|
|
29
|
+
},
|
|
22
30
|
"files": [
|
|
23
31
|
"dist",
|
|
24
32
|
"src"
|
|
25
33
|
],
|
|
34
|
+
"types": "./dist/index.d.mts",
|
|
26
35
|
"exports": {
|
|
27
36
|
".": "./dist/index.mjs",
|
|
28
37
|
"./package.json": "./package.json"
|
|
29
38
|
},
|
|
30
|
-
"
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=24"
|
|
41
|
+
},
|
|
31
42
|
"repository": {
|
|
32
43
|
"type": "git",
|
|
33
44
|
"url": "https://github.com/prisma/prisma-next.git",
|
package/src/builder.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { contractModels, type PlanMeta } from '@prisma-next/contract/types';
|
|
2
2
|
import type {
|
|
3
3
|
ExtractMongoCodecTypes,
|
|
4
4
|
MongoContract,
|
|
@@ -820,7 +820,7 @@ export class PipelineChain<
|
|
|
820
820
|
let resultShape: MongoResultShape | undefined;
|
|
821
821
|
if (modelName !== undefined) {
|
|
822
822
|
if (pipelineSupportsFlatResultShape(this.#state.stages)) {
|
|
823
|
-
const model = contractNarrow
|
|
823
|
+
const model = contractModels(contractNarrow)[modelName] as MongoModelDefinition | undefined;
|
|
824
824
|
resultShape = model ? contractModelToMongoResultShape(model) : { kind: 'unknown' as const };
|
|
825
825
|
} else {
|
|
826
826
|
resultShape = { kind: 'unknown' as const };
|
package/src/lookup-builder.ts
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { contractModels } from '@prisma-next/contract/types';
|
|
2
|
+
import type {
|
|
3
|
+
MongoContract,
|
|
4
|
+
MongoModelDefinition,
|
|
5
|
+
MongoModelsMap,
|
|
6
|
+
RootModelName,
|
|
7
|
+
} from '@prisma-next/mongo-contract';
|
|
2
8
|
import { createFieldAccessor, type FieldAccessor, type LeafExpression } from './field-accessor';
|
|
3
9
|
import type { ModelNestedShape } from './resolve-path';
|
|
4
10
|
import type { DocField, DocShape, ModelToDocShape } from './types';
|
|
5
11
|
|
|
6
12
|
/**
|
|
7
13
|
* Resolved foreign-model name for a contract root. Looks `RootName` up
|
|
8
|
-
* through `TContract['roots']` and
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
14
|
+
* through `TContract['roots']` and extracts the referenced model name
|
|
15
|
+
* so it can be used as a `ModelName` index into `models`. Resolves to
|
|
16
|
+
* `never` when the root is not present (this surface should never be
|
|
17
|
+
* reachable through normal use because `from()` constrains its `R`
|
|
18
|
+
* parameter to `keyof TContract['roots']`).
|
|
13
19
|
*/
|
|
14
20
|
export type ModelOf<
|
|
15
21
|
TContract extends MongoContract,
|
|
16
22
|
RootName extends keyof TContract['roots'] & string,
|
|
17
|
-
> = TContract
|
|
23
|
+
> = RootModelName<TContract, RootName>;
|
|
18
24
|
|
|
19
25
|
/**
|
|
20
26
|
* Object returned by the user from the `on(...)` callback. Each side is
|
|
@@ -92,7 +98,7 @@ export interface LookupBuilder<
|
|
|
92
98
|
on(
|
|
93
99
|
cb: (
|
|
94
100
|
local: FieldAccessor<Shape, Nested>,
|
|
95
|
-
foreign: ModelName extends keyof TContract
|
|
101
|
+
foreign: ModelName extends keyof MongoModelsMap<TContract> & string
|
|
96
102
|
? FieldAccessor<
|
|
97
103
|
ModelToDocShape<TContract, ModelName>,
|
|
98
104
|
ModelNestedShape<TContract, ModelName>
|
|
@@ -137,12 +143,12 @@ export function createLookupFrom<
|
|
|
137
143
|
Nested extends Record<string, DocField>,
|
|
138
144
|
>(contract: TContract): LookupFrom<TContract, Shape, Nested> {
|
|
139
145
|
const callable = ((rootName) => {
|
|
140
|
-
const modelName = contract.roots[rootName];
|
|
146
|
+
const modelName = contract.roots[rootName]?.model;
|
|
141
147
|
if (!modelName) {
|
|
142
148
|
const validRoots = Object.keys(contract.roots).join(', ');
|
|
143
149
|
throw new Error(`lookup() unknown root: "${rootName}". Valid roots: ${validRoots}`);
|
|
144
150
|
}
|
|
145
|
-
const model = contract
|
|
151
|
+
const model = contractModels(contract)[modelName] as MongoModelDefinition | undefined;
|
|
146
152
|
const foreignCollection = model?.storage?.collection ?? rootName;
|
|
147
153
|
return createLookupBuilder({
|
|
148
154
|
rootName,
|
|
@@ -260,7 +266,7 @@ export function extractLookupResult(
|
|
|
260
266
|
'Returning a hand-rolled options object is not supported.',
|
|
261
267
|
);
|
|
262
268
|
}
|
|
263
|
-
const model = contract
|
|
269
|
+
const model = contractModels(contract)[result._model] as MongoModelDefinition | undefined;
|
|
264
270
|
const foreignCollection = model?.storage?.collection ?? result._root;
|
|
265
271
|
return {
|
|
266
272
|
foreignCollection,
|
package/src/query.ts
CHANGED
|
@@ -3,8 +3,10 @@ import type {
|
|
|
3
3
|
MongoContract,
|
|
4
4
|
MongoContractWithTypeMaps,
|
|
5
5
|
MongoTypeMaps,
|
|
6
|
+
RootModelName,
|
|
6
7
|
} from '@prisma-next/mongo-contract';
|
|
7
8
|
import type { AnyMongoCommand, MongoQueryPlan } from '@prisma-next/mongo-query-ast/execution';
|
|
9
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
8
10
|
import { asMongoContract, type CollectionHandle, createCollectionHandle } from './state-classes';
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -23,14 +25,17 @@ export interface QueryRoot<
|
|
|
23
25
|
> {
|
|
24
26
|
from<K extends keyof TContract['roots'] & string>(
|
|
25
27
|
rootName: K,
|
|
26
|
-
): CollectionHandle<TContract, TContract
|
|
28
|
+
): CollectionHandle<TContract, RootModelName<TContract, K>>;
|
|
27
29
|
rawCommand<C extends AnyMongoCommand>(command: C): MongoQueryPlan<unknown, C>;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export function mongoQuery<
|
|
31
33
|
TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>,
|
|
32
34
|
>(options: { contractJson: unknown }): QueryRoot<TContract> {
|
|
33
|
-
const contract =
|
|
35
|
+
const contract = blindCast<
|
|
36
|
+
TContract,
|
|
37
|
+
'mongoQuery accepts validated contract JSON with domain.namespaces'
|
|
38
|
+
>(options.contractJson);
|
|
34
39
|
return {
|
|
35
40
|
from<K extends keyof TContract['roots'] & string>(rootName: K) {
|
|
36
41
|
return createCollectionHandle(contract, rootName);
|
package/src/resolve-path.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContractValueObjectsMap } from '@prisma-next/contract/types';
|
|
2
|
+
import type { MongoContract, MongoModelsMap } from '@prisma-next/mongo-contract';
|
|
2
3
|
import type { DocField } from './types';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -95,10 +96,6 @@ export type NestedDocShape = Record<string, DocField>;
|
|
|
95
96
|
|
|
96
97
|
// ── Contract → NestedDocShape translation ────────────────────────────────
|
|
97
98
|
|
|
98
|
-
type ContractHasValueObjects = {
|
|
99
|
-
readonly valueObjects?: Record<string, { readonly fields: Record<string, unknown> }>;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
99
|
type FieldToLeaf<F> = F extends {
|
|
103
100
|
readonly type: { readonly kind: 'scalar'; readonly codecId: infer C extends string };
|
|
104
101
|
readonly nullable: infer N extends boolean;
|
|
@@ -122,7 +119,7 @@ type FieldToLeaf<F> = F extends {
|
|
|
122
119
|
* `ModelNestedShape` hover output and `keyof`/indexed-access resolution
|
|
123
120
|
* concrete instead of collapsing to `{ [x: string]: … }`.
|
|
124
121
|
*/
|
|
125
|
-
type TranslateField<TContract extends
|
|
122
|
+
type TranslateField<TContract extends MongoContract, F> = F extends {
|
|
126
123
|
readonly many: true;
|
|
127
124
|
}
|
|
128
125
|
? FieldToLeaf<F>
|
|
@@ -147,16 +144,10 @@ type TranslateField<TContract extends ContractHasValueObjects, F> = F extends {
|
|
|
147
144
|
* `VOs[VOName]['fields']` is preserved and the hover / indexed-access
|
|
148
145
|
* surface stays concrete at instantiation time.
|
|
149
146
|
*/
|
|
150
|
-
type VONestedShape<
|
|
151
|
-
TContract
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
readonly valueObjects: infer VOs extends Record<
|
|
155
|
-
string,
|
|
156
|
-
{ readonly fields: Record<string, unknown> }
|
|
157
|
-
>;
|
|
158
|
-
}
|
|
159
|
-
? VOName extends keyof VOs
|
|
147
|
+
type VONestedShape<TContract extends MongoContract, VOName extends string> = [
|
|
148
|
+
ContractValueObjectsMap<TContract>,
|
|
149
|
+
] extends [infer VOs extends Record<string, { readonly fields: Record<string, unknown> }>]
|
|
150
|
+
? VOName extends keyof VOs & string
|
|
160
151
|
? {
|
|
161
152
|
readonly [K in keyof VOs[VOName]['fields'] & string]: TranslateField<
|
|
162
153
|
TContract,
|
|
@@ -174,7 +165,7 @@ type VONestedShape<
|
|
|
174
165
|
*
|
|
175
166
|
* The mapped iteration is inlined (not hidden behind a helper type that
|
|
176
167
|
* takes `Fields` as a generic) so TypeScript recognises the mapped type
|
|
177
|
-
* as homomorphic over `TContract[
|
|
168
|
+
* as homomorphic over `MongoModelsMap<TContract>[ModelName]['fields']`. That
|
|
178
169
|
* preserves the literal field-name keys at instantiation — without this,
|
|
179
170
|
* the intersection of `Record<string, ContractField>` and the specific
|
|
180
171
|
* literal field record collapses `keyof` to `string` and the result hover
|
|
@@ -182,11 +173,11 @@ type VONestedShape<
|
|
|
182
173
|
*/
|
|
183
174
|
export type ModelNestedShape<
|
|
184
175
|
TContract extends MongoContract,
|
|
185
|
-
ModelName extends string & keyof TContract
|
|
176
|
+
ModelName extends string & keyof MongoModelsMap<TContract>,
|
|
186
177
|
> = {
|
|
187
|
-
readonly [K in keyof TContract[
|
|
188
|
-
TContract
|
|
189
|
-
TContract[
|
|
178
|
+
readonly [K in keyof MongoModelsMap<TContract>[ModelName]['fields'] & string]: TranslateField<
|
|
179
|
+
TContract,
|
|
180
|
+
MongoModelsMap<TContract>[ModelName]['fields'][K]
|
|
190
181
|
>;
|
|
191
182
|
};
|
|
192
183
|
|
package/src/state-classes.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { contractModels, type PlanMeta } from '@prisma-next/contract/types';
|
|
2
2
|
import type {
|
|
3
3
|
ExtractMongoCodecTypes,
|
|
4
4
|
MongoContract,
|
|
5
5
|
MongoContractWithTypeMaps,
|
|
6
|
+
MongoModelDefinition,
|
|
7
|
+
MongoModelsMap,
|
|
6
8
|
MongoTypeMaps,
|
|
9
|
+
RootModelName,
|
|
7
10
|
} from '@prisma-next/mongo-contract';
|
|
8
11
|
import type {
|
|
9
12
|
DeleteResult,
|
|
@@ -92,7 +95,7 @@ function writeMeta(storageHash: string): PlanMeta {
|
|
|
92
95
|
*/
|
|
93
96
|
export class CollectionHandle<
|
|
94
97
|
TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>,
|
|
95
|
-
ModelName extends keyof TContract
|
|
98
|
+
ModelName extends keyof MongoModelsMap<TContract> & string,
|
|
96
99
|
> extends PipelineChain<
|
|
97
100
|
TContract,
|
|
98
101
|
ModelToDocShape<TContract, ModelName>,
|
|
@@ -316,7 +319,7 @@ export class CollectionHandle<
|
|
|
316
319
|
*/
|
|
317
320
|
export class FilteredCollection<
|
|
318
321
|
TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>,
|
|
319
|
-
ModelName extends keyof TContract
|
|
322
|
+
ModelName extends keyof MongoModelsMap<TContract> & string,
|
|
320
323
|
> extends PipelineChain<
|
|
321
324
|
TContract,
|
|
322
325
|
ModelToDocShape<TContract, ModelName>,
|
|
@@ -632,18 +635,18 @@ export function createCollectionHandle<
|
|
|
632
635
|
>(
|
|
633
636
|
contract: TContract,
|
|
634
637
|
rootName: RootName,
|
|
635
|
-
): CollectionHandle<TContract, TContract
|
|
638
|
+
): CollectionHandle<TContract, RootModelName<TContract, RootName>> {
|
|
636
639
|
const c = asMongoContract(contract);
|
|
637
|
-
const modelName = c.roots[rootName];
|
|
640
|
+
const modelName = c.roots[rootName]?.model;
|
|
638
641
|
if (!modelName) {
|
|
639
642
|
const validRoots = Object.keys(c.roots).join(', ');
|
|
640
643
|
throw new Error(`Unknown root: "${rootName}". Valid roots: ${validRoots}`);
|
|
641
644
|
}
|
|
642
|
-
const model = c
|
|
645
|
+
const model = contractModels(c)[modelName] as MongoModelDefinition | undefined;
|
|
643
646
|
if (!model) {
|
|
644
647
|
throw new Error(`Unknown model: "${modelName}" referenced by root "${rootName}".`);
|
|
645
648
|
}
|
|
646
|
-
const collectionName = model.storage
|
|
649
|
+
const collectionName = model.storage.collection ?? rootName;
|
|
647
650
|
if (!c.storage?.storageHash) {
|
|
648
651
|
throw new Error(
|
|
649
652
|
'Contract is missing storage.storageHash. Pass a validated contract to mongoQuery().',
|
|
@@ -655,6 +658,6 @@ export function createCollectionHandle<
|
|
|
655
658
|
collection: collectionName,
|
|
656
659
|
storageHash: String(c.storage.storageHash),
|
|
657
660
|
},
|
|
658
|
-
modelName as TContract
|
|
661
|
+
modelName as RootModelName<TContract, RootName>,
|
|
659
662
|
);
|
|
660
663
|
}
|
package/src/types.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
InferModelRow,
|
|
4
4
|
MongoContract,
|
|
5
5
|
MongoContractWithTypeMaps,
|
|
6
|
+
MongoModelsMap,
|
|
6
7
|
MongoTypeMaps,
|
|
7
8
|
} from '@prisma-next/mongo-contract';
|
|
8
9
|
import type { MongoAggAccumulator, MongoAggExpr } from '@prisma-next/mongo-query-ast/execution';
|
|
@@ -41,11 +42,11 @@ type ExtractCodecId<F> = F extends { type: { kind: 'scalar'; codecId: infer C }
|
|
|
41
42
|
|
|
42
43
|
export type ModelToDocShape<
|
|
43
44
|
TContract extends MongoContract,
|
|
44
|
-
ModelName extends string & keyof TContract
|
|
45
|
+
ModelName extends string & keyof MongoModelsMap<TContract>,
|
|
45
46
|
> = {
|
|
46
|
-
[K in keyof TContract[
|
|
47
|
-
readonly codecId: ExtractCodecId<TContract[
|
|
48
|
-
readonly nullable: TContract[
|
|
47
|
+
[K in keyof MongoModelsMap<TContract>[ModelName]['fields'] & string]: {
|
|
48
|
+
readonly codecId: ExtractCodecId<MongoModelsMap<TContract>[ModelName]['fields'][K]>;
|
|
49
|
+
readonly nullable: MongoModelsMap<TContract>[ModelName]['fields'][K]['nullable'];
|
|
49
50
|
};
|
|
50
51
|
} & ModelOriginBranded<ModelName>;
|
|
51
52
|
|
|
@@ -65,7 +66,7 @@ type ResolveFields<
|
|
|
65
66
|
-readonly [K in keyof Shape & string]: Shape[K] extends ModelArrayField<infer ModelName>
|
|
66
67
|
? IsConcreteContract<TContract> extends true
|
|
67
68
|
? TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>
|
|
68
|
-
? ModelName extends string & keyof TContract
|
|
69
|
+
? ModelName extends string & keyof MongoModelsMap<TContract>
|
|
69
70
|
? Array<InferModelRow<TContract, ModelName>>
|
|
70
71
|
: unknown[]
|
|
71
72
|
: unknown[]
|
|
@@ -131,7 +132,7 @@ export type ResolveRow<
|
|
|
131
132
|
> = Shape extends { readonly [ModelOriginBrand]?: infer ModelName extends string }
|
|
132
133
|
? IsConcreteContract<TContract> extends true
|
|
133
134
|
? TContract extends MongoContractWithTypeMaps<MongoContract, MongoTypeMaps>
|
|
134
|
-
? ModelName extends string & keyof TContract
|
|
135
|
+
? ModelName extends string & keyof MongoModelsMap<TContract>
|
|
135
136
|
? Flatten<
|
|
136
137
|
InferModelRow<TContract, ModelName> &
|
|
137
138
|
Omit<
|