@prisma-next/sql-relational-core 0.3.0-dev.2 → 0.3.0-dev.21

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 (106) hide show
  1. package/README.md +1 -1
  2. package/dist/ast/adapter-types.d.ts +28 -0
  3. package/dist/ast/adapter-types.d.ts.map +1 -0
  4. package/dist/{query-lane-context-BhOMmb_K.d.ts → ast/codec-types.d.ts} +14 -31
  5. package/dist/ast/codec-types.d.ts.map +1 -0
  6. package/dist/ast/common.d.ts +7 -0
  7. package/dist/ast/common.d.ts.map +1 -0
  8. package/dist/ast/delete.d.ts +8 -0
  9. package/dist/ast/delete.d.ts.map +1 -0
  10. package/dist/ast/driver-types.d.ts +20 -0
  11. package/dist/ast/driver-types.d.ts.map +1 -0
  12. package/dist/ast/insert.d.ts +8 -0
  13. package/dist/ast/insert.d.ts.map +1 -0
  14. package/dist/ast/join.d.ts +6 -0
  15. package/dist/ast/join.d.ts.map +1 -0
  16. package/dist/ast/order.d.ts +6 -0
  17. package/dist/ast/order.d.ts.map +1 -0
  18. package/dist/ast/predicate.d.ts +4 -0
  19. package/dist/ast/predicate.d.ts.map +1 -0
  20. package/dist/ast/select.d.ts +18 -0
  21. package/dist/ast/select.d.ts.map +1 -0
  22. package/dist/{plan-D0OG5qzy.d.ts → ast/types.d.ts} +23 -47
  23. package/dist/ast/types.d.ts.map +1 -0
  24. package/dist/ast/update.d.ts +9 -0
  25. package/dist/ast/update.d.ts.map +1 -0
  26. package/dist/ast/util.d.ts +2 -0
  27. package/dist/ast/util.d.ts.map +1 -0
  28. package/dist/{chunk-MM74SVJ4.js → chunk-D4JLPIWO.js} +1 -1
  29. package/dist/{chunk-MM74SVJ4.js.map → chunk-D4JLPIWO.js.map} +1 -1
  30. package/dist/{chunk-WZBPVEZI.js → chunk-J6O2HVBM.js} +2 -2
  31. package/dist/chunk-J6O2HVBM.js.map +1 -0
  32. package/dist/{chunk-CBTYMOX2.js → chunk-U7IAFPVU.js} +2 -2
  33. package/dist/errors.d.ts +2 -0
  34. package/dist/errors.d.ts.map +1 -0
  35. package/dist/exports/ast.d.ts +14 -119
  36. package/dist/exports/ast.d.ts.map +1 -0
  37. package/dist/exports/ast.js +2 -2
  38. package/dist/exports/errors.d.ts +2 -1
  39. package/dist/exports/errors.d.ts.map +1 -0
  40. package/dist/exports/guards.d.ts +2 -63
  41. package/dist/exports/guards.d.ts.map +1 -0
  42. package/dist/exports/operations-registry.d.ts +2 -13
  43. package/dist/exports/operations-registry.d.ts.map +1 -0
  44. package/dist/exports/param.d.ts +3 -14
  45. package/dist/exports/param.d.ts.map +1 -0
  46. package/dist/exports/plan.d.ts +2 -5
  47. package/dist/exports/plan.d.ts.map +1 -0
  48. package/dist/exports/query-lane-context.d.ts +2 -4
  49. package/dist/exports/query-lane-context.d.ts.map +1 -0
  50. package/dist/exports/schema.d.ts +3 -69
  51. package/dist/exports/schema.d.ts.map +1 -0
  52. package/dist/exports/schema.js +2 -2
  53. package/dist/exports/types.d.ts +2 -335
  54. package/dist/exports/types.d.ts.map +1 -0
  55. package/dist/exports/types.js +1 -1
  56. package/dist/index.d.ts +9 -13
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +3 -3
  59. package/dist/operations-registry.d.ts +5 -0
  60. package/dist/operations-registry.d.ts.map +1 -0
  61. package/dist/param.d.ts +4 -0
  62. package/dist/param.d.ts.map +1 -0
  63. package/dist/plan.d.ts +23 -0
  64. package/dist/plan.d.ts.map +1 -0
  65. package/dist/query-lane-context.d.ts +16 -0
  66. package/dist/query-lane-context.d.ts.map +1 -0
  67. package/dist/schema.d.ts +63 -0
  68. package/dist/schema.d.ts.map +1 -0
  69. package/dist/types.d.ts +332 -0
  70. package/dist/types.d.ts.map +1 -0
  71. package/dist/utils/guards.d.ts +55 -0
  72. package/dist/utils/guards.d.ts.map +1 -0
  73. package/package.json +17 -18
  74. package/src/ast/adapter-types.ts +36 -0
  75. package/src/ast/codec-types.ts +376 -0
  76. package/src/ast/common.ts +36 -0
  77. package/src/ast/delete.ts +17 -0
  78. package/src/ast/driver-types.ts +25 -0
  79. package/src/ast/insert.ts +17 -0
  80. package/src/ast/join.ts +54 -0
  81. package/src/ast/order.ts +11 -0
  82. package/src/ast/predicate.ts +30 -0
  83. package/src/ast/select.ts +39 -0
  84. package/src/ast/types.ts +133 -0
  85. package/src/ast/update.ts +19 -0
  86. package/src/ast/util.ts +9 -0
  87. package/src/errors.ts +1 -0
  88. package/src/exports/ast.ts +13 -0
  89. package/src/exports/errors.ts +1 -0
  90. package/src/exports/guards.ts +10 -0
  91. package/src/exports/operations-registry.ts +1 -0
  92. package/src/exports/param.ts +2 -0
  93. package/src/exports/plan.ts +1 -0
  94. package/src/exports/query-lane-context.ts +1 -0
  95. package/src/exports/schema.ts +6 -0
  96. package/src/exports/types.ts +1 -0
  97. package/src/index.ts +8 -0
  98. package/src/operations-registry.ts +237 -0
  99. package/src/param.ts +15 -0
  100. package/src/plan.ts +39 -0
  101. package/src/query-lane-context.ts +18 -0
  102. package/src/schema.ts +373 -0
  103. package/src/types.ts +548 -0
  104. package/src/utils/guards.ts +123 -0
  105. package/dist/chunk-WZBPVEZI.js.map +0 -1
  106. /package/dist/{chunk-CBTYMOX2.js.map → chunk-U7IAFPVU.js.map} +0 -0
@@ -0,0 +1,133 @@
1
+ import type { ReturnSpec } from '@prisma-next/operations';
2
+ import type { SqlLoweringSpec } from '@prisma-next/sql-operations';
3
+
4
+ // SQL-specific AST types and supporting types
5
+ // These types are needed by adapters and runtime for SQL query execution
6
+
7
+ export type Direction = 'asc' | 'desc';
8
+
9
+ export interface TableRef {
10
+ readonly kind: 'table';
11
+ readonly name: string;
12
+ }
13
+
14
+ export interface ColumnRef {
15
+ readonly kind: 'col';
16
+ readonly table: string;
17
+ readonly column: string;
18
+ }
19
+
20
+ export interface ParamRef {
21
+ readonly kind: 'param';
22
+ readonly index: number;
23
+ readonly name?: string;
24
+ }
25
+
26
+ export interface LiteralExpr {
27
+ readonly kind: 'literal';
28
+ readonly value: unknown;
29
+ }
30
+
31
+ export interface OperationExpr {
32
+ readonly kind: 'operation';
33
+ readonly method: string;
34
+ readonly forTypeId: string;
35
+ readonly self: ColumnRef | OperationExpr;
36
+ readonly args: ReadonlyArray<ColumnRef | ParamRef | LiteralExpr | OperationExpr>;
37
+ readonly returns: ReturnSpec;
38
+ readonly lowering: SqlLoweringSpec;
39
+ }
40
+
41
+ export function isOperationExpr(expr: ColumnRef | OperationExpr): expr is OperationExpr {
42
+ return expr.kind === 'operation';
43
+ }
44
+
45
+ export type BinaryOp = 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte';
46
+
47
+ export interface BinaryExpr {
48
+ readonly kind: 'bin';
49
+ readonly op: BinaryOp;
50
+ readonly left: ColumnRef | OperationExpr;
51
+ readonly right: ColumnRef | ParamRef;
52
+ }
53
+
54
+ export interface ExistsExpr {
55
+ readonly kind: 'exists';
56
+ readonly not: boolean;
57
+ readonly subquery: SelectAst;
58
+ }
59
+
60
+ export type JoinOnExpr = {
61
+ readonly kind: 'eqCol';
62
+ readonly left: ColumnRef;
63
+ readonly right: ColumnRef;
64
+ };
65
+
66
+ export interface JoinAst {
67
+ readonly kind: 'join';
68
+ readonly joinType: 'inner' | 'left' | 'right' | 'full';
69
+ readonly table: TableRef;
70
+ readonly on: JoinOnExpr;
71
+ }
72
+
73
+ export interface IncludeRef {
74
+ readonly kind: 'includeRef';
75
+ readonly alias: string;
76
+ }
77
+
78
+ export interface IncludeAst {
79
+ readonly kind: 'includeMany';
80
+ readonly alias: string;
81
+ readonly child: {
82
+ readonly table: TableRef;
83
+ readonly on: JoinOnExpr;
84
+ readonly where?: BinaryExpr | ExistsExpr;
85
+ readonly orderBy?: ReadonlyArray<{ expr: ColumnRef | OperationExpr; dir: Direction }>;
86
+ readonly limit?: number;
87
+ readonly project: ReadonlyArray<{ alias: string; expr: ColumnRef | OperationExpr }>;
88
+ };
89
+ }
90
+
91
+ export interface SelectAst {
92
+ readonly kind: 'select';
93
+ readonly from: TableRef;
94
+ readonly joins?: ReadonlyArray<JoinAst>;
95
+ readonly includes?: ReadonlyArray<IncludeAst>;
96
+ readonly project: ReadonlyArray<{
97
+ alias: string;
98
+ expr: ColumnRef | IncludeRef | OperationExpr | LiteralExpr;
99
+ }>;
100
+ readonly where?: BinaryExpr | ExistsExpr;
101
+ readonly orderBy?: ReadonlyArray<{ expr: ColumnRef | OperationExpr; dir: Direction }>;
102
+ readonly limit?: number;
103
+ }
104
+
105
+ export interface InsertAst {
106
+ readonly kind: 'insert';
107
+ readonly table: TableRef;
108
+ readonly values: Record<string, ColumnRef | ParamRef>;
109
+ readonly returning?: ReadonlyArray<ColumnRef>;
110
+ }
111
+
112
+ export interface UpdateAst {
113
+ readonly kind: 'update';
114
+ readonly table: TableRef;
115
+ readonly set: Record<string, ColumnRef | ParamRef>;
116
+ readonly where: BinaryExpr;
117
+ readonly returning?: ReadonlyArray<ColumnRef>;
118
+ }
119
+
120
+ export interface DeleteAst {
121
+ readonly kind: 'delete';
122
+ readonly table: TableRef;
123
+ readonly where: BinaryExpr;
124
+ readonly returning?: ReadonlyArray<ColumnRef>;
125
+ }
126
+
127
+ export type QueryAst = SelectAst | InsertAst | UpdateAst | DeleteAst;
128
+
129
+ export interface LoweredStatement {
130
+ readonly sql: string;
131
+ readonly params: readonly unknown[];
132
+ readonly annotations?: Record<string, unknown>;
133
+ }
@@ -0,0 +1,19 @@
1
+ import type { BinaryExpr, ColumnRef, ParamRef, TableRef, UpdateAst } from './types';
2
+ import { compact } from './util';
3
+
4
+ export interface CreateUpdateAstOptions {
5
+ readonly table: TableRef;
6
+ readonly set: Record<string, ColumnRef | ParamRef>;
7
+ readonly where: BinaryExpr;
8
+ readonly returning?: ReadonlyArray<ColumnRef>;
9
+ }
10
+
11
+ export function createUpdateAst(options: CreateUpdateAstOptions): UpdateAst {
12
+ return compact({
13
+ kind: 'update',
14
+ table: options.table,
15
+ set: options.set,
16
+ where: options.where,
17
+ returning: options.returning,
18
+ }) as UpdateAst;
19
+ }
@@ -0,0 +1,9 @@
1
+ export function compact<T extends Record<string, unknown>>(o: T): T {
2
+ const out: Record<string, unknown> = {};
3
+ for (const [k, v] of Object.entries(o)) {
4
+ if (v === undefined || v === null) continue;
5
+ if (Array.isArray(v) && v.length === 0) continue;
6
+ out[k] = v;
7
+ }
8
+ return out as T;
9
+ }
package/src/errors.ts ADDED
@@ -0,0 +1 @@
1
+ export { planInvalid, planUnsupported } from '@prisma-next/plan';
@@ -0,0 +1,13 @@
1
+ export * from '../ast/adapter-types';
2
+ export * from '../ast/codec-types';
3
+ export * from '../ast/common';
4
+ export * from '../ast/delete';
5
+ export * from '../ast/driver-types';
6
+ export * from '../ast/insert';
7
+ export * from '../ast/join';
8
+ export * from '../ast/order';
9
+ export * from '../ast/predicate';
10
+ export * from '../ast/select';
11
+ export * from '../ast/types';
12
+ export * from '../ast/update';
13
+ export * from '../ast/util';
@@ -0,0 +1 @@
1
+ export { planInvalid, planUnsupported } from '../errors';
@@ -0,0 +1,10 @@
1
+ export {
2
+ collectColumnRefs,
3
+ extractBaseColumnRef,
4
+ getColumnInfo,
5
+ getColumnMeta,
6
+ getOperationExpr,
7
+ isColumnBuilder,
8
+ isOperationExpr,
9
+ isParamPlaceholder,
10
+ } from '../utils/guards';
@@ -0,0 +1 @@
1
+ export { attachOperationsToColumnBuilder } from '../operations-registry';
@@ -0,0 +1,2 @@
1
+ export type { Parameter } from '../param';
2
+ export { param } from '../param';
@@ -0,0 +1 @@
1
+ export * from '../plan';
@@ -0,0 +1 @@
1
+ export * from '../query-lane-context';
@@ -0,0 +1,6 @@
1
+ export type {
2
+ ColumnBuilderImpl as Column,
3
+ SchemaHandle,
4
+ TableBuilderImpl as Table,
5
+ } from '../schema';
6
+ export { ColumnBuilderImpl, schema, TableBuilderImpl } from '../schema';
@@ -0,0 +1 @@
1
+ export * from '../types';
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './exports/ast';
2
+ export * from './exports/errors';
3
+ export * from './exports/operations-registry';
4
+ export * from './exports/param';
5
+ export * from './exports/plan';
6
+ export * from './exports/query-lane-context';
7
+ export * from './exports/schema';
8
+ export * from './exports/types';
@@ -0,0 +1,237 @@
1
+ import type { OperationRegistry } from '@prisma-next/operations';
2
+ import { hasAllCapabilities } from '@prisma-next/operations';
3
+ import { planInvalid } from '@prisma-next/plan';
4
+ import type { StorageColumn } from '@prisma-next/sql-contract/types';
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';
9
+
10
+ function isColumnBuilder(value: unknown): value is AnyColumnBuilder {
11
+ return (
12
+ typeof value === 'object' &&
13
+ value !== null &&
14
+ 'kind' in value &&
15
+ (value as { kind: unknown }).kind === 'column'
16
+ );
17
+ }
18
+
19
+ /**
20
+ * Executes an operation and returns a column-shaped result object.
21
+ * This is the canonical entrypoint for operation invocation, enabling
22
+ * future enhancements like telemetry, caching, or tracing.
23
+ *
24
+ * @param signature - The operation signature from the registry
25
+ * @param selfBuilder - The column builder that the operation is called on
26
+ * @param args - The arguments passed to the operation
27
+ * @param columnMeta - The metadata of the column the operation is called on
28
+ * @returns A column-shaped builder with the operation expression attached
29
+ */
30
+ function executeOperation(
31
+ signature: SqlOperationSignature,
32
+ selfBuilder: AnyColumnBuilder,
33
+ args: unknown[],
34
+ columnMeta: StorageColumn,
35
+ operationRegistry?: OperationRegistry,
36
+ contractCapabilities?: Record<string, Record<string, boolean>>,
37
+ ): AnyColumnBuilder & { _operationExpr?: OperationExpr } {
38
+ if (args.length !== signature.args.length) {
39
+ throw planInvalid(
40
+ `Operation ${signature.method} expects ${signature.args.length} arguments, got ${args.length}`,
41
+ );
42
+ }
43
+
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> = [];
59
+ for (let i = 0; i < args.length; i++) {
60
+ const arg = args[i];
61
+ const argSpec = signature.args[i];
62
+ if (!argSpec) {
63
+ throw planInvalid(`Missing argument spec for argument ${i}`);
64
+ }
65
+
66
+ 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
+ });
75
+ } 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
+ });
94
+ }
95
+ } else if (argSpec.kind === 'literal') {
96
+ operationArgs.push({
97
+ kind: 'literal',
98
+ value: arg,
99
+ });
100
+ }
101
+ }
102
+
103
+ const operationExpr: OperationExpr = {
104
+ kind: 'operation',
105
+ method: signature.method,
106
+ forTypeId: signature.forTypeId,
107
+ self: selfExpr,
108
+ args: operationArgs,
109
+ returns: signature.returns,
110
+ lowering: signature.lowering,
111
+ };
112
+
113
+ const returnTypeId = signature.returns.kind === 'typeId' ? signature.returns.type : undefined;
114
+ const returnColumnMeta: StorageColumn = returnTypeId
115
+ ? {
116
+ ...columnMeta,
117
+ codecId: returnTypeId,
118
+ }
119
+ : columnMeta;
120
+
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,
133
+ get columnMeta() {
134
+ return returnColumnMeta;
135
+ },
136
+ eq: createComparisonMethod('eq'),
137
+ neq: createComparisonMethod('neq'),
138
+ gt: createComparisonMethod('gt'),
139
+ lt: createComparisonMethod('lt'),
140
+ gte: createComparisonMethod('gte'),
141
+ lte: createComparisonMethod('lte'),
142
+ asc() {
143
+ return Object.freeze({
144
+ kind: 'order' as const,
145
+ expr: operationExpr,
146
+ dir: 'asc' as const,
147
+ });
148
+ },
149
+ desc() {
150
+ return Object.freeze({
151
+ kind: 'order' as const,
152
+ expr: operationExpr,
153
+ dir: 'desc' as const,
154
+ });
155
+ },
156
+ _operationExpr: operationExpr,
157
+ } as unknown as AnyColumnBuilder & {
158
+ _operationExpr?: OperationExpr;
159
+ };
160
+
161
+ // If the return type is a typeId, attach operations for that type
162
+ if (returnTypeId && operationRegistry) {
163
+ const resultWithOps = attachOperationsToColumnBuilder(
164
+ baseResult as ColumnBuilder<string, StorageColumn, unknown, Record<string, never>>,
165
+ returnColumnMeta,
166
+ operationRegistry,
167
+ contractCapabilities,
168
+ ) as AnyColumnBuilder & {
169
+ _operationExpr?: OperationExpr;
170
+ };
171
+ return Object.freeze(resultWithOps);
172
+ }
173
+
174
+ return Object.freeze(baseResult);
175
+ }
176
+
177
+ export function attachOperationsToColumnBuilder<
178
+ ColumnName extends string,
179
+ ColumnMeta extends StorageColumn,
180
+ JsType = unknown,
181
+ Operations extends OperationTypes = Record<string, never>,
182
+ >(
183
+ columnBuilder: ColumnBuilder<ColumnName, ColumnMeta, JsType, Record<string, never>>,
184
+ columnMeta: ColumnMeta,
185
+ registry: OperationRegistry | undefined,
186
+ contractCapabilities?: Record<string, Record<string, boolean>>,
187
+ ): ColumnBuilder<ColumnName, ColumnMeta, JsType, Operations> {
188
+ if (!registry) {
189
+ return columnBuilder as ColumnBuilder<ColumnName, ColumnMeta, JsType, Operations>;
190
+ }
191
+
192
+ // Use codecId to look up operations registered for this column's type
193
+ const codecId = columnMeta.codecId;
194
+ if (!codecId) {
195
+ return columnBuilder as ColumnBuilder<ColumnName, ColumnMeta, JsType, Operations>;
196
+ }
197
+
198
+ const operations = registry.byType(codecId) as SqlOperationSignature[];
199
+ if (operations.length === 0) {
200
+ return columnBuilder as ColumnBuilder<ColumnName, ColumnMeta, JsType, Operations>;
201
+ }
202
+
203
+ const builderWithOps = columnBuilder as unknown as ColumnBuilder<
204
+ ColumnName,
205
+ ColumnMeta,
206
+ JsType,
207
+ Operations
208
+ >;
209
+
210
+ for (const operation of operations) {
211
+ if (operation.capabilities && operation.capabilities.length > 0) {
212
+ if (!contractCapabilities) {
213
+ continue;
214
+ }
215
+
216
+ if (!hasAllCapabilities(operation.capabilities, contractCapabilities)) {
217
+ continue;
218
+ }
219
+ }
220
+ // Method sugar: attach operation as a method on the column builder
221
+ (builderWithOps as Record<string, unknown>)[operation.method] = function (
222
+ this: ColumnBuilder<ColumnName, ColumnMeta, JsType, Record<string, never>>,
223
+ ...args: unknown[]
224
+ ) {
225
+ return executeOperation(
226
+ operation,
227
+ this as unknown as ColumnBuilder<string, StorageColumn, unknown>,
228
+ args,
229
+ columnMeta,
230
+ registry,
231
+ contractCapabilities,
232
+ );
233
+ };
234
+ }
235
+
236
+ return builderWithOps;
237
+ }
package/src/param.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { planInvalid } from '@prisma-next/plan';
2
+ import type { ParamPlaceholder } from './types';
3
+
4
+ export type Parameter = ParamPlaceholder;
5
+
6
+ export function param(name: string): Parameter {
7
+ if (typeof name !== 'string' || name.length === 0) {
8
+ throw planInvalid('Parameter name must be a non-empty string');
9
+ }
10
+
11
+ return Object.freeze({
12
+ kind: 'param-placeholder' as const,
13
+ name,
14
+ }) satisfies Parameter;
15
+ }
package/src/plan.ts ADDED
@@ -0,0 +1,39 @@
1
+ import type { ExecutionPlan, ParamDescriptor } from '@prisma-next/contract/types';
2
+ import type { StorageColumn } from '@prisma-next/sql-contract/types';
3
+ import type { QueryAst } from './ast/types';
4
+
5
+ /**
6
+ * SQL query plan produced by lanes before lowering.
7
+ *
8
+ * Lanes build ASTs and metadata but do not perform SQL lowering.
9
+ * The `sql` field is absent - lowering happens in the runtime executor.
10
+ *
11
+ * Structurally aligns with ExecutionPlan<Row, QueryAst> (without sql field) to maintain
12
+ * compatibility with ExecutionPlan/Plan-based utilities.
13
+ * The generic parameter `_Row` is preserved for type extraction via ResultType.
14
+ */
15
+ export interface SqlQueryPlan<_Row = unknown>
16
+ extends Pick<ExecutionPlan<_Row, QueryAst>, 'params' | 'meta'> {
17
+ readonly ast: QueryAst;
18
+ // Phantom property to preserve generic parameter for type extraction
19
+ // This allows ResultType to extract _Row for SqlQueryPlan values.
20
+ readonly _Row?: _Row;
21
+ }
22
+
23
+ /**
24
+ * Augments the last ParamDescriptor in the array with codecId and nativeType from columnMeta.
25
+ * This is used when building WHERE expressions to ensure param descriptors have type information.
26
+ */
27
+ export function augmentDescriptorWithColumnMeta(
28
+ descriptors: ParamDescriptor[],
29
+ columnMeta: StorageColumn | undefined,
30
+ ): void {
31
+ const descriptor = descriptors[descriptors.length - 1];
32
+ if (descriptor && columnMeta) {
33
+ descriptors[descriptors.length - 1] = {
34
+ ...descriptor,
35
+ codecId: columnMeta.codecId,
36
+ nativeType: columnMeta.nativeType,
37
+ };
38
+ }
39
+ }
@@ -0,0 +1,18 @@
1
+ import type { OperationRegistry } from '@prisma-next/operations';
2
+ import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
3
+ import type { CodecRegistry } from './ast/codec-types';
4
+
5
+ /**
6
+ * Minimal context interface for SQL query lanes.
7
+ *
8
+ * Lanes only need contract, operations, and codecs to build typed ASTs and attach
9
+ * operation builders. This interface explicitly excludes runtime concerns like
10
+ * adapters, connection management, and transaction state.
11
+ */
12
+ export interface QueryLaneContext<
13
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
14
+ > {
15
+ readonly contract: TContract;
16
+ readonly operations: OperationRegistry;
17
+ readonly codecs: CodecRegistry;
18
+ }