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