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
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../src/comments/turnstile.ts","../../../../../../../src/astro/routes/api/comments/[collection]/[contentId]/index.ts"],"sourcesContent":["/**\n * Server-side Turnstile verification for public comment submissions.\n *\n * The comment form widget (`CommentForm.astro`) submits a `turnstileToken`;\n * this verifies it against Cloudflare's siteverify API. Enforcement is\n * opt-in: it only runs when the operator configures the Turnstile secret\n * key (`EMDASH_TURNSTILE_SECRET_KEY` or `TURNSTILE_SECRET_KEY`), so\n * existing non-Turnstile sites are unaffected.\n *\n * Mirrors `verifyTurnstile` in `@emdash-cms/plugin-forms` (not imported —\n * core doesn't depend on plugin packages).\n */\n\nconst SITEVERIFY_URL = \"https://challenges.cloudflare.com/turnstile/v0/siteverify\";\n\n/**\n * Resolve the configured Turnstile secret key, or `\"\"` when Turnstile\n * enforcement is not configured.\n */\nexport function getTurnstileSecretKey(): string {\n\treturn import.meta.env.EMDASH_TURNSTILE_SECRET_KEY || import.meta.env.TURNSTILE_SECRET_KEY || \"\";\n}\n\n/**\n * Verify a Turnstile response token via siteverify.\n *\n * Fails closed: a missing token, a failed verification, and a siteverify\n * transport error all return `false` — when the operator has configured a\n * secret, an unverifiable submission must not be persisted.\n */\nexport async function verifyTurnstileToken(\n\ttoken: string | undefined,\n\tsecretKey: string,\n\tremoteIp?: string | null,\n): Promise<boolean> {\n\tif (!token) return false;\n\n\tconst body: Record<string, string> = { secret: secretKey, response: token };\n\tif (remoteIp) {\n\t\tbody.remoteip = remoteIp;\n\t}\n\n\ttry {\n\t\tconst res = await fetch(SITEVERIFY_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(body),\n\t\t\t// Fail closed *quickly* if siteverify is slow — without a timeout\n\t\t\t// the comment POST would hang until the runtime kills it\n\t\t\tsignal: AbortSignal.timeout(10_000),\n\t\t});\n\t\tconst data: { success?: boolean; \"error-codes\"?: string[] } = await res.json();\n\t\tif (!data.success) {\n\t\t\tconsole.warn(\"[comments] Turnstile verification failed:\", data[\"error-codes\"] ?? []);\n\t\t}\n\t\treturn data.success === true;\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t\"[comments] Turnstile siteverify request failed:\",\n\t\t\terror instanceof Error ? error.message : error,\n\t\t);\n\t\treturn false;\n\t}\n}\n","/**\n * Public comment endpoints\n *\n * GET /_emdash/api/comments/:collection/:contentId - List approved comments\n * POST /_emdash/api/comments/:collection/:contentId - Submit a comment\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { apiError, apiSuccess, handleError, requireDb, unwrapResult } from \"#api/error.js\";\nimport { handleCommentList, checkRateLimit, hashIp } from \"#api/handlers/comments.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { createCommentBody } from \"#api/schemas.js\";\nimport { getSiteBaseUrl } from \"#api/site-url.js\";\nimport { sendCommentNotification } from \"#comments/notifications.js\";\nimport { createComment, type CommentHookRunner } from \"#comments/service.js\";\nimport { getTurnstileSecretKey, verifyTurnstileToken } from \"#comments/turnstile.js\";\nimport { resolveSecretsCached } from \"#config/secrets.js\";\nimport { CommentRepository } from \"#db/repositories/comment.js\";\nimport { validateIdentifier } from \"#db/validate.js\";\nimport { extractRequestMeta } from \"#plugins/request-meta.js\";\nimport type { CollectionCommentSettings, ModerationDecision } from \"#plugins/types.js\";\n\nexport const prerender = false;\n\n/**\n * List approved comments for a content item (public, no auth required)\n */\nexport const GET: APIRoute = async ({ params, url, locals }) => {\n\tconst { emdash } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\n\ttry {\n\t\tconst limit = Math.min(Number(url.searchParams.get(\"limit\") || 50), 100);\n\t\tconst cursor = url.searchParams.get(\"cursor\") ?? undefined;\n\t\tconst threaded = url.searchParams.get(\"threaded\") === \"true\";\n\n\t\t// Check collection exists and has comments enabled\n\t\tconst collectionRow = await emdash.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select([\"comments_enabled\"])\n\t\t\t.where(\"slug\", \"=\", collection)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!collectionRow) {\n\t\t\treturn apiError(\"NOT_FOUND\", `Collection '${collection}' not found`, 404);\n\t\t}\n\n\t\tif (!collectionRow.comments_enabled) {\n\t\t\treturn apiError(\"COMMENTS_DISABLED\", \"Comments are not enabled for this collection\", 403);\n\t\t}\n\n\t\tconst result = await handleCommentList(emdash.db, collection, contentId, {\n\t\t\tlimit,\n\t\t\tcursor,\n\t\t\tthreaded,\n\t\t});\n\n\t\treturn unwrapResult(result);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to list comments\", \"COMMENT_LIST_ERROR\");\n\t}\n};\n\n/**\n * Submit a comment (public, gated by anti-spam checks)\n */\nexport const POST: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash, user } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\n\ttry {\n\t\t// Parse and validate input\n\t\tconst body = await parseBody(request, createCommentBody);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Check collection exists and has comments enabled\n\t\tconst collectionRow = await emdash.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select([\n\t\t\t\t\"comments_enabled\",\n\t\t\t\t\"comments_moderation\",\n\t\t\t\t\"comments_closed_after_days\",\n\t\t\t\t\"comments_auto_approve_users\",\n\t\t\t])\n\t\t\t.where(\"slug\", \"=\", collection)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!collectionRow) {\n\t\t\treturn apiError(\"NOT_FOUND\", `Collection '${collection}' not found`, 404);\n\t\t}\n\n\t\tif (!collectionRow.comments_enabled) {\n\t\t\treturn apiError(\"COMMENTS_DISABLED\", \"Comments are not enabled for this collection\", 403);\n\t\t}\n\n\t\t// Verify the content item exists, is published, and not soft-deleted\n\t\tvalidateIdentifier(collection, \"collection\");\n\t\tconst contentRow = await emdash.db\n\t\t\t.selectFrom(`ec_${collection}` as never)\n\t\t\t.select([\"id\" as never, \"slug\" as never, \"author_id\" as never, \"published_at\" as never])\n\t\t\t.where(\"id\" as never, \"=\", contentId as never)\n\t\t\t.where(\"status\" as never, \"=\", \"published\" as never)\n\t\t\t.where(\"deleted_at\" as never, \"is\", null as never)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!contentRow) {\n\t\t\treturn apiError(\"NOT_FOUND\", \"Content not found\", 404);\n\t\t}\n\n\t\t// Check if comments are closed (published_at + closed_after_days)\n\t\tif (collectionRow.comments_closed_after_days > 0) {\n\t\t\tconst publishedAt = (contentRow as { published_at: string | null }).published_at;\n\t\t\tif (publishedAt) {\n\t\t\t\tconst closedDate = new Date(publishedAt);\n\t\t\t\tclosedDate.setDate(closedDate.getDate() + collectionRow.comments_closed_after_days);\n\t\t\t\tif (new Date() > closedDate) {\n\t\t\t\t\treturn apiError(\"COMMENTS_CLOSED\", \"Comments are closed for this content\", 403);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Anti-spam: Honeypot — hidden field filled only by bots\n\t\tif (body.website_url) {\n\t\t\t// Silently accept — don't reveal the honeypot to bots\n\t\t\treturn apiSuccess({ status: \"pending\", message: \"Comment submitted for review\" });\n\t\t}\n\n\t\t// Anti-spam: Rate limiting\n\t\tconst meta = extractRequestMeta(request, emdash.config);\n\t\tconst { ipSalt } = await resolveSecretsCached(emdash.db);\n\t\tlet ipHash: string;\n\t\tif (meta.ip) {\n\t\t\tipHash = await hashIp(meta.ip, ipSalt);\n\t\t} else {\n\t\t\t// No trusted IP — fail closed by bucketing all unidentifiable\n\t\t\t// requests together. A larger limit reflects the shared bucket.\n\t\t\t//\n\t\t\t// Self-hosted operators behind a reverse proxy should set\n\t\t\t// `trustedProxyHeaders` in the EmDash config (or the\n\t\t\t// EMDASH_TRUSTED_PROXY_HEADERS env var) so this path isn't hit\n\t\t\t// for legitimate traffic. UA-hashing was previously used here\n\t\t\t// but was trivially rotatable — the shared bucket is stricter\n\t\t\t// and forces operators toward a real fix.\n\t\t\tipHash = \"unknown\";\n\t\t}\n\t\tconst unknownBucketLimit = ipHash === \"unknown\" ? 20 : undefined;\n\t\tconst rateLimited = await checkRateLimit(emdash.db, ipHash, unknownBucketLimit);\n\t\tif (rateLimited) {\n\t\t\treturn apiError(\"RATE_LIMITED\", \"Too many comments. Please try again later.\", 429);\n\t\t}\n\n\t\t// Anti-spam: Turnstile — enforced only when the operator configured a\n\t\t// secret key. Runs after the free checks (honeypot, rate limit) so\n\t\t// obvious spam never triggers a siteverify subrequest. Fails closed:\n\t\t// missing token, failed verification, and siteverify errors all reject.\n\t\tconst turnstileSecretKey = getTurnstileSecretKey();\n\t\tif (turnstileSecretKey) {\n\t\t\tconst verified = await verifyTurnstileToken(body.turnstileToken, turnstileSecretKey, meta.ip);\n\t\t\tif (!verified) {\n\t\t\t\treturn apiError(\"TURNSTILE_FAILED\", \"CAPTCHA verification failed\", 403);\n\t\t\t}\n\t\t}\n\n\t\t// Build collection settings\n\t\tconst collectionSettings: CollectionCommentSettings = {\n\t\t\tcommentsEnabled: collectionRow.comments_enabled === 1,\n\t\t\tcommentsModeration:\n\t\t\t\tcollectionRow.comments_moderation as CollectionCommentSettings[\"commentsModeration\"],\n\t\t\tcommentsClosedAfterDays: collectionRow.comments_closed_after_days,\n\t\t\tcommentsAutoApproveUsers: collectionRow.comments_auto_approve_users === 1,\n\t\t};\n\n\t\t// Determine author fields — authenticated user overrides form input\n\t\tlet authorName = body.authorName;\n\t\tlet authorEmail = body.authorEmail;\n\t\tlet authorUserId: string | null = null;\n\n\t\tif (user) {\n\t\t\tauthorName = user.name || authorName;\n\t\t\tauthorEmail = user.email;\n\t\t\tauthorUserId = user.id;\n\t\t}\n\n\t\t// Validate parent exists and belongs to the same content.\n\t\t// Enforce 1-level nesting: if the parent is itself a reply, attach to its root.\n\t\tlet resolvedParentId = body.parentId ?? null;\n\t\tif (body.parentId) {\n\t\t\tconst repo = new CommentRepository(emdash.db);\n\t\t\tconst parent = await repo.findById(body.parentId);\n\t\t\tif (!parent) {\n\t\t\t\treturn apiError(\"VALIDATION_ERROR\", \"Parent comment not found\", 400);\n\t\t\t}\n\t\t\tif (parent.collection !== collection || parent.contentId !== contentId) {\n\t\t\t\treturn apiError(\"VALIDATION_ERROR\", \"Parent comment belongs to different content\", 400);\n\t\t\t}\n\t\t\t// Flatten: if parent is a reply, use its parent (the root) instead\n\t\t\tresolvedParentId = parent.parentId ?? parent.id;\n\t\t}\n\n\t\t// Wire the comment service to the real hook pipeline\n\t\tconst hookRunner: CommentHookRunner = {\n\t\t\tasync runBeforeCreate(event) {\n\t\t\t\treturn emdash.hooks.runCommentBeforeCreate(event);\n\t\t\t},\n\t\t\tasync runModerate(event) {\n\t\t\t\tconst result = await emdash.hooks.invokeExclusiveHook(\"comment:moderate\", event);\n\t\t\t\tif (!result) return { status: \"pending\" as const, reason: \"No moderator configured\" };\n\t\t\t\tif (result.error) {\n\t\t\t\t\tconsole.error(`[comments] Moderation error (${result.pluginId}):`, result.error.message);\n\t\t\t\t\treturn { status: \"pending\" as const, reason: \"Moderation error\" };\n\t\t\t\t}\n\t\t\t\treturn result.result as ModerationDecision;\n\t\t\t},\n\t\t\tfireAfterCreate(event) {\n\t\t\t\temdash.hooks\n\t\t\t\t\t.runCommentAfterCreate(event)\n\t\t\t\t\t.catch((err) =>\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\"[comments] afterCreate error:\",\n\t\t\t\t\t\t\terr instanceof Error ? err.message : err,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t},\n\t\t\tfireAfterModerate(event) {\n\t\t\t\temdash.hooks\n\t\t\t\t\t.runCommentAfterModerate(event)\n\t\t\t\t\t.catch((err) =>\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\"[comments] afterModerate error:\",\n\t\t\t\t\t\t\terr instanceof Error ? err.message : err,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t},\n\t\t};\n\n\t\t// Build content info for afterCreate hooks (e.g. email notifications)\n\t\tconst typedContent = contentRow as {\n\t\t\tid: string;\n\t\t\tslug: string;\n\t\t\tauthor_id: string | null;\n\t\t};\n\t\tlet contentAuthor: { id: string; name: string | null; email: string } | undefined;\n\t\tif (typedContent.author_id) {\n\t\t\tconst authorRow = await emdash.db\n\t\t\t\t.selectFrom(\"users\")\n\t\t\t\t.select([\"id\", \"name\", \"email\", \"email_verified\"])\n\t\t\t\t.where(\"id\", \"=\", typedContent.author_id)\n\t\t\t\t.executeTakeFirst();\n\t\t\tif (authorRow && authorRow.email_verified) {\n\t\t\t\tcontentAuthor = {\n\t\t\t\t\tid: authorRow.id,\n\t\t\t\t\tname: authorRow.name,\n\t\t\t\t\temail: authorRow.email,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tconst result = await createComment(\n\t\t\temdash.db,\n\t\t\t{\n\t\t\t\tcollection,\n\t\t\t\tcontentId,\n\t\t\t\tparentId: resolvedParentId,\n\t\t\t\tauthorName,\n\t\t\t\tauthorEmail,\n\t\t\t\tauthorUserId,\n\t\t\t\tbody: body.body,\n\t\t\t\tipHash,\n\t\t\t\tuserAgent: meta.userAgent,\n\t\t\t},\n\t\t\tcollectionSettings,\n\t\t\thookRunner,\n\t\t\t{\n\t\t\t\tid: typedContent.id,\n\t\t\t\tcollection,\n\t\t\t\tslug: typedContent.slug,\n\t\t\t\tauthor: contentAuthor,\n\t\t\t},\n\t\t);\n\n\t\tif (!result) {\n\t\t\treturn apiError(\"COMMENT_REJECTED\", \"Comment was rejected\", 403);\n\t\t}\n\n\t\t// Send notification to content author (awaited so it completes before\n\t\t// the response is sent — required for Cloudflare Workers where the\n\t\t// isolate terminates after the response).\n\t\tif (result.comment.status === \"approved\" && emdash.email && contentAuthor) {\n\t\t\ttry {\n\t\t\t\tconst adminBaseUrl = await getSiteBaseUrl(emdash.db, request, emdash.config);\n\t\t\t\tawait sendCommentNotification({\n\t\t\t\t\temail: emdash.email,\n\t\t\t\t\tcomment: result.comment,\n\t\t\t\t\tcontentAuthor,\n\t\t\t\t\tadminBaseUrl,\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"[comments] notification error:\", err instanceof Error ? err.message : err);\n\t\t\t}\n\t\t}\n\n\t\treturn apiSuccess(\n\t\t\t{\n\t\t\t\tid: result.comment.id,\n\t\t\t\tstatus: result.comment.status,\n\t\t\t\tmessage:\n\t\t\t\t\tresult.comment.status === \"approved\"\n\t\t\t\t\t\t? \"Comment published\"\n\t\t\t\t\t\t: \"Comment submitted for review\",\n\t\t\t},\n\t\t\t201,\n\t\t);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to submit comment\", \"COMMENT_CREATE_ERROR\");\n\t}\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/comments/[collection]/[contentId]/index.ts"],"sourcesContent":["/**\n * Public comment endpoints\n *\n * GET /_emdash/api/comments/:collection/:contentId - List approved comments\n * POST /_emdash/api/comments/:collection/:contentId - Submit a comment\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { apiError, handleError, requireDb, unwrapResult } from \"#api/error.js\";\nimport { handleCommentList } from \"#api/handlers/comments.js\";\nimport { submitPublicComment } from \"#comments/public-submission.js\";\n\nexport const prerender = false;\n\n/**\n * List approved comments for a content item (public, no auth required)\n */\nexport const GET: APIRoute = async ({ params, url, locals }) => {\n\tconst { emdash } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\n\ttry {\n\t\tconst limit = Math.min(Number(url.searchParams.get(\"limit\") || 50), 100);\n\t\tconst cursor = url.searchParams.get(\"cursor\") ?? undefined;\n\t\tconst threaded = url.searchParams.get(\"threaded\") === \"true\";\n\n\t\t// Check collection exists and has comments enabled\n\t\tconst collectionRow = await emdash.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select([\"comments_enabled\"])\n\t\t\t.where(\"slug\", \"=\", collection)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!collectionRow) {\n\t\t\treturn apiError(\"NOT_FOUND\", `Collection '${collection}' not found`, 404);\n\t\t}\n\n\t\tif (!collectionRow.comments_enabled) {\n\t\t\treturn apiError(\"COMMENTS_DISABLED\", \"Comments are not enabled for this collection\", 403);\n\t\t}\n\n\t\tconst result = await handleCommentList(emdash.db, collection, contentId, {\n\t\t\tlimit,\n\t\t\tcursor,\n\t\t\tthreaded,\n\t\t});\n\n\t\treturn unwrapResult(result);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to list comments\", \"COMMENT_LIST_ERROR\");\n\t}\n};\n\n/**\n * Submit a comment (public, gated by anti-spam checks)\n */\nexport const POST: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash, user } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\treturn submitPublicComment(emdash, collection, contentId, request, user);\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,MAAa,YAAY;;;;AAKzB,MAAa,MAAgB,OAAO,EAAE,QAAQ,KAAK,aAAa;CAC/D,MAAM,EAAE,WAAW;CACnB,MAAM,EAAE,YAAY,cAAc;AAElC,KAAI,CAAC,cAAc,CAAC,UACnB,QAAO,SAAS,oBAAoB,sCAAsC,IAAI;CAG/E,MAAM,QAAQ,UAAU,QAAQ,GAAG;AACnC,KAAI,MAAO,QAAO;AAElB,KAAI;EACH,MAAM,QAAQ,KAAK,IAAI,OAAO,IAAI,aAAa,IAAI,QAAQ,IAAI,GAAG,EAAE,IAAI;EACxE,MAAM,SAAS,IAAI,aAAa,IAAI,SAAS,IAAI;EACjD,MAAM,WAAW,IAAI,aAAa,IAAI,WAAW,KAAK;EAGtD,MAAM,gBAAgB,MAAM,OAAO,GACjC,WAAW,sBAAsB,CACjC,OAAO,CAAC,mBAAmB,CAAC,CAC5B,MAAM,QAAQ,KAAK,WAAW,CAC9B,kBAAkB;AAEpB,MAAI,CAAC,cACJ,QAAO,SAAS,aAAa,eAAe,WAAW,cAAc,IAAI;AAG1E,MAAI,CAAC,cAAc,iBAClB,QAAO,SAAS,qBAAqB,gDAAgD,IAAI;AAS1F,SAAO,aANQ,MAAM,kBAAkB,OAAO,IAAI,YAAY,WAAW;GACxE;GACA;GACA;GACA,CAAC,CAEyB;UACnB,OAAO;AACf,SAAO,YAAY,OAAO,2BAA2B,qBAAqB;;;;;;AAO5E,MAAa,OAAiB,OAAO,EAAE,QAAQ,SAAS,aAAa;CACpE,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,EAAE,YAAY,cAAc;AAElC,KAAI,CAAC,cAAc,CAAC,UACnB,QAAO,SAAS,oBAAoB,sCAAsC,IAAI;CAG/E,MAAM,QAAQ,UAAU,QAAQ,GAAG;AACnC,KAAI,MAAO,QAAO;AAClB,QAAO,oBAAoB,QAAQ,YAAY,WAAW,SAAS,KAAK"}
@@ -1,21 +1,22 @@
1
- import "../../../../../../config-C3EBstHi.mjs";
2
- import "../../../../../../after-CBU2vkoO.mjs";
3
- import { l as invalidateCommentObjectCache } from "../../../../../../object-cache-DVKnyOfy.mjs";
4
- import "../../../../../../base64-CvLhUKQv.mjs";
5
- import "../../../../../../types-CQPWhPxE.mjs";
6
- import "../../../../../../comment-vxOzWbZN.mjs";
7
- import "../../../../../../options-BHPeIbBd.mjs";
8
- import { a as unwrapResult, i as requireDb, n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-DFrQjppn.mjs";
9
- import { n as parseBody, t as isParseError } from "../../../../../../parse-Ckpg-Qfp.mjs";
10
- import "../../../../../../media-BHjus86Y.mjs";
11
- import { Tt as createReactionBody } from "../../../../../../redirects-BLNOWQTn.mjs";
12
- import "../../../../../../relations-C4htk5sb.mjs";
13
- import "../../../../../../status-B777-dXz.mjs";
1
+ import "../../../../../../config-CGVeT8Hc.mjs";
2
+ import "../../../../../../after-PcEvMY_6.mjs";
3
+ import "../../../../../../options-D5WcorD5.mjs";
4
+ import "../../../../../../base64-DvnNgP7e.mjs";
5
+ import { a as resolveSecretsCached } from "../../../../../../secrets-DNgVgz_e.mjs";
6
+ import { l as invalidateCommentObjectCache } from "../../../../../../object-cache-DlSVbn5Y.mjs";
7
+ import "../../../../../../types-BkUg2yHx.mjs";
8
+ import "../../../../../../comment-DcT8qdPK.mjs";
9
+ import { a as unwrapResult, i as requireDb, n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CCTCskie.mjs";
10
+ import { n as parseBody, t as isParseError } from "../../../../../../parse-Cr379Av9.mjs";
11
+ import "../../../../../../redirects-BCiTaIQ-.mjs";
12
+ import "../../../../../../entry-lock-D3C99MXS.mjs";
13
+ import { l as createReactionBody } from "../../../../../../comments-BVzzt6x5.mjs";
14
+ import "../../../../../../relations-B4w-G5U9.mjs";
15
+ import "../../../../../../status-DLoBmcDz.mjs";
14
16
  import "../../../../../../api/schemas/index.mjs";
15
- import { t as extractRequestMeta } from "../../../../../../request-meta-DYxLlnmz.mjs";
16
- import { t as CommentReactionRepository } from "../../../../../../comment-reaction-BhrvSHml.mjs";
17
- import { i as resolveSecretsCached } from "../../../../../../secrets-rEtHt-6z.mjs";
18
- import { c as hashIp } from "../../../../../../comments-Ct4ensnf.mjs";
17
+ import { t as extractRequestMeta } from "../../../../../../request-meta-C8yl_sIs.mjs";
18
+ import { t as CommentReactionRepository } from "../../../../../../comment-reaction-DY5-y8Y5.mjs";
19
+ import { c as hashIp } from "../../../../../../comments-B67VRNGw.mjs";
19
20
 
20
21
  //#region src/api/handlers/comment-reactions.ts
21
22
  /** Max reactions a single voter may register per window before throttling. */
@@ -1 +1 @@
1
- {"version":3,"file":"reactions.mjs","names":[],"sources":["../../../../../../../src/api/handlers/comment-reactions.ts","../../../../../../../src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts"],"sourcesContent":["/**\n * Comment reaction handlers (Tier 1 of the best-in-class comments RFC).\n *\n * Business logic for toggling reactions and reading aggregate counts. Route\n * files stay thin wrappers; these return `ApiResult<T>`.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport {\n\tCommentReactionRepository,\n\ttype ReactionCounts,\n} from \"#db/repositories/comment-reaction.js\";\nimport type { Database } from \"#db/types.js\";\n\nimport { invalidateCommentObjectCache } from \"../../object-cache/index.js\";\nimport type { ApiResult } from \"../types.js\";\n\n/** Max reactions a single voter may register per window before throttling. */\nconst REACTION_RATE_LIMIT = 30;\nconst REACTION_RATE_WINDOW_MINUTES = 10;\n\n/**\n * Reactions the system accepts. Positive-only for now (matches the shipped\n * widget); kept as an allowlist so a voter can't spam arbitrary reaction\n * strings and bloat a comment's count map. Extend (or make configurable) as\n * the UI grows.\n */\nconst ALLOWED_REACTIONS: ReadonlySet<string> = new Set([\"like\"]);\n\nexport interface ReactionToggleResult {\n\tcommentId: string;\n\treaction: string;\n\t/** true if the reaction was added, false if an existing one was removed */\n\treacted: boolean;\n\t/** updated counts for this comment after the toggle */\n\tcounts: ReactionCounts;\n}\n\nexport interface ReactionCountsResult {\n\t/** comment id -> reaction counts */\n\treactions: Record<string, ReactionCounts>;\n\t/** comment id -> reactions the current voter has active (omitted if anonymous) */\n\tviewer?: Record<string, string[]>;\n}\n\n/**\n * Toggle a reaction for a voter on an approved comment belonging to the given\n * content item. Rate-limited per voter.\n */\nexport async function handleReactionToggle(\n\tdb: Kysely<Database>,\n\tparams: {\n\t\tcollection: string;\n\t\tcontentId: string;\n\t\tcommentId: string;\n\t\treaction: string;\n\t\tvoterHash: string;\n\t},\n): Promise<ApiResult<ReactionToggleResult>> {\n\ttry {\n\t\tconst { collection, contentId, commentId, reaction, voterHash } = params;\n\n\t\tif (!ALLOWED_REACTIONS.has(reaction)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"VALIDATION_ERROR\", message: \"Unsupported reaction\" },\n\t\t\t};\n\t\t}\n\n\t\t// The comment must exist, be approved, and belong to this content item.\n\t\tconst comment = await db\n\t\t\t.selectFrom(\"_emdash_comments\")\n\t\t\t.select([\"id\", \"status\"])\n\t\t\t.where(\"id\", \"=\", commentId)\n\t\t\t.where(\"collection\", \"=\", collection)\n\t\t\t.where(\"content_id\", \"=\", contentId)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!comment) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Comment not found\" } };\n\t\t}\n\t\tif (comment.status !== \"approved\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"COMMENT_NOT_APPROVED\", message: \"Cannot react to this comment\" },\n\t\t\t};\n\t\t}\n\n\t\tconst repo = new CommentReactionRepository(db);\n\n\t\tconst recent = await repo.countRecentByVoter(voterHash, REACTION_RATE_WINDOW_MINUTES);\n\t\tif (recent >= REACTION_RATE_LIMIT) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"RATE_LIMITED\", message: \"Too many reactions. Please try again later.\" },\n\t\t\t};\n\t\t}\n\n\t\tconst { reacted } = await repo.toggle({ commentId, reaction, voterHash });\n\t\tconst countsMap = await repo.countsForComments([commentId]);\n\n\t\t// Reaction counts (and `best` ordering) are folded into cached getComments\n\t\t// reads, so a toggle must orphan them.\n\t\tinvalidateCommentObjectCache();\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { commentId, reaction, reacted, counts: countsMap.get(commentId) ?? {} },\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"REACTION_TOGGLE_ERROR\", message: \"Failed to toggle reaction\" },\n\t\t};\n\t}\n}\n\n/**\n * Read aggregate reaction counts for every approved comment on a content item,\n * plus (optionally) which reactions the current voter has active.\n */\nexport async function handleReactionCounts(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tcontentId: string,\n\tvoterHash?: string,\n): Promise<ApiResult<ReactionCountsResult>> {\n\ttry {\n\t\tconst comments = await db\n\t\t\t.selectFrom(\"_emdash_comments\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"collection\", \"=\", collection)\n\t\t\t.where(\"content_id\", \"=\", contentId)\n\t\t\t.where(\"status\", \"=\", \"approved\")\n\t\t\t.execute();\n\n\t\tconst ids = comments.map((c) => c.id);\n\t\tconst repo = new CommentReactionRepository(db);\n\n\t\tconst countsMap = await repo.countsForComments(ids);\n\t\tconst reactions: Record<string, ReactionCounts> = {};\n\t\tfor (const [id, counts] of countsMap) {\n\t\t\treactions[id] = counts;\n\t\t}\n\n\t\tconst data: ReactionCountsResult = { reactions };\n\n\t\tif (voterHash) {\n\t\t\tconst viewerMap = await repo.viewerReactions(ids, voterHash);\n\t\t\tconst viewer: Record<string, string[]> = {};\n\t\t\tfor (const [id, list] of viewerMap) {\n\t\t\t\tviewer[id] = list;\n\t\t\t}\n\t\t\tdata.viewer = viewer;\n\t\t}\n\n\t\treturn { success: true, data };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"REACTION_COUNTS_ERROR\", message: \"Failed to read reactions\" },\n\t\t};\n\t}\n}\n","/**\n * Public comment reaction endpoints (Tier 1 of the best-in-class comments RFC).\n *\n * GET /_emdash/api/comments/:collection/:contentId/reactions\n * - Aggregate reaction counts for the content's approved comments, plus the\n * current visitor's active reactions.\n * POST /_emdash/api/comments/:collection/:contentId/reactions\n * - Toggle a reaction on a comment. Public, honeypot- and rate-limit-gated.\n *\n * Inherits the `/_emdash/api/comments/` public prefix (no auth); the POST still\n * requires the `X-EmDash-Request: 1` CSRF header like the comment POST.\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { apiError, apiSuccess, handleError, requireDb, unwrapResult } from \"#api/error.js\";\nimport { handleReactionCounts, handleReactionToggle } from \"#api/handlers/comment-reactions.js\";\nimport { hashIp } from \"#api/handlers/comments.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { createReactionBody } from \"#api/schemas.js\";\nimport { resolveSecretsCached } from \"#config/secrets.js\";\nimport { extractRequestMeta } from \"#plugins/request-meta.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\n\ttry {\n\t\t// Salted voter hash from request IP (same primitive as comment ip_hash).\n\t\t// Behind Cloudflare (CF-Connecting-IP) or a configured trusted proxy this\n\t\t// is per-visitor. Without a trusted IP it collapses to a shared \"unknown\"\n\t\t// bucket, so reaction dedup degrades for those visitors — a real\n\t\t// per-visitor token is Tier 2 (visitor identity). Operators should set\n\t\t// trustedProxyHeaders; see the comment ingest route for the same note.\n\t\tconst meta = extractRequestMeta(request, emdash.config);\n\t\tlet voterHash = \"unknown\";\n\t\tif (meta.ip) {\n\t\t\tconst { ipSalt } = await resolveSecretsCached(emdash.db);\n\t\t\tvoterHash = await hashIp(meta.ip, ipSalt);\n\t\t}\n\n\t\tconst result = await handleReactionCounts(emdash.db, collection, contentId, voterHash);\n\t\treturn unwrapResult(result);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to read reactions\", \"REACTION_COUNTS_ERROR\");\n\t}\n};\n\nexport const POST: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\n\ttry {\n\t\tconst body = await parseBody(request, createReactionBody);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Anti-spam: honeypot — hidden field filled only by bots. Silently accept.\n\t\tif (body.website_url) {\n\t\t\treturn apiSuccess({ reacted: false, counts: {} });\n\t\t}\n\n\t\tconst meta = extractRequestMeta(request, emdash.config);\n\t\tlet voterHash = \"unknown\";\n\t\tif (meta.ip) {\n\t\t\tconst { ipSalt } = await resolveSecretsCached(emdash.db);\n\t\t\tvoterHash = await hashIp(meta.ip, ipSalt);\n\t\t}\n\n\t\tconst result = await handleReactionToggle(emdash.db, {\n\t\t\tcollection,\n\t\t\tcontentId,\n\t\t\tcommentId: body.commentId,\n\t\t\treaction: body.reaction,\n\t\t\tvoterHash,\n\t\t});\n\n\t\treturn unwrapResult(result, 200);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to toggle reaction\", \"REACTION_TOGGLE_ERROR\");\n\t}\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"reactions.mjs","names":[],"sources":["../../../../../../../src/api/handlers/comment-reactions.ts","../../../../../../../src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts"],"sourcesContent":["/**\n * Comment reaction handlers (Tier 1 of the best-in-class comments RFC).\n *\n * Business logic for toggling reactions and reading aggregate counts. Route\n * files stay thin wrappers; these return `ApiResult<T>`.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport {\n\tCommentReactionRepository,\n\ttype ReactionCounts,\n} from \"#db/repositories/comment-reaction.js\";\nimport type { Database } from \"#db/types.js\";\n\nimport { invalidateCommentObjectCache } from \"../../object-cache/index.js\";\nimport type { ApiResult } from \"../types.js\";\n\n/** Max reactions a single voter may register per window before throttling. */\nconst REACTION_RATE_LIMIT = 30;\nconst REACTION_RATE_WINDOW_MINUTES = 10;\n\n/**\n * Reactions the system accepts. Positive-only for now (matches the shipped\n * widget); kept as an allowlist so a voter can't spam arbitrary reaction\n * strings and bloat a comment's count map. Extend (or make configurable) as\n * the UI grows.\n */\nconst ALLOWED_REACTIONS: ReadonlySet<string> = new Set([\"like\"]);\n\nexport interface ReactionToggleResult {\n\tcommentId: string;\n\treaction: string;\n\t/** true if the reaction was added, false if an existing one was removed */\n\treacted: boolean;\n\t/** updated counts for this comment after the toggle */\n\tcounts: ReactionCounts;\n}\n\nexport interface ReactionCountsResult {\n\t/** comment id -> reaction counts */\n\treactions: Record<string, ReactionCounts>;\n\t/** comment id -> reactions the current voter has active (omitted if anonymous) */\n\tviewer?: Record<string, string[]>;\n}\n\n/**\n * Toggle a reaction for a voter on an approved comment belonging to the given\n * content item. Rate-limited per voter.\n */\nexport async function handleReactionToggle(\n\tdb: Kysely<Database>,\n\tparams: {\n\t\tcollection: string;\n\t\tcontentId: string;\n\t\tcommentId: string;\n\t\treaction: string;\n\t\tvoterHash: string;\n\t},\n): Promise<ApiResult<ReactionToggleResult>> {\n\ttry {\n\t\tconst { collection, contentId, commentId, reaction, voterHash } = params;\n\n\t\tif (!ALLOWED_REACTIONS.has(reaction)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"VALIDATION_ERROR\", message: \"Unsupported reaction\" },\n\t\t\t};\n\t\t}\n\n\t\t// The comment must exist, be approved, and belong to this content item.\n\t\tconst comment = await db\n\t\t\t.selectFrom(\"_emdash_comments\")\n\t\t\t.select([\"id\", \"status\"])\n\t\t\t.where(\"id\", \"=\", commentId)\n\t\t\t.where(\"collection\", \"=\", collection)\n\t\t\t.where(\"content_id\", \"=\", contentId)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!comment) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Comment not found\" } };\n\t\t}\n\t\tif (comment.status !== \"approved\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"COMMENT_NOT_APPROVED\", message: \"Cannot react to this comment\" },\n\t\t\t};\n\t\t}\n\n\t\tconst repo = new CommentReactionRepository(db);\n\n\t\tconst recent = await repo.countRecentByVoter(voterHash, REACTION_RATE_WINDOW_MINUTES);\n\t\tif (recent >= REACTION_RATE_LIMIT) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"RATE_LIMITED\", message: \"Too many reactions. Please try again later.\" },\n\t\t\t};\n\t\t}\n\n\t\tconst { reacted } = await repo.toggle({ commentId, reaction, voterHash });\n\t\tconst countsMap = await repo.countsForComments([commentId]);\n\n\t\t// Reaction counts (and `best` ordering) are folded into cached getComments\n\t\t// reads, so a toggle must orphan them.\n\t\tinvalidateCommentObjectCache();\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { commentId, reaction, reacted, counts: countsMap.get(commentId) ?? {} },\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"REACTION_TOGGLE_ERROR\", message: \"Failed to toggle reaction\" },\n\t\t};\n\t}\n}\n\n/**\n * Read aggregate reaction counts for every approved comment on a content item,\n * plus (optionally) which reactions the current voter has active.\n */\nexport async function handleReactionCounts(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tcontentId: string,\n\tvoterHash?: string,\n): Promise<ApiResult<ReactionCountsResult>> {\n\ttry {\n\t\tconst comments = await db\n\t\t\t.selectFrom(\"_emdash_comments\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"collection\", \"=\", collection)\n\t\t\t.where(\"content_id\", \"=\", contentId)\n\t\t\t.where(\"status\", \"=\", \"approved\")\n\t\t\t.execute();\n\n\t\tconst ids = comments.map((c) => c.id);\n\t\tconst repo = new CommentReactionRepository(db);\n\n\t\tconst countsMap = await repo.countsForComments(ids);\n\t\tconst reactions: Record<string, ReactionCounts> = {};\n\t\tfor (const [id, counts] of countsMap) {\n\t\t\treactions[id] = counts;\n\t\t}\n\n\t\tconst data: ReactionCountsResult = { reactions };\n\n\t\tif (voterHash) {\n\t\t\tconst viewerMap = await repo.viewerReactions(ids, voterHash);\n\t\t\tconst viewer: Record<string, string[]> = {};\n\t\t\tfor (const [id, list] of viewerMap) {\n\t\t\t\tviewer[id] = list;\n\t\t\t}\n\t\t\tdata.viewer = viewer;\n\t\t}\n\n\t\treturn { success: true, data };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"REACTION_COUNTS_ERROR\", message: \"Failed to read reactions\" },\n\t\t};\n\t}\n}\n","/**\n * Public comment reaction endpoints (Tier 1 of the best-in-class comments RFC).\n *\n * GET /_emdash/api/comments/:collection/:contentId/reactions\n * - Aggregate reaction counts for the content's approved comments, plus the\n * current visitor's active reactions.\n * POST /_emdash/api/comments/:collection/:contentId/reactions\n * - Toggle a reaction on a comment. Public, honeypot- and rate-limit-gated.\n *\n * Inherits the `/_emdash/api/comments/` public prefix (no auth); the POST still\n * requires the `X-EmDash-Request: 1` CSRF header like the comment POST.\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { apiError, apiSuccess, handleError, requireDb, unwrapResult } from \"#api/error.js\";\nimport { handleReactionCounts, handleReactionToggle } from \"#api/handlers/comment-reactions.js\";\nimport { hashIp } from \"#api/handlers/comments.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { createReactionBody } from \"#api/schemas.js\";\nimport { resolveSecretsCached } from \"#config/secrets.js\";\nimport { extractRequestMeta } from \"#plugins/request-meta.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\n\ttry {\n\t\t// Salted voter hash from request IP (same primitive as comment ip_hash).\n\t\t// Behind Cloudflare (CF-Connecting-IP) or a configured trusted proxy this\n\t\t// is per-visitor. Without a trusted IP it collapses to a shared \"unknown\"\n\t\t// bucket, so reaction dedup degrades for those visitors — a real\n\t\t// per-visitor token is Tier 2 (visitor identity). Operators should set\n\t\t// trustedProxyHeaders; see the comment ingest route for the same note.\n\t\tconst meta = extractRequestMeta(request, emdash.config);\n\t\tlet voterHash = \"unknown\";\n\t\tif (meta.ip) {\n\t\t\tconst { ipSalt } = await resolveSecretsCached(emdash.db);\n\t\t\tvoterHash = await hashIp(meta.ip, ipSalt);\n\t\t}\n\n\t\tconst result = await handleReactionCounts(emdash.db, collection, contentId, voterHash);\n\t\treturn unwrapResult(result);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to read reactions\", \"REACTION_COUNTS_ERROR\");\n\t}\n};\n\nexport const POST: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash } = locals;\n\tconst { collection, contentId } = params;\n\n\tif (!collection || !contentId) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Collection and content ID required\", 400);\n\t}\n\n\tconst dbErr = requireDb(emdash?.db);\n\tif (dbErr) return dbErr;\n\n\ttry {\n\t\tconst body = await parseBody(request, createReactionBody);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Anti-spam: honeypot — hidden field filled only by bots. Silently accept.\n\t\tif (body.website_url) {\n\t\t\treturn apiSuccess({ reacted: false, counts: {} });\n\t\t}\n\n\t\tconst meta = extractRequestMeta(request, emdash.config);\n\t\tlet voterHash = \"unknown\";\n\t\tif (meta.ip) {\n\t\t\tconst { ipSalt } = await resolveSecretsCached(emdash.db);\n\t\t\tvoterHash = await hashIp(meta.ip, ipSalt);\n\t\t}\n\n\t\tconst result = await handleReactionToggle(emdash.db, {\n\t\t\tcollection,\n\t\t\tcontentId,\n\t\t\tcommentId: body.commentId,\n\t\t\treaction: body.reaction,\n\t\t\tvoterHash,\n\t\t});\n\n\t\treturn unwrapResult(result, 200);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to toggle reaction\", \"REACTION_TOGGLE_ERROR\");\n\t}\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import "../../../../../../base64-CvLhUKQv.mjs";
2
- import "../../../../../../types-CQPWhPxE.mjs";
3
- import { a as unwrapResult, t as apiError } from "../../../../../../error-DFrQjppn.mjs";
4
- import { r as requirePerm } from "../../../../../../authorize-Bkf_UHhD.mjs";
1
+ import "../../../../../../base64-DvnNgP7e.mjs";
2
+ import "../../../../../../types-BkUg2yHx.mjs";
3
+ import { a as unwrapResult, t as apiError } from "../../../../../../error-CCTCskie.mjs";
4
+ import { r as requirePerm } from "../../../../../../authorize-BXpfMpp0.mjs";
5
5
 
6
6
  //#region src/astro/routes/api/content/[collection]/[id]/compare.ts
7
7
  const prerender = false;
@@ -1 +1 @@
1
- {"version":3,"file":"discard-draft.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/discard-draft.ts"],"mappings":";;;cAaa,SAAA;AAAA,cAEA,IAAA,EAAM,QAAA"}
1
+ {"version":3,"file":"discard-draft.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/discard-draft.ts"],"mappings":";;;cAca,SAAA;AAAA,cAEA,IAAA,EAAM,QAAA"}
@@ -1,15 +1,19 @@
1
- import "../../../../../../config-C3EBstHi.mjs";
2
- import "../../../../../../base64-CvLhUKQv.mjs";
3
- import "../../../../../../types-CQPWhPxE.mjs";
4
- import { n as mapErrorStatus } from "../../../../../../errors-DsVoDUjJ.mjs";
5
- import { a as unwrapResult, t as apiError } from "../../../../../../error-DFrQjppn.mjs";
6
- import { r as parseOptionalBody, t as isParseError } from "../../../../../../parse-Ckpg-Qfp.mjs";
7
- import "../../../../../../media-BHjus86Y.mjs";
8
- import { rn as contentRevisionConditionBody } from "../../../../../../redirects-BLNOWQTn.mjs";
9
- import "../../../../../../relations-C4htk5sb.mjs";
10
- import "../../../../../../status-B777-dXz.mjs";
1
+ import "../../../../../../dialect-helpers-CtYdsX4W.mjs";
2
+ import "../../../../../../config-CGVeT8Hc.mjs";
3
+ import "../../../../../../base64-DvnNgP7e.mjs";
4
+ import "../../../../../../types-BkUg2yHx.mjs";
5
+ import "../../../../../../entry-locks-CO_KaoU5.mjs";
6
+ import { n as mapErrorStatus } from "../../../../../../errors-W3PA8HqB.mjs";
7
+ import { a as unwrapResult, t as apiError } from "../../../../../../error-CCTCskie.mjs";
8
+ import { r as parseOptionalBody, t as isParseError } from "../../../../../../parse-Cr379Av9.mjs";
9
+ import "../../../../../../redirects-BCiTaIQ-.mjs";
10
+ import { $n as contentRevisionConditionBody } from "../../../../../../entry-lock-D3C99MXS.mjs";
11
+ import "../../../../../../comments-BVzzt6x5.mjs";
12
+ import "../../../../../../relations-B4w-G5U9.mjs";
13
+ import "../../../../../../status-DLoBmcDz.mjs";
11
14
  import "../../../../../../api/schemas/index.mjs";
12
- import { n as requireOwnerPerm } from "../../../../../../authorize-Bkf_UHhD.mjs";
15
+ import { n as requireOwnerPerm } from "../../../../../../authorize-BXpfMpp0.mjs";
16
+ import { t as claimEntryLockForWrite } from "../../../../../../entry-lock-D9rnj2Lu.mjs";
13
17
 
14
18
  //#region src/astro/routes/api/content/[collection]/[id]/discard-draft.ts
15
19
  const prerender = false;
@@ -28,6 +32,8 @@ const POST = async ({ params, request, locals, url, cache }) => {
28
32
  const denied = requireOwnerPerm(user, typeof existingItem?.authorId === "string" ? existingItem.authorId : "", "content:edit_own", "content:edit_any");
29
33
  if (denied) return denied;
30
34
  const resolvedId = typeof existingItem?.id === "string" ? existingItem.id : id;
35
+ const refusal = await claimEntryLockForWrite(emdash.db, collection, resolvedId, user.id, { override: body?.overrideLock });
36
+ if (refusal) return apiError(refusal.code, refusal.message, mapErrorStatus(refusal.code), { ...refusal.details });
31
37
  const result = await emdash.handleContentDiscardDraft(collection, resolvedId, { _rev: body?._rev });
32
38
  if (!result.success) return unwrapResult(result);
33
39
  if (cache?.enabled) await cache.invalidate({ tags: [collection, resolvedId] });
@@ -1 +1 @@
1
- {"version":3,"file":"discard-draft.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/discard-draft.ts"],"sourcesContent":["/**\n * Discard draft changes - reverts to live version\n *\n * POST /_emdash/api/content/{collection}/{id}/discard-draft\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requireOwnerPerm } from \"#api/authorize.js\";\nimport { apiError, mapErrorStatus, unwrapResult } from \"#api/error.js\";\nimport { isParseError, parseOptionalBody } from \"#api/parse.js\";\nimport { contentRevisionConditionBody } from \"#api/schemas.js\";\n\nexport const prerender = false;\n\nexport const POST: APIRoute = async ({ params, request, locals, url, cache }) => {\n\tconst { emdash, user } = locals;\n\tconst collection = params.collection!;\n\tconst id = params.id!;\n\n\tif (!emdash?.handleContentDiscardDraft || !emdash?.handleContentGet) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\tconst body = await parseOptionalBody(request, contentRevisionConditionBody, {});\n\tif (isParseError(body)) return body;\n\n\tconst locale = url.searchParams.get(\"locale\") || undefined;\n\n\t// Fetch item to check ownership\n\tconst existing = await emdash.handleContentGet(collection, id, locale);\n\tif (!existing.success) {\n\t\treturn apiError(\n\t\t\texisting.error?.code ?? \"UNKNOWN_ERROR\",\n\t\t\texisting.error?.message ?? \"Unknown error\",\n\t\t\tmapErrorStatus(existing.error?.code),\n\t\t);\n\t}\n\tconst existingData =\n\t\texisting.data && typeof existing.data === \"object\"\n\t\t\t? // eslint-disable-next-line typescript/no-unsafe-type-assertion -- handler returns unknown data; narrowed by typeof check above\n\t\t\t\t(existing.data as Record<string, unknown>)\n\t\t\t: undefined;\n\t// Handler returns { item, _rev } — extract the item for ownership check\n\tconst existingItem =\n\t\texistingData?.item && typeof existingData.item === \"object\"\n\t\t\t? // eslint-disable-next-line typescript/no-unsafe-type-assertion -- narrowed by typeof check above\n\t\t\t\t(existingData.item as Record<string, unknown>)\n\t\t\t: existingData;\n\tconst authorId = typeof existingItem?.authorId === \"string\" ? existingItem.authorId : \"\";\n\tconst denied = requireOwnerPerm(user, authorId, \"content:edit_own\", \"content:edit_any\");\n\tif (denied) return denied;\n\n\tconst resolvedId = typeof existingItem?.id === \"string\" ? existingItem.id : id;\n\n\tconst result = await emdash.handleContentDiscardDraft(collection, resolvedId, {\n\t\t_rev: body?._rev,\n\t});\n\n\tif (!result.success) return unwrapResult(result);\n\n\tif (cache?.enabled) await cache.invalidate({ tags: [collection, resolvedId] });\n\n\treturn unwrapResult(result);\n};\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,YAAY;AAEzB,MAAa,OAAiB,OAAO,EAAE,QAAQ,SAAS,QAAQ,KAAK,YAAY;CAChF,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,aAAa,OAAO;CAC1B,MAAM,KAAK,OAAO;AAElB,KAAI,CAAC,QAAQ,6BAA6B,CAAC,QAAQ,iBAClD,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAEpE,MAAM,OAAO,MAAM,kBAAkB,SAAS,8BAA8B,EAAE,CAAC;AAC/E,KAAI,aAAa,KAAK,CAAE,QAAO;CAE/B,MAAM,SAAS,IAAI,aAAa,IAAI,SAAS,IAAI;CAGjD,MAAM,WAAW,MAAM,OAAO,iBAAiB,YAAY,IAAI,OAAO;AACtE,KAAI,CAAC,SAAS,QACb,QAAO,SACN,SAAS,OAAO,QAAQ,iBACxB,SAAS,OAAO,WAAW,iBAC3B,eAAe,SAAS,OAAO,KAAK,CACpC;CAEF,MAAM,eACL,SAAS,QAAQ,OAAO,SAAS,SAAS,WAEvC,SAAS,OACT;CAEJ,MAAM,eACL,cAAc,QAAQ,OAAO,aAAa,SAAS,WAEhD,aAAa,OACb;CAEJ,MAAM,SAAS,iBAAiB,MADf,OAAO,cAAc,aAAa,WAAW,aAAa,WAAW,IACtC,oBAAoB,mBAAmB;AACvF,KAAI,OAAQ,QAAO;CAEnB,MAAM,aAAa,OAAO,cAAc,OAAO,WAAW,aAAa,KAAK;CAE5E,MAAM,SAAS,MAAM,OAAO,0BAA0B,YAAY,YAAY,EAC7E,MAAM,MAAM,MACZ,CAAC;AAEF,KAAI,CAAC,OAAO,QAAS,QAAO,aAAa,OAAO;AAEhD,KAAI,OAAO,QAAS,OAAM,MAAM,WAAW,EAAE,MAAM,CAAC,YAAY,WAAW,EAAE,CAAC;AAE9E,QAAO,aAAa,OAAO"}
1
+ {"version":3,"file":"discard-draft.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/discard-draft.ts"],"sourcesContent":["/**\n * Discard draft changes - reverts to live version\n *\n * POST /_emdash/api/content/{collection}/{id}/discard-draft\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requireOwnerPerm } from \"#api/authorize.js\";\nimport { apiError, mapErrorStatus, unwrapResult } from \"#api/error.js\";\nimport { claimEntryLockForWrite } from \"#api/handlers/entry-lock.js\";\nimport { isParseError, parseOptionalBody } from \"#api/parse.js\";\nimport { contentRevisionConditionBody } from \"#api/schemas.js\";\n\nexport const prerender = false;\n\nexport const POST: APIRoute = async ({ params, request, locals, url, cache }) => {\n\tconst { emdash, user } = locals;\n\tconst collection = params.collection!;\n\tconst id = params.id!;\n\n\tif (!emdash?.handleContentDiscardDraft || !emdash?.handleContentGet) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\tconst body = await parseOptionalBody(request, contentRevisionConditionBody, {});\n\tif (isParseError(body)) return body;\n\n\tconst locale = url.searchParams.get(\"locale\") || undefined;\n\n\t// Fetch item to check ownership\n\tconst existing = await emdash.handleContentGet(collection, id, locale);\n\tif (!existing.success) {\n\t\treturn apiError(\n\t\t\texisting.error?.code ?? \"UNKNOWN_ERROR\",\n\t\t\texisting.error?.message ?? \"Unknown error\",\n\t\t\tmapErrorStatus(existing.error?.code),\n\t\t);\n\t}\n\tconst existingData =\n\t\texisting.data && typeof existing.data === \"object\"\n\t\t\t? // eslint-disable-next-line typescript/no-unsafe-type-assertion -- handler returns unknown data; narrowed by typeof check above\n\t\t\t\t(existing.data as Record<string, unknown>)\n\t\t\t: undefined;\n\t// Handler returns { item, _rev } — extract the item for ownership check\n\tconst existingItem =\n\t\texistingData?.item && typeof existingData.item === \"object\"\n\t\t\t? // eslint-disable-next-line typescript/no-unsafe-type-assertion -- narrowed by typeof check above\n\t\t\t\t(existingData.item as Record<string, unknown>)\n\t\t\t: existingData;\n\tconst authorId = typeof existingItem?.authorId === \"string\" ? existingItem.authorId : \"\";\n\tconst denied = requireOwnerPerm(user, authorId, \"content:edit_own\", \"content:edit_any\");\n\tif (denied) return denied;\n\n\tconst resolvedId = typeof existingItem?.id === \"string\" ? existingItem.id : id;\n\n\tconst refusal = await claimEntryLockForWrite(emdash.db, collection, resolvedId, user!.id, {\n\t\toverride: body?.overrideLock,\n\t});\n\tif (refusal) {\n\t\treturn apiError(refusal.code, refusal.message, mapErrorStatus(refusal.code), {\n\t\t\t...refusal.details,\n\t\t});\n\t}\n\n\tconst result = await emdash.handleContentDiscardDraft(collection, resolvedId, {\n\t\t_rev: body?._rev,\n\t});\n\n\tif (!result.success) return unwrapResult(result);\n\n\tif (cache?.enabled) await cache.invalidate({ tags: [collection, resolvedId] });\n\n\treturn unwrapResult(result);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAcA,MAAa,YAAY;AAEzB,MAAa,OAAiB,OAAO,EAAE,QAAQ,SAAS,QAAQ,KAAK,YAAY;CAChF,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,aAAa,OAAO;CAC1B,MAAM,KAAK,OAAO;AAElB,KAAI,CAAC,QAAQ,6BAA6B,CAAC,QAAQ,iBAClD,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAEpE,MAAM,OAAO,MAAM,kBAAkB,SAAS,8BAA8B,EAAE,CAAC;AAC/E,KAAI,aAAa,KAAK,CAAE,QAAO;CAE/B,MAAM,SAAS,IAAI,aAAa,IAAI,SAAS,IAAI;CAGjD,MAAM,WAAW,MAAM,OAAO,iBAAiB,YAAY,IAAI,OAAO;AACtE,KAAI,CAAC,SAAS,QACb,QAAO,SACN,SAAS,OAAO,QAAQ,iBACxB,SAAS,OAAO,WAAW,iBAC3B,eAAe,SAAS,OAAO,KAAK,CACpC;CAEF,MAAM,eACL,SAAS,QAAQ,OAAO,SAAS,SAAS,WAEvC,SAAS,OACT;CAEJ,MAAM,eACL,cAAc,QAAQ,OAAO,aAAa,SAAS,WAEhD,aAAa,OACb;CAEJ,MAAM,SAAS,iBAAiB,MADf,OAAO,cAAc,aAAa,WAAW,aAAa,WAAW,IACtC,oBAAoB,mBAAmB;AACvF,KAAI,OAAQ,QAAO;CAEnB,MAAM,aAAa,OAAO,cAAc,OAAO,WAAW,aAAa,KAAK;CAE5E,MAAM,UAAU,MAAM,uBAAuB,OAAO,IAAI,YAAY,YAAY,KAAM,IAAI,EACzF,UAAU,MAAM,cAChB,CAAC;AACF,KAAI,QACH,QAAO,SAAS,QAAQ,MAAM,QAAQ,SAAS,eAAe,QAAQ,KAAK,EAAE,EAC5E,GAAG,QAAQ,SACX,CAAC;CAGH,MAAM,SAAS,MAAM,OAAO,0BAA0B,YAAY,YAAY,EAC7E,MAAM,MAAM,MACZ,CAAC;AAEF,KAAI,CAAC,OAAO,QAAS,QAAO,aAAa,OAAO;AAEhD,KAAI,OAAO,QAAS,OAAM,MAAM,WAAW,EAAE,MAAM,CAAC,YAAY,WAAW,EAAE,CAAC;AAE9E,QAAO,aAAa,OAAO"}
@@ -1,8 +1,8 @@
1
- import "../../../../../../base64-CvLhUKQv.mjs";
2
- import "../../../../../../types-CQPWhPxE.mjs";
3
- import { n as mapErrorStatus } from "../../../../../../errors-DsVoDUjJ.mjs";
4
- import { a as unwrapResult, t as apiError } from "../../../../../../error-DFrQjppn.mjs";
5
- import { n as requireOwnerPerm, r as requirePerm } from "../../../../../../authorize-Bkf_UHhD.mjs";
1
+ import "../../../../../../base64-DvnNgP7e.mjs";
2
+ import "../../../../../../types-BkUg2yHx.mjs";
3
+ import { n as mapErrorStatus } from "../../../../../../errors-W3PA8HqB.mjs";
4
+ import { a as unwrapResult, t as apiError } from "../../../../../../error-CCTCskie.mjs";
5
+ import { n as requireOwnerPerm, r as requirePerm } from "../../../../../../authorize-BXpfMpp0.mjs";
6
6
 
7
7
  //#region src/astro/routes/api/content/[collection]/[id]/duplicate.ts
8
8
  const prerender = false;
@@ -0,0 +1,10 @@
1
+ import { APIRoute } from "astro";
2
+
3
+ //#region src/astro/routes/api/content/[collection]/[id]/lock.d.ts
4
+ declare const prerender = false;
5
+ declare const GET: APIRoute;
6
+ declare const POST: APIRoute;
7
+ declare const DELETE: APIRoute;
8
+ //#endregion
9
+ export { DELETE, GET, POST, prerender };
10
+ //# sourceMappingURL=lock.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/lock.ts"],"mappings":";;;cAoBa,SAAA;AAAA,cAmDA,GAAA,EAAK,QAAA;AAAA,cAgBL,IAAA,EAAM,QAAA;AAAA,cAyBN,MAAA,EAAQ,QAAA"}
@@ -0,0 +1,67 @@
1
+ import "../../../../../../dialect-helpers-CtYdsX4W.mjs";
2
+ import "../../../../../../config-CGVeT8Hc.mjs";
3
+ import "../../../../../../base64-DvnNgP7e.mjs";
4
+ import "../../../../../../types-BkUg2yHx.mjs";
5
+ import "../../../../../../entry-locks-CO_KaoU5.mjs";
6
+ import { n as mapErrorStatus } from "../../../../../../errors-W3PA8HqB.mjs";
7
+ import { a as unwrapResult, t as apiError } from "../../../../../../error-CCTCskie.mjs";
8
+ import { r as parseOptionalBody, t as isParseError } from "../../../../../../parse-Cr379Av9.mjs";
9
+ import "../../../../../../redirects-BCiTaIQ-.mjs";
10
+ import { t as entryLockAcquireBody } from "../../../../../../entry-lock-D3C99MXS.mjs";
11
+ import "../../../../../../comments-BVzzt6x5.mjs";
12
+ import "../../../../../../relations-B4w-G5U9.mjs";
13
+ import "../../../../../../status-DLoBmcDz.mjs";
14
+ import "../../../../../../api/schemas/index.mjs";
15
+ import { n as requireOwnerPerm } from "../../../../../../authorize-BXpfMpp0.mjs";
16
+ import { i as handleEntryLockRelease, n as handleEntryLockAcquire, r as handleEntryLockRead } from "../../../../../../entry-lock-D9rnj2Lu.mjs";
17
+
18
+ //#region src/astro/routes/api/content/[collection]/[id]/lock.ts
19
+ const prerender = false;
20
+ /**
21
+ * Resolves the entry the way every other single-entry route does, and applies
22
+ * the same edit permission, since holding a lock is the prelude to a write.
23
+ */
24
+ async function resolveEntry(locals, collection, id, locale) {
25
+ const { emdash, user } = locals;
26
+ if (!emdash?.handleContentGet) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
27
+ const existing = await emdash.handleContentGet(collection, id, locale);
28
+ if (!existing.success) return apiError(existing.error?.code ?? "UNKNOWN_ERROR", existing.error?.message ?? "Unknown error", mapErrorStatus(existing.error?.code));
29
+ const existingData = existing.data && typeof existing.data === "object" ? existing.data : void 0;
30
+ const existingItem = existingData?.item && typeof existingData.item === "object" ? existingData.item : existingData;
31
+ const denied = requireOwnerPerm(user, typeof existingItem?.authorId === "string" ? existingItem.authorId : "", "content:edit_own", "content:edit_any");
32
+ if (denied) return denied;
33
+ return {
34
+ resolvedId: typeof existingItem?.id === "string" ? existingItem.id : id,
35
+ userId: user.id
36
+ };
37
+ }
38
+ const GET = async ({ params, locals, url }) => {
39
+ const collection = params.collection;
40
+ const id = params.id;
41
+ const resolved = await resolveEntry(locals, collection, id, url.searchParams.get("locale") || void 0);
42
+ if (resolved instanceof Response) return resolved;
43
+ return unwrapResult(await handleEntryLockRead(locals.emdash.db, collection, resolved.resolvedId, resolved.userId));
44
+ };
45
+ const POST = async ({ params, request, locals, url }) => {
46
+ const collection = params.collection;
47
+ const id = params.id;
48
+ const body = await parseOptionalBody(request, entryLockAcquireBody, {});
49
+ if (isParseError(body)) return body;
50
+ const resolved = await resolveEntry(locals, collection, id, url.searchParams.get("locale") || void 0);
51
+ if (resolved instanceof Response) return resolved;
52
+ return unwrapResult(await handleEntryLockAcquire(locals.emdash.db, collection, resolved.resolvedId, resolved.userId, {
53
+ takeover: body?.takeover,
54
+ token: body?.token
55
+ }));
56
+ };
57
+ const DELETE = async ({ params, locals, url }) => {
58
+ const collection = params.collection;
59
+ const id = params.id;
60
+ const resolved = await resolveEntry(locals, collection, id, url.searchParams.get("locale") || void 0);
61
+ if (resolved instanceof Response) return resolved;
62
+ return unwrapResult(await handleEntryLockRelease(locals.emdash.db, collection, resolved.resolvedId, resolved.userId, { token: url.searchParams.get("token") ?? void 0 }));
63
+ };
64
+
65
+ //#endregion
66
+ export { DELETE, GET, POST, prerender };
67
+ //# sourceMappingURL=lock.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/lock.ts"],"sourcesContent":["/**\n * Entry edit lock\n *\n * GET /_emdash/api/content/{collection}/{id}/lock - Read the current holder\n * POST /_emdash/api/content/{collection}/{id}/lock - Take or refresh the lock\n * DELETE /_emdash/api/content/{collection}/{id}/lock - Release the caller's lock\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requireOwnerPerm } from \"#api/authorize.js\";\nimport { apiError, mapErrorStatus, unwrapResult } from \"#api/error.js\";\nimport {\n\thandleEntryLockAcquire,\n\thandleEntryLockRead,\n\thandleEntryLockRelease,\n} from \"#api/handlers/entry-lock.js\";\nimport { isParseError, parseOptionalBody } from \"#api/parse.js\";\nimport { entryLockAcquireBody } from \"#api/schemas.js\";\n\nexport const prerender = false;\n\ninterface ResolvedEntry {\n\tresolvedId: string;\n\tuserId: string;\n}\n\n/**\n * Resolves the entry the way every other single-entry route does, and applies\n * the same edit permission, since holding a lock is the prelude to a write.\n */\nasync function resolveEntry(\n\tlocals: App.Locals,\n\tcollection: string,\n\tid: string,\n\tlocale: string | undefined,\n): Promise<ResolvedEntry | Response> {\n\tconst { emdash, user } = locals;\n\tif (!emdash?.handleContentGet) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst existing = await emdash.handleContentGet(collection, id, locale);\n\tif (!existing.success) {\n\t\treturn apiError(\n\t\t\texisting.error?.code ?? \"UNKNOWN_ERROR\",\n\t\t\texisting.error?.message ?? \"Unknown error\",\n\t\t\tmapErrorStatus(existing.error?.code),\n\t\t);\n\t}\n\n\tconst existingData =\n\t\texisting.data && typeof existing.data === \"object\"\n\t\t\t? // eslint-disable-next-line typescript/no-unsafe-type-assertion -- handler returns unknown data; narrowed by typeof check above\n\t\t\t\t(existing.data as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst existingItem =\n\t\texistingData?.item && typeof existingData.item === \"object\"\n\t\t\t? // eslint-disable-next-line typescript/no-unsafe-type-assertion -- narrowed by typeof check above\n\t\t\t\t(existingData.item as Record<string, unknown>)\n\t\t\t: existingData;\n\tconst authorId = typeof existingItem?.authorId === \"string\" ? existingItem.authorId : \"\";\n\tconst denied = requireOwnerPerm(user, authorId, \"content:edit_own\", \"content:edit_any\");\n\tif (denied) return denied;\n\n\treturn {\n\t\tresolvedId: typeof existingItem?.id === \"string\" ? existingItem.id : id,\n\t\tuserId: user!.id,\n\t};\n}\n\nexport const GET: APIRoute = async ({ params, locals, url }) => {\n\tconst collection = params.collection!;\n\tconst id = params.id!;\n\tconst resolved = await resolveEntry(\n\t\tlocals,\n\t\tcollection,\n\t\tid,\n\t\turl.searchParams.get(\"locale\") || undefined,\n\t);\n\tif (resolved instanceof Response) return resolved;\n\n\treturn unwrapResult(\n\t\tawait handleEntryLockRead(locals.emdash.db, collection, resolved.resolvedId, resolved.userId),\n\t);\n};\n\nexport const POST: APIRoute = async ({ params, request, locals, url }) => {\n\tconst collection = params.collection!;\n\tconst id = params.id!;\n\tconst body = await parseOptionalBody(request, entryLockAcquireBody, {});\n\tif (isParseError(body)) return body;\n\n\tconst resolved = await resolveEntry(\n\t\tlocals,\n\t\tcollection,\n\t\tid,\n\t\turl.searchParams.get(\"locale\") || undefined,\n\t);\n\tif (resolved instanceof Response) return resolved;\n\n\treturn unwrapResult(\n\t\tawait handleEntryLockAcquire(\n\t\t\tlocals.emdash.db,\n\t\t\tcollection,\n\t\t\tresolved.resolvedId,\n\t\t\tresolved.userId,\n\t\t\t{ takeover: body?.takeover, token: body?.token },\n\t\t),\n\t);\n};\n\nexport const DELETE: APIRoute = async ({ params, locals, url }) => {\n\tconst collection = params.collection!;\n\tconst id = params.id!;\n\tconst resolved = await resolveEntry(\n\t\tlocals,\n\t\tcollection,\n\t\tid,\n\t\turl.searchParams.get(\"locale\") || undefined,\n\t);\n\tif (resolved instanceof Response) return resolved;\n\n\treturn unwrapResult(\n\t\tawait handleEntryLockRelease(\n\t\t\tlocals.emdash.db,\n\t\t\tcollection,\n\t\t\tresolved.resolvedId,\n\t\t\tresolved.userId,\n\t\t\t{ token: url.searchParams.get(\"token\") ?? undefined },\n\t\t),\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,MAAa,YAAY;;;;;AAWzB,eAAe,aACd,QACA,YACA,IACA,QACoC;CACpC,MAAM,EAAE,QAAQ,SAAS;AACzB,KAAI,CAAC,QAAQ,iBACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,WAAW,MAAM,OAAO,iBAAiB,YAAY,IAAI,OAAO;AACtE,KAAI,CAAC,SAAS,QACb,QAAO,SACN,SAAS,OAAO,QAAQ,iBACxB,SAAS,OAAO,WAAW,iBAC3B,eAAe,SAAS,OAAO,KAAK,CACpC;CAGF,MAAM,eACL,SAAS,QAAQ,OAAO,SAAS,SAAS,WAEvC,SAAS,OACT;CACJ,MAAM,eACL,cAAc,QAAQ,OAAO,aAAa,SAAS,WAEhD,aAAa,OACb;CAEJ,MAAM,SAAS,iBAAiB,MADf,OAAO,cAAc,aAAa,WAAW,aAAa,WAAW,IACtC,oBAAoB,mBAAmB;AACvF,KAAI,OAAQ,QAAO;AAEnB,QAAO;EACN,YAAY,OAAO,cAAc,OAAO,WAAW,aAAa,KAAK;EACrE,QAAQ,KAAM;EACd;;AAGF,MAAa,MAAgB,OAAO,EAAE,QAAQ,QAAQ,UAAU;CAC/D,MAAM,aAAa,OAAO;CAC1B,MAAM,KAAK,OAAO;CAClB,MAAM,WAAW,MAAM,aACtB,QACA,YACA,IACA,IAAI,aAAa,IAAI,SAAS,IAAI,OAClC;AACD,KAAI,oBAAoB,SAAU,QAAO;AAEzC,QAAO,aACN,MAAM,oBAAoB,OAAO,OAAO,IAAI,YAAY,SAAS,YAAY,SAAS,OAAO,CAC7F;;AAGF,MAAa,OAAiB,OAAO,EAAE,QAAQ,SAAS,QAAQ,UAAU;CACzE,MAAM,aAAa,OAAO;CAC1B,MAAM,KAAK,OAAO;CAClB,MAAM,OAAO,MAAM,kBAAkB,SAAS,sBAAsB,EAAE,CAAC;AACvE,KAAI,aAAa,KAAK,CAAE,QAAO;CAE/B,MAAM,WAAW,MAAM,aACtB,QACA,YACA,IACA,IAAI,aAAa,IAAI,SAAS,IAAI,OAClC;AACD,KAAI,oBAAoB,SAAU,QAAO;AAEzC,QAAO,aACN,MAAM,uBACL,OAAO,OAAO,IACd,YACA,SAAS,YACT,SAAS,QACT;EAAE,UAAU,MAAM;EAAU,OAAO,MAAM;EAAO,CAChD,CACD;;AAGF,MAAa,SAAmB,OAAO,EAAE,QAAQ,QAAQ,UAAU;CAClE,MAAM,aAAa,OAAO;CAC1B,MAAM,KAAK,OAAO;CAClB,MAAM,WAAW,MAAM,aACtB,QACA,YACA,IACA,IAAI,aAAa,IAAI,SAAS,IAAI,OAClC;AACD,KAAI,oBAAoB,SAAU,QAAO;AAEzC,QAAO,aACN,MAAM,uBACL,OAAO,OAAO,IACd,YACA,SAAS,YACT,SAAS,QACT,EAAE,OAAO,IAAI,aAAa,IAAI,QAAQ,IAAI,QAAW,CACrD,CACD"}
@@ -1,7 +1,7 @@
1
- import "../../../../../../base64-CvLhUKQv.mjs";
2
- import "../../../../../../types-CQPWhPxE.mjs";
3
- import { a as unwrapResult, t as apiError } from "../../../../../../error-DFrQjppn.mjs";
4
- import { r as requirePerm } from "../../../../../../authorize-Bkf_UHhD.mjs";
1
+ import "../../../../../../base64-DvnNgP7e.mjs";
2
+ import "../../../../../../types-BkUg2yHx.mjs";
3
+ import { a as unwrapResult, t as apiError } from "../../../../../../error-CCTCskie.mjs";
4
+ import { r as requirePerm } from "../../../../../../authorize-BXpfMpp0.mjs";
5
5
 
6
6
  //#region src/astro/routes/api/content/[collection]/[id]/permanent.ts
7
7
  const prerender = false;
@@ -0,0 +1,8 @@
1
+ import { APIRoute } from "astro";
2
+
3
+ //#region src/astro/routes/api/content/[collection]/[id]/plugin-extensions/[pluginId]/[kind]/[extensionId].d.ts
4
+ declare const prerender = false;
5
+ declare const POST: APIRoute;
6
+ //#endregion
7
+ export { POST, prerender };
8
+ //# sourceMappingURL=_extensionId_.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_extensionId_.d.mts","names":[],"sources":["../../../../../../../../../../src/astro/routes/api/content/[collection]/[id]/plugin-extensions/[pluginId]/[kind]/[extensionId].ts"],"mappings":";;;cAKa,SAAA;AAAA,cAEA,IAAA,EAAM,QAAA"}
@@ -0,0 +1,35 @@
1
+ import "../../../../../../../../../base64-DvnNgP7e.mjs";
2
+ import "../../../../../../../../../types-BkUg2yHx.mjs";
3
+ import "../../../../../../../../../hash-CLVFzWvx.mjs";
4
+ import "../../../../../../../../../zod-generator-D_yHIWfs.mjs";
5
+ import { t as apiError } from "../../../../../../../../../error-CCTCskie.mjs";
6
+ import "../../../../../../../../../route-wire-D66L2oaZ.mjs";
7
+ import "../../../../../../../../../api-tokens-DS1VzN7_.mjs";
8
+ import "../../../../../../../../../authorize-BXpfMpp0.mjs";
9
+ import "../../../../../../../../../scopes-Bn8_rCSt.mjs";
10
+ import { n as dispatchPluginEditorExtensionApiRequest } from "../../../../../../../../../http-route-dispatch-DAKlanXb.mjs";
11
+
12
+ //#region src/astro/routes/api/content/[collection]/[id]/plugin-extensions/[pluginId]/[kind]/[extensionId].ts
13
+ const prerender = false;
14
+ const POST = async ({ params, request, locals, cache }) => {
15
+ const { emdash, user } = locals;
16
+ if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
17
+ const kind = params.kind;
18
+ if (kind !== "panel" && kind !== "action") return apiError("NOT_FOUND", "Plugin editor extension not found", 404);
19
+ return dispatchPluginEditorExtensionApiRequest({
20
+ runtime: emdash,
21
+ pluginId: params.pluginId,
22
+ kind,
23
+ extensionId: params.extensionId,
24
+ collection: params.collection,
25
+ entryId: params.id,
26
+ request,
27
+ user,
28
+ tokenScopes: locals.tokenScopes,
29
+ invalidateContentCache: cache?.enabled ? (tags) => cache.invalidate({ tags }) : void 0
30
+ });
31
+ };
32
+
33
+ //#endregion
34
+ export { POST, prerender };
35
+ //# sourceMappingURL=_extensionId_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_extensionId_.mjs","names":[],"sources":["../../../../../../../../../../src/astro/routes/api/content/[collection]/[id]/plugin-extensions/[pluginId]/[kind]/[extensionId].ts"],"sourcesContent":["import type { APIRoute } from \"astro\";\n\nimport { apiError } from \"#api/error.js\";\nimport { dispatchPluginEditorExtensionApiRequest } from \"#plugins/http-route-dispatch.js\";\n\nexport const prerender = false;\n\nexport const POST: APIRoute = async ({ params, request, locals, cache }) => {\n\tconst { emdash, user } = locals;\n\tif (!emdash) return apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\n\tconst kind = params.kind;\n\tif (kind !== \"panel\" && kind !== \"action\") {\n\t\treturn apiError(\"NOT_FOUND\", \"Plugin editor extension not found\", 404);\n\t}\n\n\treturn dispatchPluginEditorExtensionApiRequest({\n\t\truntime: emdash,\n\t\tpluginId: params.pluginId!,\n\t\tkind,\n\t\textensionId: params.extensionId!,\n\t\tcollection: params.collection!,\n\t\tentryId: params.id!,\n\t\trequest,\n\t\tuser,\n\t\ttokenScopes: locals.tokenScopes,\n\t\tinvalidateContentCache: cache?.enabled ? (tags) => cache.invalidate({ tags }) : undefined,\n\t});\n};\n"],"mappings":";;;;;;;;;;;;AAKA,MAAa,YAAY;AAEzB,MAAa,OAAiB,OAAO,EAAE,QAAQ,SAAS,QAAQ,YAAY;CAC3E,MAAM,EAAE,QAAQ,SAAS;AACzB,KAAI,CAAC,OAAQ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAEhF,MAAM,OAAO,OAAO;AACpB,KAAI,SAAS,WAAW,SAAS,SAChC,QAAO,SAAS,aAAa,qCAAqC,IAAI;AAGvE,QAAO,wCAAwC;EAC9C,SAAS;EACT,UAAU,OAAO;EACjB;EACA,aAAa,OAAO;EACpB,YAAY,OAAO;EACnB,SAAS,OAAO;EAChB;EACA;EACA,aAAa,OAAO;EACpB,wBAAwB,OAAO,WAAW,SAAS,MAAM,WAAW,EAAE,MAAM,CAAC,GAAG;EAChF,CAAC"}
@@ -1,19 +1,20 @@
1
- import { r as getI18nConfig } from "../../../../../../config-C3EBstHi.mjs";
2
- import "../../../../../../after-CBU2vkoO.mjs";
3
- import "../../../../../../base64-CvLhUKQv.mjs";
4
- import "../../../../../../types-CQPWhPxE.mjs";
5
- import "../../../../../../options-BHPeIbBd.mjs";
6
- import { a as unwrapResult, n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-DFrQjppn.mjs";
7
- import { r as parseOptionalBody, t as isParseError } from "../../../../../../parse-Ckpg-Qfp.mjs";
8
- import "../../../../../../media-BHjus86Y.mjs";
9
- import { en as contentPreviewUrlBody } from "../../../../../../redirects-BLNOWQTn.mjs";
10
- import "../../../../../../relations-C4htk5sb.mjs";
11
- import "../../../../../../status-B777-dXz.mjs";
1
+ import { r as getI18nConfig } from "../../../../../../config-CGVeT8Hc.mjs";
2
+ import "../../../../../../after-PcEvMY_6.mjs";
3
+ import "../../../../../../options-D5WcorD5.mjs";
4
+ import "../../../../../../base64-DvnNgP7e.mjs";
5
+ import { a as resolveSecretsCached } from "../../../../../../secrets-DNgVgz_e.mjs";
6
+ import "../../../../../../types-BkUg2yHx.mjs";
7
+ import { a as unwrapResult, n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CCTCskie.mjs";
8
+ import { r as parseOptionalBody, t as isParseError } from "../../../../../../parse-Cr379Av9.mjs";
9
+ import "../../../../../../redirects-BCiTaIQ-.mjs";
10
+ import { Yn as contentPreviewUrlBody } from "../../../../../../entry-lock-D3C99MXS.mjs";
11
+ import "../../../../../../comments-BVzzt6x5.mjs";
12
+ import "../../../../../../relations-B4w-G5U9.mjs";
13
+ import "../../../../../../status-DLoBmcDz.mjs";
12
14
  import "../../../../../../api/schemas/index.mjs";
13
- import "../../../../../../tokens-BCO1oruF.mjs";
14
- import { i as getPreviewUrl } from "../../../../../../preview-B_vJLvf8.mjs";
15
- import { i as resolveSecretsCached } from "../../../../../../secrets-rEtHt-6z.mjs";
16
- import { r as requirePerm } from "../../../../../../authorize-Bkf_UHhD.mjs";
15
+ import "../../../../../../tokens-Ns02GAma.mjs";
16
+ import { i as getPreviewUrl } from "../../../../../../preview-Cup2bj8c.mjs";
17
+ import { r as requirePerm } from "../../../../../../authorize-BXpfMpp0.mjs";
17
18
 
18
19
  //#region src/astro/routes/api/content/[collection]/[id]/preview-url.ts
19
20
  const prerender = false;
@@ -1 +1 @@
1
- {"version":3,"file":"preview-url.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/preview-url.ts"],"sourcesContent":["/**\n * Preview URL endpoint - generates a signed preview URL for content\n *\n * POST /_emdash/api/content/{collection}/{id}/preview-url\n *\n * Request body:\n * {\n * expiresIn?: string | number; // Default: \"1h\"\n * pathPattern?: string; // Default: \"/{collection}/{id}\" (or EMDASH_PREVIEW_PATH_PATTERN)\n * }\n *\n * Response:\n * {\n * url: string; // The preview URL with token\n * expiresAt: number; // Unix timestamp when token expires\n * }\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, apiSuccess, handleError, unwrapResult } from \"#api/error.js\";\nimport { parseOptionalBody, isParseError } from \"#api/parse.js\";\nimport { contentPreviewUrlBody } from \"#api/schemas.js\";\nimport { resolveSecretsCached } from \"#config/secrets.js\";\nimport { getPreviewUrl } from \"#preview/index.js\";\n\nimport { getI18nConfig } from \"../../../../../../i18n/config.js\";\n\nexport const prerender = false;\n\nconst DURATION_PATTERN = /^(\\d+)([smhdw])$/;\n\nexport const POST: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash, user } = locals;\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\tconst denied = requirePerm(user, \"content:read_drafts\");\n\tif (denied) return denied;\n\tconst collection = params.collection!;\n\tconst id = params.id!;\n\n\t// Resolve the preview secret. Env override wins; otherwise a stable\n\t// site-specific value is read from (or generated into) the options table.\n\t// The resolver always returns a usable secret, so this path can no\n\t// longer be silently disabled by a missing env var.\n\tconst { previewSecret } = await resolveSecretsCached(emdash.db);\n\n\t// Verify the content exists. The fetched item also yields the entry's\n\t// locale, used below to resolve the `{locale}` placeholder.\n\tlet entryLocale: string | null = null;\n\tif (emdash?.handleContentGet) {\n\t\tconst result = await emdash.handleContentGet(collection, id);\n\t\tif (!result.success) return unwrapResult(result);\n\t\tentryLocale = result.data?.item?.locale ?? null;\n\t}\n\n\t// Parse request body\n\tconst body = await parseOptionalBody(request, contentPreviewUrlBody, {});\n\tif (isParseError(body)) return body;\n\n\tconst expiresIn = body.expiresIn || \"1h\";\n\t// Allow a project-wide default `pathPattern` so the admin's \"View on site\"\n\t// link can match the site's actual route shape without each call having\n\t// to override the default `/{collection}/{id}`.\n\tconst defaultPathPattern = import.meta.env.EMDASH_PREVIEW_PATH_PATTERN || \"/{collection}/{id}\";\n\tconst pathPattern = body.pathPattern || defaultPathPattern;\n\n\t// Resolve the locale segment substituted for `{locale}`: empty when the\n\t// entry is in the default locale and `prefixDefaultLocale` is `false`,\n\t// the entry's own locale otherwise.\n\tconst i18n = getI18nConfig();\n\tlet localeSegment = \"\";\n\tif (entryLocale && i18n) {\n\t\tconst isDefault = entryLocale === i18n.defaultLocale;\n\t\tlocaleSegment = isDefault && !i18n.prefixDefaultLocale ? \"\" : entryLocale;\n\t} else if (entryLocale) {\n\t\tlocaleSegment = entryLocale;\n\t}\n\n\t// Calculate expiry timestamp\n\tconst expiresInSeconds = typeof expiresIn === \"number\" ? expiresIn : parseExpiresIn(expiresIn);\n\tconst expiresAt = Math.floor(Date.now() / 1000) + expiresInSeconds;\n\n\ttry {\n\t\tconst url = await getPreviewUrl({\n\t\t\tcollection,\n\t\t\tid,\n\t\t\tsecret: previewSecret,\n\t\t\texpiresIn,\n\t\t\tpathPattern,\n\t\t\tlocale: localeSegment,\n\t\t});\n\n\t\treturn apiSuccess({ url, expiresAt });\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to generate preview URL\", \"TOKEN_ERROR\");\n\t}\n};\n\n/**\n * Parse duration string to seconds\n */\nfunction parseExpiresIn(duration: string): number {\n\tconst match = duration.match(DURATION_PATTERN);\n\tif (!match) {\n\t\treturn 3600; // Default 1 hour\n\t}\n\n\tconst value = parseInt(match[1], 10);\n\tconst unit = match[2];\n\n\tswitch (unit) {\n\t\tcase \"s\":\n\t\t\treturn value;\n\t\tcase \"m\":\n\t\t\treturn value * 60;\n\t\tcase \"h\":\n\t\t\treturn value * 60 * 60;\n\t\tcase \"d\":\n\t\t\treturn value * 60 * 60 * 24;\n\t\tcase \"w\":\n\t\t\treturn value * 60 * 60 * 24 * 7;\n\t\tdefault:\n\t\t\treturn 3600;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA6BA,MAAa,YAAY;AAEzB,MAAM,mBAAmB;AAEzB,MAAa,OAAiB,OAAO,EAAE,QAAQ,SAAS,aAAa;CACpE,MAAM,EAAE,QAAQ,SAAS;AACzB,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAEpE,MAAM,SAAS,YAAY,MAAM,sBAAsB;AACvD,KAAI,OAAQ,QAAO;CACnB,MAAM,aAAa,OAAO;CAC1B,MAAM,KAAK,OAAO;CAMlB,MAAM,EAAE,kBAAkB,MAAM,qBAAqB,OAAO,GAAG;CAI/D,IAAI,cAA6B;AACjC,KAAI,QAAQ,kBAAkB;EAC7B,MAAM,SAAS,MAAM,OAAO,iBAAiB,YAAY,GAAG;AAC5D,MAAI,CAAC,OAAO,QAAS,QAAO,aAAa,OAAO;AAChD,gBAAc,OAAO,MAAM,MAAM,UAAU;;CAI5C,MAAM,OAAO,MAAM,kBAAkB,SAAS,uBAAuB,EAAE,CAAC;AACxE,KAAI,aAAa,KAAK,CAAE,QAAO;CAE/B,MAAM,YAAY,KAAK,aAAa;CAIpC,MAAM,qBAAqB,OAAO,KAAK,IAAI,+BAA+B;CAC1E,MAAM,cAAc,KAAK,eAAe;CAKxC,MAAM,OAAO,eAAe;CAC5B,IAAI,gBAAgB;AACpB,KAAI,eAAe,KAElB,iBADkB,gBAAgB,KAAK,iBACV,CAAC,KAAK,sBAAsB,KAAK;UACpD,YACV,iBAAgB;CAIjB,MAAM,mBAAmB,OAAO,cAAc,WAAW,YAAY,eAAe,UAAU;CAC9F,MAAM,YAAY,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG;AAElD,KAAI;AAUH,SAAO,WAAW;GAAE,KATR,MAAM,cAAc;IAC/B;IACA;IACA,QAAQ;IACR;IACA;IACA,QAAQ;IACR,CAAC;GAEuB;GAAW,CAAC;UAC7B,OAAO;AACf,SAAO,YAAY,OAAO,kCAAkC,cAAc;;;;;;AAO5E,SAAS,eAAe,UAA0B;CACjD,MAAM,QAAQ,SAAS,MAAM,iBAAiB;AAC9C,KAAI,CAAC,MACJ,QAAO;CAGR,MAAM,QAAQ,SAAS,MAAM,IAAI,GAAG;AAGpC,SAFa,MAAM,IAEnB;EACC,KAAK,IACJ,QAAO;EACR,KAAK,IACJ,QAAO,QAAQ;EAChB,KAAK,IACJ,QAAO,QAAQ,KAAK;EACrB,KAAK,IACJ,QAAO,QAAQ,KAAK,KAAK;EAC1B,KAAK,IACJ,QAAO,QAAQ,KAAK,KAAK,KAAK;EAC/B,QACC,QAAO"}
1
+ {"version":3,"file":"preview-url.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/preview-url.ts"],"sourcesContent":["/**\n * Preview URL endpoint - generates a signed preview URL for content\n *\n * POST /_emdash/api/content/{collection}/{id}/preview-url\n *\n * Request body:\n * {\n * expiresIn?: string | number; // Default: \"1h\"\n * pathPattern?: string; // Default: \"/{collection}/{id}\" (or EMDASH_PREVIEW_PATH_PATTERN)\n * }\n *\n * Response:\n * {\n * url: string; // The preview URL with token\n * expiresAt: number; // Unix timestamp when token expires\n * }\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, apiSuccess, handleError, unwrapResult } from \"#api/error.js\";\nimport { parseOptionalBody, isParseError } from \"#api/parse.js\";\nimport { contentPreviewUrlBody } from \"#api/schemas.js\";\nimport { resolveSecretsCached } from \"#config/secrets.js\";\nimport { getPreviewUrl } from \"#preview/index.js\";\n\nimport { getI18nConfig } from \"../../../../../../i18n/config.js\";\n\nexport const prerender = false;\n\nconst DURATION_PATTERN = /^(\\d+)([smhdw])$/;\n\nexport const POST: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash, user } = locals;\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\tconst denied = requirePerm(user, \"content:read_drafts\");\n\tif (denied) return denied;\n\tconst collection = params.collection!;\n\tconst id = params.id!;\n\n\t// Resolve the preview secret. Env override wins; otherwise a stable\n\t// site-specific value is read from (or generated into) the options table.\n\t// The resolver always returns a usable secret, so this path can no\n\t// longer be silently disabled by a missing env var.\n\tconst { previewSecret } = await resolveSecretsCached(emdash.db);\n\n\t// Verify the content exists. The fetched item also yields the entry's\n\t// locale, used below to resolve the `{locale}` placeholder.\n\tlet entryLocale: string | null = null;\n\tif (emdash?.handleContentGet) {\n\t\tconst result = await emdash.handleContentGet(collection, id);\n\t\tif (!result.success) return unwrapResult(result);\n\t\tentryLocale = result.data?.item?.locale ?? null;\n\t}\n\n\t// Parse request body\n\tconst body = await parseOptionalBody(request, contentPreviewUrlBody, {});\n\tif (isParseError(body)) return body;\n\n\tconst expiresIn = body.expiresIn || \"1h\";\n\t// Allow a project-wide default `pathPattern` so the admin's \"View on site\"\n\t// link can match the site's actual route shape without each call having\n\t// to override the default `/{collection}/{id}`.\n\tconst defaultPathPattern = import.meta.env.EMDASH_PREVIEW_PATH_PATTERN || \"/{collection}/{id}\";\n\tconst pathPattern = body.pathPattern || defaultPathPattern;\n\n\t// Resolve the locale segment substituted for `{locale}`: empty when the\n\t// entry is in the default locale and `prefixDefaultLocale` is `false`,\n\t// the entry's own locale otherwise.\n\tconst i18n = getI18nConfig();\n\tlet localeSegment = \"\";\n\tif (entryLocale && i18n) {\n\t\tconst isDefault = entryLocale === i18n.defaultLocale;\n\t\tlocaleSegment = isDefault && !i18n.prefixDefaultLocale ? \"\" : entryLocale;\n\t} else if (entryLocale) {\n\t\tlocaleSegment = entryLocale;\n\t}\n\n\t// Calculate expiry timestamp\n\tconst expiresInSeconds = typeof expiresIn === \"number\" ? expiresIn : parseExpiresIn(expiresIn);\n\tconst expiresAt = Math.floor(Date.now() / 1000) + expiresInSeconds;\n\n\ttry {\n\t\tconst url = await getPreviewUrl({\n\t\t\tcollection,\n\t\t\tid,\n\t\t\tsecret: previewSecret,\n\t\t\texpiresIn,\n\t\t\tpathPattern,\n\t\t\tlocale: localeSegment,\n\t\t});\n\n\t\treturn apiSuccess({ url, expiresAt });\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to generate preview URL\", \"TOKEN_ERROR\");\n\t}\n};\n\n/**\n * Parse duration string to seconds\n */\nfunction parseExpiresIn(duration: string): number {\n\tconst match = duration.match(DURATION_PATTERN);\n\tif (!match) {\n\t\treturn 3600; // Default 1 hour\n\t}\n\n\tconst value = parseInt(match[1], 10);\n\tconst unit = match[2];\n\n\tswitch (unit) {\n\t\tcase \"s\":\n\t\t\treturn value;\n\t\tcase \"m\":\n\t\t\treturn value * 60;\n\t\tcase \"h\":\n\t\t\treturn value * 60 * 60;\n\t\tcase \"d\":\n\t\t\treturn value * 60 * 60 * 24;\n\t\tcase \"w\":\n\t\t\treturn value * 60 * 60 * 24 * 7;\n\t\tdefault:\n\t\t\treturn 3600;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA6BA,MAAa,YAAY;AAEzB,MAAM,mBAAmB;AAEzB,MAAa,OAAiB,OAAO,EAAE,QAAQ,SAAS,aAAa;CACpE,MAAM,EAAE,QAAQ,SAAS;AACzB,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAEpE,MAAM,SAAS,YAAY,MAAM,sBAAsB;AACvD,KAAI,OAAQ,QAAO;CACnB,MAAM,aAAa,OAAO;CAC1B,MAAM,KAAK,OAAO;CAMlB,MAAM,EAAE,kBAAkB,MAAM,qBAAqB,OAAO,GAAG;CAI/D,IAAI,cAA6B;AACjC,KAAI,QAAQ,kBAAkB;EAC7B,MAAM,SAAS,MAAM,OAAO,iBAAiB,YAAY,GAAG;AAC5D,MAAI,CAAC,OAAO,QAAS,QAAO,aAAa,OAAO;AAChD,gBAAc,OAAO,MAAM,MAAM,UAAU;;CAI5C,MAAM,OAAO,MAAM,kBAAkB,SAAS,uBAAuB,EAAE,CAAC;AACxE,KAAI,aAAa,KAAK,CAAE,QAAO;CAE/B,MAAM,YAAY,KAAK,aAAa;CAIpC,MAAM,qBAAqB,OAAO,KAAK,IAAI,+BAA+B;CAC1E,MAAM,cAAc,KAAK,eAAe;CAKxC,MAAM,OAAO,eAAe;CAC5B,IAAI,gBAAgB;AACpB,KAAI,eAAe,KAElB,iBADkB,gBAAgB,KAAK,iBACV,CAAC,KAAK,sBAAsB,KAAK;UACpD,YACV,iBAAgB;CAIjB,MAAM,mBAAmB,OAAO,cAAc,WAAW,YAAY,eAAe,UAAU;CAC9F,MAAM,YAAY,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG;AAElD,KAAI;AAUH,SAAO,WAAW;GAAE,KATR,MAAM,cAAc;IAC/B;IACA;IACA,QAAQ;IACR;IACA;IACA,QAAQ;IACR,CAAC;GAEuB;GAAW,CAAC;UAC7B,OAAO;AACf,SAAO,YAAY,OAAO,kCAAkC,cAAc;;;;;;AAO5E,SAAS,eAAe,UAA0B;CACjD,MAAM,QAAQ,SAAS,MAAM,iBAAiB;AAC9C,KAAI,CAAC,MACJ,QAAO;CAGR,MAAM,QAAQ,SAAS,MAAM,IAAI,GAAG;AAGpC,SAFa,MAAM,IAEnB;EACC,KAAK,IACJ,QAAO;EACR,KAAK,IACJ,QAAO,QAAQ;EAChB,KAAK,IACJ,QAAO,QAAQ,KAAK;EACrB,KAAK,IACJ,QAAO,QAAQ,KAAK,KAAK;EAC1B,KAAK,IACJ,QAAO,QAAQ,KAAK,KAAK,KAAK;EAC/B,QACC,QAAO"}
@@ -1,8 +1,15 @@
1
- import { APIRoute } from "astro";
1
+ import { APIContext, APIRoute } from "astro";
2
2
 
3
3
  //#region src/astro/routes/api/content/[collection]/[id]/publish.d.ts
4
4
  declare const prerender = false;
5
+ declare function publishContent({
6
+ params,
7
+ request,
8
+ locals,
9
+ url,
10
+ cache
11
+ }: APIContext, originSource: "api" | "visual-editor"): Promise<Response>;
5
12
  declare const POST: APIRoute;
6
13
  //#endregion
7
- export { POST, prerender };
14
+ export { POST, prerender, publishContent };
8
15
  //# sourceMappingURL=publish.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"publish.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/publish.ts"],"mappings":";;;cAoBa,SAAA;AAAA,cAEA,IAAA,EAAM,QAAA"}
1
+ {"version":3,"file":"publish.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/content/[collection]/[id]/publish.ts"],"mappings":";;;cAqBa,SAAA;AAAA,iBAES,cAAA,CAAA;EACnB,MAAA;EAAQ,OAAA;EAAS,MAAA;EAAQ,GAAA;EAAK;AAAA,GAAS,UAAA,EACzC,YAAA,4BACE,OAAA,CAAQ,QAAA;AAAA,cA+EE,IAAA,EAAM,QAAA"}