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.
- package/README.md +121 -0
- package/build/client/_app/immutable/assets/2.X44Wyac-.css +1 -0
- package/build/client/_app/immutable/assets/2.X44Wyac-.css.br +0 -0
- package/build/client/_app/immutable/assets/2.X44Wyac-.css.gz +0 -0
- package/build/client/_app/immutable/assets/{3.C6xo25uI.css → 3.66PJT3JC.css} +1 -1
- package/build/client/_app/immutable/assets/3.66PJT3JC.css.br +0 -0
- package/build/client/_app/immutable/assets/3.66PJT3JC.css.gz +0 -0
- package/build/client/_app/immutable/assets/{AssetSourceMenu.IjDdjx3o.css → AssetSourceMenu.B5fzYfym.css} +1 -1
- package/build/client/_app/immutable/assets/AssetSourceMenu.B5fzYfym.css.br +0 -0
- package/build/client/_app/immutable/assets/AssetSourceMenu.B5fzYfym.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B06eqbax.js +108 -0
- package/build/client/_app/immutable/chunks/B06eqbax.js.br +0 -0
- package/build/client/_app/immutable/chunks/B06eqbax.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{dNO-9VOT.js → B97y-eFA.js} +1 -1
- package/build/client/_app/immutable/chunks/B97y-eFA.js.br +0 -0
- package/build/client/_app/immutable/chunks/B97y-eFA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BmOjTxFk.js +1 -0
- package/build/client/_app/immutable/chunks/BmOjTxFk.js.br +0 -0
- package/build/client/_app/immutable/chunks/BmOjTxFk.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C9MzfQz6.js +2 -0
- package/build/client/_app/immutable/chunks/C9MzfQz6.js.br +0 -0
- package/build/client/_app/immutable/chunks/C9MzfQz6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CcuyGBqj.js +1 -0
- package/build/client/_app/immutable/chunks/CcuyGBqj.js.br +0 -0
- package/build/client/_app/immutable/chunks/CcuyGBqj.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{77p2oEJ1.js → D6c2mfMB.js} +1 -1
- package/build/client/_app/immutable/chunks/D6c2mfMB.js.br +2 -0
- package/build/client/_app/immutable/chunks/D6c2mfMB.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DY9QjkXW.js +1 -0
- package/build/client/_app/immutable/chunks/DY9QjkXW.js.br +0 -0
- package/build/client/_app/immutable/chunks/DY9QjkXW.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Z8rcWjXZ.js +3 -0
- package/build/client/_app/immutable/chunks/Z8rcWjXZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/Z8rcWjXZ.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.V1MmmICK.js +2 -0
- package/build/client/_app/immutable/entry/app.V1MmmICK.js.br +0 -0
- package/build/client/_app/immutable/entry/app.V1MmmICK.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BbyflZUw.js +1 -0
- package/build/client/_app/immutable/entry/start.BbyflZUw.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BbyflZUw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.BJOUVkow.js +1 -0
- package/build/client/_app/immutable/nodes/0.BJOUVkow.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.BJOUVkow.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.BqoPRvUU.js +1 -0
- package/build/client/_app/immutable/nodes/1.BqoPRvUU.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.BqoPRvUU.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.BSUVFDfW.js +3 -0
- package/build/client/_app/immutable/nodes/2.BSUVFDfW.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.BSUVFDfW.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.B6beFiTQ.js +1 -0
- package/build/client/_app/immutable/nodes/3.B6beFiTQ.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.B6beFiTQ.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.Dt96q8V4.js +2 -0
- package/build/client/_app/immutable/nodes/4.Dt96q8V4.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.Dt96q8V4.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/handler.js +8 -7
- package/build/handler.js.map +1 -1
- package/build/index.js +8 -7
- package/build/index.js.map +1 -1
- package/build/server/chunks/chunks/{context.js-CVuTSPjH.js → context.js-BXaBgcZT.js} +627 -134
- package/build/server/chunks/chunks/context.js-BXaBgcZT.js.map +1 -0
- package/build/server/chunks/chunks/{contract.js-itFN0Gon.js → contract.js-IY1F-HE_.js} +94 -58
- package/build/server/chunks/chunks/contract.js-IY1F-HE_.js.map +1 -0
- package/build/server/chunks/chunks/{core.js-CABVXpby.js → core.js-D1sYC_78.js} +144 -143
- package/build/server/chunks/chunks/core.js-D1sYC_78.js.map +1 -0
- package/build/server/chunks/chunks/{exports.js-B13PkE0J.js → exports.js-B5DLeNXr.js} +2 -2
- package/build/server/chunks/chunks/{exports.js-B13PkE0J.js.map → exports.js-B5DLeNXr.js.map} +1 -1
- package/build/server/chunks/chunks/{http.js-ChQRRKfZ.js → http.js-CzB9Igb0.js} +2 -2
- package/build/server/chunks/chunks/{http.js-ChQRRKfZ.js.map → http.js-CzB9Igb0.js.map} +1 -1
- package/build/server/chunks/chunks/{internal.js-DlKoWKM-.js → internal.js-HE35Pm1C.js} +5 -3
- package/build/server/chunks/chunks/internal.js-HE35Pm1C.js.map +1 -0
- package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
- package/build/server/chunks/chunks/{manifest-membership.js-BnSECWpJ.js → manifest-membership.js-Cm_2fU-Z.js} +2 -2
- package/build/server/chunks/chunks/{manifest-membership.js-BnSECWpJ.js.map → manifest-membership.js-Cm_2fU-Z.js.map} +1 -1
- package/build/server/chunks/chunks/{raw-reconciliation.js-ZEOCk_jA.js → raw-reconciliation.js-1_IwPhKb.js} +3 -3
- package/build/server/chunks/chunks/raw-reconciliation.js-1_IwPhKb.js.map +1 -0
- package/build/server/chunks/chunks/{raw-reconciliation2.js-CscuoBC2.js → raw-reconciliation2.js-CcO9li5n.js} +2 -2
- package/build/server/chunks/chunks/{raw-reconciliation2.js-CscuoBC2.js.map → raw-reconciliation2.js-CcO9li5n.js.map} +1 -1
- package/build/server/chunks/chunks/{shared.js-DKt4pwWi.js → shared.js-MR8sPPTu.js} +2 -2
- package/build/server/chunks/chunks/{shared.js-DKt4pwWi.js.map → shared.js-MR8sPPTu.js.map} +1 -1
- package/build/server/chunks/chunks/{utils.js-BYMC-4Wt.js → utils.js-C2UFBITa.js} +3 -3
- package/build/server/chunks/chunks/{utils.js-BYMC-4Wt.js.map → utils.js-C2UFBITa.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-z988EDp2.js → _server.ts.js-BnRJ5Qnd.js} +6 -6
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-z988EDp2.js.map → _server.ts.js-BnRJ5Qnd.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-C68ru6gS.js → _server.ts.js-BZPR6n5n.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-C68ru6gS.js.map → _server.ts.js-BZPR6n5n.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-C0tk6RFk.js → _server.ts.js-DiBS3A0C.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-C0tk6RFk.js.map → _server.ts.js-DiBS3A0C.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-I03oZuo8.js → _server.ts.js-LOO6qm2-.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-I03oZuo8.js.map → _server.ts.js-LOO6qm2-.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-BsQB8YDq.js → _server.ts.js-CRtJJoSs.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-BsQB8YDq.js.map → _server.ts.js-CRtJJoSs.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-CJuFE6Fb.js → _server.ts.js-Ds4zCZ9H.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-CJuFE6Fb.js.map → _server.ts.js-Ds4zCZ9H.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DuOZRRiA.js → _server.ts.js-DD4N8pcj.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DuOZRRiA.js.map → _server.ts.js-DD4N8pcj.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-DGzYpQbv.js → _server.ts.js-CZev9aYz.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-DGzYpQbv.js.map → _server.ts.js-CZev9aYz.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-B045QoCA.js → _server.ts.js-MBDVW0q1.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-B045QoCA.js.map → _server.ts.js-MBDVW0q1.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-HUkVdz19.js → _server.ts.js-C7naXnsR.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-HUkVdz19.js.map → _server.ts.js-C7naXnsR.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-ry509mom.js → _server.ts.js-DuGyRdf3.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-ry509mom.js.map → _server.ts.js-DuGyRdf3.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-DU0J7U25.js → _server.ts.js-0-ZCt0qH.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-DU0J7U25.js.map → _server.ts.js-0-ZCt0qH.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-AZIV2PIn.js → _server.ts.js-DFYU_sZL.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-AZIV2PIn.js.map → _server.ts.js-DFYU_sZL.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CDL0hCfM.js → _server.ts.js-BqJpK0sJ.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CDL0hCfM.js.map → _server.ts.js-BqJpK0sJ.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-B13c17fq.js → _server.ts.js--LSqADJp.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-B13c17fq.js.map → _server.ts.js--LSqADJp.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-BCxjyAGC.js → _server.ts.js-DcL8nYDM.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-BCxjyAGC.js.map → _server.ts.js-DcL8nYDM.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-BveeMZc2.js → _server.ts.js-72OcyLfP.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-BveeMZc2.js.map → _server.ts.js-72OcyLfP.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-BZjTd9a0.js → _server.ts.js-D0bOxmG0.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-BZjTd9a0.js.map → _server.ts.js-D0bOxmG0.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-BbTfPvC9.js → _server.ts.js-BjDVCRNV.js} +9 -7
- package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-BbTfPvC9.js.map → _server.ts.js-BjDVCRNV.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-8VPJMLBk.js → _server.ts.js-CndfoXXd.js} +6 -6
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-8VPJMLBk.js.map → _server.ts.js-CndfoXXd.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-BqR2J2sB.js → _server.ts.js-Ck1mgbk5.js} +9 -7
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-BqR2J2sB.js.map → _server.ts.js-Ck1mgbk5.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-DbA28dCY.js → _server.ts.js-lZ9oP8tz.js} +9 -7
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-DbA28dCY.js.map → _server.ts.js-lZ9oP8tz.js.map} +1 -1
- package/build/server/chunks/entries/{hooks.server.js-9PBc_3Jh.js → hooks.server.js-DQ6l2RSK.js} +8 -6
- package/build/server/chunks/entries/{hooks.server.js-9PBc_3Jh.js.map → hooks.server.js-DQ6l2RSK.js.map} +1 -1
- package/build/server/chunks/{handler-XxBNCHhb.js → handler-Dfk_4a-r.js} +5 -5
- package/build/server/chunks/{handler-XxBNCHhb.js.map → handler-Dfk_4a-r.js.map} +1 -1
- package/build/server/chunks/{index.js-B_76Gq5Y.js → index.js-O3Wl1zok.js} +5 -5
- package/build/server/chunks/{index.js-B_76Gq5Y.js.map → index.js-O3Wl1zok.js.map} +1 -1
- package/build/server/chunks/{manifest.js-C2MZZt3o.js → manifest.js-51nEZnKQ.js} +29 -29
- package/build/server/chunks/{manifest.js-C2MZZt3o.js.map → manifest.js-51nEZnKQ.js.map} +1 -1
- package/build/server/chunks/nodes/{0.js-BLURyWmd.js → 0.js-DjqMfDtB.js} +2 -2
- package/build/server/chunks/nodes/{0.js-BLURyWmd.js.map → 0.js-DjqMfDtB.js.map} +1 -1
- package/build/server/chunks/nodes/1.js-BwfSLYJH.js +7 -0
- package/build/server/chunks/nodes/{1.js-CITI7d3d.js.map → 1.js-BwfSLYJH.js.map} +1 -1
- package/build/server/chunks/nodes/2.js-buHbEytf.js +7 -0
- package/build/server/chunks/nodes/2.js-buHbEytf.js.map +1 -0
- package/build/server/chunks/nodes/3.js-D7_hF0qp.js +7 -0
- package/build/server/chunks/nodes/3.js-D7_hF0qp.js.map +1 -0
- package/build/server/chunks/nodes/4.js-D58M2chZ.js +7 -0
- package/build/server/chunks/nodes/{4.js-BRlAiVnn.js.map → 4.js-D58M2chZ.js.map} +1 -1
- package/dist/config.d.ts +3 -3
- package/dist/config.js +2 -2
- package/dist/core/api-types.d.ts +22 -2
- package/dist/core/config.d.ts +82 -0
- package/dist/core/config.js +9 -0
- package/dist/core/index.d.ts +10 -5
- package/dist/core/index.js +5 -2
- package/dist/core/library-validation.d.ts +13 -0
- package/dist/core/library-validation.js +48 -0
- package/dist/core/library.d.ts +19 -0
- package/dist/core/library.js +4 -4
- package/dist/core/manifest-membership.d.ts +2 -2
- package/dist/core/package-declaration.d.ts +43 -0
- package/dist/core/package-declaration.js +80 -0
- package/dist/core/package-merge.d.ts +65 -0
- package/dist/core/package-merge.js +173 -0
- package/dist/core/reference-graph.d.ts +3 -3
- package/dist/runtime/components/Image.svelte +5 -6
- package/dist/runtime/components/Image.svelte.d.ts +2 -3
- package/dist/server/build.js +26 -11
- package/dist/server/check.d.ts +13 -3
- package/dist/server/check.js +112 -24
- package/dist/server/codegen.d.ts +3 -1
- package/dist/server/codegen.js +18 -0
- package/dist/server/config-loader.d.ts +35 -1
- package/dist/server/config-loader.js +185 -4
- package/dist/server/library-store.d.ts +11 -1
- package/dist/server/library-store.js +42 -60
- package/dist/server/operations.js +162 -47
- package/package.json +1 -1
- package/build/client/_app/immutable/assets/2.C-1MfvLQ.css +0 -1
- package/build/client/_app/immutable/assets/2.C-1MfvLQ.css.br +0 -0
- package/build/client/_app/immutable/assets/2.C-1MfvLQ.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.C6xo25uI.css.br +0 -0
- package/build/client/_app/immutable/assets/3.C6xo25uI.css.gz +0 -0
- package/build/client/_app/immutable/assets/AssetSourceMenu.IjDdjx3o.css.br +0 -0
- package/build/client/_app/immutable/assets/AssetSourceMenu.IjDdjx3o.css.gz +0 -0
- package/build/client/_app/immutable/chunks/77p2oEJ1.js.br +0 -0
- package/build/client/_app/immutable/chunks/77p2oEJ1.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B9HdDE5n.js +0 -1
- package/build/client/_app/immutable/chunks/B9HdDE5n.js.br +0 -0
- package/build/client/_app/immutable/chunks/B9HdDE5n.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B_PWcB6g.js +0 -108
- package/build/client/_app/immutable/chunks/B_PWcB6g.js.br +0 -0
- package/build/client/_app/immutable/chunks/B_PWcB6g.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Q50krHyn.js +0 -2
- package/build/client/_app/immutable/chunks/Q50krHyn.js.br +0 -0
- package/build/client/_app/immutable/chunks/Q50krHyn.js.gz +0 -0
- package/build/client/_app/immutable/chunks/RgXSPQ_h.js +0 -1
- package/build/client/_app/immutable/chunks/RgXSPQ_h.js.br +0 -0
- package/build/client/_app/immutable/chunks/RgXSPQ_h.js.gz +0 -0
- package/build/client/_app/immutable/chunks/YpiA5Xry.js +0 -3
- package/build/client/_app/immutable/chunks/YpiA5Xry.js.br +0 -0
- package/build/client/_app/immutable/chunks/YpiA5Xry.js.gz +0 -0
- package/build/client/_app/immutable/chunks/dNO-9VOT.js.br +0 -0
- package/build/client/_app/immutable/chunks/dNO-9VOT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/hUfV2O0k.js +0 -1
- package/build/client/_app/immutable/chunks/hUfV2O0k.js.br +0 -0
- package/build/client/_app/immutable/chunks/hUfV2O0k.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.BsvwTApt.js +0 -2
- package/build/client/_app/immutable/entry/app.BsvwTApt.js.br +0 -0
- package/build/client/_app/immutable/entry/app.BsvwTApt.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BdjLMMsY.js +0 -1
- package/build/client/_app/immutable/entry/start.BdjLMMsY.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BdjLMMsY.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CjQfQrD6.js +0 -1
- package/build/client/_app/immutable/nodes/0.CjQfQrD6.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CjQfQrD6.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.DyPcUKIh.js +0 -1
- package/build/client/_app/immutable/nodes/1.DyPcUKIh.js.br +0 -2
- package/build/client/_app/immutable/nodes/1.DyPcUKIh.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.CworwA2R.js +0 -3
- package/build/client/_app/immutable/nodes/2.CworwA2R.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CworwA2R.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.BKqbML1T.js +0 -1
- package/build/client/_app/immutable/nodes/3.BKqbML1T.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.BKqbML1T.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.Cmigd8CT.js +0 -2
- package/build/client/_app/immutable/nodes/4.Cmigd8CT.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.Cmigd8CT.js.gz +0 -0
- package/build/server/chunks/chunks/context.js-CVuTSPjH.js.map +0 -1
- package/build/server/chunks/chunks/contract.js-itFN0Gon.js.map +0 -1
- package/build/server/chunks/chunks/core.js-CABVXpby.js.map +0 -1
- package/build/server/chunks/chunks/internal.js-DlKoWKM-.js.map +0 -1
- package/build/server/chunks/chunks/raw-reconciliation.js-ZEOCk_jA.js.map +0 -1
- package/build/server/chunks/nodes/1.js-CITI7d3d.js +0 -7
- package/build/server/chunks/nodes/2.js-DAls5TjF.js +0 -7
- package/build/server/chunks/nodes/2.js-DAls5TjF.js.map +0 -1
- package/build/server/chunks/nodes/3.js-CesAmg_E.js +0 -7
- package/build/server/chunks/nodes/3.js-CesAmg_E.js.map +0 -1
- 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-
|
|
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,
|
|
3
|
-
import { c as collectAllReferences, a as assetIdError, b as computeLibraryMembership, d as allDeliveredAssetIds } from './manifest-membership.js-
|
|
4
|
-
import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation2.js-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.#
|
|
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
|
|
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,
|
|
1842
|
-
await generateManifestModules(this.#config,
|
|
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,
|
|
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(
|
|
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
|
|
1901
|
-
folder: folderOfRawPath(
|
|
1902
|
-
rawUrl: `/files/raw/${encodeRelativePathForUrl(
|
|
1903
|
-
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(
|
|
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-
|
|
2608
|
+
//# sourceMappingURL=context.js-BXaBgcZT.js.map
|