@prisma/orm-family-sql 8.0.0-rc.1-dev.46 → 8.0.0-rc.10-dev.1

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 (207) hide show
  1. package/README.md +2 -6
  2. package/dist/{ast-Lbl4VwqP.mjs → ast-5tg0fGPQ.mjs} +2 -58
  3. package/dist/ast-5tg0fGPQ.mjs.map +1 -0
  4. package/dist/{ast-HFcfQZr-.d.mts → ast-DuLukI6f.d.mts} +4 -36
  5. package/dist/ast-DuLukI6f.d.mts.map +1 -0
  6. package/dist/{authored-check-naming-Hf9990DV.mjs → authored-check-naming-BEvfamnI.mjs} +2 -2
  7. package/dist/{authored-check-naming-Hf9990DV.mjs.map → authored-check-naming-BEvfamnI.mjs.map} +1 -1
  8. package/dist/{authoring-type-constructors-Blqoa2Ua-DqvNCOb2.mjs → authoring-type-constructors-BD-XuavC-CJV-TxFh.mjs} +10 -4
  9. package/dist/authoring-type-constructors-BD-XuavC-CJV-TxFh.mjs.map +1 -0
  10. package/dist/builder.d.mts +3 -3
  11. package/dist/builder__runtime.d.mts +26 -9
  12. package/dist/builder__runtime.d.mts.map +1 -1
  13. package/dist/builder__runtime.mjs +18 -9
  14. package/dist/builder__runtime.mjs.map +1 -1
  15. package/dist/builder__types.d.mts +3 -3
  16. package/dist/{codec-descriptor-registry-N0dhtKaH.mjs → codec-descriptor-registry-ECZ4ohtG.mjs} +2 -2
  17. package/dist/{codec-descriptor-registry-N0dhtKaH.mjs.map → codec-descriptor-registry-ECZ4ohtG.mjs.map} +1 -1
  18. package/dist/{config-types-gAm54C_v.mjs → config-types-BNJgLUUQ.mjs} +2 -2
  19. package/dist/{config-types-gAm54C_v.mjs.map → config-types-BNJgLUUQ.mjs.map} +1 -1
  20. package/dist/{config-types-D9fdKG3g.d.mts → config-types-Bd3ud-mX.d.mts} +3 -3
  21. package/dist/{config-types-D9fdKG3g.d.mts.map → config-types-Bd3ud-mX.d.mts.map} +1 -1
  22. package/dist/{contract-builder-D4a5dT7j.mjs → contract-builder-BOmEsrRi.mjs} +24 -5
  23. package/dist/contract-builder-BOmEsrRi.mjs.map +1 -0
  24. package/dist/{contract-builder-CG_tGDbB.d.mts → contract-builder-De_sioHE.d.mts} +15 -3
  25. package/dist/contract-builder-De_sioHE.d.mts.map +1 -0
  26. package/dist/contract-emitter.mjs +1 -1
  27. package/dist/contract-psl.d.mts +1 -1
  28. package/dist/contract-psl.mjs +1 -1
  29. package/dist/contract-psl__attribute-specs.d.mts +77 -0
  30. package/dist/contract-psl__attribute-specs.d.mts.map +1 -0
  31. package/dist/contract-psl__attribute-specs.mjs +2 -0
  32. package/dist/contract-psl__provider.d.mts +1 -1
  33. package/dist/contract-psl__provider.mjs +3 -3
  34. package/dist/contract-psl__provider.mjs.map +1 -1
  35. package/dist/contract-ts.d.mts +3 -3
  36. package/dist/contract-ts.mjs +3 -3
  37. package/dist/contract-ts__config-types.d.mts +1 -1
  38. package/dist/contract-ts__config-types.mjs +1 -1
  39. package/dist/contract-ts__contract-builder.d.mts +2 -2
  40. package/dist/contract-ts__contract-builder.mjs +2 -2
  41. package/dist/contract.d.mts +3 -3
  42. package/dist/contract.mjs +6 -6
  43. package/dist/contract__authored-check-naming.mjs +1 -1
  44. package/dist/contract__foreign-key-materialization.mjs +1 -1
  45. package/dist/contract__index-naming.mjs +1 -1
  46. package/dist/contract__types.d.mts +2 -2
  47. package/dist/contract__types.mjs +2 -2
  48. package/dist/contract__validators.d.mts +2 -2
  49. package/dist/contract__validators.mjs +2 -2
  50. package/dist/{control-D3cB5YQp.mjs → control-BIIMOKMy.mjs} +11 -9
  51. package/dist/control-BIIMOKMy.mjs.map +1 -0
  52. package/dist/{control-adapter-C99J7aEF-B7eQd7vD.d.mts → control-adapter-C99J7aEF-GODO43Ai.d.mts} +5 -5
  53. package/dist/{control-adapter-C99J7aEF-B7eQd7vD.d.mts.map → control-adapter-C99J7aEF-GODO43Ai.d.mts.map} +1 -1
  54. package/dist/control-adapter-DzTFiMaG.d.mts +1 -0
  55. package/dist/{control-DTLJ1WtZ.d.mts → control-b-6t8eI_.d.mts} +138 -19
  56. package/dist/control-b-6t8eI_.d.mts.map +1 -0
  57. package/dist/{db-D18PrXKW-DvTv4JFn.d.mts → db-BhQdL6Za-DubRGJvv.d.mts} +86 -62
  58. package/dist/{db-D18PrXKW-DvTv4JFn.d.mts.map → db-BhQdL6Za-DubRGJvv.d.mts.map} +1 -1
  59. package/dist/{ddl-types-CXx4vPz6-BsgrnSUY.d.mts → ddl-types-CXx4vPz6-Dko-GTTj.d.mts} +3 -3
  60. package/dist/{ddl-types-CXx4vPz6-BsgrnSUY.d.mts.map → ddl-types-CXx4vPz6-Dko-GTTj.d.mts.map} +1 -1
  61. package/dist/{derived-checks-DFMRmiAu-DGfB8aS4.mjs → derived-checks-DGjY5t7S-B3txNm7X.mjs} +48 -15
  62. package/dist/derived-checks-DGjY5t7S-B3txNm7X.mjs.map +1 -0
  63. package/dist/{derived-checks-DPdD01O0-DGqOFjs6.d.mts → derived-checks-DPdD01O0-DNBs1ZDA.d.mts} +2 -2
  64. package/dist/{derived-checks-DPdD01O0-DGqOFjs6.d.mts.map → derived-checks-DPdD01O0-DNBs1ZDA.d.mts.map} +1 -1
  65. package/dist/{diff-DbTNVm2f.d.mts → diff-CN1ou7vM.d.mts} +5 -5
  66. package/dist/{diff-DbTNVm2f.d.mts.map → diff-CN1ou7vM.d.mts.map} +1 -1
  67. package/dist/{dist-ZK6oeI5e.mjs → dist-D5__KJs-.mjs} +2 -1
  68. package/dist/dist-D5__KJs-.mjs.map +1 -0
  69. package/dist/{expression-CX5mTA-z.mjs → expression-B2Ox7zKM.mjs} +6 -2
  70. package/dist/expression-B2Ox7zKM.mjs.map +1 -0
  71. package/dist/{expression-FJK6Ar-d.d.mts → expression-mku9I7Ue.d.mts} +16 -7
  72. package/dist/{expression-FJK6Ar-d.d.mts.map → expression-mku9I7Ue.d.mts.map} +1 -1
  73. package/dist/family.d.mts +10 -10
  74. package/dist/family.mjs +8 -8
  75. package/dist/family__control-adapter.d.mts +2 -2
  76. package/dist/family__control.d.mts +4 -4
  77. package/dist/family__control.mjs +4 -4
  78. package/dist/family__diff.d.mts +2 -2
  79. package/dist/family__diff.mjs +1 -1
  80. package/dist/family__ir.d.mts +1 -1
  81. package/dist/family__ir.mjs +1 -1
  82. package/dist/family__migration.d.mts +1 -1
  83. package/dist/family__pack.d.mts +72 -0
  84. package/dist/family__pack.d.mts.map +1 -1
  85. package/dist/family__pack.mjs +4 -2
  86. package/dist/family__pack.mjs.map +1 -1
  87. package/dist/family__psl-infer.mjs +1 -1
  88. package/dist/family__runtime.d.mts +1 -1
  89. package/dist/family__runtime.mjs +1 -1
  90. package/dist/family__verify.mjs +1 -1
  91. package/dist/{foreign-key-materialization-Cu7-7LHl.mjs → foreign-key-materialization-0TrwfShD.mjs} +2 -2
  92. package/dist/{foreign-key-materialization-Cu7-7LHl.mjs.map → foreign-key-materialization-0TrwfShD.mjs.map} +1 -1
  93. package/dist/{index-C5I8D-MB.d.mts → index-CLAshwKN.d.mts} +2 -2
  94. package/dist/{index-C5I8D-MB.d.mts.map → index-CLAshwKN.d.mts.map} +1 -1
  95. package/dist/{index-C-vQOMY_.d.mts → index-DzBzeTAy.d.mts} +10 -10
  96. package/dist/{index-C-vQOMY_.d.mts.map → index-DzBzeTAy.d.mts.map} +1 -1
  97. package/dist/{index-naming-DREt6js7-CRH27yUv.mjs → index-naming-fQMLqyC4-4FzPVtCR.mjs} +4 -4
  98. package/dist/index-naming-fQMLqyC4-4FzPVtCR.mjs.map +1 -0
  99. package/dist/{interpreter-DyiUUAWh-DYdjIpiE.mjs → interpreter-CZ_iVQV4-CJ6COgSE.mjs} +123 -302
  100. package/dist/interpreter-CZ_iVQV4-CJ6COgSE.mjs.map +1 -0
  101. package/dist/ir-I-xciGUH.mjs.map +1 -1
  102. package/dist/{ir-Bghjt-FG.d.mts → ir-R9GE8gsm.d.mts} +2 -2
  103. package/dist/{ir-Bghjt-FG.d.mts.map → ir-R9GE8gsm.d.mts.map} +1 -1
  104. package/dist/{middleware-AhTz1BOW-th-Suxuf.d.mts → middleware-AhTz1BOW-CtQWS4mb.d.mts} +2 -2
  105. package/dist/{middleware-AhTz1BOW-th-Suxuf.d.mts.map → middleware-AhTz1BOW-CtQWS4mb.d.mts.map} +1 -1
  106. package/dist/middleware-Cev-ZFyS.d.mts +1 -0
  107. package/dist/{migration-CjDRZNep.d.mts → migration-Bhce5i_m.d.mts} +3 -3
  108. package/dist/{migration-CjDRZNep.d.mts.map → migration-Bhce5i_m.d.mts.map} +1 -1
  109. package/dist/operations.d.mts +1 -1
  110. package/dist/orm-client.d.mts +131 -95
  111. package/dist/orm-client.d.mts.map +1 -1
  112. package/dist/orm-client.mjs +1021 -942
  113. package/dist/orm-client.mjs.map +1 -1
  114. package/dist/plan-C7VP7jOh.d.mts +2 -0
  115. package/dist/{plan-CDxduYaN-pLIyyJaB.d.mts → plan-CDxduYaN-B2kMLIQQ.d.mts} +3 -3
  116. package/dist/{plan-CDxduYaN-pLIyyJaB.d.mts.map → plan-CDxduYaN-B2kMLIQQ.d.mts.map} +1 -1
  117. package/dist/{prepared-statement-9QpkE6JG-C430V3MO.d.mts → prepared-statement-9QpkE6JG-B9xqBu5T.d.mts} +16 -16
  118. package/dist/{prepared-statement-9QpkE6JG-C430V3MO.d.mts.map → prepared-statement-9QpkE6JG-B9xqBu5T.d.mts.map} +1 -1
  119. package/dist/{psl-infer-Dk5kgKre.mjs → psl-infer-TBwKfKgU.mjs} +2 -2
  120. package/dist/{psl-infer-Dk5kgKre.mjs.map → psl-infer-TBwKfKgU.mjs.map} +1 -1
  121. package/dist/query-lane-context-CGdMIEuv.d.mts +1 -0
  122. package/dist/{query-lane-context-Qa-eddrE-kuZ8Z86-.d.mts → query-lane-context-Qa-eddrE-BQV6J9nV.d.mts} +4 -4
  123. package/dist/{query-lane-context-Qa-eddrE-kuZ8Z86-.d.mts.map → query-lane-context-Qa-eddrE-BQV6J9nV.d.mts.map} +1 -1
  124. package/dist/relational-core.d.mts +12 -12
  125. package/dist/relational-core.mjs +3 -3
  126. package/dist/relational-core__aggregate-descriptor-registry.d.mts +1 -1
  127. package/dist/relational-core__ast.d.mts +4 -4
  128. package/dist/relational-core__ast.mjs +2 -2
  129. package/dist/relational-core__codec-descriptor-registry.d.mts +3 -3
  130. package/dist/relational-core__codec-descriptor-registry.mjs +1 -1
  131. package/dist/relational-core__contract-free.d.mts +3 -3
  132. package/dist/relational-core__expression.d.mts +1 -1
  133. package/dist/relational-core__expression.mjs +1 -1
  134. package/dist/relational-core__middleware.d.mts +2 -2
  135. package/dist/relational-core__plan.d.mts +3 -3
  136. package/dist/relational-core__query-lane-context.d.mts +2 -2
  137. package/dist/relational-core__types.d.mts +2 -2
  138. package/dist/{runtime-DpKF2Yu2.d.mts → runtime-CzCx0TKe.d.mts} +3 -3
  139. package/dist/{runtime-DpKF2Yu2.d.mts.map → runtime-CzCx0TKe.d.mts.map} +1 -1
  140. package/dist/{runtime-tIHpGCcG.mjs → runtime-PknWErjr.mjs} +2 -2
  141. package/dist/{runtime-tIHpGCcG.mjs.map → runtime-PknWErjr.mjs.map} +1 -1
  142. package/dist/runtime.d.mts +4 -4
  143. package/dist/runtime.mjs +2 -2
  144. package/dist/runtime__internal__prepared-query.d.mts +1 -1
  145. package/dist/{schema-differ-DpG_gnur-DFAtGezx.d.mts → schema-differ-DpG_gnur-BICVtTHY.d.mts} +2 -2
  146. package/dist/{schema-differ-DpG_gnur-DFAtGezx.d.mts.map → schema-differ-DpG_gnur-BICVtTHY.d.mts.map} +1 -1
  147. package/dist/schema-ir.mjs +1 -1
  148. package/dist/schema-ir__types.mjs +1 -1
  149. package/dist/{schema-verify-C_PEdlAr-Dxxjm6EM.mjs → schema-verify-C_PEdlAr-CmXrFuW1.mjs} +2 -2
  150. package/dist/{schema-verify-C_PEdlAr-Dxxjm6EM.mjs.map → schema-verify-C_PEdlAr-CmXrFuW1.mjs.map} +1 -1
  151. package/dist/sql-attribute-specs-CG0yitvD-CG-0eW98.mjs +275 -0
  152. package/dist/sql-attribute-specs-CG0yitvD-CG-0eW98.mjs.map +1 -0
  153. package/dist/{sql-contract-serializer-2oBWuxTe-DKZTf2n8.mjs → sql-contract-serializer-Bxu4a5oQ-D0lKpb4a.mjs} +24 -5
  154. package/dist/sql-contract-serializer-Bxu4a5oQ-D0lKpb4a.mjs.map +1 -0
  155. package/dist/{sql-execution-plan--jKyLpe5-CMGhgO0M.d.mts → sql-execution-plan--jKyLpe5-Bcz9QM2s.d.mts} +2 -2
  156. package/dist/{sql-execution-plan--jKyLpe5-CMGhgO0M.d.mts.map → sql-execution-plan--jKyLpe5-Bcz9QM2s.d.mts.map} +1 -1
  157. package/dist/{timestamp-now-generator-DRXygu32-DN9Qb1uI.mjs → timestamp-now-generator-BZnBo7IC-DbN5Apqe.mjs} +27 -19
  158. package/dist/timestamp-now-generator-BZnBo7IC-DbN5Apqe.mjs.map +1 -0
  159. package/dist/{types-4YenawkP-CwaaZSid.mjs → types-BvupgHcG-c8QDupnu.mjs} +13 -6
  160. package/dist/types-BvupgHcG-c8QDupnu.mjs.map +1 -0
  161. package/dist/{types-UcHa2cTe.d.mts → types-C36_3E6_.d.mts} +3 -2
  162. package/dist/types-C36_3E6_.d.mts.map +1 -0
  163. package/dist/{types-CyxGtOOh-BggSa6Fe.d.mts → types-CyxGtOOh-BJnoWm0f.d.mts} +8 -8
  164. package/dist/{types-CyxGtOOh-BggSa6Fe.d.mts.map → types-CyxGtOOh-BJnoWm0f.d.mts.map} +1 -1
  165. package/dist/{types-CUsJrvEl.mjs → types-D0B65hip.mjs} +3 -2
  166. package/dist/types-D0B65hip.mjs.map +1 -0
  167. package/dist/types-DvsoMNLs.d.mts +1 -0
  168. package/dist/{types-IqZMLrFC-DcH8v_u3.d.mts → types-IqZMLrFC-BIRftuU7.d.mts} +4 -4
  169. package/dist/{types-IqZMLrFC-DcH8v_u3.d.mts.map → types-IqZMLrFC-BIRftuU7.d.mts.map} +1 -1
  170. package/dist/{types-v3qxLLxo-DCeKv7yY.d.mts → types-v3qxLLxo-Clw_yBAh.d.mts} +2 -2
  171. package/dist/{types-v3qxLLxo-DCeKv7yY.d.mts.map → types-v3qxLLxo-Clw_yBAh.d.mts.map} +1 -1
  172. package/dist/{validators-Belo8QqM.d.mts → validators-CbqMxQfW.d.mts} +23 -4
  173. package/dist/validators-CbqMxQfW.d.mts.map +1 -0
  174. package/dist/{validators-CrWD6bSP.mjs → validators-DD98VrpC.mjs} +0 -0
  175. package/dist/validators-DD98VrpC.mjs.map +1 -0
  176. package/dist/{verify-u0UTdZgD-DSAaz9rW.mjs → verify-ChiDeTk8-HEewdjrM.mjs} +3 -3
  177. package/dist/verify-ChiDeTk8-HEewdjrM.mjs.map +1 -0
  178. package/package.json +20 -21
  179. package/dist/ast-HFcfQZr-.d.mts.map +0 -1
  180. package/dist/ast-Lbl4VwqP.mjs.map +0 -1
  181. package/dist/authoring-type-constructors-Blqoa2Ua-DqvNCOb2.mjs.map +0 -1
  182. package/dist/contract-builder-CG_tGDbB.d.mts.map +0 -1
  183. package/dist/contract-builder-D4a5dT7j.mjs.map +0 -1
  184. package/dist/control-D3cB5YQp.mjs.map +0 -1
  185. package/dist/control-DTLJ1WtZ.d.mts.map +0 -1
  186. package/dist/control-adapter-MZJQiwcE.d.mts +0 -1
  187. package/dist/derived-checks-DFMRmiAu-DGfB8aS4.mjs.map +0 -1
  188. package/dist/dist-ZK6oeI5e.mjs.map +0 -1
  189. package/dist/expression-CX5mTA-z.mjs.map +0 -1
  190. package/dist/index-naming-DREt6js7-CRH27yUv.mjs.map +0 -1
  191. package/dist/interpreter-DyiUUAWh-DYdjIpiE.mjs.map +0 -1
  192. package/dist/lane-query-builder.d.mts +0 -236
  193. package/dist/lane-query-builder.d.mts.map +0 -1
  194. package/dist/lane-query-builder.mjs +0 -67
  195. package/dist/lane-query-builder.mjs.map +0 -1
  196. package/dist/middleware--TtoxUiW.d.mts +0 -1
  197. package/dist/plan-BHLdb0Z7.d.mts +0 -2
  198. package/dist/query-lane-context-XMvk7fmY.d.mts +0 -1
  199. package/dist/sql-contract-serializer-2oBWuxTe-DKZTf2n8.mjs.map +0 -1
  200. package/dist/timestamp-now-generator-DRXygu32-DN9Qb1uI.mjs.map +0 -1
  201. package/dist/types-4YenawkP-CwaaZSid.mjs.map +0 -1
  202. package/dist/types-B0msOnBM.d.mts +0 -1
  203. package/dist/types-CUsJrvEl.mjs.map +0 -1
  204. package/dist/types-UcHa2cTe.d.mts.map +0 -1
  205. package/dist/validators-Belo8QqM.d.mts.map +0 -1
  206. package/dist/validators-CrWD6bSP.mjs.map +0 -1
  207. package/dist/verify-u0UTdZgD-DSAaz9rW.mjs.map +0 -1
@@ -1,5 +1,6 @@
1
1
  import { t as deriveValueSetFromEntity } from "./value-set-derivation-hook-Di9JZ0X7.mjs";
2
- import { n as buildSqlContractFromDefinition } from "./derived-checks-DFMRmiAu-DGfB8aS4.mjs";
2
+ import { a as interpretFieldAttribute, i as findModelAttributeNode, n as fieldSpecContext, o as interpretModelAttribute, r as findFieldAttributeNode, s as sqlAttributeSpecs, t as PSL_CHECK_ON_STI_VARIANT } from "./sql-attribute-specs-CG0yitvD-CG-0eW98.mjs";
3
+ import { n as buildSqlContractFromDefinition } from "./derived-checks-DGjY5t7S-B3txNm7X.mjs";
3
4
  import { structuredError } from "@prisma/orm-framework/utils/structured-error";
4
5
  import { hasRegisteredFieldNamespace, instantiateAuthoringEntityType, instantiateAuthoringFieldPreset, instantiateAuthoringTypeConstructor, isAuthoringEntityTypeDescriptor, isAuthoringFieldPresetDescriptor, isAuthoringModelAttributeDescriptor, isAuthoringPslBlockDescriptor, isAuthoringTypeConstructorDescriptor, validateAuthoringHelperArguments } from "@prisma/orm-framework/components/authoring";
5
6
  import { UNBOUND_NAMESPACE_ID } from "@prisma/orm-framework/components/ir";
@@ -7,10 +8,12 @@ import { InternalError } from "@prisma/orm-framework/utils/internal-error";
7
8
  import { crossRef } from "@prisma/orm-framework/contract/types";
8
9
  import { ifDefined } from "@prisma/orm-framework/utils/defined";
9
10
  import { blindCast } from "@prisma/orm-framework/utils/casts";
10
- import { bool, entityRef, fieldAttribute, fieldRef, findBlockDescriptor, funcCall, identifier, interpretAttribute, keywordPslSpan, leafDiagnostic, list, modelAttribute, nodePslSpan, num, oneOf, optional, record, str } from "@prisma/orm-framework/psl-parser";
11
- import { assertDefined, invariant } from "@prisma/orm-framework/utils/assertions";
11
+ import { findBlockDescriptor, keywordPslSpan, nodePslSpan } from "@prisma/orm-framework/psl-parser";
12
12
  import { notOk, ok } from "@prisma/orm-framework/utils/result";
13
- //#region ../../../2-sql/2-authoring/contract-psl/dist/interpreter-DyiUUAWh.mjs
13
+ import { resolveToOneRelationNullable } from "@prisma/orm-framework/contract-authoring";
14
+ import { consumeInvalidFkPairing, fkRelationPairKey, requiredOneToOneBackrelationDiagnostic } from "@prisma/orm-framework/psl-parser/interpret";
15
+ import { assertDefined, invariant } from "@prisma/orm-framework/utils/assertions";
16
+ //#region ../../../2-sql/2-authoring/contract-psl/dist/interpreter-CZ_iVQV4.mjs
14
17
  function contractError(code, message, options) {
15
18
  return structuredError(code, message, options);
16
19
  }
@@ -364,196 +367,6 @@ function mapPslHelperArgs(input) {
364
367
  }
365
368
  return mappedArgs;
366
369
  }
367
- function findModelAttributeNode(model, name) {
368
- for (const attribute of model.node.attributes()) if (attribute.name()?.isSimpleName(name) === true) return attribute;
369
- }
370
- function findFieldAttributeNode(field, name) {
371
- for (const attribute of field.node.attributes()) if (attribute.name()?.isSimpleName(name) === true) return attribute;
372
- }
373
- function buildModelInterpretCtx(input) {
374
- return {
375
- level: "model",
376
- sourceId: input.sourceId,
377
- sourceFile: input.sourceFile,
378
- selfModel: input.selfModel,
379
- resolveReferencedModel: () => void 0
380
- };
381
- }
382
- function buildFieldInterpretCtx(input) {
383
- return {
384
- level: "field",
385
- sourceId: input.sourceId,
386
- sourceFile: input.sourceFile,
387
- selfModel: input.selfModel,
388
- resolveReferencedModel: input.resolveReferencedModel ?? (() => void 0),
389
- field: input.field
390
- };
391
- }
392
- function interpretModelAttribute(input) {
393
- const result = interpretAttribute(input.node, input.spec, buildModelInterpretCtx({
394
- selfModel: input.model,
395
- sourceFile: input.sourceFile,
396
- sourceId: input.sourceId
397
- }));
398
- if (!result.ok) {
399
- for (const failure of result.failure) input.diagnostics.push(failure);
400
- return;
401
- }
402
- return result.value;
403
- }
404
- function interpretFieldAttribute(input) {
405
- const result = interpretAttribute(input.node, input.spec, buildFieldInterpretCtx({
406
- selfModel: input.model,
407
- field: input.field,
408
- sourceFile: input.sourceFile,
409
- sourceId: input.sourceId,
410
- resolveReferencedModel: input.resolveReferencedModel
411
- }));
412
- if (!result.ok) {
413
- for (const failure of result.failure) input.diagnostics.push(failure);
414
- return;
415
- }
416
- return result.value;
417
- }
418
- const mapModelSpec = modelAttribute("map", { positional: [{
419
- key: "name",
420
- type: str()
421
- }] });
422
- const mapFieldSpec = fieldAttribute("map", { positional: [{
423
- key: "name",
424
- type: str()
425
- }] });
426
- function buildDefaultSpec(input) {
427
- const literal = () => oneOf(str(), num(), bool());
428
- const funcArms = [...input.registry.entries()].map(([name, entry]) => funcCall(name, blindCast(entry.signature)));
429
- return fieldAttribute("default", { positional: [{
430
- key: "value",
431
- type: oneOf(...input.isList ? [list(literal()), ...funcArms] : [
432
- str(),
433
- num(),
434
- bool(),
435
- ...funcArms
436
- ])
437
- }] });
438
- }
439
- function buildEnumDefaultSpec(memberNames) {
440
- const [first, ...rest] = memberNames;
441
- return fieldAttribute("default", { positional: [{
442
- key: "member",
443
- type: oneOf(...[identifier(first), ...rest.map((name) => identifier(name))])
444
- }] });
445
- }
446
- const idFieldSpec = fieldAttribute("id", { named: { map: optional(str()) } });
447
- const uniqueFieldSpec = fieldAttribute("unique", { named: { map: optional(str()) } });
448
- const noCheckKindArgument = () => oneOf(identifier("membership"), identifier("elementNotNull"));
449
- /**
450
- * `@noCheck` waives generated CHECK constraints on one column: bare for every
451
- * kind the column's shape derives, or naming concrete kinds. Two optional
452
- * positional slots cover the whole kind vocabulary; a third argument is
453
- * necessarily a duplicate and fails as excess arity.
454
- */
455
- const noCheckFieldSpec = fieldAttribute("noCheck", {
456
- positional: [{
457
- key: "first",
458
- type: optional(noCheckKindArgument())
459
- }, {
460
- key: "second",
461
- type: optional(noCheckKindArgument())
462
- }],
463
- refine: (value, ctx, attributeNode) => {
464
- if (value.first !== void 0 && value.first === value.second) return [leafDiagnostic(ctx, attributeNode, "`@noCheck` names the same kind twice")];
465
- return [];
466
- }
467
- });
468
- const idModelSpec = modelAttribute("id", {
469
- positional: [{
470
- key: "fields",
471
- type: list(fieldRef("self"), {
472
- nonEmpty: true,
473
- unique: true
474
- })
475
- }],
476
- named: { map: optional(str()) }
477
- });
478
- const uniqueModelSpec = modelAttribute("unique", {
479
- positional: [{
480
- key: "fields",
481
- type: list(fieldRef("self"), {
482
- nonEmpty: true,
483
- unique: true
484
- })
485
- }],
486
- named: { map: optional(str()) }
487
- });
488
- const PSL_INDEX_FIELDS_XOR_EXPRESSION = "PSL_INDEX_FIELDS_XOR_EXPRESSION";
489
- const PSL_INDEX_EXPRESSION_REQUIRES_NAME = "PSL_INDEX_EXPRESSION_REQUIRES_NAME";
490
- const PSL_INDEX_NAME_XOR_MAP = "PSL_INDEX_NAME_XOR_MAP";
491
- const indexModelSpec = modelAttribute("index", {
492
- positional: [{
493
- key: "fields",
494
- type: optional(list(fieldRef("self"), {
495
- nonEmpty: true,
496
- unique: true
497
- }))
498
- }],
499
- named: {
500
- expression: optional(str()),
501
- where: optional(str()),
502
- unique: optional(bool()),
503
- name: optional(str()),
504
- map: optional(str()),
505
- type: optional(str()),
506
- options: optional(record(str()))
507
- },
508
- refine: (value, ctx, attributeNode) => {
509
- const diagnostics = [];
510
- if (value.fields === void 0 === (value.expression === void 0)) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` requires exactly one of a fields list or an `expression` argument", PSL_INDEX_FIELDS_XOR_EXPRESSION));
511
- if (value.expression !== void 0 && value.name === void 0 && value.map === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` with an `expression` argument requires a `name` or `map` argument (a default name cannot be derived from an expression)", PSL_INDEX_EXPRESSION_REQUIRES_NAME));
512
- if (value.name !== void 0 && value.map !== void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` takes at most one of `name` and `map`", PSL_INDEX_NAME_XOR_MAP));
513
- if (value.options !== void 0 && value.type === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@index` options argument requires a type argument"));
514
- return diagnostics;
515
- }
516
- });
517
- const PSL_CHECK_REQUIRES_NAME_OR_MAP = "PSL_CHECK_REQUIRES_NAME_OR_MAP";
518
- const PSL_CHECK_NAME_XOR_MAP = "PSL_CHECK_NAME_XOR_MAP";
519
- const PSL_CHECK_EXPRESSION_EMPTY = "PSL_CHECK_EXPRESSION_EMPTY";
520
- /**
521
- * A single-table-inheritance variant (`@@base` with no own `@@map`) shares
522
- * its base model's storage table and has no table of its own to declare a
523
- * check on — raised from {@link interpretPslDocumentToSqlContract}, not from
524
- * this spec's own `refine`, because the rule needs the model's `@@base`
525
- * declaration, which a single attribute's `refine` cannot see.
526
- */
527
- const PSL_CHECK_ON_STI_VARIANT = "PSL_CHECK_ON_STI_VARIANT";
528
- const checkModelSpec = modelAttribute("check", {
529
- named: {
530
- expression: str(),
531
- name: optional(str()),
532
- map: optional(str())
533
- },
534
- refine: (value, ctx, attributeNode) => {
535
- const diagnostics = [];
536
- if (value.expression.trim().length === 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` expression must not be empty — an empty predicate is not a constraint", PSL_CHECK_EXPRESSION_EMPTY));
537
- if (value.name === void 0 && value.map === void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` requires a `name` or `map` argument (a default name cannot be derived — a check has no column tuple to name itself after)", PSL_CHECK_REQUIRES_NAME_OR_MAP));
538
- if (value.name !== void 0 && value.map !== void 0) diagnostics.push(leafDiagnostic(ctx, attributeNode, "`@@check` takes at most one of `name` and `map`", PSL_CHECK_NAME_XOR_MAP));
539
- return diagnostics;
540
- }
541
- });
542
- const controlModelSpec = modelAttribute("control", { positional: [{
543
- key: "policy",
544
- type: oneOf(identifier("managed"), identifier("tolerated"), identifier("external"), identifier("observed"))
545
- }] });
546
- const discriminatorModelSpec = modelAttribute("discriminator", { positional: [{
547
- key: "field",
548
- type: fieldRef("self")
549
- }] });
550
- const baseModelSpec = modelAttribute("base", { positional: [{
551
- key: "base",
552
- type: entityRef()
553
- }, {
554
- key: "value",
555
- type: str()
556
- }] });
557
370
  function toNamedTypeFieldDescriptor(typeRef, descriptor) {
558
371
  return {
559
372
  codecId: descriptor.codecId,
@@ -951,10 +764,12 @@ function lowerDefaultForField(input) {
951
764
  if (node === void 0) return {};
952
765
  const interpreted = interpretFieldAttribute({
953
766
  node,
954
- spec: buildDefaultSpec({
955
- isList: input.isList ?? false,
956
- registry: input.defaultFunctionRegistry
957
- }),
767
+ spec: sqlAttributeSpecs.field.default(fieldSpecContext({
768
+ symbols: input.symbolTable,
769
+ model: input.model,
770
+ field: input.field,
771
+ controlMutationDefaults: input.defaultFunctionRegistry
772
+ })),
958
773
  model: input.model,
959
774
  field: input.field,
960
775
  sourceFile: input.sourceFile,
@@ -1027,11 +842,15 @@ function lowerEnumDefaultForField(input) {
1027
842
  const { field, model, sourceFile, enumHandle, sourceId, diagnostics } = input;
1028
843
  const node = findFieldAttributeNode(field, "default");
1029
844
  if (node === void 0) return {};
1030
- const [firstMember, ...restMembers] = enumHandle.enumMembers.map((m) => m.name);
1031
- if (firstMember === void 0) return {};
845
+ if (enumHandle.enumMembers.length === 0) return {};
1032
846
  const interpreted = interpretFieldAttribute({
1033
847
  node,
1034
- spec: buildEnumDefaultSpec([firstMember, ...restMembers]),
848
+ spec: sqlAttributeSpecs.field.default(fieldSpecContext({
849
+ symbols: input.symbolTable,
850
+ model,
851
+ field,
852
+ controlMutationDefaults: input.defaultFunctionRegistry
853
+ })),
1035
854
  model,
1036
855
  field,
1037
856
  sourceFile,
@@ -1039,7 +858,8 @@ function lowerEnumDefaultForField(input) {
1039
858
  diagnostics
1040
859
  });
1041
860
  if (interpreted === void 0) return {};
1042
- const member = interpreted.member;
861
+ const member = interpreted.value;
862
+ invariant(typeof member === "string", "the enum @default grammar admits only member identifiers, so the parsed value is a string");
1043
863
  const match = enumHandle.enumMembers.find((m) => m.name === member);
1044
864
  if (!match) return {};
1045
865
  return { defaultValue: {
@@ -1051,25 +871,17 @@ const MODEL_COORDINATE_SEPARATOR = "\0";
1051
871
  function modelCoordinateKey(namespaceId, modelName) {
1052
872
  return `${namespaceId}${MODEL_COORDINATE_SEPARATOR}${modelName}`;
1053
873
  }
1054
- const BUILTIN_FIELD_ATTRIBUTE_NAMES = /* @__PURE__ */ new Set([
1055
- "id",
1056
- "unique",
1057
- "default",
1058
- "relation",
1059
- "map",
1060
- "noCheck"
1061
- ]);
1062
874
  const REMOVED_ATTRIBUTE_RULES = /* @__PURE__ */ new Map([["updatedAt", {
1063
875
  hint: "Use `temporal.updatedAt()` as a field-preset call instead.",
1064
876
  suppressWhen: (field) => field.typeConstructor?.path[0] === "temporal"
1065
877
  }]]);
1066
878
  {
1067
- const overlap = [...REMOVED_ATTRIBUTE_RULES.keys()].filter((name) => BUILTIN_FIELD_ATTRIBUTE_NAMES.has(name));
1068
- if (overlap.length > 0) throw new InternalError(`BUILTIN_FIELD_ATTRIBUTE_NAMES and REMOVED_ATTRIBUTE_RULES must not overlap. Names in both: ${overlap.join(", ")}`);
879
+ const overlap = [...REMOVED_ATTRIBUTE_RULES.keys()].filter((name) => Object.hasOwn(sqlAttributeSpecs.field, name));
880
+ if (overlap.length > 0) throw new InternalError(`Registered SQL field attributes and REMOVED_ATTRIBUTE_RULES must not overlap. Names in both: ${overlap.join(", ")}`);
1069
881
  }
1070
882
  function validateFieldAttributes(input) {
1071
883
  for (const attribute of input.field.attributes) {
1072
- if (BUILTIN_FIELD_ATTRIBUTE_NAMES.has(attribute.name)) continue;
884
+ if (Object.hasOwn(sqlAttributeSpecs.field, attribute.name)) continue;
1073
885
  if (attribute.name.startsWith("db.")) {
1074
886
  input.diagnostics.push({
1075
887
  code: "PSL_UNSUPPORTED_FIELD_ATTRIBUTE",
@@ -1111,7 +923,7 @@ function extractFieldConstraintNames(input) {
1111
923
  const idNode = findFieldAttributeNode(input.field, "id");
1112
924
  const idName = idNode === void 0 ? void 0 : interpretFieldAttribute({
1113
925
  node: idNode,
1114
- spec: idFieldSpec,
926
+ spec: sqlAttributeSpecs.field.id(),
1115
927
  model: input.model,
1116
928
  field: input.field,
1117
929
  sourceFile: input.sourceFile,
@@ -1125,7 +937,7 @@ function extractFieldConstraintNames(input) {
1125
937
  idName,
1126
938
  uniqueName: uniqueNode === void 0 ? void 0 : interpretFieldAttribute({
1127
939
  node: uniqueNode,
1128
- spec: uniqueFieldSpec,
940
+ spec: sqlAttributeSpecs.field.unique(),
1129
941
  model: input.model,
1130
942
  field: input.field,
1131
943
  sourceFile: input.sourceFile,
@@ -1146,7 +958,7 @@ function lowerNoCheckForField(input) {
1146
958
  if (node === void 0) return void 0;
1147
959
  const interpreted = interpretFieldAttribute({
1148
960
  node,
1149
- spec: noCheckFieldSpec,
961
+ spec: sqlAttributeSpecs.field.noCheck(),
1150
962
  model: input.model,
1151
963
  field: input.field,
1152
964
  sourceFile: input.sourceFile,
@@ -1185,7 +997,7 @@ function lowerNoCheckForField(input) {
1185
997
  return [...authored].sort();
1186
998
  }
1187
999
  function collectResolvedFields(input) {
1188
- const { model, mapping, enumTypeDescriptors, namedTypeDescriptors, modelNames, compositeTypeNames, composedExtensions, authoringContributions, familyId, targetId, defaultFunctionRegistry, generatorDescriptorById, diagnostics, sourceId, scalarColumnDescriptors, enumHandles, capabilities, namespaceId, namespaceExtensionEntities, codecLookup } = input;
1000
+ const { model, symbolTable, mapping, enumTypeDescriptors, namedTypeDescriptors, modelNames, compositeTypeNames, composedExtensions, authoringContributions, familyId, targetId, defaultFunctionRegistry, generatorDescriptorById, diagnostics, sourceId, scalarColumnDescriptors, enumHandles, capabilities, namespaceId, namespaceExtensionEntities, codecLookup } = input;
1189
1001
  const resolvedFields = [];
1190
1002
  const valueObjectStorageTypeName = authoringContributions?.valueObjectStorageType;
1191
1003
  const declaredControlPolicy = getAttribute(model.attributes, "control")?.args.find((arg) => arg.kind === "positional")?.value.trim();
@@ -1300,22 +1112,24 @@ function collectResolvedFields(input) {
1300
1112
  fieldName: field.name,
1301
1113
  field,
1302
1114
  model,
1115
+ symbolTable,
1303
1116
  sourceFile: input.sourceFile,
1304
1117
  enumHandle,
1305
1118
  sourceId,
1119
+ defaultFunctionRegistry,
1306
1120
  diagnostics
1307
1121
  }) : lowerDefaultForField({
1308
1122
  modelName: model.name,
1309
1123
  fieldName: field.name,
1310
1124
  field,
1311
1125
  model,
1126
+ symbolTable,
1312
1127
  sourceFile: input.sourceFile,
1313
1128
  columnDescriptor: descriptor,
1314
1129
  generatorDescriptorById,
1315
1130
  sourceId,
1316
1131
  defaultFunctionRegistry,
1317
- diagnostics,
1318
- isList: isListField
1132
+ diagnostics
1319
1133
  }) : {};
1320
1134
  const loweredOnCreate = loweredDefault.executionDefaults?.onCreate;
1321
1135
  const loweredFunctionDefault = loweredDefault.defaultValue?.kind === "function";
@@ -1411,7 +1225,7 @@ function buildModelMappings(modelEntries, defaultNamespaceId, diagnostics, sourc
1411
1225
  const mapNode = findModelAttributeNode(model, "map");
1412
1226
  const tableName = mapNode === void 0 ? lowerFirst(model.name) : interpretModelAttribute({
1413
1227
  node: mapNode,
1414
- spec: mapModelSpec,
1228
+ spec: sqlAttributeSpecs.model.map(),
1415
1229
  model,
1416
1230
  sourceFile,
1417
1231
  sourceId,
@@ -1422,7 +1236,7 @@ function buildModelMappings(modelEntries, defaultNamespaceId, diagnostics, sourc
1422
1236
  const fieldMapNode = findFieldAttributeNode(field, "map");
1423
1237
  const columnName = fieldMapNode === void 0 ? field.name : interpretFieldAttribute({
1424
1238
  node: fieldMapNode,
1425
- spec: mapFieldSpec,
1239
+ spec: sqlAttributeSpecs.field.map(),
1426
1240
  model,
1427
1241
  field,
1428
1242
  sourceFile,
@@ -1587,58 +1401,9 @@ const REFERENTIAL_ACTION_MAP = {
1587
1401
  setNull: "setNull",
1588
1402
  setDefault: "setDefault"
1589
1403
  };
1590
- function fkRelationPairKey(declaringModelName, targetModelName) {
1591
- return `${declaringModelName}::${targetModelName}`;
1592
- }
1593
1404
  function normalizeReferentialAction(actionToken) {
1594
1405
  return REFERENTIAL_ACTION_MAP[actionToken];
1595
1406
  }
1596
- function relationInvariants(parsed, ctx) {
1597
- if (parsed.fields !== void 0 !== (parsed.references !== void 0)) return [{
1598
- code: "PSL_INVALID_ATTRIBUTE_SYNTAX",
1599
- message: `Relation field "${ctx.selfModel.name}.${ctx.field?.name ?? ""}" requires fields and references arguments`,
1600
- sourceId: ctx.sourceId,
1601
- span: relationAttributeSpan(ctx)
1602
- }];
1603
- return [];
1604
- }
1605
- const sqlRelation = fieldAttribute("relation", {
1606
- positional: [{
1607
- key: "name",
1608
- type: optional(str())
1609
- }],
1610
- named: {
1611
- name: optional(str()),
1612
- fields: optional(list(fieldRef("self"), {
1613
- nonEmpty: true,
1614
- unique: true
1615
- })),
1616
- references: optional(list(fieldRef("referenced"), {
1617
- nonEmpty: true,
1618
- unique: true
1619
- })),
1620
- map: optional(str()),
1621
- onDelete: optional(oneOf(identifier("NoAction"), identifier("Restrict"), identifier("Cascade"), identifier("SetNull"), identifier("SetDefault"))),
1622
- onUpdate: optional(oneOf(identifier("NoAction"), identifier("Restrict"), identifier("Cascade"), identifier("SetNull"), identifier("SetDefault"))),
1623
- /**
1624
- * Opts a foreign key out of its default backing index
1625
- * (`index: false`). Omitted (the default) keeps the FK's derived
1626
- * backing-index expectation; only `false` is meaningful — there is no
1627
- * `index: true` spelling since that is already the default.
1628
- */
1629
- index: optional(bool())
1630
- },
1631
- refine: relationInvariants
1632
- });
1633
- function relationAttributeSpan(ctx) {
1634
- const field = ctx.field;
1635
- if (field !== void 0) {
1636
- const node = findFieldAttributeNode(field, "relation");
1637
- if (node !== void 0) return nodePslSpan(node.syntax, ctx.sourceFile);
1638
- return field.span;
1639
- }
1640
- return ctx.selfModel.span;
1641
- }
1642
1407
  function resolveReferencedModel(symbols, field) {
1643
1408
  const topLevel = symbols.topLevel.models[field.typeName];
1644
1409
  if (topLevel !== void 0) return topLevel;
@@ -1652,7 +1417,7 @@ function interpretRelationAttribute(input) {
1652
1417
  if (node === void 0) return void 0;
1653
1418
  return interpretFieldAttribute({
1654
1419
  node,
1655
- spec: sqlRelation,
1420
+ spec: sqlAttributeSpecs.field.relation(),
1656
1421
  model: input.selfModel,
1657
1422
  field: input.field,
1658
1423
  sourceFile: input.sourceFile,
@@ -1678,6 +1443,7 @@ function indexFkRelations(input) {
1678
1443
  toTable: relation.targetTableName,
1679
1444
  ...ifDefined("toNamespaceId", relation.targetNamespaceId),
1680
1445
  cardinality: "N:1",
1446
+ nullable: relation.nullable,
1681
1447
  on: {
1682
1448
  parentTable: relation.declaringTableName,
1683
1449
  parentColumns: relation.localColumns,
@@ -1853,6 +1619,7 @@ function applyBackrelationCandidates(input) {
1853
1619
  const pairMatches = input.fkRelationsByPair.get(pairKey) ?? [];
1854
1620
  const matches = candidate.relationName ? pairMatches.filter((relation) => relation.relationName === candidate.relationName) : [...pairMatches];
1855
1621
  if (matches.length === 0) {
1622
+ if (consumeInvalidFkPairing(candidate, pairKey, input.invalidFkPairings)) continue;
1856
1623
  if (candidate.isList) {
1857
1624
  const { pairs: junctionPairs, nearMisses } = findJunctionFkPairs({
1858
1625
  candidate,
@@ -1911,12 +1678,22 @@ function applyBackrelationCandidates(input) {
1911
1678
  continue;
1912
1679
  }
1913
1680
  }
1681
+ if (!candidate.isList && !candidate.field.optional) input.diagnostics.push(requiredOneToOneBackrelationDiagnostic({
1682
+ modelName: candidate.modelName,
1683
+ field: candidate.field,
1684
+ targetModelName: candidate.targetModelName,
1685
+ sourceId: input.sourceId,
1686
+ recordNoun: "row"
1687
+ }));
1914
1688
  relationsForModel(input.modelRelations, candidate.modelName).push({
1915
1689
  fieldName: candidate.field.name,
1916
1690
  toModel: matched.declaringModelName,
1917
1691
  toTable: matched.declaringTableName,
1918
1692
  ...ifDefined("toNamespaceId", matched.declaringNamespaceId),
1919
- cardinality: candidate.isList ? "1:N" : "1:1",
1693
+ ...candidate.isList ? { cardinality: "1:N" } : {
1694
+ cardinality: "1:1",
1695
+ nullable: true
1696
+ },
1920
1697
  on: {
1921
1698
  parentTable: candidate.tableName,
1922
1699
  parentColumns: matched.referencedColumns,
@@ -2283,6 +2060,22 @@ function composedBlockKeywords(authoringContributions) {
2283
2060
  function relationAttributeDeclaresOwningSide(relationAttribute) {
2284
2061
  return getNamedArgument(relationAttribute, "fields") !== void 0 || getNamedArgument(relationAttribute, "references") !== void 0;
2285
2062
  }
2063
+ function relationNullabilityMismatch(relationField, localColumns, resolvedFields) {
2064
+ return resolveToOneRelationNullable({
2065
+ declaredNullable: relationField.optional,
2066
+ localFieldNullability: resolvedFields.filter((resolvedField) => localColumns.includes(resolvedField.columnName)).map((resolvedField) => resolvedField.nullable),
2067
+ ownsReference: true
2068
+ }).contradiction !== void 0;
2069
+ }
2070
+ function relationNullabilityMismatchDiagnostic(modelName, relationAttribute, sourceId) {
2071
+ const fieldLabel = `Relation field "${modelName}.${relationAttribute.field.name}"`;
2072
+ return {
2073
+ code: "PSL_RELATION_NULLABILITY_MISMATCH",
2074
+ message: relationAttribute.field.optional ? `${fieldLabel} is optional but every field in @relation(fields: [...]) is required. Make one of those fields optional with "?" or remove "?" from "${relationAttribute.field.name}".` : `${fieldLabel} is required but a field in @relation(fields: [...]) is optional. Add "?" to "${relationAttribute.field.name}" or make those fields required.`,
2075
+ sourceId,
2076
+ span: relationAttribute.field.span
2077
+ };
2078
+ }
2286
2079
  function buildModelNodeFromPsl(input) {
2287
2080
  const { model, mapping, sourceId, diagnostics } = input;
2288
2081
  const tableName = mapping.tableName;
@@ -2290,6 +2083,7 @@ function buildModelNodeFromPsl(input) {
2290
2083
  const namespaceExtensionEntitiesForModel = modelNamespaceId !== void 0 ? input.namespaceExtensionEntities?.get(modelNamespaceId) : void 0;
2291
2084
  const resolvedFields = collectResolvedFields({
2292
2085
  model,
2086
+ symbolTable: input.symbolTable,
2293
2087
  mapping,
2294
2088
  enumTypeDescriptors: input.enumTypeDescriptors,
2295
2089
  namedTypeDescriptors: input.namedTypeDescriptors,
@@ -2398,6 +2192,30 @@ function buildModelNodeFromPsl(input) {
2398
2192
  const foreignKeyNodes = [];
2399
2193
  const modelAttributeNodes = Array.from(model.node.attributes());
2400
2194
  for (const [attributeIndex, modelAttribute] of model.attributes.entries()) {
2195
+ if (!Object.hasOwn(sqlAttributeSpecs.model, modelAttribute.name) && !input.modelAttributesByName.has(modelAttribute.name)) {
2196
+ const uncomposedNamespace = checkUncomposedNamespace(modelAttribute.name, input.composedExtensions, {
2197
+ familyId: input.familyId,
2198
+ targetId: input.targetId,
2199
+ authoringContributions: input.authoringContributions
2200
+ });
2201
+ if (uncomposedNamespace) {
2202
+ reportUncomposedNamespace({
2203
+ subjectLabel: `Attribute "@@${modelAttribute.name}"`,
2204
+ namespace: uncomposedNamespace,
2205
+ sourceId,
2206
+ span: modelAttribute.span,
2207
+ diagnostics
2208
+ });
2209
+ continue;
2210
+ }
2211
+ diagnostics.push({
2212
+ code: "PSL_UNSUPPORTED_MODEL_ATTRIBUTE",
2213
+ message: `Model "${model.name}" uses unsupported attribute "@@${modelAttribute.name}"`,
2214
+ sourceId,
2215
+ span: modelAttribute.span
2216
+ });
2217
+ continue;
2218
+ }
2401
2219
  if (modelAttribute.name === "map") continue;
2402
2220
  if (modelAttribute.name === "discriminator" || modelAttribute.name === "base") continue;
2403
2221
  if (modelAttribute.name === "control") {
@@ -2415,7 +2233,7 @@ function buildModelNodeFromPsl(input) {
2415
2233
  if (node === void 0) continue;
2416
2234
  const parsed = interpretModelAttribute({
2417
2235
  node,
2418
- spec: controlModelSpec,
2236
+ spec: sqlAttributeSpecs.model.control(),
2419
2237
  model,
2420
2238
  sourceFile: input.sourceFile,
2421
2239
  sourceId,
@@ -2449,7 +2267,7 @@ function buildModelNodeFromPsl(input) {
2449
2267
  if (node === void 0) continue;
2450
2268
  const parsed = interpretModelAttribute({
2451
2269
  node,
2452
- spec: idModelSpec,
2270
+ spec: sqlAttributeSpecs.model.id(),
2453
2271
  model,
2454
2272
  sourceFile: input.sourceFile,
2455
2273
  sourceId,
@@ -2489,7 +2307,7 @@ function buildModelNodeFromPsl(input) {
2489
2307
  if (node === void 0) continue;
2490
2308
  const parsed = interpretModelAttribute({
2491
2309
  node,
2492
- spec: uniqueModelSpec,
2310
+ spec: sqlAttributeSpecs.model.unique(),
2493
2311
  model,
2494
2312
  sourceFile: input.sourceFile,
2495
2313
  sourceId,
@@ -2517,7 +2335,7 @@ function buildModelNodeFromPsl(input) {
2517
2335
  if (node === void 0) continue;
2518
2336
  const parsed = interpretModelAttribute({
2519
2337
  node,
2520
- spec: indexModelSpec,
2338
+ spec: sqlAttributeSpecs.model.index(),
2521
2339
  model,
2522
2340
  sourceFile: input.sourceFile,
2523
2341
  sourceId,
@@ -2564,7 +2382,7 @@ function buildModelNodeFromPsl(input) {
2564
2382
  }
2565
2383
  const parsed = interpretModelAttribute({
2566
2384
  node,
2567
- spec: checkModelSpec,
2385
+ spec: sqlAttributeSpecs.model.check(),
2568
2386
  model,
2569
2387
  sourceFile: input.sourceFile,
2570
2388
  sourceId,
@@ -2594,7 +2412,11 @@ function buildModelNodeFromPsl(input) {
2594
2412
  if (node === void 0) continue;
2595
2413
  const parsed = interpretModelAttribute({
2596
2414
  node,
2597
- spec: blindCast(contributedModelAttribute.spec),
2415
+ spec: blindCast(contributedModelAttribute.spec)({
2416
+ symbols: input.symbolTable,
2417
+ model,
2418
+ controlMutationDefaults: input.defaultFunctionRegistry
2419
+ }),
2598
2420
  model,
2599
2421
  sourceFile: input.sourceFile,
2600
2422
  sourceId,
@@ -2618,29 +2440,10 @@ function buildModelNodeFromPsl(input) {
2618
2440
  slot[lowered.key] = lowered.entity;
2619
2441
  continue;
2620
2442
  }
2621
- const uncomposedNamespace = checkUncomposedNamespace(modelAttribute.name, input.composedExtensions, {
2622
- familyId: input.familyId,
2623
- targetId: input.targetId,
2624
- authoringContributions: input.authoringContributions
2625
- });
2626
- if (uncomposedNamespace) {
2627
- reportUncomposedNamespace({
2628
- subjectLabel: `Attribute "@@${modelAttribute.name}"`,
2629
- namespace: uncomposedNamespace,
2630
- sourceId,
2631
- span: modelAttribute.span,
2632
- diagnostics
2633
- });
2634
- continue;
2635
- }
2636
- diagnostics.push({
2637
- code: "PSL_UNSUPPORTED_MODEL_ATTRIBUTE",
2638
- message: `Model "${model.name}" uses unsupported attribute "@@${modelAttribute.name}"`,
2639
- sourceId,
2640
- span: modelAttribute.span
2641
- });
2443
+ throw new InternalError(`Model attribute "@@${modelAttribute.name}" is registered but has no interpreter branch`);
2642
2444
  }
2643
2445
  const resultFkRelationMetadata = [];
2446
+ const resultInvalidFkPairings = [];
2644
2447
  const resultCrossSpaceRelations = [];
2645
2448
  for (const relationAttribute of relationAttributes) {
2646
2449
  const { typeName: fieldTypeName, typeNamespaceId: fieldTypeNamespaceId, typeContractSpaceId: fieldTypeContractSpaceId } = relationAttribute.field;
@@ -2697,6 +2500,10 @@ function buildModelNodeFromPsl(input) {
2697
2500
  entityLabel: `Relation field "${model.name}.${relationAttribute.field.name}"`
2698
2501
  });
2699
2502
  if (!localColumns) continue;
2503
+ if (relationNullabilityMismatch(relationAttribute.field, localColumns, resolvedFields)) {
2504
+ diagnostics.push(relationNullabilityMismatchDiagnostic(model.name, relationAttribute, sourceId));
2505
+ continue;
2506
+ }
2700
2507
  const referencedColumns = parsedRelation.references;
2701
2508
  if (localColumns.length !== referencedColumns.length) {
2702
2509
  diagnostics.push({
@@ -2747,6 +2554,7 @@ function buildModelNodeFromPsl(input) {
2747
2554
  toModel: fieldTypeName,
2748
2555
  toTable: crossTargetTableName,
2749
2556
  cardinality: "N:1",
2557
+ nullable: relationAttribute.field.optional,
2750
2558
  spaceId: fieldTypeContractSpaceId,
2751
2559
  namespaceId: crossTargetNamespaceId,
2752
2560
  on: {
@@ -2816,6 +2624,14 @@ function buildModelNodeFromPsl(input) {
2816
2624
  entityLabel: `Relation field "${model.name}.${relationAttribute.field.name}"`
2817
2625
  });
2818
2626
  if (!localColumns) continue;
2627
+ if (relationNullabilityMismatch(relationAttribute.field, localColumns, resolvedFields)) {
2628
+ diagnostics.push(relationNullabilityMismatchDiagnostic(model.name, relationAttribute, sourceId));
2629
+ resultInvalidFkPairings.push({
2630
+ pairKey: fkRelationPairKey(model.name, targetMapping.model.name),
2631
+ ...ifDefined("relationName", parsedRelation.name)
2632
+ });
2633
+ continue;
2634
+ }
2819
2635
  const referencedColumns = mapFieldNamesToColumns({
2820
2636
  modelName: targetMapping.model.name,
2821
2637
  fieldNames: parsedRelation.references,
@@ -2860,6 +2676,7 @@ function buildModelNodeFromPsl(input) {
2860
2676
  targetTableName: targetMapping.tableName,
2861
2677
  ...ifDefined("targetNamespaceId", targetNamespaceId),
2862
2678
  ...ifDefined("relationName", parsedRelation.name),
2679
+ nullable: relationAttribute.field.optional,
2863
2680
  localColumns,
2864
2681
  referencedColumns
2865
2682
  });
@@ -2890,6 +2707,7 @@ function buildModelNodeFromPsl(input) {
2890
2707
  ...ifDefined("control", controlPolicy)
2891
2708
  },
2892
2709
  fkRelationMetadata: resultFkRelationMetadata,
2710
+ invalidFkPairings: resultInvalidFkPairings,
2893
2711
  crossSpaceRelations: resultCrossSpaceRelations,
2894
2712
  backrelationCandidates: resultBackrelationCandidates,
2895
2713
  resolvedFields,
@@ -3001,7 +2819,7 @@ function collectPolymorphismDeclarations(models, sourceFile, sourceId, diagnosti
3001
2819
  if (discriminatorNode !== void 0) {
3002
2820
  const parsed = interpretModelAttribute({
3003
2821
  node: discriminatorNode,
3004
- spec: discriminatorModelSpec,
2822
+ spec: sqlAttributeSpecs.model.discriminator(),
3005
2823
  model,
3006
2824
  sourceFile,
3007
2825
  sourceId,
@@ -3026,7 +2844,7 @@ function collectPolymorphismDeclarations(models, sourceFile, sourceId, diagnosti
3026
2844
  if (baseNode !== void 0) {
3027
2845
  const parsed = interpretModelAttribute({
3028
2846
  node: baseNode,
3029
- spec: baseModelSpec,
2847
+ spec: sqlAttributeSpecs.model.base(),
3030
2848
  model,
3031
2849
  sourceFile,
3032
2850
  sourceId,
@@ -3490,6 +3308,7 @@ function interpretPslDocumentToSqlContract(input) {
3490
3308
  for (const mapping of modelMappingsByCoordinate.values()) modelMappings.set(mapping.model.name, mapping);
3491
3309
  const modelNodes = [];
3492
3310
  const fkRelationMetadata = [];
3311
+ const invalidFkPairings = [];
3493
3312
  const backrelationCandidates = [];
3494
3313
  const modelResolvedFields = /* @__PURE__ */ new Map();
3495
3314
  const crossSpaceRelationsByModel = /* @__PURE__ */ new Map();
@@ -3532,6 +3351,7 @@ function interpretPslDocumentToSqlContract(input) {
3532
3351
  namespaceId
3533
3352
  } : result.modelNode);
3534
3353
  fkRelationMetadata.push(...result.fkRelationMetadata);
3354
+ invalidFkPairings.push(...result.invalidFkPairings);
3535
3355
  backrelationCandidates.push(...result.backrelationCandidates);
3536
3356
  modelResolvedFields.set(coordinate, result.resolvedFields);
3537
3357
  if (result.crossSpaceRelations.length > 0) {
@@ -3561,6 +3381,7 @@ function interpretPslDocumentToSqlContract(input) {
3561
3381
  applyBackrelationCandidates({
3562
3382
  backrelationCandidates,
3563
3383
  fkRelationsByPair,
3384
+ invalidFkPairings,
3564
3385
  fkRelationsByDeclaringModel,
3565
3386
  modelIdColumns,
3566
3387
  modelUniqueColumnSets,
@@ -3677,4 +3498,4 @@ function interpretPslDocumentToSqlContract(input) {
3677
3498
  //#endregion
3678
3499
  export { interpretPslDocumentToSqlContract as t };
3679
3500
 
3680
- //# sourceMappingURL=interpreter-DyiUUAWh-DYdjIpiE.mjs.map
3501
+ //# sourceMappingURL=interpreter-CZ_iVQV4-CJ6COgSE.mjs.map