@prisma-next/sql-relational-core 0.11.0 → 0.12.0

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 (53) hide show
  1. package/dist/codec-types-Cezo7k-i.d.mts.map +1 -1
  2. package/dist/errors-BF7W5uUd.mjs.map +1 -1
  3. package/dist/{errors-Duz3ppqk.d.mts → errors-Bavu5wZA.d.mts} +2 -2
  4. package/dist/errors-Bavu5wZA.d.mts.map +1 -0
  5. package/dist/exports/ast.d.mts +6 -3
  6. package/dist/exports/ast.d.mts.map +1 -1
  7. package/dist/exports/ast.mjs +2 -2
  8. package/dist/exports/ast.mjs.map +1 -1
  9. package/dist/exports/codec-descriptor-registry.d.mts.map +1 -1
  10. package/dist/exports/codec-descriptor-registry.mjs +3 -3
  11. package/dist/exports/codec-descriptor-registry.mjs.map +1 -1
  12. package/dist/exports/errors.d.mts +1 -1
  13. package/dist/exports/expression.d.mts +46 -2
  14. package/dist/exports/expression.d.mts.map +1 -1
  15. package/dist/exports/expression.mjs +55 -2
  16. package/dist/exports/expression.mjs.map +1 -1
  17. package/dist/exports/middleware.d.mts +1 -1
  18. package/dist/exports/plan.d.mts +2 -2
  19. package/dist/exports/plan.mjs.map +1 -1
  20. package/dist/exports/types.d.mts +2 -2
  21. package/dist/index.d.mts +9 -9
  22. package/dist/index.mjs +3 -3
  23. package/dist/middleware-B0yz0pff.mjs.map +1 -1
  24. package/dist/{middleware-DI2DqOSg.d.mts → middleware-EOcO8Ogo.d.mts} +2 -2
  25. package/dist/middleware-EOcO8Ogo.d.mts.map +1 -0
  26. package/dist/{plan-D-Q5B-z_.d.mts → plan-CG3sy5kw.d.mts} +2 -2
  27. package/dist/plan-CG3sy5kw.d.mts.map +1 -0
  28. package/dist/query-lane-context-Dw1Tz0kv.d.mts.map +1 -1
  29. package/dist/{sql-execution-plan-B84vOmgK.d.mts → sql-execution-plan-D4OimCVH.d.mts} +2 -2
  30. package/dist/sql-execution-plan-D4OimCVH.d.mts.map +1 -0
  31. package/dist/{types-CceENhhm.mjs → types-C4EdOD-s.mjs} +76 -2
  32. package/dist/types-C4EdOD-s.mjs.map +1 -0
  33. package/dist/{types-DNGyueh7.d.mts → types-C_1ZqLwZ.d.mts} +62 -3
  34. package/dist/types-C_1ZqLwZ.d.mts.map +1 -0
  35. package/dist/{types-BJHEQbci.d.mts → types-CkTDkFcK.d.mts} +3 -3
  36. package/dist/types-CkTDkFcK.d.mts.map +1 -0
  37. package/dist/{types-DiV49xLs.d.mts → types-DoolOzqd.d.mts} +6 -6
  38. package/dist/types-DoolOzqd.d.mts.map +1 -0
  39. package/dist/util-DWmhUCEO.mjs.map +1 -1
  40. package/package.json +23 -12
  41. package/src/ast/adapter-types.ts +4 -1
  42. package/src/ast/types.ts +129 -1
  43. package/src/codec-ref-for-column.ts +3 -3
  44. package/src/expression.ts +108 -2
  45. package/src/types.ts +12 -14
  46. package/dist/errors-Duz3ppqk.d.mts.map +0 -1
  47. package/dist/middleware-DI2DqOSg.d.mts.map +0 -1
  48. package/dist/plan-D-Q5B-z_.d.mts.map +0 -1
  49. package/dist/sql-execution-plan-B84vOmgK.d.mts.map +0 -1
  50. package/dist/types-BJHEQbci.d.mts.map +0 -1
  51. package/dist/types-CceENhhm.mjs.map +0 -1
  52. package/dist/types-DNGyueh7.d.mts.map +0 -1
  53. package/dist/types-DiV49xLs.d.mts.map +0 -1
@@ -1,5 +1,5 @@
1
- import { t as SqlExecutionPlan } from "./sql-execution-plan-B84vOmgK.mjs";
2
- import { t as SqlQueryPlan } from "./plan-D-Q5B-z_.mjs";
1
+ import { t as SqlExecutionPlan } from "./sql-execution-plan-D4OimCVH.mjs";
2
+ import { t as SqlQueryPlan } from "./plan-CG3sy5kw.mjs";
3
3
  import { RuntimeExecutor } from "@prisma-next/framework-components/runtime";
4
4
 
5
5
  //#region src/runtime-scope.d.ts
@@ -20,4 +20,4 @@ type SqlOrmPlan = SqlExecutionPlan | SqlQueryPlan;
20
20
  type RuntimeScope = Pick<RuntimeExecutor<SqlOrmPlan>, 'execute'>;
21
21
  //#endregion
22
22
  export { SqlOrmPlan as n, RuntimeScope as t };
23
- //# sourceMappingURL=types-BJHEQbci.d.mts.map
23
+ //# sourceMappingURL=types-CkTDkFcK.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CkTDkFcK.d.mts","names":[],"sources":["../src/runtime-scope.ts"],"mappings":";;;;;;;;AASA;;KAAY,UAAA,GAAa,gBAAA,GAAmB,YAAY;;AAAA;AAUxD;;;;;;KAAY,YAAA,GAAe,IAAA,CAAK,eAAA,CAAgB,UAAA"}
@@ -1,8 +1,8 @@
1
- import { J as ParamRef, g as ColumnRef } from "./types-DNGyueh7.mjs";
1
+ import { J as ParamRef, g as ColumnRef } from "./types-C_1ZqLwZ.mjs";
2
2
  import { r as ExecutionContext } from "./query-lane-context-Dw1Tz0kv.mjs";
3
- import { t as SqlExecutionPlan } from "./sql-execution-plan-B84vOmgK.mjs";
3
+ import { t as SqlExecutionPlan } from "./sql-execution-plan-D4OimCVH.mjs";
4
4
  import { ExtractFieldOutputTypes, SqlStorage, StorageColumn } from "@prisma-next/sql-contract/types";
5
- import { Contract } from "@prisma-next/contract/types";
5
+ import { Contract, ContractModelsMap } from "@prisma-next/contract/types";
6
6
  import { ParamSpec } from "@prisma-next/operations";
7
7
  import { SqlLoweringSpec } from "@prisma-next/sql-operations";
8
8
 
@@ -12,7 +12,7 @@ type Expr = ColumnRef | ParamRef;
12
12
  * Extracts the model name for a given table by iterating models to find the one
13
13
  * whose `storage.table` matches.
14
14
  */
15
- type ExtractTableToModel<TContract extends Contract<SqlStorage>, TableName extends string> = TContract['models'] extends infer Models extends Record<string, unknown> ? { [M in keyof Models & string]: Models[M] extends {
15
+ type ExtractTableToModel<TContract extends Contract<SqlStorage>, TableName extends string> = ContractModelsMap<TContract> extends infer Models extends Record<string, unknown> ? { [M in keyof Models & string]: Models[M] extends {
16
16
  readonly storage: {
17
17
  readonly table: TableName;
18
18
  };
@@ -21,7 +21,7 @@ type ExtractTableToModel<TContract extends Contract<SqlStorage>, TableName exten
21
21
  * Extracts the field name for a given column by finding the field in
22
22
  * `model.storage.fields` whose `column` matches.
23
23
  */
24
- type ExtractColumnToField<TContract extends Contract<SqlStorage>, TableName extends string, ColumnName extends string> = ExtractTableToModel<TContract, TableName> extends infer ModelName extends string ? TContract['models'] extends infer Models extends Record<string, unknown> ? ModelName & keyof Models extends infer MKey extends string ? Models[MKey] extends {
24
+ type ExtractColumnToField<TContract extends Contract<SqlStorage>, TableName extends string, ColumnName extends string> = ExtractTableToModel<TContract, TableName> extends infer ModelName extends string ? ContractModelsMap<TContract> extends infer Models extends Record<string, unknown> ? ModelName & keyof Models extends infer MKey extends string ? Models[MKey] extends {
25
25
  readonly storage: {
26
26
  readonly fields: infer Fields extends Record<string, unknown>;
27
27
  };
@@ -190,4 +190,4 @@ interface SqlBuilderOptions<TContract extends Contract<SqlStorage> = Contract<Sq
190
190
  }
191
191
  //#endregion
192
192
  export { TableKey as C, TableDef as S, TablesOf as T, RawTemplateFactory as _, ComputeColumnJsType as a, SqlBuilderOptions as b, META as c, ModelMetadata as d, OperationTypeSignature as f, RawFunctionOptions as g, RawFactory as h, ColumnsOf as i, Meta as l, OperationsForTypeId as m, BuildParamsMap as n, Expr as o, OperationTypes as p, CodecTypes as r, HasIncludeManyCapabilities as s, BuildOptions as t, ModelDef as u, RawTemplateOptions as v, TableMetadata as w, SqlPlan as x, RuntimeError as y };
193
- //# sourceMappingURL=types-DiV49xLs.d.mts.map
193
+ //# sourceMappingURL=types-DoolOzqd.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DoolOzqd.d.mts","names":[],"sources":["../src/types.ts"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"util-DWmhUCEO.mjs","names":[],"sources":["../src/ast/util.ts"],"sourcesContent":["import type { AnyParamRef, AnyQueryAst } from './types';\n\nexport function compact<T extends Record<string, unknown>>(o: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(o)) {\n if (v === undefined || v === null) continue;\n if (Array.isArray(v) && v.length === 0) continue;\n out[k] = v;\n }\n return out as T;\n}\n\n/**\n * Walks an AST's parameter references in first-encounter order and dedupes\n * by ParamRef identity. The single canonical helper used by every consumer\n * that aligns `plan.params` with metadata-by-index — the SQL builder lane,\n * the SQL ORM client, the SQL runtime encoder, and the Postgres renderer's\n * `$N` index map — so the four walks cannot drift in dedupe semantics.\n *\n * SQLite's `?`-placeholder renderer intentionally does NOT use this helper\n * because it needs one params entry per occurrence in the SQL.\n */\nexport function collectOrderedParamRefs(ast: AnyQueryAst): ReadonlyArray<AnyParamRef> {\n const seen = new Set<AnyParamRef>();\n const ordered: AnyParamRef[] = [];\n for (const ref of ast.collectParamRefs()) {\n if (seen.has(ref)) continue;\n seen.add(ref);\n ordered.push(ref);\n }\n return Object.freeze(ordered);\n}\n"],"mappings":";AAEA,SAAgB,QAA2C,GAAS;CAClE,MAAM,MAA+B,EAAE;CACvC,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,EAAE,EAAE;EACtC,IAAI,MAAM,KAAA,KAAa,MAAM,MAAM;EACnC,IAAI,MAAM,QAAQ,EAAE,IAAI,EAAE,WAAW,GAAG;EACxC,IAAI,KAAK;;CAEX,OAAO;;;;;;;;;;;;AAaT,SAAgB,wBAAwB,KAA8C;CACpF,MAAM,uBAAO,IAAI,KAAkB;CACnC,MAAM,UAAyB,EAAE;CACjC,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE;EACxC,IAAI,KAAK,IAAI,IAAI,EAAE;EACnB,KAAK,IAAI,IAAI;EACb,QAAQ,KAAK,IAAI;;CAEnB,OAAO,OAAO,OAAO,QAAQ"}
1
+ {"version":3,"file":"util-DWmhUCEO.mjs","names":[],"sources":["../src/ast/util.ts"],"sourcesContent":["import type { AnyParamRef, AnyQueryAst } from './types';\n\nexport function compact<T extends Record<string, unknown>>(o: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(o)) {\n if (v === undefined || v === null) continue;\n if (Array.isArray(v) && v.length === 0) continue;\n out[k] = v;\n }\n return out as T;\n}\n\n/**\n * Walks an AST's parameter references in first-encounter order and dedupes\n * by ParamRef identity. The single canonical helper used by every consumer\n * that aligns `plan.params` with metadata-by-index — the SQL builder lane,\n * the SQL ORM client, the SQL runtime encoder, and the Postgres renderer's\n * `$N` index map — so the four walks cannot drift in dedupe semantics.\n *\n * SQLite's `?`-placeholder renderer intentionally does NOT use this helper\n * because it needs one params entry per occurrence in the SQL.\n */\nexport function collectOrderedParamRefs(ast: AnyQueryAst): ReadonlyArray<AnyParamRef> {\n const seen = new Set<AnyParamRef>();\n const ordered: AnyParamRef[] = [];\n for (const ref of ast.collectParamRefs()) {\n if (seen.has(ref)) continue;\n seen.add(ref);\n ordered.push(ref);\n }\n return Object.freeze(ordered);\n}\n"],"mappings":";AAEA,SAAgB,QAA2C,GAAS;CAClE,MAAM,MAA+B,CAAC;CACtC,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,CAAC,GAAG;EACtC,IAAI,MAAM,KAAA,KAAa,MAAM,MAAM;EACnC,IAAI,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG;EACxC,IAAI,KAAK;CACX;CACA,OAAO;AACT;;;;;;;;;;;AAYA,SAAgB,wBAAwB,KAA8C;CACpF,MAAM,uBAAO,IAAI,IAAiB;CAClC,MAAM,UAAyB,CAAC;CAChC,KAAK,MAAM,OAAO,IAAI,iBAAiB,GAAG;EACxC,IAAI,KAAK,IAAI,GAAG,GAAG;EACnB,KAAK,IAAI,GAAG;EACZ,QAAQ,KAAK,GAAG;CAClB;CACA,OAAO,OAAO,OAAO,OAAO;AAC9B"}
package/package.json CHANGED
@@ -1,34 +1,43 @@
1
1
  {
2
2
  "name": "@prisma-next/sql-relational-core",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "AST types, query lane context, and type utilities for Prisma Next SQL lanes",
8
8
  "dependencies": {
9
- "@prisma-next/contract": "0.11.0",
10
- "@prisma-next/framework-components": "0.11.0",
11
- "@prisma-next/operations": "0.11.0",
12
- "@prisma-next/sql-contract": "0.11.0",
13
- "@prisma-next/sql-operations": "0.11.0",
14
- "@prisma-next/utils": "0.11.0",
9
+ "@prisma-next/contract": "0.12.0",
10
+ "@prisma-next/framework-components": "0.12.0",
11
+ "@prisma-next/operations": "0.12.0",
12
+ "@prisma-next/sql-contract": "0.12.0",
13
+ "@prisma-next/sql-operations": "0.12.0",
14
+ "@prisma-next/utils": "0.12.0",
15
15
  "@standard-schema/spec": "^1.1.0",
16
16
  "arktype": "^2.2.0",
17
17
  "ts-toolbelt": "^9.6.0"
18
18
  },
19
19
  "devDependencies": {
20
- "@prisma-next/sql-contract-ts": "0.11.0",
21
- "@prisma-next/test-utils": "0.11.0",
22
- "@prisma-next/tsconfig": "0.11.0",
23
- "@prisma-next/tsdown": "0.11.0",
20
+ "@prisma-next/sql-contract-ts": "0.12.0",
21
+ "@prisma-next/test-utils": "0.12.0",
22
+ "@prisma-next/tsconfig": "0.12.0",
23
+ "@prisma-next/tsdown": "0.12.0",
24
24
  "tsdown": "0.22.0",
25
25
  "typescript": "5.9.3",
26
26
  "vitest": "4.1.6"
27
27
  },
28
+ "peerDependencies": {
29
+ "typescript": ">=5.9"
30
+ },
31
+ "peerDependenciesMeta": {
32
+ "typescript": {
33
+ "optional": true
34
+ }
35
+ },
28
36
  "files": [
29
37
  "dist",
30
38
  "src"
31
39
  ],
40
+ "types": "./dist/index.d.mts",
32
41
  "exports": {
33
42
  ".": "./dist/index.mjs",
34
43
  "./ast": "./dist/exports/ast.mjs",
@@ -41,7 +50,9 @@
41
50
  "./types": "./dist/exports/types.mjs",
42
51
  "./package.json": "./package.json"
43
52
  },
44
- "types": "./dist/index.d.mts",
53
+ "engines": {
54
+ "node": ">=24"
55
+ },
45
56
  "repository": {
46
57
  "type": "git",
47
58
  "url": "https://github.com/prisma/prisma-next.git",
@@ -10,7 +10,10 @@ export interface MarkerStatement {
10
10
  }
11
11
 
12
12
  /**
13
- * Outcome of an adapter's marker read. `no-table` means the marker storage itself is absent (e.g. attaching to a database that was never `db init`'d); `absent` means the storage exists but holds no row for the requested space; `present` carries the parsed record. Callers distinguish these so runtime telemetry and `requireMarker` policy can react to each case appropriately.
13
+ * Outcome of an adapter's marker read. `no-table` means the marker storage itself is absent
14
+ * (e.g. attaching to a database that was never `db init`'d); `absent` means the storage exists
15
+ * but holds no row for the requested space; `present` carries the parsed record. Callers
16
+ * distinguish these to produce appropriate log diagnostics for each case.
14
17
  */
15
18
  export type MarkerReadResult =
16
19
  | { readonly kind: 'present'; readonly record: ContractMarkerRecord }
package/src/ast/types.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ParamSpec } from '@prisma-next/operations';
2
2
  import type { SqlLoweringSpec } from '@prisma-next/sql-operations';
3
+ import { ifDefined } from '@prisma-next/utils/defined';
3
4
  import type { CodecRef } from './codec-types';
4
5
 
5
6
  export type Direction = 'asc' | 'desc';
@@ -10,6 +11,18 @@ export type AggregateCountFn = 'count';
10
11
  export type AggregateOpFn = 'sum' | 'avg' | 'min' | 'max';
11
12
  export type AggregateFn = AggregateCountFn | AggregateOpFn;
12
13
 
14
+ /**
15
+ * Window function names. Currently only `row_number` is wired up — added
16
+ * to support `ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) = 1`
17
+ * lowering for `.distinct(cols)` semantics in the SQL ORM client. `rank`
18
+ * and `dense_rank` are reserved here so future additions don't churn the
19
+ * type; renderers only need to dispatch on the function name string.
20
+ */
21
+ export type WindowFn = 'row_number' | 'rank' | 'dense_rank';
22
+
23
+ /** Scalar JS values that map directly to a SQL wire type. Values outside this set must be routed through `param(value, { codecId })` to declare the target codec explicitly. */
24
+ export type RawSqlLiteral = number | bigint | string | boolean | Uint8Array;
25
+
13
26
  export interface ExpressionSource {
14
27
  toExpr(): AnyExpression;
15
28
  }
@@ -22,6 +35,7 @@ export interface ExpressionRewriter {
22
35
  literal?(expr: LiteralExpr): LiteralExpr;
23
36
  list?(expr: ListExpression): ListExpression | LiteralExpr;
24
37
  select?(ast: SelectAst): SelectAst;
38
+ rawExpr?(expr: RawExpr): AnyExpression;
25
39
  }
26
40
 
27
41
  export interface AstRewriter extends ExpressionRewriter {
@@ -35,6 +49,7 @@ export interface ExprVisitor<R> {
35
49
  subquery(expr: SubqueryExpr): R;
36
50
  operation(expr: OperationExpr): R;
37
51
  aggregate(expr: AggregateExpr): R;
52
+ windowFunc(expr: WindowFuncExpr): R;
38
53
  jsonObject(expr: JsonObjectExpr): R;
39
54
  jsonArrayAgg(expr: JsonArrayAggExpr): R;
40
55
  binary(expr: BinaryExpr): R;
@@ -47,6 +62,7 @@ export interface ExprVisitor<R> {
47
62
  param(expr: ParamRef): R;
48
63
  preparedParam(expr: PreparedParamRef): R;
49
64
  list(expr: ListExpression): R;
65
+ rawExpr(expr: RawExpr): R;
50
66
  }
51
67
 
52
68
  export interface ExpressionFolder<T> {
@@ -60,6 +76,7 @@ export interface ExpressionFolder<T> {
60
76
  literal?(expr: LiteralExpr): T;
61
77
  list?(expr: ListExpression): T;
62
78
  select?(ast: SelectAst): T;
79
+ rawExpr?(expr: RawExpr): T;
63
80
  }
64
81
 
65
82
  export type ProjectionExpr = AnyExpression;
@@ -606,6 +623,42 @@ export class OperationExpr extends Expression {
606
623
  }
607
624
  }
608
625
 
626
+ export class RawExpr extends Expression {
627
+ readonly kind = 'raw-expr' as const;
628
+ readonly parts: ReadonlyArray<string | AnyExpression>;
629
+ readonly returns: ParamSpec;
630
+
631
+ constructor(options: {
632
+ readonly parts: ReadonlyArray<string | AnyExpression>;
633
+ readonly returns: ParamSpec;
634
+ }) {
635
+ super();
636
+ this.parts = frozenArrayCopy(options.parts);
637
+ this.returns = options.returns;
638
+ this.freeze();
639
+ }
640
+
641
+ override accept<R>(visitor: ExprVisitor<R>): R {
642
+ return visitor.rawExpr(this);
643
+ }
644
+
645
+ override rewrite(rewriter: ExpressionRewriter): AnyExpression {
646
+ return rewriter.rawExpr ? rewriter.rawExpr(this) : this;
647
+ }
648
+
649
+ override fold<T>(folder: ExpressionFolder<T>): T {
650
+ if (folder.rawExpr) {
651
+ return folder.rawExpr(this);
652
+ }
653
+ return combineAll(
654
+ folder,
655
+ this.parts
656
+ .filter((p): p is AnyExpression => typeof p !== 'string')
657
+ .map((p) => () => p.fold(folder)),
658
+ );
659
+ }
660
+ }
661
+
609
662
  export class AggregateExpr extends Expression {
610
663
  readonly kind = 'aggregate' as const;
611
664
  readonly fn: AggregateFn;
@@ -654,6 +707,79 @@ export class AggregateExpr extends Expression {
654
707
  }
655
708
  }
656
709
 
710
+ /**
711
+ * Window function call: `fn(args) OVER (PARTITION BY ... ORDER BY ...)`.
712
+ *
713
+ * Both `partitionBy` and `orderBy` are optional; an empty `OVER ()`
714
+ * clause is legal SQL but rarely useful. For `ROW_NUMBER`, `RANK`, and
715
+ * `DENSE_RANK` the standard mandates an `ORDER BY` for deterministic
716
+ * results — callers are expected to provide one, but the AST does not
717
+ * enforce it.
718
+ *
719
+ * The `args` slot exists for future window function additions that take
720
+ * arguments (e.g. `COUNT(*) OVER`, `SUM(x) OVER`); `ROW_NUMBER` and the
721
+ * other ranking functions take no arguments.
722
+ */
723
+ export class WindowFuncExpr extends Expression {
724
+ readonly kind = 'window-func' as const;
725
+ readonly fn: WindowFn;
726
+ readonly args: ReadonlyArray<AnyExpression>;
727
+ readonly partitionBy: ReadonlyArray<AnyExpression> | undefined;
728
+ readonly orderBy: ReadonlyArray<OrderByItem> | undefined;
729
+
730
+ constructor(options: {
731
+ readonly fn: WindowFn;
732
+ readonly args?: ReadonlyArray<AnyExpression>;
733
+ readonly partitionBy?: ReadonlyArray<AnyExpression>;
734
+ readonly orderBy?: ReadonlyArray<OrderByItem>;
735
+ }) {
736
+ super();
737
+ this.fn = options.fn;
738
+ this.args = options.args && options.args.length > 0 ? frozenArrayCopy(options.args) : [];
739
+ this.partitionBy =
740
+ options.partitionBy && options.partitionBy.length > 0
741
+ ? frozenArrayCopy(options.partitionBy)
742
+ : undefined;
743
+ this.orderBy =
744
+ options.orderBy && options.orderBy.length > 0 ? frozenArrayCopy(options.orderBy) : undefined;
745
+ this.freeze();
746
+ }
747
+
748
+ static rowNumber(options: {
749
+ readonly partitionBy?: ReadonlyArray<AnyExpression>;
750
+ readonly orderBy?: ReadonlyArray<OrderByItem>;
751
+ }): WindowFuncExpr {
752
+ return new WindowFuncExpr({ fn: 'row_number', ...options });
753
+ }
754
+
755
+ override accept<R>(visitor: ExprVisitor<R>): R {
756
+ return visitor.windowFunc(this);
757
+ }
758
+
759
+ override rewrite(rewriter: ExpressionRewriter): AnyExpression {
760
+ return new WindowFuncExpr({
761
+ fn: this.fn,
762
+ args: this.args.map((arg) => arg.rewrite(rewriter)),
763
+ ...ifDefined(
764
+ 'partitionBy',
765
+ this.partitionBy?.map((expr) => expr.rewrite(rewriter)),
766
+ ),
767
+ ...ifDefined(
768
+ 'orderBy',
769
+ this.orderBy?.map((orderItem) => orderItem.rewrite(rewriter)),
770
+ ),
771
+ });
772
+ }
773
+
774
+ override fold<T>(folder: ExpressionFolder<T>): T {
775
+ return combineAll(folder, [
776
+ ...this.args.map((arg) => () => arg.fold(folder)),
777
+ ...(this.partitionBy ?? []).map((expr) => () => expr.fold(folder)),
778
+ ...(this.orderBy ?? []).map((orderItem) => () => orderItem.expr.fold(folder)),
779
+ ]);
780
+ }
781
+ }
782
+
657
783
  export class JsonObjectExpr extends Expression {
658
784
  readonly kind = 'json-object' as const;
659
785
  readonly entries: ReadonlyArray<JsonObjectEntry>;
@@ -1758,6 +1884,7 @@ export type AnyExpression =
1758
1884
  | SubqueryExpr
1759
1885
  | OperationExpr
1760
1886
  | AggregateExpr
1887
+ | WindowFuncExpr
1761
1888
  | JsonObjectExpr
1762
1889
  | JsonArrayAggExpr
1763
1890
  | ListExpression
@@ -1766,7 +1893,8 @@ export type AnyExpression =
1766
1893
  | OrExpr
1767
1894
  | ExistsExpr
1768
1895
  | NullCheckExpr
1769
- | NotExpr;
1896
+ | NotExpr
1897
+ | RawExpr;
1770
1898
  export type AnyParamRef = ParamRef | PreparedParamRef;
1771
1899
  export type AnyInsertOnConflictAction = DoNothingConflictAction | DoUpdateSetConflictAction;
1772
1900
  export type AnyInsertValue = ColumnRef | ParamRef | PreparedParamRef | DefaultValueExpr;
@@ -38,9 +38,9 @@ export function codecRefForStorageColumn(
38
38
  let instance: unknown = storage.types?.[columnDef.typeRef];
39
39
  if (!instance) {
40
40
  for (const ns of Object.values(storage.namespaces)) {
41
- const nsTypes = (ns as { types?: Record<string, unknown> }).types;
42
- if (nsTypes) {
43
- const nsEntry = nsTypes[columnDef.typeRef];
41
+ const nsEnums = (ns as { enum?: Record<string, unknown> }).enum;
42
+ if (nsEnums) {
43
+ const nsEntry = nsEnums[columnDef.typeRef];
44
44
  if (nsEntry !== undefined) {
45
45
  instance = nsEntry;
46
46
  break;
package/src/expression.ts CHANGED
@@ -3,8 +3,8 @@ import type { ParamSpec } from '@prisma-next/operations';
3
3
  import type { QueryOperationReturn } from '@prisma-next/sql-contract/types';
4
4
  import type { SqlLoweringSpec } from '@prisma-next/sql-operations';
5
5
  import type { CodecRef } from './ast/codec-types';
6
- import type { AnyExpression as AstExpression } from './ast/types';
7
- import { OperationExpr, ParamRef } from './ast/types';
6
+ import type { AnyExpression as AstExpression, RawSqlLiteral } from './ast/types';
7
+ import { OperationExpr, ParamRef, RawExpr } from './ast/types';
8
8
 
9
9
  export type ScopeField = {
10
10
  codecId: string;
@@ -94,6 +94,13 @@ export function toExpr(value: unknown, codec?: CodecRef): AstExpression {
94
94
  return ParamRef.of(value, { codec });
95
95
  }
96
96
 
97
+ /**
98
+ * Construct a `ParamRef` for a value whose codec identity is known at call time. Use this when interpolating a value into a raw SQL expression and the codec cannot be inferred from context — e.g. `param(myDate, { codecId: 'pg/timestamptz@1' })`.
99
+ */
100
+ export function param<T>(value: T, opts: { codecId: string }): ParamRef {
101
+ return ParamRef.of(value, { codec: { codecId: opts.codecId } });
102
+ }
103
+
97
104
  /**
98
105
  * Derive the {@link CodecRef} carried by an expression-like value.
99
106
  *
@@ -152,3 +159,102 @@ export function buildOperation<R extends ScopeField>(spec: BuildOperationSpec<R>
152
159
  buildAst: () => op,
153
160
  };
154
161
  }
162
+
163
+ /**
164
+ * Resolves a codec id for a bare JavaScript value interpolated into a raw-SQL
165
+ * template — e.g. `` rawSql`SELECT ${42}` `` calls `inferCodec(42)` to pick
166
+ * the codec id (`pg/int4`, `sqlite/integer@1`, etc.) that will encode the
167
+ * value as a bound parameter.
168
+ *
169
+ * Targets implement this once per dialect: examine the JS value's runtime
170
+ * shape (number, bigint, string, boolean, `Uint8Array`) and return a codec
171
+ * id known to the target's codec registry. Throw when the value falls
172
+ * outside the supported set — callers should wrap such values with
173
+ * `param(value, { codecId })` to declare the codec explicitly.
174
+ */
175
+ export interface RawCodecInferer {
176
+ inferCodec(value: RawSqlLiteral): string;
177
+ }
178
+
179
+ /** The one-method builder returned by a `RawSqlTag` template call before `.returns()` is called. */
180
+ export interface RawSqlBuilder {
181
+ returns<S extends string>(spec: S): Expression<{ codecId: S; nullable: false }>;
182
+ returns<S extends string, N extends boolean = false>(spec: {
183
+ readonly codecId: S;
184
+ readonly nullable?: N;
185
+ }): Expression<{ codecId: S; nullable: N }>;
186
+ }
187
+
188
+ /** Tagged-template function returned by {@link createRawSql}. */
189
+ export type RawSqlTag = (
190
+ strings: TemplateStringsArray,
191
+ ...values: RawSqlInterpolation[]
192
+ ) => RawSqlBuilder;
193
+
194
+ type RawSqlInterpolation = Expression<ScopeField> | ParamRef | RawSqlLiteral;
195
+
196
+ function resolveInterpolation(
197
+ adapter: RawCodecInferer,
198
+ value: RawSqlInterpolation,
199
+ ): AstExpression | ParamRef {
200
+ if (isExpressionLike(value)) {
201
+ return value.buildAst();
202
+ }
203
+ if (value instanceof ParamRef) {
204
+ return value;
205
+ }
206
+ if (
207
+ typeof value === 'number' ||
208
+ typeof value === 'bigint' ||
209
+ typeof value === 'string' ||
210
+ typeof value === 'boolean' ||
211
+ value instanceof Uint8Array
212
+ ) {
213
+ return ParamRef.of(value, { codec: { codecId: adapter.inferCodec(value) } });
214
+ }
215
+
216
+ value satisfies never;
217
+ throw runtimeError(
218
+ 'RUNTIME.RAW_SQL_UNSUPPORTED_INTERPOLATION',
219
+ 'unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec',
220
+ );
221
+ }
222
+
223
+ /**
224
+ * Create a tagged-template builder for raw SQL expressions. The returned tag accepts SQL string fragments interleaved with typed {@link Expression}, {@link ParamRef}, or bare {@link RawSqlLiteral} interpolations. Call `.returns(spec)` on the result to obtain a typed {@link Expression} whose AST is a {@link RawExpr}.
225
+ *
226
+ * Bare {@link RawSqlLiteral} interpolations are wrapped as `ParamRef` nodes with the codec resolved via `adapter.inferCodec(value)`. Use {@link param} when the codec cannot be inferred from the value alone (e.g. `Date`).
227
+ */
228
+ export function createRawSql(adapter: RawCodecInferer): RawSqlTag {
229
+ return (strings, ...values) => {
230
+ const parts: (string | AstExpression | ParamRef)[] = [];
231
+ parts.push(strings[0] ?? '');
232
+ values.forEach((value, i) => {
233
+ parts.push(resolveInterpolation(adapter, value));
234
+ parts.push(strings[i + 1] ?? '');
235
+ });
236
+ return new RawSqlBuilderImpl(parts);
237
+ };
238
+ }
239
+
240
+ class RawSqlBuilderImpl implements RawSqlBuilder {
241
+ constructor(private readonly parts: readonly (string | AstExpression | ParamRef)[]) {}
242
+
243
+ returns<S extends string>(spec: S): Expression<{ codecId: S; nullable: false }>;
244
+ returns<S extends string, N extends boolean = false>(spec: {
245
+ readonly codecId: S;
246
+ readonly nullable?: N;
247
+ }): Expression<{ codecId: S; nullable: N }>;
248
+ returns(
249
+ spec: string | { readonly codecId: string; readonly nullable?: boolean },
250
+ ): Expression<{ codecId: string; nullable: boolean }> {
251
+ const codecId = typeof spec === 'string' ? spec : spec.codecId;
252
+ const nullable = typeof spec === 'string' ? false : (spec.nullable ?? false);
253
+ const paramSpec: ParamSpec = { codecId, nullable };
254
+ const node = new RawExpr({ parts: this.parts, returns: paramSpec });
255
+ return {
256
+ returnType: { codecId, nullable },
257
+ buildAst: () => node,
258
+ };
259
+ }
260
+ }
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Contract } from '@prisma-next/contract/types';
1
+ import type { Contract, ContractModelsMap } from '@prisma-next/contract/types';
2
2
  import type { ParamSpec } from '@prisma-next/operations';
3
3
  import type {
4
4
  ExtractFieldOutputTypes,
@@ -16,18 +16,16 @@ export type Expr = ColumnRef | ParamRef;
16
16
  * Extracts the model name for a given table by iterating models to find the one
17
17
  * whose `storage.table` matches.
18
18
  */
19
- type ExtractTableToModel<
20
- TContract extends Contract<SqlStorage>,
21
- TableName extends string,
22
- > = TContract['models'] extends infer Models extends Record<string, unknown>
23
- ? {
24
- [M in keyof Models & string]: Models[M] extends {
25
- readonly storage: { readonly table: TableName };
26
- }
27
- ? M
28
- : never;
29
- }[keyof Models & string]
30
- : never;
19
+ type ExtractTableToModel<TContract extends Contract<SqlStorage>, TableName extends string> =
20
+ ContractModelsMap<TContract> extends infer Models extends Record<string, unknown>
21
+ ? {
22
+ [M in keyof Models & string]: Models[M] extends {
23
+ readonly storage: { readonly table: TableName };
24
+ }
25
+ ? M
26
+ : never;
27
+ }[keyof Models & string]
28
+ : never;
31
29
 
32
30
  /**
33
31
  * Extracts the field name for a given column by finding the field in
@@ -39,7 +37,7 @@ type ExtractColumnToField<
39
37
  ColumnName extends string,
40
38
  > =
41
39
  ExtractTableToModel<TContract, TableName> extends infer ModelName extends string
42
- ? TContract['models'] extends infer Models extends Record<string, unknown>
40
+ ? ContractModelsMap<TContract> extends infer Models extends Record<string, unknown>
43
41
  ? ModelName & keyof Models extends infer MKey extends string
44
42
  ? Models[MKey] extends {
45
43
  readonly storage: { readonly fields: infer Fields extends Record<string, unknown> };
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors-Duz3ppqk.d.mts","names":[],"sources":["../src/errors.ts"],"mappings":";;;iBAEgB,WAAA,CACd,OAAA,UACA,OAAA,GAAU,MAAA,mBACV,KAAA,sBACA,IAAA,uBACC,YAAA;AAAA,iBAkBa,eAAA,CACd,OAAA,UACA,OAAA,GAAU,MAAA,mBACV,KAAA,sBACA,IAAA,uBACC,YAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware-DI2DqOSg.d.mts","names":[],"sources":["../src/middleware/param-ref-mutator.ts"],"mappings":";;;;;;AAG8D;;;;;AAuB9D;;;cAXc,mBAAA;;;;;;AAoBd;;;;UATiB,cAAA;EAAA,UACL,mBAAA,GAAsB,QAAA;AAAA;;;;;;UAQjB,aAAA;EAAA,SACN,GAAA,EAAK,cAAA,CAAe,QAAA;EAAA,SACpB,KAAA;EAAA,SACA,OAAA,EAAS,QAAA;AAAA;AAWpB;;;;;;;;AAAA,KAAY,kBAAA,mBAAqC,MAAA,mCAC/B,SAAA,YAAqB,aAAA,CAAc,CAAA,UAAW,SAAA,aAC5D,aAAA;;;;;;;;;;;AA0BJ;;;;;;;;;;;;;;UAAiB,kBAAA,mBACG,MAAA,oBAA0B,MAAA,2BACpC,eAAA;EAmBU;EAjBlB,OAAA,IAAW,gBAAA,CAAiB,kBAAA,CAAmB,SAAA;EAFvC;;;;;;EAUR,YAAA,wBAAoC,SAAA,WAClC,GAAA,EAAK,cAAA,CAAe,QAAA,GACpB,QAAA,EAAU,SAAA,CAAU,QAAA;EAEtB,YAAA,CAAa,GAAA,EAAK,cAAA,aAA2B,QAAA;EAZlC;EAeX,aAAA,CACE,OAAA,EAAS,QAAA;IAAA,SACE,GAAA,EAAK,cAAA,QAAsB,SAAA;IAAA,SAC3B,QAAA;EAAA;AAAA;;;;;;;;;;;UAeE,0BAAA,mBACG,MAAA,oBAA0B,MAAA,2BACpC,kBAAA,CAAmB,SAAA;EAC3B,aAAA;AAAA;;;;;;;AAHF;;;;;;;;;iBAuBgB,wBAAA,mBACI,MAAA,oBAA0B,MAAA,kBAAA,CAC5C,IAAA,EAAM,gBAAA,GAAmB,0BAAA,CAA2B,SAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"plan-D-Q5B-z_.d.mts","names":[],"sources":["../src/plan.ts"],"mappings":";;;;;;;;AAkBA;;;;;;;;;;;UAAiB,YAAA,wBAAoC,SAAA,CAAU,GAAA;EAAA,SACpD,GAAA,EAAK,WAAA;EAAA,SACL,MAAA;AAAA;;AAoBX;;;;;;;;;;;;;;;;iBAAgB,WAAA,eAAA,CACd,GAAA,EAAK,WAAA,EACL,QAAA,EAAU,QAAA,CAAS,UAAA,GACnB,MAAA,YACC,YAAA,CAAa,GAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sql-execution-plan-B84vOmgK.d.mts","names":[],"sources":["../src/sql-execution-plan.ts"],"mappings":";;;;;;AAuBA;;;;;;;;;;;;;;;;;;UAAiB,gBAAA,wBAAwC,aAAA,CAAc,GAAA;EAAA,SAC5D,GAAA;EAAA,SACA,MAAA;EAAA,SACA,GAAA,EAAK,WAAA;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-BJHEQbci.d.mts","names":[],"sources":["../src/runtime-scope.ts"],"mappings":";;;;;;;;AASA;;KAAY,UAAA,GAAa,gBAAA,GAAmB,YAAA;;;AAU5C;;;;;;KAAY,YAAA,GAAe,IAAA,CAAK,eAAA,CAAgB,UAAA"}