emdash 0.21.0 → 0.22.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 (620) hide show
  1. package/dist/{adapters-BxSmgtbF.d.mts → adapters-hUy8vOB-.d.mts} +1 -1
  2. package/dist/{adapters-BxSmgtbF.d.mts.map → adapters-hUy8vOB-.d.mts.map} +1 -1
  3. package/dist/after-B1IIdH3Y.mjs +29 -0
  4. package/dist/after-B1IIdH3Y.mjs.map +1 -0
  5. package/dist/{allowed-origins-BqC8cul8.mjs → allowed-origins-DjlhyfNN.mjs} +2 -2
  6. package/dist/{allowed-origins-BqC8cul8.mjs.map → allowed-origins-DjlhyfNN.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +20 -19
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +2 -2
  11. package/dist/api/schemas/index.mjs +4 -4
  12. package/dist/{api-DxjIV2o8.mjs → api-BDuM4bEy.mjs} +31 -25
  13. package/dist/api-BDuM4bEy.mjs.map +1 -0
  14. package/dist/{api-tokens-BFFkB0jB.mjs → api-tokens-ViYKeIp9.mjs} +13 -3
  15. package/dist/api-tokens-ViYKeIp9.mjs.map +1 -0
  16. package/dist/{apply-CLjxheyb.mjs → apply-wDqQoxX4.mjs} +18 -18
  17. package/dist/{apply-CLjxheyb.mjs.map → apply-wDqQoxX4.mjs.map} +1 -1
  18. package/dist/astro/image-endpoint.d.mts +8 -0
  19. package/dist/astro/image-endpoint.d.mts.map +1 -0
  20. package/dist/astro/image-endpoint.mjs +55 -0
  21. package/dist/astro/image-endpoint.mjs.map +1 -0
  22. package/dist/astro/index.d.mts +36 -11
  23. package/dist/astro/index.d.mts.map +1 -1
  24. package/dist/astro/index.mjs +114 -24
  25. package/dist/astro/index.mjs.map +1 -1
  26. package/dist/astro/middleware/auth.d.mts +9 -9
  27. package/dist/astro/middleware/auth.d.mts.map +1 -1
  28. package/dist/astro/middleware/auth.mjs +12 -10
  29. package/dist/astro/middleware/auth.mjs.map +1 -1
  30. package/dist/astro/middleware/redirect.mjs +6 -6
  31. package/dist/astro/middleware/request-context.mjs +5 -5
  32. package/dist/astro/middleware/setup.mjs +1 -1
  33. package/dist/astro/middleware.d.mts +1 -1
  34. package/dist/astro/middleware.d.mts.map +1 -1
  35. package/dist/astro/middleware.mjs +153 -79
  36. package/dist/astro/middleware.mjs.map +1 -1
  37. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  38. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  39. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  40. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  42. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
  43. package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
  44. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
  45. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -16
  46. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  47. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -16
  48. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  49. package/dist/astro/routes/api/admin/bylines/index.mjs +17 -16
  50. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  51. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +15 -13
  52. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -6
  54. package/dist/astro/routes/api/admin/comments/_id_.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -10
  56. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -6
  58. package/dist/astro/routes/api/admin/comments/counts.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/comments/index.mjs +12 -10
  60. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  62. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  63. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  64. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  65. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +40 -39
  66. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +40 -39
  68. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +39 -38
  70. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +39 -38
  72. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +39 -38
  74. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/index.mjs +39 -38
  76. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +39 -38
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +39 -38
  81. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +39 -38
  83. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +39 -38
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +40 -39
  87. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +39 -38
  89. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +40 -39
  91. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/updates.mjs +39 -38
  93. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +39 -38
  95. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  97. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +39 -38
  98. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  99. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  100. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  101. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
  102. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  103. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  104. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  105. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  106. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  107. package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
  108. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  109. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  110. package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -11
  111. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  112. package/dist/astro/routes/api/auth/me.mjs +8 -8
  113. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  114. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  115. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  116. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  117. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  118. package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
  119. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  120. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  121. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  122. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  123. package/dist/astro/routes/api/auth/signup/request.mjs +11 -11
  124. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  125. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +16 -15
  126. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  127. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts +9 -0
  128. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts.map +1 -0
  129. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +179 -0
  130. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -0
  131. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  132. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
  133. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  134. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  135. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -13
  136. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
  137. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  138. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  139. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  140. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -15
  141. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  142. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  143. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
  144. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  145. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  146. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  147. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  148. package/dist/astro/routes/api/dashboard.mjs +10 -8
  149. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  150. package/dist/astro/routes/api/dev/emails.mjs +4 -4
  151. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  152. package/dist/astro/routes/api/import/probe.mjs +12 -12
  153. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  154. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  155. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -15
  156. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  157. package/dist/astro/routes/api/import/wordpress/media.mjs +10 -10
  158. package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
  159. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +10 -10
  160. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  161. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +12 -12
  162. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  163. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  164. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +18 -17
  165. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  166. package/dist/astro/routes/api/manifest.mjs +5 -5
  167. package/dist/astro/routes/api/mcp.mjs +213 -46
  168. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  169. package/dist/astro/routes/api/media/_id_/confirm.mjs +8 -8
  170. package/dist/astro/routes/api/media/_id_.mjs +8 -8
  171. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  172. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  173. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  174. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  175. package/dist/astro/routes/api/media/upload-url.mjs +10 -10
  176. package/dist/astro/routes/api/media.mjs +13 -13
  177. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -9
  178. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  179. package/dist/astro/routes/api/menus/_name_/items.mjs +11 -9
  180. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  181. package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -9
  182. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  183. package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -9
  184. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  185. package/dist/astro/routes/api/menus/_name_.mjs +11 -9
  186. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  187. package/dist/astro/routes/api/menus/index.mjs +11 -9
  188. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  189. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  190. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
  191. package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
  192. package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
  193. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  194. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
  195. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
  196. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  197. package/dist/astro/routes/api/openapi.json.mjs +5 -5
  198. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
  199. package/dist/astro/routes/api/redirects/404s/index.mjs +11 -11
  200. package/dist/astro/routes/api/redirects/404s/summary.mjs +11 -11
  201. package/dist/astro/routes/api/redirects/_id_.mjs +12 -12
  202. package/dist/astro/routes/api/redirects/index.mjs +12 -12
  203. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  204. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
  205. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +39 -38
  206. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  207. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +39 -38
  208. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  209. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +39 -38
  210. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  211. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +39 -38
  212. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  213. package/dist/astro/routes/api/schema/collections/index.mjs +39 -38
  214. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  215. package/dist/astro/routes/api/schema/index.mjs +7 -7
  216. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +39 -38
  217. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  218. package/dist/astro/routes/api/schema/orphans/index.mjs +39 -38
  219. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  220. package/dist/astro/routes/api/search/enable.mjs +11 -11
  221. package/dist/astro/routes/api/search/index.mjs +10 -10
  222. package/dist/astro/routes/api/search/rebuild.mjs +11 -11
  223. package/dist/astro/routes/api/search/stats.mjs +7 -7
  224. package/dist/astro/routes/api/search/suggest.mjs +10 -10
  225. package/dist/astro/routes/api/sections/_slug_.mjs +10 -10
  226. package/dist/astro/routes/api/sections/index.mjs +10 -10
  227. package/dist/astro/routes/api/settings/email.mjs +6 -6
  228. package/dist/astro/routes/api/settings.mjs +16 -15
  229. package/dist/astro/routes/api/settings.mjs.map +1 -1
  230. package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
  231. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  232. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  233. package/dist/astro/routes/api/setup/dev-bypass.mjs +29 -27
  234. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  235. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  236. package/dist/astro/routes/api/setup/index.mjs +29 -28
  237. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  238. package/dist/astro/routes/api/setup/status.mjs +5 -5
  239. package/dist/astro/routes/api/snapshot.d.mts.map +1 -1
  240. package/dist/astro/routes/api/snapshot.mjs +10 -9
  241. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  242. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -14
  243. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  244. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -14
  245. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  246. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -14
  247. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  248. package/dist/astro/routes/api/taxonomies/index.mjs +16 -14
  249. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  250. package/dist/astro/routes/api/themes/preview.mjs +8 -8
  251. package/dist/astro/routes/api/typegen.mjs +6 -6
  252. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  253. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  254. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  255. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  256. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -11
  257. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -11
  258. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
  259. package/dist/astro/routes/api/widget-areas/index.mjs +11 -11
  260. package/dist/astro/routes/api/widget-components.mjs +4 -4
  261. package/dist/astro/routes/robots.txt.mjs +10 -9
  262. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  263. package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -12
  264. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  265. package/dist/astro/routes/sitemap.xml.mjs +11 -10
  266. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  267. package/dist/astro/types.d.mts +16 -12
  268. package/dist/astro/types.d.mts.map +1 -1
  269. package/dist/auth/providers/github.d.mts +1 -1
  270. package/dist/auth/providers/google.d.mts +1 -1
  271. package/dist/{authorize-D5gfBVU5.mjs → authorize-C0EYoUeV.mjs} +2 -2
  272. package/dist/{authorize-D5gfBVU5.mjs.map → authorize-C0EYoUeV.mjs.map} +1 -1
  273. package/dist/{base64-CqR-7kqF.mjs → base64-CmWvODNW.mjs} +1 -1
  274. package/dist/{base64-CqR-7kqF.mjs.map → base64-CmWvODNW.mjs.map} +1 -1
  275. package/dist/{byline-V_Qp1Ziw.mjs → byline-CC0WS4Gu.mjs} +17 -8
  276. package/dist/byline-CC0WS4Gu.mjs.map +1 -0
  277. package/dist/{byline-fields-B0NO1yUB.mjs → byline-fields-53i9Et0x.mjs} +3 -3
  278. package/dist/{byline-fields-B0NO1yUB.mjs.map → byline-fields-53i9Et0x.mjs.map} +1 -1
  279. package/dist/{byline-fields-nBVqK_Ff.mjs → byline-fields-DNp0HNKc.mjs} +2 -2
  280. package/dist/{byline-fields-nBVqK_Ff.mjs.map → byline-fields-DNp0HNKc.mjs.map} +1 -1
  281. package/dist/{byline-fields-CQJRIQkn.d.mts → byline-fields-jy07PZJM.d.mts} +36 -31
  282. package/dist/byline-fields-jy07PZJM.d.mts.map +1 -0
  283. package/dist/{byline-registry-DedidtqC.mjs → byline-registry-BOjqDOim.mjs} +3 -3
  284. package/dist/{byline-registry-DedidtqC.mjs.map → byline-registry-BOjqDOim.mjs.map} +1 -1
  285. package/dist/{bylines-DfGDnred.mjs → bylines-CCO1CYnH.mjs} +8 -8
  286. package/dist/{bylines-DfGDnred.mjs.map → bylines-CCO1CYnH.mjs.map} +1 -1
  287. package/dist/{bylines-B2NWnIwS.mjs → bylines-DGekMGGm.mjs} +10 -4
  288. package/dist/{bylines-B2NWnIwS.mjs.map → bylines-DGekMGGm.mjs.map} +1 -1
  289. package/dist/{cache-DTTHWD8n.mjs → cache-pXTpun6s.mjs} +3 -3
  290. package/dist/{cache-DTTHWD8n.mjs.map → cache-pXTpun6s.mjs.map} +1 -1
  291. package/dist/{challenge-store-woE0bbCf.mjs → challenge-store-C6E_kWTs.mjs} +1 -1
  292. package/dist/{challenge-store-woE0bbCf.mjs.map → challenge-store-C6E_kWTs.mjs.map} +1 -1
  293. package/dist/{chunks-BerYVuve.mjs → chunks-SyjZaYwV.mjs} +2 -2
  294. package/dist/{chunks-BerYVuve.mjs.map → chunks-SyjZaYwV.mjs.map} +1 -1
  295. package/dist/cli/index.mjs +27 -26
  296. package/dist/cli/index.mjs.map +1 -1
  297. package/dist/client/cf-access.d.mts +1 -1
  298. package/dist/client/index.d.mts +1 -1
  299. package/dist/client/index.mjs +2 -1
  300. package/dist/client/index.mjs.map +1 -1
  301. package/dist/{comment-sqQxNpN3.mjs → comment-80UyJJUR.mjs} +11 -3
  302. package/dist/comment-80UyJJUR.mjs.map +1 -0
  303. package/dist/comment-reaction-B6AdcpXw.mjs +85 -0
  304. package/dist/comment-reaction-B6AdcpXw.mjs.map +1 -0
  305. package/dist/{comments-D2hNuxNa.mjs → comments-CtPkT2tp.mjs} +3 -3
  306. package/dist/{comments-D2hNuxNa.mjs.map → comments-CtPkT2tp.mjs.map} +1 -1
  307. package/dist/{components-DYKp2gmo.mjs → components-D6ZnrzbB.mjs} +1 -1
  308. package/dist/{components-DYKp2gmo.mjs.map → components-D6ZnrzbB.mjs.map} +1 -1
  309. package/dist/{content-BIlVx-RX.mjs → content-2PTDNnoh.mjs} +22 -7
  310. package/dist/content-2PTDNnoh.mjs.map +1 -0
  311. package/dist/{context-Cm4pt1Ws.mjs → context-f1__jpzF.mjs} +11 -11
  312. package/dist/{context-Cm4pt1Ws.mjs.map → context-f1__jpzF.mjs.map} +1 -1
  313. package/dist/{cron-DdEVrQ2Y.mjs → cron-CQPxBjYs.mjs} +1 -1
  314. package/dist/{cron-DdEVrQ2Y.mjs.map → cron-CQPxBjYs.mjs.map} +1 -1
  315. package/dist/{dashboard-C-UYpps0.mjs → dashboard-BOESNcwE.mjs} +4 -4
  316. package/dist/{dashboard-C-UYpps0.mjs.map → dashboard-BOESNcwE.mjs.map} +1 -1
  317. package/dist/database/instrumentation.d.mts +19 -0
  318. package/dist/database/instrumentation.d.mts.map +1 -1
  319. package/dist/database/instrumentation.mjs +8 -1
  320. package/dist/database/instrumentation.mjs.map +1 -1
  321. package/dist/db/index.d.mts +3 -3
  322. package/dist/db/index.mjs +1 -1
  323. package/dist/db/libsql.d.mts +1 -1
  324. package/dist/db/postgres.d.mts +1 -1
  325. package/dist/db/sqlite.d.mts +1 -1
  326. package/dist/{db-errors-BluWkwGI.mjs → db-errors-CrC5w3Jz.mjs} +1 -1
  327. package/dist/{db-errors-BluWkwGI.mjs.map → db-errors-CrC5w3Jz.mjs.map} +1 -1
  328. package/dist/{default-NHGuJzQ3.mjs → default-CpBEPn6a.mjs} +1 -1
  329. package/dist/{default-NHGuJzQ3.mjs.map → default-CpBEPn6a.mjs.map} +1 -1
  330. package/dist/{device-flow-BQApWgnW.mjs → device-flow-Bn-qiDrw.mjs} +5 -5
  331. package/dist/{device-flow-BQApWgnW.mjs.map → device-flow-Bn-qiDrw.mjs.map} +1 -1
  332. package/dist/{email-console-BbU3RbWv.mjs → email-console-B9VS6eN4.mjs} +1 -1
  333. package/dist/{email-console-BbU3RbWv.mjs.map → email-console-B9VS6eN4.mjs.map} +1 -1
  334. package/dist/{error-CNn_w7jf.mjs → error-BQ1pxs0L.mjs} +2 -2
  335. package/dist/{error-CNn_w7jf.mjs.map → error-BQ1pxs0L.mjs.map} +1 -1
  336. package/dist/{escape-DPgcxcpL.mjs → escape-BtbJWyaW.mjs} +1 -1
  337. package/dist/{escape-DPgcxcpL.mjs.map → escape-BtbJWyaW.mjs.map} +1 -1
  338. package/dist/{fts-manager-Cx5z8jdA.mjs → fts-manager-DtiWqwNJ.mjs} +2 -2
  339. package/dist/{fts-manager-Cx5z8jdA.mjs.map → fts-manager-DtiWqwNJ.mjs.map} +1 -1
  340. package/dist/{hash-DlvIFn0b.mjs → hash-BowcuPwv.mjs} +1 -1
  341. package/dist/{hash-DlvIFn0b.mjs.map → hash-BowcuPwv.mjs.map} +1 -1
  342. package/dist/{import-KyxT1Mbs.mjs → import-DqSGOlmR.mjs} +4 -4
  343. package/dist/{import-KyxT1Mbs.mjs.map → import-DqSGOlmR.mjs.map} +1 -1
  344. package/dist/{index-D2VAiumu.d.mts → index-C2dLNT6S.d.mts} +172 -17
  345. package/dist/index-C2dLNT6S.d.mts.map +1 -0
  346. package/dist/{index-uT2yR66F.d.mts → index-ZDEwR7qW.d.mts} +3 -3
  347. package/dist/{index-uT2yR66F.d.mts.map → index-ZDEwR7qW.d.mts.map} +1 -1
  348. package/dist/index.d.mts +18 -17
  349. package/dist/index.mjs +63 -61
  350. package/dist/{init-lock-DlBHjf9-.mjs → init-lock-6b309ZrF.mjs} +2 -29
  351. package/dist/init-lock-6b309ZrF.mjs.map +1 -0
  352. package/dist/{load-Dq91b_DK.mjs → load-Dtoo7KcJ.mjs} +2 -2
  353. package/dist/{load-Dq91b_DK.mjs.map → load-Dtoo7KcJ.mjs.map} +1 -1
  354. package/dist/{loader-BqWjcH3h.mjs → loader-C8Z48Uof.mjs} +4 -4
  355. package/dist/{loader-BqWjcH3h.mjs.map → loader-C8Z48Uof.mjs.map} +1 -1
  356. package/dist/{manifest-schema-DFPeqMAn.mjs → manifest-schema-DDSbwkAL.mjs} +1 -1
  357. package/dist/{manifest-schema-DFPeqMAn.mjs.map → manifest-schema-DDSbwkAL.mjs.map} +1 -1
  358. package/dist/media/image-endpoint.d.mts +74 -0
  359. package/dist/media/image-endpoint.d.mts.map +1 -0
  360. package/dist/media/image-endpoint.mjs +162 -0
  361. package/dist/media/image-endpoint.mjs.map +1 -0
  362. package/dist/media/index.d.mts +1 -1
  363. package/dist/media/index.mjs +2 -2
  364. package/dist/media/local-runtime.d.mts +11 -11
  365. package/dist/media/local-runtime.mjs +9 -8
  366. package/dist/media/local-runtime.mjs.map +1 -1
  367. package/dist/{media-JOf3pNkw.mjs → media-Bw0sA6rb.mjs} +2 -2
  368. package/dist/{media-JOf3pNkw.mjs.map → media-Bw0sA6rb.mjs.map} +1 -1
  369. package/dist/{media-allowlist-_A0SuDn4.mjs → media-allowlist-DunzrKFM.mjs} +2 -2
  370. package/dist/{media-allowlist-_A0SuDn4.mjs.map → media-allowlist-DunzrKFM.mjs.map} +1 -1
  371. package/dist/{media-url-CqLd69IO.mjs → media-url-S22B6aPr.mjs} +1 -1
  372. package/dist/{media-url-CqLd69IO.mjs.map → media-url-S22B6aPr.mjs.map} +1 -1
  373. package/dist/{menus-DX4_E01q.mjs → menus-CYs0WZoL.mjs} +20 -6
  374. package/dist/menus-CYs0WZoL.mjs.map +1 -0
  375. package/dist/{menus-Ryk9L7fT.mjs → menus-DOs1MQJg.mjs} +120 -20
  376. package/dist/menus-DOs1MQJg.mjs.map +1 -0
  377. package/dist/{mime-YbtlEtvS.mjs → mime-DYpsOAny.mjs} +1 -1
  378. package/dist/{mime-YbtlEtvS.mjs.map → mime-DYpsOAny.mjs.map} +1 -1
  379. package/dist/{mode-CGXzIbD8.mjs → mode-CFh8Dw8G.mjs} +1 -1
  380. package/dist/{mode-CGXzIbD8.mjs.map → mode-CFh8Dw8G.mjs.map} +1 -1
  381. package/dist/{normalize-DKsg36ty.mjs → normalize-Uam4_Vkr.mjs} +1 -1
  382. package/dist/{normalize-DKsg36ty.mjs.map → normalize-Uam4_Vkr.mjs.map} +1 -1
  383. package/dist/{oauth-authorization-C2kVyjXI.mjs → oauth-authorization-BN-t83Uy.mjs} +5 -5
  384. package/dist/{oauth-authorization-C2kVyjXI.mjs.map → oauth-authorization-BN-t83Uy.mjs.map} +1 -1
  385. package/dist/{oauth-clients-BC873NCV.mjs → oauth-clients-R6I_V0qz.mjs} +1 -1
  386. package/dist/{oauth-clients-BC873NCV.mjs.map → oauth-clients-R6I_V0qz.mjs.map} +1 -1
  387. package/dist/{oauth-state-store-Cd--TUaq.mjs → oauth-state-store-Csoc6kkR.mjs} +1 -1
  388. package/dist/{oauth-state-store-Cd--TUaq.mjs.map → oauth-state-store-Csoc6kkR.mjs.map} +1 -1
  389. package/dist/{oauth-user-lookup-e4wOvDud.mjs → oauth-user-lookup-d7VYjTpx.mjs} +1 -1
  390. package/dist/{oauth-user-lookup-e4wOvDud.mjs.map → oauth-user-lookup-d7VYjTpx.mjs.map} +1 -1
  391. package/dist/object-cache/memory.d.mts +15 -0
  392. package/dist/object-cache/memory.d.mts.map +1 -0
  393. package/dist/object-cache/memory.mjs +56 -0
  394. package/dist/object-cache/memory.mjs.map +1 -0
  395. package/dist/object-cache-SEb2IM4Z.mjs +373 -0
  396. package/dist/object-cache-SEb2IM4Z.mjs.map +1 -0
  397. package/dist/{options-9kLgkE8m.d.mts → options-DFFpvNJU.d.mts} +3 -3
  398. package/dist/{options-9kLgkE8m.d.mts.map → options-DFFpvNJU.d.mts.map} +1 -1
  399. package/dist/{options-BPCVnesz.mjs → options-DTTML-Tx.mjs} +1 -1
  400. package/dist/{options-BPCVnesz.mjs.map → options-DTTML-Tx.mjs.map} +1 -1
  401. package/dist/page/index.d.mts +2 -2
  402. package/dist/{parse-DzSrk1t8.mjs → parse-qrHlnzTy.mjs} +2 -2
  403. package/dist/{parse-DzSrk1t8.mjs.map → parse-qrHlnzTy.mjs.map} +1 -1
  404. package/dist/{passkey-config-BpjbE_Uv.mjs → passkey-config-BJTbcnI5.mjs} +1 -1
  405. package/dist/{passkey-config-BpjbE_Uv.mjs.map → passkey-config-BJTbcnI5.mjs.map} +1 -1
  406. package/dist/{patterns-p-RBdTbM.mjs → patterns-BKmjvM7K.mjs} +1 -1
  407. package/dist/{patterns-p-RBdTbM.mjs.map → patterns-BKmjvM7K.mjs.map} +1 -1
  408. package/dist/{placeholder-2xumZh4g.mjs → placeholder-CIDCpyEY.mjs} +1 -1
  409. package/dist/{placeholder-2xumZh4g.mjs.map → placeholder-CIDCpyEY.mjs.map} +1 -1
  410. package/dist/{placeholder-BevVKfay.d.mts → placeholder-CirPauNG.d.mts} +1 -1
  411. package/dist/{placeholder-BevVKfay.d.mts.map → placeholder-CirPauNG.d.mts.map} +1 -1
  412. package/dist/plugin-types.d.mts +1 -1
  413. package/dist/plugin-utils.d.mts +9 -9
  414. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  415. package/dist/plugins/adapt-sandbox-entry.mjs +4 -2
  416. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  417. package/dist/{transport-1cIrOb1Y.mjs → portable-text-BIFhrU6T.mjs} +2 -135
  418. package/dist/portable-text-BIFhrU6T.mjs.map +1 -0
  419. package/dist/{preview-Dqv2hwXr.mjs → preview-IDye9SPQ.mjs} +2 -2
  420. package/dist/{preview-Dqv2hwXr.mjs.map → preview-IDye9SPQ.mjs.map} +1 -1
  421. package/dist/{public-url-D_zARuvZ.mjs → public-url-8lFyQ8ZF.mjs} +1 -1
  422. package/dist/{public-url-D_zARuvZ.mjs.map → public-url-8lFyQ8ZF.mjs.map} +1 -1
  423. package/dist/{query-Crm038Mc.mjs → query-B1RVFUNM.mjs} +159 -31
  424. package/dist/query-B1RVFUNM.mjs.map +1 -0
  425. package/dist/{rate-limit-hRTBqmw1.mjs → rate-limit-DfNAqIWW.mjs} +2 -2
  426. package/dist/{rate-limit-hRTBqmw1.mjs.map → rate-limit-DfNAqIWW.mjs.map} +1 -1
  427. package/dist/{redirect-C-OOkyku.mjs → redirect-B4wuX2A5.mjs} +1 -1
  428. package/dist/{redirect-C-OOkyku.mjs.map → redirect-B4wuX2A5.mjs.map} +1 -1
  429. package/dist/{redirect-CRWIt8Zj.mjs → redirect-Bifv_yHv.mjs} +3 -3
  430. package/dist/{redirect-CRWIt8Zj.mjs.map → redirect-Bifv_yHv.mjs.map} +1 -1
  431. package/dist/{redirects-CP3TnTLO.mjs → redirects-CT_vb3NV.mjs} +6 -6
  432. package/dist/{redirects-CP3TnTLO.mjs.map → redirects-CT_vb3NV.mjs.map} +1 -1
  433. package/dist/{redirects-6Zg2SoYo.mjs → redirects-DUvXgzCX.mjs} +8 -3
  434. package/dist/redirects-DUvXgzCX.mjs.map +1 -0
  435. package/dist/{registry-diMzD1Wf.mjs → registry-CjK96fHD.mjs} +6 -6
  436. package/dist/{registry-diMzD1Wf.mjs.map → registry-CjK96fHD.mjs.map} +1 -1
  437. package/dist/{request-cache-UwmBAiUK.mjs → request-cache-KCNHp_RJ.mjs} +1 -1
  438. package/dist/{request-cache-UwmBAiUK.mjs.map → request-cache-KCNHp_RJ.mjs.map} +1 -1
  439. package/dist/{request-meta-DPechd0W.mjs → request-meta-ei3ATilC.mjs} +2 -2
  440. package/dist/{request-meta-DPechd0W.mjs.map → request-meta-ei3ATilC.mjs.map} +1 -1
  441. package/dist/{resolve-B3NUUtVY.mjs → resolve-CpbBglV0.mjs} +1 -1
  442. package/dist/{resolve-B3NUUtVY.mjs.map → resolve-CpbBglV0.mjs.map} +1 -1
  443. package/dist/{runner--4wMWwKM.mjs → runner-DYYnW530.mjs} +201 -170
  444. package/dist/runner-DYYnW530.mjs.map +1 -0
  445. package/dist/{runner-C8vcbvCe.d.mts → runner-jdXtFEd3.d.mts} +2 -2
  446. package/dist/{runner-C8vcbvCe.d.mts.map → runner-jdXtFEd3.d.mts.map} +1 -1
  447. package/dist/runtime.d.mts +10 -10
  448. package/dist/runtime.mjs +3 -3
  449. package/dist/{schema-BDOkd3OU.mjs → schema-5z2Jfnbm.mjs} +13 -8
  450. package/dist/schema-5z2Jfnbm.mjs.map +1 -0
  451. package/dist/{search-Bs_J_EW-.mjs → search-D9FkoM-k.mjs} +4 -4
  452. package/dist/{search-Bs_J_EW-.mjs.map → search-D9FkoM-k.mjs.map} +1 -1
  453. package/dist/{secrets-C8xmE6mR.mjs → secrets-BUE5UQys.mjs} +5 -5
  454. package/dist/{secrets-C8xmE6mR.mjs.map → secrets-BUE5UQys.mjs.map} +1 -1
  455. package/dist/{sections-P0zuBlyz.mjs → sections-DWYZo6HK.mjs} +3 -3
  456. package/dist/{sections-P0zuBlyz.mjs.map → sections-DWYZo6HK.mjs.map} +1 -1
  457. package/dist/seed/index.d.mts +2 -2
  458. package/dist/seed/index.mjs +22 -21
  459. package/dist/seo/index.d.mts +1 -1
  460. package/dist/seo/index.mjs +1 -1
  461. package/dist/{seo-DpNgGQjF.mjs → seo-Cu47j3mJ.mjs} +5 -2
  462. package/dist/seo-Cu47j3mJ.mjs.map +1 -0
  463. package/dist/{seo-CLhm-Fmb.mjs → seo-DRnqnstF.mjs} +1 -1
  464. package/dist/{seo-CLhm-Fmb.mjs.map → seo-DRnqnstF.mjs.map} +1 -1
  465. package/dist/{service-CDQQnT8W.mjs → service-DTmtqCnw.mjs} +3 -3
  466. package/dist/{service-CDQQnT8W.mjs.map → service-DTmtqCnw.mjs.map} +1 -1
  467. package/dist/session-user-DmtPMNa1.mjs +51 -0
  468. package/dist/session-user-DmtPMNa1.mjs.map +1 -0
  469. package/dist/{settings-sO0Fif4p.mjs → settings-DUrVDN0c.mjs} +3 -3
  470. package/dist/{settings-sO0Fif4p.mjs.map → settings-DUrVDN0c.mjs.map} +1 -1
  471. package/dist/{settings-BjBsmVAo.mjs → settings-yaxu9mU-.mjs} +18 -10
  472. package/dist/settings-yaxu9mU-.mjs.map +1 -0
  473. package/dist/{setup-complete-CMMr-oZU.mjs → setup-complete-BWFHzgvZ.mjs} +2 -2
  474. package/dist/{setup-complete-CMMr-oZU.mjs.map → setup-complete-BWFHzgvZ.mjs.map} +1 -1
  475. package/dist/{setup-nonce-169xl4fV.mjs → setup-nonce-DFWG-J5c.mjs} +1 -1
  476. package/dist/{setup-nonce-169xl4fV.mjs.map → setup-nonce-DFWG-J5c.mjs.map} +1 -1
  477. package/dist/{single-flight-cache-C0UV1Npg.mjs → single-flight-cache-B5p5cNOL.mjs} +2 -2
  478. package/dist/{single-flight-cache-C0UV1Npg.mjs.map → single-flight-cache-B5p5cNOL.mjs.map} +1 -1
  479. package/dist/{site-url-vtsuOvSD.mjs → site-url-BOTPgmeM.mjs} +2 -2
  480. package/dist/{site-url-vtsuOvSD.mjs.map → site-url-BOTPgmeM.mjs.map} +1 -1
  481. package/dist/{slugify-Cjh1ssOZ.mjs → slugify-Cce3dTdg.mjs} +1 -1
  482. package/dist/{slugify-Cjh1ssOZ.mjs.map → slugify-Cce3dTdg.mjs.map} +1 -1
  483. package/dist/{ssrf-XO05Voq6.mjs → ssrf-B0VeRLrp.mjs} +1 -1
  484. package/dist/{ssrf-XO05Voq6.mjs.map → ssrf-B0VeRLrp.mjs.map} +1 -1
  485. package/dist/{status-2gZklYuj.mjs → status-CB2basWJ.mjs} +1 -1
  486. package/dist/{status-2gZklYuj.mjs.map → status-CB2basWJ.mjs.map} +1 -1
  487. package/dist/storage/local.d.mts +1 -1
  488. package/dist/storage/local.mjs +1 -1
  489. package/dist/storage/s3.d.mts +1 -1
  490. package/dist/storage/s3.mjs +1 -1
  491. package/dist/{taxonomies-BBxYA38v.mjs → taxonomies-Be9B1jEj.mjs} +156 -122
  492. package/dist/taxonomies-Be9B1jEj.mjs.map +1 -0
  493. package/dist/{taxonomies-DuESHWKI.mjs → taxonomies-CJmkEpdS.mjs} +7 -7
  494. package/dist/{taxonomies-DuESHWKI.mjs.map → taxonomies-CJmkEpdS.mjs.map} +1 -1
  495. package/dist/{taxonomy-CdllE4oq.mjs → taxonomy-B2HQuVf5.mjs} +19 -6
  496. package/dist/taxonomy-B2HQuVf5.mjs.map +1 -0
  497. package/dist/{tokens-DMkVjxrx.mjs → tokens-BvrJvIB6.mjs} +2 -2
  498. package/dist/{tokens-DMkVjxrx.mjs.map → tokens-BvrJvIB6.mjs.map} +1 -1
  499. package/dist/{transaction-x2tJQ-A1.mjs → transaction-qfqpPVpu.mjs} +1 -1
  500. package/dist/{transaction-x2tJQ-A1.mjs.map → transaction-qfqpPVpu.mjs.map} +1 -1
  501. package/dist/transport-B4rXnSTf.mjs +135 -0
  502. package/dist/transport-B4rXnSTf.mjs.map +1 -0
  503. package/dist/{transport-jdvsZEIt.d.mts → transport-k7YjfmEn.d.mts} +1 -1
  504. package/dist/{transport-jdvsZEIt.d.mts.map → transport-k7YjfmEn.d.mts.map} +1 -1
  505. package/dist/{trusted-proxy-CHp41Fjj.mjs → trusted-proxy-DY1_UqHr.mjs} +1 -1
  506. package/dist/{trusted-proxy-CHp41Fjj.mjs.map → trusted-proxy-DY1_UqHr.mjs.map} +1 -1
  507. package/dist/{types-DO7whVYU.d.mts → types-CIKX2HO5.d.mts} +2 -2
  508. package/dist/{types-DO7whVYU.d.mts.map → types-CIKX2HO5.d.mts.map} +1 -1
  509. package/dist/{types-u_XxjbS8.d.mts → types-CKNXt63n.d.mts} +1 -1
  510. package/dist/{types-u_XxjbS8.d.mts.map → types-CKNXt63n.d.mts.map} +1 -1
  511. package/dist/{types-BTnnBYVX.d.mts → types-CWGYDYqF.d.mts} +2 -2
  512. package/dist/{types-BTnnBYVX.d.mts.map → types-CWGYDYqF.d.mts.map} +1 -1
  513. package/dist/{types-CkEuk-Zr.d.mts → types-CgvhU-hF.d.mts} +1 -1
  514. package/dist/{types-CkEuk-Zr.d.mts.map → types-CgvhU-hF.d.mts.map} +1 -1
  515. package/dist/{types-BFgYtuKd.d.mts → types-CmivgZbp.d.mts} +1 -1
  516. package/dist/{types-BFgYtuKd.d.mts.map → types-CmivgZbp.d.mts.map} +1 -1
  517. package/dist/{types-Del0VMij.d.mts → types-Czg1S3gB.d.mts} +9 -1
  518. package/dist/{types-Del0VMij.d.mts.map → types-Czg1S3gB.d.mts.map} +1 -1
  519. package/dist/types-DCNNfeCv.d.mts +124 -0
  520. package/dist/types-DCNNfeCv.d.mts.map +1 -0
  521. package/dist/{types-Bzfk2yC8.d.mts → types-DPCpkzvS.d.mts} +1 -1
  522. package/dist/{types-Bzfk2yC8.d.mts.map → types-DPCpkzvS.d.mts.map} +1 -1
  523. package/dist/{types-DdkL6fyv.d.mts → types-DXLVzV2w.d.mts} +1 -1
  524. package/dist/{types-DdkL6fyv.d.mts.map → types-DXLVzV2w.d.mts.map} +1 -1
  525. package/dist/{types-BXSUSAjt.mjs → types-DXOIbece.mjs} +3 -3
  526. package/dist/{types-BXSUSAjt.mjs.map → types-DXOIbece.mjs.map} +1 -1
  527. package/dist/{types-DejCHqWT.mjs → types-DYF2_Vf4.mjs} +1 -1
  528. package/dist/{types-DejCHqWT.mjs.map → types-DYF2_Vf4.mjs.map} +1 -1
  529. package/dist/{types-BIduXPJk.mjs → types-tM44hEcf.mjs} +1 -1
  530. package/dist/{types-BIduXPJk.mjs.map → types-tM44hEcf.mjs.map} +1 -1
  531. package/dist/{user-C0um7wrg.mjs → user-Db-Rti_z.mjs} +3 -3
  532. package/dist/{user-C0um7wrg.mjs.map → user-Db-Rti_z.mjs.map} +1 -1
  533. package/dist/{utils-C4M981Br.mjs → utils-LbHcSRTj.mjs} +2 -2
  534. package/dist/{utils-C4M981Br.mjs.map → utils-LbHcSRTj.mjs.map} +1 -1
  535. package/dist/{validate-DGhQPXzI.mjs → validate-Bwl64sxv.mjs} +3 -3
  536. package/dist/{validate-DGhQPXzI.mjs.map → validate-Bwl64sxv.mjs.map} +1 -1
  537. package/dist/{validate-cJOiOvT2.d.mts → validate-CE2M0nvx.d.mts} +5 -5
  538. package/dist/{validate-cJOiOvT2.d.mts.map → validate-CE2M0nvx.d.mts.map} +1 -1
  539. package/dist/{validation-DVHjPM1M.mjs → validation-C_yOvFaO.mjs} +6 -6
  540. package/dist/{validation-DVHjPM1M.mjs.map → validation-C_yOvFaO.mjs.map} +1 -1
  541. package/dist/version-RnYXYjzD.mjs +7 -0
  542. package/dist/{version-BOjj_cfz.mjs.map → version-RnYXYjzD.mjs.map} +1 -1
  543. package/dist/{widgets-Ci6hLwfO.mjs → widgets-8GONuRHo.mjs} +4 -4
  544. package/dist/{widgets-Ci6hLwfO.mjs.map → widgets-8GONuRHo.mjs.map} +1 -1
  545. package/dist/{zod-generator-CarzgPAu.mjs → zod-generator-D481JjzD.mjs} +3 -3
  546. package/dist/{zod-generator-CarzgPAu.mjs.map → zod-generator-D481JjzD.mjs.map} +1 -1
  547. package/package.json +18 -6
  548. package/src/api/handlers/api-tokens.ts +19 -0
  549. package/src/api/handlers/comment-reactions.ts +165 -0
  550. package/src/api/handlers/schema.ts +8 -0
  551. package/src/api/schemas/comments.ts +10 -0
  552. package/src/astro/image-endpoint.ts +84 -0
  553. package/src/astro/index.ts +6 -0
  554. package/src/astro/integration/index.ts +83 -22
  555. package/src/astro/integration/routes.ts +5 -0
  556. package/src/astro/integration/runtime.ts +65 -1
  557. package/src/astro/integration/virtual-modules.ts +32 -0
  558. package/src/astro/integration/vite-config.ts +16 -0
  559. package/src/astro/middleware/auth.ts +4 -3
  560. package/src/astro/middleware/stream-end-metrics.ts +11 -1
  561. package/src/astro/middleware.ts +41 -3
  562. package/src/astro/object-cache/adapters.ts +50 -0
  563. package/src/astro/prefetch.ts +77 -0
  564. package/src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts +97 -0
  565. package/src/astro/routes/api/setup/dev-bypass.ts +5 -1
  566. package/src/astro/routes/api/snapshot.ts +3 -1
  567. package/src/astro/session-user.ts +57 -0
  568. package/src/astro/types.ts +1 -0
  569. package/src/comments/query.ts +78 -7
  570. package/src/comments/ranking.ts +58 -0
  571. package/src/components/Comments.astro +136 -1
  572. package/src/database/instrumentation.ts +21 -1
  573. package/src/database/migrations/044_comment_reactions.ts +56 -0
  574. package/src/database/migrations/runner.ts +2 -0
  575. package/src/database/repositories/byline.ts +13 -0
  576. package/src/database/repositories/comment-reaction.ts +132 -0
  577. package/src/database/repositories/comment.ts +10 -0
  578. package/src/database/repositories/content.ts +25 -3
  579. package/src/database/repositories/menu.ts +13 -1
  580. package/src/database/repositories/seo.ts +3 -0
  581. package/src/database/repositories/taxonomy.ts +13 -1
  582. package/src/database/types.ts +9 -0
  583. package/src/emdash-runtime.ts +18 -4
  584. package/src/index.ts +22 -0
  585. package/src/mcp/server.ts +307 -20
  586. package/src/media/image-endpoint.ts +167 -0
  587. package/src/menus/index.ts +11 -4
  588. package/src/object-cache/codec.ts +73 -0
  589. package/src/object-cache/index.ts +495 -0
  590. package/src/object-cache/memory.ts +91 -0
  591. package/src/object-cache/types.ts +124 -0
  592. package/src/plugins/adapt-sandbox-entry.ts +11 -1
  593. package/src/query.ts +196 -17
  594. package/src/schema/query.ts +11 -4
  595. package/src/settings/index.ts +18 -5
  596. package/src/taxonomies/index.ts +237 -165
  597. package/src/virtual-modules.d.ts +11 -0
  598. package/dist/api-DxjIV2o8.mjs.map +0 -1
  599. package/dist/api-tokens-BFFkB0jB.mjs.map +0 -1
  600. package/dist/byline-V_Qp1Ziw.mjs.map +0 -1
  601. package/dist/byline-fields-CQJRIQkn.d.mts.map +0 -1
  602. package/dist/comment-sqQxNpN3.mjs.map +0 -1
  603. package/dist/content-BIlVx-RX.mjs.map +0 -1
  604. package/dist/index-D2VAiumu.d.mts.map +0 -1
  605. package/dist/init-lock-DlBHjf9-.mjs.map +0 -1
  606. package/dist/menus-DX4_E01q.mjs.map +0 -1
  607. package/dist/menus-Ryk9L7fT.mjs.map +0 -1
  608. package/dist/query-Crm038Mc.mjs.map +0 -1
  609. package/dist/redirects-6Zg2SoYo.mjs.map +0 -1
  610. package/dist/runner--4wMWwKM.mjs.map +0 -1
  611. package/dist/schema-BDOkd3OU.mjs.map +0 -1
  612. package/dist/seo-DpNgGQjF.mjs.map +0 -1
  613. package/dist/settings-BjBsmVAo.mjs.map +0 -1
  614. package/dist/taxonomies-BBxYA38v.mjs.map +0 -1
  615. package/dist/taxonomy-CdllE4oq.mjs.map +0 -1
  616. package/dist/transport-1cIrOb1Y.mjs.map +0 -1
  617. package/dist/version-BOjj_cfz.mjs +0 -7
  618. /package/dist/{api-tokens-C7ywRx7l.mjs → api-tokens-BVH-H8Z9.mjs} +0 -0
  619. /package/dist/{ssrf-CRZGzjdL.mjs → ssrf-Cz1e2QPn.mjs} +0 -0
  620. /package/dist/{types-BoRm8-pp.mjs → types-Bfr2Pj6z.mjs} +0 -0
@@ -1,11 +1,11 @@
1
- import "../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../types-BXSUSAjt.mjs";
3
- import { t as UserRepository } from "../../../../user-C0um7wrg.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../error-CNn_w7jf.mjs";
5
- import { n as parseBody, t as isParseError } from "../../../../parse-DzSrk1t8.mjs";
6
- import "../../../../redirects-6Zg2SoYo.mjs";
7
- import { v as authMeActionBody } from "../../../../byline-fields-B0NO1yUB.mjs";
8
- import "../../../../status-2gZklYuj.mjs";
1
+ import "../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../types-DXOIbece.mjs";
3
+ import { t as UserRepository } from "../../../../user-Db-Rti_z.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../error-BQ1pxs0L.mjs";
5
+ import { n as parseBody, t as isParseError } from "../../../../parse-qrHlnzTy.mjs";
6
+ import "../../../../redirects-DUvXgzCX.mjs";
7
+ import { v as authMeActionBody } from "../../../../byline-fields-53i9Et0x.mjs";
8
+ import "../../../../status-CB2basWJ.mjs";
9
9
  import "../../../../api/schemas/index.mjs";
10
10
 
11
11
  //#region src/astro/routes/api/auth/me.ts
@@ -1,4 +1,4 @@
1
- import { t as getAuthMode } from "../../../../mode-CGXzIbD8.mjs";
1
+ import { t as getAuthMode } from "../../../../mode-CFh8Dw8G.mjs";
2
2
 
3
3
  //#region src/astro/routes/api/auth/mode.ts
4
4
  const prerender = false;
@@ -1,7 +1,7 @@
1
- import { t as OptionsRepository } from "../../../../../../options-BPCVnesz.mjs";
2
- import { n as getPublicOrigin } from "../../../../../../public-url-D_zARuvZ.mjs";
3
- import { t as finalizeSetup } from "../../../../../../setup-complete-CMMr-oZU.mjs";
4
- import { t as createOAuthStateStore } from "../../../../../../oauth-state-store-Cd--TUaq.mjs";
1
+ import { t as OptionsRepository } from "../../../../../../options-DTTML-Tx.mjs";
2
+ import { n as getPublicOrigin } from "../../../../../../public-url-8lFyQ8ZF.mjs";
3
+ import { t as finalizeSetup } from "../../../../../../setup-complete-BWFHzgvZ.mjs";
4
+ import { t as createOAuthStateStore } from "../../../../../../oauth-state-store-Csoc6kkR.mjs";
5
5
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
6
6
  import { OAuthError, Role, handleOAuthCallback } from "@emdash-cms/auth";
7
7
 
@@ -1,5 +1,5 @@
1
- import { n as getPublicOrigin } from "../../../../../public-url-D_zARuvZ.mjs";
2
- import { t as createOAuthStateStore } from "../../../../../oauth-state-store-Cd--TUaq.mjs";
1
+ import { n as getPublicOrigin } from "../../../../../public-url-8lFyQ8ZF.mjs";
2
+ import { t as createOAuthStateStore } from "../../../../../oauth-state-store-Csoc6kkR.mjs";
3
3
  import { createAuthorizationUrl } from "@emdash-cms/auth";
4
4
 
5
5
  //#region src/astro/routes/api/auth/oauth/[provider].ts
@@ -1,10 +1,10 @@
1
- import "../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../types-BXSUSAjt.mjs";
3
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
4
- import { n as parseBody, t as isParseError } from "../../../../../parse-DzSrk1t8.mjs";
5
- import "../../../../../redirects-6Zg2SoYo.mjs";
6
- import { E as passkeyRenameBody } from "../../../../../byline-fields-B0NO1yUB.mjs";
7
- import "../../../../../status-2gZklYuj.mjs";
1
+ import "../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../types-DXOIbece.mjs";
3
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-BQ1pxs0L.mjs";
4
+ import { n as parseBody, t as isParseError } from "../../../../../parse-qrHlnzTy.mjs";
5
+ import "../../../../../redirects-DUvXgzCX.mjs";
6
+ import { E as passkeyRenameBody } from "../../../../../byline-fields-53i9Et0x.mjs";
7
+ import "../../../../../status-CB2basWJ.mjs";
8
8
  import "../../../../../api/schemas/index.mjs";
9
9
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
10
10
 
@@ -1,6 +1,6 @@
1
- import "../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../types-BXSUSAjt.mjs";
3
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
1
+ import "../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../types-DXOIbece.mjs";
3
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-BQ1pxs0L.mjs";
4
4
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
5
5
 
6
6
  //#region src/astro/routes/api/auth/passkey/index.ts
@@ -1,17 +1,17 @@
1
- import "../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../types-BXSUSAjt.mjs";
3
- import { t as OptionsRepository } from "../../../../../options-BPCVnesz.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
5
- import { r as parseOptionalBody, t as isParseError } from "../../../../../parse-DzSrk1t8.mjs";
6
- import "../../../../../redirects-6Zg2SoYo.mjs";
7
- import { C as passkeyOptionsBody } from "../../../../../byline-fields-B0NO1yUB.mjs";
8
- import "../../../../../status-2gZklYuj.mjs";
1
+ import "../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../types-DXOIbece.mjs";
3
+ import { t as OptionsRepository } from "../../../../../options-DTTML-Tx.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-BQ1pxs0L.mjs";
5
+ import { r as parseOptionalBody, t as isParseError } from "../../../../../parse-qrHlnzTy.mjs";
6
+ import "../../../../../redirects-DUvXgzCX.mjs";
7
+ import { C as passkeyOptionsBody } from "../../../../../byline-fields-53i9Et0x.mjs";
8
+ import "../../../../../status-CB2basWJ.mjs";
9
9
  import "../../../../../api/schemas/index.mjs";
10
- import { t as getTrustedProxyHeaders } from "../../../../../trusted-proxy-CHp41Fjj.mjs";
11
- import { n as getPublicOrigin } from "../../../../../public-url-D_zARuvZ.mjs";
12
- import { n as createChallengeStore, t as cleanupExpiredChallenges } from "../../../../../challenge-store-woE0bbCf.mjs";
13
- import { t as getPasskeyConfig } from "../../../../../passkey-config-BpjbE_Uv.mjs";
14
- import { n as getClientIp, r as rateLimitResponse, t as checkRateLimit } from "../../../../../rate-limit-hRTBqmw1.mjs";
10
+ import { t as getTrustedProxyHeaders } from "../../../../../trusted-proxy-DY1_UqHr.mjs";
11
+ import { n as getPublicOrigin } from "../../../../../public-url-8lFyQ8ZF.mjs";
12
+ import { n as createChallengeStore, t as cleanupExpiredChallenges } from "../../../../../challenge-store-C6E_kWTs.mjs";
13
+ import { t as getPasskeyConfig } from "../../../../../passkey-config-BJTbcnI5.mjs";
14
+ import { n as getClientIp, r as rateLimitResponse, t as checkRateLimit } from "../../../../../rate-limit-DfNAqIWW.mjs";
15
15
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
16
16
  import { generateAuthenticationOptions } from "@emdash-cms/auth/passkey";
17
17
 
@@ -1,15 +1,15 @@
1
- import "../../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../../types-BXSUSAjt.mjs";
3
- import { t as OptionsRepository } from "../../../../../../options-BPCVnesz.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
5
- import { r as parseOptionalBody, t as isParseError } from "../../../../../../parse-DzSrk1t8.mjs";
6
- import "../../../../../../redirects-6Zg2SoYo.mjs";
7
- import { w as passkeyRegisterOptionsBody } from "../../../../../../byline-fields-B0NO1yUB.mjs";
8
- import "../../../../../../status-2gZklYuj.mjs";
1
+ import "../../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../../types-DXOIbece.mjs";
3
+ import { t as OptionsRepository } from "../../../../../../options-DTTML-Tx.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-BQ1pxs0L.mjs";
5
+ import { r as parseOptionalBody, t as isParseError } from "../../../../../../parse-qrHlnzTy.mjs";
6
+ import "../../../../../../redirects-DUvXgzCX.mjs";
7
+ import { w as passkeyRegisterOptionsBody } from "../../../../../../byline-fields-53i9Et0x.mjs";
8
+ import "../../../../../../status-CB2basWJ.mjs";
9
9
  import "../../../../../../api/schemas/index.mjs";
10
- import { n as getPublicOrigin } from "../../../../../../public-url-D_zARuvZ.mjs";
11
- import { n as createChallengeStore } from "../../../../../../challenge-store-woE0bbCf.mjs";
12
- import { t as getPasskeyConfig } from "../../../../../../passkey-config-BpjbE_Uv.mjs";
10
+ import { n as getPublicOrigin } from "../../../../../../public-url-8lFyQ8ZF.mjs";
11
+ import { n as createChallengeStore } from "../../../../../../challenge-store-C6E_kWTs.mjs";
12
+ import { t as getPasskeyConfig } from "../../../../../../passkey-config-BJTbcnI5.mjs";
13
13
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
14
14
  import { generateRegistrationOptions } from "@emdash-cms/auth/passkey";
15
15
 
@@ -1,16 +1,16 @@
1
- import "../../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../../types-BXSUSAjt.mjs";
3
- import { t as OptionsRepository } from "../../../../../../options-BPCVnesz.mjs";
4
- import { n as apiSuccess, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
5
- import { n as parseBody, t as isParseError } from "../../../../../../parse-DzSrk1t8.mjs";
6
- import "../../../../../../redirects-6Zg2SoYo.mjs";
7
- import { T as passkeyRegisterVerifyBody } from "../../../../../../byline-fields-B0NO1yUB.mjs";
8
- import "../../../../../../status-2gZklYuj.mjs";
1
+ import "../../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../../types-DXOIbece.mjs";
3
+ import { t as OptionsRepository } from "../../../../../../options-DTTML-Tx.mjs";
4
+ import { n as apiSuccess, t as apiError } from "../../../../../../error-BQ1pxs0L.mjs";
5
+ import { n as parseBody, t as isParseError } from "../../../../../../parse-qrHlnzTy.mjs";
6
+ import "../../../../../../redirects-DUvXgzCX.mjs";
7
+ import { T as passkeyRegisterVerifyBody } from "../../../../../../byline-fields-53i9Et0x.mjs";
8
+ import "../../../../../../status-CB2basWJ.mjs";
9
9
  import "../../../../../../api/schemas/index.mjs";
10
- import { n as getPublicOrigin } from "../../../../../../public-url-D_zARuvZ.mjs";
11
- import { n as validateAllowedOrigins, t as getConfiguredAllowedOrigins } from "../../../../../../allowed-origins-BqC8cul8.mjs";
12
- import { n as createChallengeStore } from "../../../../../../challenge-store-woE0bbCf.mjs";
13
- import { t as getPasskeyConfig } from "../../../../../../passkey-config-BpjbE_Uv.mjs";
10
+ import { n as getPublicOrigin } from "../../../../../../public-url-8lFyQ8ZF.mjs";
11
+ import { n as validateAllowedOrigins, t as getConfiguredAllowedOrigins } from "../../../../../../allowed-origins-DjlhyfNN.mjs";
12
+ import { n as createChallengeStore } from "../../../../../../challenge-store-C6E_kWTs.mjs";
13
+ import { t as getPasskeyConfig } from "../../../../../../passkey-config-BJTbcnI5.mjs";
14
14
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
15
15
  import { registerPasskey, verifyRegistrationResponse } from "@emdash-cms/auth/passkey";
16
16
 
@@ -1,16 +1,16 @@
1
- import "../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../types-BXSUSAjt.mjs";
3
- import { t as OptionsRepository } from "../../../../../options-BPCVnesz.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
5
- import { n as parseBody, t as isParseError } from "../../../../../parse-DzSrk1t8.mjs";
6
- import "../../../../../redirects-6Zg2SoYo.mjs";
7
- import { D as passkeyVerifyBody } from "../../../../../byline-fields-B0NO1yUB.mjs";
8
- import "../../../../../status-2gZklYuj.mjs";
1
+ import "../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../types-DXOIbece.mjs";
3
+ import { t as OptionsRepository } from "../../../../../options-DTTML-Tx.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-BQ1pxs0L.mjs";
5
+ import { n as parseBody, t as isParseError } from "../../../../../parse-qrHlnzTy.mjs";
6
+ import "../../../../../redirects-DUvXgzCX.mjs";
7
+ import { D as passkeyVerifyBody } from "../../../../../byline-fields-53i9Et0x.mjs";
8
+ import "../../../../../status-CB2basWJ.mjs";
9
9
  import "../../../../../api/schemas/index.mjs";
10
- import { n as getPublicOrigin } from "../../../../../public-url-D_zARuvZ.mjs";
11
- import { n as validateAllowedOrigins, t as getConfiguredAllowedOrigins } from "../../../../../allowed-origins-BqC8cul8.mjs";
12
- import { n as createChallengeStore } from "../../../../../challenge-store-woE0bbCf.mjs";
13
- import { t as getPasskeyConfig } from "../../../../../passkey-config-BpjbE_Uv.mjs";
10
+ import { n as getPublicOrigin } from "../../../../../public-url-8lFyQ8ZF.mjs";
11
+ import { n as validateAllowedOrigins, t as getConfiguredAllowedOrigins } from "../../../../../allowed-origins-DjlhyfNN.mjs";
12
+ import { n as createChallengeStore } from "../../../../../challenge-store-C6E_kWTs.mjs";
13
+ import { t as getPasskeyConfig } from "../../../../../passkey-config-BJTbcnI5.mjs";
14
14
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
15
15
  import { PasskeyAuthenticationError, authenticateWithPasskey } from "@emdash-cms/auth/passkey";
16
16
 
@@ -1,16 +1,16 @@
1
- import "../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../types-BXSUSAjt.mjs";
3
- import { t as OptionsRepository } from "../../../../../options-BPCVnesz.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
5
- import { n as parseBody, t as isParseError } from "../../../../../parse-DzSrk1t8.mjs";
6
- import "../../../../../redirects-6Zg2SoYo.mjs";
7
- import { O as signupCompleteBody } from "../../../../../byline-fields-B0NO1yUB.mjs";
8
- import "../../../../../status-2gZklYuj.mjs";
1
+ import "../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../types-DXOIbece.mjs";
3
+ import { t as OptionsRepository } from "../../../../../options-DTTML-Tx.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-BQ1pxs0L.mjs";
5
+ import { n as parseBody, t as isParseError } from "../../../../../parse-qrHlnzTy.mjs";
6
+ import "../../../../../redirects-DUvXgzCX.mjs";
7
+ import { O as signupCompleteBody } from "../../../../../byline-fields-53i9Et0x.mjs";
8
+ import "../../../../../status-CB2basWJ.mjs";
9
9
  import "../../../../../api/schemas/index.mjs";
10
- import { n as getPublicOrigin } from "../../../../../public-url-D_zARuvZ.mjs";
11
- import { n as validateAllowedOrigins, t as getConfiguredAllowedOrigins } from "../../../../../allowed-origins-BqC8cul8.mjs";
12
- import { n as createChallengeStore } from "../../../../../challenge-store-woE0bbCf.mjs";
13
- import { t as getPasskeyConfig } from "../../../../../passkey-config-BpjbE_Uv.mjs";
10
+ import { n as getPublicOrigin } from "../../../../../public-url-8lFyQ8ZF.mjs";
11
+ import { n as validateAllowedOrigins, t as getConfiguredAllowedOrigins } from "../../../../../allowed-origins-DjlhyfNN.mjs";
12
+ import { n as createChallengeStore } from "../../../../../challenge-store-C6E_kWTs.mjs";
13
+ import { t as getPasskeyConfig } from "../../../../../passkey-config-BJTbcnI5.mjs";
14
14
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
15
15
  import { SignupError, completeSignup } from "@emdash-cms/auth";
16
16
  import { registerPasskey, verifyRegistrationResponse } from "@emdash-cms/auth/passkey";
@@ -1,15 +1,15 @@
1
- import "../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../types-BXSUSAjt.mjs";
3
- import { t as OptionsRepository } from "../../../../../options-BPCVnesz.mjs";
4
- import { n as apiSuccess, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
5
- import { n as parseBody, t as isParseError } from "../../../../../parse-DzSrk1t8.mjs";
6
- import "../../../../../redirects-6Zg2SoYo.mjs";
7
- import { k as signupRequestBody } from "../../../../../byline-fields-B0NO1yUB.mjs";
8
- import "../../../../../status-2gZklYuj.mjs";
1
+ import "../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../types-DXOIbece.mjs";
3
+ import { t as OptionsRepository } from "../../../../../options-DTTML-Tx.mjs";
4
+ import { n as apiSuccess, t as apiError } from "../../../../../error-BQ1pxs0L.mjs";
5
+ import { n as parseBody, t as isParseError } from "../../../../../parse-qrHlnzTy.mjs";
6
+ import "../../../../../redirects-DUvXgzCX.mjs";
7
+ import { k as signupRequestBody } from "../../../../../byline-fields-53i9Et0x.mjs";
8
+ import "../../../../../status-CB2basWJ.mjs";
9
9
  import "../../../../../api/schemas/index.mjs";
10
- import { t as getTrustedProxyHeaders } from "../../../../../trusted-proxy-CHp41Fjj.mjs";
11
- import { t as getSiteBaseUrl } from "../../../../../site-url-vtsuOvSD.mjs";
12
- import { n as getClientIp, t as checkRateLimit } from "../../../../../rate-limit-hRTBqmw1.mjs";
10
+ import { t as getTrustedProxyHeaders } from "../../../../../trusted-proxy-DY1_UqHr.mjs";
11
+ import { t as getSiteBaseUrl } from "../../../../../site-url-BOTPgmeM.mjs";
12
+ import { n as getClientIp, t as checkRateLimit } from "../../../../../rate-limit-DfNAqIWW.mjs";
13
13
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
14
14
  import { requestSignup } from "@emdash-cms/auth";
15
15
 
@@ -1,6 +1,6 @@
1
- import "../../../../../base64-CqR-7kqF.mjs";
2
- import "../../../../../types-BXSUSAjt.mjs";
3
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
1
+ import "../../../../../base64-CmWvODNW.mjs";
2
+ import "../../../../../types-DXOIbece.mjs";
3
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-BQ1pxs0L.mjs";
4
4
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
5
5
  import { SignupError, roleFromLevel, validateSignupToken } from "@emdash-cms/auth";
6
6
 
@@ -1,20 +1,21 @@
1
1
  import { t as validateIdentifier } from "../../../../../../validate-VPnKoIzW.mjs";
2
- import "../../../../../../base64-CqR-7kqF.mjs";
3
- import "../../../../../../types-BXSUSAjt.mjs";
4
- import { t as CommentRepository } from "../../../../../../comment-sqQxNpN3.mjs";
5
- import "../../../../../../options-BPCVnesz.mjs";
6
- import "../../../../../../init-lock-DlBHjf9-.mjs";
7
- import { a as unwrapResult, i as requireDb, n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
8
- import { n as parseBody, t as isParseError } from "../../../../../../parse-DzSrk1t8.mjs";
9
- import { yt as createCommentBody } from "../../../../../../redirects-6Zg2SoYo.mjs";
10
- import "../../../../../../byline-fields-B0NO1yUB.mjs";
11
- import "../../../../../../status-2gZklYuj.mjs";
2
+ import "../../../../../../after-B1IIdH3Y.mjs";
3
+ import "../../../../../../object-cache-SEb2IM4Z.mjs";
4
+ import "../../../../../../base64-CmWvODNW.mjs";
5
+ import "../../../../../../types-DXOIbece.mjs";
6
+ import { t as CommentRepository } from "../../../../../../comment-80UyJJUR.mjs";
7
+ import "../../../../../../options-DTTML-Tx.mjs";
8
+ import { a as unwrapResult, i as requireDb, n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-BQ1pxs0L.mjs";
9
+ import { n as parseBody, t as isParseError } from "../../../../../../parse-qrHlnzTy.mjs";
10
+ import { yt as createCommentBody } from "../../../../../../redirects-DUvXgzCX.mjs";
11
+ import "../../../../../../byline-fields-53i9Et0x.mjs";
12
+ import "../../../../../../status-CB2basWJ.mjs";
12
13
  import "../../../../../../api/schemas/index.mjs";
13
- import { t as extractRequestMeta } from "../../../../../../request-meta-DPechd0W.mjs";
14
- import { i as resolveSecretsCached } from "../../../../../../secrets-C8xmE6mR.mjs";
15
- import { c as hashIp, s as handleCommentList, t as checkRateLimit } from "../../../../../../comments-D2hNuxNa.mjs";
16
- import { t as getSiteBaseUrl } from "../../../../../../site-url-vtsuOvSD.mjs";
17
- import { i as sendCommentNotification, t as createComment } from "../../../../../../service-CDQQnT8W.mjs";
14
+ import { t as extractRequestMeta } from "../../../../../../request-meta-ei3ATilC.mjs";
15
+ import { i as resolveSecretsCached } from "../../../../../../secrets-BUE5UQys.mjs";
16
+ import { c as hashIp, s as handleCommentList, t as checkRateLimit } from "../../../../../../comments-CtPkT2tp.mjs";
17
+ import { t as getSiteBaseUrl } from "../../../../../../site-url-BOTPgmeM.mjs";
18
+ import { i as sendCommentNotification, t as createComment } from "../../../../../../service-DTmtqCnw.mjs";
18
19
 
19
20
  //#region src/astro/routes/api/comments/[collection]/[contentId]/index.ts
20
21
  const prerender = false;
@@ -1 +1 @@
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, 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 { 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// 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);\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, 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 { 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// 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);\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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"}
@@ -0,0 +1,9 @@
1
+ import { APIRoute } from "astro";
2
+
3
+ //#region src/astro/routes/api/comments/[collection]/[contentId]/reactions.d.ts
4
+ declare const prerender = false;
5
+ declare const GET: APIRoute;
6
+ declare const POST: APIRoute;
7
+ //#endregion
8
+ export { GET, POST, prerender };
9
+ //# sourceMappingURL=reactions.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactions.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts"],"mappings":";;;cAuBa,SAAA;AAAA,cAEA,GAAA,EAAK,QAAA;AAAA,cAgCL,IAAA,EAAM,QAAA"}
@@ -0,0 +1,179 @@
1
+ import "../../../../../../after-B1IIdH3Y.mjs";
2
+ import { s as invalidateCommentObjectCache } from "../../../../../../object-cache-SEb2IM4Z.mjs";
3
+ import "../../../../../../base64-CmWvODNW.mjs";
4
+ import "../../../../../../types-DXOIbece.mjs";
5
+ import "../../../../../../comment-80UyJJUR.mjs";
6
+ import "../../../../../../options-DTTML-Tx.mjs";
7
+ import { a as unwrapResult, i as requireDb, n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-BQ1pxs0L.mjs";
8
+ import { n as parseBody, t as isParseError } from "../../../../../../parse-qrHlnzTy.mjs";
9
+ import { bt as createReactionBody } from "../../../../../../redirects-DUvXgzCX.mjs";
10
+ import "../../../../../../byline-fields-53i9Et0x.mjs";
11
+ import "../../../../../../status-CB2basWJ.mjs";
12
+ import "../../../../../../api/schemas/index.mjs";
13
+ import { t as extractRequestMeta } from "../../../../../../request-meta-ei3ATilC.mjs";
14
+ import { t as CommentReactionRepository } from "../../../../../../comment-reaction-B6AdcpXw.mjs";
15
+ import { i as resolveSecretsCached } from "../../../../../../secrets-BUE5UQys.mjs";
16
+ import { c as hashIp } from "../../../../../../comments-CtPkT2tp.mjs";
17
+
18
+ //#region src/api/handlers/comment-reactions.ts
19
+ /** Max reactions a single voter may register per window before throttling. */
20
+ const REACTION_RATE_LIMIT = 30;
21
+ const REACTION_RATE_WINDOW_MINUTES = 10;
22
+ /**
23
+ * Reactions the system accepts. Positive-only for now (matches the shipped
24
+ * widget); kept as an allowlist so a voter can't spam arbitrary reaction
25
+ * strings and bloat a comment's count map. Extend (or make configurable) as
26
+ * the UI grows.
27
+ */
28
+ const ALLOWED_REACTIONS = new Set(["like"]);
29
+ /**
30
+ * Toggle a reaction for a voter on an approved comment belonging to the given
31
+ * content item. Rate-limited per voter.
32
+ */
33
+ async function handleReactionToggle(db, params) {
34
+ try {
35
+ const { collection, contentId, commentId, reaction, voterHash } = params;
36
+ if (!ALLOWED_REACTIONS.has(reaction)) return {
37
+ success: false,
38
+ error: {
39
+ code: "VALIDATION_ERROR",
40
+ message: "Unsupported reaction"
41
+ }
42
+ };
43
+ const comment = await db.selectFrom("_emdash_comments").select(["id", "status"]).where("id", "=", commentId).where("collection", "=", collection).where("content_id", "=", contentId).executeTakeFirst();
44
+ if (!comment) return {
45
+ success: false,
46
+ error: {
47
+ code: "NOT_FOUND",
48
+ message: "Comment not found"
49
+ }
50
+ };
51
+ if (comment.status !== "approved") return {
52
+ success: false,
53
+ error: {
54
+ code: "COMMENT_NOT_APPROVED",
55
+ message: "Cannot react to this comment"
56
+ }
57
+ };
58
+ const repo = new CommentReactionRepository(db);
59
+ if (await repo.countRecentByVoter(voterHash, REACTION_RATE_WINDOW_MINUTES) >= REACTION_RATE_LIMIT) return {
60
+ success: false,
61
+ error: {
62
+ code: "RATE_LIMITED",
63
+ message: "Too many reactions. Please try again later."
64
+ }
65
+ };
66
+ const { reacted } = await repo.toggle({
67
+ commentId,
68
+ reaction,
69
+ voterHash
70
+ });
71
+ const countsMap = await repo.countsForComments([commentId]);
72
+ invalidateCommentObjectCache();
73
+ return {
74
+ success: true,
75
+ data: {
76
+ commentId,
77
+ reaction,
78
+ reacted,
79
+ counts: countsMap.get(commentId) ?? {}
80
+ }
81
+ };
82
+ } catch {
83
+ return {
84
+ success: false,
85
+ error: {
86
+ code: "REACTION_TOGGLE_ERROR",
87
+ message: "Failed to toggle reaction"
88
+ }
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Read aggregate reaction counts for every approved comment on a content item,
94
+ * plus (optionally) which reactions the current voter has active.
95
+ */
96
+ async function handleReactionCounts(db, collection, contentId, voterHash) {
97
+ try {
98
+ const ids = (await db.selectFrom("_emdash_comments").select("id").where("collection", "=", collection).where("content_id", "=", contentId).where("status", "=", "approved").execute()).map((c) => c.id);
99
+ const repo = new CommentReactionRepository(db);
100
+ const countsMap = await repo.countsForComments(ids);
101
+ const reactions = {};
102
+ for (const [id, counts] of countsMap) reactions[id] = counts;
103
+ const data = { reactions };
104
+ if (voterHash) {
105
+ const viewerMap = await repo.viewerReactions(ids, voterHash);
106
+ const viewer = {};
107
+ for (const [id, list] of viewerMap) viewer[id] = list;
108
+ data.viewer = viewer;
109
+ }
110
+ return {
111
+ success: true,
112
+ data
113
+ };
114
+ } catch {
115
+ return {
116
+ success: false,
117
+ error: {
118
+ code: "REACTION_COUNTS_ERROR",
119
+ message: "Failed to read reactions"
120
+ }
121
+ };
122
+ }
123
+ }
124
+
125
+ //#endregion
126
+ //#region src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts
127
+ const prerender = false;
128
+ const GET = async ({ params, request, locals }) => {
129
+ const { emdash } = locals;
130
+ const { collection, contentId } = params;
131
+ if (!collection || !contentId) return apiError("VALIDATION_ERROR", "Collection and content ID required", 400);
132
+ const dbErr = requireDb(emdash?.db);
133
+ if (dbErr) return dbErr;
134
+ try {
135
+ const meta = extractRequestMeta(request, emdash.config);
136
+ let voterHash = "unknown";
137
+ if (meta.ip) {
138
+ const { ipSalt } = await resolveSecretsCached(emdash.db);
139
+ voterHash = await hashIp(meta.ip, ipSalt);
140
+ }
141
+ return unwrapResult(await handleReactionCounts(emdash.db, collection, contentId, voterHash));
142
+ } catch (error) {
143
+ return handleError(error, "Failed to read reactions", "REACTION_COUNTS_ERROR");
144
+ }
145
+ };
146
+ const POST = async ({ params, request, locals }) => {
147
+ const { emdash } = locals;
148
+ const { collection, contentId } = params;
149
+ if (!collection || !contentId) return apiError("VALIDATION_ERROR", "Collection and content ID required", 400);
150
+ const dbErr = requireDb(emdash?.db);
151
+ if (dbErr) return dbErr;
152
+ try {
153
+ const body = await parseBody(request, createReactionBody);
154
+ if (isParseError(body)) return body;
155
+ if (body.website_url) return apiSuccess({
156
+ reacted: false,
157
+ counts: {}
158
+ });
159
+ const meta = extractRequestMeta(request, emdash.config);
160
+ let voterHash = "unknown";
161
+ if (meta.ip) {
162
+ const { ipSalt } = await resolveSecretsCached(emdash.db);
163
+ voterHash = await hashIp(meta.ip, ipSalt);
164
+ }
165
+ return unwrapResult(await handleReactionToggle(emdash.db, {
166
+ collection,
167
+ contentId,
168
+ commentId: body.commentId,
169
+ reaction: body.reaction,
170
+ voterHash
171
+ }), 200);
172
+ } catch (error) {
173
+ return handleError(error, "Failed to toggle reaction", "REACTION_TOGGLE_ERROR");
174
+ }
175
+ };
176
+
177
+ //#endregion
178
+ export { GET, POST, prerender };
179
+ //# sourceMappingURL=reactions.mjs.map