emdash 0.28.0 → 0.29.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 (687) hide show
  1. package/dist/{adapters-hUy8vOB-.d.mts → adapters-DPAkL6QF.d.mts} +1 -1
  2. package/dist/{adapters-hUy8vOB-.d.mts.map → adapters-DPAkL6QF.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-CRsJ6BPM.mjs → allowed-origins-FXB-FplB.mjs} +2 -2
  4. package/dist/{allowed-origins-CRsJ6BPM.mjs.map → allowed-origins-FXB-FplB.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +22 -21
  7. package/dist/api/route-utils.mjs.map +1 -1
  8. package/dist/api/schemas/index.d.mts +2 -2
  9. package/dist/api/schemas/index.mjs +4 -4
  10. package/dist/{api-BFURZn1i.mjs → api-DVbHNApo.mjs} +75 -23
  11. package/dist/api-DVbHNApo.mjs.map +1 -0
  12. package/dist/{api-tokens-DvqeZmVq.mjs → api-tokens-UYBkl17d.mjs} +2 -2
  13. package/dist/{api-tokens-DvqeZmVq.mjs.map → api-tokens-UYBkl17d.mjs.map} +1 -1
  14. package/dist/{apply-Bu-8nYHL.mjs → apply-D23iUV4q.mjs} +20 -20
  15. package/dist/{apply-Bu-8nYHL.mjs.map → apply-D23iUV4q.mjs.map} +1 -1
  16. package/dist/astro/index.d.mts +13 -12
  17. package/dist/astro/index.d.mts.map +1 -1
  18. package/dist/astro/index.mjs +10 -5
  19. package/dist/astro/index.mjs.map +1 -1
  20. package/dist/astro/middleware/auth.d.mts +11 -10
  21. package/dist/astro/middleware/auth.d.mts.map +1 -1
  22. package/dist/astro/middleware/auth.mjs +8 -8
  23. package/dist/astro/middleware/redirect.mjs +7 -7
  24. package/dist/astro/middleware/request-context.d.mts +3 -0
  25. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  26. package/dist/astro/middleware/request-context.mjs +257 -30
  27. package/dist/astro/middleware/request-context.mjs.map +1 -1
  28. package/dist/astro/middleware/setup.mjs +1 -1
  29. package/dist/astro/middleware.d.mts +2 -2
  30. package/dist/astro/middleware.d.mts.map +1 -1
  31. package/dist/astro/middleware.mjs +125 -79
  32. package/dist/astro/middleware.mjs.map +1 -1
  33. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  34. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  35. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  36. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  37. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  38. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
  39. package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
  40. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
  41. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -17
  42. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -17
  43. package/dist/astro/routes/api/admin/bylines/index.mjs +17 -17
  44. package/dist/astro/routes/api/admin/comments/_id_/status.d.mts.map +1 -1
  45. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +13 -13
  46. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  47. package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
  48. package/dist/astro/routes/api/admin/comments/bulk.mjs +10 -10
  49. package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
  50. package/dist/astro/routes/api/admin/comments/index.d.mts.map +1 -1
  51. package/dist/astro/routes/api/admin/comments/index.mjs +10 -10
  52. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  54. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  55. package/dist/astro/routes/api/admin/media-usage/repair.d.mts +8 -0
  56. package/dist/astro/routes/api/admin/media-usage/repair.d.mts.map +1 -0
  57. package/dist/astro/routes/api/admin/media-usage/repair.mjs +28 -0
  58. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -0
  59. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  60. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  61. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +43 -41
  62. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +43 -41
  64. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  65. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +42 -40
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +42 -40
  68. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +42 -40
  70. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/index.mjs +42 -40
  72. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  74. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +42 -40
  75. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +42 -40
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +42 -40
  79. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +42 -40
  81. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +43 -41
  83. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +42 -40
  85. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +43 -41
  87. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/updates.mjs +42 -40
  89. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +42 -40
  91. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  93. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +42 -40
  94. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  96. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  97. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
  98. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  99. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  100. package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -7
  101. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  102. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  103. package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
  104. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  105. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  106. package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -11
  107. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  108. package/dist/astro/routes/api/auth/me.mjs +8 -8
  109. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  110. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  111. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs.map +1 -1
  112. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  113. package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
  114. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  115. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  116. package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
  117. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  118. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  119. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  120. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  121. package/dist/astro/routes/api/auth/signup/request.mjs +11 -11
  122. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  123. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.d.mts.map +1 -1
  124. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +69 -14
  125. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  126. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +13 -13
  127. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  128. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
  129. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  130. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  131. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +12 -12
  132. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
  133. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +9 -0
  134. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -0
  135. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +71 -0
  136. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -0
  137. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.d.mts +8 -0
  138. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.d.mts.map +1 -0
  139. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +50 -0
  140. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -0
  141. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  142. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  143. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  144. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +15 -15
  145. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  146. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
  147. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  148. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  149. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  150. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  151. package/dist/astro/routes/api/dashboard.mjs +8 -8
  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 +18 -18
  155. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  156. package/dist/astro/routes/api/import/wordpress/execute.d.mts +12 -11
  157. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  158. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
  159. package/dist/astro/routes/api/import/wordpress/media.d.mts +11 -10
  160. package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
  161. package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
  162. package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
  163. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +12 -16
  164. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
  165. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +11 -11
  166. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  167. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +18 -18
  168. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  169. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +12 -11
  170. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
  171. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +28 -28
  172. package/dist/astro/routes/api/manifest.mjs +6 -6
  173. package/dist/astro/routes/api/mcp.mjs +56 -47
  174. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  175. package/dist/astro/routes/api/media/_id_/confirm.mjs +9 -9
  176. package/dist/astro/routes/api/media/_id_.mjs +8 -8
  177. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  178. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  179. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  180. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  181. package/dist/astro/routes/api/media/upload-url.mjs +10 -10
  182. package/dist/astro/routes/api/media.mjs +13 -13
  183. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -9
  184. package/dist/astro/routes/api/menus/_name_/items.mjs +9 -9
  185. package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -9
  186. package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -9
  187. package/dist/astro/routes/api/menus/_name_.mjs +9 -9
  188. package/dist/astro/routes/api/menus/index.mjs +9 -9
  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 +24 -5
  198. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  199. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
  200. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +7 -15
  201. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
  202. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -12
  203. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -12
  204. package/dist/astro/routes/api/redirects/_id_.mjs +13 -13
  205. package/dist/astro/routes/api/redirects/index.mjs +13 -13
  206. package/dist/astro/routes/api/relations/_id_/index.d.mts +10 -0
  207. package/dist/astro/routes/api/relations/_id_/index.d.mts.map +1 -0
  208. package/dist/astro/routes/api/relations/_id_/index.mjs +69 -0
  209. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -0
  210. package/dist/astro/routes/api/relations/_id_/translations.d.mts +8 -0
  211. package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +1 -0
  212. package/dist/astro/routes/api/relations/_id_/translations.mjs +34 -0
  213. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -0
  214. package/dist/astro/routes/api/relations/index.d.mts +9 -0
  215. package/dist/astro/routes/api/relations/index.d.mts.map +1 -0
  216. package/dist/astro/routes/api/relations/index.mjs +53 -0
  217. package/dist/astro/routes/api/relations/index.mjs.map +1 -0
  218. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  219. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
  220. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.d.mts.map +1 -1
  221. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +42 -40
  222. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  223. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.d.mts.map +1 -1
  224. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +42 -40
  225. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  226. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +42 -40
  227. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  228. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +42 -40
  229. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  230. package/dist/astro/routes/api/schema/collections/index.mjs +42 -40
  231. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  232. package/dist/astro/routes/api/schema/index.mjs +9 -9
  233. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +42 -40
  234. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  235. package/dist/astro/routes/api/schema/orphans/index.mjs +42 -40
  236. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  237. package/dist/astro/routes/api/search/enable.mjs +12 -12
  238. package/dist/astro/routes/api/search/index.mjs +13 -12
  239. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/search/rebuild.mjs +12 -12
  241. package/dist/astro/routes/api/search/stats.mjs +8 -8
  242. package/dist/astro/routes/api/search/suggest.mjs +11 -11
  243. package/dist/astro/routes/api/sections/_slug_.mjs +11 -11
  244. package/dist/astro/routes/api/sections/index.mjs +11 -11
  245. package/dist/astro/routes/api/settings/email.mjs +6 -6
  246. package/dist/astro/routes/api/settings.mjs +15 -15
  247. package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
  248. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  249. package/dist/astro/routes/api/setup/dev-bypass.mjs +29 -29
  250. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  251. package/dist/astro/routes/api/setup/index.mjs +30 -30
  252. package/dist/astro/routes/api/setup/status.mjs +5 -5
  253. package/dist/astro/routes/api/snapshot.mjs +8 -8
  254. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +15 -15
  255. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +15 -15
  256. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +15 -15
  257. package/dist/astro/routes/api/taxonomies/index.mjs +15 -15
  258. package/dist/astro/routes/api/themes/preview.mjs +7 -7
  259. package/dist/astro/routes/api/typegen.mjs +6 -6
  260. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  261. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  262. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  263. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  264. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +12 -12
  265. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +12 -12
  266. package/dist/astro/routes/api/widget-areas/_name_.mjs +8 -8
  267. package/dist/astro/routes/api/widget-areas/index.mjs +12 -12
  268. package/dist/astro/routes/api/widget-components.mjs +4 -4
  269. package/dist/astro/routes/robots.txt.mjs +9 -9
  270. package/dist/astro/routes/sitemap-_collection_.xml.mjs +12 -12
  271. package/dist/astro/routes/sitemap.xml.mjs +10 -10
  272. package/dist/astro/types.d.mts +16 -13
  273. package/dist/astro/types.d.mts.map +1 -1
  274. package/dist/auth/providers/github.d.mts +1 -1
  275. package/dist/auth/providers/google.d.mts +1 -1
  276. package/dist/{authorize-Dz88F_Fw.mjs → authorize-BmCwQCib.mjs} +2 -2
  277. package/dist/{authorize-Dz88F_Fw.mjs.map → authorize-BmCwQCib.mjs.map} +1 -1
  278. package/dist/{base64-CmWvODNW.mjs → base64-C74Msx8h.mjs} +1 -1
  279. package/dist/{base64-CmWvODNW.mjs.map → base64-C74Msx8h.mjs.map} +1 -1
  280. package/dist/{byline-Bm8ZgUP9.mjs → byline-BWb5H-65.mjs} +8 -8
  281. package/dist/{byline-Bm8ZgUP9.mjs.map → byline-BWb5H-65.mjs.map} +1 -1
  282. package/dist/{byline-fields-CIx_GuN4.mjs → byline-fields-DO6bAYK8.mjs} +2 -2
  283. package/dist/{byline-fields-CIx_GuN4.mjs.map → byline-fields-DO6bAYK8.mjs.map} +1 -1
  284. package/dist/{byline-registry-BOjqDOim.mjs → byline-registry-BCuOp4UF.mjs} +3 -3
  285. package/dist/{byline-registry-BOjqDOim.mjs.map → byline-registry-BCuOp4UF.mjs.map} +1 -1
  286. package/dist/{bylines-6tm9mgQb.mjs → bylines-BGuKFaBy.mjs} +4 -4
  287. package/dist/{bylines-6tm9mgQb.mjs.map → bylines-BGuKFaBy.mjs.map} +1 -1
  288. package/dist/{bylines-Woq87129.mjs → bylines-CHojDMpj.mjs} +8 -8
  289. package/dist/{bylines-Woq87129.mjs.map → bylines-CHojDMpj.mjs.map} +1 -1
  290. package/dist/{cache-CEBAZjir.mjs → cache-BeR7RfN8.mjs} +3 -3
  291. package/dist/{cache-CEBAZjir.mjs.map → cache-BeR7RfN8.mjs.map} +1 -1
  292. package/dist/{challenge-store-anhwVER0.mjs → challenge-store-B426wQ6O.mjs} +1 -1
  293. package/dist/{challenge-store-anhwVER0.mjs.map → challenge-store-B426wQ6O.mjs.map} +1 -1
  294. package/dist/{chunks-B2isWQhr.mjs → chunks-BU5_nrAC.mjs} +2 -2
  295. package/dist/{chunks-B2isWQhr.mjs.map → chunks-BU5_nrAC.mjs.map} +1 -1
  296. package/dist/cli/index.mjs +28 -28
  297. package/dist/cli/index.mjs.map +1 -1
  298. package/dist/client/cf-access.d.mts +1 -1
  299. package/dist/client/index.d.mts +34 -2
  300. package/dist/client/index.d.mts.map +1 -1
  301. package/dist/client/index.mjs +6 -2
  302. package/dist/client/index.mjs.map +1 -1
  303. package/dist/{comment-CzeatwBV.mjs → comment-SWh31kS0.mjs} +2 -2
  304. package/dist/{comment-CzeatwBV.mjs.map → comment-SWh31kS0.mjs.map} +1 -1
  305. package/dist/{comment-reaction-Cj9QJY7I.mjs → comment-reaction-DgcpziXI.mjs} +2 -2
  306. package/dist/{comment-reaction-Cj9QJY7I.mjs.map → comment-reaction-DgcpziXI.mjs.map} +1 -1
  307. package/dist/{comments-BLE-jv5k.mjs → comments-kZYGppMS.mjs} +3 -3
  308. package/dist/{comments-BLE-jv5k.mjs.map → comments-kZYGppMS.mjs.map} +1 -1
  309. package/dist/{components-B_sATNUc.mjs → components-CliOkZAs.mjs} +1 -1
  310. package/dist/{components-B_sATNUc.mjs.map → components-CliOkZAs.mjs.map} +1 -1
  311. package/dist/{content-DhgEth4k.mjs → content-BO61Sx4j.mjs} +179 -20
  312. package/dist/content-BO61Sx4j.mjs.map +1 -0
  313. package/dist/{content-refresh-CA4uKwzH.mjs → content-refresh-BkkApzeS.mjs} +20 -14
  314. package/dist/content-refresh-BkkApzeS.mjs.map +1 -0
  315. package/dist/{context-CUsR9dXL.mjs → context-DtSFYFuS.mjs} +71 -14
  316. package/dist/context-DtSFYFuS.mjs.map +1 -0
  317. package/dist/{cron-v4FTEFR_.mjs → cron-YFJ7uNVA.mjs} +1 -1
  318. package/dist/{cron-v4FTEFR_.mjs.map → cron-YFJ7uNVA.mjs.map} +1 -1
  319. package/dist/{dashboard-EvEKF5en.mjs → dashboard-xo_gPs_D.mjs} +6 -5
  320. package/dist/dashboard-xo_gPs_D.mjs.map +1 -0
  321. package/dist/database/pg-migration-lock.d.mts +21 -0
  322. package/dist/database/pg-migration-lock.d.mts.map +1 -0
  323. package/dist/database/pg-migration-lock.mjs +45 -0
  324. package/dist/database/pg-migration-lock.mjs.map +1 -0
  325. package/dist/db/index.d.mts +3 -3
  326. package/dist/db/index.mjs +2 -2
  327. package/dist/db/libsql.d.mts +1 -1
  328. package/dist/db/postgres.d.mts +1 -1
  329. package/dist/db/postgres.d.mts.map +1 -1
  330. package/dist/db/postgres.mjs +2 -8
  331. package/dist/db/postgres.mjs.map +1 -1
  332. package/dist/db/sqlite.d.mts +1 -1
  333. package/dist/{db-errors-CK46D-ly.mjs → db-errors-BKuXh_fi.mjs} +1 -1
  334. package/dist/{db-errors-CK46D-ly.mjs.map → db-errors-BKuXh_fi.mjs.map} +1 -1
  335. package/dist/{default-CM_D83Mg.mjs → default-DY5ovGUG.mjs} +1 -1
  336. package/dist/{default-CM_D83Mg.mjs.map → default-DY5ovGUG.mjs.map} +1 -1
  337. package/dist/{device-flow-CfGP18Uw.mjs → device-flow-CPXQ_QfW.mjs} +5 -5
  338. package/dist/{device-flow-CfGP18Uw.mjs.map → device-flow-CPXQ_QfW.mjs.map} +1 -1
  339. package/dist/{dialect-helpers-DRI5pyY3.mjs → dialect-helpers-Cue7QQOR.mjs} +21 -2
  340. package/dist/dialect-helpers-Cue7QQOR.mjs.map +1 -0
  341. package/dist/{email-console-CIf4Lfvv.mjs → email-console-CjkQc7oY.mjs} +1 -1
  342. package/dist/{email-console-CIf4Lfvv.mjs.map → email-console-CjkQc7oY.mjs.map} +1 -1
  343. package/dist/{enrich-BQ0mxJRs.mjs → enrich-CFJJgxs_.mjs} +2 -2
  344. package/dist/{enrich-BQ0mxJRs.mjs.map → enrich-CFJJgxs_.mjs.map} +1 -1
  345. package/dist/{error-CkAseSqZ.mjs → error-CfJMLSkd.mjs} +12 -3
  346. package/dist/error-CfJMLSkd.mjs.map +1 -0
  347. package/dist/{escape-DqD0aCKu.mjs → escape-r8_GbEU2.mjs} +1 -1
  348. package/dist/{escape-DqD0aCKu.mjs.map → escape-r8_GbEU2.mjs.map} +1 -1
  349. package/dist/{field-defs-cache-WUI88LX5.mjs → field-defs-cache-BVrNCgSj.mjs} +5 -5
  350. package/dist/{field-defs-cache-WUI88LX5.mjs.map → field-defs-cache-BVrNCgSj.mjs.map} +1 -1
  351. package/dist/{fts-manager-BbFaF_V8.mjs → fts-manager-BD9s77qh.mjs} +27 -3
  352. package/dist/{fts-manager-BbFaF_V8.mjs.map → fts-manager-BD9s77qh.mjs.map} +1 -1
  353. package/dist/{hash-DrvzIXcz.mjs → hash-DFFrkivP.mjs} +1 -1
  354. package/dist/{hash-DrvzIXcz.mjs.map → hash-DFFrkivP.mjs.map} +1 -1
  355. package/dist/hreflang-CgIxhH4k.d.mts +48 -0
  356. package/dist/hreflang-CgIxhH4k.d.mts.map +1 -0
  357. package/dist/hreflang-pAWUiPd_.mjs +102 -0
  358. package/dist/hreflang-pAWUiPd_.mjs.map +1 -0
  359. package/dist/{import-fYLf14Co.mjs → import-2jHtLzsO.mjs} +6 -6
  360. package/dist/{import-fYLf14Co.mjs.map → import-2jHtLzsO.mjs.map} +1 -1
  361. package/dist/{index-B9sIxwe4.d.mts → index-BXOCyLj0.d.mts} +115 -21
  362. package/dist/index-BXOCyLj0.d.mts.map +1 -0
  363. package/dist/{index-Bm-Gy8Mh.d.mts → index-DxjWLKGT.d.mts} +3 -3
  364. package/dist/{index-Bm-Gy8Mh.d.mts.map → index-DxjWLKGT.d.mts.map} +1 -1
  365. package/dist/index.d.mts +20 -19
  366. package/dist/index.mjs +68 -64
  367. package/dist/{init-lock-6b309ZrF.mjs → init-lock-DJkX6Hto.mjs} +1 -1
  368. package/dist/{init-lock-6b309ZrF.mjs.map → init-lock-DJkX6Hto.mjs.map} +1 -1
  369. package/dist/{load-Djn3HWQS.mjs → load-DgoWMdRX.mjs} +2 -2
  370. package/dist/{load-Djn3HWQS.mjs.map → load-DgoWMdRX.mjs.map} +1 -1
  371. package/dist/{loader-CB6YHeul.mjs → loader-Rb8QlGZp.mjs} +5 -20
  372. package/dist/loader-Rb8QlGZp.mjs.map +1 -0
  373. package/dist/{manifest-schema-BHlgZM1W.mjs → manifest-schema-DeGNma2O.mjs} +3 -1
  374. package/dist/manifest-schema-DeGNma2O.mjs.map +1 -0
  375. package/dist/media/image-endpoint.mjs +1 -1
  376. package/dist/media/index.d.mts +1 -1
  377. package/dist/media/index.mjs +2 -2
  378. package/dist/media/local-runtime.d.mts +13 -12
  379. package/dist/media/local-runtime.d.mts.map +1 -1
  380. package/dist/media/local-runtime.mjs +8 -8
  381. package/dist/{media-BrXIaMFN.mjs → media-D2ZFowpn.mjs} +2 -2
  382. package/dist/media-D2ZFowpn.mjs.map +1 -0
  383. package/dist/{media-allowlist-CRHEeJ_i.mjs → media-allowlist-Dc05vKtt.mjs} +2 -2
  384. package/dist/{media-allowlist-CRHEeJ_i.mjs.map → media-allowlist-Dc05vKtt.mjs.map} +1 -1
  385. package/dist/{media-url-CKi5XSw4.mjs → media-url-DgIEYZr4.mjs} +1 -1
  386. package/dist/{media-url-CKi5XSw4.mjs.map → media-url-DgIEYZr4.mjs.map} +1 -1
  387. package/dist/media-usage-B__v9NMm.mjs +421 -0
  388. package/dist/media-usage-B__v9NMm.mjs.map +1 -0
  389. package/dist/{menus-Cfivc2Ad.mjs → menus-BpfevlJD.mjs} +3 -3
  390. package/dist/{menus-Cfivc2Ad.mjs.map → menus-BpfevlJD.mjs.map} +1 -1
  391. package/dist/{menus-CsZ2ZEK2.mjs → menus-BtvH7Z7t.mjs} +31 -12
  392. package/dist/menus-BtvH7Z7t.mjs.map +1 -0
  393. package/dist/{mime-CCEzze7W.mjs → mime-DfIVjNkr.mjs} +1 -1
  394. package/dist/{mime-CCEzze7W.mjs.map → mime-DfIVjNkr.mjs.map} +1 -1
  395. package/dist/{mode-BM9QgEmt.mjs → mode-BVnhGZ2o.mjs} +1 -1
  396. package/dist/{mode-BM9QgEmt.mjs.map → mode-BVnhGZ2o.mjs.map} +1 -1
  397. package/dist/{normalize-CeglrBT9.mjs → normalize-C-SHXmra.mjs} +1 -1
  398. package/dist/{normalize-CeglrBT9.mjs.map → normalize-C-SHXmra.mjs.map} +1 -1
  399. package/dist/{oauth-authorization-CXWkIGT4.mjs → oauth-authorization-BWqWTHBK.mjs} +5 -5
  400. package/dist/{oauth-authorization-CXWkIGT4.mjs.map → oauth-authorization-BWqWTHBK.mjs.map} +1 -1
  401. package/dist/{oauth-clients-BmTI5rsl.mjs → oauth-clients-43_XADoa.mjs} +1 -1
  402. package/dist/{oauth-clients-BmTI5rsl.mjs.map → oauth-clients-43_XADoa.mjs.map} +1 -1
  403. package/dist/{oauth-state-store-YLFLcH5F.mjs → oauth-state-store-BRSUEkmx.mjs} +1 -1
  404. package/dist/{oauth-state-store-YLFLcH5F.mjs.map → oauth-state-store-BRSUEkmx.mjs.map} +1 -1
  405. package/dist/{oauth-user-lookup-Bsc_GsX-.mjs → oauth-user-lookup-Ctgemb0k.mjs} +1 -1
  406. package/dist/{oauth-user-lookup-Bsc_GsX-.mjs.map → oauth-user-lookup-Ctgemb0k.mjs.map} +1 -1
  407. package/dist/object-cache/memory.d.mts +1 -1
  408. package/dist/{options-DTTML-Tx.mjs → options-BlmBHTvX.mjs} +1 -1
  409. package/dist/{options-DTTML-Tx.mjs.map → options-BlmBHTvX.mjs.map} +1 -1
  410. package/dist/{options-iMpRRxIe.d.mts → options-COXGTtqd.d.mts} +3 -3
  411. package/dist/{options-iMpRRxIe.d.mts.map → options-COXGTtqd.d.mts.map} +1 -1
  412. package/dist/page/index.d.mts +2 -2
  413. package/dist/{parse-GmjecGct.mjs → parse-GLksnn-B.mjs} +2 -2
  414. package/dist/{parse-GmjecGct.mjs.map → parse-GLksnn-B.mjs.map} +1 -1
  415. package/dist/{passkey-config-De0ahnRg.mjs → passkey-config-CjA1UbDj.mjs} +1 -1
  416. package/dist/{passkey-config-De0ahnRg.mjs.map → passkey-config-CjA1UbDj.mjs.map} +1 -1
  417. package/dist/{patterns-BKmjvM7K.mjs → patterns-CiyXeDgr.mjs} +1 -1
  418. package/dist/{patterns-BKmjvM7K.mjs.map → patterns-CiyXeDgr.mjs.map} +1 -1
  419. package/dist/{placeholder-BSKwzRe4.d.mts → placeholder-DR-eeZr-.d.mts} +1 -1
  420. package/dist/{placeholder-BSKwzRe4.d.mts.map → placeholder-DR-eeZr-.d.mts.map} +1 -1
  421. package/dist/plugin-types.d.mts +1 -1
  422. package/dist/plugin-utils.d.mts +11 -10
  423. package/dist/plugin-utils.d.mts.map +1 -1
  424. package/dist/plugins/adapt-sandbox-entry.d.mts +11 -10
  425. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  426. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  427. package/dist/{portable-text-cCa0cGV6.mjs → portable-text-BAkgEKcv.mjs} +1 -1
  428. package/dist/{portable-text-cCa0cGV6.mjs.map → portable-text-BAkgEKcv.mjs.map} +1 -1
  429. package/dist/{preview-SSXNVPAC.mjs → preview-Rloa09Wp.mjs} +2 -2
  430. package/dist/{preview-SSXNVPAC.mjs.map → preview-Rloa09Wp.mjs.map} +1 -1
  431. package/dist/{public-url-Danv47cS.mjs → public-url-C0cEvrRu.mjs} +1 -1
  432. package/dist/{public-url-Danv47cS.mjs.map → public-url-C0cEvrRu.mjs.map} +1 -1
  433. package/dist/{schema-Blhoxp3P.mjs → query-BxT95opY.mjs} +5 -10
  434. package/dist/query-BxT95opY.mjs.map +1 -0
  435. package/dist/{query-ByGq6ver.mjs → query-ZzvXyxWq.mjs} +15 -15
  436. package/dist/query-ZzvXyxWq.mjs.map +1 -0
  437. package/dist/{rate-limit-C_Lf63Dd.mjs → rate-limit-Cg4Rvc_-.mjs} +2 -2
  438. package/dist/{rate-limit-C_Lf63Dd.mjs.map → rate-limit-Cg4Rvc_-.mjs.map} +1 -1
  439. package/dist/{redirect-CoW3G-0U.mjs → redirect-Ce_6Yb6z.mjs} +1 -1
  440. package/dist/{redirect-CoW3G-0U.mjs.map → redirect-Ce_6Yb6z.mjs.map} +1 -1
  441. package/dist/{redirect-IyfNirgS.mjs → redirect-Ch3E98qZ.mjs} +4 -4
  442. package/dist/{redirect-IyfNirgS.mjs.map → redirect-Ch3E98qZ.mjs.map} +1 -1
  443. package/dist/{redirects-Bs1g42Ri.mjs → redirects-CXmVGRNZ.mjs} +6 -6
  444. package/dist/{redirects-Bs1g42Ri.mjs.map → redirects-CXmVGRNZ.mjs.map} +1 -1
  445. package/dist/{redirects-DXEXBAII.mjs → redirects-CeD7K7EX.mjs} +43 -5
  446. package/dist/redirects-CeD7K7EX.mjs.map +1 -0
  447. package/dist/{registry-B65mUtPa.mjs → registry-CyIXPi4E.mjs} +8 -8
  448. package/dist/{registry-B65mUtPa.mjs.map → registry-CyIXPi4E.mjs.map} +1 -1
  449. package/dist/relation-Ba68Tm4Z.mjs +334 -0
  450. package/dist/relation-Ba68Tm4Z.mjs.map +1 -0
  451. package/dist/{byline-fields-2Lp5Hbgf.mjs → relations-BmBmX4Eb.mjs} +60 -4
  452. package/dist/relations-BmBmX4Eb.mjs.map +1 -0
  453. package/dist/relations-C8hVyEy0.mjs +397 -0
  454. package/dist/relations-C8hVyEy0.mjs.map +1 -0
  455. package/dist/{byline-fields-Cgrt9-aL.d.mts → relations-CbBpoOys.d.mts} +180 -27
  456. package/dist/relations-CbBpoOys.d.mts.map +1 -0
  457. package/dist/{request-cache-KCNHp_RJ.mjs → request-cache-BSUptuJR.mjs} +1 -1
  458. package/dist/{request-cache-KCNHp_RJ.mjs.map → request-cache-BSUptuJR.mjs.map} +1 -1
  459. package/dist/{request-meta-DbvXaAvU.mjs → request-meta-DCwktC5P.mjs} +2 -2
  460. package/dist/{request-meta-DbvXaAvU.mjs.map → request-meta-DCwktC5P.mjs.map} +1 -1
  461. package/dist/{resolve-DR3wqMTy.mjs → resolve-Cd9dzclN.mjs} +1 -1
  462. package/dist/{resolve-DR3wqMTy.mjs.map → resolve-Cd9dzclN.mjs.map} +1 -1
  463. package/dist/{runner-DvFWoz8-.d.mts → runner-CiNdIk3y.d.mts} +8 -2
  464. package/dist/runner-CiNdIk3y.d.mts.map +1 -0
  465. package/dist/{runner-K8XK101B.mjs → runner-jt65bF7F.mjs} +24 -7
  466. package/dist/{runner-K8XK101B.mjs.map → runner-jt65bF7F.mjs.map} +1 -1
  467. package/dist/runtime.d.mts +12 -11
  468. package/dist/runtime.d.mts.map +1 -1
  469. package/dist/runtime.mjs +4 -4
  470. package/dist/{scheduled-publish-Drffrf2a.d.mts → scheduled-publish-DlJHGcuL.d.mts} +1 -1
  471. package/dist/scheduled-publish-DlJHGcuL.d.mts.map +1 -0
  472. package/dist/schema-DwjufZ1S.mjs +9 -0
  473. package/dist/schema-DwjufZ1S.mjs.map +1 -0
  474. package/dist/{search-DZN2HZ-V.mjs → search-Cl875CVE.mjs} +62 -12
  475. package/dist/search-Cl875CVE.mjs.map +1 -0
  476. package/dist/{secrets-kp760LlD.mjs → secrets-CO_bEmII.mjs} +4 -4
  477. package/dist/{secrets-kp760LlD.mjs.map → secrets-CO_bEmII.mjs.map} +1 -1
  478. package/dist/{sections-CpF5SaGr.mjs → sections-DTKzgoiS.mjs} +3 -3
  479. package/dist/{sections-CpF5SaGr.mjs.map → sections-DTKzgoiS.mjs.map} +1 -1
  480. package/dist/seed/index.d.mts +2 -2
  481. package/dist/seed/index.mjs +23 -23
  482. package/dist/seo/index.d.mts +4 -2
  483. package/dist/seo/index.d.mts.map +1 -1
  484. package/dist/seo/index.mjs +19 -2
  485. package/dist/seo/index.mjs.map +1 -1
  486. package/dist/{seo-DXu2UQnC.mjs → seo-BLm6SXzS.mjs} +2 -2
  487. package/dist/{seo-DXu2UQnC.mjs.map → seo-BLm6SXzS.mjs.map} +1 -1
  488. package/dist/{seo-89-53DDs.mjs → seo-BjrbXAd_.mjs} +1 -1
  489. package/dist/{seo-89-53DDs.mjs.map → seo-BjrbXAd_.mjs.map} +1 -1
  490. package/dist/{service-DQmiBMzt.mjs → service-D6zDmKXy.mjs} +3 -3
  491. package/dist/{service-DQmiBMzt.mjs.map → service-D6zDmKXy.mjs.map} +1 -1
  492. package/dist/{session-user-Cascbax7.mjs → session-user-DoSs6YM8.mjs} +1 -1
  493. package/dist/{session-user-Cascbax7.mjs.map → session-user-DoSs6YM8.mjs.map} +1 -1
  494. package/dist/{settings-zhmdKyJQ.mjs → settings-BuQYvLfy.mjs} +6 -6
  495. package/dist/{settings-zhmdKyJQ.mjs.map → settings-BuQYvLfy.mjs.map} +1 -1
  496. package/dist/{settings-rZyHEcNT.mjs → settings-CmS3TwXf.mjs} +3 -3
  497. package/dist/{settings-rZyHEcNT.mjs.map → settings-CmS3TwXf.mjs.map} +1 -1
  498. package/dist/{setup-complete-Cb3LRyzy.mjs → setup-complete-BPNgLHlU.mjs} +2 -2
  499. package/dist/{setup-complete-Cb3LRyzy.mjs.map → setup-complete-BPNgLHlU.mjs.map} +1 -1
  500. package/dist/{setup-nonce-Z8x0tHf8.mjs → setup-nonce-DEPZX96T.mjs} +1 -1
  501. package/dist/{setup-nonce-Z8x0tHf8.mjs.map → setup-nonce-DEPZX96T.mjs.map} +1 -1
  502. package/dist/{single-flight-cache-BG3B_GhN.mjs → single-flight-cache-DEtW-OEG.mjs} +2 -2
  503. package/dist/{single-flight-cache-BG3B_GhN.mjs.map → single-flight-cache-DEtW-OEG.mjs.map} +1 -1
  504. package/dist/{site-url-BBfDTgZB.mjs → site-url-CcLy5D5s.mjs} +2 -2
  505. package/dist/{site-url-BBfDTgZB.mjs.map → site-url-CcLy5D5s.mjs.map} +1 -1
  506. package/dist/{slugify-Cce3dTdg.mjs → slugify-C_tqlU4G.mjs} +1 -1
  507. package/dist/{slugify-Cce3dTdg.mjs.map → slugify-C_tqlU4G.mjs.map} +1 -1
  508. package/dist/{ssrf-1g7usGBg.mjs → ssrf-TrKYJAy0.mjs} +1 -1
  509. package/dist/{ssrf-1g7usGBg.mjs.map → ssrf-TrKYJAy0.mjs.map} +1 -1
  510. package/dist/{status-CqJQX1QN.mjs → status-D3Gy1Zc6.mjs} +1 -1
  511. package/dist/{status-CqJQX1QN.mjs.map → status-D3Gy1Zc6.mjs.map} +1 -1
  512. package/dist/storage/local.d.mts +1 -1
  513. package/dist/storage/local.mjs +1 -1
  514. package/dist/storage/s3.d.mts +1 -1
  515. package/dist/storage/s3.mjs +1 -1
  516. package/dist/{taxonomies-BGBd16Eu.mjs → taxonomies-ClS4RKaZ.mjs} +13 -9
  517. package/dist/taxonomies-ClS4RKaZ.mjs.map +1 -0
  518. package/dist/{taxonomies-Cnb4F-Pb.mjs → taxonomies-pUkuD6nj.mjs} +115 -36
  519. package/dist/taxonomies-pUkuD6nj.mjs.map +1 -0
  520. package/dist/{taxonomy-BxGxZZdu.mjs → taxonomy-BkxbUMSw.mjs} +12 -3
  521. package/dist/{taxonomy-BxGxZZdu.mjs.map → taxonomy-BkxbUMSw.mjs.map} +1 -1
  522. package/dist/{tokens-BGT0TUUo.mjs → tokens-BV6fgl5A.mjs} +2 -2
  523. package/dist/{tokens-BGT0TUUo.mjs.map → tokens-BV6fgl5A.mjs.map} +1 -1
  524. package/dist/{transaction-qfqpPVpu.mjs → transaction-D0FOsb3X.mjs} +1 -1
  525. package/dist/{transaction-qfqpPVpu.mjs.map → transaction-D0FOsb3X.mjs.map} +1 -1
  526. package/dist/{transport-DPefPMcz.mjs → transport-DTFhhPOg.mjs} +1 -1
  527. package/dist/{transport-DPefPMcz.mjs.map → transport-DTFhhPOg.mjs.map} +1 -1
  528. package/dist/{transport-BMDWHSgZ.d.mts → transport-DmlmzD2U.d.mts} +1 -1
  529. package/dist/{transport-BMDWHSgZ.d.mts.map → transport-DmlmzD2U.d.mts.map} +1 -1
  530. package/dist/{trusted-proxy-VTPRiX2s.mjs → trusted-proxy-CSgZVESw.mjs} +1 -1
  531. package/dist/{trusted-proxy-VTPRiX2s.mjs.map → trusted-proxy-CSgZVESw.mjs.map} +1 -1
  532. package/dist/{types-CgvhU-hF.d.mts → types-B6-N9cBB.d.mts} +1 -1
  533. package/dist/{types-CgvhU-hF.d.mts.map → types-B6-N9cBB.d.mts.map} +1 -1
  534. package/dist/{types-g_aFIdW0.d.mts → types-BCVuUPrL.d.mts} +1 -1
  535. package/dist/{types-g_aFIdW0.d.mts.map → types-BCVuUPrL.d.mts.map} +1 -1
  536. package/dist/{types-Jo3UYd6b.mjs → types-BNZsPL9z.mjs} +1 -1
  537. package/dist/{types-Jo3UYd6b.mjs.map → types-BNZsPL9z.mjs.map} +1 -1
  538. package/dist/{types-vgEWF18A.d.mts → types-B_pmP7Yq.d.mts} +1 -1
  539. package/dist/{types-vgEWF18A.d.mts.map → types-B_pmP7Yq.d.mts.map} +1 -1
  540. package/dist/{types-CuW0zWDA.mjs → types-Ch8pFMEm.mjs} +3 -3
  541. package/dist/{types-CuW0zWDA.mjs.map → types-Ch8pFMEm.mjs.map} +1 -1
  542. package/dist/{types-ea9sAPck.d.mts → types-Cm4Cz-8M.d.mts} +1 -1
  543. package/dist/{types-ea9sAPck.d.mts.map → types-Cm4Cz-8M.d.mts.map} +1 -1
  544. package/dist/{types-CGbYowGQ.d.mts → types-CtDVagM4.d.mts} +55 -3
  545. package/dist/types-CtDVagM4.d.mts.map +1 -0
  546. package/dist/{types-BcLUUbbR.d.mts → types-DLIrNtv5.d.mts} +11 -3
  547. package/dist/{types-BcLUUbbR.d.mts.map → types-DLIrNtv5.d.mts.map} +1 -1
  548. package/dist/{types-DmHk7vAt.d.mts → types-QnlQIyPE.d.mts} +1 -1
  549. package/dist/{types-DmHk7vAt.d.mts.map → types-QnlQIyPE.d.mts.map} +1 -1
  550. package/dist/{types-_HFLRzTn.d.mts → types-momGysZk.d.mts} +1 -1
  551. package/dist/{types-_HFLRzTn.d.mts.map → types-momGysZk.d.mts.map} +1 -1
  552. package/dist/{types-tM44hEcf.mjs → types-o7xo7VgH.mjs} +1 -1
  553. package/dist/{types-tM44hEcf.mjs.map → types-o7xo7VgH.mjs.map} +1 -1
  554. package/dist/{types-ClUkdbWb.d.mts → types-qljd1hsL.d.mts} +1 -1
  555. package/dist/{types-ClUkdbWb.d.mts.map → types-qljd1hsL.d.mts.map} +1 -1
  556. package/dist/{user-BjAOvU3Z.mjs → user-DTxX_Fha.mjs} +3 -3
  557. package/dist/{user-BjAOvU3Z.mjs.map → user-DTxX_Fha.mjs.map} +1 -1
  558. package/dist/{utils-BJXElxdw.mjs → utils-Cz8PVrl4.mjs} +3 -3
  559. package/dist/{utils-BJXElxdw.mjs.map → utils-Cz8PVrl4.mjs.map} +1 -1
  560. package/dist/{validate-Z1b86_3B.d.mts → validate-9jLuE301.d.mts} +5 -5
  561. package/dist/{validate-Z1b86_3B.d.mts.map → validate-9jLuE301.d.mts.map} +1 -1
  562. package/dist/{validate-CWSnKVIJ.mjs → validate-C3CpWlNt.mjs} +3 -3
  563. package/dist/{validate-CWSnKVIJ.mjs.map → validate-C3CpWlNt.mjs.map} +1 -1
  564. package/dist/{validation-c8WjhH8z.mjs → validation-DM2K_NJC.mjs} +10 -10
  565. package/dist/{validation-c8WjhH8z.mjs.map → validation-DM2K_NJC.mjs.map} +1 -1
  566. package/dist/version-BlIJvNAZ.mjs +7 -0
  567. package/dist/{version-CaccU7DM.mjs.map → version-BlIJvNAZ.mjs.map} +1 -1
  568. package/dist/{widgets-hWcIicX8.mjs → widgets-B_X6_UXJ.mjs} +4 -4
  569. package/dist/{widgets-hWcIicX8.mjs.map → widgets-B_X6_UXJ.mjs.map} +1 -1
  570. package/dist/{wxr-taxonomies-BC3OYpvx.mjs → wxr-taxonomies-oNJB2S81.mjs} +4 -4
  571. package/dist/{wxr-taxonomies-BC3OYpvx.mjs.map → wxr-taxonomies-oNJB2S81.mjs.map} +1 -1
  572. package/dist/{wxr-taxonomies-0_uxSrmf.d.mts → wxr-taxonomies-tADW4KTa.d.mts} +1 -1
  573. package/dist/{wxr-taxonomies-0_uxSrmf.d.mts.map → wxr-taxonomies-tADW4KTa.d.mts.map} +1 -1
  574. package/dist/{zod-generator-CacrR-i8.mjs → zod-generator-CrfV79De.mjs} +3 -3
  575. package/dist/{zod-generator-CacrR-i8.mjs.map → zod-generator-CrfV79De.mjs.map} +1 -1
  576. package/package.json +11 -7
  577. package/src/api/errors.ts +11 -0
  578. package/src/api/handlers/content.ts +111 -1
  579. package/src/api/handlers/dashboard.ts +2 -0
  580. package/src/api/handlers/index.ts +6 -0
  581. package/src/api/handlers/media-usage.ts +80 -0
  582. package/src/api/handlers/relations.ts +474 -0
  583. package/src/api/handlers/taxonomies.ts +26 -4
  584. package/src/api/handlers/validate-media-fields.ts +1 -1
  585. package/src/api/openapi/document.ts +25 -0
  586. package/src/api/parse.ts +1 -1
  587. package/src/api/schemas/comments.ts +6 -0
  588. package/src/api/schemas/content.ts +8 -0
  589. package/src/api/schemas/index.ts +2 -0
  590. package/src/api/schemas/media-usage.ts +48 -0
  591. package/src/api/schemas/relations.ts +109 -0
  592. package/src/api/schemas/search.ts +1 -0
  593. package/src/astro/integration/index.ts +1 -0
  594. package/src/astro/integration/routes.ts +5 -0
  595. package/src/astro/integration/runtime.ts +24 -0
  596. package/src/astro/middleware/request-context.ts +162 -20
  597. package/src/astro/middleware.ts +22 -9
  598. package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -2
  599. package/src/astro/routes/api/admin/comments/index.ts +1 -2
  600. package/src/astro/routes/api/admin/media-usage/repair.ts +24 -0
  601. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +1 -2
  602. package/src/astro/routes/api/auth/oauth/[provider].ts +1 -2
  603. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +13 -0
  604. package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +97 -0
  605. package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/parents.ts +48 -0
  606. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +17 -15
  607. package/src/astro/routes/api/relations/[id]/index.ts +84 -0
  608. package/src/astro/routes/api/relations/[id]/translations.ts +33 -0
  609. package/src/astro/routes/api/relations/index.ts +56 -0
  610. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +1 -7
  611. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +1 -2
  612. package/src/astro/routes/api/search/index.ts +2 -0
  613. package/src/astro/types.ts +2 -0
  614. package/src/cli/commands/export-seed.ts +1 -10
  615. package/src/client/index.ts +39 -0
  616. package/src/comments/service.ts +1 -1
  617. package/src/comments/turnstile.ts +64 -0
  618. package/src/components/BlockquoteGroup.astro +34 -0
  619. package/src/components/CommentForm.astro +12 -5
  620. package/src/components/EmDashHead.astro +27 -1
  621. package/src/components/InlinePortableTextEditor.tsx +34 -0
  622. package/src/components/PortableText.astro +7 -1
  623. package/src/components/index.ts +2 -0
  624. package/src/components/portable-text-blockquote-group.ts +68 -0
  625. package/src/content/converters/portable-text-to-prosemirror.ts +32 -1
  626. package/src/database/dialect-helpers.ts +34 -0
  627. package/src/database/migrations/039_fix_fts5_triggers.ts +1 -1
  628. package/src/database/migrations/runner.ts +46 -6
  629. package/src/database/pg-migration-lock.ts +72 -0
  630. package/src/database/repositories/comment.ts +1 -1
  631. package/src/database/repositories/content.ts +172 -21
  632. package/src/database/repositories/media-usage.ts +25 -3
  633. package/src/database/repositories/media.ts +1 -1
  634. package/src/database/repositories/relation.ts +130 -5
  635. package/src/database/repositories/taxonomy.ts +9 -0
  636. package/src/database/repositories/types.ts +8 -0
  637. package/src/db/postgres.ts +5 -2
  638. package/src/emdash-runtime.ts +72 -4
  639. package/src/index.ts +6 -2
  640. package/src/loader.ts +1 -31
  641. package/src/mcp/server.ts +29 -3
  642. package/src/media/usage/content-repair.ts +206 -22
  643. package/src/media/usage/content-snapshots.ts +4 -0
  644. package/src/plugins/context.ts +85 -0
  645. package/src/plugins/define-plugin.ts +1 -0
  646. package/src/plugins/index.ts +4 -0
  647. package/src/plugins/manifest-schema.ts +2 -0
  648. package/src/plugins/types.ts +59 -0
  649. package/src/schema/byline-registry.ts +1 -1
  650. package/src/search/fts-manager.ts +34 -0
  651. package/src/search/match.ts +50 -0
  652. package/src/search/query.ts +94 -9
  653. package/src/seo/hreflang.ts +192 -0
  654. package/src/seo/index.ts +3 -0
  655. package/src/taxonomies/index.ts +62 -45
  656. package/src/taxonomies/term-counts.ts +117 -0
  657. package/src/virtual-modules.d.ts +1 -0
  658. package/src/visual-editing/editable.ts +41 -35
  659. package/src/visual-editing/toolbar-bootstrap.ts +120 -0
  660. package/src/visual-editing/toolbar.ts +46 -0
  661. package/dist/api-BFURZn1i.mjs.map +0 -1
  662. package/dist/byline-fields-2Lp5Hbgf.mjs.map +0 -1
  663. package/dist/byline-fields-Cgrt9-aL.d.mts.map +0 -1
  664. package/dist/content-DhgEth4k.mjs.map +0 -1
  665. package/dist/content-refresh-CA4uKwzH.mjs.map +0 -1
  666. package/dist/context-CUsR9dXL.mjs.map +0 -1
  667. package/dist/dashboard-EvEKF5en.mjs.map +0 -1
  668. package/dist/dialect-helpers-DRI5pyY3.mjs.map +0 -1
  669. package/dist/error-CkAseSqZ.mjs.map +0 -1
  670. package/dist/index-B9sIxwe4.d.mts.map +0 -1
  671. package/dist/loader-CB6YHeul.mjs.map +0 -1
  672. package/dist/manifest-schema-BHlgZM1W.mjs.map +0 -1
  673. package/dist/media-BrXIaMFN.mjs.map +0 -1
  674. package/dist/menus-CsZ2ZEK2.mjs.map +0 -1
  675. package/dist/query-ByGq6ver.mjs.map +0 -1
  676. package/dist/redirects-DXEXBAII.mjs.map +0 -1
  677. package/dist/runner-DvFWoz8-.d.mts.map +0 -1
  678. package/dist/scheduled-publish-Drffrf2a.d.mts.map +0 -1
  679. package/dist/schema-Blhoxp3P.mjs.map +0 -1
  680. package/dist/search-DZN2HZ-V.mjs.map +0 -1
  681. package/dist/taxonomies-BGBd16Eu.mjs.map +0 -1
  682. package/dist/taxonomies-Cnb4F-Pb.mjs.map +0 -1
  683. package/dist/types-CGbYowGQ.d.mts.map +0 -1
  684. package/dist/version-CaccU7DM.mjs +0 -7
  685. /package/dist/{api-tokens-DsvvCtdh.mjs → api-tokens-Dk2GrJMY.mjs} +0 -0
  686. /package/dist/{ssrf-CmuGgCq3.mjs → ssrf-B5DOv5E5.mjs} +0 -0
  687. /package/dist/{types-DROWRxYV.mjs → types-DeCZBZxn.mjs} +0 -0
@@ -0,0 +1,109 @@
1
+ import { z } from "zod";
2
+
3
+ const slugPattern = /^[a-z][a-z0-9_]*$/;
4
+ const collectionSlug = z
5
+ .string()
6
+ .min(1)
7
+ .max(63)
8
+ .regex(slugPattern, "Invalid collection slug format");
9
+
10
+ export const createRelationBody = z
11
+ .object({
12
+ name: z
13
+ .string()
14
+ .min(1)
15
+ .max(63)
16
+ .regex(slugPattern, "Name must be lowercase alphanumeric with underscores"),
17
+ parentCollection: collectionSlug.optional(),
18
+ childCollection: collectionSlug.optional(),
19
+ parentLabel: z.string().min(1).max(200),
20
+ childLabel: z.string().min(1).max(200),
21
+ locale: z.string().min(1).optional(),
22
+ translationOf: z.string().min(1).optional(),
23
+ })
24
+ // A translation inherits its structural fields (name, parentCollection,
25
+ // childCollection) from the source relation, so the handler ignores any
26
+ // collections supplied alongside `translationOf`. Require them only when
27
+ // minting a base relation, so callers aren't forced to pass discarded values.
28
+ .refine(
29
+ (body) =>
30
+ body.translationOf !== undefined ||
31
+ (body.parentCollection !== undefined && body.childCollection !== undefined),
32
+ { message: "parentCollection and childCollection are required unless translationOf is set" },
33
+ )
34
+ .meta({ id: "CreateRelationBody" });
35
+
36
+ export const updateRelationBody = z
37
+ .object({
38
+ parentLabel: z.string().min(1).max(200).optional(),
39
+ childLabel: z.string().min(1).max(200).optional(),
40
+ })
41
+ // Reject empty payloads: an update touching no field is a client mistake, not
42
+ // a successful no-op. Without this, `{}` validates and the handler returns 200
43
+ // with the unchanged row, so a typo'd payload looks like it landed.
44
+ .refine((body) => body.parentLabel !== undefined || body.childLabel !== undefined, {
45
+ message: "At least one of parentLabel or childLabel is required",
46
+ })
47
+ .meta({ id: "UpdateRelationBody" });
48
+
49
+ export const setReferenceChildrenBody = z
50
+ .object({ childIds: z.array(z.string().min(1)).max(1000) })
51
+ .meta({ id: "SetReferenceChildrenBody" });
52
+
53
+ export const relationDefSchema = z
54
+ .object({
55
+ id: z.string(),
56
+ name: z.string(),
57
+ parentCollection: z.string(),
58
+ childCollection: z.string(),
59
+ parentLabel: z.string(),
60
+ childLabel: z.string(),
61
+ locale: z.string(),
62
+ translationGroup: z.string(),
63
+ })
64
+ .meta({ id: "RelationDef" });
65
+
66
+ export const relationListResponseSchema = z
67
+ .object({ relations: z.array(relationDefSchema) })
68
+ .meta({ id: "RelationListResponse" });
69
+
70
+ export const relationResponseSchema = z
71
+ .object({ relation: relationDefSchema })
72
+ .meta({ id: "RelationResponse" });
73
+
74
+ export const relationTranslationsSchema = z
75
+ .object({
76
+ translationGroup: z.string(),
77
+ translations: z.array(
78
+ z.object({
79
+ id: z.string(),
80
+ name: z.string(),
81
+ locale: z.string(),
82
+ parentLabel: z.string(),
83
+ childLabel: z.string(),
84
+ }),
85
+ ),
86
+ })
87
+ .meta({ id: "RelationTranslations" });
88
+
89
+ export const entryRefSchema = z
90
+ .object({
91
+ id: z.string(),
92
+ slug: z.string().nullable(),
93
+ collection: z.string(),
94
+ // The actual locale of the resolved variant. When no variant matches the
95
+ // requesting entry's locale, the ref falls back to another locale's row;
96
+ // this field makes that substitution explicit instead of silently
97
+ // presenting a wrong-locale entry under the requested context.
98
+ locale: z.string().nullable(),
99
+ sortOrder: z.number().int().optional(),
100
+ })
101
+ .meta({ id: "ReferenceEntryRef" });
102
+
103
+ export const referenceChildrenResponseSchema = z
104
+ .object({ children: z.array(entryRefSchema), nextCursor: z.string().optional() })
105
+ .meta({ id: "ReferenceChildrenResponse" });
106
+
107
+ export const referenceParentsResponseSchema = z
108
+ .object({ parents: z.array(entryRefSchema), nextCursor: z.string().optional() })
109
+ .meta({ id: "ReferenceParentsResponse" });
@@ -13,6 +13,7 @@ export const searchQuery = z
13
13
  status: z.string().optional(),
14
14
  locale: localeCode.optional(),
15
15
  limit: z.coerce.number().int().min(1).max(100).optional(),
16
+ cursor: z.string().optional(),
16
17
  })
17
18
  .meta({ id: "SearchQuery" });
18
19
 
@@ -350,6 +350,7 @@ export function emdash(config: EmDashConfig = {}): AstroIntegration {
350
350
  trustedProxyHeaders: resolvedConfig.trustedProxyHeaders,
351
351
  maxUploadSize: resolvedConfig.maxUploadSize,
352
352
  admin: resolvedConfig.admin,
353
+ toolbar: resolvedConfig.toolbar,
353
354
  };
354
355
 
355
356
  // Determine auth mode for route injection
@@ -234,6 +234,11 @@ export function injectCoreRoutes(
234
234
  entrypoint: resolveRoute("api/media/providers/[providerId]/[itemId].ts"),
235
235
  });
236
236
 
237
+ injectRoute({
238
+ pattern: "/_emdash/api/admin/media-usage/repair",
239
+ entrypoint: resolveRoute("api/admin/media-usage/repair.ts"),
240
+ });
241
+
237
242
  // Import API routes
238
243
  injectRoute({
239
244
  pattern: "/_emdash/api/import/probe",
@@ -589,6 +589,30 @@ export interface EmDashConfig {
589
589
  favicon?: string;
590
590
  };
591
591
 
592
+ /**
593
+ * Editor toolbar delivery on public pages.
594
+ *
595
+ * - `"server"` (default): the toolbar is injected server-side into every
596
+ * HTML response rendered for an authenticated editor. Simple and
597
+ * zero-config, but behind a shared cache (Cloudflare Cache Everything /
598
+ * Workers Cache, Fastly, Varnish, …) editors often receive the cached
599
+ * anonymous variant — without the toolbar — whenever an anonymous visitor
600
+ * primed the cache first, so the toolbar appears and disappears with
601
+ * cache state.
602
+ * - `"client"`: public HTML is identical for everyone (nothing
603
+ * session-specific is injected server-side, so shared caches stay fully
604
+ * effective). A tiny bootstrap script shows an "Edit" pill for browsers
605
+ * that have logged into the admin (non-secret localStorage flag). Clicking
606
+ * it verifies the session and reloads the page with an `_edit` query
607
+ * param, which is always rendered fresh (never cached) with the full
608
+ * toolbar. Logged-out visitors opening an `_edit` URL are redirected to
609
+ * the canonical URL.
610
+ * - `false`: never render the toolbar or bootstrap script.
611
+ *
612
+ * See the visual-editing docs for the cache-behavior details.
613
+ */
614
+ toolbar?: "server" | "client" | false;
615
+
592
616
  /**
593
617
  * Version of Astro the host project is building with. Populated by the
594
618
  * integration's `astro:config:setup` hook (not authored by the user) and
@@ -8,37 +8,123 @@
8
8
  * - Preview tokens: _preview query param with signed HMAC token
9
9
  * - Edit mode: emdash-edit-mode cookie (for visual editing)
10
10
  * - Toolbar injection: floating pill for authenticated editors
11
+ * - Client toolbar mode (`toolbar: "client"`): cache-identical HTML with a
12
+ * client-side bootstrap pill and an `_edit` query param for fresh editor
13
+ * renders (Discussion #1742)
11
14
  */
12
15
 
16
+ import type { APIContext } from "astro";
13
17
  import { defineMiddleware } from "astro:middleware";
18
+ // @ts-ignore - virtual module
19
+ import virtualConfig from "virtual:emdash/config";
14
20
 
15
21
  import { resolveSecretsCached } from "#config/secrets.js";
16
22
 
17
23
  import { verifyPreviewToken, parseContentId } from "../../preview/tokens.js";
18
24
  import { getRequestContext, runWithContext } from "../../request-context.js";
25
+ import { EDIT_PARAM, renderToolbarBootstrap } from "../../visual-editing/toolbar-bootstrap.js";
19
26
  import { renderToolbar } from "../../visual-editing/toolbar.js";
20
27
 
28
+ type ToolbarMode = "server" | "client" | false;
29
+
30
+ const toolbarMode: ToolbarMode = virtualConfig?.toolbar ?? "server";
31
+
32
+ /** Astro's route-cache handle. EmDash requires Astro 6+, so it's always present. */
33
+ type RouteCache = APIContext["cache"];
34
+
21
35
  /**
22
- * Inject toolbar HTML into a response if it's an HTML page.
23
- * Returns the original response if not HTML.
36
+ * Opt the current request out of Astro's route cache (e.g. Workers Cache on
37
+ * Cloudflare). `Cache-Control` headers do NOT cover this: the adapter derives
38
+ * the shared-cache TTL from the route-cache options (on Cloudflare via
39
+ * `Cloudflare-CDN-Cache-Control`), so session-specific responses must
40
+ * explicitly disable it or they get stored in the shared cache and served to
41
+ * anonymous visitors without ever invoking the middleware again. With no cache
42
+ * provider configured this is a no-op (`NoopAstroCache`/`DisabledAstroCache`).
24
43
  */
25
- async function injectToolbar(response: Response, toolbarHtml: string): Promise<Response> {
44
+ function optOutOfRouteCache(cache: RouteCache): void {
45
+ cache.set(false);
46
+ }
47
+
48
+ /**
49
+ * Inject HTML before `</body>` if the response is an HTML page with a body
50
+ * end tag. Does not touch cache headers — callers decide whether the result
51
+ * is still shareable. `injected` tells the caller whether anything changed.
52
+ */
53
+ async function injectBeforeBodyEnd(
54
+ response: Response,
55
+ htmlToInject: string,
56
+ ): Promise<{ response: Response; injected: boolean }> {
26
57
  const contentType = response.headers.get("content-type");
27
- if (!contentType?.includes("text/html")) return response;
58
+ if (!contentType?.includes("text/html")) return { response, injected: false };
28
59
 
29
60
  const html = await response.text();
30
- if (!html.includes("</body>")) return new Response(html, response);
61
+ if (!html.includes("</body>")) {
62
+ // Body already consumed — rebuild the response unchanged.
63
+ return { response: new Response(html, response), injected: false };
64
+ }
65
+
66
+ const injected = html.replace("</body>", `${htmlToInject}</body>`);
67
+ return {
68
+ response: new Response(injected, {
69
+ status: response.status,
70
+ headers: response.headers,
71
+ }),
72
+ injected: true,
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Inject toolbar HTML into a response if it's an HTML page.
78
+ * Returns the original response if not HTML.
79
+ */
80
+ async function injectToolbar(
81
+ response: Response,
82
+ toolbarHtml: string,
83
+ routeCache: RouteCache,
84
+ ): Promise<Response> {
85
+ const result = await injectBeforeBodyEnd(response, toolbarHtml);
86
+ if (result.injected) {
87
+ // Toolbar-injected HTML is session-specific (its presence reveals an
88
+ // active editor session); it must never be stored in a shared CDN cache
89
+ // and served to anonymous visitors. Mirrors the preview branch's guard
90
+ // (#1398). `Cache-Control` covers browsers/downstream proxies; the
91
+ // route-cache opt-out covers the shared edge cache, which ignores
92
+ // `Cache-Control`.
93
+ result.response.headers.set("Cache-Control", "private, no-store");
94
+ optOutOfRouteCache(routeCache);
95
+ }
96
+ return result.response;
97
+ }
31
98
 
32
- const injected = html.replace("</body>", `${toolbarHtml}</body>`);
33
- const result = new Response(injected, {
34
- status: response.status,
35
- headers: response.headers,
99
+ /**
100
+ * Inject the client-toolbar bootstrap script. Identical for every visitor, so
101
+ * cache headers and route-cache options are left untouched and the response
102
+ * stays fully shareable.
103
+ */
104
+ async function injectBootstrap(response: Response): Promise<Response> {
105
+ const result = await injectBeforeBodyEnd(response, renderToolbarBootstrap());
106
+ return result.response;
107
+ }
108
+
109
+ /**
110
+ * Redirect an `_edit` URL to its canonical form (same URL without the param).
111
+ * Applied when the requester is not an authenticated editor, so a shared
112
+ * `?_edit` link degrades gracefully for everyone else (Discussion #1742).
113
+ */
114
+ function redirectToCanonical(url: URL): Response {
115
+ const canonical = new URL(url);
116
+ canonical.searchParams.delete(EDIT_PARAM);
117
+ return new Response(null, {
118
+ status: 302,
119
+ headers: {
120
+ Location: canonical.pathname + canonical.search + canonical.hash,
121
+ // Header-following caches (Fastly, Varnish, browsers) must not store
122
+ // the redirect — a cached 302 would bounce editors back to the
123
+ // canonical URL. The route-cache opt-out at the call site covers the
124
+ // Workers Cache, which ignores Cache-Control.
125
+ "Cache-Control": "private, no-store",
126
+ },
36
127
  });
37
- // Toolbar-injected HTML is session-specific (its presence reveals an active
38
- // editor session); it must never be stored in a shared CDN cache and served
39
- // to anonymous visitors. Mirrors the preview branch's guard (#1398).
40
- result.headers.set("Cache-Control", "private, no-store");
41
- return result;
42
128
  }
43
129
 
44
130
  export const onRequest = defineMiddleware(async (context, next) => {
@@ -73,9 +159,30 @@ export const onRequest = defineMiddleware(async (context, next) => {
73
159
  // Fast path: check for CMS signals before doing any work
74
160
  const hasEditCookie = cookies.get("emdash-edit-mode")?.value === "true";
75
161
  const hasPreviewToken = url.searchParams.has("_preview");
162
+ // `_edit` requests a fresh (never cached) editor render; only meaningful in
163
+ // client toolbar mode where public HTML is otherwise identical for everyone.
164
+ const hasEditParam = toolbarMode === "client" && url.searchParams.has(EDIT_PARAM);
165
+
166
+ if (hasEditParam) {
167
+ // `_edit` URLs are their own cache key. Never store them in the route
168
+ // cache — a cached anonymous redirect would bounce editors back to the
169
+ // canonical URL, and a cached editor render must never be shared.
170
+ optOutOfRouteCache(context.cache);
171
+
172
+ // A non-editor (anonymous, logged-out, or insufficient role) opening an
173
+ // `_edit` URL is sent to the canonical URL — shared `?_edit` links
174
+ // degrade gracefully and never prime a cache entry with page content.
175
+ if (!isEditor) {
176
+ return redirectToCanonical(url);
177
+ }
178
+ }
76
179
 
77
- // No CMS signals and not an editor → skip everything (zero overhead)
180
+ // No CMS signals and not an editor → skip everything (zero overhead in
181
+ // server mode; client mode injects the identical-for-everyone bootstrap)
78
182
  if (!hasEditCookie && !hasPreviewToken && !isEditor) {
183
+ if (toolbarMode === "client") {
184
+ return injectBootstrap(await next());
185
+ }
79
186
  return next();
80
187
  }
81
188
 
@@ -86,6 +193,8 @@ export const onRequest = defineMiddleware(async (context, next) => {
86
193
  // eslint-disable-next-line typescript/no-unsafe-type-assertion -- Astro context includes currentLocale when i18n is configured
87
194
  const locale = (context as { currentLocale?: string }).currentLocale;
88
195
 
196
+ const routeCache = context.cache;
197
+
89
198
  // Verify preview token if present.
90
199
  // The preview secret is resolved via `resolveSecretsCached`: env wins,
91
200
  // otherwise a DB-stored value is read (or generated on first need).
@@ -122,32 +231,65 @@ export const onRequest = defineMiddleware(async (context, next) => {
122
231
 
123
232
  // Preview responses must not be cached -- draft content could leak past token expiry.
124
233
  // Clone the response before modifying headers — the original may be immutable.
234
+ // `Cache-Control` only governs browsers/downstream proxies; the shared
235
+ // edge cache follows the route-cache options, so opt out of those too —
236
+ // otherwise the draft response is stored in the shared cache and served
237
+ // on cache hits without token verification until TTL/purge. Opt out for
238
+ // any request carrying a `_preview` param (valid or not): those URLs are
239
+ // per-token, so cached copies are useless at best and drafts at worst.
240
+ if (hasPreviewToken) {
241
+ optOutOfRouteCache(routeCache);
242
+ }
125
243
  if (preview) {
126
244
  response = new Response(response.body, response);
127
245
  response.headers.set("Cache-Control", "private, no-store");
128
246
  }
129
247
 
130
- // Inject toolbar for authenticated editors
131
- if (isEditor) {
248
+ // Inject toolbar for authenticated editors. Preview and edit-mode
249
+ // responses are session-specific (`private, no-store` + route-cache
250
+ // opt-out) in every toolbar mode, so the server toolbar is safe to
251
+ // inject here even in client mode.
252
+ if (isEditor && toolbarMode !== false) {
132
253
  const toolbarHtml = renderToolbar({
133
254
  editMode,
134
255
  isPreview: !!preview,
135
256
  });
136
- return injectToolbar(response, toolbarHtml);
257
+ return injectToolbar(response, toolbarHtml, routeCache);
258
+ }
259
+
260
+ // Stale edit cookie without a session (client mode): still serve the
261
+ // shareable bootstrap variant.
262
+ if (toolbarMode === "client" && !isEditor && !preview) {
263
+ return injectBootstrap(response);
137
264
  }
138
265
 
139
266
  return response;
140
267
  });
141
268
  }
142
269
 
143
- // Editor without CMS signals — no ALS needed, but inject toolbar
270
+ // Editor without preview/edit-mode signals.
144
271
  if (isEditor) {
272
+ if (toolbarMode === false) {
273
+ return next();
274
+ }
275
+
276
+ // Client mode: without the `_edit` param the response must stay
277
+ // byte-identical to the anonymous variant (plus the same bootstrap
278
+ // script), so shared caches serve one entry for everyone. The bootstrap
279
+ // pill is the editor's entry point into the fresh `_edit` render.
280
+ if (toolbarMode === "client" && !hasEditParam) {
281
+ return injectBootstrap(await next());
282
+ }
283
+
284
+ // Server mode, or an `_edit` request in client mode: inject the full
285
+ // toolbar (response becomes `private, no-store` and route-cache
286
+ // opted out).
145
287
  const response = await next();
146
288
  const toolbarHtml = renderToolbar({
147
289
  editMode: false,
148
290
  isPreview: false,
149
291
  });
150
- return injectToolbar(response, toolbarHtml);
292
+ return injectToolbar(response, toolbarHtml, routeCache);
151
293
  }
152
294
 
153
295
  return next();
@@ -76,6 +76,17 @@ import type { EmDashHandlers } from "./types.js";
76
76
  */
77
77
  const RUNTIME_INIT_DEADLINE_MS = DB_INIT_DEADLINE_MS + 15_000;
78
78
 
79
+ /**
80
+ * Throttle for the anonymous-path runtime-init failure log. While a site is
81
+ * stuck (e.g. a failing migration in its backoff window, #1744) every
82
+ * anonymous request lands in that catch; one line per interval per isolate
83
+ * keeps the failure visible without flooding logs on a busy site. Plain
84
+ * module state (not globalThis): a duplicated SSR chunk just means an extra
85
+ * log line, which is harmless.
86
+ */
87
+ const RUNTIME_INIT_ERROR_LOG_INTERVAL_MS = 30_000;
88
+ let lastRuntimeInitErrorLogAt = 0;
89
+
79
90
  /**
80
91
  * Whether we've verified the database has been set up.
81
92
  * On a fresh deployment the first request may hit a public page, bypassing
@@ -152,8 +163,7 @@ function getConfig(): EmDashConfig | null {
152
163
  }
153
164
  }
154
165
 
155
- // eslint-disable-next-line typescript/no-unsafe-type-assertion -- virtual module import is untyped (@ts-ignore above)
156
- return virtualConfig as EmDashConfig;
166
+ return virtualConfig;
157
167
  }
158
168
  return null;
159
169
  }
@@ -524,11 +534,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
524
534
  try {
525
535
  const { getDb } = await import("../loader.js");
526
536
  const db = await getDb();
527
- await db
528
- .selectFrom("_emdash_migrations" as keyof Database)
529
- .selectAll()
530
- .limit(1)
531
- .execute();
537
+ await db.selectFrom("_emdash_migrations").selectAll().limit(1).execute();
532
538
  markSetupVerified();
533
539
  } catch (error) {
534
540
  // Only a genuinely-missing migrations table means a fresh,
@@ -571,8 +577,15 @@ export const onRequest = defineMiddleware(async (context, next) => {
571
577
  // requests carry no session.
572
578
  storage: runtime.storage,
573
579
  } as EmDashHandlers;
574
- } catch {
575
- // Non-fatal — EmDashHead will fall back to base SEO contributions
580
+ } catch (error) {
581
+ // Non-fatal — EmDashHead falls back to base SEO contributions
582
+ // but log it (throttled): a persistently failing init (e.g. a
583
+ // failing migration, #1744) is otherwise invisible on the
584
+ // anonymous path, silently degrading every public page.
585
+ if (Date.now() - lastRuntimeInitErrorLogAt >= RUNTIME_INIT_ERROR_LOG_INTERVAL_MS) {
586
+ lastRuntimeInitErrorLogAt = Date.now();
587
+ console.error("[emdash] runtime init failed (page renders without CMS data):", error);
588
+ }
576
589
  }
577
590
  timings.push({ name: "rt", dur: performance.now() - t0, desc: "Runtime init" });
578
591
  // Append cold-only sub-phase timings so the breakdown is visible
@@ -14,7 +14,6 @@ import { commentStatusBody } from "#api/schemas.js";
14
14
  import { getSiteBaseUrl } from "#api/site-url.js";
15
15
  import { lookupContentAuthor, sendCommentNotification } from "#comments/notifications.js";
16
16
  import { moderateComment, type CommentHookRunner } from "#comments/service.js";
17
- import type { CommentStatus } from "#db/repositories/comment.js";
18
17
  import type { ModerationDecision } from "#plugins/types.js";
19
18
 
20
19
  export const prerender = false;
@@ -37,7 +36,7 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
37
36
  const body = await parseBody(request, commentStatusBody);
38
37
  if (isParseError(body)) return body;
39
38
 
40
- const newStatus = body.status as CommentStatus;
39
+ const newStatus = body.status;
41
40
 
42
41
  // Build hook runner for the service
43
42
  const hookRunner: CommentHookRunner = {
@@ -11,7 +11,6 @@ import { handleError, requireDb, unwrapResult } from "#api/error.js";
11
11
  import { handleCommentInbox } from "#api/handlers/comments.js";
12
12
  import { isParseError, parseQuery } from "#api/parse.js";
13
13
  import { commentListQuery } from "#api/schemas.js";
14
- import type { CommentStatus } from "#db/repositories/comment.js";
15
14
 
16
15
  export const prerender = false;
17
16
 
@@ -32,7 +31,7 @@ export const GET: APIRoute = async ({ url, locals }) => {
32
31
  if (isParseError(query)) return query;
33
32
 
34
33
  const result = await handleCommentInbox(emdash.db, {
35
- status: query.status as CommentStatus | undefined,
34
+ status: query.status,
36
35
  collection: query.collection,
37
36
  search: query.search,
38
37
  limit: query.limit,
@@ -0,0 +1,24 @@
1
+ import type { APIRoute } from "astro";
2
+
3
+ import { requirePerm } from "#api/authorize.js";
4
+ import { requireDb, unwrapResult } from "#api/error.js";
5
+ import { handleMediaUsageRepair } from "#api/handlers/media-usage.js";
6
+ import { isParseError, parseBody } from "#api/parse.js";
7
+ import { mediaUsageRepairBody } from "#api/schemas.js";
8
+
9
+ export const prerender = false;
10
+
11
+ export const POST: APIRoute = async ({ request, locals }) => {
12
+ const { emdash, user } = locals;
13
+ const dbErr = requireDb(emdash?.db);
14
+ if (dbErr) return dbErr;
15
+
16
+ const denied = requirePerm(user, "schema:manage");
17
+ if (denied) return denied;
18
+
19
+ const body = await parseBody(request, mediaUsageRepairBody);
20
+ if (isParseError(body)) return body;
21
+
22
+ const result = await handleMediaUsageRepair(emdash.db, body);
23
+ return unwrapResult(result);
24
+ };
@@ -118,8 +118,7 @@ export const GET: APIRoute = async ({ params, request, locals, session, redirect
118
118
  // Get OAuth providers from environment
119
119
  // eslint-disable-next-line typescript/no-unsafe-type-assertion -- locals.runtime is injected by the Cloudflare adapter at runtime; not declared on App.Locals since the adapter is optional
120
120
  const runtimeLocals = locals as unknown as { runtime?: { env?: Record<string, unknown> } };
121
- // eslint-disable-next-line typescript/no-unsafe-type-assertion -- import.meta.env is typed as ImportMetaEnv but we need Record<string, unknown> for getOAuthConfig
122
- const env = runtimeLocals.runtime?.env ?? (import.meta.env as Record<string, unknown>);
121
+ const env = runtimeLocals.runtime?.env ?? import.meta.env;
123
122
  const providers = getOAuthConfig(env);
124
123
 
125
124
  if (!providers[provider]) {
@@ -97,8 +97,7 @@ export const GET: APIRoute = async ({ params, request, locals, redirect }) => {
97
97
  // Access via locals.runtime for Cloudflare, or import.meta.env for Node
98
98
  // eslint-disable-next-line typescript/no-unsafe-type-assertion -- locals.runtime is injected by the Cloudflare adapter at runtime; not declared on App.Locals since the adapter is optional
99
99
  const runtimeLocals = locals as unknown as { runtime?: { env?: Record<string, unknown> } };
100
- // eslint-disable-next-line typescript/no-unsafe-type-assertion -- import.meta.env is typed as ImportMetaEnv but we need Record<string, unknown> for getOAuthConfig
101
- const env = runtimeLocals.runtime?.env ?? (import.meta.env as Record<string, unknown>);
100
+ const env = runtimeLocals.runtime?.env ?? import.meta.env;
102
101
  const providers = getOAuthConfig(env);
103
102
 
104
103
  if (!providers[provider]) {
@@ -14,6 +14,7 @@ import { createCommentBody } from "#api/schemas.js";
14
14
  import { getSiteBaseUrl } from "#api/site-url.js";
15
15
  import { sendCommentNotification } from "#comments/notifications.js";
16
16
  import { createComment, type CommentHookRunner } from "#comments/service.js";
17
+ import { getTurnstileSecretKey, verifyTurnstileToken } from "#comments/turnstile.js";
17
18
  import { resolveSecretsCached } from "#config/secrets.js";
18
19
  import { CommentRepository } from "#db/repositories/comment.js";
19
20
  import { validateIdentifier } from "#db/validate.js";
@@ -163,6 +164,18 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
163
164
  return apiError("RATE_LIMITED", "Too many comments. Please try again later.", 429);
164
165
  }
165
166
 
167
+ // Anti-spam: Turnstile — enforced only when the operator configured a
168
+ // secret key. Runs after the free checks (honeypot, rate limit) so
169
+ // obvious spam never triggers a siteverify subrequest. Fails closed:
170
+ // missing token, failed verification, and siteverify errors all reject.
171
+ const turnstileSecretKey = getTurnstileSecretKey();
172
+ if (turnstileSecretKey) {
173
+ const verified = await verifyTurnstileToken(body.turnstileToken, turnstileSecretKey, meta.ip);
174
+ if (!verified) {
175
+ return apiError("TURNSTILE_FAILED", "CAPTCHA verification failed", 403);
176
+ }
177
+ }
178
+
166
179
  // Build collection settings
167
180
  const collectionSettings: CollectionCommentSettings = {
168
181
  commentsEnabled: collectionRow.comments_enabled === 1,