@phtngyn/cms 0.2.0-beta.8 → 0.3.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 (524) hide show
  1. package/LICENSE +18 -10
  2. package/README.md +59 -404
  3. package/drizzle/20261003215543_initial/migration.sql +251 -0
  4. package/drizzle/20261003215543_initial/snapshot.json +1941 -0
  5. package/package.json +75 -71
  6. package/src/Authoring.d.ts +41 -49
  7. package/src/Authoring.js +1 -1
  8. package/src/Blocks-BrxSemnd.js +40 -0
  9. package/src/Client.d.ts +8186 -0
  10. package/src/Client.js +41 -0
  11. package/src/Collections.d.ts +142 -0
  12. package/src/Collections.js +142 -0
  13. package/src/Config-CMiwciub.js +130 -0
  14. package/src/Config.d.ts +172 -0
  15. package/src/Config.js +2 -0
  16. package/src/Configuration-Dk2k3OIc.js +73 -0
  17. package/src/DataTransfer-BmECvPHB.js +488 -0
  18. package/src/Database-DSsNCGft.d.ts +3 -0
  19. package/src/Delivery.d.ts +28 -0
  20. package/src/Delivery.js +7 -0
  21. package/src/Document-CKXMSEf1.js +293 -0
  22. package/src/Document-TgwYKJZM.d.ts +220 -0
  23. package/src/DocumentRenderer-Wz2xaNyf.js +394 -0
  24. package/src/EditorSchema-wrDv-id6.js +296 -0
  25. package/src/Fields-BegSgYhj.d.ts +166 -0
  26. package/src/Fields-ioGaMEh9.js +130 -0
  27. package/src/Forms-BuKAXQxr.d.ts +203 -0
  28. package/src/Forms.d.ts +48 -11
  29. package/src/Forms.js +342 -7
  30. package/src/I18n-Ckf9h0rC.js +154 -0
  31. package/src/I18n.d.ts +45 -2
  32. package/src/I18n.js +2 -1
  33. package/src/Image-CJWPLnhP.js +110 -0
  34. package/src/Links-CJYyy7rC.js +28 -0
  35. package/src/Links-Dx1yOni8.d.ts +28 -0
  36. package/src/Locales-Ch7a5xuA.js +67 -0
  37. package/src/Locales-jwbmJaOp.d.ts +43 -0
  38. package/src/Locales.d.ts +3 -0
  39. package/src/Locales.js +3 -0
  40. package/src/Media-BQ0uL4w7.d.ts +15 -0
  41. package/src/Media-DSyvd14o.js +87 -0
  42. package/src/Module.d.ts +2 -10
  43. package/src/Module.js +1040 -152
  44. package/src/Operations.d.ts +57 -0
  45. package/src/Operations.js +263 -0
  46. package/src/People-DvNZauWw.js +69 -0
  47. package/src/PreviewFocus-C_EelZO5.js +104 -0
  48. package/src/Query-C0kGJF5_.d.ts +261 -0
  49. package/src/RevisionPreview-IVwbJ9Wy.js +133 -0
  50. package/src/Routes-BaZvm2LE.js +126 -0
  51. package/src/Routes-DM1rRp3r.d.ts +15 -0
  52. package/src/S3MediaObjects-y-WacEi9.js +193 -0
  53. package/src/Seo-BcpqxoAs.d.ts +57 -0
  54. package/src/Seo-CjNUtUkj.js +254 -0
  55. package/src/StudioApi-CXLwwocX.js +833 -0
  56. package/src/StudioErrors-T5zLGQ1M.js +117 -0
  57. package/src/StudioErrors-kq-E44lQ.d.ts +104 -0
  58. package/src/StudioServer.d.ts +20 -0
  59. package/src/StudioServer.js +34 -0
  60. package/src/answers-DcTg0Xv2.js +41 -0
  61. package/src/cli.js +681 -187
  62. package/src/contracts-rprW3ZOB.js +130 -0
  63. package/src/forms-3xuf0Ym7.d.ts +206 -0
  64. package/src/localeConfiguration-BPbkLi7-.js +32 -0
  65. package/src/localeContext-DhF3SPvM.js +59 -0
  66. package/src/locales-6OD4XGIZ.js +12 -0
  67. package/src/nuxtDelivery-BYX_Cddb.js +466 -0
  68. package/src/plugin-DTYuDaQu.js +7171 -0
  69. package/src/previewContext-dt3ZUh-w.js +4 -0
  70. package/src/previewRegions-CXjk5cbP.js +145 -0
  71. package/src/previewSource-fb-q3ESM.js +144 -0
  72. package/src/rendering-D9LVeEKX.js +47 -0
  73. package/src/rolldown-runtime-8H4AJuhK.js +14 -0
  74. package/src/runtime/CmsImage.js +38 -0
  75. package/src/runtime/DocumentPage.vue +10 -0
  76. package/src/runtime/DocumentPageContent.js +48 -0
  77. package/src/runtime/DocumentRenderer.d.ts +129 -0
  78. package/src/runtime/DocumentRenderer.js +2 -0
  79. package/src/runtime/api.js +48 -6
  80. package/src/runtime/delivery/useCmsDocument.js +2 -0
  81. package/src/runtime/delivery/useCmsDocumentQuery.js +2 -0
  82. package/src/runtime/delivery/useCmsDocumentSeo.js +2 -114
  83. package/src/runtime/delivery/useCmsLocale.js +10 -0
  84. package/src/runtime/plugin.js +2 -40
  85. package/src/runtime/preview.css +85 -0
  86. package/src/runtime/preview.js +277 -0
  87. package/src/runtime/previewSource.js +82 -0
  88. package/src/runtime/revisionPrivacy.js +13 -0
  89. package/src/runtime/studio.js +10 -0
  90. package/src/runtime/studioIcons.js +36 -0
  91. package/src/validation-3pggwcnm.js +396 -0
  92. package/src/validation-DpUwPC8Y.js +224 -0
  93. package/studio/THIRD-PARTY-LICENSES.md +2406 -0
  94. package/studio/chunks/AccountPage-DL3DitDM.js +288 -0
  95. package/studio/chunks/AccountPage-DL3DitDM.js.br +0 -0
  96. package/studio/chunks/AccountPage-DL3DitDM.js.gz +0 -0
  97. package/studio/chunks/ActivityPage-CLqVUqTh.js +584 -0
  98. package/studio/chunks/ActivityPage-CLqVUqTh.js.br +0 -0
  99. package/studio/chunks/ActivityPage-CLqVUqTh.js.gz +0 -0
  100. package/studio/chunks/Alert-D0D24z_a.js +335 -0
  101. package/studio/chunks/Alert-D0D24z_a.js.br +0 -0
  102. package/studio/chunks/Alert-D0D24z_a.js.gz +0 -0
  103. package/studio/chunks/Badge-BBFs88TI.js +346 -0
  104. package/studio/chunks/Badge-BBFs88TI.js.br +0 -0
  105. package/studio/chunks/Badge-BBFs88TI.js.gz +0 -0
  106. package/studio/chunks/Button-BT3ztSPx.js +14319 -0
  107. package/studio/chunks/Button-BT3ztSPx.js.br +0 -0
  108. package/studio/chunks/Button-BT3ztSPx.js.gz +0 -0
  109. package/studio/chunks/Collapsible-CKnEYIlp.js +246 -0
  110. package/studio/chunks/Collapsible-CKnEYIlp.js.br +0 -0
  111. package/studio/chunks/Collapsible-CKnEYIlp.js.gz +0 -0
  112. package/studio/chunks/ContentInventory-D7nsFA6U.js +1745 -0
  113. package/studio/chunks/ContentInventory-D7nsFA6U.js.br +0 -0
  114. package/studio/chunks/ContentInventory-D7nsFA6U.js.gz +0 -0
  115. package/studio/chunks/ContentPage-DCxt6BeD.js +18 -0
  116. package/studio/chunks/ContentPage-DCxt6BeD.js.br +0 -0
  117. package/studio/chunks/ContentPage-DCxt6BeD.js.gz +0 -0
  118. package/studio/chunks/DashboardSearch-DjyMjJwF.js +2413 -0
  119. package/studio/chunks/DashboardSearch-DjyMjJwF.js.br +0 -0
  120. package/studio/chunks/DashboardSearch-DjyMjJwF.js.gz +0 -0
  121. package/studio/chunks/DocumentLocaleMenu-0EkkOr6_.js +26063 -0
  122. package/studio/chunks/DocumentLocaleMenu-0EkkOr6_.js.br +0 -0
  123. package/studio/chunks/DocumentLocaleMenu-0EkkOr6_.js.gz +0 -0
  124. package/studio/chunks/DropdownMenu-CA9fB0uZ.js +4400 -0
  125. package/studio/chunks/DropdownMenu-CA9fB0uZ.js.br +0 -0
  126. package/studio/chunks/DropdownMenu-CA9fB0uZ.js.gz +0 -0
  127. package/studio/chunks/EditorPage-D_PAYEE4.js +7799 -0
  128. package/studio/chunks/EditorPage-D_PAYEE4.js.br +0 -0
  129. package/studio/chunks/EditorPage-D_PAYEE4.js.gz +0 -0
  130. package/studio/chunks/FormField-CgM6l2Yn.js +198 -0
  131. package/studio/chunks/FormField-CgM6l2Yn.js.br +0 -0
  132. package/studio/chunks/FormField-CgM6l2Yn.js.gz +0 -0
  133. package/studio/chunks/HelpPage-C-vrFcT_.js +552 -0
  134. package/studio/chunks/HelpPage-C-vrFcT_.js.br +0 -0
  135. package/studio/chunks/HelpPage-C-vrFcT_.js.gz +0 -0
  136. package/studio/chunks/Kbd-Ot7TIhVZ.js +271 -0
  137. package/studio/chunks/Kbd-Ot7TIhVZ.js.br +0 -0
  138. package/studio/chunks/Kbd-Ot7TIhVZ.js.gz +0 -0
  139. package/studio/chunks/MediaFolderDialog-DYu-eu-q.js +101 -0
  140. package/studio/chunks/MediaFolderDialog-DYu-eu-q.js.br +0 -0
  141. package/studio/chunks/MediaFolderDialog-DYu-eu-q.js.gz +0 -0
  142. package/studio/chunks/MediaPage-D-jaWtdl.js +923 -0
  143. package/studio/chunks/MediaPage-D-jaWtdl.js.br +0 -0
  144. package/studio/chunks/MediaPage-D-jaWtdl.js.gz +0 -0
  145. package/studio/chunks/MediaPicker-BZs2wUFz.js +837 -0
  146. package/studio/chunks/MediaPicker-BZs2wUFz.js.br +0 -0
  147. package/studio/chunks/MediaPicker-BZs2wUFz.js.gz +0 -0
  148. package/studio/chunks/MediaUploadPanel-C7Kyg6aR.js +1173 -0
  149. package/studio/chunks/MediaUploadPanel-C7Kyg6aR.js.br +0 -0
  150. package/studio/chunks/MediaUploadPanel-C7Kyg6aR.js.gz +0 -0
  151. package/studio/chunks/Modal-D6hSvxHd.js +265 -0
  152. package/studio/chunks/Modal-D6hSvxHd.js.br +0 -0
  153. package/studio/chunks/Modal-D6hSvxHd.js.gz +0 -0
  154. package/studio/chunks/NewDocumentDialog-C8B6_r3J.js +277 -0
  155. package/studio/chunks/NewDocumentDialog-C8B6_r3J.js.br +0 -0
  156. package/studio/chunks/NewDocumentDialog-C8B6_r3J.js.gz +0 -0
  157. package/studio/chunks/Pagination-D9BSo5H2.js +573 -0
  158. package/studio/chunks/Pagination-D9BSo5H2.js.br +0 -0
  159. package/studio/chunks/Pagination-D9BSo5H2.js.gz +0 -0
  160. package/studio/chunks/PeoplePage-CWIXitBD.js +783 -0
  161. package/studio/chunks/PeoplePage-CWIXitBD.js.br +0 -0
  162. package/studio/chunks/PeoplePage-CWIXitBD.js.gz +0 -0
  163. package/studio/chunks/Popover-B63bkTMS.js +128 -0
  164. package/studio/chunks/Popover-B63bkTMS.js.br +0 -0
  165. package/studio/chunks/Popover-B63bkTMS.js.gz +0 -0
  166. package/studio/chunks/PublicationActionDialog-Cm_P0C3I.js +255 -0
  167. package/studio/chunks/PublicationActionDialog-Cm_P0C3I.js.br +0 -0
  168. package/studio/chunks/PublicationActionDialog-Cm_P0C3I.js.gz +0 -0
  169. package/studio/chunks/Routes-DLYHmulE.js +102 -0
  170. package/studio/chunks/Routes-DLYHmulE.js.br +0 -0
  171. package/studio/chunks/Routes-DLYHmulE.js.gz +0 -0
  172. package/studio/chunks/RovingFocusItem-QZNg-wWF.js +95 -0
  173. package/studio/chunks/RovingFocusItem-QZNg-wWF.js.br +0 -0
  174. package/studio/chunks/RovingFocusItem-QZNg-wWF.js.gz +0 -0
  175. package/studio/chunks/ScheduledPage-C0hqrkr5.js +332 -0
  176. package/studio/chunks/ScheduledPage-C0hqrkr5.js.br +0 -0
  177. package/studio/chunks/ScheduledPage-C0hqrkr5.js.gz +0 -0
  178. package/studio/chunks/Search-BEgCe9Aj.js +14646 -0
  179. package/studio/chunks/Search-BEgCe9Aj.js.br +0 -0
  180. package/studio/chunks/Search-BEgCe9Aj.js.gz +0 -0
  181. package/studio/chunks/Select-B50WZMW-.js +2145 -0
  182. package/studio/chunks/Select-B50WZMW-.js.br +0 -0
  183. package/studio/chunks/Select-B50WZMW-.js.gz +0 -0
  184. package/studio/chunks/SelectMenu-DSweWGMz.js +2109 -0
  185. package/studio/chunks/SelectMenu-DSweWGMz.js.br +0 -0
  186. package/studio/chunks/SelectMenu-DSweWGMz.js.gz +0 -0
  187. package/studio/chunks/SeoPage-CNNxGe4h.js +846 -0
  188. package/studio/chunks/SeoPage-CNNxGe4h.js.br +0 -0
  189. package/studio/chunks/SeoPage-CNNxGe4h.js.gz +0 -0
  190. package/studio/chunks/Skeleton-COz8dcrw.js +39 -0
  191. package/studio/chunks/Skeleton-COz8dcrw.js.br +2 -0
  192. package/studio/chunks/Skeleton-COz8dcrw.js.gz +0 -0
  193. package/studio/chunks/Slideover-QMMHAAys.js +289 -0
  194. package/studio/chunks/Slideover-QMMHAAys.js.br +0 -0
  195. package/studio/chunks/Slideover-QMMHAAys.js.gz +0 -0
  196. package/studio/chunks/StudioPage-ngEIDr5d.js +80 -0
  197. package/studio/chunks/StudioPage-ngEIDr5d.js.br +0 -0
  198. package/studio/chunks/StudioPage-ngEIDr5d.js.gz +0 -0
  199. package/studio/chunks/StudioPageToolbar-BwHnqyr6.js +2524 -0
  200. package/studio/chunks/StudioPageToolbar-BwHnqyr6.js.br +0 -0
  201. package/studio/chunks/StudioPageToolbar-BwHnqyr6.js.gz +0 -0
  202. package/studio/chunks/Switch-qKl1aDn7.js +484 -0
  203. package/studio/chunks/Switch-qKl1aDn7.js.br +0 -0
  204. package/studio/chunks/Switch-qKl1aDn7.js.gz +0 -0
  205. package/studio/chunks/ToolPage-DxoVAJVk.js +29 -0
  206. package/studio/chunks/ToolPage-DxoVAJVk.js.br +0 -0
  207. package/studio/chunks/ToolPage-DxoVAJVk.js.gz +0 -0
  208. package/studio/chunks/Tooltip-Bu15m_DB.js +693 -0
  209. package/studio/chunks/Tooltip-Bu15m_DB.js.br +0 -0
  210. package/studio/chunks/Tooltip-Bu15m_DB.js.gz +0 -0
  211. package/studio/chunks/TrashPage-lhqLLdoG.js +12 -0
  212. package/studio/chunks/TrashPage-lhqLLdoG.js.br +0 -0
  213. package/studio/chunks/TrashPage-lhqLLdoG.js.gz +0 -0
  214. package/studio/chunks/VersionsPage-Cqy6UAp9.js +2349 -0
  215. package/studio/chunks/VersionsPage-Cqy6UAp9.js.br +0 -0
  216. package/studio/chunks/VersionsPage-Cqy6UAp9.js.gz +0 -0
  217. package/studio/chunks/VisuallyHiddenInput-Cu8hQLRf.js +113 -0
  218. package/studio/chunks/VisuallyHiddenInput-Cu8hQLRf.js.br +0 -0
  219. package/studio/chunks/VisuallyHiddenInput-Cu8hQLRf.js.gz +0 -0
  220. package/studio/chunks/arrays-CUJkmV4I.js +10 -0
  221. package/studio/chunks/arrays-CUJkmV4I.js.br +0 -0
  222. package/studio/chunks/arrays-CUJkmV4I.js.gz +0 -0
  223. package/studio/chunks/base-DkTekJe8.js +213 -0
  224. package/studio/chunks/base-DkTekJe8.js.br +0 -0
  225. package/studio/chunks/base-DkTekJe8.js.gz +0 -0
  226. package/studio/chunks/content-DUGl3N4d.js +6012 -0
  227. package/studio/chunks/content-DUGl3N4d.js.br +0 -0
  228. package/studio/chunks/content-DUGl3N4d.js.gz +0 -0
  229. package/studio/chunks/destinations-DPIQVQa6.js +227 -0
  230. package/studio/chunks/destinations-DPIQVQa6.js.br +0 -0
  231. package/studio/chunks/destinations-DPIQVQa6.js.gz +0 -0
  232. package/studio/chunks/en-073cjKW4.js +152 -0
  233. package/studio/chunks/en-073cjKW4.js.br +0 -0
  234. package/studio/chunks/en-073cjKW4.js.gz +0 -0
  235. package/studio/chunks/en-Bn8mxPuf.js +134 -0
  236. package/studio/chunks/en-Bn8mxPuf.js.br +0 -0
  237. package/studio/chunks/en-Bn8mxPuf.js.gz +0 -0
  238. package/studio/chunks/en-C9OiaUDZ.js +251 -0
  239. package/studio/chunks/en-C9OiaUDZ.js.br +0 -0
  240. package/studio/chunks/en-C9OiaUDZ.js.gz +0 -0
  241. package/studio/chunks/en-CHAR6jzx.js +147 -0
  242. package/studio/chunks/en-CHAR6jzx.js.br +0 -0
  243. package/studio/chunks/en-CHAR6jzx.js.gz +0 -0
  244. package/studio/chunks/en-Cq4N1vEF.js +93 -0
  245. package/studio/chunks/en-Cq4N1vEF.js.br +2 -0
  246. package/studio/chunks/en-Cq4N1vEF.js.gz +0 -0
  247. package/studio/chunks/en-D2hRqlse.js +140 -0
  248. package/studio/chunks/en-D2hRqlse.js.br +0 -0
  249. package/studio/chunks/en-D2hRqlse.js.gz +0 -0
  250. package/studio/chunks/en-DiUC3-j6.js +144 -0
  251. package/studio/chunks/en-DiUC3-j6.js.br +0 -0
  252. package/studio/chunks/en-DiUC3-j6.js.gz +0 -0
  253. package/studio/chunks/english-Cs_Adu-u.js +8 -0
  254. package/studio/chunks/english-Cs_Adu-u.js.br +0 -0
  255. package/studio/chunks/english-Cs_Adu-u.js.gz +0 -0
  256. package/studio/chunks/esm-D6DqSiL1.js +752 -0
  257. package/studio/chunks/esm-D6DqSiL1.js.br +0 -0
  258. package/studio/chunks/esm-D6DqSiL1.js.gz +0 -0
  259. package/studio/chunks/externalRequest-CTzr2nDq.js +23 -0
  260. package/studio/chunks/externalRequest-CTzr2nDq.js.br +0 -0
  261. package/studio/chunks/externalRequest-CTzr2nDq.js.gz +0 -0
  262. package/studio/chunks/iconify-DR9ryCPv.js +1007 -0
  263. package/studio/chunks/iconify-DR9ryCPv.js.br +0 -0
  264. package/studio/chunks/iconify-DR9ryCPv.js.gz +0 -0
  265. package/studio/chunks/icons-D2MsAaXq.js +183 -0
  266. package/studio/chunks/icons-D2MsAaXq.js.br +0 -0
  267. package/studio/chunks/icons-D2MsAaXq.js.gz +0 -0
  268. package/studio/chunks/leaveGuards-D22fTGgr.js +26 -0
  269. package/studio/chunks/leaveGuards-D22fTGgr.js.br +0 -0
  270. package/studio/chunks/leaveGuards-D22fTGgr.js.gz +0 -0
  271. package/studio/chunks/lucideIcons-EyqyPBsX.js +238 -0
  272. package/studio/chunks/lucideIcons-EyqyPBsX.js.br +0 -0
  273. package/studio/chunks/lucideIcons-EyqyPBsX.js.gz +0 -0
  274. package/studio/chunks/mediaRoute--8cY8rUe.js +17 -0
  275. package/studio/chunks/mediaRoute--8cY8rUe.js.br +0 -0
  276. package/studio/chunks/mediaRoute--8cY8rUe.js.gz +0 -0
  277. package/studio/chunks/newDocumentPlanning-C26DHpvh.js +77 -0
  278. package/studio/chunks/newDocumentPlanning-C26DHpvh.js.br +0 -0
  279. package/studio/chunks/newDocumentPlanning-C26DHpvh.js.gz +0 -0
  280. package/studio/chunks/notifications-OKOLc40v.js +110 -0
  281. package/studio/chunks/notifications-OKOLc40v.js.br +0 -0
  282. package/studio/chunks/notifications-OKOLc40v.js.gz +0 -0
  283. package/studio/chunks/operations-CjNHyrEX.js +57 -0
  284. package/studio/chunks/operations-CjNHyrEX.js.br +0 -0
  285. package/studio/chunks/operations-CjNHyrEX.js.gz +0 -0
  286. package/studio/chunks/overlay-DnqFLZTc.js +1733 -0
  287. package/studio/chunks/overlay-DnqFLZTc.js.br +0 -0
  288. package/studio/chunks/overlay-DnqFLZTc.js.gz +0 -0
  289. package/studio/chunks/presentation-DF83w0hE.js +57 -0
  290. package/studio/chunks/presentation-DF83w0hE.js.br +0 -0
  291. package/studio/chunks/presentation-DF83w0hE.js.gz +0 -0
  292. package/studio/chunks/runtime-core.esm-bundler-DKFA9Rep.js +4557 -0
  293. package/studio/chunks/runtime-core.esm-bundler-DKFA9Rep.js.br +0 -0
  294. package/studio/chunks/runtime-core.esm-bundler-DKFA9Rep.js.gz +0 -0
  295. package/studio/chunks/searchPresentation-DFwxQkt3.js +76 -0
  296. package/studio/chunks/searchPresentation-DFwxQkt3.js.br +0 -0
  297. package/studio/chunks/searchPresentation-DFwxQkt3.js.gz +0 -0
  298. package/studio/chunks/status-DQv6ihkU.js +38 -0
  299. package/studio/chunks/status-DQv6ihkU.js.br +0 -0
  300. package/studio/chunks/status-DQv6ihkU.js.gz +0 -0
  301. package/studio/chunks/studioContext-I8HozGU1.js +4953 -0
  302. package/studio/chunks/studioContext-I8HozGU1.js.br +0 -0
  303. package/studio/chunks/studioContext-I8HozGU1.js.gz +0 -0
  304. package/studio/chunks/studioQueries-BR-9NT5F.js +73 -0
  305. package/studio/chunks/studioQueries-BR-9NT5F.js.br +0 -0
  306. package/studio/chunks/studioQueries-BR-9NT5F.js.gz +0 -0
  307. package/studio/chunks/studioSearch-ByaL-QpM.js +1095 -0
  308. package/studio/chunks/studioSearch-ByaL-QpM.js.br +0 -0
  309. package/studio/chunks/studioSearch-ByaL-QpM.js.gz +0 -0
  310. package/studio/chunks/useAcknowledgedDraft-0_c9sWI6.js +62 -0
  311. package/studio/chunks/useAcknowledgedDraft-0_c9sWI6.js.br +0 -0
  312. package/studio/chunks/useAcknowledgedDraft-0_c9sWI6.js.gz +0 -0
  313. package/studio/chunks/useApi-CUWMwLLw-B3Q3g2nf.js +189 -0
  314. package/studio/chunks/useApi-CUWMwLLw-B3Q3g2nf.js.br +0 -0
  315. package/studio/chunks/useApi-CUWMwLLw-B3Q3g2nf.js.gz +0 -0
  316. package/studio/chunks/useDocumentMessage-BAWvc38w.js +16 -0
  317. package/studio/chunks/useDocumentMessage-BAWvc38w.js.br +3 -0
  318. package/studio/chunks/useDocumentMessage-BAWvc38w.js.gz +0 -0
  319. package/studio/chunks/useFilter-DzyiTR7f.js +87 -0
  320. package/studio/chunks/useFilter-DzyiTR7f.js.br +0 -0
  321. package/studio/chunks/useFilter-DzyiTR7f.js.gz +0 -0
  322. package/studio/chunks/useFormControl-CL7sSCUo.js +8 -0
  323. package/studio/chunks/useFormControl-CL7sSCUo.js.br +0 -0
  324. package/studio/chunks/useFormControl-CL7sSCUo.js.gz +0 -0
  325. package/studio/chunks/useGraceArea-Chcy25IQ.js +154 -0
  326. package/studio/chunks/useGraceArea-Chcy25IQ.js.br +0 -0
  327. package/studio/chunks/useGraceArea-Chcy25IQ.js.gz +0 -0
  328. package/studio/chunks/useLeaveConfirmation-_iCSnKEp.js +44 -0
  329. package/studio/chunks/useLeaveConfirmation-_iCSnKEp.js.br +8 -0
  330. package/studio/chunks/useLeaveConfirmation-_iCSnKEp.js.gz +0 -0
  331. package/studio/chunks/useLinkCopy-CMjQteCy.js +35 -0
  332. package/studio/chunks/useLinkCopy-CMjQteCy.js.br +0 -0
  333. package/studio/chunks/useLinkCopy-CMjQteCy.js.gz +0 -0
  334. package/studio/chunks/usePointerMotion-DwRcwBNQ.js +16 -0
  335. package/studio/chunks/usePointerMotion-DwRcwBNQ.js.br +0 -0
  336. package/studio/chunks/usePointerMotion-DwRcwBNQ.js.gz +0 -0
  337. package/studio/chunks/useStudioNavigation-CLwtSYpb.js +298 -0
  338. package/studio/chunks/useStudioNavigation-CLwtSYpb.js.br +0 -0
  339. package/studio/chunks/useStudioNavigation-CLwtSYpb.js.gz +0 -0
  340. package/studio/chunks/useStudioPages-DR9qmYLg.js +79 -0
  341. package/studio/chunks/useStudioPages-DR9qmYLg.js.br +0 -0
  342. package/studio/chunks/useStudioPages-DR9qmYLg.js.gz +0 -0
  343. package/studio/chunks/utils-mdScC0v0.js +59 -0
  344. package/studio/chunks/utils-mdScC0v0.js.br +0 -0
  345. package/studio/chunks/utils-mdScC0v0.js.gz +0 -0
  346. package/studio/chunks/virtualizer-D1S0bZ4t.js +781 -0
  347. package/studio/chunks/virtualizer-D1S0bZ4t.js.br +0 -0
  348. package/studio/chunks/virtualizer-D1S0bZ4t.js.gz +0 -0
  349. package/studio/help/64f767fe29c2-save-and-publish.svg +7 -0
  350. package/studio/host.css +1 -1
  351. package/studio/host.css.br +0 -0
  352. package/studio/host.css.gz +0 -0
  353. package/studio/host.js +8793 -39395
  354. package/studio/host.js.br +0 -0
  355. package/studio/host.js.gz +0 -0
  356. package/CHANGELOG.md +0 -14
  357. package/bin/cms.mjs +0 -2
  358. package/src/ApplicationTypes.d.ts +0 -84
  359. package/src/ApplicationTypes.js +0 -1
  360. package/src/Configuration-CMweD9bn.js +0 -1191
  361. package/src/Configuration-CMweD9bn.js.map +0 -1
  362. package/src/Configuration.d.ts +0 -82
  363. package/src/Configuration.js +0 -8
  364. package/src/Configuration.js.map +0 -1
  365. package/src/Content.d.ts +0 -68
  366. package/src/Content.js +0 -373
  367. package/src/Content.js.map +0 -1
  368. package/src/ContentTransfer-BxwswWn3.js +0 -86
  369. package/src/ContentTransfer-BxwswWn3.js.map +0 -1
  370. package/src/ContentTransfer-Z9FHyLez.d.ts +0 -72
  371. package/src/DocumentEngine-tYtwbBjr.js +0 -978
  372. package/src/DocumentEngine-tYtwbBjr.js.map +0 -1
  373. package/src/DocumentModel.d.ts +0 -52
  374. package/src/DocumentModel.js +0 -66
  375. package/src/DocumentModel.js.map +0 -1
  376. package/src/Forms-CX-hwmJF.js +0 -391
  377. package/src/Forms-CX-hwmJF.js.map +0 -1
  378. package/src/Forms-CfNPTiCr.js +0 -110
  379. package/src/Forms-CfNPTiCr.js.map +0 -1
  380. package/src/Forms-R0HoTR-o.d.ts +0 -92
  381. package/src/Forms.js.map +0 -1
  382. package/src/HttpPaths-Be3vshPJ.js +0 -20
  383. package/src/HttpPaths-Be3vshPJ.js.map +0 -1
  384. package/src/I18n-wxswIRyY.d.ts +0 -30
  385. package/src/Media-j1bTritO.js +0 -112
  386. package/src/Media-j1bTritO.js.map +0 -1
  387. package/src/Module.js.map +0 -1
  388. package/src/References-CCPDAPve.js +0 -45
  389. package/src/References-CCPDAPve.js.map +0 -1
  390. package/src/S3MediaObjects-BXfjaZOu.js +0 -2756
  391. package/src/S3MediaObjects-BXfjaZOu.js.map +0 -1
  392. package/src/Seo-402YumpT.d.ts +0 -198
  393. package/src/cli/content.js +0 -101
  394. package/src/cli/content.js.map +0 -1
  395. package/src/cli.js.map +0 -1
  396. package/src/connection-BP80q4d-.js +0 -92
  397. package/src/connection-BP80q4d-.js.map +0 -1
  398. package/src/dev-lifecycle-3I_pozUl.js +0 -535
  399. package/src/dev-lifecycle-3I_pozUl.js.map +0 -1
  400. package/src/installation-DxqSSVbH.js +0 -9105
  401. package/src/installation-DxqSSVbH.js.map +0 -1
  402. package/src/internal/application-types.js +0 -43
  403. package/src/internal/application-types.js.map +0 -1
  404. package/src/internal/authoring-catalog.js +0 -158
  405. package/src/internal/authoring-catalog.js.map +0 -1
  406. package/src/internal/authoring-compiler.js +0 -146
  407. package/src/internal/authoring-compiler.js.map +0 -1
  408. package/src/internal/authoring-metadata.js +0 -191
  409. package/src/internal/authoring-metadata.js.map +0 -1
  410. package/src/internal/cms-config.js +0 -45
  411. package/src/internal/cms-config.js.map +0 -1
  412. package/src/internal/configuration.js +0 -228
  413. package/src/internal/configuration.js.map +0 -1
  414. package/src/internal/dev-lifecycle.js +0 -3
  415. package/src/internal/diagnostics.js +0 -47
  416. package/src/internal/diagnostics.js.map +0 -1
  417. package/src/internal/document-model.js +0 -376
  418. package/src/internal/document-model.js.map +0 -1
  419. package/src/internal/field-metadata.js +0 -7
  420. package/src/internal/field-metadata.js.map +0 -1
  421. package/src/internal/form-capabilities.js +0 -12
  422. package/src/internal/form-capabilities.js.map +0 -1
  423. package/src/internal/i18n.js +0 -73
  424. package/src/internal/i18n.js.map +0 -1
  425. package/src/internal/studio-app.js +0 -68
  426. package/src/internal/studio-app.js.map +0 -1
  427. package/src/location-CMNGO3lU.js +0 -35
  428. package/src/location-CMNGO3lU.js.map +0 -1
  429. package/src/metadata-DN9_K6Yl.js +0 -201
  430. package/src/metadata-DN9_K6Yl.js.map +0 -1
  431. package/src/models-5j67LMqW.js +0 -131
  432. package/src/models-5j67LMqW.js.map +0 -1
  433. package/src/models-VmGmG19-.js +0 -628
  434. package/src/models-VmGmG19-.js.map +0 -1
  435. package/src/runtime/api.js.map +0 -1
  436. package/src/runtime/blocks.js +0 -30
  437. package/src/runtime/blocks.js.map +0 -1
  438. package/src/runtime/collaboration.js +0 -45
  439. package/src/runtime/collaboration.js.map +0 -1
  440. package/src/runtime/delivery/DocumentField.js +0 -23
  441. package/src/runtime/delivery/DocumentField.js.map +0 -1
  442. package/src/runtime/delivery/DocumentRenderer.js +0 -61
  443. package/src/runtime/delivery/DocumentRenderer.js.map +0 -1
  444. package/src/runtime/delivery/DocumentScope.js +0 -41
  445. package/src/runtime/delivery/DocumentScope.js.map +0 -1
  446. package/src/runtime/delivery/blocks.js +0 -8
  447. package/src/runtime/delivery/blocks.js.map +0 -1
  448. package/src/runtime/delivery/context.js +0 -12
  449. package/src/runtime/delivery/context.js.map +0 -1
  450. package/src/runtime/delivery/document-page.js +0 -21
  451. package/src/runtime/delivery/document-page.js.map +0 -1
  452. package/src/runtime/delivery/document.js +0 -43
  453. package/src/runtime/delivery/document.js.map +0 -1
  454. package/src/runtime/delivery/error.js +0 -11
  455. package/src/runtime/delivery/error.js.map +0 -1
  456. package/src/runtime/delivery/plugin.js +0 -104
  457. package/src/runtime/delivery/plugin.js.map +0 -1
  458. package/src/runtime/delivery/preview.d.ts +0 -11
  459. package/src/runtime/delivery/preview.js +0 -6
  460. package/src/runtime/delivery/preview.js.map +0 -1
  461. package/src/runtime/delivery/types.d.ts +0 -2
  462. package/src/runtime/delivery/types.js +0 -1
  463. package/src/runtime/delivery/useCmsDocumentSeo.d.ts +0 -67
  464. package/src/runtime/delivery/useCmsDocumentSeo.js.map +0 -1
  465. package/src/runtime/delivery/useDocument.d.ts +0 -6
  466. package/src/runtime/delivery/useDocument.js +0 -23
  467. package/src/runtime/delivery/useDocument.js.map +0 -1
  468. package/src/runtime/delivery/useDocumentQuery.d.ts +0 -7
  469. package/src/runtime/delivery/useDocumentQuery.js +0 -29
  470. package/src/runtime/delivery/useDocumentQuery.js.map +0 -1
  471. package/src/runtime/forms/document.js +0 -38
  472. package/src/runtime/forms/document.js.map +0 -1
  473. package/src/runtime/forms/useCmsForm.js +0 -257
  474. package/src/runtime/forms/useCmsForm.js.map +0 -1
  475. package/src/runtime/i18n/translator.js +0 -58
  476. package/src/runtime/i18n/translator.js.map +0 -1
  477. package/src/runtime/i18n/useCmsI18n.d.ts +0 -13
  478. package/src/runtime/i18n/useCmsI18n.js +0 -38
  479. package/src/runtime/i18n/useCmsI18n.js.map +0 -1
  480. package/src/runtime/installation.js +0 -3
  481. package/src/runtime/plugin.js.map +0 -1
  482. package/src/runtime/preview/CmsStudioPreviewMarker.js +0 -29
  483. package/src/runtime/preview/CmsStudioPreviewMarker.js.map +0 -1
  484. package/src/runtime/preview/comark-document.js +0 -37
  485. package/src/runtime/preview/comark-document.js.map +0 -1
  486. package/src/runtime/preview/connection.js +0 -3
  487. package/src/runtime/preview/controller.js +0 -265
  488. package/src/runtime/preview/controller.js.map +0 -1
  489. package/src/runtime/preview/crypto.js +0 -16
  490. package/src/runtime/preview/crypto.js.map +0 -1
  491. package/src/runtime/preview/overlay.js +0 -122
  492. package/src/runtime/preview/overlay.js.map +0 -1
  493. package/src/runtime/preview/plugin.client.js +0 -68
  494. package/src/runtime/preview/plugin.client.js.map +0 -1
  495. package/src/runtime/preview/preview.css +0 -91
  496. package/src/runtime/preview/protocol.d.ts +0 -16
  497. package/src/runtime/preview/protocol.js +0 -23
  498. package/src/runtime/preview/protocol.js.map +0 -1
  499. package/src/runtime/preview/regions.js +0 -142
  500. package/src/runtime/preview/regions.js.map +0 -1
  501. package/src/runtime/preview/store.js +0 -4
  502. package/src/runtime/sitemap-entries.js +0 -17
  503. package/src/runtime/sitemap-entries.js.map +0 -1
  504. package/src/runtime/sitemap.js +0 -23
  505. package/src/runtime/sitemap.js.map +0 -1
  506. package/src/runtime/studio-app.js +0 -17
  507. package/src/runtime/studio-app.js.map +0 -1
  508. package/src/runtime/studio-document.js +0 -46
  509. package/src/runtime/studio-document.js.map +0 -1
  510. package/src/runtime/studio-entry.js +0 -19
  511. package/src/runtime/studio-entry.js.map +0 -1
  512. package/src/runtime/studio-navigation.js +0 -11
  513. package/src/runtime/studio-navigation.js.map +0 -1
  514. package/src/scalars-CA6kyipS.d.ts +0 -7
  515. package/src/scalars-CVZqT3L0.js +0 -22
  516. package/src/scalars-CVZqT3L0.js.map +0 -1
  517. package/src/store-X1e1o_MF.js +0 -209
  518. package/src/store-X1e1o_MF.js.map +0 -1
  519. package/src/types-DZ0IV-Ow.d.ts +0 -101
  520. package/studio/CreateDocumentDialog-C4_JBo1w.js +0 -335
  521. package/studio/SelectMenu-wXqxymUw.js +0 -34045
  522. package/studio/collaboration-DcK2F6v9.js +0 -4566
  523. package/studio/editor-P2rB7Csp.js +0 -30128
  524. package/studio/rolldown-runtime-Dy4uBu1J.js +0 -11
@@ -1,2756 +0,0 @@
1
- import { i as DocumentVersion, l as Slug, n as DocumentHistoryCursor, o as PublicPath, r as DocumentId, s as RevisionId, t as DocumentGeneration, u as nonNegativeInt } from "./scalars-CVZqT3L0.js";
2
- import { $ as MEDIA_ACTIONS, A as RestoreDocumentInput, B as SeoConfiguration, C as MoveDocumentInput, D as PublishedDocumentQuery, E as PublishedDocumentPage, F as GlobalSeoSettings, G as SeoSnapshot, H as SeoMediaUnavailable, I as PublishSeoInput, J as SeoVersionConflict, K as SeoState, L as SaveSeoInput, N as UpdateDocumentInput, O as PublishedDocumentSurroundQuery, Q as DOCUMENT_ACTIONS, R as SeoCanonicalOrigin, T as PublishedDocumentLookup, U as SeoMutationResult, V as SeoConfirmationRequired, X as AccessDenied, Y as SitemapEntry, Z as AuthenticationRequired, b as DocumentValidationResult, d as DocumentNavigationItem, et as Role, f as DocumentNavigationQuery, g as DocumentSource, h as DocumentRevisionAction, i as CreateDocumentInput, j as UndeleteDocumentInput, k as RemoveDocumentInput, l as DocumentIssue, m as DocumentQueryScalar, n as CmsMarkdownDocument, nt as StudioEntryDenied, o as DeletedDocument, p as DocumentPlacement, q as SeoUrl, r as CompiledDocument, s as DocumentBrowseQuery, st as RequestId, tt as StudioActor, u as DocumentMutationResult, v as DocumentSummary, w as PublishDocumentInput, x as DuplicateDocumentInput, y as DocumentSurround, z as SeoCapabilities } from "./models-VmGmG19-.js";
3
- import { _ as MediaReferenced, a as MediaConflict, b as MediaUpload, c as MediaId, f as MediaNotFound, g as MediaReference, h as MediaQuery, i as MediaCleanupReport, l as MediaIntegrityReport, m as MediaPage, n as MediaAsset, p as MediaObjectKey, r as MediaByteSize, s as MediaFolder, t as ImageMimeType, u as MediaInvalid, y as MediaTooLarge } from "./Media-j1bTritO.js";
4
- import { a as ContentSnapshot, c as ContentTransferConflict, d as DocumentNotFound, f as DocumentRouteConflict, h as PublishedDocumentNotFound, i as ContentPlan, l as ContentTransferInput, m as DocumentVersionConflict, n as ContentApplyResult, p as DocumentValidationFailed, t as ContentApplyInput, u as DocumentMediaUnavailable } from "./ContentTransfer-BxwswWn3.js";
5
- import { u as STUDIO_API_PATH } from "./HttpPaths-Be3vshPJ.js";
6
- import { c as FormSubmission, o as FormResult } from "./Forms-CfNPTiCr.js";
7
- import { m as toComarkDocument } from "./Forms-CX-hwmJF.js";
8
- import { i as withoutEditorMetadata } from "./metadata-DN9_K6Yl.js";
9
- import { f as EditorRenderFailed, i as MediaConfiguration, r as DocumentConfiguration } from "./Configuration-CMweD9bn.js";
10
- import { n as DocumentCompilationFailed, t as createDocumentEngine } from "./DocumentEngine-tYtwbBjr.js";
11
- import { Context, Crypto, Data, DateTime, Effect, Encoding, Layer, Option, Predicate, PubSub, Redacted, Ref, Result, Schedule, Schema, Semaphore, Stream, flow } from "effect";
12
- import { NodeStream } from "@effect/platform-node-shared";
13
- import { Multipart } from "effect/unstable/http";
14
- import { HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema } from "effect/unstable/httpapi";
15
- import { renderMarkdown } from "comark/render";
16
- import { diffArrays } from "diff";
17
- import { CopyObjectCommand, CreateBucketCommand, DeleteObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
18
-
19
- //#region ../protocol/src/Activity.ts
20
- /**
21
- * Immutable completed Activity facts. Pages are ordered newest-first; cursors are opaque,
22
- * stable continuation tokens and an invalid cursor is a caller-visible failure.
23
- */
24
- const ActivityId = Schema.String.check(Schema.isUUID()).pipe(Schema.brand("ActivityId"));
25
- const ActivityCursor = Schema.NonEmptyString.pipe(Schema.brand("ActivityCursor"));
26
- const ACTIVITY_ACTIONS = [
27
- "document.created",
28
- "document.updated",
29
- "document.moved",
30
- "document.trashed",
31
- "document.revision.restored",
32
- "document.untrashed",
33
- "document.published",
34
- "document.unpublished",
35
- "media.uploaded",
36
- "media.replaced",
37
- "media.removed",
38
- "media.cleaned",
39
- "seo.saved",
40
- "seo.published",
41
- "user.created",
42
- "user.removed",
43
- "user.role.changed",
44
- "user.sessions.revoked",
45
- "authentication.signed-in",
46
- "authentication.signed-out",
47
- "authentication.password.changed",
48
- "authentication.password.reset"
49
- ];
50
- const ActivityAction = Schema.Literals(ACTIVITY_ACTIONS);
51
- const DocumentActivityTarget = Schema.Struct({
52
- kind: Schema.tag("document"),
53
- documentId: DocumentId
54
- });
55
- const MediaActivityTarget = Schema.Struct({
56
- kind: Schema.tag("media"),
57
- mediaId: MediaId
58
- });
59
- const MediaLibraryActivityTarget = Schema.Struct({ kind: Schema.tag("media-library") });
60
- const ActivityTarget = Schema.Union([
61
- DocumentActivityTarget,
62
- MediaActivityTarget,
63
- MediaLibraryActivityTarget,
64
- Schema.Struct({ kind: Schema.tag("seo") }),
65
- Schema.Struct({
66
- kind: Schema.tag("user"),
67
- userId: Schema.NonEmptyString
68
- })
69
- ]).pipe(Schema.toTaggedUnion("kind"));
70
- const ActivityTargetKind = Schema.Literals([
71
- "document",
72
- "media",
73
- "media-library",
74
- "seo",
75
- "user"
76
- ]);
77
- const ActivityContext = Schema.Struct({
78
- actor: StudioActor,
79
- requestId: RequestId,
80
- reason: Schema.optionalKey(Schema.NonEmptyString.check(Schema.isMaxLength(1e3)))
81
- }).annotate({ identifier: "ActivityContext" });
82
- const ActivityEntry = Schema.Struct({
83
- id: ActivityId,
84
- action: ActivityAction,
85
- actor: StudioActor,
86
- requestId: RequestId,
87
- reason: ActivityContext.fields.reason,
88
- target: ActivityTarget,
89
- details: Schema.JsonObject,
90
- occurredAt: Schema.DateTimeUtcFromString
91
- }).annotate({ identifier: "ActivityEntry" });
92
- const ActivityEntryDraft = Schema.Struct({
93
- action: ActivityAction,
94
- context: ActivityContext,
95
- target: ActivityTarget,
96
- details: Schema.JsonObject
97
- }).annotate({ identifier: "ActivityEntryDraft" });
98
- const ActivityQuery = Schema.Struct({
99
- action: Schema.optionalKey(ActivityAction),
100
- actorId: Schema.optionalKey(StudioActor.fields.id),
101
- cursor: Schema.optionalKey(ActivityCursor),
102
- limit: Schema.optionalKey(Schema.Int.check(Schema.isBetween({
103
- minimum: 1,
104
- maximum: 100
105
- }))),
106
- requestId: Schema.optionalKey(RequestId),
107
- targetId: Schema.optionalKey(Schema.NonEmptyString),
108
- targetKind: Schema.optionalKey(ActivityTargetKind)
109
- }).annotate({ identifier: "ActivityQuery" });
110
- const ActivityPage = Schema.Struct({
111
- entries: Schema.Array(ActivityEntry),
112
- nextCursor: Schema.optionalKey(ActivityCursor),
113
- total: nonNegativeInt
114
- }).annotate({ identifier: "ActivityPage" });
115
- var ActivityCursorInvalid = class extends Schema.TaggedError()("Activity.CursorInvalid", {}) {};
116
-
117
- //#endregion
118
- //#region ../protocol/src/internal/documents/history.ts
119
- const DocumentRevisionSummary = Schema.Struct({
120
- action: DocumentRevisionAction,
121
- activity: ActivityEntry,
122
- createdAt: Schema.DateTimeUtcFromString,
123
- documentId: DocumentId,
124
- placement: DocumentPlacement,
125
- revisionId: RevisionId,
126
- version: DocumentVersion
127
- }).annotate({ identifier: "DocumentRevisionSummary" });
128
- const DocumentRevision = Schema.Struct({
129
- ...DocumentRevisionSummary.fields,
130
- markdown: Schema.String
131
- }).annotate({ identifier: "DocumentRevision" });
132
- const DocumentHistoryQuery = Schema.Struct({
133
- documentId: DocumentId,
134
- cursor: Schema.optionalKey(DocumentHistoryCursor),
135
- limit: Schema.optionalKey(Schema.Int.check(Schema.isBetween({
136
- minimum: 1,
137
- maximum: 100
138
- })))
139
- }).annotate({ identifier: "DocumentHistoryQuery" });
140
- const DocumentRevisionPage = Schema.Struct({
141
- revisions: Schema.Array(DocumentRevisionSummary),
142
- nextCursor: Schema.optionalKey(DocumentHistoryCursor),
143
- total: nonNegativeInt
144
- }).annotate({ identifier: "DocumentRevisionPage" });
145
- const LineNumber = Schema.Int.check(Schema.isGreaterThan(0));
146
- const DocumentRevisionChange = Schema.Union([
147
- Schema.Struct({
148
- kind: Schema.tag("equal"),
149
- beforeLine: LineNumber,
150
- afterLine: LineNumber,
151
- line: Schema.String
152
- }),
153
- Schema.Struct({
154
- kind: Schema.tag("added"),
155
- afterLine: LineNumber,
156
- line: Schema.String
157
- }),
158
- Schema.Struct({
159
- kind: Schema.tag("removed"),
160
- beforeLine: LineNumber,
161
- line: Schema.String
162
- })
163
- ]).pipe(Schema.toTaggedUnion("kind"));
164
- const CompareDocumentRevisionsInput = Schema.Struct({
165
- documentId: DocumentId,
166
- fromRevisionId: RevisionId,
167
- toRevisionId: RevisionId
168
- }).annotate({ identifier: "CompareDocumentRevisionsInput" });
169
- const DocumentRevisionComparison = Schema.Struct({
170
- from: DocumentRevision,
171
- to: DocumentRevision,
172
- changes: Schema.Array(DocumentRevisionChange)
173
- }).annotate({ identifier: "DocumentRevisionComparison" });
174
- var DocumentHistoryInvalidCursor = class extends Schema.TaggedError()("DocumentHistory.InvalidCursor", {}) {};
175
- var DocumentHistoryComparisonTooLarge = class extends Schema.TaggedError()("DocumentHistory.ComparisonTooLarge", {
176
- maximumEditLength: Schema.Int.check(Schema.isGreaterThan(0)),
177
- maximumLines: Schema.Int.check(Schema.isGreaterThan(0))
178
- }) {};
179
-
180
- //#endregion
181
- //#region ../protocol/src/Collaboration.ts
182
- /**
183
- * Collaboration handshake and WebSocket envelopes. Command results correlate by RequestId;
184
- * checkpoints carry the durable state vector needed for retry and recovery.
185
- */
186
- const CollaborationColors = [
187
- "#2563eb",
188
- "#7c3aed",
189
- "#db2777",
190
- "#dc2626",
191
- "#d97706",
192
- "#059669",
193
- "#0891b2",
194
- "#4f46e5",
195
- "#9333ea",
196
- "#c026d3",
197
- "#e11d48",
198
- "#0d9488"
199
- ];
200
- const StateVector = Schema.String.check(Schema.isBase64()).pipe(Schema.brand("StateVector"));
201
- const HttpErrorStatus = Schema.Int.check(Schema.isBetween({
202
- minimum: 400,
203
- maximum: 599
204
- }));
205
- const CollaborationUser = Schema.Struct({
206
- color: Schema.NonEmptyString,
207
- id: Schema.NonEmptyString,
208
- name: Schema.NonEmptyString
209
- });
210
- const CollaborationTicket = Schema.Struct({
211
- authoringRevision: Schema.NonEmptyString,
212
- authoredStateVector: StateVector,
213
- documentName: Schema.NonEmptyString,
214
- source: DocumentSource,
215
- token: Schema.NonEmptyString,
216
- url: Schema.NonEmptyString,
217
- user: CollaborationUser,
218
- workingStateVector: StateVector
219
- }).annotate({ identifier: "CollaborationTicket" });
220
- const CollaborationPreview = DocumentValidationResult.pipe(Schema.fieldsAssign({
221
- markdown: Schema.String,
222
- preview: Schema.Struct({
223
- body: CmsMarkdownDocument,
224
- fallbacks: Schema.Record(Schema.String, Schema.String)
225
- })
226
- })).annotate({ identifier: "CollaborationPreview" });
227
- const CheckpointMessage = Schema.Struct({ type: Schema.tag("checkpoint") });
228
- const PreviewMessage = Schema.Struct({
229
- type: Schema.tag("preview"),
230
- requestId: RequestId
231
- });
232
- const PublishMessage = Schema.Struct({
233
- type: Schema.tag("publish"),
234
- requestId: RequestId
235
- });
236
- const CollaborationClientMessage = Schema.Union([
237
- CheckpointMessage,
238
- PreviewMessage,
239
- PublishMessage
240
- ]).pipe(Schema.toTaggedUnion("type"));
241
- const requestFailure = {
242
- error: Schema.NonEmptyString,
243
- statusCode: HttpErrorStatus
244
- };
245
- const RequestFailure = Schema.Struct({
246
- status: Schema.tag("failure"),
247
- ...requestFailure
248
- });
249
- const PreviewOutcome = Schema.Union([Schema.Struct({
250
- status: Schema.tag("success"),
251
- result: CollaborationPreview
252
- }), RequestFailure]).pipe(Schema.toTaggedUnion("status"));
253
- const PublishCheckpoint = Schema.Struct({
254
- authoredStateVector: StateVector,
255
- result: Schema.optionalKey(DocumentMutationResult)
256
- });
257
- const PublishOutcome = Schema.Union([Schema.Struct({
258
- status: Schema.tag("success"),
259
- authoredStateVector: StateVector,
260
- result: DocumentMutationResult
261
- }), Schema.Struct({
262
- status: Schema.tag("failure"),
263
- ...requestFailure,
264
- checkpoint: Schema.optionalKey(PublishCheckpoint)
265
- })]).pipe(Schema.toTaggedUnion("status"));
266
- const WorkingSavedMessage = Schema.Struct({
267
- type: Schema.tag("working-saved"),
268
- workingStateVector: StateVector
269
- });
270
- const WorkingSaveErrorMessage = Schema.Struct({
271
- type: Schema.tag("working-save-error"),
272
- error: Schema.NonEmptyString
273
- });
274
- const PreviewResultMessage = Schema.Struct({
275
- type: Schema.tag("preview-result"),
276
- requestId: RequestId,
277
- outcome: PreviewOutcome
278
- });
279
- const PublishResultMessage = Schema.Struct({
280
- type: Schema.tag("publish-result"),
281
- requestId: RequestId,
282
- outcome: PublishOutcome
283
- });
284
- const CollaborationServerMessage = Schema.Union([
285
- WorkingSavedMessage,
286
- WorkingSaveErrorMessage,
287
- PreviewResultMessage,
288
- PublishResultMessage
289
- ]).pipe(Schema.toTaggedUnion("type"));
290
-
291
- //#endregion
292
- //#region ../protocol/src/Users.ts
293
- /**
294
- * User administration inputs, offset-paginated directory results, and caller-visible command
295
- * failures. Commands carry no idempotency key; clients resolve ambiguous outcomes by listing again.
296
- */
297
- const UserEmail = Schema.NonEmptyString.check(Schema.isMaxLength(320), Schema.isPattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/u)).annotate({ identifier: "UserEmail" });
298
- const UserName = Schema.NonEmptyString.check(Schema.isMaxLength(200)).annotate({ identifier: "UserName" });
299
- const UserPassword = Schema.NonEmptyString.check(Schema.isMinLength(8), Schema.isMaxLength(200)).annotate({ identifier: "UserPassword" });
300
- const User = Schema.Struct({
301
- id: Schema.NonEmptyString,
302
- email: UserEmail,
303
- name: UserName,
304
- role: Role,
305
- emailVerified: Schema.Boolean,
306
- banned: Schema.Boolean,
307
- createdAt: Schema.DateTimeUtcFromString,
308
- updatedAt: Schema.DateTimeUtcFromString
309
- }).annotate({ identifier: "User" });
310
- const UserPage = Schema.Struct({
311
- users: Schema.Array(User),
312
- total: nonNegativeInt
313
- }).annotate({ identifier: "UserPage" });
314
- const UserQuery = Schema.Struct({
315
- limit: Schema.optionalKey(Schema.Int.check(Schema.isBetween({
316
- minimum: 1,
317
- maximum: 100
318
- }))),
319
- offset: Schema.optionalKey(nonNegativeInt),
320
- search: Schema.optionalKey(Schema.NonEmptyString.check(Schema.isMaxLength(200)))
321
- }).annotate({ identifier: "UserQuery" });
322
- const CreateUserInput = Schema.Struct({
323
- email: UserEmail,
324
- name: UserName,
325
- password: UserPassword,
326
- role: Role
327
- }).annotate({ identifier: "CreateUserInput" });
328
- var UserAlreadyExists = class extends Schema.TaggedError()("User.AlreadyExists", { email: UserEmail }) {};
329
- var UserNotFound = class extends Schema.TaggedError()("User.NotFound", { userId: User.fields.id }) {};
330
- var UserSelfRemovalDenied = class extends Schema.TaggedError()("User.SelfRemovalDenied", { userId: User.fields.id }) {};
331
- var UserSelfRoleChangeDenied = class extends Schema.TaggedError()("User.SelfRoleChangeDenied", { userId: User.fields.id }) {};
332
- var UserAdministrationDenied = class extends Schema.TaggedError()("UserAdministration.Denied", {}) {};
333
-
334
- //#endregion
335
- //#region ../protocol/src/Initialization.ts
336
- const InitializationInput = Schema.Struct({
337
- email: UserEmail,
338
- initializationToken: Schema.NonEmptyString.check(Schema.isMaxLength(512)),
339
- name: UserName,
340
- password: UserPassword
341
- }).annotate({ identifier: "InitializationInput" });
342
- const InitializationState = Schema.Struct({ needsAdministrator: Schema.Boolean }).annotate({ identifier: "InitializationState" });
343
- var InitializationAlreadyCompleted = class extends Schema.TaggedError()("Initialization.AlreadyCompleted", {}) {};
344
- var InitializationProofInvalid = class extends Schema.TaggedError()("Initialization.ProofInvalid", {}) {};
345
-
346
- //#endregion
347
- //#region ../protocol/src/internal/http/failures.ts
348
- var StudioInternalError = class extends Schema.TaggedError()("Studio.InternalError", { message: Schema.Literal("The request could not be completed.") }) {};
349
- function studioInternalError() {
350
- return new StudioInternalError({ message: "The request could not be completed." });
351
- }
352
-
353
- //#endregion
354
- //#region ../protocol/src/internal/http/delivery.ts
355
- const DeliverySurroundPayload = Schema.Struct({
356
- lookup: PublishedDocumentLookup,
357
- query: PublishedDocumentSurroundQuery
358
- }).annotate({ identifier: "DeliverySurroundPayload" });
359
- const InternalError$1 = StudioInternalError.pipe(HttpApiSchema.status(500));
360
- const PublishedNotFound = PublishedDocumentNotFound.pipe(HttpApiSchema.status(404));
361
- const Forbidden$1 = AccessDenied.pipe(HttpApiSchema.status(403));
362
- const PublishedDeliveryApi = HttpApiGroup.make("delivery").add(HttpApiEndpoint.post("read", "/read", {
363
- payload: PublishedDocumentLookup,
364
- success: CompiledDocument,
365
- error: [PublishedNotFound, InternalError$1]
366
- }), HttpApiEndpoint.post("query", "/query", {
367
- payload: PublishedDocumentQuery,
368
- success: PublishedDocumentPage,
369
- error: InternalError$1
370
- }), HttpApiEndpoint.post("navigation", "/navigation", {
371
- payload: DocumentNavigationQuery,
372
- success: Schema.Array(DocumentNavigationItem),
373
- error: InternalError$1
374
- }), HttpApiEndpoint.post("surround", "/surround", {
375
- payload: DeliverySurroundPayload,
376
- success: DocumentSurround,
377
- error: [PublishedNotFound, InternalError$1]
378
- }), HttpApiEndpoint.get("seo", "/seo", {
379
- success: SeoSnapshot,
380
- error: InternalError$1
381
- }), HttpApiEndpoint.get("sitemap", "/sitemap", {
382
- success: Schema.Array(SitemapEntry),
383
- error: InternalError$1
384
- })).prefix("/delivery");
385
- const PreviewDeliveryApi = HttpApiGroup.make("previewDelivery").add(HttpApiEndpoint.post("read", "/read", {
386
- payload: PublishedDocumentLookup,
387
- success: CompiledDocument,
388
- error: [
389
- PublishedNotFound,
390
- InternalError$1,
391
- Forbidden$1
392
- ]
393
- }), HttpApiEndpoint.post("query", "/query", {
394
- payload: PublishedDocumentQuery,
395
- success: PublishedDocumentPage,
396
- error: [InternalError$1, Forbidden$1]
397
- }), HttpApiEndpoint.post("navigation", "/navigation", {
398
- payload: DocumentNavigationQuery,
399
- success: Schema.Array(DocumentNavigationItem),
400
- error: [InternalError$1, Forbidden$1]
401
- }), HttpApiEndpoint.post("surround", "/surround", {
402
- payload: DeliverySurroundPayload,
403
- success: DocumentSurround,
404
- error: [
405
- PublishedNotFound,
406
- InternalError$1,
407
- Forbidden$1
408
- ]
409
- }), HttpApiEndpoint.get("seo", "/seo", {
410
- success: SeoSnapshot,
411
- error: [InternalError$1, Forbidden$1]
412
- })).prefix("/preview");
413
-
414
- //#endregion
415
- //#region ../protocol/src/StudioHttp.ts
416
- /**
417
- * Studio HTTP paths, middleware contracts, payloads, and the composed CMS API. Every expected
418
- * caller failure is a tagged schema with an explicit status; unclassified failures become the
419
- * deliberately opaque `StudioInternalError`.
420
- */
421
- const ApiVersion = Schema.NonEmptyString.pipe(Schema.brand("ApiVersion"));
422
- const StudioBootstrap = Schema.Struct({
423
- basePath: PublicPath,
424
- documents: DocumentConfiguration,
425
- media: MediaConfiguration,
426
- seo: Schema.optionalKey(SeoConfiguration),
427
- version: ApiVersion
428
- }).annotate({ identifier: "StudioBootstrap" });
429
- var StudioBadRequest = class extends Schema.TaggedError()("Studio.BadRequest", { kind: Schema.Literals([
430
- "Headers",
431
- "Params",
432
- "Payload",
433
- "Query"
434
- ]) }) {};
435
- var StudioRequestConflict = class extends Schema.TaggedError()("Studio.RequestConflict", { retryable: Schema.Literal(true) }) {};
436
- var StudioSchemaError = class extends HttpApiMiddleware.Service()("@internal/protocol/StudioSchemaError", { error: [StudioBadRequest.pipe(HttpApiSchema.status(400)), StudioInternalError.pipe(HttpApiSchema.status(500))] }) {};
437
- var CurrentStudioRequest = class extends Context.Service()("@internal/protocol/CurrentStudioRequest") {};
438
- var StudioAuthentication = class extends HttpApiMiddleware.Service()("@internal/protocol/StudioAuthentication", { error: [
439
- AuthenticationRequired.pipe(HttpApiSchema.status(401)),
440
- StudioEntryDenied.pipe(HttpApiSchema.status(403)),
441
- StudioInternalError.pipe(HttpApiSchema.status(500))
442
- ] }) {};
443
- const ValidateDocumentPayload = Schema.Struct({
444
- expectedVersion: UpdateDocumentInput.fields.expectedVersion,
445
- markdown: UpdateDocumentInput.fields.markdown
446
- });
447
- const UpdateDocumentPayload = ValidateDocumentPayload.pipe(Schema.fieldsAssign({ reason: UpdateDocumentInput.fields.reason }));
448
- const MoveDocumentPayload = Schema.Struct({
449
- expectedVersion: MoveDocumentInput.fields.expectedVersion,
450
- placement: MoveDocumentInput.fields.placement,
451
- reason: MoveDocumentInput.fields.reason
452
- });
453
- const PublishDocumentPayload = Schema.Struct({
454
- expectedVersion: PublishDocumentInput.fields.expectedVersion,
455
- reason: PublishDocumentInput.fields.reason
456
- });
457
- const RemoveDocumentPayload = Schema.Struct({
458
- expectedVersion: RemoveDocumentInput.fields.expectedVersion,
459
- reason: RemoveDocumentInput.fields.reason
460
- });
461
- const RestoreDocumentPayload = Schema.Struct({
462
- expectedVersion: RestoreDocumentInput.fields.expectedVersion,
463
- revisionId: RestoreDocumentInput.fields.revisionId,
464
- reason: RestoreDocumentInput.fields.reason
465
- });
466
- const UndeleteDocumentPayload = Schema.Struct({
467
- expectedVersion: UndeleteDocumentInput.fields.expectedVersion,
468
- reason: UndeleteDocumentInput.fields.reason
469
- });
470
- const ChangeRolePayload = Schema.Struct({ role: Role }).annotate({ identifier: "ChangeRolePayload" });
471
- const MediaUploadQuery = Schema.Struct({
472
- declaredByteSize: MediaUpload.fields.declaredByteSize,
473
- folder: Schema.optionalKey(MediaFolder)
474
- }).annotate({ identifier: "MediaUploadQuery" });
475
- const MediaUploadPayload = Schema.Struct({ file: Multipart.SingleFileSchema }).pipe(HttpApiSchema.asMultipartStream({ maxParts: 1 }));
476
- const NotFound = DocumentNotFound.pipe(HttpApiSchema.status(404));
477
- const VersionConflict = DocumentVersionConflict.pipe(HttpApiSchema.status(409));
478
- const Conflict = Schema.Union([
479
- DocumentMediaUnavailable,
480
- DocumentRouteConflict,
481
- DocumentVersionConflict
482
- ]).pipe(HttpApiSchema.status(409));
483
- const ValidationFailed = DocumentValidationFailed.pipe(HttpApiSchema.status(422));
484
- const RequestConflict = StudioRequestConflict.pipe(HttpApiSchema.status(409));
485
- const InternalError = StudioInternalError.pipe(HttpApiSchema.status(500));
486
- const Forbidden = AccessDenied.pipe(HttpApiSchema.status(403));
487
- const MutationErrors = [
488
- NotFound,
489
- Conflict,
490
- ValidationFailed,
491
- RequestConflict,
492
- Forbidden,
493
- InternalError
494
- ];
495
- const MediaNotFoundResponse = MediaNotFound.pipe(HttpApiSchema.status(404));
496
- const MediaInvalidQuery = MediaInvalid.pipe(HttpApiSchema.status(400));
497
- const MediaInvalidUpload = MediaInvalid.pipe(HttpApiSchema.status(422));
498
- const MediaTooLargeResponse = MediaTooLarge.pipe(HttpApiSchema.status(413));
499
- const MediaReferencedResponse = MediaReferenced.pipe(HttpApiSchema.status(409));
500
- const MediaConflictResponse = MediaConflict.pipe(HttpApiSchema.status(409));
501
- const InvalidActivityCursor = ActivityCursorInvalid.pipe(HttpApiSchema.status(400));
502
- const InvalidHistoryCursor = DocumentHistoryInvalidCursor.pipe(HttpApiSchema.status(400));
503
- const HistoryComparisonTooLarge = DocumentHistoryComparisonTooLarge.pipe(HttpApiSchema.status(422));
504
- const ContentConflict = ContentTransferConflict.pipe(HttpApiSchema.status(409));
505
- const AlreadyInitialized = InitializationAlreadyCompleted.pipe(HttpApiSchema.status(409));
506
- const InitializationProofRejected = InitializationProofInvalid.pipe(HttpApiSchema.status(403));
507
- const UserAdministrationForbidden = UserAdministrationDenied.pipe(HttpApiSchema.status(403));
508
- const UserDuplicate = UserAlreadyExists.pipe(HttpApiSchema.status(409));
509
- const MissingUser = UserNotFound.pipe(HttpApiSchema.status(404));
510
- const UserSelfRemoval = UserSelfRemovalDenied.pipe(HttpApiSchema.status(409));
511
- const UserSelfRoleChange = UserSelfRoleChangeDenied.pipe(HttpApiSchema.status(409));
512
- const SeoConflict = SeoVersionConflict.pipe(HttpApiSchema.status(409));
513
- const SeoConfirmation = SeoConfirmationRequired.pipe(HttpApiSchema.status(409));
514
- const SeoMediaInvalid = SeoMediaUnavailable.pipe(HttpApiSchema.status(422));
515
- const StudioDocumentsApi = HttpApiGroup.make("documents").add(HttpApiEndpoint.get("browse", "/", {
516
- query: DocumentBrowseQuery,
517
- success: Schema.Array(DocumentSummary),
518
- error: [Forbidden, InternalError]
519
- }), HttpApiEndpoint.get("trash", "/trash", {
520
- success: Schema.Array(DeletedDocument),
521
- error: [Forbidden, InternalError]
522
- }), HttpApiEndpoint.get("read", "/:documentId", {
523
- params: { documentId: DocumentId },
524
- success: DocumentSource,
525
- error: [
526
- NotFound,
527
- Forbidden,
528
- InternalError
529
- ]
530
- }), HttpApiEndpoint.post("create", "/", {
531
- payload: CreateDocumentInput,
532
- success: DocumentMutationResult.pipe(HttpApiSchema.status(201)),
533
- error: MutationErrors
534
- }), HttpApiEndpoint.put("update", "/:documentId", {
535
- params: { documentId: DocumentId },
536
- payload: UpdateDocumentPayload,
537
- success: DocumentMutationResult,
538
- error: MutationErrors
539
- }), HttpApiEndpoint.post("validate", "/:documentId/validate", {
540
- params: { documentId: DocumentId },
541
- payload: ValidateDocumentPayload,
542
- success: DocumentValidationResult,
543
- error: [
544
- NotFound,
545
- VersionConflict,
546
- Forbidden,
547
- InternalError
548
- ]
549
- }), HttpApiEndpoint.post("move", "/:documentId/move", {
550
- params: { documentId: DocumentId },
551
- payload: MoveDocumentPayload,
552
- success: DocumentMutationResult,
553
- error: MutationErrors
554
- }), HttpApiEndpoint.post("duplicate", "/:documentId/duplicate", {
555
- params: { documentId: DocumentId },
556
- payload: Schema.Struct({
557
- ...MoveDocumentPayload.fields,
558
- includeChildren: DuplicateDocumentInput.fields.includeChildren,
559
- locale: DuplicateDocumentInput.fields.locale
560
- }),
561
- success: DocumentMutationResult,
562
- error: MutationErrors
563
- }), HttpApiEndpoint.post("unpublish", "/:documentId/unpublish", {
564
- params: { documentId: DocumentId },
565
- payload: PublishDocumentPayload,
566
- success: DocumentMutationResult,
567
- error: MutationErrors
568
- }), HttpApiEndpoint.post("publish", "/:documentId/publish", {
569
- params: { documentId: DocumentId },
570
- payload: PublishDocumentPayload,
571
- success: DocumentMutationResult,
572
- error: MutationErrors
573
- }), HttpApiEndpoint.post("remove", "/:documentId/remove", {
574
- params: { documentId: DocumentId },
575
- payload: RemoveDocumentPayload,
576
- success: DocumentMutationResult,
577
- error: MutationErrors
578
- }), HttpApiEndpoint.post("restore", "/:documentId/restore", {
579
- params: { documentId: DocumentId },
580
- payload: RestoreDocumentPayload,
581
- success: DocumentMutationResult,
582
- error: MutationErrors
583
- }), HttpApiEndpoint.post("undelete", "/:documentId/undelete", {
584
- params: { documentId: DocumentId },
585
- payload: UndeleteDocumentPayload,
586
- success: DocumentMutationResult,
587
- error: MutationErrors
588
- })).middleware(StudioAuthentication).prefix("/documents");
589
- const StudioContentApi = HttpApiGroup.make("content").add(HttpApiEndpoint.get("snapshot", "/snapshot", {
590
- success: ContentSnapshot,
591
- error: [Forbidden, InternalError]
592
- }), HttpApiEndpoint.post("plan", "/plan", {
593
- payload: ContentTransferInput,
594
- success: ContentPlan,
595
- error: [
596
- ContentConflict,
597
- Forbidden,
598
- InternalError
599
- ]
600
- }), HttpApiEndpoint.post("apply", "/apply", {
601
- payload: ContentApplyInput,
602
- success: ContentApplyResult,
603
- error: [
604
- ContentConflict,
605
- ValidationFailed,
606
- Forbidden,
607
- InternalError
608
- ]
609
- })).middleware(StudioAuthentication).prefix("/content");
610
- const StudioMediaApi = HttpApiGroup.make("media").add(HttpApiEndpoint.get("search", "/", {
611
- query: MediaQuery,
612
- success: MediaPage,
613
- error: [
614
- MediaInvalidQuery,
615
- Forbidden,
616
- InternalError
617
- ]
618
- }), HttpApiEndpoint.post("upload", "/", {
619
- query: MediaUploadQuery,
620
- payload: MediaUploadPayload,
621
- success: MediaAsset.pipe(HttpApiSchema.status(201)),
622
- error: [
623
- MediaInvalidUpload,
624
- MediaTooLargeResponse,
625
- Forbidden,
626
- InternalError
627
- ]
628
- }), HttpApiEndpoint.put("replace", "/:mediaId", {
629
- params: { mediaId: MediaId },
630
- query: MediaUploadQuery,
631
- payload: MediaUploadPayload,
632
- success: MediaAsset,
633
- error: [
634
- MediaNotFoundResponse,
635
- MediaConflictResponse,
636
- MediaInvalidUpload,
637
- MediaTooLargeResponse,
638
- Forbidden,
639
- InternalError
640
- ]
641
- }), HttpApiEndpoint.post("cleanup", "/cleanup", {
642
- success: MediaCleanupReport,
643
- error: [Forbidden, InternalError]
644
- }), HttpApiEndpoint.get("integrity", "/integrity", {
645
- success: MediaIntegrityReport,
646
- error: [Forbidden, InternalError]
647
- }), HttpApiEndpoint.get("get", "/:mediaId", {
648
- params: { mediaId: MediaId },
649
- success: MediaAsset,
650
- error: [
651
- MediaNotFoundResponse,
652
- Forbidden,
653
- InternalError
654
- ]
655
- }), HttpApiEndpoint.delete("remove", "/:mediaId", {
656
- params: { mediaId: MediaId },
657
- success: HttpApiSchema.NoContent,
658
- error: [
659
- MediaNotFoundResponse,
660
- MediaConflictResponse,
661
- MediaReferencedResponse,
662
- Forbidden,
663
- InternalError
664
- ]
665
- })).middleware(StudioAuthentication).prefix("/media");
666
- const StudioConfigurationApi = HttpApiGroup.make("configuration").add(HttpApiEndpoint.get("bootstrap", "/bootstrap", { success: StudioBootstrap })).middleware(StudioAuthentication);
667
- const StudioSessionApi = HttpApiGroup.make("session").add(HttpApiEndpoint.get("current", "/session", { success: StudioActor })).middleware(StudioAuthentication);
668
- const InitializationApi = HttpApiGroup.make("initialization").add(HttpApiEndpoint.get("status", "/initialization", {
669
- success: InitializationState,
670
- error: InternalError
671
- }), HttpApiEndpoint.post("claim", "/initialization", {
672
- payload: InitializationInput,
673
- success: User.pipe(HttpApiSchema.status(201)),
674
- error: [
675
- AlreadyInitialized,
676
- InitializationProofRejected,
677
- InternalError
678
- ]
679
- }));
680
- const StudioDiagnosticsApi = HttpApiGroup.make("diagnostics").add(HttpApiEndpoint.get("documents", "/diagnostics/documents", {
681
- success: Schema.Array(DocumentIssue),
682
- error: [Forbidden, InternalError]
683
- })).middleware(StudioAuthentication);
684
- const StudioHistoryApi = HttpApiGroup.make("history").add(HttpApiEndpoint.get("list", "/", {
685
- query: DocumentHistoryQuery,
686
- success: DocumentRevisionPage,
687
- error: [
688
- InvalidHistoryCursor,
689
- Forbidden,
690
- InternalError
691
- ]
692
- }), HttpApiEndpoint.get("read", "/:documentId/:revisionId", {
693
- params: {
694
- documentId: DocumentId,
695
- revisionId: DocumentRevision.fields.revisionId
696
- },
697
- success: DocumentRevision,
698
- error: [
699
- NotFound,
700
- Forbidden,
701
- InternalError
702
- ]
703
- }), HttpApiEndpoint.post("compare", "/compare", {
704
- payload: CompareDocumentRevisionsInput,
705
- success: DocumentRevisionComparison,
706
- error: [
707
- NotFound,
708
- HistoryComparisonTooLarge,
709
- Forbidden,
710
- InternalError
711
- ]
712
- })).middleware(StudioAuthentication).prefix("/history");
713
- const StudioActivityApi = HttpApiGroup.make("activity").add(HttpApiEndpoint.get("list", "/", {
714
- query: ActivityQuery,
715
- success: ActivityPage,
716
- error: [
717
- InvalidActivityCursor,
718
- Forbidden,
719
- InternalError
720
- ]
721
- })).middleware(StudioAuthentication).prefix("/activity");
722
- const StudioSeoApi = HttpApiGroup.make("seo").add(HttpApiEndpoint.get("read", "/", {
723
- success: SeoState,
724
- error: [Forbidden, InternalError]
725
- }), HttpApiEndpoint.put("save", "/", {
726
- payload: SaveSeoInput,
727
- success: SeoMutationResult,
728
- error: [
729
- SeoConflict,
730
- SeoConfirmation,
731
- SeoMediaInvalid,
732
- Forbidden,
733
- InternalError
734
- ]
735
- }), HttpApiEndpoint.post("publish", "/publish", {
736
- payload: PublishSeoInput,
737
- success: SeoMutationResult,
738
- error: [
739
- SeoConflict,
740
- SeoConfirmation,
741
- SeoMediaInvalid,
742
- Forbidden,
743
- InternalError
744
- ]
745
- })).middleware(StudioAuthentication).prefix("/seo");
746
- const StudioUserAdministrationApi = HttpApiGroup.make("users").add(HttpApiEndpoint.get("list", "/", {
747
- query: UserQuery,
748
- success: UserPage,
749
- error: [UserAdministrationForbidden, InternalError]
750
- }), HttpApiEndpoint.post("create", "/", {
751
- payload: CreateUserInput,
752
- success: User.pipe(HttpApiSchema.status(201)),
753
- error: [
754
- UserDuplicate,
755
- UserAdministrationForbidden,
756
- InternalError
757
- ]
758
- }), HttpApiEndpoint.post("changeRole", "/:userId/role", {
759
- params: { userId: User.fields.id },
760
- payload: ChangeRolePayload,
761
- success: User,
762
- error: [
763
- MissingUser,
764
- UserSelfRoleChange,
765
- UserAdministrationForbidden,
766
- InternalError
767
- ]
768
- }), HttpApiEndpoint.post("revokeSessions", "/:userId/sessions/revoke", {
769
- params: { userId: User.fields.id },
770
- success: User,
771
- error: [
772
- MissingUser,
773
- UserAdministrationForbidden,
774
- InternalError
775
- ]
776
- }), HttpApiEndpoint.delete("remove", "/:userId", {
777
- params: { userId: User.fields.id },
778
- success: User,
779
- error: [
780
- MissingUser,
781
- UserSelfRemoval,
782
- UserAdministrationForbidden,
783
- InternalError
784
- ]
785
- })).middleware(StudioAuthentication).prefix("/users");
786
- const StudioCollaborationApi = HttpApiGroup.make("collaboration").add(HttpApiEndpoint.post("ticket", "/:documentId/ticket", {
787
- params: { documentId: DocumentId },
788
- success: CollaborationTicket,
789
- error: [
790
- NotFound,
791
- Forbidden,
792
- InternalError
793
- ]
794
- }), HttpApiEndpoint.post("discard", "/:documentId/discard", {
795
- params: { documentId: DocumentId },
796
- success: CollaborationTicket,
797
- error: [
798
- NotFound,
799
- Forbidden,
800
- InternalError
801
- ]
802
- })).middleware(StudioAuthentication).prefix("/collaboration");
803
- const FormsApi = HttpApiGroup.make("forms").add(HttpApiEndpoint.post("submit", "/submit", {
804
- payload: FormSubmission,
805
- success: FormResult
806
- })).prefix("/forms");
807
- var StudioApi = class extends HttpApi.make("StudioApi").add(FormsApi, InitializationApi, PublishedDeliveryApi, StudioConfigurationApi, StudioSessionApi, StudioDiagnosticsApi, PreviewDeliveryApi.middleware(StudioAuthentication), StudioDocumentsApi, StudioContentApi, StudioHistoryApi, StudioActivityApi, StudioSeoApi, StudioUserAdministrationApi, StudioMediaApi, StudioCollaborationApi).middleware(StudioSchemaError).prefix(STUDIO_API_PATH) {};
808
-
809
- //#endregion
810
- //#region ../document/src/Seo.ts
811
- function resolveDocumentSeo({ document, global, capabilities }) {
812
- const authored = document.seo;
813
- const baseTitle = authored?.title ?? document.title;
814
- const title = global.titleTemplate?.replaceAll("%s", baseTitle) ?? baseTitle;
815
- const description = authored?.description ?? document.description ?? global.defaultDescription;
816
- const socialTitle = authored?.socialTitle ?? global.socialTitle ?? title;
817
- const socialDescription = authored?.socialDescription ?? global.socialDescription ?? description;
818
- const socialImage = authored?.socialImage ?? global.socialImage;
819
- const canonicalUrl = authored?.canonicalUrl ?? SeoUrl.make(new URL(document.path, `${global.canonicalOrigin}/`).href);
820
- const structuredData = resolveStructuredData(authored?.structuredData, capabilities);
821
- const identity = resolveIdentity(global.identity, capabilities);
822
- return {
823
- title,
824
- ...description === void 0 ? void 0 : { description },
825
- socialTitle,
826
- ...socialDescription === void 0 ? void 0 : { socialDescription },
827
- ...socialImage === void 0 ? void 0 : { socialImage },
828
- canonicalUrl,
829
- index: global.index && (authored?.index ?? true),
830
- follow: global.follow && (authored?.follow ?? true),
831
- ...structuredData === void 0 ? void 0 : { structuredData },
832
- ...identity === void 0 ? void 0 : { identity }
833
- };
834
- }
835
- function resolveStructuredData(authored, capabilities) {
836
- if (authored && capabilities.structuredDataTypes.includes(authored.type)) return authored;
837
- return capabilities.structuredDataTypes.includes("WebPage") ? { type: "WebPage" } : void 0;
838
- }
839
- function resolveIdentity(identity, capabilities) {
840
- return identity && capabilities.identityTypes.includes(identity.type) ? identity : void 0;
841
- }
842
-
843
- //#endregion
844
- //#region ../server/src/internal/access-control.ts
845
- const VIEWER_ACTIONS = /* @__PURE__ */ new Set([
846
- "document.browse",
847
- "document.read",
848
- "document.trash",
849
- "document.history",
850
- "media.read",
851
- "media.search",
852
- "media.integrity"
853
- ]);
854
- const EDITOR_ACTIONS = /* @__PURE__ */ new Set([...DOCUMENT_ACTIONS.filter((action) => action !== "document.transfer"), ...MEDIA_ACTIONS.filter((action) => action !== "media.cleanup")]);
855
- var AccessControl = class extends Context.Service()("@internal/server/AccessControl") {};
856
- const defaultAccessControlLayer = Layer.succeed(AccessControl, AccessControl.of({ require: Effect.fn("AccessControl.require")(function* (context, decision) {
857
- if (isAllowed(context, decision.action)) return;
858
- return yield* new AccessDenied({
859
- action: decision.action,
860
- actorId: context.actor.id,
861
- resource: decision.resource
862
- });
863
- }) }));
864
- function isAllowed(context, action) {
865
- return context.actor.roles.some((role) => {
866
- if (role === "administrator") return true;
867
- return role === "editor" && EDITOR_ACTIONS.has(action) || role === "viewer" && VIEWER_ACTIONS.has(action);
868
- });
869
- }
870
-
871
- //#endregion
872
- //#region ../document/src/internal/editor/render.ts
873
- const renderEditorMarkdown = Effect.fn("EditorDocument.renderMarkdown")((document) => {
874
- return Effect.tryPromise({
875
- try: () => renderMarkdown(toComarkDocument(withoutEditorMetadata(document))),
876
- catch: (cause) => new EditorRenderFailed({ cause })
877
- });
878
- });
879
-
880
- //#endregion
881
- //#region ../document/src/DocumentPlanning.ts
882
- function planDocumentCreation(configuration, input) {
883
- return Result.gen(function* () {
884
- const collection = configuration.types.find((candidate) => candidate.collection === input.collection);
885
- if (!collection) return yield* invalid(`Document collection "${input.collection}" does not exist.`, "collection");
886
- const title = input.title.trim();
887
- if (!title) return yield* invalid("A document title is required.", "title");
888
- const locale = yield* resolveLocale(configuration, input.locale);
889
- return Object.assign({
890
- collection,
891
- placement: input.placement,
892
- title
893
- }, locale === void 0 ? void 0 : { locale });
894
- });
895
- }
896
- const createInitialDocumentSource = Effect.fn("DocumentPlanning.createInitialSource")(function* (plan) {
897
- const body = CmsMarkdownDocument.make({
898
- frontmatter: initialFrontmatter(plan),
899
- meta: {},
900
- nodes: [[
901
- "h1",
902
- {},
903
- plan.title
904
- ]]
905
- });
906
- return {
907
- body,
908
- markdown: yield* renderEditorMarkdown(body)
909
- };
910
- });
911
- function initialFrontmatter(plan) {
912
- return Object.assign(structuredDefaults(plan.collection.authoringFields), { title: plan.title });
913
- }
914
- function structuredDefaults(fields) {
915
- return Object.fromEntries(fields.flatMap((field) => {
916
- if (field.defaultValue !== void 0) return [[field.name, structuredClone(field.defaultValue)]];
917
- if (field.type !== "object") return [];
918
- const nested = structuredDefaults(field.fields ?? []);
919
- return Object.keys(nested).length === 0 ? [] : [[field.name, nested]];
920
- }));
921
- }
922
- function resolveLocale(configuration, requested) {
923
- const locales = configuration.locales;
924
- if (!locales) return requested === void 0 ? Result.succeed(void 0) : invalid(`Document locale "${requested}" is not configured.`, "locale");
925
- const locale = requested ?? locales.defaultLocale;
926
- return locales.locales.includes(locale) ? Result.succeed(locale) : invalid(`Document locale "${locale}" does not exist.`, "locale");
927
- }
928
- function invalid(message, field) {
929
- return Result.fail(new DocumentValidationFailed({ issues: [field === void 0 ? {
930
- code: "document.invalid",
931
- message,
932
- severity: "error"
933
- } : {
934
- code: "document.invalid",
935
- field,
936
- message,
937
- severity: "error"
938
- }] }));
939
- }
940
-
941
- //#endregion
942
- //#region ../server/src/internal/documents/document-state.ts
943
- const isDocumentCompilationFailed = Schema.is(DocumentCompilationFailed);
944
- function makeDocumentState(authored, published, snapshot) {
945
- const activeById = /* @__PURE__ */ new Map();
946
- for (const source of snapshot.active) {
947
- if (activeById.has(source.documentId)) throw new Error(`Document "${source.documentId}" appears more than once in the repository snapshot.`);
948
- activeById.set(source.documentId, source);
949
- }
950
- const authoredById = /* @__PURE__ */ new Map();
951
- for (const document of authored.documents) {
952
- if (authoredById.has(document.id)) throw new Error(`Compiled document "${document.id}" appears more than once in the authored catalog.`);
953
- if (!activeById.has(document.id)) throw new Error(`Compiled document "${document.id}" is missing from the repository snapshot.`);
954
- authoredById.set(document.id, document);
955
- }
956
- for (const documentId of activeById.keys()) if (!authoredById.has(documentId)) throw new Error(`Compiled document "${documentId}" is missing from the repository snapshot.`);
957
- const publishedById = /* @__PURE__ */ new Map();
958
- for (const document of published.documents) {
959
- if (publishedById.has(document.id)) throw new Error(`Compiled document "${document.id}" appears more than once in the published catalog.`);
960
- publishedById.set(document.id, document);
961
- }
962
- return {
963
- activeById,
964
- authored,
965
- authoredById,
966
- published,
967
- publishedById,
968
- snapshot
969
- };
970
- }
971
- const compileDocumentState = Effect.fn("DocumentState.compile")(function* (engine, snapshot, previous) {
972
- return makeDocumentState(yield* engine.compileAll({
973
- previous: previous?.authored,
974
- sources: authoredSources(snapshot)
975
- }), yield* engine.compileAll({
976
- previous: previous?.published,
977
- sources: publishedSources(snapshot)
978
- }), snapshot);
979
- });
980
- function authoredSources(snapshot) {
981
- return snapshot.active.map((source) => ({
982
- draft: source.publishedVersion !== source.version,
983
- identity: source.identity,
984
- markdown: source.markdown,
985
- placement: source.placement
986
- }));
987
- }
988
- function publishedSources(snapshot) {
989
- return snapshot.published.map((source) => ({
990
- draft: false,
991
- identity: source.identity,
992
- markdown: source.markdown,
993
- placement: source.placement,
994
- publishedAt: source.editedAt
995
- }));
996
- }
997
- const compileValidCatalog = Effect.fn("DocumentState.compileValid")(function* (engine, sources, previous) {
998
- const result = yield* Effect.result(engine.compileAll({
999
- previous,
1000
- sources
1001
- }));
1002
- if (Result.isFailure(result)) return yield* new DocumentValidationFailed({ issues: compilationIssues(result.failure) });
1003
- const errors = result.success.issues.filter((issue) => issue.severity === "error");
1004
- if (errors.length > 0) return yield* new DocumentValidationFailed({ issues: errors });
1005
- return result.success;
1006
- });
1007
- const validateDocumentSources = Effect.fn("DocumentState.validate")(function* (engine, sources, documentId, previous) {
1008
- const result = yield* Effect.result(engine.compileAll({
1009
- previous,
1010
- sources
1011
- }));
1012
- if (Result.isFailure(result)) return DocumentValidationResult.make({
1013
- issues: compilationIssues(result.failure),
1014
- valid: false
1015
- });
1016
- const catalog = result.success;
1017
- const document = catalog.documents.find((candidate) => candidate.id === documentId);
1018
- const issues = catalog.issues;
1019
- const validation = {
1020
- issues,
1021
- valid: document !== void 0 && !issues.some((issue) => issue.severity === "error")
1022
- };
1023
- return DocumentValidationResult.make(Object.assign(validation, document === void 0 ? void 0 : { document }));
1024
- });
1025
- function authoringEntries(state, query) {
1026
- return state.snapshot.active.flatMap((source) => {
1027
- const document = state.authoredById.get(source.documentId);
1028
- if (!document) throw new Error(`Compiled document "${source.documentId}" is missing from the repository snapshot.`);
1029
- if (query.collection !== void 0 && document.collection !== query.collection) return [];
1030
- if (query.locale !== void 0 && document.locale !== query.locale) return [];
1031
- return [DocumentSummary.make({
1032
- ...browseMetadata(state, source),
1033
- document: summaryDocument(document),
1034
- version: source.version
1035
- })];
1036
- });
1037
- }
1038
- function deletedEntries(state) {
1039
- return state.snapshot.deleted.map((source) => DeletedDocument.make({
1040
- ...source.title ? { title: source.title } : void 0,
1041
- ...source.path ? { path: source.path } : void 0,
1042
- ...source.trashBatchId ? { trashBatchId: source.trashBatchId } : void 0,
1043
- documentId: source.documentId,
1044
- identity: source.identity,
1045
- placement: source.placement,
1046
- deletedAt: source.deletedAt,
1047
- version: source.version
1048
- }));
1049
- }
1050
- function entryById(state, documentId) {
1051
- const source = state.activeById.get(documentId);
1052
- const document = state.authoredById.get(documentId);
1053
- return source && document ? DocumentSummary.make({
1054
- ...browseMetadata(state, source),
1055
- document: summaryDocument(document),
1056
- version: source.version
1057
- }) : void 0;
1058
- }
1059
- function summaryDocument(document) {
1060
- return {
1061
- collection: document.collection,
1062
- draft: document.draft,
1063
- id: document.id,
1064
- identity: document.identity,
1065
- issues: document.issues,
1066
- key: document.key,
1067
- ...document.locale ? { locale: document.locale } : void 0,
1068
- path: document.path,
1069
- placement: document.placement,
1070
- searchText: document.analysis.searchText,
1071
- title: document.title
1072
- };
1073
- }
1074
- function compilationIssues(error) {
1075
- if (isDocumentCompilationFailed(error)) return error.issues;
1076
- return [{
1077
- code: "markdown.parse",
1078
- message: errorMessage(error.cause),
1079
- severity: "error",
1080
- documentId: error.documentId
1081
- }];
1082
- }
1083
- function errorMessage(cause) {
1084
- return cause instanceof Error && cause.message ? cause.message : "Markdown could not be parsed.";
1085
- }
1086
- function browseMetadata(state, source) {
1087
- const live = state.publishedById.get(source.documentId);
1088
- const metadata = {};
1089
- if (source.createdBy) metadata.createdBy = source.createdBy;
1090
- if (source.editedBy) metadata.editedBy = source.editedBy;
1091
- if (source.editedAt) metadata.editedAt = source.editedAt;
1092
- if (source.publishedVersion) metadata.publishedVersion = source.publishedVersion;
1093
- if (live) metadata.publishedPath = live.path;
1094
- return metadata;
1095
- }
1096
-
1097
- //#endregion
1098
- //#region ../server/src/internal/documents/document-tree-mutation.ts
1099
- function subtreeIds(state, documentId, catalog = "authored") {
1100
- const documents = catalog === "authored" ? state.authored.documents : state.published.documents;
1101
- const children = /* @__PURE__ */ new Map();
1102
- for (const document of documents) {
1103
- if (document.placement.kind === "home") continue;
1104
- const existing = children.get(document.placement.parentDocumentId) ?? [];
1105
- existing.push(document.id);
1106
- children.set(document.placement.parentDocumentId, existing);
1107
- }
1108
- const result = [];
1109
- const pending = [documentId];
1110
- while (pending.length > 0) {
1111
- const current = pending.shift();
1112
- if (!current || result.includes(current)) continue;
1113
- result.push(current);
1114
- pending.push(...children.get(current) ?? []);
1115
- }
1116
- return result;
1117
- }
1118
- const prepareTreeMutation = Effect.fn("Documents.prepareTreeMutation")(function* (dependencies, state, command) {
1119
- const { engine } = dependencies;
1120
- const input = command.input;
1121
- const root = command.action === "document.undelete" ? state.snapshot.deleted.find((source) => source.documentId === input.documentId) : state.activeById.get(input.documentId);
1122
- if (!root) return yield* new DocumentNotFound({ documentId: input.documentId });
1123
- if (root.version !== input.expectedVersion) return yield* new DocumentVersionConflict({
1124
- documentId: root.documentId,
1125
- actualVersion: root.version,
1126
- expectedVersion: input.expectedVersion
1127
- });
1128
- const sources = affectedSources(state, root, command);
1129
- const authored = authoredSources(state.snapshot);
1130
- const published = publishedSources(state.snapshot);
1131
- const plans = [];
1132
- let nextAuthored = [...authored];
1133
- let nextPublished = [...published];
1134
- switch (command.action) {
1135
- case "document.move": {
1136
- const next = compilationSource$2(root, command.input.placement);
1137
- nextAuthored = replaceSource$1(nextAuthored, next);
1138
- plans.push({
1139
- action: command.action,
1140
- documentId: root.documentId,
1141
- expectedVersion: root.version,
1142
- markdown: root.markdown,
1143
- placement: command.input.placement,
1144
- publishedVersion: root.publishedVersion
1145
- });
1146
- break;
1147
- }
1148
- case "document.duplicate": {
1149
- const ids = /* @__PURE__ */ new Map();
1150
- for (const source of sources) ids.set(source.documentId, yield* command.nextDocumentId);
1151
- for (const source of sources) {
1152
- const documentId = ids.get(source.documentId);
1153
- if (!documentId) return yield* Effect.die(/* @__PURE__ */ new Error("Duplicate document identity was not allocated."));
1154
- const placement = duplicatePlacement(source, root, command.input.placement, ids);
1155
- const identity = {
1156
- ...source.identity,
1157
- documentId,
1158
- ...command.input.locale === void 0 ? void 0 : { locale: command.input.locale }
1159
- };
1160
- const next = {
1161
- draft: true,
1162
- identity,
1163
- markdown: source.markdown,
1164
- placement
1165
- };
1166
- nextAuthored.push(next);
1167
- plans.push({
1168
- action: "document.create",
1169
- identity,
1170
- markdown: source.markdown,
1171
- placement
1172
- });
1173
- }
1174
- break;
1175
- }
1176
- case "document.remove": {
1177
- const ids = new Set(sources.map((source) => source.documentId));
1178
- nextAuthored = nextAuthored.filter((source) => !ids.has(source.identity.documentId));
1179
- nextPublished = nextPublished.filter((source) => !ids.has(source.identity.documentId));
1180
- for (const source of sources) {
1181
- const page = state.authoredById.get(source.documentId);
1182
- plans.push({
1183
- action: command.action,
1184
- trashBatchId: root.version,
1185
- title: page?.title,
1186
- path: page?.path,
1187
- documentId: source.documentId,
1188
- expectedVersion: source.version,
1189
- markdown: source.markdown,
1190
- placement: source.placement
1191
- });
1192
- }
1193
- break;
1194
- }
1195
- case "document.undelete": for (const source of sources) {
1196
- const next = compilationSource$2(source, source.placement);
1197
- nextAuthored.push(next);
1198
- plans.push({
1199
- action: command.action,
1200
- documentId: source.documentId,
1201
- expectedVersion: source.version,
1202
- markdown: source.markdown,
1203
- placement: source.placement
1204
- });
1205
- }
1206
- }
1207
- const first = plans[0];
1208
- if (!first) return yield* Effect.die(/* @__PURE__ */ new Error("Empty subtree mutation."));
1209
- return {
1210
- authored: yield* compileValidCatalog(engine, nextAuthored, state.authored),
1211
- published: yield* compileValidCatalog(engine, nextPublished, state.published),
1212
- commitPlan: first,
1213
- additionalPlans: plans.slice(1)
1214
- };
1215
- });
1216
- function affectedSources(state, root, command) {
1217
- if (command.action === "document.undelete") {
1218
- if (!("deletedAt" in root)) return [];
1219
- return state.snapshot.deleted.filter((source) => source.documentId === root.documentId || root.trashBatchId !== void 0 && source.trashBatchId === root.trashBatchId);
1220
- }
1221
- const ids = new Set(command.action === "document.duplicate" && !command.input.includeChildren ? [root.documentId] : subtreeIds(state, root.documentId));
1222
- return [root, ...state.snapshot.active.filter((source) => source.documentId !== root.documentId && ids.has(source.documentId))];
1223
- }
1224
- function compilationSource$2(source, placement) {
1225
- return {
1226
- draft: true,
1227
- identity: source.identity,
1228
- markdown: source.markdown,
1229
- placement
1230
- };
1231
- }
1232
- function duplicatePlacement(source, root, rootPlacement, ids) {
1233
- if (source.documentId === root.documentId) return rootPlacement;
1234
- if (source.placement.kind === "home") return source.placement;
1235
- const parentDocumentId = ids.get(source.placement.parentDocumentId);
1236
- return parentDocumentId === void 0 ? source.placement : {
1237
- ...source.placement,
1238
- parentDocumentId
1239
- };
1240
- }
1241
- function replaceSource$1(sources, source) {
1242
- return [...sources.filter((candidate) => candidate.identity.documentId !== source.identity.documentId), source];
1243
- }
1244
-
1245
- //#endregion
1246
- //#region ../server/src/internal/documents/document-lifecycle.ts
1247
- const PreparedDocumentMutation = Data.taggedEnum();
1248
- const prepareDocumentMutation = Effect.fn("DocumentLifecycle.prepare")(function* (dependencies, state, command) {
1249
- const { engine, repository } = dependencies;
1250
- if (command.action === "document.move" || command.action === "document.remove" || command.action === "document.undelete" || command.action === "document.duplicate") return PreparedDocumentMutation.Commit(yield* prepareTreeMutation(dependencies, state, command));
1251
- const authored = authoredSources(state.snapshot);
1252
- const published = publishedSources(state.snapshot);
1253
- switch (command.action) {
1254
- case "document.create": {
1255
- const source = compilationSource$1(command.identity, command.placement, command.markdown, true);
1256
- return PreparedDocumentMutation.Commit({
1257
- authored: yield* compileValidCatalog(engine, [...authored, source], state.authored),
1258
- published: state.published,
1259
- commitPlan: {
1260
- action: command.action,
1261
- identity: command.identity,
1262
- markdown: command.markdown,
1263
- placement: command.placement
1264
- }
1265
- });
1266
- }
1267
- case "document.update": {
1268
- const current = yield* requireActive(state, command.input.documentId);
1269
- yield* requireVersion(current, command.input.expectedVersion);
1270
- const source = compilationSource$1(current.identity, current.placement, command.input.markdown, true);
1271
- return PreparedDocumentMutation.Commit({
1272
- authored: yield* compileValidCatalog(engine, replaceSource(authored, source), state.authored),
1273
- published: state.published,
1274
- commitPlan: {
1275
- action: command.action,
1276
- documentId: current.documentId,
1277
- expectedVersion: command.input.expectedVersion,
1278
- markdown: command.input.markdown,
1279
- placement: current.placement,
1280
- publishedVersion: current.publishedVersion
1281
- }
1282
- });
1283
- }
1284
- case "document.restore": {
1285
- const current = yield* requireActive(state, command.input.documentId);
1286
- yield* requireVersion(current, command.input.expectedVersion);
1287
- const historical = yield* repository.revision(current.documentId, command.input.revisionId);
1288
- const source = compilationSource$1(current.identity, historical.placement, historical.markdown, true);
1289
- return PreparedDocumentMutation.Commit({
1290
- authored: yield* compileValidCatalog(engine, replaceSource(authored, source), state.authored),
1291
- published: state.published,
1292
- commitPlan: {
1293
- action: command.action,
1294
- documentId: current.documentId,
1295
- expectedVersion: command.input.expectedVersion,
1296
- markdown: historical.markdown,
1297
- placement: historical.placement,
1298
- publishedVersion: current.publishedVersion,
1299
- revisionId: command.input.revisionId
1300
- }
1301
- });
1302
- }
1303
- case "document.unpublish": {
1304
- const current = yield* requireActive(state, command.input.documentId);
1305
- yield* requireVersion(current, command.input.expectedVersion);
1306
- const ids = new Set(subtreeIds(state, current.documentId, "published"));
1307
- const plans = state.snapshot.active.filter((source) => ids.has(source.documentId) && source.publishedVersion !== void 0).map((source) => ({
1308
- action: "document.unpublish",
1309
- documentId: source.documentId,
1310
- expectedVersion: source.version,
1311
- markdown: source.markdown,
1312
- placement: source.placement,
1313
- revisionId: source.revisionId
1314
- }));
1315
- const first = plans[0];
1316
- if (!first) return unchanged(state, current, "document.unpublish");
1317
- return PreparedDocumentMutation.Commit({
1318
- authored: yield* compileValidCatalog(engine, authored.map((source) => ids.has(source.identity.documentId) ? Object.assign({}, source, { draft: true }) : source), state.authored),
1319
- published: yield* compileValidCatalog(engine, published.filter((source) => !ids.has(source.identity.documentId)), state.published),
1320
- commitPlan: first,
1321
- additionalPlans: plans.slice(1)
1322
- });
1323
- }
1324
- case "document.publish": {
1325
- const current = yield* requireActive(state, command.input.documentId);
1326
- yield* requireVersion(current, command.input.expectedVersion);
1327
- if (current.publishedVersion === current.version) return unchanged(state, current, "document.publish");
1328
- const source = compilationSource$1(current.identity, current.placement, current.markdown, false);
1329
- return PreparedDocumentMutation.Commit({
1330
- authored: yield* compileValidCatalog(engine, replaceSource(authored, source), state.authored),
1331
- published: yield* compileValidCatalog(engine, replaceSource(published, source), state.published),
1332
- commitPlan: {
1333
- action: command.action,
1334
- documentId: current.documentId,
1335
- expectedVersion: command.input.expectedVersion,
1336
- markdown: current.markdown,
1337
- placement: current.placement,
1338
- revisionId: current.revisionId
1339
- }
1340
- });
1341
- }
1342
- }
1343
- });
1344
- const validateDocumentUpdate = Effect.fn("DocumentLifecycle.validateUpdate")(function* (engine, state, input) {
1345
- const current = yield* requireActive(state, input.documentId);
1346
- yield* requireVersion(current, input.expectedVersion);
1347
- const source = compilationSource$1(current.identity, current.placement, input.markdown, true);
1348
- return yield* validateDocumentSources(engine, replaceSource(authoredSources(state.snapshot), source), current.documentId, state.authored);
1349
- });
1350
- function compilationSource$1(identity, placement, markdown, draft) {
1351
- return {
1352
- draft,
1353
- identity,
1354
- markdown,
1355
- placement
1356
- };
1357
- }
1358
- function unchanged(state, current, action) {
1359
- const entry = entryById(state, current.documentId);
1360
- const result = DocumentMutationResult.make({
1361
- action,
1362
- affectedDocumentIds: [current.documentId],
1363
- documentId: current.documentId,
1364
- generation: state.snapshot.generation,
1365
- revisionId: current.revisionId,
1366
- version: current.version,
1367
- ...entry === void 0 ? void 0 : { entry }
1368
- });
1369
- return PreparedDocumentMutation.Unchanged({ result });
1370
- }
1371
- function requireActive(state, documentId) {
1372
- const source = state.activeById.get(documentId);
1373
- return source ? Effect.succeed(source) : Effect.fail(new DocumentNotFound({ documentId }));
1374
- }
1375
- function requireVersion(source, expectedVersion) {
1376
- return source.version === expectedVersion ? Effect.void : Effect.fail(new DocumentVersionConflict({
1377
- actualVersion: source.version,
1378
- documentId: source.documentId,
1379
- expectedVersion
1380
- }));
1381
- }
1382
- function replaceSource(sources, source) {
1383
- return [...sources.filter((candidate) => candidate.identity.documentId !== source.identity.documentId), source];
1384
- }
1385
-
1386
- //#endregion
1387
- //#region ../server/src/internal/documents/document-media-references.ts
1388
- function projectMediaReferences(authored, published, documentId) {
1389
- const references = [...referencesFromCatalog(authored, documentId), ...referencesFromCatalog(published, documentId)];
1390
- return [...new Map(references.map((reference) => [referenceIdentity(reference), reference])).values()];
1391
- }
1392
- function referencesFromCatalog(catalog, documentId) {
1393
- return catalog.references.all.filter((reference) => reference.target.kind === "media" && (documentId === void 0 || reference.source.documentId === documentId)).map(toMediaReference);
1394
- }
1395
- function toMediaReference(reference) {
1396
- if (reference.target.kind !== "media") throw new Error("Expected a media reference.");
1397
- return MediaReference.make({
1398
- documentId: reference.source.documentId,
1399
- ...reference.target.mediaId ? { mediaId: reference.target.mediaId } : void 0,
1400
- nodePath: reference.nodePath,
1401
- objectKey: MediaObjectKey.make(reference.target.key),
1402
- route: reference.source.route
1403
- });
1404
- }
1405
- function referenceIdentity(reference) {
1406
- return `${reference.documentId}:${reference.nodePath.join(".")}:${reference.objectKey}`;
1407
- }
1408
-
1409
- //#endregion
1410
- //#region ../server/src/internal/documents/content-transfer.ts
1411
- /** Import/export adapter planning. File paths are consumed here and never enter document state. */
1412
- const planContentTransfer = Effect.fn("ContentTransfer.plan")(function* (engine, configuration, state, input, crypto) {
1413
- const incoming = yield* resolveSources(configuration, state, input.sources, crypto);
1414
- const currentById = new Map(state.snapshot.active.map((source) => [source.documentId, source]));
1415
- const seen = /* @__PURE__ */ new Set();
1416
- const commitPlans = [];
1417
- const entries = [];
1418
- const authored = new Map(authoredSources(state.snapshot).map((source) => [source.identity.documentId, source]));
1419
- const published = new Map(publishedSources(state.snapshot).map((source) => [source.identity.documentId, source]));
1420
- const now = yield* DateTime.now;
1421
- let created = 0;
1422
- let updated = 0;
1423
- let publishedCount = 0;
1424
- let unchanged = 0;
1425
- for (const source of incoming) {
1426
- if (seen.has(source.filePath)) return yield* new ContentTransferConflict({ message: `Duplicate content file path: ${source.filePath}` });
1427
- seen.add(source.filePath);
1428
- const current = currentById.get(source.identity.documentId);
1429
- const shouldPublish = input.publish && source.published;
1430
- const shouldUnpublish = input.publish && !source.published && current?.publishedVersion !== void 0;
1431
- const identityConflict = current !== void 0 && !sameIdentity(current.identity, source.identity);
1432
- const changed = current !== void 0 && (current.markdown !== source.markdown || !samePlacement(current.placement, source.placement) || source.revisionId !== void 0 && current.revisionId !== source.revisionId);
1433
- const action = identityConflict ? "conflict" : !current ? "create" : changed ? input.overwrite ? "update" : "conflict" : shouldPublish && current.publishedVersion !== current.version ? "publish" : shouldUnpublish ? "unpublish" : "unchanged";
1434
- entries.push({
1435
- filePath: source.filePath,
1436
- action,
1437
- currentRevisionId: current?.revisionId ?? null
1438
- });
1439
- if (action === "create" || action === "update") {
1440
- if (current) {
1441
- commitPlans.push({
1442
- action: "document.update",
1443
- documentId: current.documentId,
1444
- expectedVersion: current.version,
1445
- markdown: source.markdown,
1446
- placement: source.placement,
1447
- publish: shouldPublish,
1448
- publishedVersion: current.publishedVersion,
1449
- ...source.revisionId === void 0 ? void 0 : { newRevisionId: source.revisionId },
1450
- ...shouldUnpublish ? { unpublish: true } : void 0
1451
- });
1452
- updated++;
1453
- } else {
1454
- commitPlans.push({
1455
- action: "document.create",
1456
- identity: source.identity,
1457
- markdown: source.markdown,
1458
- placement: source.placement,
1459
- publish: shouldPublish,
1460
- ...source.revisionId === void 0 ? void 0 : { newRevisionId: source.revisionId }
1461
- });
1462
- created++;
1463
- }
1464
- if (shouldPublish) publishedCount++;
1465
- const compiled = compilationSource(source, !shouldPublish);
1466
- authored.set(source.identity.documentId, compiled);
1467
- if (shouldPublish) published.set(source.identity.documentId, Object.assign({}, compiled, {
1468
- draft: false,
1469
- publishedAt: now
1470
- }));
1471
- else if (shouldUnpublish) published.delete(source.identity.documentId);
1472
- } else if (action === "publish" && current) {
1473
- commitPlans.push({
1474
- action: "document.publish",
1475
- documentId: current.documentId,
1476
- expectedVersion: current.version,
1477
- markdown: current.markdown,
1478
- placement: current.placement,
1479
- revisionId: current.revisionId
1480
- });
1481
- publishedCount++;
1482
- const compiled = compilationSource(source, false);
1483
- authored.set(source.identity.documentId, compiled);
1484
- published.set(source.identity.documentId, Object.assign({}, compiled, { publishedAt: now }));
1485
- } else if (action === "unpublish" && current) {
1486
- commitPlans.push({
1487
- action: "document.unpublish",
1488
- documentId: current.documentId,
1489
- expectedVersion: current.version,
1490
- markdown: current.markdown,
1491
- placement: current.placement,
1492
- revisionId: current.revisionId
1493
- });
1494
- published.delete(source.identity.documentId);
1495
- } else if (action === "unchanged") unchanged++;
1496
- }
1497
- const firstDocumentId = incoming[0]?.identity.documentId;
1498
- const publishedValues = [...published.values()];
1499
- const publishedDocumentId = publishedValues[0]?.identity.documentId;
1500
- const authoredValidation = firstDocumentId ? yield* validateDocumentSources(engine, [...authored.values()], firstDocumentId, state.authored) : DocumentValidationResult.make({
1501
- issues: [],
1502
- valid: true
1503
- });
1504
- const publishedValidation = input.publish && publishedDocumentId ? yield* validateDocumentSources(engine, publishedValues, publishedDocumentId, state.published) : DocumentValidationResult.make({
1505
- issues: [],
1506
- valid: true
1507
- });
1508
- const issues = [...authoredValidation.issues, ...publishedValidation.issues];
1509
- return {
1510
- plan: ContentPlan.make({
1511
- generation: state.snapshot.generation,
1512
- entries,
1513
- issues,
1514
- valid: authoredValidation.valid && !entries.some((entry) => entry.action === "conflict") && !issues.some((issue) => issue.severity === "error")
1515
- }),
1516
- authoredSources: [...authored.values()],
1517
- publishedSources: publishedValues,
1518
- commitPlans,
1519
- counts: {
1520
- created,
1521
- updated,
1522
- published: publishedCount,
1523
- unchanged
1524
- }
1525
- };
1526
- });
1527
- function resolveSources(configuration, state, sources, crypto) {
1528
- return Effect.gen(function* () {
1529
- const resolved = [];
1530
- const indexed = [];
1531
- const unindexed = [];
1532
- for (const source of sources) {
1533
- if (source.identity && source.placement) {
1534
- indexed.push(Object.assign({}, source, {
1535
- identity: source.identity,
1536
- placement: source.placement
1537
- }));
1538
- continue;
1539
- }
1540
- if (source.identity || source.placement) return yield* new ContentTransferConflict({ message: `${source.filePath}: indexed content must include both identity and placement.` });
1541
- unindexed.push(source);
1542
- }
1543
- resolved.push(...indexed);
1544
- const byPlacement = placementIndex([...state.snapshot.active, ...indexed]);
1545
- const pending = unindexed.map((source) => ({
1546
- inferred: inferFilePlacement(configuration, source.filePath),
1547
- source
1548
- })).toSorted((left, right) => Number(right.inferred.home) - Number(left.inferred.home) || left.inferred.segments.length - right.inferred.segments.length || left.source.filePath.localeCompare(right.source.filePath));
1549
- for (const { inferred, source } of pending) {
1550
- const scope = `${inferred.collection}:${inferred.locale ?? ""}`;
1551
- const key = `${scope}:${inferred.segments.join("/")}`;
1552
- let identity = byPlacement.get(key);
1553
- if (!identity) identity = {
1554
- collection: inferred.collection,
1555
- documentId: DocumentId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie)),
1556
- ...inferred.locale === void 0 ? void 0 : { locale: inferred.locale }
1557
- };
1558
- const placement = inferred.home ? { kind: "home" } : {
1559
- kind: "entry",
1560
- parentDocumentId: byPlacement.get(`${scope}:${inferred.segments.slice(0, -1).join("/")}`)?.documentId ?? (yield* new ContentTransferConflict({ message: `${source.filePath}: parent document is missing from the import and target catalog.` })),
1561
- slug: Slug.make(inferred.segments.at(-1) ?? "")
1562
- };
1563
- const value = Object.assign({}, source, {
1564
- identity,
1565
- placement
1566
- });
1567
- resolved.push(value);
1568
- byPlacement.set(key, identity);
1569
- }
1570
- return resolved;
1571
- });
1572
- }
1573
- function inferFilePlacement(configuration, filePath) {
1574
- const segments = filePath.replace(/\.(?:md|mdc)$/iu, "").split("/");
1575
- let locale = configuration.locales?.locales.find((candidate) => candidate === segments[0]);
1576
- if (locale) segments.shift();
1577
- else locale = configuration.locales?.defaultLocale;
1578
- let collection = configuration.types[0]?.collection;
1579
- const configured = configuration.types.find((candidate) => candidate.collection === segments[0]);
1580
- if (configured) {
1581
- collection = configured.collection;
1582
- segments.shift();
1583
- }
1584
- if (!collection) throw new Error("Content import needs at least one configured collection.");
1585
- const home = segments.length === 1 && segments[0]?.toLocaleLowerCase() === "index";
1586
- const normalized = home ? [] : segments.at(-1)?.toLocaleLowerCase() === "index" ? segments.slice(0, -1) : segments;
1587
- return {
1588
- collection,
1589
- home,
1590
- locale,
1591
- segments: normalized
1592
- };
1593
- }
1594
- function placementIndex(sources) {
1595
- const index = /* @__PURE__ */ new Map();
1596
- const byId = new Map(sources.map((source) => [source.identity.documentId, source]));
1597
- const resolved = /* @__PURE__ */ new Map();
1598
- const segmentsFor = (documentId, ancestors) => {
1599
- const cached = resolved.get(documentId);
1600
- if (cached) return cached;
1601
- if (ancestors.has(documentId)) return void 0;
1602
- const source = byId.get(documentId);
1603
- if (!source) return void 0;
1604
- if (source.placement.kind === "home") {
1605
- resolved.set(documentId, []);
1606
- return [];
1607
- }
1608
- const parent = segmentsFor(source.placement.parentDocumentId, /* @__PURE__ */ new Set([...ancestors, documentId]));
1609
- if (!parent) return void 0;
1610
- const segments = [...parent, source.placement.slug];
1611
- resolved.set(documentId, segments);
1612
- return segments;
1613
- };
1614
- for (const source of sources) {
1615
- const segments = segmentsFor(source.identity.documentId, /* @__PURE__ */ new Set());
1616
- if (segments) index.set(placementIndexKey(source.identity, segments), source.identity);
1617
- }
1618
- return index;
1619
- }
1620
- function placementIndexKey(identity, segments) {
1621
- return `${identity.collection}:${identity.locale ?? ""}:${segments.join("/")}`;
1622
- }
1623
- function compilationSource(source, draft) {
1624
- return {
1625
- draft,
1626
- identity: source.identity,
1627
- markdown: source.markdown,
1628
- placement: source.placement
1629
- };
1630
- }
1631
- function samePlacement(left, right) {
1632
- return left.kind === right.kind && (left.kind === "home" || right.kind === "entry" && left.parentDocumentId === right.parentDocumentId && left.slug === right.slug);
1633
- }
1634
- function sameIdentity(left, right) {
1635
- return left.documentId === right.documentId && left.collection === right.collection && left.locale === right.locale;
1636
- }
1637
-
1638
- //#endregion
1639
- //#region ../server/src/internal/documents/document-mutation.ts
1640
- /** Commit validated sources and their media references through one generation fence. */
1641
- const commitApprovedDocumentPlans = Effect.fn("Documents.commitApprovedPlans")(function* (input) {
1642
- const [plan, ...additionalPlans] = input.plans;
1643
- return yield* input.repository.commit({
1644
- activity: input.activity,
1645
- plan,
1646
- additionalPlans,
1647
- expectedGeneration: input.current.snapshot.generation,
1648
- ...input.configurationRevision === void 0 ? void 0 : { expectedConfigurationRevision: input.configurationRevision },
1649
- mediaReferences: input.plans.flatMap((candidate) => projectMediaReferences(input.authored, input.published, planDocumentId(candidate)))
1650
- });
1651
- });
1652
- /** Authorize every affected document before the adapter commits the approved plan atomically. */
1653
- const commitDocumentMutation = Effect.fn("Documents.commitMutation")(function* (accessControl, dependencies, current, command, activity) {
1654
- if (command.action === "document.move" || command.action === "document.remove" || command.action === "document.duplicate") {
1655
- const ids = command.action === "document.duplicate" && !command.input.includeChildren ? [command.input.documentId] : subtreeIds(current, command.input.documentId);
1656
- for (const documentId of ids) yield* accessControl.require({
1657
- actor: activity.actor,
1658
- requestId: activity.requestId
1659
- }, {
1660
- action: command.action,
1661
- resource: {
1662
- kind: "document",
1663
- documentId
1664
- }
1665
- });
1666
- if (command.action === "document.duplicate") {
1667
- const source = current.authoredById.get(command.input.documentId);
1668
- if (source) yield* accessControl.require({
1669
- actor: activity.actor,
1670
- requestId: activity.requestId
1671
- }, {
1672
- action: "document.create",
1673
- resource: {
1674
- kind: "collection",
1675
- collection: source.collection,
1676
- locale: command.input.locale ?? source.locale
1677
- }
1678
- });
1679
- }
1680
- }
1681
- const prepared = yield* prepareDocumentMutation(dependencies, current, command);
1682
- if (command.action === "document.undelete" && Predicate.isTagged("Commit")(prepared)) for (const plan of [prepared.commitPlan, ...prepared.additionalPlans ?? []]) yield* accessControl.require({
1683
- actor: activity.actor,
1684
- requestId: activity.requestId
1685
- }, {
1686
- action: "document.undelete",
1687
- resource: {
1688
- kind: "document",
1689
- documentId: planDocumentId(plan)
1690
- }
1691
- });
1692
- if (Predicate.isTagged("Unchanged")(prepared)) return {
1693
- kind: "unchanged",
1694
- result: prepared.result
1695
- };
1696
- const committed = yield* commitApprovedDocumentPlans({
1697
- repository: dependencies.repository,
1698
- current,
1699
- plans: [prepared.commitPlan, ...prepared.additionalPlans ?? []],
1700
- authored: prepared.authored,
1701
- published: prepared.published,
1702
- activity,
1703
- ...dependencies.configurationRevision === void 0 ? void 0 : { configurationRevision: dependencies.configurationRevision }
1704
- });
1705
- const next = makeDocumentState(prepared.authored, prepared.published, committed.snapshot);
1706
- const entry = entryById(next, committed.mutation.documentId);
1707
- return {
1708
- kind: "committed",
1709
- next,
1710
- result: DocumentMutationResult.make(Object.assign({}, committed.mutation, entry === void 0 ? void 0 : { entry }))
1711
- };
1712
- });
1713
- function planDocumentId(plan) {
1714
- return plan.action === "document.create" ? plan.identity.documentId : plan.documentId;
1715
- }
1716
-
1717
- //#endregion
1718
- //#region ../server/src/internal/documents/document-store.ts
1719
- var DocumentStore = class extends Context.Service()("@internal/server/DocumentStore") {};
1720
-
1721
- //#endregion
1722
- //#region ../server/src/internal/documents/document-failures.ts
1723
- var DocumentPersistenceError = class extends Schema.TaggedError()("Documents.PersistenceError", {
1724
- operation: Schema.NonEmptyString,
1725
- cause: Schema.Defect()
1726
- }) {};
1727
- var DocumentGenerationConflict = class extends Schema.TaggedError()("Documents.GenerationConflict", {
1728
- expectedGeneration: DocumentGeneration,
1729
- actualGeneration: DocumentGeneration
1730
- }) {};
1731
- var DocumentConfigurationConflict = class extends Schema.TaggedError()("Documents.ConfigurationConflict", {
1732
- expectedRevision: Schema.NonEmptyString,
1733
- actualRevision: Schema.NullOr(Schema.NonEmptyString)
1734
- }) {};
1735
-
1736
- //#endregion
1737
- //#region ../server/src/internal/cursor.ts
1738
- function cursorCodec(schema, makeCursor, invalid) {
1739
- const decodeJson = Schema.decodeUnknownResult(schema);
1740
- const encodeJson = flow(Schema.encodeResult(schema), Result.getOrThrow);
1741
- return {
1742
- decode: (cursor) => {
1743
- const decoded = Encoding.decodeBase64UrlString(cursor);
1744
- if (Result.isFailure(decoded)) return Result.fail(invalid());
1745
- return decodeJson(decoded.success).pipe(Result.mapError(invalid));
1746
- },
1747
- encode: (payload) => makeCursor(Encoding.encodeBase64Url(encodeJson(payload)))
1748
- };
1749
- }
1750
-
1751
- //#endregion
1752
- //#region ../server/src/internal/documents/document-history.ts
1753
- const CursorPayload = Schema.Struct({
1754
- createdAt: Schema.DateTimeUtcFromString,
1755
- revisionId: RevisionId
1756
- });
1757
- const CursorJson = Schema.fromJsonString(CursorPayload);
1758
- const cursors = cursorCodec(CursorJson, (value) => DocumentHistoryCursor.make(value), () => new DocumentHistoryInvalidCursor());
1759
- function documentHistoryCapability(accessControl, repository) {
1760
- const requireHistory = (context, documentId) => accessControl.require(context, {
1761
- action: "document.history",
1762
- resource: {
1763
- documentId,
1764
- kind: "document"
1765
- }
1766
- });
1767
- const read = Effect.fn("Documents.history.read")(function* (context, documentId, revisionId) {
1768
- yield* requireHistory(context, documentId);
1769
- return yield* repository.revision(documentId, revisionId);
1770
- });
1771
- const list = Effect.fn("Documents.history.list")(function* (context, query) {
1772
- yield* requireHistory(context, query.documentId);
1773
- const cursor = query.cursor ? yield* Effect.fromResult(cursors.decode(query.cursor)) : void 0;
1774
- const page = yield* repository.revisions({
1775
- cursor,
1776
- documentId: query.documentId,
1777
- limit: query.limit ?? 25
1778
- });
1779
- const output = {
1780
- revisions: page.revisions.map(({ markdown: _markdown, ...revision }) => revision),
1781
- total: page.total
1782
- };
1783
- return page.next ? DocumentRevisionPage.make({
1784
- ...output,
1785
- nextCursor: cursors.encode(page.next)
1786
- }) : DocumentRevisionPage.make(output);
1787
- });
1788
- return {
1789
- compare: Effect.fn("Documents.history.compare")(function* (context, input) {
1790
- yield* requireHistory(context, input.documentId);
1791
- const from = yield* repository.revision(input.documentId, input.fromRevisionId);
1792
- const to = yield* repository.revision(input.documentId, input.toRevisionId);
1793
- const changes = yield* compareLines(from.markdown, to.markdown);
1794
- return DocumentRevisionComparison.make({
1795
- changes,
1796
- from,
1797
- to
1798
- });
1799
- }),
1800
- list,
1801
- read
1802
- };
1803
- }
1804
- const MAXIMUM_COMPARISON_LINES = 1e4;
1805
- const MAXIMUM_EDIT_LENGTH = 2e3;
1806
- const comparisonTooLarge = () => new DocumentHistoryComparisonTooLarge({
1807
- maximumEditLength: MAXIMUM_EDIT_LENGTH,
1808
- maximumLines: MAXIMUM_COMPARISON_LINES
1809
- });
1810
- const compareLines = Effect.fn("Documents.history.compareLines")(function* (beforeMarkdown, afterMarkdown) {
1811
- const before = beforeMarkdown.split("\n");
1812
- const after = afterMarkdown.split("\n");
1813
- if (before.length > MAXIMUM_COMPARISON_LINES || after.length > MAXIMUM_COMPARISON_LINES) return yield* comparisonTooLarge();
1814
- const diff = diffArrays(before, after, {
1815
- maxEditLength: MAXIMUM_EDIT_LENGTH,
1816
- oneChangePerToken: true,
1817
- timeout: 100
1818
- });
1819
- if (!diff) return yield* comparisonTooLarge();
1820
- const changes = [];
1821
- let beforeLine = 1;
1822
- let afterLine = 1;
1823
- for (const change of diff) for (const line of change.value) if (change.removed) {
1824
- changes.push({
1825
- beforeLine,
1826
- kind: "removed",
1827
- line
1828
- });
1829
- beforeLine += 1;
1830
- } else if (change.added) {
1831
- changes.push({
1832
- afterLine,
1833
- kind: "added",
1834
- line
1835
- });
1836
- afterLine += 1;
1837
- } else {
1838
- changes.push({
1839
- afterLine,
1840
- beforeLine,
1841
- kind: "equal",
1842
- line
1843
- });
1844
- beforeLine += 1;
1845
- afterLine += 1;
1846
- }
1847
- return changes;
1848
- });
1849
-
1850
- //#endregion
1851
- //#region ../server/src/internal/documents/document-delivery.ts
1852
- function documentDelivery(configuration, catalog) {
1853
- const read = Effect.fn("Documents.delivery.read")(function* (lookup) {
1854
- const document = findDocument(yield* catalog, lookup);
1855
- return Option.isSome(document) ? document.value : yield* new PublishedDocumentNotFound({ lookup });
1856
- });
1857
- const query = Effect.fn("Documents.delivery.query")(function* (input) {
1858
- return queryDocuments((yield* catalog).documents, input, {
1859
- limit: input.limit,
1860
- offset: input.offset ?? 0
1861
- });
1862
- });
1863
- const navigation = Effect.fn("Documents.delivery.navigation")(function* (input) {
1864
- return createNavigation((yield* catalog).documents, input, configuration);
1865
- });
1866
- const surround = Effect.fn("Documents.delivery.surround")(function* (lookup, input) {
1867
- const current = yield* catalog;
1868
- const document = findDocument(current, lookup);
1869
- if (Option.isNone(document)) return yield* new PublishedDocumentNotFound({ lookup });
1870
- const surroundQuery = Object.assign({}, { collection: input.collection ?? document.value.collection }, input.locale === void 0 && document.value.locale === void 0 ? void 0 : { locale: input.locale ?? document.value.locale }, input.where === void 0 ? void 0 : { where: input.where }, input.sort === void 0 ? void 0 : { sort: input.sort });
1871
- const page = queryDocuments(current.documents, surroundQuery);
1872
- const index = page.items.findIndex((candidate) => candidate.id === document.value.id);
1873
- return DocumentSurround.make({
1874
- previous: index > 0 ? page.items[index - 1] ?? null : null,
1875
- next: index >= 0 ? page.items[index + 1] ?? null : null
1876
- });
1877
- });
1878
- return {
1879
- diagnostics: catalog.pipe(Effect.map((current) => current.issues)),
1880
- navigation,
1881
- query,
1882
- read,
1883
- surround
1884
- };
1885
- }
1886
- function findDocument(catalog, lookup) {
1887
- switch (lookup.kind) {
1888
- case "id": return Option.fromNullishOr(catalog.documents.find((document) => document.id === lookup.documentId));
1889
- case "path": return catalog.findByPath(lookup.path);
1890
- case "key": return catalog.findByKey(lookup.key, lookup.locale).pipe(Option.filter((document) => lookup.collection === void 0 || document.collection === lookup.collection));
1891
- }
1892
- }
1893
- function queryDocuments(documents, query, page) {
1894
- const filtered = documents.filter((document) => {
1895
- if (query.collection !== void 0 && document.collection !== query.collection) return false;
1896
- if (query.locale !== void 0 && document.locale !== query.locale) return false;
1897
- return Object.entries(query.where ?? {}).every(([field, expected]) => matchesValue(documentField(document, field), expected));
1898
- });
1899
- const sorted = query.sort && query.sort.length > 0 ? sortDocuments(filtered, query.sort) : filtered;
1900
- const items = page ? sorted.slice(page.offset, page.offset + page.limit) : sorted;
1901
- return PublishedDocumentPage.make({
1902
- items,
1903
- total: filtered.length
1904
- });
1905
- }
1906
- function createNavigation(documents, query, configuration) {
1907
- const locale = query.locale ?? configuration.locales?.defaultLocale;
1908
- const candidates = documents.filter((document) => (query.collection === void 0 || document.collection === query.collection) && (locale === void 0 || document.locale === locale) && document.data.navigation !== false);
1909
- const roots = [];
1910
- const itemsById = new Map(candidates.map((document) => [document.id, navigationItem(document)]));
1911
- const orderByItem = /* @__PURE__ */ new Map();
1912
- for (const document of candidates) {
1913
- const item = itemsById.get(document.id);
1914
- if (!item) continue;
1915
- orderByItem.set(item, document.placement.kind === "home" ? Number.NEGATIVE_INFINITY : navigationOrder(document));
1916
- if (document.placement.kind === "entry") {
1917
- const parent = itemsById.get(document.placement.parentDocumentId);
1918
- if (parent) parent.children.push(item);
1919
- else roots.push(item);
1920
- } else roots.push(item);
1921
- }
1922
- sortNavigation(roots, orderByItem);
1923
- return roots.map((item) => DocumentNavigationItem.make(item));
1924
- }
1925
- function navigationItem(document) {
1926
- const navigation = document.data.navigation;
1927
- const configuredTitle = Schema.is(Schema.JsonObject)(navigation) ? navigation.title : void 0;
1928
- return Object.assign({
1929
- children: [],
1930
- documentId: document.id,
1931
- key: document.key,
1932
- path: document.path,
1933
- title: Schema.is(Schema.String)(configuredTitle) && configuredTitle.trim() ? configuredTitle.trim() : document.title
1934
- }, document.locale === void 0 ? void 0 : { locale: document.locale });
1935
- }
1936
- function navigationOrder(document) {
1937
- const navigation = document.data.navigation;
1938
- const order = (Schema.is(Schema.JsonObject)(navigation) ? navigation.order : void 0) ?? document.data.order;
1939
- return Schema.is(Schema.Finite)(order) ? order : Number.POSITIVE_INFINITY;
1940
- }
1941
- function sortNavigation(items, orderByItem) {
1942
- items.sort((left, right) => {
1943
- return (orderByItem.get(left) ?? Number.POSITIVE_INFINITY) - (orderByItem.get(right) ?? Number.POSITIVE_INFINITY) || left.title.localeCompare(right.title);
1944
- });
1945
- items.forEach((item) => sortNavigation(item.children, orderByItem));
1946
- }
1947
- function documentField(document, field) {
1948
- switch (field) {
1949
- case "collection": return document.collection;
1950
- case "description": return document.description;
1951
- case "id": return document.id;
1952
- case "key": return document.key;
1953
- case "locale": return document.locale;
1954
- case "path": return document.path;
1955
- case "title": return document.title;
1956
- default: return nestedValue(document.data, field.startsWith("data.") ? field.slice(5) : field);
1957
- }
1958
- }
1959
- function nestedValue(value, path) {
1960
- return path.split(".").reduce((current, segment) => {
1961
- if (!Schema.is(Schema.JsonObject)(current)) return void 0;
1962
- return current[segment];
1963
- }, value);
1964
- }
1965
- function matchesValue(actual, expected) {
1966
- const expectedValues = Array.isArray(expected) ? expected : [expected];
1967
- return (Array.isArray(actual) ? actual : [actual]).some((value) => Schema.is(DocumentQueryScalar)(value) && expectedValues.includes(value));
1968
- }
1969
- function sortDocuments(documents, sorts) {
1970
- return documents.toSorted((left, right) => {
1971
- for (const sort of sorts) {
1972
- const comparison = compareValues(documentField(left, sort.field), documentField(right, sort.field));
1973
- if (comparison !== 0) return sort.direction === "desc" ? -comparison : comparison;
1974
- }
1975
- return 0;
1976
- });
1977
- }
1978
- function compareValues(left, right) {
1979
- if (left === right) return 0;
1980
- if (left === void 0 || left === null) return 1;
1981
- if (right === void 0 || right === null) return -1;
1982
- if (Schema.is(Schema.Finite)(left) && Schema.is(Schema.Finite)(right)) return left - right;
1983
- const leftText = Schema.is(Schema.String)(left) ? left : JSON.stringify(left) ?? "";
1984
- const rightText = Schema.is(Schema.String)(right) ? right : JSON.stringify(right) ?? "";
1985
- return leftText.localeCompare(rightText);
1986
- }
1987
-
1988
- //#endregion
1989
- //#region ../server/src/internal/documents/documents.ts
1990
- const isDocumentGenerationConflict = Schema.is(DocumentGenerationConflict);
1991
- const isDocumentMediaUnavailable = Schema.is(DocumentMediaUnavailable);
1992
- const CONTENT_MUTATION_BUFFER_CAPACITY = 16;
1993
- var Documents = class extends Context.Service()("@internal/server/Documents") {};
1994
- var DocumentPreviews = class extends Context.Service()("@internal/server/DocumentPreviews") {};
1995
- var PublishedDocuments = class extends Context.Service()("@internal/server/PublishedDocuments") {};
1996
- var DocumentMaintenance = class extends Context.Service()("@internal/server/internal/DocumentMaintenance") {};
1997
- const makeDocuments = Effect.fn("Documents.make")(function* (configuration, options) {
1998
- const repository = yield* DocumentStore;
1999
- const accessControl = yield* AccessControl;
2000
- const crypto = yield* Crypto.Crypto;
2001
- const engine = yield* createDocumentEngine(configuration, options);
2002
- const state = yield* Ref.make(yield* loadSynchronizedState(repository, engine));
2003
- const semaphore = yield* Semaphore.make(1);
2004
- const mutationEvents = yield* Effect.acquireRelease(PubSub.sliding(CONTENT_MUTATION_BUFFER_CAPACITY), PubSub.shutdown);
2005
- const dependencies = {
2006
- engine,
2007
- configuration,
2008
- ...options.configurationRevision === void 0 ? void 0 : { configurationRevision: options.configurationRevision },
2009
- repository
2010
- };
2011
- const refreshUnlocked = Effect.fn("Documents.refreshUnlocked")(function* (force = false) {
2012
- const current = yield* Ref.get(state);
2013
- const snapshot = force ? yield* loadRequired(repository) : yield* repository.load(current.snapshot.generation);
2014
- if (!snapshot || !generationIsAfter(snapshot.generation, current.snapshot.generation)) return current.snapshot.generation;
2015
- const refreshed = yield* compileDocumentState(engine, snapshot, current);
2016
- yield* Ref.set(state, refreshed);
2017
- return refreshed.snapshot.generation;
2018
- });
2019
- const executeUnlocked = Effect.fn("Documents.execute")(function* (command, activity) {
2020
- return yield* Effect.gen(function* () {
2021
- yield* refreshUnlocked();
2022
- const current = yield* Ref.get(state);
2023
- const outcome = yield* commitDocumentMutation(accessControl, dependencies, current, command, activity);
2024
- if (outcome.kind === "unchanged") return outcome.result;
2025
- yield* Ref.set(state, outcome.next);
2026
- yield* PubSub.publish(mutationEvents, outcome.result);
2027
- return outcome.result;
2028
- }).pipe(Effect.tapError((error) => isDocumentGenerationConflict(error) ? refreshUnlocked(true) : Effect.void), Effect.retry({
2029
- schedule: Schedule.recurs(3),
2030
- while: isDocumentGenerationConflict
2031
- }));
2032
- });
2033
- const runMutation = Effect.fn("Documents.runMutation")(function* (command, activity, reason) {
2034
- const resolvedActivity = enrichActivity(activity, reason);
2035
- return yield* semaphore.withPermits(1)(executeUnlocked(command, resolvedActivity));
2036
- });
2037
- const authored = semaphore.withPermits(1)(Effect.gen(function* () {
2038
- yield* refreshUnlocked();
2039
- return (yield* Ref.get(state)).authored;
2040
- })).pipe(Effect.withSpan("Documents.authored"));
2041
- const browse = Effect.fn("Documents.browse")((query) => semaphore.withPermits(1)(Effect.gen(function* () {
2042
- yield* refreshUnlocked();
2043
- return authoringEntries(yield* Ref.get(state), query);
2044
- })));
2045
- const create = Effect.fn("Documents.create")(function* (input, activity) {
2046
- const collection = configuration.types.find((candidate) => candidate.collection === input.collection);
2047
- if (collection && !collection.canCreate) return yield* new DocumentValidationFailed({ issues: [{
2048
- code: "document.invalid",
2049
- field: "collection",
2050
- message: `Document collection "${input.collection}" does not allow creation.`,
2051
- severity: "error"
2052
- }] });
2053
- const plan = yield* Effect.fromResult(planDocumentCreation(configuration, input));
2054
- const source = yield* createInitialDocumentSource(plan);
2055
- const documentId = DocumentId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
2056
- const identity = Object.assign({
2057
- collection: plan.collection.collection,
2058
- documentId
2059
- }, plan.locale === void 0 ? void 0 : { locale: plan.locale });
2060
- return yield* runMutation({
2061
- action: "document.create",
2062
- identity,
2063
- markdown: source.markdown,
2064
- placement: plan.placement
2065
- }, activity, input.reason);
2066
- });
2067
- const duplicate = Effect.fn("Documents.duplicate")((input, activity) => runMutation({
2068
- action: "document.duplicate",
2069
- input,
2070
- nextDocumentId: crypto.randomUUIDv4.pipe(Effect.orDie, Effect.map((value) => DocumentId.make(value)))
2071
- }, activity, input.reason));
2072
- const unpublish = Effect.fn("Documents.unpublish")((input, activity) => runMutation({
2073
- action: "document.unpublish",
2074
- input
2075
- }, activity, input.reason));
2076
- const move = Effect.fn("Documents.move")((input, activity) => runMutation({
2077
- action: "document.move",
2078
- input
2079
- }, activity, input.reason));
2080
- const subscribeMutations = Effect.gen(function* () {
2081
- const subscription = yield* PubSub.subscribe(mutationEvents);
2082
- const baseline = yield* semaphore.withPermits(1)(Ref.get(state).pipe(Effect.map((current) => current.snapshot.generation)));
2083
- return {
2084
- baseline,
2085
- mutations: Stream.fromSubscription(subscription).pipe(Stream.filter((mutation) => generationIsAfter(mutation.generation, baseline)))
2086
- };
2087
- }).pipe(Effect.withSpan("Documents.subscribeMutations"));
2088
- const publish = Effect.fn("Documents.publish")((input, activity) => runMutation({
2089
- action: "document.publish",
2090
- input
2091
- }, activity, input.reason));
2092
- const published = semaphore.withPermits(1)(Effect.gen(function* () {
2093
- yield* refreshUnlocked();
2094
- return (yield* Ref.get(state)).published;
2095
- })).pipe(Effect.withSpan("Documents.published"));
2096
- const read = Effect.fn("Documents.read")((documentId) => semaphore.withPermits(1)(Effect.gen(function* () {
2097
- yield* refreshUnlocked();
2098
- return (yield* Ref.get(state)).activeById.get(documentId) || (yield* new DocumentNotFound({ documentId }));
2099
- })));
2100
- const refresh = semaphore.withPermits(1)(refreshUnlocked()).pipe(Effect.withSpan("Documents.refresh"));
2101
- const remove = Effect.fn("Documents.remove")((input, activity) => runMutation({
2102
- action: "document.remove",
2103
- input
2104
- }, activity, input.reason));
2105
- const restore = Effect.fn("Documents.restore")((input, activity) => runMutation({
2106
- action: "document.restore",
2107
- input
2108
- }, activity, input.reason));
2109
- const trash = semaphore.withPermits(1)(Effect.gen(function* () {
2110
- yield* refreshUnlocked();
2111
- return deletedEntries(yield* Ref.get(state));
2112
- })).pipe(Effect.withSpan("Documents.trash"));
2113
- const undelete = Effect.fn("Documents.undelete")((input, activity) => runMutation({
2114
- action: "document.undelete",
2115
- input
2116
- }, activity, input.reason));
2117
- const update = Effect.fn("Documents.update")((input, activity) => runMutation({
2118
- action: "document.update",
2119
- input
2120
- }, activity, input.reason));
2121
- const validate = Effect.fn("Documents.validate")((input) => semaphore.withPermits(1)(Effect.gen(function* () {
2122
- yield* refreshUnlocked();
2123
- return yield* validateDocumentUpdate(engine, yield* Ref.get(state), input);
2124
- })));
2125
- const history = documentHistoryCapability(accessControl, repository);
2126
- const delivery = documentDelivery(configuration, published);
2127
- const document = (documentId) => ({
2128
- documentId,
2129
- kind: "document"
2130
- });
2131
- const requireThen = (context, action, resource, effect) => accessControl.require(context, {
2132
- action,
2133
- resource
2134
- }).pipe(Effect.andThen(effect));
2135
- const requireContentTransfer = (context) => accessControl.require(context, {
2136
- action: "document.transfer",
2137
- resource: { kind: "catalog" }
2138
- });
2139
- const contentSnapshot = (context) => requireContentTransfer(context).pipe(Effect.andThen(semaphore.withPermits(1)(Effect.gen(function* () {
2140
- yield* refreshUnlocked();
2141
- const current = yield* Ref.get(state);
2142
- return ContentSnapshot.make({
2143
- version: 2,
2144
- sources: current.snapshot.active.map((source) => ({
2145
- identity: source.identity,
2146
- placement: source.placement,
2147
- markdown: source.markdown,
2148
- published: source.publishedVersion === source.version,
2149
- revisionId: source.revisionId
2150
- })).sort((left, right) => left.identity.documentId.localeCompare(right.identity.documentId))
2151
- });
2152
- }))));
2153
- const contentPlan = (context, input) => requireContentTransfer(context).pipe(Effect.andThen(semaphore.withPermits(1)(Effect.gen(function* () {
2154
- yield* refreshUnlocked();
2155
- return (yield* planContentTransfer(engine, configuration, yield* Ref.get(state), input, crypto)).plan;
2156
- }))));
2157
- const contentApply = (context, input) => requireContentTransfer(context).pipe(Effect.andThen(semaphore.withPermits(1)(Effect.gen(function* () {
2158
- yield* refreshUnlocked();
2159
- const current = yield* Ref.get(state);
2160
- if (current.snapshot.generation !== input.expectedGeneration) return yield* new ContentTransferConflict({ message: "Content changed since the plan. Run content plan again." });
2161
- const planned = yield* planContentTransfer(engine, configuration, current, input, crypto);
2162
- if (planned.plan.entries.some((entry) => entry.action === "conflict")) return yield* new ContentTransferConflict({ message: "Destination content differs. Use --overwrite after reviewing the plan." });
2163
- if (!planned.plan.valid) return yield* new DocumentValidationFailed({ issues: planned.plan.issues });
2164
- if (planned.commitPlans.length === 0) return ContentApplyResult.make({
2165
- ...planned.counts,
2166
- generation: current.snapshot.generation
2167
- });
2168
- const authored = yield* compileValidCatalog(engine, planned.authoredSources, current.authored);
2169
- const publishedCatalog = yield* compileValidCatalog(engine, planned.publishedSources, current.published);
2170
- const [first, ...additionalPlans] = planned.commitPlans;
2171
- if (!first) throw new Error("Content import requires a commit plan.");
2172
- const committed = yield* commitApprovedDocumentPlans({
2173
- repository,
2174
- current,
2175
- plans: [first, ...additionalPlans],
2176
- authored,
2177
- published: publishedCatalog,
2178
- activity: requestActivity$1(context, "CMS content import"),
2179
- ...options.configurationRevision === void 0 ? void 0 : { configurationRevision: options.configurationRevision }
2180
- }).pipe(Effect.mapError((error) => isDocumentGenerationConflict(error) ? new ContentTransferConflict({ message: "Content changed since the plan. Run content plan again." }) : error));
2181
- yield* Ref.set(state, yield* compileDocumentState(engine, committed.snapshot, current));
2182
- yield* PubSub.publish(mutationEvents, committed.mutation);
2183
- return ContentApplyResult.make({
2184
- ...planned.counts,
2185
- generation: committed.snapshot.generation
2186
- });
2187
- }))));
2188
- const documents = Documents.of({
2189
- contentSnapshot,
2190
- contentPlan,
2191
- contentApply,
2192
- browse: (context, query) => requireThen(context, "document.browse", query.collection ? {
2193
- collection: query.collection,
2194
- kind: "collection",
2195
- locale: query.locale
2196
- } : { kind: "catalog" }, () => browse(query)),
2197
- create: (context, input) => requireThen(context, "document.create", {
2198
- collection: input.collection,
2199
- kind: "collection",
2200
- locale: input.locale
2201
- }, () => create(input, requestActivity$1(context, input.reason))),
2202
- historyCompare: history.compare,
2203
- historyList: history.list,
2204
- historyRead: history.read,
2205
- duplicate: (context, input) => requireThen(context, "document.duplicate", document(input.documentId), () => duplicate(input, requestActivity$1(context, input.reason))),
2206
- unpublish: (context, input) => requireThen(context, "document.unpublish", document(input.documentId), () => unpublish(input, requestActivity$1(context, input.reason))),
2207
- move: (context, input) => requireThen(context, "document.move", document(input.documentId), () => move(input, requestActivity$1(context, input.reason))),
2208
- publish: (context, input) => requireThen(context, "document.publish", document(input.documentId), () => publish(input, requestActivity$1(context, input.reason))),
2209
- read: (context, documentId) => requireThen(context, "document.read", document(documentId), () => read(documentId)),
2210
- remove: (context, input) => requireThen(context, "document.remove", document(input.documentId), () => remove(input, requestActivity$1(context, input.reason))),
2211
- restore: (context, input) => requireThen(context, "document.restore", document(input.documentId), () => restore(input, requestActivity$1(context, input.reason))),
2212
- trash: (context) => requireThen(context, "document.trash", { kind: "catalog" }, () => trash),
2213
- undelete: (context, input) => requireThen(context, "document.undelete", document(input.documentId), () => undelete(input, requestActivity$1(context, input.reason))),
2214
- update: (context, input) => requireThen(context, "document.update", document(input.documentId), () => update(input, requestActivity$1(context, input.reason))),
2215
- validate: (context, input) => requireThen(context, "document.validate", document(input.documentId), () => validate(input))
2216
- });
2217
- const draftDelivery = documentDelivery(configuration, authored);
2218
- const previews = DocumentPreviews.of({
2219
- read: (context, lookup) => requireThen(context, "document.browse", { kind: "catalog" }, () => draftDelivery.read(lookup)),
2220
- query: (context, query) => requireThen(context, "document.browse", { kind: "catalog" }, () => draftDelivery.query(query)),
2221
- navigation: (context, query) => requireThen(context, "document.browse", { kind: "catalog" }, () => draftDelivery.navigation(query)),
2222
- surround: (context, lookup, query) => requireThen(context, "document.browse", { kind: "catalog" }, () => draftDelivery.surround(lookup, query))
2223
- });
2224
- const publishedService = PublishedDocuments.of({
2225
- navigation: delivery.navigation,
2226
- query: delivery.query,
2227
- read: delivery.read,
2228
- snapshot: published.pipe(Effect.map((catalog) => catalog.documents)),
2229
- surround: delivery.surround,
2230
- diagnostics: (context) => accessControl.require(context, {
2231
- action: "document.browse",
2232
- resource: { kind: "catalog" }
2233
- }).pipe(Effect.andThen(delivery.diagnostics))
2234
- });
2235
- return {
2236
- documents,
2237
- maintenance: DocumentMaintenance.of({
2238
- compile: (source) => engine.compile({
2239
- draft: source.publishedVersion !== source.version,
2240
- identity: source.identity,
2241
- markdown: source.markdown,
2242
- placement: source.placement
2243
- }),
2244
- mediaReferences: (documentId) => semaphore.withPermits(1)(Effect.gen(function* () {
2245
- yield* refreshUnlocked();
2246
- const current = yield* Ref.get(state);
2247
- return projectMediaReferences(current.authored, current.published, documentId);
2248
- })),
2249
- publish,
2250
- read,
2251
- refresh,
2252
- subscribeMutations,
2253
- validate
2254
- }),
2255
- previews,
2256
- publishedDocuments: publishedService
2257
- };
2258
- });
2259
- function documentsLayer(configuration, options) {
2260
- return Layer.effectContext(makeDocuments(configuration, options).pipe(Effect.map(({ documents, maintenance, previews, publishedDocuments }) => Context.empty().pipe(Context.add(Documents, documents), Context.add(DocumentMaintenance, maintenance), Context.add(DocumentPreviews, previews), Context.add(PublishedDocuments, publishedDocuments)))));
2261
- }
2262
- function loadRequired(repository) {
2263
- return repository.load().pipe(Effect.filterOrFail((snapshot) => snapshot !== void 0, () => new DocumentPersistenceError({
2264
- cause: /* @__PURE__ */ new Error("DocumentStore returned no initial snapshot."),
2265
- operation: "DocumentStore.load"
2266
- })));
2267
- }
2268
- function loadSynchronizedState(repository, engine) {
2269
- return Effect.gen(function* () {
2270
- const snapshot = yield* loadRequired(repository);
2271
- const state = yield* compileDocumentState(engine, snapshot);
2272
- yield* repository.synchronizeMediaReferences({
2273
- expectedGeneration: snapshot.generation,
2274
- references: projectMediaReferences(state.authored, state.published)
2275
- });
2276
- return state;
2277
- }).pipe(Effect.retry({
2278
- schedule: Schedule.recurs(3),
2279
- while: isDocumentGenerationConflict
2280
- }), Effect.mapError((error) => isDocumentGenerationConflict(error) || isDocumentMediaUnavailable(error) ? new DocumentPersistenceError({
2281
- cause: error,
2282
- operation: "Documents.synchronizeMediaReferences"
2283
- }) : error));
2284
- }
2285
- function generationIsAfter(candidate, current) {
2286
- return BigInt(candidate) > BigInt(current);
2287
- }
2288
- function enrichActivity(activity, reason) {
2289
- return ActivityContext.make(Object.assign({}, activity, reason === void 0 ? void 0 : { reason }));
2290
- }
2291
- function requestActivity$1(context, reason) {
2292
- return ActivityContext.make(Object.assign({
2293
- actor: context.actor,
2294
- requestId: context.requestId
2295
- }, reason === void 0 ? void 0 : { reason }));
2296
- }
2297
-
2298
- //#endregion
2299
- //#region ../server/src/internal/seo/seo-store.ts
2300
- var SeoPersistenceError = class extends Schema.TaggedError()("Seo.PersistenceError", {
2301
- operation: Schema.NonEmptyString,
2302
- cause: Schema.Defect()
2303
- }) {};
2304
- var SeoStore = class extends Context.Service()("@internal/server/SeoStore") {};
2305
-
2306
- //#endregion
2307
- //#region ../server/src/internal/seo/seo.ts
2308
- var Seo = class extends Context.Service()("@internal/server/Seo") {};
2309
- var PublishedSeo = class extends Context.Service()("@internal/server/PublishedSeo") {};
2310
- var PreviewSeo = class extends Context.Service()("@internal/server/PreviewSeo") {};
2311
- var SeoDelivery = class extends Context.Service()("@internal/server/SeoDelivery") {};
2312
- function makeDefaultSeoOptions(baseUrl) {
2313
- const url = new URL(baseUrl);
2314
- return {
2315
- capabilities: SeoCapabilities.make({
2316
- generatedSocialImageTemplateIds: [],
2317
- identityTypes: [
2318
- "Person",
2319
- "Organization",
2320
- "LocalBusiness"
2321
- ],
2322
- structuredDataTypes: ["WebPage", "Article"]
2323
- }),
2324
- defaults: GlobalSeoSettings.make({
2325
- canonicalOrigin: SeoCanonicalOrigin.make(url.origin),
2326
- follow: true,
2327
- index: true,
2328
- siteName: url.hostname
2329
- })
2330
- };
2331
- }
2332
- const seoLayer = (options) => Layer.effectContext(Effect.gen(function* () {
2333
- const accessControl = yield* AccessControl;
2334
- const store = yield* SeoStore;
2335
- const load = Effect.fn("Seo.load")(function* () {
2336
- return (yield* store.load) ?? (yield* store.initialize(options.defaults));
2337
- });
2338
- const state = Effect.fn("Seo.state")(function* () {
2339
- return makeState(yield* load(), options.capabilities);
2340
- });
2341
- const requireAdministrator = (context, action) => accessControl.require(context, {
2342
- action,
2343
- resource: { kind: "seo" }
2344
- });
2345
- const read = Effect.fn("Seo.read")(function* (context) {
2346
- yield* requireAdministrator(context, "seo.read");
2347
- return yield* state();
2348
- });
2349
- const save = Effect.fn("Seo.save")(function* (context, input) {
2350
- yield* requireAdministrator(context, "seo.save");
2351
- const snapshot = yield* store.save({
2352
- activity: requestActivity(context, input.reason),
2353
- expectedVersion: input.expectedVersion,
2354
- settings: input.settings
2355
- });
2356
- return SeoMutationResult.make({
2357
- action: "seo.save",
2358
- state: makeState(snapshot, options.capabilities)
2359
- });
2360
- });
2361
- const publish = Effect.fn("Seo.publish")(function* (context, input) {
2362
- yield* requireAdministrator(context, "seo.publish");
2363
- const snapshot = yield* load();
2364
- const confirmationChanges = productionChanges(snapshot.published?.settings ?? options.defaults, snapshot.working.settings);
2365
- if (confirmationChanges.length > 0 && input.confirmedSiteWideChange !== true) return yield* new SeoConfirmationRequired({ changes: confirmationChanges });
2366
- const published = yield* store.publish({
2367
- activity: requestActivity(context, input.reason),
2368
- expectedVersion: input.expectedVersion
2369
- });
2370
- return SeoMutationResult.make({
2371
- action: "seo.publish",
2372
- state: makeState(published, options.capabilities)
2373
- });
2374
- });
2375
- const seo = Seo.of({
2376
- publish,
2377
- read,
2378
- save
2379
- });
2380
- const publishedSeo = PublishedSeo.of({ read: load().pipe(Effect.map((snapshot) => SeoSnapshot.make({
2381
- capabilities: options.capabilities,
2382
- revision: snapshot.published ?? snapshot.working
2383
- }))) });
2384
- const previewSeo = PreviewSeo.of({ read: load().pipe(Effect.map((snapshot) => SeoSnapshot.make({
2385
- capabilities: options.capabilities,
2386
- revision: snapshot.working
2387
- }))) });
2388
- return Context.empty().pipe(Context.add(Seo, seo), Context.add(PublishedSeo, publishedSeo), Context.add(PreviewSeo, previewSeo));
2389
- }));
2390
- const seoDeliveryLayer = Layer.effect(SeoDelivery, Effect.gen(function* () {
2391
- const previews = yield* PreviewSeo;
2392
- const published = yield* PublishedSeo;
2393
- const documents = yield* PublishedDocuments;
2394
- const alternatives = (document) => documents.snapshot.pipe(Effect.map((snapshot) => snapshot.flatMap((candidate) => candidate.key === document.key && candidate.locale !== void 0 ? [{
2395
- locale: candidate.locale,
2396
- path: candidate.path
2397
- }] : [])));
2398
- const resolveWith = (document, snapshot, localized) => CompiledDocument.make(Object.assign({}, document, {
2399
- alternatives: localized,
2400
- resolvedSeo: resolveDocumentSeo({
2401
- capabilities: snapshot.capabilities,
2402
- document,
2403
- global: snapshot.revision.settings
2404
- })
2405
- }));
2406
- const publishedDocument = Effect.fn("SeoDelivery.publishedDocument")((document) => Effect.all({
2407
- snapshot: published.read,
2408
- alternatives: alternatives(document)
2409
- }).pipe(Effect.map(({ alternatives, snapshot }) => resolveWith(document, snapshot, alternatives))));
2410
- const previewDocument = Effect.fn("SeoDelivery.previewDocument")((document) => Effect.all({
2411
- snapshot: previews.read,
2412
- alternatives: alternatives(document)
2413
- }).pipe(Effect.map(({ alternatives, snapshot }) => resolveWith(document, snapshot, alternatives))));
2414
- const sitemap = Effect.gen(function* () {
2415
- const snapshot = yield* published.read;
2416
- const resolved = (yield* documents.snapshot).flatMap((document) => {
2417
- const resolvedDocument = resolveWith(document, snapshot, []);
2418
- return resolvedDocument.resolvedSeo?.index === true && resolvedDocument.source.publishedAt !== void 0 ? [resolvedDocument] : [];
2419
- });
2420
- const localesByKey = /* @__PURE__ */ new Map();
2421
- for (const document of resolved) {
2422
- if (document.locale === void 0) continue;
2423
- const alternatives = localesByKey.get(document.key) ?? [];
2424
- alternatives.push({
2425
- locale: document.locale,
2426
- loc: document.path
2427
- });
2428
- localesByKey.set(document.key, alternatives);
2429
- }
2430
- return resolved.flatMap((document) => {
2431
- const publishedAt = document.source.publishedAt;
2432
- if (publishedAt === void 0) return [];
2433
- const alternatives = localesByKey.get(document.key);
2434
- const entry = {
2435
- loc: document.path,
2436
- lastmod: publishedAt
2437
- };
2438
- return [SitemapEntry.make(alternatives && alternatives.length > 1 ? {
2439
- ...entry,
2440
- alternatives
2441
- } : entry)];
2442
- }).sort((left, right) => left.loc.localeCompare(right.loc));
2443
- }).pipe(Effect.withSpan("SeoDelivery.sitemap"));
2444
- return SeoDelivery.of({
2445
- previewDocument,
2446
- publishedDocument,
2447
- sitemap
2448
- });
2449
- }));
2450
- function makeState(snapshot, capabilities) {
2451
- return SeoState.make(snapshot.published === void 0 ? {
2452
- capabilities,
2453
- working: snapshot.working
2454
- } : {
2455
- capabilities,
2456
- published: snapshot.published,
2457
- working: snapshot.working
2458
- });
2459
- }
2460
- function requestActivity(context, reason) {
2461
- return {
2462
- actor: context.actor,
2463
- requestId: context.requestId,
2464
- ...reason === void 0 ? void 0 : { reason }
2465
- };
2466
- }
2467
- function productionChanges(previous, next) {
2468
- const changes = [];
2469
- if (previous.canonicalOrigin !== next.canonicalOrigin) changes.push("canonicalOrigin");
2470
- if (previous.index !== next.index || previous.follow !== next.follow) changes.push("indexability");
2471
- return changes;
2472
- }
2473
-
2474
- //#endregion
2475
- //#region ../server/src/internal/media/media-object-store.ts
2476
- const mediaObjectPrefix = "media/";
2477
- var MediaObjectStore = class extends Context.Service()("@internal/server/MediaObjectStore") {};
2478
-
2479
- //#endregion
2480
- //#region ../server/src/internal/media/media-failures.ts
2481
- var MediaPersistenceError = class extends Schema.TaggedError()("Media.PersistenceError", {
2482
- operation: Schema.NonEmptyString,
2483
- cause: Schema.Defect()
2484
- }) {};
2485
- var MediaStorageError = class extends Schema.TaggedError()("Media.StorageError", {
2486
- operation: Schema.NonEmptyString,
2487
- cause: Schema.Defect()
2488
- }) {};
2489
-
2490
- //#endregion
2491
- //#region ../s3/src/internal/client.ts
2492
- var S3RequestError = class extends Schema.TaggedError()("S3.RequestError", {
2493
- cause: Schema.Defect(),
2494
- operation: Schema.NonEmptyString
2495
- }) {};
2496
- function openAwsS3MediaObjectClient(options) {
2497
- const credentials = options.credentials ? {
2498
- accessKeyId: options.credentials.accessKeyId,
2499
- secretAccessKey: Redacted.value(options.credentials.secretAccessKey),
2500
- sessionToken: options.credentials.sessionToken ? Redacted.value(options.credentials.sessionToken) : void 0
2501
- } : void 0;
2502
- return makeAwsS3MediaObjectClient(new S3Client({
2503
- credentials,
2504
- endpoint: options.endpoint,
2505
- forcePathStyle: options.forcePathStyle,
2506
- region: options.region,
2507
- requestChecksumCalculation: "WHEN_REQUIRED"
2508
- }));
2509
- }
2510
- function makeAwsS3MediaObjectClient(client) {
2511
- const request = (operation, send) => Effect.tryPromise({
2512
- catch: (cause) => new S3RequestError({
2513
- cause,
2514
- operation
2515
- }),
2516
- try: send
2517
- });
2518
- return {
2519
- close: Effect.sync(() => client.destroy()),
2520
- copyObject: (input) => request("MediaObjectStore.S3.copyObject", (signal) => client.send(new CopyObjectCommand({
2521
- Bucket: input.bucket,
2522
- CacheControl: input.cacheControl,
2523
- ContentType: input.contentType,
2524
- CopySource: input.copySource,
2525
- Key: input.key,
2526
- MetadataDirective: "REPLACE"
2527
- }), { abortSignal: signal })).pipe(Effect.asVoid),
2528
- createBucket: (input) => request("MediaObjectStore.S3.createBucket", (signal) => client.send(new CreateBucketCommand({
2529
- Bucket: input.bucket,
2530
- CreateBucketConfiguration: input.locationConstraint ? { LocationConstraint: input.locationConstraint } : void 0
2531
- }), { abortSignal: signal })).pipe(Effect.asVoid),
2532
- deleteObject: (input) => request("MediaObjectStore.S3.deleteObject", (signal) => client.send(new DeleteObjectCommand({
2533
- Bucket: input.bucket,
2534
- Key: input.key
2535
- }), { abortSignal: signal })).pipe(Effect.asVoid),
2536
- headBucket: (input) => request("MediaObjectStore.S3.headBucket", (signal) => client.send(new HeadBucketCommand({ Bucket: input.bucket }), { abortSignal: signal })).pipe(Effect.asVoid),
2537
- headObject: (input) => request("MediaObjectStore.S3.headObject", (signal) => client.send(new HeadObjectCommand({
2538
- Bucket: input.bucket,
2539
- Key: input.key
2540
- }), { abortSignal: signal })).pipe(Effect.map((output) => ({
2541
- contentLength: output.ContentLength,
2542
- contentType: output.ContentType
2543
- }))),
2544
- listObjects: (input) => request("MediaObjectStore.S3.listObjects", (signal) => client.send(new ListObjectsV2Command({
2545
- Bucket: input.bucket,
2546
- ContinuationToken: input.continuationToken,
2547
- Prefix: input.prefix
2548
- }), { abortSignal: signal })).pipe(Effect.map((output) => ({
2549
- isTruncated: output.IsTruncated === true,
2550
- nextContinuationToken: output.NextContinuationToken,
2551
- objects: (output.Contents ?? []).map((object) => ({
2552
- key: object.Key,
2553
- size: object.Size
2554
- }))
2555
- }))),
2556
- putObject: (input) => request("MediaObjectStore.S3.putObject", (signal) => client.send(new PutObjectCommand({
2557
- Body: NodeStream.toReadableNever(input.body),
2558
- Bucket: input.bucket,
2559
- CacheControl: input.cacheControl,
2560
- ContentLength: input.contentLength,
2561
- ContentType: input.contentType,
2562
- Key: input.key
2563
- }), { abortSignal: signal })).pipe(Effect.asVoid)
2564
- };
2565
- }
2566
-
2567
- //#endregion
2568
- //#region ../s3/src/internal/media-object-store.ts
2569
- const replaceableMediaCacheControl = "public, max-age=0, must-revalidate";
2570
- const isWriteBodyError = Schema.is(Schema.Union([MediaInvalid, MediaStorageError]));
2571
- function s3MediaObjectStoreLayer(options) {
2572
- return Layer.effect(MediaObjectStore, resolveOptions(options).pipe(Effect.flatMap((resolved) => Effect.acquireRelease(Effect.sync(() => openAwsS3MediaObjectClient(resolved)), (client) => client.close).pipe(Effect.tap((client) => provisionBucket(resolved, client)), Effect.map((client) => makeStore(resolved, client))))));
2573
- }
2574
- function makeStore(options, client) {
2575
- return {
2576
- list: listObjects(options.bucket, options.prefix, client),
2577
- promote: (input) => promoteObject(options.bucket, options.prefix, input, client),
2578
- put: (input) => putObject(options.bucket, options.prefix, input, client),
2579
- remove: (objectKey) => providerRequest("MediaObjectStore.S3.remove", client.deleteObject({
2580
- bucket: options.bucket,
2581
- key: physicalKey(options.prefix, objectKey)
2582
- })),
2583
- stat: (objectKey) => statObject(options.bucket, options.prefix, objectKey, client)
2584
- };
2585
- }
2586
- function promoteObject(bucket, prefix, input, client) {
2587
- if (input.byteSize > 5e9) return Effect.fail(storageError("MediaObjectStore.S3.promote", "The object exceeds the S3 single-copy size limit."));
2588
- return statObject(bucket, prefix, input.sourceObjectKey, client).pipe(Effect.flatMap((source) => Option.isSome(source) && source.value.byteSize === input.byteSize && source.value.mimeType === input.mimeType ? Effect.void : Effect.fail(storageError("MediaObjectStore.S3.promote.source", "The staged object metadata does not match its intent."))), Effect.flatMap(() => providerRequest("MediaObjectStore.S3.promote.copy", client.copyObject({
2589
- bucket,
2590
- cacheControl: replaceableMediaCacheControl,
2591
- contentType: input.mimeType,
2592
- copySource: copySource(bucket, physicalKey(prefix, input.sourceObjectKey)),
2593
- key: physicalKey(prefix, input.destinationObjectKey)
2594
- }))), Effect.flatMap(() => statObject(bucket, prefix, input.destinationObjectKey, client)), Effect.flatMap((destination) => Option.isSome(destination) && destination.value.byteSize === input.byteSize && destination.value.mimeType === input.mimeType ? Effect.succeed(destination.value) : Effect.fail(storageError("MediaObjectStore.S3.promote.verify", "The promoted object metadata does not match its intent."))));
2595
- }
2596
- function copySource(bucket, objectKey) {
2597
- return `/${encodeURIComponent(bucket)}/${objectKey.split("/").map(encodeURIComponent).join("/")}`;
2598
- }
2599
- function putObject(bucket, prefix, input, client) {
2600
- return Effect.gen(function* () {
2601
- const body = yield* validatedWriteBody(input);
2602
- yield* client.putObject({
2603
- body,
2604
- bucket,
2605
- cacheControl: replaceableMediaCacheControl,
2606
- contentLength: input.byteSize,
2607
- contentType: input.mimeType,
2608
- key: physicalKey(prefix, input.objectKey)
2609
- }).pipe(Effect.catch((failure) => isWriteBodyError(failure.cause) ? Effect.fail(failure.cause) : Effect.fail(providerError("MediaObjectStore.S3.put", failure))));
2610
- return {
2611
- byteSize: input.byteSize,
2612
- mimeType: input.mimeType,
2613
- objectKey: input.objectKey
2614
- };
2615
- });
2616
- }
2617
- const validatedWriteBody = Effect.fn("MediaObjectStore.S3.validateWriteBody")(function* (input) {
2618
- const byteLength = yield* Ref.make(0);
2619
- return input.body.pipe(Stream.mapEffect((chunk) => Effect.gen(function* () {
2620
- if ((yield* Ref.updateAndGet(byteLength, (current) => current + chunk.byteLength)) > input.byteSize) return yield* storageError("MediaObjectStore.S3.put.body", "The object body exceeds its declared byte size.");
2621
- return chunk;
2622
- })), Stream.concat(Stream.fromEffect(Ref.get(byteLength).pipe(Effect.flatMap((actual) => actual === input.byteSize ? Effect.void : Effect.fail(storageError("MediaObjectStore.S3.put.body", "The object body does not match its declared byte size."))))).pipe(Stream.drain)));
2623
- });
2624
- function statObject(bucket, prefix, objectKey, client) {
2625
- return client.headObject({
2626
- bucket,
2627
- key: physicalKey(prefix, objectKey)
2628
- }).pipe(Effect.matchEffect({
2629
- onFailure: (failure) => isMissingObject(failure.cause) ? Effect.succeed(Option.none()) : Effect.fail(providerError("MediaObjectStore.S3.stat", failure)),
2630
- onSuccess: (output) => decodeStoredObject("MediaObjectStore.S3.stat", objectKey, output.contentLength, output.contentType).pipe(Effect.asSome)
2631
- }));
2632
- }
2633
- function listObjects(bucket, prefix, client) {
2634
- return Stream.suspend(() => {
2635
- const seenTokens = /* @__PURE__ */ new Set();
2636
- return Stream.paginate(void 0, (continuationToken) => providerRequest("MediaObjectStore.S3.list", client.listObjects({
2637
- bucket,
2638
- continuationToken,
2639
- prefix: `${prefix}${mediaObjectPrefix}`
2640
- })).pipe(Effect.flatMap((page) => Effect.gen(function* () {
2641
- return [yield* Effect.forEach(page.objects, (object) => decodeListedObject(object, prefix)), yield* validateNextContinuationToken(continuationToken, seenTokens, page)];
2642
- }))));
2643
- });
2644
- }
2645
- function decodeListedObject(object, prefix) {
2646
- if (object.key === void 0) return Effect.fail(storageError("MediaObjectStore.S3.list", "The provider returned object metadata without a key."));
2647
- return decodeStoredObject("MediaObjectStore.S3.list", object.key.slice(prefix.length), object.size);
2648
- }
2649
- function validateNextContinuationToken(continuationToken, seenTokens, page) {
2650
- if (!page.isTruncated) return Effect.succeedNone;
2651
- const token = page.nextContinuationToken;
2652
- if (!token || token === continuationToken || seenTokens.has(token)) return Effect.fail(storageError("MediaObjectStore.S3.list", "The provider returned an invalid continuation token."));
2653
- seenTokens.add(token);
2654
- return Effect.succeedSome(token);
2655
- }
2656
- function decodeStoredObject(operation, objectKey, byteSize, contentType) {
2657
- const decodedObjectKey = Schema.decodeOption(MediaObjectKey)(objectKey);
2658
- const decodedByteSize = Schema.decodeUnknownOption(MediaByteSize)(byteSize);
2659
- if (Option.isNone(decodedObjectKey) || Option.isNone(decodedByteSize)) return Effect.fail(storageError(operation, "The provider returned invalid object metadata."));
2660
- const decodedMimeType = Schema.decodeUnknownOption(ImageMimeType)(contentType);
2661
- const storedObject = {
2662
- byteSize: decodedByteSize.value,
2663
- objectKey: decodedObjectKey.value
2664
- };
2665
- return Effect.succeed(Option.isSome(decodedMimeType) ? {
2666
- ...storedObject,
2667
- mimeType: decodedMimeType.value
2668
- } : storedObject);
2669
- }
2670
- function providerRequest(operation, request) {
2671
- return request.pipe(Effect.mapError((failure) => providerError(operation, failure)));
2672
- }
2673
- function provisionBucket(options, client) {
2674
- if (!options.provisionBucket) return Effect.void;
2675
- return client.headBucket({ bucket: options.bucket }).pipe(Effect.catch((failure) => isMissingBucket(failure.cause) ? createMissingBucket(options, client) : Effect.fail(providerError("MediaObjectStore.S3.bucket.head", failure))));
2676
- }
2677
- function createMissingBucket(options, client) {
2678
- return client.createBucket({
2679
- bucket: options.bucket,
2680
- locationConstraint: options.endpoint || options.region === "us-east-1" ? void 0 : options.region
2681
- }).pipe(Effect.catch((failure) => isBucketAlreadyOwned(failure.cause) ? providerRequest("MediaObjectStore.S3.bucket.verify", client.headBucket({ bucket: options.bucket })) : Effect.fail(providerError("MediaObjectStore.S3.bucket.create", failure))));
2682
- }
2683
- const ProviderFailureDetails = Schema.Struct({
2684
- $metadata: Schema.optionalKey(Schema.Struct({
2685
- attempts: Schema.optionalKey(Schema.Finite),
2686
- httpStatusCode: Schema.optionalKey(Schema.Finite)
2687
- })),
2688
- name: Schema.optionalKey(Schema.String)
2689
- });
2690
- const decodeProviderFailure = Schema.decodeUnknownOption(ProviderFailureDetails);
2691
- function providerError(operation, failure) {
2692
- const details = decodeProviderFailure(failure.cause);
2693
- const diagnostics = [];
2694
- if (Option.isSome(details)) {
2695
- if (details.value.name) diagnostics.push(`name=${details.value.name}`);
2696
- if (details.value.$metadata?.httpStatusCode !== void 0) diagnostics.push(`status=${details.value.$metadata.httpStatusCode}`);
2697
- if (details.value.$metadata?.attempts !== void 0) diagnostics.push(`attempts=${details.value.$metadata.attempts}`);
2698
- }
2699
- return storageError(operation, `The S3 provider request failed${diagnostics.length > 0 ? ` (${diagnostics.join(", ")}).` : "."}`);
2700
- }
2701
- function isMissingObject(cause) {
2702
- const details = decodeProviderFailure(cause);
2703
- if (Option.isNone(details)) return false;
2704
- return details.value.name === "NoSuchKey" || details.value.name === "NotFound";
2705
- }
2706
- function isMissingBucket(cause) {
2707
- const details = decodeProviderFailure(cause);
2708
- if (Option.isNone(details)) return false;
2709
- return details.value.name === "NoSuchBucket" || details.value.$metadata?.httpStatusCode === 404;
2710
- }
2711
- function isBucketAlreadyOwned(cause) {
2712
- const details = decodeProviderFailure(cause);
2713
- return Option.isSome(details) && details.value.name === "BucketAlreadyOwnedByYou";
2714
- }
2715
- function resolveOptions(options) {
2716
- const bucket = options.bucket.trim();
2717
- const region = options.region.trim();
2718
- const endpoint = options.endpoint?.trim();
2719
- const prefix = options.prefix.trim();
2720
- if (!bucket || !region || options.endpoint !== void 0 && !endpoint || !prefix || prefix.startsWith("/") || !prefix.endsWith("/") || prefix.includes("..")) return Effect.fail(storageError("MediaObjectStore.S3.configure", "The bucket, region, configured endpoint, and relative object prefix must be valid."));
2721
- if (options.credentials) {
2722
- const secretAccessKey = Redacted.value(options.credentials.secretAccessKey);
2723
- const sessionToken = options.credentials.sessionToken && Redacted.value(options.credentials.sessionToken);
2724
- if (!options.credentials.accessKeyId.trim() || !secretAccessKey || sessionToken === "") return Effect.fail(storageError("MediaObjectStore.S3.configure", "The configured credentials must be non-empty."));
2725
- }
2726
- return Effect.succeed({
2727
- ...options,
2728
- bucket,
2729
- credentials: options.credentials ? {
2730
- ...options.credentials,
2731
- accessKeyId: options.credentials.accessKeyId.trim()
2732
- } : void 0,
2733
- endpoint,
2734
- forcePathStyle: options.forcePathStyle ?? false,
2735
- prefix,
2736
- provisionBucket: options.provisionBucket ?? false,
2737
- region
2738
- });
2739
- }
2740
- function physicalKey(prefix, objectKey) {
2741
- return `${prefix}${objectKey}`;
2742
- }
2743
- function storageError(operation, message) {
2744
- return new MediaStorageError({
2745
- cause: new Error(message),
2746
- operation
2747
- });
2748
- }
2749
-
2750
- //#endregion
2751
- //#region ../s3/src/S3MediaObjects.ts
2752
- const maxS3SingleCopyBytes = 5e9;
2753
-
2754
- //#endregion
2755
- export { DocumentHistoryComparisonTooLarge as $, StudioAuthentication as A, CreateUserInput as B, DocumentPersistenceError as C, defaultAccessControlLayer as D, AccessControl as E, StudioInternalError as F, UserPage as G, UserAdministrationDenied as H, studioInternalError as I, CollaborationClientMessage as J, UserSelfRemovalDenied as K, InitializationAlreadyCompleted as L, StudioBootstrap as M, StudioRequestConflict as N, CurrentStudioRequest as O, StudioSchemaError as P, StateVector as Q, InitializationProofInvalid as R, DocumentGenerationConflict as S, renderEditorMarkdown as T, UserAlreadyExists as U, User as V, UserNotFound as W, CollaborationServerMessage as X, CollaborationColors as Y, CollaborationTicket as Z, Documents as _, mediaObjectPrefix as a, ActivityCursor as at, cursorCodec as b, Seo as c, ActivityEntryDraft as ct, seoDeliveryLayer as d, ActivityTarget as dt, DocumentHistoryInvalidCursor as et, seoLayer as f, ActivityTargetKind as ft, DocumentPreviews as g, DocumentMaintenance as h, MediaObjectStore as i, ActivityContext as it, StudioBadRequest as j, StudioApi as k, SeoDelivery as l, ActivityId as lt, SeoStore as m, s3MediaObjectStoreLayer as n, ACTIVITY_ACTIONS as nt, PreviewSeo as o, ActivityCursorInvalid as ot, SeoPersistenceError as p, UserSelfRoleChangeDenied as q, MediaPersistenceError as r, ActivityAction as rt, PublishedSeo as s, ActivityEntry as st, maxS3SingleCopyBytes as t, DocumentRevision as tt, makeDefaultSeoOptions as u, ActivityPage as ut, PublishedDocuments as v, DocumentStore as w, DocumentConfigurationConflict as x, documentsLayer as y, InitializationState as z };
2756
- //# sourceMappingURL=S3MediaObjects-BXfjaZOu.js.map