emdash 0.19.0 → 0.21.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 (595) hide show
  1. package/dist/{adapters-C5AWLJSD.d.mts → adapters-BxSmgtbF.d.mts} +1 -1
  2. package/dist/{adapters-C5AWLJSD.d.mts.map → adapters-BxSmgtbF.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-CyYLEJkp.mjs → allowed-origins-BqC8cul8.mjs} +2 -2
  4. package/dist/{allowed-origins-CyYLEJkp.mjs.map → allowed-origins-BqC8cul8.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +13 -12
  7. package/dist/api/route-utils.mjs.map +1 -1
  8. package/dist/api/schemas/index.d.mts +1 -1
  9. package/dist/api/schemas/index.mjs +3 -2
  10. package/dist/{api-BZ6bhjYs.mjs → api-DxjIV2o8.mjs} +46 -15
  11. package/dist/api-DxjIV2o8.mjs.map +1 -0
  12. package/dist/{api-tokens-VrXNiNvV.mjs → api-tokens-BFFkB0jB.mjs} +2 -2
  13. package/dist/{api-tokens-VrXNiNvV.mjs.map → api-tokens-BFFkB0jB.mjs.map} +1 -1
  14. package/dist/{apply-hQkKKBCf.mjs → apply-CLjxheyb.mjs} +12 -12
  15. package/dist/{apply-hQkKKBCf.mjs.map → apply-CLjxheyb.mjs.map} +1 -1
  16. package/dist/astro/index.d.mts +10 -10
  17. package/dist/astro/index.d.mts.map +1 -1
  18. package/dist/astro/index.mjs +50 -15
  19. package/dist/astro/index.mjs.map +1 -1
  20. package/dist/astro/middleware/auth.d.mts +9 -9
  21. package/dist/astro/middleware/auth.mjs +5 -5
  22. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  23. package/dist/astro/middleware/redirect.mjs +11 -2
  24. package/dist/astro/middleware/redirect.mjs.map +1 -1
  25. package/dist/astro/middleware/request-context.mjs +3 -2
  26. package/dist/astro/middleware/request-context.mjs.map +1 -1
  27. package/dist/astro/middleware/setup.mjs +1 -1
  28. package/dist/astro/middleware.d.mts +1 -1
  29. package/dist/astro/middleware.d.mts.map +1 -1
  30. package/dist/astro/middleware.mjs +91 -137
  31. package/dist/astro/middleware.mjs.map +1 -1
  32. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -4
  33. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
  34. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -4
  35. package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
  36. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
  37. package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
  38. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  39. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -7
  40. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
  41. package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -7
  42. package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
  43. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -7
  44. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -12
  46. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  47. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +14 -12
  48. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  49. package/dist/astro/routes/api/admin/bylines/index.mjs +14 -12
  50. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  51. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +9 -8
  52. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/comments/_id_.mjs +3 -3
  54. package/dist/astro/routes/api/admin/comments/bulk.mjs +7 -6
  55. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/comments/counts.mjs +3 -3
  57. package/dist/astro/routes/api/admin/comments/index.mjs +7 -6
  58. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +3 -3
  60. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +2 -2
  61. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  62. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  63. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +29 -27
  64. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  65. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +29 -27
  66. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +28 -26
  68. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +28 -26
  70. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +28 -26
  72. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/index.mjs +28 -26
  74. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  76. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +28 -26
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +28 -26
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +28 -26
  81. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +28 -26
  83. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +29 -27
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +28 -26
  87. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +29 -27
  89. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/updates.mjs +28 -26
  91. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +28 -26
  93. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  95. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +28 -26
  96. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  97. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +1 -1
  98. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  99. package/dist/astro/routes/api/admin/users/_id_/index.mjs +5 -4
  100. package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
  102. package/dist/astro/routes/api/admin/users/index.mjs +5 -4
  103. package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
  104. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  105. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  106. package/dist/astro/routes/api/auth/invite/complete.mjs +9 -8
  107. package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
  108. package/dist/astro/routes/api/auth/invite/index.mjs +6 -5
  109. package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
  110. package/dist/astro/routes/api/auth/invite/register-options.mjs +8 -7
  111. package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
  112. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  113. package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -7
  114. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  115. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  116. package/dist/astro/routes/api/auth/me.mjs +5 -4
  117. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  118. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  119. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  120. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  121. package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -4
  122. package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
  123. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  124. package/dist/astro/routes/api/auth/passkey/options.mjs +10 -9
  125. package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
  126. package/dist/astro/routes/api/auth/passkey/register/options.mjs +8 -7
  127. package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
  128. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +9 -8
  129. package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
  130. package/dist/astro/routes/api/auth/passkey/verify.mjs +9 -8
  131. package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
  132. package/dist/astro/routes/api/auth/signup/complete.mjs +9 -8
  133. package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
  134. package/dist/astro/routes/api/auth/signup/request.mjs +8 -7
  135. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  136. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  137. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -9
  138. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  139. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  140. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +2 -2
  141. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +2 -2
  142. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
  143. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +10 -8
  144. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
  145. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -5
  146. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  147. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +2 -2
  148. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  149. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +6 -5
  150. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  151. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +10 -9
  152. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  153. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  154. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +2 -2
  155. package/dist/astro/routes/api/content/_collection_/_id_.mjs +6 -5
  156. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  157. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  158. package/dist/astro/routes/api/content/_collection_/index.mjs +6 -5
  159. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  160. package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -5
  161. package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
  162. package/dist/astro/routes/api/dashboard.mjs +3 -3
  163. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  164. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  165. package/dist/astro/routes/api/import/probe.mjs +10 -9
  166. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  167. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  168. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  169. package/dist/astro/routes/api/import/wordpress/execute.mjs +10 -9
  170. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  171. package/dist/astro/routes/api/import/wordpress/media.mjs +8 -7
  172. package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
  173. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -8
  174. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  175. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +8 -7
  176. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  177. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  178. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +10 -9
  179. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  180. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  181. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +14 -12
  182. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  183. package/dist/astro/routes/api/manifest.mjs +3 -3
  184. package/dist/astro/routes/api/mcp.mjs +20 -19
  185. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  186. package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -5
  187. package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
  188. package/dist/astro/routes/api/media/_id_.mjs +6 -5
  189. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  190. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  191. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  192. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  193. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  194. package/dist/astro/routes/api/media/upload-url.mjs +8 -7
  195. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  196. package/dist/astro/routes/api/media.mjs +10 -9
  197. package/dist/astro/routes/api/media.mjs.map +1 -1
  198. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +6 -5
  199. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  200. package/dist/astro/routes/api/menus/_name_/items.mjs +6 -5
  201. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  202. package/dist/astro/routes/api/menus/_name_/reorder.mjs +6 -5
  203. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  204. package/dist/astro/routes/api/menus/_name_/translations.mjs +6 -5
  205. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  206. package/dist/astro/routes/api/menus/_name_.mjs +6 -5
  207. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  208. package/dist/astro/routes/api/menus/index.mjs +6 -5
  209. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  210. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  211. package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
  212. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  213. package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
  214. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  215. package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
  216. package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
  217. package/dist/astro/routes/api/oauth/token.mjs +5 -5
  218. package/dist/astro/routes/api/openapi.json.mjs +3 -2
  219. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  220. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
  221. package/dist/astro/routes/api/redirects/404s/index.mjs +7 -6
  222. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  223. package/dist/astro/routes/api/redirects/404s/summary.mjs +7 -6
  224. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  225. package/dist/astro/routes/api/redirects/_id_.mjs +8 -7
  226. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  227. package/dist/astro/routes/api/redirects/index.mjs +8 -7
  228. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  229. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  230. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +2 -2
  231. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +28 -26
  232. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  233. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +28 -26
  234. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  235. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +28 -26
  236. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  237. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +28 -26
  238. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  239. package/dist/astro/routes/api/schema/collections/index.mjs +28 -26
  240. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  241. package/dist/astro/routes/api/schema/index.mjs +8 -13
  242. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  243. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +28 -26
  244. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  245. package/dist/astro/routes/api/schema/orphans/index.mjs +28 -26
  246. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  247. package/dist/astro/routes/api/search/enable.mjs +9 -8
  248. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  249. package/dist/astro/routes/api/search/index.mjs +8 -7
  250. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  251. package/dist/astro/routes/api/search/rebuild.mjs +9 -8
  252. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  253. package/dist/astro/routes/api/search/stats.mjs +5 -5
  254. package/dist/astro/routes/api/search/suggest.mjs +8 -7
  255. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  256. package/dist/astro/routes/api/sections/_slug_.mjs +8 -7
  257. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  258. package/dist/astro/routes/api/sections/index.mjs +8 -7
  259. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  260. package/dist/astro/routes/api/settings/email.mjs +3 -3
  261. package/dist/astro/routes/api/settings.mjs +11 -9
  262. package/dist/astro/routes/api/settings.mjs.map +1 -1
  263. package/dist/astro/routes/api/setup/admin-verify.mjs +10 -9
  264. package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
  265. package/dist/astro/routes/api/setup/admin.mjs +9 -8
  266. package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
  267. package/dist/astro/routes/api/setup/dev-bypass.mjs +19 -18
  268. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  269. package/dist/astro/routes/api/setup/dev-reset.mjs +1 -1
  270. package/dist/astro/routes/api/setup/index.mjs +20 -18
  271. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  272. package/dist/astro/routes/api/setup/status.mjs +3 -3
  273. package/dist/astro/routes/api/snapshot.mjs +5 -4
  274. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  275. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +11 -10
  276. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  277. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -10
  278. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  279. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -10
  280. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  281. package/dist/astro/routes/api/taxonomies/index.mjs +11 -10
  282. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  283. package/dist/astro/routes/api/themes/preview.mjs +5 -4
  284. package/dist/astro/routes/api/themes/preview.mjs.map +1 -1
  285. package/dist/astro/routes/api/typegen.mjs +4 -4
  286. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  287. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  288. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  289. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -5
  290. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  291. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +9 -7
  292. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  293. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +9 -7
  294. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  295. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -4
  296. package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
  297. package/dist/astro/routes/api/widget-areas/index.mjs +9 -7
  298. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  299. package/dist/astro/routes/api/widget-components.mjs +2 -2
  300. package/dist/astro/routes/robots.txt.mjs +5 -4
  301. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  302. package/dist/astro/routes/sitemap-_collection_.xml.d.mts.map +1 -1
  303. package/dist/astro/routes/sitemap-_collection_.xml.mjs +15 -7
  304. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  305. package/dist/astro/routes/sitemap.xml.mjs +6 -5
  306. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  307. package/dist/astro/types.d.mts +12 -12
  308. package/dist/auth/providers/github.d.mts +1 -1
  309. package/dist/auth/providers/google.d.mts +1 -1
  310. package/dist/{authorize-C_8t2KGa.mjs → authorize-D5gfBVU5.mjs} +2 -2
  311. package/dist/{authorize-C_8t2KGa.mjs.map → authorize-D5gfBVU5.mjs.map} +1 -1
  312. package/dist/{byline-DUx48sJp.mjs → byline-V_Qp1Ziw.mjs} +27 -14
  313. package/dist/byline-V_Qp1Ziw.mjs.map +1 -0
  314. package/dist/{byline-fields-51kg6Vuv.mjs → byline-fields-B0NO1yUB.mjs} +3 -3
  315. package/dist/{byline-fields-51kg6Vuv.mjs.map → byline-fields-B0NO1yUB.mjs.map} +1 -1
  316. package/dist/{byline-fields-DYXKDuNX.d.mts → byline-fields-CQJRIQkn.d.mts} +36 -32
  317. package/dist/byline-fields-CQJRIQkn.d.mts.map +1 -0
  318. package/dist/{byline-fields-C_OsR-KF.mjs → byline-fields-nBVqK_Ff.mjs} +2 -2
  319. package/dist/{byline-fields-C_OsR-KF.mjs.map → byline-fields-nBVqK_Ff.mjs.map} +1 -1
  320. package/dist/{byline-registry-CWP7I71B.mjs → byline-registry-DedidtqC.mjs} +2 -2
  321. package/dist/{byline-registry-CWP7I71B.mjs.map → byline-registry-DedidtqC.mjs.map} +1 -1
  322. package/dist/{bylines-Cx5n-WqP.mjs → bylines-B2NWnIwS.mjs} +2 -2
  323. package/dist/{bylines-Cx5n-WqP.mjs.map → bylines-B2NWnIwS.mjs.map} +1 -1
  324. package/dist/{bylines-wurS258E.mjs → bylines-DfGDnred.mjs} +7 -7
  325. package/dist/{bylines-wurS258E.mjs.map → bylines-DfGDnred.mjs.map} +1 -1
  326. package/dist/{cache-B_HzASVT.mjs → cache-DTTHWD8n.mjs} +1 -1
  327. package/dist/{cache-B_HzASVT.mjs.map → cache-DTTHWD8n.mjs.map} +1 -1
  328. package/dist/{challenge-store-DGwuCc4R.mjs → challenge-store-woE0bbCf.mjs} +1 -1
  329. package/dist/{challenge-store-DGwuCc4R.mjs.map → challenge-store-woE0bbCf.mjs.map} +1 -1
  330. package/dist/cli/index.mjs +22 -20
  331. package/dist/cli/index.mjs.map +1 -1
  332. package/dist/client/cf-access.d.mts +1 -1
  333. package/dist/client/index.d.mts +1 -1
  334. package/dist/client/index.mjs +1 -1
  335. package/dist/{comments-CJ0RZsYR.mjs → comments-D2hNuxNa.mjs} +1 -1
  336. package/dist/{comments-CJ0RZsYR.mjs.map → comments-D2hNuxNa.mjs.map} +1 -1
  337. package/dist/{components-CTfpu3PZ.mjs → components-DYKp2gmo.mjs} +1 -1
  338. package/dist/{components-CTfpu3PZ.mjs.map → components-DYKp2gmo.mjs.map} +1 -1
  339. package/dist/{context-GG52SPgh.mjs → context-Cm4pt1Ws.mjs} +5 -5
  340. package/dist/{context-GG52SPgh.mjs.map → context-Cm4pt1Ws.mjs.map} +1 -1
  341. package/dist/{cron-BJ2ClIlj.mjs → cron-DdEVrQ2Y.mjs} +1 -1
  342. package/dist/{cron-BJ2ClIlj.mjs.map → cron-DdEVrQ2Y.mjs.map} +1 -1
  343. package/dist/{dashboard-2JgAMWxK.mjs → dashboard-C-UYpps0.mjs} +1 -1
  344. package/dist/{dashboard-2JgAMWxK.mjs.map → dashboard-C-UYpps0.mjs.map} +1 -1
  345. package/dist/database/instrumentation.d.mts +10 -1
  346. package/dist/database/instrumentation.d.mts.map +1 -1
  347. package/dist/database/instrumentation.mjs +13 -1
  348. package/dist/database/instrumentation.mjs.map +1 -1
  349. package/dist/db/index.d.mts +3 -3
  350. package/dist/db/libsql.d.mts +1 -1
  351. package/dist/db/postgres.d.mts +1 -1
  352. package/dist/db/sqlite.d.mts +1 -1
  353. package/dist/{db-errors-CtzxKBxe.mjs → db-errors-BluWkwGI.mjs} +1 -1
  354. package/dist/{db-errors-CtzxKBxe.mjs.map → db-errors-BluWkwGI.mjs.map} +1 -1
  355. package/dist/{default-xLFNSsZ9.mjs → default-NHGuJzQ3.mjs} +1 -1
  356. package/dist/{default-xLFNSsZ9.mjs.map → default-NHGuJzQ3.mjs.map} +1 -1
  357. package/dist/{device-flow-s6_q3T7A.mjs → device-flow-BQApWgnW.mjs} +4 -4
  358. package/dist/{device-flow-s6_q3T7A.mjs.map → device-flow-BQApWgnW.mjs.map} +1 -1
  359. package/dist/{email-console-DHT2Fbpj.mjs → email-console-BbU3RbWv.mjs} +1 -1
  360. package/dist/{email-console-DHT2Fbpj.mjs.map → email-console-BbU3RbWv.mjs.map} +1 -1
  361. package/dist/{error-RwM4dD35.mjs → error-CNn_w7jf.mjs} +1 -1
  362. package/dist/{error-RwM4dD35.mjs.map → error-CNn_w7jf.mjs.map} +1 -1
  363. package/dist/{escape-bIyGoW5W.mjs → escape-DPgcxcpL.mjs} +1 -1
  364. package/dist/{escape-bIyGoW5W.mjs.map → escape-DPgcxcpL.mjs.map} +1 -1
  365. package/dist/{fts-manager-1RgHmopc.mjs → fts-manager-Cx5z8jdA.mjs} +1 -1
  366. package/dist/{fts-manager-1RgHmopc.mjs.map → fts-manager-Cx5z8jdA.mjs.map} +1 -1
  367. package/dist/{hash-9w3pd3-m.mjs → hash-DlvIFn0b.mjs} +1 -1
  368. package/dist/{hash-9w3pd3-m.mjs.map → hash-DlvIFn0b.mjs.map} +1 -1
  369. package/dist/{import-Dh8bWmyq.mjs → import-KyxT1Mbs.mjs} +3 -3
  370. package/dist/{import-Dh8bWmyq.mjs.map → import-KyxT1Mbs.mjs.map} +1 -1
  371. package/dist/{index-FfiTQJq2.d.mts → index-D2VAiumu.d.mts} +46 -15
  372. package/dist/{index-FfiTQJq2.d.mts.map → index-D2VAiumu.d.mts.map} +1 -1
  373. package/dist/{index-BpYeJO1E.d.mts → index-uT2yR66F.d.mts} +3 -3
  374. package/dist/{index-BpYeJO1E.d.mts.map → index-uT2yR66F.d.mts.map} +1 -1
  375. package/dist/index.d.mts +16 -16
  376. package/dist/index.mjs +48 -46
  377. package/dist/init-lock-DlBHjf9-.mjs +83 -0
  378. package/dist/init-lock-DlBHjf9-.mjs.map +1 -0
  379. package/dist/{load-B84ohfBk.mjs → load-Dq91b_DK.mjs} +1 -1
  380. package/dist/{load-B84ohfBk.mjs.map → load-Dq91b_DK.mjs.map} +1 -1
  381. package/dist/{loader-CpZKpFz0.mjs → loader-BqWjcH3h.mjs} +12 -15
  382. package/dist/loader-BqWjcH3h.mjs.map +1 -0
  383. package/dist/{manifest-schema-Cj-YrzrF.mjs → manifest-schema-DFPeqMAn.mjs} +55 -2
  384. package/dist/manifest-schema-DFPeqMAn.mjs.map +1 -0
  385. package/dist/media/index.d.mts +1 -1
  386. package/dist/media/index.mjs +2 -2
  387. package/dist/media/local-runtime.d.mts +11 -11
  388. package/dist/media/local-runtime.mjs +4 -3
  389. package/dist/media/local-runtime.mjs.map +1 -1
  390. package/dist/{media-allowlist-CMcoYIjQ.mjs → media-allowlist-_A0SuDn4.mjs} +2 -2
  391. package/dist/{media-allowlist-CMcoYIjQ.mjs.map → media-allowlist-_A0SuDn4.mjs.map} +1 -1
  392. package/dist/media-url-CqLd69IO.mjs +26 -0
  393. package/dist/media-url-CqLd69IO.mjs.map +1 -0
  394. package/dist/{menus-Dp9xporj.mjs → menus-Ryk9L7fT.mjs} +10 -37
  395. package/dist/menus-Ryk9L7fT.mjs.map +1 -0
  396. package/dist/{mime-CCEzze7W.mjs → mime-YbtlEtvS.mjs} +1 -1
  397. package/dist/{mime-CCEzze7W.mjs.map → mime-YbtlEtvS.mjs.map} +1 -1
  398. package/dist/{mode-BjlXswIw.mjs → mode-CGXzIbD8.mjs} +1 -1
  399. package/dist/{mode-BjlXswIw.mjs.map → mode-CGXzIbD8.mjs.map} +1 -1
  400. package/dist/{normalize-CK5o04zr.mjs → normalize-DKsg36ty.mjs} +1 -1
  401. package/dist/{normalize-CK5o04zr.mjs.map → normalize-DKsg36ty.mjs.map} +1 -1
  402. package/dist/{oauth-authorization-1aPAYjiC.mjs → oauth-authorization-C2kVyjXI.mjs} +4 -4
  403. package/dist/{oauth-authorization-1aPAYjiC.mjs.map → oauth-authorization-C2kVyjXI.mjs.map} +1 -1
  404. package/dist/{oauth-clients-8mPDStMv.mjs → oauth-clients-BC873NCV.mjs} +1 -1
  405. package/dist/{oauth-clients-8mPDStMv.mjs.map → oauth-clients-BC873NCV.mjs.map} +1 -1
  406. package/dist/{oauth-state-store-BJ7YtrfD.mjs → oauth-state-store-Cd--TUaq.mjs} +1 -1
  407. package/dist/{oauth-state-store-BJ7YtrfD.mjs.map → oauth-state-store-Cd--TUaq.mjs.map} +1 -1
  408. package/dist/{oauth-user-lookup-BdDSDvjF.mjs → oauth-user-lookup-e4wOvDud.mjs} +1 -1
  409. package/dist/{oauth-user-lookup-BdDSDvjF.mjs.map → oauth-user-lookup-e4wOvDud.mjs.map} +1 -1
  410. package/dist/{options-D4MnavW_.d.mts → options-9kLgkE8m.d.mts} +3 -3
  411. package/dist/{options-D4MnavW_.d.mts.map → options-9kLgkE8m.d.mts.map} +1 -1
  412. package/dist/page/index.d.mts +2 -2
  413. package/dist/{parse-CrGndy1A.mjs → parse-DzSrk1t8.mjs} +2 -2
  414. package/dist/{parse-CrGndy1A.mjs.map → parse-DzSrk1t8.mjs.map} +1 -1
  415. package/dist/{passkey-config-BDVM86Tj.mjs → passkey-config-BpjbE_Uv.mjs} +1 -1
  416. package/dist/{passkey-config-BDVM86Tj.mjs.map → passkey-config-BpjbE_Uv.mjs.map} +1 -1
  417. package/dist/{placeholder-BZxr8W1j.mjs → placeholder-2xumZh4g.mjs} +1 -1
  418. package/dist/{placeholder-BZxr8W1j.mjs.map → placeholder-2xumZh4g.mjs.map} +1 -1
  419. package/dist/{placeholder-B9lUUEmj.d.mts → placeholder-BevVKfay.d.mts} +1 -1
  420. package/dist/{placeholder-B9lUUEmj.d.mts.map → placeholder-BevVKfay.d.mts.map} +1 -1
  421. package/dist/plugin-types.d.mts +1 -1
  422. package/dist/plugin-utils.d.mts +9 -9
  423. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  424. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  425. package/dist/{preview-BfuRkVKW.mjs → preview-Dqv2hwXr.mjs} +2 -2
  426. package/dist/{preview-BfuRkVKW.mjs.map → preview-Dqv2hwXr.mjs.map} +1 -1
  427. package/dist/{public-url-egRHCy1m.mjs → public-url-D_zARuvZ.mjs} +1 -1
  428. package/dist/{public-url-egRHCy1m.mjs.map → public-url-D_zARuvZ.mjs.map} +1 -1
  429. package/dist/{query-BFQ029Ts.mjs → query-Crm038Mc.mjs} +21 -11
  430. package/dist/query-Crm038Mc.mjs.map +1 -0
  431. package/dist/{rate-limit-ClFFUga6.mjs → rate-limit-hRTBqmw1.mjs} +2 -2
  432. package/dist/{rate-limit-ClFFUga6.mjs.map → rate-limit-hRTBqmw1.mjs.map} +1 -1
  433. package/dist/{redirect-Cw3JTlmj.mjs → redirect-C-OOkyku.mjs} +1 -1
  434. package/dist/{redirect-Cw3JTlmj.mjs.map → redirect-C-OOkyku.mjs.map} +1 -1
  435. package/dist/{redirects-DEygMrRO.mjs → redirects-6Zg2SoYo.mjs} +11 -10
  436. package/dist/redirects-6Zg2SoYo.mjs.map +1 -0
  437. package/dist/{redirects-OIu6vQ2i.mjs → redirects-CP3TnTLO.mjs} +20 -14
  438. package/dist/redirects-CP3TnTLO.mjs.map +1 -0
  439. package/dist/{registry-brYh-rAT.mjs → registry-diMzD1Wf.mjs} +3 -3
  440. package/dist/{registry-brYh-rAT.mjs.map → registry-diMzD1Wf.mjs.map} +1 -1
  441. package/dist/{request-cache-D32LpnmI.mjs → request-cache-UwmBAiUK.mjs} +1 -1
  442. package/dist/{request-cache-D32LpnmI.mjs.map → request-cache-UwmBAiUK.mjs.map} +1 -1
  443. package/dist/request-context.d.mts +7 -0
  444. package/dist/request-context.d.mts.map +1 -1
  445. package/dist/request-context.mjs +2 -1
  446. package/dist/request-context.mjs.map +1 -1
  447. package/dist/{request-meta-7ByVLxB-.mjs → request-meta-DPechd0W.mjs} +2 -2
  448. package/dist/{request-meta-7ByVLxB-.mjs.map → request-meta-DPechd0W.mjs.map} +1 -1
  449. package/dist/{resolve-BqYMVG0D.mjs → resolve-B3NUUtVY.mjs} +1 -1
  450. package/dist/{resolve-BqYMVG0D.mjs.map → resolve-B3NUUtVY.mjs.map} +1 -1
  451. package/dist/{runner-BcRuXq_h.d.mts → runner-C8vcbvCe.d.mts} +2 -2
  452. package/dist/{runner-BcRuXq_h.d.mts.map → runner-C8vcbvCe.d.mts.map} +1 -1
  453. package/dist/runtime.d.mts +10 -10
  454. package/dist/runtime.mjs +1 -1
  455. package/dist/{schema-CS7Eg5gh.mjs → schema-BDOkd3OU.mjs} +4 -4
  456. package/dist/{schema-CS7Eg5gh.mjs.map → schema-BDOkd3OU.mjs.map} +1 -1
  457. package/dist/{search-o-aQzHI1.mjs → search-Bs_J_EW-.mjs} +3 -3
  458. package/dist/{search-o-aQzHI1.mjs.map → search-Bs_J_EW-.mjs.map} +1 -1
  459. package/dist/{secrets-C_ZtRos3.mjs → secrets-C8xmE6mR.mjs} +21 -11
  460. package/dist/secrets-C8xmE6mR.mjs.map +1 -0
  461. package/dist/{sections-DhsZ0ns9.mjs → sections-P0zuBlyz.mjs} +2 -2
  462. package/dist/{sections-DhsZ0ns9.mjs.map → sections-P0zuBlyz.mjs.map} +1 -1
  463. package/dist/seed/index.d.mts +2 -2
  464. package/dist/seed/index.mjs +14 -13
  465. package/dist/seo/index.d.mts +1 -1
  466. package/dist/seo/index.d.mts.map +1 -1
  467. package/dist/seo/index.mjs +3 -12
  468. package/dist/seo/index.mjs.map +1 -1
  469. package/dist/{seo-DfjLvu8i.mjs → seo-CLhm-Fmb.mjs} +4 -3
  470. package/dist/seo-CLhm-Fmb.mjs.map +1 -0
  471. package/dist/{seo-B5e6y9Wk.mjs → seo-DpNgGQjF.mjs} +1 -1
  472. package/dist/{seo-B5e6y9Wk.mjs.map → seo-DpNgGQjF.mjs.map} +1 -1
  473. package/dist/{service-DAxg8RPR.mjs → service-CDQQnT8W.mjs} +2 -2
  474. package/dist/{service-DAxg8RPR.mjs.map → service-CDQQnT8W.mjs.map} +1 -1
  475. package/dist/{settings-B1p-gPUK.mjs → settings-BjBsmVAo.mjs} +32 -30
  476. package/dist/settings-BjBsmVAo.mjs.map +1 -0
  477. package/dist/{settings-DIsbHTRE.mjs → settings-sO0Fif4p.mjs} +2 -2
  478. package/dist/{settings-DIsbHTRE.mjs.map → settings-sO0Fif4p.mjs.map} +1 -1
  479. package/dist/{setup-complete-Yuv78yua.mjs → setup-complete-CMMr-oZU.mjs} +1 -1
  480. package/dist/{setup-complete-Yuv78yua.mjs.map → setup-complete-CMMr-oZU.mjs.map} +1 -1
  481. package/dist/{setup-nonce-Bm0uKqmf.mjs → setup-nonce-169xl4fV.mjs} +1 -1
  482. package/dist/{setup-nonce-Bm0uKqmf.mjs.map → setup-nonce-169xl4fV.mjs.map} +1 -1
  483. package/dist/single-flight-cache-C0UV1Npg.mjs +104 -0
  484. package/dist/single-flight-cache-C0UV1Npg.mjs.map +1 -0
  485. package/dist/{site-url-mEVmwIFi.mjs → site-url-vtsuOvSD.mjs} +1 -1
  486. package/dist/{site-url-mEVmwIFi.mjs.map → site-url-vtsuOvSD.mjs.map} +1 -1
  487. package/dist/{ssrf-BsVGIE0Z.mjs → ssrf-XO05Voq6.mjs} +1 -1
  488. package/dist/{ssrf-BsVGIE0Z.mjs.map → ssrf-XO05Voq6.mjs.map} +1 -1
  489. package/dist/status-2gZklYuj.mjs +30 -0
  490. package/dist/status-2gZklYuj.mjs.map +1 -0
  491. package/dist/storage/local.d.mts +1 -1
  492. package/dist/storage/local.mjs +2 -2
  493. package/dist/storage/s3.d.mts +1 -1
  494. package/dist/storage/s3.mjs +1 -1
  495. package/dist/{taxonomies-BEW7S5AI.mjs → taxonomies-BBxYA38v.mjs} +49 -12
  496. package/dist/taxonomies-BBxYA38v.mjs.map +1 -0
  497. package/dist/{taxonomies-UusDXv3C.mjs → taxonomies-DuESHWKI.mjs} +2 -2
  498. package/dist/{taxonomies-UusDXv3C.mjs.map → taxonomies-DuESHWKI.mjs.map} +1 -1
  499. package/dist/{tokens-Bx2afeT-.mjs → tokens-DMkVjxrx.mjs} +1 -1
  500. package/dist/{tokens-Bx2afeT-.mjs.map → tokens-DMkVjxrx.mjs.map} +1 -1
  501. package/dist/{transport--Ck3RBin.mjs → transport-1cIrOb1Y.mjs} +1 -1
  502. package/dist/{transport--Ck3RBin.mjs.map → transport-1cIrOb1Y.mjs.map} +1 -1
  503. package/dist/{transport-BwQeeY2p.d.mts → transport-jdvsZEIt.d.mts} +1 -1
  504. package/dist/{transport-BwQeeY2p.d.mts.map → transport-jdvsZEIt.d.mts.map} +1 -1
  505. package/dist/{trusted-proxy-B4AfnoAp.mjs → trusted-proxy-CHp41Fjj.mjs} +1 -1
  506. package/dist/{trusted-proxy-B4AfnoAp.mjs.map → trusted-proxy-CHp41Fjj.mjs.map} +1 -1
  507. package/dist/{types-DWnN7weG.d.mts → types-BFgYtuKd.d.mts} +1 -1
  508. package/dist/{types-DWnN7weG.d.mts.map → types-BFgYtuKd.d.mts.map} +1 -1
  509. package/dist/{types-DZk_y-MU.mjs → types-BIduXPJk.mjs} +1 -1
  510. package/dist/types-BIduXPJk.mjs.map +1 -0
  511. package/dist/{types-WVmpZBJV.d.mts → types-BTnnBYVX.d.mts} +2 -2
  512. package/dist/{types-WVmpZBJV.d.mts.map → types-BTnnBYVX.d.mts.map} +1 -1
  513. package/dist/types-BoRm8-pp.mjs +3 -0
  514. package/dist/{types-DbCWhHet.d.mts → types-Bzfk2yC8.d.mts} +2 -2
  515. package/dist/types-Bzfk2yC8.d.mts.map +1 -0
  516. package/dist/{types-Qa7-HJJC.d.mts → types-CkEuk-Zr.d.mts} +1 -1
  517. package/dist/{types-Qa7-HJJC.d.mts.map → types-CkEuk-Zr.d.mts.map} +1 -1
  518. package/dist/{types-DMwSpvcw.d.mts → types-DO7whVYU.d.mts} +9 -3
  519. package/dist/{types-DMwSpvcw.d.mts.map → types-DO7whVYU.d.mts.map} +1 -1
  520. package/dist/{types-DX6v9KzJ.d.mts → types-DdkL6fyv.d.mts} +1 -1
  521. package/dist/{types-DX6v9KzJ.d.mts.map → types-DdkL6fyv.d.mts.map} +1 -1
  522. package/dist/{types-DpFmlNyB.mjs → types-DejCHqWT.mjs} +1 -1
  523. package/dist/{types-DpFmlNyB.mjs.map → types-DejCHqWT.mjs.map} +1 -1
  524. package/dist/{types-OT_Es5mp.d.mts → types-Del0VMij.d.mts} +1 -1
  525. package/dist/{types-OT_Es5mp.d.mts.map → types-Del0VMij.d.mts.map} +1 -1
  526. package/dist/{types-kwqCOUxj.d.mts → types-u_XxjbS8.d.mts} +1 -1
  527. package/dist/{types-kwqCOUxj.d.mts.map → types-u_XxjbS8.d.mts.map} +1 -1
  528. package/dist/{utils-C4Ih4DML.mjs → utils-C4M981Br.mjs} +1 -1
  529. package/dist/{utils-C4Ih4DML.mjs.map → utils-C4M981Br.mjs.map} +1 -1
  530. package/dist/{validate-ZP9Dvg0P.mjs → validate-DGhQPXzI.mjs} +2 -2
  531. package/dist/{validate-ZP9Dvg0P.mjs.map → validate-DGhQPXzI.mjs.map} +1 -1
  532. package/dist/{validate-BPAHUSge.d.mts → validate-cJOiOvT2.d.mts} +5 -5
  533. package/dist/{validate-BPAHUSge.d.mts.map → validate-cJOiOvT2.d.mts.map} +1 -1
  534. package/dist/{validation-CE5i4q0c.mjs → validation-DVHjPM1M.mjs} +5 -5
  535. package/dist/{validation-CE5i4q0c.mjs.map → validation-DVHjPM1M.mjs.map} +1 -1
  536. package/dist/version-BOjj_cfz.mjs +7 -0
  537. package/dist/{version-Dw0JXu45.mjs.map → version-BOjj_cfz.mjs.map} +1 -1
  538. package/dist/{widgets-ClEnYQCH.mjs → widgets-Ci6hLwfO.mjs} +47 -44
  539. package/dist/widgets-Ci6hLwfO.mjs.map +1 -0
  540. package/dist/{zod-generator-Djo_VHCt.mjs → zod-generator-CarzgPAu.mjs} +2 -2
  541. package/dist/{zod-generator-Djo_VHCt.mjs.map → zod-generator-CarzgPAu.mjs.map} +1 -1
  542. package/package.json +10 -10
  543. package/src/api/handlers/marketplace.ts +2 -5
  544. package/src/api/handlers/redirects.ts +24 -13
  545. package/src/api/handlers/registry.ts +70 -0
  546. package/src/api/handlers/seo.ts +9 -1
  547. package/src/api/schemas/redirects.ts +11 -4
  548. package/src/api/schemas/schema.ts +13 -1
  549. package/src/astro/integration/index.ts +44 -8
  550. package/src/astro/integration/routes.ts +46 -9
  551. package/src/astro/middleware/redirect.ts +12 -0
  552. package/src/astro/middleware.ts +20 -6
  553. package/src/astro/routes/api/schema/index.ts +7 -15
  554. package/src/astro/routes/sitemap-[collection].xml.ts +13 -2
  555. package/src/bylines/field-defs-cache.ts +70 -20
  556. package/src/cli/commands/bundle-utils.ts +2 -0
  557. package/src/cli/commands/doctor.ts +1 -1
  558. package/src/cli/commands/secrets.ts +2 -2
  559. package/src/config/secrets.ts +28 -14
  560. package/src/database/instrumentation.ts +13 -0
  561. package/src/emdash-runtime.ts +31 -25
  562. package/src/loader.ts +24 -15
  563. package/src/plugins/manifest-schema.ts +75 -0
  564. package/src/plugins/marketplace.ts +2 -5
  565. package/src/plugins/types.ts +12 -0
  566. package/src/query.ts +13 -2
  567. package/src/redirects/status.ts +27 -0
  568. package/src/request-context.ts +8 -0
  569. package/src/schema/types.ts +11 -1
  570. package/src/seo/index.ts +2 -28
  571. package/src/seo/media-url.ts +32 -0
  572. package/src/settings/index.ts +32 -40
  573. package/src/taxonomies/index.ts +78 -12
  574. package/src/utils/single-flight-cache.ts +194 -0
  575. package/src/widgets/index.ts +57 -54
  576. package/dist/api-BZ6bhjYs.mjs.map +0 -1
  577. package/dist/byline-DUx48sJp.mjs.map +0 -1
  578. package/dist/byline-fields-DYXKDuNX.d.mts.map +0 -1
  579. package/dist/loader-CpZKpFz0.mjs.map +0 -1
  580. package/dist/manifest-schema-Cj-YrzrF.mjs.map +0 -1
  581. package/dist/menus-Dp9xporj.mjs.map +0 -1
  582. package/dist/query-BFQ029Ts.mjs.map +0 -1
  583. package/dist/redirects-DEygMrRO.mjs.map +0 -1
  584. package/dist/redirects-OIu6vQ2i.mjs.map +0 -1
  585. package/dist/secrets-C_ZtRos3.mjs.map +0 -1
  586. package/dist/seo-DfjLvu8i.mjs.map +0 -1
  587. package/dist/settings-B1p-gPUK.mjs.map +0 -1
  588. package/dist/taxonomies-BEW7S5AI.mjs.map +0 -1
  589. package/dist/types-Cj2S6FuC.mjs +0 -3
  590. package/dist/types-DZk_y-MU.mjs.map +0 -1
  591. package/dist/types-DbCWhHet.d.mts.map +0 -1
  592. package/dist/version-Dw0JXu45.mjs +0 -7
  593. package/dist/widgets-ClEnYQCH.mjs.map +0 -1
  594. /package/dist/{api-tokens-B6VgoE6M.mjs → api-tokens-C7ywRx7l.mjs} +0 -0
  595. /package/dist/{ssrf-BvgVcfNQ.mjs → ssrf-CRZGzjdL.mjs} +0 -0
@@ -23,6 +23,7 @@ import {
23
23
  matchCachedPatterns,
24
24
  setCachedRedirects,
25
25
  } from "../../redirects/cache.js";
26
+ import { isTerminalStatus } from "../../redirects/status.js";
26
27
 
27
28
  /** Paths that should never be intercepted by redirects */
28
29
  const SKIP_PREFIXES = ["/_emdash", "/_image"];
@@ -80,6 +81,12 @@ export const onRequest = defineMiddleware(async (context, next) => {
80
81
  exact = cached.exact.get(alt);
81
82
  }
82
83
  if (exact) {
84
+ // Terminal statuses (410 Gone / 451): serve the status directly,
85
+ // with no Location header.
86
+ if (isTerminalStatus(exact.type)) {
87
+ repo.recordHit(exact.id).catch(() => {});
88
+ return new Response(null, { status: exact.type });
89
+ }
83
90
  const dest = exact.destination;
84
91
  if (dest.startsWith("//") || dest.startsWith("/\\")) return next();
85
92
  repo.recordHit(exact.id).catch(() => {});
@@ -91,6 +98,11 @@ export const onRequest = defineMiddleware(async (context, next) => {
91
98
  const patternMatch = matchCachedPatterns(cached.patterns, pathname);
92
99
  if (patternMatch) {
93
100
  const { redirect, destination } = patternMatch;
101
+ // Terminal statuses (410 Gone / 451): serve the status directly.
102
+ if (isTerminalStatus(redirect.type)) {
103
+ repo.recordHit(redirect.id).catch(() => {});
104
+ return new Response(null, { status: redirect.type });
105
+ }
94
106
  if (destination.startsWith("//") || destination.startsWith("/\\")) return next();
95
107
  repo.recordHit(redirect.id).catch(() => {});
96
108
  const code = isRedirectCode(redirect.type) ? redirect.type : 301;
@@ -333,6 +333,9 @@ function pushMetricsTimings(
333
333
  timings.push({ name: "db.last", dur: metrics.dbLastOffset, desc: "Last query at" });
334
334
  }
335
335
  }
336
+ if (metrics.rpcCount > 0) {
337
+ timings.push({ name: "rpc.count", dur: metrics.rpcCount, desc: "DB round trips" });
338
+ }
336
339
  if (metrics.cacheHits + metrics.cacheMisses > 0) {
337
340
  timings.push({ name: "cache.hit", dur: metrics.cacheHits, desc: "Cache hits" });
338
341
  timings.push({ name: "cache.miss", dur: metrics.cacheMisses, desc: "Cache misses" });
@@ -510,9 +513,15 @@ export const onRequest = defineMiddleware(async (context, next) => {
510
513
  ? { ...parent, db: anonScoped.db }
511
514
  : { editMode: false, db: anonScoped.db, metrics };
512
515
  return runWithContext(ctx, async () => {
513
- const response = await runAnon();
514
- anonScoped.commit();
515
- return response;
516
+ // commit() in finally: the write reached the primary independently
517
+ // of render, so the bookmark cookie must be persisted even if
518
+ // render throws -- otherwise a write-then-failed-render leaves the
519
+ // next request able to read pre-write state off a lagging replica.
520
+ try {
521
+ return await runAnon();
522
+ } finally {
523
+ anonScoped.commit();
524
+ }
516
525
  });
517
526
  }
518
527
  return runAnon();
@@ -681,9 +690,14 @@ export const onRequest = defineMiddleware(async (context, next) => {
681
690
  ? { ...parent, db: scoped.db }
682
691
  : { editMode: false, db: scoped.db, metrics };
683
692
  return runWithContext(ctx, async () => {
684
- const response = await renderAndFinalize();
685
- scoped.commit();
686
- return response;
693
+ // commit() in finally: persist the bookmark cookie even if render
694
+ // throws -- the write already reached the primary, so a failed
695
+ // render must not strand the next request on a stale replica read.
696
+ try {
697
+ return await renderAndFinalize();
698
+ } finally {
699
+ scoped.commit();
700
+ }
687
701
  });
688
702
  }
689
703
 
@@ -13,7 +13,7 @@ import type { APIRoute } from "astro";
13
13
  import { hashString } from "emdash";
14
14
 
15
15
  import { requirePerm } from "#api/authorize.js";
16
- import { handleError, requireDb } from "#api/error.js";
16
+ import { apiSuccess, handleError, requireDb } from "#api/error.js";
17
17
  import { SchemaRegistry } from "#schema/registry.js";
18
18
  import { generateTypeScript } from "#schema/zod-generator.js";
19
19
 
@@ -89,20 +89,12 @@ import type { PortableTextBlock } from "emdash";
89
89
 
90
90
  const version = await hashString(JSON.stringify(schemaExport));
91
91
 
92
- return new Response(
93
- JSON.stringify({
94
- ...schemaExport,
95
- version,
96
- }),
97
- {
98
- status: 200,
99
- headers: {
100
- "Content-Type": "application/json",
101
- "Cache-Control": "private, no-store",
102
- "X-Schema-Version": version,
103
- },
104
- },
105
- );
92
+ const response = apiSuccess({
93
+ ...schemaExport,
94
+ version,
95
+ });
96
+ response.headers.set("X-Schema-Version", version);
97
+ return response;
106
98
  } catch (error) {
107
99
  return handleError(error, "Schema export failed", "SCHEMA_EXPORT_ERROR");
108
100
  }
@@ -23,6 +23,7 @@ import { getSiteSettingsWithDb } from "#settings/index.js";
23
23
 
24
24
  import { getI18nConfig, isI18nEnabled } from "../../i18n/config.js";
25
25
  import { interpolateUrlPattern, localizePath } from "../../i18n/resolve.js";
26
+ import { buildSeoImageUrl } from "../../seo/media-url.js";
26
27
 
27
28
  export const prerender = false;
28
29
 
@@ -112,8 +113,8 @@ export const GET: APIRoute = async ({ params, locals, url }) => {
112
113
  const lines: string[] = ['<?xml version="1.0" encoding="UTF-8"?>'];
113
114
  lines.push(
114
115
  useXhtml
115
- ? '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">'
116
- : '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
116
+ ? '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">'
117
+ : '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">',
117
118
  );
118
119
 
119
120
  const writeUrl = async (entry: Entry, siblings: Entry[] | null) => {
@@ -127,6 +128,16 @@ export const GET: APIRoute = async ({ params, locals, url }) => {
127
128
  lines.push(` <loc>${escapeXml(loc)}</loc>`);
128
129
  lines.push(` <lastmod>${escapeXml(entry.updatedAt)}</lastmod>`);
129
130
 
131
+ // Google image sitemap extension: advertise the entry's SEO
132
+ // image (the same "preferred image" used for og:image) so it
133
+ // can be discovered and indexed for Google Images.
134
+ if (entry.image) {
135
+ const imageLoc = buildSeoImageUrl(entry.image, siteUrl);
136
+ lines.push(" <image:image>");
137
+ lines.push(` <image:loc>${escapeXml(imageLoc)}</image:loc>`);
138
+ lines.push(" </image:image>");
139
+ }
140
+
130
141
  if (useXhtml && siblings && siblings.length > 1) {
131
142
  // Emit one xhtml:link per sibling (including self -- Google
132
143
  // recommends including the page's own hreflang annotation).
@@ -8,8 +8,12 @@
8
8
  * but are read on every byline hydration (admin pages, content rendering,
9
9
  * API responses). Caching at the isolate level drops the SELECT-from-
10
10
  * `_emdash_byline_fields` from once-per-hydration to once-per-isolate-
11
- * after-bump. The cache holds a Promise (not the resolved value) so
12
- * concurrent cold-isolate readers share the in-flight query.
11
+ * after-bump. The cache holds the resolved *value* behind a reclaimable
12
+ * single-flight lock (see `utils/single-flight-cache.ts`), never an
13
+ * in-flight promise: concurrent cold-isolate readers coalesce onto one
14
+ * query by polling the published value, so a reader whose request is
15
+ * cancelled mid-query can never strand later byline hydrations on the
16
+ * isolate (the workerd never-settling-promise hazard that produced 524s).
13
17
  *
14
18
  * Stored on globalThis under `Symbol.for("emdash:byline-field-defs")` so
15
19
  * Vite SSR chunk duplication can't produce two independent caches (same
@@ -50,17 +54,23 @@
50
54
 
51
55
  import type { Kysely } from "kysely";
52
56
 
57
+ import { after } from "../after.js";
53
58
  import type { Database } from "../database/types.js";
54
59
  import { requestCached } from "../request-cache.js";
55
60
  import { getRequestContext } from "../request-context.js";
56
61
  import { BylineSchemaRegistry } from "../schema/byline-registry.js";
57
62
  import type { BylineFieldDefinition } from "../schema/types.js";
63
+ import { createInitLock, type InitLock, initWithLock } from "../utils/init-lock.js";
58
64
 
59
65
  interface FieldDefsHolder {
60
- /** In-flight or resolved defs promise for the cached version. Null until first read. */
61
- cached: Promise<BylineFieldDefinition[]> | null;
62
- /** Persisted-version value that `cached` was fetched against. */
66
+ /** Last resolved defs, valid only when `hasValue` is true. */
67
+ value: BylineFieldDefinition[] | null;
68
+ /** Presence flag, separate from `value` so an empty-array result still caches. */
69
+ hasValue: boolean;
70
+ /** Persisted-version value that `value` was fetched against. */
63
71
  cachedVersion: number;
72
+ /** Reclaimable single-flight lock so a cancelled owner can't wedge readers. */
73
+ lock: InitLock;
64
74
  }
65
75
 
66
76
  const HOLDER_KEY = Symbol.for("emdash:byline-field-defs");
@@ -69,7 +79,12 @@ const holder: FieldDefsHolder =
69
79
  // eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see request-cache.ts)
70
80
  (g[HOLDER_KEY] as FieldDefsHolder | undefined) ??
71
81
  (() => {
72
- const h: FieldDefsHolder = { cached: null, cachedVersion: -1 };
82
+ const h: FieldDefsHolder = {
83
+ value: null,
84
+ hasValue: false,
85
+ cachedVersion: -1,
86
+ lock: createInitLock(),
87
+ };
73
88
  g[HOLDER_KEY] = h;
74
89
  return h;
75
90
  })();
@@ -77,6 +92,16 @@ const holder: FieldDefsHolder =
77
92
  const REQUEST_CACHE_KEY_VERSION = "byline-fields-version";
78
93
  const REQUEST_CACHE_KEY_DEFS_PREFIX = "byline-field-defs:";
79
94
 
95
+ /**
96
+ * Reclaim window for the single-flight lock: if an owner holds it past
97
+ * this without publishing (e.g. its request was cancelled and the
98
+ * anchored fetch hasn't completed yet), the next reader reclaims and
99
+ * refetches. `listFields` is a single fast SELECT, so this only needs to
100
+ * cover a genuinely slow/stranded query. Mutable solely so tests can
101
+ * shorten it; production never changes it.
102
+ */
103
+ let reclaimDeadlineMs = 10_000;
104
+
80
105
  /**
81
106
  * Read the persisted `options.byline_fields_version` counter. Cached for
82
107
  * the duration of the current request via `requestCached`. Returns `0`
@@ -107,19 +132,29 @@ export async function getBylineFieldDefs(db: Kysely<Database>): Promise<BylineFi
107
132
  if (isolated || dirty) {
108
133
  return new BylineSchemaRegistry(db).listFields();
109
134
  }
110
- if (holder.cached !== null && holder.cachedVersion === version) {
111
- return holder.cached;
112
- }
113
- const defs = new BylineSchemaRegistry(db).listFields().catch((error) => {
114
- if (holder.cached === defs) {
115
- holder.cached = null;
116
- holder.cachedVersion = -1;
117
- }
118
- throw error;
119
- });
120
- holder.cached = defs;
121
- holder.cachedVersion = version;
122
- return defs;
135
+ // Per-isolate single-flight cache keyed on the persisted version.
136
+ // Coalesce concurrent cold readers via the lock and read the
137
+ // published value; never await another request's in-flight promise
138
+ // (a cancelled owner would otherwise strand every later byline
139
+ // hydration on the isolate). The fetch is anchored so a cancelled
140
+ // originator still drives it to completion and populates the cache.
141
+ return initWithLock<BylineFieldDefinition[]>(
142
+ holder.lock,
143
+ () => (holder.hasValue && holder.cachedVersion === version ? holder.value : null),
144
+ (isCurrentClaim) =>
145
+ (async () => {
146
+ const defs = await new BylineSchemaRegistry(db).listFields();
147
+ // Publish only while still the current claim, and never
148
+ // regress over a newer version a concurrent reader stored.
149
+ if (isCurrentClaim() && version >= holder.cachedVersion) {
150
+ holder.value = defs;
151
+ holder.hasValue = true;
152
+ holder.cachedVersion = version;
153
+ }
154
+ return defs;
155
+ })(),
156
+ { deadlineMs: reclaimDeadlineMs, anchor: (promise) => after(() => promise) },
157
+ );
123
158
  });
124
159
  }
125
160
 
@@ -133,6 +168,21 @@ export async function getBylineFieldDefs(db: Kysely<Database>): Promise<BylineFi
133
168
  * coordination that lets other isolates see the change.
134
169
  */
135
170
  export function resetBylineFieldDefsCacheForTests(): void {
136
- holder.cached = null;
171
+ holder.value = null;
172
+ holder.hasValue = false;
137
173
  holder.cachedVersion = -1;
174
+ holder.lock.ownerStartedAt = null;
175
+ holder.lock.generation = 0;
176
+ reclaimDeadlineMs = 10_000;
177
+ }
178
+
179
+ /**
180
+ * Test-only: shorten the single-flight reclaim window so a "stranded
181
+ * owner" scenario can be exercised without waiting out the production
182
+ * deadline. Reset by `resetBylineFieldDefsCacheForTests`.
183
+ *
184
+ * @internal
185
+ */
186
+ export function setBylineFieldDefsReclaimDeadlineForTests(ms: number): void {
187
+ reclaimDeadlineMs = ms;
138
188
  }
@@ -13,6 +13,7 @@ import { pipeline } from "node:stream/promises";
13
13
  import { imageSize } from "image-size";
14
14
  import { packTar } from "modern-tar/fs";
15
15
 
16
+ import { capabilitiesToDeclaredAccess } from "../../plugins/types.js";
16
17
  import type {
17
18
  PluginManifest,
18
19
  ResolvedPlugin,
@@ -151,6 +152,7 @@ export function extractManifest(plugin: ResolvedPlugin): PluginManifest {
151
152
  return {
152
153
  id: plugin.id,
153
154
  version: plugin.version,
155
+ declaredAccess: capabilitiesToDeclaredAccess(plugin.capabilities, plugin.allowedHosts),
154
156
  capabilities: plugin.capabilities,
155
157
  allowedHosts: plugin.allowedHosts,
156
158
  storage: plugin.storage,
@@ -124,7 +124,7 @@ async function checkDatabase(dbPath: string): Promise<CheckResult[]> {
124
124
  try {
125
125
  const usersResult = await sql<{
126
126
  count: number;
127
- }>`SELECT COUNT(id) as count FROM _emdash_users`.execute(db);
127
+ }>`SELECT COUNT(id) as count FROM users`.execute(db);
128
128
  const count = usersResult.rows[0]?.count ?? 0;
129
129
  results.push({
130
130
  name: "users",
@@ -4,7 +4,7 @@
4
4
  * Pure (no-DB) commands for working with EmDash secrets:
5
5
  *
6
6
  * - `emdash secrets generate` — emits a fresh `EMDASH_ENCRYPTION_KEY`.
7
- * Optionally writes it to `.dev.vars` (Workers) or `.env` (Node).
7
+ * Optionally writes it to a local-secrets file (`.env`).
8
8
  * - `emdash secrets fingerprint <key>` — prints the kid for a key,
9
9
  * useful in CI for verifying what's been deployed without exposing
10
10
  * the raw value.
@@ -87,7 +87,7 @@ const generateCommand = defineCommand({
87
87
  write: {
88
88
  type: "string",
89
89
  description:
90
- "Optional path to write the key to (e.g. .dev.vars or .env). " +
90
+ "Optional path to write the key to (e.g. .env). " +
91
91
  "Won't overwrite an existing entry without --force.",
92
92
  },
93
93
  force: {
@@ -31,9 +31,15 @@ import { sha256 } from "@oslojs/crypto/sha2";
31
31
  import { encodeHexLowerCase } from "@oslojs/encoding";
32
32
  import type { Kysely } from "kysely";
33
33
 
34
+ import { after } from "../after.js";
34
35
  import { OptionsRepository } from "../database/repositories/options.js";
35
36
  import type { Database } from "../database/types.js";
36
37
  import { decodeBase64url, encodeBase64url } from "../utils/base64.js";
38
+ import {
39
+ createSingleFlightCache,
40
+ type SingleFlightCache,
41
+ singleFlightCached,
42
+ } from "../utils/single-flight-cache.js";
37
43
 
38
44
  /** v1 encryption key prefix. Bumping requires a separate KDF version. */
39
45
  export const ENCRYPTION_KEY_PREFIX = "emdash_enc_v1_";
@@ -370,17 +376,23 @@ export async function validateEncryptionKeyAtStartup(env?: SecretsEnv): Promise<
370
376
  *
371
377
  * Lives on `globalThis` so module-duplication during SSR bundling can't
372
378
  * fragment the cache. See `request-context.ts` for the same pattern.
379
+ *
380
+ * Each db gets its own poison-immune single-flight cache (see
381
+ * `utils/single-flight-cache.ts`): the resolved *value* is cached, never an
382
+ * in-flight promise, so a request cancelled mid-resolve can't strand later
383
+ * preview/comment requests on the isolate.
373
384
  */
374
385
  // Versioned to prevent cache fragmentation if `ResolvedSecrets`'s shape
375
386
  // ever changes. Bump the suffix on incompatible changes so a co-resident
376
- // older build doesn't read a newer-shape value.
377
- const SECRETS_CACHE_KEY = Symbol.for("@emdash-cms/core/secrets-cache@1");
387
+ // older build doesn't read a newer-shape value. Bumped to @2 when the cached
388
+ // value changed from a bare promise to a single-flight cache.
389
+ const SECRETS_CACHE_KEY = Symbol.for("@emdash-cms/core/secrets-cache@2");
378
390
 
379
391
  interface SecretsCacheHolder {
380
- cache: WeakMap<Kysely<Database>, Promise<ResolvedSecrets>>;
392
+ cache: WeakMap<Kysely<Database>, SingleFlightCache<ResolvedSecrets>>;
381
393
  }
382
394
 
383
- function getSecretsCache(): WeakMap<Kysely<Database>, Promise<ResolvedSecrets>> {
395
+ function getSecretsCache(): WeakMap<Kysely<Database>, SingleFlightCache<ResolvedSecrets>> {
384
396
  // eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern
385
397
  const holder = globalThis as Record<symbol, SecretsCacheHolder | undefined>;
386
398
  let entry = holder[SECRETS_CACHE_KEY];
@@ -397,19 +409,21 @@ function getSecretsCache(): WeakMap<Kysely<Database>, Promise<ResolvedSecrets>>
397
409
  * env / re-query options on every request.
398
410
  *
399
411
  * The cache is keyed by `Kysely` instance, so playground / per-DO / per-test
400
- * databases each get their own resolution.
412
+ * databases each get their own resolution. Concurrent cold callers coalesce
413
+ * onto one resolution via the single-flight lock; a failed resolution
414
+ * propagates to the caller and releases the lock so the next caller retries.
401
415
  */
402
416
  export function resolveSecretsCached(db: Kysely<Database>): Promise<ResolvedSecrets> {
403
- const cache = getSecretsCache();
404
- const cached = cache.get(db);
405
- if (cached) return cached;
406
- const promise = resolveSecrets({ db }).catch((error) => {
407
- // Don't poison the cache on transient failure; next caller retries.
408
- cache.delete(db);
409
- throw error;
417
+ const caches = getSecretsCache();
418
+ let cache = caches.get(db);
419
+ if (!cache) {
420
+ cache = createSingleFlightCache<ResolvedSecrets>();
421
+ caches.set(db, cache);
422
+ }
423
+ return singleFlightCached(cache, () => resolveSecrets({ db }), {
424
+ anchor: (promise) => after(() => promise),
425
+ ownerTimeoutMs: 30_000,
410
426
  });
411
- cache.set(db, promise);
412
- return promise;
413
427
  }
414
428
 
415
429
  /**
@@ -110,3 +110,16 @@ function kyselyLog(event: LogEvent): void {
110
110
  export function kyselyLogOption(): Logger {
111
111
  return kyselyLog;
112
112
  }
113
+
114
+ /**
115
+ * Record physical database round trips for the current request.
116
+ *
117
+ * Called by backends that batch (the DO SQL driver coalesces same-turn SELECTs
118
+ * into one RPC), so we can see round-trip count separately from logical query
119
+ * count (`dbCount`, bumped by the Kysely log hook). No-op outside a request or
120
+ * when metrics aren't attached (e.g. migrations on the singleton).
121
+ */
122
+ export function recordRpc(count = 1): void {
123
+ const ctx = getRequestContext();
124
+ if (ctx?.metrics) ctx.metrics.rpcCount += count;
125
+ }
@@ -45,6 +45,7 @@ import type {
45
45
  import type { FieldType } from "./schema/types.js";
46
46
  import { hashString } from "./utils/hash.js";
47
47
  import { createInitLock, type InitLock, initWithLock } from "./utils/init-lock.js";
48
+ import { createSingleFlightCache, singleFlightCached } from "./utils/single-flight-cache.js";
48
49
  import { COMMIT, VERSION } from "./version.js";
49
50
 
50
51
  const LEADING_SLASH_PATTERN = /^\//;
@@ -417,12 +418,12 @@ export class EmDashRuntime {
417
418
  private pluginStates: Map<string, string>;
418
419
 
419
420
  /**
420
- * Set to true after FTS indexes have been verified for this worker
421
- * lifetime so we don't re-scan on every admin request. See
422
- * ensureSearchHealthy().
421
+ * Isolate-lifetime guard so FTS indexes are verified at most once per
422
+ * worker rather than on every admin request. See ensureSearchHealthy().
423
+ * Uses the poison-immune single-flight cache (never a shared awaitable
424
+ * promise) so a cancelled first caller can't wedge later ones.
423
425
  */
424
- private _searchHealthChecked = false;
425
- private _searchHealthPromise: Promise<void> | null = null;
426
+ private readonly _searchHealthCache = createSingleFlightCache<void>();
426
427
 
427
428
  /** Current hook pipeline. Use the `hooks` getter for external access. */
428
429
  get hooks(): HookPipeline {
@@ -2228,27 +2229,32 @@ export class EmDashRuntime {
2228
2229
  * defend against FTS not existing yet (pre-setup).
2229
2230
  */
2230
2231
  async ensureSearchHealthy(): Promise<void> {
2231
- if (this._searchHealthChecked) return;
2232
- if (this._searchHealthPromise) return this._searchHealthPromise;
2233
- if (!isSqlite(this._db)) {
2234
- this._searchHealthChecked = true;
2235
- return;
2232
+ // Non-SQLite has no FTS to verify; the check is a cheap synchronous
2233
+ // branch, no need to cache it.
2234
+ if (!isSqlite(this._db)) return;
2235
+ try {
2236
+ await singleFlightCached(
2237
+ this._searchHealthCache,
2238
+ async () => {
2239
+ try {
2240
+ const ftsManager = new FTSManager(this._db);
2241
+ const repaired = await ftsManager.verifyAndRepairAll();
2242
+ if (repaired > 0) {
2243
+ console.log(`Repaired ${repaired} corrupted FTS index(es)`);
2244
+ }
2245
+ } catch {
2246
+ // FTS tables may not exist yet (pre-setup). Non-fatal — cache
2247
+ // the "checked" state regardless so we don't re-scan.
2248
+ }
2249
+ },
2250
+ { anchor: (promise) => after(() => promise), ownerTimeoutMs: 30_000 },
2251
+ );
2252
+ } catch {
2253
+ // This check is best-effort and must never fail the calling request.
2254
+ // The inner body already swallows verify errors; this guards the
2255
+ // outer failure modes (owner timeout, waiter give-up) so a slow FTS
2256
+ // scan degrades to "unverified", not a 500 on admin/search routes.
2236
2257
  }
2237
- this._searchHealthPromise = (async () => {
2238
- try {
2239
- const ftsManager = new FTSManager(this._db);
2240
- const repaired = await ftsManager.verifyAndRepairAll();
2241
- if (repaired > 0) {
2242
- console.log(`Repaired ${repaired} corrupted FTS index(es)`);
2243
- }
2244
- } catch {
2245
- // FTS tables may not exist yet (pre-setup). Non-fatal.
2246
- } finally {
2247
- this._searchHealthChecked = true;
2248
- this._searchHealthPromise = null;
2249
- }
2250
- })();
2251
- return this._searchHealthPromise;
2252
2258
  }
2253
2259
 
2254
2260
  // =========================================================================
package/src/loader.ts CHANGED
@@ -680,7 +680,12 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
680
680
 
681
681
  // Separate taxonomy / byline filters from field filters
682
682
  let result: { rows: Record<string, unknown>[] };
683
- let taxonomyFilter: { name: string; slugs: string[] } | null = null;
683
+ // Taxonomy filters AND together: each entry constrains the base
684
+ // row to match at least one of its slugs *within that taxonomy*.
685
+ // Term slugs are unique only within a taxonomy, so every filter
686
+ // keeps its own `name` and emits its own `EXISTS` clause rather
687
+ // than pooling slugs into one `IN`.
688
+ const taxonomyFilters: { name: string; slugs: string[] }[] = [];
684
689
  // A byline filter matches entries credited to any of the given
685
690
  // byline translation groups via the `_emdash_content_bylines`
686
691
  // junction table. `null` means no byline filter; an empty
@@ -710,14 +715,8 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
710
715
  );
711
716
  continue;
712
717
  }
713
- if (taxonomyFilter) {
714
- console.warn(
715
- `[emdash] where filter: only one taxonomy is supported per query, "${key}" ignored`,
716
- );
717
- continue;
718
- }
719
718
  const slugs = Array.isArray(value) ? value : [value];
720
- taxonomyFilter = { name: key, slugs };
719
+ taxonomyFilters.push({ name: key, slugs });
721
720
  } else {
722
721
  fieldFilters[key] = value;
723
722
  }
@@ -729,7 +728,7 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
729
728
  // SQL on both dialects).
730
729
  if (
731
730
  (bylineFilter && bylineFilter.groups.length === 0) ||
732
- (taxonomyFilter && taxonomyFilter.slugs.length === 0)
731
+ taxonomyFilters.some((f) => f.slugs.length === 0)
733
732
  ) {
734
733
  return { entries: [], cacheHint: { tags: [type] } };
735
734
  }
@@ -753,16 +752,26 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
753
752
  const fieldCondsSQL =
754
753
  fieldConds.length > 0 ? sql`${sql.join(fieldConds, sql` AND `)}` : null;
755
754
 
756
- const taxonomyCond = taxonomyFilter
757
- ? sql`AND EXISTS (
755
+ // One `EXISTS` per taxonomy, AND'd together: an entry must be
756
+ // tagged with a matching term in *every* requested taxonomy.
757
+ // Each clause pins its own `t.name`, so slugs never pool
758
+ // across taxonomies (they're only unique within one).
759
+ const taxonomyCond =
760
+ taxonomyFilters.length > 0
761
+ ? sql`${sql.join(
762
+ taxonomyFilters.map(
763
+ (f) => sql`AND EXISTS (
758
764
  SELECT 1 FROM content_taxonomies ct
759
765
  INNER JOIN taxonomies t ON t.id = ct.taxonomy_id
760
766
  WHERE ct.collection = ${type}
761
767
  AND ct.entry_id = ${sql.ref(tableName)}.id
762
- AND t.name = ${taxonomyFilter.name}
763
- AND t.slug IN (${sql.join(taxonomyFilter.slugs.map((s) => sql`${s}`))})
764
- )`
765
- : sql``;
768
+ AND t.name = ${f.name}
769
+ AND t.slug IN (${sql.join(f.slugs.map((s) => sql`${s}`))})
770
+ )`,
771
+ ),
772
+ sql` `,
773
+ )}`
774
+ : sql``;
766
775
 
767
776
  // `_emdash_content_bylines.byline_id` stores the byline's
768
777
  // translation_group (migration 040), so a credit spans every