@prisma/orm-family-sql 0.16.0-dev.36

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