@prisma-next/sql-relational-core 0.3.0-dev.11 → 0.3.0-dev.113
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/LICENSE +201 -0
- package/README.md +18 -1
- package/dist/errors-BNiBIGfC.d.mts +2 -0
- package/dist/errors-DXSQwbhk.mjs +3 -0
- package/dist/exports/ast.d.mts +126 -0
- package/dist/exports/ast.d.mts.map +1 -0
- package/dist/exports/ast.mjs +253 -0
- package/dist/exports/ast.mjs.map +1 -0
- package/dist/exports/errors.d.mts +2 -0
- package/dist/exports/errors.mjs +3 -0
- package/dist/exports/guards.d.mts +5 -0
- package/dist/exports/guards.mjs +3 -0
- package/dist/exports/operations-registry.d.mts +5 -0
- package/dist/exports/operations-registry.mjs +3 -0
- package/dist/exports/param.d.mts +5 -0
- package/dist/exports/param.mjs +3 -0
- package/dist/exports/plan.d.mts +2 -0
- package/dist/exports/plan.mjs +17 -0
- package/dist/exports/plan.mjs.map +1 -0
- package/dist/exports/query-lane-context.d.mts +2 -0
- package/dist/exports/query-lane-context.mjs +1 -0
- package/dist/exports/query-operations.d.mts +2 -0
- package/dist/exports/query-operations.mjs +18 -0
- package/dist/exports/query-operations.mjs.map +1 -0
- package/dist/exports/schema.d.mts +5 -0
- package/dist/exports/schema.mjs +4 -0
- package/dist/exports/types.d.mts +4 -0
- package/dist/exports/types.mjs +3 -0
- package/dist/exports/utils/guards.d.mts +5 -0
- package/dist/exports/utils/guards.mjs +3 -0
- package/dist/guards-D1ax7TKN.mjs +57 -0
- package/dist/guards-D1ax7TKN.mjs.map +1 -0
- package/dist/guards-DC2Ll67p.d.mts +31 -0
- package/dist/guards-DC2Ll67p.d.mts.map +1 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.mjs +13 -0
- package/dist/operations-registry-CBmGut8O.d.mts +9 -0
- package/dist/operations-registry-CBmGut8O.d.mts.map +1 -0
- package/dist/operations-registry-D8INFH9J.mjs +145 -0
- package/dist/operations-registry-D8INFH9J.mjs.map +1 -0
- package/dist/param-CFyhvphn.mjs +14 -0
- package/dist/param-CFyhvphn.mjs.map +1 -0
- package/dist/param-Cmdv_exJ.d.mts +8 -0
- package/dist/param-Cmdv_exJ.d.mts.map +1 -0
- package/dist/plan-BrZtMUA9.d.mts +517 -0
- package/dist/plan-BrZtMUA9.d.mts.map +1 -0
- package/dist/query-lane-context-BTtg0xm8.d.mts +278 -0
- package/dist/query-lane-context-BTtg0xm8.d.mts.map +1 -0
- package/dist/query-operation-registry-B6bClJs8.d.mts +27 -0
- package/dist/query-operation-registry-B6bClJs8.d.mts.map +1 -0
- package/dist/schema-XcyJSq4j.mjs +174 -0
- package/dist/schema-XcyJSq4j.mjs.map +1 -0
- package/dist/schema-j3Srik3R.d.mts +88 -0
- package/dist/schema-j3Srik3R.d.mts.map +1 -0
- package/dist/types-BZKzxgOb.mjs +18 -0
- package/dist/types-BZKzxgOb.mjs.map +1 -0
- package/dist/types-CMyotK6U.d.mts +443 -0
- package/dist/types-CMyotK6U.d.mts.map +1 -0
- package/dist/types-I6Hsg-GU.mjs +1102 -0
- package/dist/types-I6Hsg-GU.mjs.map +1 -0
- package/package.json +40 -56
- package/src/ast/codec-types.ts +123 -22
- package/src/ast/driver-types.ts +20 -3
- package/src/ast/join.ts +3 -23
- package/src/ast/sql-codecs.ts +81 -0
- package/src/ast/types.ts +1704 -74
- package/src/exports/ast.ts +1 -7
- package/src/exports/guards.ts +3 -4
- package/src/exports/query-operations.ts +1 -0
- package/src/exports/utils/guards.ts +1 -0
- package/src/operations-registry.ts +115 -89
- package/src/plan.ts +4 -4
- package/src/query-lane-context.ts +79 -1
- package/src/query-operation-registry.ts +35 -0
- package/src/schema.ts +104 -43
- package/src/types.ts +333 -84
- package/src/utils/guards.ts +44 -80
- package/dist/ast/adapter-types.d.ts +0 -28
- package/dist/ast/adapter-types.d.ts.map +0 -1
- package/dist/ast/codec-types.d.ts +0 -141
- package/dist/ast/codec-types.d.ts.map +0 -1
- package/dist/ast/common.d.ts +0 -7
- package/dist/ast/common.d.ts.map +0 -1
- package/dist/ast/delete.d.ts +0 -8
- package/dist/ast/delete.d.ts.map +0 -1
- package/dist/ast/driver-types.d.ts +0 -20
- package/dist/ast/driver-types.d.ts.map +0 -1
- package/dist/ast/insert.d.ts +0 -8
- package/dist/ast/insert.d.ts.map +0 -1
- package/dist/ast/join.d.ts +0 -6
- package/dist/ast/join.d.ts.map +0 -1
- package/dist/ast/order.d.ts +0 -6
- package/dist/ast/order.d.ts.map +0 -1
- package/dist/ast/predicate.d.ts +0 -4
- package/dist/ast/predicate.d.ts.map +0 -1
- package/dist/ast/select.d.ts +0 -18
- package/dist/ast/select.d.ts.map +0 -1
- package/dist/ast/types.d.ts +0 -118
- package/dist/ast/types.d.ts.map +0 -1
- package/dist/ast/update.d.ts +0 -9
- package/dist/ast/update.d.ts.map +0 -1
- package/dist/ast/util.d.ts +0 -2
- package/dist/ast/util.d.ts.map +0 -1
- package/dist/chunk-2F7DSEOU.js +0 -8
- package/dist/chunk-2F7DSEOU.js.map +0 -1
- package/dist/chunk-36WJWNHT.js +0 -1
- package/dist/chunk-36WJWNHT.js.map +0 -1
- package/dist/chunk-5N34PNVZ.js +0 -62
- package/dist/chunk-5N34PNVZ.js.map +0 -1
- package/dist/chunk-7I3EMQID.js +0 -16
- package/dist/chunk-7I3EMQID.js.map +0 -1
- package/dist/chunk-CBTYMOX2.js +0 -152
- package/dist/chunk-CBTYMOX2.js.map +0 -1
- package/dist/chunk-G52ENULI.js +0 -1
- package/dist/chunk-G52ENULI.js.map +0 -1
- package/dist/chunk-KYSP7L5C.js +0 -16
- package/dist/chunk-KYSP7L5C.js.map +0 -1
- package/dist/chunk-M23L3JHG.js +0 -159
- package/dist/chunk-M23L3JHG.js.map +0 -1
- package/dist/chunk-MM74SVJ4.js +0 -13
- package/dist/chunk-MM74SVJ4.js.map +0 -1
- package/dist/chunk-U7AXAUJA.js +0 -1
- package/dist/chunk-U7AXAUJA.js.map +0 -1
- package/dist/chunk-WZBPVEZI.js +0 -320
- package/dist/chunk-WZBPVEZI.js.map +0 -1
- package/dist/errors.d.ts +0 -2
- package/dist/errors.d.ts.map +0 -1
- package/dist/exports/ast.d.ts +0 -14
- package/dist/exports/ast.d.ts.map +0 -1
- package/dist/exports/ast.js +0 -46
- package/dist/exports/ast.js.map +0 -1
- package/dist/exports/errors.d.ts +0 -2
- package/dist/exports/errors.d.ts.map +0 -1
- package/dist/exports/errors.js +0 -9
- package/dist/exports/errors.js.map +0 -1
- package/dist/exports/guards.d.ts +0 -2
- package/dist/exports/guards.d.ts.map +0 -1
- package/dist/exports/guards.js +0 -21
- package/dist/exports/guards.js.map +0 -1
- package/dist/exports/operations-registry.d.ts +0 -2
- package/dist/exports/operations-registry.d.ts.map +0 -1
- package/dist/exports/operations-registry.js +0 -9
- package/dist/exports/operations-registry.js.map +0 -1
- package/dist/exports/param.d.ts +0 -3
- package/dist/exports/param.d.ts.map +0 -1
- package/dist/exports/param.js +0 -7
- package/dist/exports/param.js.map +0 -1
- package/dist/exports/plan.d.ts +0 -2
- package/dist/exports/plan.d.ts.map +0 -1
- package/dist/exports/plan.js +0 -7
- package/dist/exports/plan.js.map +0 -1
- package/dist/exports/query-lane-context.d.ts +0 -2
- package/dist/exports/query-lane-context.d.ts.map +0 -1
- package/dist/exports/query-lane-context.js +0 -2
- package/dist/exports/query-lane-context.js.map +0 -1
- package/dist/exports/schema.d.ts +0 -3
- package/dist/exports/schema.d.ts.map +0 -1
- package/dist/exports/schema.js +0 -14
- package/dist/exports/schema.js.map +0 -1
- package/dist/exports/types.d.ts +0 -2
- package/dist/exports/types.d.ts.map +0 -1
- package/dist/exports/types.js +0 -10
- package/dist/exports/types.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -81
- package/dist/index.js.map +0 -1
- package/dist/operations-registry.d.ts +0 -5
- package/dist/operations-registry.d.ts.map +0 -1
- package/dist/param.d.ts +0 -4
- package/dist/param.d.ts.map +0 -1
- package/dist/plan.d.ts +0 -23
- package/dist/plan.d.ts.map +0 -1
- package/dist/query-lane-context.d.ts +0 -16
- package/dist/query-lane-context.d.ts.map +0 -1
- package/dist/schema.d.ts +0 -63
- package/dist/schema.d.ts.map +0 -1
- package/dist/types.d.ts +0 -332
- package/dist/types.d.ts.map +0 -1
- package/dist/utils/guards.d.ts +0 -55
- package/dist/utils/guards.d.ts.map +0 -1
- package/src/ast/common.ts +0 -36
- package/src/ast/delete.ts +0 -17
- package/src/ast/insert.ts +0 -17
- package/src/ast/order.ts +0 -11
- package/src/ast/predicate.ts +0 -30
- package/src/ast/select.ts +0 -39
- package/src/ast/update.ts +0 -19
package/src/exports/ast.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
export * from '../ast/adapter-types';
|
|
2
2
|
export * from '../ast/codec-types';
|
|
3
|
-
export * from '../ast/common';
|
|
4
|
-
export * from '../ast/delete';
|
|
5
3
|
export * from '../ast/driver-types';
|
|
6
|
-
export * from '../ast/insert';
|
|
7
4
|
export * from '../ast/join';
|
|
8
|
-
export * from '../ast/
|
|
9
|
-
export * from '../ast/predicate';
|
|
10
|
-
export * from '../ast/select';
|
|
5
|
+
export * from '../ast/sql-codecs';
|
|
11
6
|
export * from '../ast/types';
|
|
12
|
-
export * from '../ast/update';
|
|
13
7
|
export * from '../ast/util';
|
package/src/exports/guards.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export {
|
|
2
|
-
collectColumnRefs,
|
|
3
|
-
extractBaseColumnRef,
|
|
4
2
|
getColumnInfo,
|
|
5
3
|
getColumnMeta,
|
|
6
|
-
getOperationExpr,
|
|
7
4
|
isColumnBuilder,
|
|
8
|
-
|
|
5
|
+
isExpressionBuilder,
|
|
6
|
+
isExpressionSource,
|
|
9
7
|
isParamPlaceholder,
|
|
8
|
+
isValueSource,
|
|
10
9
|
} from '../utils/guards';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../query-operation-registry';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../guards';
|
|
@@ -3,59 +3,69 @@ import { hasAllCapabilities } from '@prisma-next/operations';
|
|
|
3
3
|
import { planInvalid } from '@prisma-next/plan';
|
|
4
4
|
import type { StorageColumn } from '@prisma-next/sql-contract/types';
|
|
5
5
|
import type { SqlOperationSignature } from '@prisma-next/sql-operations';
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import {
|
|
7
|
+
type AnyOperationArg,
|
|
8
|
+
type BinaryOp,
|
|
9
|
+
type ExpressionSource,
|
|
10
|
+
LiteralExpr,
|
|
11
|
+
OperationExpr,
|
|
12
|
+
ParamRef,
|
|
13
|
+
} from './ast/types';
|
|
14
|
+
import type {
|
|
15
|
+
AnyBinaryBuilder,
|
|
16
|
+
AnyOrderBuilder,
|
|
17
|
+
ColumnBuilder,
|
|
18
|
+
ExpressionBuilder,
|
|
19
|
+
OperationTypes,
|
|
20
|
+
ValueSource,
|
|
21
|
+
} from './types';
|
|
9
22
|
|
|
10
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Type guard to check if a value is an ExpressionSource (has toExpr method).
|
|
25
|
+
*/
|
|
26
|
+
function isExpressionSource(value: unknown): value is ExpressionSource {
|
|
11
27
|
return (
|
|
12
28
|
typeof value === 'object' &&
|
|
13
29
|
value !== null &&
|
|
14
|
-
'
|
|
15
|
-
(value as
|
|
30
|
+
'toExpr' in value &&
|
|
31
|
+
typeof (value as ExpressionSource).toExpr === 'function'
|
|
16
32
|
);
|
|
17
33
|
}
|
|
18
34
|
|
|
19
35
|
/**
|
|
20
|
-
* Executes an operation and returns
|
|
36
|
+
* Executes an operation and returns an ExpressionBuilder.
|
|
21
37
|
* This is the canonical entrypoint for operation invocation, enabling
|
|
22
38
|
* future enhancements like telemetry, caching, or tracing.
|
|
23
39
|
*
|
|
40
|
+
* The returned ExpressionBuilder:
|
|
41
|
+
* - Has `kind: 'expression'` to distinguish it from ColumnBuilder
|
|
42
|
+
* - Contains the operation expression in `expr`
|
|
43
|
+
* - Provides `toExpr()` method to get the Expression
|
|
44
|
+
* - Provides comparison and ordering methods for chaining
|
|
45
|
+
*
|
|
24
46
|
* @param signature - The operation signature from the registry
|
|
25
|
-
* @param selfBuilder - The
|
|
47
|
+
* @param selfBuilder - The expression source that the operation is called on
|
|
26
48
|
* @param args - The arguments passed to the operation
|
|
27
49
|
* @param columnMeta - The metadata of the column the operation is called on
|
|
28
|
-
* @returns
|
|
50
|
+
* @returns An ExpressionBuilder containing the operation expression
|
|
29
51
|
*/
|
|
30
52
|
function executeOperation(
|
|
31
53
|
signature: SqlOperationSignature,
|
|
32
|
-
selfBuilder:
|
|
54
|
+
selfBuilder: ExpressionSource,
|
|
33
55
|
args: unknown[],
|
|
34
56
|
columnMeta: StorageColumn,
|
|
35
57
|
operationRegistry?: OperationRegistry,
|
|
36
58
|
contractCapabilities?: Record<string, Record<string, boolean>>,
|
|
37
|
-
):
|
|
59
|
+
): ExpressionBuilder {
|
|
38
60
|
if (args.length !== signature.args.length) {
|
|
39
61
|
throw planInvalid(
|
|
40
62
|
`Operation ${signature.method} expects ${signature.args.length} arguments, got ${args.length}`,
|
|
41
63
|
);
|
|
42
64
|
}
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
table: string;
|
|
48
|
-
column: string;
|
|
49
|
-
};
|
|
50
|
-
const selfExpr: ColumnRef | OperationExpr = selfBuilderWithExpr._operationExpr
|
|
51
|
-
? selfBuilderWithExpr._operationExpr
|
|
52
|
-
: {
|
|
53
|
-
kind: 'col',
|
|
54
|
-
table: selfBuilderWithExpr.table,
|
|
55
|
-
column: selfBuilderWithExpr.column,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const operationArgs: Array<ColumnRef | ParamRef | LiteralExpr | OperationExpr> = [];
|
|
66
|
+
const selfExpr = selfBuilder.toExpr();
|
|
67
|
+
|
|
68
|
+
const operationArgs: AnyOperationArg[] = [];
|
|
59
69
|
for (let i = 0; i < args.length; i++) {
|
|
60
70
|
const arg = args[i];
|
|
61
71
|
const argSpec = signature.args[i];
|
|
@@ -64,51 +74,29 @@ function executeOperation(
|
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
if (argSpec.kind === 'param') {
|
|
67
|
-
|
|
68
|
-
throw planInvalid(`Argument ${i} must be a parameter placeholder`);
|
|
69
|
-
}
|
|
70
|
-
operationArgs.push({
|
|
71
|
-
kind: 'param',
|
|
72
|
-
index: 0,
|
|
73
|
-
name: arg.name,
|
|
74
|
-
});
|
|
77
|
+
operationArgs.push(ParamRef.of(arg, { name: `arg_${i}`, codecId: columnMeta.codecId }));
|
|
75
78
|
} else if (argSpec.kind === 'typeId') {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
table: string;
|
|
82
|
-
column: string;
|
|
83
|
-
};
|
|
84
|
-
// Check if the column builder has an operation expression
|
|
85
|
-
if (colBuilderWithExpr._operationExpr) {
|
|
86
|
-
operationArgs.push(colBuilderWithExpr._operationExpr);
|
|
87
|
-
} else {
|
|
88
|
-
// Fall back to raw ColumnRef
|
|
89
|
-
operationArgs.push({
|
|
90
|
-
kind: 'col',
|
|
91
|
-
table: colBuilderWithExpr.table,
|
|
92
|
-
column: colBuilderWithExpr.column,
|
|
93
|
-
});
|
|
79
|
+
// Accept ExpressionSource (ColumnBuilder or ExpressionBuilder)
|
|
80
|
+
if (!isExpressionSource(arg)) {
|
|
81
|
+
throw planInvalid(
|
|
82
|
+
`Argument ${i} must be an ExpressionSource (ColumnBuilder or ExpressionBuilder)`,
|
|
83
|
+
);
|
|
94
84
|
}
|
|
85
|
+
// Use toExpr() to get the Expression
|
|
86
|
+
operationArgs.push(arg.toExpr());
|
|
95
87
|
} else if (argSpec.kind === 'literal') {
|
|
96
|
-
operationArgs.push(
|
|
97
|
-
kind: 'literal',
|
|
98
|
-
value: arg,
|
|
99
|
-
});
|
|
88
|
+
operationArgs.push(new LiteralExpr(arg));
|
|
100
89
|
}
|
|
101
90
|
}
|
|
102
91
|
|
|
103
|
-
const operationExpr
|
|
104
|
-
kind: 'operation',
|
|
92
|
+
const operationExpr = new OperationExpr({
|
|
105
93
|
method: signature.method,
|
|
106
94
|
forTypeId: signature.forTypeId,
|
|
107
95
|
self: selfExpr,
|
|
108
96
|
args: operationArgs,
|
|
109
97
|
returns: signature.returns,
|
|
110
98
|
lowering: signature.lowering,
|
|
111
|
-
};
|
|
99
|
+
});
|
|
112
100
|
|
|
113
101
|
const returnTypeId = signature.returns.kind === 'typeId' ? signature.returns.type : undefined;
|
|
114
102
|
const returnColumnMeta: StorageColumn = returnTypeId
|
|
@@ -118,18 +106,19 @@ function executeOperation(
|
|
|
118
106
|
}
|
|
119
107
|
: columnMeta;
|
|
120
108
|
|
|
121
|
-
const createComparisonMethod =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
109
|
+
const createComparisonMethod =
|
|
110
|
+
(op: BinaryOp) =>
|
|
111
|
+
(value: ValueSource): AnyBinaryBuilder =>
|
|
112
|
+
Object.freeze({
|
|
113
|
+
kind: 'binary' as const,
|
|
114
|
+
op,
|
|
115
|
+
left: operationExpr,
|
|
116
|
+
right: value,
|
|
117
|
+
}) as AnyBinaryBuilder;
|
|
118
|
+
|
|
119
|
+
const baseResult: ExpressionBuilder = {
|
|
120
|
+
kind: 'expression' as const,
|
|
121
|
+
expr: operationExpr,
|
|
133
122
|
get columnMeta() {
|
|
134
123
|
return returnColumnMeta;
|
|
135
124
|
},
|
|
@@ -139,41 +128,84 @@ function executeOperation(
|
|
|
139
128
|
lt: createComparisonMethod('lt'),
|
|
140
129
|
gte: createComparisonMethod('gte'),
|
|
141
130
|
lte: createComparisonMethod('lte'),
|
|
142
|
-
asc() {
|
|
131
|
+
asc(): AnyOrderBuilder {
|
|
143
132
|
return Object.freeze({
|
|
144
133
|
kind: 'order' as const,
|
|
145
134
|
expr: operationExpr,
|
|
146
135
|
dir: 'asc' as const,
|
|
147
136
|
});
|
|
148
137
|
},
|
|
149
|
-
desc() {
|
|
138
|
+
desc(): AnyOrderBuilder {
|
|
150
139
|
return Object.freeze({
|
|
151
140
|
kind: 'order' as const,
|
|
152
141
|
expr: operationExpr,
|
|
153
142
|
dir: 'desc' as const,
|
|
154
143
|
});
|
|
155
144
|
},
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
145
|
+
toExpr(): OperationExpr {
|
|
146
|
+
return operationExpr;
|
|
147
|
+
},
|
|
148
|
+
get __jsType(): unknown {
|
|
149
|
+
return undefined;
|
|
150
|
+
},
|
|
159
151
|
};
|
|
160
152
|
|
|
161
153
|
// If the return type is a typeId, attach operations for that type
|
|
162
154
|
if (returnTypeId && operationRegistry) {
|
|
163
|
-
const resultWithOps =
|
|
164
|
-
baseResult
|
|
155
|
+
const resultWithOps = attachOperationsToExpressionBuilder(
|
|
156
|
+
baseResult,
|
|
165
157
|
returnColumnMeta,
|
|
166
158
|
operationRegistry,
|
|
167
159
|
contractCapabilities,
|
|
168
|
-
)
|
|
169
|
-
_operationExpr?: OperationExpr;
|
|
170
|
-
};
|
|
160
|
+
);
|
|
171
161
|
return Object.freeze(resultWithOps);
|
|
172
162
|
}
|
|
173
163
|
|
|
174
164
|
return Object.freeze(baseResult);
|
|
175
165
|
}
|
|
176
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Attaches operation methods to an ExpressionBuilder for chained operations.
|
|
169
|
+
* When an operation returns a typeId, the result ExpressionBuilder needs
|
|
170
|
+
* operation methods for that type.
|
|
171
|
+
*/
|
|
172
|
+
function attachOperationsToExpressionBuilder(
|
|
173
|
+
expressionBuilder: ExpressionBuilder,
|
|
174
|
+
columnMeta: StorageColumn,
|
|
175
|
+
registry: OperationRegistry,
|
|
176
|
+
contractCapabilities?: Record<string, Record<string, boolean>>,
|
|
177
|
+
): ExpressionBuilder {
|
|
178
|
+
const codecId = columnMeta.codecId;
|
|
179
|
+
if (!codecId) {
|
|
180
|
+
return expressionBuilder;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const operations = registry.byType(codecId) as SqlOperationSignature[];
|
|
184
|
+
if (operations.length === 0) {
|
|
185
|
+
return expressionBuilder;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const builderWithOps = expressionBuilder as ExpressionBuilder & Record<string, unknown>;
|
|
189
|
+
|
|
190
|
+
for (const operation of operations) {
|
|
191
|
+
if (operation.capabilities && operation.capabilities.length > 0) {
|
|
192
|
+
if (!contractCapabilities) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (!hasAllCapabilities(operation.capabilities, contractCapabilities)) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Method sugar: attach operation as a method on the expression builder
|
|
201
|
+
builderWithOps[operation.method] = function (this: ExpressionBuilder, ...args: unknown[]) {
|
|
202
|
+
return executeOperation(operation, this, args, columnMeta, registry, contractCapabilities);
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return builderWithOps;
|
|
207
|
+
}
|
|
208
|
+
|
|
177
209
|
export function attachOperationsToColumnBuilder<
|
|
178
210
|
ColumnName extends string,
|
|
179
211
|
ColumnMeta extends StorageColumn,
|
|
@@ -218,18 +250,12 @@ export function attachOperationsToColumnBuilder<
|
|
|
218
250
|
}
|
|
219
251
|
}
|
|
220
252
|
// Method sugar: attach operation as a method on the column builder
|
|
253
|
+
// Operations return ExpressionBuilder, not ColumnBuilder
|
|
221
254
|
(builderWithOps as Record<string, unknown>)[operation.method] = function (
|
|
222
255
|
this: ColumnBuilder<ColumnName, ColumnMeta, JsType, Record<string, never>>,
|
|
223
256
|
...args: unknown[]
|
|
224
257
|
) {
|
|
225
|
-
return executeOperation(
|
|
226
|
-
operation,
|
|
227
|
-
this as unknown as ColumnBuilder<string, StorageColumn, unknown>,
|
|
228
|
-
args,
|
|
229
|
-
columnMeta,
|
|
230
|
-
registry,
|
|
231
|
-
contractCapabilities,
|
|
232
|
-
);
|
|
258
|
+
return executeOperation(operation, this, args, columnMeta, registry, contractCapabilities);
|
|
233
259
|
};
|
|
234
260
|
}
|
|
235
261
|
|
package/src/plan.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ExecutionPlan, ParamDescriptor } from '@prisma-next/contract/types';
|
|
2
2
|
import type { StorageColumn } from '@prisma-next/sql-contract/types';
|
|
3
|
-
import type {
|
|
3
|
+
import type { AnyQueryAst } from './ast/types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* SQL query plan produced by lanes before lowering.
|
|
@@ -8,13 +8,13 @@ import type { QueryAst } from './ast/types';
|
|
|
8
8
|
* Lanes build ASTs and metadata but do not perform SQL lowering.
|
|
9
9
|
* The `sql` field is absent - lowering happens in the runtime executor.
|
|
10
10
|
*
|
|
11
|
-
* Structurally aligns with ExecutionPlan<Row,
|
|
11
|
+
* Structurally aligns with ExecutionPlan<Row, AnyQueryAst> (without sql field) to maintain
|
|
12
12
|
* compatibility with ExecutionPlan/Plan-based utilities.
|
|
13
13
|
* The generic parameter `_Row` is preserved for type extraction via ResultType.
|
|
14
14
|
*/
|
|
15
15
|
export interface SqlQueryPlan<_Row = unknown>
|
|
16
|
-
extends Pick<ExecutionPlan<_Row,
|
|
17
|
-
readonly ast:
|
|
16
|
+
extends Pick<ExecutionPlan<_Row, AnyQueryAst>, 'params' | 'meta'> {
|
|
17
|
+
readonly ast: AnyQueryAst;
|
|
18
18
|
// Phantom property to preserve generic parameter for type extraction
|
|
19
19
|
// This allows ResultType to extract _Row for SqlQueryPlan values.
|
|
20
20
|
readonly _Row?: _Row;
|
|
@@ -1,6 +1,68 @@
|
|
|
1
1
|
import type { OperationRegistry } from '@prisma-next/operations';
|
|
2
2
|
import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
3
3
|
import type { CodecRegistry } from './ast/codec-types';
|
|
4
|
+
import type { QueryOperationRegistry } from './query-operation-registry';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Registry of initialized type helpers from storage.types.
|
|
8
|
+
* Each key is a type name from storage.types, and the value is:
|
|
9
|
+
* - The result of the codec's init hook (if provided), or
|
|
10
|
+
* - The full StorageTypeInstance metadata (codecId, nativeType, typeParams) if no init hook
|
|
11
|
+
*/
|
|
12
|
+
export type TypeHelperRegistry = Record<string, unknown>;
|
|
13
|
+
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// JSON Schema Validation Types
|
|
16
|
+
// =============================================================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A single validation error from JSON Schema validation.
|
|
20
|
+
*/
|
|
21
|
+
export interface JsonSchemaValidationError {
|
|
22
|
+
readonly path: string;
|
|
23
|
+
readonly message: string;
|
|
24
|
+
readonly keyword: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Result of a JSON Schema validation.
|
|
29
|
+
*/
|
|
30
|
+
export type JsonSchemaValidationResult =
|
|
31
|
+
| { readonly valid: true }
|
|
32
|
+
| { readonly valid: false; readonly errors: ReadonlyArray<JsonSchemaValidationError> };
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A compiled JSON Schema validate function.
|
|
36
|
+
* Returns a structured result indicating whether the value conforms to the schema.
|
|
37
|
+
*/
|
|
38
|
+
export type JsonSchemaValidateFn = (value: unknown) => JsonSchemaValidationResult;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Registry of compiled JSON Schema validators for columns with typed JSON/JSONB.
|
|
42
|
+
*
|
|
43
|
+
* Built during context creation by scanning the contract for columns whose codec
|
|
44
|
+
* descriptor provides an `init` hook that returns a `{ validate }` helper.
|
|
45
|
+
* Keys are `"table.column"` (e.g., `"user.metadata"`).
|
|
46
|
+
*/
|
|
47
|
+
export interface JsonSchemaValidatorRegistry {
|
|
48
|
+
/** Get the compiled validator for a column. Key format: "table.column". */
|
|
49
|
+
get(key: string): JsonSchemaValidateFn | undefined;
|
|
50
|
+
/** Number of registered validators. */
|
|
51
|
+
readonly size: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type MutationDefaultsOp = 'create' | 'update';
|
|
55
|
+
|
|
56
|
+
export type AppliedMutationDefault = {
|
|
57
|
+
readonly column: string;
|
|
58
|
+
readonly value: unknown;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type MutationDefaultsOptions = {
|
|
62
|
+
readonly op: MutationDefaultsOp;
|
|
63
|
+
readonly table: string;
|
|
64
|
+
readonly values: Record<string, unknown>;
|
|
65
|
+
};
|
|
4
66
|
|
|
5
67
|
/**
|
|
6
68
|
* Minimal context interface for SQL query lanes.
|
|
@@ -9,10 +71,26 @@ import type { CodecRegistry } from './ast/codec-types';
|
|
|
9
71
|
* operation builders. This interface explicitly excludes runtime concerns like
|
|
10
72
|
* adapters, connection management, and transaction state.
|
|
11
73
|
*/
|
|
12
|
-
export interface
|
|
74
|
+
export interface ExecutionContext<
|
|
13
75
|
TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
|
|
14
76
|
> {
|
|
15
77
|
readonly contract: TContract;
|
|
16
78
|
readonly operations: OperationRegistry;
|
|
17
79
|
readonly codecs: CodecRegistry;
|
|
80
|
+
readonly queryOperations: QueryOperationRegistry;
|
|
81
|
+
/**
|
|
82
|
+
* Type helper registry for parameterized types.
|
|
83
|
+
* Schema builders expose these helpers via schema.types.
|
|
84
|
+
*/
|
|
85
|
+
readonly types: TypeHelperRegistry;
|
|
86
|
+
/**
|
|
87
|
+
* Compiled JSON Schema validators for typed JSON/JSONB columns.
|
|
88
|
+
* Present only when the contract declares columns with JSON Schema typeParams.
|
|
89
|
+
*/
|
|
90
|
+
readonly jsonSchemaValidators?: JsonSchemaValidatorRegistry;
|
|
91
|
+
/**
|
|
92
|
+
* Applies execution-time mutation defaults for the given table.
|
|
93
|
+
* Returns the applied defaults (caller-provided values always win).
|
|
94
|
+
*/
|
|
95
|
+
applyMutationDefaults(options: MutationDefaultsOptions): ReadonlyArray<AppliedMutationDefault>;
|
|
18
96
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface QueryOperationEntry {
|
|
2
|
+
readonly args: readonly { readonly codecId: string; readonly nullable: boolean }[];
|
|
3
|
+
readonly returns: { readonly codecId: string; readonly nullable: boolean };
|
|
4
|
+
readonly lowering: {
|
|
5
|
+
readonly targetFamily: 'sql';
|
|
6
|
+
readonly strategy: 'infix' | 'function';
|
|
7
|
+
readonly template: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface QueryOperationDescriptor extends QueryOperationEntry {
|
|
12
|
+
readonly method: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface QueryOperationRegistry {
|
|
16
|
+
register(descriptor: QueryOperationDescriptor): void;
|
|
17
|
+
entries(): Readonly<Record<string, QueryOperationEntry>>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createQueryOperationRegistry(): QueryOperationRegistry {
|
|
21
|
+
const map = new Map<string, QueryOperationEntry>();
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
register(descriptor) {
|
|
25
|
+
if (map.has(descriptor.method)) {
|
|
26
|
+
throw new Error(`Query operation "${descriptor.method}" is already registered`);
|
|
27
|
+
}
|
|
28
|
+
const { method: _, ...entry } = descriptor;
|
|
29
|
+
map.set(descriptor.method, entry);
|
|
30
|
+
},
|
|
31
|
+
entries() {
|
|
32
|
+
return Object.freeze(Object.fromEntries(map));
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|