@prisma-next/sql-orm-client 0.5.0-dev.8 → 0.5.0-dev.85
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 +11 -1
- package/dist/index.d.mts +53 -45
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +310 -214
- package/dist/index.mjs.map +1 -1
- package/package.json +22 -22
- package/src/collection-contract.ts +19 -0
- package/src/collection-dispatch.ts +2 -2
- package/src/collection-mutation-dispatch.ts +1 -1
- package/src/collection-runtime.ts +3 -2
- package/src/collection.ts +104 -9
- package/src/execute-query-plan.ts +4 -5
- package/src/filters.ts +1 -1
- package/src/include-strategy.ts +36 -14
- package/src/model-accessor.ts +69 -63
- package/src/mutation-executor.ts +10 -2
- package/src/query-plan-aggregate.ts +32 -13
- package/src/query-plan-meta.ts +6 -66
- package/src/query-plan-mutations.ts +31 -23
- package/src/query-plan-select.ts +16 -6
- package/src/types.ts +88 -103
- package/src/where-binding.ts +10 -2
package/src/types.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { Contract
|
|
2
|
-
import type { AsyncIterableResult } from '@prisma-next/runtime-executor';
|
|
1
|
+
import type { Contract } from '@prisma-next/contract/types';
|
|
3
2
|
import type {
|
|
4
3
|
ExtractCodecTypes,
|
|
5
4
|
ExtractQueryOperationTypes,
|
|
@@ -17,15 +16,12 @@ import {
|
|
|
17
16
|
OrderByItem,
|
|
18
17
|
ParamRef,
|
|
19
18
|
} from '@prisma-next/sql-relational-core/ast';
|
|
20
|
-
import type {
|
|
19
|
+
import type { Expression } from '@prisma-next/sql-relational-core/expression';
|
|
21
20
|
import type { ExecutionContext } from '@prisma-next/sql-relational-core/query-lane-context';
|
|
22
|
-
import type { ComputeColumnJsType } from '@prisma-next/sql-relational-core/types';
|
|
21
|
+
import type { ComputeColumnJsType, RuntimeScope } from '@prisma-next/sql-relational-core/types';
|
|
22
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
23
23
|
import type { RowSelection } from './collection-internal-types';
|
|
24
24
|
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
// Comparison / Filter / Order / Include
|
|
27
|
-
// ---------------------------------------------------------------------------
|
|
28
|
-
|
|
29
25
|
export type AggregateFn = 'count' | 'sum' | 'avg' | 'min' | 'max';
|
|
30
26
|
|
|
31
27
|
export interface IncludeScalar<Result> extends RowSelection<Result> {
|
|
@@ -65,10 +61,6 @@ export interface IncludeExpr {
|
|
|
65
61
|
readonly combine: Readonly<Record<string, IncludeCombineBranch>> | undefined;
|
|
66
62
|
}
|
|
67
63
|
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
|
-
// CollectionState — plain data, no query builder types
|
|
70
|
-
// ---------------------------------------------------------------------------
|
|
71
|
-
|
|
72
64
|
export interface CollectionState {
|
|
73
65
|
readonly filters: readonly AnyExpression[];
|
|
74
66
|
readonly includes: readonly IncludeExpr[];
|
|
@@ -113,16 +105,6 @@ export type DefaultCollectionTypeState = {
|
|
|
113
105
|
readonly variantName: undefined;
|
|
114
106
|
};
|
|
115
107
|
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
|
-
// CollectionContext — bundles lane context + runtime
|
|
118
|
-
// ---------------------------------------------------------------------------
|
|
119
|
-
|
|
120
|
-
export interface RuntimeScope {
|
|
121
|
-
execute<Row = Record<string, unknown>>(
|
|
122
|
-
plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
|
|
123
|
-
): AsyncIterableResult<Row>;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
108
|
export interface RuntimeConnection extends RuntimeScope {
|
|
127
109
|
release?(): Promise<void>;
|
|
128
110
|
transaction?(): Promise<RuntimeTransaction>;
|
|
@@ -143,10 +125,6 @@ export interface CollectionContext<TContract extends Contract<SqlStorage>> {
|
|
|
143
125
|
readonly context: ExecutionContext<TContract>;
|
|
144
126
|
}
|
|
145
127
|
|
|
146
|
-
// ---------------------------------------------------------------------------
|
|
147
|
-
// ModelAccessor — type-safe proxy for where() callbacks
|
|
148
|
-
// ---------------------------------------------------------------------------
|
|
149
|
-
|
|
150
128
|
export type ComparisonMethodFns<T> = {
|
|
151
129
|
eq(value: T): AnyExpression;
|
|
152
130
|
neq(value: T): AnyExpression;
|
|
@@ -164,8 +142,7 @@ export type ComparisonMethodFns<T> = {
|
|
|
164
142
|
};
|
|
165
143
|
|
|
166
144
|
/**
|
|
167
|
-
* Trait-gated comparison methods. Only methods whose required traits are
|
|
168
|
-
* all present in `Traits` are included.
|
|
145
|
+
* Trait-gated comparison methods. Only methods whose required traits are all present in `Traits` are included.
|
|
169
146
|
*
|
|
170
147
|
* - `traits: []` → always available (isNull, isNotNull)
|
|
171
148
|
*/
|
|
@@ -175,10 +152,6 @@ export type ComparisonMethods<T, Traits> = {
|
|
|
175
152
|
: never]: ComparisonMethodFns<T>[K];
|
|
176
153
|
};
|
|
177
154
|
|
|
178
|
-
// ---------------------------------------------------------------------------
|
|
179
|
-
// Extension operation result — returned by calling an extension method
|
|
180
|
-
// ---------------------------------------------------------------------------
|
|
181
|
-
|
|
182
155
|
type QueryOperationReturnTraits<
|
|
183
156
|
Returns,
|
|
184
157
|
TCodecTypes extends Record<string, unknown>,
|
|
@@ -203,26 +176,6 @@ type QueryOperationReturnJsType<
|
|
|
203
176
|
: unknown
|
|
204
177
|
: unknown;
|
|
205
178
|
|
|
206
|
-
type CodecArgJsType<Arg, TCodecTypes extends Record<string, unknown>> = Arg extends {
|
|
207
|
-
readonly codecId: infer CId extends string;
|
|
208
|
-
readonly nullable: infer N;
|
|
209
|
-
}
|
|
210
|
-
? CId extends keyof TCodecTypes
|
|
211
|
-
? TCodecTypes[CId] extends { readonly output: infer O }
|
|
212
|
-
? N extends true
|
|
213
|
-
? O | null
|
|
214
|
-
: O
|
|
215
|
-
: unknown
|
|
216
|
-
: unknown
|
|
217
|
-
: unknown;
|
|
218
|
-
|
|
219
|
-
type MapArgsToJsTypes<
|
|
220
|
-
Args extends readonly unknown[],
|
|
221
|
-
TCodecTypes extends Record<string, unknown>,
|
|
222
|
-
> = Args extends readonly [infer Head, ...infer Tail]
|
|
223
|
-
? [CodecArgJsType<Head, TCodecTypes>, ...MapArgsToJsTypes<Tail, TCodecTypes>]
|
|
224
|
-
: [];
|
|
225
|
-
|
|
226
179
|
type IsBooleanReturn<Returns, TCodecTypes extends Record<string, unknown>> = Returns extends {
|
|
227
180
|
readonly codecId: infer Id extends string;
|
|
228
181
|
}
|
|
@@ -235,22 +188,41 @@ type IsBooleanReturn<Returns, TCodecTypes extends Record<string, unknown>> = Ret
|
|
|
235
188
|
: false
|
|
236
189
|
: false;
|
|
237
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Extract the `{codecId, nullable}` spec carried inside an `Expression<T>`. Used to recover the op's return spec from its impl signature so the pre-existing `QueryOperationReturn*` helpers can consume it unchanged.
|
|
193
|
+
*/
|
|
194
|
+
type SpecOf<E> = E extends Expression<infer T> ? T : never;
|
|
195
|
+
|
|
196
|
+
type ImplReturnSpec<Impl> = Impl extends (...args: never[]) => infer Ret ? SpecOf<Ret> : never;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Builds the ORM column-method signature for an operation.
|
|
200
|
+
*
|
|
201
|
+
* - User args: drops the impl's first parameter (the column is bound at access time) and forwards the rest unchanged. Each remaining arg keeps its authored `CodecExpression` / `TraitExpression` shape — so callers can pass a raw JS value, another column handle (which itself implements `Expression`), or `null` when nullable.
|
|
202
|
+
* - Return: predicate ops (boolean-traited return) yield `AnyExpression`; non-predicate ops yield `ComparisonMethods<JsType, Traits>` of the return codec.
|
|
203
|
+
*/
|
|
238
204
|
type QueryOperationMethod<Op, TCodecTypes extends Record<string, unknown>> = Op extends {
|
|
239
|
-
readonly args:
|
|
240
|
-
readonly returns: infer Returns;
|
|
205
|
+
readonly impl: (...args: never[]) => unknown;
|
|
241
206
|
}
|
|
242
|
-
?
|
|
243
|
-
?
|
|
244
|
-
|
|
245
|
-
...args:
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
207
|
+
? Op['impl'] extends (first: never, ...rest: infer UserArgs extends readonly unknown[]) => unknown
|
|
208
|
+
? ImplReturnSpec<Op['impl']> extends infer Returns
|
|
209
|
+
? IsBooleanReturn<Returns, TCodecTypes> extends true
|
|
210
|
+
? (...args: UserArgs) => AnyExpression
|
|
211
|
+
: (
|
|
212
|
+
...args: UserArgs
|
|
213
|
+
) => ComparisonMethods<
|
|
214
|
+
QueryOperationReturnJsType<Returns, TCodecTypes>,
|
|
215
|
+
QueryOperationReturnTraits<Returns, TCodecTypes>
|
|
216
|
+
>
|
|
217
|
+
: never
|
|
218
|
+
: never
|
|
250
219
|
: never;
|
|
251
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Tests whether an operation's `self` dispatch hint reaches a field with the given codec identity. Codec hints match by identity; trait hints match when every required trait is present in the field codec's trait set.
|
|
223
|
+
*/
|
|
252
224
|
type OpMatchesField<Op, CodecId extends string, CT extends Record<string, unknown>> = Op extends {
|
|
253
|
-
readonly
|
|
225
|
+
readonly self: infer Self;
|
|
254
226
|
}
|
|
255
227
|
? Self extends { readonly codecId: CodecId }
|
|
256
228
|
? true
|
|
@@ -283,21 +255,43 @@ type FieldOperations<
|
|
|
283
255
|
: unknown
|
|
284
256
|
: unknown;
|
|
285
257
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
258
|
+
/**
|
|
259
|
+
* Resolve the unique column ref carried by `left` so its surrounding `ParamRef` can dispatch through `forColumn`. The previous implementation only matched bare `column-ref` expressions, which lost refs the moment the expression got wrapped (`upper(f.id)`, `BinaryExpr`, function-call expressions, etc.) — and column-aware dispatch (AC-5) silently degraded for any predicate that touched a computed column.
|
|
260
|
+
*
|
|
261
|
+
* Walking via `collectColumnRefs()` and accepting only a single unambiguous ref gives `eq(upper(f.id), value)` and friends correct dispatch without inventing refs for ambiguous shapes (e.g. `eq(concat(f.firstName, f.lastName), value)` returns `undefined` and falls through to the codec-id path, which is correct for non-parameterized comparisons).
|
|
262
|
+
*/
|
|
263
|
+
function refsFromLeft(left: AnyExpression): { table: string; column: string } | undefined {
|
|
264
|
+
if (left.kind === 'column-ref') {
|
|
265
|
+
return { table: left.table, column: left.column };
|
|
266
|
+
}
|
|
267
|
+
const columnRefs = left.collectColumnRefs();
|
|
268
|
+
if (columnRefs.length !== 1) return undefined;
|
|
269
|
+
const single = columnRefs[0];
|
|
270
|
+
if (!single) return undefined;
|
|
271
|
+
return { table: single.table, column: single.column };
|
|
272
|
+
}
|
|
289
273
|
|
|
290
|
-
function param(
|
|
291
|
-
|
|
274
|
+
function param(
|
|
275
|
+
codecId: string | undefined,
|
|
276
|
+
value: unknown,
|
|
277
|
+
refs: { table: string; column: string } | undefined,
|
|
278
|
+
): ParamRef {
|
|
279
|
+
if (codecId === undefined && refs === undefined) return ParamRef.of(value);
|
|
280
|
+
return ParamRef.of(value, {
|
|
281
|
+
...ifDefined('codecId', codecId),
|
|
282
|
+
...ifDefined('refs', refs),
|
|
283
|
+
});
|
|
292
284
|
}
|
|
293
285
|
|
|
294
|
-
function paramList(
|
|
295
|
-
|
|
286
|
+
function paramList(
|
|
287
|
+
codecId: string | undefined,
|
|
288
|
+
values: readonly unknown[],
|
|
289
|
+
refs: { table: string; column: string } | undefined,
|
|
290
|
+
): ListExpression {
|
|
291
|
+
return ListExpression.of(values.map((value) => param(codecId, value, refs)));
|
|
296
292
|
}
|
|
297
293
|
|
|
298
|
-
// never[] is intentional: factories have heterogeneous signatures (value: unknown,
|
|
299
|
-
// values: readonly unknown[], pattern: string, etc.) but are only called through
|
|
300
|
-
// the typed ComparisonMethodFns interface, never through this type directly.
|
|
294
|
+
// never[] is intentional: factories have heterogeneous signatures (value: unknown, values: readonly unknown[], pattern: string, etc.) but are only called through the typed ComparisonMethodFns interface, never through this type directly.
|
|
301
295
|
type MethodFactory = (
|
|
302
296
|
left: AnyExpression,
|
|
303
297
|
codecId: string | undefined,
|
|
@@ -310,12 +304,16 @@ type ComparisonMethodMeta = {
|
|
|
310
304
|
|
|
311
305
|
function scalarComparisonMethod(op: BinaryOp) {
|
|
312
306
|
return ((left, codecId) => (value: unknown) =>
|
|
313
|
-
new BinaryExpr(op, left, param(codecId, value))) satisfies MethodFactory;
|
|
307
|
+
new BinaryExpr(op, left, param(codecId, value, refsFromLeft(left)))) satisfies MethodFactory;
|
|
314
308
|
}
|
|
315
309
|
|
|
316
310
|
function listComparisonMethod(op: BinaryOp) {
|
|
317
311
|
return ((left, codecId) => (values: readonly unknown[]) =>
|
|
318
|
-
new BinaryExpr(
|
|
312
|
+
new BinaryExpr(
|
|
313
|
+
op,
|
|
314
|
+
left,
|
|
315
|
+
paramList(codecId, values, refsFromLeft(left)),
|
|
316
|
+
)) satisfies MethodFactory;
|
|
319
317
|
}
|
|
320
318
|
|
|
321
319
|
/**
|
|
@@ -400,10 +398,11 @@ export type RelationFilterAccessor<
|
|
|
400
398
|
};
|
|
401
399
|
|
|
402
400
|
type ScalarModelAccessor<TContract extends Contract<SqlStorage>, ModelName extends string> = {
|
|
403
|
-
[K in keyof FieldsOf<TContract, ModelName> & string]:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
> &
|
|
401
|
+
[K in keyof FieldsOf<TContract, ModelName> & string]: Expression<{
|
|
402
|
+
codecId: FieldCodecId<TContract, ModelName, K>;
|
|
403
|
+
nullable: FieldNullable<TContract, ModelName, K>;
|
|
404
|
+
}> &
|
|
405
|
+
ComparisonMethods<FieldJsType<TContract, ModelName, K>, FieldTraits<TContract, ModelName, K>> &
|
|
407
406
|
FieldOperations<TContract, ModelName, K>;
|
|
408
407
|
};
|
|
409
408
|
|
|
@@ -419,18 +418,10 @@ export type ModelAccessor<
|
|
|
419
418
|
ModelName extends string,
|
|
420
419
|
> = ScalarModelAccessor<TContract, ModelName> & RelationModelAccessor<TContract, ModelName>;
|
|
421
420
|
|
|
422
|
-
// ---------------------------------------------------------------------------
|
|
423
|
-
// DefaultModelRow — all scalar fields with JS types
|
|
424
|
-
// ---------------------------------------------------------------------------
|
|
425
|
-
|
|
426
421
|
export type DefaultModelRow<TContract extends Contract<SqlStorage>, ModelName extends string> = {
|
|
427
422
|
[K in keyof FieldsOf<TContract, ModelName> & string]: FieldJsType<TContract, ModelName, K>;
|
|
428
423
|
};
|
|
429
424
|
|
|
430
|
-
// ---------------------------------------------------------------------------
|
|
431
|
-
// InferRootRow — discriminated union for polymorphic base models
|
|
432
|
-
// ---------------------------------------------------------------------------
|
|
433
|
-
|
|
434
425
|
type Simplify<T> = { [K in keyof T]: T[K] } & {};
|
|
435
426
|
|
|
436
427
|
type VariantRow<TContract extends Contract<SqlStorage>, ModelName extends string> = ModelDef<
|
|
@@ -551,10 +542,6 @@ export type ShorthandWhereFilter<
|
|
|
551
542
|
| undefined;
|
|
552
543
|
}>;
|
|
553
544
|
|
|
554
|
-
// ---------------------------------------------------------------------------
|
|
555
|
-
// Helpers for extracting fields / types from the contract
|
|
556
|
-
// ---------------------------------------------------------------------------
|
|
557
|
-
|
|
558
545
|
type ModelsOf<TContract extends Contract<SqlStorage>> =
|
|
559
546
|
TContract['models'] extends Record<string, unknown> ? TContract['models'] : Record<string, never>;
|
|
560
547
|
|
|
@@ -668,10 +655,6 @@ type FieldStorageColumn<
|
|
|
668
655
|
FieldName extends string,
|
|
669
656
|
> = ResolvedStorageColumn<TContract, ModelName, FieldName>;
|
|
670
657
|
|
|
671
|
-
// ---------------------------------------------------------------------------
|
|
672
|
-
// Field trait resolution from contract CodecTypes
|
|
673
|
-
// ---------------------------------------------------------------------------
|
|
674
|
-
|
|
675
658
|
type FieldCodecId<
|
|
676
659
|
TContract extends Contract<SqlStorage>,
|
|
677
660
|
ModelName extends string,
|
|
@@ -682,6 +665,16 @@ type FieldCodecId<
|
|
|
682
665
|
? Id
|
|
683
666
|
: never;
|
|
684
667
|
|
|
668
|
+
type FieldNullable<
|
|
669
|
+
TContract extends Contract<SqlStorage>,
|
|
670
|
+
ModelName extends string,
|
|
671
|
+
FieldName extends string,
|
|
672
|
+
> = FieldStorageColumn<TContract, ModelName, FieldName> extends {
|
|
673
|
+
readonly nullable: infer N extends boolean;
|
|
674
|
+
}
|
|
675
|
+
? N
|
|
676
|
+
: false;
|
|
677
|
+
|
|
685
678
|
type FieldTraits<
|
|
686
679
|
TContract extends Contract<SqlStorage>,
|
|
687
680
|
ModelName extends string,
|
|
@@ -782,10 +775,6 @@ export type CreateInput<TContract extends Contract<SqlStorage>, ModelName extend
|
|
|
782
775
|
> &
|
|
783
776
|
RelationMutationFields<TContract, ModelName>;
|
|
784
777
|
|
|
785
|
-
// ---------------------------------------------------------------------------
|
|
786
|
-
// Polymorphic write gating
|
|
787
|
-
// ---------------------------------------------------------------------------
|
|
788
|
-
|
|
789
778
|
type IsPolymorphicBase<TContract extends Contract<SqlStorage>, ModelName extends string> = ModelDef<
|
|
790
779
|
TContract,
|
|
791
780
|
ModelName
|
|
@@ -1057,10 +1046,6 @@ export type MutationUpdateInput<
|
|
|
1057
1046
|
ModelName extends string,
|
|
1058
1047
|
> = Partial<DefaultModelRow<TContract, ModelName>> & RelationMutationFields<TContract, ModelName>;
|
|
1059
1048
|
|
|
1060
|
-
// ---------------------------------------------------------------------------
|
|
1061
|
-
// Relation helpers
|
|
1062
|
-
// ---------------------------------------------------------------------------
|
|
1063
|
-
|
|
1064
1049
|
type ModelRelations<TContract extends Contract<SqlStorage>, ModelName extends string> = ModelDef<
|
|
1065
1050
|
TContract,
|
|
1066
1051
|
ModelName
|
package/src/where-binding.ts
CHANGED
|
@@ -122,7 +122,10 @@ function createParamRef(
|
|
|
122
122
|
if (!codecId) {
|
|
123
123
|
throw new Error(`Unknown column "${columnRef.column}" in table "${columnRef.table}"`);
|
|
124
124
|
}
|
|
125
|
-
return ParamRef.of(value, {
|
|
125
|
+
return ParamRef.of(value, {
|
|
126
|
+
codecId,
|
|
127
|
+
refs: { table: columnRef.table, column: columnRef.column },
|
|
128
|
+
});
|
|
126
129
|
}
|
|
127
130
|
|
|
128
131
|
function createExpressionBinder(contract: Contract<SqlStorage>): ExpressionRewriter {
|
|
@@ -170,7 +173,12 @@ function bindSelectAst(contract: Contract<SqlStorage>, ast: SelectAst): SelectAs
|
|
|
170
173
|
joins: ast.joins?.map((join) => bindJoin(contract, join)),
|
|
171
174
|
projection: ast.projection.map(
|
|
172
175
|
(projection) =>
|
|
173
|
-
new ProjectionItem(
|
|
176
|
+
new ProjectionItem(
|
|
177
|
+
projection.alias,
|
|
178
|
+
bindProjectionExpr(contract, projection.expr),
|
|
179
|
+
projection.codecId,
|
|
180
|
+
projection.refs,
|
|
181
|
+
),
|
|
174
182
|
),
|
|
175
183
|
where: ast.where ? bindWhereExprNode(contract, ast.where) : undefined,
|
|
176
184
|
orderBy: ast.orderBy?.map((orderItem) => bindOrderByItem(contract, orderItem)),
|