@prisma/orm-family-sql 0.17.0-dev.1 → 0.17.0-dev.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.
Files changed (147) hide show
  1. package/dist/aggregate-descriptor-registry-DPV4z8MS.mjs +111 -0
  2. package/dist/aggregate-descriptor-registry-DPV4z8MS.mjs.map +1 -0
  3. package/dist/{ast-DSuzmsWn.d.mts → ast--BZUAzN1.d.mts} +3 -4
  4. package/dist/ast--BZUAzN1.d.mts.map +1 -0
  5. package/dist/{ast-BstHjAoG.mjs → ast-DDAyIKdt.mjs} +2 -2
  6. package/dist/ast-DDAyIKdt.mjs.map +1 -0
  7. package/dist/builder.d.mts +2 -2
  8. package/dist/builder__runtime.d.mts +14 -10
  9. package/dist/builder__runtime.d.mts.map +1 -1
  10. package/dist/builder__runtime.mjs +161 -107
  11. package/dist/builder__runtime.mjs.map +1 -1
  12. package/dist/builder__types.d.mts +2 -2
  13. package/dist/codec-types-B_xmJL2m-CC_Q-_u9.mjs +24 -0
  14. package/dist/codec-types-B_xmJL2m-CC_Q-_u9.mjs.map +1 -0
  15. package/dist/{config-types-47qB33rW.d.mts → config-types-DKKhWdzf.d.mts} +2 -2
  16. package/dist/{config-types-47qB33rW.d.mts.map → config-types-DKKhWdzf.d.mts.map} +1 -1
  17. package/dist/{contract-builder-MvJJrQ-5.d.mts → contract-builder-Cj-lKWgM.d.mts} +4 -4
  18. package/dist/{contract-builder-MvJJrQ-5.d.mts.map → contract-builder-Cj-lKWgM.d.mts.map} +1 -1
  19. package/dist/contract-emitter.mjs +1 -1
  20. package/dist/contract-psl.d.mts +2 -2
  21. package/dist/contract-psl__provider.d.mts +1 -1
  22. package/dist/contract-ts.d.mts +2 -2
  23. package/dist/contract-ts__config-types.d.mts +1 -1
  24. package/dist/contract-ts__contract-builder.d.mts +1 -1
  25. package/dist/contract.d.mts +6 -6
  26. package/dist/contract__factories.d.mts +1 -1
  27. package/dist/contract__index-type-validation.d.mts +1 -1
  28. package/dist/contract__types.d.mts +3 -3
  29. package/dist/contract__validators.d.mts +1 -1
  30. package/dist/{control-BHmsZudH.d.mts → control-BqrVERXN.d.mts} +10 -10
  31. package/dist/{control-BHmsZudH.d.mts.map → control-BqrVERXN.d.mts.map} +1 -1
  32. package/dist/{control-adapter-C99J7aEF-C-17lFY8.d.mts → control-adapter-C99J7aEF-mjOpiO_9.d.mts} +6 -6
  33. package/dist/{control-adapter-C99J7aEF-C-17lFY8.d.mts.map → control-adapter-C99J7aEF-mjOpiO_9.d.mts.map} +1 -1
  34. package/dist/control-adapter-xEtAQKd9.d.mts +1 -0
  35. package/dist/{control-B7iS4jv4.mjs → control-mG3RlNzm.mjs} +2 -2
  36. package/dist/{control-B7iS4jv4.mjs.map → control-mG3RlNzm.mjs.map} +1 -1
  37. package/dist/{db-DhMsmBS--DKENDi3l.d.mts → db-B5PMfDDd-BiWfkubp.d.mts} +65 -32
  38. package/dist/db-B5PMfDDd-BiWfkubp.d.mts.map +1 -0
  39. package/dist/{ddl-types-rrMsf77U-DGctYf-T.d.mts → ddl-types-h_3_pXmq-QBLq6WbP.d.mts} +4 -5
  40. package/dist/ddl-types-h_3_pXmq-QBLq6WbP.d.mts.map +1 -0
  41. package/dist/{diff-DhlzHOMD.d.mts → diff-CIIMSaVD.d.mts} +5 -5
  42. package/dist/{diff-DhlzHOMD.d.mts.map → diff-CIIMSaVD.d.mts.map} +1 -1
  43. package/dist/{dist-DrScXbhq.mjs → dist-CYkK9Vbk.mjs} +55 -2
  44. package/dist/dist-CYkK9Vbk.mjs.map +1 -0
  45. package/dist/{expression-RUO52bJB.mjs → expression-Dhu3dLiu.mjs} +2 -2
  46. package/dist/{expression-RUO52bJB.mjs.map → expression-Dhu3dLiu.mjs.map} +1 -1
  47. package/dist/{expression-DIf8F4Mc.d.mts → expression-KPBpeH4T.d.mts} +5 -6
  48. package/dist/expression-KPBpeH4T.d.mts.map +1 -0
  49. package/dist/{factories-B7tA4y9D.d.mts → factories-MfcqTt5R.d.mts} +2 -2
  50. package/dist/{factories-B7tA4y9D.d.mts.map → factories-MfcqTt5R.d.mts.map} +1 -1
  51. package/dist/family.d.mts +9 -9
  52. package/dist/family.mjs +1 -1
  53. package/dist/family__control-adapter.d.mts +2 -2
  54. package/dist/family__control.d.mts +3 -3
  55. package/dist/family__control.mjs +1 -1
  56. package/dist/family__diff.d.mts +2 -2
  57. package/dist/family__ir.d.mts +1 -1
  58. package/dist/family__migration.d.mts +1 -1
  59. package/dist/family__runtime.d.mts +1 -1
  60. package/dist/{index-BgaTJRxj.d.mts → index-BZF7Wehu.d.mts} +3 -3
  61. package/dist/{index-BgaTJRxj.d.mts.map → index-BZF7Wehu.d.mts.map} +1 -1
  62. package/dist/{index-Bb9U36N4.d.mts → index-D_QTT11u.d.mts} +15 -16
  63. package/dist/index-D_QTT11u.d.mts.map +1 -0
  64. package/dist/{index-type-validation-DN0L2mqm.d.mts → index-type-validation-D_vuj-76.d.mts} +2 -2
  65. package/dist/{index-type-validation-DN0L2mqm.d.mts.map → index-type-validation-D_vuj-76.d.mts.map} +1 -1
  66. package/dist/{ir-B3bKMnGQ.d.mts → ir-Cvj3eU-K.d.mts} +2 -2
  67. package/dist/{ir-B3bKMnGQ.d.mts.map → ir-Cvj3eU-K.d.mts.map} +1 -1
  68. package/dist/lane-query-builder.d.mts +3 -3
  69. package/dist/middleware-ChwIEKBC.d.mts +1 -0
  70. package/dist/{middleware-B4XbF4d4-tfwBl6mX.d.mts → middleware-eb7YwdD4-D0M6ACQ-.d.mts} +3 -3
  71. package/dist/{middleware-B4XbF4d4-tfwBl6mX.d.mts.map → middleware-eb7YwdD4-D0M6ACQ-.d.mts.map} +1 -1
  72. package/dist/{migration-CW0ZJLxP.d.mts → migration-Dtyw2JeL.d.mts} +3 -3
  73. package/dist/{migration-CW0ZJLxP.d.mts.map → migration-Dtyw2JeL.d.mts.map} +1 -1
  74. package/dist/operations.d.mts +1 -1
  75. package/dist/orm-client.d.mts +82 -39
  76. package/dist/orm-client.d.mts.map +1 -1
  77. package/dist/orm-client.mjs +157 -122
  78. package/dist/orm-client.mjs.map +1 -1
  79. package/dist/{plan-BTD8xFfa-Dd_K-A1R.d.mts → plan-Bmp5R9sq-DKMRkx6Z.d.mts} +4 -4
  80. package/dist/plan-Bmp5R9sq-DKMRkx6Z.d.mts.map +1 -0
  81. package/dist/plan-mKgmSe0R.d.mts +2 -0
  82. package/dist/query-lane-context-Dcj4eXUl.d.mts +1 -0
  83. package/dist/{query-lane-context-DtdVMqoz-C2Tj5QHA.d.mts → query-lane-context-DjyAyYht-HDNYE_oF.d.mts} +62 -6
  84. package/dist/query-lane-context-DjyAyYht-HDNYE_oF.d.mts.map +1 -0
  85. package/dist/relational-core.d.mts +12 -13
  86. package/dist/relational-core.mjs +4 -3
  87. package/dist/relational-core__aggregate-descriptor-registry.d.mts +12 -0
  88. package/dist/relational-core__aggregate-descriptor-registry.d.mts.map +1 -0
  89. package/dist/relational-core__aggregate-descriptor-registry.mjs +2 -0
  90. package/dist/relational-core__ast.d.mts +3 -4
  91. package/dist/relational-core__ast.mjs +3 -2
  92. package/dist/relational-core__codec-descriptor-registry.d.mts +3 -3
  93. package/dist/relational-core__contract-free.d.mts +3 -4
  94. package/dist/relational-core__contract-free.d.mts.map +1 -1
  95. package/dist/relational-core__contract-free.mjs +1 -1
  96. package/dist/relational-core__contract-free.mjs.map +1 -1
  97. package/dist/relational-core__expression.d.mts +1 -1
  98. package/dist/relational-core__expression.mjs +1 -1
  99. package/dist/relational-core__middleware.d.mts +2 -2
  100. package/dist/relational-core__plan.d.mts +3 -3
  101. package/dist/relational-core__query-lane-context.d.mts +3 -3
  102. package/dist/relational-core__types.d.mts +2 -2
  103. package/dist/{runtime-DNewRuec.d.mts → runtime-DXPO2ytG.d.mts} +2 -2
  104. package/dist/{runtime-DNewRuec.d.mts.map → runtime-DXPO2ytG.d.mts.map} +1 -1
  105. package/dist/runtime.d.mts +3 -3
  106. package/dist/runtime.mjs +12 -3
  107. package/dist/runtime.mjs.map +1 -1
  108. package/dist/{schema-differ-DpG_gnur-g5_iks8G.d.mts → schema-differ-DpG_gnur-zSwkxqxK.d.mts} +2 -2
  109. package/dist/{schema-differ-DpG_gnur-g5_iks8G.d.mts.map → schema-differ-DpG_gnur-zSwkxqxK.d.mts.map} +1 -1
  110. package/dist/{sql-execution-plan-CJmsCP7n-DoEpNn7r.d.mts → sql-execution-plan-Da_d82pz-IHBEmGSa.d.mts} +3 -3
  111. package/dist/sql-execution-plan-Da_d82pz-IHBEmGSa.d.mts.map +1 -0
  112. package/dist/{types-DIBA80mc-wf5wLmON.d.mts → types-BwePDa3m-BVrPIi8V.d.mts} +117 -5
  113. package/dist/types-BwePDa3m-BVrPIi8V.d.mts.map +1 -0
  114. package/dist/types-Cty2fvYD.d.mts +1 -0
  115. package/dist/{types-BgkZru_1-H7yfikSQ.mjs → types-D43EhRac-DOJmnq_t.mjs} +4 -21
  116. package/dist/types-D43EhRac-DOJmnq_t.mjs.map +1 -0
  117. package/dist/{types-CuDrWc5v-ISVXBmBs.d.mts → types-D_plAPEe-DqK5It_K.d.mts} +30 -4
  118. package/dist/types-D_plAPEe-DqK5It_K.d.mts.map +1 -0
  119. package/dist/{types-IqZMLrFC-DtdJNICr.d.mts → types-IqZMLrFC-C1Zu2oo9.d.mts} +5 -5
  120. package/dist/{types-IqZMLrFC-DtdJNICr.d.mts.map → types-IqZMLrFC-C1Zu2oo9.d.mts.map} +1 -1
  121. package/dist/{types-Dl20lxky-DC_jdA0T.d.mts → types-dD8JJfeD-BOvMw2Iu.d.mts} +9 -9
  122. package/dist/{types-Dl20lxky-DC_jdA0T.d.mts.map → types-dD8JJfeD-BOvMw2Iu.d.mts.map} +1 -1
  123. package/dist/{types-BchwQpmO.d.mts → types-wy2-Y8wQ.d.mts} +2 -2
  124. package/dist/{types-BchwQpmO.d.mts.map → types-wy2-Y8wQ.d.mts.map} +1 -1
  125. package/dist/{validators-CxeHhHrf.d.mts → validators-Ds_fvIs_.d.mts} +2 -2
  126. package/dist/{validators-CxeHhHrf.d.mts.map → validators-Ds_fvIs_.d.mts.map} +1 -1
  127. package/package.json +19 -18
  128. package/dist/ast-BstHjAoG.mjs.map +0 -1
  129. package/dist/ast-DSuzmsWn.d.mts.map +0 -1
  130. package/dist/codec-types-MOaceoPi-C5eL2sao.d.mts +0 -116
  131. package/dist/codec-types-MOaceoPi-C5eL2sao.d.mts.map +0 -1
  132. package/dist/control-adapter-4y1O8Ps3.d.mts +0 -1
  133. package/dist/db-DhMsmBS--DKENDi3l.d.mts.map +0 -1
  134. package/dist/ddl-types-rrMsf77U-DGctYf-T.d.mts.map +0 -1
  135. package/dist/dist-DrScXbhq.mjs.map +0 -1
  136. package/dist/expression-DIf8F4Mc.d.mts.map +0 -1
  137. package/dist/index-Bb9U36N4.d.mts.map +0 -1
  138. package/dist/middleware-ByRsXxxq.d.mts +0 -1
  139. package/dist/plan-BTD8xFfa-Dd_K-A1R.d.mts.map +0 -1
  140. package/dist/plan-Cm4jaoNM.d.mts +0 -2
  141. package/dist/query-lane-context-Bz8XJZ45.d.mts +0 -1
  142. package/dist/query-lane-context-DtdVMqoz-C2Tj5QHA.d.mts.map +0 -1
  143. package/dist/sql-execution-plan-CJmsCP7n-DoEpNn7r.d.mts.map +0 -1
  144. package/dist/types-BgkZru_1-H7yfikSQ.mjs.map +0 -1
  145. package/dist/types-CuDrWc5v-ISVXBmBs.d.mts.map +0 -1
  146. package/dist/types-DIBA80mc-wf5wLmON.d.mts.map +0 -1
  147. package/dist/types-DMxc5KZa.d.mts +0 -1
@@ -1,6 +1,6 @@
1
- import { C as LiteralExpr, D as OrExpr, F as SubqueryExpr, I as TableSource, L as UpdateAst, O as OrderByItem, P as SelectAst, S as ListExpression, T as NullCheckExpr, _ as InsertAst, c as DeleteAst, g as IdentifierRef, j as ProjectionItem, k as ParamRef, l as DerivedTableSource, n as AndExpr, o as ColumnRef, p as ExistsExpr, r as BinaryExpr, t as AggregateExpr, y as JoinAst } from "./types-BgkZru_1-H7yfikSQ.mjs";
1
+ import { C as LiteralExpr, D as OrExpr, F as SubqueryExpr, I as TableSource, L as UpdateAst, O as OrderByItem, P as SelectAst, S as ListExpression, T as NullCheckExpr, _ as InsertAst, c as DeleteAst, g as IdentifierRef, j as ProjectionItem, k as ParamRef, l as DerivedTableSource, n as AndExpr, o as ColumnRef, p as ExistsExpr, r as BinaryExpr, t as AggregateExpr, y as JoinAst } from "./types-D43EhRac-DOJmnq_t.mjs";
2
2
  import { t as collectOrderedParamRefs } from "./util-DQQgv2j1-D6INZaRG.mjs";
3
- import { a as toExpr, n as codecOf, r as createRawSql } from "./expression-RUO52bJB.mjs";
3
+ import { a as toExpr, n as codecOf, r as createRawSql } from "./expression-Dhu3dLiu.mjs";
4
4
  import { n as codecRefForStorageColumn } from "./codec-descriptor-registry-BJVJRftS.mjs";
5
5
  import { assertAnnotationsApplicable } from "@prisma/orm-framework/components/runtime";
6
6
  //#region ../../../2-sql/4-lanes/sql-builder/dist/runtime/index.mjs
@@ -8,20 +8,33 @@ import { assertAnnotationsApplicable } from "@prisma/orm-framework/components/ru
8
8
  * Runtime wrapper around a relational-core AST expression node. Carries ScopeField metadata (codecId, nullable) so aggregate-like combinators can propagate the input codec onto their result.
9
9
  *
10
10
  * `codec` records the column-bound {@link CodecRef} when the field-proxy knows the binding — both the namespaced form (`f.user.email` → `ColumnRef`) and the top-level shortcut (`f.email` → `IdentifierRef`) stamp the ref derived from contract storage. `codecOf(expression)` exposes it for operation implementations forwarding the ref to `toExpr`.
11
+ *
12
+ * `projectionAst` carries the descriptor-lowered rendering of the expression, where a target declares one (e.g. SQLite's `CAST(count(*) AS TEXT)`). Lowering exists to carry the value across the driver boundary, so only the projection site consumes it — predicate and ordering positions (`buildAst()`) keep the plain form, where the rendering would change SQL semantics.
11
13
  */
12
14
  var ExpressionImpl = class {
13
15
  ast;
16
+ projectionAst;
14
17
  returnType;
15
18
  codec;
16
- constructor(ast, returnType, codec) {
19
+ constructor(ast, returnType, codec, projectionAst) {
17
20
  this.ast = ast;
18
21
  this.returnType = returnType;
19
22
  this.codec = codec;
23
+ this.projectionAst = projectionAst;
20
24
  }
21
25
  buildAst() {
22
26
  return this.ast;
23
27
  }
28
+ buildProjectionAst() {
29
+ return this.projectionAst ?? this.ast;
30
+ }
24
31
  };
32
+ /**
33
+ * The AST to project for an expression: the descriptor-lowered form when the expression carries one, the plain form otherwise. `resolveSelectArgs` calls this where a lane expression becomes a `ProjectionItem` — the one place the value crosses the driver boundary.
34
+ */
35
+ function projectionAstOf(expr) {
36
+ return expr instanceof ExpressionImpl ? expr.buildProjectionAst() : expr.buildAst();
37
+ }
25
38
  function createFieldProxy(scope) {
26
39
  return new Proxy({}, { get(_target, prop) {
27
40
  if (Object.hasOwn(scope.topLevel, prop)) {
@@ -42,6 +55,85 @@ function createNamespaceProxy(namespaceName, fields) {
42
55
  }
43
56
  } });
44
57
  }
58
+ /**
59
+ * **Last-resort escape hatch for unsafe type assertions. Not a sanctioned tool to reach for.**
60
+ *
61
+ * Before reaching for `blindCast`, **rewrite the surrounding code so the cast becomes
62
+ * unnecessary**: tighten an input type, add a runtime check that narrows via a type
63
+ * predicate, restructure a generic so the compiler can see the relationship you're
64
+ * asserting, or use {@link castAs} when the value already satisfies the target type.
65
+ * Only when no rewrite is feasible does `blindCast` become the right answer — and at
66
+ * that point, the `Reason` literal you supply must articulate the compromise in
67
+ * language a reviewer can evaluate.
68
+ *
69
+ * The reviewer **will** validate the `Reason`. If it doesn't hold up under scrutiny,
70
+ * that is not a signal to soften the reason; it is a signal to go back and solve the
71
+ * underlying type-system problem properly. An unconvincing justification is rework,
72
+ * not a free pass.
73
+ *
74
+ * `blindCast` is the auditable form of `as Foo` / `as unknown as Foo`: it bypasses
75
+ * the compiler's checks (the input type is `unknown`, the output type is whatever the
76
+ * caller asks for), but it forces the unsafety to be named at the call site instead of
77
+ * smuggled in via a bare `as`. The `Reason` type parameter exists only at compile
78
+ * time — it is not present in the emitted JavaScript — but it is grep-able and
79
+ * visible to future readers.
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const stringValue = blindCast<
84
+ * string,
85
+ * "JSON.parse returns `unknown`; this field is documented to be a string in the API contract"
86
+ * >(parsed[key]);
87
+ * ```
88
+ *
89
+ * @typeParam TargetType - The type the caller is asserting the input has.
90
+ * @typeParam _Reason - A string literal describing why bypassing the type system is necessary here.
91
+ * Only meaningful at compile time. The reviewer evaluates whether it justifies the unsafety.
92
+ */
93
+ function blindCast(input) {
94
+ return input;
95
+ }
96
+ /**
97
+ * Returns an object with the key/value if value is defined, otherwise an empty object.
98
+ *
99
+ * Use with spread to conditionally include optional properties while satisfying
100
+ * exactOptionalPropertyTypes. This is explicit about which properties are optional
101
+ * and won't inadvertently strip other undefined values.
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * // Instead of:
106
+ * const obj = {
107
+ * required: 'value',
108
+ * ...(optional ? { optional } : {}),
109
+ * };
110
+ *
111
+ * // Use:
112
+ * const obj = {
113
+ * required: 'value',
114
+ * ...ifDefined('optional', optional),
115
+ * };
116
+ * ```
117
+ */
118
+ function ifDefined(key, value) {
119
+ return value !== void 0 ? blindCast({ [key]: value }) : {};
120
+ }
121
+ function structuredError(code, message, options) {
122
+ const error = options?.cause !== void 0 ? new Error(message, { cause: options.cause }) : new Error(message);
123
+ Object.defineProperty(error, "name", {
124
+ value: "StructuredError",
125
+ configurable: true
126
+ });
127
+ return Object.assign(error, {
128
+ code,
129
+ ...ifDefined("why", options?.why),
130
+ ...ifDefined("fix", options?.fix),
131
+ ...ifDefined("where", options?.where),
132
+ ...ifDefined("severity", options?.severity),
133
+ ...ifDefined("meta", options?.meta),
134
+ ...ifDefined("docsUrl", options?.docsUrl)
135
+ });
136
+ }
45
137
  const BOOL_FIELD = {
46
138
  codecId: "pg/bool@1",
47
139
  nullable: false
@@ -98,11 +190,50 @@ function inOrNotIn(expr, valuesOrSubquery, op) {
98
190
  }
99
191
  return boolExpr(binaryFn(left, SubqueryExpr.of(valuesOrSubquery.buildAst())));
100
192
  }
101
- function numericAgg(fn, expr) {
102
- return new ExpressionImpl(AggregateExpr[fn](expr.buildAst()), {
103
- codecId: expr.returnType.codecId,
104
- nullable: true
193
+ /**
194
+ * Build an aggregate through the target's own answer for it.
195
+ *
196
+ * What an aggregate returns is neither the input's codec nor a fixed id: a
197
+ * target widens `sum` over small integers, takes `avg` somewhere else again,
198
+ * and may want the result rendered a particular way. All three come from the
199
+ * registry, and the result carries the codec it declared so decoding resolves
200
+ * through the ordinary path.
201
+ *
202
+ * The declared rendering (`lower`) exists to carry the value across the driver
203
+ * boundary — a projection concern. It is carried beside the plain form so only
204
+ * the projection site consumes it; HAVING and ORDER BY compare the value inside
205
+ * the database, where the rendering would change SQL semantics (SQLite's
206
+ * `CAST(count(*) AS TEXT)` compares and sorts lexicographically).
207
+ *
208
+ * A pair the target declares no overload for is rejected outright. The typed
209
+ * surface already makes it inexpressible; this backs that up for dynamic
210
+ * invocation, instead of executing SQL whose result no declaration types or
211
+ * decodes — SQLite's `sum` over text, which reads whatever leading numbers the
212
+ * rows happened to hold, is the shape of value that path would hand back.
213
+ */
214
+ function aggregate(aggregates, fn, expr) {
215
+ const field = expr?.returnType;
216
+ const inputCodec = field === void 0 ? void 0 : field.codec ?? { codecId: field.codecId };
217
+ const resolved = aggregates.resolve(fn, inputCodec);
218
+ if (resolved === void 0) throw structuredError("ORM.AGGREGATE_UNSUPPORTED", inputCodec === void 0 ? `The composed target declares no '${fn}' aggregate for a call without an input.` : `The composed target declares no '${fn}' aggregate over codec '${inputCodec.codecId}'.`, {
219
+ why: "An aggregate result decodes through the codec its target declares; an undeclared pair has no declared result to type or decode.",
220
+ fix: `Aggregate an input the target declares '${fn}' for, or contribute an aggregate descriptor for this pair.`,
221
+ meta: {
222
+ operation: fn,
223
+ ...ifDefined("inputCodecId", inputCodec?.codecId)
224
+ }
105
225
  });
226
+ const inputAst = expr?.buildAst();
227
+ const ast = new AggregateExpr(fn, inputAst);
228
+ const projectionAst = resolved.lower?.({
229
+ expr: inputAst,
230
+ inputCodec
231
+ });
232
+ return new ExpressionImpl(ast, {
233
+ codecId: resolved.output.codecId,
234
+ nullable: resolved.nullable,
235
+ codec: resolved.output
236
+ }, void 0, projectionAst);
106
237
  }
107
238
  function createBuiltinFunctions(rawCodecInferer) {
108
239
  return {
@@ -121,19 +252,20 @@ function createBuiltinFunctions(rawCodecInferer) {
121
252
  raw: createRawSql(rawCodecInferer)
122
253
  };
123
254
  }
124
- function createAggregateOnlyFunctions() {
255
+ /**
256
+ * The aggregate implementations, erased.
257
+ *
258
+ * What each returns is the contract's answer — a function of the target's map
259
+ * and the input's codec — which no runtime value can state. The typed surface
260
+ * is `AggregateFunctions<QC>`, applied where these are handed out.
261
+ */
262
+ function createAggregateOnlyFunctions(aggregates) {
125
263
  return {
126
- count: (expr) => {
127
- const astExpr = expr ? expr.buildAst() : void 0;
128
- return new ExpressionImpl(AggregateExpr.count(astExpr), {
129
- codecId: "pg/int8@1",
130
- nullable: false
131
- });
132
- },
133
- sum: (expr) => numericAgg("sum", expr),
134
- avg: (expr) => numericAgg("avg", expr),
135
- min: (expr) => numericAgg("min", expr),
136
- max: (expr) => numericAgg("max", expr)
264
+ count: (expr) => aggregate(aggregates, "count", expr),
265
+ sum: (expr) => aggregate(aggregates, "sum", expr),
266
+ avg: (expr) => aggregate(aggregates, "avg", expr),
267
+ min: (expr) => aggregate(aggregates, "min", expr),
268
+ max: (expr) => aggregate(aggregates, "max", expr)
137
269
  };
138
270
  }
139
271
  function createFunctions(operations, rawCodecInferer) {
@@ -144,9 +276,9 @@ function createFunctions(operations, rawCodecInferer) {
144
276
  if (op) return op.impl;
145
277
  } });
146
278
  }
147
- function createAggregateFunctions(operations, rawCodecInferer) {
279
+ function createAggregateFunctions(operations, rawCodecInferer, aggregateRegistry) {
148
280
  const baseFns = createFunctions(operations, rawCodecInferer);
149
- const aggregates = createAggregateOnlyFunctions();
281
+ const aggregates = createAggregateOnlyFunctions(aggregateRegistry);
150
282
  return new Proxy({}, { get(_target, prop) {
151
283
  const agg = aggregates[prop];
152
284
  if (agg) return agg;
@@ -160,85 +292,6 @@ function resolveTableInNamespace(storage, namespaceId, tableName) {
160
292
  if (tables === void 0 || !Object.hasOwn(tables, tableName)) return void 0;
161
293
  return tables[tableName];
162
294
  }
163
- /**
164
- * **Last-resort escape hatch for unsafe type assertions. Not a sanctioned tool to reach for.**
165
- *
166
- * Before reaching for `blindCast`, **rewrite the surrounding code so the cast becomes
167
- * unnecessary**: tighten an input type, add a runtime check that narrows via a type
168
- * predicate, restructure a generic so the compiler can see the relationship you're
169
- * asserting, or use {@link castAs} when the value already satisfies the target type.
170
- * Only when no rewrite is feasible does `blindCast` become the right answer — and at
171
- * that point, the `Reason` literal you supply must articulate the compromise in
172
- * language a reviewer can evaluate.
173
- *
174
- * The reviewer **will** validate the `Reason`. If it doesn't hold up under scrutiny,
175
- * that is not a signal to soften the reason; it is a signal to go back and solve the
176
- * underlying type-system problem properly. An unconvincing justification is rework,
177
- * not a free pass.
178
- *
179
- * `blindCast` is the auditable form of `as Foo` / `as unknown as Foo`: it bypasses
180
- * the compiler's checks (the input type is `unknown`, the output type is whatever the
181
- * caller asks for), but it forces the unsafety to be named at the call site instead of
182
- * smuggled in via a bare `as`. The `Reason` type parameter exists only at compile
183
- * time — it is not present in the emitted JavaScript — but it is grep-able and
184
- * visible to future readers.
185
- *
186
- * @example
187
- * ```typescript
188
- * const stringValue = blindCast<
189
- * string,
190
- * "JSON.parse returns `unknown`; this field is documented to be a string in the API contract"
191
- * >(parsed[key]);
192
- * ```
193
- *
194
- * @typeParam TargetType - The type the caller is asserting the input has.
195
- * @typeParam _Reason - A string literal describing why bypassing the type system is necessary here.
196
- * Only meaningful at compile time. The reviewer evaluates whether it justifies the unsafety.
197
- */
198
- function blindCast(input) {
199
- return input;
200
- }
201
- /**
202
- * Returns an object with the key/value if value is defined, otherwise an empty object.
203
- *
204
- * Use with spread to conditionally include optional properties while satisfying
205
- * exactOptionalPropertyTypes. This is explicit about which properties are optional
206
- * and won't inadvertently strip other undefined values.
207
- *
208
- * @example
209
- * ```typescript
210
- * // Instead of:
211
- * const obj = {
212
- * required: 'value',
213
- * ...(optional ? { optional } : {}),
214
- * };
215
- *
216
- * // Use:
217
- * const obj = {
218
- * required: 'value',
219
- * ...ifDefined('optional', optional),
220
- * };
221
- * ```
222
- */
223
- function ifDefined(key, value) {
224
- return value !== void 0 ? blindCast({ [key]: value }) : {};
225
- }
226
- function structuredError(code, message, options) {
227
- const error = options?.cause !== void 0 ? new Error(message, { cause: options.cause }) : new Error(message);
228
- Object.defineProperty(error, "name", {
229
- value: "StructuredError",
230
- configurable: true
231
- });
232
- return Object.assign(error, {
233
- code,
234
- ...ifDefined("why", options?.why),
235
- ...ifDefined("fix", options?.fix),
236
- ...ifDefined("where", options?.where),
237
- ...ifDefined("severity", options?.severity),
238
- ...ifDefined("meta", options?.meta),
239
- ...ifDefined("docsUrl", options?.docsUrl)
240
- });
241
- }
242
295
  var BuilderBase = class {
243
296
  ctx;
244
297
  constructor(ctx) {
@@ -407,10 +460,10 @@ function resolveSelectArgs(args, scope, ctx) {
407
460
  if (typeof args[0] === "string" && typeof args[1] === "function") {
408
461
  const alias = args[0];
409
462
  const exprFn = args[1];
410
- const fns = createAggregateFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer);
463
+ const fns = createAggregateFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer, ctx.aggregates);
411
464
  const result = exprFn(createFieldProxy(scope), fns);
412
465
  const field = result.returnType;
413
- projections.push(ProjectionItem.of(alias, result.buildAst(), field.codec));
466
+ projections.push(ProjectionItem.of(alias, projectionAstOf(result), field.codec));
414
467
  newRowFields[alias] = field;
415
468
  return {
416
469
  projections,
@@ -419,11 +472,11 @@ function resolveSelectArgs(args, scope, ctx) {
419
472
  }
420
473
  if (typeof args[0] === "function") {
421
474
  const callbackFn = args[0];
422
- const fns = createAggregateFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer);
475
+ const fns = createAggregateFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer, ctx.aggregates);
423
476
  const record = callbackFn(createFieldProxy(scope), fns);
424
477
  for (const [key, expr] of Object.entries(record)) {
425
478
  const field = expr.returnType;
426
- projections.push(ProjectionItem.of(key, expr.buildAst(), field.codec));
479
+ projections.push(ProjectionItem.of(key, projectionAstOf(expr), field.codec));
427
480
  newRowFields[key] = field;
428
481
  }
429
482
  return {
@@ -442,7 +495,7 @@ function resolveOrderBy(arg, options, scope, rowFields, ctx, useAggregateFns) {
442
495
  }
443
496
  if (typeof arg === "function") {
444
497
  const combined = orderByScopeOf(scope, rowFields);
445
- const fns = useAggregateFns ? createAggregateFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer) : createFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer);
498
+ const fns = useAggregateFns ? createAggregateFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer, ctx.aggregates) : createFunctions(ctx.queryOperationTypes, ctx.rawCodecInferer);
446
499
  const result = arg(createFieldProxy(combined), fns);
447
500
  return dir === "asc" ? OrderByItem.asc(result.buildAst()) : OrderByItem.desc(result.buildAst());
448
501
  }
@@ -574,7 +627,7 @@ var GroupedQueryImpl = class GroupedQueryImpl extends QueryBase {
574
627
  }
575
628
  having(expr) {
576
629
  const combined = orderByScopeOf(this.state.scope, this.state.rowFields);
577
- const fns = createAggregateFunctions(this.ctx.queryOperationTypes, this.ctx.rawCodecInferer);
630
+ const fns = createAggregateFunctions(this.ctx.queryOperationTypes, this.ctx.rawCodecInferer, this.ctx.aggregates);
578
631
  const result = expr(createFieldProxy(combined), fns);
579
632
  return new GroupedQueryImpl(cloneState(this.state, { having: result.buildAst() }), this.ctx);
580
633
  }
@@ -935,7 +988,8 @@ function sql(options) {
935
988
  storageHash: context.contract.storage.storageHash ?? "unknown",
936
989
  storage: context.contract.storage,
937
990
  applyMutationDefaults: (options) => context.applyMutationDefaults(options),
938
- rawCodecInferer
991
+ rawCodecInferer,
992
+ aggregates: context.aggregateDescriptors
939
993
  };
940
994
  const { storage } = context.contract;
941
995
  return new Proxy({}, { get(_target, prop) {