fundus 0.2.0 → 0.4.0

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