fundus 0.0.2 → 0.0.4
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 +73 -0
- package/build/client/_app/immutable/assets/0.DLhIsYA_.css.br +0 -0
- package/build/client/_app/immutable/assets/0.DLhIsYA_.css.gz +0 -0
- package/build/client/_app/immutable/assets/2.ohi-TClG.css +1 -0
- 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.JwgtcTEd.css +1 -0
- package/build/client/_app/immutable/assets/3.JwgtcTEd.css.br +0 -0
- package/build/client/_app/immutable/assets/3.JwgtcTEd.css.gz +0 -0
- package/build/client/_app/immutable/assets/4.p004hmEN.css +1 -0
- package/build/client/_app/immutable/assets/4.p004hmEN.css.br +0 -0
- package/build/client/_app/immutable/assets/4.p004hmEN.css.gz +0 -0
- package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css +1 -0
- package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css.br +0 -0
- package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css.gz +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.CMefGNE2.css +1 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.CMefGNE2.css.br +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.CMefGNE2.css.gz +0 -0
- package/build/client/_app/immutable/chunks/Bjy-W4x2.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bjy-W4x2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CNRz3sSw.js.br +0 -0
- package/build/client/_app/immutable/chunks/CNRz3sSw.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CO4RBJfa.js.br +0 -0
- package/build/client/_app/immutable/chunks/CO4RBJfa.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DOpBpjxS.js +108 -0
- package/build/client/_app/immutable/chunks/DOpBpjxS.js.br +0 -0
- package/build/client/_app/immutable/chunks/DOpBpjxS.js.gz +0 -0
- package/{dist/editor/_app/immutable/chunks/BfPE5wdt.js → build/client/_app/immutable/chunks/DVEQFclp.js} +1 -1
- package/build/client/_app/immutable/chunks/DVEQFclp.js.br +1 -0
- package/build/client/_app/immutable/chunks/DVEQFclp.js.gz +0 -0
- package/{dist/editor/_app/immutable/chunks/DjvOiDmq.js → build/client/_app/immutable/chunks/DiFoWL2c.js} +1 -1
- package/build/client/_app/immutable/chunks/DiFoWL2c.js.br +0 -0
- package/build/client/_app/immutable/chunks/DiFoWL2c.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DkADHpZF.js +1 -0
- package/build/client/_app/immutable/chunks/DkADHpZF.js.br +0 -0
- package/build/client/_app/immutable/chunks/DkADHpZF.js.gz +0 -0
- package/build/client/_app/immutable/chunks/xihTtKlq.js.br +1 -0
- package/build/client/_app/immutable/chunks/xihTtKlq.js.gz +0 -0
- package/{dist/editor/_app/immutable/entry/app.BkqbfI8n.js → build/client/_app/immutable/entry/app.CKgtYXQb.js} +2 -2
- package/build/client/_app/immutable/entry/app.CKgtYXQb.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CKgtYXQb.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CYZu5qE1.js +1 -0
- package/build/client/_app/immutable/entry/start.CYZu5qE1.js.br +0 -0
- package/build/client/_app/immutable/entry/start.CYZu5qE1.js.gz +0 -0
- package/{dist/editor/_app/immutable/nodes/0.xdMI5GEU.js → build/client/_app/immutable/nodes/0.I_1SApYQ.js} +1 -1
- package/build/client/_app/immutable/nodes/0.I_1SApYQ.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.I_1SApYQ.js.gz +0 -0
- package/{dist/editor/_app/immutable/nodes/1.D9p2tfoJ.js → build/client/_app/immutable/nodes/1.v6eUTnWq.js} +1 -1
- package/build/client/_app/immutable/nodes/1.v6eUTnWq.js.br +2 -0
- package/build/client/_app/immutable/nodes/1.v6eUTnWq.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DoA7Dfl-.js +3 -0
- package/build/client/_app/immutable/nodes/2.DoA7Dfl-.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DoA7Dfl-.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.C-DO70Bs.js +1 -0
- package/build/client/_app/immutable/nodes/3.C-DO70Bs.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.C-DO70Bs.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.CALOuSyz.js +2 -0
- package/build/client/_app/immutable/nodes/4.CALOuSyz.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CALOuSyz.js.gz +0 -0
- package/build/client/_app/version.json +1 -0
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/env.js +100 -0
- package/build/env.js.map +1 -0
- package/build/handler.js +22 -0
- package/build/handler.js.map +1 -0
- package/build/index.js +145 -0
- package/build/index.js.map +1 -0
- package/build/server/chunks/chunks/context.js-BUZqFfWG.js +429 -0
- package/build/server/chunks/chunks/context.js-BUZqFfWG.js.map +1 -0
- package/build/server/chunks/chunks/core.js-xfrkaQpS.js +458 -0
- package/build/server/chunks/chunks/core.js-xfrkaQpS.js.map +1 -0
- package/build/server/chunks/chunks/env.js-l0sNRNKZ.js +2 -0
- package/build/server/chunks/chunks/env.js-l0sNRNKZ.js.map +1 -0
- package/build/server/chunks/chunks/exports.js-C0rwMMtk.js +152 -0
- package/build/server/chunks/chunks/exports.js-C0rwMMtk.js.map +1 -0
- package/build/server/chunks/chunks/folder-path.js-ytx9ucgg.js +64 -0
- package/build/server/chunks/chunks/folder-path.js-ytx9ucgg.js.map +1 -0
- package/build/server/chunks/chunks/http.js-DvopzwKh.js +100 -0
- package/build/server/chunks/chunks/http.js-DvopzwKh.js.map +1 -0
- package/build/server/chunks/chunks/internal.js-DGo2jPcg.js +5753 -0
- package/build/server/chunks/chunks/internal.js-DGo2jPcg.js.map +1 -0
- package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js +22 -0
- package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -0
- package/{dist/operations-DYM-5KVl.js → build/server/chunks/chunks/library-store.js-ZLudCJlT.js} +463 -492
- package/build/server/chunks/chunks/library-store.js-ZLudCJlT.js.map +1 -0
- package/build/server/chunks/chunks/manifest-appearance.js-DTk355LQ.js +146 -0
- package/build/server/chunks/chunks/manifest-appearance.js-DTk355LQ.js.map +1 -0
- package/build/server/chunks/chunks/routing.js-y-tryuip.js +213 -0
- package/build/server/chunks/chunks/routing.js-y-tryuip.js.map +1 -0
- package/build/server/chunks/chunks/shared.js-B1gC9MiJ.js +255 -0
- package/build/server/chunks/chunks/shared.js-B1gC9MiJ.js.map +1 -0
- package/build/server/chunks/chunks/utils.js-DnEJ3UjO.js +1048 -0
- package/build/server/chunks/chunks/utils.js-DnEJ3UjO.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/_...path_/_server.ts.js-Cq5gXVQT.js +27 -0
- package/build/server/chunks/entries/endpoints/api/_...path_/_server.ts.js-Cq5gXVQT.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/assets/_id_/_server.ts.js-RXbedi8q.js +24 -0
- package/build/server/chunks/entries/endpoints/api/assets/_id_/_server.ts.js-RXbedi8q.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/assets/_server.ts.js-D7Qae9vU.js +45 -0
- package/build/server/chunks/entries/endpoints/api/assets/_server.ts.js-D7Qae9vU.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/assets/delete/_server.ts.js-DtO20kgB.js +31 -0
- package/build/server/chunks/entries/endpoints/api/assets/delete/_server.ts.js-DtO20kgB.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/assets/move/_server.ts.js-BUebPbd5.js +31 -0
- package/build/server/chunks/entries/endpoints/api/assets/move/_server.ts.js-BUebPbd5.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/folders/_path_/_server.ts.js-BjT2qPMT.js +38 -0
- package/build/server/chunks/entries/endpoints/api/folders/_path_/_server.ts.js-BjT2qPMT.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/folders/_server.ts.js-DYRLsoT7.js +31 -0
- package/build/server/chunks/entries/endpoints/api/folders/_server.ts.js-DYRLsoT7.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/_server.ts.js-BbN2fGNN.js +24 -0
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/_server.ts.js-BbN2fGNN.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/manifests/_server.ts.js-b_MKZ41b.js +31 -0
- package/build/server/chunks/entries/endpoints/api/manifests/_server.ts.js-b_MKZ41b.js.map +1 -0
- package/build/server/chunks/entries/endpoints/api/state/_server.ts.js-evEfMpvn.js +24 -0
- package/build/server/chunks/entries/endpoints/api/state/_server.ts.js-evEfMpvn.js.map +1 -0
- package/build/server/chunks/entries/endpoints/files/_...path_/_server.ts.js-C04XE_1w.js +27 -0
- package/build/server/chunks/entries/endpoints/files/_...path_/_server.ts.js-C04XE_1w.js.map +1 -0
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/_server.ts.js-DB8TdoEv.js +24 -0
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/_server.ts.js-DB8TdoEv.js.map +1 -0
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/_server.ts.js-BrpaijZO.js +24 -0
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/_server.ts.js-BrpaijZO.js.map +1 -0
- package/build/server/chunks/entries/hooks.server.js-BJJwZW_I.js +23 -0
- package/build/server/chunks/entries/hooks.server.js-BJJwZW_I.js.map +1 -0
- package/build/server/chunks/handler-DnbS2t1B.js +1475 -0
- package/build/server/chunks/handler-DnbS2t1B.js.map +1 -0
- package/build/server/chunks/index.js-g77q3Boj.js +3789 -0
- package/build/server/chunks/index.js-g77q3Boj.js.map +1 -0
- package/build/server/chunks/manifest.js-qmEXbstS.js +149 -0
- package/build/server/chunks/manifest.js-qmEXbstS.js.map +1 -0
- package/build/server/chunks/nodes/0.js-Bk6IZ-vD.js +11 -0
- package/build/server/chunks/nodes/0.js-Bk6IZ-vD.js.map +1 -0
- package/build/server/chunks/nodes/1.js-H-qwo4GJ.js +7 -0
- package/build/server/chunks/nodes/1.js-H-qwo4GJ.js.map +1 -0
- package/build/server/chunks/nodes/2.js-DRpXVLwp.js +7 -0
- package/build/server/chunks/nodes/2.js-DRpXVLwp.js.map +1 -0
- package/build/server/chunks/nodes/3.js-CDEzNFeU.js +7 -0
- package/build/server/chunks/nodes/3.js-CDEzNFeU.js.map +1 -0
- package/build/server/chunks/nodes/4.js-BKL7LSSm.js +7 -0
- package/build/server/chunks/nodes/4.js-BKL7LSSm.js.map +1 -0
- package/build/shims.js +33 -0
- package/build/shims.js.map +1 -0
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +116 -1336
- package/dist/config.d.ts +3 -2
- package/dist/config.js +2 -2
- package/dist/core/api-types.d.ts +141 -0
- package/dist/core/api-types.js +1 -0
- package/dist/core/asset-id.d.ts +28 -0
- package/dist/core/asset-id.js +59 -0
- package/dist/core/asset-reference.d.ts +23 -0
- package/dist/core/asset-reference.js +15 -0
- package/dist/core/canonicalize.d.ts +9 -0
- package/dist/core/canonicalize.js +36 -0
- package/dist/core/chroma-key.d.ts +30 -0
- package/dist/core/chroma-key.js +55 -0
- package/dist/core/config.d.ts +35 -0
- package/dist/core/config.js +4 -0
- package/dist/core/folder-path.d.ts +19 -0
- package/dist/core/folder-path.js +86 -0
- package/dist/core/index.d.ts +33 -499
- package/dist/core/index.js +17 -962
- package/dist/core/ingest.d.ts +24 -0
- package/dist/core/ingest.js +42 -0
- package/dist/core/library.d.ts +54 -0
- package/dist/core/library.js +138 -0
- package/dist/core/manifest-appearance.d.ts +35 -0
- package/dist/core/manifest-appearance.js +123 -0
- package/dist/core/manifest-entry.d.ts +104 -0
- package/dist/core/manifest-entry.js +1 -0
- package/dist/core/manifest-membership.d.ts +56 -0
- package/dist/core/manifest-membership.js +54 -0
- package/dist/core/plugins/audio.d.ts +26 -0
- package/dist/core/plugins/audio.js +44 -0
- package/dist/core/plugins/chroma-key-video.d.ts +29 -0
- package/dist/core/plugins/chroma-key-video.js +69 -0
- package/dist/core/plugins/contract.d.ts +35 -0
- package/dist/core/plugins/contract.js +1 -0
- package/dist/core/plugins/image.d.ts +30 -0
- package/dist/core/plugins/image.js +45 -0
- package/dist/core/plugins/registry.d.ts +16 -0
- package/dist/core/plugins/registry.js +52 -0
- package/dist/core/plugins/slice.d.ts +22 -0
- package/dist/core/plugins/slice.js +60 -0
- package/dist/core/plugins/video.d.ts +45 -0
- package/dist/core/plugins/video.js +77 -0
- package/dist/core/reference-graph.d.ts +41 -0
- package/dist/core/reference-graph.js +138 -0
- package/dist/core/slice-data.d.ts +61 -0
- package/dist/core/slice-data.js +49 -0
- package/dist/runtime/chroma-key-gl.d.ts +40 -22
- package/dist/runtime/chroma-key-gl.js +189 -183
- package/dist/runtime/components/ChromaKeyVideo.svelte +3 -3
- package/dist/runtime/components/ChromaKeyVideo.svelte.d.ts +21 -0
- package/dist/runtime/components/Image.svelte +1 -1
- package/dist/runtime/components/Image.svelte.d.ts +9 -0
- package/dist/runtime/components/Slice.svelte +1 -1
- package/dist/runtime/components/Slice.svelte.d.ts +19 -0
- package/dist/runtime/components/SliceCanvas.svelte +3 -3
- package/dist/runtime/components/SliceCanvas.svelte.d.ts +10 -0
- package/dist/runtime/components/SliceDom.svelte +3 -3
- package/dist/runtime/components/SliceDom.svelte.d.ts +10 -0
- package/dist/runtime/components/Video.svelte +2 -2
- package/dist/runtime/components/Video.svelte.d.ts +18 -0
- package/dist/runtime/geometry.d.ts +55 -35
- package/dist/runtime/geometry.js +186 -191
- package/dist/runtime/index.d.ts +9 -9
- package/dist/runtime/index.js +9 -9
- package/dist/runtime/kind-handlers.d.ts +33 -30
- package/dist/runtime/kind-handlers.js +85 -67
- package/dist/runtime/manifest.d.ts +53 -47
- package/dist/runtime/manifest.js +133 -113
- package/dist/runtime/observe-border-box-size.d.ts +1 -4
- package/dist/runtime/observe-border-box-size.js +9 -10
- package/dist/runtime/preload-registry.d.ts +22 -8
- package/dist/runtime/preload-registry.js +65 -62
- package/dist/server/build.d.ts +8 -0
- package/dist/server/build.js +25 -0
- package/dist/server/check.d.ts +24 -0
- package/dist/server/check.js +199 -0
- package/dist/server/cli-commands.d.ts +25 -0
- package/dist/server/cli-commands.js +1178 -0
- package/dist/server/cli-init.d.ts +3 -0
- package/dist/server/cli-init.js +53 -0
- package/dist/server/cli-io.d.ts +46 -0
- package/dist/server/cli-io.js +105 -0
- package/dist/server/codegen.d.ts +58 -0
- package/dist/server/codegen.js +185 -0
- package/dist/server/config-loader.d.ts +35 -0
- package/dist/server/config-loader.js +79 -0
- package/dist/server/context.d.ts +8 -0
- package/dist/server/context.js +19 -0
- package/dist/server/folder-filesystem.d.ts +7 -0
- package/dist/server/folder-filesystem.js +39 -0
- package/dist/server/http.d.ts +12 -0
- package/dist/server/http.js +100 -0
- package/dist/server/index.d.ts +17 -0
- package/dist/server/index.js +9 -0
- package/dist/server/job-hash.d.ts +10 -0
- package/dist/server/job-hash.js +23 -0
- package/dist/server/library-store.d.ts +82 -0
- package/dist/server/library-store.js +763 -0
- package/dist/server/operations.d.ts +87 -0
- package/dist/server/operations.js +427 -0
- package/dist/server/plugins/audio.d.ts +8 -0
- package/dist/server/plugins/audio.js +41 -0
- package/dist/server/plugins/chroma-key-video.d.ts +9 -0
- package/dist/server/plugins/chroma-key-video.js +40 -0
- package/dist/server/plugins/config.d.ts +13 -0
- package/dist/server/plugins/config.js +32 -0
- package/dist/server/plugins/contract.d.ts +114 -0
- package/dist/server/plugins/contract.js +16 -0
- package/dist/server/plugins/image.d.ts +9 -0
- package/dist/server/plugins/image.js +43 -0
- package/dist/server/plugins/slice.d.ts +15 -0
- package/dist/server/plugins/slice.js +76 -0
- package/dist/server/plugins/video.d.ts +7 -0
- package/dist/server/plugins/video.js +54 -0
- package/dist/server/plugins.d.ts +23 -0
- package/dist/server/plugins.js +35 -0
- package/dist/server/processing/audio-processing.d.ts +17 -0
- package/dist/server/processing/audio-processing.js +46 -0
- package/dist/server/processing/ffmpeg.d.ts +9 -0
- package/dist/server/processing/ffmpeg.js +50 -0
- package/dist/server/processing/image-processing.d.ts +16 -0
- package/dist/server/processing/image-processing.js +26 -0
- package/dist/server/processing/media-probe.d.ts +15 -0
- package/dist/server/processing/media-probe.js +27 -0
- package/dist/server/processing/processor.d.ts +50 -0
- package/dist/server/processing/processor.js +158 -0
- package/dist/server/processing/video-processing.d.ts +35 -0
- package/dist/server/processing/video-processing.js +87 -0
- package/dist/server/server.d.ts +13 -0
- package/dist/server/server.js +57 -0
- package/dist/server/start.d.ts +13 -0
- package/dist/server/start.js +80 -0
- package/package.json +31 -16
- package/dist/build-CZYFLLvl.js +0 -191
- package/dist/core/image-Dqmz8FXS.js +0 -54
- package/dist/core/reference-graph-CjuHbLDw.d.ts +0 -280
- package/dist/core/testing.d.ts +0 -27
- package/dist/core/testing.js +0 -80
- package/dist/editor/200.html +0 -37
- package/dist/editor/_app/immutable/assets/2.DIbbW7U1.css +0 -1
- package/dist/editor/_app/immutable/assets/3.C-9vFQ9A.css +0 -1
- package/dist/editor/_app/immutable/assets/4.BS8ElpOV.css +0 -1
- package/dist/editor/_app/immutable/assets/ConfirmDialog.CHEISE-L.css +0 -1
- package/dist/editor/_app/immutable/assets/LibraryContextMenu.CDjCmdV-.css +0 -1
- package/dist/editor/_app/immutable/chunks/Cx6qtxJg.js +0 -1
- package/dist/editor/_app/immutable/chunks/DjdrdRzT.js +0 -1
- package/dist/editor/_app/immutable/chunks/n7mvYc42.js +0 -5
- package/dist/editor/_app/immutable/entry/start.C8HHOLly.js +0 -1
- package/dist/editor/_app/immutable/nodes/2.BrA0Hyzu.js +0 -3
- package/dist/editor/_app/immutable/nodes/3.WO7tZH_d.js +0 -104
- package/dist/editor/_app/immutable/nodes/4.DQtx17aW.js +0 -2
- package/dist/editor/_app/version.json +0 -1
- package/dist/index.d.ts +0 -370
- package/dist/index.js +0 -4
- package/dist/start-Bhnqt9Dc.js +0 -279
- package/dist/start-D2IXOrni.js +0 -2
- /package/{dist/editor → build/client}/_app/immutable/assets/0.DLhIsYA_.css +0 -0
- /package/{dist/editor → build/client}/_app/immutable/chunks/Bjy-W4x2.js +0 -0
- /package/{dist/editor → build/client}/_app/immutable/chunks/CNRz3sSw.js +0 -0
- /package/{dist/editor → build/client}/_app/immutable/chunks/CO4RBJfa.js +0 -0
- /package/{dist/editor → build/client}/_app/immutable/chunks/xihTtKlq.js +0 -0
|
@@ -1,46 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The runtime part of the type-plugin contract: per-kind preload
|
|
3
|
+
* strategy and its inverse release strategy. Each first-party kind registers
|
|
4
|
+
* a handler that knows how its delivered file is loaded — image-backed kinds
|
|
5
|
+
* fetch + optionally decode, media kinds (video/audio) fetch fully and mint
|
|
6
|
+
* an object URL — and how what it loaded is disposed (revoke the object URL;
|
|
7
|
+
* image-backed kinds have nothing to dispose). An unknown kind falls back to
|
|
8
|
+
* a plain full fetch: no decode, no retention.
|
|
9
|
+
*
|
|
10
|
+
* Handlers are pure strategy: refcounting, cross-manifest dedup, and
|
|
11
|
+
* in-flight bookkeeping live in the module-wide registry
|
|
12
|
+
* (preload-registry.ts); kind-agnostic orchestration lives in `Manifest`.
|
|
13
|
+
*/
|
|
14
|
+
import type { AudioManifestEntry, PreloadOptions } from '../core/index.js';
|
|
4
15
|
/** The playable URL hosts feed to their own audio engine. */
|
|
5
|
-
declare function audioSourceOf(entry: AudioManifestEntry): string;
|
|
16
|
+
export declare function audioSourceOf(entry: AudioManifestEntry): string;
|
|
6
17
|
/**
|
|
7
18
|
* What a handler's `preload` acquired and its `release` must dispose. For
|
|
8
19
|
* retained media kinds this is the minted object URL; cache-backed kinds
|
|
9
20
|
* (image, slice, unknown) hold no disposable resources.
|
|
10
21
|
*/
|
|
11
|
-
interface KindHandlerResources {
|
|
12
|
-
|
|
13
|
-
|
|
22
|
+
export interface KindHandlerResources {
|
|
23
|
+
/** Object URL minted over the fully fetched file (retained media kinds). */
|
|
24
|
+
objectUrl?: string;
|
|
14
25
|
}
|
|
15
26
|
/** How one asset kind preloads — and releases — its delivered file. */
|
|
16
|
-
interface KindRuntimeHandler {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
export interface KindRuntimeHandler {
|
|
28
|
+
/**
|
|
29
|
+
* Fully load one source of this kind — the promise resolves only once the
|
|
30
|
+
* file is completely transferred (plus the kind's strategy: decoded /
|
|
31
|
+
* retained as an object URL) — and return the resources `release` disposes.
|
|
32
|
+
*/
|
|
33
|
+
preload(url: string, options: PreloadOptions): Promise<KindHandlerResources>;
|
|
34
|
+
/**
|
|
35
|
+
* The inverse of `preload`: dispose the resources it returned (revoke the
|
|
36
|
+
* object URL). Omitted = the kind acquires nothing disposable.
|
|
37
|
+
*/
|
|
38
|
+
release?(resources: KindHandlerResources): void;
|
|
28
39
|
}
|
|
29
|
-
|
|
30
|
-
* Entry kinds whose delivered file is retained as an object URL by
|
|
31
|
-
* `preload()` while held. A chroma-key-video's own `src` is a video file, so
|
|
32
|
-
* it retains too; its inlined mask/fallback entries are `image` kind and
|
|
33
|
-
* follow the image handler via the source walk.
|
|
34
|
-
*/
|
|
35
|
-
declare const RETAINED_KINDS: ReadonlySet<string>;
|
|
40
|
+
export declare const RETAINED_KINDS: ReadonlySet<string>;
|
|
36
41
|
/**
|
|
37
42
|
* Whether a source of `kind` decodes under the given per-kind preload options
|
|
38
43
|
* (options are namespaced per plugin type, like `plugins.<type>` in
|
|
39
44
|
* the config). Image-backed kinds decode by default; each kind opts out
|
|
40
45
|
* independently (`{ image: { decode: false } }` leaves slices decoding).
|
|
41
46
|
*/
|
|
42
|
-
declare function shouldDecode(kind: string, options: PreloadOptions): boolean;
|
|
47
|
+
export declare function shouldDecode(kind: string, options: PreloadOptions): boolean;
|
|
43
48
|
/** The runtime handler owning `kind`'s preload/release strategy (fallback for unknown kinds). */
|
|
44
|
-
declare function runtimeHandlerFor(kind: string): KindRuntimeHandler;
|
|
45
|
-
//#endregion
|
|
46
|
-
export { KindHandlerResources, KindRuntimeHandler, RETAINED_KINDS, audioSourceOf, runtimeHandlerFor, shouldDecode };
|
|
49
|
+
export declare function runtimeHandlerFor(kind: string): KindRuntimeHandler;
|
|
@@ -1,86 +1,104 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { plugins } from '../core/plugins/registry.js';
|
|
2
|
+
import { resolveRetainedSource } from './preload-registry.js';
|
|
3
3
|
/** The playable URL hosts feed to their own audio engine. */
|
|
4
|
-
function audioSourceOf(entry) {
|
|
5
|
-
|
|
4
|
+
export function audioSourceOf(entry) {
|
|
5
|
+
return resolveRetainedSource(entry.src);
|
|
6
6
|
}
|
|
7
7
|
/** Entry kinds whose delivered file is an image the browser can pre-decode. */
|
|
8
|
-
const IMAGE_BACKED_KINDS = new Set([
|
|
8
|
+
const IMAGE_BACKED_KINDS = new Set(['image', 'slice']);
|
|
9
9
|
/**
|
|
10
|
-
* Entry kinds whose delivered file is retained as an object URL by
|
|
11
|
-
* `preload()` while held. A chroma-key-video's own `src` is a video file, so
|
|
12
|
-
* it retains too; its inlined mask/fallback entries are `image` kind and
|
|
13
|
-
* follow the image handler via the source walk.
|
|
14
|
-
*/
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
* Entry kinds whose delivered file is retained as an object URL by
|
|
11
|
+
* `preload()` while held. A chroma-key-video's own `src` is a video file, so
|
|
12
|
+
* it retains too; its inlined mask/fallback entries are `image` kind and
|
|
13
|
+
* follow the image handler via the source walk.
|
|
14
|
+
*/
|
|
15
|
+
const RETAINED_KIND_CATALOGUE = new Set([
|
|
16
|
+
'video',
|
|
17
|
+
'chroma-key-video',
|
|
18
|
+
'audio'
|
|
19
19
|
]);
|
|
20
|
+
export const RETAINED_KINDS = new Set([...RETAINED_KIND_CATALOGUE].filter((kind) => plugins.has(kind)));
|
|
20
21
|
/**
|
|
21
|
-
* Whether a source of `kind` decodes under the given per-kind preload options
|
|
22
|
-
* (options are namespaced per plugin type, like `plugins.<type>` in
|
|
23
|
-
* the config). Image-backed kinds decode by default; each kind opts out
|
|
24
|
-
* independently (`{ image: { decode: false } }` leaves slices decoding).
|
|
25
|
-
*/
|
|
26
|
-
function shouldDecode(kind, options) {
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
* Whether a source of `kind` decodes under the given per-kind preload options
|
|
23
|
+
* (options are namespaced per plugin type, like `plugins.<type>` in
|
|
24
|
+
* the config). Image-backed kinds decode by default; each kind opts out
|
|
25
|
+
* independently (`{ image: { decode: false } }` leaves slices decoding).
|
|
26
|
+
*/
|
|
27
|
+
export function shouldDecode(kind, options) {
|
|
28
|
+
if (!IMAGE_BACKED_KINDS.has(kind))
|
|
29
|
+
return false;
|
|
30
|
+
// The image-backed check above narrows the kind — only these carry `decode`.
|
|
31
|
+
const kindOptions = options[kind];
|
|
32
|
+
return kindOptions?.decode ?? true;
|
|
29
33
|
}
|
|
30
34
|
/** Fetch a source, throwing a uniform error on a non-OK response. */
|
|
31
35
|
async function fetchCompletely(url) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
const response = await fetch(url);
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
throw new Error(`Preloading "${url}" failed: ${response.status} ${response.statusText}.`);
|
|
39
|
+
}
|
|
40
|
+
return response;
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
|
-
* The image-backed strategy (image, slice): fetch the full file, then decode
|
|
38
|
-
* by default. Decoding goes via an HTMLImageElement where a DOM exists (the
|
|
39
|
-
* browser serves the bytes from cache); headless environments (Node tests,
|
|
40
|
-
* SSR) skip decoding. Nothing to release — the browser cache owns the bytes.
|
|
41
|
-
*/
|
|
43
|
+
* The image-backed strategy (image, slice): fetch the full file, then decode
|
|
44
|
+
* by default. Decoding goes via an HTMLImageElement where a DOM exists (the
|
|
45
|
+
* browser serves the bytes from cache); headless environments (Node tests,
|
|
46
|
+
* SSR) skip decoding. Nothing to release — the browser cache owns the bytes.
|
|
47
|
+
*/
|
|
42
48
|
function imageBackedHandler(kind) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
return {
|
|
50
|
+
async preload(url, options) {
|
|
51
|
+
const response = await fetchCompletely(url);
|
|
52
|
+
// Read the body fully so the file is actually transferred (and
|
|
53
|
+
// cached), not just the response headers.
|
|
54
|
+
await response.arrayBuffer();
|
|
55
|
+
if (shouldDecode(kind, options) && typeof globalThis.Image === 'function') {
|
|
56
|
+
const image = new globalThis.Image();
|
|
57
|
+
image.src = url;
|
|
58
|
+
await image.decode();
|
|
59
|
+
}
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
52
63
|
}
|
|
53
64
|
/**
|
|
54
|
-
* The retained-media strategy (video, chroma-key-video, audio): fetch the
|
|
55
|
-
* full file and retain it as an object URL so later playback does not touch
|
|
56
|
-
* the network. Release revokes the URL, freeing the
|
|
57
|
-
* retained memory. Environments without object URLs (SSR) still fetch fully
|
|
58
|
-
* but retain nothing.
|
|
59
|
-
*/
|
|
65
|
+
* The retained-media strategy (video, chroma-key-video, audio): fetch the
|
|
66
|
+
* full file and retain it as an object URL so later playback does not touch
|
|
67
|
+
* the network. Release revokes the URL, freeing the
|
|
68
|
+
* retained memory. Environments without object URLs (SSR) still fetch fully
|
|
69
|
+
* but retain nothing.
|
|
70
|
+
*/
|
|
60
71
|
const retainedMediaHandler = {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
async preload(url) {
|
|
73
|
+
const response = await fetchCompletely(url);
|
|
74
|
+
const blob = await response.blob();
|
|
75
|
+
if (typeof URL.createObjectURL !== 'function')
|
|
76
|
+
return {};
|
|
77
|
+
return { objectUrl: URL.createObjectURL(blob) };
|
|
78
|
+
},
|
|
79
|
+
release(resources) {
|
|
80
|
+
if (resources.objectUrl !== undefined && typeof URL.revokeObjectURL === 'function') {
|
|
81
|
+
URL.revokeObjectURL(resources.objectUrl);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
69
84
|
};
|
|
70
85
|
/** Fallback for kinds without a registered handler: plain full fetch. */
|
|
71
|
-
const unknownKindHandler = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
const unknownKindHandler = {
|
|
87
|
+
async preload(url) {
|
|
88
|
+
await (await fetchCompletely(url)).arrayBuffer();
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const runtimeHandlerCatalogue = {
|
|
93
|
+
image: imageBackedHandler('image'),
|
|
94
|
+
slice: imageBackedHandler('slice'),
|
|
95
|
+
video: retainedMediaHandler,
|
|
96
|
+
'chroma-key-video': retainedMediaHandler,
|
|
97
|
+
audio: retainedMediaHandler
|
|
98
|
+
};
|
|
99
|
+
/** The runtime facets of the centrally registered plugins. */
|
|
100
|
+
const handlerByKind = new Map(Object.entries(plugins.project(runtimeHandlerCatalogue, 'runtime handler')));
|
|
81
101
|
/** The runtime handler owning `kind`'s preload/release strategy (fallback for unknown kinds). */
|
|
82
|
-
function runtimeHandlerFor(kind) {
|
|
83
|
-
|
|
102
|
+
export function runtimeHandlerFor(kind) {
|
|
103
|
+
return handlerByKind.get(kind) ?? unknownKindHandler;
|
|
84
104
|
}
|
|
85
|
-
//#endregion
|
|
86
|
-
export { RETAINED_KINDS, audioSourceOf, runtimeHandlerFor, shouldDecode };
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The runtime manifest: generated modules call `createManifest` with data-only
|
|
3
|
+
* entries, and the entries become direct, typed, readonly properties
|
|
4
|
+
* — no global registry, no string keys, a removed asset is a compile error.
|
|
5
|
+
*
|
|
6
|
+
* `Manifest` owns only kind-agnostic orchestration — entry-source collection
|
|
7
|
+
* (including inlined reference entries), URL dedup, in-flight/idempotency.
|
|
8
|
+
* How each kind actually loads (decode, retention) is the per-kind runtime
|
|
9
|
+
* handler's strategy — see kind-handlers.ts.
|
|
10
|
+
*/
|
|
11
|
+
import type { ManifestEntry, PreloadOptions } from '../core/index.js';
|
|
4
12
|
/** One deliverable file of an entry: its URL and the owning entry's kind. */
|
|
5
|
-
interface EntrySource {
|
|
6
|
-
|
|
7
|
-
|
|
13
|
+
export interface EntrySource {
|
|
14
|
+
url: string;
|
|
15
|
+
kind: string;
|
|
8
16
|
}
|
|
9
17
|
/**
|
|
10
18
|
* Collect every deliverable URL of an entry, including the entries codegen
|
|
@@ -12,49 +20,47 @@ interface EntrySource {
|
|
|
12
20
|
* a string `kind` is an entry, and its `src` (when present) is a source.
|
|
13
21
|
* Generic by design: adding a kind does not change preload orchestration.
|
|
14
22
|
*/
|
|
15
|
-
declare function collectEntrySources(entry: ManifestEntry): EntrySource[];
|
|
16
|
-
declare class Manifest {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
23
|
+
export declare function collectEntrySources(entry: ManifestEntry): EntrySource[];
|
|
24
|
+
export declare class Manifest {
|
|
25
|
+
#private;
|
|
26
|
+
constructor(entries: Record<string, ManifestEntry>);
|
|
27
|
+
/**
|
|
28
|
+
* Fetch every deliverable file of this manifest up front — including the
|
|
29
|
+
* reference closure, which codegen inlined into the entries — and decode
|
|
30
|
+
* image-backed entries. Options are namespaced per asset kind, mirroring
|
|
31
|
+
* `plugins.<type>` in the config: `{ image: { decode: false } }`
|
|
32
|
+
* skips decoding for image entries only; slices keep decoding unless
|
|
33
|
+
* `slice: { decode: false }` is passed too. An option applies to every
|
|
34
|
+
* entry of its kind, inlined reference entries included.
|
|
35
|
+
*
|
|
36
|
+
* Idempotent and concurrent-safe: one in-flight promise per manifest; a
|
|
37
|
+
* second call joins it (or resolves immediately once done), and URLs shared
|
|
38
|
+
* by several entries are fetched once. Sharing goes further than this
|
|
39
|
+
* manifest: every URL is acquired through the module-wide refcounted
|
|
40
|
+
* registry, so a URL another manifest already preloaded (or is preloading)
|
|
41
|
+
* is never fetched again — this manifest just takes a hold on it. A failed
|
|
42
|
+
* preload rolls back this manifest's holds and clears the in-flight state
|
|
43
|
+
* so it can be retried. A joined call's options are ignored: options apply
|
|
44
|
+
* per preload run (the first call after construction or `release()`).
|
|
45
|
+
*/
|
|
46
|
+
preload(options?: PreloadOptions): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Drop this manifest's holds on everything it preloaded. Assets shared
|
|
49
|
+
* with another preloaded manifest stay fully alive for that holder; assets
|
|
50
|
+
* nobody holds anymore are disposed via their kind's release strategy
|
|
51
|
+
* (retained media object URLs are revoked, freeing the memory). Consumers
|
|
52
|
+
* of a fully released source fall back to its network URL.
|
|
53
|
+
*
|
|
54
|
+
* Safe in every state: before or without `preload()` it is a no-op, and
|
|
55
|
+
* calling it while a `preload()` is still in flight drops the holds
|
|
56
|
+
* without cancelling — when the in-flight load completes unheld, the
|
|
57
|
+
* registry disposes it immediately (no leak). Afterwards the manifest's
|
|
58
|
+
* preload state is reset, so a later `preload()` re-acquires from scratch.
|
|
59
|
+
*/
|
|
60
|
+
release(): void;
|
|
53
61
|
}
|
|
54
62
|
/**
|
|
55
63
|
* Construct a manifest whose entries are direct readonly properties:
|
|
56
64
|
* `mainCatalog.navigationPanel` is fully typed, and a typo is a compile error.
|
|
57
65
|
*/
|
|
58
|
-
declare function createManifest<T extends Record<string, ManifestEntry>>(entries: T): Manifest & Readonly<T>;
|
|
59
|
-
//#endregion
|
|
60
|
-
export { EntrySource, Manifest, collectEntrySources, createManifest };
|
|
66
|
+
export declare function createManifest<T extends Record<string, ManifestEntry>>(entries: T): Manifest & Readonly<T>;
|
package/dist/runtime/manifest.js
CHANGED
|
@@ -1,117 +1,137 @@
|
|
|
1
|
-
import { acquireSource, releaseSource } from
|
|
2
|
-
//#region src/manifest.ts
|
|
1
|
+
import { acquireSource, releaseSource } from './preload-registry.js';
|
|
3
2
|
/**
|
|
4
|
-
* Collect every deliverable URL of an entry, including the entries codegen
|
|
5
|
-
* inlined in place of asset references: any nested object carrying
|
|
6
|
-
* a string `kind` is an entry, and its `src` (when present) is a source.
|
|
7
|
-
* Generic by design: adding a kind does not change preload orchestration.
|
|
8
|
-
*/
|
|
9
|
-
function collectEntrySources(entry) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
3
|
+
* Collect every deliverable URL of an entry, including the entries codegen
|
|
4
|
+
* inlined in place of asset references: any nested object carrying
|
|
5
|
+
* a string `kind` is an entry, and its `src` (when present) is a source.
|
|
6
|
+
* Generic by design: adding a kind does not change preload orchestration.
|
|
7
|
+
*/
|
|
8
|
+
export function collectEntrySources(entry) {
|
|
9
|
+
const sources = [];
|
|
10
|
+
visit(entry);
|
|
11
|
+
return sources;
|
|
12
|
+
function visit(value) {
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
for (const element of value)
|
|
15
|
+
visit(element);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value !== 'object' || value === null)
|
|
19
|
+
return;
|
|
20
|
+
const record = value;
|
|
21
|
+
if (typeof record.kind === 'string' && typeof record.src === 'string') {
|
|
22
|
+
sources.push({ url: record.src, kind: record.kind });
|
|
23
|
+
}
|
|
24
|
+
for (const nested of Object.values(record))
|
|
25
|
+
visit(nested);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class Manifest {
|
|
29
|
+
#entries;
|
|
30
|
+
#preloading = null;
|
|
31
|
+
/**
|
|
32
|
+
* URLs this manifest currently holds in the module-wide registry (each
|
|
33
|
+
* held at most once — the registry's reference count counts holding
|
|
34
|
+
* manifests, not preload calls). Replaced wholesale by `release()`: an
|
|
35
|
+
* in-flight preload run keeps operating on the set object it captured, so
|
|
36
|
+
* a release during the run (which drains that set) turns the run's own
|
|
37
|
+
* failure rollback into a no-op instead of a double release.
|
|
38
|
+
*/
|
|
39
|
+
#heldUrls = new Set();
|
|
40
|
+
constructor(entries) {
|
|
41
|
+
for (const key of Object.keys(entries)) {
|
|
42
|
+
// Belt-and-braces with core's reserved-id check: codegen validates ids, but a
|
|
43
|
+
// hand-written call must not silently shadow a class member either.
|
|
44
|
+
if (key in this) {
|
|
45
|
+
throw new Error(`Manifest entry id "${key}" collides with a Manifest member.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
Object.assign(this, entries);
|
|
49
|
+
this.#entries = entries;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Fetch every deliverable file of this manifest up front — including the
|
|
53
|
+
* reference closure, which codegen inlined into the entries — and decode
|
|
54
|
+
* image-backed entries. Options are namespaced per asset kind, mirroring
|
|
55
|
+
* `plugins.<type>` in the config: `{ image: { decode: false } }`
|
|
56
|
+
* skips decoding for image entries only; slices keep decoding unless
|
|
57
|
+
* `slice: { decode: false }` is passed too. An option applies to every
|
|
58
|
+
* entry of its kind, inlined reference entries included.
|
|
59
|
+
*
|
|
60
|
+
* Idempotent and concurrent-safe: one in-flight promise per manifest; a
|
|
61
|
+
* second call joins it (or resolves immediately once done), and URLs shared
|
|
62
|
+
* by several entries are fetched once. Sharing goes further than this
|
|
63
|
+
* manifest: every URL is acquired through the module-wide refcounted
|
|
64
|
+
* registry, so a URL another manifest already preloaded (or is preloading)
|
|
65
|
+
* is never fetched again — this manifest just takes a hold on it. A failed
|
|
66
|
+
* preload rolls back this manifest's holds and clears the in-flight state
|
|
67
|
+
* so it can be retried. A joined call's options are ignored: options apply
|
|
68
|
+
* per preload run (the first call after construction or `release()`).
|
|
69
|
+
*/
|
|
70
|
+
preload(options = {}) {
|
|
71
|
+
if (!this.#preloading) {
|
|
72
|
+
const tracked = this.#preloadAll(options, this.#heldUrls).catch((cause) => {
|
|
73
|
+
// Reset for retry — unless release() or a follow-up preload()
|
|
74
|
+
// already superseded this run while it was in flight.
|
|
75
|
+
if (this.#preloading === tracked)
|
|
76
|
+
this.#preloading = null;
|
|
77
|
+
throw cause;
|
|
78
|
+
});
|
|
79
|
+
this.#preloading = tracked;
|
|
80
|
+
}
|
|
81
|
+
return this.#preloading;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Drop this manifest's holds on everything it preloaded. Assets shared
|
|
85
|
+
* with another preloaded manifest stay fully alive for that holder; assets
|
|
86
|
+
* nobody holds anymore are disposed via their kind's release strategy
|
|
87
|
+
* (retained media object URLs are revoked, freeing the memory). Consumers
|
|
88
|
+
* of a fully released source fall back to its network URL.
|
|
89
|
+
*
|
|
90
|
+
* Safe in every state: before or without `preload()` it is a no-op, and
|
|
91
|
+
* calling it while a `preload()` is still in flight drops the holds
|
|
92
|
+
* without cancelling — when the in-flight load completes unheld, the
|
|
93
|
+
* registry disposes it immediately (no leak). Afterwards the manifest's
|
|
94
|
+
* preload state is reset, so a later `preload()` re-acquires from scratch.
|
|
95
|
+
*/
|
|
96
|
+
release() {
|
|
97
|
+
const held = this.#heldUrls;
|
|
98
|
+
this.#heldUrls = new Set();
|
|
99
|
+
this.#preloading = null;
|
|
100
|
+
for (const url of held)
|
|
101
|
+
releaseSource(url);
|
|
102
|
+
// Drain the old set so an in-flight run's failure rollback (which
|
|
103
|
+
// captured it) finds nothing left to release.
|
|
104
|
+
held.clear();
|
|
105
|
+
}
|
|
106
|
+
async #preloadAll(options, held) {
|
|
107
|
+
const kindByUrl = new Map();
|
|
108
|
+
for (const entry of Object.values(this.#entries)) {
|
|
109
|
+
for (const source of collectEntrySources(entry)) {
|
|
110
|
+
if (!kindByUrl.has(source.url))
|
|
111
|
+
kindByUrl.set(source.url, source.kind);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const acquisitions = [];
|
|
115
|
+
for (const [url, kind] of kindByUrl) {
|
|
116
|
+
held.add(url);
|
|
117
|
+
acquisitions.push(acquireSource(url, kind, options));
|
|
118
|
+
}
|
|
119
|
+
const outcomes = await Promise.allSettled(acquisitions);
|
|
120
|
+
const failure = outcomes.find((outcome) => outcome.status === 'rejected');
|
|
121
|
+
if (failure) {
|
|
122
|
+
// Roll back every hold of this run — unless release() already
|
|
123
|
+
// dropped them mid-flight (it drains the captured set).
|
|
124
|
+
for (const url of held)
|
|
125
|
+
releaseSource(url);
|
|
126
|
+
held.clear();
|
|
127
|
+
throw failure.reason;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
26
130
|
}
|
|
27
|
-
var Manifest = class {
|
|
28
|
-
#entries;
|
|
29
|
-
#preloading = null;
|
|
30
|
-
/**
|
|
31
|
-
* URLs this manifest currently holds in the module-wide registry (each
|
|
32
|
-
* held at most once — the registry's reference count counts holding
|
|
33
|
-
* manifests, not preload calls). Replaced wholesale by `release()`: an
|
|
34
|
-
* in-flight preload run keeps operating on the set object it captured, so
|
|
35
|
-
* a release during the run (which drains that set) turns the run's own
|
|
36
|
-
* failure rollback into a no-op instead of a double release.
|
|
37
|
-
*/
|
|
38
|
-
#heldUrls = /* @__PURE__ */ new Set();
|
|
39
|
-
constructor(entries) {
|
|
40
|
-
for (const key of Object.keys(entries)) if (key in this) throw new Error(`Manifest entry id "${key}" collides with a Manifest member.`);
|
|
41
|
-
Object.assign(this, entries);
|
|
42
|
-
this.#entries = entries;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Fetch every deliverable file of this manifest up front — including the
|
|
46
|
-
* reference closure, which codegen inlined into the entries — and decode
|
|
47
|
-
* image-backed entries. Options are namespaced per asset kind, mirroring
|
|
48
|
-
* `plugins.<type>` in the config: `{ image: { decode: false } }`
|
|
49
|
-
* skips decoding for image entries only; slices keep decoding unless
|
|
50
|
-
* `slice: { decode: false }` is passed too. An option applies to every
|
|
51
|
-
* entry of its kind, inlined reference entries included.
|
|
52
|
-
*
|
|
53
|
-
* Idempotent and concurrent-safe: one in-flight promise per manifest; a
|
|
54
|
-
* second call joins it (or resolves immediately once done), and URLs shared
|
|
55
|
-
* by several entries are fetched once. Sharing goes further than this
|
|
56
|
-
* manifest: every URL is acquired through the module-wide refcounted
|
|
57
|
-
* registry, so a URL another manifest already preloaded (or is preloading)
|
|
58
|
-
* is never fetched again — this manifest just takes a hold on it. A failed
|
|
59
|
-
* preload rolls back this manifest's holds and clears the in-flight state
|
|
60
|
-
* so it can be retried. A joined call's options are ignored: options apply
|
|
61
|
-
* per preload run (the first call after construction or `release()`).
|
|
62
|
-
*/
|
|
63
|
-
preload(options = {}) {
|
|
64
|
-
if (!this.#preloading) {
|
|
65
|
-
const tracked = this.#preloadAll(options, this.#heldUrls).catch((cause) => {
|
|
66
|
-
if (this.#preloading === tracked) this.#preloading = null;
|
|
67
|
-
throw cause;
|
|
68
|
-
});
|
|
69
|
-
this.#preloading = tracked;
|
|
70
|
-
}
|
|
71
|
-
return this.#preloading;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Drop this manifest's holds on everything it preloaded. Assets shared
|
|
75
|
-
* with another preloaded manifest stay fully alive for that holder; assets
|
|
76
|
-
* nobody holds anymore are disposed via their kind's release strategy
|
|
77
|
-
* (retained media object URLs are revoked, freeing the memory). Consumers
|
|
78
|
-
* of a fully released source fall back to its network URL.
|
|
79
|
-
*
|
|
80
|
-
* Safe in every state: before or without `preload()` it is a no-op, and
|
|
81
|
-
* calling it while a `preload()` is still in flight drops the holds
|
|
82
|
-
* without cancelling — when the in-flight load completes unheld, the
|
|
83
|
-
* registry disposes it immediately (no leak). Afterwards the manifest's
|
|
84
|
-
* preload state is reset, so a later `preload()` re-acquires from scratch.
|
|
85
|
-
*/
|
|
86
|
-
release() {
|
|
87
|
-
const held = this.#heldUrls;
|
|
88
|
-
this.#heldUrls = /* @__PURE__ */ new Set();
|
|
89
|
-
this.#preloading = null;
|
|
90
|
-
for (const url of held) releaseSource(url);
|
|
91
|
-
held.clear();
|
|
92
|
-
}
|
|
93
|
-
async #preloadAll(options, held) {
|
|
94
|
-
const kindByUrl = /* @__PURE__ */ new Map();
|
|
95
|
-
for (const entry of Object.values(this.#entries)) for (const source of collectEntrySources(entry)) if (!kindByUrl.has(source.url)) kindByUrl.set(source.url, source.kind);
|
|
96
|
-
const acquisitions = [];
|
|
97
|
-
for (const [url, kind] of kindByUrl) {
|
|
98
|
-
held.add(url);
|
|
99
|
-
acquisitions.push(acquireSource(url, kind, options));
|
|
100
|
-
}
|
|
101
|
-
const failure = (await Promise.allSettled(acquisitions)).find((outcome) => outcome.status === "rejected");
|
|
102
|
-
if (failure) {
|
|
103
|
-
for (const url of held) releaseSource(url);
|
|
104
|
-
held.clear();
|
|
105
|
-
throw failure.reason;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
131
|
/**
|
|
110
|
-
* Construct a manifest whose entries are direct readonly properties:
|
|
111
|
-
* `mainCatalog.navigationPanel` is fully typed, and a typo is a compile error.
|
|
112
|
-
*/
|
|
113
|
-
function createManifest(entries) {
|
|
114
|
-
|
|
132
|
+
* Construct a manifest whose entries are direct readonly properties:
|
|
133
|
+
* `mainCatalog.navigationPanel` is fully typed, and a typo is a compile error.
|
|
134
|
+
*/
|
|
135
|
+
export function createManifest(entries) {
|
|
136
|
+
return new Manifest(entries);
|
|
115
137
|
}
|
|
116
|
-
//#endregion
|
|
117
|
-
export { Manifest, collectEntrySources, createManifest };
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
//#region src/observe-border-box-size.d.ts
|
|
2
1
|
/** Observe an element's layout border-box size in whole CSS pixels. */
|
|
3
|
-
declare function observeBorderBoxSize(element: HTMLElement, onSize: (width: number, height: number) => void): () => void;
|
|
4
|
-
//#endregion
|
|
5
|
-
export { observeBorderBoxSize };
|
|
2
|
+
export declare function observeBorderBoxSize(element: HTMLElement, onSize: (width: number, height: number) => void): () => void;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
//#region src/observe-border-box-size.ts
|
|
2
1
|
/** Observe an element's layout border-box size in whole CSS pixels. */
|
|
3
|
-
function observeBorderBoxSize(element, onSize) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
export function observeBorderBoxSize(element, onSize) {
|
|
3
|
+
const observer = new ResizeObserver((entries) => {
|
|
4
|
+
// Measure layout, not getBoundingClientRect(): transforms must not freeze
|
|
5
|
+
// render geometry after an animation because they do not retrigger resize.
|
|
6
|
+
const size = entries[0]?.borderBoxSize?.[0];
|
|
7
|
+
onSize(Math.round(size?.inlineSize ?? element.offsetWidth), Math.round(size?.blockSize ?? element.offsetHeight));
|
|
8
|
+
});
|
|
9
|
+
observer.observe(element);
|
|
10
|
+
return () => observer.disconnect();
|
|
10
11
|
}
|
|
11
|
-
//#endregion
|
|
12
|
-
export { observeBorderBoxSize };
|