@prisma-next/sql-relational-core 0.3.0-dev.6 → 0.3.0-dev.63

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 (174) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +18 -2
  3. package/dist/errors-7_V3El9I.mjs +3 -0
  4. package/dist/errors-DVufq9PT.d.mts +2 -0
  5. package/dist/exports/ast.d.mts +192 -0
  6. package/dist/exports/ast.d.mts.map +1 -0
  7. package/dist/exports/ast.mjs +361 -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/schema.d.mts +5 -0
  23. package/dist/exports/schema.mjs +4 -0
  24. package/dist/exports/types.d.mts +4 -0
  25. package/dist/exports/types.mjs +3 -0
  26. package/dist/exports/utils/guards.d.mts +5 -0
  27. package/dist/exports/utils/guards.mjs +4 -0
  28. package/dist/guards-0ycyntYX.mjs +132 -0
  29. package/dist/guards-0ycyntYX.mjs.map +1 -0
  30. package/dist/guards-DCCpAlOL.d.mts +87 -0
  31. package/dist/guards-DCCpAlOL.d.mts.map +1 -0
  32. package/dist/index.d.mts +12 -0
  33. package/dist/index.mjs +12 -0
  34. package/dist/operations-registry-DPZ5aElH.mjs +152 -0
  35. package/dist/operations-registry-DPZ5aElH.mjs.map +1 -0
  36. package/dist/operations-registry-wVEaiLyt.d.mts +9 -0
  37. package/dist/operations-registry-wVEaiLyt.d.mts.map +1 -0
  38. package/dist/param-C4n0OW59.d.mts +8 -0
  39. package/dist/param-C4n0OW59.d.mts.map +1 -0
  40. package/dist/param-DMU3OWfI.mjs +14 -0
  41. package/dist/param-DMU3OWfI.mjs.map +1 -0
  42. package/dist/plan-BhSWuTfw.d.mts +194 -0
  43. package/dist/plan-BhSWuTfw.d.mts.map +1 -0
  44. package/dist/query-lane-context-CgkPuKaR.d.mts +259 -0
  45. package/dist/query-lane-context-CgkPuKaR.d.mts.map +1 -0
  46. package/dist/schema-Bi5p4aAc.mjs +175 -0
  47. package/dist/schema-Bi5p4aAc.mjs.map +1 -0
  48. package/dist/schema-CgrEMqEd.d.mts +86 -0
  49. package/dist/schema-CgrEMqEd.d.mts.map +1 -0
  50. package/dist/types-CEUzDuDC.d.mts +447 -0
  51. package/dist/types-CEUzDuDC.d.mts.map +1 -0
  52. package/dist/types-Cdi4Whda.mjs +18 -0
  53. package/dist/types-Cdi4Whda.mjs.map +1 -0
  54. package/package.json +38 -55
  55. package/src/ast/codec-types.ts +77 -8
  56. package/src/ast/delete.ts +2 -2
  57. package/src/ast/driver-types.ts +20 -3
  58. package/src/ast/predicate.ts +14 -4
  59. package/src/ast/select.ts +4 -3
  60. package/src/ast/sql-codecs.ts +67 -0
  61. package/src/ast/types.ts +89 -19
  62. package/src/ast/update.ts +2 -2
  63. package/src/exports/ast.ts +1 -0
  64. package/src/exports/guards.ts +5 -0
  65. package/src/exports/utils/guards.ts +1 -0
  66. package/src/operations-registry.ts +112 -73
  67. package/src/query-lane-context.ts +77 -1
  68. package/src/schema.ts +91 -33
  69. package/src/types.ts +327 -75
  70. package/src/utils/guards.ts +88 -18
  71. package/dist/ast/adapter-types.d.ts +0 -28
  72. package/dist/ast/adapter-types.d.ts.map +0 -1
  73. package/dist/ast/codec-types.d.ts +0 -141
  74. package/dist/ast/codec-types.d.ts.map +0 -1
  75. package/dist/ast/common.d.ts +0 -7
  76. package/dist/ast/common.d.ts.map +0 -1
  77. package/dist/ast/delete.d.ts +0 -8
  78. package/dist/ast/delete.d.ts.map +0 -1
  79. package/dist/ast/driver-types.d.ts +0 -20
  80. package/dist/ast/driver-types.d.ts.map +0 -1
  81. package/dist/ast/insert.d.ts +0 -8
  82. package/dist/ast/insert.d.ts.map +0 -1
  83. package/dist/ast/join.d.ts +0 -6
  84. package/dist/ast/join.d.ts.map +0 -1
  85. package/dist/ast/order.d.ts +0 -6
  86. package/dist/ast/order.d.ts.map +0 -1
  87. package/dist/ast/predicate.d.ts +0 -4
  88. package/dist/ast/predicate.d.ts.map +0 -1
  89. package/dist/ast/select.d.ts +0 -18
  90. package/dist/ast/select.d.ts.map +0 -1
  91. package/dist/ast/types.d.ts +0 -118
  92. package/dist/ast/types.d.ts.map +0 -1
  93. package/dist/ast/update.d.ts +0 -9
  94. package/dist/ast/update.d.ts.map +0 -1
  95. package/dist/ast/util.d.ts +0 -2
  96. package/dist/ast/util.d.ts.map +0 -1
  97. package/dist/chunk-2F7DSEOU.js +0 -8
  98. package/dist/chunk-2F7DSEOU.js.map +0 -1
  99. package/dist/chunk-36WJWNHT.js +0 -1
  100. package/dist/chunk-36WJWNHT.js.map +0 -1
  101. package/dist/chunk-5N34PNVZ.js +0 -62
  102. package/dist/chunk-5N34PNVZ.js.map +0 -1
  103. package/dist/chunk-7I3EMQID.js +0 -16
  104. package/dist/chunk-7I3EMQID.js.map +0 -1
  105. package/dist/chunk-CBTYMOX2.js +0 -152
  106. package/dist/chunk-CBTYMOX2.js.map +0 -1
  107. package/dist/chunk-G52ENULI.js +0 -1
  108. package/dist/chunk-G52ENULI.js.map +0 -1
  109. package/dist/chunk-KYSP7L5C.js +0 -16
  110. package/dist/chunk-KYSP7L5C.js.map +0 -1
  111. package/dist/chunk-M23L3JHG.js +0 -159
  112. package/dist/chunk-M23L3JHG.js.map +0 -1
  113. package/dist/chunk-MM74SVJ4.js +0 -13
  114. package/dist/chunk-MM74SVJ4.js.map +0 -1
  115. package/dist/chunk-U7AXAUJA.js +0 -1
  116. package/dist/chunk-U7AXAUJA.js.map +0 -1
  117. package/dist/chunk-WZBPVEZI.js +0 -320
  118. package/dist/chunk-WZBPVEZI.js.map +0 -1
  119. package/dist/errors.d.ts +0 -2
  120. package/dist/errors.d.ts.map +0 -1
  121. package/dist/exports/ast.d.ts +0 -14
  122. package/dist/exports/ast.d.ts.map +0 -1
  123. package/dist/exports/ast.js +0 -46
  124. package/dist/exports/ast.js.map +0 -1
  125. package/dist/exports/errors.d.ts +0 -2
  126. package/dist/exports/errors.d.ts.map +0 -1
  127. package/dist/exports/errors.js +0 -9
  128. package/dist/exports/errors.js.map +0 -1
  129. package/dist/exports/guards.d.ts +0 -2
  130. package/dist/exports/guards.d.ts.map +0 -1
  131. package/dist/exports/guards.js +0 -21
  132. package/dist/exports/guards.js.map +0 -1
  133. package/dist/exports/operations-registry.d.ts +0 -2
  134. package/dist/exports/operations-registry.d.ts.map +0 -1
  135. package/dist/exports/operations-registry.js +0 -9
  136. package/dist/exports/operations-registry.js.map +0 -1
  137. package/dist/exports/param.d.ts +0 -3
  138. package/dist/exports/param.d.ts.map +0 -1
  139. package/dist/exports/param.js +0 -7
  140. package/dist/exports/param.js.map +0 -1
  141. package/dist/exports/plan.d.ts +0 -2
  142. package/dist/exports/plan.d.ts.map +0 -1
  143. package/dist/exports/plan.js +0 -7
  144. package/dist/exports/plan.js.map +0 -1
  145. package/dist/exports/query-lane-context.d.ts +0 -2
  146. package/dist/exports/query-lane-context.d.ts.map +0 -1
  147. package/dist/exports/query-lane-context.js +0 -2
  148. package/dist/exports/query-lane-context.js.map +0 -1
  149. package/dist/exports/schema.d.ts +0 -3
  150. package/dist/exports/schema.d.ts.map +0 -1
  151. package/dist/exports/schema.js +0 -14
  152. package/dist/exports/schema.js.map +0 -1
  153. package/dist/exports/types.d.ts +0 -2
  154. package/dist/exports/types.d.ts.map +0 -1
  155. package/dist/exports/types.js +0 -10
  156. package/dist/exports/types.js.map +0 -1
  157. package/dist/index.d.ts +0 -9
  158. package/dist/index.d.ts.map +0 -1
  159. package/dist/index.js +0 -81
  160. package/dist/index.js.map +0 -1
  161. package/dist/operations-registry.d.ts +0 -5
  162. package/dist/operations-registry.d.ts.map +0 -1
  163. package/dist/param.d.ts +0 -4
  164. package/dist/param.d.ts.map +0 -1
  165. package/dist/plan.d.ts +0 -23
  166. package/dist/plan.d.ts.map +0 -1
  167. package/dist/query-lane-context.d.ts +0 -16
  168. package/dist/query-lane-context.d.ts.map +0 -1
  169. package/dist/schema.d.ts +0 -63
  170. package/dist/schema.d.ts.map +0 -1
  171. package/dist/types.d.ts +0 -332
  172. package/dist/types.d.ts.map +0 -1
  173. package/dist/utils/guards.d.ts +0 -55
  174. package/dist/utils/guards.d.ts.map +0 -1
package/src/types.ts CHANGED
@@ -10,25 +10,35 @@ import type {
10
10
  BinaryOp,
11
11
  ColumnRef,
12
12
  Direction,
13
+ Expression,
14
+ ExpressionSource,
13
15
  OperationExpr,
14
16
  ParamRef,
15
17
  QueryAst,
16
18
  } from './ast/types';
17
19
  import type { SqlQueryPlan } from './plan';
18
- import type { QueryLaneContext } from './query-lane-context';
20
+ import type { ExecutionContext } from './query-lane-context';
19
21
 
20
22
  export interface ParamPlaceholder {
21
23
  readonly kind: 'param-placeholder';
22
24
  readonly name: string;
23
25
  }
24
26
 
27
+ /**
28
+ * ValueSource represents any value that can appear in a comparison or as an argument.
29
+ * This includes:
30
+ * - ParamPlaceholder: A parameter placeholder (e.g., `param('userId')`)
31
+ * - ExpressionSource: Something that can be converted to an Expression (ColumnBuilder, ExpressionBuilder)
32
+ */
33
+ export type ValueSource = ParamPlaceholder | ExpressionSource;
34
+
25
35
  export interface OrderBuilder<
26
- ColumnName extends string = string,
27
- ColumnMeta extends StorageColumn = StorageColumn,
28
- JsType = unknown,
36
+ _ColumnName extends string = string,
37
+ _ColumnMeta extends StorageColumn = StorageColumn,
38
+ _JsType = unknown,
29
39
  > {
30
40
  readonly kind: 'order';
31
- readonly expr: ColumnBuilder<ColumnName, ColumnMeta, JsType> | OperationExpr;
41
+ readonly expr: Expression;
32
42
  readonly dir: Direction;
33
43
  }
34
44
 
@@ -45,6 +55,9 @@ export function createOrderBuilder(
45
55
  /**
46
56
  * ColumnBuilder with optional operation methods based on the column's typeId.
47
57
  * When Operations is provided and the column's typeId matches, operation methods are included.
58
+ * Implements ExpressionSource to provide type-safe conversion to ColumnRef.
59
+ *
60
+ * For nullable columns (ColumnMeta['nullable'] extends true), includes isNull() and isNotNull() methods.
48
61
  */
49
62
  export type ColumnBuilder<
50
63
  ColumnName extends string = string,
@@ -56,20 +69,17 @@ export type ColumnBuilder<
56
69
  readonly table: string;
57
70
  readonly column: ColumnName;
58
71
  readonly columnMeta: ColumnMeta;
59
- eq(value: ParamPlaceholder | AnyColumnBuilderBase): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
60
- neq(
61
- value: ParamPlaceholder | AnyColumnBuilderBase,
62
- ): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
63
- gt(value: ParamPlaceholder | AnyColumnBuilderBase): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
64
- lt(value: ParamPlaceholder | AnyColumnBuilderBase): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
65
- gte(
66
- value: ParamPlaceholder | AnyColumnBuilderBase,
67
- ): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
68
- lte(
69
- value: ParamPlaceholder | AnyColumnBuilderBase,
70
- ): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
72
+ // Methods accept ValueSource (ParamPlaceholder or ExpressionSource)
73
+ eq(value: ValueSource): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
74
+ neq(value: ValueSource): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
75
+ gt(value: ValueSource): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
76
+ lt(value: ValueSource): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
77
+ gte(value: ValueSource): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
78
+ lte(value: ValueSource): BinaryBuilder<ColumnName, ColumnMeta, JsType>;
71
79
  asc(): OrderBuilder<ColumnName, ColumnMeta, JsType>;
72
80
  desc(): OrderBuilder<ColumnName, ColumnMeta, JsType>;
81
+ /** Converts this column builder to a ColumnRef expression */
82
+ toExpr(): ColumnRef;
73
83
  // Helper property for type extraction (not used at runtime)
74
84
  readonly __jsType: JsType;
75
85
  } & (ColumnMeta['codecId'] extends string
@@ -81,17 +91,92 @@ export type ColumnBuilder<
81
91
  JsType
82
92
  >
83
93
  : Record<string, never>
84
- : Record<string, never>);
94
+ : Record<string, never>) &
95
+ (ColumnMeta['nullable'] extends true
96
+ ? NullableMethods<ColumnName, ColumnMeta, JsType>
97
+ : Record<string, never>);
85
98
 
86
99
  export interface BinaryBuilder<
100
+ _ColumnName extends string = string,
101
+ _ColumnMeta extends StorageColumn = StorageColumn,
102
+ _JsType = unknown,
103
+ > {
104
+ readonly kind: 'binary';
105
+ readonly op: BinaryOp;
106
+ readonly left: Expression;
107
+ readonly right: ValueSource;
108
+ }
109
+
110
+ /**
111
+ * Builder for IS NULL / IS NOT NULL checks.
112
+ * Used to build unary null check expressions in WHERE clauses.
113
+ */
114
+ export interface NullCheckBuilder<
115
+ _ColumnName extends string = string,
116
+ _ColumnMeta extends StorageColumn = StorageColumn,
117
+ _JsType = unknown,
118
+ > {
119
+ readonly kind: 'nullCheck';
120
+ readonly expr: Expression;
121
+ readonly isNull: boolean;
122
+ }
123
+
124
+ /**
125
+ * Union type for unary builders (currently just NullCheckBuilder).
126
+ * Extensible for future unary operators.
127
+ */
128
+ export type UnaryBuilder = NullCheckBuilder;
129
+
130
+ // Forward declare AnyBinaryBuilder and AnyOrderBuilder for use in ExpressionBuilder
131
+ export type AnyBinaryBuilder = BinaryBuilder;
132
+ export type AnyOrderBuilder = OrderBuilder;
133
+ export type AnyUnaryBuilder = UnaryBuilder;
134
+
135
+ /**
136
+ * Methods available only on nullable columns.
137
+ * These are conditionally added to ColumnBuilder when ColumnMeta['nullable'] is true.
138
+ * Note: Index signature is required for compatibility with AnyColumnBuilderBase's index signature.
139
+ */
140
+ export interface NullableMethods<
87
141
  ColumnName extends string = string,
88
142
  ColumnMeta extends StorageColumn = StorageColumn,
89
143
  JsType = unknown,
90
144
  > {
91
- readonly kind: 'binary';
92
- readonly op: BinaryOp;
93
- readonly left: ColumnBuilder<ColumnName, ColumnMeta, JsType> | OperationExpr;
94
- readonly right: ParamPlaceholder | AnyColumnBuilderBase;
145
+ /** Creates an IS NULL check for this column */
146
+ isNull(): NullCheckBuilder<ColumnName, ColumnMeta, JsType>;
147
+ /** Creates an IS NOT NULL check for this column */
148
+ isNotNull(): NullCheckBuilder<ColumnName, ColumnMeta, JsType>;
149
+ /** Index signature for compatibility with AnyColumnBuilderBase */
150
+ readonly [key: string]: unknown;
151
+ }
152
+
153
+ /**
154
+ * ExpressionBuilder represents the result of an operation (e.g., col.distance(...)).
155
+ * Unlike ColumnBuilder (which represents a column), ExpressionBuilder represents
156
+ * an operation expression and provides the same DSL methods for chaining.
157
+ *
158
+ * Implements ExpressionSource to provide type-safe conversion to OperationExpr.
159
+ */
160
+ export interface ExpressionBuilder<JsType = unknown> extends ExpressionSource {
161
+ readonly kind: 'expression';
162
+ readonly expr: OperationExpr;
163
+ readonly columnMeta: StorageColumn;
164
+
165
+ // Methods accept ValueSource (ParamPlaceholder or ExpressionSource)
166
+ eq(value: ValueSource): AnyBinaryBuilder;
167
+ neq(value: ValueSource): AnyBinaryBuilder;
168
+ gt(value: ValueSource): AnyBinaryBuilder;
169
+ lt(value: ValueSource): AnyBinaryBuilder;
170
+ gte(value: ValueSource): AnyBinaryBuilder;
171
+ lte(value: ValueSource): AnyBinaryBuilder;
172
+ asc(): AnyOrderBuilder;
173
+ desc(): AnyOrderBuilder;
174
+
175
+ /** Converts this expression builder to the underlying OperationExpr */
176
+ toExpr(): OperationExpr;
177
+
178
+ // Helper property for type extraction (not used at runtime)
179
+ readonly __jsType: JsType;
95
180
  }
96
181
 
97
182
  // Helper aliases for usage sites where the specific column parameters are irrelevant
@@ -108,15 +193,20 @@ export type AnyColumnBuilderBase = {
108
193
  readonly table: string;
109
194
  readonly column: string;
110
195
  readonly columnMeta: StorageColumn;
111
- eq(value: ParamPlaceholder | AnyColumnBuilderBase): AnyBinaryBuilder;
112
- neq(value: ParamPlaceholder | AnyColumnBuilderBase): AnyBinaryBuilder;
113
- gt(value: ParamPlaceholder | AnyColumnBuilderBase): AnyBinaryBuilder;
114
- lt(value: ParamPlaceholder | AnyColumnBuilderBase): AnyBinaryBuilder;
115
- gte(value: ParamPlaceholder | AnyColumnBuilderBase): AnyBinaryBuilder;
116
- lte(value: ParamPlaceholder | AnyColumnBuilderBase): AnyBinaryBuilder;
196
+ // Methods accept ValueSource (ParamPlaceholder or ExpressionSource)
197
+ eq(value: ValueSource): AnyBinaryBuilder;
198
+ neq(value: ValueSource): AnyBinaryBuilder;
199
+ gt(value: ValueSource): AnyBinaryBuilder;
200
+ lt(value: ValueSource): AnyBinaryBuilder;
201
+ gte(value: ValueSource): AnyBinaryBuilder;
202
+ lte(value: ValueSource): AnyBinaryBuilder;
117
203
  asc(): AnyOrderBuilder;
118
204
  desc(): AnyOrderBuilder;
205
+ toExpr(): ColumnRef;
119
206
  readonly __jsType: unknown;
207
+ // Optional nullable methods (present when columnMeta.nullable is true)
208
+ isNull?(): AnyUnaryBuilder;
209
+ isNotNull?(): AnyUnaryBuilder;
120
210
  // Allow any operation methods (from conditional type)
121
211
  readonly [key: string]: unknown;
122
212
  };
@@ -130,8 +220,12 @@ export type AnyColumnBuilder =
130
220
  any
131
221
  >
132
222
  | AnyColumnBuilderBase;
133
- export type AnyBinaryBuilder = BinaryBuilder<string, StorageColumn, unknown>;
134
- export type AnyOrderBuilder = OrderBuilder<string, StorageColumn, unknown>;
223
+
224
+ /**
225
+ * Union type for any builder that can produce an Expression.
226
+ * Used in DSL method signatures where either a column or operation result can be passed.
227
+ */
228
+ export type AnyExpressionSource = AnyColumnBuilder | ExpressionBuilder;
135
229
 
136
230
  export function isColumnBuilder(value: unknown): value is AnyColumnBuilder {
137
231
  return (
@@ -167,6 +261,136 @@ type ExtractCodecOutputType<
167
261
  : never
168
262
  : never;
169
263
 
264
+ /**
265
+ * Extracts the model name for a given table from the contract mappings.
266
+ */
267
+ type ExtractTableToModel<
268
+ Contract extends SqlContract<SqlStorage>,
269
+ TableName extends string,
270
+ > = Contract['mappings'] extends {
271
+ readonly tableToModel: infer TableToModel;
272
+ }
273
+ ? TableToModel extends Record<string, string>
274
+ ? TableName extends keyof TableToModel
275
+ ? TableToModel[TableName]
276
+ : never
277
+ : never
278
+ : never;
279
+
280
+ /**
281
+ * Extracts the field name for a given table column from the contract mappings.
282
+ */
283
+ type ExtractColumnToField<
284
+ Contract extends SqlContract<SqlStorage>,
285
+ TableName extends string,
286
+ ColumnName extends string,
287
+ > = Contract['mappings'] extends {
288
+ readonly columnToField: infer ColumnToField;
289
+ }
290
+ ? ColumnToField extends Record<string, Record<string, string>>
291
+ ? TableName extends keyof ColumnToField
292
+ ? ColumnName extends keyof ColumnToField[TableName]
293
+ ? ColumnToField[TableName][ColumnName]
294
+ : never
295
+ : never
296
+ : never
297
+ : never;
298
+
299
+ /**
300
+ * Extracts the field value type from a model's fields.
301
+ */
302
+ type ExtractFieldValue<
303
+ Contract extends SqlContract<SqlStorage>,
304
+ ModelName extends string,
305
+ FieldName extends string,
306
+ > = Contract['models'] extends infer Models
307
+ ? Models extends Record<string, unknown>
308
+ ? ModelName extends keyof Models
309
+ ? Models[ModelName] extends { readonly fields: infer Fields }
310
+ ? Fields extends Record<string, unknown>
311
+ ? FieldName extends keyof Fields
312
+ ? Fields[FieldName]
313
+ : never
314
+ : never
315
+ : never
316
+ : never
317
+ : never
318
+ : never;
319
+
320
+ /**
321
+ * Extracts the JavaScript type for a column from model mappings if available.
322
+ * Returns `never` if the column maps to a ModelField object (which indicates
323
+ * a relation that should fall through to codec-based type resolution).
324
+ *
325
+ * The check for ModelField uses `Exclude<keyof FieldValue, 'column'> extends never`
326
+ * to ensure we only skip pure `{ column: string }` marker objects, not richer
327
+ * object types that happen to include a `column` property.
328
+ */
329
+ type ExtractColumnJsTypeFromModels<
330
+ Contract extends SqlContract<SqlStorage>,
331
+ TableName extends string,
332
+ ColumnName extends string,
333
+ > = ExtractTableToModel<Contract, TableName> extends infer ModelName
334
+ ? ModelName extends string
335
+ ? ExtractColumnToField<Contract, TableName, ColumnName> extends infer FieldName
336
+ ? FieldName extends string
337
+ ? ExtractFieldValue<Contract, ModelName, FieldName> extends infer FieldValue
338
+ ? FieldValue extends { readonly column: string }
339
+ ? Exclude<keyof FieldValue, 'column'> extends never
340
+ ? never
341
+ : FieldValue
342
+ : FieldValue
343
+ : never
344
+ : never
345
+ : never
346
+ : never
347
+ : never;
348
+
349
+ /**
350
+ * Resolves type params for a column from either:
351
+ * - inline `columnMeta.typeParams`, or
352
+ * - `columnMeta.typeRef` (resolving into `contract.storage.types[typeRef].typeParams`).
353
+ */
354
+ type ResolveColumnTypeParams<
355
+ Contract extends SqlContract<SqlStorage>,
356
+ ColumnMeta extends StorageColumn,
357
+ > = ColumnMeta extends { typeParams: infer Params }
358
+ ? Params extends object
359
+ ? Params
360
+ : undefined
361
+ : ColumnMeta extends { typeRef: infer TypeRef extends string }
362
+ ? Contract['storage'] extends { types: infer Types }
363
+ ? Types extends Record<string, unknown>
364
+ ? TypeRef extends keyof Types
365
+ ? Types[TypeRef] extends { typeParams: infer Params }
366
+ ? Params extends object
367
+ ? Params
368
+ : undefined
369
+ : undefined
370
+ : undefined
371
+ : undefined
372
+ : undefined
373
+ : undefined;
374
+
375
+ /**
376
+ * If a codec entry exposes a type-level parameterized output surface, compute the output type
377
+ * for a specific params object. Falls back to `never` if not supported.
378
+ *
379
+ * This enables lane typing to incorporate `columnMeta.typeParams` without branching on codec IDs
380
+ * in core lane code.
381
+ */
382
+ type ExtractParameterizedCodecOutputType<
383
+ CodecId extends string,
384
+ Params,
385
+ CodecTypes extends Record<string, { readonly output: unknown }>,
386
+ > = CodecId extends keyof CodecTypes
387
+ ? CodecTypes[CodecId] extends { readonly parameterizedOutput: infer Fn }
388
+ ? Fn extends (params: Params) => infer Out
389
+ ? Out
390
+ : never
391
+ : never
392
+ : never;
393
+
170
394
  /**
171
395
  * Type-level operation signature.
172
396
  * Represents an operation at the type level, similar to OperationSignature at runtime.
@@ -264,7 +488,7 @@ type OperationArgs<Args extends ReadonlyArray<ArgSpec>> = Args extends readonly
264
488
  : [];
265
489
 
266
490
  type ArgToType<Arg extends ArgSpec> = Arg extends { kind: 'typeId' }
267
- ? AnyColumnBuilder
491
+ ? AnyExpressionSource
268
492
  : Arg extends { kind: 'param' }
269
493
  ? ParamPlaceholder
270
494
  : Arg extends { kind: 'literal' }
@@ -273,25 +497,25 @@ type ArgToType<Arg extends ArgSpec> = Arg extends { kind: 'typeId' }
273
497
 
274
498
  /**
275
499
  * Maps operation return spec to return type.
276
- * - builtin types: ColumnBuilder with appropriate JsType (matches runtime behavior)
277
- * - typeId types: ColumnBuilder (for now, could be more specific in future)
500
+ * Operations return ExpressionBuilder, not ColumnBuilder, because the result
501
+ * represents an expression (OperationExpr) rather than a column reference.
278
502
  */
279
503
  type OperationReturn<
280
504
  Returns extends ReturnSpec,
281
- ColumnName extends string,
282
- ColumnMeta extends StorageColumn,
505
+ _ColumnName extends string,
506
+ _ColumnMeta extends StorageColumn,
283
507
  _JsType,
284
508
  > = Returns extends { kind: 'builtin'; type: infer T }
285
509
  ? T extends 'number'
286
- ? ColumnBuilder<ColumnName, ColumnMeta, number>
510
+ ? ExpressionBuilder<number>
287
511
  : T extends 'boolean'
288
- ? ColumnBuilder<ColumnName, ColumnMeta, boolean>
512
+ ? ExpressionBuilder<boolean>
289
513
  : T extends 'string'
290
- ? ColumnBuilder<ColumnName, ColumnMeta, string>
291
- : ColumnBuilder<ColumnName, ColumnMeta, unknown>
514
+ ? ExpressionBuilder<string>
515
+ : ExpressionBuilder<unknown>
292
516
  : Returns extends { kind: 'typeId' }
293
- ? AnyColumnBuilder
294
- : ColumnBuilder<ColumnName, ColumnMeta, unknown>;
517
+ ? ExpressionBuilder<unknown>
518
+ : ExpressionBuilder<unknown>;
295
519
 
296
520
  /**
297
521
  * Computes JavaScript type for a column at column creation time.
@@ -308,23 +532,47 @@ type ColumnMetaTypeId<ColumnMeta> = ColumnMeta extends { codecId: infer CodecId
308
532
  : never;
309
533
 
310
534
  export type ComputeColumnJsType<
311
- _Contract extends SqlContract<SqlStorage>,
312
- _TableName extends string,
313
- _ColumnName extends string,
535
+ Contract extends SqlContract<SqlStorage>,
536
+ TableName extends string,
537
+ ColumnName extends string,
314
538
  ColumnMeta extends StorageColumn,
315
539
  CodecTypes extends Record<string, { readonly output: unknown }>,
316
- > = ColumnMeta extends { nullable: infer Nullable }
317
- ? ColumnMetaTypeId<ColumnMeta> extends infer TypeId
318
- ? TypeId extends string
319
- ? ExtractCodecOutputType<TypeId, CodecTypes> extends infer CodecOutput
320
- ? [CodecOutput] extends [never]
321
- ? unknown // Codec not found in CodecTypes
322
- : Nullable extends true
323
- ? CodecOutput | null
324
- : CodecOutput
540
+ > = ExtractColumnJsTypeFromModels<Contract, TableName, ColumnName> extends infer FromModels
541
+ ? [FromModels] extends [never]
542
+ ? ColumnMeta extends { nullable: infer Nullable }
543
+ ? ColumnMetaTypeId<ColumnMeta> extends infer TypeId
544
+ ? TypeId extends string
545
+ ? ResolveColumnTypeParams<Contract, ColumnMeta> extends infer Params
546
+ ? Params extends object
547
+ ? ExtractParameterizedCodecOutputType<
548
+ TypeId,
549
+ Params,
550
+ CodecTypes
551
+ > extends infer ParamOutput
552
+ ? [ParamOutput] extends [never]
553
+ ? ExtractCodecOutputType<TypeId, CodecTypes> extends infer CodecOutput
554
+ ? [CodecOutput] extends [never]
555
+ ? unknown // Codec not found in CodecTypes
556
+ : Nullable extends true
557
+ ? CodecOutput | null
558
+ : CodecOutput
559
+ : unknown
560
+ : Nullable extends true
561
+ ? ParamOutput | null
562
+ : ParamOutput
563
+ : unknown
564
+ : ExtractCodecOutputType<TypeId, CodecTypes> extends infer CodecOutput
565
+ ? [CodecOutput] extends [never]
566
+ ? unknown // Codec not found in CodecTypes
567
+ : Nullable extends true
568
+ ? CodecOutput | null
569
+ : CodecOutput
570
+ : unknown
571
+ : unknown
572
+ : unknown
325
573
  : unknown
326
574
  : unknown
327
- : unknown
575
+ : FromModels
328
576
  : unknown;
329
577
 
330
578
  /**
@@ -336,31 +584,33 @@ export type ComputeColumnJsType<
336
584
  /**
337
585
  * Extracts the inferred JsType carried by a ColumnBuilder.
338
586
  */
339
- type ExtractJsTypeFromColumnBuilder<CB extends AnyColumnBuilder> = CB extends ColumnBuilder<
340
- infer _ColumnName extends string,
341
- infer _ColumnMeta extends StorageColumn,
342
- infer JsType,
343
- infer _Ops
344
- >
345
- ? JsType
346
- : never;
587
+ type ExtractJsTypeFromColumnBuilder<CB extends AnyColumnBuilder> =
588
+ CB extends ColumnBuilder<
589
+ infer _ColumnName extends string,
590
+ infer _ColumnMeta extends StorageColumn,
591
+ infer JsType,
592
+ infer _Ops
593
+ >
594
+ ? JsType
595
+ : never;
347
596
 
348
597
  export type InferProjectionRow<P extends Record<string, AnyColumnBuilder>> = {
349
598
  [K in keyof P]: ExtractJsTypeFromColumnBuilder<P[K]>;
350
599
  };
351
600
 
352
601
  /**
353
- * Nested projection type - allows recursive nesting of ColumnBuilder or nested objects.
602
+ * Nested projection type - allows recursive nesting of ColumnBuilder, ExpressionBuilder, or nested objects.
354
603
  */
355
604
  export type NestedProjection = Record<
356
605
  string,
357
- | AnyColumnBuilder
606
+ | AnyExpressionSource
358
607
  | Record<
359
608
  string,
360
- | AnyColumnBuilder
609
+ | AnyExpressionSource
361
610
  | Record<
362
611
  string,
363
- AnyColumnBuilder | Record<string, AnyColumnBuilder | Record<string, AnyColumnBuilder>>
612
+ | AnyExpressionSource
613
+ | Record<string, AnyExpressionSource | Record<string, AnyExpressionSource>>
364
614
  >
365
615
  >
366
616
  >;
@@ -383,17 +633,19 @@ type ExtractIncludeType<
383
633
  * by looking up the include alias in the Includes type map.
384
634
  */
385
635
  export type InferNestedProjectionRow<
386
- P extends Record<string, AnyColumnBuilder | boolean | NestedProjection>,
636
+ P extends Record<string, AnyExpressionSource | boolean | NestedProjection>,
387
637
  CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
388
638
  Includes extends Record<string, unknown> = Record<string, never>,
389
639
  > = {
390
- [K in keyof P]: P[K] extends AnyColumnBuilder
391
- ? ExtractJsTypeFromColumnBuilder<P[K]>
392
- : P[K] extends true
393
- ? Array<ExtractIncludeType<K & string, Includes>> // Include reference - infers Array<ChildShape> from Includes map
394
- : P[K] extends NestedProjection
395
- ? InferNestedProjectionRow<P[K], CodecTypes, Includes>
396
- : never;
640
+ [K in keyof P]: P[K] extends ExpressionBuilder<infer JsType>
641
+ ? JsType
642
+ : P[K] extends AnyColumnBuilder
643
+ ? ExtractJsTypeFromColumnBuilder<P[K]>
644
+ : P[K] extends true
645
+ ? Array<ExtractIncludeType<K & string, Includes>> // Include reference - infers Array<ChildShape> from Includes map
646
+ : P[K] extends NestedProjection
647
+ ? InferNestedProjectionRow<P[K], CodecTypes, Includes>
648
+ : never;
397
649
  };
398
650
 
399
651
  /**
@@ -536,7 +788,7 @@ export interface BuildOptions {
536
788
  export interface SqlBuilderOptions<
537
789
  TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
538
790
  > {
539
- readonly context: QueryLaneContext<TContract>;
791
+ readonly context: ExecutionContext<TContract>;
540
792
  }
541
793
 
542
794
  /**