fundus 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/README.md +121 -0
  2. package/build/client/_app/immutable/assets/2.X44Wyac-.css +1 -0
  3. package/build/client/_app/immutable/assets/2.X44Wyac-.css.br +0 -0
  4. package/build/client/_app/immutable/assets/2.X44Wyac-.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/{3.C6xo25uI.css → 3.66PJT3JC.css} +1 -1
  6. package/build/client/_app/immutable/assets/3.66PJT3JC.css.br +0 -0
  7. package/build/client/_app/immutable/assets/3.66PJT3JC.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/{AssetSourceMenu.IjDdjx3o.css → AssetSourceMenu.B5fzYfym.css} +1 -1
  9. package/build/client/_app/immutable/assets/AssetSourceMenu.B5fzYfym.css.br +0 -0
  10. package/build/client/_app/immutable/assets/AssetSourceMenu.B5fzYfym.css.gz +0 -0
  11. package/build/client/_app/immutable/chunks/B06eqbax.js +108 -0
  12. package/build/client/_app/immutable/chunks/B06eqbax.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/B06eqbax.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/{dNO-9VOT.js → B97y-eFA.js} +1 -1
  15. package/build/client/_app/immutable/chunks/B97y-eFA.js.br +0 -0
  16. package/build/client/_app/immutable/chunks/B97y-eFA.js.gz +0 -0
  17. package/build/client/_app/immutable/chunks/BmOjTxFk.js +1 -0
  18. package/build/client/_app/immutable/chunks/BmOjTxFk.js.br +0 -0
  19. package/build/client/_app/immutable/chunks/BmOjTxFk.js.gz +0 -0
  20. package/build/client/_app/immutable/chunks/C9MzfQz6.js +2 -0
  21. package/build/client/_app/immutable/chunks/C9MzfQz6.js.br +0 -0
  22. package/build/client/_app/immutable/chunks/C9MzfQz6.js.gz +0 -0
  23. package/build/client/_app/immutable/chunks/CcuyGBqj.js +1 -0
  24. package/build/client/_app/immutable/chunks/CcuyGBqj.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/CcuyGBqj.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/{77p2oEJ1.js → D6c2mfMB.js} +1 -1
  27. package/build/client/_app/immutable/chunks/D6c2mfMB.js.br +2 -0
  28. package/build/client/_app/immutable/chunks/D6c2mfMB.js.gz +0 -0
  29. package/build/client/_app/immutable/chunks/DY9QjkXW.js +1 -0
  30. package/build/client/_app/immutable/chunks/DY9QjkXW.js.br +0 -0
  31. package/build/client/_app/immutable/chunks/DY9QjkXW.js.gz +0 -0
  32. package/build/client/_app/immutable/chunks/Z8rcWjXZ.js +3 -0
  33. package/build/client/_app/immutable/chunks/Z8rcWjXZ.js.br +0 -0
  34. package/build/client/_app/immutable/chunks/Z8rcWjXZ.js.gz +0 -0
  35. package/build/client/_app/immutable/entry/app.V1MmmICK.js +2 -0
  36. package/build/client/_app/immutable/entry/app.V1MmmICK.js.br +0 -0
  37. package/build/client/_app/immutable/entry/app.V1MmmICK.js.gz +0 -0
  38. package/build/client/_app/immutable/entry/start.BbyflZUw.js +1 -0
  39. package/build/client/_app/immutable/entry/start.BbyflZUw.js.br +0 -0
  40. package/build/client/_app/immutable/entry/start.BbyflZUw.js.gz +0 -0
  41. package/build/client/_app/immutable/nodes/0.BJOUVkow.js +1 -0
  42. package/build/client/_app/immutable/nodes/0.BJOUVkow.js.br +0 -0
  43. package/build/client/_app/immutable/nodes/0.BJOUVkow.js.gz +0 -0
  44. package/build/client/_app/immutable/nodes/1.BqoPRvUU.js +1 -0
  45. package/build/client/_app/immutable/nodes/1.BqoPRvUU.js.br +0 -0
  46. package/build/client/_app/immutable/nodes/1.BqoPRvUU.js.gz +0 -0
  47. package/build/client/_app/immutable/nodes/2.BSUVFDfW.js +3 -0
  48. package/build/client/_app/immutable/nodes/2.BSUVFDfW.js.br +0 -0
  49. package/build/client/_app/immutable/nodes/2.BSUVFDfW.js.gz +0 -0
  50. package/build/client/_app/immutable/nodes/3.B6beFiTQ.js +1 -0
  51. package/build/client/_app/immutable/nodes/3.B6beFiTQ.js.br +0 -0
  52. package/build/client/_app/immutable/nodes/3.B6beFiTQ.js.gz +0 -0
  53. package/build/client/_app/immutable/nodes/4.Dt96q8V4.js +2 -0
  54. package/build/client/_app/immutable/nodes/4.Dt96q8V4.js.br +0 -0
  55. package/build/client/_app/immutable/nodes/4.Dt96q8V4.js.gz +0 -0
  56. package/build/client/_app/version.json +1 -1
  57. package/build/client/_app/version.json.br +0 -0
  58. package/build/client/_app/version.json.gz +0 -0
  59. package/build/handler.js +8 -7
  60. package/build/handler.js.map +1 -1
  61. package/build/index.js +8 -7
  62. package/build/index.js.map +1 -1
  63. package/build/server/chunks/chunks/{context.js-CVuTSPjH.js → context.js-BXaBgcZT.js} +627 -134
  64. package/build/server/chunks/chunks/context.js-BXaBgcZT.js.map +1 -0
  65. package/build/server/chunks/chunks/{contract.js-itFN0Gon.js → contract.js-IY1F-HE_.js} +94 -58
  66. package/build/server/chunks/chunks/contract.js-IY1F-HE_.js.map +1 -0
  67. package/build/server/chunks/chunks/{core.js-CABVXpby.js → core.js-D1sYC_78.js} +144 -143
  68. package/build/server/chunks/chunks/core.js-D1sYC_78.js.map +1 -0
  69. package/build/server/chunks/chunks/{exports.js-B13PkE0J.js → exports.js-B5DLeNXr.js} +2 -2
  70. package/build/server/chunks/chunks/{exports.js-B13PkE0J.js.map → exports.js-B5DLeNXr.js.map} +1 -1
  71. package/build/server/chunks/chunks/{http.js-ChQRRKfZ.js → http.js-CzB9Igb0.js} +2 -2
  72. package/build/server/chunks/chunks/{http.js-ChQRRKfZ.js.map → http.js-CzB9Igb0.js.map} +1 -1
  73. package/build/server/chunks/chunks/{internal.js-DlKoWKM-.js → internal.js-HE35Pm1C.js} +5 -3
  74. package/build/server/chunks/chunks/internal.js-HE35Pm1C.js.map +1 -0
  75. package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
  76. package/build/server/chunks/chunks/{manifest-membership.js-BnSECWpJ.js → manifest-membership.js-Cm_2fU-Z.js} +2 -2
  77. package/build/server/chunks/chunks/{manifest-membership.js-BnSECWpJ.js.map → manifest-membership.js-Cm_2fU-Z.js.map} +1 -1
  78. package/build/server/chunks/chunks/{raw-reconciliation.js-ZEOCk_jA.js → raw-reconciliation.js-1_IwPhKb.js} +3 -3
  79. package/build/server/chunks/chunks/raw-reconciliation.js-1_IwPhKb.js.map +1 -0
  80. package/build/server/chunks/chunks/{raw-reconciliation2.js-CscuoBC2.js → raw-reconciliation2.js-CcO9li5n.js} +2 -2
  81. package/build/server/chunks/chunks/{raw-reconciliation2.js-CscuoBC2.js.map → raw-reconciliation2.js-CcO9li5n.js.map} +1 -1
  82. package/build/server/chunks/chunks/{shared.js-DKt4pwWi.js → shared.js-MR8sPPTu.js} +2 -2
  83. package/build/server/chunks/chunks/{shared.js-DKt4pwWi.js.map → shared.js-MR8sPPTu.js.map} +1 -1
  84. package/build/server/chunks/chunks/{utils.js-BYMC-4Wt.js → utils.js-C2UFBITa.js} +3 -3
  85. package/build/server/chunks/chunks/{utils.js-BYMC-4Wt.js.map → utils.js-C2UFBITa.js.map} +1 -1
  86. package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-z988EDp2.js → _server.ts.js-BnRJ5Qnd.js} +6 -6
  87. package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-z988EDp2.js.map → _server.ts.js-BnRJ5Qnd.js.map} +1 -1
  88. package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-C68ru6gS.js → _server.ts.js-BZPR6n5n.js} +9 -7
  89. package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-C68ru6gS.js.map → _server.ts.js-BZPR6n5n.js.map} +1 -1
  90. package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-C0tk6RFk.js → _server.ts.js-DiBS3A0C.js} +9 -7
  91. package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-C0tk6RFk.js.map → _server.ts.js-DiBS3A0C.js.map} +1 -1
  92. package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-I03oZuo8.js → _server.ts.js-LOO6qm2-.js} +9 -7
  93. package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-I03oZuo8.js.map → _server.ts.js-LOO6qm2-.js.map} +1 -1
  94. package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-BsQB8YDq.js → _server.ts.js-CRtJJoSs.js} +9 -7
  95. package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-BsQB8YDq.js.map → _server.ts.js-CRtJJoSs.js.map} +1 -1
  96. package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-CJuFE6Fb.js → _server.ts.js-Ds4zCZ9H.js} +9 -7
  97. package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-CJuFE6Fb.js.map → _server.ts.js-Ds4zCZ9H.js.map} +1 -1
  98. package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DuOZRRiA.js → _server.ts.js-DD4N8pcj.js} +9 -7
  99. package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DuOZRRiA.js.map → _server.ts.js-DD4N8pcj.js.map} +1 -1
  100. package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-DGzYpQbv.js → _server.ts.js-CZev9aYz.js} +9 -7
  101. package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-DGzYpQbv.js.map → _server.ts.js-CZev9aYz.js.map} +1 -1
  102. package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-B045QoCA.js → _server.ts.js-MBDVW0q1.js} +9 -7
  103. package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-B045QoCA.js.map → _server.ts.js-MBDVW0q1.js.map} +1 -1
  104. package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-HUkVdz19.js → _server.ts.js-C7naXnsR.js} +9 -7
  105. package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-HUkVdz19.js.map → _server.ts.js-C7naXnsR.js.map} +1 -1
  106. package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-ry509mom.js → _server.ts.js-DuGyRdf3.js} +9 -7
  107. package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-ry509mom.js.map → _server.ts.js-DuGyRdf3.js.map} +1 -1
  108. package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-DU0J7U25.js → _server.ts.js-0-ZCt0qH.js} +9 -7
  109. package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-DU0J7U25.js.map → _server.ts.js-0-ZCt0qH.js.map} +1 -1
  110. package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-AZIV2PIn.js → _server.ts.js-DFYU_sZL.js} +9 -7
  111. package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-AZIV2PIn.js.map → _server.ts.js-DFYU_sZL.js.map} +1 -1
  112. package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CDL0hCfM.js → _server.ts.js-BqJpK0sJ.js} +9 -7
  113. package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CDL0hCfM.js.map → _server.ts.js-BqJpK0sJ.js.map} +1 -1
  114. package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-B13c17fq.js → _server.ts.js--LSqADJp.js} +9 -7
  115. package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-B13c17fq.js.map → _server.ts.js--LSqADJp.js.map} +1 -1
  116. package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-BCxjyAGC.js → _server.ts.js-DcL8nYDM.js} +9 -7
  117. package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-BCxjyAGC.js.map → _server.ts.js-DcL8nYDM.js.map} +1 -1
  118. package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-BveeMZc2.js → _server.ts.js-72OcyLfP.js} +9 -7
  119. package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-BveeMZc2.js.map → _server.ts.js-72OcyLfP.js.map} +1 -1
  120. package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-BZjTd9a0.js → _server.ts.js-D0bOxmG0.js} +9 -7
  121. package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-BZjTd9a0.js.map → _server.ts.js-D0bOxmG0.js.map} +1 -1
  122. package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-BbTfPvC9.js → _server.ts.js-BjDVCRNV.js} +9 -7
  123. package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-BbTfPvC9.js.map → _server.ts.js-BjDVCRNV.js.map} +1 -1
  124. package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-8VPJMLBk.js → _server.ts.js-CndfoXXd.js} +6 -6
  125. package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-8VPJMLBk.js.map → _server.ts.js-CndfoXXd.js.map} +1 -1
  126. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-BqR2J2sB.js → _server.ts.js-Ck1mgbk5.js} +9 -7
  127. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-BqR2J2sB.js.map → _server.ts.js-Ck1mgbk5.js.map} +1 -1
  128. package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-DbA28dCY.js → _server.ts.js-lZ9oP8tz.js} +9 -7
  129. package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-DbA28dCY.js.map → _server.ts.js-lZ9oP8tz.js.map} +1 -1
  130. package/build/server/chunks/entries/{hooks.server.js-9PBc_3Jh.js → hooks.server.js-DQ6l2RSK.js} +8 -6
  131. package/build/server/chunks/entries/{hooks.server.js-9PBc_3Jh.js.map → hooks.server.js-DQ6l2RSK.js.map} +1 -1
  132. package/build/server/chunks/{handler-XxBNCHhb.js → handler-Dfk_4a-r.js} +5 -5
  133. package/build/server/chunks/{handler-XxBNCHhb.js.map → handler-Dfk_4a-r.js.map} +1 -1
  134. package/build/server/chunks/{index.js-B_76Gq5Y.js → index.js-O3Wl1zok.js} +5 -5
  135. package/build/server/chunks/{index.js-B_76Gq5Y.js.map → index.js-O3Wl1zok.js.map} +1 -1
  136. package/build/server/chunks/{manifest.js-C2MZZt3o.js → manifest.js-51nEZnKQ.js} +29 -29
  137. package/build/server/chunks/{manifest.js-C2MZZt3o.js.map → manifest.js-51nEZnKQ.js.map} +1 -1
  138. package/build/server/chunks/nodes/{0.js-BLURyWmd.js → 0.js-DjqMfDtB.js} +2 -2
  139. package/build/server/chunks/nodes/{0.js-BLURyWmd.js.map → 0.js-DjqMfDtB.js.map} +1 -1
  140. package/build/server/chunks/nodes/1.js-BwfSLYJH.js +7 -0
  141. package/build/server/chunks/nodes/{1.js-CITI7d3d.js.map → 1.js-BwfSLYJH.js.map} +1 -1
  142. package/build/server/chunks/nodes/2.js-buHbEytf.js +7 -0
  143. package/build/server/chunks/nodes/2.js-buHbEytf.js.map +1 -0
  144. package/build/server/chunks/nodes/3.js-D7_hF0qp.js +7 -0
  145. package/build/server/chunks/nodes/3.js-D7_hF0qp.js.map +1 -0
  146. package/build/server/chunks/nodes/4.js-D58M2chZ.js +7 -0
  147. package/build/server/chunks/nodes/{4.js-BRlAiVnn.js.map → 4.js-D58M2chZ.js.map} +1 -1
  148. package/dist/config.d.ts +3 -3
  149. package/dist/config.js +2 -2
  150. package/dist/core/api-types.d.ts +22 -2
  151. package/dist/core/config.d.ts +82 -0
  152. package/dist/core/config.js +9 -0
  153. package/dist/core/index.d.ts +10 -5
  154. package/dist/core/index.js +5 -2
  155. package/dist/core/library-validation.d.ts +13 -0
  156. package/dist/core/library-validation.js +48 -0
  157. package/dist/core/library.d.ts +19 -0
  158. package/dist/core/library.js +4 -4
  159. package/dist/core/manifest-membership.d.ts +2 -2
  160. package/dist/core/package-declaration.d.ts +43 -0
  161. package/dist/core/package-declaration.js +80 -0
  162. package/dist/core/package-merge.d.ts +65 -0
  163. package/dist/core/package-merge.js +173 -0
  164. package/dist/core/reference-graph.d.ts +3 -3
  165. package/dist/runtime/components/Image.svelte +5 -6
  166. package/dist/runtime/components/Image.svelte.d.ts +2 -3
  167. package/dist/server/build.js +26 -11
  168. package/dist/server/check.d.ts +13 -3
  169. package/dist/server/check.js +112 -24
  170. package/dist/server/codegen.d.ts +3 -1
  171. package/dist/server/codegen.js +18 -0
  172. package/dist/server/config-loader.d.ts +35 -1
  173. package/dist/server/config-loader.js +185 -4
  174. package/dist/server/library-store.d.ts +11 -1
  175. package/dist/server/library-store.js +42 -60
  176. package/dist/server/operations.js +162 -47
  177. package/package.json +1 -1
  178. package/build/client/_app/immutable/assets/2.C-1MfvLQ.css +0 -1
  179. package/build/client/_app/immutable/assets/2.C-1MfvLQ.css.br +0 -0
  180. package/build/client/_app/immutable/assets/2.C-1MfvLQ.css.gz +0 -0
  181. package/build/client/_app/immutable/assets/3.C6xo25uI.css.br +0 -0
  182. package/build/client/_app/immutable/assets/3.C6xo25uI.css.gz +0 -0
  183. package/build/client/_app/immutable/assets/AssetSourceMenu.IjDdjx3o.css.br +0 -0
  184. package/build/client/_app/immutable/assets/AssetSourceMenu.IjDdjx3o.css.gz +0 -0
  185. package/build/client/_app/immutable/chunks/77p2oEJ1.js.br +0 -0
  186. package/build/client/_app/immutable/chunks/77p2oEJ1.js.gz +0 -0
  187. package/build/client/_app/immutable/chunks/B9HdDE5n.js +0 -1
  188. package/build/client/_app/immutable/chunks/B9HdDE5n.js.br +0 -0
  189. package/build/client/_app/immutable/chunks/B9HdDE5n.js.gz +0 -0
  190. package/build/client/_app/immutable/chunks/B_PWcB6g.js +0 -108
  191. package/build/client/_app/immutable/chunks/B_PWcB6g.js.br +0 -0
  192. package/build/client/_app/immutable/chunks/B_PWcB6g.js.gz +0 -0
  193. package/build/client/_app/immutable/chunks/Q50krHyn.js +0 -2
  194. package/build/client/_app/immutable/chunks/Q50krHyn.js.br +0 -0
  195. package/build/client/_app/immutable/chunks/Q50krHyn.js.gz +0 -0
  196. package/build/client/_app/immutable/chunks/RgXSPQ_h.js +0 -1
  197. package/build/client/_app/immutable/chunks/RgXSPQ_h.js.br +0 -0
  198. package/build/client/_app/immutable/chunks/RgXSPQ_h.js.gz +0 -0
  199. package/build/client/_app/immutable/chunks/YpiA5Xry.js +0 -3
  200. package/build/client/_app/immutable/chunks/YpiA5Xry.js.br +0 -0
  201. package/build/client/_app/immutable/chunks/YpiA5Xry.js.gz +0 -0
  202. package/build/client/_app/immutable/chunks/dNO-9VOT.js.br +0 -0
  203. package/build/client/_app/immutable/chunks/dNO-9VOT.js.gz +0 -0
  204. package/build/client/_app/immutable/chunks/hUfV2O0k.js +0 -1
  205. package/build/client/_app/immutable/chunks/hUfV2O0k.js.br +0 -0
  206. package/build/client/_app/immutable/chunks/hUfV2O0k.js.gz +0 -0
  207. package/build/client/_app/immutable/entry/app.BsvwTApt.js +0 -2
  208. package/build/client/_app/immutable/entry/app.BsvwTApt.js.br +0 -0
  209. package/build/client/_app/immutable/entry/app.BsvwTApt.js.gz +0 -0
  210. package/build/client/_app/immutable/entry/start.BdjLMMsY.js +0 -1
  211. package/build/client/_app/immutable/entry/start.BdjLMMsY.js.br +0 -0
  212. package/build/client/_app/immutable/entry/start.BdjLMMsY.js.gz +0 -0
  213. package/build/client/_app/immutable/nodes/0.CjQfQrD6.js +0 -1
  214. package/build/client/_app/immutable/nodes/0.CjQfQrD6.js.br +0 -0
  215. package/build/client/_app/immutable/nodes/0.CjQfQrD6.js.gz +0 -0
  216. package/build/client/_app/immutable/nodes/1.DyPcUKIh.js +0 -1
  217. package/build/client/_app/immutable/nodes/1.DyPcUKIh.js.br +0 -2
  218. package/build/client/_app/immutable/nodes/1.DyPcUKIh.js.gz +0 -0
  219. package/build/client/_app/immutable/nodes/2.CworwA2R.js +0 -3
  220. package/build/client/_app/immutable/nodes/2.CworwA2R.js.br +0 -0
  221. package/build/client/_app/immutable/nodes/2.CworwA2R.js.gz +0 -0
  222. package/build/client/_app/immutable/nodes/3.BKqbML1T.js +0 -1
  223. package/build/client/_app/immutable/nodes/3.BKqbML1T.js.br +0 -0
  224. package/build/client/_app/immutable/nodes/3.BKqbML1T.js.gz +0 -0
  225. package/build/client/_app/immutable/nodes/4.Cmigd8CT.js +0 -2
  226. package/build/client/_app/immutable/nodes/4.Cmigd8CT.js.br +0 -0
  227. package/build/client/_app/immutable/nodes/4.Cmigd8CT.js.gz +0 -0
  228. package/build/server/chunks/chunks/context.js-CVuTSPjH.js.map +0 -1
  229. package/build/server/chunks/chunks/contract.js-itFN0Gon.js.map +0 -1
  230. package/build/server/chunks/chunks/core.js-CABVXpby.js.map +0 -1
  231. package/build/server/chunks/chunks/internal.js-DlKoWKM-.js.map +0 -1
  232. package/build/server/chunks/chunks/raw-reconciliation.js-ZEOCk_jA.js.map +0 -1
  233. package/build/server/chunks/nodes/1.js-CITI7d3d.js +0 -7
  234. package/build/server/chunks/nodes/2.js-DAls5TjF.js +0 -7
  235. package/build/server/chunks/nodes/2.js-DAls5TjF.js.map +0 -1
  236. package/build/server/chunks/nodes/3.js-CesAmg_E.js +0 -7
  237. package/build/server/chunks/nodes/3.js-CesAmg_E.js.map +0 -1
  238. package/build/server/chunks/nodes/4.js-BRlAiVnn.js +0 -7
@@ -1,11 +1,13 @@
1
- import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, H as typesForFileName, J as proposeAssetId, k as parentFolderPath, u as portableFolderPathKey } from './core.js-CABVXpby.js';
2
- import { s as serverPluginsByType, i as isRecord, L as LibraryStore, d as descriptorsByType, m as manifestModuleFileName, l as locateGeneratedAssetDeclaration, a as serializeLibrary, b as serverPluginForType, S as SourceImportError, p as processAssets, g as generateManifestModules, r as readCurrentProxy, e as encodeRelativePathForUrl, c as invalidInput, f as parseLibrary } from './contract.js-itFN0Gon.js';
3
- import { c as collectAllReferences, a as assetIdError, b as computeLibraryMembership, d as allDeliveredAssetIds } from './manifest-membership.js-BnSECWpJ.js';
4
- import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation2.js-CscuoBC2.js';
5
- import { isAbsolute, resolve, join, extname, relative, sep } from 'node:path';
6
- import { existsSync } from 'node:fs';
7
- import { createJiti } from 'jiti';
1
+ import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, H as typesForFileName, J as proposeAssetId, k as parentFolderPath, u as portableFolderPathKey, B as isAssetReference } from './core.js-D1sYC_78.js';
2
+ import { s as serverPluginsByType, i as isRecord, L as LibraryStore, d as descriptorsByType, m as manifestModuleFileName, l as locateGeneratedAssetDeclaration, a as serializeLibrary, b as serverPluginForType, S as SourceImportError, p as processAssets, g as generateManifestModules, r as readCurrentProxy, e as encodeRelativePathForUrl, f as flatLibraryIssues, c as manifestModuleCollisionIssues, h as invalidInput, j as parseLibrary, k as isRecord$1, n as assertSafeKey, o as parseManifestRecord, q as parseImportSource } from './contract.js-IY1F-HE_.js';
3
+ import { c as collectAllReferences, a as assetIdError, b as computeLibraryMembership, d as allDeliveredAssetIds } from './manifest-membership.js-Cm_2fU-Z.js';
4
+ import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation2.js-CcO9li5n.js';
5
+ import { createRequire } from 'node:module';
6
+ import { isAbsolute, resolve, join, dirname, extname, relative, sep } from 'node:path';
7
+ import { existsSync, readFileSync } from 'node:fs';
8
8
  import { readFile, realpath } from 'node:fs/promises';
9
+ import { pathToFileURL } from 'node:url';
10
+ import { createJiti } from 'jiti';
9
11
  import { execFile } from 'node:child_process';
10
12
  import { isDeepStrictEqual, promisify } from 'node:util';
11
13
  import sharp from 'sharp';
@@ -14,6 +16,224 @@ import { lookup } from 'node:dns/promises';
14
16
  import { isIP } from 'node:net';
15
17
  import { request } from 'node:https';
16
18
 
19
+ //#region src/lib/core/package-declaration.ts
20
+ function parsePackageAsset(origin, id, value) {
21
+ if (!isRecord$1(value)) throw new Error(`Package "${origin}" asset "${id}" must be an object.`);
22
+ if (typeof value.type !== "string" || value.type.length === 0) throw new Error(`Package "${origin}" asset "${id}" is missing a string "type".`);
23
+ if ("raw" in value || "rawHash" in value) throw new Error(`Package "${origin}" asset "${id}" declares "raw"/"rawHash"; Packages ship byte-less slots only.`);
24
+ if (!Array.isArray(value.manifests) || value.manifests.some((entry) => typeof entry !== "string")) throw new Error(`Package "${origin}" asset "${id}" must have a "manifests" array of strings.`);
25
+ const record = {
26
+ type: value.type,
27
+ parameters: "parameters" in value ? value.parameters : {},
28
+ manifests: value.manifests
29
+ };
30
+ if (value.importSource !== void 0) record.importSource = parseImportSource(id, value.importSource);
31
+ return record;
32
+ }
33
+ /**
34
+ * Parse and structurally validate a `fundus.package.json` (JSON text). Delegates
35
+ * to {@link validatePackageDeclaration} after `JSON.parse`.
36
+ */
37
+ function parsePackageDeclaration(json, origin) {
38
+ let value;
39
+ try {
40
+ value = JSON.parse(json);
41
+ } catch (cause) {
42
+ throw new Error(`Package "${origin}" declaration is not valid JSON: ${cause instanceof Error ? cause.message : String(cause)}`);
43
+ }
44
+ return validatePackageDeclaration(value, origin);
45
+ }
46
+ /**
47
+ * Structurally validate an already-parsed package declaration — the shared core of
48
+ * both the JSON path ({@link parsePackageDeclaration}) and the TypeScript-module path
49
+ * (a `fundus.package.ts` default export loaded via jiti). Throws with a clear,
50
+ * origin-tagged message on any malformed part. Plugin parameter validation and
51
+ * id/manifest-name validity are separate steps that run over the merged
52
+ * (effective) library, not here — mirroring `parseLibrary`. `version` defaults to 1.
53
+ */
54
+ function validatePackageDeclaration(value, origin) {
55
+ if (!isRecord$1(value)) throw new Error(`Package "${origin}" declaration must be an object.`);
56
+ if (value.version !== void 0 && value.version !== 1) throw new Error(`Package "${origin}" declaration has unsupported version ${JSON.stringify(value.version)} (expected 1).`);
57
+ if (!isRecord$1(value.assets)) throw new Error(`Package "${origin}" declaration "assets" must be an object.`);
58
+ if (value.manifests !== void 0 && !isRecord$1(value.manifests)) throw new Error(`Package "${origin}" declaration "manifests" must be an object.`);
59
+ const assets = {};
60
+ for (const [id, record] of Object.entries(value.assets)) {
61
+ assertSafeKey("asset", id);
62
+ assets[id] = parsePackageAsset(origin, id, record);
63
+ }
64
+ const manifests = {};
65
+ if (isRecord$1(value.manifests)) for (const [name, record] of Object.entries(value.manifests)) {
66
+ assertSafeKey("manifest", name);
67
+ if (!isRecord$1(record)) throw new Error(`Package "${origin}" manifest "${name}" must be an object.`);
68
+ manifests[name] = parseManifestRecord(name, record);
69
+ }
70
+ return {
71
+ version: 1,
72
+ assets,
73
+ manifests
74
+ };
75
+ }
76
+ //#endregion
77
+ //#region src/lib/core/package-merge.ts
78
+ /**
79
+ * The pure Package merge: fold package-shipped partial libraries **under** the
80
+ * host library into one in-memory *effective* library. Host wins per-field
81
+ * (deep). No disk, no config — testable like `resolveConfig`. The effective
82
+ * library is never serialized (a host `Library` always carries `raw`/`rawHash`);
83
+ * `materializeLibrary` drops raw-less inert slots to hand a plain `Library` to
84
+ * processing/codegen once the slot/validation gates have passed.
85
+ */
86
+ function sortDedupManifests(names) {
87
+ return [...new Set(names)].sort(compareCodeUnits);
88
+ }
89
+ /**
90
+ * Deep-merge plugin `parameters` — overlay (host) wins. Recurses into plain
91
+ * objects only; arrays are replaced wholesale (host-replace) and `{ $asset }`
92
+ * reference markers are treated as atomic (never merged field-by-field). Applied
93
+ * to `parameters` only — the record-level `manifests` array is unioned by the
94
+ * caller, never routed through here.
95
+ */
96
+ function deepMergeParameters(base, overlay) {
97
+ if (isRecord$1(base) && isRecord$1(overlay) && !isAssetReference(base) && !isAssetReference(overlay)) {
98
+ const result = { ...base };
99
+ for (const [key, value] of Object.entries(overlay)) result[key] = key in base ? deepMergeParameters(base[key], value) : value;
100
+ return result;
101
+ }
102
+ return overlay;
103
+ }
104
+ /**
105
+ * Merge `packages` under `host` (host wins, per-field deep). Returns the merged
106
+ * effective library, per-asset provenance, and merge findings. `host` is an
107
+ * `EffectiveLibrary` so a raw-less host override branch stays reachable/testable
108
+ * and v2-ready; a plain `Library` is assignable.
109
+ */
110
+ function mergePackages(host, packages) {
111
+ const findings = [];
112
+ const pkgAssets = /* @__PURE__ */ new Map();
113
+ const pkgManifests = /* @__PURE__ */ new Map();
114
+ for (const { origin, declaration } of packages) {
115
+ for (const [id, decl] of Object.entries(declaration.assets)) {
116
+ const existing = pkgAssets.get(id);
117
+ if (existing) {
118
+ findings.push({
119
+ kind: "package-conflict",
120
+ assetId: id,
121
+ origins: [existing.origin, origin],
122
+ message: `Asset "${id}" is declared by two Packages ("${existing.origin}" and "${origin}"); Package ids must be unique.`
123
+ });
124
+ continue;
125
+ }
126
+ pkgAssets.set(id, {
127
+ origin,
128
+ decl
129
+ });
130
+ }
131
+ for (const [name, record] of Object.entries(declaration.manifests)) if (!pkgManifests.has(name)) pkgManifests.set(name, record);
132
+ }
133
+ const assets = {};
134
+ const provenance = {};
135
+ for (const [id, hostRecord] of Object.entries(host.assets)) {
136
+ const pkg = pkgAssets.get(id);
137
+ if (!pkg) {
138
+ assets[id] = { ...hostRecord };
139
+ provenance[id] = { source: "host" };
140
+ continue;
141
+ }
142
+ if (pkg.decl.type !== hostRecord.type) {
143
+ findings.push({
144
+ kind: "package-type-mismatch",
145
+ assetId: id,
146
+ origin: pkg.origin,
147
+ message: `Asset "${id}" overrides Package "${pkg.origin}" but changes its type from "${pkg.decl.type}" to "${hostRecord.type}"; changing the type is a different asset, not an override.`
148
+ });
149
+ assets[id] = { ...hostRecord };
150
+ provenance[id] = {
151
+ source: "override",
152
+ origin: pkg.origin
153
+ };
154
+ continue;
155
+ }
156
+ const merged = {
157
+ type: hostRecord.type,
158
+ parameters: deepMergeParameters(pkg.decl.parameters, hostRecord.parameters),
159
+ manifests: sortDedupManifests([...pkg.decl.manifests, ...hostRecord.manifests])
160
+ };
161
+ if (hostRecord.raw !== void 0 || hostRecord.importSource !== void 0) {
162
+ if (hostRecord.raw !== void 0) merged.raw = hostRecord.raw;
163
+ if (hostRecord.rawHash !== void 0) merged.rawHash = hostRecord.rawHash;
164
+ if (hostRecord.importSource !== void 0) merged.importSource = hostRecord.importSource;
165
+ } else if (pkg.decl.importSource !== void 0) merged.importSource = pkg.decl.importSource;
166
+ assets[id] = merged;
167
+ provenance[id] = {
168
+ source: "override",
169
+ origin: pkg.origin
170
+ };
171
+ findings.push({
172
+ kind: "package-overridden",
173
+ assetId: id,
174
+ origin: pkg.origin,
175
+ message: `Asset "${id}" from Package "${pkg.origin}" is overridden by the host library.`
176
+ });
177
+ }
178
+ for (const [id, { origin, decl }] of pkgAssets) {
179
+ if (Object.hasOwn(host.assets, id)) continue;
180
+ const record = {
181
+ type: decl.type,
182
+ parameters: decl.parameters,
183
+ manifests: sortDedupManifests(decl.manifests)
184
+ };
185
+ if (decl.importSource !== void 0) record.importSource = decl.importSource;
186
+ assets[id] = record;
187
+ provenance[id] = {
188
+ source: "package",
189
+ origin
190
+ };
191
+ }
192
+ const manifests = {};
193
+ for (const [name, record] of pkgManifests) manifests[name] = { ...record };
194
+ for (const [name, record] of Object.entries(host.manifests)) manifests[name] = {
195
+ ...manifests[name],
196
+ ...record
197
+ };
198
+ return {
199
+ library: {
200
+ version: Object.values(assets).some((record) => record.importSource !== void 0) ? 2 : host.version,
201
+ folders: host.folders,
202
+ assets,
203
+ manifests
204
+ },
205
+ provenance,
206
+ findings
207
+ };
208
+ }
209
+ /**
210
+ * Drop raw-less (unfilled) slots from an effective library, yielding a plain
211
+ * `Library` for processing/codegen. Safe only after the slot/validation gates
212
+ * pass — every remaining delivered asset then has `raw`; dropped slots are
213
+ * provably inert (not delivered).
214
+ */
215
+ function materializeLibrary(effective) {
216
+ const assets = {};
217
+ for (const [id, record] of Object.entries(effective.assets)) {
218
+ if (record.raw === void 0 || record.rawHash === void 0) continue;
219
+ const materialized = {
220
+ type: record.type,
221
+ raw: record.raw,
222
+ rawHash: record.rawHash,
223
+ parameters: record.parameters,
224
+ manifests: record.manifests
225
+ };
226
+ if (record.importSource !== void 0) materialized.importSource = record.importSource;
227
+ assets[id] = materialized;
228
+ }
229
+ return {
230
+ version: effective.version,
231
+ folders: effective.folders,
232
+ assets,
233
+ manifests: effective.manifests
234
+ };
235
+ }
236
+ //#endregion
17
237
  //#region src/lib/server/config-loader.ts
18
238
  /**
19
239
  * Loads and resolves the host's `fundus.config.ts` through jiti, validates
@@ -37,6 +257,70 @@ function configDefinitionsFor(registry) {
37
257
  }
38
258
  return [...byNamespace.values()];
39
259
  }
260
+ /**
261
+ * A string `packages` entry is a *path* when it looks like one (starts with
262
+ * `.`/`/`, is absolute, or ends `.json`), or a bare relative path with a
263
+ * separator; otherwise it is a package *name*. A scoped name (`@scope/pkg`)
264
+ * contains a `/` but is a name.
265
+ */
266
+ function classifyPackageSpec(spec) {
267
+ if (spec.startsWith(".") || spec.startsWith("/") || isAbsolute(spec)) return "path";
268
+ if (DECLARATION_FILE_RE.test(spec)) return "path";
269
+ if (spec.startsWith("@")) return "name";
270
+ if (spec.includes("/") || spec.includes("\\")) return "path";
271
+ return "name";
272
+ }
273
+ /** A declaration file is JSON or a JS/TS module (the latter loaded via jiti). */
274
+ var DECLARATION_FILE_RE = /\.(json|[mc]?[jt]s)$/;
275
+ /**
276
+ * Read a package declaration from its resolved file: a JSON `fundus.package.json`
277
+ * (parsed as text) or a JS/TS module (`fundus.package.ts`) whose default export is
278
+ * the declaration — loaded through the same jiti path as `fundus.config.ts`, which
279
+ * keeps the resource `type`s literal for the package's `PackageAssets<…>` derivation.
280
+ */
281
+ async function loadPackageDeclaration(file, origin) {
282
+ if (/\.[mc]?[jt]s$/.test(file)) {
283
+ let module;
284
+ try {
285
+ module = await createJiti(import.meta.url, { interopDefault: false }).import(file);
286
+ } catch (cause) {
287
+ throw new Error(`Cannot load fundus package "${origin}" (${file}): ${cause instanceof Error ? cause.message : String(cause)}`);
288
+ }
289
+ return validatePackageDeclaration(isRecord(module) && "default" in module ? module.default : module, origin);
290
+ }
291
+ let text;
292
+ try {
293
+ text = await readFile(file, "utf8");
294
+ } catch (cause) {
295
+ throw new Error(`Cannot read fundus package "${origin}" (${file}): ${cause instanceof Error ? cause.message : String(cause)}`);
296
+ }
297
+ return parsePackageDeclaration(text, origin);
298
+ }
299
+ function normalizePackageSource(projectRoot, entry) {
300
+ let spec;
301
+ let rawDirOverride;
302
+ if (typeof entry === "string") spec = entry;
303
+ else if (isRecord(entry) && typeof entry.package === "string" && entry.package.length > 0) {
304
+ spec = entry.package;
305
+ if (entry.rawDir !== void 0) {
306
+ if (typeof entry.rawDir !== "string" || entry.rawDir.length === 0) throw new Error("fundus.config: a \"packages\" entry \"rawDir\" must be a non-empty string.");
307
+ rawDirOverride = entry.rawDir;
308
+ }
309
+ } else throw new Error("fundus.config: each \"packages\" entry must be a package name, a path string, or { package: string; rawDir?: string }.");
310
+ const kind = classifyPackageSpec(spec);
311
+ const reference = kind === "path" ? resolve(projectRoot, spec) : spec;
312
+ return {
313
+ origin: spec,
314
+ kind,
315
+ reference,
316
+ ...rawDirOverride !== void 0 ? { rawDirOverride } : {}
317
+ };
318
+ }
319
+ function resolvePackageSources(projectRoot, value) {
320
+ if (value === void 0) return [];
321
+ if (!Array.isArray(value)) throw new Error("fundus.config: \"packages\" must be an array.");
322
+ return value.map((entry) => normalizePackageSource(projectRoot, entry));
323
+ }
40
324
  /** Pure resolution step (testable without a config file on disk). */
41
325
  function resolveConfig(projectRoot, value, registry = serverPluginsByType) {
42
326
  if (!isRecord(value)) throw new Error("fundus.config must default-export a configuration object.");
@@ -74,9 +358,88 @@ function resolveConfig(projectRoot, value, registry = serverPluginsByType) {
74
358
  ...figma.token !== void 0 ? { token: figma.token } : {},
75
359
  defaults: { scale }
76
360
  } },
77
- usage: usage === void 0 ? null : usage
361
+ usage: usage === void 0 ? null : usage,
362
+ packageSources: resolvePackageSources(projectRoot, value.packages),
363
+ packages: []
78
364
  };
79
365
  }
366
+ function nearestNamedPackageJson(entryPath, name) {
367
+ let dir = dirname(entryPath);
368
+ for (;;) {
369
+ const candidate = join(dir, "package.json");
370
+ if (existsSync(candidate)) try {
371
+ const pkg = JSON.parse(readFileSync(candidate, "utf8"));
372
+ if (isRecord(pkg) && pkg.name === name) return {
373
+ dir,
374
+ pkg
375
+ };
376
+ } catch {}
377
+ const parent = dirname(dir);
378
+ if (parent === dir) break;
379
+ dir = parent;
380
+ }
381
+ throw new Error(`Cannot find the package.json for fundus package "${name}" (resolved to ${entryPath}).`);
382
+ }
383
+ /**
384
+ * Resolve a name-form Package to its root directory + parsed `package.json`. A
385
+ * declaration-only Package ships no JS entry module, so resolving the bare name
386
+ * would throw `MODULE_NOT_FOUND`; resolve its `package.json` subpath first and
387
+ * only fall back to entry resolution when an `exports` map hides it.
388
+ */
389
+ function resolvePackageRoot(require, reference, origin) {
390
+ try {
391
+ const manifestPath = require.resolve(`${reference}/package.json`);
392
+ const pkg = JSON.parse(readFileSync(manifestPath, "utf8"));
393
+ if (isRecord(pkg)) return {
394
+ dir: dirname(manifestPath),
395
+ pkg
396
+ };
397
+ } catch {}
398
+ let entry;
399
+ try {
400
+ entry = require.resolve(reference);
401
+ } catch {
402
+ throw new Error(`Cannot resolve fundus package "${origin}": no installed package declares it — is it a dependency?`);
403
+ }
404
+ return nearestNamedPackageJson(entry, reference);
405
+ }
406
+ /**
407
+ * Read and parse every declared Package from disk. Name entries resolve through
408
+ * the host's module resolver (respecting `exports`), then walk up to the nearest
409
+ * `package.json` that declares the name and read its `"fundus"` field. Path
410
+ * entries point directly at a `fundus.package.json`. Throws a clear,
411
+ * origin-tagged error on any resolution/read/parse failure — Package assembly
412
+ * failures are symmetric with a missing `fundus.config.ts`.
413
+ */
414
+ async function loadPackages(projectRoot, sources) {
415
+ const require = createRequire(pathToFileURL(join(projectRoot, "fundus.config.ts")).href);
416
+ const packages = [];
417
+ for (const source of sources) {
418
+ let file;
419
+ let defaultRawDir;
420
+ if (source.kind === "path") {
421
+ file = source.reference;
422
+ if (!existsSync(file)) throw new Error(`Fundus package file not found: ${file} (from "${source.origin}").`);
423
+ defaultRawDir = dirname(file);
424
+ } else {
425
+ const { dir, pkg } = resolvePackageRoot(require, source.reference, source.origin);
426
+ const fundusField = pkg.fundus;
427
+ if (!isRecord(fundusField) || typeof fundusField.package !== "string" || fundusField.package.length === 0) throw new Error(`Fundus package "${source.origin}" is missing a "fundus.package" field in its package.json.`);
428
+ file = resolve(dir, fundusField.package);
429
+ if (!existsSync(file)) throw new Error(`Fundus package "${source.origin}" declaration not found: ${file}.`);
430
+ defaultRawDir = typeof fundusField.rawDir === "string" && fundusField.rawDir.length > 0 ? resolve(dir, fundusField.rawDir) : dir;
431
+ }
432
+ const declaration = await loadPackageDeclaration(file, source.origin);
433
+ const rawDir = source.rawDirOverride !== void 0 ? resolve(projectRoot, source.rawDirOverride) : defaultRawDir;
434
+ packages.push({
435
+ origin: source.origin,
436
+ file,
437
+ rawDir,
438
+ declaration
439
+ });
440
+ }
441
+ return packages;
442
+ }
80
443
  /** Load `fundus.config.ts` from the host project root. */
81
444
  async function loadConfig(projectRoot) {
82
445
  const root = resolve(projectRoot);
@@ -88,7 +451,152 @@ async function loadConfig(projectRoot) {
88
451
  } catch (cause) {
89
452
  throw new Error(`Cannot load fundus.config.ts: ${cause instanceof Error ? cause.message : String(cause)}`);
90
453
  }
91
- return resolveConfig(root, isRecord(module) && "default" in module ? module.default : module);
454
+ const config = resolveConfig(root, isRecord(module) && "default" in module ? module.default : module);
455
+ return {
456
+ ...config,
457
+ packages: await loadPackages(root, config.packageSources)
458
+ };
459
+ }
460
+ async function imageFingerprint(filePath, hashSize) {
461
+ const width = hashSize + 1;
462
+ const pixels = await sharp(filePath).rotate().trim({
463
+ background: {
464
+ r: 0,
465
+ g: 0,
466
+ b: 0,
467
+ alpha: 0
468
+ },
469
+ threshold: 0
470
+ }).resize({
471
+ width,
472
+ height: hashSize,
473
+ fit: "fill"
474
+ }).ensureAlpha().toColourspace("srgb").raw().toBuffer();
475
+ const hash = new Uint8Array(Math.ceil(hashSize * hashSize / 8));
476
+ const alphaHash = new Uint8Array(hash.length);
477
+ const colorTotals = [
478
+ 0,
479
+ 0,
480
+ 0
481
+ ];
482
+ let alphaTotal = 0;
483
+ let bit = 0;
484
+ for (let row = 0; row < hashSize; row++) for (let column = 0; column < hashSize; column++) {
485
+ const leftOffset = (row * width + column) * 4;
486
+ const rightOffset = leftOffset + 4;
487
+ const leftAlpha = pixels[leftOffset + 3] / 255;
488
+ const rightAlpha = pixels[rightOffset + 3] / 255;
489
+ if (visibleLuminance(pixels, leftOffset, leftAlpha) < visibleLuminance(pixels, rightOffset, rightAlpha)) hash[bit >> 3] |= 1 << 7 - (bit & 7);
490
+ if (leftAlpha < rightAlpha) alphaHash[bit >> 3] |= 1 << 7 - (bit & 7);
491
+ for (let channel = 0; channel < 3; channel++) colorTotals[channel] += pixels[leftOffset + channel] * leftAlpha;
492
+ alphaTotal += leftAlpha;
493
+ bit += 1;
494
+ }
495
+ const pixelCount = hashSize * hashSize;
496
+ return {
497
+ hash,
498
+ alphaHash,
499
+ meanColor: colorTotals.map((total) => alphaTotal === 0 ? 0 : total / alphaTotal),
500
+ meanAlpha: alphaTotal / pixelCount
501
+ };
502
+ }
503
+ function visibleLuminance(pixels, offset, alpha) {
504
+ return (pixels[offset] * .2126 + pixels[offset + 1] * .7152 + pixels[offset + 2] * .0722) * alpha + 127 * (1 - alpha);
505
+ }
506
+ function colorDistance(left, right) {
507
+ return Math.hypot(left[0] - right[0], left[1] - right[1], left[2] - right[2]);
508
+ }
509
+ /** Count differing bits between two equally sized perceptual hashes. */
510
+ function hammingDistance(left, right) {
511
+ if (left.length !== right.length) throw new Error("Image hashes must have the same length.");
512
+ let distance = 0;
513
+ for (let index = 0; index < left.length; index++) {
514
+ let value = left[index] ^ right[index];
515
+ while (value !== 0) {
516
+ value &= value - 1;
517
+ distance += 1;
518
+ }
519
+ }
520
+ return distance;
521
+ }
522
+ /**
523
+ * Stateful so the editor can reuse fingerprints by content hash between state
524
+ * snapshots. Unreadable raws are omitted: duplicate detection is advisory and
525
+ * must not hide the editor or replace the pipeline's canonical diagnostics.
526
+ */
527
+ var ImageDuplicateDetector = class {
528
+ #fingerprints = /* @__PURE__ */ new Map();
529
+ async find(library, rawDir) {
530
+ const images = Object.entries(library.assets).filter(([, record]) => record.type === "image").sort(([left], [right]) => compareCodeUnits(left, right));
531
+ const activeHashes = new Set(images.map(([, record]) => record.rawHash));
532
+ for (const hash of this.#fingerprints.keys()) if (!activeHashes.has(hash)) this.#fingerprints.delete(hash);
533
+ const readable = [];
534
+ for (const [id, record] of images) {
535
+ let fingerprint = this.#fingerprints.get(record.rawHash);
536
+ if (!fingerprint) {
537
+ fingerprint = imageFingerprint(join(rawDir, record.raw), 8);
538
+ this.#fingerprints.set(record.rawHash, fingerprint);
539
+ }
540
+ try {
541
+ readable.push({
542
+ id,
543
+ fingerprint: await fingerprint
544
+ });
545
+ } catch {
546
+ this.#fingerprints.delete(record.rawHash);
547
+ }
548
+ }
549
+ const duplicates = /* @__PURE__ */ new Map();
550
+ for (let leftIndex = 0; leftIndex < readable.length; leftIndex++) for (let rightIndex = leftIndex + 1; rightIndex < readable.length; rightIndex++) {
551
+ const left = readable[leftIndex];
552
+ const right = readable[rightIndex];
553
+ if (hammingDistance(left.fingerprint.hash, right.fingerprint.hash) > 5 || hammingDistance(left.fingerprint.alphaHash, right.fingerprint.alphaHash) > 5 || Math.abs(left.fingerprint.meanAlpha - right.fingerprint.meanAlpha) > .125 || colorDistance(left.fingerprint.meanColor, right.fingerprint.meanColor) > 32) continue;
554
+ const leftDuplicates = duplicates.get(left.id) ?? [];
555
+ leftDuplicates.push(right.id);
556
+ duplicates.set(left.id, leftDuplicates);
557
+ const rightDuplicates = duplicates.get(right.id) ?? [];
558
+ rightDuplicates.push(left.id);
559
+ duplicates.set(right.id, rightDuplicates);
560
+ }
561
+ return duplicates;
562
+ }
563
+ };
564
+ //#endregion
565
+ //#region src/lib/server/check.ts
566
+ /**
567
+ * The delivered-slot contract: a Package slot that is delivered (explicit member
568
+ * or in a delivered manifest's reference closure) but has no host-supplied bytes
569
+ * must be filled. A slot with an `importSource` is `slot-unmaterialized` (run
570
+ * import); a slot with nothing is `slot-unfilled`. Inert (undelivered) slots
571
+ * produce no finding.
572
+ */
573
+ function packageSlotFindings(library, provenance, membership) {
574
+ const deliveringManifests = /* @__PURE__ */ new Map();
575
+ for (const [name, manifestMembership] of Object.entries(membership)) for (const assetId of manifestMembership.deliveredAssetIds) {
576
+ const names = deliveringManifests.get(assetId) ?? [];
577
+ names.push(name);
578
+ deliveringManifests.set(assetId, names);
579
+ }
580
+ const findings = [];
581
+ for (const [assetId, record] of Object.entries(library.assets)) {
582
+ if (record.raw !== void 0) continue;
583
+ const names = deliveringManifests.get(assetId);
584
+ if (!names || names.length === 0) continue;
585
+ const originRecord = provenance[assetId];
586
+ const origin = originRecord && originRecord.source !== "host" ? originRecord.origin : "a package";
587
+ const deliveredBy = [...names].sort(compareCodeUnits).map((name) => `"${name}"`).join(", ");
588
+ if (record.importSource !== void 0) findings.push({
589
+ kind: "slot-unmaterialized",
590
+ assetId,
591
+ message: `Slot "${assetId}" (from ${origin}) has an import source but no bytes yet — run import to fill it. Delivered by: ${deliveredBy}.`
592
+ });
593
+ else findings.push({
594
+ kind: "slot-unfilled",
595
+ assetId,
596
+ message: `Slot "${assetId}" (from ${origin}) has no bytes, import source, or host override. Delivered by: ${deliveredBy}.`
597
+ });
598
+ }
599
+ return findings;
92
600
  }
93
601
  //#endregion
94
602
  //#region src/lib/server/raw-safety.ts
@@ -1075,110 +1583,6 @@ function pathsFromRoot(root, target, referencesByAsset, countMemo = /* @__PURE__
1075
1583
  function usageSnapshotRevision(parts) {
1076
1584
  return createHash("sha256").update(parts.join("\0")).digest("hex");
1077
1585
  }
1078
- async function imageFingerprint(filePath, hashSize) {
1079
- const width = hashSize + 1;
1080
- const pixels = await sharp(filePath).rotate().trim({
1081
- background: {
1082
- r: 0,
1083
- g: 0,
1084
- b: 0,
1085
- alpha: 0
1086
- },
1087
- threshold: 0
1088
- }).resize({
1089
- width,
1090
- height: hashSize,
1091
- fit: "fill"
1092
- }).ensureAlpha().toColourspace("srgb").raw().toBuffer();
1093
- const hash = new Uint8Array(Math.ceil(hashSize * hashSize / 8));
1094
- const alphaHash = new Uint8Array(hash.length);
1095
- const colorTotals = [
1096
- 0,
1097
- 0,
1098
- 0
1099
- ];
1100
- let alphaTotal = 0;
1101
- let bit = 0;
1102
- for (let row = 0; row < hashSize; row++) for (let column = 0; column < hashSize; column++) {
1103
- const leftOffset = (row * width + column) * 4;
1104
- const rightOffset = leftOffset + 4;
1105
- const leftAlpha = pixels[leftOffset + 3] / 255;
1106
- const rightAlpha = pixels[rightOffset + 3] / 255;
1107
- if (visibleLuminance(pixels, leftOffset, leftAlpha) < visibleLuminance(pixels, rightOffset, rightAlpha)) hash[bit >> 3] |= 1 << 7 - (bit & 7);
1108
- if (leftAlpha < rightAlpha) alphaHash[bit >> 3] |= 1 << 7 - (bit & 7);
1109
- for (let channel = 0; channel < 3; channel++) colorTotals[channel] += pixels[leftOffset + channel] * leftAlpha;
1110
- alphaTotal += leftAlpha;
1111
- bit += 1;
1112
- }
1113
- const pixelCount = hashSize * hashSize;
1114
- return {
1115
- hash,
1116
- alphaHash,
1117
- meanColor: colorTotals.map((total) => alphaTotal === 0 ? 0 : total / alphaTotal),
1118
- meanAlpha: alphaTotal / pixelCount
1119
- };
1120
- }
1121
- function visibleLuminance(pixels, offset, alpha) {
1122
- return (pixels[offset] * .2126 + pixels[offset + 1] * .7152 + pixels[offset + 2] * .0722) * alpha + 127 * (1 - alpha);
1123
- }
1124
- function colorDistance(left, right) {
1125
- return Math.hypot(left[0] - right[0], left[1] - right[1], left[2] - right[2]);
1126
- }
1127
- /** Count differing bits between two equally sized perceptual hashes. */
1128
- function hammingDistance(left, right) {
1129
- if (left.length !== right.length) throw new Error("Image hashes must have the same length.");
1130
- let distance = 0;
1131
- for (let index = 0; index < left.length; index++) {
1132
- let value = left[index] ^ right[index];
1133
- while (value !== 0) {
1134
- value &= value - 1;
1135
- distance += 1;
1136
- }
1137
- }
1138
- return distance;
1139
- }
1140
- /**
1141
- * Stateful so the editor can reuse fingerprints by content hash between state
1142
- * snapshots. Unreadable raws are omitted: duplicate detection is advisory and
1143
- * must not hide the editor or replace the pipeline's canonical diagnostics.
1144
- */
1145
- var ImageDuplicateDetector = class {
1146
- #fingerprints = /* @__PURE__ */ new Map();
1147
- async find(library, rawDir) {
1148
- const images = Object.entries(library.assets).filter(([, record]) => record.type === "image").sort(([left], [right]) => compareCodeUnits(left, right));
1149
- const activeHashes = new Set(images.map(([, record]) => record.rawHash));
1150
- for (const hash of this.#fingerprints.keys()) if (!activeHashes.has(hash)) this.#fingerprints.delete(hash);
1151
- const readable = [];
1152
- for (const [id, record] of images) {
1153
- let fingerprint = this.#fingerprints.get(record.rawHash);
1154
- if (!fingerprint) {
1155
- fingerprint = imageFingerprint(join(rawDir, record.raw), 8);
1156
- this.#fingerprints.set(record.rawHash, fingerprint);
1157
- }
1158
- try {
1159
- readable.push({
1160
- id,
1161
- fingerprint: await fingerprint
1162
- });
1163
- } catch {
1164
- this.#fingerprints.delete(record.rawHash);
1165
- }
1166
- }
1167
- const duplicates = /* @__PURE__ */ new Map();
1168
- for (let leftIndex = 0; leftIndex < readable.length; leftIndex++) for (let rightIndex = leftIndex + 1; rightIndex < readable.length; rightIndex++) {
1169
- const left = readable[leftIndex];
1170
- const right = readable[rightIndex];
1171
- if (hammingDistance(left.fingerprint.hash, right.fingerprint.hash) > 5 || hammingDistance(left.fingerprint.alphaHash, right.fingerprint.alphaHash) > 5 || Math.abs(left.fingerprint.meanAlpha - right.fingerprint.meanAlpha) > .125 || colorDistance(left.fingerprint.meanColor, right.fingerprint.meanColor) > 32) continue;
1172
- const leftDuplicates = duplicates.get(left.id) ?? [];
1173
- leftDuplicates.push(right.id);
1174
- duplicates.set(left.id, leftDuplicates);
1175
- const rightDuplicates = duplicates.get(right.id) ?? [];
1176
- rightDuplicates.push(left.id);
1177
- duplicates.set(right.id, rightDuplicates);
1178
- }
1179
- return duplicates;
1180
- }
1181
- };
1182
1586
  //#endregion
1183
1587
  //#region src/lib/server/operations.ts
1184
1588
  /**
@@ -1584,7 +1988,24 @@ var FundusOperations = class {
1584
1988
  this.#validateImportedRaw(raw);
1585
1989
  const fileName = raw.suggestedFileName ?? `${options.id}.${raw.extension}`;
1586
1990
  const plugin = serverPluginForType(options.type, this.#registry);
1587
- const library = await this.#store.createAsset({
1991
+ const packageBase = this.#packageBase(await this.#store.read(), options.id);
1992
+ if (packageBase && packageBase.type !== options.type) throw new SourceImportError("invalid-input", `Filling slot "${options.id}" requires the package type "${packageBase.type}", not "${options.type}".`);
1993
+ let slotOverride = {};
1994
+ if (packageBase) {
1995
+ const pixelRatio = figmaSlicePixelRatio(raw, options.type);
1996
+ if (pixelRatio !== void 0) slotOverride = mergeParameterPatch(slotOverride, { pixelRatio });
1997
+ if (options.parametersPatch !== void 0) slotOverride = mergeParameterPatch(slotOverride, options.parametersPatch);
1998
+ }
1999
+ const library = packageBase ? await this.#store.createAsset({
2000
+ fileName,
2001
+ bytes: raw.bytes,
2002
+ type: options.type,
2003
+ id: options.id,
2004
+ folder: options.folder,
2005
+ manifests: options.manifests,
2006
+ importSource: raw.importSource,
2007
+ parametersOverride: slotOverride
2008
+ }) : await this.#store.createAsset({
1588
2009
  fileName,
1589
2010
  bytes: raw.bytes,
1590
2011
  type: options.type,
@@ -1619,7 +2040,8 @@ var FundusOperations = class {
1619
2040
  const folder = normalizeFolderPath(options.folder ?? "");
1620
2041
  if (folder !== "" && !library.folders.includes(folder)) throw new SourceImportError("invalid-input", `Unknown folder "${folder}".`);
1621
2042
  if (options.manifests !== void 0 && (!Array.isArray(options.manifests) || options.manifests.some((value) => typeof value !== "string"))) throw new SourceImportError("invalid-input", "Import manifests must be an array of strings.");
1622
- for (const manifest of new Set(options.manifests ?? [])) if (!Object.hasOwn(library.manifests, manifest)) throw new SourceImportError("invalid-input", `Unknown manifest "${manifest}".`);
2043
+ const validManifests = this.#effectiveOf(library).effective.manifests;
2044
+ for (const manifest of new Set(options.manifests ?? [])) if (!Object.hasOwn(validManifests, manifest)) throw new SourceImportError("invalid-input", `Unknown manifest "${manifest}".`);
1623
2045
  }
1624
2046
  #validateImportedRaw(raw, importerKind) {
1625
2047
  if (!(raw.bytes instanceof Uint8Array) || !/^[a-z0-9]+$/.test(raw.extension)) throw new SourceImportError("invalid-response", "The source importer returned invalid raw data.");
@@ -1634,7 +2056,7 @@ var FundusOperations = class {
1634
2056
  }
1635
2057
  async #patchAsset(id, body) {
1636
2058
  let library = await this.#store.read();
1637
- this.#requireAsset(library, id);
2059
+ this.#assertHostAsset(library, id, "editing it");
1638
2060
  if (body.parameters !== void 0) library = await this.#store.updateParameters(id, body.parameters);
1639
2061
  if (body.manifests !== void 0) {
1640
2062
  if (!Array.isArray(body.manifests) || body.manifests.some((name) => typeof name !== "string")) throw new Error("\"manifests\" must be an array of manifest names.");
@@ -1835,11 +2257,13 @@ var FundusOperations = class {
1835
2257
  async #runAfterMutation(library) {
1836
2258
  const pipelineIssues = [];
1837
2259
  const classification = await this.#classifyRawDirectory(library);
1838
- const ordinaryIssues = await this.#store.validate(library);
2260
+ const { effective, provenance, mergeFindings } = this.#effectiveOf(library);
2261
+ const materialized = materializeLibrary(effective);
2262
+ const ordinaryIssues = [...await this.#store.validate(library, { flatSpace: false }), ...this.#flatIssues(effective, provenance, mergeFindings)];
1839
2263
  const safetyIssues = this.#rawSafetyIssues(library, classification);
1840
2264
  if (ordinaryIssues.length === 0 && safetyIssues.length === 0) try {
1841
- const report = await processAssets(this.#config, library, this.#registry);
1842
- await generateManifestModules(this.#config, library, report.proxies, this.#registry);
2265
+ const report = await processAssets(this.#config, materialized, this.#registry);
2266
+ await generateManifestModules(this.#config, materialized, report.proxies, this.#registry);
1843
2267
  } catch (cause) {
1844
2268
  pipelineIssues.push({ message: `Processing failed: ${cause instanceof Error ? cause.message : String(cause)}` });
1845
2269
  }
@@ -1851,10 +2275,10 @@ var FundusOperations = class {
1851
2275
  state: await this.#snapshotState(latestLibrary, latestClassification, pipelineIssues)
1852
2276
  };
1853
2277
  }
1854
- async #buildState(library, issues, classification) {
1855
- const [gitBranch, changedGitAssets] = await Promise.all([currentGitBranch(this.#config.projectRoot), gitAssetChanges(this.#config.projectRoot, this.#config.library, library)]);
2278
+ async #buildState(host, library, provenance, issues, classification) {
2279
+ const [gitBranch, changedGitAssets] = await Promise.all([currentGitBranch(this.#config.projectRoot), gitAssetChanges(this.#config.projectRoot, this.#config.library, host)]);
1856
2280
  const referencesByAsset = collectAllReferences(library, descriptorsByType(this.#registry));
1857
- const duplicatesByAsset = await this.#duplicateDetector.find(library, this.#config.rawDir);
2281
+ const duplicatesByAsset = await this.#duplicateDetector.find(host, this.#config.rawDir);
1858
2282
  const membershipByManifest = computeLibraryMembership(library, referencesByAsset);
1859
2283
  const delivered = allDeliveredAssetIds(membershipByManifest);
1860
2284
  const passiveManifestsByAsset = /* @__PURE__ */ new Map();
@@ -1878,12 +2302,21 @@ var FundusOperations = class {
1878
2302
  const assets = [];
1879
2303
  for (const assetId of Object.keys(library.assets).sort(compareCodeUnits)) {
1880
2304
  const record = library.assets[assetId];
2305
+ const prov = provenance[assetId] ?? { source: "host" };
2306
+ const origin = prov.source === "host" ? { kind: "host" } : prov.source === "package" ? {
2307
+ kind: "package",
2308
+ origin: prov.origin
2309
+ } : {
2310
+ kind: "override",
2311
+ origin: prov.origin
2312
+ };
2313
+ const isSlot = record.raw === void 0;
1881
2314
  const warnings = [];
1882
2315
  for (const issue of issues) if (issue.assetId === assetId) warnings.push(issue.message);
1883
- if (record.manifests.length === 0 && !delivered.has(assetId)) warnings.push("In no manifest and not referenced by any delivered asset — nothing is processed or generated for it.");
2316
+ if (record.manifests.length === 0 && !delivered.has(assetId) && !isSlot) warnings.push("In no manifest and not referenced by any delivered asset — nothing is processed or generated for it.");
1884
2317
  if (record.importSource && !this.#importers.has(record.importSource.importer)) warnings.push(`Importer "${record.importSource.importer}" is unavailable; the local raw file remains usable.`);
1885
2318
  let proxy = null;
1886
- if (delivered.has(assetId)) try {
2319
+ if (delivered.has(assetId) && !isSlot) try {
1887
2320
  const currentProxy = await readCurrentProxy(assetId, record, this.#config, this.#registry);
1888
2321
  if (currentProxy) proxy = {
1889
2322
  url: `/files/proxy/${encodeRelativePathForUrl(currentProxy.relativePath)}`,
@@ -1894,13 +2327,15 @@ var FundusOperations = class {
1894
2327
  } catch (cause) {
1895
2328
  warnings.push(cause instanceof Error ? cause.message : String(cause));
1896
2329
  }
2330
+ const raw = record.raw ?? "";
2331
+ const rawHash = record.rawHash ?? "";
1897
2332
  assets.push({
1898
2333
  id: assetId,
1899
2334
  type: record.type,
1900
- raw: record.raw,
1901
- folder: folderOfRawPath(record.raw),
1902
- rawUrl: `/files/raw/${encodeRelativePathForUrl(record.raw)}?v=${record.rawHash.slice(0, 12)}`,
1903
- rawHash: record.rawHash,
2335
+ raw,
2336
+ folder: folderOfRawPath(raw),
2337
+ rawUrl: isSlot ? "" : `/files/raw/${encodeRelativePathForUrl(raw)}?v=${rawHash.slice(0, 12)}`,
2338
+ rawHash,
1904
2339
  gitStatus: changedGitAssets.get(assetId) ?? null,
1905
2340
  importSource: record.importSource,
1906
2341
  parameters: record.parameters,
@@ -1915,7 +2350,9 @@ var FundusOperations = class {
1915
2350
  assetId: reference.assetId
1916
2351
  })),
1917
2352
  incoming: incomingByAsset.get(assetId) ?? []
1918
- }
2353
+ },
2354
+ origin,
2355
+ overridden: origin.kind === "override"
1919
2356
  });
1920
2357
  }
1921
2358
  const proxySizeByAssetId = new Map(assets.filter((asset) => asset.proxy).map((asset) => [asset.id, asset.proxy?.fileSize ?? 0]));
@@ -1939,7 +2376,7 @@ var FundusOperations = class {
1939
2376
  presetNames[type] = names;
1940
2377
  presetCapabilities[type] = Object.fromEntries(names.map((name) => [name, plugin.presetCapabilities?.(presets[name]) ?? {}]));
1941
2378
  }
1942
- const rawIngestionQueue = this.#buildRawIngestionQueue(library, classification);
2379
+ const rawIngestionQueue = this.#buildRawIngestionQueue(host, classification);
1943
2380
  return {
1944
2381
  gitBranch,
1945
2382
  library,
@@ -1950,7 +2387,8 @@ var FundusOperations = class {
1950
2387
  presetCapabilities,
1951
2388
  manifestMemberships,
1952
2389
  manifestDeliveredBytes,
1953
- rawIngestionQueue
2390
+ rawIngestionQueue,
2391
+ packageOrigins: this.#config.packages.map((pkg) => pkg.origin).sort(compareCodeUnits)
1954
2392
  };
1955
2393
  }
1956
2394
  #compatibleTypes(path) {
@@ -1963,8 +2401,10 @@ var FundusOperations = class {
1963
2401
  return rawSafetyIssues(library, classification, (path) => this.#compatibleTypes(path));
1964
2402
  }
1965
2403
  async #snapshotState(library, classification, extraIssues = []) {
2404
+ const { effective, provenance, mergeFindings } = this.#effectiveOf(library);
1966
2405
  const issues = [
1967
- ...await this.#store.validate(library),
2406
+ ...await this.#store.validate(library, { flatSpace: false }),
2407
+ ...this.#flatIssues(effective, provenance, mergeFindings),
1968
2408
  ...this.#rawSafetyIssues(library, classification),
1969
2409
  ...extraIssues
1970
2410
  ];
@@ -1975,7 +2415,7 @@ var FundusOperations = class {
1975
2415
  seen.add(key);
1976
2416
  return true;
1977
2417
  });
1978
- return this.#buildState(library, uniqueIssues, classification);
2418
+ return this.#buildState(library, effective, provenance, uniqueIssues, classification);
1979
2419
  }
1980
2420
  #canAutoReconcile(classification, retry = false) {
1981
2421
  return classification.complete && classification.blockers.length === 0 && classification.moves.length + classification.deletions.length > 0 && (!retry || classification.edited.length === 0 && classification.unmanaged.length === 0);
@@ -2064,6 +2504,59 @@ var FundusOperations = class {
2064
2504
  #requireAsset(library, id) {
2065
2505
  if (!Object.hasOwn(library.assets, id)) throw new Error(`Unknown asset "${id}".`);
2066
2506
  }
2507
+ /** Merge the configured Packages under the host library (host wins). */
2508
+ #effectiveOf(host) {
2509
+ const { library, provenance, findings } = mergePackages(host, this.#config.packages ?? []);
2510
+ return {
2511
+ effective: library,
2512
+ provenance,
2513
+ mergeFindings: findings
2514
+ };
2515
+ }
2516
+ /**
2517
+ * The Package base record for `id` when `id` is a read-only Package asset the
2518
+ * host has not yet filled — i.e. this create is a *slot fill*. Returns null
2519
+ * for a plain new host asset.
2520
+ */
2521
+ #packageBase(host, id) {
2522
+ if (Object.hasOwn(host.assets, id)) return null;
2523
+ const { effective, provenance } = this.#effectiveOf(host);
2524
+ if (provenance[id]?.source === "package") return { type: effective.assets[id].type };
2525
+ return null;
2526
+ }
2527
+ /**
2528
+ * Flat-space validation over the effective library: merge errors, id/type/
2529
+ * parameter/membership/appearance/reference checks, module collisions, and
2530
+ * delivered-slot findings. Disk/host checks stay in `store.validate(host,
2531
+ * { flatSpace: false })`.
2532
+ */
2533
+ #flatIssues(effective, provenance, mergeFindings) {
2534
+ const membership = computeLibraryMembership(effective, collectAllReferences(effective, descriptorsByType(this.#registry)));
2535
+ return [
2536
+ ...mergeFindings.filter((finding) => finding.kind !== "package-overridden").map((finding) => ({
2537
+ assetId: finding.assetId,
2538
+ message: finding.message
2539
+ })),
2540
+ ...flatLibraryIssues(effective, descriptorsByType(this.#registry)),
2541
+ ...manifestModuleCollisionIssues(effective.manifests),
2542
+ ...packageSlotFindings(effective, provenance, membership).map((finding) => ({
2543
+ assetId: finding.assetId,
2544
+ message: finding.message
2545
+ }))
2546
+ ];
2547
+ }
2548
+ /**
2549
+ * Whether an id is a read-only Package asset the host has not overridden.
2550
+ * Such ids can be filled/overridden (write a host record) but not mutated,
2551
+ * renamed, moved, or deleted in place.
2552
+ */
2553
+ #assertHostAsset(host, id, action) {
2554
+ if (Object.hasOwn(host.assets, id)) return;
2555
+ const { provenance } = this.#effectiveOf(host);
2556
+ const prov = provenance[id];
2557
+ if (prov && prov.source !== "host") throw new Error(`Asset "${id}" is provided by package "${prov.origin}"; ${action} is not available. Override it by importing or uploading bytes with this id.`);
2558
+ throw new Error(`Unknown asset "${id}".`);
2559
+ }
2067
2560
  /**
2068
2561
  * Apply a CLI asset change to the store, validating the resulting library
2069
2562
  * on an in-memory candidate first — nothing is persisted when the change
@@ -2112,4 +2605,4 @@ async function createFundusContext() {
2112
2605
  }
2113
2606
 
2114
2607
  export { getFundusContext as g, initializeFundusContext as i };
2115
- //# sourceMappingURL=context.js-CVuTSPjH.js.map
2608
+ //# sourceMappingURL=context.js-BXaBgcZT.js.map