emdash 0.17.2 → 0.18.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 (289) hide show
  1. package/dist/api/route-utils.mjs +10 -10
  2. package/dist/api/schemas/index.d.mts +1 -1
  3. package/dist/{api-B7GATEYo.mjs → api-Cs7DAACP.mjs} +12 -12
  4. package/dist/{api-B7GATEYo.mjs.map → api-Cs7DAACP.mjs.map} +1 -1
  5. package/dist/{apply-BrVqULFe.mjs → apply-BWMV4Zmw.mjs} +16 -16
  6. package/dist/{apply-BrVqULFe.mjs.map → apply-BWMV4Zmw.mjs.map} +1 -1
  7. package/dist/astro/index.d.mts +2 -2
  8. package/dist/astro/index.mjs +1 -1
  9. package/dist/astro/middleware/auth.d.mts +2 -2
  10. package/dist/astro/middleware/auth.mjs +2 -2
  11. package/dist/astro/middleware/redirect.mjs +4 -4
  12. package/dist/astro/middleware.d.mts.map +1 -1
  13. package/dist/astro/middleware.mjs +250 -83
  14. package/dist/astro/middleware.mjs.map +1 -1
  15. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +3 -3
  16. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +3 -3
  17. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +2 -2
  18. package/dist/astro/routes/api/admin/api-tokens/index.mjs +3 -3
  19. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +3 -3
  20. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +4 -4
  21. package/dist/astro/routes/api/admin/byline-fields/index.mjs +4 -4
  22. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +4 -4
  23. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +8 -8
  24. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +8 -8
  25. package/dist/astro/routes/api/admin/bylines/index.mjs +8 -8
  26. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +7 -7
  27. package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
  28. package/dist/astro/routes/api/admin/comments/bulk.mjs +6 -6
  29. package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
  30. package/dist/astro/routes/api/admin/comments/index.mjs +6 -6
  31. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  32. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  33. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  34. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  35. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +25 -25
  36. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +25 -25
  37. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +25 -25
  38. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +25 -25
  39. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +25 -25
  40. package/dist/astro/routes/api/admin/plugins/index.mjs +25 -25
  41. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  42. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +25 -25
  43. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +25 -25
  44. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +25 -25
  45. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +25 -25
  46. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +26 -26
  47. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +25 -25
  48. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +26 -26
  49. package/dist/astro/routes/api/admin/plugins/updates.mjs +25 -25
  50. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +25 -25
  51. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  52. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +25 -25
  53. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  54. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  55. package/dist/astro/routes/api/admin/users/_id_/index.mjs +3 -3
  56. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
  57. package/dist/astro/routes/api/admin/users/index.mjs +3 -3
  58. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  59. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  60. package/dist/astro/routes/api/auth/invite/complete.mjs +3 -3
  61. package/dist/astro/routes/api/auth/invite/index.mjs +3 -3
  62. package/dist/astro/routes/api/auth/invite/register-options.mjs +3 -3
  63. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  64. package/dist/astro/routes/api/auth/magic-link/send.mjs +4 -4
  65. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  66. package/dist/astro/routes/api/auth/me.mjs +4 -4
  67. package/dist/astro/routes/api/auth/passkey/_id_.mjs +3 -3
  68. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  69. package/dist/astro/routes/api/auth/passkey/options.mjs +4 -4
  70. package/dist/astro/routes/api/auth/passkey/register/options.mjs +3 -3
  71. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +3 -3
  72. package/dist/astro/routes/api/auth/passkey/verify.mjs +3 -3
  73. package/dist/astro/routes/api/auth/signup/complete.mjs +3 -3
  74. package/dist/astro/routes/api/auth/signup/request.mjs +4 -4
  75. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  76. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +6 -6
  77. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  78. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  79. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  80. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  81. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +4 -4
  82. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +4 -4
  83. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  84. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  85. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +4 -4
  86. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +8 -8
  87. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  88. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  89. package/dist/astro/routes/api/content/_collection_/_id_.mjs +4 -4
  90. package/dist/astro/routes/api/content/_collection_/index.mjs +4 -4
  91. package/dist/astro/routes/api/content/_collection_/trash.mjs +4 -4
  92. package/dist/astro/routes/api/dashboard.mjs +7 -7
  93. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  94. package/dist/astro/routes/api/import/probe.mjs +4 -4
  95. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  96. package/dist/astro/routes/api/import/wordpress/execute.d.mts +2 -2
  97. package/dist/astro/routes/api/import/wordpress/execute.mjs +7 -7
  98. package/dist/astro/routes/api/import/wordpress/media.mjs +4 -4
  99. package/dist/astro/routes/api/import/wordpress/prepare.mjs +6 -6
  100. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +5 -5
  101. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +4 -4
  102. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +5 -5
  103. package/dist/astro/routes/api/manifest.mjs +3 -3
  104. package/dist/astro/routes/api/mcp.mjs +26 -26
  105. package/dist/astro/routes/api/media/_id_/confirm.mjs +4 -4
  106. package/dist/astro/routes/api/media/_id_.mjs +4 -4
  107. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  108. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  109. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  110. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  111. package/dist/astro/routes/api/media/upload-url.mjs +4 -4
  112. package/dist/astro/routes/api/media.mjs +5 -5
  113. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +5 -5
  114. package/dist/astro/routes/api/menus/_name_/items.mjs +5 -5
  115. package/dist/astro/routes/api/menus/_name_/reorder.mjs +5 -5
  116. package/dist/astro/routes/api/menus/_name_/translations.mjs +5 -5
  117. package/dist/astro/routes/api/menus/_name_.mjs +5 -5
  118. package/dist/astro/routes/api/menus/index.mjs +5 -5
  119. package/dist/astro/routes/api/oauth/device/authorize.mjs +3 -3
  120. package/dist/astro/routes/api/oauth/device/code.mjs +4 -4
  121. package/dist/astro/routes/api/oauth/device/token.mjs +4 -4
  122. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  123. package/dist/astro/routes/api/oauth/token/refresh.mjs +3 -3
  124. package/dist/astro/routes/api/oauth/token/revoke.mjs +3 -3
  125. package/dist/astro/routes/api/oauth/token.mjs +2 -2
  126. package/dist/astro/routes/api/openapi.json.mjs +2 -2
  127. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
  128. package/dist/astro/routes/api/redirects/404s/index.mjs +6 -6
  129. package/dist/astro/routes/api/redirects/404s/summary.mjs +6 -6
  130. package/dist/astro/routes/api/redirects/_id_.mjs +7 -7
  131. package/dist/astro/routes/api/redirects/index.mjs +7 -7
  132. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  133. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  134. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +25 -25
  135. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +25 -25
  136. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +25 -25
  137. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +25 -25
  138. package/dist/astro/routes/api/schema/collections/index.mjs +25 -25
  139. package/dist/astro/routes/api/schema/index.mjs +6 -6
  140. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +25 -25
  141. package/dist/astro/routes/api/schema/orphans/index.mjs +25 -25
  142. package/dist/astro/routes/api/search/enable.mjs +7 -7
  143. package/dist/astro/routes/api/search/index.mjs +6 -6
  144. package/dist/astro/routes/api/search/rebuild.mjs +7 -7
  145. package/dist/astro/routes/api/search/stats.mjs +6 -6
  146. package/dist/astro/routes/api/search/suggest.mjs +6 -6
  147. package/dist/astro/routes/api/sections/_slug_.mjs +6 -6
  148. package/dist/astro/routes/api/sections/index.mjs +6 -6
  149. package/dist/astro/routes/api/settings/email.mjs +4 -4
  150. package/dist/astro/routes/api/settings.mjs +8 -8
  151. package/dist/astro/routes/api/setup/admin-verify.mjs +3 -3
  152. package/dist/astro/routes/api/setup/admin.mjs +3 -3
  153. package/dist/astro/routes/api/setup/dev-bypass.mjs +15 -15
  154. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  155. package/dist/astro/routes/api/setup/index.mjs +16 -16
  156. package/dist/astro/routes/api/setup/status.mjs +3 -3
  157. package/dist/astro/routes/api/snapshot.mjs +3 -3
  158. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +8 -8
  159. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +8 -8
  160. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +8 -8
  161. package/dist/astro/routes/api/taxonomies/index.mjs +8 -8
  162. package/dist/astro/routes/api/themes/preview.mjs +3 -3
  163. package/dist/astro/routes/api/typegen.mjs +5 -5
  164. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +4 -4
  165. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +6 -6
  166. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +6 -6
  167. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  168. package/dist/astro/routes/api/widget-areas/index.mjs +6 -6
  169. package/dist/astro/routes/api/widget-components.mjs +2 -2
  170. package/dist/astro/routes/robots.txt.mjs +4 -4
  171. package/dist/astro/routes/sitemap-_collection_.xml.mjs +4 -4
  172. package/dist/astro/routes/sitemap.xml.mjs +4 -4
  173. package/dist/astro/types.d.mts +2 -2
  174. package/dist/{authorize-CLTmOUyx.mjs → authorize-CotM4Yiu.mjs} +2 -2
  175. package/dist/{authorize-CLTmOUyx.mjs.map → authorize-CotM4Yiu.mjs.map} +1 -1
  176. package/dist/{byline-CAhk4FrG.mjs → byline-CWQ9aSoz.mjs} +3 -3
  177. package/dist/{byline-CAhk4FrG.mjs.map → byline-CWQ9aSoz.mjs.map} +1 -1
  178. package/dist/{byline-fields-CR5hGLMw.d.mts → byline-fields-BNy7Ng1U.d.mts} +28 -28
  179. package/dist/{byline-fields-CR5hGLMw.d.mts.map → byline-fields-BNy7Ng1U.d.mts.map} +1 -1
  180. package/dist/{bylines-DCczH3AV.mjs → bylines-BJSva1Un.mjs} +4 -4
  181. package/dist/{bylines-DCczH3AV.mjs.map → bylines-BJSva1Un.mjs.map} +1 -1
  182. package/dist/{bylines-CbrD7STW.mjs → bylines-LJMgENMI.mjs} +3 -3
  183. package/dist/{bylines-CbrD7STW.mjs.map → bylines-LJMgENMI.mjs.map} +1 -1
  184. package/dist/{cache-DIHHyPkt.mjs → cache-lZL7SgVb.mjs} +2 -2
  185. package/dist/{cache-DIHHyPkt.mjs.map → cache-lZL7SgVb.mjs.map} +1 -1
  186. package/dist/{chunks-DnnHlRG3.mjs → chunks-BU-vP9Dh.mjs} +2 -2
  187. package/dist/{chunks-DnnHlRG3.mjs.map → chunks-BU-vP9Dh.mjs.map} +1 -1
  188. package/dist/cli/index.mjs +13 -13
  189. package/dist/{comment-DkAfGX9E.mjs → comment-C4jVbCM8.mjs} +2 -2
  190. package/dist/{comment-DkAfGX9E.mjs.map → comment-C4jVbCM8.mjs.map} +1 -1
  191. package/dist/{comments-DLFnXs7J.mjs → comments-BTAbC0Ek.mjs} +3 -3
  192. package/dist/{comments-DLFnXs7J.mjs.map → comments-BTAbC0Ek.mjs.map} +1 -1
  193. package/dist/{content-C7aJ7keg.mjs → content-CyqOmOzm.mjs} +3 -3
  194. package/dist/{content-C7aJ7keg.mjs.map → content-CyqOmOzm.mjs.map} +1 -1
  195. package/dist/{context-Ca0HkaIh.mjs → context-DZ7bEh5-.mjs} +7 -7
  196. package/dist/{context-Ca0HkaIh.mjs.map → context-DZ7bEh5-.mjs.map} +1 -1
  197. package/dist/{dashboard-BrfLIsX1.mjs → dashboard-B5WQpNTP.mjs} +4 -4
  198. package/dist/{dashboard-BrfLIsX1.mjs.map → dashboard-B5WQpNTP.mjs.map} +1 -1
  199. package/dist/db/index.mjs +1 -1
  200. package/dist/{error-Bk9s3Ism.mjs → error-DJOsMVSt.mjs} +2 -2
  201. package/dist/{error-Bk9s3Ism.mjs.map → error-DJOsMVSt.mjs.map} +1 -1
  202. package/dist/{fts-manager-XpDfbIKo.mjs → fts-manager-DR1ERA0c.mjs} +2 -2
  203. package/dist/{fts-manager-XpDfbIKo.mjs.map → fts-manager-DR1ERA0c.mjs.map} +1 -1
  204. package/dist/{index-C8ciqSMJ.d.mts → index-CjKdMZ3U.d.mts} +4 -4
  205. package/dist/{index-C8ciqSMJ.d.mts.map → index-CjKdMZ3U.d.mts.map} +1 -1
  206. package/dist/index.d.mts +2 -2
  207. package/dist/index.mjs +34 -34
  208. package/dist/{load-CF5oETkh.mjs → load-6ZrRhepW.mjs} +2 -2
  209. package/dist/{load-CF5oETkh.mjs.map → load-6ZrRhepW.mjs.map} +1 -1
  210. package/dist/{loader-BxyvbrZP.mjs → loader-Dyx8dhFV.mjs} +3 -3
  211. package/dist/{loader-BxyvbrZP.mjs.map → loader-Dyx8dhFV.mjs.map} +1 -1
  212. package/dist/media/local-runtime.d.mts +2 -2
  213. package/dist/media/local-runtime.mjs +4 -4
  214. package/dist/{media-Cyz5BhSN.mjs → media-C-oovGCG.mjs} +2 -2
  215. package/dist/{media-Cyz5BhSN.mjs.map → media-C-oovGCG.mjs.map} +1 -1
  216. package/dist/{menus-CIdZ_Q6U.mjs → menus-BKkxXCmd.mjs} +30 -11
  217. package/dist/menus-BKkxXCmd.mjs.map +1 -0
  218. package/dist/{menus-PFp8FDuO.mjs → menus-DugoYwTX.mjs} +2 -2
  219. package/dist/{menus-PFp8FDuO.mjs.map → menus-DugoYwTX.mjs.map} +1 -1
  220. package/dist/{parse-B-K21lvm.mjs → parse-BBkFmLVr.mjs} +2 -2
  221. package/dist/{parse-B-K21lvm.mjs.map → parse-BBkFmLVr.mjs.map} +1 -1
  222. package/dist/plugin-utils.d.mts +2 -2
  223. package/dist/plugins/adapt-sandbox-entry.d.mts +2 -2
  224. package/dist/{query-Cc649nDl.mjs → query-Ctlq1aOk.mjs} +10 -10
  225. package/dist/{query-Cc649nDl.mjs.map → query-Ctlq1aOk.mjs.map} +1 -1
  226. package/dist/{rate-limit-BI1OdpQH.mjs → rate-limit-CH6W6ikK.mjs} +2 -2
  227. package/dist/{rate-limit-BI1OdpQH.mjs.map → rate-limit-CH6W6ikK.mjs.map} +1 -1
  228. package/dist/{redirect-C-FeA4j9.mjs → redirect-C6tJA7tk.mjs} +2 -2
  229. package/dist/{redirect-C-FeA4j9.mjs.map → redirect-C6tJA7tk.mjs.map} +1 -1
  230. package/dist/{redirects-C1UgU9E0.mjs → redirects-CacE9eQa.mjs} +3 -3
  231. package/dist/{redirects-C1UgU9E0.mjs.map → redirects-CacE9eQa.mjs.map} +1 -1
  232. package/dist/{registry-C-T_PWgp.mjs → registry-CIDxZbhh.mjs} +4 -4
  233. package/dist/{registry-C-T_PWgp.mjs.map → registry-CIDxZbhh.mjs.map} +1 -1
  234. package/dist/runner-DM1yR5qd.d.mts.map +1 -1
  235. package/dist/{runner-BiuUfx-V.mjs → runner-pt6Wl-l-.mjs} +8 -3
  236. package/dist/{runner-BiuUfx-V.mjs.map → runner-pt6Wl-l-.mjs.map} +1 -1
  237. package/dist/runtime.d.mts +2 -2
  238. package/dist/runtime.mjs +2 -2
  239. package/dist/{schema-BpCJh2lU.mjs → schema-B4tk0HAG.mjs} +4 -4
  240. package/dist/{schema-BpCJh2lU.mjs.map → schema-B4tk0HAG.mjs.map} +1 -1
  241. package/dist/{search-BrF7k0Ho.mjs → search-f-fNfwab.mjs} +4 -4
  242. package/dist/{search-BrF7k0Ho.mjs.map → search-f-fNfwab.mjs.map} +1 -1
  243. package/dist/{sections-8DEa-dWt.mjs → sections-biElLfT9.mjs} +3 -3
  244. package/dist/{sections-8DEa-dWt.mjs.map → sections-biElLfT9.mjs.map} +1 -1
  245. package/dist/seed/index.mjs +13 -13
  246. package/dist/{seo-CKr7pLfA.mjs → seo-BR39kvTF.mjs} +2 -2
  247. package/dist/{seo-CKr7pLfA.mjs.map → seo-BR39kvTF.mjs.map} +1 -1
  248. package/dist/{service-9P2cdyR_.mjs → service-BhR2acnc.mjs} +2 -2
  249. package/dist/{service-9P2cdyR_.mjs.map → service-BhR2acnc.mjs.map} +1 -1
  250. package/dist/{settings-DYVzINdn.mjs → settings-D_NJvjgN.mjs} +3 -3
  251. package/dist/{settings-DYVzINdn.mjs.map → settings-D_NJvjgN.mjs.map} +1 -1
  252. package/dist/{settings-Jro4YcUb.mjs → settings-b5zW1R1T.mjs} +3 -3
  253. package/dist/{settings-Jro4YcUb.mjs.map → settings-b5zW1R1T.mjs.map} +1 -1
  254. package/dist/{taxonomies-CGD6y79Q.mjs → taxonomies-Crtzy4MT.mjs} +8 -7
  255. package/dist/taxonomies-Crtzy4MT.mjs.map +1 -0
  256. package/dist/{taxonomies-C0bVme_m.mjs → taxonomies-Mhn9rjTQ.mjs} +4 -4
  257. package/dist/{taxonomies-C0bVme_m.mjs.map → taxonomies-Mhn9rjTQ.mjs.map} +1 -1
  258. package/dist/{taxonomy-Db5xwphL.mjs → taxonomy-DTZrIQpi.mjs} +3 -3
  259. package/dist/{taxonomy-Db5xwphL.mjs.map → taxonomy-DTZrIQpi.mjs.map} +1 -1
  260. package/dist/{types-CfyYQ7eY.mjs → types-K3MDsxpy.mjs} +2 -2
  261. package/dist/{types-CfyYQ7eY.mjs.map → types-K3MDsxpy.mjs.map} +1 -1
  262. package/dist/{user-tLdHUEXV.mjs → user-DzEUl5zA.mjs} +2 -2
  263. package/dist/{user-tLdHUEXV.mjs.map → user-DzEUl5zA.mjs.map} +1 -1
  264. package/dist/{validate-DWmnRg6E.mjs → validate-JCXcsqiY.mjs} +2 -2
  265. package/dist/{validate-DWmnRg6E.mjs.map → validate-JCXcsqiY.mjs.map} +1 -1
  266. package/dist/{validation-BQ_TP-On.mjs → validation-Bq-VyKJg.mjs} +5 -5
  267. package/dist/{validation-BQ_TP-On.mjs.map → validation-Bq-VyKJg.mjs.map} +1 -1
  268. package/dist/version-CnS-Cr8A.mjs +7 -0
  269. package/dist/{version-CgcnMvqS.mjs.map → version-CnS-Cr8A.mjs.map} +1 -1
  270. package/dist/{widgets-DzlINGI6.mjs → widgets-Bap1eS1X.mjs} +2 -2
  271. package/dist/{widgets-DzlINGI6.mjs.map → widgets-Bap1eS1X.mjs.map} +1 -1
  272. package/dist/{zod-generator-MMm56Prt.mjs → zod-generator-BSDpkqSH.mjs} +4 -3
  273. package/dist/zod-generator-BSDpkqSH.mjs.map +1 -0
  274. package/package.json +7 -7
  275. package/src/astro/middleware/stream-end-metrics.ts +96 -0
  276. package/src/astro/middleware.ts +80 -32
  277. package/src/components/EmDashImage.astro +1 -0
  278. package/src/database/migrations/runner.ts +7 -2
  279. package/src/emdash-runtime.ts +177 -126
  280. package/src/menus/index.ts +27 -9
  281. package/src/plugins/hooks.ts +35 -6
  282. package/src/plugins/manager.ts +1 -0
  283. package/src/schema/zod-generator.ts +6 -2
  284. package/src/taxonomies/index.ts +12 -8
  285. package/src/utils/init-lock.ts +143 -0
  286. package/dist/menus-CIdZ_Q6U.mjs.map +0 -1
  287. package/dist/taxonomies-CGD6y79Q.mjs.map +0 -1
  288. package/dist/version-CgcnMvqS.mjs +0 -7
  289. package/dist/zod-generator-MMm56Prt.mjs.map +0 -1
@@ -1297,6 +1297,13 @@ export interface ExclusiveHookResolutionOptions {
1297
1297
  isActive: (pluginId: string) => boolean;
1298
1298
  /** Read an option value from persistent storage. */
1299
1299
  getOption: (key: string) => Promise<string | null>;
1300
+ /**
1301
+ * Batch-read option values for many keys in a single round trip.
1302
+ * When provided, resolution reads all current selections through this
1303
+ * instead of one getOption() call per hook. Keys absent from the
1304
+ * returned map are treated as unset.
1305
+ */
1306
+ getOptions?: (keys: string[]) => Promise<ReadonlyMap<string, string>>;
1300
1307
  /** Write an option value to persistent storage. */
1301
1308
  setOption: (key: string, value: string) => Promise<void>;
1302
1309
  /** Delete an option from persistent storage. */
@@ -1322,8 +1329,26 @@ const EXCLUSIVE_HOOK_KEY_PREFIX = "emdash:exclusive_hook:";
1322
1329
  * 5. If multiple providers and no hint → leave unselected (admin must choose).
1323
1330
  */
1324
1331
  export async function resolveExclusiveHooks(opts: ExclusiveHookResolutionOptions): Promise<void> {
1325
- const { pipeline, isActive, getOption, setOption, deleteOption, preferredHints } = opts;
1332
+ const { pipeline, isActive, getOption, getOptions, setOption, deleteOption, preferredHints } =
1333
+ opts;
1326
1334
  const exclusiveHookNames = pipeline.getRegisteredExclusiveHooks();
1335
+ if (exclusiveHookNames.length === 0) return;
1336
+
1337
+ // Batch-read current selections in one round trip when the caller
1338
+ // provides a batch reader (1 query instead of N sequential gets).
1339
+ let batchedSelections: ReadonlyMap<string, string> | undefined;
1340
+ if (getOptions) {
1341
+ try {
1342
+ batchedSelections = await getOptions(
1343
+ exclusiveHookNames.map((hookName) => `${EXCLUSIVE_HOOK_KEY_PREFIX}${hookName}`),
1344
+ );
1345
+ } catch {
1346
+ // Options table may not be ready. Matches the per-key tolerance
1347
+ // below: every hook's read would fail, so resolution is skipped
1348
+ // entirely without touching any selection.
1349
+ return;
1350
+ }
1351
+ }
1327
1352
 
1328
1353
  for (const hookName of exclusiveHookNames) {
1329
1354
  const providers = pipeline.getExclusiveHookProviders(hookName);
@@ -1333,11 +1358,15 @@ export async function resolveExclusiveHooks(opts: ExclusiveHookResolutionOptions
1333
1358
 
1334
1359
  const key = `${EXCLUSIVE_HOOK_KEY_PREFIX}${hookName}`;
1335
1360
  let currentSelection: string | null = null;
1336
- try {
1337
- currentSelection = await getOption(key);
1338
- } catch {
1339
- // Options table may not be ready
1340
- continue;
1361
+ if (batchedSelections) {
1362
+ currentSelection = batchedSelections.get(key) ?? null;
1363
+ } else {
1364
+ try {
1365
+ currentSelection = await getOption(key);
1366
+ } catch {
1367
+ // Options table may not be ready
1368
+ continue;
1369
+ }
1341
1370
  }
1342
1371
 
1343
1372
  // If selection exists and the plugin is still active → keep it
@@ -544,6 +544,7 @@ export class PluginManager {
544
544
  pipeline: this.hookPipeline!,
545
545
  isActive: (pluginId) => this.isActive(pluginId),
546
546
  getOption: (key) => optionsRepo.get<string>(key),
547
+ getOptions: (keys) => optionsRepo.getMany<string>(keys),
547
548
  setOption: (key, value) => optionsRepo.set(key, value),
548
549
  deleteOption: async (key) => {
549
550
  await optionsRepo.delete(key);
@@ -288,6 +288,9 @@ export function generateTypeScript(collection: CollectionWithFields): string {
288
288
  lines.push(` publishedAt: Date | null;`);
289
289
  // Bylines are eagerly loaded by getEmDashCollection/getEmDashEntry
290
290
  lines.push(` bylines?: ContentBylineCredit[];`);
291
+ // Taxonomy terms are eagerly loaded by getEmDashCollection/getEmDashEntry,
292
+ // keyed by taxonomy name (e.g. data.terms?.tag)
293
+ lines.push(` terms?: Record<string, TaxonomyTerm[]>;`);
291
294
  lines.push(`}`);
292
295
 
293
296
  return lines.join("\n");
@@ -312,8 +315,9 @@ export function generateTypesFile(collections: CollectionWithFields[]): string {
312
315
  c.fields.some((f) => f.type === "portableText"),
313
316
  );
314
317
 
315
- // Build imports - ContentBylineCredit is always needed for bylines
316
- const imports = ["ContentBylineCredit"];
318
+ // Build imports - ContentBylineCredit and TaxonomyTerm are always needed
319
+ // for the hydrated bylines/terms fields
320
+ const imports = ["ContentBylineCredit", "TaxonomyTerm"];
317
321
  if (needsPortableText) {
318
322
  imports.push("PortableTextBlock");
319
323
  }
@@ -189,13 +189,6 @@ export async function getTerm(
189
189
 
190
190
  if (!row) return null;
191
191
 
192
- const countResult = await db
193
- .selectFrom("content_taxonomies")
194
- .select((eb) => eb.fn.count<number>("entry_id").as("count"))
195
- .where("taxonomy_id", "=", row.translation_group ?? row.id)
196
- .executeTakeFirst();
197
- const count = countResult?.count ?? 0;
198
-
199
192
  let childrenQuery = db
200
193
  .selectFrom("taxonomies")
201
194
  .selectAll()
@@ -203,7 +196,18 @@ export async function getTerm(
203
196
  .orderBy("label", "asc");
204
197
  const termLocale = row.locale;
205
198
  if (termLocale) childrenQuery = childrenQuery.where("locale", "=", termLocale);
206
- const childRows = await childrenQuery.execute();
199
+
200
+ // The usage-count and children queries both depend only on the term row,
201
+ // so run them concurrently to save a round trip on remote databases.
202
+ const [countResult, childRows] = await Promise.all([
203
+ db
204
+ .selectFrom("content_taxonomies")
205
+ .select((eb) => eb.fn.count<number>("entry_id").as("count"))
206
+ .where("taxonomy_id", "=", row.translation_group ?? row.id)
207
+ .executeTakeFirst(),
208
+ childrenQuery.execute(),
209
+ ]);
210
+ const count = countResult?.count ?? 0;
207
211
 
208
212
  const children = childRows.map<TaxonomyTerm>((child) => ({
209
213
  id: child.id,
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Reclaimable initialization lock for isolate-lifetime singletons.
3
+ *
4
+ * Guards "first request initializes, everyone else waits" sections
5
+ * (runtime creation, database init) against a workerd failure mode: if the
6
+ * request that owns the initialization is cancelled mid-await (client
7
+ * disconnect, context teardown), its continuation — including any `finally`
8
+ * that would release the lock — never runs. A plain boolean or shared
9
+ * promise then stays stuck forever and every subsequent request in the
10
+ * isolate hangs until the platform kills it (observed as 524s at the
11
+ * 100-second wall limit, with the isolate poisoned until eviction).
12
+ *
13
+ * This lock instead records *when* the owner started. Waiters poll — we
14
+ * deliberately never await a promise created by another request, which
15
+ * workerd flags — and if the owner has held the lock past `deadlineMs`,
16
+ * the next waiter assumes the owner is dead, reclaims the lock, and runs
17
+ * the initialization itself. Waiters also give up after `maxWaitMs` so a
18
+ * request degrades to an error response rather than hanging.
19
+ */
20
+
21
+ export interface InitLock {
22
+ /** Epoch ms when the current owner claimed the lock, or null when free. */
23
+ ownerStartedAt: number | null;
24
+ /**
25
+ * Monotonic claim counter identifying the current owner. Release is
26
+ * gated on it: a slow owner that finishes after a waiter has reclaimed
27
+ * the lock must not clear the reclaimer's claim — that would let yet
28
+ * another caller claim the lock and start a third concurrent init.
29
+ */
30
+ generation: number;
31
+ }
32
+
33
+ export function createInitLock(): InitLock {
34
+ return { ownerStartedAt: null, generation: 0 };
35
+ }
36
+
37
+ export interface InitLockOptions {
38
+ /**
39
+ * Reclaim the lock if the owner has held it longer than this. Must be
40
+ * comfortably above the slowest legitimate init (cold migrations on a
41
+ * contended D1, including the concurrent-migrator wait) — a too-short
42
+ * deadline risks two concurrent inits, a too-long one delays recovery
43
+ * of a poisoned isolate. Nested locks must compose: an outer lock's
44
+ * deadline must exceed the deadline of any lock its init acquires.
45
+ */
46
+ deadlineMs?: number;
47
+ /** Waiter poll interval. */
48
+ pollMs?: number;
49
+ /**
50
+ * Give up waiting after this long and throw instead of hanging.
51
+ * Defaults to `deadlineMs` plus headroom so a waiter always survives
52
+ * long enough to reclaim a dead owner before giving up.
53
+ */
54
+ maxWaitMs?: number;
55
+ /**
56
+ * Called with the in-flight init promise (errors pre-swallowed) so the
57
+ * caller can hand it to the host's lifetime extender (waitUntil via
58
+ * `after()`). If the owning request is cancelled mid-init, the anchored
59
+ * promise keeps the context alive: init completes, populates the cache,
60
+ * and the `finally` below releases the lock — preventing the poisoning
61
+ * instead of merely recovering from it via reclaim.
62
+ */
63
+ anchor?: (promise: Promise<void>) => void;
64
+ }
65
+
66
+ const DEFAULT_DEADLINE_MS = 15_000;
67
+ const DEFAULT_POLL_MS = 50;
68
+ const MAX_WAIT_HEADROOM_MS = 15_000;
69
+
70
+ function sleep(ms: number): Promise<void> {
71
+ return new Promise((resolve) => setTimeout(resolve, ms));
72
+ }
73
+
74
+ /**
75
+ * Return the cached value if present, otherwise initialize it under the
76
+ * lock. `init` is responsible for storing the value so that `getCached`
77
+ * returns it on subsequent calls — waiters re-check `getCached` after the
78
+ * owner finishes rather than sharing the owner's promise.
79
+ *
80
+ * `init` receives an `isCurrentClaim` predicate and must gate its cache
81
+ * publication on it: a slow init that was reclaimed past the deadline
82
+ * must not overwrite the value published by the reclaimer (for the
83
+ * runtime singleton that would orphan the reclaimer's active cron
84
+ * scheduler). A losing init should also tear down any side resources it
85
+ * started, since its result will never be published.
86
+ */
87
+ export async function initWithLock<T>(
88
+ lock: InitLock,
89
+ getCached: () => T | null | undefined,
90
+ init: (isCurrentClaim: () => boolean) => Promise<T>,
91
+ options?: InitLockOptions,
92
+ ): Promise<T> {
93
+ const deadlineMs = options?.deadlineMs ?? DEFAULT_DEADLINE_MS;
94
+ const pollMs = options?.pollMs ?? DEFAULT_POLL_MS;
95
+ const maxWaitMs = options?.maxWaitMs ?? deadlineMs + MAX_WAIT_HEADROOM_MS;
96
+ // Date.now() is deliberate and only works because every loop iteration
97
+ // awaits: in workerd the clock only advances across I/O, so a sync spin
98
+ // would never observe the deadline. Don't "optimize" away the sleep.
99
+ const waitStart = Date.now();
100
+
101
+ for (;;) {
102
+ const cached = getCached();
103
+ if (cached !== null && cached !== undefined) {
104
+ return cached;
105
+ }
106
+
107
+ const ownerStartedAt = lock.ownerStartedAt;
108
+ if (ownerStartedAt === null || Date.now() - ownerStartedAt > deadlineMs) {
109
+ // Free, or the owner has been gone past the deadline — claim it.
110
+ // Synchronous between awaits, so two waiters can't both claim.
111
+ lock.generation += 1;
112
+ const claim = lock.generation;
113
+ lock.ownerStartedAt = Date.now();
114
+ try {
115
+ // Promise.resolve().then(...) so a synchronous throw from
116
+ // init still becomes a rejection after the anchor attaches.
117
+ const isCurrentClaim = () => lock.generation === claim;
118
+ const initPromise = Promise.resolve().then(() => init(isCurrentClaim));
119
+ options?.anchor?.(
120
+ initPromise.then(
121
+ () => undefined,
122
+ () => undefined,
123
+ ),
124
+ );
125
+ return await initPromise;
126
+ } finally {
127
+ // If this request dies mid-init unanchored this never runs;
128
+ // the next waiter reclaims after deadlineMs instead. Release
129
+ // only while still the current owner: a reclaimer may have
130
+ // taken the lock while this (slow) init was running, and
131
+ // clearing its claim would admit a third concurrent init.
132
+ if (lock.generation === claim) {
133
+ lock.ownerStartedAt = null;
134
+ }
135
+ }
136
+ }
137
+
138
+ if (Date.now() - waitStart > maxWaitMs) {
139
+ throw new Error(`initWithLock: timed out after ${maxWaitMs}ms waiting for initialization`);
140
+ }
141
+ await sleep(pollMs);
142
+ }
143
+ }