emdash 0.37.0 → 0.39.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 (1445) hide show
  1. package/dist/action-token-On1sot_c.mjs +26 -0
  2. package/dist/action-token-On1sot_c.mjs.map +1 -0
  3. package/dist/activation-CaMfdBt1.mjs +382 -0
  4. package/dist/activation-CaMfdBt1.mjs.map +1 -0
  5. package/dist/adapters-Cq10K4_c.d.mts +171 -0
  6. package/dist/adapters-Cq10K4_c.d.mts.map +1 -0
  7. package/dist/after-PcEvMY_6.mjs +96 -0
  8. package/dist/after-PcEvMY_6.mjs.map +1 -0
  9. package/dist/allowed-origins-1Sa-2wZK.mjs +116 -0
  10. package/dist/allowed-origins-1Sa-2wZK.mjs.map +1 -0
  11. package/dist/api/route-utils.d.mts +4 -3
  12. package/dist/api/route-utils.d.mts.map +1 -1
  13. package/dist/api/route-utils.mjs +45 -29
  14. package/dist/api/route-utils.mjs.map +1 -1
  15. package/dist/api/schemas/index.d.mts +2 -2
  16. package/dist/api/schemas/index.mjs +7 -6
  17. package/dist/api-DmjKxPCY.mjs +4831 -0
  18. package/dist/api-DmjKxPCY.mjs.map +1 -0
  19. package/dist/api-tokens-BIXItFKV.mjs +163 -0
  20. package/dist/api-tokens-BIXItFKV.mjs.map +1 -0
  21. package/dist/apply-drpfmqrR.mjs +1005 -0
  22. package/dist/apply-drpfmqrR.mjs.map +1 -0
  23. package/dist/artifact-fetch-COiMhVgk.mjs +813 -0
  24. package/dist/artifact-fetch-COiMhVgk.mjs.map +1 -0
  25. package/dist/astro/index.d.mts +14 -12
  26. package/dist/astro/index.d.mts.map +1 -1
  27. package/dist/astro/index.mjs +123 -13
  28. package/dist/astro/index.mjs.map +1 -1
  29. package/dist/astro/middleware/auth.d.mts +12 -10
  30. package/dist/astro/middleware/auth.d.mts.map +1 -1
  31. package/dist/astro/middleware/auth.mjs +20 -11
  32. package/dist/astro/middleware/auth.mjs.map +1 -1
  33. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  34. package/dist/astro/middleware/redirect.mjs +11 -9
  35. package/dist/astro/middleware/redirect.mjs.map +1 -1
  36. package/dist/astro/middleware/request-context.d.mts +1 -1
  37. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  38. package/dist/astro/middleware/request-context.mjs +154 -28
  39. package/dist/astro/middleware/request-context.mjs.map +1 -1
  40. package/dist/astro/middleware/setup.mjs +1 -1
  41. package/dist/astro/middleware.d.mts +13 -10
  42. package/dist/astro/middleware.d.mts.map +1 -1
  43. package/dist/astro/middleware.mjs +122 -3041
  44. package/dist/astro/middleware.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +10 -9
  46. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
  47. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +10 -9
  48. package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
  49. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  50. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  51. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  52. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +13 -12
  53. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
  54. package/dist/astro/routes/api/admin/byline-fields/index.mjs +13 -12
  55. package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +13 -12
  57. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
  58. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +22 -21
  59. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  60. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +22 -21
  61. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  62. package/dist/astro/routes/api/admin/bylines/index.mjs +22 -21
  63. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/comments/_id_/status.d.mts.map +1 -1
  65. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +21 -54
  66. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
  68. package/dist/astro/routes/api/admin/comments/bulk.mjs +15 -14
  69. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
  71. package/dist/astro/routes/api/admin/comments/index.mjs +15 -14
  72. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  74. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  75. package/dist/astro/routes/api/admin/media-usage/activation.mjs +17 -16
  76. package/dist/astro/routes/api/admin/media-usage/activation.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +19 -18
  78. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +19 -18
  80. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -1
  81. package/dist/astro/routes/api/admin/media-usage/progress.mjs +17 -17
  82. package/dist/astro/routes/api/admin/media-usage/repair.mjs +21 -20
  83. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +19 -18
  85. package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +19 -18
  87. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  89. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  90. package/dist/astro/routes/api/admin/plugins/_id_/disable.d.mts.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +9 -66
  92. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/_id_/enable.d.mts.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +9 -69
  95. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +66 -59
  97. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +6 -6
  99. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +65 -59
  100. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +70 -61
  102. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  103. package/dist/astro/routes/api/admin/plugins/_id_/update.d.mts.map +1 -1
  104. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +87 -63
  105. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  106. package/dist/astro/routes/api/admin/plugins/index.mjs +66 -59
  107. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  108. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  109. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +65 -59
  110. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  111. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.d.mts.map +1 -1
  112. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +85 -63
  113. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  114. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +65 -59
  115. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  116. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +70 -61
  117. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  118. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
  119. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +90 -66
  120. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  121. package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts.map +1 -1
  122. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +9 -7
  123. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  124. package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
  125. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +77 -63
  126. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  127. package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts.map +1 -1
  128. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +67 -61
  129. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  130. package/dist/astro/routes/api/admin/plugins/updates.d.mts.map +1 -1
  131. package/dist/astro/routes/api/admin/plugins/updates.mjs +66 -60
  132. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  133. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.d.mts +8 -0
  134. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.d.mts.map +1 -0
  135. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +27 -0
  136. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs.map +1 -0
  137. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +65 -59
  138. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  139. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  140. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +65 -59
  141. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  142. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  143. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  144. package/dist/astro/routes/api/admin/users/_id_/index.mjs +11 -10
  145. package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
  146. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  147. package/dist/astro/routes/api/admin/users/index.mjs +10 -9
  148. package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
  149. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
  150. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  151. package/dist/astro/routes/api/auth/invite/complete.mjs +15 -14
  152. package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
  153. package/dist/astro/routes/api/auth/invite/index.mjs +12 -11
  154. package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
  155. package/dist/astro/routes/api/auth/invite/register-options.mjs +14 -13
  156. package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
  157. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  158. package/dist/astro/routes/api/auth/magic-link/send.mjs +14 -13
  159. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  160. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  161. package/dist/astro/routes/api/auth/me.mjs +11 -10
  162. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  163. package/dist/astro/routes/api/auth/mode.mjs +4 -4
  164. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  165. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  166. package/dist/astro/routes/api/auth/passkey/_id_.mjs +10 -9
  167. package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
  168. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  169. package/dist/astro/routes/api/auth/passkey/options.mjs +16 -15
  170. package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
  171. package/dist/astro/routes/api/auth/passkey/register/options.mjs +14 -13
  172. package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
  173. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +15 -14
  174. package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
  175. package/dist/astro/routes/api/auth/passkey/verify.mjs +15 -14
  176. package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
  177. package/dist/astro/routes/api/auth/signup/complete.mjs +15 -14
  178. package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
  179. package/dist/astro/routes/api/auth/signup/request.mjs +14 -13
  180. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  181. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  182. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.d.mts.map +1 -1
  183. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +15 -211
  184. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  185. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -17
  186. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -1
  187. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  188. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
  189. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -11
  190. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  191. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
  192. package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts +10 -0
  193. package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts.map +1 -0
  194. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +67 -0
  195. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs.map +1 -0
  196. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  197. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.d.mts +8 -0
  198. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.d.mts.map +1 -0
  199. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +35 -0
  200. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs.map +1 -0
  201. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +16 -15
  202. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
  203. package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts +9 -2
  204. package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts.map +1 -1
  205. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +28 -16
  206. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  207. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +27 -23
  208. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  209. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +27 -23
  210. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  211. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
  212. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  213. package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
  214. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +27 -12
  215. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  216. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +23 -20
  217. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  218. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  219. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
  220. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +25 -12
  221. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  222. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  223. package/dist/astro/routes/api/content/_collection_/_id_.mjs +27 -14
  224. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  225. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  226. package/dist/astro/routes/api/content/_collection_/index.mjs +18 -12
  227. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  228. package/dist/astro/routes/api/content/_collection_/trash.mjs +11 -10
  229. package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
  230. package/dist/astro/routes/api/dashboard.mjs +14 -12
  231. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  232. package/dist/astro/routes/api/dev/emails.mjs +4 -4
  233. package/dist/astro/routes/api/health.d.mts +8 -0
  234. package/dist/astro/routes/api/health.d.mts.map +1 -0
  235. package/dist/astro/routes/api/health.mjs +21 -0
  236. package/dist/astro/routes/api/health.mjs.map +1 -0
  237. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  238. package/dist/astro/routes/api/import/probe.mjs +25 -23
  239. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  240. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  241. package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -11
  242. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  243. package/dist/astro/routes/api/import/wordpress/execute.mjs +20 -19
  244. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  245. package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -10
  246. package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
  247. package/dist/astro/routes/api/import/wordpress/media.mjs +15 -14
  248. package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
  249. package/dist/astro/routes/api/import/wordpress/prepare.mjs +14 -13
  250. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  251. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -11
  252. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
  253. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +18 -17
  254. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  255. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  256. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +25 -23
  257. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  258. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  259. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -11
  260. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
  261. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +36 -33
  262. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  263. package/dist/astro/routes/api/manifest.mjs +17 -9
  264. package/dist/astro/routes/api/manifest.mjs.map +1 -1
  265. package/dist/astro/routes/api/mcp.d.mts.map +1 -1
  266. package/dist/astro/routes/api/mcp.mjs +192 -110
  267. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  268. package/dist/astro/routes/api/media/_id_/confirm.mjs +15 -14
  269. package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
  270. package/dist/astro/routes/api/media/_id_/replace.mjs +12 -11
  271. package/dist/astro/routes/api/media/_id_/replace.mjs.map +1 -1
  272. package/dist/astro/routes/api/media/_id_/upload.mjs +8 -8
  273. package/dist/astro/routes/api/media/_id_/usage.mjs +23 -22
  274. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  275. package/dist/astro/routes/api/media/_id_.mjs +22 -21
  276. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  277. package/dist/astro/routes/api/media/asset/_id_/_filename_.d.mts +8 -0
  278. package/dist/astro/routes/api/media/asset/_id_/_filename_.d.mts.map +1 -0
  279. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +52 -0
  280. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs.map +1 -0
  281. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  282. package/dist/astro/routes/api/media/folders/_id_.mjs +12 -11
  283. package/dist/astro/routes/api/media/folders/_id_.mjs.map +1 -1
  284. package/dist/astro/routes/api/media/folders/index.mjs +12 -11
  285. package/dist/astro/routes/api/media/folders/index.mjs.map +1 -1
  286. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  287. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  288. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  289. package/dist/astro/routes/api/media/upload-url.mjs +14 -13
  290. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  291. package/dist/astro/routes/api/media.mjs +26 -25
  292. package/dist/astro/routes/api/media.mjs.map +1 -1
  293. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +15 -14
  294. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  295. package/dist/astro/routes/api/menus/_name_/items.mjs +15 -14
  296. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  297. package/dist/astro/routes/api/menus/_name_/reorder.mjs +15 -14
  298. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  299. package/dist/astro/routes/api/menus/_name_/translations.mjs +15 -14
  300. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  301. package/dist/astro/routes/api/menus/_name_.mjs +15 -14
  302. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  303. package/dist/astro/routes/api/menus/index.mjs +15 -14
  304. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  305. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  306. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
  307. package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
  308. package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
  309. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  310. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
  311. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
  312. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  313. package/dist/astro/routes/api/openapi.json.mjs +95 -24
  314. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  315. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts +2 -1
  316. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
  317. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +22 -40
  318. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
  319. package/dist/astro/routes/api/redirects/404s/index.mjs +18 -14
  320. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  321. package/dist/astro/routes/api/redirects/404s/summary.mjs +18 -14
  322. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  323. package/dist/astro/routes/api/redirects/_id_.d.mts.map +1 -1
  324. package/dist/astro/routes/api/redirects/_id_.mjs +20 -22
  325. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  326. package/dist/astro/routes/api/redirects/index.d.mts.map +1 -1
  327. package/dist/astro/routes/api/redirects/index.mjs +19 -19
  328. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  329. package/dist/astro/routes/api/relations/_id_/index.mjs +27 -23
  330. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  331. package/dist/astro/routes/api/relations/_id_/translations.mjs +21 -18
  332. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  333. package/dist/astro/routes/api/relations/index.mjs +27 -23
  334. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  335. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  336. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
  337. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +65 -59
  338. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  339. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +65 -59
  340. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  341. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +65 -59
  342. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  343. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +65 -59
  344. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  345. package/dist/astro/routes/api/schema/collections/index.mjs +65 -59
  346. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  347. package/dist/astro/routes/api/schema/collections/reorder.mjs +65 -59
  348. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  349. package/dist/astro/routes/api/schema/index.mjs +16 -14
  350. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  351. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +65 -59
  352. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  353. package/dist/astro/routes/api/schema/orphans/index.mjs +65 -59
  354. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  355. package/dist/astro/routes/api/search/enable.mjs +16 -14
  356. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  357. package/dist/astro/routes/api/search/index.mjs +17 -14
  358. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  359. package/dist/astro/routes/api/search/rebuild.mjs +16 -14
  360. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  361. package/dist/astro/routes/api/search/stats.mjs +10 -9
  362. package/dist/astro/routes/api/search/stats.mjs.map +1 -1
  363. package/dist/astro/routes/api/search/suggest.mjs +15 -13
  364. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  365. package/dist/astro/routes/api/sections/_slug_.mjs +15 -13
  366. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  367. package/dist/astro/routes/api/sections/index.mjs +15 -13
  368. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  369. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +9 -8
  370. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs.map +1 -1
  371. package/dist/astro/routes/api/settings/backups/archives/index.mjs +8 -7
  372. package/dist/astro/routes/api/settings/backups/archives/index.mjs.map +1 -1
  373. package/dist/astro/routes/api/settings/backups/export.mjs +9 -8
  374. package/dist/astro/routes/api/settings/backups/export.mjs.map +1 -1
  375. package/dist/astro/routes/api/settings/backups/index.mjs +10 -9
  376. package/dist/astro/routes/api/settings/backups/index.mjs.map +1 -1
  377. package/dist/astro/routes/api/settings/email.mjs +6 -6
  378. package/dist/astro/routes/api/settings.mjs +22 -20
  379. package/dist/astro/routes/api/settings.mjs.map +1 -1
  380. package/dist/astro/routes/api/setup/admin-verify.mjs +16 -15
  381. package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
  382. package/dist/astro/routes/api/setup/admin.mjs +15 -14
  383. package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
  384. package/dist/astro/routes/api/setup/dev-bypass.mjs +42 -38
  385. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  386. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  387. package/dist/astro/routes/api/setup/index.mjs +43 -38
  388. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  389. package/dist/astro/routes/api/setup/status.mjs +5 -5
  390. package/dist/astro/routes/api/snapshot.mjs +11 -10
  391. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  392. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -21
  393. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  394. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -21
  395. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  396. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -21
  397. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  398. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -21
  399. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  400. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -20
  401. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
  402. package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -21
  403. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
  404. package/dist/astro/routes/api/taxonomies/index.mjs +23 -21
  405. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  406. package/dist/astro/routes/api/themes/preview.mjs +8 -8
  407. package/dist/astro/routes/api/typegen.mjs +6 -6
  408. package/dist/astro/routes/api/visual-editing/action-token.d.mts +8 -0
  409. package/dist/astro/routes/api/visual-editing/action-token.d.mts.map +1 -0
  410. package/dist/astro/routes/api/visual-editing/action-token.mjs +25 -0
  411. package/dist/astro/routes/api/visual-editing/action-token.mjs.map +1 -0
  412. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.d.mts +8 -0
  413. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.d.mts.map +1 -0
  414. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +37 -0
  415. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs.map +1 -0
  416. package/dist/astro/routes/api/visual-editing/toolbar-labels.d.mts +8 -0
  417. package/dist/astro/routes/api/visual-editing/toolbar-labels.d.mts.map +1 -0
  418. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +20 -0
  419. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs.map +1 -0
  420. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  421. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  422. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  423. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +12 -11
  424. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  425. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +16 -15
  426. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  427. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +16 -15
  428. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  429. package/dist/astro/routes/api/widget-areas/_name_.mjs +10 -10
  430. package/dist/astro/routes/api/widget-areas/index.mjs +16 -15
  431. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  432. package/dist/astro/routes/api/widget-components.mjs +4 -4
  433. package/dist/astro/routes/robots.txt.mjs +13 -12
  434. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  435. package/dist/astro/routes/sitemap-_collection_.xml.d.mts.map +1 -1
  436. package/dist/astro/routes/sitemap-_collection_.xml.mjs +24 -19
  437. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  438. package/dist/astro/routes/sitemap.xml.mjs +14 -13
  439. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  440. package/dist/astro/types.d.mts +79 -26
  441. package/dist/astro/types.d.mts.map +1 -1
  442. package/dist/auth/providers/github.d.mts +1 -1
  443. package/dist/auth/providers/google.d.mts +1 -1
  444. package/dist/authoritative-records-DbqshfKD.mjs +5172 -0
  445. package/dist/authoritative-records-DbqshfKD.mjs.map +1 -0
  446. package/dist/authorize-BXpfMpp0.mjs +40 -0
  447. package/dist/authorize-BXpfMpp0.mjs.map +1 -0
  448. package/dist/backup-BsPQdwnS.mjs +246 -0
  449. package/dist/backup-BsPQdwnS.mjs.map +1 -0
  450. package/dist/base64-DvnNgP7e.mjs +63 -0
  451. package/dist/base64-DvnNgP7e.mjs.map +1 -0
  452. package/dist/byline-Doh-wt99.mjs +906 -0
  453. package/dist/byline-Doh-wt99.mjs.map +1 -0
  454. package/dist/byline-fields-CsrdvaLV.mjs +123 -0
  455. package/dist/byline-fields-CsrdvaLV.mjs.map +1 -0
  456. package/dist/byline-registry-D6lWzXk6.mjs +406 -0
  457. package/dist/byline-registry-D6lWzXk6.mjs.map +1 -0
  458. package/dist/bylines-Cop0hkoy.mjs +214 -0
  459. package/dist/bylines-Cop0hkoy.mjs.map +1 -0
  460. package/dist/bylines-kpBzHPr8.mjs +232 -0
  461. package/dist/bylines-kpBzHPr8.mjs.map +1 -0
  462. package/dist/cache-B0pOlXdM.mjs +108 -0
  463. package/dist/cache-B0pOlXdM.mjs.map +1 -0
  464. package/dist/capture-triggers-gxQxnxrJ.mjs +362 -0
  465. package/dist/capture-triggers-gxQxnxrJ.mjs.map +1 -0
  466. package/dist/challenge-store-CkRdSdd8.mjs +51 -0
  467. package/dist/challenge-store-CkRdSdd8.mjs.map +1 -0
  468. package/dist/checksum-Bsi2D9M1.mjs +162 -0
  469. package/dist/checksum-Bsi2D9M1.mjs.map +1 -0
  470. package/dist/chrome-tags-D7LGB91U.mjs +24 -0
  471. package/dist/chrome-tags-D7LGB91U.mjs.map +1 -0
  472. package/dist/chunks-BmWyou79.mjs +25 -0
  473. package/dist/chunks-BmWyou79.mjs.map +1 -0
  474. package/dist/cli/index.mjs +921 -106
  475. package/dist/cli/index.mjs.map +1 -1
  476. package/dist/client/cf-access.d.mts +1 -1
  477. package/dist/client/index.d.mts +17 -7
  478. package/dist/client/index.d.mts.map +1 -1
  479. package/dist/client/index.mjs +17 -12
  480. package/dist/client/index.mjs.map +1 -1
  481. package/dist/collection-deletion-C3Xixmkx.mjs +436 -0
  482. package/dist/collection-deletion-C3Xixmkx.mjs.map +1 -0
  483. package/dist/collection-slugs-cache-D9auiKmI.mjs +85 -0
  484. package/dist/collection-slugs-cache-D9auiKmI.mjs.map +1 -0
  485. package/dist/comment-DcT8qdPK.mjs +313 -0
  486. package/dist/comment-DcT8qdPK.mjs.map +1 -0
  487. package/dist/comment-reaction-DY5-y8Y5.mjs +85 -0
  488. package/dist/comment-reaction-DY5-y8Y5.mjs.map +1 -0
  489. package/dist/comments-B67VRNGw.mjs +204 -0
  490. package/dist/comments-B67VRNGw.mjs.map +1 -0
  491. package/dist/comments-BVzzt6x5.mjs +99 -0
  492. package/dist/comments-BVzzt6x5.mjs.map +1 -0
  493. package/dist/components-DIl9Qzh6.mjs +108 -0
  494. package/dist/components-DIl9Qzh6.mjs.map +1 -0
  495. package/dist/config-B2acLeC5.mjs +242 -0
  496. package/dist/config-B2acLeC5.mjs.map +1 -0
  497. package/dist/config-CGVeT8Hc.mjs +73 -0
  498. package/dist/config-CGVeT8Hc.mjs.map +1 -0
  499. package/dist/config-D3HhLON3.d.mts +39 -0
  500. package/dist/config-D3HhLON3.d.mts.map +1 -0
  501. package/dist/config-DS7e4EZ9.d.mts +6387 -0
  502. package/dist/config-DS7e4EZ9.d.mts.map +1 -0
  503. package/dist/content-DZ3B5qtA.mjs +2216 -0
  504. package/dist/content-DZ3B5qtA.mjs.map +1 -0
  505. package/dist/content-list-query-CbPdzsna.d.mts +26 -0
  506. package/dist/content-list-query-CbPdzsna.d.mts.map +1 -0
  507. package/dist/content-policy-CM4skrNi.mjs +46 -0
  508. package/dist/content-policy-CM4skrNi.mjs.map +1 -0
  509. package/dist/content-refresh-BHLHJgyt.mjs +3599 -0
  510. package/dist/content-refresh-BHLHJgyt.mjs.map +1 -0
  511. package/dist/content-repair-BVll5WNl.mjs +440 -0
  512. package/dist/content-repair-BVll5WNl.mjs.map +1 -0
  513. package/dist/context-B195kjqZ.mjs +1835 -0
  514. package/dist/context-B195kjqZ.mjs.map +1 -0
  515. package/dist/cron-BcR3RN4K.mjs +282 -0
  516. package/dist/cron-BcR3RN4K.mjs.map +1 -0
  517. package/dist/dashboard-CZD4G7k_.mjs +151 -0
  518. package/dist/dashboard-CZD4G7k_.mjs.map +1 -0
  519. package/dist/database/migration-lock.d.mts +37 -0
  520. package/dist/database/migration-lock.d.mts.map +1 -0
  521. package/dist/database/migration-lock.mjs +76 -0
  522. package/dist/database/migration-lock.mjs.map +1 -0
  523. package/dist/database/pg-migration-lock.d.mts +1 -1
  524. package/dist/database/pg-migration-lock.mjs +1 -1
  525. package/dist/database/pg-migration-lock.mjs.map +1 -1
  526. package/dist/datetime-normalization-PeiEdcRY.mjs +187 -0
  527. package/dist/datetime-normalization-PeiEdcRY.mjs.map +1 -0
  528. package/dist/db/index.d.mts +3 -3
  529. package/dist/db/index.mjs +4 -3
  530. package/dist/db/index.mjs.map +1 -1
  531. package/dist/db/libsql-migrations.d.mts +1 -1
  532. package/dist/db/libsql-migrations.mjs +7 -6
  533. package/dist/db/libsql-migrations.mjs.map +1 -1
  534. package/dist/db/libsql.d.mts +1 -1
  535. package/dist/db/postgres-migrations.d.mts +1 -1
  536. package/dist/db/postgres-migrations.mjs +7 -6
  537. package/dist/db/postgres-migrations.mjs.map +1 -1
  538. package/dist/db/postgres.d.mts +1 -1
  539. package/dist/db/sqlite-migrations.d.mts +1 -1
  540. package/dist/db/sqlite-migrations.mjs +7 -6
  541. package/dist/db/sqlite-migrations.mjs.map +1 -1
  542. package/dist/db/sqlite.d.mts +1 -1
  543. package/dist/db/sqlite.mjs +1 -1
  544. package/dist/db-errors-CBD5yMro.mjs +55 -0
  545. package/dist/db-errors-CBD5yMro.mjs.map +1 -0
  546. package/dist/default-BtlxWgh9.mjs +81 -0
  547. package/dist/default-BtlxWgh9.mjs.map +1 -0
  548. package/dist/deferred-tasks-Ba9fphlE.d.mts +9 -0
  549. package/dist/deferred-tasks-Ba9fphlE.d.mts.map +1 -0
  550. package/dist/dev-typegen-CZaPLl3V.mjs +29 -0
  551. package/dist/dev-typegen-CZaPLl3V.mjs.map +1 -0
  552. package/dist/device-flow-3E5l0fpH.mjs +466 -0
  553. package/dist/device-flow-3E5l0fpH.mjs.map +1 -0
  554. package/dist/dialect-helpers-CtYdsX4W.mjs +307 -0
  555. package/dist/dialect-helpers-CtYdsX4W.mjs.map +1 -0
  556. package/dist/direct-executor-ZI8E01Yt.mjs +104 -0
  557. package/dist/direct-executor-ZI8E01Yt.mjs.map +1 -0
  558. package/dist/dist-2hDLsLeq.mjs +810 -0
  559. package/dist/dist-2hDLsLeq.mjs.map +1 -0
  560. package/dist/email-console-gc-E3Eqj.mjs +50 -0
  561. package/dist/email-console-gc-E3Eqj.mjs.map +1 -0
  562. package/dist/emdash-runtime-DZGinqTL.mjs +4041 -0
  563. package/dist/emdash-runtime-DZGinqTL.mjs.map +1 -0
  564. package/dist/enrich-C2Mk0lwE.mjs +194 -0
  565. package/dist/enrich-C2Mk0lwE.mjs.map +1 -0
  566. package/dist/entry-lock-D3C99MXS.mjs +1520 -0
  567. package/dist/entry-lock-D3C99MXS.mjs.map +1 -0
  568. package/dist/entry-lock-D9rnj2Lu.mjs +163 -0
  569. package/dist/entry-lock-D9rnj2Lu.mjs.map +1 -0
  570. package/dist/entry-lock-DX7QkqEg.d.mts +3503 -0
  571. package/dist/entry-lock-DX7QkqEg.d.mts.map +1 -0
  572. package/dist/entry-locks-CO_KaoU5.mjs +167 -0
  573. package/dist/entry-locks-CO_KaoU5.mjs.map +1 -0
  574. package/dist/error-CCTCskie.mjs +90 -0
  575. package/dist/error-CCTCskie.mjs.map +1 -0
  576. package/dist/errors-W3PA8HqB.mjs +447 -0
  577. package/dist/errors-W3PA8HqB.mjs.map +1 -0
  578. package/dist/escape-DN4Qmjsl.mjs +9 -0
  579. package/dist/escape-DN4Qmjsl.mjs.map +1 -0
  580. package/dist/field-defs-cache-B337z8UJ.mjs +77 -0
  581. package/dist/field-defs-cache-B337z8UJ.mjs.map +1 -0
  582. package/dist/focal-point-Gr34o-4o.mjs +23 -0
  583. package/dist/focal-point-Gr34o-4o.mjs.map +1 -0
  584. package/dist/fts-manager-DMb0sbIQ.mjs +413 -0
  585. package/dist/fts-manager-DMb0sbIQ.mjs.map +1 -0
  586. package/dist/hash-CLVFzWvx.mjs +37 -0
  587. package/dist/hash-CLVFzWvx.mjs.map +1 -0
  588. package/dist/hook-result-KY1jq21o.d.mts +31 -0
  589. package/dist/hook-result-KY1jq21o.d.mts.map +1 -0
  590. package/dist/hreflang-BgS2FqhH.d.mts +50 -0
  591. package/dist/hreflang-BgS2FqhH.d.mts.map +1 -0
  592. package/dist/hreflang-CrJwqoeb.mjs +105 -0
  593. package/dist/hreflang-CrJwqoeb.mjs.map +1 -0
  594. package/dist/http-route-dispatch-DAKlanXb.mjs +339 -0
  595. package/dist/http-route-dispatch-DAKlanXb.mjs.map +1 -0
  596. package/dist/identity-DRGSHEEr.mjs +35 -0
  597. package/dist/identity-DRGSHEEr.mjs.map +1 -0
  598. package/dist/import-DFr5B_hC.mjs +2020 -0
  599. package/dist/import-DFr5B_hC.mjs.map +1 -0
  600. package/dist/index-CDwKDkTq.d.mts +623 -0
  601. package/dist/index-CDwKDkTq.d.mts.map +1 -0
  602. package/dist/index.d.mts +27 -22
  603. package/dist/index.mjs +101 -86
  604. package/dist/init-lock-4eRRB4Le.mjs +56 -0
  605. package/dist/init-lock-4eRRB4Le.mjs.map +1 -0
  606. package/dist/install-finalization-5Os-QZ-2.mjs +58 -0
  607. package/dist/install-finalization-5Os-QZ-2.mjs.map +1 -0
  608. package/dist/lifecycle-7e-Lt_kX.mjs +25 -0
  609. package/dist/lifecycle-7e-Lt_kX.mjs.map +1 -0
  610. package/dist/load-Cu5bvCZh.mjs +28 -0
  611. package/dist/load-Cu5bvCZh.mjs.map +1 -0
  612. package/dist/loader-t4TxaFiQ.mjs +1004 -0
  613. package/dist/loader-t4TxaFiQ.mjs.map +1 -0
  614. package/dist/manifest-builder-D31UoJCu.mjs +189 -0
  615. package/dist/manifest-builder-D31UoJCu.mjs.map +1 -0
  616. package/dist/manifest-schema-Bkh8SeHd.mjs +491 -0
  617. package/dist/manifest-schema-Bkh8SeHd.mjs.map +1 -0
  618. package/dist/media/image-endpoint.mjs +1 -1
  619. package/dist/media/index.d.mts +1 -1
  620. package/dist/media/index.mjs +4 -4
  621. package/dist/media/local-runtime.d.mts +14 -12
  622. package/dist/media/local-runtime.d.mts.map +1 -1
  623. package/dist/media/local-runtime.mjs +12 -11
  624. package/dist/media/local-runtime.mjs.map +1 -1
  625. package/dist/media-TBlKCwo7.mjs +334 -0
  626. package/dist/media-TBlKCwo7.mjs.map +1 -0
  627. package/dist/media-allowlist-s60eAIf6.mjs +44 -0
  628. package/dist/media-allowlist-s60eAIf6.mjs.map +1 -0
  629. package/dist/media-folders-ClIRLUQv.mjs +210 -0
  630. package/dist/media-folders-ClIRLUQv.mjs.map +1 -0
  631. package/dist/media-url-DY_ijO3B.mjs +43 -0
  632. package/dist/media-url-DY_ijO3B.mjs.map +1 -0
  633. package/dist/media-usage-C4NolTpQ.mjs +1833 -0
  634. package/dist/media-usage-C4NolTpQ.mjs.map +1 -0
  635. package/dist/media-usage-activation-CAhmb14O.mjs +78 -0
  636. package/dist/media-usage-activation-CAhmb14O.mjs.map +1 -0
  637. package/dist/media-usage-work-Cu5DqewW.mjs +586 -0
  638. package/dist/media-usage-work-Cu5DqewW.mjs.map +1 -0
  639. package/dist/media-usage-work-DJr3rOEN.mjs +152 -0
  640. package/dist/media-usage-work-DJr3rOEN.mjs.map +1 -0
  641. package/dist/media-usage-write-fence-DW5oHT7q.mjs +42 -0
  642. package/dist/media-usage-write-fence-DW5oHT7q.mjs.map +1 -0
  643. package/dist/menus-DbgU9z5Q.mjs +3732 -0
  644. package/dist/menus-DbgU9z5Q.mjs.map +1 -0
  645. package/dist/menus-Wy8m5NcH.mjs +753 -0
  646. package/dist/menus-Wy8m5NcH.mjs.map +1 -0
  647. package/dist/migrations/index.d.mts +2 -2
  648. package/dist/migrations/index.d.mts.map +1 -1
  649. package/dist/migrations/index.mjs +6 -5
  650. package/dist/mime-CCYRC4r1.mjs +36 -0
  651. package/dist/mime-CCYRC4r1.mjs.map +1 -0
  652. package/dist/mode-CkmOhFqj.mjs +23 -0
  653. package/dist/mode-CkmOhFqj.mjs.map +1 -0
  654. package/dist/node-sqlite-compat-vpVaILnb.mjs +46 -0
  655. package/dist/node-sqlite-compat-vpVaILnb.mjs.map +1 -0
  656. package/dist/normalize-dChXQjwS.mjs +191 -0
  657. package/dist/normalize-dChXQjwS.mjs.map +1 -0
  658. package/dist/oauth-authorization-DZ-R-hmx.mjs +274 -0
  659. package/dist/oauth-authorization-DZ-R-hmx.mjs.map +1 -0
  660. package/dist/oauth-clients-BMPA8vjl.mjs +266 -0
  661. package/dist/oauth-clients-BMPA8vjl.mjs.map +1 -0
  662. package/dist/oauth-state-store-0gIdb48-.mjs +50 -0
  663. package/dist/oauth-state-store-0gIdb48-.mjs.map +1 -0
  664. package/dist/oauth-user-lookup-ChVW4UWu.mjs +26 -0
  665. package/dist/oauth-user-lookup-ChVW4UWu.mjs.map +1 -0
  666. package/dist/object-cache/memory.d.mts +1 -1
  667. package/dist/object-cache-DlSVbn5Y.mjs +534 -0
  668. package/dist/object-cache-DlSVbn5Y.mjs.map +1 -0
  669. package/dist/options-D5WcorD5.mjs +200 -0
  670. package/dist/options-D5WcorD5.mjs.map +1 -0
  671. package/dist/options-DAknChnw.d.mts +77 -0
  672. package/dist/options-DAknChnw.d.mts.map +1 -0
  673. package/dist/page/index.d.mts +2 -2
  674. package/dist/page/index.d.mts.map +1 -1
  675. package/dist/page/index.mjs +13 -0
  676. package/dist/page/index.mjs.map +1 -1
  677. package/dist/parse-Cr379Av9.mjs +81 -0
  678. package/dist/parse-Cr379Av9.mjs.map +1 -0
  679. package/dist/parse-tj9XLNO_.d.mts +165 -0
  680. package/dist/parse-tj9XLNO_.d.mts.map +1 -0
  681. package/dist/passkey-config-BD-wMaCf.mjs +46 -0
  682. package/dist/passkey-config-BD-wMaCf.mjs.map +1 -0
  683. package/dist/patterns-Do3iqi7N.mjs +145 -0
  684. package/dist/patterns-Do3iqi7N.mjs.map +1 -0
  685. package/dist/placeholder-CubPFn_L.d.mts +306 -0
  686. package/dist/placeholder-CubPFn_L.d.mts.map +1 -0
  687. package/dist/plugin-test-runtime.d.mts +97 -0
  688. package/dist/plugin-test-runtime.d.mts.map +1 -0
  689. package/dist/plugin-test-runtime.mjs +105 -0
  690. package/dist/plugin-types.d.mts +53 -15
  691. package/dist/plugin-types.d.mts.map +1 -1
  692. package/dist/plugin-types.mjs +18 -1
  693. package/dist/plugin-types.mjs.map +1 -0
  694. package/dist/plugin-utils.d.mts +12 -10
  695. package/dist/plugin-utils.d.mts.map +1 -1
  696. package/dist/plugins/adapt-sandbox-entry.d.mts +12 -10
  697. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  698. package/dist/plugins/adapt-sandbox-entry.mjs +18 -13
  699. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  700. package/dist/plugins/host.d.mts +7 -0
  701. package/dist/plugins/host.mjs +45 -0
  702. package/dist/plugins/http-wire.d.mts +25 -0
  703. package/dist/plugins/http-wire.d.mts.map +1 -0
  704. package/dist/plugins/http-wire.mjs +148 -0
  705. package/dist/plugins/http-wire.mjs.map +1 -0
  706. package/dist/plugins/secret-redactor.d.mts +9 -0
  707. package/dist/plugins/secret-redactor.d.mts.map +1 -0
  708. package/dist/plugins/secret-redactor.mjs +51 -0
  709. package/dist/plugins/secret-redactor.mjs.map +1 -0
  710. package/dist/plugins-DHurtdXQ.mjs +277 -0
  711. package/dist/plugins-DHurtdXQ.mjs.map +1 -0
  712. package/dist/policy-lyZnjpwz.mjs +45 -0
  713. package/dist/policy-lyZnjpwz.mjs.map +1 -0
  714. package/dist/portable-text-oAwodbPS.mjs +286 -0
  715. package/dist/portable-text-oAwodbPS.mjs.map +1 -0
  716. package/dist/preview-Cup2bj8c.mjs +107 -0
  717. package/dist/preview-Cup2bj8c.mjs.map +1 -0
  718. package/dist/protocol-C1CNiKX4.d.mts +61 -0
  719. package/dist/protocol-C1CNiKX4.d.mts.map +1 -0
  720. package/dist/public-submission-Cs-pFMQK.mjs +245 -0
  721. package/dist/public-submission-Cs-pFMQK.mjs.map +1 -0
  722. package/dist/public-url-BWVHsfQv.mjs +101 -0
  723. package/dist/public-url-BWVHsfQv.mjs.map +1 -0
  724. package/dist/query-D-lxiOgn.mjs +890 -0
  725. package/dist/query-D-lxiOgn.mjs.map +1 -0
  726. package/dist/query-D7kHKOws.mjs +41 -0
  727. package/dist/query-D7kHKOws.mjs.map +1 -0
  728. package/dist/rate-limit-CqJn-w4h.mjs +120 -0
  729. package/dist/rate-limit-CqJn-w4h.mjs.map +1 -0
  730. package/dist/redirect-BrChFPIu.mjs +17 -0
  731. package/dist/redirect-BrChFPIu.mjs.map +1 -0
  732. package/dist/redirect-D2Yo-b6S.mjs +415 -0
  733. package/dist/redirect-D2Yo-b6S.mjs.map +1 -0
  734. package/dist/redirects-BCiTaIQ-.mjs +146 -0
  735. package/dist/redirects-BCiTaIQ-.mjs.map +1 -0
  736. package/dist/redirects-ByItliuu.mjs +644 -0
  737. package/dist/redirects-ByItliuu.mjs.map +1 -0
  738. package/dist/registry/testing.d.mts +14 -0
  739. package/dist/registry/testing.d.mts.map +1 -0
  740. package/dist/registry/testing.mjs +255 -0
  741. package/dist/registry/testing.mjs.map +1 -0
  742. package/dist/registry-CkuPoZs7.mjs +1222 -0
  743. package/dist/registry-CkuPoZs7.mjs.map +1 -0
  744. package/dist/relation-XTAtOpJO.mjs +334 -0
  745. package/dist/relation-XTAtOpJO.mjs.map +1 -0
  746. package/dist/relations-B4w-G5U9.mjs +309 -0
  747. package/dist/relations-B4w-G5U9.mjs.map +1 -0
  748. package/dist/relations-O63JWBRj.mjs +403 -0
  749. package/dist/relations-O63JWBRj.mjs.map +1 -0
  750. package/dist/request-cache-DaMhSQdx.mjs +104 -0
  751. package/dist/request-cache-DaMhSQdx.mjs.map +1 -0
  752. package/dist/request-context.d.mts +1 -1
  753. package/dist/request-meta-C8yl_sIs.mjs +141 -0
  754. package/dist/request-meta-C8yl_sIs.mjs.map +1 -0
  755. package/dist/resolve-BJIS8wKr.mjs +199 -0
  756. package/dist/resolve-BJIS8wKr.mjs.map +1 -0
  757. package/dist/route-wire-D66L2oaZ.mjs +197 -0
  758. package/dist/route-wire-D66L2oaZ.mjs.map +1 -0
  759. package/dist/routes-DYsTe-oR.mjs +321 -0
  760. package/dist/routes-DYsTe-oR.mjs.map +1 -0
  761. package/dist/runner-3gfxRsJG.d.mts +68 -0
  762. package/dist/runner-3gfxRsJG.d.mts.map +1 -0
  763. package/dist/runner-ClrleR8A.mjs +5502 -0
  764. package/dist/runner-ClrleR8A.mjs.map +1 -0
  765. package/dist/runtime.d.mts +13 -11
  766. package/dist/runtime.d.mts.map +1 -1
  767. package/dist/runtime.mjs +6 -5
  768. package/dist/runtime.mjs.map +1 -1
  769. package/dist/schema-CPhPM9Do.mjs +420 -0
  770. package/dist/schema-CPhPM9Do.mjs.map +1 -0
  771. package/dist/schema-DEERRrKS.mjs +9 -0
  772. package/dist/schema-DEERRrKS.mjs.map +1 -0
  773. package/dist/scopes-Bn8_rCSt.mjs +27 -0
  774. package/dist/scopes-Bn8_rCSt.mjs.map +1 -0
  775. package/dist/search-lami_Ota.mjs +448 -0
  776. package/dist/search-lami_Ota.mjs.map +1 -0
  777. package/dist/secrets-DNgVgz_e.mjs +341 -0
  778. package/dist/secrets-DNgVgz_e.mjs.map +1 -0
  779. package/dist/sections-BIpd4Cxf.mjs +346 -0
  780. package/dist/sections-BIpd4Cxf.mjs.map +1 -0
  781. package/dist/seed/index.d.mts +2 -2
  782. package/dist/seed/index.mjs +35 -31
  783. package/dist/seo/index.d.mts +3 -3
  784. package/dist/seo/index.d.mts.map +1 -1
  785. package/dist/seo/index.mjs +27 -26
  786. package/dist/seo/index.mjs.map +1 -1
  787. package/dist/seo-BtU70b7l.mjs +114 -0
  788. package/dist/seo-BtU70b7l.mjs.map +1 -0
  789. package/dist/seo-_4qmazxz.mjs +133 -0
  790. package/dist/seo-_4qmazxz.mjs.map +1 -0
  791. package/dist/service-Bpy5iTX0.mjs +150 -0
  792. package/dist/service-Bpy5iTX0.mjs.map +1 -0
  793. package/dist/session-user-BQeS2Mrb.mjs +51 -0
  794. package/dist/session-user-BQeS2Mrb.mjs.map +1 -0
  795. package/dist/settings-DmroR53o.mjs +420 -0
  796. package/dist/settings-DmroR53o.mjs.map +1 -0
  797. package/dist/settings-g2F2a3Ub.mjs +51 -0
  798. package/dist/settings-g2F2a3Ub.mjs.map +1 -0
  799. package/dist/setup-complete-BrZaXpVV.mjs +26 -0
  800. package/dist/setup-complete-BrZaXpVV.mjs.map +1 -0
  801. package/dist/setup-nonce-Cb9-884O.mjs +25 -0
  802. package/dist/setup-nonce-Cb9-884O.mjs.map +1 -0
  803. package/dist/single-flight-cache-B5O2qhO1.mjs +104 -0
  804. package/dist/single-flight-cache-B5O2qhO1.mjs.map +1 -0
  805. package/dist/site-url-DjhYCaep.mjs +16 -0
  806. package/dist/site-url-DjhYCaep.mjs.map +1 -0
  807. package/dist/slugify-T5GHH42D.mjs +17 -0
  808. package/dist/slugify-T5GHH42D.mjs.map +1 -0
  809. package/dist/snapshot-C32Xuv3o.mjs +233 -0
  810. package/dist/snapshot-C32Xuv3o.mjs.map +1 -0
  811. package/dist/ssrf-Co1GGFZz.mjs +406 -0
  812. package/dist/ssrf-Co1GGFZz.mjs.map +1 -0
  813. package/dist/state-C7gCoiHr.mjs +153 -0
  814. package/dist/state-C7gCoiHr.mjs.map +1 -0
  815. package/dist/status-DLoBmcDz.mjs +30 -0
  816. package/dist/status-DLoBmcDz.mjs.map +1 -0
  817. package/dist/storage/local.d.mts +1 -1
  818. package/dist/storage/local.mjs +1 -1
  819. package/dist/storage/s3.d.mts +1 -1
  820. package/dist/storage/s3.mjs +1 -1
  821. package/dist/storage-query-CPctdMKX.d.mts +1519 -0
  822. package/dist/storage-query-CPctdMKX.d.mts.map +1 -0
  823. package/dist/target-CUKlGrXb.mjs +27 -0
  824. package/dist/target-CUKlGrXb.mjs.map +1 -0
  825. package/dist/taxonomies-BpqpXJUE.mjs +707 -0
  826. package/dist/taxonomies-BpqpXJUE.mjs.map +1 -0
  827. package/dist/taxonomies-ClCo4IGO.mjs +899 -0
  828. package/dist/taxonomies-ClCo4IGO.mjs.map +1 -0
  829. package/dist/taxonomy-Dj1vpw5E.mjs +508 -0
  830. package/dist/taxonomy-Dj1vpw5E.mjs.map +1 -0
  831. package/dist/tokens-Ns02GAma.mjs +171 -0
  832. package/dist/tokens-Ns02GAma.mjs.map +1 -0
  833. package/dist/transaction-BcJO4Tmc.mjs +29 -0
  834. package/dist/transaction-BcJO4Tmc.mjs.map +1 -0
  835. package/dist/transport-B8P1xsqk.mjs +136 -0
  836. package/dist/transport-B8P1xsqk.mjs.map +1 -0
  837. package/dist/transport-BLHZZcD_.d.mts +42 -0
  838. package/dist/transport-BLHZZcD_.d.mts.map +1 -0
  839. package/dist/trusted-proxy-Cg7SuD15.mjs +51 -0
  840. package/dist/trusted-proxy-Cg7SuD15.mjs.map +1 -0
  841. package/dist/turnstile-DWCSh_Qc.mjs +53 -0
  842. package/dist/turnstile-DWCSh_Qc.mjs.map +1 -0
  843. package/dist/types-B3RkqvDW.mjs +156 -0
  844. package/dist/types-B3RkqvDW.mjs.map +1 -0
  845. package/dist/types-BkUg2yHx.mjs +92 -0
  846. package/dist/types-BkUg2yHx.mjs.map +1 -0
  847. package/dist/types-BtuppOTV.mjs +16 -0
  848. package/dist/types-BtuppOTV.mjs.map +1 -0
  849. package/dist/types-CCR3ivXE.d.mts +363 -0
  850. package/dist/types-CCR3ivXE.d.mts.map +1 -0
  851. package/dist/types-CSHgU_-_.mjs +18 -0
  852. package/dist/types-CSHgU_-_.mjs.map +1 -0
  853. package/dist/types-CbwqGOXm.d.mts +766 -0
  854. package/dist/types-CbwqGOXm.d.mts.map +1 -0
  855. package/dist/types-D4RGIc2I.d.mts +198 -0
  856. package/dist/types-D4RGIc2I.d.mts.map +1 -0
  857. package/dist/types-DEHidMEk.d.mts +1637 -0
  858. package/dist/types-DEHidMEk.d.mts.map +1 -0
  859. package/dist/types-DQeU2SR7.d.mts +279 -0
  860. package/dist/types-DQeU2SR7.d.mts.map +1 -0
  861. package/dist/types-DxQWoQLA.d.mts +264 -0
  862. package/dist/types-DxQWoQLA.d.mts.map +1 -0
  863. package/dist/types-FBBnGZ2Y.d.mts +198 -0
  864. package/dist/types-FBBnGZ2Y.d.mts.map +1 -0
  865. package/dist/types-ZCnlropY.mjs +69 -0
  866. package/dist/types-ZCnlropY.mjs.map +1 -0
  867. package/dist/types-_Qtyawiy.d.mts +124 -0
  868. package/dist/types-_Qtyawiy.d.mts.map +1 -0
  869. package/dist/types-gC6FAoa_.d.mts +75 -0
  870. package/dist/types-gC6FAoa_.d.mts.map +1 -0
  871. package/dist/types-k--LneIF.mjs +22 -0
  872. package/dist/types-k--LneIF.mjs.map +1 -0
  873. package/dist/upload-attempts-2xdnoKGe.mjs +27 -0
  874. package/dist/upload-attempts-2xdnoKGe.mjs.map +1 -0
  875. package/dist/url-pattern-3m3reMzr.mjs +33 -0
  876. package/dist/url-pattern-3m3reMzr.mjs.map +1 -0
  877. package/dist/user-DroRntkx.mjs +171 -0
  878. package/dist/user-DroRntkx.mjs.map +1 -0
  879. package/dist/utils-CC2oNGV8.mjs +435 -0
  880. package/dist/utils-CC2oNGV8.mjs.map +1 -0
  881. package/dist/validate-BCP9HNDn.mjs +384 -0
  882. package/dist/validate-BCP9HNDn.mjs.map +1 -0
  883. package/dist/validate-CyQ7I3xF.d.mts +410 -0
  884. package/dist/validate-CyQ7I3xF.d.mts.map +1 -0
  885. package/dist/validate-DANX1-Qi.mjs +120 -0
  886. package/dist/validate-DANX1-Qi.mjs.map +1 -0
  887. package/dist/validation-DBy6WF94.mjs +216 -0
  888. package/dist/validation-DBy6WF94.mjs.map +1 -0
  889. package/dist/version-B57E4Uo7.mjs +7 -0
  890. package/dist/version-B57E4Uo7.mjs.map +1 -0
  891. package/dist/widgets-wQ7Xcgq8.mjs +126 -0
  892. package/dist/widgets-wQ7Xcgq8.mjs.map +1 -0
  893. package/dist/wxr-taxonomies-DIHfvEDt.mjs +406 -0
  894. package/dist/wxr-taxonomies-DIHfvEDt.mjs.map +1 -0
  895. package/dist/wxr-taxonomies-DU2ZSiGc.d.mts +34 -0
  896. package/dist/wxr-taxonomies-DU2ZSiGc.d.mts.map +1 -0
  897. package/dist/zod-generator-D_yHIWfs.mjs +329 -0
  898. package/dist/zod-generator-D_yHIWfs.mjs.map +1 -0
  899. package/package.json +39 -12
  900. package/src/api/errors.ts +23 -0
  901. package/src/api/handlers/backup.ts +11 -5
  902. package/src/api/handlers/content.ts +226 -85
  903. package/src/api/handlers/dashboard.ts +31 -1
  904. package/src/api/handlers/entry-lock.ts +206 -0
  905. package/src/api/handlers/index.ts +3 -0
  906. package/src/api/handlers/manifest.ts +5 -6
  907. package/src/api/handlers/marketplace.ts +126 -34
  908. package/src/api/handlers/media-upload.ts +31 -4
  909. package/src/api/handlers/menus.ts +9 -0
  910. package/src/api/handlers/plugin-settings.ts +35 -3
  911. package/src/api/handlers/redirects.ts +221 -138
  912. package/src/api/handlers/registry.ts +75 -29
  913. package/src/api/handlers/revision.ts +16 -27
  914. package/src/api/handlers/seo.ts +10 -1
  915. package/src/api/handlers/snapshot.ts +87 -72
  916. package/src/api/handlers/taxonomies.ts +79 -5
  917. package/src/api/handlers/validation.ts +120 -19
  918. package/src/api/openapi/document.ts +133 -11
  919. package/src/api/schemas/content.ts +32 -12
  920. package/src/api/schemas/entry-lock.ts +57 -0
  921. package/src/api/schemas/index.ts +1 -0
  922. package/src/api/schemas/schema.ts +10 -1
  923. package/src/api/schemas/search.ts +4 -0
  924. package/src/api/types.ts +4 -0
  925. package/src/astro/integration/index.ts +22 -6
  926. package/src/astro/integration/routes.ts +89 -0
  927. package/src/astro/integration/runtime.ts +40 -24
  928. package/src/astro/integration/virtual-modules.ts +4 -0
  929. package/src/astro/integration/vite-config.ts +31 -0
  930. package/src/astro/middleware/auth.ts +25 -4
  931. package/src/astro/middleware/request-context.ts +28 -10
  932. package/src/astro/middleware.ts +33 -1
  933. package/src/astro/prefetch.ts +2 -2
  934. package/src/astro/routes/api/admin/comments/[id]/status.ts +22 -58
  935. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +2 -15
  936. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +2 -25
  937. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +1 -0
  938. package/src/astro/routes/api/admin/plugins/[id]/update.ts +23 -4
  939. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +12 -2
  940. package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +1 -0
  941. package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +29 -10
  942. package/src/astro/routes/api/admin/plugins/registry/artifact.ts +8 -2
  943. package/src/astro/routes/api/admin/plugins/registry/install.ts +15 -4
  944. package/src/astro/routes/api/admin/plugins/registry/verify.ts +2 -1
  945. package/src/astro/routes/api/admin/plugins/updates.ts +6 -1
  946. package/src/astro/routes/api/admin/scheduled-policy-rejections/[collection]/[id].ts +34 -0
  947. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +4 -259
  948. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +10 -0
  949. package/src/astro/routes/api/content/[collection]/[id]/lock.ts +133 -0
  950. package/src/astro/routes/api/content/[collection]/[id]/plugin-extensions/[pluginId]/[kind]/[extensionId].ts +29 -0
  951. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +21 -4
  952. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +30 -1
  953. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +15 -1
  954. package/src/astro/routes/api/content/[collection]/[id].ts +27 -2
  955. package/src/astro/routes/api/content/[collection]/index.ts +3 -0
  956. package/src/astro/routes/api/health.ts +23 -0
  957. package/src/astro/routes/api/manifest.ts +14 -4
  958. package/src/astro/routes/api/mcp.ts +2 -1
  959. package/src/astro/routes/api/media/asset/[id]/[filename].ts +50 -0
  960. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +13 -81
  961. package/src/astro/routes/api/redirects/[id].ts +0 -3
  962. package/src/astro/routes/api/redirects/index.ts +0 -2
  963. package/src/astro/routes/api/search/index.ts +1 -0
  964. package/src/astro/routes/api/visual-editing/action-token.ts +36 -0
  965. package/src/astro/routes/api/visual-editing/content/[collection]/[id]/publish.ts +32 -0
  966. package/src/astro/routes/api/visual-editing/toolbar-labels.ts +16 -0
  967. package/src/astro/routes/sitemap-[collection].xml.ts +11 -4
  968. package/src/astro/types.ts +83 -12
  969. package/src/cli/commands/bundle-utils.ts +19 -19
  970. package/src/cli/commands/bundle.ts +9 -6
  971. package/src/cli/commands/content.ts +32 -6
  972. package/src/cli/commands/doctor.ts +25 -0
  973. package/src/cli/commands/export-seed.ts +195 -56
  974. package/src/cli/commands/migrate.ts +71 -23
  975. package/src/cli/commands/publish.ts +2 -2
  976. package/src/client/index.ts +34 -7
  977. package/src/comments/public-submission.ts +246 -0
  978. package/src/comments/service.ts +59 -12
  979. package/src/components/EmDashBodyEnd.astro +4 -1
  980. package/src/components/EmDashBodyStart.astro +4 -1
  981. package/src/components/EmDashHead.astro +36 -16
  982. package/src/components/Gallery.astro +18 -4
  983. package/src/components/InlineEditor.astro +3 -1
  984. package/src/components/InlinePortableTextEditor.tsx +106 -11
  985. package/src/components/PortableText.astro +4 -0
  986. package/src/components/Table.astro +147 -62
  987. package/src/components/widgets/Archives.astro +6 -5
  988. package/src/config/errors.ts +13 -0
  989. package/src/config/secrets.ts +25 -11
  990. package/src/content/converters/portable-text-to-prosemirror.ts +26 -2
  991. package/src/content/converters/prosemirror-to-portable-text.ts +35 -6
  992. package/src/content/converters/types.ts +10 -0
  993. package/src/content/known-fields.ts +44 -0
  994. package/src/database/connection.ts +5 -1
  995. package/src/database/content-datetime.ts +123 -0
  996. package/src/database/datetime-storage.ts +452 -0
  997. package/src/database/dialect-helpers.ts +161 -1
  998. package/src/database/migration-lock.ts +140 -0
  999. package/src/database/migrations/075_entry_edit_locks.ts +44 -0
  1000. package/src/database/migrations/076_collection_nav_group.ts +22 -0
  1001. package/src/database/migrations/077_plugin_storage_revisions.ts +89 -0
  1002. package/src/database/migrations/078_menu_item_translation_groups.ts +15 -0
  1003. package/src/database/migrations/079_datetime_normalization.ts +13 -0
  1004. package/src/database/migrations/080_content_translation_locale_unique.ts +88 -0
  1005. package/src/database/migrations/081_redirect_write_guards.ts +257 -0
  1006. package/src/database/migrations/082_taxonomy_translation_locale_unique.ts +49 -0
  1007. package/src/database/migrations/runner.ts +63 -15
  1008. package/src/database/pg-migration-lock.ts +2 -2
  1009. package/src/database/repositories/byline.ts +9 -0
  1010. package/src/database/repositories/comment.ts +86 -0
  1011. package/src/database/repositories/content.ts +560 -69
  1012. package/src/database/repositories/entry-locks.ts +257 -0
  1013. package/src/database/repositories/media.ts +35 -4
  1014. package/src/database/repositories/menu.ts +1 -0
  1015. package/src/database/repositories/options.ts +113 -7
  1016. package/src/database/repositories/plugin-storage.ts +159 -0
  1017. package/src/database/repositories/redirect.ts +262 -56
  1018. package/src/database/repositories/revision.ts +116 -17
  1019. package/src/database/repositories/taxonomy.ts +42 -0
  1020. package/src/database/repositories/types.ts +5 -0
  1021. package/src/database/types.ts +26 -1
  1022. package/src/datetime-normalization.ts +311 -0
  1023. package/src/db/node-sqlite-compat.ts +3 -2
  1024. package/src/emdash-runtime.ts +1994 -424
  1025. package/src/fields/image.ts +2 -0
  1026. package/src/i18n/config.ts +6 -6
  1027. package/src/i18n/resolve.ts +98 -15
  1028. package/src/index.ts +101 -0
  1029. package/src/loader.ts +49 -4
  1030. package/src/mcp/server.ts +216 -68
  1031. package/src/media/responsive.ts +23 -0
  1032. package/src/media/usage/content-refresh.ts +2 -1
  1033. package/src/media/usage/extractor.ts +50 -15
  1034. package/src/media/usage/types.ts +1 -1
  1035. package/src/menus/index.ts +64 -35
  1036. package/src/migrations/direct-executor.ts +40 -2
  1037. package/src/migrations/index.ts +1 -0
  1038. package/src/migrations/protocol.ts +11 -1
  1039. package/src/page/seo-contributions.ts +78 -1
  1040. package/src/page/seo-panel.ts +47 -0
  1041. package/src/plugin-test-runtime.ts +17 -0
  1042. package/src/plugin-types.ts +128 -21
  1043. package/src/plugins/adapt-sandbox-entry.ts +34 -27
  1044. package/src/plugins/conditional-storage.ts +30 -0
  1045. package/src/plugins/content-access.ts +170 -0
  1046. package/src/plugins/content-policy.ts +74 -0
  1047. package/src/plugins/context.ts +790 -166
  1048. package/src/plugins/cron.ts +18 -10
  1049. package/src/plugins/define-plugin.ts +55 -54
  1050. package/src/plugins/editor-draft.ts +257 -0
  1051. package/src/plugins/hooks.ts +136 -3
  1052. package/src/plugins/host.ts +29 -0
  1053. package/src/plugins/http-route-dispatch.ts +389 -0
  1054. package/src/plugins/http-wire.ts +180 -0
  1055. package/src/plugins/index.ts +97 -3
  1056. package/src/plugins/install-finalization.ts +77 -0
  1057. package/src/plugins/lifecycle.ts +47 -0
  1058. package/src/plugins/manager.ts +5 -2
  1059. package/src/plugins/manifest-schema.ts +314 -58
  1060. package/src/plugins/media.ts +166 -0
  1061. package/src/plugins/request-meta.ts +12 -2
  1062. package/src/plugins/route-wire.ts +304 -0
  1063. package/src/plugins/routes.ts +38 -5
  1064. package/src/plugins/sandbox/index.ts +4 -0
  1065. package/src/plugins/sandbox/proxy.ts +129 -0
  1066. package/src/plugins/sandbox/types.ts +83 -7
  1067. package/src/plugins/secret-redactor.ts +65 -0
  1068. package/src/plugins/settings.ts +303 -0
  1069. package/src/plugins/state.ts +26 -0
  1070. package/src/plugins/storage-query.ts +45 -0
  1071. package/src/plugins/storage-update.ts +96 -0
  1072. package/src/plugins/types.ts +602 -15
  1073. package/src/query.ts +84 -4
  1074. package/src/registry/authoritative-records.ts +26 -0
  1075. package/src/registry/config.ts +182 -31
  1076. package/src/registry/testing.ts +100 -0
  1077. package/src/registry/types.ts +12 -70
  1078. package/src/scheduled-publish.ts +70 -3
  1079. package/src/schema/collection-slugs-cache.ts +157 -0
  1080. package/src/schema/index.ts +1 -0
  1081. package/src/schema/registry.ts +64 -1
  1082. package/src/schema/types.ts +32 -6
  1083. package/src/schema/zod-generator.ts +5 -13
  1084. package/src/search/fts-manager.ts +3 -3
  1085. package/src/search/query.ts +32 -5
  1086. package/src/search/types.ts +8 -0
  1087. package/src/security/ssrf.ts +167 -141
  1088. package/src/seed/apply.ts +41 -3
  1089. package/src/seed/types.ts +13 -3
  1090. package/src/seed/validate.ts +18 -1
  1091. package/src/seo/hreflang.ts +10 -6
  1092. package/src/seo/index.ts +5 -10
  1093. package/src/seo/media-url.ts +26 -0
  1094. package/src/settings/index.ts +53 -11
  1095. package/src/taxonomies/term-counts.ts +22 -5
  1096. package/src/visual-editing/action-token.ts +31 -0
  1097. package/src/visual-editing/toolbar-bootstrap.ts +31 -6
  1098. package/src/visual-editing/toolbar.ts +103 -12
  1099. package/src/widgets/archives.ts +10 -9
  1100. package/src/widgets/index.ts +11 -1
  1101. package/dist/activation-K0kGBWuJ.mjs +0 -382
  1102. package/dist/activation-K0kGBWuJ.mjs.map +0 -1
  1103. package/dist/adapters-BDQwg236.d.mts +0 -171
  1104. package/dist/adapters-BDQwg236.d.mts.map +0 -1
  1105. package/dist/after-CBU2vkoO.mjs +0 -96
  1106. package/dist/after-CBU2vkoO.mjs.map +0 -1
  1107. package/dist/allowed-origins-BGglilcs.mjs +0 -116
  1108. package/dist/allowed-origins-BGglilcs.mjs.map +0 -1
  1109. package/dist/api-Dz6rgoa3.mjs +0 -10040
  1110. package/dist/api-Dz6rgoa3.mjs.map +0 -1
  1111. package/dist/api-tokens-BSsQACNe.mjs +0 -163
  1112. package/dist/api-tokens-BSsQACNe.mjs.map +0 -1
  1113. package/dist/apply-B4SIOxR1.mjs +0 -980
  1114. package/dist/apply-B4SIOxR1.mjs.map +0 -1
  1115. package/dist/authorize-Bkf_UHhD.mjs +0 -40
  1116. package/dist/authorize-Bkf_UHhD.mjs.map +0 -1
  1117. package/dist/backup-rwVAl9NI.mjs +0 -241
  1118. package/dist/backup-rwVAl9NI.mjs.map +0 -1
  1119. package/dist/base64-CvLhUKQv.mjs +0 -63
  1120. package/dist/base64-CvLhUKQv.mjs.map +0 -1
  1121. package/dist/bundle-C8S2Zl6U.mjs +0 -663
  1122. package/dist/bundle-C8S2Zl6U.mjs.map +0 -1
  1123. package/dist/byline-DuhF7NWl.mjs +0 -902
  1124. package/dist/byline-DuhF7NWl.mjs.map +0 -1
  1125. package/dist/byline-fields-BovY4KYM.mjs +0 -123
  1126. package/dist/byline-fields-BovY4KYM.mjs.map +0 -1
  1127. package/dist/byline-registry-Bpu9-MVs.mjs +0 -406
  1128. package/dist/byline-registry-Bpu9-MVs.mjs.map +0 -1
  1129. package/dist/bylines-CJ5nd6Lw.mjs +0 -232
  1130. package/dist/bylines-CJ5nd6Lw.mjs.map +0 -1
  1131. package/dist/bylines-RwBAeOF1.mjs +0 -214
  1132. package/dist/bylines-RwBAeOF1.mjs.map +0 -1
  1133. package/dist/cache-BF5Kvn59.mjs +0 -108
  1134. package/dist/cache-BF5Kvn59.mjs.map +0 -1
  1135. package/dist/capture-triggers-CNW1q3HK.mjs +0 -362
  1136. package/dist/capture-triggers-CNW1q3HK.mjs.map +0 -1
  1137. package/dist/challenge-store-DQN_Yrck.mjs +0 -51
  1138. package/dist/challenge-store-DQN_Yrck.mjs.map +0 -1
  1139. package/dist/chrome-tags-D8fiZG94.mjs +0 -24
  1140. package/dist/chrome-tags-D8fiZG94.mjs.map +0 -1
  1141. package/dist/chunks-C4szrD8o.mjs +0 -25
  1142. package/dist/chunks-C4szrD8o.mjs.map +0 -1
  1143. package/dist/collection-deletion-Bj07NHbj.mjs +0 -436
  1144. package/dist/collection-deletion-Bj07NHbj.mjs.map +0 -1
  1145. package/dist/comment-reaction-BhrvSHml.mjs +0 -85
  1146. package/dist/comment-reaction-BhrvSHml.mjs.map +0 -1
  1147. package/dist/comment-vxOzWbZN.mjs +0 -255
  1148. package/dist/comment-vxOzWbZN.mjs.map +0 -1
  1149. package/dist/comments-Ct4ensnf.mjs +0 -204
  1150. package/dist/comments-Ct4ensnf.mjs.map +0 -1
  1151. package/dist/components-DJbo1z0S.mjs +0 -108
  1152. package/dist/components-DJbo1z0S.mjs.map +0 -1
  1153. package/dist/config-B9eZ340f.d.mts +0 -34
  1154. package/dist/config-B9eZ340f.d.mts.map +0 -1
  1155. package/dist/config-C3EBstHi.mjs +0 -72
  1156. package/dist/config-C3EBstHi.mjs.map +0 -1
  1157. package/dist/config-it29yDLA.mjs +0 -1163
  1158. package/dist/config-it29yDLA.mjs.map +0 -1
  1159. package/dist/content-DjvM0T92.mjs +0 -1725
  1160. package/dist/content-DjvM0T92.mjs.map +0 -1
  1161. package/dist/content-list-query-Btqd4uV2.d.mts +0 -26
  1162. package/dist/content-list-query-Btqd4uV2.d.mts.map +0 -1
  1163. package/dist/content-refresh-Bwp-8yGy.mjs +0 -3588
  1164. package/dist/content-refresh-Bwp-8yGy.mjs.map +0 -1
  1165. package/dist/content-repair-Czdp7jz5.mjs +0 -440
  1166. package/dist/content-repair-Czdp7jz5.mjs.map +0 -1
  1167. package/dist/context-CX6gxOLW.mjs +0 -1068
  1168. package/dist/context-CX6gxOLW.mjs.map +0 -1
  1169. package/dist/cron-C6o7VppJ.mjs +0 -277
  1170. package/dist/cron-C6o7VppJ.mjs.map +0 -1
  1171. package/dist/dashboard-C2kTeeRI.mjs +0 -140
  1172. package/dist/dashboard-C2kTeeRI.mjs.map +0 -1
  1173. package/dist/db-errors-Cl-sKYTm.mjs +0 -55
  1174. package/dist/db-errors-Cl-sKYTm.mjs.map +0 -1
  1175. package/dist/default-Clra32mw.mjs +0 -81
  1176. package/dist/default-Clra32mw.mjs.map +0 -1
  1177. package/dist/deferred-tasks-CvDETTJO.d.mts +0 -9
  1178. package/dist/deferred-tasks-CvDETTJO.d.mts.map +0 -1
  1179. package/dist/dev-typegen-DzOPfsNj.mjs +0 -29
  1180. package/dist/dev-typegen-DzOPfsNj.mjs.map +0 -1
  1181. package/dist/device-flow-D2oCWvLJ.mjs +0 -466
  1182. package/dist/device-flow-D2oCWvLJ.mjs.map +0 -1
  1183. package/dist/dialect-helpers-BSbfaO3F.mjs +0 -202
  1184. package/dist/dialect-helpers-BSbfaO3F.mjs.map +0 -1
  1185. package/dist/direct-executor-Bfa5_ToE.mjs +0 -85
  1186. package/dist/direct-executor-Bfa5_ToE.mjs.map +0 -1
  1187. package/dist/dist-89xCrGqi.mjs +0 -810
  1188. package/dist/dist-89xCrGqi.mjs.map +0 -1
  1189. package/dist/email-console-Dzb6uGYa.mjs +0 -50
  1190. package/dist/email-console-Dzb6uGYa.mjs.map +0 -1
  1191. package/dist/enrich-BX0IDp4z.mjs +0 -194
  1192. package/dist/enrich-BX0IDp4z.mjs.map +0 -1
  1193. package/dist/error-DFrQjppn.mjs +0 -90
  1194. package/dist/error-DFrQjppn.mjs.map +0 -1
  1195. package/dist/errors-DsVoDUjJ.mjs +0 -427
  1196. package/dist/errors-DsVoDUjJ.mjs.map +0 -1
  1197. package/dist/escape-HmHTC1Is.mjs +0 -9
  1198. package/dist/escape-HmHTC1Is.mjs.map +0 -1
  1199. package/dist/field-defs-cache-BM4SIRqH.mjs +0 -77
  1200. package/dist/field-defs-cache-BM4SIRqH.mjs.map +0 -1
  1201. package/dist/focal-point-BeWFo6Xx.mjs +0 -23
  1202. package/dist/focal-point-BeWFo6Xx.mjs.map +0 -1
  1203. package/dist/fts-manager-Do1BlW2r.mjs +0 -413
  1204. package/dist/fts-manager-Do1BlW2r.mjs.map +0 -1
  1205. package/dist/hash-3JJPlHF2.mjs +0 -37
  1206. package/dist/hash-3JJPlHF2.mjs.map +0 -1
  1207. package/dist/hook-result-DCh2WUpe.d.mts +0 -31
  1208. package/dist/hook-result-DCh2WUpe.d.mts.map +0 -1
  1209. package/dist/hreflang-B6hbAuuO.d.mts +0 -48
  1210. package/dist/hreflang-B6hbAuuO.d.mts.map +0 -1
  1211. package/dist/hreflang-DQbPZliA.mjs +0 -102
  1212. package/dist/hreflang-DQbPZliA.mjs.map +0 -1
  1213. package/dist/identity-DksvEazf.mjs +0 -35
  1214. package/dist/identity-DksvEazf.mjs.map +0 -1
  1215. package/dist/import-CJpaBBBT.mjs +0 -2020
  1216. package/dist/import-CJpaBBBT.mjs.map +0 -1
  1217. package/dist/index-BJNMCWmu.d.mts +0 -6562
  1218. package/dist/index-BJNMCWmu.d.mts.map +0 -1
  1219. package/dist/index-Du8K7bWa.d.mts +0 -278
  1220. package/dist/index-Du8K7bWa.d.mts.map +0 -1
  1221. package/dist/init-lock-DJkX6Hto.mjs +0 -56
  1222. package/dist/init-lock-DJkX6Hto.mjs.map +0 -1
  1223. package/dist/load-CawHjTOH.mjs +0 -28
  1224. package/dist/load-CawHjTOH.mjs.map +0 -1
  1225. package/dist/loader-Z8vl7zTq.mjs +0 -966
  1226. package/dist/loader-Z8vl7zTq.mjs.map +0 -1
  1227. package/dist/manifest-builder-COtzuca2.mjs +0 -189
  1228. package/dist/manifest-builder-COtzuca2.mjs.map +0 -1
  1229. package/dist/manifest-schema-BNWwR8Vd.mjs +0 -301
  1230. package/dist/manifest-schema-BNWwR8Vd.mjs.map +0 -1
  1231. package/dist/media-BBm8Wg3f.mjs +0 -318
  1232. package/dist/media-BBm8Wg3f.mjs.map +0 -1
  1233. package/dist/media-BHjus86Y.mjs +0 -464
  1234. package/dist/media-BHjus86Y.mjs.map +0 -1
  1235. package/dist/media-allowlist-CoTBWoDp.mjs +0 -44
  1236. package/dist/media-allowlist-CoTBWoDp.mjs.map +0 -1
  1237. package/dist/media-folders-BGkATs8n.mjs +0 -210
  1238. package/dist/media-folders-BGkATs8n.mjs.map +0 -1
  1239. package/dist/media-upload-BCidR-EY.mjs +0 -147
  1240. package/dist/media-upload-BCidR-EY.mjs.map +0 -1
  1241. package/dist/media-url-DHoPr0hq.mjs +0 -26
  1242. package/dist/media-url-DHoPr0hq.mjs.map +0 -1
  1243. package/dist/media-usage-CdY5jhSR.mjs +0 -1833
  1244. package/dist/media-usage-CdY5jhSR.mjs.map +0 -1
  1245. package/dist/media-usage-activation-BgeMtK5C.mjs +0 -78
  1246. package/dist/media-usage-activation-BgeMtK5C.mjs.map +0 -1
  1247. package/dist/media-usage-work-CnGCdHxx.mjs +0 -152
  1248. package/dist/media-usage-work-CnGCdHxx.mjs.map +0 -1
  1249. package/dist/media-usage-work-D6D9sMCA.mjs +0 -586
  1250. package/dist/media-usage-work-D6D9sMCA.mjs.map +0 -1
  1251. package/dist/media-usage-write-fence-hjeD4u7s.mjs +0 -42
  1252. package/dist/media-usage-write-fence-hjeD4u7s.mjs.map +0 -1
  1253. package/dist/menus-6qSwTNxG.mjs +0 -4010
  1254. package/dist/menus-6qSwTNxG.mjs.map +0 -1
  1255. package/dist/menus-uvPLXMZf.mjs +0 -744
  1256. package/dist/menus-uvPLXMZf.mjs.map +0 -1
  1257. package/dist/mime-CUIG6x84.mjs +0 -36
  1258. package/dist/mime-CUIG6x84.mjs.map +0 -1
  1259. package/dist/mode-DN_WneRx.mjs +0 -23
  1260. package/dist/mode-DN_WneRx.mjs.map +0 -1
  1261. package/dist/node-sqlite-compat-BuJXIeMz.mjs +0 -46
  1262. package/dist/node-sqlite-compat-BuJXIeMz.mjs.map +0 -1
  1263. package/dist/normalize-C2xNjTSG.mjs +0 -191
  1264. package/dist/normalize-C2xNjTSG.mjs.map +0 -1
  1265. package/dist/oauth-authorization-Dj6Kwc21.mjs +0 -274
  1266. package/dist/oauth-authorization-Dj6Kwc21.mjs.map +0 -1
  1267. package/dist/oauth-clients-FD7I0J8m.mjs +0 -266
  1268. package/dist/oauth-clients-FD7I0J8m.mjs.map +0 -1
  1269. package/dist/oauth-state-store-DkmDOmHs.mjs +0 -50
  1270. package/dist/oauth-state-store-DkmDOmHs.mjs.map +0 -1
  1271. package/dist/oauth-user-lookup-CvIwGpYd.mjs +0 -26
  1272. package/dist/oauth-user-lookup-CvIwGpYd.mjs.map +0 -1
  1273. package/dist/object-cache-DVKnyOfy.mjs +0 -534
  1274. package/dist/object-cache-DVKnyOfy.mjs.map +0 -1
  1275. package/dist/options-BHPeIbBd.mjs +0 -117
  1276. package/dist/options-BHPeIbBd.mjs.map +0 -1
  1277. package/dist/options-CYb4y7hM.d.mts +0 -221
  1278. package/dist/options-CYb4y7hM.d.mts.map +0 -1
  1279. package/dist/parse-Ckpg-Qfp.mjs +0 -81
  1280. package/dist/parse-Ckpg-Qfp.mjs.map +0 -1
  1281. package/dist/passkey-config-O_lj3y0k.mjs +0 -46
  1282. package/dist/passkey-config-O_lj3y0k.mjs.map +0 -1
  1283. package/dist/patterns-D9iDO3j8.mjs +0 -145
  1284. package/dist/patterns-D9iDO3j8.mjs.map +0 -1
  1285. package/dist/placeholder-4X9BrRrp.d.mts +0 -306
  1286. package/dist/placeholder-4X9BrRrp.d.mts.map +0 -1
  1287. package/dist/policy-Dhtwntrt.mjs +0 -45
  1288. package/dist/policy-Dhtwntrt.mjs.map +0 -1
  1289. package/dist/portable-text-U85hOafW.mjs +0 -286
  1290. package/dist/portable-text-U85hOafW.mjs.map +0 -1
  1291. package/dist/preview-B_vJLvf8.mjs +0 -107
  1292. package/dist/preview-B_vJLvf8.mjs.map +0 -1
  1293. package/dist/protocol-JdD2YhY9.d.mts +0 -52
  1294. package/dist/protocol-JdD2YhY9.d.mts.map +0 -1
  1295. package/dist/public-url-CarhZJgf.mjs +0 -101
  1296. package/dist/public-url-CarhZJgf.mjs.map +0 -1
  1297. package/dist/query-BZKZcG5b.mjs +0 -881
  1298. package/dist/query-BZKZcG5b.mjs.map +0 -1
  1299. package/dist/query-BndaFxxp.mjs +0 -41
  1300. package/dist/query-BndaFxxp.mjs.map +0 -1
  1301. package/dist/rate-limit-BZmATC6W.mjs +0 -120
  1302. package/dist/rate-limit-BZmATC6W.mjs.map +0 -1
  1303. package/dist/redirect-CZkbozu9.mjs +0 -313
  1304. package/dist/redirect-CZkbozu9.mjs.map +0 -1
  1305. package/dist/redirect-CzqnLxK-.mjs +0 -17
  1306. package/dist/redirect-CzqnLxK-.mjs.map +0 -1
  1307. package/dist/redirects-BLNOWQTn.mjs +0 -1238
  1308. package/dist/redirects-BLNOWQTn.mjs.map +0 -1
  1309. package/dist/redirects-CqzNM0KM.mjs +0 -579
  1310. package/dist/redirects-CqzNM0KM.mjs.map +0 -1
  1311. package/dist/registry-AZAsRsor.mjs +0 -1179
  1312. package/dist/registry-AZAsRsor.mjs.map +0 -1
  1313. package/dist/relation-04DfKRTO.mjs +0 -334
  1314. package/dist/relation-04DfKRTO.mjs.map +0 -1
  1315. package/dist/relations-C4htk5sb.mjs +0 -309
  1316. package/dist/relations-C4htk5sb.mjs.map +0 -1
  1317. package/dist/relations-CcFwDJdJ.mjs +0 -403
  1318. package/dist/relations-CcFwDJdJ.mjs.map +0 -1
  1319. package/dist/relations-DnRK4YIT.d.mts +0 -3354
  1320. package/dist/relations-DnRK4YIT.d.mts.map +0 -1
  1321. package/dist/request-cache-DH9zdCOD.mjs +0 -104
  1322. package/dist/request-cache-DH9zdCOD.mjs.map +0 -1
  1323. package/dist/request-meta-DYxLlnmz.mjs +0 -140
  1324. package/dist/request-meta-DYxLlnmz.mjs.map +0 -1
  1325. package/dist/resolve-prZ3mP7l.mjs +0 -143
  1326. package/dist/resolve-prZ3mP7l.mjs.map +0 -1
  1327. package/dist/runner-BLIDKpmA.mjs +0 -4676
  1328. package/dist/runner-BLIDKpmA.mjs.map +0 -1
  1329. package/dist/runner-YKfIMnaF.d.mts +0 -67
  1330. package/dist/runner-YKfIMnaF.d.mts.map +0 -1
  1331. package/dist/schema-CGnBeLiW.mjs +0 -9
  1332. package/dist/schema-CGnBeLiW.mjs.map +0 -1
  1333. package/dist/schema-DYr-Vd-L.mjs +0 -420
  1334. package/dist/schema-DYr-Vd-L.mjs.map +0 -1
  1335. package/dist/scopes-BhWvBavj.mjs +0 -27
  1336. package/dist/scopes-BhWvBavj.mjs.map +0 -1
  1337. package/dist/search-C-qDk4kx.mjs +0 -439
  1338. package/dist/search-C-qDk4kx.mjs.map +0 -1
  1339. package/dist/secrets-rEtHt-6z.mjs +0 -330
  1340. package/dist/secrets-rEtHt-6z.mjs.map +0 -1
  1341. package/dist/sections-B_nYvlwn.mjs +0 -346
  1342. package/dist/sections-B_nYvlwn.mjs.map +0 -1
  1343. package/dist/seo-926NRIgt.mjs +0 -133
  1344. package/dist/seo-926NRIgt.mjs.map +0 -1
  1345. package/dist/seo-CVWkdv6x.mjs +0 -113
  1346. package/dist/seo-CVWkdv6x.mjs.map +0 -1
  1347. package/dist/service-CJl3ZAYs.mjs +0 -195
  1348. package/dist/service-CJl3ZAYs.mjs.map +0 -1
  1349. package/dist/session-user-BlMgqCHS.mjs +0 -51
  1350. package/dist/session-user-BlMgqCHS.mjs.map +0 -1
  1351. package/dist/settings--wobrkkC.mjs +0 -258
  1352. package/dist/settings--wobrkkC.mjs.map +0 -1
  1353. package/dist/settings-Cwm6o2jY.mjs +0 -51
  1354. package/dist/settings-Cwm6o2jY.mjs.map +0 -1
  1355. package/dist/setup-complete-DQbClIN2.mjs +0 -26
  1356. package/dist/setup-complete-DQbClIN2.mjs.map +0 -1
  1357. package/dist/setup-nonce-DZCFS2sn.mjs +0 -25
  1358. package/dist/setup-nonce-DZCFS2sn.mjs.map +0 -1
  1359. package/dist/single-flight-cache-BPuGPdcN.mjs +0 -104
  1360. package/dist/single-flight-cache-BPuGPdcN.mjs.map +0 -1
  1361. package/dist/site-url-BrxA_E9H.mjs +0 -16
  1362. package/dist/site-url-BrxA_E9H.mjs.map +0 -1
  1363. package/dist/slugify-B994zkXC.mjs +0 -17
  1364. package/dist/slugify-B994zkXC.mjs.map +0 -1
  1365. package/dist/snapshot--OCDTqdb.mjs +0 -216
  1366. package/dist/snapshot--OCDTqdb.mjs.map +0 -1
  1367. package/dist/ssrf-5sIM5jzl.mjs +0 -349
  1368. package/dist/ssrf-5sIM5jzl.mjs.map +0 -1
  1369. package/dist/state-BpFVsJZB.mjs +0 -136
  1370. package/dist/state-BpFVsJZB.mjs.map +0 -1
  1371. package/dist/status-B777-dXz.mjs +0 -30
  1372. package/dist/status-B777-dXz.mjs.map +0 -1
  1373. package/dist/target-BmR0iTwz.mjs +0 -27
  1374. package/dist/target-BmR0iTwz.mjs.map +0 -1
  1375. package/dist/taxonomies-DkAkMupr.mjs +0 -837
  1376. package/dist/taxonomies-DkAkMupr.mjs.map +0 -1
  1377. package/dist/taxonomies-Wfy_Lg12.mjs +0 -698
  1378. package/dist/taxonomies-Wfy_Lg12.mjs.map +0 -1
  1379. package/dist/taxonomy-tJepplLL.mjs +0 -484
  1380. package/dist/taxonomy-tJepplLL.mjs.map +0 -1
  1381. package/dist/tokens-BCO1oruF.mjs +0 -171
  1382. package/dist/tokens-BCO1oruF.mjs.map +0 -1
  1383. package/dist/transaction-0KOpOyMu.mjs +0 -29
  1384. package/dist/transaction-0KOpOyMu.mjs.map +0 -1
  1385. package/dist/transport-Dr3qtwXC.mjs +0 -136
  1386. package/dist/transport-Dr3qtwXC.mjs.map +0 -1
  1387. package/dist/transport-xh6YKW2G.d.mts +0 -42
  1388. package/dist/transport-xh6YKW2G.d.mts.map +0 -1
  1389. package/dist/trusted-proxy-BR5F1Otp.mjs +0 -51
  1390. package/dist/trusted-proxy-BR5F1Otp.mjs.map +0 -1
  1391. package/dist/types-3qNFPlci.mjs +0 -16
  1392. package/dist/types-3qNFPlci.mjs.map +0 -1
  1393. package/dist/types-75KIqzL9.mjs +0 -142
  1394. package/dist/types-75KIqzL9.mjs.map +0 -1
  1395. package/dist/types-B6GrPic4.d.mts +0 -1335
  1396. package/dist/types-B6GrPic4.d.mts.map +0 -1
  1397. package/dist/types-BuHW4xDE.d.mts +0 -259
  1398. package/dist/types-BuHW4xDE.d.mts.map +0 -1
  1399. package/dist/types-C00oyCZp.d.mts +0 -198
  1400. package/dist/types-C00oyCZp.d.mts.map +0 -1
  1401. package/dist/types-CDtkNSFQ.d.mts +0 -75
  1402. package/dist/types-CDtkNSFQ.d.mts.map +0 -1
  1403. package/dist/types-CPeXo1wF.d.mts +0 -124
  1404. package/dist/types-CPeXo1wF.d.mts.map +0 -1
  1405. package/dist/types-CQPWhPxE.mjs +0 -92
  1406. package/dist/types-CQPWhPxE.mjs.map +0 -1
  1407. package/dist/types-CXFkwEGC.d.mts +0 -198
  1408. package/dist/types-CXFkwEGC.d.mts.map +0 -1
  1409. package/dist/types-DM3vioBY.mjs +0 -18
  1410. package/dist/types-DM3vioBY.mjs.map +0 -1
  1411. package/dist/types-DczELMop.d.mts +0 -363
  1412. package/dist/types-DczELMop.d.mts.map +0 -1
  1413. package/dist/types-DfuTR6dL.mjs +0 -3
  1414. package/dist/types-FV23hEoW.d.mts +0 -743
  1415. package/dist/types-FV23hEoW.d.mts.map +0 -1
  1416. package/dist/types-xDMtUFnO.d.mts +0 -257
  1417. package/dist/types-xDMtUFnO.d.mts.map +0 -1
  1418. package/dist/upload-attempts-BsqoQ1fn.mjs +0 -27
  1419. package/dist/upload-attempts-BsqoQ1fn.mjs.map +0 -1
  1420. package/dist/url-pattern-D4c2czpJ.mjs +0 -33
  1421. package/dist/url-pattern-D4c2czpJ.mjs.map +0 -1
  1422. package/dist/user-BTZ40aq6.mjs +0 -171
  1423. package/dist/user-BTZ40aq6.mjs.map +0 -1
  1424. package/dist/utils-BKvNjjhY.mjs +0 -435
  1425. package/dist/utils-BKvNjjhY.mjs.map +0 -1
  1426. package/dist/validate-BpwoDOgt.mjs +0 -120
  1427. package/dist/validate-BpwoDOgt.mjs.map +0 -1
  1428. package/dist/validate-DE_LRwo9.mjs +0 -379
  1429. package/dist/validate-DE_LRwo9.mjs.map +0 -1
  1430. package/dist/validate-DUP27OYD.d.mts +0 -400
  1431. package/dist/validate-DUP27OYD.d.mts.map +0 -1
  1432. package/dist/validation-BMImFJ11.mjs +0 -153
  1433. package/dist/validation-BMImFJ11.mjs.map +0 -1
  1434. package/dist/version-Bii3suaO.mjs +0 -7
  1435. package/dist/version-Bii3suaO.mjs.map +0 -1
  1436. package/dist/widgets-D3gJ10xU.mjs +0 -122
  1437. package/dist/widgets-D3gJ10xU.mjs.map +0 -1
  1438. package/dist/wxr-taxonomies-B2Og_6rU.d.mts +0 -34
  1439. package/dist/wxr-taxonomies-B2Og_6rU.d.mts.map +0 -1
  1440. package/dist/wxr-taxonomies-Cxngsjwo.mjs +0 -406
  1441. package/dist/wxr-taxonomies-Cxngsjwo.mjs.map +0 -1
  1442. package/dist/zod-generator-BuYSQJB7.mjs +0 -331
  1443. package/dist/zod-generator-BuYSQJB7.mjs.map +0 -1
  1444. /package/dist/{api-tokens-BfYts-sq.mjs → api-tokens-DS1VzN7_.mjs} +0 -0
  1445. /package/dist/{ssrf-Dg3cIT-b.mjs → ssrf-BRpTDMV6.mjs} +0 -0
@@ -8,16 +8,31 @@
8
8
  import type { Kysely } from "kysely";
9
9
  import { ulid } from "ulidx";
10
10
 
11
+ import {
12
+ handleRedirectCreate,
13
+ handleRedirectDelete,
14
+ handleRedirectList,
15
+ handleRedirectUpdate,
16
+ } from "../api/handlers/redirects.js";
17
+ import { handleTermCreate } from "../api/handlers/taxonomies.js";
18
+ import { createRedirectBody, updateRedirectBody } from "../api/schemas/redirects.js";
19
+ import { CommentRepository, type Comment } from "../database/repositories/comment.js";
11
20
  import { ContentRepository } from "../database/repositories/content.js";
21
+ import { EntryLockRepository } from "../database/repositories/entry-locks.js";
12
22
  import { MediaRepository } from "../database/repositories/media.js";
13
23
  import { OptionsRepository } from "../database/repositories/options.js";
14
24
  import { PluginStorageRepository } from "../database/repositories/plugin-storage.js";
25
+ import {
26
+ RedirectRepository,
27
+ type Redirect,
28
+ type VersionedRedirectRecord,
29
+ } from "../database/repositories/redirect.js";
15
30
  import { SeoRepository } from "../database/repositories/seo.js";
16
31
  import { TaxonomyRepository, type Taxonomy } from "../database/repositories/taxonomy.js";
17
32
  import { UserRepository } from "../database/repositories/user.js";
18
33
  import { withTransaction } from "../database/transaction.js";
19
34
  import type { Database } from "../database/types.js";
20
- import { resolveContentCreateLocale } from "../i18n/config.js";
35
+ import { getI18nConfig, resolveContentCreateLocale } from "../i18n/config.js";
21
36
  import {
22
37
  resolveAndValidateExternalUrl,
23
38
  SsrfError,
@@ -25,20 +40,38 @@ import {
25
40
  } from "../import/ssrf.js";
26
41
  import { enrichImageMetadata } from "../media/enrich.js";
27
42
  import { markContentMediaUsageCollectionStaleSafely } from "../media/usage/content-refresh.js";
43
+ import { SchemaRegistry } from "../schema/registry.js";
28
44
  import { invalidateSiteSettingsCache } from "../settings/index.js";
29
45
  import type { Storage } from "../storage/types.js";
46
+ import { assertStorageKey } from "./conditional-storage.js";
47
+ import { createContentAccess } from "./content-access.js";
30
48
  import { CronAccessImpl } from "./cron.js";
31
49
  import type { EmailPipeline } from "./email.js";
50
+ import {
51
+ bufferPluginHttpRequest,
52
+ pluginHttpRedirectAction,
53
+ pluginHttpResponseFromWire,
54
+ pluginHttpResponseToWire,
55
+ rewritePluginHttpRedirect,
56
+ } from "./http-wire.js";
57
+ import { readPluginMediaBytes, toPluginMediaItem, updatePluginMediaMetadata } from "./media.js";
58
+ import {
59
+ createPluginSecretRedactor,
60
+ createSettingsAccess,
61
+ type PluginSecretRedactor,
62
+ } from "./settings.js";
32
63
  import type {
33
64
  ResolvedPlugin,
34
65
  PluginContext,
35
66
  PluginStorageConfig,
36
67
  StorageCollection,
37
68
  KVAccess,
69
+ SettingsAccess,
38
70
  CronAccess,
39
71
  EmailAccess,
40
72
  ContentAccess,
41
73
  ContentAccessWithWrite,
74
+ VersionedContentItem,
42
75
  MediaAccess,
43
76
  MediaAccessWithWrite,
44
77
  HttpAccess,
@@ -53,14 +86,32 @@ import type {
53
86
  MediaItem,
54
87
  PaginatedResult,
55
88
  QueryOptions,
56
- ContentListOptions,
57
89
  MediaListOptions,
58
90
  TaxonomyAccess,
91
+ TaxonomyAccessWithWrite,
59
92
  TaxonomyDefInfo,
60
93
  TaxonomyTermInfo,
94
+ TaxonomyTermCreateInput,
61
95
  TaxonomyReadOptions,
96
+ CommentAccess,
97
+ CommentListOptions,
98
+ PluginComment,
99
+ PluginCommentStatus,
100
+ RedirectAccess,
101
+ RedirectAccessWithWrite,
102
+ RedirectCreateInput,
103
+ RedirectInfo,
104
+ RedirectListOptions,
105
+ RedirectStatus,
106
+ RedirectUpdateInput,
107
+ VersionedRedirect,
108
+ SchemaAccess,
109
+ CollectionSchemaInfo,
110
+ PluginContentCreateCallback,
62
111
  } from "./types.js";
63
112
 
113
+ export { createContentAccess } from "./content-access.js";
114
+
64
115
  // =============================================================================
65
116
  // KV Access
66
117
  // =============================================================================
@@ -69,32 +120,76 @@ import type {
69
120
  * Create KV accessor for a plugin
70
121
  * All keys are automatically prefixed with the plugin ID
71
122
  */
72
- export function createKVAccess(optionsRepo: OptionsRepository, pluginId: string): KVAccess {
123
+ export function createKVAccess(
124
+ optionsRepo: OptionsRepository,
125
+ pluginId: string,
126
+ settings: SettingsAccess = createSettingsAccess(optionsRepo, pluginId),
127
+ ): KVAccess {
73
128
  const prefix = `plugin:${pluginId}:`;
74
129
 
75
130
  return {
76
131
  async get<T>(key: string): Promise<T | null> {
132
+ if (key.startsWith("settings:")) return settings.get<T>(key.slice("settings:".length));
77
133
  return optionsRepo.get<T>(`${prefix}${key}`);
78
134
  },
135
+ async getVersioned<T>(key: string) {
136
+ assertStorageKey(key);
137
+ if (key.startsWith("settings:")) {
138
+ return settings.getVersioned<T>(key.slice("settings:".length));
139
+ }
140
+ return optionsRepo.getVersioned<T>(`${prefix}${key}`);
141
+ },
142
+ async compareAndSet(key, expectedRevision, value) {
143
+ assertStorageKey(key);
144
+ if (key.startsWith("settings:")) {
145
+ return settings.compareAndSet(key.slice("settings:".length), expectedRevision, value);
146
+ }
147
+ return optionsRepo.compareAndSet(`${prefix}${key}`, expectedRevision, value);
148
+ },
149
+ async compareAndDelete(key, expectedRevision) {
150
+ assertStorageKey(key);
151
+ if (key.startsWith("settings:")) {
152
+ return settings.compareAndDelete(key.slice("settings:".length), expectedRevision);
153
+ }
154
+ return optionsRepo.compareAndDelete(`${prefix}${key}`, expectedRevision);
155
+ },
79
156
 
80
157
  async set(key: string, value: unknown): Promise<void> {
158
+ if (key.startsWith("settings:")) {
159
+ await settings.set(key.slice("settings:".length), value);
160
+ return;
161
+ }
81
162
  await optionsRepo.set(`${prefix}${key}`, value);
82
163
  },
83
164
 
84
165
  async delete(key: string): Promise<boolean> {
166
+ if (key.startsWith("settings:")) return settings.delete(key.slice("settings:".length));
85
167
  return optionsRepo.delete(`${prefix}${key}`);
86
168
  },
87
169
 
88
170
  async list(keyPrefix?: string): Promise<Array<{ key: string; value: unknown }>> {
89
- const fullPrefix = `${prefix}${keyPrefix ?? ""}`;
171
+ const requestedPrefix = keyPrefix ?? "";
172
+ const includesSettings =
173
+ "settings:".startsWith(requestedPrefix) || requestedPrefix.startsWith("settings:");
174
+ const fullPrefix = `${prefix}${requestedPrefix}`;
90
175
  const entriesMap = await optionsRepo.getByPrefix(fullPrefix);
91
176
  const result: Array<{ key: string; value: unknown }> = [];
92
177
  for (const [fullKey, value] of entriesMap) {
178
+ if (includesSettings && fullKey.startsWith(`${prefix}settings:`)) continue;
93
179
  result.push({
94
180
  key: fullKey.slice(prefix.length),
95
181
  value,
96
182
  });
97
183
  }
184
+ if (includesSettings) {
185
+ const settingPrefix = requestedPrefix.startsWith("settings:")
186
+ ? requestedPrefix.slice("settings:".length)
187
+ : "";
188
+ for (const entry of await settings.list(settingPrefix)) {
189
+ const key = `settings:${entry.key}`;
190
+ if (key.startsWith(requestedPrefix)) result.push({ key, value: entry.value });
191
+ }
192
+ }
98
193
  return result;
99
194
  },
100
195
  };
@@ -118,6 +213,9 @@ function createStorageCollection<T>(
118
213
 
119
214
  return {
120
215
  get: (id) => repo.get(id),
216
+ getVersioned: (id) => repo.getVersioned(id),
217
+ compareAndSet: (id, expectedRevision, data) => repo.compareAndSet(id, expectedRevision, data),
218
+ compareAndDelete: (id, expectedRevision) => repo.compareAndDelete(id, expectedRevision),
121
219
  put: (id, data) => repo.put(id, data),
122
220
  delete: (id) => repo.delete(id),
123
221
  exists: (id) => repo.exists(id),
@@ -125,6 +223,7 @@ function createStorageCollection<T>(
125
223
  putMany: (items) => repo.putMany(items),
126
224
  deleteMany: (ids) => repo.deleteMany(ids),
127
225
  count: (where) => repo.count(where),
226
+ updateIf: (id, updateArgs) => repo.updateIf(id, updateArgs),
128
227
 
129
228
  // Query returns PaginatedResult instead of the old format
130
229
  async query(options?: QueryOptions): Promise<PaginatedResult<{ id: string; data: T }>> {
@@ -232,88 +331,53 @@ function taxonomyToTermInfo(term: Taxonomy): TaxonomyTermInfo {
232
331
  };
233
332
  }
234
333
 
235
- /**
236
- * Create read-only content access
237
- */
238
- export function createContentAccess(db: Kysely<Database>): ContentAccess {
239
- const contentRepo = new ContentRepository(db);
240
- const seoRepo = new SeoRepository(db);
241
-
334
+ function collectionToSchemaInfo(
335
+ collection: Awaited<ReturnType<SchemaRegistry["getCollectionWithFields"]>>,
336
+ ): CollectionSchemaInfo | null {
337
+ if (!collection) return null;
242
338
  return {
243
- async get(collection: string, id: string): Promise<ContentItem | null> {
244
- const item = await contentRepo.findById(collection, id);
245
- if (!item) return null;
246
-
247
- const result: ContentItem = {
248
- id: item.id,
249
- type: item.type,
250
- slug: item.slug,
251
- status: item.status,
252
- data: item.data,
253
- createdAt: item.createdAt,
254
- updatedAt: item.updatedAt,
255
- locale: item.locale,
256
- publishedAt: item.publishedAt,
257
- scheduledAt: item.scheduledAt,
258
- };
339
+ slug: collection.slug,
340
+ label: collection.label,
341
+ labelSingular: collection.labelSingular ?? null,
342
+ description: collection.description ?? null,
343
+ supports: collection.supports,
344
+ hasSeo: collection.hasSeo,
345
+ titleField: collection.titleField ?? null,
346
+ dateField: collection.dateField ?? null,
347
+ urlPattern: collection.urlPattern ?? null,
348
+ routable: collection.routable !== false,
349
+ hidden: collection.hidden,
350
+ fields: collection.fields.map((field) => ({
351
+ slug: field.slug,
352
+ label: field.label,
353
+ type: field.type,
354
+ required: field.required,
355
+ unique: field.unique,
356
+ ...(field.defaultValue === undefined ? {} : { default: field.defaultValue }),
357
+ ...(field.validation === undefined ? {} : { validation: field.validation }),
358
+ ...(field.widget === undefined ? {} : { widget: field.widget }),
359
+ ...(field.options === undefined ? {} : { options: field.options }),
360
+ searchable: field.searchable,
361
+ indexed: field.indexed,
362
+ translatable: field.translatable,
363
+ sortOrder: field.sortOrder,
364
+ })),
365
+ };
366
+ }
259
367
 
260
- if (await seoRepo.isEnabled(collection)) {
261
- result.seo = await seoRepo.get(collection, item.id);
368
+ export function createSchemaAccess(db: Kysely<Database>): SchemaAccess {
369
+ const registry = new SchemaRegistry(db);
370
+ return {
371
+ async listCollections() {
372
+ const collections: CollectionSchemaInfo[] = [];
373
+ for (const collection of await registry.listCollectionsWithFields()) {
374
+ const info = collectionToSchemaInfo(collection);
375
+ if (info) collections.push(info);
262
376
  }
263
-
264
- return result;
377
+ return collections;
265
378
  },
266
-
267
- async list(
268
- collection: string,
269
- options?: ContentListOptions,
270
- ): Promise<PaginatedResult<ContentItem>> {
271
- // Convert orderBy format if provided
272
- let orderBy: { field: string; direction: "asc" | "desc" } | undefined;
273
- if (options?.orderBy) {
274
- const entries = Object.entries(options.orderBy);
275
- const first = entries[0];
276
- if (first) {
277
- orderBy = { field: first[0], direction: first[1] };
278
- }
279
- }
280
-
281
- const result = await contentRepo.findMany(collection, {
282
- limit: options?.limit ?? 50,
283
- cursor: options?.cursor,
284
- orderBy,
285
- where: options?.where,
286
- });
287
-
288
- const items: ContentItem[] = result.items.map((item) => ({
289
- id: item.id,
290
- type: item.type,
291
- slug: item.slug,
292
- status: item.status,
293
- data: item.data,
294
- createdAt: item.createdAt,
295
- updatedAt: item.updatedAt,
296
- locale: item.locale,
297
- publishedAt: item.publishedAt,
298
- scheduledAt: item.scheduledAt,
299
- }));
300
-
301
- if (items.length > 0 && (await seoRepo.isEnabled(collection))) {
302
- const seoMap = await seoRepo.getMany(
303
- collection,
304
- items.map((i) => i.id),
305
- );
306
- for (const item of items) {
307
- const seo = seoMap.get(item.id);
308
- if (seo) item.seo = seo;
309
- }
310
- }
311
-
312
- return {
313
- items,
314
- cursor: result.nextCursor,
315
- hasMore: !!result.nextCursor,
316
- };
379
+ async getCollection(slug) {
380
+ return collectionToSchemaInfo(await registry.getCollectionWithFields(slug));
317
381
  },
318
382
  };
319
383
  }
@@ -360,6 +424,327 @@ export function createTaxonomyAccess(db: Kysely<Database>): TaxonomyAccess {
360
424
  };
361
425
  }
362
426
 
427
+ function toPluginComment(comment: Comment): PluginComment {
428
+ if (comment.status === "trash") throw new Error("Trashed comments are not plugin-readable");
429
+ return {
430
+ id: comment.id,
431
+ collection: comment.collection,
432
+ contentId: comment.contentId,
433
+ parentId: comment.parentId,
434
+ authorName: comment.authorName,
435
+ authorEmail: comment.authorEmail,
436
+ body: comment.body,
437
+ status: comment.status,
438
+ ipHash: comment.ipHash,
439
+ userAgent: comment.userAgent,
440
+ moderationMetadata: comment.moderationMetadata,
441
+ createdAt: comment.createdAt,
442
+ updatedAt: comment.updatedAt,
443
+ };
444
+ }
445
+
446
+ export function createCommentAccess(
447
+ db: Kysely<Database>,
448
+ moderate?: (
449
+ id: string,
450
+ status: PluginCommentStatus,
451
+ expectedStatus: PluginCommentStatus,
452
+ ) => Promise<PluginComment>,
453
+ ): CommentAccess {
454
+ const repo = new CommentRepository(db);
455
+ return {
456
+ async get(id) {
457
+ const comment = await repo.findById(id);
458
+ return !comment || comment.status === "trash" ? null : toPluginComment(comment);
459
+ },
460
+ async list(options: CommentListOptions = {}) {
461
+ const result = await repo.findForPlugin(options);
462
+ return {
463
+ items: result.items.map(toPluginComment),
464
+ cursor: result.nextCursor,
465
+ hasMore: result.nextCursor !== undefined,
466
+ };
467
+ },
468
+ count: (options) => repo.countForPlugin(options),
469
+ ...(moderate
470
+ ? {
471
+ setStatus: (id, status, options) => moderate(id, status, options.expectedStatus),
472
+ }
473
+ : {}),
474
+ };
475
+ }
476
+
477
+ export class RedirectAccessError extends Error {
478
+ override readonly name = "RedirectAccessError";
479
+
480
+ constructor(
481
+ readonly code: string,
482
+ message: string,
483
+ ) {
484
+ super(message);
485
+ }
486
+ }
487
+
488
+ const REDIRECT_REVISION_PREFIX = "r1.";
489
+ const BASE64_PADDING_RE = /=+$/;
490
+
491
+ function encodeRedirectRevision(id: string, revision: string): string {
492
+ const payload = `${id}\0${revision}`;
493
+ return `${REDIRECT_REVISION_PREFIX}${btoa(payload)
494
+ .replaceAll("+", "-")
495
+ .replaceAll("/", "_")
496
+ .replace(BASE64_PADDING_RE, "")}`;
497
+ }
498
+
499
+ function decodeRedirectRevision(id: string, revision: string): string {
500
+ if (typeof revision !== "string" || !revision.startsWith(REDIRECT_REVISION_PREFIX)) {
501
+ throw new RedirectAccessError("INVALID_PRECONDITION", "Invalid redirect revision");
502
+ }
503
+ try {
504
+ const encoded = revision
505
+ .slice(REDIRECT_REVISION_PREFIX.length)
506
+ .replaceAll("-", "+")
507
+ .replaceAll("_", "/");
508
+ const padded = encoded.padEnd(Math.ceil(encoded.length / 4) * 4, "=");
509
+ const [revisionId, updatedAt, extra] = atob(padded).split("\0");
510
+ if (revisionId !== id || !updatedAt || extra !== undefined) throw new Error("invalid");
511
+ return updatedAt;
512
+ } catch (error) {
513
+ if (error instanceof RedirectAccessError) throw error;
514
+ throw new RedirectAccessError("INVALID_PRECONDITION", "Invalid redirect revision");
515
+ }
516
+ }
517
+
518
+ function toRedirectInfo(redirect: Redirect): RedirectInfo {
519
+ return {
520
+ ...redirect,
521
+ type: redirect.type as RedirectStatus,
522
+ };
523
+ }
524
+
525
+ function toVersionedRedirect(record: VersionedRedirectRecord): VersionedRedirect {
526
+ return {
527
+ redirect: toRedirectInfo(record.redirect),
528
+ _rev: encodeRedirectRevision(record.redirect.id, record.configRevision),
529
+ };
530
+ }
531
+
532
+ async function readVersionedRedirect(
533
+ repo: RedirectRepository,
534
+ id: string,
535
+ ): Promise<VersionedRedirect | null> {
536
+ const record = await repo.findVersionedById(id);
537
+ return record ? toVersionedRedirect(record) : null;
538
+ }
539
+
540
+ function throwRedirectResult(error: { code: string; message: string }): never {
541
+ throw new RedirectAccessError(error.code, error.message);
542
+ }
543
+
544
+ function assertNoAutomaticRedirectMarker(input: object): void {
545
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
546
+ throw new RedirectAccessError("VALIDATION_ERROR", "Redirect input must be an object");
547
+ }
548
+ if (Object.hasOwn(input, "auto")) {
549
+ throw new RedirectAccessError(
550
+ "VALIDATION_ERROR",
551
+ "The automatic redirect marker is managed by EmDash",
552
+ );
553
+ }
554
+ }
555
+
556
+ export function createRedirectAccess(db: Kysely<Database>): RedirectAccess;
557
+ export function createRedirectAccess(db: Kysely<Database>, writable: true): RedirectAccessWithWrite;
558
+ export function createRedirectAccess(
559
+ db: Kysely<Database>,
560
+ writable = false,
561
+ ): RedirectAccess | RedirectAccessWithWrite {
562
+ const repo = new RedirectRepository(db);
563
+ const readAccess: RedirectAccess = {
564
+ async list(options: RedirectListOptions = {}) {
565
+ const result = await handleRedirectList(db, options);
566
+ if (!result.success) return throwRedirectResult(result.error);
567
+ return {
568
+ items: result.data.items.map(toRedirectInfo),
569
+ cursor: result.data.nextCursor,
570
+ hasMore: result.data.nextCursor !== undefined,
571
+ };
572
+ },
573
+ get: (id: string) => readVersionedRedirect(repo, id),
574
+ };
575
+ if (!writable) return readAccess;
576
+
577
+ return {
578
+ ...readAccess,
579
+ async create(input: RedirectCreateInput) {
580
+ assertNoAutomaticRedirectMarker(input);
581
+ const parsed = createRedirectBody.safeParse(input);
582
+ if (!parsed.success) {
583
+ throw new RedirectAccessError(
584
+ "VALIDATION_ERROR",
585
+ parsed.error.issues[0]?.message ?? "Invalid redirect",
586
+ );
587
+ }
588
+ const result = await handleRedirectCreate(db, parsed.data);
589
+ if (!result.success) return throwRedirectResult(result.error);
590
+ const current = await readVersionedRedirect(repo, result.data.id);
591
+ if (!current) throw new RedirectAccessError("NOT_FOUND", "Created redirect not found");
592
+ return current;
593
+ },
594
+ async update(id: string, input: RedirectUpdateInput & { _rev: string }) {
595
+ assertNoAutomaticRedirectMarker(input);
596
+ const { _rev, ...patch } = input;
597
+ const expectedRevision = decodeRedirectRevision(id, _rev);
598
+ const parsed = updateRedirectBody.safeParse(patch);
599
+ if (!parsed.success) {
600
+ throw new RedirectAccessError(
601
+ "VALIDATION_ERROR",
602
+ parsed.error.issues[0]?.message ?? "Invalid redirect",
603
+ );
604
+ }
605
+ const result = await handleRedirectUpdate(db, id, parsed.data, { expectedRevision });
606
+ if (!result.success) return throwRedirectResult(result.error);
607
+ const current = await readVersionedRedirect(repo, result.data.id);
608
+ if (!current) throw new RedirectAccessError("NOT_FOUND", "Updated redirect not found");
609
+ return current;
610
+ },
611
+ async delete(id: string, options: { _rev: string }) {
612
+ if (typeof options !== "object" || options === null) {
613
+ throw new RedirectAccessError("INVALID_PRECONDITION", "Invalid redirect revision");
614
+ }
615
+ const expectedRevision = decodeRedirectRevision(id, options._rev);
616
+ const result = await handleRedirectDelete(db, id, { expectedRevision });
617
+ if (!result.success) return throwRedirectResult(result.error);
618
+ return result.data.deleted;
619
+ },
620
+ };
621
+ }
622
+
623
+ const MAX_TAXONOMY_DELTA_TERMS = 64;
624
+
625
+ function taxonomyAccessError(code: string, message: string): Error {
626
+ return Object.assign(new Error(message), { code });
627
+ }
628
+
629
+ async function resolveTaxonomyDelta(
630
+ db: Kysely<Database>,
631
+ collection: string,
632
+ entryId: string,
633
+ taxonomy: string,
634
+ termIds: string[],
635
+ ): Promise<{ repo: TaxonomyRepository; groups: string[]; locale: string }> {
636
+ if (termIds.length > MAX_TAXONOMY_DELTA_TERMS) {
637
+ throw taxonomyAccessError(
638
+ "VALIDATION_ERROR",
639
+ `A taxonomy assignment delta can contain at most ${MAX_TAXONOMY_DELTA_TERMS} term IDs`,
640
+ );
641
+ }
642
+ if (termIds.some((id) => typeof id !== "string" || id.length === 0)) {
643
+ throw taxonomyAccessError("VALIDATION_ERROR", "Taxonomy term IDs must be non-empty strings");
644
+ }
645
+
646
+ const defs = await db
647
+ .selectFrom("_emdash_taxonomy_defs")
648
+ .select(["collections"])
649
+ .where("name", "=", taxonomy)
650
+ .execute();
651
+ if (defs.length === 0) {
652
+ throw taxonomyAccessError("NOT_FOUND", `Taxonomy '${taxonomy}' not found`);
653
+ }
654
+ const attached = defs.some((def) => parseCollectionsColumn(def.collections).includes(collection));
655
+ if (!attached) {
656
+ throw taxonomyAccessError(
657
+ "VALIDATION_ERROR",
658
+ `Taxonomy '${taxonomy}' is not attached to collection '${collection}'`,
659
+ );
660
+ }
661
+
662
+ const entry = await new ContentRepository(db).findById(collection, entryId);
663
+ if (!entry) {
664
+ throw taxonomyAccessError(
665
+ "NOT_FOUND",
666
+ `Content entry '${entryId}' not found in '${collection}'`,
667
+ );
668
+ }
669
+
670
+ const repo = new TaxonomyRepository(db);
671
+ const groups: string[] = [];
672
+ for (const id of new Set(termIds)) {
673
+ const term = await repo.findByIdOrTranslationGroup(id);
674
+ if (!term) throw taxonomyAccessError("NOT_FOUND", `Taxonomy term '${id}' not found`);
675
+ if (term.name !== taxonomy) {
676
+ throw taxonomyAccessError(
677
+ "VALIDATION_ERROR",
678
+ `Taxonomy term '${id}' belongs to '${term.name}', not '${taxonomy}'`,
679
+ );
680
+ }
681
+ groups.push(term.translationGroup ?? term.id);
682
+ }
683
+
684
+ return { repo, groups, locale: entry.locale ?? getI18nConfig()?.defaultLocale ?? "en" };
685
+ }
686
+
687
+ async function readResolvedEntryTerms(
688
+ repo: TaxonomyRepository,
689
+ collection: string,
690
+ entryId: string,
691
+ taxonomy: string,
692
+ locale: string,
693
+ ): Promise<TaxonomyTermInfo[]> {
694
+ const defaultLocale = getI18nConfig()?.defaultLocale ?? locale;
695
+ const assignments = await repo.getTermAssignmentsForEntry(
696
+ collection,
697
+ entryId,
698
+ taxonomy,
699
+ locale,
700
+ defaultLocale,
701
+ );
702
+ return assignments.flatMap(({ term }) => (term ? [taxonomyToTermInfo(term)] : []));
703
+ }
704
+
705
+ export function createTaxonomyAccessWithWrite(db: Kysely<Database>): TaxonomyAccessWithWrite {
706
+ return {
707
+ ...createTaxonomyAccess(db),
708
+ async createTerm(taxonomy: string, input: TaxonomyTermCreateInput) {
709
+ const result = await handleTermCreate(db, taxonomy, input);
710
+ if (!result.success) throw taxonomyAccessError(result.error.code, result.error.message);
711
+ const { term } = result.data;
712
+ return {
713
+ id: term.id,
714
+ taxonomy: term.name,
715
+ slug: term.slug,
716
+ label: term.label,
717
+ parentId: term.parentId,
718
+ data: term.description ? { description: term.description } : null,
719
+ locale: term.locale,
720
+ translationGroup: term.translationGroup,
721
+ };
722
+ },
723
+ async addEntryTerms(collection, entryId, taxonomy, termIds) {
724
+ const { repo, groups, locale } = await resolveTaxonomyDelta(
725
+ db,
726
+ collection,
727
+ entryId,
728
+ taxonomy,
729
+ termIds,
730
+ );
731
+ await repo.attachGroupsToEntry(collection, entryId, groups);
732
+ return readResolvedEntryTerms(repo, collection, entryId, taxonomy, locale);
733
+ },
734
+ async removeEntryTerms(collection, entryId, taxonomy, termIds) {
735
+ const { repo, groups, locale } = await resolveTaxonomyDelta(
736
+ db,
737
+ collection,
738
+ entryId,
739
+ taxonomy,
740
+ termIds,
741
+ );
742
+ await repo.detachGroupsFromEntry(collection, entryId, groups);
743
+ return readResolvedEntryTerms(repo, collection, entryId, taxonomy, locale);
744
+ },
745
+ };
746
+ }
747
+
363
748
  /**
364
749
  * Create full content access with write operations.
365
750
  *
@@ -372,8 +757,14 @@ export function createTaxonomyAccess(db: Kysely<Database>): TaxonomyAccess {
372
757
  export function createContentAccessWithWrite(
373
758
  db: Kysely<Database>,
374
759
  beforeContentWrite?: () => Promise<void>,
760
+ accessOptions?: { site?: SiteInfo; revisions?: boolean },
761
+ contentCreate?: (data: {
762
+ collection: string;
763
+ input: ContentWriteInput;
764
+ options?: ContentCreateOptions;
765
+ }) => Promise<ContentItem>,
375
766
  ): ContentAccessWithWrite {
376
- const readAccess = createContentAccess(db);
767
+ const readAccess = createContentAccess(db, accessOptions);
377
768
 
378
769
  return {
379
770
  ...readAccess,
@@ -385,6 +776,13 @@ export function createContentAccessWithWrite(
385
776
  ): Promise<ContentItem> {
386
777
  const locale = resolveContentCreateLocale(options?.locale);
387
778
  await beforeContentWrite?.();
779
+ if (contentCreate) {
780
+ return contentCreate({
781
+ collection,
782
+ input: data,
783
+ options: { ...options, locale },
784
+ });
785
+ }
388
786
  const { fields, seo } = splitSeoFromInput(data);
389
787
  let contentMutated = false;
390
788
 
@@ -399,6 +797,7 @@ export function createContentAccessWithWrite(
399
797
  type: collection,
400
798
  data: fields,
401
799
  locale,
800
+ translationOf: options?.translationOf,
402
801
  });
403
802
  contentMutated = true;
404
803
 
@@ -500,6 +899,9 @@ export function createContentAccessWithWrite(
500
899
  const contentRepo = new ContentRepository(db);
501
900
  const deleted = await contentRepo.delete(collection, id);
502
901
  if (deleted) {
902
+ // A trashed entry can no longer be opened, so its holder can never
903
+ // release the lease itself. Mirrors handleContentDelete.
904
+ await new EntryLockRepository(db).releaseEntry(collection, id);
503
905
  await markContentMediaUsageCollectionStaleSafely(db, collection, "CONTENT_USAGE_STALE");
504
906
  }
505
907
  return deleted;
@@ -520,17 +922,7 @@ export function createMediaAccess(db: Kysely<Database>): MediaAccess {
520
922
  return {
521
923
  async get(id: string): Promise<MediaItem | null> {
522
924
  const item = await mediaRepo.findById(id);
523
- if (!item) return null;
524
-
525
- return {
526
- id: item.id,
527
- filename: item.filename,
528
- mimeType: item.mimeType,
529
- size: item.size,
530
- // Construct URL from storage key (or use a sensible default path)
531
- url: `/media/${item.id}/${item.filename}`,
532
- createdAt: item.createdAt,
533
- };
925
+ return item?.status === "ready" ? toPluginMediaItem(item) : null;
534
926
  },
535
927
 
536
928
  async list(options?: MediaListOptions): Promise<PaginatedResult<MediaItem>> {
@@ -541,14 +933,7 @@ export function createMediaAccess(db: Kysely<Database>): MediaAccess {
541
933
  });
542
934
 
543
935
  return {
544
- items: result.items.map((item) => ({
545
- id: item.id,
546
- filename: item.filename,
547
- mimeType: item.mimeType,
548
- size: item.size,
549
- url: `/media/${item.id}/${item.filename}`,
550
- createdAt: item.createdAt,
551
- })),
936
+ items: result.items.map(toPluginMediaItem),
552
937
  cursor: result.nextCursor,
553
938
  hasMore: !!result.nextCursor,
554
939
  };
@@ -556,6 +941,17 @@ export function createMediaAccess(db: Kysely<Database>): MediaAccess {
556
941
  };
557
942
  }
558
943
 
944
+ function mediaReadDenied(): never {
945
+ throw new Error("Missing capability: media:read");
946
+ }
947
+
948
+ function createBlockedMediaReadAccess(): MediaAccess {
949
+ return {
950
+ get: async () => mediaReadDenied(),
951
+ list: async () => mediaReadDenied(),
952
+ };
953
+ }
954
+
559
955
  /**
560
956
  * Create full media access with write operations.
561
957
  *
@@ -689,30 +1085,62 @@ export function createMediaAccessWithWrite(
689
1085
  /** Maximum number of redirects to follow in plugin HTTP access */
690
1086
  const MAX_PLUGIN_REDIRECTS = 5;
691
1087
 
1088
+ function stripTrailingDots(value: string): string {
1089
+ let end = value.length;
1090
+ while (end > 0 && value.charCodeAt(end - 1) === 46) end--;
1091
+ return end === value.length ? value : value.slice(0, end);
1092
+ }
1093
+
692
1094
  /**
693
1095
  * Check if a hostname matches any pattern in the allowed list.
694
1096
  * Patterns: "*" matches all, "*.example.com" matches subdomains AND bare "example.com",
695
1097
  * "api.example.com" matches exactly.
696
1098
  */
697
1099
  function isHostAllowed(host: string, allowedHosts: string[]): boolean {
1100
+ const normalizedHost = stripTrailingDots(host.toLowerCase());
698
1101
  return allowedHosts.some((pattern) => {
699
- if (pattern === "*") return true;
700
- if (pattern.startsWith("*.")) {
701
- const suffix = pattern.slice(1); // ".example.com"
1102
+ const normalizedPattern = stripTrailingDots(pattern.toLowerCase());
1103
+ if (normalizedPattern === "*") return true;
1104
+ if (normalizedPattern.startsWith("*.")) {
1105
+ const suffix = normalizedPattern.slice(1); // ".example.com"
702
1106
  // Match subdomains (foo.example.com) and bare domain (example.com)
703
- return host.endsWith(suffix) || host === pattern.slice(2);
1107
+ return normalizedHost.endsWith(suffix) || normalizedHost === normalizedPattern.slice(2);
704
1108
  }
705
- return host === pattern;
1109
+ return normalizedHost === normalizedPattern;
706
1110
  });
707
1111
  }
708
1112
 
1113
+ function tryParsePluginHttpTarget(url: string): URL | null {
1114
+ try {
1115
+ return new URL(url);
1116
+ } catch {
1117
+ return null;
1118
+ }
1119
+ }
1120
+
1121
+ async function validatePluginHttpTarget(pluginId: string, url: string): Promise<URL> {
1122
+ try {
1123
+ return await resolveAndValidateExternalUrl(url);
1124
+ } catch (error) {
1125
+ const message = error instanceof SsrfError ? error.message : "SSRF validation failed";
1126
+ const target = tryParsePluginHttpTarget(url);
1127
+ throw new Error(
1128
+ `Plugin "${pluginId}": blocked fetch to "${target ? target.hostname : "invalid URL"}": ${message}`,
1129
+ { cause: error },
1130
+ );
1131
+ }
1132
+ }
1133
+
709
1134
  /**
710
- * Create HTTP access with host validation.
1135
+ * Create HTTP access with host validation and SSRF protection.
711
1136
  *
712
- * Uses redirect: "manual" to re-validate each redirect target against
713
- * the allowedHosts list, preventing redirects to unauthorized hosts.
1137
+ * Uses redirect: "manual" to re-validate each redirect target before dispatch.
714
1138
  */
715
- export function createHttpAccess(pluginId: string, allowedHosts: string[]): HttpAccess {
1139
+ export function createHttpAccess(
1140
+ pluginId: string,
1141
+ allowedHosts: string[],
1142
+ fetchImpl: typeof fetch = globalThis.fetch,
1143
+ ): HttpAccess {
716
1144
  return {
717
1145
  async fetch(url: string, init?: RequestInit): Promise<Response> {
718
1146
  // Deny by default — plugins must declare allowed hosts
@@ -725,36 +1153,51 @@ export function createHttpAccess(pluginId: string, allowedHosts: string[]): Http
725
1153
 
726
1154
  let currentUrl = url;
727
1155
  let currentInit = init;
1156
+ let requestBuffered = false;
1157
+ let redirected = false;
728
1158
 
729
1159
  for (let i = 0; i <= MAX_PLUGIN_REDIRECTS; i++) {
730
- const hostname = new URL(currentUrl).hostname;
731
- if (!isHostAllowed(hostname, allowedHosts)) {
1160
+ const target = tryParsePluginHttpTarget(currentUrl);
1161
+ if (target && !isHostAllowed(target.hostname, allowedHosts)) {
732
1162
  throw new Error(
733
- `Plugin "${pluginId}" is not allowed to fetch from host "${hostname}". ` +
1163
+ `Plugin "${pluginId}" is not allowed to fetch from host "${target.hostname}". ` +
734
1164
  `Allowed hosts: ${allowedHosts.join(", ")}`,
735
1165
  );
736
1166
  }
1167
+ await validatePluginHttpTarget(pluginId, currentUrl);
1168
+ if (!requestBuffered) {
1169
+ currentInit = await bufferPluginHttpRequest(currentInit);
1170
+ requestBuffered = true;
1171
+ }
737
1172
 
738
- const response = await globalThis.fetch(currentUrl, {
1173
+ const response = await fetchImpl(currentUrl, {
739
1174
  ...currentInit,
740
1175
  redirect: "manual",
741
1176
  });
742
1177
 
743
- // Not a redirect -- return directly
744
- if (response.status < 300 || response.status >= 400) {
745
- return response;
746
- }
747
-
748
- // Extract redirect target
749
1178
  const location = response.headers.get("Location");
750
- if (!location) {
751
- return response;
1179
+ if (location === null) {
1180
+ return pluginHttpResponseFromWire(
1181
+ await pluginHttpResponseToWire(response, currentUrl, redirected),
1182
+ );
1183
+ }
1184
+ const redirectAction = pluginHttpRedirectAction(response.status, true, currentInit);
1185
+ if (redirectAction === "return") {
1186
+ return pluginHttpResponseFromWire(
1187
+ await pluginHttpResponseToWire(response, currentUrl, redirected),
1188
+ );
1189
+ }
1190
+ await response.body?.cancel();
1191
+ if (redirectAction === "error") {
1192
+ throw new Error(`Plugin "${pluginId}": redirect mode is "error"`);
752
1193
  }
753
1194
 
754
1195
  // Resolve relative redirects; strip credentials on cross-origin hops
755
1196
  const previousOrigin = new URL(currentUrl).origin;
756
1197
  currentUrl = new URL(location, currentUrl).href;
1198
+ redirected = true;
757
1199
  const nextOrigin = new URL(currentUrl).origin;
1200
+ currentInit = rewritePluginHttpRedirect(response.status, currentInit);
758
1201
 
759
1202
  if (previousOrigin !== nextOrigin && currentInit) {
760
1203
  currentInit = stripCredentialHeaders(currentInit);
@@ -767,49 +1210,56 @@ export function createHttpAccess(pluginId: string, allowedHosts: string[]): Http
767
1210
  }
768
1211
 
769
1212
  /**
770
- * Create unrestricted HTTP access (for plugins with network:fetch:any capability).
1213
+ * Create unrestricted HTTP access (for plugins with network:request:unrestricted capability).
771
1214
  * No host validation, but applies SSRF protection on redirect targets to
772
1215
  * prevent plugins from being tricked into reaching internal services.
773
1216
  */
774
- export function createUnrestrictedHttpAccess(pluginId: string): HttpAccess {
1217
+ export function createUnrestrictedHttpAccess(
1218
+ pluginId: string,
1219
+ fetchImpl: typeof fetch = globalThis.fetch,
1220
+ ): HttpAccess {
775
1221
  return {
776
1222
  async fetch(url: string, init?: RequestInit): Promise<Response> {
777
1223
  let currentUrl = url;
778
1224
  let currentInit = init;
1225
+ let requestBuffered = false;
1226
+ let redirected = false;
779
1227
 
780
1228
  for (let i = 0; i <= MAX_PLUGIN_REDIRECTS; i++) {
781
- // Validate each URL against SSRF rules (private IPs, metadata
782
- // endpoints, wildcard DNS, resolved-IP private ranges).
783
- try {
784
- await resolveAndValidateExternalUrl(currentUrl);
785
- } catch (e) {
786
- const msg = e instanceof SsrfError ? e.message : "SSRF validation failed";
787
- throw new Error(
788
- `Plugin "${pluginId}": blocked fetch to "${new URL(currentUrl).hostname}": ${msg}`,
789
- { cause: e },
790
- );
1229
+ await validatePluginHttpTarget(pluginId, currentUrl);
1230
+ if (!requestBuffered) {
1231
+ currentInit = await bufferPluginHttpRequest(currentInit);
1232
+ requestBuffered = true;
791
1233
  }
792
1234
 
793
- const response = await globalThis.fetch(currentUrl, {
1235
+ const response = await fetchImpl(currentUrl, {
794
1236
  ...currentInit,
795
1237
  redirect: "manual",
796
1238
  });
797
1239
 
798
- // Not a redirect -- return directly
799
- if (response.status < 300 || response.status >= 400) {
800
- return response;
801
- }
802
-
803
- // Extract redirect target
804
1240
  const location = response.headers.get("Location");
805
- if (!location) {
806
- return response;
1241
+ if (location === null) {
1242
+ return pluginHttpResponseFromWire(
1243
+ await pluginHttpResponseToWire(response, currentUrl, redirected),
1244
+ );
1245
+ }
1246
+ const redirectAction = pluginHttpRedirectAction(response.status, true, currentInit);
1247
+ if (redirectAction === "return") {
1248
+ return pluginHttpResponseFromWire(
1249
+ await pluginHttpResponseToWire(response, currentUrl, redirected),
1250
+ );
1251
+ }
1252
+ await response.body?.cancel();
1253
+ if (redirectAction === "error") {
1254
+ throw new Error(`Plugin "${pluginId}": redirect mode is "error"`);
807
1255
  }
808
1256
 
809
1257
  // Resolve relative redirects; strip credentials on cross-origin hops
810
1258
  const previousOrigin = new URL(currentUrl).origin;
811
1259
  currentUrl = new URL(location, currentUrl).href;
1260
+ redirected = true;
812
1261
  const nextOrigin = new URL(currentUrl).origin;
1262
+ currentInit = rewritePluginHttpRedirect(response.status, currentInit);
813
1263
 
814
1264
  if (previousOrigin !== nextOrigin && currentInit) {
815
1265
  currentInit = stripCredentialHeaders(currentInit);
@@ -842,39 +1292,40 @@ export function createBlockedHttpAccess(pluginId: string): HttpAccess {
842
1292
  /**
843
1293
  * Create logger for a plugin
844
1294
  */
845
- export function createLogAccess(pluginId: string): LogAccess {
1295
+ export function createLogAccess(pluginId: string, redactor?: PluginSecretRedactor): LogAccess {
846
1296
  const prefix = `[plugin:${pluginId}]`;
1297
+ const redact = <T>(value: T): T => redactor?.redact(value) ?? value;
847
1298
 
848
1299
  return {
849
1300
  debug(message: string, data?: unknown): void {
850
1301
  if (data !== undefined) {
851
- console.debug(prefix, message, data);
1302
+ console.debug(prefix, redact(message), redact(data));
852
1303
  } else {
853
- console.debug(prefix, message);
1304
+ console.debug(prefix, redact(message));
854
1305
  }
855
1306
  },
856
1307
 
857
1308
  info(message: string, data?: unknown): void {
858
1309
  if (data !== undefined) {
859
- console.info(prefix, message, data);
1310
+ console.info(prefix, redact(message), redact(data));
860
1311
  } else {
861
- console.info(prefix, message);
1312
+ console.info(prefix, redact(message));
862
1313
  }
863
1314
  },
864
1315
 
865
1316
  warn(message: string, data?: unknown): void {
866
1317
  if (data !== undefined) {
867
- console.warn(prefix, message, data);
1318
+ console.warn(prefix, redact(message), redact(data));
868
1319
  } else {
869
- console.warn(prefix, message);
1320
+ console.warn(prefix, redact(message));
870
1321
  }
871
1322
  },
872
1323
 
873
1324
  error(message: string, data?: unknown): void {
874
1325
  if (data !== undefined) {
875
- console.error(prefix, message, data);
1326
+ console.error(prefix, redact(message), redact(data));
876
1327
  } else {
877
- console.error(prefix, message);
1328
+ console.error(prefix, redact(message));
878
1329
  }
879
1330
  },
880
1331
  };
@@ -1005,6 +1456,8 @@ export function createUserAccess(db: Kysely<Database>): UserAccess {
1005
1456
  export interface PluginContextFactoryOptions {
1006
1457
  db: Kysely<Database>;
1007
1458
  beforeContentWrite?: () => Promise<void>;
1459
+ contentCreate?: PluginContentCreateCallback;
1460
+ contentActions?: ContentActionCallbacks;
1008
1461
  /**
1009
1462
  * Resolver for the database connection, preferred over `db` when present.
1010
1463
  * Called per `createContext()` so connection-backed adapters (e.g. Postgres
@@ -1040,6 +1493,8 @@ export interface PluginContextFactoryOptions {
1040
1493
  * If not provided, ctx.cron will not be available.
1041
1494
  */
1042
1495
  cronReschedule?: () => void;
1496
+ /** Clock used to calculate the first run of recurring plugin tasks. */
1497
+ now?: () => Date;
1043
1498
  /**
1044
1499
  * Email pipeline instance for ctx.email.
1045
1500
  * If not provided (or no provider configured), ctx.email will be undefined.
@@ -1052,6 +1507,73 @@ export interface PluginContextFactoryOptions {
1052
1507
  * client IP the core auth path does.
1053
1508
  */
1054
1509
  trustedProxyHeaders?: string[];
1510
+ commentModerate?: (
1511
+ pluginId: string,
1512
+ id: string,
1513
+ status: PluginCommentStatus,
1514
+ expectedStatus: PluginCommentStatus,
1515
+ ) => Promise<PluginComment>;
1516
+ }
1517
+
1518
+ export interface ContentActionCallbacks {
1519
+ /** Register a sandbox invocation before it can call a content action. */
1520
+ begin?(
1521
+ pluginId: string,
1522
+ invocationId: string,
1523
+ invalidateContentCache?: (tags: string[]) => Promise<void>,
1524
+ ): void;
1525
+ /** Release queued after-hooks; `final: false` keeps late actions self-scheduling after timeout. */
1526
+ flush(pluginId: string, invocationId?: string, final?: boolean): Promise<void>;
1527
+ getVersioned(
1528
+ pluginId: string,
1529
+ collection: string,
1530
+ id: string,
1531
+ ): Promise<VersionedContentItem | null>;
1532
+ publish(
1533
+ pluginId: string,
1534
+ collection: string,
1535
+ id: string,
1536
+ options: { _rev: string },
1537
+ invocationId?: string,
1538
+ invalidateContentCache?: (tags: string[]) => Promise<void>,
1539
+ ): Promise<VersionedContentItem>;
1540
+ unpublish(
1541
+ pluginId: string,
1542
+ collection: string,
1543
+ id: string,
1544
+ options: { _rev: string },
1545
+ invocationId?: string,
1546
+ invalidateContentCache?: (tags: string[]) => Promise<void>,
1547
+ ): Promise<VersionedContentItem>;
1548
+ schedule(
1549
+ pluginId: string,
1550
+ collection: string,
1551
+ id: string,
1552
+ options: { scheduledAt: string; _rev: string },
1553
+ invocationId?: string,
1554
+ invalidateContentCache?: (tags: string[]) => Promise<void>,
1555
+ ): Promise<VersionedContentItem>;
1556
+ unschedule(
1557
+ pluginId: string,
1558
+ collection: string,
1559
+ id: string,
1560
+ options: { _rev: string },
1561
+ invocationId?: string,
1562
+ invalidateContentCache?: (tags: string[]) => Promise<void>,
1563
+ ): Promise<VersionedContentItem>;
1564
+ getTrashedVersioned(
1565
+ pluginId: string,
1566
+ collection: string,
1567
+ id: string,
1568
+ ): Promise<VersionedContentItem | null>;
1569
+ restore(
1570
+ pluginId: string,
1571
+ collection: string,
1572
+ id: string,
1573
+ options: { _rev: string },
1574
+ invocationId?: string,
1575
+ invalidateContentCache?: (tags: string[]) => Promise<void>,
1576
+ ): Promise<VersionedContentItem>;
1055
1577
  }
1056
1578
 
1057
1579
  /**
@@ -1060,6 +1582,8 @@ export interface PluginContextFactoryOptions {
1060
1582
  export class PluginContextFactory {
1061
1583
  private resolveDb: () => Kysely<Database>;
1062
1584
  private beforeContentWrite?: () => Promise<void>;
1585
+ private contentCreate?: PluginContentCreateCallback;
1586
+ private contentActions?: ContentActionCallbacks;
1063
1587
  private storage?: Storage;
1064
1588
  private getUploadUrl?: (
1065
1589
  filename: string,
@@ -1068,7 +1592,9 @@ export class PluginContextFactory {
1068
1592
  private site: SiteInfo;
1069
1593
  private urlHelper: (path: string) => string;
1070
1594
  private cronReschedule?: () => void;
1595
+ private now: () => Date;
1071
1596
  private emailPipeline?: EmailPipeline;
1597
+ private commentModerate?: PluginContextFactoryOptions["commentModerate"];
1072
1598
  /**
1073
1599
  * Plugin IDs already warned about a missing media-write backend, so the
1074
1600
  * warning fires once per factory instead of on every hook/route context
@@ -1080,12 +1606,16 @@ export class PluginContextFactory {
1080
1606
  const fixedDb = options.db;
1081
1607
  this.resolveDb = options.getDb ?? (() => fixedDb);
1082
1608
  this.beforeContentWrite = options.beforeContentWrite;
1609
+ this.contentCreate = options.contentCreate;
1610
+ this.contentActions = options.contentActions;
1083
1611
  this.storage = options.storage;
1084
1612
  this.getUploadUrl = options.getUploadUrl;
1085
1613
  this.site = createSiteInfo(options.siteInfo ?? {});
1086
1614
  this.urlHelper = createUrlHelper(this.site.url);
1087
1615
  this.cronReschedule = options.cronReschedule;
1616
+ this.now = options.now ?? (() => new Date());
1088
1617
  this.emailPipeline = options.emailPipeline;
1618
+ this.commentModerate = options.commentModerate;
1089
1619
  }
1090
1620
 
1091
1621
  /**
@@ -1102,8 +1632,16 @@ export class PluginContextFactory {
1102
1632
  const optionsRepo = new OptionsRepository(db);
1103
1633
 
1104
1634
  // Always available
1105
- const kv = createKVAccess(optionsRepo, plugin.id);
1106
- const log = createLogAccess(plugin.id);
1635
+ const secretRedactor = createPluginSecretRedactor();
1636
+ const settings = createSettingsAccess(
1637
+ optionsRepo,
1638
+ plugin.id,
1639
+ plugin.admin.settingsSchema ?? {},
1640
+ undefined,
1641
+ secretRedactor.add,
1642
+ );
1643
+ const kv = createKVAccess(optionsRepo, plugin.id, settings);
1644
+ const log = createLogAccess(plugin.id, secretRedactor);
1107
1645
  const storage = createStorageAccess(db, plugin.id, plugin.storage);
1108
1646
 
1109
1647
  // Capability-gated: content
@@ -1112,23 +1650,93 @@ export class PluginContextFactory {
1112
1650
  // names ("read:content", "write:content") never appear here.
1113
1651
  let content: ContentAccess | ContentAccessWithWrite | undefined;
1114
1652
  if (capabilities.has("content:write")) {
1115
- content = createContentAccessWithWrite(db, this.beforeContentWrite);
1653
+ content = createContentAccessWithWrite(
1654
+ db,
1655
+ this.beforeContentWrite,
1656
+ {
1657
+ site: this.site,
1658
+ revisions: capabilities.has("content:revisions:read"),
1659
+ },
1660
+ this.contentCreate
1661
+ ? (input) => this.contentCreate!(plugin.id, input.collection, input.input, input.options)
1662
+ : undefined,
1663
+ );
1116
1664
  } else if (capabilities.has("content:read")) {
1117
- content = createContentAccess(db);
1665
+ content = createContentAccess(db, {
1666
+ site: this.site,
1667
+ revisions: capabilities.has("content:revisions:read"),
1668
+ });
1669
+ }
1670
+ if (capabilities.has("content:publish") && this.contentActions) {
1671
+ content = Object.assign(content ?? createContentAccess(db), {
1672
+ getVersioned: (collection: string, id: string) =>
1673
+ this.contentActions!.getVersioned(plugin.id, collection, id),
1674
+ publish: (collection: string, id: string, options: { _rev: string }) =>
1675
+ this.contentActions!.publish(plugin.id, collection, id, options),
1676
+ unpublish: (collection: string, id: string, options: { _rev: string }) =>
1677
+ this.contentActions!.unpublish(plugin.id, collection, id, options),
1678
+ schedule: (
1679
+ collection: string,
1680
+ id: string,
1681
+ options: { scheduledAt: string; _rev: string },
1682
+ ) => this.contentActions!.schedule(plugin.id, collection, id, options),
1683
+ unschedule: (collection: string, id: string, options: { _rev: string }) =>
1684
+ this.contentActions!.unschedule(plugin.id, collection, id, options),
1685
+ });
1686
+ }
1687
+ if (capabilities.has("content:restore") && this.contentActions) {
1688
+ content = Object.assign(
1689
+ content ?? {
1690
+ get: async () => {
1691
+ throw new Error("Missing capability: content:read");
1692
+ },
1693
+ list: async () => {
1694
+ throw new Error("Missing capability: content:read");
1695
+ },
1696
+ },
1697
+ {
1698
+ getTrashedVersioned: (collection: string, id: string) =>
1699
+ this.contentActions!.getTrashedVersioned(plugin.id, collection, id),
1700
+ restore: (collection: string, id: string, options: { _rev: string }) =>
1701
+ this.contentActions!.restore(plugin.id, collection, id, options),
1702
+ },
1703
+ );
1118
1704
  }
1119
1705
 
1120
- // Capability-gated: taxonomies (read-only)
1121
- let taxonomies: TaxonomyAccess | undefined;
1122
- if (capabilities.has("taxonomies:read")) {
1706
+ const schema = capabilities.has("schema:read") ? createSchemaAccess(db) : undefined;
1707
+
1708
+ // Capability-gated: taxonomies
1709
+ let taxonomies: TaxonomyAccess | TaxonomyAccessWithWrite | undefined;
1710
+ if (capabilities.has("taxonomies:write")) {
1711
+ taxonomies = createTaxonomyAccessWithWrite(db);
1712
+ } else if (capabilities.has("taxonomies:read")) {
1123
1713
  taxonomies = createTaxonomyAccess(db);
1124
1714
  }
1125
1715
 
1716
+ let redirects: RedirectAccess | RedirectAccessWithWrite | undefined;
1717
+ if (capabilities.has("redirects:write")) {
1718
+ redirects = createRedirectAccess(db, true);
1719
+ } else if (capabilities.has("redirects:read")) {
1720
+ redirects = createRedirectAccess(db);
1721
+ }
1722
+
1126
1723
  // Capability-gated: media
1127
1724
  // `upload()` only needs `storage`; `getUploadUrl()` is derived from
1128
1725
  // storage when no explicit provider is wired. Granting write access on
1129
1726
  // either avoids silently degrading media:write to read-only — the bug
1130
1727
  // where the runtime threads `storage` but not `getUploadUrl`.
1131
1728
  let media: MediaAccess | MediaAccessWithWrite | undefined;
1729
+ const hasMediaAccess =
1730
+ capabilities.has("media:read") ||
1731
+ capabilities.has("media:write") ||
1732
+ capabilities.has("media:bytes:read") ||
1733
+ capabilities.has("media:metadata:write");
1734
+ if (hasMediaAccess) {
1735
+ media =
1736
+ capabilities.has("media:read") || capabilities.has("media:write")
1737
+ ? createMediaAccess(db)
1738
+ : createBlockedMediaReadAccess();
1739
+ }
1132
1740
  if (capabilities.has("media:write")) {
1133
1741
  if (this.getUploadUrl || this.storage) {
1134
1742
  media = createMediaAccessWithWrite(db, this.getUploadUrl, this.storage);
@@ -1139,12 +1747,14 @@ export class PluginContextFactory {
1139
1747
  "declares the media:write capability but no storage backend is configured; upload() is unavailable.",
1140
1748
  );
1141
1749
  }
1142
- if (capabilities.has("media:read")) {
1143
- media = createMediaAccess(db);
1144
- }
1750
+ media ??= createMediaAccess(db);
1145
1751
  }
1146
- } else if (capabilities.has("media:read")) {
1147
- media = createMediaAccess(db);
1752
+ }
1753
+ if (capabilities.has("media:bytes:read") && media) {
1754
+ media.readBytes = (id, options) => readPluginMediaBytes(db, this.storage, id, options);
1755
+ }
1756
+ if (capabilities.has("media:metadata:write") && media) {
1757
+ media.updateMetadata = (id, patch) => updatePluginMediaMetadata(db, id, patch);
1148
1758
  }
1149
1759
 
1150
1760
  // Capability-gated: http
@@ -1161,11 +1771,21 @@ export class PluginContextFactory {
1161
1771
  users = createUserAccess(db);
1162
1772
  }
1163
1773
 
1774
+ let comments: CommentAccess | undefined;
1775
+ if (capabilities.has("comments:moderate")) {
1776
+ comments = createCommentAccess(db, (id, status, expectedStatus) => {
1777
+ if (!this.commentModerate) throw new Error("Comment moderation is unavailable");
1778
+ return this.commentModerate(plugin.id, id, status, expectedStatus);
1779
+ });
1780
+ } else if (capabilities.has("comments:read")) {
1781
+ comments = createCommentAccess(db);
1782
+ }
1783
+
1164
1784
  // Cron access — always available (scoped to plugin), but only if
1165
1785
  // the runtime provided a reschedule callback (i.e. cron is wired up).
1166
1786
  let cron: CronAccess | undefined;
1167
1787
  if (this.cronReschedule) {
1168
- cron = new CronAccessImpl(db, plugin.id, this.cronReschedule);
1788
+ cron = new CronAccessImpl(db, plugin.id, this.cronReschedule, this.now);
1169
1789
  }
1170
1790
 
1171
1791
  // Email access — requires email:send capability AND a configured provider
@@ -1185,14 +1805,18 @@ export class PluginContextFactory {
1185
1805
  },
1186
1806
  storage,
1187
1807
  kv,
1808
+ settings,
1188
1809
  content,
1810
+ schema,
1189
1811
  taxonomies,
1812
+ redirects,
1190
1813
  media,
1191
1814
  http,
1192
1815
  log,
1193
1816
  site: this.site,
1194
1817
  url: this.urlHelper,
1195
1818
  users,
1819
+ comments,
1196
1820
  cron,
1197
1821
  email,
1198
1822
  };