@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.
Files changed (188) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +18 -1
  3. package/dist/errors-BNiBIGfC.d.mts +2 -0
  4. package/dist/errors-DXSQwbhk.mjs +3 -0
  5. package/dist/exports/ast.d.mts +126 -0
  6. package/dist/exports/ast.d.mts.map +1 -0
  7. package/dist/exports/ast.mjs +253 -0
  8. package/dist/exports/ast.mjs.map +1 -0
  9. package/dist/exports/errors.d.mts +2 -0
  10. package/dist/exports/errors.mjs +3 -0
  11. package/dist/exports/guards.d.mts +5 -0
  12. package/dist/exports/guards.mjs +3 -0
  13. package/dist/exports/operations-registry.d.mts +5 -0
  14. package/dist/exports/operations-registry.mjs +3 -0
  15. package/dist/exports/param.d.mts +5 -0
  16. package/dist/exports/param.mjs +3 -0
  17. package/dist/exports/plan.d.mts +2 -0
  18. package/dist/exports/plan.mjs +17 -0
  19. package/dist/exports/plan.mjs.map +1 -0
  20. package/dist/exports/query-lane-context.d.mts +2 -0
  21. package/dist/exports/query-lane-context.mjs +1 -0
  22. package/dist/exports/query-operations.d.mts +2 -0
  23. package/dist/exports/query-operations.mjs +18 -0
  24. package/dist/exports/query-operations.mjs.map +1 -0
  25. package/dist/exports/schema.d.mts +5 -0
  26. package/dist/exports/schema.mjs +4 -0
  27. package/dist/exports/types.d.mts +4 -0
  28. package/dist/exports/types.mjs +3 -0
  29. package/dist/exports/utils/guards.d.mts +5 -0
  30. package/dist/exports/utils/guards.mjs +3 -0
  31. package/dist/guards-D1ax7TKN.mjs +57 -0
  32. package/dist/guards-D1ax7TKN.mjs.map +1 -0
  33. package/dist/guards-DC2Ll67p.d.mts +31 -0
  34. package/dist/guards-DC2Ll67p.d.mts.map +1 -0
  35. package/dist/index.d.mts +12 -0
  36. package/dist/index.mjs +13 -0
  37. package/dist/operations-registry-CBmGut8O.d.mts +9 -0
  38. package/dist/operations-registry-CBmGut8O.d.mts.map +1 -0
  39. package/dist/operations-registry-D8INFH9J.mjs +145 -0
  40. package/dist/operations-registry-D8INFH9J.mjs.map +1 -0
  41. package/dist/param-CFyhvphn.mjs +14 -0
  42. package/dist/param-CFyhvphn.mjs.map +1 -0
  43. package/dist/param-Cmdv_exJ.d.mts +8 -0
  44. package/dist/param-Cmdv_exJ.d.mts.map +1 -0
  45. package/dist/plan-BrZtMUA9.d.mts +517 -0
  46. package/dist/plan-BrZtMUA9.d.mts.map +1 -0
  47. package/dist/query-lane-context-BTtg0xm8.d.mts +278 -0
  48. package/dist/query-lane-context-BTtg0xm8.d.mts.map +1 -0
  49. package/dist/query-operation-registry-B6bClJs8.d.mts +27 -0
  50. package/dist/query-operation-registry-B6bClJs8.d.mts.map +1 -0
  51. package/dist/schema-XcyJSq4j.mjs +174 -0
  52. package/dist/schema-XcyJSq4j.mjs.map +1 -0
  53. package/dist/schema-j3Srik3R.d.mts +88 -0
  54. package/dist/schema-j3Srik3R.d.mts.map +1 -0
  55. package/dist/types-BZKzxgOb.mjs +18 -0
  56. package/dist/types-BZKzxgOb.mjs.map +1 -0
  57. package/dist/types-CMyotK6U.d.mts +443 -0
  58. package/dist/types-CMyotK6U.d.mts.map +1 -0
  59. package/dist/types-I6Hsg-GU.mjs +1102 -0
  60. package/dist/types-I6Hsg-GU.mjs.map +1 -0
  61. package/package.json +40 -56
  62. package/src/ast/codec-types.ts +123 -22
  63. package/src/ast/driver-types.ts +20 -3
  64. package/src/ast/join.ts +3 -23
  65. package/src/ast/sql-codecs.ts +81 -0
  66. package/src/ast/types.ts +1704 -74
  67. package/src/exports/ast.ts +1 -7
  68. package/src/exports/guards.ts +3 -4
  69. package/src/exports/query-operations.ts +1 -0
  70. package/src/exports/utils/guards.ts +1 -0
  71. package/src/operations-registry.ts +115 -89
  72. package/src/plan.ts +4 -4
  73. package/src/query-lane-context.ts +79 -1
  74. package/src/query-operation-registry.ts +35 -0
  75. package/src/schema.ts +104 -43
  76. package/src/types.ts +333 -84
  77. package/src/utils/guards.ts +44 -80
  78. package/dist/ast/adapter-types.d.ts +0 -28
  79. package/dist/ast/adapter-types.d.ts.map +0 -1
  80. package/dist/ast/codec-types.d.ts +0 -141
  81. package/dist/ast/codec-types.d.ts.map +0 -1
  82. package/dist/ast/common.d.ts +0 -7
  83. package/dist/ast/common.d.ts.map +0 -1
  84. package/dist/ast/delete.d.ts +0 -8
  85. package/dist/ast/delete.d.ts.map +0 -1
  86. package/dist/ast/driver-types.d.ts +0 -20
  87. package/dist/ast/driver-types.d.ts.map +0 -1
  88. package/dist/ast/insert.d.ts +0 -8
  89. package/dist/ast/insert.d.ts.map +0 -1
  90. package/dist/ast/join.d.ts +0 -6
  91. package/dist/ast/join.d.ts.map +0 -1
  92. package/dist/ast/order.d.ts +0 -6
  93. package/dist/ast/order.d.ts.map +0 -1
  94. package/dist/ast/predicate.d.ts +0 -4
  95. package/dist/ast/predicate.d.ts.map +0 -1
  96. package/dist/ast/select.d.ts +0 -18
  97. package/dist/ast/select.d.ts.map +0 -1
  98. package/dist/ast/types.d.ts +0 -118
  99. package/dist/ast/types.d.ts.map +0 -1
  100. package/dist/ast/update.d.ts +0 -9
  101. package/dist/ast/update.d.ts.map +0 -1
  102. package/dist/ast/util.d.ts +0 -2
  103. package/dist/ast/util.d.ts.map +0 -1
  104. package/dist/chunk-2F7DSEOU.js +0 -8
  105. package/dist/chunk-2F7DSEOU.js.map +0 -1
  106. package/dist/chunk-36WJWNHT.js +0 -1
  107. package/dist/chunk-36WJWNHT.js.map +0 -1
  108. package/dist/chunk-5N34PNVZ.js +0 -62
  109. package/dist/chunk-5N34PNVZ.js.map +0 -1
  110. package/dist/chunk-7I3EMQID.js +0 -16
  111. package/dist/chunk-7I3EMQID.js.map +0 -1
  112. package/dist/chunk-CBTYMOX2.js +0 -152
  113. package/dist/chunk-CBTYMOX2.js.map +0 -1
  114. package/dist/chunk-G52ENULI.js +0 -1
  115. package/dist/chunk-G52ENULI.js.map +0 -1
  116. package/dist/chunk-KYSP7L5C.js +0 -16
  117. package/dist/chunk-KYSP7L5C.js.map +0 -1
  118. package/dist/chunk-M23L3JHG.js +0 -159
  119. package/dist/chunk-M23L3JHG.js.map +0 -1
  120. package/dist/chunk-MM74SVJ4.js +0 -13
  121. package/dist/chunk-MM74SVJ4.js.map +0 -1
  122. package/dist/chunk-U7AXAUJA.js +0 -1
  123. package/dist/chunk-U7AXAUJA.js.map +0 -1
  124. package/dist/chunk-WZBPVEZI.js +0 -320
  125. package/dist/chunk-WZBPVEZI.js.map +0 -1
  126. package/dist/errors.d.ts +0 -2
  127. package/dist/errors.d.ts.map +0 -1
  128. package/dist/exports/ast.d.ts +0 -14
  129. package/dist/exports/ast.d.ts.map +0 -1
  130. package/dist/exports/ast.js +0 -46
  131. package/dist/exports/ast.js.map +0 -1
  132. package/dist/exports/errors.d.ts +0 -2
  133. package/dist/exports/errors.d.ts.map +0 -1
  134. package/dist/exports/errors.js +0 -9
  135. package/dist/exports/errors.js.map +0 -1
  136. package/dist/exports/guards.d.ts +0 -2
  137. package/dist/exports/guards.d.ts.map +0 -1
  138. package/dist/exports/guards.js +0 -21
  139. package/dist/exports/guards.js.map +0 -1
  140. package/dist/exports/operations-registry.d.ts +0 -2
  141. package/dist/exports/operations-registry.d.ts.map +0 -1
  142. package/dist/exports/operations-registry.js +0 -9
  143. package/dist/exports/operations-registry.js.map +0 -1
  144. package/dist/exports/param.d.ts +0 -3
  145. package/dist/exports/param.d.ts.map +0 -1
  146. package/dist/exports/param.js +0 -7
  147. package/dist/exports/param.js.map +0 -1
  148. package/dist/exports/plan.d.ts +0 -2
  149. package/dist/exports/plan.d.ts.map +0 -1
  150. package/dist/exports/plan.js +0 -7
  151. package/dist/exports/plan.js.map +0 -1
  152. package/dist/exports/query-lane-context.d.ts +0 -2
  153. package/dist/exports/query-lane-context.d.ts.map +0 -1
  154. package/dist/exports/query-lane-context.js +0 -2
  155. package/dist/exports/query-lane-context.js.map +0 -1
  156. package/dist/exports/schema.d.ts +0 -3
  157. package/dist/exports/schema.d.ts.map +0 -1
  158. package/dist/exports/schema.js +0 -14
  159. package/dist/exports/schema.js.map +0 -1
  160. package/dist/exports/types.d.ts +0 -2
  161. package/dist/exports/types.d.ts.map +0 -1
  162. package/dist/exports/types.js +0 -10
  163. package/dist/exports/types.js.map +0 -1
  164. package/dist/index.d.ts +0 -9
  165. package/dist/index.d.ts.map +0 -1
  166. package/dist/index.js +0 -81
  167. package/dist/index.js.map +0 -1
  168. package/dist/operations-registry.d.ts +0 -5
  169. package/dist/operations-registry.d.ts.map +0 -1
  170. package/dist/param.d.ts +0 -4
  171. package/dist/param.d.ts.map +0 -1
  172. package/dist/plan.d.ts +0 -23
  173. package/dist/plan.d.ts.map +0 -1
  174. package/dist/query-lane-context.d.ts +0 -16
  175. package/dist/query-lane-context.d.ts.map +0 -1
  176. package/dist/schema.d.ts +0 -63
  177. package/dist/schema.d.ts.map +0 -1
  178. package/dist/types.d.ts +0 -332
  179. package/dist/types.d.ts.map +0 -1
  180. package/dist/utils/guards.d.ts +0 -55
  181. package/dist/utils/guards.d.ts.map +0 -1
  182. package/src/ast/common.ts +0 -36
  183. package/src/ast/delete.ts +0 -17
  184. package/src/ast/insert.ts +0 -17
  185. package/src/ast/order.ts +0 -11
  186. package/src/ast/predicate.ts +0 -30
  187. package/src/ast/select.ts +0 -39
  188. package/src/ast/update.ts +0 -19
@@ -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/order';
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';
@@ -1,10 +1,9 @@
1
1
  export {
2
- collectColumnRefs,
3
- extractBaseColumnRef,
4
2
  getColumnInfo,
5
3
  getColumnMeta,
6
- getOperationExpr,
7
4
  isColumnBuilder,
8
- isOperationExpr,
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 type { BinaryOp, ColumnRef, LiteralExpr, OperationExpr, ParamRef } from './ast/types';
7
- import type { AnyColumnBuilder, ColumnBuilder, OperationTypes, ParamPlaceholder } from './types';
8
- import { isParamPlaceholder } from './utils/guards';
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
- function isColumnBuilder(value: unknown): value is AnyColumnBuilder {
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
- 'kind' in value &&
15
- (value as { kind: unknown }).kind === 'column'
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 a column-shaped result object.
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 column builder that the operation is called on
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 A column-shaped builder with the operation expression attached
50
+ * @returns An ExpressionBuilder containing the operation expression
29
51
  */
30
52
  function executeOperation(
31
53
  signature: SqlOperationSignature,
32
- selfBuilder: AnyColumnBuilder,
54
+ selfBuilder: ExpressionSource,
33
55
  args: unknown[],
34
56
  columnMeta: StorageColumn,
35
57
  operationRegistry?: OperationRegistry,
36
58
  contractCapabilities?: Record<string, Record<string, boolean>>,
37
- ): AnyColumnBuilder & { _operationExpr?: OperationExpr } {
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
- // Check if this column builder has an existing operation expression
45
- const selfBuilderWithExpr = selfBuilder as unknown as {
46
- _operationExpr?: OperationExpr;
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
- if (!isParamPlaceholder(arg)) {
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
- if (!isColumnBuilder(arg)) {
77
- throw planInvalid(`Argument ${i} must be a ColumnBuilder`);
78
- }
79
- const colBuilderWithExpr = arg as unknown as {
80
- _operationExpr?: OperationExpr;
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: 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 = (op: BinaryOp) => (value: ParamPlaceholder) =>
122
- Object.freeze({
123
- kind: 'binary' as const,
124
- op,
125
- left: operationExpr,
126
- right: value,
127
- });
128
-
129
- const baseResult = {
130
- kind: 'column' as const,
131
- table: selfBuilderWithExpr.table,
132
- column: selfBuilderWithExpr.column,
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
- _operationExpr: operationExpr,
157
- } as unknown as AnyColumnBuilder & {
158
- _operationExpr?: OperationExpr;
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 = attachOperationsToColumnBuilder(
164
- baseResult as ColumnBuilder<string, StorageColumn, unknown, Record<string, never>>,
155
+ const resultWithOps = attachOperationsToExpressionBuilder(
156
+ baseResult,
165
157
  returnColumnMeta,
166
158
  operationRegistry,
167
159
  contractCapabilities,
168
- ) as AnyColumnBuilder & {
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 { QueryAst } from './ast/types';
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, QueryAst> (without sql field) to maintain
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, QueryAst>, 'params' | 'meta'> {
17
- readonly ast: QueryAst;
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 QueryLaneContext<
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
+ }