emdash 0.21.0 → 0.23.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 (655) hide show
  1. package/dist/{adapters-BxSmgtbF.d.mts → adapters-DAAjOID4.d.mts} +1 -1
  2. package/dist/{adapters-BxSmgtbF.d.mts.map → adapters-DAAjOID4.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-D5FxMUo8.mjs} +2 -2
  6. package/dist/{allowed-origins-BqC8cul8.mjs.map → allowed-origins-D5FxMUo8.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-BQ_yKRdG.mjs} +31 -25
  13. package/dist/api-BQ_yKRdG.mjs.map +1 -0
  14. package/dist/{api-tokens-BFFkB0jB.mjs → api-tokens-D6ppjIVi.mjs} +13 -3
  15. package/dist/api-tokens-D6ppjIVi.mjs.map +1 -0
  16. package/dist/{apply-CLjxheyb.mjs → apply-CWRyxIoO.mjs} +18 -18
  17. package/dist/{apply-CLjxheyb.mjs.map → apply-CWRyxIoO.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 +122 -26
  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.d.mts.map +1 -1
  32. package/dist/astro/middleware/request-context.mjs +8 -6
  33. package/dist/astro/middleware/request-context.mjs.map +1 -1
  34. package/dist/astro/middleware/setup.mjs +1 -1
  35. package/dist/astro/middleware.d.mts +1 -1
  36. package/dist/astro/middleware.d.mts.map +1 -1
  37. package/dist/astro/middleware.mjs +444 -149
  38. package/dist/astro/middleware.mjs.map +1 -1
  39. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  40. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  41. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  42. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  43. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  44. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
  45. package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
  46. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
  47. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +18 -16
  48. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  49. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +18 -16
  50. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  51. package/dist/astro/routes/api/admin/bylines/index.mjs +18 -16
  52. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +15 -13
  54. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -6
  56. package/dist/astro/routes/api/admin/comments/_id_.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -10
  58. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -6
  60. package/dist/astro/routes/api/admin/comments/counts.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/comments/index.mjs +12 -10
  62. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  64. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  65. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  66. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  67. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +41 -39
  68. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +41 -39
  70. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +40 -38
  72. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +40 -38
  74. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +40 -38
  76. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/index.mjs +40 -38
  78. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +40 -38
  81. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +40 -38
  83. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +40 -38
  85. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +40 -38
  87. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +41 -39
  89. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +40 -38
  91. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +41 -39
  93. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs +40 -38
  95. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +40 -38
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  99. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +40 -38
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  102. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  103. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
  104. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  105. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  106. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  107. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  108. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  109. package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
  110. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  111. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  112. package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -11
  113. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  114. package/dist/astro/routes/api/auth/me.mjs +8 -8
  115. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  116. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  117. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  118. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  119. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  120. package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
  121. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  122. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  123. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  124. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  125. package/dist/astro/routes/api/auth/signup/request.mjs +11 -11
  126. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  127. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +16 -15
  128. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  129. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts +9 -0
  130. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts.map +1 -0
  131. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +179 -0
  132. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -0
  133. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  134. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
  135. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  136. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  137. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -13
  138. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
  139. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  140. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  141. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  142. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -15
  143. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  144. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  145. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
  146. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  147. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  148. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  149. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  150. package/dist/astro/routes/api/dashboard.mjs +10 -8
  151. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  152. package/dist/astro/routes/api/dev/emails.mjs +4 -4
  153. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  154. package/dist/astro/routes/api/import/probe.mjs +12 -12
  155. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  156. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  157. package/dist/astro/routes/api/import/wordpress/execute.mjs +17 -15
  158. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  159. package/dist/astro/routes/api/import/wordpress/media.mjs +10 -10
  160. package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
  161. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +10 -10
  162. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  163. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +12 -12
  164. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  165. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  166. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +19 -17
  167. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  168. package/dist/astro/routes/api/manifest.mjs +5 -5
  169. package/dist/astro/routes/api/mcp.mjs +213 -46
  170. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  171. package/dist/astro/routes/api/media/_id_/confirm.mjs +8 -8
  172. package/dist/astro/routes/api/media/_id_.mjs +8 -8
  173. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  174. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  175. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  176. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  177. package/dist/astro/routes/api/media/upload-url.mjs +10 -10
  178. package/dist/astro/routes/api/media.mjs +13 -13
  179. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -9
  180. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  181. package/dist/astro/routes/api/menus/_name_/items.mjs +11 -9
  182. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  183. package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -9
  184. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  185. package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -9
  186. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  187. package/dist/astro/routes/api/menus/_name_.mjs +11 -9
  188. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  189. package/dist/astro/routes/api/menus/index.mjs +11 -9
  190. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  191. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  192. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
  193. package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
  194. package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
  195. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  196. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
  197. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
  198. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  199. package/dist/astro/routes/api/openapi.json.mjs +5 -5
  200. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
  201. package/dist/astro/routes/api/redirects/404s/index.mjs +11 -11
  202. package/dist/astro/routes/api/redirects/404s/summary.mjs +11 -11
  203. package/dist/astro/routes/api/redirects/_id_.mjs +12 -12
  204. package/dist/astro/routes/api/redirects/index.mjs +12 -12
  205. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  206. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
  207. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +40 -38
  208. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  209. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +40 -38
  210. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  211. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +40 -38
  212. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  213. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +40 -38
  214. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  215. package/dist/astro/routes/api/schema/collections/index.mjs +40 -38
  216. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  217. package/dist/astro/routes/api/schema/index.mjs +9 -8
  218. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  219. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +40 -38
  220. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  221. package/dist/astro/routes/api/schema/orphans/index.mjs +40 -38
  222. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  223. package/dist/astro/routes/api/search/enable.mjs +11 -11
  224. package/dist/astro/routes/api/search/index.mjs +10 -10
  225. package/dist/astro/routes/api/search/rebuild.mjs +11 -11
  226. package/dist/astro/routes/api/search/stats.mjs +7 -7
  227. package/dist/astro/routes/api/search/suggest.mjs +10 -10
  228. package/dist/astro/routes/api/sections/_slug_.mjs +10 -10
  229. package/dist/astro/routes/api/sections/index.mjs +10 -10
  230. package/dist/astro/routes/api/settings/email.mjs +6 -6
  231. package/dist/astro/routes/api/settings.mjs +16 -15
  232. package/dist/astro/routes/api/settings.mjs.map +1 -1
  233. package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
  234. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  235. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  236. package/dist/astro/routes/api/setup/dev-bypass.mjs +30 -27
  237. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  238. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  239. package/dist/astro/routes/api/setup/index.mjs +30 -28
  240. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  241. package/dist/astro/routes/api/setup/status.mjs +5 -5
  242. package/dist/astro/routes/api/snapshot.d.mts.map +1 -1
  243. package/dist/astro/routes/api/snapshot.mjs +10 -9
  244. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  245. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -14
  246. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  247. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -14
  248. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  249. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -14
  250. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  251. package/dist/astro/routes/api/taxonomies/index.mjs +16 -14
  252. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  253. package/dist/astro/routes/api/themes/preview.mjs +8 -8
  254. package/dist/astro/routes/api/typegen.mjs +6 -6
  255. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  256. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  257. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  258. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  259. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -11
  260. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -11
  261. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
  262. package/dist/astro/routes/api/widget-areas/index.mjs +11 -11
  263. package/dist/astro/routes/api/widget-components.mjs +4 -4
  264. package/dist/astro/routes/robots.txt.mjs +10 -9
  265. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  266. package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -12
  267. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  268. package/dist/astro/routes/sitemap.xml.mjs +11 -10
  269. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  270. package/dist/astro/types.d.mts +16 -12
  271. package/dist/astro/types.d.mts.map +1 -1
  272. package/dist/auth/providers/github.d.mts +1 -1
  273. package/dist/auth/providers/google.d.mts +1 -1
  274. package/dist/{authorize-D5gfBVU5.mjs → authorize-Cse0k7B0.mjs} +2 -2
  275. package/dist/{authorize-D5gfBVU5.mjs.map → authorize-Cse0k7B0.mjs.map} +1 -1
  276. package/dist/{base64-CqR-7kqF.mjs → base64-CmWvODNW.mjs} +1 -1
  277. package/dist/{base64-CqR-7kqF.mjs.map → base64-CmWvODNW.mjs.map} +1 -1
  278. package/dist/{byline-V_Qp1Ziw.mjs → byline-DVo-liaP.mjs} +27 -76
  279. package/dist/byline-DVo-liaP.mjs.map +1 -0
  280. package/dist/{byline-fields-B0NO1yUB.mjs → byline-fields-B-KXkg5R.mjs} +3 -3
  281. package/dist/{byline-fields-B0NO1yUB.mjs.map → byline-fields-B-KXkg5R.mjs.map} +1 -1
  282. package/dist/{byline-fields-nBVqK_Ff.mjs → byline-fields-DaMKzkhO.mjs} +2 -2
  283. package/dist/{byline-fields-nBVqK_Ff.mjs.map → byline-fields-DaMKzkhO.mjs.map} +1 -1
  284. package/dist/{byline-fields-CQJRIQkn.d.mts → byline-fields-RFPkDLRw.d.mts} +56 -31
  285. package/dist/byline-fields-RFPkDLRw.d.mts.map +1 -0
  286. package/dist/{byline-registry-DedidtqC.mjs → byline-registry-BOjqDOim.mjs} +3 -3
  287. package/dist/{byline-registry-DedidtqC.mjs.map → byline-registry-BOjqDOim.mjs.map} +1 -1
  288. package/dist/{bylines-DfGDnred.mjs → bylines-f5ppBpD5.mjs} +8 -8
  289. package/dist/{bylines-DfGDnred.mjs.map → bylines-f5ppBpD5.mjs.map} +1 -1
  290. package/dist/{bylines-B2NWnIwS.mjs → bylines-pIKgc_TL.mjs} +10 -4
  291. package/dist/{bylines-B2NWnIwS.mjs.map → bylines-pIKgc_TL.mjs.map} +1 -1
  292. package/dist/{cache-DTTHWD8n.mjs → cache-Q6V4U-Xz.mjs} +3 -3
  293. package/dist/{cache-DTTHWD8n.mjs.map → cache-Q6V4U-Xz.mjs.map} +1 -1
  294. package/dist/{challenge-store-woE0bbCf.mjs → challenge-store-LhiqMccz.mjs} +1 -1
  295. package/dist/{challenge-store-woE0bbCf.mjs.map → challenge-store-LhiqMccz.mjs.map} +1 -1
  296. package/dist/{chunks-BerYVuve.mjs → chunks-SyjZaYwV.mjs} +2 -2
  297. package/dist/{chunks-BerYVuve.mjs.map → chunks-SyjZaYwV.mjs.map} +1 -1
  298. package/dist/cli/index.mjs +29 -27
  299. package/dist/cli/index.mjs.map +1 -1
  300. package/dist/client/cf-access.d.mts +1 -1
  301. package/dist/client/index.d.mts +1 -1
  302. package/dist/client/index.mjs +2 -1
  303. package/dist/client/index.mjs.map +1 -1
  304. package/dist/{comment-sqQxNpN3.mjs → comment-80UyJJUR.mjs} +11 -3
  305. package/dist/comment-80UyJJUR.mjs.map +1 -0
  306. package/dist/comment-reaction-Dyb-AutY.mjs +85 -0
  307. package/dist/comment-reaction-Dyb-AutY.mjs.map +1 -0
  308. package/dist/{comments-D2hNuxNa.mjs → comments-Cczx7AvD.mjs} +3 -3
  309. package/dist/{comments-D2hNuxNa.mjs.map → comments-Cczx7AvD.mjs.map} +1 -1
  310. package/dist/{components-DYKp2gmo.mjs → components-CYt4uVK9.mjs} +1 -1
  311. package/dist/{components-DYKp2gmo.mjs.map → components-CYt4uVK9.mjs.map} +1 -1
  312. package/dist/{content-BIlVx-RX.mjs → content-2PTDNnoh.mjs} +22 -7
  313. package/dist/content-2PTDNnoh.mjs.map +1 -0
  314. package/dist/{context-Cm4pt1Ws.mjs → context-B1W8soLv.mjs} +64 -26
  315. package/dist/context-B1W8soLv.mjs.map +1 -0
  316. package/dist/{cron-DdEVrQ2Y.mjs → cron-C5LVoNmP.mjs} +14 -2
  317. package/dist/cron-C5LVoNmP.mjs.map +1 -0
  318. package/dist/{dashboard-C-UYpps0.mjs → dashboard-CYjpQZ6-.mjs} +4 -4
  319. package/dist/{dashboard-C-UYpps0.mjs.map → dashboard-CYjpQZ6-.mjs.map} +1 -1
  320. package/dist/database/instrumentation.d.mts +19 -0
  321. package/dist/database/instrumentation.d.mts.map +1 -1
  322. package/dist/database/instrumentation.mjs +8 -1
  323. package/dist/database/instrumentation.mjs.map +1 -1
  324. package/dist/db/index.d.mts +3 -3
  325. package/dist/db/index.mjs +1 -1
  326. package/dist/db/libsql.d.mts +1 -1
  327. package/dist/db/postgres.d.mts +1 -1
  328. package/dist/db/sqlite.d.mts +1 -1
  329. package/dist/{db-errors-BluWkwGI.mjs → db-errors-UXB1CK42.mjs} +1 -1
  330. package/dist/{db-errors-BluWkwGI.mjs.map → db-errors-UXB1CK42.mjs.map} +1 -1
  331. package/dist/{default-NHGuJzQ3.mjs → default-CeRG-Ot4.mjs} +1 -1
  332. package/dist/{default-NHGuJzQ3.mjs.map → default-CeRG-Ot4.mjs.map} +1 -1
  333. package/dist/{device-flow-BQApWgnW.mjs → device-flow-DENDCQ9F.mjs} +5 -5
  334. package/dist/{device-flow-BQApWgnW.mjs.map → device-flow-DENDCQ9F.mjs.map} +1 -1
  335. package/dist/{email-console-BbU3RbWv.mjs → email-console-DJP32ucW.mjs} +1 -1
  336. package/dist/{email-console-BbU3RbWv.mjs.map → email-console-DJP32ucW.mjs.map} +1 -1
  337. package/dist/{error-CNn_w7jf.mjs → error-Bl6kZgtt.mjs} +2 -2
  338. package/dist/{error-CNn_w7jf.mjs.map → error-Bl6kZgtt.mjs.map} +1 -1
  339. package/dist/{escape-DPgcxcpL.mjs → escape-Bjio4ZsM.mjs} +1 -1
  340. package/dist/{escape-DPgcxcpL.mjs.map → escape-Bjio4ZsM.mjs.map} +1 -1
  341. package/dist/field-defs-cache-ztrdzUGb.mjs +77 -0
  342. package/dist/field-defs-cache-ztrdzUGb.mjs.map +1 -0
  343. package/dist/{fts-manager-Cx5z8jdA.mjs → fts-manager-CQuHt-vS.mjs} +2 -2
  344. package/dist/{fts-manager-Cx5z8jdA.mjs.map → fts-manager-CQuHt-vS.mjs.map} +1 -1
  345. package/dist/{hash-DlvIFn0b.mjs → hash-DrvzIXcz.mjs} +1 -1
  346. package/dist/{hash-DlvIFn0b.mjs.map → hash-DrvzIXcz.mjs.map} +1 -1
  347. package/dist/{import-KyxT1Mbs.mjs → import-Bb1T9WJS.mjs} +4 -4
  348. package/dist/{import-KyxT1Mbs.mjs.map → import-Bb1T9WJS.mjs.map} +1 -1
  349. package/dist/{index-D2VAiumu.d.mts → index-BaIj5hIq.d.mts} +198 -21
  350. package/dist/index-BaIj5hIq.d.mts.map +1 -0
  351. package/dist/{index-uT2yR66F.d.mts → index-qbL02uhs.d.mts} +3 -3
  352. package/dist/{index-uT2yR66F.d.mts.map → index-qbL02uhs.d.mts.map} +1 -1
  353. package/dist/index.d.mts +18 -17
  354. package/dist/index.mjs +64 -61
  355. package/dist/{init-lock-DlBHjf9-.mjs → init-lock-6b309ZrF.mjs} +2 -29
  356. package/dist/init-lock-6b309ZrF.mjs.map +1 -0
  357. package/dist/{load-Dq91b_DK.mjs → load-BNo-ER8C.mjs} +2 -2
  358. package/dist/{load-Dq91b_DK.mjs.map → load-BNo-ER8C.mjs.map} +1 -1
  359. package/dist/{loader-BqWjcH3h.mjs → loader-Dn74CG1b.mjs} +70 -11
  360. package/dist/loader-Dn74CG1b.mjs.map +1 -0
  361. package/dist/{manifest-schema-DFPeqMAn.mjs → manifest-schema-BWKnQYQF.mjs} +1 -1
  362. package/dist/{manifest-schema-DFPeqMAn.mjs.map → manifest-schema-BWKnQYQF.mjs.map} +1 -1
  363. package/dist/media/image-endpoint.d.mts +74 -0
  364. package/dist/media/image-endpoint.d.mts.map +1 -0
  365. package/dist/media/image-endpoint.mjs +162 -0
  366. package/dist/media/image-endpoint.mjs.map +1 -0
  367. package/dist/media/index.d.mts +1 -1
  368. package/dist/media/index.mjs +2 -2
  369. package/dist/media/local-runtime.d.mts +19 -11
  370. package/dist/media/local-runtime.d.mts.map +1 -1
  371. package/dist/media/local-runtime.mjs +16 -13
  372. package/dist/media/local-runtime.mjs.map +1 -1
  373. package/dist/{media-JOf3pNkw.mjs → media-Bw0sA6rb.mjs} +2 -2
  374. package/dist/{media-JOf3pNkw.mjs.map → media-Bw0sA6rb.mjs.map} +1 -1
  375. package/dist/{media-allowlist-_A0SuDn4.mjs → media-allowlist-B77I5_bw.mjs} +2 -2
  376. package/dist/{media-allowlist-_A0SuDn4.mjs.map → media-allowlist-B77I5_bw.mjs.map} +1 -1
  377. package/dist/{media-url-CqLd69IO.mjs → media-url-O4rm9-SQ.mjs} +1 -1
  378. package/dist/{media-url-CqLd69IO.mjs.map → media-url-O4rm9-SQ.mjs.map} +1 -1
  379. package/dist/{menus-DX4_E01q.mjs → menus-CYs0WZoL.mjs} +20 -6
  380. package/dist/menus-CYs0WZoL.mjs.map +1 -0
  381. package/dist/{menus-Ryk9L7fT.mjs → menus-DS8VTZgo.mjs} +167 -24
  382. package/dist/menus-DS8VTZgo.mjs.map +1 -0
  383. package/dist/{mime-YbtlEtvS.mjs → mime-BTzvzJ8M.mjs} +1 -1
  384. package/dist/{mime-YbtlEtvS.mjs.map → mime-BTzvzJ8M.mjs.map} +1 -1
  385. package/dist/{mode-CGXzIbD8.mjs → mode-BB0F8xTC.mjs} +1 -1
  386. package/dist/{mode-CGXzIbD8.mjs.map → mode-BB0F8xTC.mjs.map} +1 -1
  387. package/dist/{normalize-DKsg36ty.mjs → normalize-ClbNIenm.mjs} +1 -1
  388. package/dist/{normalize-DKsg36ty.mjs.map → normalize-ClbNIenm.mjs.map} +1 -1
  389. package/dist/{oauth-authorization-C2kVyjXI.mjs → oauth-authorization-CsvzIp_F.mjs} +5 -5
  390. package/dist/{oauth-authorization-C2kVyjXI.mjs.map → oauth-authorization-CsvzIp_F.mjs.map} +1 -1
  391. package/dist/{oauth-clients-BC873NCV.mjs → oauth-clients-C9SYwEbZ.mjs} +1 -1
  392. package/dist/{oauth-clients-BC873NCV.mjs.map → oauth-clients-C9SYwEbZ.mjs.map} +1 -1
  393. package/dist/{oauth-state-store-Cd--TUaq.mjs → oauth-state-store---zrApfB.mjs} +1 -1
  394. package/dist/{oauth-state-store-Cd--TUaq.mjs.map → oauth-state-store---zrApfB.mjs.map} +1 -1
  395. package/dist/{oauth-user-lookup-e4wOvDud.mjs → oauth-user-lookup-SHsWRlG9.mjs} +1 -1
  396. package/dist/{oauth-user-lookup-e4wOvDud.mjs.map → oauth-user-lookup-SHsWRlG9.mjs.map} +1 -1
  397. package/dist/object-cache/memory.d.mts +15 -0
  398. package/dist/object-cache/memory.d.mts.map +1 -0
  399. package/dist/object-cache/memory.mjs +56 -0
  400. package/dist/object-cache/memory.mjs.map +1 -0
  401. package/dist/object-cache-SEb2IM4Z.mjs +373 -0
  402. package/dist/object-cache-SEb2IM4Z.mjs.map +1 -0
  403. package/dist/{options-9kLgkE8m.d.mts → options-CqECG0gM.d.mts} +3 -3
  404. package/dist/{options-9kLgkE8m.d.mts.map → options-CqECG0gM.d.mts.map} +1 -1
  405. package/dist/{options-BPCVnesz.mjs → options-DTTML-Tx.mjs} +1 -1
  406. package/dist/{options-BPCVnesz.mjs.map → options-DTTML-Tx.mjs.map} +1 -1
  407. package/dist/page/index.d.mts +2 -2
  408. package/dist/{parse-DzSrk1t8.mjs → parse-C9hpjUyY.mjs} +2 -2
  409. package/dist/{parse-DzSrk1t8.mjs.map → parse-C9hpjUyY.mjs.map} +1 -1
  410. package/dist/{passkey-config-BpjbE_Uv.mjs → passkey-config-C0YfSBko.mjs} +1 -1
  411. package/dist/{passkey-config-BpjbE_Uv.mjs.map → passkey-config-C0YfSBko.mjs.map} +1 -1
  412. package/dist/{patterns-p-RBdTbM.mjs → patterns-BKmjvM7K.mjs} +1 -1
  413. package/dist/{patterns-p-RBdTbM.mjs.map → patterns-BKmjvM7K.mjs.map} +1 -1
  414. package/dist/{placeholder-2xumZh4g.mjs → placeholder-B0s2mWu5.mjs} +1 -1
  415. package/dist/{placeholder-2xumZh4g.mjs.map → placeholder-B0s2mWu5.mjs.map} +1 -1
  416. package/dist/{placeholder-BevVKfay.d.mts → placeholder-QoI4gEzP.d.mts} +1 -1
  417. package/dist/{placeholder-BevVKfay.d.mts.map → placeholder-QoI4gEzP.d.mts.map} +1 -1
  418. package/dist/plugin-types.d.mts +1 -1
  419. package/dist/plugin-utils.d.mts +9 -9
  420. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  421. package/dist/plugins/adapt-sandbox-entry.mjs +4 -2
  422. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  423. package/dist/{transport-1cIrOb1Y.mjs → portable-text-BICg8bTk.mjs} +2 -135
  424. package/dist/portable-text-BICg8bTk.mjs.map +1 -0
  425. package/dist/{preview-Dqv2hwXr.mjs → preview-DKGCt2_p.mjs} +2 -2
  426. package/dist/{preview-Dqv2hwXr.mjs.map → preview-DKGCt2_p.mjs.map} +1 -1
  427. package/dist/{public-url-D_zARuvZ.mjs → public-url-CTVqgMmg.mjs} +1 -1
  428. package/dist/{public-url-D_zARuvZ.mjs.map → public-url-CTVqgMmg.mjs.map} +1 -1
  429. package/dist/{query-Crm038Mc.mjs → query-DgUHZLWB.mjs} +230 -31
  430. package/dist/query-DgUHZLWB.mjs.map +1 -0
  431. package/dist/{rate-limit-hRTBqmw1.mjs → rate-limit-BuQ5d4X_.mjs} +2 -2
  432. package/dist/{rate-limit-hRTBqmw1.mjs.map → rate-limit-BuQ5d4X_.mjs.map} +1 -1
  433. package/dist/{redirect-CRWIt8Zj.mjs → redirect-Bifv_yHv.mjs} +3 -3
  434. package/dist/{redirect-CRWIt8Zj.mjs.map → redirect-Bifv_yHv.mjs.map} +1 -1
  435. package/dist/{redirect-C-OOkyku.mjs → redirect-CS-PHtNh.mjs} +1 -1
  436. package/dist/{redirect-C-OOkyku.mjs.map → redirect-CS-PHtNh.mjs.map} +1 -1
  437. package/dist/{redirects-CP3TnTLO.mjs → redirects-BZ8Mxn8H.mjs} +6 -6
  438. package/dist/{redirects-CP3TnTLO.mjs.map → redirects-BZ8Mxn8H.mjs.map} +1 -1
  439. package/dist/{redirects-6Zg2SoYo.mjs → redirects-x9eFPeyi.mjs} +10 -3
  440. package/dist/redirects-x9eFPeyi.mjs.map +1 -0
  441. package/dist/{registry-diMzD1Wf.mjs → registry-CK1SS6pi.mjs} +6 -6
  442. package/dist/{registry-diMzD1Wf.mjs.map → registry-CK1SS6pi.mjs.map} +1 -1
  443. package/dist/{request-cache-UwmBAiUK.mjs → request-cache-KCNHp_RJ.mjs} +1 -1
  444. package/dist/{request-cache-UwmBAiUK.mjs.map → request-cache-KCNHp_RJ.mjs.map} +1 -1
  445. package/dist/{request-meta-DPechd0W.mjs → request-meta-CmS1tDFf.mjs} +2 -2
  446. package/dist/{request-meta-DPechd0W.mjs.map → request-meta-CmS1tDFf.mjs.map} +1 -1
  447. package/dist/{resolve-B3NUUtVY.mjs → resolve-C7I0qiR0.mjs} +1 -1
  448. package/dist/{resolve-B3NUUtVY.mjs.map → resolve-C7I0qiR0.mjs.map} +1 -1
  449. package/dist/{runner-C8vcbvCe.d.mts → runner-CEtq-6Sm.d.mts} +2 -2
  450. package/dist/{runner-C8vcbvCe.d.mts.map → runner-CEtq-6Sm.d.mts.map} +1 -1
  451. package/dist/{runner--4wMWwKM.mjs → runner-DYYnW530.mjs} +201 -170
  452. package/dist/runner-DYYnW530.mjs.map +1 -0
  453. package/dist/runtime.d.mts +10 -10
  454. package/dist/runtime.mjs +3 -3
  455. package/dist/{schema-BDOkd3OU.mjs → schema-CbFRFoM7.mjs} +13 -8
  456. package/dist/schema-CbFRFoM7.mjs.map +1 -0
  457. package/dist/{search-Bs_J_EW-.mjs → search-C-waE_YW.mjs} +4 -4
  458. package/dist/{search-Bs_J_EW-.mjs.map → search-C-waE_YW.mjs.map} +1 -1
  459. package/dist/{secrets-C8xmE6mR.mjs → secrets-BSf9pRRY.mjs} +5 -5
  460. package/dist/{secrets-C8xmE6mR.mjs.map → secrets-BSf9pRRY.mjs.map} +1 -1
  461. package/dist/{sections-P0zuBlyz.mjs → sections-osX9U-YJ.mjs} +3 -3
  462. package/dist/{sections-P0zuBlyz.mjs.map → sections-osX9U-YJ.mjs.map} +1 -1
  463. package/dist/seed/index.d.mts +2 -2
  464. package/dist/seed/index.mjs +23 -21
  465. package/dist/seo/index.d.mts +1 -1
  466. package/dist/seo/index.mjs +1 -1
  467. package/dist/{seo-DpNgGQjF.mjs → seo-4FovMwNS.mjs} +5 -2
  468. package/dist/seo-4FovMwNS.mjs.map +1 -0
  469. package/dist/{seo-CLhm-Fmb.mjs → seo-DCEF-AVr.mjs} +1 -1
  470. package/dist/{seo-CLhm-Fmb.mjs.map → seo-DCEF-AVr.mjs.map} +1 -1
  471. package/dist/{service-CDQQnT8W.mjs → service-jby1RRmU.mjs} +3 -3
  472. package/dist/{service-CDQQnT8W.mjs.map → service-jby1RRmU.mjs.map} +1 -1
  473. package/dist/session-user-B8aLtKAH.mjs +51 -0
  474. package/dist/session-user-B8aLtKAH.mjs.map +1 -0
  475. package/dist/{settings-sO0Fif4p.mjs → settings-4bRT2NIf.mjs} +3 -3
  476. package/dist/{settings-sO0Fif4p.mjs.map → settings-4bRT2NIf.mjs.map} +1 -1
  477. package/dist/{settings-BjBsmVAo.mjs → settings-t-H2jPuJ.mjs} +18 -10
  478. package/dist/settings-t-H2jPuJ.mjs.map +1 -0
  479. package/dist/{setup-complete-CMMr-oZU.mjs → setup-complete-gEiySUc-.mjs} +2 -2
  480. package/dist/{setup-complete-CMMr-oZU.mjs.map → setup-complete-gEiySUc-.mjs.map} +1 -1
  481. package/dist/{setup-nonce-169xl4fV.mjs → setup-nonce-DzS50zme.mjs} +1 -1
  482. package/dist/{setup-nonce-169xl4fV.mjs.map → setup-nonce-DzS50zme.mjs.map} +1 -1
  483. package/dist/{single-flight-cache-C0UV1Npg.mjs → single-flight-cache-Cdfkic3t.mjs} +2 -2
  484. package/dist/{single-flight-cache-C0UV1Npg.mjs.map → single-flight-cache-Cdfkic3t.mjs.map} +1 -1
  485. package/dist/{site-url-vtsuOvSD.mjs → site-url-BLebyON8.mjs} +2 -2
  486. package/dist/{site-url-vtsuOvSD.mjs.map → site-url-BLebyON8.mjs.map} +1 -1
  487. package/dist/{slugify-Cjh1ssOZ.mjs → slugify-Cce3dTdg.mjs} +1 -1
  488. package/dist/{slugify-Cjh1ssOZ.mjs.map → slugify-Cce3dTdg.mjs.map} +1 -1
  489. package/dist/{ssrf-XO05Voq6.mjs → ssrf-BRKb343l.mjs} +1 -1
  490. package/dist/{ssrf-XO05Voq6.mjs.map → ssrf-BRKb343l.mjs.map} +1 -1
  491. package/dist/{status-2gZklYuj.mjs → status-vUK0SA17.mjs} +1 -1
  492. package/dist/{status-2gZklYuj.mjs.map → status-vUK0SA17.mjs.map} +1 -1
  493. package/dist/storage/local.d.mts +1 -1
  494. package/dist/storage/local.mjs +1 -1
  495. package/dist/storage/s3.d.mts +1 -1
  496. package/dist/storage/s3.mjs +1 -1
  497. package/dist/{taxonomies-DuESHWKI.mjs → taxonomies-BBB8O-CU.mjs} +7 -7
  498. package/dist/{taxonomies-DuESHWKI.mjs.map → taxonomies-BBB8O-CU.mjs.map} +1 -1
  499. package/dist/{taxonomies-BBxYA38v.mjs → taxonomies-Dxrc_szG.mjs} +177 -123
  500. package/dist/taxonomies-Dxrc_szG.mjs.map +1 -0
  501. package/dist/{taxonomy-CdllE4oq.mjs → taxonomy-B2HQuVf5.mjs} +19 -6
  502. package/dist/taxonomy-B2HQuVf5.mjs.map +1 -0
  503. package/dist/{tokens-DMkVjxrx.mjs → tokens-LeuXF9gG.mjs} +2 -2
  504. package/dist/{tokens-DMkVjxrx.mjs.map → tokens-LeuXF9gG.mjs.map} +1 -1
  505. package/dist/{transaction-x2tJQ-A1.mjs → transaction-qfqpPVpu.mjs} +1 -1
  506. package/dist/{transaction-x2tJQ-A1.mjs.map → transaction-qfqpPVpu.mjs.map} +1 -1
  507. package/dist/{transport-jdvsZEIt.d.mts → transport-BZ-03aFT.d.mts} +1 -1
  508. package/dist/{transport-jdvsZEIt.d.mts.map → transport-BZ-03aFT.d.mts.map} +1 -1
  509. package/dist/transport-_2nBz7e9.mjs +135 -0
  510. package/dist/transport-_2nBz7e9.mjs.map +1 -0
  511. package/dist/{trusted-proxy-CHp41Fjj.mjs → trusted-proxy-DZY5WCn2.mjs} +1 -1
  512. package/dist/{trusted-proxy-CHp41Fjj.mjs.map → trusted-proxy-DZY5WCn2.mjs.map} +1 -1
  513. package/dist/{types-Del0VMij.d.mts → types-B-gIxFCE.d.mts} +9 -1
  514. package/dist/{types-Del0VMij.d.mts.map → types-B-gIxFCE.d.mts.map} +1 -1
  515. package/dist/{types-DdkL6fyv.d.mts → types-BG8_XTLj.d.mts} +1 -1
  516. package/dist/{types-DdkL6fyv.d.mts.map → types-BG8_XTLj.d.mts.map} +1 -1
  517. package/dist/{types-BTnnBYVX.d.mts → types-BWh2MjmA.d.mts} +15 -2
  518. package/dist/types-BWh2MjmA.d.mts.map +1 -0
  519. package/dist/{types-CkEuk-Zr.d.mts → types-BWqGVhFn.d.mts} +1 -1
  520. package/dist/{types-CkEuk-Zr.d.mts.map → types-BWqGVhFn.d.mts.map} +1 -1
  521. package/dist/{types-DejCHqWT.mjs → types-CQAugunJ.mjs} +1 -1
  522. package/dist/{types-DejCHqWT.mjs.map → types-CQAugunJ.mjs.map} +1 -1
  523. package/dist/{types-Bzfk2yC8.d.mts → types-CTLJYMhN.d.mts} +1 -1
  524. package/dist/{types-Bzfk2yC8.d.mts.map → types-CTLJYMhN.d.mts.map} +1 -1
  525. package/dist/{types-BFgYtuKd.d.mts → types-CUsXGRVj.d.mts} +1 -1
  526. package/dist/{types-BFgYtuKd.d.mts.map → types-CUsXGRVj.d.mts.map} +1 -1
  527. package/dist/{types-BXSUSAjt.mjs → types-DXOIbece.mjs} +3 -3
  528. package/dist/types-DXOIbece.mjs.map +1 -0
  529. package/dist/{types-u_XxjbS8.d.mts → types-DrYMm9s5.d.mts} +1 -1
  530. package/dist/{types-u_XxjbS8.d.mts.map → types-DrYMm9s5.d.mts.map} +1 -1
  531. package/dist/{types-DO7whVYU.d.mts → types-TTx8uP7V.d.mts} +2 -2
  532. package/dist/{types-DO7whVYU.d.mts.map → types-TTx8uP7V.d.mts.map} +1 -1
  533. package/dist/types-fS7-VTdR.d.mts +124 -0
  534. package/dist/types-fS7-VTdR.d.mts.map +1 -0
  535. package/dist/{types-BIduXPJk.mjs → types-tM44hEcf.mjs} +1 -1
  536. package/dist/{types-BIduXPJk.mjs.map → types-tM44hEcf.mjs.map} +1 -1
  537. package/dist/{user-C0um7wrg.mjs → user-Db-Rti_z.mjs} +3 -3
  538. package/dist/{user-C0um7wrg.mjs.map → user-Db-Rti_z.mjs.map} +1 -1
  539. package/dist/{utils-C4M981Br.mjs → utils-B7A57fm9.mjs} +2 -2
  540. package/dist/{utils-C4M981Br.mjs.map → utils-B7A57fm9.mjs.map} +1 -1
  541. package/dist/{validate-DGhQPXzI.mjs → validate-0Utjspbs.mjs} +3 -3
  542. package/dist/{validate-DGhQPXzI.mjs.map → validate-0Utjspbs.mjs.map} +1 -1
  543. package/dist/{validate-cJOiOvT2.d.mts → validate-DOFrIb-c.d.mts} +5 -5
  544. package/dist/{validate-cJOiOvT2.d.mts.map → validate-DOFrIb-c.d.mts.map} +1 -1
  545. package/dist/{validation-DVHjPM1M.mjs → validation-D9EnzH1T.mjs} +6 -6
  546. package/dist/{validation-DVHjPM1M.mjs.map → validation-D9EnzH1T.mjs.map} +1 -1
  547. package/dist/version-BgVM_1MU.mjs +7 -0
  548. package/dist/{version-BOjj_cfz.mjs.map → version-BgVM_1MU.mjs.map} +1 -1
  549. package/dist/{widgets-Ci6hLwfO.mjs → widgets-BSTzPUYa.mjs} +4 -4
  550. package/dist/{widgets-Ci6hLwfO.mjs.map → widgets-BSTzPUYa.mjs.map} +1 -1
  551. package/dist/{zod-generator-CarzgPAu.mjs → zod-generator-ElVQOav7.mjs} +51 -15
  552. package/dist/zod-generator-ElVQOav7.mjs.map +1 -0
  553. package/package.json +19 -6
  554. package/src/api/handlers/api-tokens.ts +19 -0
  555. package/src/api/handlers/comment-reactions.ts +165 -0
  556. package/src/api/handlers/schema.ts +8 -0
  557. package/src/api/schemas/bylines.ts +8 -0
  558. package/src/api/schemas/comments.ts +10 -0
  559. package/src/astro/image-endpoint.ts +84 -0
  560. package/src/astro/index.ts +6 -0
  561. package/src/astro/integration/index.ts +83 -22
  562. package/src/astro/integration/routes.ts +5 -0
  563. package/src/astro/integration/runtime.ts +65 -1
  564. package/src/astro/integration/virtual-modules.ts +40 -0
  565. package/src/astro/integration/vite-config.ts +25 -1
  566. package/src/astro/middleware/auth.ts +4 -3
  567. package/src/astro/middleware/request-context.ts +6 -1
  568. package/src/astro/middleware/scoped-db.ts +131 -0
  569. package/src/astro/middleware/stream-end-metrics.ts +15 -9
  570. package/src/astro/middleware.ts +131 -31
  571. package/src/astro/object-cache/adapters.ts +50 -0
  572. package/src/astro/prefetch.ts +77 -0
  573. package/src/astro/routes/admin.astro +5 -1
  574. package/src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts +97 -0
  575. package/src/astro/routes/api/schema/index.ts +9 -3
  576. package/src/astro/routes/api/setup/dev-bypass.ts +5 -1
  577. package/src/astro/routes/api/snapshot.ts +3 -1
  578. package/src/astro/session-user.ts +57 -0
  579. package/src/astro/types.ts +1 -0
  580. package/src/cli/commands/export-seed.ts +10 -7
  581. package/src/comments/query.ts +78 -7
  582. package/src/comments/ranking.ts +58 -0
  583. package/src/components/Block.astro +71 -0
  584. package/src/components/Comments.astro +136 -1
  585. package/src/components/EmDashMedia.astro +1 -2
  586. package/src/components/Image.astro +36 -2
  587. package/src/components/InlinePortableTextEditor.tsx +10 -2
  588. package/src/components/index.ts +5 -0
  589. package/src/components/portable-text-text-align.ts +38 -0
  590. package/src/content/converters/portable-text-to-prosemirror.ts +5 -1
  591. package/src/content/converters/prosemirror-to-portable-text.ts +8 -0
  592. package/src/content/converters/types.ts +1 -0
  593. package/src/database/instrumentation.ts +21 -1
  594. package/src/database/migrations/044_comment_reactions.ts +56 -0
  595. package/src/database/migrations/runner.ts +2 -0
  596. package/src/database/repositories/byline.ts +27 -0
  597. package/src/database/repositories/comment-reaction.ts +132 -0
  598. package/src/database/repositories/comment.ts +10 -0
  599. package/src/database/repositories/content.ts +25 -3
  600. package/src/database/repositories/menu.ts +13 -1
  601. package/src/database/repositories/seo.ts +3 -0
  602. package/src/database/repositories/taxonomy.ts +13 -1
  603. package/src/database/repositories/types.ts +13 -0
  604. package/src/database/types.ts +9 -0
  605. package/src/emdash-runtime.ts +244 -75
  606. package/src/index.ts +22 -0
  607. package/src/loader.ts +97 -5
  608. package/src/mcp/server.ts +307 -20
  609. package/src/media/image-endpoint.ts +167 -0
  610. package/src/media/local-runtime.ts +18 -5
  611. package/src/menus/index.ts +11 -4
  612. package/src/object-cache/codec.ts +73 -0
  613. package/src/object-cache/index.ts +495 -0
  614. package/src/object-cache/memory.ts +91 -0
  615. package/src/object-cache/types.ts +124 -0
  616. package/src/plugins/adapt-sandbox-entry.ts +11 -1
  617. package/src/plugins/context.ts +94 -22
  618. package/src/plugins/cron.ts +18 -2
  619. package/src/plugins/routes.ts +40 -1
  620. package/src/query.ts +304 -18
  621. package/src/schema/query.ts +11 -4
  622. package/src/schema/zod-generator.ts +53 -8
  623. package/src/settings/index.ts +18 -5
  624. package/src/taxonomies/index.ts +263 -165
  625. package/src/ui.ts +5 -0
  626. package/src/virtual-modules.d.ts +24 -0
  627. package/dist/api-DxjIV2o8.mjs.map +0 -1
  628. package/dist/api-tokens-BFFkB0jB.mjs.map +0 -1
  629. package/dist/byline-V_Qp1Ziw.mjs.map +0 -1
  630. package/dist/byline-fields-CQJRIQkn.d.mts.map +0 -1
  631. package/dist/comment-sqQxNpN3.mjs.map +0 -1
  632. package/dist/content-BIlVx-RX.mjs.map +0 -1
  633. package/dist/context-Cm4pt1Ws.mjs.map +0 -1
  634. package/dist/cron-DdEVrQ2Y.mjs.map +0 -1
  635. package/dist/index-D2VAiumu.d.mts.map +0 -1
  636. package/dist/init-lock-DlBHjf9-.mjs.map +0 -1
  637. package/dist/loader-BqWjcH3h.mjs.map +0 -1
  638. package/dist/menus-DX4_E01q.mjs.map +0 -1
  639. package/dist/menus-Ryk9L7fT.mjs.map +0 -1
  640. package/dist/query-Crm038Mc.mjs.map +0 -1
  641. package/dist/redirects-6Zg2SoYo.mjs.map +0 -1
  642. package/dist/runner--4wMWwKM.mjs.map +0 -1
  643. package/dist/schema-BDOkd3OU.mjs.map +0 -1
  644. package/dist/seo-DpNgGQjF.mjs.map +0 -1
  645. package/dist/settings-BjBsmVAo.mjs.map +0 -1
  646. package/dist/taxonomies-BBxYA38v.mjs.map +0 -1
  647. package/dist/taxonomy-CdllE4oq.mjs.map +0 -1
  648. package/dist/transport-1cIrOb1Y.mjs.map +0 -1
  649. package/dist/types-BTnnBYVX.d.mts.map +0 -1
  650. package/dist/types-BXSUSAjt.mjs.map +0 -1
  651. package/dist/version-BOjj_cfz.mjs +0 -7
  652. package/dist/zod-generator-CarzgPAu.mjs.map +0 -1
  653. /package/dist/{api-tokens-C7ywRx7l.mjs → api-tokens-B4BQybOp.mjs} +0 -0
  654. /package/dist/{ssrf-CRZGzjdL.mjs → ssrf-CcX9zvMK.mjs} +0 -0
  655. /package/dist/{types-BoRm8-pp.mjs → types-BvbeGEtr.mjs} +0 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Object-cache adapter functions (config time).
3
+ *
4
+ * These run in `astro.config.mjs` and return serializable
5
+ * {@link ObjectCacheDescriptor}s. The backend is instantiated at runtime by
6
+ * loading the descriptor's `entrypoint`.
7
+ *
8
+ * For Cloudflare KV, use `kvCache()` from `@emdash-cms/cloudflare`.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * // astro.config.mjs (Node / local)
13
+ * import emdash, { memoryCache } from "emdash/astro";
14
+ *
15
+ * export default defineConfig({
16
+ * integrations: [emdash({ objectCache: memoryCache() })],
17
+ * });
18
+ * ```
19
+ */
20
+
21
+ import type { ObjectCacheDescriptor, ObjectCacheRuntimeConfig } from "../../object-cache/types.js";
22
+
23
+ /** Options for {@link memoryCache}. */
24
+ export interface MemoryCacheOptions extends ObjectCacheRuntimeConfig {
25
+ /**
26
+ * Soft cap on the number of cached keys per isolate before FIFO eviction.
27
+ * @default 1000
28
+ */
29
+ maxEntries?: number;
30
+ }
31
+
32
+ /**
33
+ * In-isolate memory object cache.
34
+ *
35
+ * Caches query results across requests within a single isolate/process. On
36
+ * Node (one long-lived process) this is a genuine cross-request cache; on
37
+ * multi-isolate platforms (Cloudflare) prefer `kvCache()` so the cache is
38
+ * shared. Useful for local development regardless of target.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * emdash({ objectCache: memoryCache({ defaultTtl: 600 }) })
43
+ * ```
44
+ */
45
+ export function memoryCache(options: MemoryCacheOptions = {}): ObjectCacheDescriptor {
46
+ return {
47
+ entrypoint: "emdash/object-cache/memory",
48
+ config: { ...options },
49
+ };
50
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Eager, transparent prefetch of site-global "chrome" data.
3
+ *
4
+ * On a public page render, the shared layout pulls the same site-global data on
5
+ * every request -- menus, widget areas, taxonomy term lists, site settings --
6
+ * but each is awaited inside a separately-rendered Astro component, so they
7
+ * execute as serial DB round trips. This fires them all CONCURRENTLY at the
8
+ * very start of the request, before `next()`:
9
+ *
10
+ * - On remote backends (D1, Durable Objects) the round trips overlap instead
11
+ * of serializing, collapsing ~N sequential RTTs into ~1 wall-clock RTT. On
12
+ * a coalescing backend they additionally batch into a single round trip.
13
+ * - The results land in the per-request `requestCached` store under the exact
14
+ * keys the layout helpers use, so when the components render they hit a warm
15
+ * (in-flight or resolved) cache entry instead of issuing their own query.
16
+ *
17
+ * Nothing here changes what templates call -- it warms the real helpers, so the
18
+ * cache keys and value shapes are guaranteed identical. The caller gates this to
19
+ * the public-page path on a request-scoped (remote) backend; it is a no-op-ish
20
+ * waste on synchronous local SQLite, so don't call it there.
21
+ *
22
+ * Fire-and-forget: never awaited by middleware, never throws (a prefetch failure
23
+ * must not affect the request -- the helpers will simply run on demand).
24
+ */
25
+
26
+ import { getDb } from "../loader.js";
27
+ import { getMenu } from "../menus/index.js";
28
+ import { setRequestCacheEntry } from "../request-cache.js";
29
+ import { getSiteSettings } from "../settings/index.js";
30
+ import { getTaxonomyDefs, getTaxonomyTerms } from "../taxonomies/index.js";
31
+ import { getWidgetAreas } from "../widgets/index.js";
32
+
33
+ /** Warm widget areas: one bulk load, primed under each per-area cache key. */
34
+ async function prefetchWidgetAreas(): Promise<void> {
35
+ const areas = await getWidgetAreas();
36
+ // getWidgetArea(name) caches under `widget-area:${name}` and returns the same
37
+ // WidgetArea shape getWidgetAreas yields, so priming here makes those calls hit.
38
+ for (const area of areas) {
39
+ setRequestCacheEntry(`widget-area:${area.name}`, area);
40
+ }
41
+ }
42
+
43
+ /** Warm every taxonomy's term list via the real helper (primes per-name keys). */
44
+ async function prefetchTaxonomyTerms(): Promise<void> {
45
+ const defs = await getTaxonomyDefs();
46
+ await Promise.allSettled(defs.map((def) => getTaxonomyTerms(def.name)));
47
+ }
48
+
49
+ /** Warm every menu via the real helper (primes `menu:${name}:${locale}`). */
50
+ async function prefetchMenus(): Promise<void> {
51
+ const db = await getDb();
52
+ // The layout calls getMenu(name) with hardcoded names; we can't know them, so
53
+ // discover every menu name and warm them all (small, bounded chrome table).
54
+ const rows = await db.selectFrom("_emdash_menus").select("name").distinct().execute();
55
+ const names = [...new Set(rows.map((r) => r.name))];
56
+ await Promise.allSettled(names.map((name) => getMenu(name)));
57
+ }
58
+
59
+ /**
60
+ * Concurrently warm the site-global layout data for the current request.
61
+ * Safe to call only inside the request ALS frame that owns the (remote)
62
+ * request-scoped db. Never throws.
63
+ */
64
+ export async function prefetchLayoutData(): Promise<void> {
65
+ try {
66
+ await Promise.allSettled([
67
+ getSiteSettings(),
68
+ prefetchMenus(),
69
+ prefetchWidgetAreas(),
70
+ prefetchTaxonomyTerms(),
71
+ ]);
72
+ } catch (error) {
73
+ // Defensive: Promise.allSettled shouldn't reject, but never let a prefetch
74
+ // failure surface to the request.
75
+ console.error("[emdash] layout prefetch failed (non-fatal):", error);
76
+ }
77
+ }
@@ -5,7 +5,10 @@
5
5
  * This page serves the EmDash admin React SPA.
6
6
  * AdminWrapper imports plugin admin modules and passes them to AdminApp.
7
7
  */
8
- import "@emdash-cms/admin/styles.css";
8
+ // `?url` keeps the admin stylesheet out of the page's CSS module graph so
9
+ // Astro's dev SSR doesn't inject it into every public route's <head>. We emit
10
+ // it as a route-scoped <link> below instead. See #1281.
11
+ import adminStylesUrl from "@emdash-cms/admin/styles.css?url";
9
12
  // Use package-qualified import so Astro generates a proper module URL
10
13
  // (relative imports resolve to absolute paths which break client hydration)
11
14
  import AdminWrapper from "emdash/routes/PluginRegistry";
@@ -28,6 +31,7 @@ const pageTitle = adminConfig?.siteName ? `${adminConfig.siteName} Admin` : "EmD
28
31
  <head>
29
32
  <meta charset="UTF-8" />
30
33
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
34
+ <link rel="stylesheet" href={adminStylesUrl} />
31
35
  <Font cssVariable="--font-emdash" />
32
36
  {adminConfig?.favicon ? (
33
37
  <link rel="icon" href={adminConfig.favicon} />
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Public comment reaction endpoints (Tier 1 of the best-in-class comments RFC).
3
+ *
4
+ * GET /_emdash/api/comments/:collection/:contentId/reactions
5
+ * - Aggregate reaction counts for the content's approved comments, plus the
6
+ * current visitor's active reactions.
7
+ * POST /_emdash/api/comments/:collection/:contentId/reactions
8
+ * - Toggle a reaction on a comment. Public, honeypot- and rate-limit-gated.
9
+ *
10
+ * Inherits the `/_emdash/api/comments/` public prefix (no auth); the POST still
11
+ * requires the `X-EmDash-Request: 1` CSRF header like the comment POST.
12
+ */
13
+
14
+ import type { APIRoute } from "astro";
15
+
16
+ import { apiError, apiSuccess, handleError, requireDb, unwrapResult } from "#api/error.js";
17
+ import { handleReactionCounts, handleReactionToggle } from "#api/handlers/comment-reactions.js";
18
+ import { hashIp } from "#api/handlers/comments.js";
19
+ import { isParseError, parseBody } from "#api/parse.js";
20
+ import { createReactionBody } from "#api/schemas.js";
21
+ import { resolveSecretsCached } from "#config/secrets.js";
22
+ import { extractRequestMeta } from "#plugins/request-meta.js";
23
+
24
+ export const prerender = false;
25
+
26
+ export const GET: APIRoute = async ({ params, request, locals }) => {
27
+ const { emdash } = locals;
28
+ const { collection, contentId } = params;
29
+
30
+ if (!collection || !contentId) {
31
+ return apiError("VALIDATION_ERROR", "Collection and content ID required", 400);
32
+ }
33
+
34
+ const dbErr = requireDb(emdash?.db);
35
+ if (dbErr) return dbErr;
36
+
37
+ try {
38
+ // Salted voter hash from request IP (same primitive as comment ip_hash).
39
+ // Behind Cloudflare (CF-Connecting-IP) or a configured trusted proxy this
40
+ // is per-visitor. Without a trusted IP it collapses to a shared "unknown"
41
+ // bucket, so reaction dedup degrades for those visitors — a real
42
+ // per-visitor token is Tier 2 (visitor identity). Operators should set
43
+ // trustedProxyHeaders; see the comment ingest route for the same note.
44
+ const meta = extractRequestMeta(request, emdash.config);
45
+ let voterHash = "unknown";
46
+ if (meta.ip) {
47
+ const { ipSalt } = await resolveSecretsCached(emdash.db);
48
+ voterHash = await hashIp(meta.ip, ipSalt);
49
+ }
50
+
51
+ const result = await handleReactionCounts(emdash.db, collection, contentId, voterHash);
52
+ return unwrapResult(result);
53
+ } catch (error) {
54
+ return handleError(error, "Failed to read reactions", "REACTION_COUNTS_ERROR");
55
+ }
56
+ };
57
+
58
+ export const POST: APIRoute = async ({ params, request, locals }) => {
59
+ const { emdash } = locals;
60
+ const { collection, contentId } = params;
61
+
62
+ if (!collection || !contentId) {
63
+ return apiError("VALIDATION_ERROR", "Collection and content ID required", 400);
64
+ }
65
+
66
+ const dbErr = requireDb(emdash?.db);
67
+ if (dbErr) return dbErr;
68
+
69
+ try {
70
+ const body = await parseBody(request, createReactionBody);
71
+ if (isParseError(body)) return body;
72
+
73
+ // Anti-spam: honeypot — hidden field filled only by bots. Silently accept.
74
+ if (body.website_url) {
75
+ return apiSuccess({ reacted: false, counts: {} });
76
+ }
77
+
78
+ const meta = extractRequestMeta(request, emdash.config);
79
+ let voterHash = "unknown";
80
+ if (meta.ip) {
81
+ const { ipSalt } = await resolveSecretsCached(emdash.db);
82
+ voterHash = await hashIp(meta.ip, ipSalt);
83
+ }
84
+
85
+ const result = await handleReactionToggle(emdash.db, {
86
+ collection,
87
+ contentId,
88
+ commentId: body.commentId,
89
+ reaction: body.reaction,
90
+ voterHash,
91
+ });
92
+
93
+ return unwrapResult(result, 200);
94
+ } catch (error) {
95
+ return handleError(error, "Failed to toggle reaction", "REACTION_TOGGLE_ERROR");
96
+ }
97
+ };
@@ -15,7 +15,7 @@ import { hashString } from "emdash";
15
15
  import { requirePerm } from "#api/authorize.js";
16
16
  import { apiSuccess, handleError, requireDb } from "#api/error.js";
17
17
  import { SchemaRegistry } from "#schema/registry.js";
18
- import { generateTypeScript } from "#schema/zod-generator.js";
18
+ import { generateTypeScript, uniqueInterfaceNames } from "#schema/zod-generator.js";
19
19
 
20
20
  export const prerender = false;
21
21
 
@@ -45,8 +45,14 @@ export const GET: APIRoute = async ({ request, locals }) => {
45
45
  const format = url.searchParams.get("format");
46
46
 
47
47
  if (format === "typescript") {
48
- // Generate TypeScript definitions
49
- const types = collectionsWithFields.map((c) => generateTypeScript(c)).join("\n\n");
48
+ // Generate TypeScript definitions. Singularizing slugs can collapse
49
+ // distinct collections onto the same interface name, so resolve names
50
+ // up front to keep every emitted interface unique (`book` + `books`
51
+ // would otherwise both emit `Book`).
52
+ const interfaceNames = uniqueInterfaceNames(collectionsWithFields);
53
+ const types = collectionsWithFields
54
+ .map((c) => generateTypeScript(c, interfaceNames.get(c.slug)))
55
+ .join("\n\n");
50
56
 
51
57
  const header = `// Generated by EmDash CLI
52
58
  // Do not edit manually - run \`emdash types\` to regenerate
@@ -23,7 +23,7 @@ import { ulid } from "ulidx";
23
23
 
24
24
  import { apiError, apiSuccess, handleError } from "#api/error.js";
25
25
  import { escapeHtml } from "#api/escape.js";
26
- import { handleApiTokenCreate } from "#api/handlers/api-tokens.js";
26
+ import { deleteApiTokensByName, handleApiTokenCreate } from "#api/handlers/api-tokens.js";
27
27
  import { getPublicOrigin } from "#api/public-url.js";
28
28
  import { isSafeRedirect } from "#api/redirect.js";
29
29
  import { runMigrations } from "#db/migrations/runner.js";
@@ -134,6 +134,10 @@ async function handleDevBypass(context: Parameters<APIRoute>[0]): Promise<Respon
134
134
  // Optionally create a PAT token (?token=1) for headless/CLI testing.
135
135
  let token: string | undefined;
136
136
  if (url.searchParams.has("token")) {
137
+ // Idempotent by name: a prior reset can leave a stale dev-bypass-token,
138
+ // and the raw token is only available at creation, so drop any existing
139
+ // one and mint a fresh, usable PAT rather than accumulating duplicates.
140
+ await deleteApiTokensByName(emdash.db, user.id, "dev-bypass-token");
137
141
  const result = await handleApiTokenCreate(emdash.db, user.id, {
138
142
  name: "dev-bypass-token",
139
143
  scopes: [
@@ -20,6 +20,8 @@ import {
20
20
  import { getPublicOrigin } from "#api/public-url.js";
21
21
  import { resolveSecretsCached } from "#config/secrets.js";
22
22
 
23
+ import { resolveSessionUser } from "../../session-user.js";
24
+
23
25
  export const prerender = false;
24
26
 
25
27
  export const GET: APIRoute = async ({ request, locals, url, session }) => {
@@ -31,7 +33,7 @@ export const GET: APIRoute = async ({ request, locals, url, session }) => {
31
33
  if (!user && session && emdash?.db) {
32
34
  try {
33
35
  const { createKyselyAdapter } = await import("@emdash-cms/auth/adapters/kysely");
34
- const sessionUser = await session.get("user");
36
+ const sessionUser = await resolveSessionUser(session);
35
37
  if (sessionUser?.id) {
36
38
  const adapter = createKyselyAdapter(emdash.db);
37
39
  const resolved = await adapter.getUserById(sessionUser.id);
@@ -0,0 +1,57 @@
1
+ import { after } from "../after.js";
2
+
3
+ /**
4
+ * Backstop timeout for resolving the session user. A live session-store read
5
+ * settles in a few ms, so this only ever fires on a genuinely stalled read.
6
+ */
7
+ export const SESSION_GET_TIMEOUT_MS = 3_000;
8
+
9
+ /**
10
+ * Resolve the Astro session user without risking an isolate-wide hang.
11
+ *
12
+ * On Cloudflare Workers, a request cancelled mid-`session.get()` (client
13
+ * disconnect, context teardown) can leave the underlying session-store read as
14
+ * a promise that never settles — neither resolving nor rejecting. Awaiting it
15
+ * directly hangs the request, and because the stalled promise is shared at the
16
+ * isolate level, every later session-bearing request hangs too (observed as
17
+ * 0-CPU, multi-minute, `canceled` responses; see #1274). A surrounding
18
+ * try/catch cannot help: the promise never rejects.
19
+ *
20
+ * Two layers, mirroring the reclaimable-cache pattern used elsewhere in core:
21
+ * 1. `after()` anchors the read so a cancelled request still drives it to
22
+ * completion — the promise settles and the isolate is not poisoned for
23
+ * subsequent requests (prevents the hang rather than merely surviving it).
24
+ * 2. A timeout is a fail-closed backstop: a still-stalled (or rejecting) read
25
+ * resolves to `undefined`, and every caller treats the absence of a session
26
+ * user as unauthenticated (anonymous on public routes, 401/redirect on
27
+ * protected ones). It can only ever drop privileges for that one request,
28
+ * never grant them.
29
+ *
30
+ * Used by every session read on the request path: the main middleware (the
31
+ * first read on a session-bearing request), the auth middleware, and the
32
+ * preview-snapshot route (which bypasses the auth middleware).
33
+ */
34
+ export async function resolveSessionUser<T>(
35
+ session: { get(key: "user"): Promise<T> } | undefined,
36
+ timeoutMs = SESSION_GET_TIMEOUT_MS,
37
+ ): Promise<T | undefined> {
38
+ if (!session) return undefined;
39
+ const read: Promise<T | undefined> = Promise.resolve(session.get("user")).catch(() => undefined);
40
+ // Keep the worker alive past response/cancellation so the read completes and
41
+ // the shared promise settles — this is what prevents the isolate poisoning.
42
+ after(() =>
43
+ read.then(
44
+ () => undefined,
45
+ () => undefined,
46
+ ),
47
+ );
48
+ let timer: ReturnType<typeof setTimeout> | undefined;
49
+ const timeout = new Promise<undefined>((resolve) => {
50
+ timer = setTimeout(resolve, timeoutMs, undefined);
51
+ });
52
+ try {
53
+ return await Promise.race([read, timeout]);
54
+ } finally {
55
+ clearTimeout(timer);
56
+ }
57
+ }
@@ -265,6 +265,7 @@ export interface EmDashHandlers {
265
265
  slug?: string;
266
266
  status?: string;
267
267
  authorId?: string;
268
+ bylines?: Array<{ bylineId: string; roleLabel?: string | null }>;
268
269
  locale?: string;
269
270
  translationOf?: string;
270
271
  createdAt?: string | null;
@@ -153,13 +153,16 @@ export async function exportSeed(db: Kysely<Database>, withContent?: string): Pr
153
153
 
154
154
  // 7. Export content (if requested)
155
155
  if (withContent !== undefined) {
156
- const collections =
157
- withContent === "" || withContent === "true"
158
- ? null // all collections
159
- : withContent
160
- .split(",")
161
- .map((s) => s.trim())
162
- .filter(Boolean);
156
+ // Treat "all" as a synonym for the bare flag and "true". The args help
157
+ // text documents `all` as a valid value, but without this the literal
158
+ // string is read as a collection name and matches no collection (#1329).
159
+ const includeAll = withContent === "" || withContent === "true" || withContent === "all";
160
+ const collections = includeAll
161
+ ? null // all collections
162
+ : withContent
163
+ .split(",")
164
+ .map((s) => s.trim())
165
+ .filter(Boolean);
163
166
 
164
167
  seed.content = await exportContent(
165
168
  db,
@@ -7,15 +7,26 @@
7
7
 
8
8
  import type { Kysely } from "kysely";
9
9
 
10
+ import { CommentReactionRepository } from "../database/repositories/comment-reaction.js";
10
11
  import { CommentRepository } from "../database/repositories/comment.js";
11
12
  import type { PublicComment } from "../database/repositories/comment.js";
12
13
  import type { Database } from "../database/types.js";
13
14
  import { getDb } from "../loader.js";
15
+ import { cachedQuery, CacheNamespace } from "../object-cache/index.js";
16
+ import { reactionScore } from "./ranking.js";
14
17
 
15
18
  export interface GetCommentsOptions {
16
19
  collection: string;
17
20
  contentId: string;
18
21
  threaded?: boolean;
22
+ /** Attach aggregate reaction counts to each comment. */
23
+ reactions?: boolean;
24
+ /**
25
+ * Order of top-level comments. `oldest` (default) preserves the existing
26
+ * chronological display; `best` ranks by Wilson-scored reactions (implies
27
+ * `reactions`). Replies always stay chronological.
28
+ */
29
+ sort?: "oldest" | "best";
19
30
  }
20
31
 
21
32
  export interface GetCommentsResult {
@@ -38,8 +49,21 @@ export interface GetCommentsResult {
38
49
  * ```
39
50
  */
40
51
  export async function getComments(options: GetCommentsOptions): Promise<GetCommentsResult> {
41
- const db = await getDb();
42
- return getCommentsWithDb(db, options);
52
+ // The result varies by every option getCommentsWithDb branches on, so all of
53
+ // them belong in the key. `best` implies reactions, so normalize the reaction
54
+ // flag — `{ sort: "best" }` and `{ sort: "best", reactions: true }` produce
55
+ // identical output and should share one entry.
56
+ const sort = options.sort ?? "oldest";
57
+ const withReactions = options.reactions || sort === "best";
58
+ const threaded = options.threaded ? "t" : "f";
59
+ return cachedQuery({
60
+ namespace: CacheNamespace.COMMENTS,
61
+ key: `comments:${options.collection}:${options.contentId}:${threaded}:${withReactions ? "r" : "n"}:${sort}`,
62
+ load: async () => {
63
+ const db = await getDb();
64
+ return getCommentsWithDb(db, options);
65
+ },
66
+ });
43
67
  }
44
68
 
45
69
  /**
@@ -65,16 +89,63 @@ export async function getCommentsWithDb(
65
89
  limit: MAX_COMMENTS,
66
90
  });
67
91
 
68
- if (options.threaded) {
69
- const threaded = CommentRepository.assembleThreads(result.items);
70
- const items = threaded.map((c) => CommentRepository.toPublicComment(c));
71
- return { items, total };
92
+ const items: PublicComment[] = options.threaded
93
+ ? CommentRepository.assembleThreads(result.items).map((c) =>
94
+ CommentRepository.toPublicComment(c),
95
+ )
96
+ : result.items.map((c) => CommentRepository.toPublicComment(c));
97
+
98
+ // `best` sort needs reaction data, so it implies reactions.
99
+ if (options.reactions || options.sort === "best") {
100
+ await attachReactions(db, items);
101
+ if (options.sort === "best") {
102
+ sortByBest(items);
103
+ }
72
104
  }
73
105
 
74
- const items = result.items.map((c) => CommentRepository.toPublicComment(c));
75
106
  return { items, total };
76
107
  }
77
108
 
109
+ /**
110
+ * Attach aggregate reaction counts to a list of public comments (and their
111
+ * replies), in a single batched query.
112
+ */
113
+ async function attachReactions(db: Kysely<Database>, items: PublicComment[]): Promise<void> {
114
+ const ids: string[] = [];
115
+ for (const comment of items) {
116
+ ids.push(comment.id);
117
+ if (comment.replies) {
118
+ for (const reply of comment.replies) ids.push(reply.id);
119
+ }
120
+ }
121
+ if (ids.length === 0) return;
122
+
123
+ const counts = await new CommentReactionRepository(db).countsForComments(ids);
124
+
125
+ const assign = (comment: PublicComment) => {
126
+ const reactions = counts.get(comment.id);
127
+ if (reactions) comment.reactions = reactions;
128
+ };
129
+ for (const comment of items) {
130
+ assign(comment);
131
+ comment.replies?.forEach(assign);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Sort top-level comments by Wilson-scored reactions (descending), tie-broken
137
+ * by oldest-first to keep ordering stable.
138
+ */
139
+ function sortByBest(items: PublicComment[]): void {
140
+ items.sort((a, b) => {
141
+ const scoreDelta = reactionScore(b.reactions ?? {}) - reactionScore(a.reactions ?? {});
142
+ if (scoreDelta !== 0) return scoreDelta;
143
+ if (a.createdAt < b.createdAt) return -1;
144
+ if (a.createdAt > b.createdAt) return 1;
145
+ return 0;
146
+ });
147
+ }
148
+
78
149
  /**
79
150
  * Get the count of approved comments for a content item.
80
151
  *
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Comment ranking utilities (Tier 1 of the best-in-class comments RFC).
3
+ *
4
+ * Wilson score lower-bound (95% confidence) — the same primitive Reddit uses
5
+ * for its "Best" comment sort. Ranks by the statistical lower bound of the
6
+ * positive-reaction proportion rather than the raw count, so a comment with a
7
+ * couple of reactions can't outrank a heavily-reacted one until it earns
8
+ * confidence, and a late-but-popular comment still rises (submission time is
9
+ * irrelevant).
10
+ *
11
+ * Positive-only reactions (the recommended default) degrade gracefully: with
12
+ * `down = 0` the score still increases monotonically with `up` while penalising
13
+ * low-sample comments — wilson(1,0) ≈ 0.21, wilson(10,0) ≈ 0.73,
14
+ * wilson(200,0) ≈ 0.98.
15
+ */
16
+
17
+ /** z for a 95% two-sided confidence interval. */
18
+ const DEFAULT_Z = 1.96;
19
+
20
+ /** Reactions that count against a comment when both signals are in use. */
21
+ const NEGATIVE_REACTIONS: ReadonlySet<string> = new Set(["dislike", "down"]);
22
+
23
+ /**
24
+ * Wilson score lower bound of the positive proportion.
25
+ *
26
+ * @param up count of positive reactions
27
+ * @param down count of negative reactions
28
+ * @returns a score in [0, 1]; 0 when there are no reactions
29
+ */
30
+ export function wilsonLowerBound(up: number, down: number, z: number = DEFAULT_Z): number {
31
+ const n = up + down;
32
+ if (n <= 0) return 0;
33
+ const phat = up / n;
34
+ const z2 = z * z;
35
+ const denom = 1 + z2 / n;
36
+ const centre = phat + z2 / (2 * n);
37
+ const margin = z * Math.sqrt((phat * (1 - phat) + z2 / (4 * n)) / n);
38
+ return (centre - margin) / denom;
39
+ }
40
+
41
+ /**
42
+ * Reduce a per-reaction count map to a single rank score via the Wilson
43
+ * lower bound. Any reaction not in {@link NEGATIVE_REACTIONS} is treated as
44
+ * positive, so the positive-only default (just `like`) works without special
45
+ * casing.
46
+ */
47
+ export function reactionScore(counts: Record<string, number>): number {
48
+ let up = 0;
49
+ let down = 0;
50
+ for (const [reaction, count] of Object.entries(counts)) {
51
+ if (NEGATIVE_REACTIONS.has(reaction)) {
52
+ down += count;
53
+ } else {
54
+ up += count;
55
+ }
56
+ }
57
+ return wilsonLowerBound(up, down);
58
+ }
@@ -0,0 +1,71 @@
1
+ ---
2
+ /**
3
+ * EmDash custom block override for `astro-portabletext`.
4
+ *
5
+ * Renders the same HTML as the upstream Block component (h1..h6, blockquote,
6
+ * `<p>` for `normal`) and additionally surfaces `textAlign` from the rich-text
7
+ * editor as a WordPress-style `has-text-align-{value}` class on the rendered
8
+ * paragraph or heading.
9
+ *
10
+ * `left` is the editor default and intentionally does not produce a class —
11
+ * paragraphs/headings without explicit alignment render exactly as they did
12
+ * before this fix, so existing content is byte-for-byte unchanged.
13
+ *
14
+ * Related: https://github.com/emdash-cms/emdash/issues/1201
15
+ */
16
+ import type { BlockProps } from "astro-portabletext/types";
17
+
18
+ import { textAlignClassName } from "./portable-text-text-align.js";
19
+
20
+ type TextAlignedNode = BlockProps["node"] & { textAlign?: string };
21
+ type Props = Omit<BlockProps, "node"> & { node: TextAlignedNode };
22
+
23
+ const props = Astro.props as Props;
24
+ const { node, index: _index, isInline: _isInline, ...attrs } = props;
25
+
26
+ const styleIs = (style: string) => style === node.style;
27
+
28
+ // Allowlist-based; attacker-controlled PT data cannot inject arbitrary classes.
29
+ // See `./portable-text-text-align.ts`.
30
+ const alignClass = textAlignClassName(node.textAlign);
31
+ ---
32
+
33
+ {
34
+ styleIs("h1") ? (
35
+ <h1 class={alignClass} {...attrs}>
36
+ <slot />
37
+ </h1>
38
+ ) : styleIs("h2") ? (
39
+ <h2 class={alignClass} {...attrs}>
40
+ <slot />
41
+ </h2>
42
+ ) : styleIs("h3") ? (
43
+ <h3 class={alignClass} {...attrs}>
44
+ <slot />
45
+ </h3>
46
+ ) : styleIs("h4") ? (
47
+ <h4 class={alignClass} {...attrs}>
48
+ <slot />
49
+ </h4>
50
+ ) : styleIs("h5") ? (
51
+ <h5 class={alignClass} {...attrs}>
52
+ <slot />
53
+ </h5>
54
+ ) : styleIs("h6") ? (
55
+ <h6 class={alignClass} {...attrs}>
56
+ <slot />
57
+ </h6>
58
+ ) : styleIs("blockquote") ? (
59
+ <blockquote class={alignClass} {...attrs}>
60
+ <slot />
61
+ </blockquote>
62
+ ) : styleIs("normal") ? (
63
+ <p class={alignClass} {...attrs}>
64
+ <slot />
65
+ </p>
66
+ ) : (
67
+ <p class={alignClass} {...attrs}>
68
+ <slot />
69
+ </p>
70
+ )
71
+ }