@prisma-next/sql-relational-core 0.3.0-dev.9 → 0.3.0-pr.100.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ast/codec-types.d.ts.map +1 -1
- package/dist/ast/predicate.d.ts +2 -2
- package/dist/ast/predicate.d.ts.map +1 -1
- package/dist/ast/types.d.ts +21 -9
- package/dist/ast/types.d.ts.map +1 -1
- package/dist/{chunk-5N34PNVZ.js → chunk-2MAKNVCP.js} +25 -1
- package/dist/chunk-2MAKNVCP.js.map +1 -0
- package/dist/{chunk-M23L3JHG.js → chunk-3F4RFQIB.js} +45 -35
- package/dist/chunk-3F4RFQIB.js.map +1 -0
- package/dist/{chunk-MM74SVJ4.js → chunk-5VGB5HY6.js} +1 -1
- package/dist/chunk-5VGB5HY6.js.map +1 -0
- package/dist/{chunk-WZBPVEZI.js → chunk-TFA5JL4O.js} +2 -2
- package/dist/chunk-TFA5JL4O.js.map +1 -0
- package/dist/{chunk-CBTYMOX2.js → chunk-YXD25S5I.js} +31 -12
- package/dist/chunk-YXD25S5I.js.map +1 -0
- package/dist/exports/ast.js +2 -2
- package/dist/exports/guards.d.ts +1 -1
- package/dist/exports/guards.d.ts.map +1 -1
- package/dist/exports/guards.js +13 -3
- package/dist/exports/operations-registry.js +2 -2
- package/dist/exports/schema.js +3 -4
- package/dist/exports/types.js +1 -1
- package/dist/index.js +5 -5
- package/dist/operations-registry.d.ts.map +1 -1
- package/dist/query-lane-context.d.ts +11 -0
- package/dist/query-lane-context.d.ts.map +1 -1
- package/dist/schema.d.ts +30 -10
- package/dist/schema.d.ts.map +1 -1
- package/dist/types.d.ts +106 -33
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/guards.d.ts +43 -16
- package/dist/utils/guards.d.ts.map +1 -1
- package/package.json +13 -13
- package/src/ast/codec-types.ts +5 -4
- package/src/ast/predicate.ts +3 -11
- package/src/ast/types.ts +23 -9
- package/src/exports/guards.ts +5 -0
- package/src/operations-registry.ts +112 -73
- package/src/query-lane-context.ts +12 -0
- package/src/schema.ts +64 -31
- package/src/types.ts +232 -73
- package/src/utils/guards.ts +88 -18
- package/dist/chunk-5N34PNVZ.js.map +0 -1
- package/dist/chunk-CBTYMOX2.js.map +0 -1
- package/dist/chunk-M23L3JHG.js.map +0 -1
- package/dist/chunk-MM74SVJ4.js.map +0 -1
- package/dist/chunk-WZBPVEZI.js.map +0 -1
package/dist/utils/guards.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { StorageColumn } from '@prisma-next/sql-contract/types';
|
|
2
|
-
import type { ColumnRef, LiteralExpr, OperationExpr, ParamRef } from '../ast/types';
|
|
3
|
-
import type { AnyColumnBuilder, ParamPlaceholder } from '../types';
|
|
2
|
+
import type { ColumnRef, Expression, ExpressionSource, LiteralExpr, OperationExpr, ParamRef } from '../ast/types';
|
|
3
|
+
import type { AnyColumnBuilder, AnyExpressionSource, ExpressionBuilder, ParamPlaceholder, ValueSource } from '../types';
|
|
4
4
|
/**
|
|
5
|
-
* Helper to extract columnMeta from a ColumnBuilder.
|
|
5
|
+
* Helper to extract columnMeta from a ColumnBuilder or ExpressionBuilder.
|
|
6
6
|
* Returns StorageColumn if present, undefined otherwise.
|
|
7
|
-
*
|
|
8
|
-
* so we can safely access it after checking for existence.
|
|
7
|
+
* Both ColumnBuilder and ExpressionBuilder have columnMeta property.
|
|
9
8
|
*/
|
|
10
|
-
export declare function getColumnMeta(expr:
|
|
9
|
+
export declare function getColumnMeta(expr: AnyExpressionSource): StorageColumn | undefined;
|
|
11
10
|
/**
|
|
12
11
|
* Type predicate to check if a value is a ParamPlaceholder.
|
|
13
12
|
*/
|
|
@@ -25,12 +24,12 @@ export declare function collectColumnRefs(expr: ColumnRef | ParamRef | LiteralEx
|
|
|
25
24
|
/**
|
|
26
25
|
* Type predicate to check if an expression is an OperationExpr.
|
|
27
26
|
*/
|
|
28
|
-
export declare function isOperationExpr(expr:
|
|
27
|
+
export declare function isOperationExpr(expr: AnyExpressionSource | OperationExpr | Expression): expr is OperationExpr;
|
|
29
28
|
/**
|
|
30
|
-
* Helper to extract table and column from a ColumnBuilder or OperationExpr.
|
|
31
|
-
* For OperationExpr, recursively unwraps to find the base ColumnRef.
|
|
29
|
+
* Helper to extract table and column from a ColumnBuilder, ExpressionBuilder, or OperationExpr.
|
|
30
|
+
* For ExpressionBuilder or OperationExpr, recursively unwraps to find the base ColumnRef.
|
|
32
31
|
*/
|
|
33
|
-
export declare function getColumnInfo(expr:
|
|
32
|
+
export declare function getColumnInfo(expr: AnyExpressionSource | OperationExpr): {
|
|
34
33
|
table: string;
|
|
35
34
|
column: string;
|
|
36
35
|
};
|
|
@@ -38,18 +37,46 @@ export declare function getColumnInfo(expr: AnyColumnBuilder | OperationExpr): {
|
|
|
38
37
|
* Type predicate to check if a value is a ColumnBuilder.
|
|
39
38
|
*/
|
|
40
39
|
export declare function isColumnBuilder(value: unknown): value is AnyColumnBuilder;
|
|
40
|
+
/**
|
|
41
|
+
* Type predicate to check if a value is an ExpressionBuilder.
|
|
42
|
+
*/
|
|
43
|
+
export declare function isExpressionBuilder(value: unknown): value is ExpressionBuilder;
|
|
44
|
+
/**
|
|
45
|
+
* Type predicate to check if a value is an ExpressionSource (has toExpr method).
|
|
46
|
+
*/
|
|
47
|
+
export declare function isExpressionSource(value: unknown): value is ExpressionSource;
|
|
48
|
+
/**
|
|
49
|
+
* Converts any ExpressionSource to an Expression.
|
|
50
|
+
* This is the canonical way to get an AST Expression from a builder.
|
|
51
|
+
*
|
|
52
|
+
* @param source - A ColumnBuilder or ExpressionBuilder
|
|
53
|
+
* @returns The corresponding Expression (ColumnRef or OperationExpr)
|
|
54
|
+
*/
|
|
55
|
+
export declare function toExpression(source: ExpressionSource): Expression;
|
|
56
|
+
/**
|
|
57
|
+
* Converts an AnyExpressionSource to an Expression.
|
|
58
|
+
* Handles both ColumnBuilder and ExpressionBuilder.
|
|
59
|
+
*
|
|
60
|
+
* @param source - A ColumnBuilder or ExpressionBuilder
|
|
61
|
+
* @returns The corresponding Expression (ColumnRef or OperationExpr)
|
|
62
|
+
*/
|
|
63
|
+
export declare function expressionFromSource(source: AnyExpressionSource): Expression;
|
|
64
|
+
/**
|
|
65
|
+
* Type predicate to check if a value is a ValueSource.
|
|
66
|
+
* ValueSource is either a ParamPlaceholder or an ExpressionSource.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isValueSource(value: unknown): value is ValueSource;
|
|
41
69
|
/**
|
|
42
70
|
* Extracts and returns an OperationExpr from a builder.
|
|
43
71
|
* Returns the OperationExpr if the builder is an OperationExpr or has an _operationExpr property,
|
|
44
72
|
* otherwise returns undefined.
|
|
45
73
|
*
|
|
74
|
+
* @deprecated Use isExpressionBuilder() instead. This function exists for backward compatibility
|
|
75
|
+
* with code that uses the hidden _operationExpr property pattern.
|
|
76
|
+
*
|
|
46
77
|
* @design-note: This function accesses the hidden `_operationExpr` property, which is a code smell.
|
|
47
|
-
* The
|
|
48
|
-
*
|
|
49
|
-
* implementation details. A cleaner design would be to have operation results be a separate
|
|
50
|
-
* type (e.g., `OperationResultBuilder`) that properly represents expression nodes rather than
|
|
51
|
-
* pretending to be a ColumnBuilder. This would require refactoring the operation execution
|
|
52
|
-
* system in relational-core to return proper expression types.
|
|
78
|
+
* The ExpressionBuilder type (introduced in the operation-expr-refactoring) provides a cleaner
|
|
79
|
+
* approach by explicitly representing operation results as a distinct type.
|
|
53
80
|
*/
|
|
54
81
|
export declare function getOperationExpr(builder: AnyColumnBuilder | OperationExpr): OperationExpr | undefined;
|
|
55
82
|
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/utils/guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/utils/guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,QAAQ,EACT,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,mBAAmB,GAAG,aAAa,GAAG,SAAS,CAOlF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAS5E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,GAAG,aAAa,GAAG,SAAS,CAK/E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,GACvD,SAAS,EAAE,CAYb;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,mBAAmB,GAAG,aAAa,GAAG,UAAU,GACrD,IAAI,IAAI,aAAa,CAEvB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,mBAAmB,GAAG,aAAa,GAAG;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAYA;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAOzE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAO9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAO5E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,mBAAmB,GAAG,UAAU,CAE5E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,GAAG,aAAa,GACxC,aAAa,GAAG,SAAS,CAM3B"}
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-relational-core",
|
|
3
|
-
"version": "0.3.0-
|
|
3
|
+
"version": "0.3.0-pr.100.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Schema and column builders, operation attachment, and AST types for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"ts-toolbelt": "^9.6.0",
|
|
9
|
-
"@prisma-next/
|
|
10
|
-
"@prisma-next/
|
|
11
|
-
"@prisma-next/
|
|
12
|
-
"@prisma-next/
|
|
13
|
-
"@prisma-next/sql-operations": "0.3.0-
|
|
9
|
+
"@prisma-next/operations": "0.3.0-pr.100.2",
|
|
10
|
+
"@prisma-next/plan": "0.3.0-pr.100.2",
|
|
11
|
+
"@prisma-next/sql-contract": "0.3.0-pr.100.2",
|
|
12
|
+
"@prisma-next/contract": "0.3.0-pr.100.2",
|
|
13
|
+
"@prisma-next/sql-operations": "0.3.0-pr.100.2"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@vitest/coverage-v8": "4.0.16",
|
|
17
16
|
"tsup": "8.5.1",
|
|
18
17
|
"typescript": "5.9.3",
|
|
19
18
|
"vitest": "4.0.16",
|
|
20
|
-
"@prisma-next/
|
|
21
|
-
"@prisma-next/
|
|
19
|
+
"@prisma-next/test-utils": "0.0.1",
|
|
20
|
+
"@prisma-next/tsconfig": "0.0.0",
|
|
21
|
+
"@prisma-next/sql-contract-ts": "0.3.0-pr.100.2"
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"dist",
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"test": "vitest run",
|
|
72
72
|
"test:coverage": "vitest run --coverage",
|
|
73
73
|
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
74
|
-
"lint": "biome check . --
|
|
75
|
-
"lint:fix": "biome check --write .
|
|
76
|
-
"lint:fix:unsafe": "biome check --write --unsafe .
|
|
77
|
-
"clean": "
|
|
74
|
+
"lint": "biome check . --error-on-warnings",
|
|
75
|
+
"lint:fix": "biome check --write .",
|
|
76
|
+
"lint:fix:unsafe": "biome check --write --unsafe .",
|
|
77
|
+
"clean": "rm -rf dist dist-tsc dist-tsc-prod coverage .tmp-output"
|
|
78
78
|
}
|
|
79
79
|
}
|
package/src/ast/codec-types.ts
CHANGED
|
@@ -176,11 +176,12 @@ export function codec<Id extends string, TWire, TJs>(config: {
|
|
|
176
176
|
/**
|
|
177
177
|
* Type helpers to extract codec types.
|
|
178
178
|
*/
|
|
179
|
-
export type CodecId<T> =
|
|
180
|
-
|
|
181
|
-
: T extends { readonly id: infer Id }
|
|
179
|
+
export type CodecId<T> =
|
|
180
|
+
T extends Codec<infer Id, unknown, unknown>
|
|
182
181
|
? Id
|
|
183
|
-
:
|
|
182
|
+
: T extends { readonly id: infer Id }
|
|
183
|
+
? Id
|
|
184
|
+
: never;
|
|
184
185
|
export type CodecInput<T> = T extends Codec<string, unknown, infer JsT> ? JsT : never;
|
|
185
186
|
export type CodecOutput<T> = T extends Codec<string, unknown, infer JsT> ? JsT : never;
|
|
186
187
|
|
package/src/ast/predicate.ts
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
BinaryExpr,
|
|
3
|
-
BinaryOp,
|
|
4
|
-
ColumnRef,
|
|
5
|
-
ExistsExpr,
|
|
6
|
-
OperationExpr,
|
|
7
|
-
ParamRef,
|
|
8
|
-
SelectAst,
|
|
9
|
-
} from './types';
|
|
1
|
+
import type { BinaryExpr, BinaryOp, ExistsExpr, Expression, ParamRef, SelectAst } from './types';
|
|
10
2
|
|
|
11
3
|
export function createBinaryExpr(
|
|
12
4
|
op: BinaryOp,
|
|
13
|
-
left:
|
|
14
|
-
right:
|
|
5
|
+
left: Expression,
|
|
6
|
+
right: Expression | ParamRef,
|
|
15
7
|
): BinaryExpr {
|
|
16
8
|
return {
|
|
17
9
|
kind: 'bin',
|
package/src/ast/types.ts
CHANGED
|
@@ -32,13 +32,27 @@ export interface OperationExpr {
|
|
|
32
32
|
readonly kind: 'operation';
|
|
33
33
|
readonly method: string;
|
|
34
34
|
readonly forTypeId: string;
|
|
35
|
-
readonly self:
|
|
36
|
-
readonly args: ReadonlyArray<
|
|
35
|
+
readonly self: Expression;
|
|
36
|
+
readonly args: ReadonlyArray<Expression | ParamRef | LiteralExpr>;
|
|
37
37
|
readonly returns: ReturnSpec;
|
|
38
38
|
readonly lowering: SqlLoweringSpec;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Unified expression type - the canonical AST representation for column references
|
|
43
|
+
* and operation expressions. This is what all builders convert to via toExpr().
|
|
44
|
+
*/
|
|
45
|
+
export type Expression = ColumnRef | OperationExpr;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Interface for any builder that can produce an Expression.
|
|
49
|
+
* Implemented by ColumnBuilder and ExpressionBuilder.
|
|
50
|
+
*/
|
|
51
|
+
export interface ExpressionSource {
|
|
52
|
+
toExpr(): Expression;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isOperationExpr(expr: Expression): expr is OperationExpr {
|
|
42
56
|
return expr.kind === 'operation';
|
|
43
57
|
}
|
|
44
58
|
|
|
@@ -47,8 +61,8 @@ export type BinaryOp = 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte';
|
|
|
47
61
|
export interface BinaryExpr {
|
|
48
62
|
readonly kind: 'bin';
|
|
49
63
|
readonly op: BinaryOp;
|
|
50
|
-
readonly left:
|
|
51
|
-
readonly right:
|
|
64
|
+
readonly left: Expression;
|
|
65
|
+
readonly right: Expression | ParamRef;
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
export interface ExistsExpr {
|
|
@@ -82,9 +96,9 @@ export interface IncludeAst {
|
|
|
82
96
|
readonly table: TableRef;
|
|
83
97
|
readonly on: JoinOnExpr;
|
|
84
98
|
readonly where?: BinaryExpr | ExistsExpr;
|
|
85
|
-
readonly orderBy?: ReadonlyArray<{ expr:
|
|
99
|
+
readonly orderBy?: ReadonlyArray<{ expr: Expression; dir: Direction }>;
|
|
86
100
|
readonly limit?: number;
|
|
87
|
-
readonly project: ReadonlyArray<{ alias: string; expr:
|
|
101
|
+
readonly project: ReadonlyArray<{ alias: string; expr: Expression }>;
|
|
88
102
|
};
|
|
89
103
|
}
|
|
90
104
|
|
|
@@ -95,10 +109,10 @@ export interface SelectAst {
|
|
|
95
109
|
readonly includes?: ReadonlyArray<IncludeAst>;
|
|
96
110
|
readonly project: ReadonlyArray<{
|
|
97
111
|
alias: string;
|
|
98
|
-
expr:
|
|
112
|
+
expr: Expression | IncludeRef | LiteralExpr;
|
|
99
113
|
}>;
|
|
100
114
|
readonly where?: BinaryExpr | ExistsExpr;
|
|
101
|
-
readonly orderBy?: ReadonlyArray<{ expr:
|
|
115
|
+
readonly orderBy?: ReadonlyArray<{ expr: Expression; dir: Direction }>;
|
|
102
116
|
readonly limit?: number;
|
|
103
117
|
}
|
|
104
118
|
|
package/src/exports/guards.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
export {
|
|
2
2
|
collectColumnRefs,
|
|
3
|
+
expressionFromSource,
|
|
3
4
|
extractBaseColumnRef,
|
|
4
5
|
getColumnInfo,
|
|
5
6
|
getColumnMeta,
|
|
6
7
|
getOperationExpr,
|
|
7
8
|
isColumnBuilder,
|
|
9
|
+
isExpressionBuilder,
|
|
10
|
+
isExpressionSource,
|
|
8
11
|
isOperationExpr,
|
|
9
12
|
isParamPlaceholder,
|
|
13
|
+
isValueSource,
|
|
14
|
+
toExpression,
|
|
10
15
|
} from '../utils/guards';
|
|
@@ -3,59 +3,71 @@ 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 {
|
|
7
|
-
|
|
6
|
+
import type {
|
|
7
|
+
BinaryOp,
|
|
8
|
+
Expression,
|
|
9
|
+
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
|
+
ParamPlaceholder,
|
|
21
|
+
} from './types';
|
|
8
22
|
import { isParamPlaceholder } from './utils/guards';
|
|
9
23
|
|
|
10
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Type guard to check if a value is an ExpressionSource (has toExpr method).
|
|
26
|
+
*/
|
|
27
|
+
function isExpressionSource(value: unknown): value is ExpressionSource {
|
|
11
28
|
return (
|
|
12
29
|
typeof value === 'object' &&
|
|
13
30
|
value !== null &&
|
|
14
|
-
'
|
|
15
|
-
(value as
|
|
31
|
+
'toExpr' in value &&
|
|
32
|
+
typeof (value as ExpressionSource).toExpr === 'function'
|
|
16
33
|
);
|
|
17
34
|
}
|
|
18
35
|
|
|
19
36
|
/**
|
|
20
|
-
* Executes an operation and returns
|
|
37
|
+
* Executes an operation and returns an ExpressionBuilder.
|
|
21
38
|
* This is the canonical entrypoint for operation invocation, enabling
|
|
22
39
|
* future enhancements like telemetry, caching, or tracing.
|
|
23
40
|
*
|
|
41
|
+
* The returned ExpressionBuilder:
|
|
42
|
+
* - Has `kind: 'expression'` to distinguish it from ColumnBuilder
|
|
43
|
+
* - Contains the operation expression in `expr`
|
|
44
|
+
* - Provides `toExpr()` method to get the Expression
|
|
45
|
+
* - Provides comparison and ordering methods for chaining
|
|
46
|
+
*
|
|
24
47
|
* @param signature - The operation signature from the registry
|
|
25
|
-
* @param selfBuilder - The
|
|
48
|
+
* @param selfBuilder - The expression source that the operation is called on
|
|
26
49
|
* @param args - The arguments passed to the operation
|
|
27
50
|
* @param columnMeta - The metadata of the column the operation is called on
|
|
28
|
-
* @returns
|
|
51
|
+
* @returns An ExpressionBuilder containing the operation expression
|
|
29
52
|
*/
|
|
30
53
|
function executeOperation(
|
|
31
54
|
signature: SqlOperationSignature,
|
|
32
|
-
selfBuilder:
|
|
55
|
+
selfBuilder: ExpressionSource,
|
|
33
56
|
args: unknown[],
|
|
34
57
|
columnMeta: StorageColumn,
|
|
35
58
|
operationRegistry?: OperationRegistry,
|
|
36
59
|
contractCapabilities?: Record<string, Record<string, boolean>>,
|
|
37
|
-
):
|
|
60
|
+
): ExpressionBuilder {
|
|
38
61
|
if (args.length !== signature.args.length) {
|
|
39
62
|
throw planInvalid(
|
|
40
63
|
`Operation ${signature.method} expects ${signature.args.length} arguments, got ${args.length}`,
|
|
41
64
|
);
|
|
42
65
|
}
|
|
43
66
|
|
|
44
|
-
//
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
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> = [];
|
|
67
|
+
// Get the Expression from the self builder using toExpr()
|
|
68
|
+
const selfExpr: Expression = selfBuilder.toExpr();
|
|
69
|
+
|
|
70
|
+
const operationArgs: Array<Expression | ParamRef | LiteralExpr> = [];
|
|
59
71
|
for (let i = 0; i < args.length; i++) {
|
|
60
72
|
const arg = args[i];
|
|
61
73
|
const argSpec = signature.args[i];
|
|
@@ -73,25 +85,14 @@ function executeOperation(
|
|
|
73
85
|
name: arg.name,
|
|
74
86
|
});
|
|
75
87
|
} 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
|
-
});
|
|
88
|
+
// Accept ExpressionSource (ColumnBuilder or ExpressionBuilder)
|
|
89
|
+
if (!isExpressionSource(arg)) {
|
|
90
|
+
throw planInvalid(
|
|
91
|
+
`Argument ${i} must be an ExpressionSource (ColumnBuilder or ExpressionBuilder)`,
|
|
92
|
+
);
|
|
94
93
|
}
|
|
94
|
+
// Use toExpr() to get the Expression
|
|
95
|
+
operationArgs.push(arg.toExpr());
|
|
95
96
|
} else if (argSpec.kind === 'literal') {
|
|
96
97
|
operationArgs.push({
|
|
97
98
|
kind: 'literal',
|
|
@@ -118,18 +119,19 @@ function executeOperation(
|
|
|
118
119
|
}
|
|
119
120
|
: columnMeta;
|
|
120
121
|
|
|
121
|
-
const createComparisonMethod =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
const createComparisonMethod =
|
|
123
|
+
(op: BinaryOp) =>
|
|
124
|
+
(value: ParamPlaceholder | ExpressionSource): AnyBinaryBuilder =>
|
|
125
|
+
Object.freeze({
|
|
126
|
+
kind: 'binary' as const,
|
|
127
|
+
op,
|
|
128
|
+
left: operationExpr,
|
|
129
|
+
right: value,
|
|
130
|
+
}) as AnyBinaryBuilder;
|
|
131
|
+
|
|
132
|
+
const baseResult: ExpressionBuilder = {
|
|
133
|
+
kind: 'expression' as const,
|
|
134
|
+
expr: operationExpr,
|
|
133
135
|
get columnMeta() {
|
|
134
136
|
return returnColumnMeta;
|
|
135
137
|
},
|
|
@@ -139,41 +141,84 @@ function executeOperation(
|
|
|
139
141
|
lt: createComparisonMethod('lt'),
|
|
140
142
|
gte: createComparisonMethod('gte'),
|
|
141
143
|
lte: createComparisonMethod('lte'),
|
|
142
|
-
asc() {
|
|
144
|
+
asc(): AnyOrderBuilder {
|
|
143
145
|
return Object.freeze({
|
|
144
146
|
kind: 'order' as const,
|
|
145
147
|
expr: operationExpr,
|
|
146
148
|
dir: 'asc' as const,
|
|
147
149
|
});
|
|
148
150
|
},
|
|
149
|
-
desc() {
|
|
151
|
+
desc(): AnyOrderBuilder {
|
|
150
152
|
return Object.freeze({
|
|
151
153
|
kind: 'order' as const,
|
|
152
154
|
expr: operationExpr,
|
|
153
155
|
dir: 'desc' as const,
|
|
154
156
|
});
|
|
155
157
|
},
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
toExpr(): OperationExpr {
|
|
159
|
+
return operationExpr;
|
|
160
|
+
},
|
|
161
|
+
get __jsType(): unknown {
|
|
162
|
+
return undefined;
|
|
163
|
+
},
|
|
159
164
|
};
|
|
160
165
|
|
|
161
166
|
// If the return type is a typeId, attach operations for that type
|
|
162
167
|
if (returnTypeId && operationRegistry) {
|
|
163
|
-
const resultWithOps =
|
|
164
|
-
baseResult
|
|
168
|
+
const resultWithOps = attachOperationsToExpressionBuilder(
|
|
169
|
+
baseResult,
|
|
165
170
|
returnColumnMeta,
|
|
166
171
|
operationRegistry,
|
|
167
172
|
contractCapabilities,
|
|
168
|
-
)
|
|
169
|
-
_operationExpr?: OperationExpr;
|
|
170
|
-
};
|
|
173
|
+
);
|
|
171
174
|
return Object.freeze(resultWithOps);
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
return Object.freeze(baseResult);
|
|
175
178
|
}
|
|
176
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Attaches operation methods to an ExpressionBuilder for chained operations.
|
|
182
|
+
* When an operation returns a typeId, the result ExpressionBuilder needs
|
|
183
|
+
* operation methods for that type.
|
|
184
|
+
*/
|
|
185
|
+
function attachOperationsToExpressionBuilder(
|
|
186
|
+
expressionBuilder: ExpressionBuilder,
|
|
187
|
+
columnMeta: StorageColumn,
|
|
188
|
+
registry: OperationRegistry,
|
|
189
|
+
contractCapabilities?: Record<string, Record<string, boolean>>,
|
|
190
|
+
): ExpressionBuilder {
|
|
191
|
+
const codecId = columnMeta.codecId;
|
|
192
|
+
if (!codecId) {
|
|
193
|
+
return expressionBuilder;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const operations = registry.byType(codecId) as SqlOperationSignature[];
|
|
197
|
+
if (operations.length === 0) {
|
|
198
|
+
return expressionBuilder;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const builderWithOps = expressionBuilder as ExpressionBuilder & Record<string, unknown>;
|
|
202
|
+
|
|
203
|
+
for (const operation of operations) {
|
|
204
|
+
if (operation.capabilities && operation.capabilities.length > 0) {
|
|
205
|
+
if (!contractCapabilities) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!hasAllCapabilities(operation.capabilities, contractCapabilities)) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Method sugar: attach operation as a method on the expression builder
|
|
214
|
+
builderWithOps[operation.method] = function (this: ExpressionBuilder, ...args: unknown[]) {
|
|
215
|
+
return executeOperation(operation, this, args, columnMeta, registry, contractCapabilities);
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return builderWithOps;
|
|
220
|
+
}
|
|
221
|
+
|
|
177
222
|
export function attachOperationsToColumnBuilder<
|
|
178
223
|
ColumnName extends string,
|
|
179
224
|
ColumnMeta extends StorageColumn,
|
|
@@ -218,18 +263,12 @@ export function attachOperationsToColumnBuilder<
|
|
|
218
263
|
}
|
|
219
264
|
}
|
|
220
265
|
// Method sugar: attach operation as a method on the column builder
|
|
266
|
+
// Operations return ExpressionBuilder, not ColumnBuilder
|
|
221
267
|
(builderWithOps as Record<string, unknown>)[operation.method] = function (
|
|
222
268
|
this: ColumnBuilder<ColumnName, ColumnMeta, JsType, Record<string, never>>,
|
|
223
269
|
...args: unknown[]
|
|
224
270
|
) {
|
|
225
|
-
return executeOperation(
|
|
226
|
-
operation,
|
|
227
|
-
this as unknown as ColumnBuilder<string, StorageColumn, unknown>,
|
|
228
|
-
args,
|
|
229
|
-
columnMeta,
|
|
230
|
-
registry,
|
|
231
|
-
contractCapabilities,
|
|
232
|
-
);
|
|
271
|
+
return executeOperation(operation, this, args, columnMeta, registry, contractCapabilities);
|
|
233
272
|
};
|
|
234
273
|
}
|
|
235
274
|
|
|
@@ -2,6 +2,13 @@ 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
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Registry of initialized type helpers from storage.types.
|
|
7
|
+
* Each key is a type name from storage.types, and the value is the initialized helper
|
|
8
|
+
* (or validated typeParams if no init hook was provided).
|
|
9
|
+
*/
|
|
10
|
+
export type TypeHelperRegistry = Record<string, unknown>;
|
|
11
|
+
|
|
5
12
|
/**
|
|
6
13
|
* Minimal context interface for SQL query lanes.
|
|
7
14
|
*
|
|
@@ -15,4 +22,9 @@ export interface QueryLaneContext<
|
|
|
15
22
|
readonly contract: TContract;
|
|
16
23
|
readonly operations: OperationRegistry;
|
|
17
24
|
readonly codecs: CodecRegistry;
|
|
25
|
+
/**
|
|
26
|
+
* Optional type helper registry for parameterized types.
|
|
27
|
+
* When present, schema() will expose these helpers via schema.types.
|
|
28
|
+
*/
|
|
29
|
+
readonly types?: TypeHelperRegistry;
|
|
18
30
|
}
|