fundus 0.2.0 → 0.4.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 +67 -2
- package/build/client/_app/immutable/assets/2.B5tQm8hR.css +1 -0
- package/build/client/_app/immutable/assets/2.B5tQm8hR.css.br +0 -0
- package/build/client/_app/immutable/assets/2.B5tQm8hR.css.gz +0 -0
- package/build/client/_app/immutable/assets/{3.ChSpCG-T.css → 3.CmXD8k9d.css} +1 -1
- package/build/client/_app/immutable/assets/3.CmXD8k9d.css.br +0 -0
- package/build/client/_app/immutable/assets/3.CmXD8k9d.css.gz +0 -0
- package/build/client/_app/immutable/assets/{LibraryContextMenu.BYvU4SY7.css → LibraryContextMenu.CVb-Lqdf.css} +1 -1
- package/build/client/_app/immutable/assets/LibraryContextMenu.CVb-Lqdf.css.br +0 -0
- package/build/client/_app/immutable/assets/{LibraryContextMenu.BYvU4SY7.css.gz → LibraryContextMenu.CVb-Lqdf.css.gz} +0 -0
- package/build/client/_app/immutable/chunks/{C8W3KwDq.js → BPiGyn-T.js} +1 -1
- package/build/client/_app/immutable/chunks/BPiGyn-T.js.br +0 -0
- package/build/client/_app/immutable/chunks/BPiGyn-T.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CP-bnOxU.js → BoEHtxM8.js} +1 -1
- package/build/client/_app/immutable/chunks/BoEHtxM8.js.br +0 -0
- package/build/client/_app/immutable/chunks/BoEHtxM8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C-T1_s5P.js +1 -0
- package/build/client/_app/immutable/chunks/C-T1_s5P.js.br +0 -0
- package/build/client/_app/immutable/chunks/C-T1_s5P.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{ByVSyIj7.js → CeJsL6hj.js} +1 -1
- package/build/client/_app/immutable/chunks/CeJsL6hj.js.br +0 -0
- package/build/client/_app/immutable/chunks/CeJsL6hj.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Db8LRH6X.js → Cq4Yaq35.js} +3 -3
- package/build/client/_app/immutable/chunks/Cq4Yaq35.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cq4Yaq35.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D5sQSsUv.js +1 -0
- package/build/client/_app/immutable/chunks/D5sQSsUv.js.br +0 -0
- package/build/client/_app/immutable/chunks/D5sQSsUv.js.gz +0 -0
- package/build/client/_app/immutable/entry/{app.nM6SgHKJ.js → app.BQ4TfPHG.js} +2 -2
- package/build/client/_app/immutable/entry/app.BQ4TfPHG.js.br +0 -0
- package/build/client/_app/immutable/entry/app.BQ4TfPHG.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.COP9tIRH.js +1 -0
- package/build/client/_app/immutable/entry/start.COP9tIRH.js.br +0 -0
- package/build/client/_app/immutable/entry/start.COP9tIRH.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CftchwYV.js +2 -0
- package/build/client/_app/immutable/nodes/0.CftchwYV.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CftchwYV.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{1.dMklHTc2.js → 1.C8DOqctV.js} +1 -1
- package/build/client/_app/immutable/nodes/1.C8DOqctV.js.br +1 -0
- package/build/client/_app/immutable/nodes/1.C8DOqctV.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.BR8OVsS9.js +3 -0
- package/build/client/_app/immutable/nodes/2.BR8OVsS9.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.BR8OVsS9.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.BO5hcxIH.js +1 -0
- package/build/client/_app/immutable/nodes/3.BO5hcxIH.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.BO5hcxIH.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{4.Dgxx52FJ.js → 4.DTaH-k-c.js} +1 -1
- package/build/client/_app/immutable/nodes/4.DTaH-k-c.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.DTaH-k-c.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 +7 -7
- package/build/index.js +7 -7
- package/build/server/chunks/chunks/asset-id.js-CFsW8jeL.js +48 -0
- package/build/server/chunks/chunks/asset-id.js-CFsW8jeL.js.map +1 -0
- package/build/server/chunks/chunks/{context.js-B77ZAVLi.js → context.js-CG2t-ufq.js} +568 -25
- package/build/server/chunks/chunks/context.js-CG2t-ufq.js.map +1 -0
- package/build/server/chunks/chunks/{library-store.js-DJ-JRE-g.js → contract.js-sHny3b-s.js} +133 -359
- package/build/server/chunks/chunks/contract.js-sHny3b-s.js.map +1 -0
- package/build/server/chunks/chunks/{core.js-EA_ysb1J.js → core.js-Clg1CHb6.js} +2 -48
- package/build/server/chunks/chunks/core.js-Clg1CHb6.js.map +1 -0
- package/build/server/chunks/chunks/{exports.js-DvhE7Ffd.js → exports.js-rOfFZumP.js} +2 -2
- package/build/server/chunks/chunks/{exports.js-DvhE7Ffd.js.map → exports.js-rOfFZumP.js.map} +1 -1
- package/build/server/chunks/chunks/{http.js-DyoR9XRI.js → http.js--6sDZFfm.js} +35 -3
- package/build/server/chunks/chunks/http.js--6sDZFfm.js.map +1 -0
- package/build/server/chunks/chunks/{internal.js-Dn37LrAW.js → internal.js-DnveDsYn.js} +3 -3
- package/build/server/chunks/chunks/{internal.js-Dn37LrAW.js.map → internal.js-DnveDsYn.js.map} +1 -1
- package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
- package/build/server/chunks/chunks/raw-reconciliation.js-DOFtjkgu.js +343 -0
- package/build/server/chunks/chunks/raw-reconciliation.js-DOFtjkgu.js.map +1 -0
- package/build/server/chunks/chunks/raw-reconciliation2.js-DFwky2ou.js +11 -0
- package/build/server/chunks/chunks/raw-reconciliation2.js-DFwky2ou.js.map +1 -0
- package/build/server/chunks/chunks/{shared.js-Dob0TlTu.js → shared.js-DtvIbMLj.js} +2 -2
- package/build/server/chunks/chunks/{shared.js-Dob0TlTu.js.map → shared.js-DtvIbMLj.js.map} +1 -1
- package/build/server/chunks/chunks/{utils.js-B4YimMxv.js → utils.js-bP1j9RdM.js} +3 -3
- package/build/server/chunks/chunks/{utils.js-B4YimMxv.js.map → utils.js-bP1j9RdM.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-H4Pq1KAE.js → _server.ts.js-CkSErIdC.js} +7 -5
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-H4Pq1KAE.js.map → _server.ts.js-CkSErIdC.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-BI3KHSfE.js → _server.ts.js-BfdsBPWo.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-BI3KHSfE.js.map → _server.ts.js-BfdsBPWo.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-BlNYUbXX.js → _server.ts.js-D0aKDq87.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-BlNYUbXX.js.map → _server.ts.js-D0aKDq87.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/_server.ts.js-DsX_m2gc.js +31 -0
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/_server.ts.js-DsX_m2gc.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-j-_N540j.js → _server.ts.js-nfThjRxs.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-j-_N540j.js.map → _server.ts.js-nfThjRxs.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-BHKobzAg.js → _server.ts.js-CseHmsYB.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-BHKobzAg.js.map → _server.ts.js-CseHmsYB.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-BFKjIOCv.js → _server.ts.js-CHiICsyC.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-BFKjIOCv.js.map → _server.ts.js-CHiICsyC.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-BxZeVw8y.js → _server.ts.js-Dgf46K5u.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-BxZeVw8y.js.map → _server.ts.js-Dgf46K5u.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-CO36U_CT.js → _server.ts.js-DwQJUZFa.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-CO36U_CT.js.map → _server.ts.js-DwQJUZFa.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/imports/_server.ts.js-BnKS8nVF.js +37 -0
- package/build/server/chunks/entries/endpoints/api/imports/_server.ts.js-BnKS8nVF.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-CBlg1Bkl.js → _server.ts.js-BrDbLcyO.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-CBlg1Bkl.js.map → _server.ts.js-BrDbLcyO.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-DcGLCjIs.js → _server.ts.js-DIUiQuyd.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-DcGLCjIs.js.map → _server.ts.js-DIUiQuyd.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-AqhtjOiL.js → _server.ts.js-BrReStaf.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-AqhtjOiL.js.map → _server.ts.js-BrReStaf.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CSa6-DcU.js → _server.ts.js-B31iGwJ-.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-CSa6-DcU.js.map → _server.ts.js-B31iGwJ-.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-DnzZUoAo.js → _server.ts.js-DeZQFNdj.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-DnzZUoAo.js.map → _server.ts.js-DeZQFNdj.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-B0KMprKq.js → _server.ts.js-DhDhUU7V.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-B0KMprKq.js.map → _server.ts.js-DhDhUU7V.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reveal/_server.ts.js-DGkPIMcq.js +80 -0
- package/build/server/chunks/entries/endpoints/api/reveal/_server.ts.js-DGkPIMcq.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-B1N9o1Ne.js → _server.ts.js-BTQgWDH1.js} +11 -6
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-B1N9o1Ne.js.map → _server.ts.js-BTQgWDH1.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-B6HbnRqq.js → _server.ts.js-DB3i4juR.js} +7 -5
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-B6HbnRqq.js.map → _server.ts.js-DB3i4juR.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-7wzPyG9v.js → _server.ts.js-kmc-gejQ.js} +11 -6
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-7wzPyG9v.js.map → _server.ts.js-kmc-gejQ.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-BWztxYge.js → _server.ts.js-B8EE1DD9.js} +11 -6
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-BWztxYge.js.map → _server.ts.js-B8EE1DD9.js.map} +1 -1
- package/build/server/chunks/entries/{hooks.server.js-CVKLksJ1.js → hooks.server.js-DbBA5yYQ.js} +10 -5
- package/build/server/chunks/entries/{hooks.server.js-CVKLksJ1.js.map → hooks.server.js-DbBA5yYQ.js.map} +1 -1
- package/build/server/chunks/{handler-DZ2Sps4a.js → handler-J6aKdov3.js} +5 -5
- package/build/server/chunks/{handler-DZ2Sps4a.js.map → handler-J6aKdov3.js.map} +1 -1
- package/build/server/chunks/{index.js-CdmTWQz8.js → index.js-CsvWJ7Qu.js} +5 -5
- package/build/server/chunks/{index.js-CdmTWQz8.js.map → index.js-CsvWJ7Qu.js.map} +1 -1
- package/build/server/chunks/{manifest.js-GhfNr35x.js → manifest.js-wHtZ9vlA.js} +46 -25
- package/build/server/chunks/manifest.js-wHtZ9vlA.js.map +1 -0
- package/build/server/chunks/nodes/0.js-By6-kbk6.js +11 -0
- package/build/server/chunks/nodes/0.js-By6-kbk6.js.map +1 -0
- package/build/server/chunks/nodes/1.js-CrPfmKpN.js +7 -0
- package/build/server/chunks/nodes/{1.js-DQgYreU0.js.map → 1.js-CrPfmKpN.js.map} +1 -1
- package/build/server/chunks/nodes/2.js-C-i3Y5t2.js +7 -0
- package/build/server/chunks/nodes/2.js-C-i3Y5t2.js.map +1 -0
- package/build/server/chunks/nodes/3.js-C1gcIGeV.js +7 -0
- package/build/server/chunks/nodes/3.js-C1gcIGeV.js.map +1 -0
- package/build/server/chunks/nodes/4.js-tgwl3VD3.js +7 -0
- package/build/server/chunks/nodes/{4.js-BebbMVXy.js.map → 4.js-tgwl3VD3.js.map} +1 -1
- package/dist/cli.js +2 -0
- package/dist/config.d.ts +1 -1
- package/dist/core/api-types.d.ts +12 -1
- package/dist/core/config.d.ts +12 -0
- package/dist/core/index.d.ts +3 -2
- package/dist/core/library.d.ts +8 -1
- package/dist/core/library.js +30 -6
- package/dist/server/cli-commands.d.ts +2 -1
- package/dist/server/cli-commands.js +155 -34
- package/dist/server/config-loader.d.ts +9 -1
- package/dist/server/config-loader.js +26 -1
- package/dist/server/file-manager.d.ts +2 -0
- package/dist/server/file-manager.js +17 -0
- package/dist/server/http.d.ts +1 -0
- package/dist/server/http.js +37 -0
- package/dist/server/importers/contract.d.ts +29 -0
- package/dist/server/importers/contract.js +13 -0
- package/dist/server/importers/figma.d.ts +21 -0
- package/dist/server/importers/figma.js +386 -0
- package/dist/server/importers/file.d.ts +6 -0
- package/dist/server/importers/file.js +33 -0
- package/dist/server/importers/pinned-https.d.ts +23 -0
- package/dist/server/importers/pinned-https.js +60 -0
- package/dist/server/importers/registry.d.ts +12 -0
- package/dist/server/importers/registry.js +31 -0
- package/dist/server/importers.d.ts +2 -0
- package/dist/server/importers.js +7 -0
- package/dist/server/library-store.d.ts +19 -1
- package/dist/server/library-store.js +110 -14
- package/dist/server/operations.d.ts +13 -1
- package/dist/server/operations.js +159 -23
- package/package.json +1 -1
- package/build/client/_app/immutable/assets/2.ohi-TClG.css +0 -1
- package/build/client/_app/immutable/assets/2.ohi-TClG.css.br +0 -0
- package/build/client/_app/immutable/assets/2.ohi-TClG.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.ChSpCG-T.css.br +0 -0
- package/build/client/_app/immutable/assets/3.ChSpCG-T.css.gz +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.BYvU4SY7.css.br +0 -0
- package/build/client/_app/immutable/chunks/BAEZPv6c.js +0 -1
- package/build/client/_app/immutable/chunks/BAEZPv6c.js.br +0 -0
- package/build/client/_app/immutable/chunks/BAEZPv6c.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ByVSyIj7.js.br +0 -1
- package/build/client/_app/immutable/chunks/ByVSyIj7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/C8W3KwDq.js.br +0 -0
- package/build/client/_app/immutable/chunks/C8W3KwDq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CP-bnOxU.js.br +0 -0
- package/build/client/_app/immutable/chunks/CP-bnOxU.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Db8LRH6X.js.br +0 -0
- package/build/client/_app/immutable/chunks/Db8LRH6X.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.nM6SgHKJ.js.br +0 -0
- package/build/client/_app/immutable/entry/app.nM6SgHKJ.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.DNXvkhtP.js +0 -1
- package/build/client/_app/immutable/entry/start.DNXvkhtP.js.br +0 -0
- package/build/client/_app/immutable/entry/start.DNXvkhtP.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.QeXQNCp2.js +0 -2
- package/build/client/_app/immutable/nodes/0.QeXQNCp2.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.QeXQNCp2.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.dMklHTc2.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.dMklHTc2.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.CW4VMcIP.js +0 -3
- package/build/client/_app/immutable/nodes/2.CW4VMcIP.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CW4VMcIP.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.CTiY_pbK.js +0 -1
- package/build/client/_app/immutable/nodes/3.CTiY_pbK.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.CTiY_pbK.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.Dgxx52FJ.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.Dgxx52FJ.js.gz +0 -0
- package/build/server/chunks/chunks/context.js-B77ZAVLi.js.map +0 -1
- package/build/server/chunks/chunks/core.js-EA_ysb1J.js.map +0 -1
- package/build/server/chunks/chunks/http.js-DyoR9XRI.js.map +0 -1
- package/build/server/chunks/chunks/library-store.js-DJ-JRE-g.js.map +0 -1
- package/build/server/chunks/manifest.js-GhfNr35x.js.map +0 -1
- package/build/server/chunks/nodes/0.js-DGT86_i-.js +0 -11
- package/build/server/chunks/nodes/0.js-DGT86_i-.js.map +0 -1
- package/build/server/chunks/nodes/1.js-DQgYreU0.js +0 -7
- package/build/server/chunks/nodes/2.js-DItreSrX.js +0 -7
- package/build/server/chunks/nodes/2.js-DItreSrX.js.map +0 -1
- package/build/server/chunks/nodes/3.js-bE1dJ_6v.js +0 -7
- package/build/server/chunks/nodes/3.js-bE1dJ_6v.js.map +0 -1
- package/build/server/chunks/nodes/4.js-BebbMVXy.js +0 -7
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as plugins, b as audioPlugin, c as chromaKeyVideoPlugin, v as videoPlugin, s as slicePlugin, d as imagePlugin, n as normalizeFolderPath, e as folderOfRawPath, g as rawFileNameOfPath, f as folderPathError, h as parentFolderPath, j as folderNameError, k as joinFolderPath, l as folderNameOf, m as isFolderOrDescendant, o as replaceFolderPrefix, q as portableFolderPathKey, t as defaultInsetsForSize, F as FOLDER_SENTINEL, r as rawFilePathError, u as isAssetReference, w as validateVideoPreset, V as VIDEO_BUILT_IN_PRESETS, x as validateAudioPreset, A as AUDIO_BUILT_IN_PRESETS, y as validateImagePreset, I as IMAGE_BUILT_IN_PRESETS, S as SLICE_BUILT_IN_PRESETS } from './core.js-Clg1CHb6.js';
|
|
2
|
+
import { a as assetIdError, m as manifestNameError } from './asset-id.js-CFsW8jeL.js';
|
|
2
3
|
import { m as manifestColorError, a as manifestEmojiError } from './manifest-appearance.js-DTk355LQ.js';
|
|
4
|
+
import { c as canonicalizeParameters, a as compareCodeUnits, v as verifyStableRawFile } from './raw-reconciliation.js-DOFtjkgu.js';
|
|
3
5
|
import { join, extname, dirname, basename, isAbsolute, resolve } from 'node:path';
|
|
4
|
-
import { existsSync
|
|
5
|
-
import { readFile, mkdir, writeFile, rename, unlink, rm, stat, readdir
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { readFile, mkdir, writeFile, rename, unlink, rm, stat, readdir } from 'node:fs/promises';
|
|
6
8
|
import ffmpegStaticPath from 'ffmpeg-static';
|
|
7
9
|
import { path } from 'ffprobe-static';
|
|
8
10
|
import { execFile } from 'node:child_process';
|
|
@@ -37,20 +39,32 @@ var DANGEROUS_KEYS = [
|
|
|
37
39
|
function assertSafeKey(kind, key) {
|
|
38
40
|
if (DANGEROUS_KEYS.includes(key)) throw new Error(`Library ${kind} key "${key}" is not allowed.`);
|
|
39
41
|
}
|
|
40
|
-
function
|
|
42
|
+
function parseImportSource(id, value) {
|
|
43
|
+
if (!isRecord$1(value)) throw new Error(`Library asset "${id}" has a non-object "importSource".`);
|
|
44
|
+
if (typeof value.importer !== "string" || value.importer.length === 0) throw new Error(`Library asset "${id}" has an invalid import source "importer".`);
|
|
45
|
+
if (!("parameters" in value)) throw new Error(`Library asset "${id}" import source is missing "parameters".`);
|
|
46
|
+
return {
|
|
47
|
+
importer: value.importer,
|
|
48
|
+
parameters: value.parameters
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function parseAssetRecord(id, value, version) {
|
|
41
52
|
if (!isRecord$1(value)) throw new Error(`Library asset "${id}" must be an object.`);
|
|
42
53
|
if (typeof value.type !== "string" || value.type.length === 0) throw new Error(`Library asset "${id}" is missing a string "type".`);
|
|
43
54
|
if (typeof value.raw !== "string" || value.raw.length === 0) throw new Error(`Library asset "${id}" is missing a string "raw" file name.`);
|
|
44
55
|
if (typeof value.rawHash !== "string" || value.rawHash.length === 0) throw new Error(`Library asset "${id}" is missing a string "rawHash".`);
|
|
45
56
|
if (!("parameters" in value)) throw new Error(`Library asset "${id}" is missing "parameters".`);
|
|
46
57
|
if (!Array.isArray(value.manifests) || value.manifests.some((entry) => typeof entry !== "string")) throw new Error(`Library asset "${id}" must have a "manifests" array of strings.`);
|
|
47
|
-
|
|
58
|
+
if (version === 1 && value.importSource !== void 0) throw new Error(`Library asset "${id}" uses "importSource", which requires library version 2.`);
|
|
59
|
+
const record = {
|
|
48
60
|
type: value.type,
|
|
49
61
|
raw: value.raw,
|
|
50
62
|
rawHash: value.rawHash,
|
|
51
63
|
parameters: value.parameters,
|
|
52
64
|
manifests: value.manifests
|
|
53
65
|
};
|
|
66
|
+
if (value.importSource !== void 0) record.importSource = parseImportSource(id, value.importSource);
|
|
67
|
+
return record;
|
|
54
68
|
}
|
|
55
69
|
function parseManifestRecord(name, value) {
|
|
56
70
|
const record = {};
|
|
@@ -77,7 +91,7 @@ function parseLibrary(json) {
|
|
|
77
91
|
throw new Error(`Library file is not valid JSON: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
78
92
|
}
|
|
79
93
|
if (!isRecord$1(value)) throw new Error("Library file must contain a JSON object.");
|
|
80
|
-
if (value.version !== 1) throw new Error(`Unsupported library version ${JSON.stringify(value.version)} (expected 1).`);
|
|
94
|
+
if (value.version !== 1 && value.version !== 2) throw new Error(`Unsupported library version ${JSON.stringify(value.version)} (expected 1 or 2).`);
|
|
81
95
|
if (!isRecord$1(value.assets)) throw new Error("Library \"assets\" must be an object.");
|
|
82
96
|
if (!isRecord$1(value.manifests)) throw new Error("Library \"manifests\" must be an object.");
|
|
83
97
|
if (value.folders !== void 0 && (!Array.isArray(value.folders) || value.folders.some((entry) => typeof entry !== "string"))) throw new Error("Library \"folders\" must be an array of strings.");
|
|
@@ -89,7 +103,7 @@ function parseLibrary(json) {
|
|
|
89
103
|
const assets = {};
|
|
90
104
|
for (const [id, record] of Object.entries(value.assets)) {
|
|
91
105
|
assertSafeKey("asset", id);
|
|
92
|
-
assets[id] = parseAssetRecord(id, record);
|
|
106
|
+
assets[id] = parseAssetRecord(id, record, value.version);
|
|
93
107
|
}
|
|
94
108
|
const manifests = {};
|
|
95
109
|
for (const [name, record] of Object.entries(value.manifests)) {
|
|
@@ -98,7 +112,7 @@ function parseLibrary(json) {
|
|
|
98
112
|
manifests[name] = parseManifestRecord(name, record);
|
|
99
113
|
}
|
|
100
114
|
return {
|
|
101
|
-
version:
|
|
115
|
+
version: value.version,
|
|
102
116
|
folders,
|
|
103
117
|
assets,
|
|
104
118
|
manifests
|
|
@@ -123,43 +137,16 @@ function sortValue(value) {
|
|
|
123
137
|
* insertion order was.
|
|
124
138
|
*/
|
|
125
139
|
function serializeLibrary(library) {
|
|
140
|
+
if (library.version === 1) {
|
|
141
|
+
const sourced = Object.entries(library.assets).find(([, record]) => record.importSource);
|
|
142
|
+
if (sourced) throw new Error(`Library asset "${sourced[0]}" uses "importSource", which requires library version 2.`);
|
|
143
|
+
}
|
|
126
144
|
return `${JSON.stringify(sortValue({
|
|
127
145
|
...library,
|
|
128
146
|
folders: [...library.folders].sort()
|
|
129
147
|
}), null, " ")}\n`;
|
|
130
148
|
}
|
|
131
149
|
//#endregion
|
|
132
|
-
//#region src/lib/core/canonicalize.ts
|
|
133
|
-
/**
|
|
134
|
-
* Stable JSON for hash inputs: recursively sorted keys, no whitespace,
|
|
135
|
-
* `undefined` object values dropped. Two parameter objects that differ only in
|
|
136
|
-
* key order (or in explicitly-undefined optionals) canonicalize identically,
|
|
137
|
-
* so the derived job hash — and thus the proxy file name — stays stable.
|
|
138
|
-
*/
|
|
139
|
-
function canonicalizeParameters(parameters) {
|
|
140
|
-
return stringify(parameters);
|
|
141
|
-
}
|
|
142
|
-
/** Deterministic UTF-16 code-unit ordering, independent of host locale. */
|
|
143
|
-
function compareCodeUnits(left, right) {
|
|
144
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
145
|
-
}
|
|
146
|
-
function stringify(value) {
|
|
147
|
-
if (value === void 0) return "null";
|
|
148
|
-
if (value === null || typeof value === "number" || typeof value === "boolean") return JSON.stringify(value);
|
|
149
|
-
if (typeof value === "string") return JSON.stringify(value);
|
|
150
|
-
if (Array.isArray(value)) return `[${value.map(stringify).join(",")}]`;
|
|
151
|
-
if (typeof value === "object") {
|
|
152
|
-
const record = value;
|
|
153
|
-
const parts = [];
|
|
154
|
-
for (const key of Object.keys(record).sort()) {
|
|
155
|
-
if (record[key] === void 0) continue;
|
|
156
|
-
parts.push(`${JSON.stringify(key)}:${stringify(record[key])}`);
|
|
157
|
-
}
|
|
158
|
-
return `{${parts.join(",")}}`;
|
|
159
|
-
}
|
|
160
|
-
throw new Error(`Cannot canonicalize a ${typeof value} value.`);
|
|
161
|
-
}
|
|
162
|
-
//#endregion
|
|
163
150
|
//#region src/lib/core/reference-graph.ts
|
|
164
151
|
/**
|
|
165
152
|
* Ask each asset's owning plugin for the references in its parameters. Assets
|
|
@@ -1003,310 +990,6 @@ function encodeRelativePathForUrl(path) {
|
|
|
1003
990
|
return path.split("/").map(encodeURIComponent).join("/");
|
|
1004
991
|
}
|
|
1005
992
|
//#endregion
|
|
1006
|
-
//#region src/lib/server/raw-reconciliation.ts
|
|
1007
|
-
function objectIdentity(value) {
|
|
1008
|
-
return `${value.dev}:${value.ino}:${value.mode}`;
|
|
1009
|
-
}
|
|
1010
|
-
function fileIdentity(value) {
|
|
1011
|
-
return `${objectIdentity(value)}:${value.size}:${value.mtimeNs}:${value.ctimeNs}`;
|
|
1012
|
-
}
|
|
1013
|
-
function pathMatchesHandle(pathStat, handleStat) {
|
|
1014
|
-
return pathStat.isFile() && objectIdentity(pathStat) === objectIdentity(handleStat);
|
|
1015
|
-
}
|
|
1016
|
-
/** Hash one regular file without following its final path component. */
|
|
1017
|
-
async function stableRawFileHash(path) {
|
|
1018
|
-
let lastProblem;
|
|
1019
|
-
for (let attempt = 0; attempt < 3; attempt++) try {
|
|
1020
|
-
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
1021
|
-
try {
|
|
1022
|
-
const before = await handle.stat({ bigint: true });
|
|
1023
|
-
const pathBefore = await lstat(path, { bigint: true });
|
|
1024
|
-
if (!before.isFile() || !pathMatchesHandle(pathBefore, before)) throw new Error("path is not the opened regular file");
|
|
1025
|
-
const hash = createHash("sha256");
|
|
1026
|
-
for await (const chunk of handle.createReadStream({ autoClose: false })) hash.update(chunk);
|
|
1027
|
-
const after = await handle.stat({ bigint: true });
|
|
1028
|
-
const pathAfter = await lstat(path, { bigint: true });
|
|
1029
|
-
if (fileIdentity(before) === fileIdentity(after) && pathMatchesHandle(pathAfter, after)) return hash.digest("hex");
|
|
1030
|
-
lastProblem = /* @__PURE__ */ new Error("changed while it was being hashed");
|
|
1031
|
-
} finally {
|
|
1032
|
-
await handle.close().catch(() => {});
|
|
1033
|
-
}
|
|
1034
|
-
} catch (cause) {
|
|
1035
|
-
lastProblem = cause;
|
|
1036
|
-
}
|
|
1037
|
-
throw lastProblem instanceof Error ? lastProblem : new Error(String(lastProblem));
|
|
1038
|
-
}
|
|
1039
|
-
async function verifyStableRawFile(path, expectedHash) {
|
|
1040
|
-
const actualHash = await stableRawFileHash(path);
|
|
1041
|
-
if (actualHash !== expectedHash) throw new Error(`Raw source changed (expected ${expectedHash}, found ${actualHash}).`);
|
|
1042
|
-
}
|
|
1043
|
-
/** Enumerate without following symlinks and retain structural scan completeness. */
|
|
1044
|
-
async function scanRawDirectory(rawDir, includeFile = () => true) {
|
|
1045
|
-
const files = [];
|
|
1046
|
-
const blockers = [];
|
|
1047
|
-
const diagnostics = [];
|
|
1048
|
-
const occupiedPaths = /* @__PURE__ */ new Set();
|
|
1049
|
-
const entryKinds = /* @__PURE__ */ new Map();
|
|
1050
|
-
const ignoredRegularPaths = [];
|
|
1051
|
-
let complete = true;
|
|
1052
|
-
function markIncomplete(path, reason) {
|
|
1053
|
-
complete = false;
|
|
1054
|
-
diagnostics.push({
|
|
1055
|
-
path,
|
|
1056
|
-
reason
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
async function visit(folder) {
|
|
1060
|
-
const absolutePath = join(rawDir, folder);
|
|
1061
|
-
let before;
|
|
1062
|
-
try {
|
|
1063
|
-
before = await lstat(absolutePath, { bigint: true });
|
|
1064
|
-
} catch (cause) {
|
|
1065
|
-
markIncomplete(folder, `${folder === "" ? "Raw directory" : `Directory "${folder}"`} cannot be read: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
if (!before.isDirectory() || before.isSymbolicLink()) {
|
|
1069
|
-
markIncomplete(folder, `${folder === "" ? "Raw directory" : `Directory "${folder}"`} is not a regular directory.`);
|
|
1070
|
-
return;
|
|
1071
|
-
}
|
|
1072
|
-
let entries;
|
|
1073
|
-
try {
|
|
1074
|
-
entries = await readdir(absolutePath, { withFileTypes: true });
|
|
1075
|
-
} catch (cause) {
|
|
1076
|
-
markIncomplete(folder, `${folder === "" ? "Raw directory" : `Directory "${folder}"`} cannot be traversed: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
1077
|
-
return;
|
|
1078
|
-
}
|
|
1079
|
-
for (const entry of entries.sort((a, b) => compareCodeUnits(a.name, b.name))) {
|
|
1080
|
-
const path = folder === "" ? entry.name : `${folder}/${entry.name}`;
|
|
1081
|
-
if (entry.name === ".gitkeep" || isFundusTransactionName(entry.name)) continue;
|
|
1082
|
-
if (entry.isDirectory()) {
|
|
1083
|
-
occupiedPaths.add(path);
|
|
1084
|
-
entryKinds.set(path, "directory");
|
|
1085
|
-
const problem = folderPathError(path);
|
|
1086
|
-
if (problem) blockers.push({
|
|
1087
|
-
path,
|
|
1088
|
-
reason: problem
|
|
1089
|
-
});
|
|
1090
|
-
else await visit(path);
|
|
1091
|
-
continue;
|
|
1092
|
-
}
|
|
1093
|
-
if (entry.isFile()) {
|
|
1094
|
-
if (!includeFile(path)) {
|
|
1095
|
-
ignoredRegularPaths.push(path);
|
|
1096
|
-
continue;
|
|
1097
|
-
}
|
|
1098
|
-
occupiedPaths.add(path);
|
|
1099
|
-
entryKinds.set(path, "file");
|
|
1100
|
-
const problem = rawFilePathError(path);
|
|
1101
|
-
if (problem) {
|
|
1102
|
-
blockers.push({
|
|
1103
|
-
path,
|
|
1104
|
-
reason: problem
|
|
1105
|
-
});
|
|
1106
|
-
continue;
|
|
1107
|
-
}
|
|
1108
|
-
try {
|
|
1109
|
-
files.push({
|
|
1110
|
-
path,
|
|
1111
|
-
hash: await stableRawFileHash(join(rawDir, path))
|
|
1112
|
-
});
|
|
1113
|
-
} catch (cause) {
|
|
1114
|
-
blockers.push({
|
|
1115
|
-
path,
|
|
1116
|
-
reason: `Could not obtain a stable file hash: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
continue;
|
|
1120
|
-
}
|
|
1121
|
-
const kind = entry.isSymbolicLink() ? "symlink" : "special";
|
|
1122
|
-
occupiedPaths.add(path);
|
|
1123
|
-
entryKinds.set(path, kind);
|
|
1124
|
-
blockers.push({
|
|
1125
|
-
path,
|
|
1126
|
-
reason: "Symlinks and special files are not supported."
|
|
1127
|
-
});
|
|
1128
|
-
}
|
|
1129
|
-
try {
|
|
1130
|
-
const after = await lstat(absolutePath, { bigint: true });
|
|
1131
|
-
if (!after.isDirectory() || objectIdentity(before) !== objectIdentity(after)) markIncomplete(folder, `${folder === "" ? "Raw directory" : `Directory "${folder}"`} changed during traversal.`);
|
|
1132
|
-
} catch (cause) {
|
|
1133
|
-
markIncomplete(folder, `${folder === "" ? "Raw directory" : `Directory "${folder}"`} changed during traversal: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
await visit("");
|
|
1137
|
-
const collisions = /* @__PURE__ */ new Map();
|
|
1138
|
-
for (const path of [...occupiedPaths].sort(compareCodeUnits)) {
|
|
1139
|
-
const key = portableRawPathKey(path);
|
|
1140
|
-
const previous = collisions.get(key);
|
|
1141
|
-
if (previous !== void 0 && previous !== path) {
|
|
1142
|
-
const reason = `Raw paths "${previous}" and "${path}" collide portably.`;
|
|
1143
|
-
blockers.push({
|
|
1144
|
-
path: previous,
|
|
1145
|
-
reason
|
|
1146
|
-
});
|
|
1147
|
-
blockers.push({
|
|
1148
|
-
path,
|
|
1149
|
-
reason
|
|
1150
|
-
});
|
|
1151
|
-
} else collisions.set(key, path);
|
|
1152
|
-
}
|
|
1153
|
-
const blockersByPath = /* @__PURE__ */ new Map();
|
|
1154
|
-
for (const blocker of blockers) if (!blockersByPath.has(blocker.path)) blockersByPath.set(blocker.path, blocker);
|
|
1155
|
-
const sortedBlockers = [...blockersByPath.values()].sort((a, b) => compareCodeUnits(a.path, b.path));
|
|
1156
|
-
const blocked = new Set(sortedBlockers.map((entry) => entry.path));
|
|
1157
|
-
return {
|
|
1158
|
-
complete,
|
|
1159
|
-
diagnostics: diagnostics.sort((a, b) => compareCodeUnits(a.path, b.path)),
|
|
1160
|
-
files: files.filter((entry) => !blocked.has(entry.path)).sort((a, b) => compareCodeUnits(a.path, b.path)),
|
|
1161
|
-
blockers: sortedBlockers,
|
|
1162
|
-
occupiedPaths,
|
|
1163
|
-
entryKinds,
|
|
1164
|
-
ignoredRegularPaths: ignoredRegularPaths.sort(compareCodeUnits)
|
|
1165
|
-
};
|
|
1166
|
-
}
|
|
1167
|
-
/** Pure deterministic matching: exact path first, then only 1:1 hash groups. */
|
|
1168
|
-
function classifyRawFiles(library, scan) {
|
|
1169
|
-
const filesByPath = new Map(scan.files.map((file) => [file.path, file]));
|
|
1170
|
-
const remainingFiles = new Map(filesByPath);
|
|
1171
|
-
const remainingRecords = /* @__PURE__ */ new Map();
|
|
1172
|
-
const unchangedAssetIds = [];
|
|
1173
|
-
const edited = [];
|
|
1174
|
-
const blockers = [...scan.blockers];
|
|
1175
|
-
const excludedPrefixes = [];
|
|
1176
|
-
for (const assetId of Object.keys(library.assets).sort(compareCodeUnits)) {
|
|
1177
|
-
const record = library.assets[assetId];
|
|
1178
|
-
const kind = scan.entryKinds.get(record.raw);
|
|
1179
|
-
if (kind !== void 0 && kind !== "file") {
|
|
1180
|
-
const existing = blockers.find((blocker) => blocker.path === record.raw);
|
|
1181
|
-
if (existing) existing.assetId = assetId;
|
|
1182
|
-
else blockers.push({
|
|
1183
|
-
assetId,
|
|
1184
|
-
path: record.raw,
|
|
1185
|
-
reason: `Managed raw path is occupied by a ${kind}.`
|
|
1186
|
-
});
|
|
1187
|
-
excludedPrefixes.push(record.raw);
|
|
1188
|
-
continue;
|
|
1189
|
-
}
|
|
1190
|
-
const exact = filesByPath.get(record.raw);
|
|
1191
|
-
if (exact) {
|
|
1192
|
-
remainingFiles.delete(record.raw);
|
|
1193
|
-
if (exact.hash === record.rawHash) unchangedAssetIds.push(assetId);
|
|
1194
|
-
else edited.push({
|
|
1195
|
-
assetId,
|
|
1196
|
-
...exact
|
|
1197
|
-
});
|
|
1198
|
-
} else if (scan.complete && !scan.occupiedPaths.has(record.raw) && !scan.blockers.some((blocker) => record.raw === blocker.path || record.raw.startsWith(`${blocker.path}/`))) remainingRecords.set(assetId, {
|
|
1199
|
-
path: record.raw,
|
|
1200
|
-
hash: record.rawHash
|
|
1201
|
-
});
|
|
1202
|
-
}
|
|
1203
|
-
for (const path of remainingFiles.keys()) if (excludedPrefixes.some((prefix) => path.startsWith(`${prefix}/`))) remainingFiles.delete(path);
|
|
1204
|
-
const recordsByHash = /* @__PURE__ */ new Map();
|
|
1205
|
-
for (const [assetId, record] of remainingRecords) recordsByHash.set(record.hash, [...recordsByHash.get(record.hash) ?? [], assetId]);
|
|
1206
|
-
const filesByHash = /* @__PURE__ */ new Map();
|
|
1207
|
-
for (const file of remainingFiles.values()) filesByHash.set(file.hash, [...filesByHash.get(file.hash) ?? [], file]);
|
|
1208
|
-
const moves = [];
|
|
1209
|
-
if (scan.complete) for (const [hash, assetIds] of recordsByHash) {
|
|
1210
|
-
const candidates = filesByHash.get(hash) ?? [];
|
|
1211
|
-
if (assetIds.length !== 1 || candidates.length !== 1) continue;
|
|
1212
|
-
const assetId = assetIds[0];
|
|
1213
|
-
const file = candidates[0];
|
|
1214
|
-
moves.push({
|
|
1215
|
-
assetId,
|
|
1216
|
-
from: remainingRecords.get(assetId)?.path ?? "",
|
|
1217
|
-
...file
|
|
1218
|
-
});
|
|
1219
|
-
remainingRecords.delete(assetId);
|
|
1220
|
-
remainingFiles.delete(file.path);
|
|
1221
|
-
}
|
|
1222
|
-
const blockerKeys = /* @__PURE__ */ new Set();
|
|
1223
|
-
const uniqueBlockers = blockers.filter((blocker) => {
|
|
1224
|
-
const key = `${blocker.assetId ?? ""}|${blocker.path}`;
|
|
1225
|
-
if (blockerKeys.has(key)) return false;
|
|
1226
|
-
blockerKeys.add(key);
|
|
1227
|
-
return true;
|
|
1228
|
-
});
|
|
1229
|
-
return {
|
|
1230
|
-
complete: scan.complete,
|
|
1231
|
-
diagnostics: scan.diagnostics,
|
|
1232
|
-
unchangedAssetIds,
|
|
1233
|
-
edited: edited.sort((a, b) => compareCodeUnits(a.path, b.path)),
|
|
1234
|
-
moves: scan.complete ? moves.sort((a, b) => compareCodeUnits(a.path, b.path)) : [],
|
|
1235
|
-
deletions: scan.complete ? [...remainingRecords].map(([assetId, record]) => ({
|
|
1236
|
-
assetId,
|
|
1237
|
-
path: record.path
|
|
1238
|
-
})) : [],
|
|
1239
|
-
unmanaged: [...remainingFiles.values()].sort((a, b) => compareCodeUnits(a.path, b.path)),
|
|
1240
|
-
blockers: uniqueBlockers.sort((a, b) => compareCodeUnits(a.path, b.path))
|
|
1241
|
-
};
|
|
1242
|
-
}
|
|
1243
|
-
async function classifyRawDirectory(rawDir, library, includeExternalFile = () => true) {
|
|
1244
|
-
const managedPaths = new Set(Object.values(library.assets).map((record) => record.raw));
|
|
1245
|
-
const scan = await scanRawDirectory(rawDir, (path) => managedPaths.has(path) || includeExternalFile(path));
|
|
1246
|
-
const classification = classifyRawFiles(library, scan);
|
|
1247
|
-
if (!classification.complete || classification.deletions.length === 0) return classification;
|
|
1248
|
-
const ignoredByHash = /* @__PURE__ */ new Map();
|
|
1249
|
-
for (const path of scan.ignoredRegularPaths) try {
|
|
1250
|
-
const hash = await stableRawFileHash(join(rawDir, path));
|
|
1251
|
-
ignoredByHash.set(hash, [...ignoredByHash.get(hash) ?? [], path]);
|
|
1252
|
-
} catch (cause) {
|
|
1253
|
-
return {
|
|
1254
|
-
...classification,
|
|
1255
|
-
complete: false,
|
|
1256
|
-
diagnostics: [...classification.diagnostics, {
|
|
1257
|
-
path,
|
|
1258
|
-
reason: `Could not safely check ignored raw file "${path}" while managed files were missing: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
1259
|
-
}].sort((a, b) => compareCodeUnits(a.path, b.path)),
|
|
1260
|
-
moves: [],
|
|
1261
|
-
deletions: []
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
const missingByHash = /* @__PURE__ */ new Map();
|
|
1265
|
-
for (const deletion of classification.deletions) {
|
|
1266
|
-
const hash = library.assets[deletion.assetId].rawHash;
|
|
1267
|
-
missingByHash.set(hash, [...missingByHash.get(hash) ?? [], deletion]);
|
|
1268
|
-
}
|
|
1269
|
-
const supportedByHash = /* @__PURE__ */ new Map();
|
|
1270
|
-
for (const file of classification.unmanaged) supportedByHash.set(file.hash, [...supportedByHash.get(file.hash) ?? [], file.path]);
|
|
1271
|
-
const protectedAssetIds = /* @__PURE__ */ new Set();
|
|
1272
|
-
const unsupportedBlockers = [];
|
|
1273
|
-
const ambiguityDiagnostics = [];
|
|
1274
|
-
for (const [hash, ignoredPaths] of ignoredByHash) {
|
|
1275
|
-
const missing = missingByHash.get(hash) ?? [];
|
|
1276
|
-
if (missing.length === 0) continue;
|
|
1277
|
-
const candidatePaths = [...supportedByHash.get(hash) ?? [], ...ignoredPaths].sort(compareCodeUnits);
|
|
1278
|
-
const sortedMissing = [...missing].sort((a, b) => compareCodeUnits(a.assetId, b.assetId));
|
|
1279
|
-
if (sortedMissing.length === 1 && ignoredPaths.length === 1 && candidatePaths.length === 1) {
|
|
1280
|
-
const [{ assetId, path: oldPath }] = sortedMissing;
|
|
1281
|
-
const [destination] = ignoredPaths;
|
|
1282
|
-
protectedAssetIds.add(assetId);
|
|
1283
|
-
unsupportedBlockers.push({
|
|
1284
|
-
assetId,
|
|
1285
|
-
path: destination,
|
|
1286
|
-
reason: `Asset "${assetId}" was moved from "${oldPath}" to unsupported path "${destination}". Rename it externally to a supported extension.`
|
|
1287
|
-
});
|
|
1288
|
-
continue;
|
|
1289
|
-
}
|
|
1290
|
-
ambiguityDiagnostics.push({
|
|
1291
|
-
path: candidatePaths[0] ?? "",
|
|
1292
|
-
reason: `Ignored raw files ambiguously match missing assets [${sortedMissing.map((entry) => entry.assetId).join(", ")}] and candidate paths [${candidatePaths.join(", ")}]. Restore or reduce the external files until the match is unique.`
|
|
1293
|
-
});
|
|
1294
|
-
}
|
|
1295
|
-
if (ambiguityDiagnostics.length > 0) return {
|
|
1296
|
-
...classification,
|
|
1297
|
-
complete: false,
|
|
1298
|
-
diagnostics: [...classification.diagnostics, ...ambiguityDiagnostics].sort((a, b) => compareCodeUnits(`${a.path}|${a.reason}`, `${b.path}|${b.reason}`)),
|
|
1299
|
-
moves: [],
|
|
1300
|
-
deletions: [],
|
|
1301
|
-
blockers: [...classification.blockers, ...unsupportedBlockers].sort((a, b) => compareCodeUnits(a.path, b.path))
|
|
1302
|
-
};
|
|
1303
|
-
return {
|
|
1304
|
-
...classification,
|
|
1305
|
-
deletions: classification.deletions.filter((deletion) => !protectedAssetIds.has(deletion.assetId)),
|
|
1306
|
-
blockers: [...classification.blockers, ...unsupportedBlockers].sort((a, b) => compareCodeUnits(a.path, b.path))
|
|
1307
|
-
};
|
|
1308
|
-
}
|
|
1309
|
-
//#endregion
|
|
1310
993
|
//#region src/lib/server/processing/processor.ts
|
|
1311
994
|
/**
|
|
1312
995
|
* The processing pipeline: every delivered asset gets exactly one
|
|
@@ -1554,9 +1237,12 @@ var LibraryStore = class {
|
|
|
1554
1237
|
* the owning plugin's default parameters. Returns the updated library.
|
|
1555
1238
|
*/
|
|
1556
1239
|
async ingest(options) {
|
|
1557
|
-
return this
|
|
1240
|
+
return this.createAsset(options);
|
|
1558
1241
|
}
|
|
1559
|
-
async
|
|
1242
|
+
async createAsset(options, prepareParameters) {
|
|
1243
|
+
return this.#enqueue(() => this.#createAsset(options, prepareParameters));
|
|
1244
|
+
}
|
|
1245
|
+
async #createAsset(options, prepareParameters) {
|
|
1560
1246
|
const idProblem = assetIdError(options.id);
|
|
1561
1247
|
if (idProblem) throw new Error(idProblem);
|
|
1562
1248
|
const plugin = serverPluginForType(options.type, this.#registry);
|
|
@@ -1566,20 +1252,49 @@ var LibraryStore = class {
|
|
|
1566
1252
|
if (Object.hasOwn(library.assets, options.id)) throw new Error(`An asset with id "${options.id}" already exists.`);
|
|
1567
1253
|
const folder = options.folder === void 0 ? "" : normalizeFolderPath(options.folder);
|
|
1568
1254
|
this.#requireFolder(library, folder);
|
|
1569
|
-
|
|
1255
|
+
const manifests = [...new Set(options.manifests ?? [])].sort();
|
|
1256
|
+
for (const manifest of manifests) if (!Object.hasOwn(library.manifests, manifest)) throw new Error(`Unknown manifest "${manifest}".`);
|
|
1257
|
+
const rawDirectory = join(this.#config.rawDir, folder);
|
|
1258
|
+
await mkdir(rawDirectory, { recursive: true });
|
|
1570
1259
|
const storedName = this.#uniqueRawName(sanitizeFileName(options.fileName), folder);
|
|
1571
1260
|
const storedPath = folder === "" ? storedName : `${folder}/${storedName}`;
|
|
1572
|
-
|
|
1573
|
-
const
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
parameters
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1261
|
+
const finalPath = join(this.#config.rawDir, storedPath);
|
|
1262
|
+
const temporaryPath = join(rawDirectory, `.fundus-create-${crypto.randomUUID()}.tmp`);
|
|
1263
|
+
let installed = false;
|
|
1264
|
+
try {
|
|
1265
|
+
await writeFile(temporaryPath, options.bytes);
|
|
1266
|
+
let parameters = plugin.descriptor.validateParameters(plugin.descriptor.defaultParameters(plugin.pluginConfig(this.#config)));
|
|
1267
|
+
if (prepareParameters) parameters = plugin.descriptor.validateParameters(await prepareParameters({
|
|
1268
|
+
rawPath: temporaryPath,
|
|
1269
|
+
rawFileName: storedName,
|
|
1270
|
+
parameters
|
|
1271
|
+
}));
|
|
1272
|
+
const record = {
|
|
1273
|
+
type: options.type,
|
|
1274
|
+
raw: storedPath,
|
|
1275
|
+
rawHash: sha256Hex(options.bytes),
|
|
1276
|
+
parameters,
|
|
1277
|
+
manifests
|
|
1278
|
+
};
|
|
1279
|
+
if (options.importSource) {
|
|
1280
|
+
record.importSource = structuredClone(options.importSource);
|
|
1281
|
+
library.version = 2;
|
|
1282
|
+
}
|
|
1283
|
+
library.assets[options.id] = record;
|
|
1284
|
+
parseLibrary(serializeLibrary(library));
|
|
1285
|
+
await rename(temporaryPath, finalPath);
|
|
1286
|
+
installed = true;
|
|
1287
|
+
await this.write(library);
|
|
1288
|
+
return library;
|
|
1289
|
+
} catch (cause) {
|
|
1290
|
+
const cleanupErrors = [];
|
|
1291
|
+
if (installed) await unlink(finalPath).catch((error) => cleanupErrors.push(error));
|
|
1292
|
+
await unlink(temporaryPath).catch((error) => {
|
|
1293
|
+
if (error.code !== "ENOENT") cleanupErrors.push(error);
|
|
1294
|
+
});
|
|
1295
|
+
if (cleanupErrors.length > 0) throw new AggregateError([cause, ...cleanupErrors], "Asset creation failed and cleanup was incomplete.");
|
|
1296
|
+
throw cause;
|
|
1297
|
+
}
|
|
1583
1298
|
}
|
|
1584
1299
|
/**
|
|
1585
1300
|
* Replace one asset's raw file while preserving its identity and authored
|
|
@@ -1598,6 +1313,7 @@ var LibraryStore = class {
|
|
|
1598
1313
|
if (!plugin.descriptor.accepts.includes(extension)) throw new Error(`The ${record.type} type does not accept ".${extension}" files (accepts: ${plugin.descriptor.accepts.join(", ")}).`);
|
|
1599
1314
|
const previousRaw = record.raw;
|
|
1600
1315
|
const previousHash = record.rawHash;
|
|
1316
|
+
const previousSource = record.importSource;
|
|
1601
1317
|
const folder = folderOfRawPath(previousRaw);
|
|
1602
1318
|
const previousName = rawFileNameOfPath(previousRaw);
|
|
1603
1319
|
const storedName = sanitizedName === previousName ? previousName : this.#uniqueRawName(sanitizedName, folder);
|
|
@@ -1620,10 +1336,12 @@ var LibraryStore = class {
|
|
|
1620
1336
|
replacementInstalled = true;
|
|
1621
1337
|
record.raw = nextRaw;
|
|
1622
1338
|
record.rawHash = sha256Hex(options.bytes);
|
|
1339
|
+
delete record.importSource;
|
|
1623
1340
|
await this.write(library);
|
|
1624
1341
|
} catch (cause) {
|
|
1625
1342
|
record.raw = previousRaw;
|
|
1626
1343
|
record.rawHash = previousHash;
|
|
1344
|
+
if (previousSource) record.importSource = previousSource;
|
|
1627
1345
|
if (replacementInstalled) await unlink(nextPath).catch(() => {});
|
|
1628
1346
|
if (previousStaged) await rename(backupPath, previousPath);
|
|
1629
1347
|
await unlink(temporaryPath).catch(() => {});
|
|
@@ -1632,6 +1350,47 @@ var LibraryStore = class {
|
|
|
1632
1350
|
if (previousStaged) await unlink(backupPath).catch(() => {});
|
|
1633
1351
|
return library;
|
|
1634
1352
|
}
|
|
1353
|
+
/** CAS-protected replacement used only by a repeatable import source. */
|
|
1354
|
+
async replaceRawFromImportSource(id, bytes, expected, nextSource) {
|
|
1355
|
+
return this.#enqueue(async () => {
|
|
1356
|
+
const library = await this.read();
|
|
1357
|
+
const record = this.#requireAsset(library, id);
|
|
1358
|
+
if (record.raw !== expected.raw || record.rawHash !== expected.rawHash || record.type !== expected.type || !record.importSource || canonicalizeParameters(record.importSource) !== expected.canonicalSource) throw new Error("stale-import");
|
|
1359
|
+
const absolutePath = join(this.#config.rawDir, record.raw);
|
|
1360
|
+
const { verifyStableRawFile } = await import('./raw-reconciliation2.js-DFwky2ou.js');
|
|
1361
|
+
try {
|
|
1362
|
+
await verifyStableRawFile(absolutePath, expected.rawHash);
|
|
1363
|
+
} catch {
|
|
1364
|
+
throw new Error("stale-import");
|
|
1365
|
+
}
|
|
1366
|
+
const token = crypto.randomUUID();
|
|
1367
|
+
const temporaryPath = `${absolutePath}.fundus-reimport-${token}.tmp`;
|
|
1368
|
+
const backupPath = `${absolutePath}.fundus-reimport-${token}`;
|
|
1369
|
+
const previousHash = record.rawHash;
|
|
1370
|
+
const previousSource = structuredClone(record.importSource);
|
|
1371
|
+
let staged = false;
|
|
1372
|
+
let installed = false;
|
|
1373
|
+
try {
|
|
1374
|
+
await writeFile(temporaryPath, bytes);
|
|
1375
|
+
await rename(absolutePath, backupPath);
|
|
1376
|
+
staged = true;
|
|
1377
|
+
await rename(temporaryPath, absolutePath);
|
|
1378
|
+
installed = true;
|
|
1379
|
+
record.rawHash = sha256Hex(bytes);
|
|
1380
|
+
if (nextSource) record.importSource = structuredClone(nextSource);
|
|
1381
|
+
await this.write(library);
|
|
1382
|
+
} catch (cause) {
|
|
1383
|
+
record.rawHash = previousHash;
|
|
1384
|
+
record.importSource = previousSource;
|
|
1385
|
+
if (installed) await unlink(absolutePath).catch(() => {});
|
|
1386
|
+
if (staged) await rename(backupPath, absolutePath);
|
|
1387
|
+
await unlink(temporaryPath).catch(() => {});
|
|
1388
|
+
throw cause;
|
|
1389
|
+
}
|
|
1390
|
+
if (staged) await unlink(backupPath).catch(() => {});
|
|
1391
|
+
return library;
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1635
1394
|
/** Replace an asset's parameters (validated by the owning plugin). */
|
|
1636
1395
|
async updateParameters(id, parameters) {
|
|
1637
1396
|
return this.#enqueue(() => this.#updateParameters(id, parameters));
|
|
@@ -2131,6 +1890,21 @@ var LibraryStore = class {
|
|
|
2131
1890
|
if (collision !== void 0) throw new Error(`Folder "${path}" collides with existing folder "${collision}".`);
|
|
2132
1891
|
}
|
|
2133
1892
|
};
|
|
1893
|
+
//#endregion
|
|
1894
|
+
//#region src/lib/server/importers/contract.ts
|
|
1895
|
+
var SourceImportError = class extends Error {
|
|
1896
|
+
code;
|
|
1897
|
+
retryAfterSeconds;
|
|
1898
|
+
constructor(code, message, retryAfterSeconds) {
|
|
1899
|
+
super(message);
|
|
1900
|
+
this.name = "SourceImportError";
|
|
1901
|
+
this.code = code;
|
|
1902
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
1903
|
+
}
|
|
1904
|
+
};
|
|
1905
|
+
function invalidInput(message) {
|
|
1906
|
+
throw new SourceImportError("invalid-input", message);
|
|
1907
|
+
}
|
|
2134
1908
|
|
|
2135
|
-
export { LibraryStore as L, serverPluginForType as a, computeLibraryMembership as b, collectAllReferences as c, descriptorsByType as d, allDeliveredAssetIds as e,
|
|
2136
|
-
//# sourceMappingURL=
|
|
1909
|
+
export { LibraryStore as L, SourceImportError as S, serverPluginForType as a, computeLibraryMembership as b, collectAllReferences as c, descriptorsByType as d, allDeliveredAssetIds as e, encodeRelativePathForUrl as f, generateManifestModules as g, invalidInput as h, isRecord as i, assertSafeRelativeFilePath as j, processAssets as p, readCurrentProxy as r, serverPluginsByType as s };
|
|
1910
|
+
//# sourceMappingURL=contract.js-sHny3b-s.js.map
|