fundus 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/README.md +58 -0
  2. package/build/client/_app/immutable/assets/0.DLhIsYA_.css.br +0 -0
  3. package/build/client/_app/immutable/assets/0.DLhIsYA_.css.gz +0 -0
  4. package/build/client/_app/immutable/assets/2.wavcNhPC.css +1 -0
  5. package/build/client/_app/immutable/assets/2.wavcNhPC.css.br +0 -0
  6. package/build/client/_app/immutable/assets/2.wavcNhPC.css.gz +0 -0
  7. package/build/client/_app/immutable/assets/3.Cjh_fXPY.css +1 -0
  8. package/build/client/_app/immutable/assets/3.Cjh_fXPY.css.br +0 -0
  9. package/build/client/_app/immutable/assets/3.Cjh_fXPY.css.gz +0 -0
  10. package/build/client/_app/immutable/assets/4.p004hmEN.css +1 -0
  11. package/build/client/_app/immutable/assets/4.p004hmEN.css.br +0 -0
  12. package/build/client/_app/immutable/assets/4.p004hmEN.css.gz +0 -0
  13. package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css +1 -0
  14. package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css.br +0 -0
  15. package/build/client/_app/immutable/assets/ConfirmDialog.BdKlitwi.css.gz +0 -0
  16. package/build/client/_app/immutable/assets/LibraryContextMenu.zyZtpKzC.css +1 -0
  17. package/build/client/_app/immutable/assets/LibraryContextMenu.zyZtpKzC.css.br +0 -0
  18. package/build/client/_app/immutable/assets/LibraryContextMenu.zyZtpKzC.css.gz +0 -0
  19. package/build/client/_app/immutable/chunks/BiIto6ft.js +1 -0
  20. package/build/client/_app/immutable/chunks/BiIto6ft.js.br +0 -0
  21. package/build/client/_app/immutable/chunks/BiIto6ft.js.gz +0 -0
  22. package/build/client/_app/immutable/chunks/Bjy-W4x2.js.br +0 -0
  23. package/build/client/_app/immutable/chunks/Bjy-W4x2.js.gz +0 -0
  24. package/build/client/_app/immutable/chunks/CNRz3sSw.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/CNRz3sSw.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/CO4RBJfa.js.br +0 -0
  27. package/build/client/_app/immutable/chunks/CO4RBJfa.js.gz +0 -0
  28. package/{dist/editor/_app/immutable/chunks/DjvOiDmq.js → build/client/_app/immutable/chunks/CvY6YsFE.js} +1 -1
  29. package/build/client/_app/immutable/chunks/CvY6YsFE.js.br +0 -0
  30. package/build/client/_app/immutable/chunks/CvY6YsFE.js.gz +0 -0
  31. package/build/client/_app/immutable/chunks/DL0_39Ys.js +5 -0
  32. package/build/client/_app/immutable/chunks/DL0_39Ys.js.br +0 -0
  33. package/build/client/_app/immutable/chunks/DL0_39Ys.js.gz +0 -0
  34. package/{dist/editor/_app/immutable/chunks/BfPE5wdt.js → build/client/_app/immutable/chunks/DQ8SXFaX.js} +1 -1
  35. package/build/client/_app/immutable/chunks/DQ8SXFaX.js.br +0 -0
  36. package/build/client/_app/immutable/chunks/DQ8SXFaX.js.gz +0 -0
  37. package/build/client/_app/immutable/chunks/DjdrdRzT.js.br +0 -0
  38. package/build/client/_app/immutable/chunks/DjdrdRzT.js.gz +0 -0
  39. package/build/client/_app/immutable/chunks/xihTtKlq.js.br +1 -0
  40. package/build/client/_app/immutable/chunks/xihTtKlq.js.gz +0 -0
  41. package/{dist/editor/_app/immutable/entry/app.BkqbfI8n.js → build/client/_app/immutable/entry/app.ubN0v9bN.js} +2 -2
  42. package/build/client/_app/immutable/entry/app.ubN0v9bN.js.br +0 -0
  43. package/build/client/_app/immutable/entry/app.ubN0v9bN.js.gz +0 -0
  44. package/build/client/_app/immutable/entry/start.BW8dBDh6.js +1 -0
  45. package/build/client/_app/immutable/entry/start.BW8dBDh6.js.br +0 -0
  46. package/build/client/_app/immutable/entry/start.BW8dBDh6.js.gz +0 -0
  47. package/{dist/editor/_app/immutable/nodes/0.xdMI5GEU.js → build/client/_app/immutable/nodes/0.Dr5ijCIl.js} +1 -1
  48. package/build/client/_app/immutable/nodes/0.Dr5ijCIl.js.br +0 -0
  49. package/build/client/_app/immutable/nodes/0.Dr5ijCIl.js.gz +0 -0
  50. package/{dist/editor/_app/immutable/nodes/1.D9p2tfoJ.js → build/client/_app/immutable/nodes/1.DiIGIRAb.js} +1 -1
  51. package/build/client/_app/immutable/nodes/1.DiIGIRAb.js.br +3 -0
  52. package/build/client/_app/immutable/nodes/1.DiIGIRAb.js.gz +0 -0
  53. package/{dist/editor/_app/immutable/nodes/2.BrA0Hyzu.js → build/client/_app/immutable/nodes/2.B8KYmQcV.js} +3 -3
  54. package/build/client/_app/immutable/nodes/2.B8KYmQcV.js.br +0 -0
  55. package/build/client/_app/immutable/nodes/2.B8KYmQcV.js.gz +0 -0
  56. package/build/client/_app/immutable/nodes/3.B1jc7arT.js +104 -0
  57. package/build/client/_app/immutable/nodes/3.B1jc7arT.js.br +0 -0
  58. package/build/client/_app/immutable/nodes/3.B1jc7arT.js.gz +0 -0
  59. package/build/client/_app/immutable/nodes/4.BPK9n1mH.js +2 -0
  60. package/build/client/_app/immutable/nodes/4.BPK9n1mH.js.br +0 -0
  61. package/build/client/_app/immutable/nodes/4.BPK9n1mH.js.gz +0 -0
  62. package/build/client/_app/version.json +1 -0
  63. package/build/client/_app/version.json.br +0 -0
  64. package/build/client/_app/version.json.gz +0 -0
  65. package/build/env.js +100 -0
  66. package/build/env.js.map +1 -0
  67. package/build/handler.js +22 -0
  68. package/build/handler.js.map +1 -0
  69. package/build/index.js +145 -0
  70. package/build/index.js.map +1 -0
  71. package/build/server/chunks/chunks/context.js-Bw4WWLhG.js +443 -0
  72. package/build/server/chunks/chunks/context.js-Bw4WWLhG.js.map +1 -0
  73. package/build/server/chunks/chunks/core.js-DDntpb72.js +409 -0
  74. package/build/server/chunks/chunks/core.js-DDntpb72.js.map +1 -0
  75. package/build/server/chunks/chunks/env.js-l0sNRNKZ.js +2 -0
  76. package/build/server/chunks/chunks/env.js-l0sNRNKZ.js.map +1 -0
  77. package/build/server/chunks/chunks/exports.js-CLTzaOxn.js +152 -0
  78. package/build/server/chunks/chunks/exports.js-CLTzaOxn.js.map +1 -0
  79. package/build/server/chunks/chunks/folder-path.js-ytx9ucgg.js +64 -0
  80. package/build/server/chunks/chunks/folder-path.js-ytx9ucgg.js.map +1 -0
  81. package/build/server/chunks/chunks/http.js-Dxoa-jtP.js +100 -0
  82. package/build/server/chunks/chunks/http.js-Dxoa-jtP.js.map +1 -0
  83. package/build/server/chunks/chunks/internal.js-BDBSzJId.js +5753 -0
  84. package/build/server/chunks/chunks/internal.js-BDBSzJId.js.map +1 -0
  85. package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js +22 -0
  86. package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -0
  87. package/{dist/operations-DYM-5KVl.js → build/server/chunks/chunks/library-store.js-BP8cL-qD.js} +344 -444
  88. package/build/server/chunks/chunks/library-store.js-BP8cL-qD.js.map +1 -0
  89. package/build/server/chunks/chunks/manifest-appearance.js-DTk355LQ.js +146 -0
  90. package/build/server/chunks/chunks/manifest-appearance.js-DTk355LQ.js.map +1 -0
  91. package/build/server/chunks/chunks/routing.js-y-tryuip.js +213 -0
  92. package/build/server/chunks/chunks/routing.js-y-tryuip.js.map +1 -0
  93. package/build/server/chunks/chunks/shared.js-BWXgl1Xf.js +255 -0
  94. package/build/server/chunks/chunks/shared.js-BWXgl1Xf.js.map +1 -0
  95. package/build/server/chunks/chunks/utils.js-9oI5Oz0w.js +1048 -0
  96. package/build/server/chunks/chunks/utils.js-9oI5Oz0w.js.map +1 -0
  97. package/build/server/chunks/entries/endpoints/api/_...path_/_server.ts.js-WknZVW_S.js +27 -0
  98. package/build/server/chunks/entries/endpoints/api/_...path_/_server.ts.js-WknZVW_S.js.map +1 -0
  99. package/build/server/chunks/entries/endpoints/api/assets/_id_/_server.ts.js-BrZ__-HZ.js +24 -0
  100. package/build/server/chunks/entries/endpoints/api/assets/_id_/_server.ts.js-BrZ__-HZ.js.map +1 -0
  101. package/build/server/chunks/entries/endpoints/api/assets/_server.ts.js-PqADGPXc.js +45 -0
  102. package/build/server/chunks/entries/endpoints/api/assets/_server.ts.js-PqADGPXc.js.map +1 -0
  103. package/build/server/chunks/entries/endpoints/api/assets/delete/_server.ts.js-OqoE5PN-.js +31 -0
  104. package/build/server/chunks/entries/endpoints/api/assets/delete/_server.ts.js-OqoE5PN-.js.map +1 -0
  105. package/build/server/chunks/entries/endpoints/api/assets/move/_server.ts.js-CJ08e1ho.js +31 -0
  106. package/build/server/chunks/entries/endpoints/api/assets/move/_server.ts.js-CJ08e1ho.js.map +1 -0
  107. package/build/server/chunks/entries/endpoints/api/folders/_path_/_server.ts.js-DdF3eK2I.js +38 -0
  108. package/build/server/chunks/entries/endpoints/api/folders/_path_/_server.ts.js-DdF3eK2I.js.map +1 -0
  109. package/build/server/chunks/entries/endpoints/api/folders/_server.ts.js-Cxt6jsJ5.js +31 -0
  110. package/build/server/chunks/entries/endpoints/api/folders/_server.ts.js-Cxt6jsJ5.js.map +1 -0
  111. package/build/server/chunks/entries/endpoints/api/manifests/_name_/_server.ts.js-BWVM2Ntl.js +24 -0
  112. package/build/server/chunks/entries/endpoints/api/manifests/_name_/_server.ts.js-BWVM2Ntl.js.map +1 -0
  113. package/build/server/chunks/entries/endpoints/api/manifests/_server.ts.js-Z2bM-qHM.js +31 -0
  114. package/build/server/chunks/entries/endpoints/api/manifests/_server.ts.js-Z2bM-qHM.js.map +1 -0
  115. package/build/server/chunks/entries/endpoints/api/state/_server.ts.js-BX9H2Z34.js +24 -0
  116. package/build/server/chunks/entries/endpoints/api/state/_server.ts.js-BX9H2Z34.js.map +1 -0
  117. package/build/server/chunks/entries/endpoints/files/_...path_/_server.ts.js-BWHDZ8mz.js +27 -0
  118. package/build/server/chunks/entries/endpoints/files/_...path_/_server.ts.js-BWHDZ8mz.js.map +1 -0
  119. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/_server.ts.js-CR_7mndO.js +24 -0
  120. package/build/server/chunks/entries/endpoints/files/proxy/_...path_/_server.ts.js-CR_7mndO.js.map +1 -0
  121. package/build/server/chunks/entries/endpoints/files/raw/_...path_/_server.ts.js-Cw1PDBvb.js +24 -0
  122. package/build/server/chunks/entries/endpoints/files/raw/_...path_/_server.ts.js-Cw1PDBvb.js.map +1 -0
  123. package/build/server/chunks/entries/hooks.server.js-BHoE0yBi.js +23 -0
  124. package/build/server/chunks/entries/hooks.server.js-BHoE0yBi.js.map +1 -0
  125. package/build/server/chunks/handler-10cx4zHn.js +1475 -0
  126. package/build/server/chunks/handler-10cx4zHn.js.map +1 -0
  127. package/build/server/chunks/index.js-DvPfiC00.js +3789 -0
  128. package/build/server/chunks/index.js-DvPfiC00.js.map +1 -0
  129. package/build/server/chunks/manifest.js-DoPjUnzD.js +149 -0
  130. package/build/server/chunks/manifest.js-DoPjUnzD.js.map +1 -0
  131. package/build/server/chunks/nodes/0.js-Di3qgAtW.js +11 -0
  132. package/build/server/chunks/nodes/0.js-Di3qgAtW.js.map +1 -0
  133. package/build/server/chunks/nodes/1.js-BlWSFIA8.js +7 -0
  134. package/build/server/chunks/nodes/1.js-BlWSFIA8.js.map +1 -0
  135. package/build/server/chunks/nodes/2.js-CO9nSPUN.js +7 -0
  136. package/build/server/chunks/nodes/2.js-CO9nSPUN.js.map +1 -0
  137. package/build/server/chunks/nodes/3.js-C2D6xpEO.js +7 -0
  138. package/build/server/chunks/nodes/3.js-C2D6xpEO.js.map +1 -0
  139. package/build/server/chunks/nodes/4.js-B3IuagJW.js +7 -0
  140. package/build/server/chunks/nodes/4.js-B3IuagJW.js.map +1 -0
  141. package/build/shims.js +33 -0
  142. package/build/shims.js.map +1 -0
  143. package/dist/cli.d.ts +2 -1
  144. package/dist/cli.js +109 -1332
  145. package/dist/config.d.ts +3 -2
  146. package/dist/config.js +2 -2
  147. package/dist/core/api-types.d.ts +141 -0
  148. package/dist/core/api-types.js +1 -0
  149. package/dist/core/asset-id.d.ts +28 -0
  150. package/dist/core/asset-id.js +59 -0
  151. package/dist/core/asset-reference.d.ts +23 -0
  152. package/dist/core/asset-reference.js +15 -0
  153. package/dist/core/canonicalize.d.ts +9 -0
  154. package/dist/core/canonicalize.js +36 -0
  155. package/dist/core/chroma-key.d.ts +30 -0
  156. package/dist/core/chroma-key.js +55 -0
  157. package/dist/core/config.d.ts +35 -0
  158. package/dist/core/config.js +4 -0
  159. package/dist/core/folder-path.d.ts +19 -0
  160. package/dist/core/folder-path.js +86 -0
  161. package/dist/core/index.d.ts +33 -499
  162. package/dist/core/index.js +17 -962
  163. package/dist/core/ingest.d.ts +18 -0
  164. package/dist/core/ingest.js +58 -0
  165. package/dist/core/library.d.ts +54 -0
  166. package/dist/core/library.js +138 -0
  167. package/dist/core/manifest-appearance.d.ts +35 -0
  168. package/dist/core/manifest-appearance.js +123 -0
  169. package/dist/core/manifest-entry.d.ts +104 -0
  170. package/dist/core/manifest-entry.js +1 -0
  171. package/dist/core/manifest-membership.d.ts +56 -0
  172. package/dist/core/manifest-membership.js +54 -0
  173. package/dist/core/plugins/audio.d.ts +26 -0
  174. package/dist/core/plugins/audio.js +44 -0
  175. package/dist/core/plugins/chroma-key-video.d.ts +29 -0
  176. package/dist/core/plugins/chroma-key-video.js +69 -0
  177. package/dist/core/plugins/contract.d.ts +35 -0
  178. package/dist/core/plugins/contract.js +1 -0
  179. package/dist/core/plugins/image.d.ts +30 -0
  180. package/dist/core/plugins/image.js +45 -0
  181. package/dist/core/plugins/slice.d.ts +22 -0
  182. package/dist/core/plugins/slice.js +60 -0
  183. package/dist/core/plugins/video.d.ts +45 -0
  184. package/dist/core/plugins/video.js +77 -0
  185. package/dist/core/reference-graph.d.ts +41 -0
  186. package/dist/core/reference-graph.js +138 -0
  187. package/dist/core/slice-data.d.ts +61 -0
  188. package/dist/core/slice-data.js +49 -0
  189. package/dist/runtime/chroma-key-gl.d.ts +40 -22
  190. package/dist/runtime/chroma-key-gl.js +189 -183
  191. package/dist/runtime/components/ChromaKeyVideo.svelte +3 -3
  192. package/dist/runtime/components/ChromaKeyVideo.svelte.d.ts +21 -0
  193. package/dist/runtime/components/Image.svelte +1 -1
  194. package/dist/runtime/components/Image.svelte.d.ts +9 -0
  195. package/dist/runtime/components/Slice.svelte +1 -1
  196. package/dist/runtime/components/Slice.svelte.d.ts +19 -0
  197. package/dist/runtime/components/SliceCanvas.svelte +3 -3
  198. package/dist/runtime/components/SliceCanvas.svelte.d.ts +10 -0
  199. package/dist/runtime/components/SliceDom.svelte +3 -3
  200. package/dist/runtime/components/SliceDom.svelte.d.ts +10 -0
  201. package/dist/runtime/components/Video.svelte +2 -2
  202. package/dist/runtime/components/Video.svelte.d.ts +18 -0
  203. package/dist/runtime/geometry.d.ts +55 -35
  204. package/dist/runtime/geometry.js +186 -191
  205. package/dist/runtime/index.d.ts +9 -9
  206. package/dist/runtime/index.js +9 -9
  207. package/dist/runtime/kind-handlers.d.ts +33 -24
  208. package/dist/runtime/kind-handlers.js +74 -65
  209. package/dist/runtime/manifest.d.ts +53 -47
  210. package/dist/runtime/manifest.js +133 -113
  211. package/dist/runtime/observe-border-box-size.d.ts +1 -4
  212. package/dist/runtime/observe-border-box-size.js +9 -10
  213. package/dist/runtime/preload-registry.d.ts +22 -8
  214. package/dist/runtime/preload-registry.js +65 -62
  215. package/dist/server/build.d.ts +8 -0
  216. package/dist/server/build.js +25 -0
  217. package/dist/server/check.d.ts +24 -0
  218. package/dist/server/check.js +199 -0
  219. package/dist/server/cli-commands.d.ts +25 -0
  220. package/dist/server/cli-commands.js +1178 -0
  221. package/dist/server/cli-init.d.ts +3 -0
  222. package/dist/server/cli-init.js +53 -0
  223. package/dist/server/cli-io.d.ts +46 -0
  224. package/dist/server/cli-io.js +105 -0
  225. package/dist/server/codegen.d.ts +58 -0
  226. package/dist/server/codegen.js +185 -0
  227. package/dist/server/config-loader.d.ts +34 -0
  228. package/dist/server/config-loader.js +103 -0
  229. package/dist/server/context.d.ts +8 -0
  230. package/dist/server/context.js +19 -0
  231. package/dist/server/folder-filesystem.d.ts +7 -0
  232. package/dist/server/folder-filesystem.js +39 -0
  233. package/dist/server/http.d.ts +12 -0
  234. package/dist/server/http.js +100 -0
  235. package/dist/server/index.d.ts +16 -0
  236. package/dist/server/index.js +9 -0
  237. package/dist/server/job-hash.d.ts +10 -0
  238. package/dist/server/job-hash.js +23 -0
  239. package/dist/server/library-store.d.ts +82 -0
  240. package/dist/server/library-store.js +763 -0
  241. package/dist/server/operations.d.ts +87 -0
  242. package/dist/server/operations.js +427 -0
  243. package/dist/server/plugins/audio.d.ts +7 -0
  244. package/dist/server/plugins/audio.js +27 -0
  245. package/dist/server/plugins/chroma-key-video.d.ts +9 -0
  246. package/dist/server/plugins/chroma-key-video.js +38 -0
  247. package/dist/server/plugins/contract.d.ts +100 -0
  248. package/dist/server/plugins/contract.js +16 -0
  249. package/dist/server/plugins/image.d.ts +8 -0
  250. package/dist/server/plugins/image.js +30 -0
  251. package/dist/server/plugins/slice.d.ts +14 -0
  252. package/dist/server/plugins/slice.js +63 -0
  253. package/dist/server/plugins/video.d.ts +6 -0
  254. package/dist/server/plugins/video.js +29 -0
  255. package/dist/server/plugins.d.ts +23 -0
  256. package/dist/server/plugins.js +33 -0
  257. package/dist/server/processing/audio-processing.d.ts +17 -0
  258. package/dist/server/processing/audio-processing.js +46 -0
  259. package/dist/server/processing/ffmpeg.d.ts +9 -0
  260. package/dist/server/processing/ffmpeg.js +50 -0
  261. package/dist/server/processing/image-processing.d.ts +16 -0
  262. package/dist/server/processing/image-processing.js +26 -0
  263. package/dist/server/processing/media-probe.d.ts +15 -0
  264. package/dist/server/processing/media-probe.js +27 -0
  265. package/dist/server/processing/processor.d.ts +50 -0
  266. package/dist/server/processing/processor.js +158 -0
  267. package/dist/server/processing/video-processing.d.ts +35 -0
  268. package/dist/server/processing/video-processing.js +87 -0
  269. package/dist/server/server.d.ts +13 -0
  270. package/dist/server/server.js +57 -0
  271. package/dist/server/start.d.ts +1 -0
  272. package/dist/server/start.js +33 -0
  273. package/package.json +29 -16
  274. package/dist/build-CZYFLLvl.js +0 -191
  275. package/dist/core/image-Dqmz8FXS.js +0 -54
  276. package/dist/core/reference-graph-CjuHbLDw.d.ts +0 -280
  277. package/dist/core/testing.d.ts +0 -27
  278. package/dist/core/testing.js +0 -80
  279. package/dist/editor/200.html +0 -37
  280. package/dist/editor/_app/immutable/assets/2.DIbbW7U1.css +0 -1
  281. package/dist/editor/_app/immutable/assets/3.C-9vFQ9A.css +0 -1
  282. package/dist/editor/_app/immutable/assets/4.BS8ElpOV.css +0 -1
  283. package/dist/editor/_app/immutable/assets/ConfirmDialog.CHEISE-L.css +0 -1
  284. package/dist/editor/_app/immutable/assets/LibraryContextMenu.CDjCmdV-.css +0 -1
  285. package/dist/editor/_app/immutable/chunks/Cx6qtxJg.js +0 -1
  286. package/dist/editor/_app/immutable/chunks/n7mvYc42.js +0 -5
  287. package/dist/editor/_app/immutable/entry/start.C8HHOLly.js +0 -1
  288. package/dist/editor/_app/immutable/nodes/3.WO7tZH_d.js +0 -104
  289. package/dist/editor/_app/immutable/nodes/4.DQtx17aW.js +0 -2
  290. package/dist/editor/_app/version.json +0 -1
  291. package/dist/index.d.ts +0 -370
  292. package/dist/index.js +0 -4
  293. package/dist/start-Bhnqt9Dc.js +0 -279
  294. package/dist/start-D2IXOrni.js +0 -2
  295. /package/{dist/editor → build/client}/_app/immutable/assets/0.DLhIsYA_.css +0 -0
  296. /package/{dist/editor → build/client}/_app/immutable/chunks/Bjy-W4x2.js +0 -0
  297. /package/{dist/editor → build/client}/_app/immutable/chunks/CNRz3sSw.js +0 -0
  298. /package/{dist/editor → build/client}/_app/immutable/chunks/CO4RBJfa.js +0 -0
  299. /package/{dist/editor → build/client}/_app/immutable/chunks/DjdrdRzT.js +0 -0
  300. /package/{dist/editor → build/client}/_app/immutable/chunks/xihTtKlq.js +0 -0
@@ -0,0 +1,3 @@
1
+ export declare const FUNDUS_CONFIG_TEMPLATE = "import { defineConfig } from 'fundus/config';\n\nexport default defineConfig({\n\trawDir: './assets/raw',\n\tproxyDir: './static/fundus',\n\tproxyBasePath: '/fundus/',\n\tlibrary: './assets/fundus.library.json',\n\tmanifestsDir: './src/lib/fundus'\n});\n";
2
+ export declare const INIT_HELP = "fundus init \u2014 create a Fundus configuration file\n\nUsage: fundus init [--json]\n\nCreates a template fundus.config.ts in the current directory. The command\nrefuses to overwrite an existing configuration file.\n\nFlags:\n --json print {\"ok\": true, \"path\": \"fundus.config.ts\"} on stdout\n --help this help\n\nExample:\n cd my-host-app && npx fundus init\n";
3
+ export declare function runInitCommand(argumentList: string[]): Promise<void>;
@@ -0,0 +1,53 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { parseArguments, printJsonDocument, requirePositionals } from './cli-io.js';
4
+ export const FUNDUS_CONFIG_TEMPLATE = `import { defineConfig } from 'fundus/config';
5
+
6
+ export default defineConfig({
7
+ rawDir: './assets/raw',
8
+ proxyDir: './static/fundus',
9
+ proxyBasePath: '/fundus/',
10
+ library: './assets/fundus.library.json',
11
+ manifestsDir: './src/lib/fundus'
12
+ });
13
+ `;
14
+ export const INIT_HELP = `fundus init — create a Fundus configuration file
15
+
16
+ Usage: fundus init [--json]
17
+
18
+ Creates a template fundus.config.ts in the current directory. The command
19
+ refuses to overwrite an existing configuration file.
20
+
21
+ Flags:
22
+ --json print {"ok": true, "path": "fundus.config.ts"} on stdout
23
+ --help this help
24
+
25
+ Example:
26
+ cd my-host-app && npx fundus init
27
+ `;
28
+ export async function runInitCommand(argumentList) {
29
+ if (argumentList.includes('--help')) {
30
+ console.log(INIT_HELP);
31
+ return;
32
+ }
33
+ const parsed = parseArguments(argumentList, {
34
+ json: { takesValue: false },
35
+ help: { takesValue: false }
36
+ }, 'fundus init');
37
+ requirePositionals(parsed, [], 'fundus init');
38
+ const configPath = resolve(process.cwd(), 'fundus.config.ts');
39
+ try {
40
+ await writeFile(configPath, FUNDUS_CONFIG_TEMPLATE, { encoding: 'utf8', flag: 'wx' });
41
+ }
42
+ catch (cause) {
43
+ if (cause.code === 'EEXIST') {
44
+ throw new Error(`fundus.config.ts already exists in ${process.cwd()}.`);
45
+ }
46
+ throw new Error(`Cannot create fundus.config.ts: ${cause instanceof Error ? cause.message : String(cause)}`);
47
+ }
48
+ if (parsed.flags.json) {
49
+ printJsonDocument({ ok: true, path: 'fundus.config.ts' });
50
+ return;
51
+ }
52
+ console.log('Created fundus.config.ts.');
53
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Terminal I/O for the fundus CLI (M7): hand-rolled flag parsing, the JSON
3
+ * output envelope, and the expected-error type — no CLI framework. The output
4
+ * contract agents rely on: with `--json`, stdout carries exactly one JSON
5
+ * document ({"ok": true, ...} on success, {"error": {"message": ...}} on an
6
+ * expected failure); without it, errors go to stderr. Exit codes: 0 success,
7
+ * 1 expected error, 2 unexpected crash (see cli.ts).
8
+ */
9
+ /**
10
+ * A wrong invocation (unknown flag/subcommand, missing positional, malformed
11
+ * flag value): an expected error whose message points at the right `--help`.
12
+ */
13
+ export declare class CliUsageError extends Error {
14
+ }
15
+ export interface FlagDefinition {
16
+ /** `--name value` / `--name=value` when true; a presence flag when false. */
17
+ takesValue: boolean;
18
+ }
19
+ export interface ParsedArguments {
20
+ positionals: string[];
21
+ flags: Record<string, string | true>;
22
+ }
23
+ /**
24
+ * Parse a command's argument list against its flag definitions. Supports
25
+ * `--flag value` and `--flag=value`; anything not starting with `--` is a
26
+ * positional. Unknown flags and missing values throw a `CliUsageError` that
27
+ * names the command's `--help`.
28
+ */
29
+ export declare function parseArguments(argumentList: string[], flagDefinitions: Record<string, FlagDefinition>, commandPath: string): ParsedArguments;
30
+ /**
31
+ * Enforce a command's exact positional shape. `names` are the placeholders
32
+ * from the synopsis (e.g. ["<id>", "<newId>"]); the mismatch message repeats
33
+ * the expected usage.
34
+ */
35
+ export declare function requirePositionals(parsed: ParsedArguments, names: string[], commandPath: string): string[];
36
+ /** The single JSON document a `--json` invocation writes to stdout. */
37
+ export declare function printJsonDocument(document: unknown): void;
38
+ /** Parse a JSON-valued flag (`--parameters`), mapping bad JSON to a usage error. */
39
+ export declare function parseJsonFlag(name: string, value: string): unknown;
40
+ /**
41
+ * Parse a `--manifests a,b` list: comma-separated names, whitespace-tolerant.
42
+ * The empty string is the explicit "no manifests" — it clears the membership.
43
+ */
44
+ export declare function parseManifestList(value: string): string[];
45
+ /** Human-readable byte count for terminal output (1024-based, one decimal). */
46
+ export declare function formatBytes(bytes: number): string;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Terminal I/O for the fundus CLI (M7): hand-rolled flag parsing, the JSON
3
+ * output envelope, and the expected-error type — no CLI framework. The output
4
+ * contract agents rely on: with `--json`, stdout carries exactly one JSON
5
+ * document ({"ok": true, ...} on success, {"error": {"message": ...}} on an
6
+ * expected failure); without it, errors go to stderr. Exit codes: 0 success,
7
+ * 1 expected error, 2 unexpected crash (see cli.ts).
8
+ */
9
+ /**
10
+ * A wrong invocation (unknown flag/subcommand, missing positional, malformed
11
+ * flag value): an expected error whose message points at the right `--help`.
12
+ */
13
+ export class CliUsageError extends Error {
14
+ }
15
+ /**
16
+ * Parse a command's argument list against its flag definitions. Supports
17
+ * `--flag value` and `--flag=value`; anything not starting with `--` is a
18
+ * positional. Unknown flags and missing values throw a `CliUsageError` that
19
+ * names the command's `--help`.
20
+ */
21
+ export function parseArguments(argumentList, flagDefinitions, commandPath) {
22
+ const positionals = [];
23
+ const flags = {};
24
+ for (let index = 0; index < argumentList.length; index++) {
25
+ const argument = argumentList[index];
26
+ if (!argument.startsWith('--')) {
27
+ positionals.push(argument);
28
+ continue;
29
+ }
30
+ const equalsIndex = argument.indexOf('=');
31
+ const name = equalsIndex === -1 ? argument.slice(2) : argument.slice(2, equalsIndex);
32
+ const definition = flagDefinitions[name];
33
+ if (!definition) {
34
+ throw new CliUsageError(`Unknown flag "--${name}" for \`${commandPath}\` — run \`${commandPath} --help\`.`);
35
+ }
36
+ if (!definition.takesValue) {
37
+ if (equalsIndex !== -1) {
38
+ throw new CliUsageError(`Flag "--${name}" takes no value.`);
39
+ }
40
+ flags[name] = true;
41
+ continue;
42
+ }
43
+ if (equalsIndex !== -1) {
44
+ flags[name] = argument.slice(equalsIndex + 1);
45
+ continue;
46
+ }
47
+ const value = argumentList[index + 1];
48
+ if (value === undefined) {
49
+ throw new CliUsageError(`Flag "--${name}" needs a value — run \`${commandPath} --help\`.`);
50
+ }
51
+ flags[name] = value;
52
+ index++;
53
+ }
54
+ return { positionals, flags };
55
+ }
56
+ /**
57
+ * Enforce a command's exact positional shape. `names` are the placeholders
58
+ * from the synopsis (e.g. ["<id>", "<newId>"]); the mismatch message repeats
59
+ * the expected usage.
60
+ */
61
+ export function requirePositionals(parsed, names, commandPath) {
62
+ if (parsed.positionals.length !== names.length) {
63
+ const usage = names.length === 0 ? commandPath : `${commandPath} ${names.join(' ')}`;
64
+ throw new CliUsageError(`\`${commandPath}\` expects ${names.length} argument(s) (usage: ${usage}) — ` +
65
+ `got ${parsed.positionals.length}. Run \`${commandPath} --help\`.`);
66
+ }
67
+ return parsed.positionals;
68
+ }
69
+ /** The single JSON document a `--json` invocation writes to stdout. */
70
+ export function printJsonDocument(document) {
71
+ console.log(JSON.stringify(document, null, '\t'));
72
+ }
73
+ /** Parse a JSON-valued flag (`--parameters`), mapping bad JSON to a usage error. */
74
+ export function parseJsonFlag(name, value) {
75
+ try {
76
+ return JSON.parse(value);
77
+ }
78
+ catch (cause) {
79
+ throw new CliUsageError(`Flag "--${name}" is not valid JSON (${cause instanceof Error ? cause.message : String(cause)}). ` +
80
+ `Pass a single JSON value, e.g. --${name} '{"preset": "default"}'.`);
81
+ }
82
+ }
83
+ /**
84
+ * Parse a `--manifests a,b` list: comma-separated names, whitespace-tolerant.
85
+ * The empty string is the explicit "no manifests" — it clears the membership.
86
+ */
87
+ export function parseManifestList(value) {
88
+ return value
89
+ .split(',')
90
+ .map((name) => name.trim())
91
+ .filter((name) => name.length > 0);
92
+ }
93
+ /** Human-readable byte count for terminal output (1024-based, one decimal). */
94
+ export function formatBytes(bytes) {
95
+ if (bytes < 1024)
96
+ return `${bytes} B`;
97
+ const units = ['KiB', 'MiB', 'GiB'];
98
+ let value = bytes;
99
+ let unitIndex = -1;
100
+ while (value >= 1024 && unitIndex < units.length - 1) {
101
+ value /= 1024;
102
+ unitIndex++;
103
+ }
104
+ return `${value.toFixed(1)} ${units[unitIndex]}`;
105
+ }
@@ -0,0 +1,58 @@
1
+ import { type AssetRecord, type Library, type ManifestEntry, type ManifestEntryData, type ManifestMembership, type ReferencesByAsset } from '../core/index.js';
2
+ import type { ResolvedFundusConfig } from './config-loader.js';
3
+ import type { ServerPluginRegistry } from './plugins/contract.js';
4
+ import type { AssetProxyInfo } from './processing/processor.js';
5
+ export declare const GENERATED_HEADER = "// generated by fundus \u2014 do not edit\n";
6
+ /** `mainCatalog` → `main-catalog`. */
7
+ export declare function kebabCaseFromCamel(name: string): string;
8
+ /** Generated module file name for a manifest. */
9
+ export declare function manifestModuleFileName(manifestName: string): string;
10
+ /**
11
+ * Build the entry data codegen emits for one asset — delegated to
12
+ * the owning server plugin's `buildManifestEntry`. Reference fields
13
+ * (chroma-key-video's mask/fallback) stay `{ $asset }` markers here — the
14
+ * generic `inlineAssetReferences` walk resolves them.
15
+ */
16
+ export declare function manifestEntryForAsset(record: AssetRecord, proxy: AssetProxyInfo, config: ResolvedFundusConfig, registry?: ServerPluginRegistry): ManifestEntryData;
17
+ /** Builds one asset's raw entry data; references may remain as `{ $asset }` markers. */
18
+ export type ManifestEntryBuilder = (assetId: string, record: AssetRecord, proxy: AssetProxyInfo, config: ResolvedFundusConfig) => ManifestEntryData;
19
+ /**
20
+ * Replace every `{ $asset }` marker in a built entry with the referenced
21
+ * asset's own (already inlined) entry data. Codegen inlines the
22
+ * resolved reference, so the runtime never resolves ids. Generic deep walk;
23
+ * plugin entry builders stay reference-unaware.
24
+ */
25
+ export declare function inlineAssetReferences(value: ManifestEntryData, resolveEntry: (assetId: string) => ManifestEntry): ManifestEntry;
26
+ /**
27
+ * Build the entries for one manifest from its membership picture: the whole
28
+ * delivery set (explicit ∪ passive members — the shared membership
29
+ * computation) in dependency order (the closure is a DAG — a
30
+ * cycle throws), each entry's markers inlined from the already-built entries.
31
+ * Only the explicit members appear top-level — they are the manifest's API
32
+ * surface; passive members exist solely inlined.
33
+ */
34
+ export declare function buildManifestEntries(options: {
35
+ membership: ManifestMembership;
36
+ library: Library;
37
+ proxies: Record<string, AssetProxyInfo>;
38
+ config: ResolvedFundusConfig;
39
+ referencesByAsset: ReferencesByAsset;
40
+ entryBuilder?: ManifestEntryBuilder;
41
+ registry?: ServerPluginRegistry;
42
+ }): Record<string, ManifestEntry>;
43
+ /** Render one generated manifest module. */
44
+ export declare function renderManifestModule(manifestName: string, entries: Record<string, ManifestEntry | ManifestEntryData>): string;
45
+ export interface CodegenReport {
46
+ /** Written module file names. */
47
+ written: string[];
48
+ /** Removed module file names (their manifest no longer exists). */
49
+ removed: string[];
50
+ }
51
+ /** Fundus-owned generated modules not present in the expected file-name set. */
52
+ export declare function strayGeneratedModuleNames(manifestsDir: string, expectedFileNames: ReadonlySet<string>): Promise<string[]>;
53
+ /**
54
+ * Write one module per manifest and remove generated modules whose manifest is
55
+ * gone. Only files starting with the fundus header are ever removed, so other
56
+ * generated files co-located in the directory stay untouched.
57
+ */
58
+ export declare function generateManifestModules(config: ResolvedFundusConfig, library: Library, proxies: Record<string, AssetProxyInfo>, registry?: ServerPluginRegistry): Promise<CodegenReport>;
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Manifest module codegen: one `<manifest-name-kebab>.generated.ts`
3
+ * per manifest in the configured manifests directory, containing data only —
4
+ * entries constructed through the runtime's `createManifest`. Deterministic:
5
+ * sorted asset ids, fixed property order, tab indentation. Generated modules
6
+ * for deleted manifests are removed (only files carrying the fundus header).
7
+ */
8
+ import { mkdir, readdir, readFile, unlink, writeFile } from 'node:fs/promises';
9
+ import { join } from 'node:path';
10
+ import { collectAllReferences, compareCodeUnits, computeLibraryMembership, isAssetReference, topologicalReferenceOrder } from '../core/index.js';
11
+ import { descriptorsByType, serverPluginForType, serverPluginsByType } from './plugins.js';
12
+ export const GENERATED_HEADER = '// generated by fundus — do not edit\n';
13
+ /** `mainCatalog` → `main-catalog`. */
14
+ export function kebabCaseFromCamel(name) {
15
+ return name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
16
+ }
17
+ /** Generated module file name for a manifest. */
18
+ export function manifestModuleFileName(manifestName) {
19
+ return `${kebabCaseFromCamel(manifestName)}.generated.ts`;
20
+ }
21
+ /**
22
+ * Build the entry data codegen emits for one asset — delegated to
23
+ * the owning server plugin's `buildManifestEntry`. Reference fields
24
+ * (chroma-key-video's mask/fallback) stay `{ $asset }` markers here — the
25
+ * generic `inlineAssetReferences` walk resolves them.
26
+ */
27
+ export function manifestEntryForAsset(record, proxy, config, registry = serverPluginsByType) {
28
+ const plugin = serverPluginForType(record.type, registry);
29
+ return plugin.buildManifestEntry({
30
+ assetId: proxy.assetId,
31
+ parameters: plugin.descriptor.validateParameters(record.parameters),
32
+ src: `${config.proxyBasePath}${proxy.relativePath
33
+ .split('/')
34
+ .map(encodeURIComponent)
35
+ .join('/')}`,
36
+ proxy
37
+ });
38
+ }
39
+ /**
40
+ * Replace every `{ $asset }` marker in a built entry with the referenced
41
+ * asset's own (already inlined) entry data. Codegen inlines the
42
+ * resolved reference, so the runtime never resolves ids. Generic deep walk;
43
+ * plugin entry builders stay reference-unaware.
44
+ */
45
+ export function inlineAssetReferences(value, resolveEntry) {
46
+ return inlineValue(value, resolveEntry);
47
+ }
48
+ function inlineValue(value, resolveEntry) {
49
+ if (isAssetReference(value)) {
50
+ return resolveEntry(value.$asset);
51
+ }
52
+ if (Array.isArray(value)) {
53
+ return value.map((element) => inlineValue(element, resolveEntry));
54
+ }
55
+ if (typeof value === 'object' && value !== null) {
56
+ const inlined = {};
57
+ for (const [key, nested] of Object.entries(value)) {
58
+ inlined[key] = inlineValue(nested, resolveEntry);
59
+ }
60
+ return inlined;
61
+ }
62
+ return value;
63
+ }
64
+ /**
65
+ * Build the entries for one manifest from its membership picture: the whole
66
+ * delivery set (explicit ∪ passive members — the shared membership
67
+ * computation) in dependency order (the closure is a DAG — a
68
+ * cycle throws), each entry's markers inlined from the already-built entries.
69
+ * Only the explicit members appear top-level — they are the manifest's API
70
+ * surface; passive members exist solely inlined.
71
+ */
72
+ export function buildManifestEntries(options) {
73
+ const buildEntry = options.entryBuilder ??
74
+ ((assetId, record, proxy, config) => manifestEntryForAsset(record, proxy, config, options.registry));
75
+ const buildOrder = topologicalReferenceOrder(options.membership.deliveredAssetIds, options.referencesByAsset);
76
+ const builtEntries = {};
77
+ const resolveEntry = (assetId) => {
78
+ if (!Object.hasOwn(builtEntries, assetId)) {
79
+ throw new Error(`Cannot inline reference to "${assetId}" — no entry was built for it.`);
80
+ }
81
+ return builtEntries[assetId];
82
+ };
83
+ for (const assetId of buildOrder) {
84
+ if (!Object.hasOwn(options.library.assets, assetId)) {
85
+ throw new Error(`Cannot build an entry for unknown asset "${assetId}".`);
86
+ }
87
+ const proxy = options.proxies[assetId];
88
+ if (!proxy) {
89
+ throw new Error(`No proxy info for asset "${assetId}". Run processing before codegen.`);
90
+ }
91
+ const rawEntry = buildEntry(assetId, options.library.assets[assetId], proxy, options.config);
92
+ builtEntries[assetId] = inlineAssetReferences(rawEntry, resolveEntry);
93
+ }
94
+ const memberEntries = {};
95
+ for (const assetId of options.membership.explicitMemberIds) {
96
+ memberEntries[assetId] = builtEntries[assetId];
97
+ }
98
+ return memberEntries;
99
+ }
100
+ /** Render one generated manifest module. */
101
+ export function renderManifestModule(manifestName, entries) {
102
+ const assetIds = Object.keys(entries).sort(compareCodeUnits);
103
+ const body = assetIds.length === 0
104
+ ? `export const ${manifestName} = createManifest({});`
105
+ : `export const ${manifestName} = createManifest({\n` +
106
+ assetIds
107
+ .map((assetId) => {
108
+ const json = JSON.stringify(entries[assetId], null, '\t').replace(/\n/g, '\n\t');
109
+ return `\t${assetId}: ${json}`;
110
+ })
111
+ .join(',\n') +
112
+ `\n});`;
113
+ return `${GENERATED_HEADER}import { createManifest } from 'fundus';\n\n${body}\n`;
114
+ }
115
+ /** Fundus-owned generated modules not present in the expected file-name set. */
116
+ export async function strayGeneratedModuleNames(manifestsDir, expectedFileNames) {
117
+ let fileNames;
118
+ try {
119
+ fileNames = await readdir(manifestsDir);
120
+ }
121
+ catch (cause) {
122
+ if (cause.code === 'ENOENT')
123
+ return [];
124
+ throw cause;
125
+ }
126
+ const strayNames = [];
127
+ for (const fileName of fileNames) {
128
+ if (!fileName.endsWith('.generated.ts') || expectedFileNames.has(fileName))
129
+ continue;
130
+ const content = await readFile(join(manifestsDir, fileName), 'utf8');
131
+ if (content.startsWith(GENERATED_HEADER))
132
+ strayNames.push(fileName);
133
+ }
134
+ return strayNames.sort(compareCodeUnits);
135
+ }
136
+ /**
137
+ * Write one module per manifest and remove generated modules whose manifest is
138
+ * gone. Only files starting with the fundus header are ever removed, so other
139
+ * generated files co-located in the directory stay untouched.
140
+ */
141
+ export async function generateManifestModules(config, library, proxies, registry = serverPluginsByType) {
142
+ await mkdir(config.manifestsDir, { recursive: true });
143
+ const report = { written: [], removed: [] };
144
+ const expectedFileNames = new Set();
145
+ // Two distinct manifest names can share a kebab form (`mainCatalog` / `mainCATALOG`
146
+ // both map to `main-catalog`) — that would make one module silently overwrite
147
+ // the other. The store rejects such names at creation; this guard is defense
148
+ // in depth for hand-edited libraries.
149
+ const namesByFileName = new Map();
150
+ for (const manifestName of Object.keys(library.manifests)) {
151
+ const fileName = manifestModuleFileName(manifestName);
152
+ namesByFileName.set(fileName, [...(namesByFileName.get(fileName) ?? []), manifestName]);
153
+ }
154
+ for (const [fileName, manifestNames] of namesByFileName) {
155
+ if (manifestNames.length > 1) {
156
+ throw new Error(`Manifests ${manifestNames.map((name) => `"${name}"`).join(' and ')} would both generate ` +
157
+ `"${fileName}" — rename one so the kebab-case module names stay distinct.`);
158
+ }
159
+ }
160
+ const referencesByAsset = collectAllReferences(library, descriptorsByType(registry));
161
+ const membershipByManifest = computeLibraryMembership(library, referencesByAsset);
162
+ const renderedModules = [];
163
+ for (const manifestName of Object.keys(library.manifests).sort(compareCodeUnits)) {
164
+ const entries = buildManifestEntries({
165
+ membership: membershipByManifest[manifestName],
166
+ library,
167
+ proxies,
168
+ config,
169
+ referencesByAsset,
170
+ registry
171
+ });
172
+ const fileName = manifestModuleFileName(manifestName);
173
+ expectedFileNames.add(fileName);
174
+ renderedModules.push({ fileName, content: renderManifestModule(manifestName, entries) });
175
+ }
176
+ for (const { fileName, content } of renderedModules) {
177
+ await writeFile(join(config.manifestsDir, fileName), content);
178
+ report.written.push(fileName);
179
+ }
180
+ for (const fileName of await strayGeneratedModuleNames(config.manifestsDir, expectedFileNames)) {
181
+ await unlink(join(config.manifestsDir, fileName));
182
+ report.removed.push(fileName);
183
+ }
184
+ return report;
185
+ }
@@ -0,0 +1,34 @@
1
+ import { type AudioPreset, type ImagePreset, type VideoPreset } from '../core/index.js';
2
+ export interface ResolvedPresetPluginConfig {
3
+ presets: Record<string, ImagePreset>;
4
+ }
5
+ export interface ResolvedVideoPluginConfig {
6
+ presets: Record<string, VideoPreset>;
7
+ /** Absolute path of the ffmpeg binary to use; null = the bundled `ffmpeg-static`. */
8
+ ffmpegPath: string | null;
9
+ /** Absolute path of the ffprobe binary to use; null = the bundled `ffprobe-static`. */
10
+ ffprobePath: string | null;
11
+ }
12
+ export interface ResolvedAudioPluginConfig {
13
+ presets: Record<string, AudioPreset>;
14
+ }
15
+ export interface ResolvedFundusConfig {
16
+ /** All paths absolute. */
17
+ rawDir: string;
18
+ proxyDir: string;
19
+ library: string;
20
+ manifestsDir: string;
21
+ /** URL prefix baked into generated proxy `src` values; always ends with '/'. */
22
+ proxyBasePath: string;
23
+ plugins: {
24
+ image: ResolvedPresetPluginConfig;
25
+ slice: ResolvedPresetPluginConfig;
26
+ /** Shared by video and chroma-key-video through one preset namespace. */
27
+ video: ResolvedVideoPluginConfig;
28
+ audio: ResolvedAudioPluginConfig;
29
+ };
30
+ }
31
+ /** Pure resolution step (testable without a config file on disk). */
32
+ export declare function resolveConfig(projectRoot: string, value: unknown): ResolvedFundusConfig;
33
+ /** Load `fundus.config.ts` from the host project root. */
34
+ export declare function loadConfig(projectRoot: string): Promise<ResolvedFundusConfig>;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Loads and resolves the host's `fundus.config.ts` through jiti, validates
3
+ * the shape, resolves all paths to
4
+ * absolute, and merges the built-in plugin preset defaults under the host's.
5
+ */
6
+ import { existsSync } from 'node:fs';
7
+ import { isAbsolute, resolve } from 'node:path';
8
+ import { createJiti } from 'jiti';
9
+ import { AUDIO_BUILT_IN_PRESETS, IMAGE_BUILT_IN_PRESETS, SLICE_BUILT_IN_PRESETS, VIDEO_BUILT_IN_PRESETS, validateAudioPreset, validateImagePreset, validateVideoPreset } from '../core/index.js';
10
+ function isRecord(value) {
11
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
12
+ }
13
+ function requiredString(config, key) {
14
+ const value = config[key];
15
+ if (typeof value !== 'string' || value.length === 0) {
16
+ throw new Error(`fundus.config: "${key}" must be a non-empty string.`);
17
+ }
18
+ return value;
19
+ }
20
+ function resolvePath(projectRoot, value) {
21
+ return isAbsolute(value) ? value : resolve(projectRoot, value);
22
+ }
23
+ function mergePresets(label, builtIn, pluginConfig, validatePreset) {
24
+ const merged = { ...builtIn };
25
+ if (pluginConfig === undefined)
26
+ return merged;
27
+ if (!isRecord(pluginConfig)) {
28
+ throw new Error(`fundus.config: "plugins.${label}" must be an object.`);
29
+ }
30
+ if (pluginConfig.presets === undefined)
31
+ return merged;
32
+ if (!isRecord(pluginConfig.presets)) {
33
+ throw new Error(`fundus.config: "plugins.${label}.presets" must be an object.`);
34
+ }
35
+ for (const [name, preset] of Object.entries(pluginConfig.presets)) {
36
+ merged[name] = validatePreset(name, preset);
37
+ }
38
+ return merged;
39
+ }
40
+ /** `plugins.video.ffmpegPath` / `ffprobePath`: optional system-binary overrides. */
41
+ function binaryPathOverride(projectRoot, pluginConfig, key) {
42
+ if (!isRecord(pluginConfig) || pluginConfig[key] === undefined)
43
+ return null;
44
+ const value = pluginConfig[key];
45
+ if (typeof value !== 'string' || value.length === 0) {
46
+ throw new Error(`fundus.config: "plugins.video.${key}" must be a non-empty string.`);
47
+ }
48
+ return resolvePath(projectRoot, value);
49
+ }
50
+ /** Pure resolution step (testable without a config file on disk). */
51
+ export function resolveConfig(projectRoot, value) {
52
+ if (!isRecord(value)) {
53
+ throw new Error('fundus.config must default-export a configuration object.');
54
+ }
55
+ const proxyBasePath = requiredString(value, 'proxyBasePath');
56
+ if (!proxyBasePath.endsWith('/')) {
57
+ throw new Error('fundus.config: "proxyBasePath" must end with "/".');
58
+ }
59
+ const plugins = value.plugins === undefined ? {} : value.plugins;
60
+ if (!isRecord(plugins)) {
61
+ throw new Error('fundus.config: "plugins" must be an object.');
62
+ }
63
+ return {
64
+ rawDir: resolvePath(projectRoot, requiredString(value, 'rawDir')),
65
+ proxyDir: resolvePath(projectRoot, requiredString(value, 'proxyDir')),
66
+ library: resolvePath(projectRoot, requiredString(value, 'library')),
67
+ manifestsDir: resolvePath(projectRoot, requiredString(value, 'manifestsDir')),
68
+ proxyBasePath,
69
+ plugins: {
70
+ image: {
71
+ presets: mergePresets('image', IMAGE_BUILT_IN_PRESETS, plugins.image, validateImagePreset)
72
+ },
73
+ slice: {
74
+ presets: mergePresets('slice', SLICE_BUILT_IN_PRESETS, plugins.slice, validateImagePreset)
75
+ },
76
+ video: {
77
+ presets: mergePresets('video', VIDEO_BUILT_IN_PRESETS, plugins.video, validateVideoPreset),
78
+ ffmpegPath: binaryPathOverride(projectRoot, plugins.video, 'ffmpegPath'),
79
+ ffprobePath: binaryPathOverride(projectRoot, plugins.video, 'ffprobePath')
80
+ },
81
+ audio: {
82
+ presets: mergePresets('audio', AUDIO_BUILT_IN_PRESETS, plugins.audio, validateAudioPreset)
83
+ }
84
+ }
85
+ };
86
+ }
87
+ /** Load `fundus.config.ts` from the host project root. */
88
+ export async function loadConfig(projectRoot) {
89
+ const root = resolve(projectRoot);
90
+ const configPath = resolve(root, 'fundus.config.ts');
91
+ if (!existsSync(configPath)) {
92
+ throw new Error(`No fundus.config.ts found in ${root}.`);
93
+ }
94
+ let module;
95
+ try {
96
+ const jiti = createJiti(import.meta.url, { interopDefault: false });
97
+ module = await jiti.import(configPath);
98
+ }
99
+ catch (cause) {
100
+ throw new Error(`Cannot load fundus.config.ts: ${cause instanceof Error ? cause.message : String(cause)}`);
101
+ }
102
+ return resolveConfig(root, isRecord(module) && 'default' in module ? module.default : module);
103
+ }
@@ -0,0 +1,8 @@
1
+ import { type ResolvedFundusConfig } from './config-loader.js';
2
+ import { FundusOperations } from './operations.js';
3
+ export interface FundusContext {
4
+ config: ResolvedFundusConfig;
5
+ operations: FundusOperations;
6
+ }
7
+ export declare function initializeFundusContext(): Promise<FundusContext>;
8
+ export declare function getFundusContext(): Promise<FundusContext>;
@@ -0,0 +1,19 @@
1
+ import { isAbsolute } from 'node:path';
2
+ import { loadConfig } from './config-loader.js';
3
+ import { FundusOperations } from './operations.js';
4
+ let context;
5
+ export function initializeFundusContext() {
6
+ context ??= createFundusContext();
7
+ return context;
8
+ }
9
+ export function getFundusContext() {
10
+ return initializeFundusContext();
11
+ }
12
+ async function createFundusContext() {
13
+ const projectRoot = process.env.FUNDUS_PROJECT_ROOT;
14
+ if (!projectRoot || !isAbsolute(projectRoot)) {
15
+ throw new Error('FUNDUS_PROJECT_ROOT must be set to an absolute host project directory.');
16
+ }
17
+ const config = await loadConfig(projectRoot);
18
+ return { config, operations: new FundusOperations(config) };
19
+ }
@@ -0,0 +1,7 @@
1
+ import { type Library } from '../core/index.js';
2
+ import type { ResolvedFundusConfig } from './config-loader.js';
3
+ export declare function ensureManagedFolder(root: string, folder: string): Promise<void>;
4
+ export declare function syncManagedFolders(config: ResolvedFundusConfig, library: Library): Promise<void>;
5
+ /** Recursively list files as POSIX-style paths relative to `root`. */
6
+ export declare function listRelativeFiles(root: string, folder?: string): Promise<string[]>;
7
+ export declare function encodeRelativePathForUrl(path: string): string;
@@ -0,0 +1,39 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { mkdir, readdir, writeFile } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { FOLDER_SENTINEL } from '../core/index.js';
5
+ export async function ensureManagedFolder(root, folder) {
6
+ const directory = join(root, folder);
7
+ await mkdir(directory, { recursive: true });
8
+ if (folder === '')
9
+ return;
10
+ const sentinel = join(directory, FOLDER_SENTINEL);
11
+ if (!existsSync(sentinel))
12
+ await writeFile(sentinel, '');
13
+ }
14
+ export async function syncManagedFolders(config, library) {
15
+ await Promise.all(library.folders.flatMap((folder) => [
16
+ ensureManagedFolder(config.rawDir, folder),
17
+ ensureManagedFolder(config.proxyDir, folder)
18
+ ]));
19
+ }
20
+ /** Recursively list files as POSIX-style paths relative to `root`. */
21
+ export async function listRelativeFiles(root, folder = '') {
22
+ const directory = join(root, folder);
23
+ if (!existsSync(directory))
24
+ return [];
25
+ const result = [];
26
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
27
+ const relativePath = folder === '' ? entry.name : `${folder}/${entry.name}`;
28
+ if (entry.isDirectory()) {
29
+ result.push(...(await listRelativeFiles(root, relativePath)));
30
+ }
31
+ else if (entry.isFile()) {
32
+ result.push(relativePath);
33
+ }
34
+ }
35
+ return result;
36
+ }
37
+ export function encodeRelativePathForUrl(path) {
38
+ return path.split('/').map(encodeURIComponent).join('/');
39
+ }