@prisma/orm-family-sql 8.0.0-rc.2-dev.3 → 8.0.0-rc.20-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 (564) hide show
  1. package/README.md +2 -6
  2. package/dist/{aggregate-descriptor-registry-C7hel5O7.mjs → aggregate-descriptor-registry-ZrKjxwQe.mjs} +5 -5
  3. package/dist/aggregate-descriptor-registry-ZrKjxwQe.mjs.map +1 -0
  4. package/dist/ast-D0miQ1B6.mjs +372 -0
  5. package/dist/ast-D0miQ1B6.mjs.map +1 -0
  6. package/dist/ast-YEMe_B8z.d.mts +292 -0
  7. package/dist/ast-YEMe_B8z.d.mts.map +1 -0
  8. package/dist/attribute-specs-DA_RwQFB.d.mts +114 -0
  9. package/dist/attribute-specs-DA_RwQFB.d.mts.map +1 -0
  10. package/dist/{authored-check-naming-Hf9990DV.mjs → authored-check-naming-BHGJhjqn.mjs} +5 -5
  11. package/dist/authored-check-naming-BHGJhjqn.mjs.map +1 -0
  12. package/dist/{authored-check-naming-BWBe-PVE.d.mts → authored-check-naming-D-o196ry.d.mts} +3 -3
  13. package/dist/authored-check-naming-D-o196ry.d.mts.map +1 -0
  14. package/dist/authoring-entity-types-CgKIgWq5-pEdfjam5.d.mts +9 -0
  15. package/dist/authoring-entity-types-CgKIgWq5-pEdfjam5.d.mts.map +1 -0
  16. package/dist/builder.d.mts +4 -3
  17. package/dist/builder__runtime.d.mts +29 -31
  18. package/dist/builder__runtime.d.mts.map +1 -1
  19. package/dist/builder__runtime.mjs +261 -191
  20. package/dist/builder__runtime.mjs.map +1 -1
  21. package/dist/builder__types.d.mts +6 -3
  22. package/dist/{canonicalization-hooks-dmXkOR4a.mjs → canonicalization-hooks-Ce1v_TDl.mjs} +2 -2
  23. package/dist/canonicalization-hooks-Ce1v_TDl.mjs.map +1 -0
  24. package/dist/{canonicalization-hooks-CYnW_sGn.d.mts → canonicalization-hooks-DyapQ0my.d.mts} +2 -2
  25. package/dist/canonicalization-hooks-DyapQ0my.d.mts.map +1 -0
  26. package/dist/{check-constraint-B7qGu6rc-HvQjjX82.d.mts → check-constraint-B7qGu6rc-Bk2ezWXu.d.mts} +4 -4
  27. package/dist/check-constraint-B7qGu6rc-Bk2ezWXu.d.mts.map +1 -0
  28. package/dist/{codec-descriptor-registry-N0dhtKaH.mjs → codec-descriptor-registry-CiiFzMtb.mjs} +13 -40
  29. package/dist/codec-descriptor-registry-CiiFzMtb.mjs.map +1 -0
  30. package/dist/collection-methods-BB8YH69u.d.mts +1 -0
  31. package/dist/collection-methods-D2UnCS0S-DOy2qHYS.d.mts +77 -0
  32. package/dist/collection-methods-D2UnCS0S-DOy2qHYS.d.mts.map +1 -0
  33. package/dist/{config-types-D9fdKG3g.d.mts → config-types-C-1mIiJO.d.mts} +5 -5
  34. package/dist/config-types-C-1mIiJO.d.mts.map +1 -0
  35. package/dist/{config-types-gAm54C_v.mjs → config-types-DkEeq_qq.mjs} +10 -6
  36. package/dist/config-types-DkEeq_qq.mjs.map +1 -0
  37. package/dist/{contract-builder-D4a5dT7j.mjs → contract-builder-50lF0kz1.mjs} +431 -226
  38. package/dist/contract-builder-50lF0kz1.mjs.map +1 -0
  39. package/dist/contract-builder-C_Zi57iD.d.mts +1967 -0
  40. package/dist/contract-builder-C_Zi57iD.d.mts.map +1 -0
  41. package/dist/contract-emitter.d.mts +4 -7
  42. package/dist/contract-emitter.d.mts.map +1 -1
  43. package/dist/contract-emitter.mjs +1 -1
  44. package/dist/{contract-errors-BCN6RVI5-5IHBF_lg.mjs → contract-errors-BCN6RVI5-DoH6b_KZ.mjs} +2 -2
  45. package/dist/contract-errors-BCN6RVI5-DoH6b_KZ.mjs.map +1 -0
  46. package/dist/contract-prisma7__provider.d.mts +97 -0
  47. package/dist/contract-prisma7__provider.d.mts.map +1 -0
  48. package/dist/contract-prisma7__provider.mjs +2011 -0
  49. package/dist/contract-prisma7__provider.mjs.map +1 -0
  50. package/dist/contract-psl.d.mts +18 -29
  51. package/dist/contract-psl.d.mts.map +1 -1
  52. package/dist/contract-psl.mjs +1 -1
  53. package/dist/contract-psl__attribute-specs.d.mts +2 -0
  54. package/dist/contract-psl__attribute-specs.mjs +2 -0
  55. package/dist/contract-psl__default-table-name.d.mts +7 -0
  56. package/dist/contract-psl__default-table-name.d.mts.map +1 -0
  57. package/dist/contract-psl__default-table-name.mjs +2 -0
  58. package/dist/contract-psl__diagnostics.d.mts +12 -0
  59. package/dist/contract-psl__diagnostics.d.mts.map +1 -0
  60. package/dist/contract-psl__diagnostics.mjs +2 -0
  61. package/dist/contract-psl__map-names.d.mts +16 -0
  62. package/dist/contract-psl__map-names.d.mts.map +1 -0
  63. package/dist/contract-psl__map-names.mjs +21 -0
  64. package/dist/contract-psl__map-names.mjs.map +1 -0
  65. package/dist/contract-psl__provider.d.mts +3 -3
  66. package/dist/contract-psl__provider.d.mts.map +1 -1
  67. package/dist/contract-psl__provider.mjs +95 -46
  68. package/dist/contract-psl__provider.mjs.map +1 -1
  69. package/dist/contract-ts.d.mts +5 -5
  70. package/dist/contract-ts.mjs +5 -4
  71. package/dist/contract-ts__config-types.d.mts +1 -1
  72. package/dist/contract-ts__config-types.mjs +1 -1
  73. package/dist/contract-ts__contract-builder.d.mts +4 -4
  74. package/dist/contract-ts__contract-builder.mjs +4 -3
  75. package/dist/{contract-view-BMR5IWk4.mjs → contract-view-DqpzeYeE.mjs} +2 -2
  76. package/dist/contract-view-DqpzeYeE.mjs.map +1 -0
  77. package/dist/{contract-view-CPHxoAEX.d.mts → contract-view-DuB35or0.d.mts} +3 -3
  78. package/dist/contract-view-DuB35or0.d.mts.map +1 -0
  79. package/dist/contract.d.mts +30 -28
  80. package/dist/contract.mjs +23 -18
  81. package/dist/contract__authored-check-naming.d.mts +1 -1
  82. package/dist/contract__authored-check-naming.mjs +1 -1
  83. package/dist/contract__canonicalization-hooks.d.mts +1 -1
  84. package/dist/contract__canonicalization-hooks.mjs +1 -1
  85. package/dist/contract__contract-view.d.mts +1 -1
  86. package/dist/contract__contract-view.mjs +1 -1
  87. package/dist/contract__data-type-support.d.mts +2 -0
  88. package/dist/contract__data-type-support.mjs +2 -0
  89. package/dist/contract__data-type.d.mts +2 -0
  90. package/dist/contract__data-type.mjs +3 -0
  91. package/dist/contract__entity-handle-lowering-hook.d.mts +2 -2
  92. package/dist/contract__entity-handle-lowering-hook.mjs +2 -2
  93. package/dist/contract__entity-kinds.d.mts +1 -1
  94. package/dist/contract__entity-kinds.mjs +1 -1
  95. package/dist/contract__factories.d.mts +1 -1
  96. package/dist/contract__factories.mjs +1 -1
  97. package/dist/contract__foreign-key-materialization.d.mts +2 -2
  98. package/dist/contract__foreign-key-materialization.mjs +3 -2
  99. package/dist/contract__index-naming.d.mts +2 -2
  100. package/dist/contract__index-naming.mjs +2 -2
  101. package/dist/contract__index-type-validation.d.mts +2 -2
  102. package/dist/contract__index-type-validation.mjs +1 -1
  103. package/dist/contract__index-types.d.mts +3 -3
  104. package/dist/contract__index-types.mjs +2 -2
  105. package/dist/contract__referential-action-sql.d.mts +1 -1
  106. package/dist/contract__referential-action-sql.mjs +1 -1
  107. package/dist/contract__resolve-storage-table.d.mts +1 -1
  108. package/dist/contract__resolve-storage-table.mjs +1 -1
  109. package/dist/contract__sql-expression.d.mts +2 -0
  110. package/dist/contract__sql-expression.mjs +2 -0
  111. package/dist/contract__types.d.mts +12 -12
  112. package/dist/contract__types.mjs +4 -4
  113. package/dist/contract__validators.d.mts +2 -2
  114. package/dist/contract__validators.mjs +3 -3
  115. package/dist/contract__value-set-derivation-hook.d.mts +1 -1
  116. package/dist/contract__value-set-derivation-hook.mjs +1 -1
  117. package/dist/control-BK50zF6c.mjs +2721 -0
  118. package/dist/control-BK50zF6c.mjs.map +1 -0
  119. package/dist/control-ChAUdOOu.d.mts +1416 -0
  120. package/dist/control-ChAUdOOu.d.mts.map +1 -0
  121. package/dist/{control-adapter-C99J7aEF-B7eQd7vD.d.mts → control-adapter-Bn0uhplA-BzP2uPqJ.d.mts} +27 -44
  122. package/dist/control-adapter-Bn0uhplA-BzP2uPqJ.d.mts.map +1 -0
  123. package/dist/control-adapter-NZ2kKc4x.d.mts +13 -0
  124. package/dist/control-adapter-NZ2kKc4x.d.mts.map +1 -0
  125. package/dist/control-adapter-SlQkTEwT.mjs +16 -0
  126. package/dist/control-adapter-SlQkTEwT.mjs.map +1 -0
  127. package/dist/data-type-BFSpaotu.mjs +52 -0
  128. package/dist/data-type-BFSpaotu.mjs.map +1 -0
  129. package/dist/data-type-DJIvKQHf.d.mts +158 -0
  130. package/dist/data-type-DJIvKQHf.d.mts.map +1 -0
  131. package/dist/data-type-support-BhSoPUFj.mjs +9 -0
  132. package/dist/data-type-support-BhSoPUFj.mjs.map +1 -0
  133. package/dist/data-type-support-CXpA0ex-.d.mts +7 -0
  134. package/dist/data-type-support-CXpA0ex-.d.mts.map +1 -0
  135. package/dist/{db-D18PrXKW-DvTv4JFn.d.mts → db-D1d75IvM-D4mRDC6w.d.mts} +123 -128
  136. package/dist/db-D1d75IvM-D4mRDC6w.d.mts.map +1 -0
  137. package/dist/{ddl-types-CXx4vPz6-BsgrnSUY.d.mts → ddl-types-By5mT2_S-CdaaFvsX.d.mts} +24 -29
  138. package/dist/ddl-types-By5mT2_S-CdaaFvsX.d.mts.map +1 -0
  139. package/dist/default-mapping-CAOONlKQ-4m07nb-O.d.mts +39 -0
  140. package/dist/default-mapping-CAOONlKQ-4m07nb-O.d.mts.map +1 -0
  141. package/dist/default-table-name-BfFY8qYR-CWZFDX6v.mjs +9 -0
  142. package/dist/default-table-name-BfFY8qYR-CWZFDX6v.mjs.map +1 -0
  143. package/dist/derived-checks-D5HVRvqN-BJx1gwPA.mjs +1508 -0
  144. package/dist/derived-checks-D5HVRvqN-BJx1gwPA.mjs.map +1 -0
  145. package/dist/{derived-checks-DPdD01O0-DGqOFjs6.d.mts → derived-checks-DpPkO6Dt-9U9UJZOo.d.mts} +4 -4
  146. package/dist/derived-checks-DpPkO6Dt-9U9UJZOo.d.mts.map +1 -0
  147. package/dist/diagnostics-RHJxoiIk.mjs +23 -0
  148. package/dist/diagnostics-RHJxoiIk.mjs.map +1 -0
  149. package/dist/{diff-DbTNVm2f.d.mts → diff-1qHOLoUB.d.mts} +23 -10
  150. package/dist/diff-1qHOLoUB.d.mts.map +1 -0
  151. package/dist/diff-C1rFOhek.mjs +21 -0
  152. package/dist/diff-C1rFOhek.mjs.map +1 -0
  153. package/dist/{dist-ZK6oeI5e.mjs → dist-C8Y-PPuE.mjs} +36 -212
  154. package/dist/dist-C8Y-PPuE.mjs.map +1 -0
  155. package/dist/{dist-C_q1_QR9.mjs → dist-CHz1hF8M.mjs} +2 -2
  156. package/dist/dist-CHz1hF8M.mjs.map +1 -0
  157. package/dist/{dist-x6jvtkKM.mjs → dist-CMDXybwm.mjs} +2 -2
  158. package/dist/dist-CMDXybwm.mjs.map +1 -0
  159. package/dist/{driver-types-BQtRkOJ0-Bv2RPSfr.d.mts → driver-types-DRsYeq3j-BimeCnUk.d.mts} +11 -2
  160. package/dist/driver-types-DRsYeq3j-BimeCnUk.d.mts.map +1 -0
  161. package/dist/entity-handle-lowering-hook-BJZSlVVF.mjs +16 -0
  162. package/dist/entity-handle-lowering-hook-BJZSlVVF.mjs.map +1 -0
  163. package/dist/{entity-handle-lowering-hook-CIvRKBfa.d.mts → entity-handle-lowering-hook-BuvLtgFi.d.mts} +8 -11
  164. package/dist/entity-handle-lowering-hook-BuvLtgFi.d.mts.map +1 -0
  165. package/dist/{entity-kinds-B5cUFU22.d.mts → entity-kinds-BPG2xCZV.d.mts} +7 -7
  166. package/dist/entity-kinds-BPG2xCZV.d.mts.map +1 -0
  167. package/dist/{entity-kinds-D7vwoN_T-CCBwFJy0.mjs → entity-kinds-JR5SAm5h-DOH6VUtL.mjs} +31 -28
  168. package/dist/entity-kinds-JR5SAm5h-DOH6VUtL.mjs.map +1 -0
  169. package/dist/{errors-B5g0xWro-mWH2C07F.mjs → errors-B5g0xWro-C8plbqga.mjs} +2 -2
  170. package/dist/errors-B5g0xWro-C8plbqga.mjs.map +1 -0
  171. package/dist/errors.d.mts +1 -1
  172. package/dist/errors.d.mts.map +1 -1
  173. package/dist/errors.mjs +1 -1
  174. package/dist/exports-C3wGYtID-D65DEUTC.mjs +2389 -0
  175. package/dist/exports-C3wGYtID-D65DEUTC.mjs.map +1 -0
  176. package/dist/{expression-FJK6Ar-d.d.mts → expression-6ld_ZQL6-fOuazzzm.d.mts} +37 -16
  177. package/dist/expression-6ld_ZQL6-fOuazzzm.d.mts.map +1 -0
  178. package/dist/expression-CieaNuRM-B1uVqxwd.d.mts +22 -0
  179. package/dist/expression-CieaNuRM-B1uVqxwd.d.mts.map +1 -0
  180. package/dist/expression-D8HstQiB.d.mts +2 -0
  181. package/dist/{expression-CX5mTA-z.mjs → expression-impl-B-XNINxr-BhN2sysZ.mjs} +41 -18
  182. package/dist/expression-impl-B-XNINxr-BhN2sysZ.mjs.map +1 -0
  183. package/dist/{factories-SVor5xIT.mjs → factories-Crobuxwn.mjs} +27 -20
  184. package/dist/factories-Crobuxwn.mjs.map +1 -0
  185. package/dist/{factories-P3qBQhO-.d.mts → factories-DbNP9qfs.d.mts} +16 -10
  186. package/dist/factories-DbNP9qfs.d.mts.map +1 -0
  187. package/dist/family.d.mts +17 -13
  188. package/dist/family.mjs +17 -12
  189. package/dist/family__control-adapter.d.mts +3 -3
  190. package/dist/family__control-adapter.mjs +2 -1
  191. package/dist/family__control.d.mts +5 -4
  192. package/dist/family__control.mjs +4 -4
  193. package/dist/family__diff.d.mts +2 -3
  194. package/dist/family__diff.mjs +2 -2
  195. package/dist/family__ir.d.mts +1 -1
  196. package/dist/family__ir.mjs +2 -2
  197. package/dist/family__migration.d.mts +1 -1
  198. package/dist/family__migration.mjs +1 -1
  199. package/dist/family__pack.d.mts +2 -249
  200. package/dist/family__pack.mjs +3 -18
  201. package/dist/family__psl-build.d.mts +3 -0
  202. package/dist/family__psl-build.mjs +3 -0
  203. package/dist/family__psl-infer.d.mts +2 -2
  204. package/dist/family__psl-infer.mjs +2 -2
  205. package/dist/family__runtime.d.mts +2 -2
  206. package/dist/family__runtime.mjs +2 -2
  207. package/dist/family__verify.d.mts +1 -1
  208. package/dist/family__verify.mjs +1 -1
  209. package/dist/foreign-key-materialization-48P2V8on.d.mts +98 -0
  210. package/dist/foreign-key-materialization-48P2V8on.d.mts.map +1 -0
  211. package/dist/foreign-key-materialization-BM59w_Xg.mjs +287 -0
  212. package/dist/foreign-key-materialization-BM59w_Xg.mjs.map +1 -0
  213. package/dist/{foreign-key-C-iTPuRT-C9ip8zFx.d.mts → foreign-key-qkDFfG8t-TaK_GYWR.d.mts} +21 -5
  214. package/dist/foreign-key-qkDFfG8t-TaK_GYWR.d.mts.map +1 -0
  215. package/dist/functions-CsOoN7I3.mjs +88 -0
  216. package/dist/functions-CsOoN7I3.mjs.map +1 -0
  217. package/dist/functions-EW-RrRn3.d.mts +73 -0
  218. package/dist/functions-EW-RrRn3.d.mts.map +1 -0
  219. package/dist/generator-functions-D_qdqBV--Bq296cED.mjs +544 -0
  220. package/dist/generator-functions-D_qdqBV--Bq296cED.mjs.map +1 -0
  221. package/dist/index-7nHHQsAj.d.mts +606 -0
  222. package/dist/index-7nHHQsAj.d.mts.map +1 -0
  223. package/dist/{index-C5I8D-MB.d.mts → index-Nqc3OHR_.d.mts} +4 -5
  224. package/dist/index-Nqc3OHR_.d.mts.map +1 -0
  225. package/dist/index-equivalence-DswCiq5l-CGsyPP9B.mjs +109 -0
  226. package/dist/index-equivalence-DswCiq5l-CGsyPP9B.mjs.map +1 -0
  227. package/dist/{index-naming-DREt6js7-CRH27yUv.mjs → index-naming-BOcJT1B3-mG8Fd6KN.mjs} +35 -9
  228. package/dist/index-naming-BOcJT1B3-mG8Fd6KN.mjs.map +1 -0
  229. package/dist/{index-naming-Ct65z5Xk.d.mts → index-naming-Cs6wwia3.d.mts} +15 -5
  230. package/dist/index-naming-Cs6wwia3.d.mts.map +1 -0
  231. package/dist/index-reference-4wsdeB7v-DCwswK-q.d.mts +67 -0
  232. package/dist/index-reference-4wsdeB7v-DCwswK-q.d.mts.map +1 -0
  233. package/dist/index-reference-BQSrkRfT.mjs +55 -0
  234. package/dist/index-reference-BQSrkRfT.mjs.map +1 -0
  235. package/dist/index-reference-D8ewQRJr.d.mts +1 -0
  236. package/dist/index-type-validation-DJEMmmw0.mjs +42 -0
  237. package/dist/index-type-validation-DJEMmmw0.mjs.map +1 -0
  238. package/dist/index-type-validation-fGGwAHWc.d.mts +16 -0
  239. package/dist/index-type-validation-fGGwAHWc.d.mts.map +1 -0
  240. package/dist/index-types-H1O43iYT-BD0VwPqV.d.mts +66 -0
  241. package/dist/index-types-H1O43iYT-BD0VwPqV.d.mts.map +1 -0
  242. package/dist/index-types-pC_5vADQ-BOOBi14R.mjs +95 -0
  243. package/dist/index-types-pC_5vADQ-BOOBi14R.mjs.map +1 -0
  244. package/dist/index-types-snhtt_Fo.d.mts +1 -0
  245. package/dist/interpreter-D5qk4B---CG0C7kdx.mjs +2280 -0
  246. package/dist/interpreter-D5qk4B---CG0C7kdx.mjs.map +1 -0
  247. package/dist/{ir-Bghjt-FG.d.mts → ir-BvptQsFW.d.mts} +11 -5
  248. package/dist/ir-BvptQsFW.d.mts.map +1 -0
  249. package/dist/{ir-I-xciGUH.mjs → ir-DzsUDO8e.mjs} +2 -2
  250. package/dist/ir-DzsUDO8e.mjs.map +1 -0
  251. package/dist/{middleware-AhTz1BOW-th-Suxuf.d.mts → middleware-DHkW6pRr-DM6hd9iZ.d.mts} +5 -5
  252. package/dist/middleware-DHkW6pRr-DM6hd9iZ.d.mts.map +1 -0
  253. package/dist/middleware-gqy3l13N.d.mts +1 -0
  254. package/dist/{middleware-CMr4CHNz-DHIUdxlm.mjs → middleware-yBAfiVWn-DZO0vCRQ.mjs} +3 -3
  255. package/dist/middleware-yBAfiVWn-DZO0vCRQ.mjs.map +1 -0
  256. package/dist/{migration-CK4oePIo.mjs → migration-BJQjkqFz.mjs} +4 -4
  257. package/dist/migration-BJQjkqFz.mjs.map +1 -0
  258. package/dist/{migration-CjDRZNep.d.mts → migration-Cxmpzaz0.d.mts} +6 -6
  259. package/dist/migration-Cxmpzaz0.d.mts.map +1 -0
  260. package/dist/{naming-CV9j2pXl-KARaDReS.d.mts → naming-BcD36g9T-Mfe_xGGL.d.mts} +9 -14
  261. package/dist/naming-BcD36g9T-Mfe_xGGL.d.mts.map +1 -0
  262. package/dist/{naming-DKr4TJd7-Cszhq9RV.mjs → naming-bM5qm5PY-jOg3JFMb.mjs} +20 -31
  263. package/dist/naming-bM5qm5PY-jOg3JFMb.mjs.map +1 -0
  264. package/dist/{ddl-types-BGdnAbXo-DKPHPUGx.mjs → opaque-sql-Dset3kln-CtsPDTXn.mjs} +24 -11
  265. package/dist/opaque-sql-Dset3kln-CtsPDTXn.mjs.map +1 -0
  266. package/dist/operations.d.mts +1 -1
  267. package/dist/operations.mjs +1 -1
  268. package/dist/orm-client.d.mts +817 -267
  269. package/dist/orm-client.d.mts.map +1 -1
  270. package/dist/orm-client.mjs +4719 -2942
  271. package/dist/orm-client.mjs.map +1 -1
  272. package/dist/pack-DA8HZ2mo.d.mts +535 -0
  273. package/dist/pack-DA8HZ2mo.d.mts.map +1 -0
  274. package/dist/pack-gSvGQWqs.mjs +80 -0
  275. package/dist/pack-gSvGQWqs.mjs.map +1 -0
  276. package/dist/{plan-CDxduYaN-pLIyyJaB.d.mts → plan-Cr4azjnG-CuL8FqXC.d.mts} +12 -8
  277. package/dist/plan-Cr4azjnG-CuL8FqXC.d.mts.map +1 -0
  278. package/dist/{plan-Dh0LbYIv-Crx5-ThG.mjs → plan-Dh0LbYIv-ubBSdUgl.mjs} +2 -2
  279. package/dist/plan-Dh0LbYIv-ubBSdUgl.mjs.map +1 -0
  280. package/dist/plan-Di6Gs2JD.d.mts +2 -0
  281. package/dist/psl-attribute-parsing-BCsFWsSp-BJ-wGlY6.mjs +42 -0
  282. package/dist/psl-attribute-parsing-BCsFWsSp-BJ-wGlY6.mjs.map +1 -0
  283. package/dist/psl-build-DFBG6vhz.mjs +426 -0
  284. package/dist/psl-build-DFBG6vhz.mjs.map +1 -0
  285. package/dist/psl-build-RelubU2E.d.mts +112 -0
  286. package/dist/psl-build-RelubU2E.d.mts.map +1 -0
  287. package/dist/psl-column-resolution-ChZqioOc-BREg4J7d.d.mts +24 -0
  288. package/dist/psl-column-resolution-ChZqioOc-BREg4J7d.d.mts.map +1 -0
  289. package/dist/psl-field-resolution-C5KQ7kzP-B0NwuRWV.mjs +1960 -0
  290. package/dist/psl-field-resolution-C5KQ7kzP-B0NwuRWV.mjs.map +1 -0
  291. package/dist/psl-infer--g4i84Go.mjs +201 -0
  292. package/dist/psl-infer--g4i84Go.mjs.map +1 -0
  293. package/dist/psl-infer-DzoxPZGd.d.mts +80 -0
  294. package/dist/psl-infer-DzoxPZGd.d.mts.map +1 -0
  295. package/dist/psl-names-C3cwe0rg-D1CTmC3a.mjs +66 -0
  296. package/dist/psl-names-C3cwe0rg-D1CTmC3a.mjs.map +1 -0
  297. package/dist/{query-lane-context-Qa-eddrE-kuZ8Z86-.d.mts → query-lane-context-BCEoKy0_-CzmyavC9.d.mts} +20 -49
  298. package/dist/query-lane-context-BCEoKy0_-CzmyavC9.d.mts.map +1 -0
  299. package/dist/query-lane-context-VqH0mS9B.d.mts +1 -0
  300. package/dist/{referential-action-sql-DJ9ps6-S.d.mts → referential-action-sql-B2vKoUK6.d.mts} +3 -3
  301. package/dist/referential-action-sql-B2vKoUK6.d.mts.map +1 -0
  302. package/dist/{referential-action-sql-DSqkrySN.mjs → referential-action-sql-BLzCtTi8.mjs} +2 -2
  303. package/dist/referential-action-sql-BLzCtTi8.mjs.map +1 -0
  304. package/dist/relational-core.d.mts +14 -13
  305. package/dist/relational-core.mjs +8 -8
  306. package/dist/relational-core__aggregate-descriptor-registry.d.mts +2 -2
  307. package/dist/relational-core__aggregate-descriptor-registry.d.mts.map +1 -1
  308. package/dist/relational-core__aggregate-descriptor-registry.mjs +1 -1
  309. package/dist/relational-core__ast.d.mts +5 -5
  310. package/dist/relational-core__ast.mjs +5 -5
  311. package/dist/relational-core__codec-descriptor-registry.d.mts +7 -8
  312. package/dist/relational-core__codec-descriptor-registry.d.mts.map +1 -1
  313. package/dist/relational-core__codec-descriptor-registry.mjs +1 -1
  314. package/dist/relational-core__collection-methods.d.mts +3 -0
  315. package/dist/relational-core__contract-free.d.mts +18 -8
  316. package/dist/relational-core__contract-free.d.mts.map +1 -1
  317. package/dist/relational-core__contract-free.mjs +26 -10
  318. package/dist/relational-core__contract-free.mjs.map +1 -1
  319. package/dist/relational-core__expression.d.mts +4 -2
  320. package/dist/relational-core__expression.mjs +2 -2
  321. package/dist/relational-core__functions.d.mts +2 -0
  322. package/dist/relational-core__functions.mjs +2 -0
  323. package/dist/relational-core__index-reference.d.mts +3 -0
  324. package/dist/relational-core__index-reference.mjs +2 -0
  325. package/dist/relational-core__middleware.d.mts +2 -2
  326. package/dist/relational-core__middleware.mjs +1 -1
  327. package/dist/relational-core__plan.d.mts +4 -4
  328. package/dist/relational-core__plan.mjs +1 -1
  329. package/dist/relational-core__query-lane-context.d.mts +3 -3
  330. package/dist/relational-core__types.d.mts +2 -2
  331. package/dist/{resolve-storage-table-DZsfnzeW.mjs → resolve-storage-table-BHLQsOza.mjs} +3 -3
  332. package/dist/resolve-storage-table-BHLQsOza.mjs.map +1 -0
  333. package/dist/{resolve-storage-table-Nyrgk4h8.d.mts → resolve-storage-table-DCqtmnSU.d.mts} +4 -4
  334. package/dist/resolve-storage-table-DCqtmnSU.d.mts.map +1 -0
  335. package/dist/{runtime-tIHpGCcG.mjs → runtime-6tH1yOxK.mjs} +6 -6
  336. package/dist/runtime-6tH1yOxK.mjs.map +1 -0
  337. package/dist/{runtime-DpKF2Yu2.d.mts → runtime-CF6rAlE5.d.mts} +7 -8
  338. package/dist/runtime-CF6rAlE5.d.mts.map +1 -0
  339. package/dist/runtime.d.mts +5 -5
  340. package/dist/runtime.mjs +2 -1799
  341. package/dist/runtime__internal__prepared-query.d.mts +2 -2
  342. package/dist/runtime__internal__prepared-query.mjs +2 -2
  343. package/dist/{schema-differ-DpG_gnur-DFAtGezx.d.mts → schema-differ-DmP74bB8-tqHKiJ88.d.mts} +6 -6
  344. package/dist/schema-differ-DmP74bB8-tqHKiJ88.d.mts.map +1 -0
  345. package/dist/schema-ir.d.mts +2 -2
  346. package/dist/schema-ir.mjs +2 -2
  347. package/dist/schema-ir__naming.d.mts +1 -1
  348. package/dist/schema-ir__naming.mjs +1 -1
  349. package/dist/schema-ir__types.d.mts +3 -3
  350. package/dist/schema-ir__types.mjs +2 -2
  351. package/dist/{schema-verify-C_PEdlAr-Dxxjm6EM.mjs → schema-verify-C3wbdviw-DMjIubOr.mjs} +50 -8
  352. package/dist/schema-verify-C3wbdviw-DMjIubOr.mjs.map +1 -0
  353. package/dist/{serialized-index-CrgG8ct1-DG3JpHc7.d.mts → serialized-index-CrgG8ct1-DKVJ7TDX.d.mts} +4 -4
  354. package/dist/serialized-index-CrgG8ct1-DKVJ7TDX.d.mts.map +1 -0
  355. package/dist/{serialized-index-nBTwanKy-_ddEK4tk.mjs → serialized-index-DjCCnXB1-DMA7BtO2.mjs} +4 -4
  356. package/dist/serialized-index-DjCCnXB1-DMA7BtO2.mjs.map +1 -0
  357. package/dist/{sql-contract-serializer-2oBWuxTe-DKZTf2n8.mjs → sql-contract-serializer-sMY3prTx-D2BfrNxs.mjs} +41 -16
  358. package/dist/sql-contract-serializer-sMY3prTx-D2BfrNxs.mjs.map +1 -0
  359. package/dist/sql-data-type-D7M-YTTY-D2vRqDxn.mjs +400 -0
  360. package/dist/sql-data-type-D7M-YTTY-D2vRqDxn.mjs.map +1 -0
  361. package/dist/{sql-execution-plan--jKyLpe5-CMGhgO0M.d.mts → sql-execution-plan-3uxYjHyu-DLknM-Pj.d.mts} +3 -3
  362. package/dist/sql-execution-plan-3uxYjHyu-DLknM-Pj.d.mts.map +1 -0
  363. package/dist/sql-expression-B4BrhGPi.d.mts +62 -0
  364. package/dist/sql-expression-B4BrhGPi.d.mts.map +1 -0
  365. package/dist/sql-expression-CKgKznXS.mjs +137 -0
  366. package/dist/sql-expression-CKgKznXS.mjs.map +1 -0
  367. package/dist/{sql-index-ByAAE7K8-DKj2V86p.d.mts → sql-index-ByAAE7K8-Dqtn_vUL.d.mts} +4 -4
  368. package/dist/sql-index-ByAAE7K8-Dqtn_vUL.d.mts.map +1 -0
  369. package/dist/{sql-node-kEz6YFZo-v2F7delx.d.mts → sql-node-kEz6YFZo-1ogT6Cxt.d.mts} +2 -2
  370. package/dist/sql-node-kEz6YFZo-1ogT6Cxt.d.mts.map +1 -0
  371. package/dist/{sql-storage-8LqxeLAY-DH4DdUXx.d.mts → sql-storage-DeCAh5Hi-CEM-m8cs.d.mts} +19 -22
  372. package/dist/sql-storage-DeCAh5Hi-CEM-m8cs.d.mts.map +1 -0
  373. package/dist/{storage-table-DSeWszOL-CI-cItEK.d.mts → storage-table-Bf1ZjnxO-pUj6pyP0.d.mts} +17 -24
  374. package/dist/storage-table-Bf1ZjnxO-pUj6pyP0.d.mts.map +1 -0
  375. package/dist/{storage-table-ZzbR-xzQ-BRoTQE_2.mjs → storage-table-DDvN83mw-DkbBFmK9.mjs} +12 -9
  376. package/dist/storage-table-DDvN83mw-DkbBFmK9.mjs.map +1 -0
  377. package/dist/{storage-value-set-BGlj5Uus-CvZD--GG.d.mts → storage-value-set-BGlj5Uus-ny2k-0PA.d.mts} +3 -3
  378. package/dist/storage-value-set-BGlj5Uus-ny2k-0PA.d.mts.map +1 -0
  379. package/dist/transaction-state-BfXhs7D7-DhmbySW9.mjs +45 -0
  380. package/dist/transaction-state-BfXhs7D7-DhmbySW9.mjs.map +1 -0
  381. package/dist/transaction-state-DR3nKTmH-D29jmVE-.d.mts +115 -0
  382. package/dist/transaction-state-DR3nKTmH-D29jmVE-.d.mts.map +1 -0
  383. package/dist/types-B9wSEUsV.d.mts +1 -0
  384. package/dist/{types-CUsJrvEl.mjs → types-CTdSkl0s.mjs} +13 -6
  385. package/dist/types-CTdSkl0s.mjs.map +1 -0
  386. package/dist/types-CkAd8SWm.d.mts +57 -0
  387. package/dist/types-CkAd8SWm.d.mts.map +1 -0
  388. package/dist/{types-IqZMLrFC-DcH8v_u3.d.mts → types-Cq6ImLAB-RlU4jJAX.d.mts} +27 -41
  389. package/dist/types-Cq6ImLAB-RlU4jJAX.d.mts.map +1 -0
  390. package/dist/{types-YStFFkKs-D9UAmnON.d.mts → types-CuCxAQat-Dz8P4xyt.d.mts} +141 -86
  391. package/dist/types-CuCxAQat-Dz8P4xyt.d.mts.map +1 -0
  392. package/dist/types-DfKvtJwS-CrpWTGBJ.d.mts +273 -0
  393. package/dist/types-DfKvtJwS-CrpWTGBJ.d.mts.map +1 -0
  394. package/dist/{types-4YenawkP-CwaaZSid.mjs → types-DoyiTsjg-2YMhMJDA.mjs} +181 -80
  395. package/dist/types-DoyiTsjg-2YMhMJDA.mjs.map +1 -0
  396. package/dist/{types-v3qxLLxo-DCeKv7yY.d.mts → types-DriMIMNQ-BkbsW7w3.d.mts} +68 -34
  397. package/dist/types-DriMIMNQ-BkbsW7w3.d.mts.map +1 -0
  398. package/dist/{types-Dt4e_jC--COeP8xzN.mjs → types-NTQsD2MS-xcLtvKO9.mjs} +83 -17
  399. package/dist/types-NTQsD2MS-xcLtvKO9.mjs.map +1 -0
  400. package/dist/{types-CyxGtOOh-BggSa6Fe.d.mts → types-TXO7x1BA-CYYIY8NI.d.mts} +14 -14
  401. package/dist/types-TXO7x1BA-CYYIY8NI.d.mts.map +1 -0
  402. package/dist/types-ljUNyiWe.d.mts +1 -0
  403. package/dist/{unique-constraint-M5TlQnJQ-BiIHJ85k.d.mts → unique-constraint-M5TlQnJQ-qX-maNUV.d.mts} +3 -3
  404. package/dist/unique-constraint-M5TlQnJQ-qX-maNUV.d.mts.map +1 -0
  405. package/dist/{util-DQQgv2j1-D6INZaRG.mjs → util-BBgcP3gI-CpL-0VuC.mjs} +12 -3
  406. package/dist/util-BBgcP3gI-CpL-0VuC.mjs.map +1 -0
  407. package/dist/{validators-CrWD6bSP.mjs → validators-BwA7ttZM.mjs} +0 -0
  408. package/dist/validators-BwA7ttZM.mjs.map +1 -0
  409. package/dist/{validators-Belo8QqM.d.mts → validators-FJs8HvFr.d.mts} +54 -16
  410. package/dist/validators-FJs8HvFr.d.mts.map +1 -0
  411. package/dist/{value-set-derivation-hook-BhgGVtw0.d.mts → value-set-derivation-hook-3E437jPU.d.mts} +3 -3
  412. package/dist/value-set-derivation-hook-3E437jPU.d.mts.map +1 -0
  413. package/dist/{value-set-derivation-hook-Di9JZ0X7.mjs → value-set-derivation-hook-HVaxhALD.mjs} +2 -2
  414. package/dist/value-set-derivation-hook-HVaxhALD.mjs.map +1 -0
  415. package/dist/{verify-u0UTdZgD-DSAaz9rW.mjs → verify-BVk5bjdH-DhKm6hB3.mjs} +8 -7
  416. package/dist/verify-BVk5bjdH-DhKm6hB3.mjs.map +1 -0
  417. package/dist/{verify-zDRnw0Rn.d.mts → verify-DHXbuZPB.d.mts} +2 -2
  418. package/dist/verify-DHXbuZPB.d.mts.map +1 -0
  419. package/package.json +33 -22
  420. package/dist/aggregate-descriptor-registry-C7hel5O7.mjs.map +0 -1
  421. package/dist/ast-HFcfQZr-.d.mts +0 -206
  422. package/dist/ast-HFcfQZr-.d.mts.map +0 -1
  423. package/dist/ast-Lbl4VwqP.mjs +0 -325
  424. package/dist/ast-Lbl4VwqP.mjs.map +0 -1
  425. package/dist/authored-check-naming-BWBe-PVE.d.mts.map +0 -1
  426. package/dist/authored-check-naming-Hf9990DV.mjs.map +0 -1
  427. package/dist/authoring-type-constructors-Blqoa2Ua-DqvNCOb2.mjs +0 -316
  428. package/dist/authoring-type-constructors-Blqoa2Ua-DqvNCOb2.mjs.map +0 -1
  429. package/dist/canonicalization-hooks-CYnW_sGn.d.mts.map +0 -1
  430. package/dist/canonicalization-hooks-dmXkOR4a.mjs.map +0 -1
  431. package/dist/check-constraint-B7qGu6rc-HvQjjX82.d.mts.map +0 -1
  432. package/dist/codec-descriptor-registry-N0dhtKaH.mjs.map +0 -1
  433. package/dist/config-types-D9fdKG3g.d.mts.map +0 -1
  434. package/dist/config-types-gAm54C_v.mjs.map +0 -1
  435. package/dist/contract-builder-CG_tGDbB.d.mts +0 -1360
  436. package/dist/contract-builder-CG_tGDbB.d.mts.map +0 -1
  437. package/dist/contract-builder-D4a5dT7j.mjs.map +0 -1
  438. package/dist/contract-errors-BCN6RVI5-5IHBF_lg.mjs.map +0 -1
  439. package/dist/contract-view-BMR5IWk4.mjs.map +0 -1
  440. package/dist/contract-view-CPHxoAEX.d.mts.map +0 -1
  441. package/dist/contract__pack-types.d.mts +0 -2
  442. package/dist/control-D3cB5YQp.mjs +0 -1267
  443. package/dist/control-D3cB5YQp.mjs.map +0 -1
  444. package/dist/control-DTLJ1WtZ.d.mts +0 -945
  445. package/dist/control-DTLJ1WtZ.d.mts.map +0 -1
  446. package/dist/control-adapter-C99J7aEF-B7eQd7vD.d.mts.map +0 -1
  447. package/dist/control-adapter-MZJQiwcE.d.mts +0 -1
  448. package/dist/db-D18PrXKW-DvTv4JFn.d.mts.map +0 -1
  449. package/dist/ddl-types-BGdnAbXo-DKPHPUGx.mjs.map +0 -1
  450. package/dist/ddl-types-CXx4vPz6-BsgrnSUY.d.mts.map +0 -1
  451. package/dist/derived-checks-DFMRmiAu-DGfB8aS4.mjs +0 -1057
  452. package/dist/derived-checks-DFMRmiAu-DGfB8aS4.mjs.map +0 -1
  453. package/dist/derived-checks-DPdD01O0-DGqOFjs6.d.mts.map +0 -1
  454. package/dist/diff-B16bL_IR.mjs +0 -13
  455. package/dist/diff-B16bL_IR.mjs.map +0 -1
  456. package/dist/diff-DbTNVm2f.d.mts.map +0 -1
  457. package/dist/dist-C_q1_QR9.mjs.map +0 -1
  458. package/dist/dist-ZK6oeI5e.mjs.map +0 -1
  459. package/dist/dist-x6jvtkKM.mjs.map +0 -1
  460. package/dist/driver-types-BQtRkOJ0-Bv2RPSfr.d.mts.map +0 -1
  461. package/dist/entity-handle-lowering-hook-CIvRKBfa.d.mts.map +0 -1
  462. package/dist/entity-handle-lowering-hook-DwLIKNiS.mjs +0 -11
  463. package/dist/entity-handle-lowering-hook-DwLIKNiS.mjs.map +0 -1
  464. package/dist/entity-kinds-B5cUFU22.d.mts.map +0 -1
  465. package/dist/entity-kinds-D7vwoN_T-CCBwFJy0.mjs.map +0 -1
  466. package/dist/errors-B5g0xWro-mWH2C07F.mjs.map +0 -1
  467. package/dist/expression-CX5mTA-z.mjs.map +0 -1
  468. package/dist/expression-FJK6Ar-d.d.mts.map +0 -1
  469. package/dist/factories-P3qBQhO-.d.mts.map +0 -1
  470. package/dist/factories-SVor5xIT.mjs.map +0 -1
  471. package/dist/family__pack.d.mts.map +0 -1
  472. package/dist/family__pack.mjs.map +0 -1
  473. package/dist/foreign-key-C-iTPuRT-C9ip8zFx.d.mts.map +0 -1
  474. package/dist/foreign-key-materialization-CkvOzJWy.d.mts +0 -65
  475. package/dist/foreign-key-materialization-CkvOzJWy.d.mts.map +0 -1
  476. package/dist/foreign-key-materialization-Cu7-7LHl.mjs +0 -73
  477. package/dist/foreign-key-materialization-Cu7-7LHl.mjs.map +0 -1
  478. package/dist/index-C-vQOMY_.d.mts +0 -84
  479. package/dist/index-C-vQOMY_.d.mts.map +0 -1
  480. package/dist/index-C5I8D-MB.d.mts.map +0 -1
  481. package/dist/index-naming-Ct65z5Xk.d.mts.map +0 -1
  482. package/dist/index-naming-DREt6js7-CRH27yUv.mjs.map +0 -1
  483. package/dist/index-type-validation-COH4d78M.mjs +0 -17
  484. package/dist/index-type-validation-COH4d78M.mjs.map +0 -1
  485. package/dist/index-type-validation-CZ5L2lli.d.mts +0 -10
  486. package/dist/index-type-validation-CZ5L2lli.d.mts.map +0 -1
  487. package/dist/index-types-CNhHgKHi.d.mts +0 -1
  488. package/dist/index-types-DJQ_xwaE.mjs +0 -40
  489. package/dist/index-types-DJQ_xwaE.mjs.map +0 -1
  490. package/dist/index-types-DPVhsW0v-D-BikM4h.d.mts +0 -31
  491. package/dist/index-types-DPVhsW0v-D-BikM4h.d.mts.map +0 -1
  492. package/dist/interpreter-DyiUUAWh-DYdjIpiE.mjs +0 -3680
  493. package/dist/interpreter-DyiUUAWh-DYdjIpiE.mjs.map +0 -1
  494. package/dist/ir-Bghjt-FG.d.mts.map +0 -1
  495. package/dist/ir-I-xciGUH.mjs.map +0 -1
  496. package/dist/lane-query-builder.d.mts +0 -236
  497. package/dist/lane-query-builder.d.mts.map +0 -1
  498. package/dist/lane-query-builder.mjs +0 -67
  499. package/dist/lane-query-builder.mjs.map +0 -1
  500. package/dist/middleware--TtoxUiW.d.mts +0 -1
  501. package/dist/middleware-AhTz1BOW-th-Suxuf.d.mts.map +0 -1
  502. package/dist/middleware-CMr4CHNz-DHIUdxlm.mjs.map +0 -1
  503. package/dist/migration-CK4oePIo.mjs.map +0 -1
  504. package/dist/migration-CjDRZNep.d.mts.map +0 -1
  505. package/dist/naming-CV9j2pXl-KARaDReS.d.mts.map +0 -1
  506. package/dist/naming-DKr4TJd7-Cszhq9RV.mjs.map +0 -1
  507. package/dist/pack-types-BcLTpwbv.d.mts +0 -14
  508. package/dist/pack-types-BcLTpwbv.d.mts.map +0 -1
  509. package/dist/plan-BHLdb0Z7.d.mts +0 -2
  510. package/dist/plan-CDxduYaN-pLIyyJaB.d.mts.map +0 -1
  511. package/dist/plan-Dh0LbYIv-Crx5-ThG.mjs.map +0 -1
  512. package/dist/prepared-query-BJr50wPm-ChoqfJbX.mjs +0 -22
  513. package/dist/prepared-query-BJr50wPm-ChoqfJbX.mjs.map +0 -1
  514. package/dist/prepared-statement-9QpkE6JG-C430V3MO.d.mts +0 -529
  515. package/dist/prepared-statement-9QpkE6JG-C430V3MO.d.mts.map +0 -1
  516. package/dist/psl-infer-CCAD6FWA.d.mts +0 -119
  517. package/dist/psl-infer-CCAD6FWA.d.mts.map +0 -1
  518. package/dist/psl-infer-Dk5kgKre.mjs +0 -362
  519. package/dist/psl-infer-Dk5kgKre.mjs.map +0 -1
  520. package/dist/query-lane-context-Qa-eddrE-kuZ8Z86-.d.mts.map +0 -1
  521. package/dist/query-lane-context-XMvk7fmY.d.mts +0 -1
  522. package/dist/referential-action-sql-DJ9ps6-S.d.mts.map +0 -1
  523. package/dist/referential-action-sql-DSqkrySN.mjs.map +0 -1
  524. package/dist/resolve-storage-table-DZsfnzeW.mjs.map +0 -1
  525. package/dist/resolve-storage-table-Nyrgk4h8.d.mts.map +0 -1
  526. package/dist/runtime-DpKF2Yu2.d.mts.map +0 -1
  527. package/dist/runtime-tIHpGCcG.mjs.map +0 -1
  528. package/dist/runtime.mjs.map +0 -1
  529. package/dist/schema-differ-DpG_gnur-DFAtGezx.d.mts.map +0 -1
  530. package/dist/schema-verify-C_PEdlAr-Dxxjm6EM.mjs.map +0 -1
  531. package/dist/serialized-index-CrgG8ct1-DG3JpHc7.d.mts.map +0 -1
  532. package/dist/serialized-index-nBTwanKy-_ddEK4tk.mjs.map +0 -1
  533. package/dist/sql-contract-serializer-2oBWuxTe-DKZTf2n8.mjs.map +0 -1
  534. package/dist/sql-execution-plan--jKyLpe5-CMGhgO0M.d.mts.map +0 -1
  535. package/dist/sql-index-ByAAE7K8-DKj2V86p.d.mts.map +0 -1
  536. package/dist/sql-node-kEz6YFZo-v2F7delx.d.mts.map +0 -1
  537. package/dist/sql-storage-8LqxeLAY-DH4DdUXx.d.mts.map +0 -1
  538. package/dist/storage-table-DSeWszOL-CI-cItEK.d.mts.map +0 -1
  539. package/dist/storage-table-ZzbR-xzQ-BRoTQE_2.mjs.map +0 -1
  540. package/dist/storage-value-set-BGlj5Uus-CvZD--GG.d.mts.map +0 -1
  541. package/dist/timestamp-now-generator-DRXygu32-DN9Qb1uI.mjs +0 -173
  542. package/dist/timestamp-now-generator-DRXygu32-DN9Qb1uI.mjs.map +0 -1
  543. package/dist/types-4YenawkP-CwaaZSid.mjs.map +0 -1
  544. package/dist/types-B0msOnBM.d.mts +0 -1
  545. package/dist/types-BDUG29Df-LE85dIXP.d.mts +0 -161
  546. package/dist/types-BDUG29Df-LE85dIXP.d.mts.map +0 -1
  547. package/dist/types-CUsJrvEl.mjs.map +0 -1
  548. package/dist/types-CyxGtOOh-BggSa6Fe.d.mts.map +0 -1
  549. package/dist/types-Dt4e_jC--COeP8xzN.mjs.map +0 -1
  550. package/dist/types-Dwcw0F8X.d.mts +0 -1
  551. package/dist/types-IqZMLrFC-DcH8v_u3.d.mts.map +0 -1
  552. package/dist/types-UcHa2cTe.d.mts +0 -17
  553. package/dist/types-UcHa2cTe.d.mts.map +0 -1
  554. package/dist/types-YStFFkKs-D9UAmnON.d.mts.map +0 -1
  555. package/dist/types-v3qxLLxo-DCeKv7yY.d.mts.map +0 -1
  556. package/dist/unique-constraint-M5TlQnJQ-BiIHJ85k.d.mts.map +0 -1
  557. package/dist/util-DQQgv2j1-D6INZaRG.mjs.map +0 -1
  558. package/dist/validators-Belo8QqM.d.mts.map +0 -1
  559. package/dist/validators-CrWD6bSP.mjs.map +0 -1
  560. package/dist/value-set-derivation-hook-BhgGVtw0.d.mts.map +0 -1
  561. package/dist/value-set-derivation-hook-Di9JZ0X7.mjs.map +0 -1
  562. package/dist/verify-u0UTdZgD-DSAaz9rW.mjs.map +0 -1
  563. package/dist/verify-zDRnw0Rn.d.mts.map +0 -1
  564. /package/dist/{contract__pack-types.mjs → relational-core__collection-methods.mjs} +0 -0
@@ -1,3680 +0,0 @@
1
- import { t as deriveValueSetFromEntity } from "./value-set-derivation-hook-Di9JZ0X7.mjs";
2
- import { n as buildSqlContractFromDefinition } from "./derived-checks-DFMRmiAu-DGfB8aS4.mjs";
3
- import { structuredError } from "@prisma/orm-framework/utils/structured-error";
4
- import { hasRegisteredFieldNamespace, instantiateAuthoringEntityType, instantiateAuthoringFieldPreset, instantiateAuthoringTypeConstructor, isAuthoringEntityTypeDescriptor, isAuthoringFieldPresetDescriptor, isAuthoringModelAttributeDescriptor, isAuthoringPslBlockDescriptor, isAuthoringTypeConstructorDescriptor, validateAuthoringHelperArguments } from "@prisma/orm-framework/components/authoring";
5
- import { UNBOUND_NAMESPACE_ID } from "@prisma/orm-framework/components/ir";
6
- import { InternalError } from "@prisma/orm-framework/utils/internal-error";
7
- import { crossRef } from "@prisma/orm-framework/contract/types";
8
- import { ifDefined } from "@prisma/orm-framework/utils/defined";
9
- 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";
12
- import { notOk, ok } from "@prisma/orm-framework/utils/result";
13
- //#region ../../../2-sql/2-authoring/contract-psl/dist/interpreter-DyiUUAWh.mjs
14
- function contractError(code, message, options) {
15
- return structuredError(code, message, options);
16
- }
17
- function lowerFirst(value) {
18
- if (value.length === 0) return value;
19
- return value[0]?.toLowerCase() + value.slice(1);
20
- }
21
- function getAttribute(attributes, name) {
22
- return attributes?.find((attribute) => attribute.name === name);
23
- }
24
- function formatDbAttributeMigrationMessage(attribute) {
25
- const renderedArguments = attribute.args.map((argument) => argument.kind === "named" && argument.name !== void 0 ? `${argument.name}: ${argument.value}` : argument.value).join(", ");
26
- const argumentList = attribute.args.length === 0 ? "" : `(${renderedArguments})`;
27
- const constructorName = attribute.name.slice(3);
28
- return `@${attribute.name}${argumentList} is no longer supported; use ${constructorName}${argumentList} in type position`;
29
- }
30
- function getNamedArgument(attribute, name) {
31
- const entry = attribute.args.find((arg) => arg.kind === "named" && arg.name === name);
32
- if (entry?.kind !== "named") return;
33
- return entry.value;
34
- }
35
- function unquoteStringLiteral(value) {
36
- const trimmed = value.trim();
37
- const match = trimmed.match(/^(['"])(.*)\1$/);
38
- if (!match) return trimmed;
39
- return match[2] ?? "";
40
- }
41
- function mapFieldNamesToColumns(input) {
42
- const columns = [];
43
- for (const fieldName of input.fieldNames) {
44
- const columnName = input.mapping.fieldColumns.get(fieldName);
45
- if (!columnName) {
46
- input.diagnostics.push({
47
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
48
- message: `${input.entityLabel} references unknown field "${input.modelName}.${fieldName}"`,
49
- sourceId: input.sourceId,
50
- span: input.span
51
- });
52
- return;
53
- }
54
- columns.push(columnName);
55
- }
56
- return columns;
57
- }
58
- function formatSupportedFunctionList(registry) {
59
- const signatures = Array.from(registry.entries()).sort(([a], [b]) => a.localeCompare(b)).flatMap(([functionName, entry]) => {
60
- const usageSignatures = entry.usageSignatures?.filter((signature) => signature.length > 0);
61
- return usageSignatures && usageSignatures.length > 0 ? usageSignatures : [`${functionName}()`];
62
- });
63
- return signatures.length > 0 ? signatures.join(", ") : "none";
64
- }
65
- function lowerDefaultFunctionWithRegistry(input) {
66
- const entry = input.registry.get(input.call.fn);
67
- if (entry) return entry.lower({
68
- call: input.call,
69
- context: input.context
70
- });
71
- const supportedFunctionList = formatSupportedFunctionList(input.registry);
72
- return {
73
- ok: false,
74
- diagnostic: {
75
- code: "PSL_UNKNOWN_DEFAULT_FUNCTION",
76
- message: `Default function "${input.call.fn}" is not supported in SQL PSL provider v1. Supported functions: ${supportedFunctionList}.`,
77
- sourceId: input.context.sourceId,
78
- span: input.call.span
79
- }
80
- };
81
- }
82
- const INVALID_AUTHORING_ARGUMENT = Symbol("invalidAuthoringArgument");
83
- function isIdentifierStartCharacter(character) {
84
- return character !== void 0 && /[A-Za-z_$]/.test(character);
85
- }
86
- function isIdentifierCharacter(character) {
87
- return character !== void 0 && /[A-Za-z0-9_$]/.test(character);
88
- }
89
- function parseJsLikeLiteral(value) {
90
- let index = 0;
91
- function skipWhitespace() {
92
- while (/\s/.test(value[index] ?? "")) index += 1;
93
- }
94
- function parseIdentifier() {
95
- const first = value[index];
96
- if (!isIdentifierStartCharacter(first)) return INVALID_AUTHORING_ARGUMENT;
97
- let end = index + 1;
98
- while (isIdentifierCharacter(value[end])) end += 1;
99
- const identifier = value.slice(index, end);
100
- index = end;
101
- return identifier;
102
- }
103
- function parseString() {
104
- const quote = value[index];
105
- if (quote !== "\"" && quote !== "'") return INVALID_AUTHORING_ARGUMENT;
106
- index += 1;
107
- let result = "";
108
- while (index < value.length) {
109
- const character = value[index];
110
- index += 1;
111
- if (character === void 0) return INVALID_AUTHORING_ARGUMENT;
112
- if (character === quote) return result;
113
- if (character !== "\\") {
114
- result += character;
115
- continue;
116
- }
117
- const escaped = value[index];
118
- index += 1;
119
- if (escaped === void 0) return INVALID_AUTHORING_ARGUMENT;
120
- switch (escaped) {
121
- case "'":
122
- case "\"":
123
- case "\\":
124
- case "/":
125
- result += escaped;
126
- break;
127
- case "b":
128
- result += "\b";
129
- break;
130
- case "f":
131
- result += "\f";
132
- break;
133
- case "n":
134
- result += "\n";
135
- break;
136
- case "r":
137
- result += "\r";
138
- break;
139
- case "t":
140
- result += " ";
141
- break;
142
- case "u": {
143
- const hex = value.slice(index, index + 4);
144
- if (!/^[0-9A-Fa-f]{4}$/.test(hex)) return INVALID_AUTHORING_ARGUMENT;
145
- result += String.fromCharCode(Number.parseInt(hex, 16));
146
- index += 4;
147
- break;
148
- }
149
- default: return INVALID_AUTHORING_ARGUMENT;
150
- }
151
- }
152
- return INVALID_AUTHORING_ARGUMENT;
153
- }
154
- function parseNumber() {
155
- const raw = value.slice(index).match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/)?.[0];
156
- if (!raw) return INVALID_AUTHORING_ARGUMENT;
157
- const parsed = Number(raw);
158
- if (!Number.isFinite(parsed)) return INVALID_AUTHORING_ARGUMENT;
159
- index += raw.length;
160
- return parsed;
161
- }
162
- function parseArray() {
163
- if (value[index] !== "[") return INVALID_AUTHORING_ARGUMENT;
164
- index += 1;
165
- const result = [];
166
- skipWhitespace();
167
- if (value[index] === "]") {
168
- index += 1;
169
- return result;
170
- }
171
- while (index < value.length) {
172
- const entry = parseValue();
173
- if (entry === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
174
- result.push(entry);
175
- skipWhitespace();
176
- if (value[index] === ",") {
177
- index += 1;
178
- skipWhitespace();
179
- continue;
180
- }
181
- if (value[index] === "]") {
182
- index += 1;
183
- return result;
184
- }
185
- return INVALID_AUTHORING_ARGUMENT;
186
- }
187
- return INVALID_AUTHORING_ARGUMENT;
188
- }
189
- function parseObject() {
190
- if (value[index] !== "{") return INVALID_AUTHORING_ARGUMENT;
191
- index += 1;
192
- const result = {};
193
- skipWhitespace();
194
- if (value[index] === "}") {
195
- index += 1;
196
- return result;
197
- }
198
- while (index < value.length) {
199
- skipWhitespace();
200
- const key = value[index] === "\"" || value[index] === "'" ? parseString() : parseIdentifier();
201
- if (key === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
202
- skipWhitespace();
203
- if (value[index] !== ":") return INVALID_AUTHORING_ARGUMENT;
204
- index += 1;
205
- const entry = parseValue();
206
- if (entry === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
207
- result[key] = entry;
208
- skipWhitespace();
209
- if (value[index] === ",") {
210
- index += 1;
211
- skipWhitespace();
212
- continue;
213
- }
214
- if (value[index] === "}") {
215
- index += 1;
216
- return result;
217
- }
218
- return INVALID_AUTHORING_ARGUMENT;
219
- }
220
- return INVALID_AUTHORING_ARGUMENT;
221
- }
222
- function parseValue() {
223
- skipWhitespace();
224
- const character = value[index];
225
- if (character === "{") return parseObject();
226
- if (character === "[") return parseArray();
227
- if (character === "\"" || character === "'") return parseString();
228
- if (character === "-" || /\d/.test(character ?? "")) return parseNumber();
229
- const identifier = parseIdentifier();
230
- if (identifier === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
231
- if (identifier === "true") return true;
232
- if (identifier === "false") return false;
233
- if (identifier === "null") return null;
234
- return INVALID_AUTHORING_ARGUMENT;
235
- }
236
- skipWhitespace();
237
- const parsed = parseValue();
238
- if (parsed === INVALID_AUTHORING_ARGUMENT) return parsed;
239
- skipWhitespace();
240
- return index === value.length ? parsed : INVALID_AUTHORING_ARGUMENT;
241
- }
242
- function parseStringArrayLiteral(value) {
243
- const parsed = parseJsLikeLiteral(value);
244
- if (parsed === INVALID_AUTHORING_ARGUMENT || !Array.isArray(parsed)) return INVALID_AUTHORING_ARGUMENT;
245
- if (!parsed.every((item) => typeof item === "string")) return INVALID_AUTHORING_ARGUMENT;
246
- return parsed;
247
- }
248
- function isPlainObject(value) {
249
- return typeof value === "object" && value !== null && !Array.isArray(value);
250
- }
251
- function parsePslObjectLiteral(value) {
252
- const trimmed = value.trim();
253
- if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return INVALID_AUTHORING_ARGUMENT;
254
- let parsed;
255
- try {
256
- parsed = JSON.parse(trimmed);
257
- } catch {
258
- parsed = parseJsLikeLiteral(trimmed);
259
- if (parsed === INVALID_AUTHORING_ARGUMENT) return INVALID_AUTHORING_ARGUMENT;
260
- }
261
- if (!isPlainObject(parsed)) return INVALID_AUTHORING_ARGUMENT;
262
- return parsed;
263
- }
264
- function parsePslAuthoringArgumentValue(descriptor, rawValue) {
265
- switch (descriptor.kind) {
266
- case "string": return unquoteStringLiteral(rawValue);
267
- case "boolean": {
268
- const trimmed = rawValue.trim();
269
- if (trimmed === "true") return true;
270
- if (trimmed === "false") return false;
271
- return INVALID_AUTHORING_ARGUMENT;
272
- }
273
- case "number": {
274
- const parsed = Number(unquoteStringLiteral(rawValue));
275
- return Number.isNaN(parsed) ? INVALID_AUTHORING_ARGUMENT : parsed;
276
- }
277
- case "stringArray": return parseStringArrayLiteral(rawValue);
278
- case "object": return parsePslObjectLiteral(rawValue);
279
- case "option": {
280
- const trimmed = rawValue.trim();
281
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(trimmed) ? trimmed : INVALID_AUTHORING_ARGUMENT;
282
- }
283
- default: return INVALID_AUTHORING_ARGUMENT;
284
- }
285
- }
286
- function pushInvalidPslHelperArgument(input) {
287
- input.diagnostics.push({
288
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
289
- message: `${input.entityLabel} ${input.helperLabel} ${input.message}`,
290
- sourceId: input.sourceId,
291
- span: input.span
292
- });
293
- }
294
- function mapPslHelperArgs(input) {
295
- const mappedArgs = input.descriptors.map(() => void 0);
296
- const positionalArgs = input.args.filter((arg) => arg.kind === "positional");
297
- const namedArgs = input.args.filter((arg) => arg.kind === "named");
298
- if (positionalArgs.length > input.descriptors.length) return pushInvalidPslHelperArgument({
299
- diagnostics: input.diagnostics,
300
- sourceId: input.sourceId,
301
- span: input.span,
302
- entityLabel: input.entityLabel,
303
- helperLabel: input.helperLabel,
304
- message: `accepts at most ${input.descriptors.length} argument(s), received ${positionalArgs.length}.`
305
- });
306
- for (const [index, argument] of positionalArgs.entries()) {
307
- const descriptor = input.descriptors[index];
308
- if (!descriptor) return pushInvalidPslHelperArgument({
309
- diagnostics: input.diagnostics,
310
- sourceId: input.sourceId,
311
- span: argument.span,
312
- entityLabel: input.entityLabel,
313
- helperLabel: input.helperLabel,
314
- message: `does not define positional argument #${index + 1}.`
315
- });
316
- const value = parsePslAuthoringArgumentValue(descriptor, argument.value);
317
- if (value === INVALID_AUTHORING_ARGUMENT) return pushInvalidPslHelperArgument({
318
- diagnostics: input.diagnostics,
319
- sourceId: input.sourceId,
320
- span: argument.span,
321
- entityLabel: input.entityLabel,
322
- helperLabel: input.helperLabel,
323
- message: `cannot parse argument #${index + 1} for descriptor kind "${descriptor.kind}".`
324
- });
325
- mappedArgs[index] = value;
326
- }
327
- for (const argument of namedArgs) {
328
- const descriptorIndex = input.descriptors.findIndex((descriptor) => descriptor.name === argument.name);
329
- if (descriptorIndex < 0) return pushInvalidPslHelperArgument({
330
- diagnostics: input.diagnostics,
331
- sourceId: input.sourceId,
332
- span: argument.span,
333
- entityLabel: input.entityLabel,
334
- helperLabel: input.helperLabel,
335
- message: `received unknown named argument "${argument.name}".`
336
- });
337
- if (mappedArgs[descriptorIndex] !== void 0) return pushInvalidPslHelperArgument({
338
- diagnostics: input.diagnostics,
339
- sourceId: input.sourceId,
340
- span: argument.span,
341
- entityLabel: input.entityLabel,
342
- helperLabel: input.helperLabel,
343
- message: `received duplicate value for argument "${argument.name}".`
344
- });
345
- const descriptor = input.descriptors[descriptorIndex];
346
- if (!descriptor) return pushInvalidPslHelperArgument({
347
- diagnostics: input.diagnostics,
348
- sourceId: input.sourceId,
349
- span: argument.span,
350
- entityLabel: input.entityLabel,
351
- helperLabel: input.helperLabel,
352
- message: `does not define named argument "${argument.name}".`
353
- });
354
- const value = parsePslAuthoringArgumentValue(descriptor, argument.value);
355
- if (value === INVALID_AUTHORING_ARGUMENT) return pushInvalidPslHelperArgument({
356
- diagnostics: input.diagnostics,
357
- sourceId: input.sourceId,
358
- span: argument.span,
359
- entityLabel: input.entityLabel,
360
- helperLabel: input.helperLabel,
361
- message: `cannot parse named argument "${argument.name}" for descriptor kind "${descriptor.kind}".`
362
- });
363
- mappedArgs[descriptorIndex] = value;
364
- }
365
- return mappedArgs;
366
- }
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
- function toNamedTypeFieldDescriptor(typeRef, descriptor) {
558
- return {
559
- codecId: descriptor.codecId,
560
- nativeType: descriptor.nativeType,
561
- typeRef
562
- };
563
- }
564
- function getAuthoringTypeConstructor(contributions, path) {
565
- let current = contributions?.type;
566
- for (const segment of path) {
567
- if (typeof current !== "object" || current === null || "kind" in current) return;
568
- current = current[segment];
569
- }
570
- return current !== void 0 && isAuthoringTypeConstructorDescriptor(current) ? current : void 0;
571
- }
572
- /**
573
- * Walks `authoringContributions.entityTypes` segment-by-segment and returns
574
- * the entity type descriptor at the resolved path, or `undefined` if no
575
- * descriptor is registered.
576
- *
577
- * Used by the PSL interpreter to dispatch declarative entity-shaped
578
- * declarations (`enum`, future `namespace { … }`, …) through the
579
- * pack entity-type mechanism — the descriptor's `factory` (or
580
- * `template`) materialises the IR-class instance without the
581
- * interpreter knowing target-specific construction.
582
- */
583
- function getAuthoringEntity(contributions, path) {
584
- let current = contributions?.entityTypes;
585
- for (const segment of path) {
586
- if (typeof current !== "object" || current === null || "kind" in current) return;
587
- current = current[segment];
588
- }
589
- return current !== void 0 && isAuthoringEntityTypeDescriptor(current) ? current : void 0;
590
- }
591
- /**
592
- * Walks `authoringContributions.field` segment-by-segment and returns the field-preset descriptor at the resolved path, or `undefined` if no descriptor is registered.
593
- *
594
- * Symmetric with `getAuthoringTypeConstructor`. Field presets are strictly richer than type constructors — they can contribute `default` / `executionDefaults` / `id` / `unique` / `nullable` in addition to the `codecId` / `nativeType` / `typeParams` triple. PSL resolution tries field presets first, then falls back to type constructors on miss (see `resolveFieldTypeDescriptor`).
595
- */
596
- function getAuthoringFieldPreset(contributions, path) {
597
- let current = contributions?.field;
598
- for (const segment of path) {
599
- if (typeof current !== "object" || current === null || "kind" in current) return;
600
- current = current[segment];
601
- }
602
- return current !== void 0 && isAuthoringFieldPresetDescriptor(current) ? current : void 0;
603
- }
604
- /**
605
- * Returns the namespace prefix of `attributeName` if it references an unrecognized extension namespace, otherwise `undefined`. A namespace is considered recognized when it is:
606
- *
607
- * - `db` (native-type spec, always allowed),
608
- * - the active family id (e.g. `sql`),
609
- * - the active target id (e.g. `postgres`),
610
- * - a registered field-preset namespace (e.g. `temporal`),
611
- * - present in `composedExtensions`.
612
- *
613
- * Family/target/field-preset namespaces are exempted so that e.g. `@sql.foo` surfaces as PSL_UNSUPPORTED_*_ATTRIBUTE (the attribute isn't defined) rather than PSL_EXTENSION_NAMESPACE_NOT_COMPOSED (the namespace is already composed).
614
- */
615
- function checkUncomposedNamespace(attributeName, composedExtensions, context) {
616
- const dotIndex = attributeName.indexOf(".");
617
- if (dotIndex <= 0 || dotIndex === attributeName.length - 1) return;
618
- const namespace = attributeName.slice(0, dotIndex);
619
- if (namespace === "db" || namespace === context?.familyId || namespace === context?.targetId || hasRegisteredFieldNamespace(context?.authoringContributions, namespace) || composedExtensions.has(namespace)) return;
620
- return namespace;
621
- }
622
- /**
623
- * Pushes the canonical `PSL_EXTENSION_NAMESPACE_NOT_COMPOSED` diagnostic for a subject (attribute, model attribute, or type constructor) that references an extension namespace which is not composed in the current contract.
624
- *
625
- * The `data` payload carries the missing namespace so machine consumers (agents, IDE extensions, CLI auto-fix) don't have to parse the prose.
626
- */
627
- function reportUncomposedNamespace(input) {
628
- input.diagnostics.push({
629
- code: "PSL_EXTENSION_NAMESPACE_NOT_COMPOSED",
630
- message: `${input.subjectLabel} uses unrecognized namespace "${input.namespace}". Add extension pack "${input.namespace}" to extensions in prisma.config.ts.`,
631
- sourceId: input.sourceId,
632
- span: input.span,
633
- data: {
634
- namespace: input.namespace,
635
- suggestedPack: input.namespace
636
- }
637
- });
638
- }
639
- /**
640
- * Pushes the canonical `PSL_UNKNOWN_FIELD_PRESET` diagnostic when a typoed preset name is referenced inside a registered field-preset namespace. The `data` payload exposes the namespace and full helper path so machine consumers (agents, IDE extensions) don't have to parse the prose.
641
- */
642
- function reportUnknownFieldPreset(input) {
643
- input.diagnostics.push({
644
- code: "PSL_UNKNOWN_FIELD_PRESET",
645
- message: `${input.entityLabel} references unknown field preset "${input.helperPath}". Check the spelling against the available presets in the "${input.namespace}" namespace.`,
646
- sourceId: input.sourceId,
647
- span: input.span,
648
- data: {
649
- namespace: input.namespace,
650
- helperPath: input.helperPath
651
- }
652
- });
653
- }
654
- function instantiatePslTypeConstructor(input) {
655
- const helperPath = input.call.path.join(".");
656
- const args = mapPslHelperArgs({
657
- args: input.call.args,
658
- descriptors: input.descriptor.args ?? [],
659
- helperLabel: `constructor "${helperPath}"`,
660
- span: input.call.span,
661
- diagnostics: input.diagnostics,
662
- sourceId: input.sourceId,
663
- entityLabel: input.entityLabel
664
- });
665
- if (!args) return;
666
- try {
667
- validateAuthoringHelperArguments(helperPath, input.descriptor.args, args);
668
- return instantiateAuthoringTypeConstructor(input.descriptor, args);
669
- } catch (error) {
670
- const message = error instanceof Error ? error.message : String(error);
671
- input.diagnostics.push({
672
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
673
- message: `${input.entityLabel} constructor "${helperPath}" ${message}`,
674
- sourceId: input.sourceId,
675
- span: input.call.span
676
- });
677
- return;
678
- }
679
- }
680
- function pushUnsupportedTypeConstructorDiagnostic(input) {
681
- input.diagnostics.push({
682
- code: input.code,
683
- message: input.message,
684
- sourceId: input.sourceId,
685
- span: input.span
686
- });
687
- }
688
- function resolvePslTypeConstructorDescriptor(input) {
689
- const descriptor = getAuthoringTypeConstructor(input.authoringContributions, input.call.path);
690
- if (descriptor) return descriptor;
691
- const uncomposedNamespace = checkUncomposedNamespace(input.call.path.join("."), input.composedExtensions, {
692
- familyId: input.familyId,
693
- targetId: input.targetId,
694
- authoringContributions: input.authoringContributions
695
- });
696
- if (uncomposedNamespace) {
697
- reportUncomposedNamespace({
698
- subjectLabel: `Type constructor "${input.call.path.join(".")}"`,
699
- namespace: uncomposedNamespace,
700
- sourceId: input.sourceId,
701
- span: input.call.span,
702
- diagnostics: input.diagnostics
703
- });
704
- return;
705
- }
706
- return pushUnsupportedTypeConstructorDiagnostic({
707
- diagnostics: input.diagnostics,
708
- sourceId: input.sourceId,
709
- span: input.call.span,
710
- code: input.unsupportedCode,
711
- message: input.unsupportedMessage
712
- });
713
- }
714
- /**
715
- * Instantiates a field-preset call against its descriptor, coercing PSL AST arguments into the descriptor's typed argument shape and returning the preset's full set of contract contributions.
716
- *
717
- * Symmetric with `instantiatePslTypeConstructor` but richer: a field preset can contribute `default`, `executionDefaults`, `id`, `unique`, and `nullable` in addition to the storage-type triple. PSL → typed-args coercion happens here (via `mapPslHelperArgs`) so that `instantiateAuthoringFieldPreset` itself stays typed-input-only and TS keeps its zero-runtime-validation cost.
718
- */
719
- function instantiateFieldPreset(input) {
720
- const helperPath = input.call.path.join(".");
721
- const args = mapPslHelperArgs({
722
- args: input.call.args,
723
- descriptors: input.descriptor.args ?? [],
724
- helperLabel: `preset "${helperPath}"`,
725
- span: input.call.span,
726
- diagnostics: input.diagnostics,
727
- sourceId: input.sourceId,
728
- entityLabel: input.entityLabel
729
- });
730
- if (!args) return;
731
- try {
732
- validateAuthoringHelperArguments(helperPath, input.descriptor.args, args);
733
- const instantiated = instantiateAuthoringFieldPreset(input.descriptor, args);
734
- return {
735
- descriptor: {
736
- codecId: instantiated.descriptor.codecId,
737
- nativeType: instantiated.descriptor.nativeType,
738
- ...instantiated.descriptor.typeParams !== void 0 ? { typeParams: instantiated.descriptor.typeParams } : {}
739
- },
740
- nullable: instantiated.nullable,
741
- ...instantiated.default !== void 0 ? { default: instantiated.default } : {},
742
- ...instantiated.executionDefaults !== void 0 ? { executionDefaults: instantiated.executionDefaults } : {},
743
- id: instantiated.id,
744
- unique: instantiated.unique
745
- };
746
- } catch (error) {
747
- const message = error instanceof Error ? error.message : String(error);
748
- input.diagnostics.push({
749
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
750
- message: `${input.entityLabel} preset "${helperPath}" ${message}`,
751
- sourceId: input.sourceId,
752
- span: input.call.span
753
- });
754
- return;
755
- }
756
- }
757
- /**
758
- * Structural check for a codec descriptor exposing the authoring-time
759
- * `columnFromEntity` hook a type constructor's `entityRefArg` resolves
760
- * through (e.g. the `pg/enum@1` codec descriptor). No casts.
761
- */
762
- function hasColumnFromEntityHook(descriptor) {
763
- return "columnFromEntity" in descriptor && typeof descriptor.columnFromEntity === "function";
764
- }
765
- /**
766
- * Resolves a type-constructor call whose descriptor declares an
767
- * `entityRefArg` (e.g. `pg.enum(AalLevel)`): extracts the call's sole
768
- * positional-argument ref string, resolves it against the field's
769
- * namespace's already-lowered extension entities (keyed by the declared
770
- * `entityRefArg.entityKind`, then block name), and converts the resolved
771
- * entity to column params via the `columnFromEntity` authoring hook on the
772
- * codec descriptor registered for `descriptor.output.codecId`. The `nativeType`
773
- * / `typeParams.typeName` `columnFromEntity` returns are bare — schema
774
- * qualification (e.g. `auth.aal_level`) is a target concern, applied later
775
- * when the target builds the field's namespace. A `valueSet` ref is
776
- * attached when the same namespace derived a value-set under the same block
777
- * name (the generic `deriveValueSet` mechanism), scoped to the field's own
778
- * namespace.
779
- */
780
- function resolveEntityRefTypeConstructorCall(input) {
781
- const entityRefArg = input.descriptor.entityRefArg;
782
- if (entityRefArg === void 0) throw new InternalError("resolveEntityRefTypeConstructorCall called with a descriptor that does not declare an entityRefArg. This is an interpreter bug.");
783
- const helperPath = input.call.path.join(".");
784
- const positionalArgs = input.call.args.filter((arg) => arg.kind === "positional");
785
- const ref = positionalArgs[entityRefArg.index]?.value;
786
- if (input.call.args.length !== 1 || positionalArgs.length !== 1 || ref === void 0) {
787
- input.diagnostics.push({
788
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
789
- message: `${input.entityLabel} type constructor "${helperPath}" expects exactly one positional argument naming the referenced entity`,
790
- sourceId: input.sourceId,
791
- span: input.call.span
792
- });
793
- return {
794
- ok: false,
795
- alreadyReported: true
796
- };
797
- }
798
- const reportUnknownRef = () => {
799
- input.diagnostics.push({
800
- code: "PSL_UNKNOWN_ENTITY_REF",
801
- message: `${input.entityLabel} type constructor "${helperPath}(${ref})" does not resolve — no entity named "${ref}" was found in namespace "${input.namespaceId ?? "(unspecified)"}"`,
802
- sourceId: input.sourceId,
803
- span: input.call.span
804
- });
805
- return {
806
- ok: false,
807
- alreadyReported: true
808
- };
809
- };
810
- const entity = input.namespaceExtensionEntities?.[entityRefArg.entityKind]?.[ref];
811
- if (entity === void 0) return reportUnknownRef();
812
- const codecId = input.descriptor.output.codecId;
813
- const codecDescriptor = input.codecLookup?.descriptorFor?.(codecId);
814
- if (codecDescriptor === void 0 || !hasColumnFromEntityHook(codecDescriptor)) throw contractError("CONTRACT.PACK_CONTRIBUTION_INVALID", `Type constructor "${helperPath}" registers codecId "${codecId}" with an entity-ref argument, but its codec descriptor has no "columnFromEntity" authoring hook. This is a contributor bug in the pack registering "${helperPath}", not a user-schema error.`, { meta: {
815
- helperPath,
816
- codecId
817
- } });
818
- const resolved = codecDescriptor.columnFromEntity(entity);
819
- if (resolved === void 0) return reportUnknownRef();
820
- const derivedValueSet = input.namespaceExtensionEntities?.["valueSet"]?.[ref];
821
- if (derivedValueSet !== void 0 && input.namespaceId === void 0) {
822
- input.diagnostics.push({
823
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
824
- message: `${input.entityLabel} type constructor "${helperPath}(${ref})" resolves to a value-set-typed entity, but the field has no resolvable namespace to scope the value-set ref to`,
825
- sourceId: input.sourceId,
826
- span: input.call.span
827
- });
828
- return {
829
- ok: false,
830
- alreadyReported: true
831
- };
832
- }
833
- const valueSet = derivedValueSet !== void 0 && input.namespaceId !== void 0 ? {
834
- plane: "storage",
835
- entityKind: "valueSet",
836
- namespaceId: input.namespaceId,
837
- entityName: ref
838
- } : void 0;
839
- return {
840
- ok: true,
841
- descriptor: {
842
- codecId,
843
- nativeType: resolved.nativeType,
844
- ...resolved.typeParams !== void 0 ? { typeParams: resolved.typeParams } : {},
845
- ...valueSet !== void 0 ? { valueSet } : {}
846
- }
847
- };
848
- }
849
- function resolveFieldTypeDescriptor(input) {
850
- if (input.field.malformedType) return {
851
- ok: false,
852
- alreadyReported: true
853
- };
854
- if (input.field.typeConstructor) {
855
- const presetDescriptor = getAuthoringFieldPreset(input.authoringContributions, input.field.typeConstructor.path);
856
- if (presetDescriptor) {
857
- const instantiated = instantiateFieldPreset({
858
- call: input.field.typeConstructor,
859
- descriptor: presetDescriptor,
860
- diagnostics: input.diagnostics,
861
- sourceId: input.sourceId,
862
- entityLabel: input.entityLabel
863
- });
864
- if (!instantiated) return {
865
- ok: false,
866
- alreadyReported: true
867
- };
868
- const presetContributions = {
869
- nullable: instantiated.nullable,
870
- id: instantiated.id,
871
- unique: instantiated.unique,
872
- ...instantiated.default !== void 0 ? { default: instantiated.default } : {},
873
- ...instantiated.executionDefaults !== void 0 ? { executionDefaults: instantiated.executionDefaults } : {}
874
- };
875
- return {
876
- ok: true,
877
- descriptor: instantiated.descriptor,
878
- presetContributions
879
- };
880
- }
881
- const helperPath = input.field.typeConstructor.path.join(".");
882
- const namespacePrefix = input.field.typeConstructor.path.length > 1 ? input.field.typeConstructor.path[0] : void 0;
883
- const typeDescriptor = getAuthoringTypeConstructor(input.authoringContributions, input.field.typeConstructor.path);
884
- if (typeDescriptor?.entityRefArg) return resolveEntityRefTypeConstructorCall({
885
- call: input.field.typeConstructor,
886
- descriptor: typeDescriptor,
887
- namespaceId: input.namespaceId,
888
- namespaceExtensionEntities: input.namespaceExtensionEntities,
889
- codecLookup: input.codecLookup,
890
- diagnostics: input.diagnostics,
891
- sourceId: input.sourceId,
892
- entityLabel: input.entityLabel
893
- });
894
- if (!typeDescriptor && namespacePrefix && hasRegisteredFieldNamespace(input.authoringContributions, namespacePrefix)) {
895
- reportUnknownFieldPreset({
896
- entityLabel: input.entityLabel,
897
- namespace: namespacePrefix,
898
- helperPath,
899
- sourceId: input.sourceId,
900
- span: input.field.typeConstructor.span,
901
- diagnostics: input.diagnostics
902
- });
903
- return {
904
- ok: false,
905
- alreadyReported: true
906
- };
907
- }
908
- const descriptor = typeDescriptor ?? resolvePslTypeConstructorDescriptor({
909
- call: input.field.typeConstructor,
910
- authoringContributions: input.authoringContributions,
911
- composedExtensions: input.composedExtensions,
912
- familyId: input.familyId,
913
- targetId: input.targetId,
914
- diagnostics: input.diagnostics,
915
- sourceId: input.sourceId,
916
- unsupportedCode: "PSL_UNSUPPORTED_FIELD_TYPE",
917
- unsupportedMessage: `${input.entityLabel} type constructor "${helperPath}" is not supported in SQL PSL provider v1`
918
- });
919
- if (!descriptor) return {
920
- ok: false,
921
- alreadyReported: true
922
- };
923
- const instantiated = instantiatePslTypeConstructor({
924
- call: input.field.typeConstructor,
925
- descriptor,
926
- diagnostics: input.diagnostics,
927
- sourceId: input.sourceId,
928
- entityLabel: input.entityLabel
929
- });
930
- if (!instantiated) return {
931
- ok: false,
932
- alreadyReported: true
933
- };
934
- return {
935
- ok: true,
936
- descriptor: instantiated
937
- };
938
- }
939
- const descriptor = resolveColumnDescriptor(input.field, input.enumTypeDescriptors, input.namedTypeDescriptors, input.scalarColumnDescriptors);
940
- if (!descriptor) return {
941
- ok: false,
942
- alreadyReported: false
943
- };
944
- return {
945
- ok: true,
946
- descriptor
947
- };
948
- }
949
- function lowerDefaultForField(input) {
950
- const node = findFieldAttributeNode(input.field, "default");
951
- if (node === void 0) return {};
952
- const interpreted = interpretFieldAttribute({
953
- node,
954
- spec: buildDefaultSpec({
955
- isList: input.isList ?? false,
956
- registry: input.defaultFunctionRegistry
957
- }),
958
- model: input.model,
959
- field: input.field,
960
- sourceFile: input.sourceFile,
961
- sourceId: input.sourceId,
962
- diagnostics: input.diagnostics
963
- });
964
- if (interpreted === void 0) return {};
965
- const value = interpreted.value;
966
- if (Array.isArray(value)) return { defaultValue: {
967
- kind: "literal",
968
- value: [...value]
969
- } };
970
- if (typeof value === "object") {
971
- const lowered = lowerDefaultFunctionWithRegistry({
972
- call: value,
973
- registry: input.defaultFunctionRegistry,
974
- context: {
975
- sourceId: input.sourceId,
976
- modelName: input.modelName,
977
- fieldName: input.fieldName,
978
- columnCodecId: input.columnDescriptor.codecId
979
- }
980
- });
981
- if (!lowered.ok) {
982
- input.diagnostics.push(lowered.diagnostic);
983
- return {};
984
- }
985
- if (lowered.value.kind === "storage") return { defaultValue: lowered.value.defaultValue };
986
- const generatorDescriptor = input.generatorDescriptorById.get(lowered.value.generated.id);
987
- if (!generatorDescriptor) {
988
- input.diagnostics.push({
989
- code: "PSL_INVALID_DEFAULT_APPLICABILITY",
990
- message: `Default generator "${lowered.value.generated.id}" is not available in the composed mutation default registry.`,
991
- sourceId: input.sourceId,
992
- span: value.span
993
- });
994
- return {};
995
- }
996
- if (generatorDescriptor.applicableCodecIds === void 0) {
997
- input.diagnostics.push({
998
- code: "PSL_INVALID_DEFAULT_APPLICABILITY",
999
- message: `Default generator "${generatorDescriptor.id}" is not applicable to "@default(...)" lowering. Use the corresponding field preset (e.g. \`temporal.${generatorDescriptor.id === "timestampNow" ? "updatedAt" : generatorDescriptor.id}()\`) instead.`,
1000
- sourceId: input.sourceId,
1001
- span: value.span
1002
- });
1003
- return {};
1004
- }
1005
- if (!generatorDescriptor.applicableCodecIds.includes(input.columnDescriptor.codecId)) {
1006
- input.diagnostics.push({
1007
- code: "PSL_INVALID_DEFAULT_APPLICABILITY",
1008
- message: `Default generator "${generatorDescriptor.id}" is not applicable to "${input.modelName}.${input.fieldName}" with codecId "${input.columnDescriptor.codecId}".`,
1009
- sourceId: input.sourceId,
1010
- span: value.span
1011
- });
1012
- return {};
1013
- }
1014
- return { executionDefaults: { onCreate: lowered.value.generated } };
1015
- }
1016
- return { defaultValue: {
1017
- kind: "literal",
1018
- value
1019
- } };
1020
- }
1021
- function resolveColumnDescriptor(field, enumTypeDescriptors, namedTypeDescriptors, scalarColumnDescriptors) {
1022
- if (namedTypeDescriptors.has(field.typeName)) return namedTypeDescriptors.get(field.typeName);
1023
- if (enumTypeDescriptors.has(field.typeName)) return enumTypeDescriptors.get(field.typeName);
1024
- return scalarColumnDescriptors.get(field.typeName);
1025
- }
1026
- function lowerEnumDefaultForField(input) {
1027
- const { field, model, sourceFile, enumHandle, sourceId, diagnostics } = input;
1028
- const node = findFieldAttributeNode(field, "default");
1029
- if (node === void 0) return {};
1030
- const [firstMember, ...restMembers] = enumHandle.enumMembers.map((m) => m.name);
1031
- if (firstMember === void 0) return {};
1032
- const interpreted = interpretFieldAttribute({
1033
- node,
1034
- spec: buildEnumDefaultSpec([firstMember, ...restMembers]),
1035
- model,
1036
- field,
1037
- sourceFile,
1038
- sourceId,
1039
- diagnostics
1040
- });
1041
- if (interpreted === void 0) return {};
1042
- const member = interpreted.member;
1043
- const match = enumHandle.enumMembers.find((m) => m.name === member);
1044
- if (!match) return {};
1045
- return { defaultValue: {
1046
- kind: "literal",
1047
- value: blindCast(match.value)
1048
- } };
1049
- }
1050
- const MODEL_COORDINATE_SEPARATOR = "\0";
1051
- function modelCoordinateKey(namespaceId, modelName) {
1052
- return `${namespaceId}${MODEL_COORDINATE_SEPARATOR}${modelName}`;
1053
- }
1054
- const BUILTIN_FIELD_ATTRIBUTE_NAMES = /* @__PURE__ */ new Set([
1055
- "id",
1056
- "unique",
1057
- "default",
1058
- "relation",
1059
- "map",
1060
- "noCheck"
1061
- ]);
1062
- const REMOVED_ATTRIBUTE_RULES = /* @__PURE__ */ new Map([["updatedAt", {
1063
- hint: "Use `temporal.updatedAt()` as a field-preset call instead.",
1064
- suppressWhen: (field) => field.typeConstructor?.path[0] === "temporal"
1065
- }]]);
1066
- {
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(", ")}`);
1069
- }
1070
- function validateFieldAttributes(input) {
1071
- for (const attribute of input.field.attributes) {
1072
- if (BUILTIN_FIELD_ATTRIBUTE_NAMES.has(attribute.name)) continue;
1073
- if (attribute.name.startsWith("db.")) {
1074
- input.diagnostics.push({
1075
- code: "PSL_UNSUPPORTED_FIELD_ATTRIBUTE",
1076
- message: formatDbAttributeMigrationMessage(attribute),
1077
- sourceId: input.sourceId,
1078
- span: attribute.span
1079
- });
1080
- continue;
1081
- }
1082
- const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
1083
- familyId: input.familyId,
1084
- targetId: input.targetId,
1085
- authoringContributions: input.authoringContributions
1086
- });
1087
- if (uncomposedNamespace) {
1088
- reportUncomposedNamespace({
1089
- subjectLabel: `Attribute "@${attribute.name}"`,
1090
- namespace: uncomposedNamespace,
1091
- sourceId: input.sourceId,
1092
- span: attribute.span,
1093
- diagnostics: input.diagnostics
1094
- });
1095
- continue;
1096
- }
1097
- const baseMessage = `Field "${input.model.name}.${input.field.name}" uses unsupported attribute "@${attribute.name}"`;
1098
- const removedRule = REMOVED_ATTRIBUTE_RULES.get(attribute.name);
1099
- const message = removedRule && !removedRule.suppressWhen(input.field) ? `${baseMessage}. ${removedRule.hint}` : baseMessage;
1100
- input.diagnostics.push({
1101
- code: "PSL_UNSUPPORTED_FIELD_ATTRIBUTE",
1102
- message,
1103
- sourceId: input.sourceId,
1104
- span: attribute.span
1105
- });
1106
- }
1107
- }
1108
- function extractFieldConstraintNames(input) {
1109
- const idAttribute = getAttribute(input.field.attributes, "id");
1110
- const uniqueAttribute = getAttribute(input.field.attributes, "unique");
1111
- const idNode = findFieldAttributeNode(input.field, "id");
1112
- const idName = idNode === void 0 ? void 0 : interpretFieldAttribute({
1113
- node: idNode,
1114
- spec: idFieldSpec,
1115
- model: input.model,
1116
- field: input.field,
1117
- sourceFile: input.sourceFile,
1118
- sourceId: input.sourceId,
1119
- diagnostics: input.diagnostics
1120
- })?.map;
1121
- const uniqueNode = findFieldAttributeNode(input.field, "unique");
1122
- return {
1123
- idAttribute,
1124
- uniqueAttribute,
1125
- idName,
1126
- uniqueName: uniqueNode === void 0 ? void 0 : interpretFieldAttribute({
1127
- node: uniqueNode,
1128
- spec: uniqueFieldSpec,
1129
- model: input.model,
1130
- field: input.field,
1131
- sourceFile: input.sourceFile,
1132
- sourceId: input.sourceId,
1133
- diagnostics: input.diagnostics
1134
- })?.map
1135
- };
1136
- }
1137
- /**
1138
- * Interprets a field's `@noCheck` attribute and resolves it against the
1139
- * column's shape: the bare form becomes every kind the shape derives, and a
1140
- * named kind that can never apply is a spec-validation diagnostic on the
1141
- * attribute node. Returns the concrete kinds in canonical ascending order —
1142
- * the only form the definition tree carries.
1143
- */
1144
- function lowerNoCheckForField(input) {
1145
- const node = findFieldAttributeNode(input.field, "noCheck");
1146
- if (node === void 0) return void 0;
1147
- const interpreted = interpretFieldAttribute({
1148
- node,
1149
- spec: noCheckFieldSpec,
1150
- model: input.model,
1151
- field: input.field,
1152
- sourceFile: input.sourceFile,
1153
- sourceId: input.sourceId,
1154
- diagnostics: input.diagnostics
1155
- });
1156
- if (interpreted === void 0) return void 0;
1157
- const span = getAttribute(input.field.attributes, "noCheck")?.span ?? input.field.span;
1158
- const subject = `Field "${input.model.name}.${input.field.name}"`;
1159
- const derivable = [];
1160
- if (input.isListField) derivable.push("elementNotNull");
1161
- if (input.isDomainEnum) derivable.push("membership");
1162
- const authored = [interpreted.first, interpreted.second].filter((kind) => kind === "membership" || kind === "elementNotNull");
1163
- if (authored.length === 0) {
1164
- if (derivable.length === 0) {
1165
- input.diagnostics.push({
1166
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
1167
- message: `${subject} @noCheck waives nothing — this column's shape derives no generated checks`,
1168
- sourceId: input.sourceId,
1169
- span
1170
- });
1171
- return;
1172
- }
1173
- return derivable;
1174
- }
1175
- for (const kind of authored) if (!derivable.includes(kind)) {
1176
- const explanation = kind === "membership" ? "membership checks are derived only from enum value sets" : "element-non-null checks are derived only for list columns";
1177
- input.diagnostics.push({
1178
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
1179
- message: `${subject} @noCheck(${kind}) does not apply — ${explanation}`,
1180
- sourceId: input.sourceId,
1181
- span
1182
- });
1183
- return;
1184
- }
1185
- return [...authored].sort();
1186
- }
1187
- 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;
1189
- const resolvedFields = [];
1190
- const valueObjectStorageTypeName = authoringContributions?.valueObjectStorageType;
1191
- const declaredControlPolicy = getAttribute(model.attributes, "control")?.args.find((arg) => arg.kind === "positional")?.value.trim();
1192
- const modelDerivesChecks = declaredControlPolicy === void 0 || declaredControlPolicy === "managed";
1193
- for (const field of Object.values(model.fields)) {
1194
- const isModelField = modelNames.has(field.typeName);
1195
- if (field.list && isModelField) continue;
1196
- validateFieldAttributes({
1197
- model,
1198
- field,
1199
- composedExtensions,
1200
- authoringContributions,
1201
- diagnostics,
1202
- sourceId,
1203
- familyId,
1204
- targetId
1205
- });
1206
- const relationAttribute = getAttribute(field.attributes, "relation");
1207
- if (isModelField && relationAttribute) continue;
1208
- if (field.typeContractSpaceId !== void 0 && relationAttribute) continue;
1209
- if (isModelField) continue;
1210
- const isValueObjectField = compositeTypeNames.has(field.typeName);
1211
- const isListField = field.list;
1212
- let descriptor;
1213
- let scalarCodecId;
1214
- let presetContributions;
1215
- const resolveInput = {
1216
- field,
1217
- enumTypeDescriptors,
1218
- namedTypeDescriptors,
1219
- scalarColumnDescriptors,
1220
- authoringContributions,
1221
- composedExtensions,
1222
- familyId,
1223
- targetId,
1224
- diagnostics,
1225
- sourceId,
1226
- entityLabel: `Field "${model.name}.${field.name}"`,
1227
- ...ifDefined("namespaceId", namespaceId),
1228
- ...ifDefined("namespaceExtensionEntities", namespaceExtensionEntities),
1229
- ...ifDefined("codecLookup", codecLookup)
1230
- };
1231
- if (isValueObjectField) descriptor = valueObjectStorageTypeName !== void 0 ? scalarColumnDescriptors.get(valueObjectStorageTypeName) : void 0;
1232
- else if (isListField) {
1233
- if (capabilities["sql"]?.["scalarList"] !== true) {
1234
- diagnostics.push({
1235
- code: "PSL_SCALAR_LIST_UNSUPPORTED_TARGET",
1236
- message: `Field "${model.name}.${field.name}" is a scalar list, but target "${targetId}" does not support scalar lists (the adapter does not report the "scalarList" capability). Remove the list or author it against a target that supports scalar lists.`,
1237
- sourceId,
1238
- span: field.span
1239
- });
1240
- continue;
1241
- }
1242
- const resolved = resolveFieldTypeDescriptor(resolveInput);
1243
- if (!resolved.ok) {
1244
- if (!resolved.alreadyReported) diagnostics.push({
1245
- code: "PSL_UNSUPPORTED_FIELD_TYPE",
1246
- message: `Field "${model.name}.${field.name}" type "${field.typeName}" is not supported in SQL PSL provider v1`,
1247
- sourceId,
1248
- span: field.span
1249
- });
1250
- continue;
1251
- }
1252
- if (resolved.presetContributions) {
1253
- diagnostics.push({
1254
- code: "PSL_PRESET_NOT_LIST",
1255
- message: `Field "${model.name}.${field.name}" uses a field-preset call as a list element type. Presets cannot be list elements; remove "[]" or use a scalar type.`,
1256
- sourceId,
1257
- span: field.span
1258
- });
1259
- continue;
1260
- }
1261
- scalarCodecId = resolved.descriptor.codecId;
1262
- descriptor = resolved.descriptor;
1263
- } else {
1264
- const resolved = resolveFieldTypeDescriptor(resolveInput);
1265
- if (!resolved.ok) {
1266
- if (!resolved.alreadyReported) diagnostics.push({
1267
- code: "PSL_UNSUPPORTED_FIELD_TYPE",
1268
- message: `Field "${model.name}.${field.name}" type "${field.typeName}" is not supported in SQL PSL provider v1`,
1269
- sourceId,
1270
- span: field.span
1271
- });
1272
- continue;
1273
- }
1274
- descriptor = resolved.descriptor;
1275
- presetContributions = resolved.presetContributions;
1276
- }
1277
- if (!descriptor) continue;
1278
- if (presetContributions && field.optional) {
1279
- diagnostics.push({
1280
- code: "PSL_PRESET_NOT_OPTIONAL",
1281
- message: `Field "${model.name}.${field.name}" uses a field-preset call and cannot be optional. Remove "?" or use a different field type.`,
1282
- sourceId,
1283
- span: field.span
1284
- });
1285
- continue;
1286
- }
1287
- const defaultAttribute = getAttribute(field.attributes, "default");
1288
- if (presetContributions && defaultAttribute) {
1289
- diagnostics.push({
1290
- code: "PSL_PRESET_AND_DEFAULT_CONFLICT",
1291
- message: `Field "${model.name}.${field.name}" uses a field-preset call and cannot also declare @default(...). The preset already specifies the default value.`,
1292
- sourceId,
1293
- span: defaultAttribute.span
1294
- });
1295
- continue;
1296
- }
1297
- const enumHandle = enumHandles?.get(field.typeName);
1298
- const loweredDefault = defaultAttribute ? enumHandle ? lowerEnumDefaultForField({
1299
- modelName: model.name,
1300
- fieldName: field.name,
1301
- field,
1302
- model,
1303
- sourceFile: input.sourceFile,
1304
- enumHandle,
1305
- sourceId,
1306
- diagnostics
1307
- }) : lowerDefaultForField({
1308
- modelName: model.name,
1309
- fieldName: field.name,
1310
- field,
1311
- model,
1312
- sourceFile: input.sourceFile,
1313
- columnDescriptor: descriptor,
1314
- generatorDescriptorById,
1315
- sourceId,
1316
- defaultFunctionRegistry,
1317
- diagnostics,
1318
- isList: isListField
1319
- }) : {};
1320
- const loweredOnCreate = loweredDefault.executionDefaults?.onCreate;
1321
- const loweredFunctionDefault = loweredDefault.defaultValue?.kind === "function";
1322
- if (isListField && (loweredOnCreate || loweredFunctionDefault)) {
1323
- const defaultExpression = defaultAttribute?.args.find((arg) => arg.kind === "positional")?.value.trim() ?? "this function";
1324
- diagnostics.push({
1325
- code: "PSL_LIST_EXECUTION_DEFAULT_UNSUPPORTED",
1326
- message: `Field "${model.name}.${field.name}" is a list and cannot use an execution default ("${defaultExpression}"). Lists have no per-element execution-default semantics; use a literal list @default or remove the default.`,
1327
- sourceId,
1328
- span: defaultAttribute?.span ?? field.span
1329
- });
1330
- continue;
1331
- }
1332
- if (field.optional && loweredOnCreate) {
1333
- const generatorDescription = loweredOnCreate.kind === "generator" ? `"${loweredOnCreate.id}"` : "for this field";
1334
- diagnostics.push({
1335
- code: "PSL_INVALID_DEFAULT_FUNCTION_ARGUMENT",
1336
- message: `Field "${model.name}.${field.name}" cannot be optional when using execution default ${generatorDescription}. Remove "?" or use a storage default.`,
1337
- sourceId,
1338
- span: defaultAttribute?.span ?? field.span
1339
- });
1340
- continue;
1341
- }
1342
- const mappedColumnName = mapping.fieldColumns.get(field.name) ?? field.name;
1343
- const { idAttribute, uniqueAttribute, idName, uniqueName } = extractFieldConstraintNames({
1344
- model,
1345
- field,
1346
- sourceFile: input.sourceFile,
1347
- sourceId,
1348
- diagnostics
1349
- });
1350
- let isIdField = Boolean(idAttribute);
1351
- if (idAttribute && isListField) {
1352
- diagnostics.push({
1353
- code: "PSL_LIST_ID_UNSUPPORTED",
1354
- message: `Field "${model.name}.${field.name}" is a list and cannot be a primary key. Remove @id; a list cannot be an identity column.`,
1355
- sourceId,
1356
- span: idAttribute.span
1357
- });
1358
- continue;
1359
- }
1360
- if (idAttribute && field.optional) {
1361
- diagnostics.push({
1362
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
1363
- message: `Field "${model.name}.${field.name}" @id cannot be optional; primary key columns must be NOT NULL`,
1364
- sourceId,
1365
- span: idAttribute.span
1366
- });
1367
- isIdField = false;
1368
- }
1369
- if (presetContributions && idAttribute && !presetContributions.id) {
1370
- diagnostics.push({
1371
- code: "PSL_PRESET_AND_ID_CONFLICT",
1372
- message: `Field "${model.name}.${field.name}" uses a field-preset call and cannot also declare @id. Use a preset that contributes id semantics, or drop @id.`,
1373
- sourceId,
1374
- span: idAttribute.span
1375
- });
1376
- continue;
1377
- }
1378
- const fieldExecutionDefaults = presetContributions?.executionDefaults ?? loweredDefault.executionDefaults;
1379
- const fieldDefaultValue = presetContributions?.default ?? loweredDefault.defaultValue;
1380
- const noCheckKinds = modelDerivesChecks ? lowerNoCheckForField({
1381
- model,
1382
- field,
1383
- sourceFile: input.sourceFile,
1384
- sourceId,
1385
- isListField: isListField && !isValueObjectField,
1386
- isDomainEnum: enumHandle !== void 0,
1387
- diagnostics
1388
- }) : void 0;
1389
- resolvedFields.push({
1390
- field,
1391
- columnName: mappedColumnName,
1392
- descriptor,
1393
- nullable: presetContributions?.nullable ?? field.optional,
1394
- ...ifDefined("defaultValue", fieldDefaultValue),
1395
- ...ifDefined("executionDefaults", fieldExecutionDefaults),
1396
- isId: isIdField || Boolean(presetContributions?.id),
1397
- isUnique: Boolean(uniqueAttribute) || Boolean(presetContributions?.unique),
1398
- ...ifDefined("idName", idName),
1399
- ...ifDefined("uniqueName", uniqueName),
1400
- ...ifDefined("many", isListField ? true : void 0),
1401
- ...ifDefined("noCheck", noCheckKinds),
1402
- ...ifDefined("valueObjectTypeName", isValueObjectField ? field.typeName : void 0),
1403
- ...ifDefined("scalarCodecId", scalarCodecId)
1404
- });
1405
- }
1406
- return resolvedFields;
1407
- }
1408
- function buildModelMappings(modelEntries, defaultNamespaceId, diagnostics, sourceId, sourceFile) {
1409
- const result = /* @__PURE__ */ new Map();
1410
- for (const { model, namespaceId } of modelEntries) {
1411
- const mapNode = findModelAttributeNode(model, "map");
1412
- const tableName = mapNode === void 0 ? lowerFirst(model.name) : interpretModelAttribute({
1413
- node: mapNode,
1414
- spec: mapModelSpec,
1415
- model,
1416
- sourceFile,
1417
- sourceId,
1418
- diagnostics
1419
- })?.name ?? lowerFirst(model.name);
1420
- const fieldColumns = /* @__PURE__ */ new Map();
1421
- for (const field of Object.values(model.fields)) {
1422
- const fieldMapNode = findFieldAttributeNode(field, "map");
1423
- const columnName = fieldMapNode === void 0 ? field.name : interpretFieldAttribute({
1424
- node: fieldMapNode,
1425
- spec: mapFieldSpec,
1426
- model,
1427
- field,
1428
- sourceFile,
1429
- sourceId,
1430
- diagnostics
1431
- })?.name ?? field.name;
1432
- fieldColumns.set(field.name, columnName);
1433
- }
1434
- result.set(modelCoordinateKey(namespaceId ?? defaultNamespaceId, model.name), {
1435
- model,
1436
- tableName,
1437
- fieldColumns
1438
- });
1439
- }
1440
- return result;
1441
- }
1442
- function validateNamedTypeAttributes(input) {
1443
- let hasUnsupportedNamedTypeAttribute = false;
1444
- for (const attribute of input.declaration.attributes) {
1445
- if (attribute.name.startsWith("db.")) {
1446
- input.diagnostics.push({
1447
- code: "PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE",
1448
- message: formatDbAttributeMigrationMessage(attribute),
1449
- sourceId: input.sourceId,
1450
- span: attribute.span
1451
- });
1452
- hasUnsupportedNamedTypeAttribute = true;
1453
- continue;
1454
- }
1455
- const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
1456
- familyId: input.familyId,
1457
- targetId: input.targetId,
1458
- authoringContributions: input.authoringContributions
1459
- });
1460
- if (uncomposedNamespace) {
1461
- reportUncomposedNamespace({
1462
- subjectLabel: `Attribute "@${attribute.name}"`,
1463
- namespace: uncomposedNamespace,
1464
- sourceId: input.sourceId,
1465
- span: attribute.span,
1466
- diagnostics: input.diagnostics
1467
- });
1468
- hasUnsupportedNamedTypeAttribute = true;
1469
- continue;
1470
- }
1471
- input.diagnostics.push({
1472
- code: "PSL_UNSUPPORTED_NAMED_TYPE_ATTRIBUTE",
1473
- message: `Named type "${input.declaration.name}" uses unsupported attribute "${attribute.name}"`,
1474
- sourceId: input.sourceId,
1475
- span: attribute.span
1476
- });
1477
- hasUnsupportedNamedTypeAttribute = true;
1478
- }
1479
- return hasUnsupportedNamedTypeAttribute;
1480
- }
1481
- function resolveNamedTypeDeclarations(input) {
1482
- const storageTypeEntries = [];
1483
- const namedTypeDescriptors = /* @__PURE__ */ new Map();
1484
- for (const declaration of input.declarations) {
1485
- if (declaration.isConstructor) {
1486
- const typeConstructor = declaration.typeConstructor;
1487
- if (typeConstructor === void 0) {
1488
- input.diagnostics.push({
1489
- code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
1490
- message: `Named type "${declaration.name}" must declare a base type or constructor`,
1491
- sourceId: input.sourceId,
1492
- span: declaration.span
1493
- });
1494
- continue;
1495
- }
1496
- if (validateNamedTypeAttributes({
1497
- declaration,
1498
- sourceId: input.sourceId,
1499
- diagnostics: input.diagnostics,
1500
- composedExtensions: input.composedExtensions,
1501
- authoringContributions: input.authoringContributions,
1502
- familyId: input.familyId,
1503
- targetId: input.targetId
1504
- })) continue;
1505
- const helperPath = typeConstructor.path.join(".");
1506
- const descriptor = resolvePslTypeConstructorDescriptor({
1507
- call: typeConstructor,
1508
- authoringContributions: input.authoringContributions,
1509
- composedExtensions: input.composedExtensions,
1510
- familyId: input.familyId,
1511
- targetId: input.targetId,
1512
- diagnostics: input.diagnostics,
1513
- sourceId: input.sourceId,
1514
- unsupportedCode: "PSL_UNSUPPORTED_NAMED_TYPE_CONSTRUCTOR",
1515
- unsupportedMessage: `Named type "${declaration.name}" references unsupported constructor "${helperPath}"`
1516
- });
1517
- if (!descriptor) continue;
1518
- const storageType = instantiatePslTypeConstructor({
1519
- call: typeConstructor,
1520
- descriptor,
1521
- diagnostics: input.diagnostics,
1522
- sourceId: input.sourceId,
1523
- entityLabel: `Named type "${declaration.name}"`
1524
- });
1525
- if (!storageType) continue;
1526
- namedTypeDescriptors.set(declaration.name, toNamedTypeFieldDescriptor(declaration.name, storageType));
1527
- storageTypeEntries.push([declaration.name, {
1528
- kind: "codec-instance",
1529
- codecId: storageType.codecId,
1530
- nativeType: storageType.nativeType,
1531
- typeParams: storageType.typeParams ?? {}
1532
- }]);
1533
- continue;
1534
- }
1535
- const baseType = declaration.baseType;
1536
- if (baseType === void 0) {
1537
- input.diagnostics.push({
1538
- code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
1539
- message: `Named type "${declaration.name}" must declare a base type or constructor`,
1540
- sourceId: input.sourceId,
1541
- span: declaration.span
1542
- });
1543
- continue;
1544
- }
1545
- const baseDescriptor = input.enumTypeDescriptors.get(baseType) ?? input.scalarColumnDescriptors.get(baseType);
1546
- if (!baseDescriptor) {
1547
- input.diagnostics.push({
1548
- code: "PSL_UNSUPPORTED_NAMED_TYPE_BASE",
1549
- message: `Named type "${declaration.name}" references unsupported base type "${baseType}"`,
1550
- sourceId: input.sourceId,
1551
- span: declaration.span
1552
- });
1553
- continue;
1554
- }
1555
- if (validateNamedTypeAttributes({
1556
- declaration,
1557
- sourceId: input.sourceId,
1558
- diagnostics: input.diagnostics,
1559
- composedExtensions: input.composedExtensions,
1560
- authoringContributions: input.authoringContributions,
1561
- familyId: input.familyId,
1562
- targetId: input.targetId
1563
- })) continue;
1564
- const descriptor = toNamedTypeFieldDescriptor(declaration.name, baseDescriptor);
1565
- namedTypeDescriptors.set(declaration.name, descriptor);
1566
- storageTypeEntries.push([declaration.name, {
1567
- kind: "codec-instance",
1568
- codecId: baseDescriptor.codecId,
1569
- nativeType: baseDescriptor.nativeType,
1570
- typeParams: baseDescriptor.typeParams ?? {}
1571
- }]);
1572
- }
1573
- return {
1574
- storageTypes: Object.fromEntries(storageTypeEntries),
1575
- namedTypeDescriptors
1576
- };
1577
- }
1578
- const REFERENTIAL_ACTION_MAP = {
1579
- NoAction: "noAction",
1580
- Restrict: "restrict",
1581
- Cascade: "cascade",
1582
- SetNull: "setNull",
1583
- SetDefault: "setDefault",
1584
- noAction: "noAction",
1585
- restrict: "restrict",
1586
- cascade: "cascade",
1587
- setNull: "setNull",
1588
- setDefault: "setDefault"
1589
- };
1590
- function fkRelationPairKey(declaringModelName, targetModelName) {
1591
- return `${declaringModelName}::${targetModelName}`;
1592
- }
1593
- function normalizeReferentialAction(actionToken) {
1594
- return REFERENTIAL_ACTION_MAP[actionToken];
1595
- }
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
- function resolveReferencedModel(symbols, field) {
1643
- const topLevel = symbols.topLevel.models[field.typeName];
1644
- if (topLevel !== void 0) return topLevel;
1645
- for (const namespace of Object.values(symbols.topLevel.namespaces)) {
1646
- const model = namespace.models[field.typeName];
1647
- if (model !== void 0) return model;
1648
- }
1649
- }
1650
- function interpretRelationAttribute(input) {
1651
- const node = findFieldAttributeNode(input.field, "relation");
1652
- if (node === void 0) return void 0;
1653
- return interpretFieldAttribute({
1654
- node,
1655
- spec: sqlRelation,
1656
- model: input.selfModel,
1657
- field: input.field,
1658
- sourceFile: input.sourceFile,
1659
- sourceId: input.sourceId,
1660
- diagnostics: input.diagnostics,
1661
- resolveReferencedModel: () => resolveReferencedModel(input.symbols, input.field)
1662
- });
1663
- }
1664
- function indexFkRelations(input) {
1665
- const modelRelations = /* @__PURE__ */ new Map();
1666
- const fkRelationsByPair = /* @__PURE__ */ new Map();
1667
- const fkRelationsByDeclaringModel = /* @__PURE__ */ new Map();
1668
- for (const relation of input.fkRelationMetadata) {
1669
- const declaringFkRelations = fkRelationsByDeclaringModel.get(relation.declaringModelName);
1670
- if (declaringFkRelations) declaringFkRelations.push(relation);
1671
- else fkRelationsByDeclaringModel.set(relation.declaringModelName, [relation]);
1672
- const existing = modelRelations.get(relation.declaringModelName);
1673
- const current = existing ?? [];
1674
- if (!existing) modelRelations.set(relation.declaringModelName, current);
1675
- current.push({
1676
- fieldName: relation.declaringFieldName,
1677
- toModel: relation.targetModelName,
1678
- toTable: relation.targetTableName,
1679
- ...ifDefined("toNamespaceId", relation.targetNamespaceId),
1680
- cardinality: "N:1",
1681
- on: {
1682
- parentTable: relation.declaringTableName,
1683
- parentColumns: relation.localColumns,
1684
- childTable: relation.targetTableName,
1685
- childColumns: relation.referencedColumns
1686
- }
1687
- });
1688
- const pairKey = fkRelationPairKey(relation.declaringModelName, relation.targetModelName);
1689
- const pairRelations = fkRelationsByPair.get(pairKey);
1690
- if (!pairRelations) {
1691
- fkRelationsByPair.set(pairKey, [relation]);
1692
- continue;
1693
- }
1694
- pairRelations.push(relation);
1695
- }
1696
- return {
1697
- modelRelations,
1698
- fkRelationsByPair,
1699
- fkRelationsByDeclaringModel
1700
- };
1701
- }
1702
- function idColumnsAreExactlyFkPair(idColumns, parentColumns, childColumns) {
1703
- if (idColumns.length !== parentColumns.length + childColumns.length) return false;
1704
- const fkColumns = /* @__PURE__ */ new Set([...parentColumns, ...childColumns]);
1705
- if (fkColumns.size !== parentColumns.length + childColumns.length) return false;
1706
- return idColumns.every((column) => fkColumns.has(column));
1707
- }
1708
- /**
1709
- * Reorders the child FK's junction columns into the target model's id-column
1710
- * order. Returns undefined unless the FK references exactly the target's full
1711
- * id, because downstream consumers pair `through.childColumns` positionally
1712
- * against the target id columns — an FK referencing anything else (a non-id
1713
- * unique, a partial id) would produce a silently wrong join.
1714
- */
1715
- function childColumnsInTargetIdOrder(childFk, targetIdColumns) {
1716
- if (childFk.referencedColumns.length !== targetIdColumns.length) return;
1717
- const localByReferenced = /* @__PURE__ */ new Map();
1718
- for (const [index, referencedColumn] of childFk.referencedColumns.entries()) {
1719
- const localColumn = childFk.localColumns[index];
1720
- if (localColumn === void 0) return;
1721
- localByReferenced.set(referencedColumn, localColumn);
1722
- }
1723
- if (localByReferenced.size !== targetIdColumns.length) return;
1724
- const ordered = [];
1725
- for (const idColumn of targetIdColumns) {
1726
- const localColumn = localByReferenced.get(idColumn);
1727
- if (localColumn === void 0) return;
1728
- ordered.push(localColumn);
1729
- }
1730
- return ordered;
1731
- }
1732
- /**
1733
- * Finds explicit junction models that connect a bare backrelation list field
1734
- * to its target model: a model whose composite id columns are exactly the FK
1735
- * columns of one relation back to the candidate's model (the parent side) and
1736
- * one relation to the candidate's target model (the child side). The child
1737
- * FK must reference exactly the target model's id columns; its junction
1738
- * columns are carried in target-id order on the pair. A relation name on the
1739
- * list field pins the parent-side FK relation, which is how self-referential
1740
- * many-to-many sides are disambiguated.
1741
- *
1742
- * Alongside the recognised pairs, returns junction-shaped near-misses (models
1743
- * that link both sides but were declined) so the caller can emit a
1744
- * junction-specific diagnostic instead of the generic orphaned-list message.
1745
- */
1746
- function findJunctionFkPairs(input) {
1747
- const targetIdColumns = input.modelIdColumns.get(input.candidate.targetModelName);
1748
- if (!targetIdColumns || targetIdColumns.length === 0) return {
1749
- pairs: [],
1750
- nearMisses: []
1751
- };
1752
- const pairs = [];
1753
- const nearMisses = [];
1754
- for (const [junctionModelName, junctionFks] of input.fkRelationsByDeclaringModel) {
1755
- const idColumns = input.modelIdColumns.get(junctionModelName);
1756
- for (const parentFk of junctionFks) {
1757
- if (parentFk.targetModelName !== input.candidate.modelName) continue;
1758
- if (input.candidate.relationName !== void 0 && parentFk.relationName !== input.candidate.relationName) continue;
1759
- for (const childFk of junctionFks) {
1760
- if (childFk === parentFk || childFk.targetModelName !== input.candidate.targetModelName) continue;
1761
- if (!idColumns || !idColumnsAreExactlyFkPair(idColumns, parentFk.localColumns, childFk.localColumns)) {
1762
- nearMisses.push({
1763
- junctionModelName,
1764
- reason: "id-not-fk-covering"
1765
- });
1766
- continue;
1767
- }
1768
- const orderedChildColumns = childColumnsInTargetIdOrder(childFk, targetIdColumns);
1769
- if (!orderedChildColumns) {
1770
- nearMisses.push({
1771
- junctionModelName,
1772
- reason: "target-fk-not-id"
1773
- });
1774
- continue;
1775
- }
1776
- pairs.push({
1777
- parentFk,
1778
- childFk,
1779
- childColumnsInTargetIdOrder: orderedChildColumns
1780
- });
1781
- }
1782
- }
1783
- }
1784
- return {
1785
- pairs,
1786
- nearMisses
1787
- };
1788
- }
1789
- function junctionNearMissDiagnostic(candidate, nearMiss, sourceId) {
1790
- const listField = `${candidate.modelName}.${candidate.field.name}`;
1791
- const data = {
1792
- listField,
1793
- junctionModel: nearMiss.junctionModelName,
1794
- targetModel: candidate.targetModelName
1795
- };
1796
- if (nearMiss.reason === "target-fk-not-id") return {
1797
- code: "PSL_JUNCTION_TARGET_FK_NOT_ID",
1798
- message: `Backrelation list field "${listField}" found junction model "${nearMiss.junctionModelName}", but its foreign key to "${candidate.targetModelName}" does not reference "${candidate.targetModelName}"'s @id. The junction's target-side foreign key must reference "${candidate.targetModelName}"'s full @id columns for many-to-many recognition.`,
1799
- sourceId,
1800
- span: candidate.field.span,
1801
- data
1802
- };
1803
- return {
1804
- code: "PSL_JUNCTION_ID_NOT_FK_COVERING",
1805
- message: `Backrelation list field "${listField}" found junction-shaped model "${nearMiss.junctionModelName}" linking "${candidate.modelName}" and "${candidate.targetModelName}", but its id does not cover exactly its foreign-key columns. Declare @@id([...]) on "${nearMiss.junctionModelName}" listing exactly the two foreign-key columns for many-to-many recognition.`,
1806
- sourceId,
1807
- span: candidate.field.span,
1808
- data
1809
- };
1810
- }
1811
- function manyToManyRelationNode(candidate, pair) {
1812
- return {
1813
- fieldName: candidate.field.name,
1814
- toModel: pair.childFk.targetModelName,
1815
- toTable: pair.childFk.targetTableName,
1816
- ...ifDefined("toNamespaceId", pair.childFk.targetNamespaceId),
1817
- cardinality: "N:M",
1818
- on: {
1819
- parentTable: candidate.tableName,
1820
- parentColumns: pair.parentFk.referencedColumns,
1821
- childTable: pair.parentFk.declaringTableName,
1822
- childColumns: pair.parentFk.localColumns
1823
- },
1824
- through: {
1825
- table: pair.parentFk.declaringTableName,
1826
- ...ifDefined("namespaceId", pair.parentFk.declaringNamespaceId),
1827
- parentColumns: pair.parentFk.localColumns,
1828
- childColumns: pair.childColumnsInTargetIdOrder
1829
- }
1830
- };
1831
- }
1832
- function relationsForModel(modelRelations, modelName) {
1833
- const existing = modelRelations.get(modelName);
1834
- if (existing) return existing;
1835
- const created = [];
1836
- modelRelations.set(modelName, created);
1837
- return created;
1838
- }
1839
- /**
1840
- * A set of columns is unique when it exactly matches one of the model's unique
1841
- * column sets — its primary key or any single- or multi-column `@unique` /
1842
- * `@@unique` constraint. Set equality (not subset) is required: a singular
1843
- * back-relation means at most one child per parent, which a unique constraint
1844
- * covering exactly the FK columns guarantees.
1845
- */
1846
- function fkColumnsAreUnique(localColumns, uniqueColumnSets) {
1847
- const local = new Set(localColumns);
1848
- return uniqueColumnSets.some((columns) => columns.length === local.size && columns.every((column) => local.has(column)));
1849
- }
1850
- function applyBackrelationCandidates(input) {
1851
- for (const candidate of input.backrelationCandidates) {
1852
- const pairKey = fkRelationPairKey(candidate.targetModelName, candidate.modelName);
1853
- const pairMatches = input.fkRelationsByPair.get(pairKey) ?? [];
1854
- const matches = candidate.relationName ? pairMatches.filter((relation) => relation.relationName === candidate.relationName) : [...pairMatches];
1855
- if (matches.length === 0) {
1856
- if (candidate.isList) {
1857
- const { pairs: junctionPairs, nearMisses } = findJunctionFkPairs({
1858
- candidate,
1859
- fkRelationsByDeclaringModel: input.fkRelationsByDeclaringModel,
1860
- modelIdColumns: input.modelIdColumns
1861
- });
1862
- const junctionPair = junctionPairs[0];
1863
- if (junctionPairs.length === 1 && junctionPair) {
1864
- relationsForModel(input.modelRelations, candidate.modelName).push(manyToManyRelationNode(candidate, junctionPair));
1865
- continue;
1866
- }
1867
- if (junctionPairs.length > 1) {
1868
- input.diagnostics.push({
1869
- code: "PSL_AMBIGUOUS_BACKRELATION",
1870
- message: `Backrelation list field "${candidate.modelName}.${candidate.field.name}" matches multiple junction FK pairs for a many-to-many relation. Add @relation(name: "...") (or @relation("...")) to the list field and the junction FK-side relation pointing back at "${candidate.modelName}" to disambiguate.`,
1871
- sourceId: input.sourceId,
1872
- span: candidate.field.span
1873
- });
1874
- continue;
1875
- }
1876
- const nearMiss = nearMisses[0];
1877
- if (nearMiss) {
1878
- input.diagnostics.push(junctionNearMissDiagnostic(candidate, nearMiss, input.sourceId));
1879
- continue;
1880
- }
1881
- }
1882
- input.diagnostics.push({
1883
- code: "PSL_ORPHANED_BACKRELATION",
1884
- message: `Backrelation field "${candidate.modelName}.${candidate.field.name}" has no matching FK-side relation on model "${candidate.targetModelName}". Add @relation(fields: [...], references: [...]) on the FK-side relation${candidate.isList ? " or use an explicit join model for many-to-many" : ""}.`,
1885
- sourceId: input.sourceId,
1886
- span: candidate.field.span
1887
- });
1888
- continue;
1889
- }
1890
- if (matches.length > 1) {
1891
- input.diagnostics.push({
1892
- code: "PSL_AMBIGUOUS_BACKRELATION",
1893
- message: `Backrelation field "${candidate.modelName}.${candidate.field.name}" matches multiple FK-side relations on model "${candidate.targetModelName}". Add @relation(name: "...") (or @relation("...")) to both sides to disambiguate.`,
1894
- sourceId: input.sourceId,
1895
- span: candidate.field.span
1896
- });
1897
- continue;
1898
- }
1899
- invariant(matches.length === 1, "Backrelation matching requires exactly one match");
1900
- const matched = matches[0];
1901
- assertDefined(matched, "Backrelation matching requires a defined relation match");
1902
- if (!candidate.isList) {
1903
- const uniqueColumnSets = input.modelUniqueColumnSets.get(matched.declaringModelName) ?? [];
1904
- if (!fkColumnsAreUnique(matched.localColumns, uniqueColumnSets)) {
1905
- input.diagnostics.push({
1906
- code: "PSL_NON_UNIQUE_BACKRELATION",
1907
- message: `Backrelation field "${candidate.modelName}.${candidate.field.name}" is singular, but the matching FK on "${matched.declaringModelName}" (fields ${matched.localColumns.map((column) => `"${column}"`).join(", ")}) is not unique. A singular back-relation implies at most one related row; add @unique (or @@unique([...])) to the FK fields, or make "${candidate.field.name}" a list.`,
1908
- sourceId: input.sourceId,
1909
- span: candidate.field.span
1910
- });
1911
- continue;
1912
- }
1913
- }
1914
- relationsForModel(input.modelRelations, candidate.modelName).push({
1915
- fieldName: candidate.field.name,
1916
- toModel: matched.declaringModelName,
1917
- toTable: matched.declaringTableName,
1918
- ...ifDefined("toNamespaceId", matched.declaringNamespaceId),
1919
- cardinality: candidate.isList ? "1:N" : "1:1",
1920
- on: {
1921
- parentTable: candidate.tableName,
1922
- parentColumns: matched.referencedColumns,
1923
- childTable: matched.declaringTableName,
1924
- childColumns: matched.localColumns
1925
- }
1926
- });
1927
- }
1928
- }
1929
- function validateBackrelationFieldAttributes(input) {
1930
- let valid = true;
1931
- for (const attribute of input.field.attributes) {
1932
- if (attribute.name === "relation") continue;
1933
- const uncomposedNamespace = checkUncomposedNamespace(attribute.name, input.composedExtensions, {
1934
- familyId: input.familyId,
1935
- targetId: input.targetId,
1936
- authoringContributions: input.authoringContributions
1937
- });
1938
- if (uncomposedNamespace) {
1939
- reportUncomposedNamespace({
1940
- subjectLabel: `Attribute "@${attribute.name}"`,
1941
- namespace: uncomposedNamespace,
1942
- sourceId: input.sourceId,
1943
- span: attribute.span,
1944
- diagnostics: input.diagnostics
1945
- });
1946
- valid = false;
1947
- continue;
1948
- }
1949
- input.diagnostics.push({
1950
- code: "PSL_UNSUPPORTED_FIELD_ATTRIBUTE",
1951
- message: `Field "${input.modelName}.${input.field.name}" uses unsupported attribute "@${attribute.name}"`,
1952
- sourceId: input.sourceId,
1953
- span: attribute.span
1954
- });
1955
- valid = false;
1956
- }
1957
- return valid;
1958
- }
1959
- function buildComposedExtensionPackRefs(target, extensionIds, extensionPackRefs = []) {
1960
- if (extensionIds.length === 0) return;
1961
- const extensionPackRefById = new Map(extensionPackRefs.map((packRef) => [packRef.id, packRef]));
1962
- return Object.fromEntries(extensionIds.map((extensionId) => [extensionId, extensionPackRefById.get(extensionId) ?? {
1963
- kind: "extension",
1964
- id: extensionId,
1965
- familyId: target.familyId,
1966
- targetId: target.targetId,
1967
- version: "0.0.1"
1968
- }]));
1969
- }
1970
- function compareStrings(left, right) {
1971
- if (left < right) return -1;
1972
- if (left > right) return 1;
1973
- return 0;
1974
- }
1975
- /**
1976
- * Name of the framework-parser synthesised bucket for top-level
1977
- * declarations. Re-declared here so the per-target dispatch does not
1978
- * have to import from `@internal/framework-components/psl-ast`
1979
- * (which would cross a layer that the interpreter does not otherwise
1980
- * import from). The value is part of the framework parser's contract;
1981
- * if it changes there, the matching test in this package's
1982
- * `interpreter.diagnostics.test.ts` flips first.
1983
- */
1984
- const UNSPECIFIED_PSL_NAMESPACE_NAME = "__unspecified__";
1985
- /**
1986
- * Per-target namespace-block validation: walk the AST's namespace buckets and
1987
- * emit diagnostics for syntactic constructs the target does not accept.
1988
- *
1989
- * - **SQLite** has no schema concept and rejects every explicit
1990
- * `namespace { … }` block. The implicit `__unspecified__` bucket
1991
- * (produced by the parser for top-level declarations outside any
1992
- * block) is the only namespace SQLite accepts.
1993
- * - **Postgres** accepts every explicit block — `namespace unbound { … }`
1994
- * is the late-binding opt-in (lowers to the IR `__unbound__` slot in
1995
- * a follow-on commit), `namespace public { … }` reopen-merges with
1996
- * the implicit bucket, and any other name lowers to a named schema.
1997
- *
1998
- * Storage-side lowering of these buckets to IR namespace slots is not
1999
- * yet wired; this helper closes only the diagnostic surface.
2000
- */
2001
- /**
2002
- * Per-target namespace lowering: map a PSL AST namespace bucket name to the
2003
- * resolved IR namespace id (the key downstream consumers use against
2004
- * `SqlStorage.namespaces`).
2005
- *
2006
- * - **Postgres**: an explicit `namespace unbound { … }` block lowers
2007
- * to the framework sentinel `__unbound__` — the slot whose binding
2008
- * the connection's `search_path` resolves at runtime. Every other
2009
- * explicit bucket name (e.g. `auth`, `public`) passes through as a
2010
- * named schema id. The implicit `__unspecified__` bucket — top-level
2011
- * declarations outside any `namespace { … }` block — leaves the
2012
- * coordinate unset; downstream consumers treat unset as the
2013
- * late-bound default, and TS / PSL authoring stay byte-identical
2014
- * on single-namespace contracts. (A future round will add a
2015
- * target-default-namespace surface so `__unspecified__` lowers to
2016
- * `public` consistently on both authoring paths.)
2017
- * - **SQLite**: SQLite has no schema concept; every namespace
2018
- * collapses to the late-bound default. The namespace-block
2019
- * validation step (above) has already rejected any explicit
2020
- * `namespace { … }` block on SQLite, so the only bucket the
2021
- * lowering ever sees there is `__unspecified__`.
2022
- *
2023
- * Returns `undefined` for targets / bucket names with no explicit
2024
- * namespaceId to assign — callers leave the model's `namespaceId`
2025
- * slot empty (which means the late-bound default at the `StorageTable`
2026
- * layer; emitted JSON omits the field).
2027
- */
2028
- function resolveNamespaceIdForSqlTarget(input) {
2029
- if (input.targetId !== "postgres") return;
2030
- if (input.bucketName === UNSPECIFIED_PSL_NAMESPACE_NAME) return "public";
2031
- if (input.bucketName === "unbound") return UNBOUND_NAMESPACE_ID;
2032
- return input.bucketName;
2033
- }
2034
- /**
2035
- * A namespace block is the unbound block when its name RESOLVES to the
2036
- * unbound id — both the `namespace unbound { }` spelling (mapped by
2037
- * {@link resolveNamespaceIdForSqlTarget}) and the raw sentinel spelling
2038
- * `namespace __unbound__ { }` (passed through verbatim) behave identically:
2039
- * same models-sibling restriction, same block-lowering bucket.
2040
- */
2041
- function isUnboundNamespaceBlock(ns, targetId) {
2042
- return resolveNamespaceIdForSqlTarget({
2043
- bucketName: ns.name,
2044
- targetId
2045
- }) === UNBOUND_NAMESPACE_ID;
2046
- }
2047
- function validateNamespaceBlocksForSqlTarget(input) {
2048
- if (input.targetId === "sqlite") {
2049
- for (const namespace of input.namespaces) input.diagnostics.push({
2050
- code: "PSL_UNSUPPORTED_NAMESPACE_BLOCK",
2051
- message: `SQLite does not support \`namespace ${namespace.name} { … }\` blocks (SQLite has no schema concept; declare models at the document top level instead).`,
2052
- sourceId: input.sourceId,
2053
- span: nodePslSpan(namespace.node.syntax, input.sourceFile)
2054
- });
2055
- return;
2056
- }
2057
- if (input.targetId === "postgres") {
2058
- const unboundBlock = input.namespaces.find((ns) => isUnboundNamespaceBlock(ns, input.targetId) && Object.keys(ns.models).length > 0);
2059
- const hasSibling = input.namespaces.some((ns) => !isUnboundNamespaceBlock(ns, input.targetId));
2060
- if (unboundBlock !== void 0 && hasSibling) input.diagnostics.push({
2061
- code: "PSL_RESERVED_NAMESPACE_NAME",
2062
- message: "Namespace \"unbound\" is reserved for the late-binding sentinel mapping; a `namespace unbound { … }` containing models cannot appear alongside other named namespace blocks. Use `namespace unbound { … }` alone (no sibling named namespaces) for late-binding multi-tenant contracts.",
2063
- sourceId: input.sourceId,
2064
- span: nodePslSpan(unboundBlock.node.syntax, input.sourceFile)
2065
- });
2066
- }
2067
- }
2068
- /**
2069
- * Walks the flat `entityTypes` namespace tree in `authoringContributions` and
2070
- * returns a map from discriminator string to the matching descriptor. The
2071
- * interpreter uses this to dispatch parsed extension blocks to their factory
2072
- * without naming any specific discriminator value (generic, by-discriminator).
2073
- */
2074
- function buildEntityTypesByDiscriminator(contributions) {
2075
- const result = /* @__PURE__ */ new Map();
2076
- const namespace = contributions?.entityTypes;
2077
- if (namespace === void 0) return result;
2078
- const walk = (node) => {
2079
- for (const value of Object.values(node)) if (isAuthoringEntityTypeDescriptor(value)) result.set(value.discriminator, value);
2080
- else if (typeof value === "object" && value !== null) walk(value);
2081
- };
2082
- walk(namespace);
2083
- return result;
2084
- }
2085
- /**
2086
- * The `PSL_DUPLICATE_ATTRIBUTE` diagnostic for a model attribute declared
2087
- * more than once on one model. Shared by the built-in `@@control` path and
2088
- * the contributed-model-attribute path so the code and wording stay in one
2089
- * place. `name` is the bare attribute name (`control`, `rls`, …).
2090
- */
2091
- function duplicateModelAttributeDiagnostic(input) {
2092
- return {
2093
- code: "PSL_DUPLICATE_ATTRIBUTE",
2094
- message: `\`@@${input.name}\` declared more than once on model "${input.modelName}".`,
2095
- sourceId: input.sourceId,
2096
- ...ifDefined("span", input.span)
2097
- };
2098
- }
2099
- /**
2100
- * Enforces `AuthoringPslBlockDescriptor.requiresModelAttribute` over one
2101
- * scope (the top level or one namespace): every block whose descriptor
2102
- * declares the requirement must name a model that carries the required
2103
- * bare `@@` attribute. Runs on the parsed symbol table, so it is
2104
- * independent of block/model declaration order and of lowering order. A
2105
- * missing parameter or an unresolvable model is skipped — the
2106
- * missing-required-parameter and unresolved-ref diagnostics own those
2107
- * failure modes.
2108
- */
2109
- function validateBlockModelAttributeRequirements(input) {
2110
- for (const scope of input.scopes) for (const blockSymbol of Object.values(scope.blocks)) {
2111
- const requirement = findBlockDescriptor(input.pslBlockDescriptors, blockSymbol.keyword)?.requiresModelAttribute;
2112
- if (requirement === void 0) continue;
2113
- const captured = blockSymbol.block.parameters[requirement.parameter];
2114
- if (captured?.kind !== "ref") continue;
2115
- const model = scope.models[captured.identifier];
2116
- if (model === void 0) continue;
2117
- if (model.attributes.some((attribute) => attribute.name === requirement.attribute)) continue;
2118
- input.diagnostics.push({
2119
- code: "PSL_EXTENSION_TARGET_MODEL_MISSING_ATTRIBUTE",
2120
- message: `\`${blockSymbol.keyword}\` block "${blockSymbol.block.name}" targets model "${captured.identifier}", which does not declare \`@@${requirement.attribute}\`. Add \`@@${requirement.attribute}\` to model "${captured.identifier}".`,
2121
- sourceId: input.sourceId,
2122
- span: captured.span
2123
- });
2124
- }
2125
- }
2126
- /**
2127
- * Walks the flat `modelAttributes` namespace tree in `authoringContributions`
2128
- * and returns a map from bare `@@` attribute name to the matching
2129
- * descriptor. The model-attribute loop in `buildModelNodeFromPsl` uses this
2130
- * to dispatch a contributed attribute without naming any specific attribute.
2131
- */
2132
- function buildModelAttributesByName(contributions) {
2133
- const result = /* @__PURE__ */ new Map();
2134
- const namespace = contributions?.modelAttributes;
2135
- if (namespace === void 0) return result;
2136
- const walk = (node) => {
2137
- for (const value of Object.values(node)) if (isAuthoringModelAttributeDescriptor(value)) result.set(value.attribute, value);
2138
- else if (typeof value === "object" && value !== null) walk(value);
2139
- };
2140
- walk(namespace);
2141
- return result;
2142
- }
2143
- /**
2144
- * For a single lexical scope (a named PSL namespace, or the document top
2145
- * level), lowers all extension blocks into IR entities via the registered
2146
- * factory for each block's discriminator. Groups results by discriminator
2147
- * (the entries key — one-string rule: discriminator === entries key).
2148
- *
2149
- * This pass is intentionally generic: no discriminator value is named here.
2150
- * The factory (registered by the target pack) owns all block-specific logic.
2151
- * A descriptor's factory output may also opt into value-set derivation via
2152
- * the SQL family's `SqlValueSetDerivingEntityTypeOutput.deriveValueSet` hook
2153
- * (probed by {@link deriveValueSetFromEntity}) — when present, the derived
2154
- * value-set is folded into the namespace's `valueSet` slot (keyed by block
2155
- * name), so a value-set-carrying pack entity (e.g. Postgres `native_enum`)
2156
- * contributes the value-set that drives value-set → codec typing without
2157
- * this pass inspecting a target-specific shape.
2158
- *
2159
- * The `namespaceId` is attached to the block before the factory call so the
2160
- * factory can record the namespace coordinate without the interpreter
2161
- * containing any target-specific knowledge about how namespace ids are used.
2162
- *
2163
- * Ref conversion is this pass's job, over typed data: each block-descriptor
2164
- * parameter declared `{ kind: 'ref', refKind: 'model' }` (same-namespace
2165
- * scope) is resolved to the referenced model's storage table name and
2166
- * attached to the block as `resolvedModelRefs` ({@link ResolvedPslModelRefs})
2167
- * before the factory runs — the factory consumes a resolved coordinate and
2168
- * never looks a model up itself. A required model ref that is missing or
2169
- * does not resolve is this pass's diagnostic; the factory is skipped.
2170
- */
2171
- function lowerExtensionBlocksForNamespace(blocks, nsId, entityTypesByDiscriminator, entityContext, pslBlockDescriptors, resolveModelTable) {
2172
- const blockSymbols = Object.values(blocks);
2173
- if (blockSymbols.length === 0) return {};
2174
- const result = {};
2175
- for (const blockSymbol of blockSymbols) {
2176
- const block = blockSymbol.block;
2177
- const descriptor = entityTypesByDiscriminator.get(block.kind);
2178
- if (descriptor === void 0) continue;
2179
- const blockDescriptor = findBlockDescriptor(pslBlockDescriptors, block.keyword);
2180
- let unresolvedRef = false;
2181
- let resolvedModelRefs;
2182
- for (const [paramName, paramDecl] of Object.entries(blockDescriptor?.parameters ?? {})) {
2183
- if (paramDecl.kind !== "ref" || paramDecl.refKind !== "model" || paramDecl.scope !== "same-namespace") continue;
2184
- const captured = block.parameters[paramName];
2185
- if (captured?.kind !== "ref") {
2186
- if (paramDecl.required === true) {
2187
- entityContext.diagnostics?.push({
2188
- code: "PSL_EXTENSION_MODEL_REF_UNRESOLVED",
2189
- message: `\`${block.keyword}\` block "${block.name}" is missing the required \`${paramName}\` model reference.`,
2190
- sourceId: entityContext.sourceId ?? "unknown",
2191
- span: block.span
2192
- });
2193
- unresolvedRef = true;
2194
- }
2195
- continue;
2196
- }
2197
- const tableName = resolveModelTable(captured.identifier);
2198
- if (tableName === void 0) {
2199
- entityContext.diagnostics?.push({
2200
- code: "PSL_EXTENSION_MODEL_REF_UNRESOLVED",
2201
- message: `\`${block.keyword}\` block "${block.name}" references model "${captured.identifier}" in \`${paramName}\`, which is not declared in the same namespace. Declare the model or fix the reference.`,
2202
- sourceId: entityContext.sourceId ?? "unknown",
2203
- span: captured.span
2204
- });
2205
- unresolvedRef = true;
2206
- continue;
2207
- }
2208
- resolvedModelRefs = {
2209
- ...resolvedModelRefs ?? {},
2210
- [paramName]: { tableName }
2211
- };
2212
- }
2213
- if (unresolvedRef) continue;
2214
- const annotatedBlock = {
2215
- ...block,
2216
- namespaceId: nsId,
2217
- ...resolvedModelRefs !== void 0 ? { resolvedModelRefs } : {}
2218
- };
2219
- const entity = instantiateAuthoringEntityType(descriptor.discriminator, descriptor, [annotatedBlock], entityContext);
2220
- if (entity === void 0) continue;
2221
- const entriesKey = descriptor.discriminator;
2222
- const slot = result[entriesKey] ?? {};
2223
- result[entriesKey] = slot;
2224
- slot[block.name] = entity;
2225
- const derivedValueSet = deriveValueSetFromEntity(descriptor.output, entity);
2226
- if (derivedValueSet !== void 0) {
2227
- const valueSetSlot = result["valueSet"] ?? {};
2228
- result["valueSet"] = valueSetSlot;
2229
- valueSetSlot[block.name] = derivedValueSet;
2230
- }
2231
- }
2232
- return result;
2233
- }
2234
- function processEnumDeclarations(input) {
2235
- const enumHandles = {};
2236
- const enumTypeDescriptors = /* @__PURE__ */ new Map();
2237
- if (input.enumBlocks.length === 0) return {
2238
- enumHandles,
2239
- enumTypeDescriptors
2240
- };
2241
- const enumDescriptor = getAuthoringEntity(input.authoringContributions, ["enum"]);
2242
- if (!enumDescriptor) {
2243
- for (const decl of input.enumBlocks) input.diagnostics.push({
2244
- code: "PSL_ENUM_MISSING_FACTORY",
2245
- message: `enum "${decl.name}" requires an "enum" entityType factory in the active authoring contributions`,
2246
- sourceId: input.sourceId,
2247
- span: decl.span
2248
- });
2249
- return {
2250
- enumHandles,
2251
- enumTypeDescriptors
2252
- };
2253
- }
2254
- for (const decl of input.enumBlocks) {
2255
- const handle = instantiateAuthoringEntityType("enum", enumDescriptor, [decl], input.entityContext);
2256
- if (handle === void 0 || handle === null) continue;
2257
- enumHandles[decl.name] = handle;
2258
- enumTypeDescriptors.set(decl.name, {
2259
- codecId: handle.codecId,
2260
- nativeType: handle.nativeType
2261
- });
2262
- }
2263
- return {
2264
- enumHandles,
2265
- enumTypeDescriptors
2266
- };
2267
- }
2268
- /** Generic top-level blocks are supported only when a composed descriptor claims their keyword. */
2269
- function composedBlockKeywords(authoringContributions) {
2270
- const keywords = /* @__PURE__ */ new Set();
2271
- const descriptors = authoringContributions?.pslBlockDescriptors ?? {};
2272
- for (const [keyword, value] of Object.entries(descriptors)) if (isAuthoringPslBlockDescriptor(value)) keywords.add(keyword);
2273
- return keywords;
2274
- }
2275
- /**
2276
- * The owning side of a relation is the one that declares `fields`/`references` on its
2277
- * `@relation` attribute — those name the FK columns. A singular model-typed field whose
2278
- * `@relation` carries only a name (or nothing at all) is the back side: infer prints exactly
2279
- * that shape for a 1:1 back-relation whenever the FK needs disambiguating (two FKs between the
2280
- * same table pair, or a self-referencing unique FK). Checking for the attribute's mere presence
2281
- * would misclassify that back side as the owning side.
2282
- */
2283
- function relationAttributeDeclaresOwningSide(relationAttribute) {
2284
- return getNamedArgument(relationAttribute, "fields") !== void 0 || getNamedArgument(relationAttribute, "references") !== void 0;
2285
- }
2286
- function buildModelNodeFromPsl(input) {
2287
- const { model, mapping, sourceId, diagnostics } = input;
2288
- const tableName = mapping.tableName;
2289
- const modelNamespaceId = input.modelNamespaceIds.get(model.name);
2290
- const namespaceExtensionEntitiesForModel = modelNamespaceId !== void 0 ? input.namespaceExtensionEntities?.get(modelNamespaceId) : void 0;
2291
- const resolvedFields = collectResolvedFields({
2292
- model,
2293
- mapping,
2294
- enumTypeDescriptors: input.enumTypeDescriptors,
2295
- namedTypeDescriptors: input.namedTypeDescriptors,
2296
- modelNames: input.modelNames,
2297
- compositeTypeNames: input.compositeTypeNames,
2298
- composedExtensions: input.composedExtensions,
2299
- authoringContributions: input.authoringContributions,
2300
- familyId: input.familyId,
2301
- targetId: input.targetId,
2302
- defaultFunctionRegistry: input.defaultFunctionRegistry,
2303
- generatorDescriptorById: input.generatorDescriptorById,
2304
- diagnostics,
2305
- sourceId,
2306
- sourceFile: input.sourceFile,
2307
- scalarColumnDescriptors: input.scalarColumnDescriptors,
2308
- ...ifDefined("enumHandles", input.enumHandles),
2309
- capabilities: input.capabilities,
2310
- ...ifDefined("namespaceId", modelNamespaceId),
2311
- ...ifDefined("namespaceExtensionEntities", namespaceExtensionEntitiesForModel),
2312
- ...ifDefined("codecLookup", input.codecLookup)
2313
- });
2314
- const inlineIdFields = resolvedFields.filter((field) => field.isId);
2315
- if (inlineIdFields.length > 1) diagnostics.push({
2316
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
2317
- message: `Model "${model.name}" cannot declare inline @id on multiple fields; use model-level @@id([...]) for composite identity`,
2318
- sourceId,
2319
- span: model.span
2320
- });
2321
- const singleInlineIdField = inlineIdFields.length === 1 ? inlineIdFields[0] : void 0;
2322
- let primaryKey = singleInlineIdField ? {
2323
- columns: [singleInlineIdField.columnName],
2324
- ...ifDefined("name", singleInlineIdField.idName)
2325
- } : void 0;
2326
- const hasInlinePrimaryKey = primaryKey !== void 0;
2327
- let blockPrimaryKeyDeclared = false;
2328
- let controlPolicyDeclared = false;
2329
- let controlPolicy;
2330
- const declaredContributedModelAttributes = /* @__PURE__ */ new Set();
2331
- const modelAttributeEntities = {};
2332
- const resultBackrelationCandidates = [];
2333
- for (const field of Object.values(model.fields)) {
2334
- if (!input.modelNames.has(field.typeName)) continue;
2335
- const relationAttribute = getAttribute(field.attributes, "relation");
2336
- if (!field.list && relationAttribute && relationAttributeDeclaresOwningSide(relationAttribute)) continue;
2337
- const attributesValid = validateBackrelationFieldAttributes({
2338
- modelName: model.name,
2339
- field,
2340
- sourceId,
2341
- composedExtensions: input.composedExtensions,
2342
- authoringContributions: input.authoringContributions,
2343
- diagnostics,
2344
- familyId: input.familyId,
2345
- targetId: input.targetId
2346
- });
2347
- let relationName;
2348
- if (relationAttribute) {
2349
- const parsedRelation = interpretRelationAttribute({
2350
- selfModel: model,
2351
- field,
2352
- symbols: input.symbolTable,
2353
- sourceFile: input.sourceFile,
2354
- sourceId,
2355
- diagnostics
2356
- });
2357
- if (!parsedRelation) continue;
2358
- if (parsedRelation.fields || parsedRelation.references) {
2359
- diagnostics.push({
2360
- code: "PSL_INVALID_RELATION_ATTRIBUTE",
2361
- message: `Backrelation list field "${model.name}.${field.name}" cannot declare fields/references; define them on the FK-side relation field`,
2362
- sourceId,
2363
- span: relationAttribute.span
2364
- });
2365
- continue;
2366
- }
2367
- if (parsedRelation.onDelete || parsedRelation.onUpdate || parsedRelation.index !== void 0) {
2368
- diagnostics.push({
2369
- code: "PSL_INVALID_RELATION_ATTRIBUTE",
2370
- message: `Backrelation list field "${model.name}.${field.name}" cannot declare onDelete/onUpdate/index; define them on the FK-side relation field`,
2371
- sourceId,
2372
- span: relationAttribute.span
2373
- });
2374
- continue;
2375
- }
2376
- relationName = parsedRelation.name;
2377
- }
2378
- if (!attributesValid) continue;
2379
- resultBackrelationCandidates.push({
2380
- modelName: model.name,
2381
- tableName,
2382
- field,
2383
- targetModelName: field.typeName,
2384
- isList: field.list,
2385
- ...ifDefined("relationName", relationName)
2386
- });
2387
- }
2388
- const relationAttributes = Object.values(model.fields).map((field) => ({
2389
- field,
2390
- relation: getAttribute(field.attributes, "relation")
2391
- })).filter((entry) => Boolean(entry.relation));
2392
- const uniqueConstraints = resolvedFields.filter((field) => field.isUnique).map((field) => ({
2393
- columns: [field.columnName],
2394
- ...ifDefined("name", field.uniqueName)
2395
- }));
2396
- const indexNodes = [];
2397
- const checkNodes = [];
2398
- const foreignKeyNodes = [];
2399
- const modelAttributeNodes = Array.from(model.node.attributes());
2400
- for (const [attributeIndex, modelAttribute] of model.attributes.entries()) {
2401
- if (modelAttribute.name === "map") continue;
2402
- if (modelAttribute.name === "discriminator" || modelAttribute.name === "base") continue;
2403
- if (modelAttribute.name === "control") {
2404
- if (controlPolicyDeclared) {
2405
- diagnostics.push(duplicateModelAttributeDiagnostic({
2406
- name: "control",
2407
- modelName: model.name,
2408
- sourceId,
2409
- span: modelAttribute.span
2410
- }));
2411
- continue;
2412
- }
2413
- controlPolicyDeclared = true;
2414
- const node = modelAttributeNodes[attributeIndex];
2415
- if (node === void 0) continue;
2416
- const parsed = interpretModelAttribute({
2417
- node,
2418
- spec: controlModelSpec,
2419
- model,
2420
- sourceFile: input.sourceFile,
2421
- sourceId,
2422
- diagnostics
2423
- });
2424
- if (parsed !== void 0) controlPolicy = parsed.policy;
2425
- continue;
2426
- }
2427
- const attributeLabel = `Model "${model.name}" @@${modelAttribute.name}`;
2428
- if (modelAttribute.name === "id") {
2429
- if (blockPrimaryKeyDeclared) {
2430
- diagnostics.push({
2431
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
2432
- message: `Model "${model.name}" declares @@id more than once`,
2433
- sourceId,
2434
- span: modelAttribute.span
2435
- });
2436
- continue;
2437
- }
2438
- if (hasInlinePrimaryKey) {
2439
- diagnostics.push({
2440
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
2441
- message: `Model "${model.name}" cannot declare both field-level @id and model-level @@id`,
2442
- sourceId,
2443
- span: modelAttribute.span
2444
- });
2445
- blockPrimaryKeyDeclared = true;
2446
- continue;
2447
- }
2448
- const node = modelAttributeNodes[attributeIndex];
2449
- if (node === void 0) continue;
2450
- const parsed = interpretModelAttribute({
2451
- node,
2452
- spec: idModelSpec,
2453
- model,
2454
- sourceFile: input.sourceFile,
2455
- sourceId,
2456
- diagnostics
2457
- });
2458
- if (parsed === void 0) continue;
2459
- const fieldNames = parsed.fields;
2460
- const nullableFieldName = fieldNames.find((name) => model.fields[name]?.optional === true);
2461
- if (nullableFieldName !== void 0) {
2462
- diagnostics.push({
2463
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
2464
- message: `${attributeLabel} cannot include optional field "${nullableFieldName}"; primary key columns must be NOT NULL`,
2465
- sourceId,
2466
- span: modelAttribute.span
2467
- });
2468
- continue;
2469
- }
2470
- const columnNames = mapFieldNamesToColumns({
2471
- modelName: model.name,
2472
- fieldNames,
2473
- mapping,
2474
- sourceId,
2475
- diagnostics,
2476
- span: modelAttribute.span,
2477
- entityLabel: attributeLabel
2478
- });
2479
- if (!columnNames) continue;
2480
- primaryKey = {
2481
- columns: columnNames,
2482
- ...ifDefined("name", parsed.map)
2483
- };
2484
- blockPrimaryKeyDeclared = true;
2485
- continue;
2486
- }
2487
- if (modelAttribute.name === "unique") {
2488
- const node = modelAttributeNodes[attributeIndex];
2489
- if (node === void 0) continue;
2490
- const parsed = interpretModelAttribute({
2491
- node,
2492
- spec: uniqueModelSpec,
2493
- model,
2494
- sourceFile: input.sourceFile,
2495
- sourceId,
2496
- diagnostics
2497
- });
2498
- if (parsed === void 0) continue;
2499
- const columnNames = mapFieldNamesToColumns({
2500
- modelName: model.name,
2501
- fieldNames: parsed.fields,
2502
- mapping,
2503
- sourceId,
2504
- diagnostics,
2505
- span: modelAttribute.span,
2506
- entityLabel: attributeLabel
2507
- });
2508
- if (!columnNames) continue;
2509
- uniqueConstraints.push({
2510
- columns: columnNames,
2511
- ...ifDefined("name", parsed.map)
2512
- });
2513
- continue;
2514
- }
2515
- if (modelAttribute.name === "index") {
2516
- const node = modelAttributeNodes[attributeIndex];
2517
- if (node === void 0) continue;
2518
- const parsed = interpretModelAttribute({
2519
- node,
2520
- spec: indexModelSpec,
2521
- model,
2522
- sourceFile: input.sourceFile,
2523
- sourceId,
2524
- diagnostics
2525
- });
2526
- if (parsed === void 0) continue;
2527
- let columnNames;
2528
- if (parsed.fields !== void 0) {
2529
- const mapped = mapFieldNamesToColumns({
2530
- modelName: model.name,
2531
- fieldNames: parsed.fields,
2532
- mapping,
2533
- sourceId,
2534
- diagnostics,
2535
- span: modelAttribute.span,
2536
- entityLabel: attributeLabel
2537
- });
2538
- if (!mapped) continue;
2539
- columnNames = mapped;
2540
- }
2541
- indexNodes.push(blindCast({
2542
- ...ifDefined("columns", columnNames),
2543
- ...ifDefined("expression", parsed.expression),
2544
- where: parsed.where,
2545
- unique: parsed.unique,
2546
- name: parsed.name,
2547
- map: parsed.map,
2548
- type: parsed.type,
2549
- options: parsed.options
2550
- }));
2551
- continue;
2552
- }
2553
- if (modelAttribute.name === "check") {
2554
- const node = modelAttributeNodes[attributeIndex];
2555
- if (node === void 0) continue;
2556
- if (input.capabilities["sql"]?.["checkConstraint"] !== true) {
2557
- diagnostics.push({
2558
- code: "PSL_CHECK_UNSUPPORTED_TARGET",
2559
- message: `Model "${model.name}" declares "@@check", but target "${input.targetId}" does not support check constraints (the adapter does not report the "checkConstraint" capability). Remove the check or author it against a target that supports check constraints.`,
2560
- sourceId,
2561
- span: modelAttribute.span
2562
- });
2563
- continue;
2564
- }
2565
- const parsed = interpretModelAttribute({
2566
- node,
2567
- spec: checkModelSpec,
2568
- model,
2569
- sourceFile: input.sourceFile,
2570
- sourceId,
2571
- diagnostics
2572
- });
2573
- if (parsed === void 0) continue;
2574
- checkNodes.push({
2575
- expression: parsed.expression,
2576
- name: parsed.name,
2577
- map: parsed.map
2578
- });
2579
- continue;
2580
- }
2581
- const contributedModelAttribute = input.modelAttributesByName.get(modelAttribute.name);
2582
- if (contributedModelAttribute !== void 0) {
2583
- if (declaredContributedModelAttributes.has(modelAttribute.name)) {
2584
- diagnostics.push(duplicateModelAttributeDiagnostic({
2585
- name: modelAttribute.name,
2586
- modelName: model.name,
2587
- sourceId,
2588
- span: modelAttribute.span
2589
- }));
2590
- continue;
2591
- }
2592
- declaredContributedModelAttributes.add(modelAttribute.name);
2593
- const node = modelAttributeNodes[attributeIndex];
2594
- if (node === void 0) continue;
2595
- const parsed = interpretModelAttribute({
2596
- node,
2597
- spec: blindCast(contributedModelAttribute.spec),
2598
- model,
2599
- sourceFile: input.sourceFile,
2600
- sourceId,
2601
- diagnostics
2602
- });
2603
- if (parsed === void 0) continue;
2604
- const lowered = blindCast(contributedModelAttribute.lower)(parsed, {
2605
- family: input.familyId,
2606
- target: input.targetId,
2607
- modelName: model.name,
2608
- storageName: tableName,
2609
- namespaceId: modelNamespaceId ?? input.defaultNamespaceId,
2610
- sourceId,
2611
- diagnostics: { push: (d) => {
2612
- diagnostics.push(blindCast(d));
2613
- } }
2614
- });
2615
- if (lowered === void 0) continue;
2616
- const slot = modelAttributeEntities[contributedModelAttribute.attribute] ?? {};
2617
- modelAttributeEntities[contributedModelAttribute.attribute] = slot;
2618
- slot[lowered.key] = lowered.entity;
2619
- continue;
2620
- }
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
- });
2642
- }
2643
- const resultFkRelationMetadata = [];
2644
- const resultCrossSpaceRelations = [];
2645
- for (const relationAttribute of relationAttributes) {
2646
- const { typeName: fieldTypeName, typeNamespaceId: fieldTypeNamespaceId, typeContractSpaceId: fieldTypeContractSpaceId } = relationAttribute.field;
2647
- if (relationAttribute.field.list) {
2648
- if (fieldTypeContractSpaceId !== void 0) diagnostics.push({
2649
- code: "PSL_UNSUPPORTED_CROSS_SPACE_LIST",
2650
- message: `Relation field "${model.name}.${relationAttribute.field.name}" is a cross-space list relation (type "${fieldTypeContractSpaceId}:${fieldTypeNamespaceId !== void 0 ? `${fieldTypeNamespaceId}.` : ""}${fieldTypeName}[]"). Cross-space relations must be singular in v0.1 — list cross-space relations are not supported.`,
2651
- sourceId,
2652
- span: relationAttribute.field.span
2653
- });
2654
- continue;
2655
- }
2656
- if (!relationAttributeDeclaresOwningSide(relationAttribute.relation)) continue;
2657
- if (fieldTypeContractSpaceId !== void 0) {
2658
- const extContractForSpace = input.composedExtensionContracts.get(fieldTypeContractSpaceId);
2659
- if (extContractForSpace === void 0) {
2660
- diagnostics.push({
2661
- code: "PSL_UNKNOWN_CONTRACT_SPACE",
2662
- message: `Relation field "${model.name}.${relationAttribute.field.name}" references contract space "${fieldTypeContractSpaceId}" which is not declared in extensions. Add "${fieldTypeContractSpaceId}" to extensions in prisma.config.ts.`,
2663
- sourceId,
2664
- span: relationAttribute.field.span,
2665
- data: {
2666
- space: fieldTypeContractSpaceId,
2667
- suggestedPack: fieldTypeContractSpaceId
2668
- }
2669
- });
2670
- continue;
2671
- }
2672
- const parsedRelation = interpretRelationAttribute({
2673
- selfModel: model,
2674
- field: relationAttribute.field,
2675
- symbols: input.symbolTable,
2676
- sourceFile: input.sourceFile,
2677
- sourceId,
2678
- diagnostics
2679
- });
2680
- if (!parsedRelation) continue;
2681
- if (!parsedRelation.fields || !parsedRelation.references) {
2682
- diagnostics.push({
2683
- code: "PSL_INVALID_RELATION_ATTRIBUTE",
2684
- message: `Relation field "${model.name}.${relationAttribute.field.name}" requires fields and references arguments`,
2685
- sourceId,
2686
- span: relationAttribute.relation.span
2687
- });
2688
- continue;
2689
- }
2690
- const localColumns = mapFieldNamesToColumns({
2691
- modelName: model.name,
2692
- fieldNames: parsedRelation.fields,
2693
- mapping,
2694
- sourceId,
2695
- diagnostics,
2696
- span: relationAttribute.relation.span,
2697
- entityLabel: `Relation field "${model.name}.${relationAttribute.field.name}"`
2698
- });
2699
- if (!localColumns) continue;
2700
- const referencedColumns = parsedRelation.references;
2701
- if (localColumns.length !== referencedColumns.length) {
2702
- diagnostics.push({
2703
- code: "PSL_INVALID_RELATION_ATTRIBUTE",
2704
- message: `Relation field "${model.name}.${relationAttribute.field.name}" must provide the same number of fields and references`,
2705
- sourceId,
2706
- span: relationAttribute.relation.span
2707
- });
2708
- continue;
2709
- }
2710
- const onDelete = parsedRelation.onDelete ? normalizeReferentialAction(parsedRelation.onDelete) : void 0;
2711
- const onUpdate = parsedRelation.onUpdate ? normalizeReferentialAction(parsedRelation.onUpdate) : void 0;
2712
- const crossTargetNamespaceId = fieldTypeNamespaceId ?? "__unbound__";
2713
- const extContract = extContractForSpace;
2714
- const resolvedTable = extContract.domain.namespaces[crossTargetNamespaceId]?.models[fieldTypeName]?.storage["table"];
2715
- if (typeof resolvedTable !== "string") {
2716
- const availableModels = Object.keys(extContract.domain.namespaces[crossTargetNamespaceId]?.models ?? {}).join(", ") || "(none)";
2717
- diagnostics.push({
2718
- code: "PSL_UNKNOWN_CROSS_SPACE_TARGET",
2719
- message: `Relation field "${model.name}.${relationAttribute.field.name}" references model "${fieldTypeName}" in namespace "${crossTargetNamespaceId}" of space "${fieldTypeContractSpaceId}", but that model was not found in the extension contract. Available models: ${availableModels}`,
2720
- sourceId,
2721
- span: relationAttribute.field.span,
2722
- data: {
2723
- space: fieldTypeContractSpaceId,
2724
- namespace: crossTargetNamespaceId,
2725
- model: fieldTypeName
2726
- }
2727
- });
2728
- continue;
2729
- }
2730
- const crossTargetTableName = resolvedTable;
2731
- foreignKeyNodes.push({
2732
- columns: localColumns,
2733
- references: {
2734
- model: fieldTypeName,
2735
- table: crossTargetTableName,
2736
- columns: referencedColumns,
2737
- namespaceId: crossTargetNamespaceId,
2738
- spaceId: fieldTypeContractSpaceId
2739
- },
2740
- ...ifDefined("name", parsedRelation.map),
2741
- ...ifDefined("onDelete", onDelete),
2742
- ...ifDefined("onUpdate", onUpdate),
2743
- ...ifDefined("index", parsedRelation.index)
2744
- });
2745
- resultCrossSpaceRelations.push({
2746
- fieldName: relationAttribute.field.name,
2747
- toModel: fieldTypeName,
2748
- toTable: crossTargetTableName,
2749
- cardinality: "N:1",
2750
- spaceId: fieldTypeContractSpaceId,
2751
- namespaceId: crossTargetNamespaceId,
2752
- on: {
2753
- parentTable: tableName,
2754
- parentColumns: localColumns,
2755
- childTable: crossTargetTableName,
2756
- childColumns: referencedColumns
2757
- }
2758
- });
2759
- continue;
2760
- }
2761
- const qualifiedTypeName = fieldTypeNamespaceId ? `${fieldTypeNamespaceId}.${fieldTypeName}` : fieldTypeName;
2762
- if (!input.modelNames.has(fieldTypeName)) {
2763
- diagnostics.push({
2764
- code: "PSL_INVALID_RELATION_TARGET",
2765
- message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${qualifiedTypeName}"`,
2766
- sourceId,
2767
- span: relationAttribute.field.span
2768
- });
2769
- continue;
2770
- }
2771
- const normalizedQualifier = fieldTypeNamespaceId === void 0 ? void 0 : fieldTypeNamespaceId === "unbound" ? "__unbound__" : fieldTypeNamespaceId;
2772
- if (normalizedQualifier !== void 0 && !input.modelMappingsByCoordinate.has(modelCoordinateKey(normalizedQualifier, fieldTypeName))) {
2773
- diagnostics.push({
2774
- code: "PSL_INVALID_RELATION_TARGET",
2775
- message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${qualifiedTypeName}"`,
2776
- sourceId,
2777
- span: relationAttribute.field.span
2778
- });
2779
- continue;
2780
- }
2781
- const parsedRelation = interpretRelationAttribute({
2782
- selfModel: model,
2783
- field: relationAttribute.field,
2784
- symbols: input.symbolTable,
2785
- sourceFile: input.sourceFile,
2786
- sourceId,
2787
- diagnostics
2788
- });
2789
- if (!parsedRelation) continue;
2790
- if (!parsedRelation.fields || !parsedRelation.references) {
2791
- diagnostics.push({
2792
- code: "PSL_INVALID_RELATION_ATTRIBUTE",
2793
- message: `Relation field "${model.name}.${relationAttribute.field.name}" requires fields and references arguments`,
2794
- sourceId,
2795
- span: relationAttribute.relation.span
2796
- });
2797
- continue;
2798
- }
2799
- const targetMapping = normalizedQualifier !== void 0 ? input.modelMappingsByCoordinate.get(modelCoordinateKey(normalizedQualifier, fieldTypeName)) : input.modelMappings.get(fieldTypeName);
2800
- if (!targetMapping) {
2801
- diagnostics.push({
2802
- code: "PSL_INVALID_RELATION_TARGET",
2803
- message: `Relation field "${model.name}.${relationAttribute.field.name}" references unknown model "${qualifiedTypeName}"`,
2804
- sourceId,
2805
- span: relationAttribute.field.span
2806
- });
2807
- continue;
2808
- }
2809
- const localColumns = mapFieldNamesToColumns({
2810
- modelName: model.name,
2811
- fieldNames: parsedRelation.fields,
2812
- mapping,
2813
- sourceId,
2814
- diagnostics,
2815
- span: relationAttribute.relation.span,
2816
- entityLabel: `Relation field "${model.name}.${relationAttribute.field.name}"`
2817
- });
2818
- if (!localColumns) continue;
2819
- const referencedColumns = mapFieldNamesToColumns({
2820
- modelName: targetMapping.model.name,
2821
- fieldNames: parsedRelation.references,
2822
- mapping: targetMapping,
2823
- sourceId,
2824
- diagnostics,
2825
- span: relationAttribute.relation.span,
2826
- entityLabel: `Relation field "${model.name}.${relationAttribute.field.name}"`
2827
- });
2828
- if (!referencedColumns) continue;
2829
- if (localColumns.length !== referencedColumns.length) {
2830
- diagnostics.push({
2831
- code: "PSL_INVALID_RELATION_ATTRIBUTE",
2832
- message: `Relation field "${model.name}.${relationAttribute.field.name}" must provide the same number of fields and references`,
2833
- sourceId,
2834
- span: relationAttribute.relation.span
2835
- });
2836
- continue;
2837
- }
2838
- const onDelete = parsedRelation.onDelete ? normalizeReferentialAction(parsedRelation.onDelete) : void 0;
2839
- const onUpdate = parsedRelation.onUpdate ? normalizeReferentialAction(parsedRelation.onUpdate) : void 0;
2840
- const targetNamespaceId = normalizedQualifier !== void 0 ? normalizedQualifier : input.modelNamespaceIds.get(targetMapping.model.name);
2841
- foreignKeyNodes.push({
2842
- columns: localColumns,
2843
- references: {
2844
- model: targetMapping.model.name,
2845
- table: targetMapping.tableName,
2846
- columns: referencedColumns,
2847
- ...ifDefined("namespaceId", targetNamespaceId)
2848
- },
2849
- ...ifDefined("name", parsedRelation.map),
2850
- ...ifDefined("onDelete", onDelete),
2851
- ...ifDefined("onUpdate", onUpdate),
2852
- ...ifDefined("index", parsedRelation.index)
2853
- });
2854
- resultFkRelationMetadata.push({
2855
- declaringModelName: model.name,
2856
- declaringFieldName: relationAttribute.field.name,
2857
- declaringTableName: tableName,
2858
- ...ifDefined("declaringNamespaceId", input.modelNamespaceIds.get(model.name)),
2859
- targetModelName: targetMapping.model.name,
2860
- targetTableName: targetMapping.tableName,
2861
- ...ifDefined("targetNamespaceId", targetNamespaceId),
2862
- ...ifDefined("relationName", parsedRelation.name),
2863
- localColumns,
2864
- referencedColumns
2865
- });
2866
- }
2867
- return {
2868
- modelNode: {
2869
- modelName: model.name,
2870
- tableName,
2871
- fields: resolvedFields.map((resolvedField) => {
2872
- const enumHandle = input.enumHandles?.get(resolvedField.field.typeName);
2873
- return {
2874
- fieldName: resolvedField.field.name,
2875
- columnName: resolvedField.columnName,
2876
- descriptor: resolvedField.descriptor,
2877
- nullable: resolvedField.nullable,
2878
- ...resolvedField.many && resolvedField.valueObjectTypeName === void 0 ? { many: true } : {},
2879
- ...ifDefined("default", resolvedField.defaultValue),
2880
- ...ifDefined("executionDefaults", resolvedField.executionDefaults),
2881
- ...ifDefined("noCheck", resolvedField.noCheck),
2882
- ...ifDefined("enumTypeHandle", enumHandle)
2883
- };
2884
- }),
2885
- ...ifDefined("id", primaryKey),
2886
- ...uniqueConstraints.length > 0 ? { uniques: uniqueConstraints } : {},
2887
- ...indexNodes.length > 0 ? { indexes: indexNodes } : {},
2888
- ...checkNodes.length > 0 ? { checks: checkNodes } : {},
2889
- ...foreignKeyNodes.length > 0 ? { foreignKeys: foreignKeyNodes } : {},
2890
- ...ifDefined("control", controlPolicy)
2891
- },
2892
- fkRelationMetadata: resultFkRelationMetadata,
2893
- crossSpaceRelations: resultCrossSpaceRelations,
2894
- backrelationCandidates: resultBackrelationCandidates,
2895
- resolvedFields,
2896
- modelAttributeEntities
2897
- };
2898
- }
2899
- function buildValueObjects(input) {
2900
- const { compositeTypes, enumTypeDescriptors, namedTypeDescriptors, scalarColumnDescriptors, composedExtensions, familyId, targetId, authoringContributions, diagnostics, sourceId } = input;
2901
- const valueObjects = {};
2902
- const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
2903
- for (const compositeType of compositeTypes) {
2904
- const fields = {};
2905
- for (const field of Object.values(compositeType.fields)) {
2906
- if (compositeTypeNames.has(field.typeName)) {
2907
- const result = {
2908
- type: {
2909
- kind: "valueObject",
2910
- name: field.typeName
2911
- },
2912
- nullable: field.optional
2913
- };
2914
- fields[field.name] = field.list ? {
2915
- ...result,
2916
- many: true
2917
- } : result;
2918
- continue;
2919
- }
2920
- const resolved = resolveFieldTypeDescriptor({
2921
- field,
2922
- enumTypeDescriptors,
2923
- namedTypeDescriptors,
2924
- scalarColumnDescriptors,
2925
- authoringContributions,
2926
- composedExtensions,
2927
- familyId,
2928
- targetId,
2929
- diagnostics,
2930
- sourceId,
2931
- entityLabel: `Field "${compositeType.name}.${field.name}"`
2932
- });
2933
- if (!resolved.ok) {
2934
- if (!resolved.alreadyReported) diagnostics.push({
2935
- code: "PSL_UNSUPPORTED_FIELD_TYPE",
2936
- message: `Field "${compositeType.name}.${field.name}" type "${field.typeName}" is not supported`,
2937
- sourceId,
2938
- span: field.span
2939
- });
2940
- continue;
2941
- }
2942
- const scalarField = {
2943
- nullable: field.optional,
2944
- type: {
2945
- kind: "scalar",
2946
- codecId: resolved.descriptor.codecId
2947
- }
2948
- };
2949
- fields[field.name] = field.list ? {
2950
- ...scalarField,
2951
- many: true
2952
- } : scalarField;
2953
- }
2954
- valueObjects[compositeType.name] = { fields };
2955
- }
2956
- return valueObjects;
2957
- }
2958
- function patchModelDomainFields(models, modelResolvedFields) {
2959
- let patched = models;
2960
- for (const [modelName, resolvedFields] of modelResolvedFields) {
2961
- const model = patched[modelName];
2962
- if (!model) continue;
2963
- let needsPatch = false;
2964
- const patchedFields = { ...model.fields };
2965
- for (const rf of resolvedFields) if (rf.valueObjectTypeName) {
2966
- needsPatch = true;
2967
- patchedFields[rf.field.name] = {
2968
- nullable: rf.field.optional,
2969
- type: {
2970
- kind: "valueObject",
2971
- name: rf.valueObjectTypeName
2972
- },
2973
- ...rf.many ? { many: true } : {}
2974
- };
2975
- } else if (rf.many && rf.scalarCodecId) {
2976
- needsPatch = true;
2977
- patchedFields[rf.field.name] = {
2978
- nullable: rf.field.optional,
2979
- type: {
2980
- kind: "scalar",
2981
- codecId: rf.scalarCodecId
2982
- },
2983
- many: true
2984
- };
2985
- }
2986
- if (needsPatch) patched = {
2987
- ...patched,
2988
- [modelName]: {
2989
- ...model,
2990
- fields: patchedFields
2991
- }
2992
- };
2993
- }
2994
- return patched;
2995
- }
2996
- function collectPolymorphismDeclarations(models, sourceFile, sourceId, diagnostics) {
2997
- const discriminatorDeclarations = /* @__PURE__ */ new Map();
2998
- const baseDeclarations = /* @__PURE__ */ new Map();
2999
- for (const model of models) {
3000
- const discriminatorNode = findModelAttributeNode(model, "discriminator");
3001
- if (discriminatorNode !== void 0) {
3002
- const parsed = interpretModelAttribute({
3003
- node: discriminatorNode,
3004
- spec: discriminatorModelSpec,
3005
- model,
3006
- sourceFile,
3007
- sourceId,
3008
- diagnostics
3009
- });
3010
- if (parsed !== void 0) {
3011
- const span = nodePslSpan(discriminatorNode.syntax, sourceFile);
3012
- const discField = model.fields[parsed.field];
3013
- if (discField && discField.typeName !== "String") diagnostics.push({
3014
- code: "PSL_INVALID_ATTRIBUTE_ARGUMENT",
3015
- message: `Discriminator field "${parsed.field}" on model "${model.name}" must be of type String, but is "${discField.typeName}"`,
3016
- sourceId,
3017
- span
3018
- });
3019
- else discriminatorDeclarations.set(model.name, {
3020
- fieldName: parsed.field,
3021
- span
3022
- });
3023
- }
3024
- }
3025
- const baseNode = findModelAttributeNode(model, "base");
3026
- if (baseNode !== void 0) {
3027
- const parsed = interpretModelAttribute({
3028
- node: baseNode,
3029
- spec: baseModelSpec,
3030
- model,
3031
- sourceFile,
3032
- sourceId,
3033
- diagnostics
3034
- });
3035
- if (parsed !== void 0) baseDeclarations.set(model.name, {
3036
- baseName: parsed.base,
3037
- value: parsed.value,
3038
- span: nodePslSpan(baseNode.syntax, sourceFile)
3039
- });
3040
- }
3041
- }
3042
- return {
3043
- discriminatorDeclarations,
3044
- baseDeclarations
3045
- };
3046
- }
3047
- function resolvePolymorphism(models, discriminatorDeclarations, baseDeclarations, modelNames, modelMappings, modelNamespaceIds, defaultNamespaceId, syntheticPkFieldsByVariant, stiBaseFieldsByBase, sourceId, diagnostics) {
3048
- let patched = models;
3049
- const coordinateFor = (modelName) => modelCoordinateKey(modelNamespaceIds.get(modelName) ?? defaultNamespaceId, modelName);
3050
- for (const [baseName, fieldNames] of stiBaseFieldsByBase) {
3051
- const baseKey = coordinateFor(baseName);
3052
- const baseModel = patched[baseKey];
3053
- if (!baseModel || fieldNames.length === 0) continue;
3054
- patched = {
3055
- ...patched,
3056
- [baseKey]: stripStorageOnlyDomainFields(baseModel, fieldNames)
3057
- };
3058
- }
3059
- for (const [modelName, decl] of discriminatorDeclarations) {
3060
- if (baseDeclarations.has(modelName)) {
3061
- diagnostics.push({
3062
- code: "PSL_DISCRIMINATOR_AND_BASE",
3063
- message: `Model "${modelName}" cannot have both @@discriminator and @@base`,
3064
- sourceId,
3065
- span: decl.span
3066
- });
3067
- continue;
3068
- }
3069
- const model = patched[coordinateFor(modelName)];
3070
- if (!model) continue;
3071
- const variants = {};
3072
- const seenValues = /* @__PURE__ */ new Map();
3073
- for (const [variantName, baseDecl] of baseDeclarations) {
3074
- if (baseDecl.baseName !== modelName) continue;
3075
- const existingVariant = seenValues.get(baseDecl.value);
3076
- if (existingVariant) {
3077
- diagnostics.push({
3078
- code: "PSL_DUPLICATE_DISCRIMINATOR_VALUE",
3079
- message: `Discriminator value "${baseDecl.value}" is used by both "${existingVariant}" and "${variantName}" on base model "${modelName}"`,
3080
- sourceId,
3081
- span: baseDecl.span
3082
- });
3083
- continue;
3084
- }
3085
- seenValues.set(baseDecl.value, variantName);
3086
- variants[variantName] = { value: baseDecl.value };
3087
- }
3088
- if (Object.keys(variants).length === 0) {
3089
- diagnostics.push({
3090
- code: "PSL_ORPHANED_DISCRIMINATOR",
3091
- message: `Model "${modelName}" has @@discriminator but no variant models declare @@base(${modelName}, ...)`,
3092
- sourceId,
3093
- span: decl.span
3094
- });
3095
- continue;
3096
- }
3097
- patched = {
3098
- ...patched,
3099
- [coordinateFor(modelName)]: {
3100
- ...model,
3101
- discriminator: { field: decl.fieldName },
3102
- variants
3103
- }
3104
- };
3105
- }
3106
- for (const [variantName, baseDecl] of baseDeclarations) {
3107
- if (!modelNames.has(baseDecl.baseName)) {
3108
- diagnostics.push({
3109
- code: "PSL_BASE_TARGET_NOT_FOUND",
3110
- message: `Model "${variantName}" @@base references non-existent model "${baseDecl.baseName}"`,
3111
- sourceId,
3112
- span: baseDecl.span
3113
- });
3114
- continue;
3115
- }
3116
- if (!discriminatorDeclarations.has(baseDecl.baseName)) {
3117
- diagnostics.push({
3118
- code: "PSL_ORPHANED_BASE",
3119
- message: `Model "${variantName}" declares @@base(${baseDecl.baseName}, ...) but "${baseDecl.baseName}" has no @@discriminator`,
3120
- sourceId,
3121
- span: baseDecl.span
3122
- });
3123
- continue;
3124
- }
3125
- if (discriminatorDeclarations.has(variantName)) continue;
3126
- const variantModel = patched[coordinateFor(variantName)];
3127
- if (!variantModel) continue;
3128
- const baseMapping = modelMappings.get(baseDecl.baseName);
3129
- const variantMapping = modelMappings.get(variantName);
3130
- const resolvedTable = variantMapping?.model.attributes.some((attr) => attr.name === "map") ?? false ? variantMapping?.tableName : baseMapping?.tableName;
3131
- const patchedVariant = {
3132
- ...variantModel,
3133
- base: crossRef(baseDecl.baseName, modelNamespaceIds.get(baseDecl.baseName) ?? defaultNamespaceId),
3134
- ...resolvedTable ? { storage: {
3135
- ...variantModel.storage,
3136
- table: resolvedTable
3137
- } } : {}
3138
- };
3139
- patched = {
3140
- ...patched,
3141
- [coordinateFor(variantName)]: stripStorageOnlyDomainFields(patchedVariant, syntheticPkFieldsByVariant.get(variantName) ?? [])
3142
- };
3143
- }
3144
- return patched;
3145
- }
3146
- /**
3147
- * Multi-table-inheritance variants (`@@base` + their own `@@map`) live in a
3148
- * separate table from their base. The ORM joins that table to the base on the
3149
- * shared primary key (`base.id = variant.id`), so the variant storage table
3150
- * must carry the base PK column even though the variant domain model declares
3151
- * only its own fields. This enriches each MTI variant's `ModelNode` with that
3152
- * link column, a primary key on it, and a FK back to the base table.
3153
- *
3154
- * The link column is reported back per variant in `syntheticPkFieldsByVariant`
3155
- * so the domain-model patch can drop it again — keeping the variant's domain
3156
- * surface thin (its create/read inputs don't gain a redundant `id`) while the
3157
- * storage table stays joinable. Single-table-inheritance variants (no own
3158
- * table) are left untouched.
3159
- */
3160
- function materializeMtiVariantStorageLinks(modelNodes, baseDeclarations, stiVariantNames) {
3161
- const nodeByModel = new Map(modelNodes.map((node) => [node.modelName, node]));
3162
- const syntheticPkFieldsByVariant = /* @__PURE__ */ new Map();
3163
- return {
3164
- modelNodes: modelNodes.map((node) => {
3165
- const baseDecl = baseDeclarations.get(node.modelName);
3166
- if (!baseDecl) return node;
3167
- const baseNode = nodeByModel.get(baseDecl.baseName);
3168
- if (!baseNode) return node;
3169
- if (stiVariantNames.has(node.modelName)) return node;
3170
- const basePrimaryKey = baseNode.id;
3171
- if (!basePrimaryKey || basePrimaryKey.columns.length === 0) return node;
3172
- const existingColumns = new Set(node.fields.map((field) => field.columnName));
3173
- const linkFields = [];
3174
- for (const pkColumn of basePrimaryKey.columns) {
3175
- if (existingColumns.has(pkColumn)) continue;
3176
- const baseField = baseNode.fields.find((field) => "descriptor" in field && field.columnName === pkColumn);
3177
- if (!baseField) continue;
3178
- linkFields.push({
3179
- fieldName: baseField.fieldName,
3180
- columnName: pkColumn,
3181
- descriptor: baseField.descriptor,
3182
- nullable: false
3183
- });
3184
- }
3185
- if (linkFields.length === 0) return node;
3186
- syntheticPkFieldsByVariant.set(node.modelName, linkFields.map((field) => field.fieldName));
3187
- const foreignKey = {
3188
- columns: basePrimaryKey.columns,
3189
- references: {
3190
- model: baseNode.modelName,
3191
- table: baseNode.tableName,
3192
- columns: basePrimaryKey.columns,
3193
- ...ifDefined("namespaceId", baseNode.namespaceId)
3194
- },
3195
- constraint: true,
3196
- index: false,
3197
- onDelete: "cascade"
3198
- };
3199
- return {
3200
- ...node,
3201
- fields: [...linkFields, ...node.fields],
3202
- id: { columns: basePrimaryKey.columns },
3203
- foreignKeys: [...node.foreignKeys ?? [], foreignKey]
3204
- };
3205
- }),
3206
- syntheticPkFieldsByVariant
3207
- };
3208
- }
3209
- /**
3210
- * Single-table-inheritance variants (`@@base` with no own `@@map`) share the
3211
- * base table: `resolvePolymorphism` points the variant's `storage.table` at the
3212
- * base, and the ORM reads variant-declared fields straight off the base table.
3213
- * For that to validate and round-trip, the base storage table must physically
3214
- * carry every STI variant's declared columns. This enriches the base
3215
- * `ModelNode` with those columns.
3216
- *
3217
- * The materialised columns are always nullable in storage: the base table hosts
3218
- * every variant's rows, so a column a variant declares as required is still
3219
- * NULL on sibling-variant rows. The variant's domain field keeps its declared
3220
- * nullability — required-in-domain / nullable-in-storage is the intended STI
3221
- * shape.
3222
- *
3223
- * Collisions (two variants declaring the same column, or a variant column name
3224
- * clashing with a base column) are resolved skip-if-exists here, mirroring the
3225
- * MTI link guard; surfacing them as diagnostics is tracked separately
3226
- * (TML-2827).
3227
- */
3228
- function materializeStiVariantStorageColumns(modelNodes, baseDeclarations, stiVariantNames) {
3229
- if (stiVariantNames.size === 0) return {
3230
- modelNodes: [...modelNodes],
3231
- stiBaseFieldsByBase: /* @__PURE__ */ new Map()
3232
- };
3233
- const nodeByModel = new Map(modelNodes.map((node) => [node.modelName, node]));
3234
- const stiColumnsByBase = /* @__PURE__ */ new Map();
3235
- for (const variantName of stiVariantNames) {
3236
- const variantNode = nodeByModel.get(variantName);
3237
- const baseDecl = baseDeclarations.get(variantName);
3238
- if (!variantNode || !baseDecl) continue;
3239
- const baseNode = nodeByModel.get(baseDecl.baseName);
3240
- if (!baseNode) continue;
3241
- const baseColumns = new Set(baseNode.fields.map((field) => field.columnName));
3242
- const claimed = stiColumnsByBase.get(baseDecl.baseName) ?? [];
3243
- const claimedColumns = new Set(claimed.map((field) => field.columnName));
3244
- for (const field of variantNode.fields) {
3245
- if (baseColumns.has(field.columnName) || claimedColumns.has(field.columnName)) continue;
3246
- claimedColumns.add(field.columnName);
3247
- claimed.push({
3248
- ...field,
3249
- nullable: true
3250
- });
3251
- }
3252
- stiColumnsByBase.set(baseDecl.baseName, claimed);
3253
- }
3254
- const stiBaseFieldsByBase = /* @__PURE__ */ new Map();
3255
- for (const [baseName, columns] of stiColumnsByBase) stiBaseFieldsByBase.set(baseName, columns.map((field) => field.fieldName));
3256
- return {
3257
- modelNodes: modelNodes.map((node) => {
3258
- if (stiVariantNames.has(node.modelName)) return {
3259
- ...node,
3260
- sharesBaseTable: true
3261
- };
3262
- const stiColumns = stiColumnsByBase.get(node.modelName);
3263
- if (!stiColumns || stiColumns.length === 0) return node;
3264
- return {
3265
- ...node,
3266
- fields: [...node.fields, ...stiColumns]
3267
- };
3268
- }),
3269
- stiBaseFieldsByBase
3270
- };
3271
- }
3272
- /**
3273
- * Drop the storage-only link fields (added by
3274
- * {@link materializeMtiVariantStorageLinks}) from a variant's domain model, so
3275
- * the domain surface stays thin while the storage table keeps the link column.
3276
- */
3277
- function stripStorageOnlyDomainFields(model, fieldNames) {
3278
- if (fieldNames.length === 0) return model;
3279
- const fields = { ...model.fields };
3280
- for (const name of fieldNames) delete fields[name];
3281
- const storage = blindCast(model.storage);
3282
- const storageFields = { ...storage.fields };
3283
- for (const name of fieldNames) delete storageFields[name];
3284
- return {
3285
- ...model,
3286
- fields,
3287
- storage: {
3288
- ...storage,
3289
- fields: storageFields
3290
- }
3291
- };
3292
- }
3293
- function interpretPslDocumentToSqlContract(input) {
3294
- const sourceId = input.sourceId;
3295
- if (!input.target) return notOk({
3296
- summary: "PSL to SQL contract interpretation failed",
3297
- diagnostics: [{
3298
- code: "PSL_TARGET_CONTEXT_REQUIRED",
3299
- message: "PSL interpretation requires an explicit target context from composition.",
3300
- sourceId
3301
- }]
3302
- });
3303
- if (!input.scalarColumnDescriptors) return notOk({
3304
- summary: "PSL to SQL contract interpretation failed",
3305
- diagnostics: [{
3306
- code: "PSL_SCALAR_TYPE_CONTEXT_REQUIRED",
3307
- message: "PSL interpretation requires composed scalar type descriptors.",
3308
- sourceId
3309
- }]
3310
- });
3311
- const { topLevel } = input.symbolTable;
3312
- const sourceFile = input.sourceFile;
3313
- const namespaceSymbols = Object.values(topLevel.namespaces);
3314
- const diagnostics = [...input.seedDiagnostics ?? []];
3315
- validateNamespaceBlocksForSqlTarget({
3316
- namespaces: namespaceSymbols,
3317
- targetId: input.target.targetId,
3318
- sourceId,
3319
- sourceFile,
3320
- diagnostics
3321
- });
3322
- validateBlockModelAttributeRequirements({
3323
- scopes: [topLevel, ...namespaceSymbols],
3324
- pslBlockDescriptors: input.authoringContributions?.pslBlockDescriptors ?? {},
3325
- sourceId,
3326
- diagnostics
3327
- });
3328
- const models = [];
3329
- const modelEntries = [];
3330
- const modelNamespaceIds = /* @__PURE__ */ new Map();
3331
- const compositeTypes = [];
3332
- const collectScope = (bucketName, scopeModels, scopeCompositeTypes) => {
3333
- const resolvedNamespaceId = resolveNamespaceIdForSqlTarget({
3334
- bucketName,
3335
- targetId: input.target.targetId
3336
- });
3337
- for (const model of scopeModels) {
3338
- models.push(model);
3339
- modelEntries.push({
3340
- model,
3341
- namespaceId: resolvedNamespaceId
3342
- });
3343
- if (resolvedNamespaceId !== void 0) modelNamespaceIds.set(model.name, resolvedNamespaceId);
3344
- }
3345
- for (const compositeType of scopeCompositeTypes) compositeTypes.push(compositeType);
3346
- };
3347
- collectScope(UNSPECIFIED_PSL_NAMESPACE_NAME, Object.values(topLevel.models), Object.values(topLevel.compositeTypes));
3348
- for (const namespace of namespaceSymbols) collectScope(namespace.name, Object.values(namespace.models), Object.values(namespace.compositeTypes));
3349
- const defaultNamespaceId = input.target.defaultNamespaceId;
3350
- const modelNames = new Set(models.map((model) => model.name));
3351
- const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
3352
- const composedExtensions = new Set(input.composedExtensions ?? []);
3353
- const composedExtensionContracts = input.composedExtensionContracts;
3354
- const defaultFunctionRegistry = input.controlMutationDefaults?.defaultFunctionRegistry ?? /* @__PURE__ */ new Map();
3355
- const generatorDescriptors = input.controlMutationDefaults?.generatorDescriptors ?? [];
3356
- const generatorDescriptorById = /* @__PURE__ */ new Map();
3357
- for (const descriptor of generatorDescriptors) generatorDescriptorById.set(descriptor.id, descriptor);
3358
- const isEnumBlock = (block) => block.keyword === "enum";
3359
- const legitimateBlockKeywords = composedBlockKeywords(input.authoringContributions);
3360
- const reportUnsupportedTopLevelBlock = (block) => {
3361
- diagnostics.push({
3362
- code: "PSL_UNSUPPORTED_TOP_LEVEL_BLOCK",
3363
- message: `Unsupported top-level block "${block.keyword}"`,
3364
- sourceId,
3365
- span: keywordPslSpan(block.node.syntax, block.keyword, sourceFile)
3366
- });
3367
- };
3368
- const topLevelEnums = [];
3369
- const topLevelExtensionBlocks = {};
3370
- for (const [blockName, block] of Object.entries(topLevel.blocks)) {
3371
- if (!legitimateBlockKeywords.has(block.keyword)) {
3372
- reportUnsupportedTopLevelBlock(block);
3373
- continue;
3374
- }
3375
- if (isEnumBlock(block)) topLevelEnums.push(block.block);
3376
- else topLevelExtensionBlocks[blockName] = block;
3377
- }
3378
- for (const namespace of namespaceSymbols) for (const block of Object.values(namespace.blocks)) {
3379
- if (isEnumBlock(block)) {
3380
- diagnostics.push({
3381
- code: "PSL_ENUM_NAMESPACE_NOT_SUPPORTED",
3382
- message: `enum "${block.name}" inside namespace "${namespace.name}" is not supported; declare enum at the top level`,
3383
- sourceId,
3384
- span: nodePslSpan(block.node.syntax, sourceFile)
3385
- });
3386
- continue;
3387
- }
3388
- if (!legitimateBlockKeywords.has(block.keyword)) reportUnsupportedTopLevelBlock(block);
3389
- }
3390
- const enumResult = processEnumDeclarations({
3391
- enumBlocks: topLevelEnums,
3392
- sourceId,
3393
- authoringContributions: input.authoringContributions,
3394
- entityContext: {
3395
- family: input.target.familyId,
3396
- target: input.target.targetId,
3397
- ...ifDefined("codecLookup", input.codecLookup),
3398
- sourceId,
3399
- diagnostics: { push: (d) => {
3400
- diagnostics.push(blindCast(d));
3401
- } },
3402
- ...ifDefined("enumInferenceCodecs", input.enumInferenceCodecs)
3403
- },
3404
- diagnostics
3405
- });
3406
- const allEnumTypeDescriptors = new Map(enumResult.enumTypeDescriptors);
3407
- const validEnumHandles = { ...enumResult.enumHandles };
3408
- const enumHandlesByName = new Map(Object.entries(validEnumHandles));
3409
- const entityTypesByDiscriminator = buildEntityTypesByDiscriminator(input.authoringContributions);
3410
- const modelAttributesByName = buildModelAttributesByName(input.authoringContributions);
3411
- const authoringWarnings = [];
3412
- const extensionEntityContext = {
3413
- family: input.target.familyId,
3414
- target: input.target.targetId,
3415
- ...ifDefined("enumInferenceCodecs", input.enumInferenceCodecs),
3416
- ...ifDefined("codecLookup", input.codecLookup),
3417
- sourceId,
3418
- diagnostics: { push: (d) => {
3419
- diagnostics.push(blindCast(d));
3420
- } },
3421
- warnings: authoringWarnings
3422
- };
3423
- const earlyModelMappingsByCoordinate = buildModelMappings(modelEntries, defaultNamespaceId, [], sourceId, sourceFile);
3424
- const composedPslBlockDescriptors = input.authoringContributions?.pslBlockDescriptors ?? {};
3425
- const namespaceExtensionEntities = /* @__PURE__ */ new Map();
3426
- const mergeNamespaceExtensionEntities = (nsId, entities) => {
3427
- if (Object.keys(entities).length === 0) return;
3428
- const existing = namespaceExtensionEntities.get(nsId);
3429
- if (existing === void 0) {
3430
- namespaceExtensionEntities.set(nsId, entities);
3431
- return;
3432
- }
3433
- const merged = { ...existing };
3434
- for (const [entriesKey, slot] of Object.entries(entities)) {
3435
- const existingSlot = existing[entriesKey];
3436
- if (existingSlot !== void 0) {
3437
- for (const name of Object.keys(slot)) if (Object.hasOwn(existingSlot, name)) diagnostics.push({
3438
- code: "PSL_DUPLICATE_EXTENSION_ENTITY",
3439
- message: `entries slot "${entriesKey}" in namespace "${nsId}": entity "${name}" is declared more than once in the same namespace.`,
3440
- sourceId
3441
- });
3442
- }
3443
- merged[entriesKey] = {
3444
- ...existingSlot,
3445
- ...slot
3446
- };
3447
- }
3448
- namespaceExtensionEntities.set(nsId, merged);
3449
- };
3450
- for (const ns of namespaceSymbols) {
3451
- if (ns.name === UNSPECIFIED_PSL_NAMESPACE_NAME) continue;
3452
- const nsId = resolveNamespaceIdForSqlTarget({
3453
- bucketName: ns.name,
3454
- targetId: input.target.targetId
3455
- });
3456
- if (nsId === void 0) continue;
3457
- mergeNamespaceExtensionEntities(nsId, lowerExtensionBlocksForNamespace(ns.blocks, nsId, entityTypesByDiscriminator, extensionEntityContext, composedPslBlockDescriptors, (modelName) => earlyModelMappingsByCoordinate.get(modelCoordinateKey(nsId, modelName))?.tableName));
3458
- }
3459
- if (Object.keys(topLevelExtensionBlocks).length > 0) {
3460
- const topLevelNsId = resolveNamespaceIdForSqlTarget({
3461
- bucketName: UNSPECIFIED_PSL_NAMESPACE_NAME,
3462
- targetId: input.target.targetId
3463
- }) ?? defaultNamespaceId;
3464
- mergeNamespaceExtensionEntities(topLevelNsId, lowerExtensionBlocksForNamespace(topLevelExtensionBlocks, topLevelNsId, entityTypesByDiscriminator, extensionEntityContext, composedPslBlockDescriptors, (modelName) => earlyModelMappingsByCoordinate.get(modelCoordinateKey(topLevelNsId, modelName))?.tableName));
3465
- }
3466
- const defaultNsExtensionValueSets = namespaceExtensionEntities.get(defaultNamespaceId)?.["valueSet"];
3467
- if (defaultNsExtensionValueSets !== void 0) {
3468
- for (const name of Object.keys(defaultNsExtensionValueSets)) if (Object.hasOwn(validEnumHandles, name)) diagnostics.push({
3469
- code: "PSL_VALUE_SET_NAME_COLLISION",
3470
- message: `namespace "${defaultNamespaceId}": name "${name}" is declared both as a domain enum and as an extension entity that derives a value-set; rename one`,
3471
- sourceId
3472
- });
3473
- }
3474
- const isScalarRefinement = (symbol) => !symbol.isConstructor && symbol.baseType !== void 0 && input.scalarColumnDescriptors.has(symbol.baseType);
3475
- const allNamedTypes = Object.values(topLevel.namedTypes);
3476
- const namedTypeResult = resolveNamedTypeDeclarations({
3477
- declarations: [...allNamedTypes.filter(isScalarRefinement), ...allNamedTypes.filter((symbol) => !isScalarRefinement(symbol))],
3478
- sourceId,
3479
- enumTypeDescriptors: allEnumTypeDescriptors,
3480
- scalarColumnDescriptors: input.scalarColumnDescriptors,
3481
- composedExtensions,
3482
- familyId: input.target.familyId,
3483
- targetId: input.target.targetId,
3484
- authoringContributions: input.authoringContributions,
3485
- diagnostics
3486
- });
3487
- const storageTypes = { ...namedTypeResult.storageTypes };
3488
- const modelMappingsByCoordinate = buildModelMappings(modelEntries, defaultNamespaceId, diagnostics, sourceId, sourceFile);
3489
- const modelMappings = /* @__PURE__ */ new Map();
3490
- for (const mapping of modelMappingsByCoordinate.values()) modelMappings.set(mapping.model.name, mapping);
3491
- const modelNodes = [];
3492
- const fkRelationMetadata = [];
3493
- const backrelationCandidates = [];
3494
- const modelResolvedFields = /* @__PURE__ */ new Map();
3495
- const crossSpaceRelationsByModel = /* @__PURE__ */ new Map();
3496
- const modelAttributeEntitiesByNamespace = /* @__PURE__ */ new Map();
3497
- for (const { model, namespaceId } of modelEntries) {
3498
- const coordinate = modelCoordinateKey(namespaceId ?? defaultNamespaceId, model.name);
3499
- const mapping = modelMappingsByCoordinate.get(coordinate);
3500
- if (!mapping) continue;
3501
- const result = buildModelNodeFromPsl({
3502
- model,
3503
- mapping,
3504
- modelMappings,
3505
- modelMappingsByCoordinate,
3506
- modelNames,
3507
- compositeTypeNames,
3508
- enumTypeDescriptors: allEnumTypeDescriptors,
3509
- namedTypeDescriptors: namedTypeResult.namedTypeDescriptors,
3510
- composedExtensions,
3511
- composedExtensionContracts,
3512
- familyId: input.target.familyId,
3513
- targetId: input.target.targetId,
3514
- authoringContributions: input.authoringContributions,
3515
- defaultFunctionRegistry,
3516
- generatorDescriptorById,
3517
- scalarColumnDescriptors: input.scalarColumnDescriptors,
3518
- sourceId,
3519
- sourceFile,
3520
- symbolTable: input.symbolTable,
3521
- diagnostics,
3522
- modelNamespaceIds,
3523
- ...enumHandlesByName.size > 0 ? { enumHandles: enumHandlesByName } : {},
3524
- capabilities: input.capabilities,
3525
- ...namespaceExtensionEntities.size > 0 ? { namespaceExtensionEntities } : {},
3526
- ...ifDefined("codecLookup", input.codecLookup),
3527
- modelAttributesByName,
3528
- defaultNamespaceId
3529
- });
3530
- modelNodes.push(namespaceId !== void 0 ? {
3531
- ...result.modelNode,
3532
- namespaceId
3533
- } : result.modelNode);
3534
- fkRelationMetadata.push(...result.fkRelationMetadata);
3535
- backrelationCandidates.push(...result.backrelationCandidates);
3536
- modelResolvedFields.set(coordinate, result.resolvedFields);
3537
- if (result.crossSpaceRelations.length > 0) {
3538
- const existing = crossSpaceRelationsByModel.get(model.name) ?? [];
3539
- crossSpaceRelationsByModel.set(model.name, [...existing, ...result.crossSpaceRelations]);
3540
- }
3541
- if (Object.keys(result.modelAttributeEntities).length > 0) {
3542
- const nsKey = namespaceId ?? defaultNamespaceId;
3543
- const existingByAttribute = modelAttributeEntitiesByNamespace.get(nsKey) ?? {};
3544
- for (const [attribute, keyed] of Object.entries(result.modelAttributeEntities)) existingByAttribute[attribute] = {
3545
- ...existingByAttribute[attribute] ?? {},
3546
- ...keyed
3547
- };
3548
- modelAttributeEntitiesByNamespace.set(nsKey, existingByAttribute);
3549
- }
3550
- }
3551
- const { modelRelations, fkRelationsByPair, fkRelationsByDeclaringModel } = indexFkRelations({ fkRelationMetadata });
3552
- const modelIdColumns = /* @__PURE__ */ new Map();
3553
- const modelUniqueColumnSets = /* @__PURE__ */ new Map();
3554
- for (const modelNode of modelNodes) {
3555
- if (modelNode.id) modelIdColumns.set(modelNode.modelName, modelNode.id.columns);
3556
- const uniqueColumnSets = [];
3557
- if (modelNode.id) uniqueColumnSets.push(modelNode.id.columns);
3558
- for (const unique of modelNode.uniques ?? []) uniqueColumnSets.push(unique.columns);
3559
- modelUniqueColumnSets.set(modelNode.modelName, uniqueColumnSets);
3560
- }
3561
- applyBackrelationCandidates({
3562
- backrelationCandidates,
3563
- fkRelationsByPair,
3564
- fkRelationsByDeclaringModel,
3565
- modelIdColumns,
3566
- modelUniqueColumnSets,
3567
- modelRelations,
3568
- diagnostics,
3569
- sourceId
3570
- });
3571
- for (const [modelName, relations] of crossSpaceRelationsByModel) {
3572
- const existing = modelRelations.get(modelName);
3573
- if (existing) existing.push(...relations);
3574
- else modelRelations.set(modelName, [...relations]);
3575
- }
3576
- const { discriminatorDeclarations, baseDeclarations } = collectPolymorphismDeclarations(models, sourceFile, sourceId, diagnostics);
3577
- const stiVariantNames = /* @__PURE__ */ new Set();
3578
- for (const variantName of baseDeclarations.keys()) if (!(modelMappings.get(variantName)?.model.attributes.some((attr) => attr.name === "map") ?? false)) stiVariantNames.add(variantName);
3579
- for (const variantName of stiVariantNames) {
3580
- const variantMapping = modelMappings.get(variantName);
3581
- if (variantMapping === void 0) continue;
3582
- const baseDecl = baseDeclarations.get(variantName);
3583
- invariant(baseDecl !== void 0, `stiVariantNames is derived from baseDeclarations.keys(), so "${variantName}" must have a base declaration`);
3584
- for (const attribute of variantMapping.model.node.attributes()) {
3585
- if (attribute.name()?.isSimpleName("check") !== true) continue;
3586
- diagnostics.push({
3587
- code: PSL_CHECK_ON_STI_VARIANT,
3588
- message: `Model "${variantName}" declares "@@check", but it shares its base model "${baseDecl.baseName}"'s storage table (single-table inheritance via @@base) and has no table of its own to declare a check constraint on. Declare the check on "${baseDecl.baseName}" instead.`,
3589
- sourceId,
3590
- span: nodePslSpan(attribute.syntax, sourceFile)
3591
- });
3592
- }
3593
- }
3594
- const { modelNodes: mtiLinkedModelNodes, syntheticPkFieldsByVariant } = materializeMtiVariantStorageLinks(modelNodes, baseDeclarations, stiVariantNames);
3595
- const { modelNodes: stiColumnModelNodes, stiBaseFieldsByBase } = materializeStiVariantStorageColumns(mtiLinkedModelNodes, baseDeclarations, stiVariantNames);
3596
- const valueObjects = buildValueObjects({
3597
- compositeTypes,
3598
- enumTypeDescriptors: allEnumTypeDescriptors,
3599
- namedTypeDescriptors: namedTypeResult.namedTypeDescriptors,
3600
- scalarColumnDescriptors: input.scalarColumnDescriptors,
3601
- composedExtensions,
3602
- familyId: input.target.familyId,
3603
- targetId: input.target.targetId,
3604
- authoringContributions: input.authoringContributions,
3605
- diagnostics,
3606
- sourceId
3607
- });
3608
- if (diagnostics.length > 0) return notOk({
3609
- summary: "PSL to SQL contract interpretation failed",
3610
- diagnostics
3611
- });
3612
- const { createNamespace } = input;
3613
- const createNamespaceWithExtensions = (nsInput) => {
3614
- const entities = namespaceExtensionEntities.get(nsInput.id);
3615
- const attributeEntities = modelAttributeEntitiesByNamespace.get(nsInput.id);
3616
- if (entities === void 0 && attributeEntities === void 0) return createNamespace(nsInput);
3617
- if (attributeEntities !== void 0) {
3618
- for (const slot of Object.keys(attributeEntities)) if (Object.hasOwn(nsInput.entries, slot) || entities !== void 0 && slot in entities) throw contractError("CONTRACT.PACK_CONTRIBUTION_INVALID", `entries slot "${slot}" in namespace "${nsInput.id}" is contributed by both a model attribute and a block/base entry kind. A model-attribute entries key must be unique across the namespace's entry kinds.`, { meta: {
3619
- slot,
3620
- namespaceId: nsInput.id
3621
- } });
3622
- }
3623
- const mergedValueSet = {
3624
- ...nsInput.entries["valueSet"],
3625
- ...entities?.["valueSet"]
3626
- };
3627
- const extended = {
3628
- ...nsInput,
3629
- entries: {
3630
- ...nsInput.entries,
3631
- ...entities,
3632
- ...attributeEntities,
3633
- ...Object.keys(mergedValueSet).length > 0 ? { valueSet: mergedValueSet } : {}
3634
- }
3635
- };
3636
- return createNamespace(extended);
3637
- };
3638
- const contract = buildSqlContractFromDefinition({
3639
- target: input.target,
3640
- warnings: authoringWarnings.length > 0 ? authoringWarnings : void 0,
3641
- ...ifDefined("extensions", buildComposedExtensionPackRefs(input.target, [...composedExtensions].sort(compareStrings), input.composedExtensionPackRefs)),
3642
- ...Object.keys(storageTypes).length > 0 ? { storageTypes } : {},
3643
- ...Object.keys(validEnumHandles).length > 0 ? { enums: validEnumHandles } : {},
3644
- ...namespaceExtensionEntities.size > 0 ? { namespaces: [...namespaceExtensionEntities.keys()] } : {},
3645
- createNamespace: createNamespaceWithExtensions,
3646
- models: stiColumnModelNodes.map((model) => ({
3647
- ...model,
3648
- ...modelRelations.has(model.modelName) ? { relations: [...modelRelations.get(model.modelName) ?? []].sort((left, right) => compareStrings(left.fieldName, right.fieldName)) } : {}
3649
- }))
3650
- }, input.codecLookup);
3651
- const modelsForPatch = {};
3652
- for (const [namespaceId, namespaceSlice] of Object.entries(contract.domain.namespaces)) for (const [modelName, model] of Object.entries(namespaceSlice.models)) {
3653
- const coordinate = modelCoordinateKey(namespaceId, modelName);
3654
- invariant(!Object.hasOwn(modelsForPatch, coordinate), `symbol table guarantees coordinate uniqueness; duplicate model "${namespaceId}.${modelName}" reached interpretation`);
3655
- modelsForPatch[coordinate] = model;
3656
- }
3657
- let patchedModels = patchModelDomainFields(modelsForPatch, modelResolvedFields);
3658
- const polyDiagnostics = [];
3659
- patchedModels = resolvePolymorphism(patchedModels, discriminatorDeclarations, baseDeclarations, modelNames, modelMappings, modelNamespaceIds, input.target.defaultNamespaceId, syntheticPkFieldsByVariant, stiBaseFieldsByBase, sourceId, polyDiagnostics);
3660
- if (polyDiagnostics.length > 0) return notOk({
3661
- summary: "PSL to SQL contract interpretation failed",
3662
- diagnostics: polyDiagnostics
3663
- });
3664
- const variantModelNames = new Set(baseDeclarations.keys());
3665
- const filteredRoots = Object.fromEntries(Object.entries(contract.roots).filter(([, crossReference]) => !variantModelNames.has(crossReference.model)));
3666
- return ok({
3667
- ...contract,
3668
- roots: filteredRoots,
3669
- domain: { namespaces: Object.fromEntries(Object.entries(contract.domain.namespaces).map(([namespaceId, namespaceSlice]) => [namespaceId, {
3670
- models: Object.fromEntries(Object.entries(namespaceSlice.models).map(([modelName, model]) => [modelName, patchedModels[modelCoordinateKey(namespaceId, modelName)] ?? model])),
3671
- ...ifDefined("enum", namespaceSlice.enum),
3672
- ...ifDefined("valueObjects", namespaceSlice.valueObjects),
3673
- ...namespaceId === input.target.defaultNamespaceId && Object.keys(valueObjects).length > 0 ? { valueObjects } : {}
3674
- }])) }
3675
- });
3676
- }
3677
- //#endregion
3678
- export { interpretPslDocumentToSqlContract as t };
3679
-
3680
- //# sourceMappingURL=interpreter-DyiUUAWh-DYdjIpiE.mjs.map