fundus 0.17.2 → 0.19.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 (221) hide show
  1. package/README.md +60 -121
  2. package/build/client/_app/immutable/assets/2.C-1MfvLQ.css +1 -0
  3. package/build/client/_app/immutable/assets/2.C-1MfvLQ.css.br +0 -0
  4. package/build/client/_app/immutable/assets/2.C-1MfvLQ.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/{3.66PJT3JC.css → 3.q3CUOEpz.css} +1 -1
  6. package/build/client/_app/immutable/assets/3.q3CUOEpz.css.br +0 -0
  7. package/build/client/_app/immutable/assets/3.q3CUOEpz.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/{AssetSourceMenu.Buj2UxUg.css → AssetSourceMenu.CgyMTAb6.css} +1 -1
  9. package/build/client/_app/immutable/assets/AssetSourceMenu.CgyMTAb6.css.br +0 -0
  10. package/build/client/_app/immutable/assets/AssetSourceMenu.CgyMTAb6.css.gz +0 -0
  11. package/build/client/_app/immutable/chunks/Bly9uffh.js +1 -0
  12. package/build/client/_app/immutable/chunks/Bly9uffh.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/Bly9uffh.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/{R0o69z6O.js → BpsKkIFc.js} +1 -1
  15. package/build/client/_app/immutable/chunks/BpsKkIFc.js.br +2 -0
  16. package/build/client/_app/immutable/chunks/BpsKkIFc.js.gz +0 -0
  17. package/build/client/_app/immutable/chunks/{jEVVu5G9.js → CrIZjnDr.js} +1 -1
  18. package/build/client/_app/immutable/chunks/CrIZjnDr.js.br +0 -0
  19. package/build/client/_app/immutable/chunks/CrIZjnDr.js.gz +0 -0
  20. package/build/client/_app/immutable/chunks/ZGU9Utak.js +108 -0
  21. package/build/client/_app/immutable/chunks/ZGU9Utak.js.br +0 -0
  22. package/build/client/_app/immutable/chunks/ZGU9Utak.js.gz +0 -0
  23. package/build/client/_app/immutable/chunks/lw3KP4og.js +2 -0
  24. package/build/client/_app/immutable/chunks/lw3KP4og.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/lw3KP4og.js.gz +0 -0
  26. package/build/client/_app/immutable/entry/{app.DxYfHxs-.js → app.D-lO1MC-.js} +2 -2
  27. package/build/client/_app/immutable/entry/app.D-lO1MC-.js.br +0 -0
  28. package/build/client/_app/immutable/entry/app.D-lO1MC-.js.gz +0 -0
  29. package/build/client/_app/immutable/entry/start.BrSEFrid.js +1 -0
  30. package/build/client/_app/immutable/entry/start.BrSEFrid.js.br +1 -0
  31. package/build/client/_app/immutable/entry/start.BrSEFrid.js.gz +0 -0
  32. package/build/client/_app/immutable/nodes/{0.Do0MsVUC.js → 0.BPGg3A-F.js} +1 -1
  33. package/build/client/_app/immutable/nodes/0.BPGg3A-F.js.br +0 -0
  34. package/build/client/_app/immutable/nodes/0.BPGg3A-F.js.gz +0 -0
  35. package/build/client/_app/immutable/nodes/{1.DhfAdUbg.js → 1.-VJ5Mlss.js} +1 -1
  36. package/build/client/_app/immutable/nodes/1.-VJ5Mlss.js.br +1 -0
  37. package/build/client/_app/immutable/nodes/1.-VJ5Mlss.js.gz +0 -0
  38. package/build/client/_app/immutable/nodes/2.Dhyvb4bF.js +3 -0
  39. package/build/client/_app/immutable/nodes/2.Dhyvb4bF.js.br +0 -0
  40. package/build/client/_app/immutable/nodes/2.Dhyvb4bF.js.gz +0 -0
  41. package/build/client/_app/immutable/nodes/3.D9Fgsq-b.js +1 -0
  42. package/build/client/_app/immutable/nodes/3.D9Fgsq-b.js.br +0 -0
  43. package/build/client/_app/immutable/nodes/3.D9Fgsq-b.js.gz +0 -0
  44. package/build/client/_app/immutable/nodes/{4.gPNAednG.js → 4.DErtysFP.js} +1 -1
  45. package/build/client/_app/immutable/nodes/4.DErtysFP.js.br +0 -0
  46. package/build/client/_app/immutable/nodes/4.DErtysFP.js.gz +0 -0
  47. package/build/client/_app/version.json +1 -1
  48. package/build/client/_app/version.json.br +0 -0
  49. package/build/client/_app/version.json.gz +0 -0
  50. package/build/handler.js +7 -7
  51. package/build/index.js +7 -7
  52. package/build/server/chunks/chunks/{context.js-Dh0ibRIF.js → context.js-BIgcUcEl.js} +216 -604
  53. package/build/server/chunks/chunks/context.js-BIgcUcEl.js.map +1 -0
  54. package/build/server/chunks/chunks/{contract.js-_LTMZBo2.js → contract.js-B6KBK8D9.js} +59 -95
  55. package/build/server/chunks/chunks/contract.js-B6KBK8D9.js.map +1 -0
  56. package/build/server/chunks/chunks/{core.js-CTyKR4bu.js → core.js-Bp-ReC60.js} +38 -38
  57. package/build/server/chunks/chunks/core.js-Bp-ReC60.js.map +1 -0
  58. package/build/server/chunks/chunks/dependencies.js-pUkjICr5.js +45 -0
  59. package/build/server/chunks/chunks/dependencies.js-pUkjICr5.js.map +1 -0
  60. package/build/server/chunks/chunks/{exports.js-gUMFfqhw.js → exports.js-bhKV7cEL.js} +2 -2
  61. package/build/server/chunks/chunks/{exports.js-gUMFfqhw.js.map → exports.js-bhKV7cEL.js.map} +1 -1
  62. package/build/server/chunks/chunks/{http.js-BiqUcAuu.js → http.js-BTq44nR5.js} +2 -2
  63. package/build/server/chunks/chunks/{http.js-BiqUcAuu.js.map → http.js-BTq44nR5.js.map} +1 -1
  64. package/build/server/chunks/chunks/{internal.js-DvC1GD8s.js → internal.js-7MmaxxwZ.js} +3 -3
  65. package/build/server/chunks/chunks/{internal.js-DvC1GD8s.js.map → internal.js-7MmaxxwZ.js.map} +1 -1
  66. package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
  67. package/build/server/chunks/chunks/{manifest-membership.js-at1ixQdW.js → manifest-membership.js-Dj3WwZgz.js} +2 -2
  68. package/build/server/chunks/chunks/{manifest-membership.js-at1ixQdW.js.map → manifest-membership.js-Dj3WwZgz.js.map} +1 -1
  69. package/build/server/chunks/chunks/{raw-reconciliation.js-CUH8IIJx.js → raw-reconciliation.js-mWOAOdgL.js} +3 -3
  70. package/build/server/chunks/chunks/raw-reconciliation.js-mWOAOdgL.js.map +1 -0
  71. package/build/server/chunks/chunks/{raw-reconciliation2.js-z4xl5zw2.js → raw-reconciliation2.js-Bo1jJgvd.js} +2 -2
  72. package/build/server/chunks/chunks/{raw-reconciliation2.js-z4xl5zw2.js.map → raw-reconciliation2.js-Bo1jJgvd.js.map} +1 -1
  73. package/build/server/chunks/chunks/{shared.js-nXNT--BO.js → shared.js-B0m3s2U9.js} +2 -2
  74. package/build/server/chunks/chunks/{shared.js-nXNT--BO.js.map → shared.js-B0m3s2U9.js.map} +1 -1
  75. package/build/server/chunks/chunks/{utils.js-C5pr7OK-.js → utils.js-BXV0zq44.js} +3 -3
  76. package/build/server/chunks/chunks/{utils.js-C5pr7OK-.js.map → utils.js-BXV0zq44.js.map} +1 -1
  77. package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-CdDjuW0r.js → _server.ts.js-B_aa_zh7.js} +6 -6
  78. package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-CdDjuW0r.js.map → _server.ts.js-B_aa_zh7.js.map} +1 -1
  79. package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-OWM1eORG.js → _server.ts.js-DbEPdkbO.js} +8 -8
  80. package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-OWM1eORG.js.map → _server.ts.js-DbEPdkbO.js.map} +1 -1
  81. package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-DoG-7ZpZ.js → _server.ts.js-BzA96yBM.js} +8 -8
  82. package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-DoG-7ZpZ.js.map → _server.ts.js-BzA96yBM.js.map} +1 -1
  83. package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-CAWjVeGd.js → _server.ts.js-fQAXFRLh.js} +8 -8
  84. package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-CAWjVeGd.js.map → _server.ts.js-fQAXFRLh.js.map} +1 -1
  85. package/build/server/chunks/entries/endpoints/api/assets/_id_/retag/{_server.ts.js-CqS4aALY.js → _server.ts.js-RTBrlhk5.js} +8 -8
  86. package/build/server/chunks/entries/endpoints/api/assets/_id_/retag/{_server.ts.js-CqS4aALY.js.map → _server.ts.js-RTBrlhk5.js.map} +1 -1
  87. package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-Bo_EsYXJ.js → _server.ts.js-Baz4gPRd.js} +8 -8
  88. package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-Bo_EsYXJ.js.map → _server.ts.js-Baz4gPRd.js.map} +1 -1
  89. package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-DW4w0XAr.js → _server.ts.js-CnqdPxWQ.js} +8 -8
  90. package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-DW4w0XAr.js.map → _server.ts.js-CnqdPxWQ.js.map} +1 -1
  91. package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-_MiNPnSy.js → _server.ts.js-bvrtSRDz.js} +8 -8
  92. package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-_MiNPnSy.js.map → _server.ts.js-bvrtSRDz.js.map} +1 -1
  93. package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-DwbrQnBc.js → _server.ts.js-cgYcVXgU.js} +8 -8
  94. package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-DwbrQnBc.js.map → _server.ts.js-cgYcVXgU.js.map} +1 -1
  95. package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-CEnHQf3b.js → _server.ts.js-DbXw3YEr.js} +8 -8
  96. package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-CEnHQf3b.js.map → _server.ts.js-DbXw3YEr.js.map} +1 -1
  97. package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-BZDuJZtF.js → _server.ts.js-D0PEYlzG.js} +8 -8
  98. package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-BZDuJZtF.js.map → _server.ts.js-D0PEYlzG.js.map} +1 -1
  99. package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-DRgdpKKd.js → _server.ts.js-Dt9Wfgs7.js} +8 -8
  100. package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-DRgdpKKd.js.map → _server.ts.js-Dt9Wfgs7.js.map} +1 -1
  101. package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-CP5QyIhz.js → _server.ts.js-BBuZYakQ.js} +8 -8
  102. package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-CP5QyIhz.js.map → _server.ts.js-BBuZYakQ.js.map} +1 -1
  103. package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-BKEvt065.js → _server.ts.js-DQ_CWMTu.js} +8 -8
  104. package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-BKEvt065.js.map → _server.ts.js-DQ_CWMTu.js.map} +1 -1
  105. package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-C_zihkDS.js → _server.ts.js-B3TVoDCl.js} +8 -8
  106. package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-C_zihkDS.js.map → _server.ts.js-B3TVoDCl.js.map} +1 -1
  107. package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-watkBmy6.js → _server.ts.js--2C2x6Q0.js} +8 -8
  108. package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-watkBmy6.js.map → _server.ts.js--2C2x6Q0.js.map} +1 -1
  109. package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-YtumLIou.js → _server.ts.js-DD2Hz15k.js} +8 -8
  110. package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-YtumLIou.js.map → _server.ts.js-DD2Hz15k.js.map} +1 -1
  111. package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-Dkouuu-M.js → _server.ts.js-Ei98ilB5.js} +8 -8
  112. package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-Dkouuu-M.js.map → _server.ts.js-Ei98ilB5.js.map} +1 -1
  113. package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-DwsEQeuf.js → _server.ts.js-NNuDGwyK.js} +8 -8
  114. package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-DwsEQeuf.js.map → _server.ts.js-NNuDGwyK.js.map} +1 -1
  115. package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-CdQxfhV3.js → _server.ts.js-6_Wl_k0H.js} +8 -8
  116. package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-CdQxfhV3.js.map → _server.ts.js-6_Wl_k0H.js.map} +1 -1
  117. package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-DDdMocWj.js → _server.ts.js-DkYQlG9U.js} +6 -6
  118. package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-DDdMocWj.js.map → _server.ts.js-DkYQlG9U.js.map} +1 -1
  119. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-DbzjbH32.js → _server.ts.js-Dft0Zgh3.js} +8 -8
  120. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-DbzjbH32.js.map → _server.ts.js-Dft0Zgh3.js.map} +1 -1
  121. package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-K_JbXZsU.js → _server.ts.js-rlV0QRQS.js} +8 -8
  122. package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-K_JbXZsU.js.map → _server.ts.js-rlV0QRQS.js.map} +1 -1
  123. package/build/server/chunks/entries/{hooks.server.js-DgZAVFbQ.js → hooks.server.js-C345JVQ2.js} +7 -7
  124. package/build/server/chunks/entries/{hooks.server.js-DgZAVFbQ.js.map → hooks.server.js-C345JVQ2.js.map} +1 -1
  125. package/build/server/chunks/{handler-C4m7sKKb.js → handler-C_S3CtEF.js} +5 -5
  126. package/build/server/chunks/{handler-C4m7sKKb.js.map → handler-C_S3CtEF.js.map} +1 -1
  127. package/build/server/chunks/{index.js-pAnkrzRH.js → index.js-CSCxgyyg.js} +5 -5
  128. package/build/server/chunks/{index.js-pAnkrzRH.js.map → index.js-CSCxgyyg.js.map} +1 -1
  129. package/build/server/chunks/{manifest.js-CXQHeYnS.js → manifest.js-CO6AjAUm.js} +30 -30
  130. package/build/server/chunks/{manifest.js-CXQHeYnS.js.map → manifest.js-CO6AjAUm.js.map} +1 -1
  131. package/build/server/chunks/nodes/{0.js-lmQMhWZd.js → 0.js-CRc8onmc.js} +2 -2
  132. package/build/server/chunks/nodes/{0.js-lmQMhWZd.js.map → 0.js-CRc8onmc.js.map} +1 -1
  133. package/build/server/chunks/nodes/1.js-CZm_Doa7.js +7 -0
  134. package/build/server/chunks/nodes/{1.js-CdH3UJI2.js.map → 1.js-CZm_Doa7.js.map} +1 -1
  135. package/build/server/chunks/nodes/2.js-B92vn1Hu.js +7 -0
  136. package/build/server/chunks/nodes/2.js-B92vn1Hu.js.map +1 -0
  137. package/build/server/chunks/nodes/3.js-C14BP7Jm.js +7 -0
  138. package/build/server/chunks/nodes/3.js-C14BP7Jm.js.map +1 -0
  139. package/build/server/chunks/nodes/4.js-BLNdVCa1.js +7 -0
  140. package/build/server/chunks/nodes/{4.js-DtgDNAZF.js.map → 4.js-BLNdVCa1.js.map} +1 -1
  141. package/dist/config.d.ts +5 -3
  142. package/dist/config.js +3 -2
  143. package/dist/core/api-types.d.ts +7 -22
  144. package/dist/core/config.d.ts +8 -82
  145. package/dist/core/config.js +0 -9
  146. package/dist/core/dependencies.d.ts +52 -0
  147. package/dist/core/dependencies.js +56 -0
  148. package/dist/core/dependency-validation.d.ts +17 -0
  149. package/dist/core/dependency-validation.js +19 -0
  150. package/dist/core/index.d.ts +8 -10
  151. package/dist/core/index.js +4 -5
  152. package/dist/core/library.d.ts +0 -19
  153. package/dist/core/library.js +4 -4
  154. package/dist/core/manifest-membership.d.ts +2 -2
  155. package/dist/core/reference-graph.d.ts +3 -3
  156. package/dist/server/build.js +12 -26
  157. package/dist/server/check.d.ts +3 -13
  158. package/dist/server/check.js +33 -112
  159. package/dist/server/codegen.d.ts +1 -3
  160. package/dist/server/codegen.js +0 -18
  161. package/dist/server/config-loader.d.ts +10 -33
  162. package/dist/server/config-loader.js +87 -156
  163. package/dist/server/index.d.ts +1 -1
  164. package/dist/server/index.js +1 -1
  165. package/dist/server/library-store.d.ts +1 -11
  166. package/dist/server/library-store.js +60 -42
  167. package/dist/server/operations.js +54 -161
  168. package/package.json +1 -1
  169. package/build/client/_app/immutable/assets/2.X44Wyac-.css +0 -1
  170. package/build/client/_app/immutable/assets/2.X44Wyac-.css.br +0 -0
  171. package/build/client/_app/immutable/assets/2.X44Wyac-.css.gz +0 -0
  172. package/build/client/_app/immutable/assets/3.66PJT3JC.css.br +0 -0
  173. package/build/client/_app/immutable/assets/3.66PJT3JC.css.gz +0 -0
  174. package/build/client/_app/immutable/assets/AssetSourceMenu.Buj2UxUg.css.br +0 -0
  175. package/build/client/_app/immutable/assets/AssetSourceMenu.Buj2UxUg.css.gz +0 -0
  176. package/build/client/_app/immutable/chunks/0SQyBKXe.js +0 -108
  177. package/build/client/_app/immutable/chunks/0SQyBKXe.js.br +0 -0
  178. package/build/client/_app/immutable/chunks/0SQyBKXe.js.gz +0 -0
  179. package/build/client/_app/immutable/chunks/DXiUbZ9S.js +0 -2
  180. package/build/client/_app/immutable/chunks/DXiUbZ9S.js.br +0 -0
  181. package/build/client/_app/immutable/chunks/DXiUbZ9S.js.gz +0 -0
  182. package/build/client/_app/immutable/chunks/R0o69z6O.js.br +0 -0
  183. package/build/client/_app/immutable/chunks/R0o69z6O.js.gz +0 -0
  184. package/build/client/_app/immutable/chunks/TrnW_5ju.js +0 -1
  185. package/build/client/_app/immutable/chunks/TrnW_5ju.js.br +0 -0
  186. package/build/client/_app/immutable/chunks/TrnW_5ju.js.gz +0 -0
  187. package/build/client/_app/immutable/chunks/jEVVu5G9.js.br +0 -0
  188. package/build/client/_app/immutable/chunks/jEVVu5G9.js.gz +0 -0
  189. package/build/client/_app/immutable/entry/app.DxYfHxs-.js.br +0 -0
  190. package/build/client/_app/immutable/entry/app.DxYfHxs-.js.gz +0 -0
  191. package/build/client/_app/immutable/entry/start.CdM7ozdO.js +0 -1
  192. package/build/client/_app/immutable/entry/start.CdM7ozdO.js.br +0 -0
  193. package/build/client/_app/immutable/entry/start.CdM7ozdO.js.gz +0 -0
  194. package/build/client/_app/immutable/nodes/0.Do0MsVUC.js.br +0 -0
  195. package/build/client/_app/immutable/nodes/0.Do0MsVUC.js.gz +0 -0
  196. package/build/client/_app/immutable/nodes/1.DhfAdUbg.js.br +0 -1
  197. package/build/client/_app/immutable/nodes/1.DhfAdUbg.js.gz +0 -0
  198. package/build/client/_app/immutable/nodes/2.lLNAdU5s.js +0 -3
  199. package/build/client/_app/immutable/nodes/2.lLNAdU5s.js.br +0 -0
  200. package/build/client/_app/immutable/nodes/2.lLNAdU5s.js.gz +0 -0
  201. package/build/client/_app/immutable/nodes/3.DA8xzCvA.js +0 -1
  202. package/build/client/_app/immutable/nodes/3.DA8xzCvA.js.br +0 -0
  203. package/build/client/_app/immutable/nodes/3.DA8xzCvA.js.gz +0 -0
  204. package/build/client/_app/immutable/nodes/4.gPNAednG.js.br +0 -0
  205. package/build/client/_app/immutable/nodes/4.gPNAednG.js.gz +0 -0
  206. package/build/server/chunks/chunks/context.js-Dh0ibRIF.js.map +0 -1
  207. package/build/server/chunks/chunks/contract.js-_LTMZBo2.js.map +0 -1
  208. package/build/server/chunks/chunks/core.js-CTyKR4bu.js.map +0 -1
  209. package/build/server/chunks/chunks/raw-reconciliation.js-CUH8IIJx.js.map +0 -1
  210. package/build/server/chunks/nodes/1.js-CdH3UJI2.js +0 -7
  211. package/build/server/chunks/nodes/2.js-BHnsJqcE.js +0 -7
  212. package/build/server/chunks/nodes/2.js-BHnsJqcE.js.map +0 -1
  213. package/build/server/chunks/nodes/3.js-cR9NdrYS.js +0 -7
  214. package/build/server/chunks/nodes/3.js-cR9NdrYS.js.map +0 -1
  215. package/build/server/chunks/nodes/4.js-DtgDNAZF.js +0 -7
  216. package/dist/core/library-validation.d.ts +0 -13
  217. package/dist/core/library-validation.js +0 -48
  218. package/dist/core/package-declaration.d.ts +0 -43
  219. package/dist/core/package-declaration.js +0 -80
  220. package/dist/core/package-merge.d.ts +0 -65
  221. package/dist/core/package-merge.js +0 -173
@@ -1,13 +1,13 @@
1
- import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, H as typesForFileName, k as parentFolderPath, u as portableFolderPathKey, B as isAssetReference } from './core.js-CTyKR4bu.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-_LTMZBo2.js';
3
- import { c as collectAllReferences, a as assetIdError, b as computeLibraryMembership, d as allDeliveredAssetIds, i as isValidAssetId } from './manifest-membership.js-at1ixQdW.js';
4
- import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation2.js-z4xl5zw2.js';
1
+ import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, H as typesForFileName, k as parentFolderPath, u as portableFolderPathKey } from './core.js-Bp-ReC60.js';
2
+ import { i as isRecord, s as serverPluginsByType, 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-B6KBK8D9.js';
3
+ import { c as collectAllReferences, a as assetIdError, b as computeLibraryMembership, d as allDeliveredAssetIds, i as isValidAssetId } from './manifest-membership.js-Dj3WwZgz.js';
4
+ import { v as validateDependencyList, f as formatRequiredBy } from './dependencies.js-pUkjICr5.js';
5
+ import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation2.js-Bo1jJgvd.js';
5
6
  import { createRequire } from 'node:module';
6
7
  import { isAbsolute, resolve, join, dirname, extname, relative, sep } from 'node:path';
7
8
  import { existsSync, readFileSync } from 'node:fs';
8
- import { readFile, realpath } from 'node:fs/promises';
9
- import { pathToFileURL } from 'node:url';
10
9
  import { createJiti } from 'jiti';
10
+ import { readFile, realpath } from 'node:fs/promises';
11
11
  import { execFile } from 'node:child_process';
12
12
  import { isDeepStrictEqual, promisify } from 'node:util';
13
13
  import sharp from 'sharp';
@@ -16,224 +16,6 @@ import { lookup } from 'node:dns/promises';
16
16
  import { isIP } from 'node:net';
17
17
  import { request } from 'node:https';
18
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
237
19
  //#region src/lib/core/propose-asset-id.ts
238
20
  /**
239
21
  * Propose a camelCase asset id from a file (or node) name: split on
@@ -252,6 +34,20 @@ function proposeAssetId(fileName) {
252
34
  return withoutLeadingDigits.charAt(0).toLowerCase() + withoutLeadingDigits.slice(1);
253
35
  }
254
36
  //#endregion
37
+ //#region src/lib/core/dependency-validation.ts
38
+ function validateDependencies(dependencies, library) {
39
+ const findings = [];
40
+ for (const dependency of dependencies) {
41
+ if (!Object.hasOwn(library.assets, dependency.id)) {
42
+ findings.push({ message: `Missing ${dependency.type} "${dependency.id}" required by ${formatRequiredBy(dependency.sources)}.` });
43
+ continue;
44
+ }
45
+ const record = library.assets[dependency.id];
46
+ if (record.type !== dependency.type) findings.push({ message: `Type mismatch for "${dependency.id}" required by ${formatRequiredBy(dependency.sources)}: expected ${dependency.type}, library has ${record.type}.` });
47
+ }
48
+ return findings;
49
+ }
50
+ //#endregion
255
51
  //#region src/lib/server/config-loader.ts
256
52
  /**
257
53
  * Loads and resolves the host's `fundus.config.ts` through jiti, validates
@@ -275,70 +71,6 @@ function configDefinitionsFor(registry) {
275
71
  }
276
72
  return [...byNamespace.values()];
277
73
  }
278
- /**
279
- * A string `packages` entry is a *path* when it looks like one (starts with
280
- * `.`/`/`, is absolute, or ends `.json`), or a bare relative path with a
281
- * separator; otherwise it is a package *name*. A scoped name (`@scope/pkg`)
282
- * contains a `/` but is a name.
283
- */
284
- function classifyPackageSpec(spec) {
285
- if (spec.startsWith(".") || spec.startsWith("/") || isAbsolute(spec)) return "path";
286
- if (DECLARATION_FILE_RE.test(spec)) return "path";
287
- if (spec.startsWith("@")) return "name";
288
- if (spec.includes("/") || spec.includes("\\")) return "path";
289
- return "name";
290
- }
291
- /** A declaration file is JSON or a JS/TS module (the latter loaded via jiti). */
292
- var DECLARATION_FILE_RE = /\.(json|[mc]?[jt]s)$/;
293
- /**
294
- * Read a package declaration from its resolved file: a JSON `fundus.package.json`
295
- * (parsed as text) or a JS/TS module (`fundus.package.ts`) whose default export is
296
- * the declaration — loaded through the same jiti path as `fundus.config.ts`, which
297
- * keeps the resource `type`s literal for the package's `PackageAssets<…>` derivation.
298
- */
299
- async function loadPackageDeclaration(file, origin) {
300
- if (/\.[mc]?[jt]s$/.test(file)) {
301
- let module;
302
- try {
303
- module = await createJiti(import.meta.url, { interopDefault: false }).import(file);
304
- } catch (cause) {
305
- throw new Error(`Cannot load fundus package "${origin}" (${file}): ${cause instanceof Error ? cause.message : String(cause)}`);
306
- }
307
- return validatePackageDeclaration(isRecord(module) && "default" in module ? module.default : module, origin);
308
- }
309
- let text;
310
- try {
311
- text = await readFile(file, "utf8");
312
- } catch (cause) {
313
- throw new Error(`Cannot read fundus package "${origin}" (${file}): ${cause instanceof Error ? cause.message : String(cause)}`);
314
- }
315
- return parsePackageDeclaration(text, origin);
316
- }
317
- function normalizePackageSource(projectRoot, entry) {
318
- let spec;
319
- let rawDirOverride;
320
- if (typeof entry === "string") spec = entry;
321
- else if (isRecord(entry) && typeof entry.package === "string" && entry.package.length > 0) {
322
- spec = entry.package;
323
- if (entry.rawDir !== void 0) {
324
- if (typeof entry.rawDir !== "string" || entry.rawDir.length === 0) throw new Error("fundus.config: a \"packages\" entry \"rawDir\" must be a non-empty string.");
325
- rawDirOverride = entry.rawDir;
326
- }
327
- } else throw new Error("fundus.config: each \"packages\" entry must be a package name, a path string, or { package: string; rawDir?: string }.");
328
- const kind = classifyPackageSpec(spec);
329
- const reference = kind === "path" ? resolve(projectRoot, spec) : spec;
330
- return {
331
- origin: spec,
332
- kind,
333
- reference,
334
- ...rawDirOverride !== void 0 ? { rawDirOverride } : {}
335
- };
336
- }
337
- function resolvePackageSources(projectRoot, value) {
338
- if (value === void 0) return [];
339
- if (!Array.isArray(value)) throw new Error("fundus.config: \"packages\" must be an array.");
340
- return value.map((entry) => normalizePackageSource(projectRoot, entry));
341
- }
342
74
  /** Pure resolution step (testable without a config file on disk). */
343
75
  function resolveConfig(projectRoot, value, registry = serverPluginsByType) {
344
76
  if (!isRecord(value)) throw new Error("fundus.config must default-export a configuration object.");
@@ -361,6 +93,7 @@ function resolveConfig(projectRoot, value, registry = serverPluginsByType) {
361
93
  if (!isRecord(defaults)) throw new Error("fundus.config: \"import.figma.defaults\" must be an object.");
362
94
  const scale = defaults.scale === void 0 ? 2 : defaults.scale;
363
95
  if (scale !== 1 && scale !== 2 && scale !== 3 && scale !== 4) throw new Error("fundus.config: \"import.figma.defaults.scale\" must be 1, 2, 3, or 4.");
96
+ dependencySpecs(value);
364
97
  const usage = value.usage;
365
98
  if (usage !== void 0 && !isRecord(usage)) throw new Error("fundus.config: \"usage\" must be an object.");
366
99
  if (usage !== void 0 && typeof usage.referenceProvider !== "function") throw new Error("fundus.config: \"usage.referenceProvider\" must be a function.");
@@ -372,93 +105,92 @@ function resolveConfig(projectRoot, value, registry = serverPluginsByType) {
372
105
  library: resolvePath(projectRoot, requiredString(value, "library")),
373
106
  manifestsDir: resolvePath(projectRoot, requiredString(value, "manifestsDir")),
374
107
  proxyBasePath,
108
+ dependencies: [],
375
109
  plugins: resolvedPlugins,
376
110
  import: { figma: {
377
111
  ...figma.token !== void 0 ? { token: figma.token } : {},
378
112
  ...figma.defaultFileKey !== void 0 ? { defaultFileKey: figma.defaultFileKey } : {},
379
113
  defaults: { scale }
380
114
  } },
381
- usage: usage === void 0 ? null : usage,
382
- packageSources: resolvePackageSources(projectRoot, value.packages),
383
- packages: []
115
+ usage: usage === void 0 ? null : usage
384
116
  };
385
117
  }
386
- function nearestNamedPackageJson(entryPath, name) {
387
- let dir = dirname(entryPath);
118
+ /** Validated dependency source specs (shape only; absent means none). */
119
+ function dependencySpecs(value) {
120
+ const specs = value.dependencies;
121
+ if (specs === void 0) return [];
122
+ if (!Array.isArray(specs) || specs.some((spec) => typeof spec !== "string" || spec.length === 0)) throw new Error("fundus.config: \"dependencies\" must be an array of non-empty strings.");
123
+ return specs;
124
+ }
125
+ /** Reject a `.json` dependency source: JSON carries no literal types (D4). */
126
+ function assertNotJson(spec, context) {
127
+ if (spec.endsWith(".json")) throw new Error(`Dependency ${context} "${spec}" must be a .ts or .js module; JSON is not supported.`);
128
+ }
129
+ /** A dependency spec is a path when it is relative/absolute or names a module file. */
130
+ function isPathSpec(spec) {
131
+ return spec.startsWith(".") || spec.startsWith("/") || spec.endsWith(".ts") || spec.endsWith(".js");
132
+ }
133
+ /** Walk up from `fromPath` to the nearest package.json whose `name` matches. */
134
+ function nearestPackageJson(fromPath, name) {
135
+ let dir = dirname(fromPath);
388
136
  for (;;) {
389
137
  const candidate = join(dir, "package.json");
390
138
  if (existsSync(candidate)) try {
391
- const pkg = JSON.parse(readFileSync(candidate, "utf8"));
392
- if (isRecord(pkg) && pkg.name === name) return {
393
- dir,
394
- pkg
395
- };
139
+ if (JSON.parse(readFileSync(candidate, "utf8")).name === name) return candidate;
396
140
  } catch {}
397
141
  const parent = dirname(dir);
398
142
  if (parent === dir) break;
399
143
  dir = parent;
400
144
  }
401
- throw new Error(`Cannot find the package.json for fundus package "${name}" (resolved to ${entryPath}).`);
145
+ throw new Error(`Cannot resolve the package.json of dependency "${name}".`);
402
146
  }
403
- /**
404
- * Resolve a name-form Package to its root directory + parsed `package.json`. A
405
- * declaration-only Package ships no JS entry module, so resolving the bare name
406
- * would throw `MODULE_NOT_FOUND`; resolve its `package.json` subpath first and
407
- * only fall back to entry resolution when an `exports` map hides it.
408
- */
409
- function resolvePackageRoot(require, reference, origin) {
410
- try {
411
- const manifestPath = require.resolve(`${reference}/package.json`);
412
- const pkg = JSON.parse(readFileSync(manifestPath, "utf8"));
413
- if (isRecord(pkg)) return {
414
- dir: dirname(manifestPath),
415
- pkg
416
- };
417
- } catch {}
418
- let entry;
147
+ /** Resolve an npm-name dependency spec to its declared source module path. */
148
+ function resolveNpmDependencyModule(spec, require) {
149
+ let packageJsonPath;
419
150
  try {
420
- entry = require.resolve(reference);
421
- } catch {
422
- throw new Error(`Cannot resolve fundus package "${origin}": no installed package declares it is it a dependency?`);
151
+ packageJsonPath = require.resolve(`${spec}/package.json`);
152
+ } catch (cause) {
153
+ if (cause !== null && typeof cause === "object" && cause.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") packageJsonPath = nearestPackageJson(require.resolve(spec), spec);
154
+ else throw cause;
423
155
  }
424
- return nearestNamedPackageJson(entry, reference);
156
+ const field = JSON.parse(readFileSync(packageJsonPath, "utf8")).fundus?.dependencies;
157
+ if (typeof field !== "string" || field.length === 0) throw new Error(`Dependency "${spec}" is missing a non-empty "fundus".dependencies module path in its package.json.`);
158
+ assertNotJson(field, `package.json "fundus".dependencies field of "${spec}"`);
159
+ return resolve(dirname(packageJsonPath), field);
425
160
  }
426
161
  /**
427
- * Read and parse every declared Package from disk. Name entries resolve through
428
- * the host's module resolver (respecting `exports`), then walk up to the nearest
429
- * `package.json` that declares the name and read its `"fundus"` field. Path
430
- * entries point directly at a `fundus.package.json`. Throws a clear,
431
- * origin-tagged error on any resolution/read/parse failure — Package assembly
432
- * failures are symmetric with a missing `fundus.config.ts`.
162
+ * Load and aggregate every configured dependency source (D3, D6). `requireAnchor`
163
+ * anchors npm-name resolution at the host project (injectable for tests). Flat:
164
+ * the dependencies of a referenced npm package are not resolved recursively.
433
165
  */
434
- async function loadPackages(projectRoot, sources) {
435
- const require = createRequire(pathToFileURL(join(projectRoot, "fundus.config.ts")).href);
436
- const packages = [];
437
- for (const source of sources) {
438
- let file;
439
- let defaultRawDir;
440
- if (source.kind === "path") {
441
- file = source.reference;
442
- if (!existsSync(file)) throw new Error(`Fundus package file not found: ${file} (from "${source.origin}").`);
443
- defaultRawDir = dirname(file);
444
- } else {
445
- const { dir, pkg } = resolvePackageRoot(require, source.reference, source.origin);
446
- const fundusField = pkg.fundus;
447
- 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.`);
448
- file = resolve(dir, fundusField.package);
449
- if (!existsSync(file)) throw new Error(`Fundus package "${source.origin}" declaration not found: ${file}.`);
450
- defaultRawDir = typeof fundusField.rawDir === "string" && fundusField.rawDir.length > 0 ? resolve(dir, fundusField.rawDir) : dir;
166
+ async function resolveDependencies(projectRoot, specs, requireAnchor = join(resolve(projectRoot), "package.json")) {
167
+ if (specs.length === 0) return [];
168
+ const jiti = createJiti(import.meta.url, { interopDefault: false });
169
+ const require = createRequire(requireAnchor);
170
+ const aggregated = /* @__PURE__ */ new Map();
171
+ for (const spec of specs) {
172
+ assertNotJson(spec, "source");
173
+ const modulePath = isPathSpec(spec) ? resolve(resolve(projectRoot), spec) : resolveNpmDependencyModule(spec, require);
174
+ const loaded = await jiti.import(modulePath);
175
+ const value = loaded.default ?? loaded;
176
+ for (const dependency of validateDependencyList(spec, value)) {
177
+ const existing = aggregated.get(dependency.id);
178
+ if (existing === void 0) {
179
+ aggregated.set(dependency.id, {
180
+ type: dependency.type,
181
+ sources: [spec]
182
+ });
183
+ continue;
184
+ }
185
+ if (existing.type !== dependency.type) throw new Error(`Dependency "${dependency.id}" is declared as "${existing.type}" by "${existing.sources.join("\", \"")}" and as "${dependency.type}" by "${spec}".`);
186
+ if (!existing.sources.includes(spec)) existing.sources.push(spec);
451
187
  }
452
- const declaration = await loadPackageDeclaration(file, source.origin);
453
- const rawDir = source.rawDirOverride !== void 0 ? resolve(projectRoot, source.rawDirOverride) : defaultRawDir;
454
- packages.push({
455
- origin: source.origin,
456
- file,
457
- rawDir,
458
- declaration
459
- });
460
188
  }
461
- return packages;
189
+ return [...aggregated].map(([id, { type, sources }]) => ({
190
+ id,
191
+ type,
192
+ sources
193
+ }));
462
194
  }
463
195
  /** Load `fundus.config.ts` from the host project root. */
464
196
  async function loadConfig(projectRoot) {
@@ -471,153 +203,14 @@ async function loadConfig(projectRoot) {
471
203
  } catch (cause) {
472
204
  throw new Error(`Cannot load fundus.config.ts: ${cause instanceof Error ? cause.message : String(cause)}`);
473
205
  }
474
- const config = resolveConfig(root, isRecord(module) && "default" in module ? module.default : module);
475
- return {
476
- ...config,
477
- packages: await loadPackages(root, config.packageSources)
478
- };
479
- }
480
- async function imageFingerprint(filePath, hashSize) {
481
- const width = hashSize + 1;
482
- const pixels = await sharp(filePath).rotate().trim({
483
- background: {
484
- r: 0,
485
- g: 0,
486
- b: 0,
487
- alpha: 0
488
- },
489
- threshold: 0
490
- }).resize({
491
- width,
492
- height: hashSize,
493
- fit: "fill"
494
- }).ensureAlpha().toColourspace("srgb").raw().toBuffer();
495
- const hash = new Uint8Array(Math.ceil(hashSize * hashSize / 8));
496
- const alphaHash = new Uint8Array(hash.length);
497
- const colorTotals = [
498
- 0,
499
- 0,
500
- 0
501
- ];
502
- let alphaTotal = 0;
503
- let bit = 0;
504
- for (let row = 0; row < hashSize; row++) for (let column = 0; column < hashSize; column++) {
505
- const leftOffset = (row * width + column) * 4;
506
- const rightOffset = leftOffset + 4;
507
- const leftAlpha = pixels[leftOffset + 3] / 255;
508
- const rightAlpha = pixels[rightOffset + 3] / 255;
509
- if (visibleLuminance(pixels, leftOffset, leftAlpha) < visibleLuminance(pixels, rightOffset, rightAlpha)) hash[bit >> 3] |= 1 << 7 - (bit & 7);
510
- if (leftAlpha < rightAlpha) alphaHash[bit >> 3] |= 1 << 7 - (bit & 7);
511
- for (let channel = 0; channel < 3; channel++) colorTotals[channel] += pixels[leftOffset + channel] * leftAlpha;
512
- alphaTotal += leftAlpha;
513
- bit += 1;
514
- }
515
- const pixelCount = hashSize * hashSize;
206
+ const value = isRecord(module) && "default" in module ? module.default : module;
207
+ const resolved = resolveConfig(root, value);
208
+ const dependencies = await resolveDependencies(root, isRecord(value) ? dependencySpecs(value) : []);
516
209
  return {
517
- hash,
518
- alphaHash,
519
- meanColor: colorTotals.map((total) => alphaTotal === 0 ? 0 : total / alphaTotal),
520
- meanAlpha: alphaTotal / pixelCount
210
+ ...resolved,
211
+ dependencies
521
212
  };
522
213
  }
523
- function visibleLuminance(pixels, offset, alpha) {
524
- return (pixels[offset] * .2126 + pixels[offset + 1] * .7152 + pixels[offset + 2] * .0722) * alpha + 127 * (1 - alpha);
525
- }
526
- function colorDistance(left, right) {
527
- return Math.hypot(left[0] - right[0], left[1] - right[1], left[2] - right[2]);
528
- }
529
- /** Count differing bits between two equally sized perceptual hashes. */
530
- function hammingDistance(left, right) {
531
- if (left.length !== right.length) throw new Error("Image hashes must have the same length.");
532
- let distance = 0;
533
- for (let index = 0; index < left.length; index++) {
534
- let value = left[index] ^ right[index];
535
- while (value !== 0) {
536
- value &= value - 1;
537
- distance += 1;
538
- }
539
- }
540
- return distance;
541
- }
542
- /**
543
- * Stateful so the editor can reuse fingerprints by content hash between state
544
- * snapshots. Unreadable raws are omitted: duplicate detection is advisory and
545
- * must not hide the editor or replace the pipeline's canonical diagnostics.
546
- */
547
- var ImageDuplicateDetector = class {
548
- #fingerprints = /* @__PURE__ */ new Map();
549
- async find(library, rawDir) {
550
- const images = Object.entries(library.assets).filter(([, record]) => record.type === "image").sort(([left], [right]) => compareCodeUnits(left, right));
551
- const activeHashes = new Set(images.map(([, record]) => record.rawHash));
552
- for (const hash of this.#fingerprints.keys()) if (!activeHashes.has(hash)) this.#fingerprints.delete(hash);
553
- const readable = [];
554
- for (const [id, record] of images) {
555
- let fingerprint = this.#fingerprints.get(record.rawHash);
556
- if (!fingerprint) {
557
- fingerprint = imageFingerprint(join(rawDir, record.raw), 8);
558
- this.#fingerprints.set(record.rawHash, fingerprint);
559
- }
560
- try {
561
- readable.push({
562
- id,
563
- fingerprint: await fingerprint
564
- });
565
- } catch {
566
- this.#fingerprints.delete(record.rawHash);
567
- }
568
- }
569
- const duplicates = /* @__PURE__ */ new Map();
570
- for (let leftIndex = 0; leftIndex < readable.length; leftIndex++) for (let rightIndex = leftIndex + 1; rightIndex < readable.length; rightIndex++) {
571
- const left = readable[leftIndex];
572
- const right = readable[rightIndex];
573
- 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;
574
- const leftDuplicates = duplicates.get(left.id) ?? [];
575
- leftDuplicates.push(right.id);
576
- duplicates.set(left.id, leftDuplicates);
577
- const rightDuplicates = duplicates.get(right.id) ?? [];
578
- rightDuplicates.push(left.id);
579
- duplicates.set(right.id, rightDuplicates);
580
- }
581
- return duplicates;
582
- }
583
- };
584
- //#endregion
585
- //#region src/lib/server/check.ts
586
- /**
587
- * The delivered-slot contract: a Package slot that is delivered (explicit member
588
- * or in a delivered manifest's reference closure) but has no host-supplied bytes
589
- * must be filled. A slot with an `importSource` is `slot-unmaterialized` (run
590
- * import); a slot with nothing is `slot-unfilled`. Inert (undelivered) slots
591
- * produce no finding.
592
- */
593
- function packageSlotFindings(library, provenance, membership) {
594
- const deliveringManifests = /* @__PURE__ */ new Map();
595
- for (const [name, manifestMembership] of Object.entries(membership)) for (const assetId of manifestMembership.deliveredAssetIds) {
596
- const names = deliveringManifests.get(assetId) ?? [];
597
- names.push(name);
598
- deliveringManifests.set(assetId, names);
599
- }
600
- const findings = [];
601
- for (const [assetId, record] of Object.entries(library.assets)) {
602
- if (record.raw !== void 0) continue;
603
- const names = deliveringManifests.get(assetId);
604
- if (!names || names.length === 0) continue;
605
- const originRecord = provenance[assetId];
606
- const origin = originRecord && originRecord.source !== "host" ? originRecord.origin : "a package";
607
- const deliveredBy = [...names].sort(compareCodeUnits).map((name) => `"${name}"`).join(", ");
608
- if (record.importSource !== void 0) findings.push({
609
- kind: "slot-unmaterialized",
610
- assetId,
611
- message: `Slot "${assetId}" (from ${origin}) has an import source but no bytes yet — run import to fill it. Delivered by: ${deliveredBy}.`
612
- });
613
- else findings.push({
614
- kind: "slot-unfilled",
615
- assetId,
616
- message: `Slot "${assetId}" (from ${origin}) has no bytes, import source, or host override. Delivered by: ${deliveredBy}.`
617
- });
618
- }
619
- return findings;
620
- }
621
214
  //#endregion
622
215
  //#region src/lib/server/raw-safety.ts
623
216
  function rawSafetyIssueKey(issue) {
@@ -1678,6 +1271,110 @@ function pathsFromRoot(root, target, referencesByAsset, countMemo = /* @__PURE__
1678
1271
  function usageSnapshotRevision(parts) {
1679
1272
  return createHash("sha256").update(parts.join("\0")).digest("hex");
1680
1273
  }
1274
+ async function imageFingerprint(filePath, hashSize) {
1275
+ const width = hashSize + 1;
1276
+ const pixels = await sharp(filePath).rotate().trim({
1277
+ background: {
1278
+ r: 0,
1279
+ g: 0,
1280
+ b: 0,
1281
+ alpha: 0
1282
+ },
1283
+ threshold: 0
1284
+ }).resize({
1285
+ width,
1286
+ height: hashSize,
1287
+ fit: "fill"
1288
+ }).ensureAlpha().toColourspace("srgb").raw().toBuffer();
1289
+ const hash = new Uint8Array(Math.ceil(hashSize * hashSize / 8));
1290
+ const alphaHash = new Uint8Array(hash.length);
1291
+ const colorTotals = [
1292
+ 0,
1293
+ 0,
1294
+ 0
1295
+ ];
1296
+ let alphaTotal = 0;
1297
+ let bit = 0;
1298
+ for (let row = 0; row < hashSize; row++) for (let column = 0; column < hashSize; column++) {
1299
+ const leftOffset = (row * width + column) * 4;
1300
+ const rightOffset = leftOffset + 4;
1301
+ const leftAlpha = pixels[leftOffset + 3] / 255;
1302
+ const rightAlpha = pixels[rightOffset + 3] / 255;
1303
+ if (visibleLuminance(pixels, leftOffset, leftAlpha) < visibleLuminance(pixels, rightOffset, rightAlpha)) hash[bit >> 3] |= 1 << 7 - (bit & 7);
1304
+ if (leftAlpha < rightAlpha) alphaHash[bit >> 3] |= 1 << 7 - (bit & 7);
1305
+ for (let channel = 0; channel < 3; channel++) colorTotals[channel] += pixels[leftOffset + channel] * leftAlpha;
1306
+ alphaTotal += leftAlpha;
1307
+ bit += 1;
1308
+ }
1309
+ const pixelCount = hashSize * hashSize;
1310
+ return {
1311
+ hash,
1312
+ alphaHash,
1313
+ meanColor: colorTotals.map((total) => alphaTotal === 0 ? 0 : total / alphaTotal),
1314
+ meanAlpha: alphaTotal / pixelCount
1315
+ };
1316
+ }
1317
+ function visibleLuminance(pixels, offset, alpha) {
1318
+ return (pixels[offset] * .2126 + pixels[offset + 1] * .7152 + pixels[offset + 2] * .0722) * alpha + 127 * (1 - alpha);
1319
+ }
1320
+ function colorDistance(left, right) {
1321
+ return Math.hypot(left[0] - right[0], left[1] - right[1], left[2] - right[2]);
1322
+ }
1323
+ /** Count differing bits between two equally sized perceptual hashes. */
1324
+ function hammingDistance(left, right) {
1325
+ if (left.length !== right.length) throw new Error("Image hashes must have the same length.");
1326
+ let distance = 0;
1327
+ for (let index = 0; index < left.length; index++) {
1328
+ let value = left[index] ^ right[index];
1329
+ while (value !== 0) {
1330
+ value &= value - 1;
1331
+ distance += 1;
1332
+ }
1333
+ }
1334
+ return distance;
1335
+ }
1336
+ /**
1337
+ * Stateful so the editor can reuse fingerprints by content hash between state
1338
+ * snapshots. Unreadable raws are omitted: duplicate detection is advisory and
1339
+ * must not hide the editor or replace the pipeline's canonical diagnostics.
1340
+ */
1341
+ var ImageDuplicateDetector = class {
1342
+ #fingerprints = /* @__PURE__ */ new Map();
1343
+ async find(library, rawDir) {
1344
+ const images = Object.entries(library.assets).filter(([, record]) => record.type === "image").sort(([left], [right]) => compareCodeUnits(left, right));
1345
+ const activeHashes = new Set(images.map(([, record]) => record.rawHash));
1346
+ for (const hash of this.#fingerprints.keys()) if (!activeHashes.has(hash)) this.#fingerprints.delete(hash);
1347
+ const readable = [];
1348
+ for (const [id, record] of images) {
1349
+ let fingerprint = this.#fingerprints.get(record.rawHash);
1350
+ if (!fingerprint) {
1351
+ fingerprint = imageFingerprint(join(rawDir, record.raw), 8);
1352
+ this.#fingerprints.set(record.rawHash, fingerprint);
1353
+ }
1354
+ try {
1355
+ readable.push({
1356
+ id,
1357
+ fingerprint: await fingerprint
1358
+ });
1359
+ } catch {
1360
+ this.#fingerprints.delete(record.rawHash);
1361
+ }
1362
+ }
1363
+ const duplicates = /* @__PURE__ */ new Map();
1364
+ for (let leftIndex = 0; leftIndex < readable.length; leftIndex++) for (let rightIndex = leftIndex + 1; rightIndex < readable.length; rightIndex++) {
1365
+ const left = readable[leftIndex];
1366
+ const right = readable[rightIndex];
1367
+ 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;
1368
+ const leftDuplicates = duplicates.get(left.id) ?? [];
1369
+ leftDuplicates.push(right.id);
1370
+ duplicates.set(left.id, leftDuplicates);
1371
+ const rightDuplicates = duplicates.get(right.id) ?? [];
1372
+ rightDuplicates.push(left.id);
1373
+ duplicates.set(right.id, rightDuplicates);
1374
+ }
1375
+ return duplicates;
1376
+ }
1377
+ };
1681
1378
  //#endregion
1682
1379
  //#region src/lib/server/operations.ts
1683
1380
  /**
@@ -2173,24 +1870,7 @@ var FundusOperations = class {
2173
1870
  this.#validateImportedRaw(raw);
2174
1871
  const fileName = raw.suggestedFileName ?? `${options.id}.${raw.extension}`;
2175
1872
  const plugin = serverPluginForType(options.type, this.#registry);
2176
- const packageBase = this.#packageBase(await this.#store.read(), options.id);
2177
- if (packageBase && packageBase.type !== options.type) throw new SourceImportError("invalid-input", `Filling slot "${options.id}" requires the package type "${packageBase.type}", not "${options.type}".`);
2178
- let slotOverride = {};
2179
- if (packageBase) {
2180
- const pixelRatio = figmaSlicePixelRatio(raw, options.type);
2181
- if (pixelRatio !== void 0) slotOverride = mergeParameterPatch(slotOverride, { pixelRatio });
2182
- if (options.parametersPatch !== void 0) slotOverride = mergeParameterPatch(slotOverride, options.parametersPatch);
2183
- }
2184
- const library = packageBase ? await this.#store.createAsset({
2185
- fileName,
2186
- bytes: raw.bytes,
2187
- type: options.type,
2188
- id: options.id,
2189
- folder: options.folder,
2190
- manifests: options.manifests,
2191
- importSource: raw.importSource,
2192
- parametersOverride: slotOverride
2193
- }) : await this.#store.createAsset({
1873
+ const library = await this.#store.createAsset({
2194
1874
  fileName,
2195
1875
  bytes: raw.bytes,
2196
1876
  type: options.type,
@@ -2225,8 +1905,7 @@ var FundusOperations = class {
2225
1905
  const folder = normalizeFolderPath(options.folder ?? "");
2226
1906
  if (folder !== "" && !library.folders.includes(folder)) throw new SourceImportError("invalid-input", `Unknown folder "${folder}".`);
2227
1907
  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.");
2228
- const validManifests = this.#effectiveOf(library).effective.manifests;
2229
- for (const manifest of new Set(options.manifests ?? [])) if (!Object.hasOwn(validManifests, manifest)) throw new SourceImportError("invalid-input", `Unknown manifest "${manifest}".`);
1908
+ for (const manifest of new Set(options.manifests ?? [])) if (!Object.hasOwn(library.manifests, manifest)) throw new SourceImportError("invalid-input", `Unknown manifest "${manifest}".`);
2230
1909
  }
2231
1910
  #validateImportedRaw(raw, importerKind) {
2232
1911
  if (!(raw.bytes instanceof Uint8Array) || !/^[a-z0-9]+$/.test(raw.extension)) throw new SourceImportError("invalid-response", "The source importer returned invalid raw data.");
@@ -2241,7 +1920,7 @@ var FundusOperations = class {
2241
1920
  }
2242
1921
  async #patchAsset(id, body) {
2243
1922
  let library = await this.#store.read();
2244
- this.#assertHostAsset(library, id, "editing it");
1923
+ this.#requireAsset(library, id);
2245
1924
  if (body.parameters !== void 0) library = await this.#store.updateParameters(id, body.parameters);
2246
1925
  if (body.manifests !== void 0) {
2247
1926
  if (!Array.isArray(body.manifests) || body.manifests.some((name) => typeof name !== "string")) throw new Error("\"manifests\" must be an array of manifest names.");
@@ -2443,13 +2122,11 @@ var FundusOperations = class {
2443
2122
  async #runAfterMutation(library) {
2444
2123
  const pipelineIssues = [];
2445
2124
  const classification = await this.#classifyRawDirectory(library);
2446
- const { effective, provenance, mergeFindings } = this.#effectiveOf(library);
2447
- const materialized = materializeLibrary(effective);
2448
- const ordinaryIssues = [...await this.#store.validate(library, { flatSpace: false }), ...this.#flatIssues(effective, provenance, mergeFindings)];
2125
+ const ordinaryIssues = await this.#store.validate(library);
2449
2126
  const safetyIssues = this.#rawSafetyIssues(library, classification);
2450
2127
  if (ordinaryIssues.length === 0 && safetyIssues.length === 0) try {
2451
- const report = await processAssets(this.#config, materialized, this.#registry);
2452
- await generateManifestModules(this.#config, materialized, report.proxies, this.#registry);
2128
+ const report = await processAssets(this.#config, library, this.#registry);
2129
+ await generateManifestModules(this.#config, library, report.proxies, this.#registry);
2453
2130
  } catch (cause) {
2454
2131
  pipelineIssues.push({ message: `Processing failed: ${cause instanceof Error ? cause.message : String(cause)}` });
2455
2132
  }
@@ -2461,10 +2138,10 @@ var FundusOperations = class {
2461
2138
  state: await this.#snapshotState(latestLibrary, latestClassification, pipelineIssues)
2462
2139
  };
2463
2140
  }
2464
- async #buildState(host, library, provenance, issues, classification) {
2465
- const [gitBranch, changedGitAssets] = await Promise.all([currentGitBranch(this.#config.projectRoot), gitAssetChanges(this.#config.projectRoot, this.#config.library, host)]);
2141
+ async #buildState(library, issues, classification) {
2142
+ const [gitBranch, changedGitAssets] = await Promise.all([currentGitBranch(this.#config.projectRoot), gitAssetChanges(this.#config.projectRoot, this.#config.library, library)]);
2466
2143
  const referencesByAsset = collectAllReferences(library, descriptorsByType(this.#registry));
2467
- const duplicatesByAsset = await this.#duplicateDetector.find(host, this.#config.rawDir);
2144
+ const duplicatesByAsset = await this.#duplicateDetector.find(library, this.#config.rawDir);
2468
2145
  const membershipByManifest = computeLibraryMembership(library, referencesByAsset);
2469
2146
  const delivered = allDeliveredAssetIds(membershipByManifest);
2470
2147
  const passiveManifestsByAsset = /* @__PURE__ */ new Map();
@@ -2485,24 +2162,17 @@ var FundusOperations = class {
2485
2162
  });
2486
2163
  incomingByAsset.set(reference.assetId, incoming);
2487
2164
  }
2165
+ const requiredByAsset = /* @__PURE__ */ new Map();
2166
+ for (const dependency of this.#config.dependencies) requiredByAsset.set(dependency.id, [...dependency.sources]);
2488
2167
  const assets = [];
2489
2168
  for (const assetId of Object.keys(library.assets).sort(compareCodeUnits)) {
2490
2169
  const record = library.assets[assetId];
2491
- const prov = provenance[assetId] ?? { source: "host" };
2492
- const origin = prov.source === "host" ? { kind: "host" } : prov.source === "package" ? {
2493
- kind: "package",
2494
- origin: prov.origin
2495
- } : {
2496
- kind: "override",
2497
- origin: prov.origin
2498
- };
2499
- const isSlot = record.raw === void 0;
2500
2170
  const warnings = [];
2501
2171
  for (const issue of issues) if (issue.assetId === assetId) warnings.push(issue.message);
2502
- 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.");
2172
+ 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.");
2503
2173
  if (record.importSource && !this.#importers.has(record.importSource.importer)) warnings.push(`Importer "${record.importSource.importer}" is unavailable; the local raw file remains usable.`);
2504
2174
  let proxy = null;
2505
- if (delivered.has(assetId) && !isSlot) try {
2175
+ if (delivered.has(assetId)) try {
2506
2176
  const currentProxy = await readCurrentProxy(assetId, record, this.#config, this.#registry);
2507
2177
  if (currentProxy) proxy = {
2508
2178
  url: `/files/proxy/${encodeRelativePathForUrl(currentProxy.relativePath)}`,
@@ -2513,15 +2183,13 @@ var FundusOperations = class {
2513
2183
  } catch (cause) {
2514
2184
  warnings.push(cause instanceof Error ? cause.message : String(cause));
2515
2185
  }
2516
- const raw = record.raw ?? "";
2517
- const rawHash = record.rawHash ?? "";
2518
2186
  assets.push({
2519
2187
  id: assetId,
2520
2188
  type: record.type,
2521
- raw,
2522
- folder: folderOfRawPath(raw),
2523
- rawUrl: isSlot ? "" : `/files/raw/${encodeRelativePathForUrl(raw)}?v=${rawHash.slice(0, 12)}`,
2524
- rawHash,
2189
+ raw: record.raw,
2190
+ folder: folderOfRawPath(record.raw),
2191
+ rawUrl: `/files/raw/${encodeRelativePathForUrl(record.raw)}?v=${record.rawHash.slice(0, 12)}`,
2192
+ rawHash: record.rawHash,
2525
2193
  gitStatus: changedGitAssets.get(assetId) ?? null,
2526
2194
  importSource: record.importSource,
2527
2195
  parameters: record.parameters,
@@ -2537,8 +2205,7 @@ var FundusOperations = class {
2537
2205
  })),
2538
2206
  incoming: incomingByAsset.get(assetId) ?? []
2539
2207
  },
2540
- origin,
2541
- overridden: origin.kind === "override"
2208
+ requiredBy: requiredByAsset.get(assetId) ?? []
2542
2209
  });
2543
2210
  }
2544
2211
  const proxySizeByAssetId = new Map(assets.filter((asset) => asset.proxy).map((asset) => [asset.id, asset.proxy?.fileSize ?? 0]));
@@ -2562,7 +2229,7 @@ var FundusOperations = class {
2562
2229
  presetNames[type] = names;
2563
2230
  presetCapabilities[type] = Object.fromEntries(names.map((name) => [name, plugin.presetCapabilities?.(presets[name]) ?? {}]));
2564
2231
  }
2565
- const rawIngestionQueue = this.#buildRawIngestionQueue(host, classification);
2232
+ const rawIngestionQueue = this.#buildRawIngestionQueue(library, classification);
2566
2233
  return {
2567
2234
  gitBranch,
2568
2235
  library,
@@ -2576,8 +2243,7 @@ var FundusOperations = class {
2576
2243
  presetCapabilities,
2577
2244
  manifestMemberships,
2578
2245
  manifestDeliveredBytes,
2579
- rawIngestionQueue,
2580
- packageOrigins: this.#config.packages.map((pkg) => pkg.origin).sort(compareCodeUnits)
2246
+ rawIngestionQueue
2581
2247
  };
2582
2248
  }
2583
2249
  #compatibleTypes(path) {
@@ -2590,11 +2256,10 @@ var FundusOperations = class {
2590
2256
  return rawSafetyIssues(library, classification, (path) => this.#compatibleTypes(path));
2591
2257
  }
2592
2258
  async #snapshotState(library, classification, extraIssues = []) {
2593
- const { effective, provenance, mergeFindings } = this.#effectiveOf(library);
2594
2259
  const issues = [
2595
- ...await this.#store.validate(library, { flatSpace: false }),
2596
- ...this.#flatIssues(effective, provenance, mergeFindings),
2260
+ ...await this.#store.validate(library),
2597
2261
  ...this.#rawSafetyIssues(library, classification),
2262
+ ...validateDependencies(this.#config.dependencies, library),
2598
2263
  ...extraIssues
2599
2264
  ];
2600
2265
  const seen = /* @__PURE__ */ new Set();
@@ -2604,7 +2269,7 @@ var FundusOperations = class {
2604
2269
  seen.add(key);
2605
2270
  return true;
2606
2271
  });
2607
- return this.#buildState(library, effective, provenance, uniqueIssues, classification);
2272
+ return this.#buildState(library, uniqueIssues, classification);
2608
2273
  }
2609
2274
  #canAutoReconcile(classification, retry = false) {
2610
2275
  return classification.complete && classification.blockers.length === 0 && classification.moves.length + classification.deletions.length > 0 && (!retry || classification.edited.length === 0 && classification.unmanaged.length === 0);
@@ -2693,59 +2358,6 @@ var FundusOperations = class {
2693
2358
  #requireAsset(library, id) {
2694
2359
  if (!Object.hasOwn(library.assets, id)) throw new Error(`Unknown asset "${id}".`);
2695
2360
  }
2696
- /** Merge the configured Packages under the host library (host wins). */
2697
- #effectiveOf(host) {
2698
- const { library, provenance, findings } = mergePackages(host, this.#config.packages ?? []);
2699
- return {
2700
- effective: library,
2701
- provenance,
2702
- mergeFindings: findings
2703
- };
2704
- }
2705
- /**
2706
- * The Package base record for `id` when `id` is a read-only Package asset the
2707
- * host has not yet filled — i.e. this create is a *slot fill*. Returns null
2708
- * for a plain new host asset.
2709
- */
2710
- #packageBase(host, id) {
2711
- if (Object.hasOwn(host.assets, id)) return null;
2712
- const { effective, provenance } = this.#effectiveOf(host);
2713
- if (provenance[id]?.source === "package") return { type: effective.assets[id].type };
2714
- return null;
2715
- }
2716
- /**
2717
- * Flat-space validation over the effective library: merge errors, id/type/
2718
- * parameter/membership/appearance/reference checks, module collisions, and
2719
- * delivered-slot findings. Disk/host checks stay in `store.validate(host,
2720
- * { flatSpace: false })`.
2721
- */
2722
- #flatIssues(effective, provenance, mergeFindings) {
2723
- const membership = computeLibraryMembership(effective, collectAllReferences(effective, descriptorsByType(this.#registry)));
2724
- return [
2725
- ...mergeFindings.filter((finding) => finding.kind !== "package-overridden").map((finding) => ({
2726
- assetId: finding.assetId,
2727
- message: finding.message
2728
- })),
2729
- ...flatLibraryIssues(effective, descriptorsByType(this.#registry)),
2730
- ...manifestModuleCollisionIssues(effective.manifests),
2731
- ...packageSlotFindings(effective, provenance, membership).map((finding) => ({
2732
- assetId: finding.assetId,
2733
- message: finding.message
2734
- }))
2735
- ];
2736
- }
2737
- /**
2738
- * Whether an id is a read-only Package asset the host has not overridden.
2739
- * Such ids can be filled/overridden (write a host record) but not mutated,
2740
- * renamed, moved, or deleted in place.
2741
- */
2742
- #assertHostAsset(host, id, action) {
2743
- if (Object.hasOwn(host.assets, id)) return;
2744
- const { provenance } = this.#effectiveOf(host);
2745
- const prov = provenance[id];
2746
- 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.`);
2747
- throw new Error(`Unknown asset "${id}".`);
2748
- }
2749
2361
  /**
2750
2362
  * Apply a CLI asset change to the store, validating the resulting library
2751
2363
  * on an in-memory candidate first — nothing is persisted when the change
@@ -2794,4 +2406,4 @@ async function createFundusContext() {
2794
2406
  }
2795
2407
 
2796
2408
  export { getFundusContext as g, initializeFundusContext as i };
2797
- //# sourceMappingURL=context.js-Dh0ibRIF.js.map
2409
+ //# sourceMappingURL=context.js-BIgcUcEl.js.map