@prisma-next/sql-orm-client 0.5.0-dev.60 → 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/dist/index.d.mts +5 -16
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +48 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -18
- package/src/query-plan-mutations.ts +11 -7
- package/src/types.ts +44 -72
- package/src/where-binding.ts +5 -1
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-orm-client",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.61",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"description": "ORM client for Prisma Next — fluent, type-safe model collections",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@prisma-next/contract": "0.5.0-dev.
|
|
10
|
-
"@prisma-next/framework-components": "0.5.0-dev.
|
|
11
|
-
"@prisma-next/
|
|
12
|
-
"@prisma-next/operations": "0.5.0-dev.
|
|
13
|
-
"@prisma-next/sql-
|
|
14
|
-
"@prisma-next/sql-
|
|
15
|
-
"@prisma-next/utils": "0.5.0-dev.
|
|
16
|
-
"@prisma-next/sql-
|
|
9
|
+
"@prisma-next/contract": "0.5.0-dev.61",
|
|
10
|
+
"@prisma-next/framework-components": "0.5.0-dev.61",
|
|
11
|
+
"@prisma-next/operations": "0.5.0-dev.61",
|
|
12
|
+
"@prisma-next/sql-operations": "0.5.0-dev.61",
|
|
13
|
+
"@prisma-next/sql-relational-core": "0.5.0-dev.61",
|
|
14
|
+
"@prisma-next/sql-contract": "0.5.0-dev.61",
|
|
15
|
+
"@prisma-next/utils": "0.5.0-dev.61",
|
|
16
|
+
"@prisma-next/sql-runtime": "0.5.0-dev.61"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/pg": "8.16.0",
|
|
@@ -21,17 +21,17 @@
|
|
|
21
21
|
"tsdown": "0.18.4",
|
|
22
22
|
"typescript": "5.9.3",
|
|
23
23
|
"vitest": "4.0.17",
|
|
24
|
-
"@prisma-next/adapter-postgres": "0.5.0-dev.
|
|
25
|
-
"@prisma-next/
|
|
26
|
-
"@prisma-next/
|
|
27
|
-
"@prisma-next/
|
|
28
|
-
"@prisma-next/sql
|
|
29
|
-
"@prisma-next/
|
|
30
|
-
"@prisma-next/
|
|
31
|
-
"@prisma-next/
|
|
24
|
+
"@prisma-next/adapter-postgres": "0.5.0-dev.61",
|
|
25
|
+
"@prisma-next/cli": "0.5.0-dev.61",
|
|
26
|
+
"@prisma-next/driver-postgres": "0.5.0-dev.61",
|
|
27
|
+
"@prisma-next/extension-pgvector": "0.5.0-dev.61",
|
|
28
|
+
"@prisma-next/family-sql": "0.5.0-dev.61",
|
|
29
|
+
"@prisma-next/sql-contract-ts": "0.5.0-dev.61",
|
|
30
|
+
"@prisma-next/ids": "0.5.0-dev.61",
|
|
31
|
+
"@prisma-next/target-postgres": "0.5.0-dev.61",
|
|
32
32
|
"@prisma-next/tsconfig": "0.0.0",
|
|
33
33
|
"@prisma-next/tsdown": "0.0.0",
|
|
34
|
-
"@prisma-next/
|
|
34
|
+
"@prisma-next/test-utils": "0.0.1"
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
37
|
"dist",
|
|
@@ -51,7 +51,11 @@ function toParamAssignments(
|
|
|
51
51
|
if (!codecId) {
|
|
52
52
|
throw new Error(`Unknown column "${column}" in table "${tableName}"`);
|
|
53
53
|
}
|
|
54
|
-
assignments[column] = ParamRef.of(value, {
|
|
54
|
+
assignments[column] = ParamRef.of(value, {
|
|
55
|
+
name: column,
|
|
56
|
+
codecId,
|
|
57
|
+
refs: { table: tableName, column },
|
|
58
|
+
});
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
return { assignments };
|
|
@@ -97,7 +101,11 @@ function normalizeInsertRows(
|
|
|
97
101
|
if (!codecId) {
|
|
98
102
|
throw new Error(`Unknown column "${column}" in table "${tableName}"`);
|
|
99
103
|
}
|
|
100
|
-
normalizedRow[column] = ParamRef.of(row[column], {
|
|
104
|
+
normalizedRow[column] = ParamRef.of(row[column], {
|
|
105
|
+
name: column,
|
|
106
|
+
codecId,
|
|
107
|
+
refs: { table: tableName, column },
|
|
108
|
+
});
|
|
101
109
|
continue;
|
|
102
110
|
}
|
|
103
111
|
normalizedRow[column] = new DefaultValueExpr();
|
|
@@ -143,11 +151,7 @@ function stripUndefinedValues(row: Record<string, unknown>): Record<string, unkn
|
|
|
143
151
|
return result;
|
|
144
152
|
}
|
|
145
153
|
|
|
146
|
-
// Groups rows by their set of present columns so each group can be emitted as a
|
|
147
|
-
// single INSERT statement. Groups are created in input order — rows with the same
|
|
148
|
-
// signature that are non-adjacent produce separate groups. This is deliberate:
|
|
149
|
-
// preserving insertion order ensures autogenerated/autoincrement columns are
|
|
150
|
-
// assigned in the same order as the caller's input.
|
|
154
|
+
// Groups rows by their set of present columns so each group can be emitted as a single INSERT statement. Groups are created in input order — rows with the same signature that are non-adjacent produce separate groups. This is deliberate: preserving insertion order ensures autogenerated/autoincrement columns are assigned in the same order as the caller's input.
|
|
151
155
|
function groupRowsByColumnSignature(
|
|
152
156
|
rows: readonly Record<string, unknown>[],
|
|
153
157
|
): ReadonlyArray<readonly Record<string, unknown>[]> {
|
package/src/types.ts
CHANGED
|
@@ -19,12 +19,9 @@ import {
|
|
|
19
19
|
import type { Expression } from '@prisma-next/sql-relational-core/expression';
|
|
20
20
|
import type { ExecutionContext } from '@prisma-next/sql-relational-core/query-lane-context';
|
|
21
21
|
import type { ComputeColumnJsType, RuntimeScope } from '@prisma-next/sql-relational-core/types';
|
|
22
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
22
23
|
import type { RowSelection } from './collection-internal-types';
|
|
23
24
|
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// Comparison / Filter / Order / Include
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
|
|
28
25
|
export type AggregateFn = 'count' | 'sum' | 'avg' | 'min' | 'max';
|
|
29
26
|
|
|
30
27
|
export interface IncludeScalar<Result> extends RowSelection<Result> {
|
|
@@ -64,10 +61,6 @@ export interface IncludeExpr {
|
|
|
64
61
|
readonly combine: Readonly<Record<string, IncludeCombineBranch>> | undefined;
|
|
65
62
|
}
|
|
66
63
|
|
|
67
|
-
// ---------------------------------------------------------------------------
|
|
68
|
-
// CollectionState — plain data, no query builder types
|
|
69
|
-
// ---------------------------------------------------------------------------
|
|
70
|
-
|
|
71
64
|
export interface CollectionState {
|
|
72
65
|
readonly filters: readonly AnyExpression[];
|
|
73
66
|
readonly includes: readonly IncludeExpr[];
|
|
@@ -112,10 +105,6 @@ export type DefaultCollectionTypeState = {
|
|
|
112
105
|
readonly variantName: undefined;
|
|
113
106
|
};
|
|
114
107
|
|
|
115
|
-
// ---------------------------------------------------------------------------
|
|
116
|
-
// CollectionContext — bundles lane context + runtime
|
|
117
|
-
// ---------------------------------------------------------------------------
|
|
118
|
-
|
|
119
108
|
export interface RuntimeConnection extends RuntimeScope {
|
|
120
109
|
release?(): Promise<void>;
|
|
121
110
|
transaction?(): Promise<RuntimeTransaction>;
|
|
@@ -136,10 +125,6 @@ export interface CollectionContext<TContract extends Contract<SqlStorage>> {
|
|
|
136
125
|
readonly context: ExecutionContext<TContract>;
|
|
137
126
|
}
|
|
138
127
|
|
|
139
|
-
// ---------------------------------------------------------------------------
|
|
140
|
-
// ModelAccessor — type-safe proxy for where() callbacks
|
|
141
|
-
// ---------------------------------------------------------------------------
|
|
142
|
-
|
|
143
128
|
export type ComparisonMethodFns<T> = {
|
|
144
129
|
eq(value: T): AnyExpression;
|
|
145
130
|
neq(value: T): AnyExpression;
|
|
@@ -157,8 +142,7 @@ export type ComparisonMethodFns<T> = {
|
|
|
157
142
|
};
|
|
158
143
|
|
|
159
144
|
/**
|
|
160
|
-
* Trait-gated comparison methods. Only methods whose required traits are
|
|
161
|
-
* all present in `Traits` are included.
|
|
145
|
+
* Trait-gated comparison methods. Only methods whose required traits are all present in `Traits` are included.
|
|
162
146
|
*
|
|
163
147
|
* - `traits: []` → always available (isNull, isNotNull)
|
|
164
148
|
*/
|
|
@@ -168,10 +152,6 @@ export type ComparisonMethods<T, Traits> = {
|
|
|
168
152
|
: never]: ComparisonMethodFns<T>[K];
|
|
169
153
|
};
|
|
170
154
|
|
|
171
|
-
// ---------------------------------------------------------------------------
|
|
172
|
-
// Extension operation result — returned by calling an extension method
|
|
173
|
-
// ---------------------------------------------------------------------------
|
|
174
|
-
|
|
175
155
|
type QueryOperationReturnTraits<
|
|
176
156
|
Returns,
|
|
177
157
|
TCodecTypes extends Record<string, unknown>,
|
|
@@ -209,9 +189,7 @@ type IsBooleanReturn<Returns, TCodecTypes extends Record<string, unknown>> = Ret
|
|
|
209
189
|
: false;
|
|
210
190
|
|
|
211
191
|
/**
|
|
212
|
-
* Extract the `{codecId, nullable}` spec carried inside an `Expression<T>`.
|
|
213
|
-
* Used to recover the op's return spec from its impl signature so the
|
|
214
|
-
* pre-existing `QueryOperationReturn*` helpers can consume it unchanged.
|
|
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.
|
|
215
193
|
*/
|
|
216
194
|
type SpecOf<E> = E extends Expression<infer T> ? T : never;
|
|
217
195
|
|
|
@@ -220,14 +198,8 @@ type ImplReturnSpec<Impl> = Impl extends (...args: never[]) => infer Ret ? SpecO
|
|
|
220
198
|
/**
|
|
221
199
|
* Builds the ORM column-method signature for an operation.
|
|
222
200
|
*
|
|
223
|
-
* - User args: drops the impl's first parameter (the column is bound at access
|
|
224
|
-
*
|
|
225
|
-
* authored `CodecExpression` / `TraitExpression` shape — so callers can pass
|
|
226
|
-
* a raw JS value, another column handle (which itself implements
|
|
227
|
-
* `Expression`), or `null` when nullable.
|
|
228
|
-
* - Return: predicate ops (boolean-traited return) yield `AnyExpression`;
|
|
229
|
-
* non-predicate ops yield `ComparisonMethods<JsType, Traits>` of the return
|
|
230
|
-
* codec.
|
|
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.
|
|
231
203
|
*/
|
|
232
204
|
type QueryOperationMethod<Op, TCodecTypes extends Record<string, unknown>> = Op extends {
|
|
233
205
|
readonly impl: (...args: never[]) => unknown;
|
|
@@ -247,9 +219,7 @@ type QueryOperationMethod<Op, TCodecTypes extends Record<string, unknown>> = Op
|
|
|
247
219
|
: never;
|
|
248
220
|
|
|
249
221
|
/**
|
|
250
|
-
* Tests whether an operation's `self` dispatch hint reaches a field with the
|
|
251
|
-
* given codec identity. Codec hints match by identity; trait hints match when
|
|
252
|
-
* every required trait is present in the field codec's trait set.
|
|
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.
|
|
253
223
|
*/
|
|
254
224
|
type OpMatchesField<Op, CodecId extends string, CT extends Record<string, unknown>> = Op extends {
|
|
255
225
|
readonly self: infer Self;
|
|
@@ -285,21 +255,43 @@ type FieldOperations<
|
|
|
285
255
|
: unknown
|
|
286
256
|
: unknown;
|
|
287
257
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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
|
+
}
|
|
291
273
|
|
|
292
|
-
function param(
|
|
293
|
-
|
|
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
|
+
});
|
|
294
284
|
}
|
|
295
285
|
|
|
296
|
-
function paramList(
|
|
297
|
-
|
|
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)));
|
|
298
292
|
}
|
|
299
293
|
|
|
300
|
-
// never[] is intentional: factories have heterogeneous signatures (value: unknown,
|
|
301
|
-
// values: readonly unknown[], pattern: string, etc.) but are only called through
|
|
302
|
-
// 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.
|
|
303
295
|
type MethodFactory = (
|
|
304
296
|
left: AnyExpression,
|
|
305
297
|
codecId: string | undefined,
|
|
@@ -312,12 +304,16 @@ type ComparisonMethodMeta = {
|
|
|
312
304
|
|
|
313
305
|
function scalarComparisonMethod(op: BinaryOp) {
|
|
314
306
|
return ((left, codecId) => (value: unknown) =>
|
|
315
|
-
new BinaryExpr(op, left, param(codecId, value))) satisfies MethodFactory;
|
|
307
|
+
new BinaryExpr(op, left, param(codecId, value, refsFromLeft(left)))) satisfies MethodFactory;
|
|
316
308
|
}
|
|
317
309
|
|
|
318
310
|
function listComparisonMethod(op: BinaryOp) {
|
|
319
311
|
return ((left, codecId) => (values: readonly unknown[]) =>
|
|
320
|
-
new BinaryExpr(
|
|
312
|
+
new BinaryExpr(
|
|
313
|
+
op,
|
|
314
|
+
left,
|
|
315
|
+
paramList(codecId, values, refsFromLeft(left)),
|
|
316
|
+
)) satisfies MethodFactory;
|
|
321
317
|
}
|
|
322
318
|
|
|
323
319
|
/**
|
|
@@ -422,18 +418,10 @@ export type ModelAccessor<
|
|
|
422
418
|
ModelName extends string,
|
|
423
419
|
> = ScalarModelAccessor<TContract, ModelName> & RelationModelAccessor<TContract, ModelName>;
|
|
424
420
|
|
|
425
|
-
// ---------------------------------------------------------------------------
|
|
426
|
-
// DefaultModelRow — all scalar fields with JS types
|
|
427
|
-
// ---------------------------------------------------------------------------
|
|
428
|
-
|
|
429
421
|
export type DefaultModelRow<TContract extends Contract<SqlStorage>, ModelName extends string> = {
|
|
430
422
|
[K in keyof FieldsOf<TContract, ModelName> & string]: FieldJsType<TContract, ModelName, K>;
|
|
431
423
|
};
|
|
432
424
|
|
|
433
|
-
// ---------------------------------------------------------------------------
|
|
434
|
-
// InferRootRow — discriminated union for polymorphic base models
|
|
435
|
-
// ---------------------------------------------------------------------------
|
|
436
|
-
|
|
437
425
|
type Simplify<T> = { [K in keyof T]: T[K] } & {};
|
|
438
426
|
|
|
439
427
|
type VariantRow<TContract extends Contract<SqlStorage>, ModelName extends string> = ModelDef<
|
|
@@ -554,10 +542,6 @@ export type ShorthandWhereFilter<
|
|
|
554
542
|
| undefined;
|
|
555
543
|
}>;
|
|
556
544
|
|
|
557
|
-
// ---------------------------------------------------------------------------
|
|
558
|
-
// Helpers for extracting fields / types from the contract
|
|
559
|
-
// ---------------------------------------------------------------------------
|
|
560
|
-
|
|
561
545
|
type ModelsOf<TContract extends Contract<SqlStorage>> =
|
|
562
546
|
TContract['models'] extends Record<string, unknown> ? TContract['models'] : Record<string, never>;
|
|
563
547
|
|
|
@@ -671,10 +655,6 @@ type FieldStorageColumn<
|
|
|
671
655
|
FieldName extends string,
|
|
672
656
|
> = ResolvedStorageColumn<TContract, ModelName, FieldName>;
|
|
673
657
|
|
|
674
|
-
// ---------------------------------------------------------------------------
|
|
675
|
-
// Field trait resolution from contract CodecTypes
|
|
676
|
-
// ---------------------------------------------------------------------------
|
|
677
|
-
|
|
678
658
|
type FieldCodecId<
|
|
679
659
|
TContract extends Contract<SqlStorage>,
|
|
680
660
|
ModelName extends string,
|
|
@@ -795,10 +775,6 @@ export type CreateInput<TContract extends Contract<SqlStorage>, ModelName extend
|
|
|
795
775
|
> &
|
|
796
776
|
RelationMutationFields<TContract, ModelName>;
|
|
797
777
|
|
|
798
|
-
// ---------------------------------------------------------------------------
|
|
799
|
-
// Polymorphic write gating
|
|
800
|
-
// ---------------------------------------------------------------------------
|
|
801
|
-
|
|
802
778
|
type IsPolymorphicBase<TContract extends Contract<SqlStorage>, ModelName extends string> = ModelDef<
|
|
803
779
|
TContract,
|
|
804
780
|
ModelName
|
|
@@ -1070,10 +1046,6 @@ export type MutationUpdateInput<
|
|
|
1070
1046
|
ModelName extends string,
|
|
1071
1047
|
> = Partial<DefaultModelRow<TContract, ModelName>> & RelationMutationFields<TContract, ModelName>;
|
|
1072
1048
|
|
|
1073
|
-
// ---------------------------------------------------------------------------
|
|
1074
|
-
// Relation helpers
|
|
1075
|
-
// ---------------------------------------------------------------------------
|
|
1076
|
-
|
|
1077
1049
|
type ModelRelations<TContract extends Contract<SqlStorage>, ModelName extends string> = ModelDef<
|
|
1078
1050
|
TContract,
|
|
1079
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 {
|
|
@@ -174,6 +177,7 @@ function bindSelectAst(contract: Contract<SqlStorage>, ast: SelectAst): SelectAs
|
|
|
174
177
|
projection.alias,
|
|
175
178
|
bindProjectionExpr(contract, projection.expr),
|
|
176
179
|
projection.codecId,
|
|
180
|
+
projection.refs,
|
|
177
181
|
),
|
|
178
182
|
),
|
|
179
183
|
where: ast.where ? bindWhereExprNode(contract, ast.where) : undefined,
|