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
@@ -1,51 +1,51 @@
1
- import { r as runMigrations } from "../runner-BiuUfx-V.mjs";
1
+ import { i as runMigrations, t as MIGRATION_RACE_WAIT_MS } from "../runner-pt6Wl-l-.mjs";
2
2
  import { t as validateIdentifier } from "../validate-VPnKoIzW.mjs";
3
3
  import { o as isSqlite } from "../dialect-helpers-DRI5pyY3.mjs";
4
4
  import { i as setI18nConfig } from "../config-CVssduLe.mjs";
5
- import { _ as definePlugin, f as PluginRouteRegistry, g as resolveExclusiveHooks, h as createHookPipeline, p as EmailPipeline, v as after } from "../menus-CIdZ_Q6U.mjs";
6
- import { r as RevisionRepository } from "../content-C7aJ7keg.mjs";
5
+ import { _ as definePlugin, f as PluginRouteRegistry, g as resolveExclusiveHooks, h as createHookPipeline, p as EmailPipeline, v as after } from "../menus-BKkxXCmd.mjs";
6
+ import { r as RevisionRepository } from "../content-CyqOmOzm.mjs";
7
7
  import "../base64-CqR-7kqF.mjs";
8
- import "../types-CfyYQ7eY.mjs";
9
- import { t as MediaRepository } from "../media-Cyz5BhSN.mjs";
10
- import "../user-tLdHUEXV.mjs";
11
- import "../taxonomy-Db5xwphL.mjs";
12
- import "../comment-DkAfGX9E.mjs";
8
+ import "../types-K3MDsxpy.mjs";
9
+ import { t as MediaRepository } from "../media-C-oovGCG.mjs";
10
+ import "../user-DzEUl5zA.mjs";
11
+ import "../taxonomy-DTZrIQpi.mjs";
12
+ import "../comment-C4jVbCM8.mjs";
13
13
  import { t as OptionsRepository } from "../options-BL4X94qY.mjs";
14
- import "../context-Ca0HkaIh.mjs";
15
- import "../menus-PFp8FDuO.mjs";
16
- import "../redirect-C-FeA4j9.mjs";
14
+ import "../context-DZ7bEh5-.mjs";
15
+ import "../menus-DugoYwTX.mjs";
16
+ import "../redirect-C6tJA7tk.mjs";
17
17
  import { createRequestMetrics, getRequestContext, runWithContext } from "../request-context.mjs";
18
18
  import { r as requestCached } from "../request-cache-BYMs-BGX.mjs";
19
19
  import "../byline-registry-CxK5g559.mjs";
20
- import "../byline-CAhk4FrG.mjs";
20
+ import "../byline-CWQ9aSoz.mjs";
21
21
  import { t as normalizeMediaValue } from "../normalize-DVV8nbrL.mjs";
22
22
  import "../placeholder-BZxr8W1j.mjs";
23
- import "../seo-CKr7pLfA.mjs";
23
+ import "../seo-BR39kvTF.mjs";
24
24
  import { n as isMissingTableError } from "../db-errors-CtzxKBxe.mjs";
25
- import { $ as handleContentGetIncludingTrashed, B as handleMediaUpdate, G as handleContentCompare, H as handleRevisionList, I as handleMediaCreate, J as handleContentCreate, K as handleContentCountScheduled, L as handleMediaDelete, Q as handleContentGet, R as handleMediaGet, S as PluginStateRepository, U as handleRevisionRestore, V as handleRevisionGet, X as handleContentDiscardDraft, Y as handleContentDelete, Z as handleContentDuplicate, _ as loadBundleFromR2, at as handleContentSchedule, ct as handleContentUnschedule, et as handleContentList, it as handleContentRestore, lt as handleContentUpdate, nt as handleContentPermanentDelete, ot as handleContentTranslations, q as handleContentCountTrashed, rt as handleContentPublish, s as normalizeRegistryConfig, st as handleContentUnpublish, tt as handleContentListTrashed, ut as validateRev, z as handleMediaList } from "../api-B7GATEYo.mjs";
26
- import "../dashboard-BrfLIsX1.mjs";
25
+ import { $ as handleContentGetIncludingTrashed, B as handleMediaUpdate, G as handleContentCompare, H as handleRevisionList, I as handleMediaCreate, J as handleContentCreate, K as handleContentCountScheduled, L as handleMediaDelete, Q as handleContentGet, R as handleMediaGet, S as PluginStateRepository, U as handleRevisionRestore, V as handleRevisionGet, X as handleContentDiscardDraft, Y as handleContentDelete, Z as handleContentDuplicate, _ as loadBundleFromR2, at as handleContentSchedule, ct as handleContentUnschedule, et as handleContentList, it as handleContentRestore, lt as handleContentUpdate, nt as handleContentPermanentDelete, ot as handleContentTranslations, q as handleContentCountTrashed, rt as handleContentPublish, s as normalizeRegistryConfig, st as handleContentUnpublish, tt as handleContentListTrashed, ut as validateRev, z as handleMediaList } from "../api-Cs7DAACP.mjs";
26
+ import "../dashboard-B5WQpNTP.mjs";
27
27
  import { n as hashString } from "../hash-9w3pd3-m.mjs";
28
- import { t as FTSManager } from "../fts-manager-XpDfbIKo.mjs";
29
- import { n as SchemaRegistry } from "../registry-C-T_PWgp.mjs";
28
+ import { t as FTSManager } from "../fts-manager-DR1ERA0c.mjs";
29
+ import { n as SchemaRegistry } from "../registry-CIDxZbhh.mjs";
30
30
  import { createRecorder, flushRecorder, isInstrumentationEnabled, kyselyLogOption } from "../database/instrumentation.mjs";
31
- import { r as getDb } from "../loader-BxyvbrZP.mjs";
32
- import "../schema-BpCJh2lU.mjs";
33
- import "../zod-generator-MMm56Prt.mjs";
31
+ import { r as getDb } from "../loader-Dyx8dhFV.mjs";
32
+ import "../schema-B4tk0HAG.mjs";
33
+ import "../zod-generator-BSDpkqSH.mjs";
34
34
  import "../seo-DfjLvu8i.mjs";
35
- import "../sections-8DEa-dWt.mjs";
36
- import { o as invalidateSiteSettingsCache } from "../settings-Jro4YcUb.mjs";
37
- import "../settings-DYVzINdn.mjs";
35
+ import "../sections-biElLfT9.mjs";
36
+ import { o as invalidateSiteSettingsCache } from "../settings-b5zW1R1T.mjs";
37
+ import "../settings-D_NJvjgN.mjs";
38
38
  import "../resolve-BqYMVG0D.mjs";
39
- import "../taxonomies-CGD6y79Q.mjs";
40
- import "../taxonomies-C0bVme_m.mjs";
39
+ import "../taxonomies-Crtzy4MT.mjs";
40
+ import "../taxonomies-Mhn9rjTQ.mjs";
41
41
  import { r as normalizeManifestRoute } from "../manifest-schema-Cj-YrzrF.mjs";
42
42
  import "../types-Cj2S6FuC.mjs";
43
43
  import "../ssrf-BsVGIE0Z.mjs";
44
- import "../error-Bk9s3Ism.mjs";
45
- import "../parse-B-K21lvm.mjs";
44
+ import "../error-DJOsMVSt.mjs";
45
+ import "../parse-BBkFmLVr.mjs";
46
46
  import "../redirects-C0L9JUk4.mjs";
47
47
  import "../byline-fields-Dr-xcb6S.mjs";
48
- import { a as invalidateUrlPatternCache } from "../query-Cc649nDl.mjs";
48
+ import { a as invalidateUrlPatternCache } from "../query-Ctlq1aOk.mjs";
49
49
  import "../import-Dh8bWmyq.mjs";
50
50
  import { t as getTrustedProxyHeaders } from "../trusted-proxy-B4AfnoAp.mjs";
51
51
  import { n as sanitizeHeadersForSandbox, t as extractRequestMeta } from "../request-meta-7ByVLxB-.mjs";
@@ -55,13 +55,13 @@ import { r as devConsoleEmailDeliver, t as DEV_CONSOLE_EMAIL_PLUGIN_ID } from ".
55
55
  import "../utils-C4Ih4DML.mjs";
56
56
  import "../tokens-Bx2afeT-.mjs";
57
57
  import "../preview-BfuRkVKW.mjs";
58
- import "../bylines-DCczH3AV.mjs";
59
- import "../widgets-DzlINGI6.mjs";
60
- import "../apply-BrVqULFe.mjs";
61
- import "../load-CF5oETkh.mjs";
62
- import "../search-BrF7k0Ho.mjs";
58
+ import "../bylines-BJSva1Un.mjs";
59
+ import "../widgets-Bap1eS1X.mjs";
60
+ import "../apply-BWMV4Zmw.mjs";
61
+ import "../load-6ZrRhepW.mjs";
62
+ import "../search-f-fNfwab.mjs";
63
63
  import "../index.mjs";
64
- import { n as VERSION, t as COMMIT } from "../version-CgcnMvqS.mjs";
64
+ import { n as VERSION, t as COMMIT } from "../version-CnS-Cr8A.mjs";
65
65
  import { t as getAuthMode } from "../mode-BjlXswIw.mjs";
66
66
  import { t as cleanupExpiredChallenges } from "../challenge-store-DGwuCc4R.mjs";
67
67
  import { a as validateEncryptionKeyAtStartup } from "../secrets-YYbTgB1w.mjs";
@@ -76,6 +76,60 @@ import { sandboxedPlugins } from "virtual:emdash/sandboxed-plugins";
76
76
  import { createStorage } from "virtual:emdash/storage";
77
77
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
78
78
 
79
+ //#region src/utils/init-lock.ts
80
+ function createInitLock() {
81
+ return {
82
+ ownerStartedAt: null,
83
+ generation: 0
84
+ };
85
+ }
86
+ const DEFAULT_DEADLINE_MS = 15e3;
87
+ const DEFAULT_POLL_MS = 50;
88
+ const MAX_WAIT_HEADROOM_MS = 15e3;
89
+ function sleep(ms) {
90
+ return new Promise((resolve) => setTimeout(resolve, ms));
91
+ }
92
+ /**
93
+ * Return the cached value if present, otherwise initialize it under the
94
+ * lock. `init` is responsible for storing the value so that `getCached`
95
+ * returns it on subsequent calls — waiters re-check `getCached` after the
96
+ * owner finishes rather than sharing the owner's promise.
97
+ *
98
+ * `init` receives an `isCurrentClaim` predicate and must gate its cache
99
+ * publication on it: a slow init that was reclaimed past the deadline
100
+ * must not overwrite the value published by the reclaimer (for the
101
+ * runtime singleton that would orphan the reclaimer's active cron
102
+ * scheduler). A losing init should also tear down any side resources it
103
+ * started, since its result will never be published.
104
+ */
105
+ async function initWithLock(lock, getCached, init, options) {
106
+ const deadlineMs = options?.deadlineMs ?? DEFAULT_DEADLINE_MS;
107
+ const pollMs = options?.pollMs ?? DEFAULT_POLL_MS;
108
+ const maxWaitMs = options?.maxWaitMs ?? deadlineMs + MAX_WAIT_HEADROOM_MS;
109
+ const waitStart = Date.now();
110
+ for (;;) {
111
+ const cached = getCached();
112
+ if (cached !== null && cached !== void 0) return cached;
113
+ const ownerStartedAt = lock.ownerStartedAt;
114
+ if (ownerStartedAt === null || Date.now() - ownerStartedAt > deadlineMs) {
115
+ lock.generation += 1;
116
+ const claim = lock.generation;
117
+ lock.ownerStartedAt = Date.now();
118
+ try {
119
+ const isCurrentClaim = () => lock.generation === claim;
120
+ const initPromise = Promise.resolve().then(() => init(isCurrentClaim));
121
+ options?.anchor?.(initPromise.then(() => void 0, () => void 0));
122
+ return await initPromise;
123
+ } finally {
124
+ if (lock.generation === claim) lock.ownerStartedAt = null;
125
+ }
126
+ }
127
+ if (Date.now() - waitStart > maxWaitMs) throw new Error(`initWithLock: timed out after ${maxWaitMs}ms waiting for initialization`);
128
+ await sleep(pollMs);
129
+ }
130
+ }
131
+
132
+ //#endregion
79
133
  //#region src/cleanup.ts
80
134
  /**
81
135
  * System cleanup
@@ -381,8 +435,35 @@ const FIELD_TYPE_TO_KIND = {
381
435
  function contentItemToRecord(item) {
382
436
  return { ...item };
383
437
  }
384
- const dbCache = /* @__PURE__ */ new Map();
385
- let dbInitPromise = null;
438
+ /**
439
+ * Db init lock reclaim deadline. Derived from the migration race wait so
440
+ * they can't drift apart: a healthy init can legitimately block for the
441
+ * full MIGRATION_RACE_WAIT_MS inside waitForConcurrentMigrator, plus cold
442
+ * connect and migrator work, before it should be presumed dead. The outer
443
+ * runtime init lock (middleware.ts) must use a strictly larger deadline —
444
+ * it wraps create() → getDatabase() → this lock, and equal deadlines would
445
+ * let the outer reclaim while the inner is legitimately still working.
446
+ */
447
+ const DB_INIT_DEADLINE_MS = MIGRATION_RACE_WAIT_MS + 2e4;
448
+ /**
449
+ * Db cache + its init lock live on globalThis behind a Symbol: the bundler
450
+ * can duplicate this module across SSR chunks (same reasoning as
451
+ * request-cache.ts), and a duplicated cache/lock would mean concurrent
452
+ * independent db inits — and duplicate migrators — per isolate.
453
+ */
454
+ const DB_HOLDER_KEY = Symbol.for("emdash:db-cache");
455
+ const globalSymbolStore = globalThis;
456
+ function getDbHolder() {
457
+ let holder = globalSymbolStore[DB_HOLDER_KEY];
458
+ if (!holder) {
459
+ holder = {
460
+ cache: /* @__PURE__ */ new Map(),
461
+ lock: createInitLock()
462
+ };
463
+ globalSymbolStore[DB_HOLDER_KEY] = holder;
464
+ }
465
+ return holder;
466
+ }
386
467
  const storageCache = /* @__PURE__ */ new Map();
387
468
  const sandboxedPluginCache = /* @__PURE__ */ new Map();
388
469
  /**
@@ -795,19 +876,13 @@ var EmDashRuntime = class EmDashRuntime {
795
876
  await phase("rt.secrets", "Validate encryption key", () => validateEncryptionKeyAtStartup());
796
877
  const storage = EmDashRuntime.getStorage(deps);
797
878
  let pluginStates = /* @__PURE__ */ new Map();
798
- await phase("rt.plugins", "Plugin states", async () => {
879
+ let siteInfo;
880
+ await Promise.all([phase("rt.plugins", "Plugin states", async () => {
799
881
  try {
800
882
  const states = await db.selectFrom("_plugin_state").select(["plugin_id", "status"]).execute();
801
883
  pluginStates = new Map(states.map((s) => [s.plugin_id, s.status]));
802
884
  } catch {}
803
- });
804
- const enabledPlugins = /* @__PURE__ */ new Set();
805
- for (const plugin of deps.plugins) {
806
- const status = pluginStates.get(plugin.id);
807
- if (status === void 0 || status === "active") enabledPlugins.add(plugin.id);
808
- }
809
- let siteInfo;
810
- await phase("rt.site", "Site info options", async () => {
885
+ }), phase("rt.site", "Site info options", async () => {
811
886
  try {
812
887
  const siteOpts = await new OptionsRepository(db).getMany([
813
888
  "emdash:site_title",
@@ -820,7 +895,12 @@ var EmDashRuntime = class EmDashRuntime {
820
895
  locale: siteOpts.get("emdash:locale") ?? void 0
821
896
  };
822
897
  } catch {}
823
- });
898
+ })]);
899
+ const enabledPlugins = /* @__PURE__ */ new Set();
900
+ for (const plugin of deps.plugins) {
901
+ const status = pluginStates.get(plugin.id);
902
+ if (status === void 0 || status === "active") enabledPlugins.add(plugin.id);
903
+ }
824
904
  const allPipelinePlugins = [...deps.plugins];
825
905
  const bypassedPluginsList = [];
826
906
  if (import.meta.env.DEV) try {
@@ -881,8 +961,10 @@ var EmDashRuntime = class EmDashRuntime {
881
961
  };
882
962
  const pipeline = createHookPipeline(enabledPluginList, pipelineFactoryOptions);
883
963
  const sandboxedPlugins = await phase("rt.sandbox", "Sandboxed plugins", () => EmDashRuntime.loadSandboxedPlugins(deps, db, storage));
884
- if (deps.config.marketplace && storage && !deps.sandboxBypassed) await phase("rt.market", "Marketplace plugins", () => EmDashRuntime.loadInstalledSandboxedPlugins("marketplace", db, storage, deps, sandboxedPlugins));
885
- if (deps.config.experimental?.registry && storage) await phase("rt.registry", "Registry plugins", () => EmDashRuntime.loadInstalledSandboxedPlugins("registry", db, storage, deps, sandboxedPlugins));
964
+ const installedTierPhases = [];
965
+ if (deps.config.marketplace && storage && !deps.sandboxBypassed) installedTierPhases.push(phase("rt.market", "Marketplace plugins", () => EmDashRuntime.loadInstalledSandboxedPlugins("marketplace", db, storage, deps, sandboxedPlugins)));
966
+ if (deps.config.experimental?.registry && storage) installedTierPhases.push(phase("rt.registry", "Registry plugins", () => EmDashRuntime.loadInstalledSandboxedPlugins("registry", db, storage, deps, sandboxedPlugins)));
967
+ if (installedTierPhases.length > 0) await Promise.all(installedTierPhases);
886
968
  const mediaProviders = /* @__PURE__ */ new Map();
887
969
  const mediaProviderEntries = deps.mediaProviderEntries ?? [];
888
970
  const providerContext = {
@@ -987,10 +1069,8 @@ var EmDashRuntime = class EmDashRuntime {
987
1069
  throw new Error("EmDash database not configured. Either configure database in astro.config.mjs or use emdashLoader in live.config.ts");
988
1070
  }
989
1071
  const cacheKey = dbConfig.entrypoint;
990
- const cached = dbCache.get(cacheKey);
991
- if (cached) return cached;
992
- if (dbInitPromise) return dbInitPromise;
993
- dbInitPromise = (async () => {
1072
+ const holder = getDbHolder();
1073
+ return initWithLock(holder.lock, () => holder.cache.get(cacheKey), async (isCurrentClaim) => {
994
1074
  const db = new Kysely({
995
1075
  dialect: deps.createDialect(dbConfig.config),
996
1076
  log: kyselyLogOption()
@@ -1006,9 +1086,9 @@ var EmDashRuntime = class EmDashRuntime {
1006
1086
  }
1007
1087
  })();
1008
1088
  if (collectionCount.count === 0 && !setupDone) {
1009
- const { applySeed } = await import("../apply-BrVqULFe.mjs").then((n) => n.n);
1010
- const { loadSeed } = await import("../load-CF5oETkh.mjs").then((n) => n.r);
1011
- const { validateSeed } = await import("../validate-DWmnRg6E.mjs").then((n) => n.n);
1089
+ const { applySeed } = await import("../apply-BWMV4Zmw.mjs").then((n) => n.n);
1090
+ const { loadSeed } = await import("../load-6ZrRhepW.mjs").then((n) => n.r);
1091
+ const { validateSeed } = await import("../validate-JCXcsqiY.mjs").then((n) => n.n);
1012
1092
  const seed = await loadSeed();
1013
1093
  if (validateSeed(seed).valid) {
1014
1094
  await applySeed(db, seed, { onConflict: "skip" });
@@ -1016,14 +1096,12 @@ var EmDashRuntime = class EmDashRuntime {
1016
1096
  }
1017
1097
  }
1018
1098
  } catch {}
1019
- dbCache.set(cacheKey, db);
1099
+ if (isCurrentClaim()) holder.cache.set(cacheKey, db);
1020
1100
  return db;
1021
- })();
1022
- try {
1023
- return await dbInitPromise;
1024
- } finally {
1025
- dbInitPromise = null;
1026
- }
1101
+ }, {
1102
+ deadlineMs: DB_INIT_DEADLINE_MS,
1103
+ anchor: (promise) => after(() => promise)
1104
+ });
1027
1105
  }
1028
1106
  /**
1029
1107
  * Get or create storage instance
@@ -1282,6 +1360,7 @@ var EmDashRuntime = class EmDashRuntime {
1282
1360
  pipeline,
1283
1361
  isActive: () => true,
1284
1362
  getOption: (key) => optionsRepo.get(key),
1363
+ getOptions: (keys) => optionsRepo.getMany(keys),
1285
1364
  setOption: (key, value) => optionsRepo.set(key, value),
1286
1365
  deleteOption: async (key) => {
1287
1366
  await optionsRepo.delete(key);
@@ -1540,7 +1619,7 @@ var EmDashRuntime = class EmDashRuntime {
1540
1619
  if (this.hooks.hasHooks("content:beforeSave")) processedData = (await this.hooks.runContentBeforeSave(body.data, collection, true)).content;
1541
1620
  processedData = await this.runSandboxedBeforeSave(processedData, collection, true);
1542
1621
  processedData = await this.normalizeMediaFields(collection, processedData);
1543
- const { validateContentData } = await import("../validation-BQ_TP-On.mjs");
1622
+ const { validateContentData } = await import("../validation-Bq-VyKJg.mjs");
1544
1623
  const validation = await validateContentData(this.db, collection, processedData, { partial: false });
1545
1624
  if (!validation.ok) return {
1546
1625
  success: false,
@@ -1556,7 +1635,7 @@ var EmDashRuntime = class EmDashRuntime {
1556
1635
  return result;
1557
1636
  }
1558
1637
  async handleContentUpdate(collection, id, body) {
1559
- const { ContentRepository } = await import("../content-C7aJ7keg.mjs").then((n) => n.n);
1638
+ const { ContentRepository } = await import("../content-CyqOmOzm.mjs").then((n) => n.n);
1560
1639
  const repo = new ContentRepository(this.db);
1561
1640
  const resolvedItem = await repo.findByIdOrSlug(collection, id, body.locale);
1562
1641
  const resolvedId = resolvedItem?.id ?? id;
@@ -1583,7 +1662,7 @@ var EmDashRuntime = class EmDashRuntime {
1583
1662
  if (this.hooks.hasHooks("content:beforeSave")) processedData = (await this.hooks.runContentBeforeSave(bodyWithoutRev.data, collection, false)).content;
1584
1663
  processedData = await this.runSandboxedBeforeSave(processedData, collection, false);
1585
1664
  processedData = await this.normalizeMediaFields(collection, processedData);
1586
- const { validateContentData } = await import("../validation-BQ_TP-On.mjs");
1665
+ const { validateContentData } = await import("../validation-Bq-VyKJg.mjs");
1587
1666
  const validation = await validateContentData(this.db, collection, processedData, { partial: true });
1588
1667
  if (!validation.ok) return {
1589
1668
  success: false,
@@ -2123,6 +2202,70 @@ function createPublicMediaUrlResolver(storage) {
2123
2202
  return (key) => resolvePublicMediaUrl(storage, key);
2124
2203
  }
2125
2204
 
2205
+ //#endregion
2206
+ //#region src/astro/middleware/stream-end-metrics.ts
2207
+ /**
2208
+ * Stream-end metrics
2209
+ *
2210
+ * Server-Timing db.* counters are snapshotted when middleware's next()
2211
+ * returns — but at that point only the response *headers* are final.
2212
+ * Astro streams the body afterwards, and components rendered during
2213
+ * streaming issue further DB queries that the headers can never report.
2214
+ *
2215
+ * This module wraps the response body in an identity TransformStream and
2216
+ * snapshots the request metrics in flush(), i.e. when the body actually
2217
+ * finishes streaming. The metrics object lives on the request context
2218
+ * (AsyncLocalStorage) and is mutated in-place by the Kysely log hook, so
2219
+ * a reference captured before wrapping observes every post-header query.
2220
+ * The snapshot is emitted as prefixed NDJSON on stdout (same transport as
2221
+ * [emdash-query-log] — console.log works in both Node and workerd).
2222
+ *
2223
+ * Gated on isInstrumentationEnabled() (EMDASH_QUERY_LOG=1): zero overhead
2224
+ * in normal production traffic.
2225
+ */
2226
+ const STREAM_END_PREFIX = "[emdash-stream-end]";
2227
+ /**
2228
+ * Astro attaches AstroCookies to outgoing responses via a well-known global
2229
+ * symbol. Constructing a new Response drops non-header metadata, so the
2230
+ * symbol must be forwarded explicitly or `cookies.set()` calls are silently
2231
+ * dropped. Same pattern as finalizeResponse in ../middleware.ts.
2232
+ */
2233
+ const ASTRO_COOKIES_SYMBOL$1 = Symbol.for("astro.cookies");
2234
+ /**
2235
+ * Wrap a response body so the FINAL request metrics are emitted when the
2236
+ * body finishes streaming. Returns the response unchanged when
2237
+ * instrumentation is disabled, the body is null, or no request metrics
2238
+ * are attached (e.g. outside the middleware's ALS context).
2239
+ */
2240
+ function wrapBodyForStreamMetrics(response) {
2241
+ if (!isInstrumentationEnabled()) return response;
2242
+ if (!response.body) return response;
2243
+ const ctx = getRequestContext();
2244
+ const metrics = ctx?.metrics;
2245
+ if (!metrics) return response;
2246
+ const recorder = ctx?.queryRecorder;
2247
+ const transform = new TransformStream({ flush() {
2248
+ const snapshot = {
2249
+ route: recorder?.route,
2250
+ method: recorder?.method,
2251
+ phase: recorder?.phase,
2252
+ totalMs: performance.now() - metrics.start,
2253
+ dbCount: metrics.dbCount,
2254
+ dbTotalMs: metrics.dbTotalMs,
2255
+ dbFirstOffset: metrics.dbFirstOffset,
2256
+ dbLastOffset: metrics.dbLastOffset,
2257
+ cacheHits: metrics.cacheHits,
2258
+ cacheMisses: metrics.cacheMisses
2259
+ };
2260
+ console.log(`${STREAM_END_PREFIX} ${JSON.stringify(snapshot)}`);
2261
+ } });
2262
+ const wrapped = new Response(response.body.pipeThrough(transform), response);
2263
+ const astroCookies = Reflect.get(response, ASTRO_COOKIES_SYMBOL$1);
2264
+ if (astroCookies !== void 0) Reflect.set(wrapped, ASTRO_COOKIES_SYMBOL$1, astroCookies);
2265
+ wrapped.headers.delete("Content-Length");
2266
+ return wrapped;
2267
+ }
2268
+
2126
2269
  //#endregion
2127
2270
  //#region src/astro/public-plugin-api-routes.ts
2128
2271
  function pluginRouteNotFound() {
@@ -2149,10 +2292,14 @@ function createPublicPluginApiRouteHandler(runtime) {
2149
2292
  * Thin wrapper that initializes EmDashRuntime and attaches it to locals.
2150
2293
  * All heavy lifting happens in EmDashRuntime.
2151
2294
  */
2152
- let runtimeInstance = null;
2153
- let runtimeInitializing = false;
2154
- /** Whether i18n config has been initialized from the virtual module */
2155
- let i18nInitialized = false;
2295
+ /**
2296
+ * Runtime init lock reclaim deadline. Must be strictly larger than the db
2297
+ * init deadline: this lock wraps EmDashRuntime.create() getDatabase()
2298
+ * the db init lock, and equal deadlines would let this outer lock reclaim
2299
+ * (spawning a second cron scheduler and sandbox runner) while the inner db
2300
+ * init is legitimately still working through a contended migration.
2301
+ */
2302
+ const RUNTIME_INIT_DEADLINE_MS = DB_INIT_DEADLINE_MS + 15e3;
2156
2303
  /**
2157
2304
  * Whether we've verified the database has been set up.
2158
2305
  * On a fresh deployment the first request may hit a public page, bypassing
@@ -2177,6 +2324,27 @@ function markSetupVerified() {
2177
2324
  setupFlagStore[SETUP_VERIFIED_KEY] = true;
2178
2325
  }
2179
2326
  /**
2327
+ * The runtime singleton and its init lock live on globalThis behind a
2328
+ * Symbol — same reasoning as SETUP_VERIFIED_KEY above: the bundler can
2329
+ * duplicate this module across SSR chunks, and a duplicated instance/lock
2330
+ * would mean multiple runtimes (each with its own cron scheduler) per
2331
+ * isolate, initializing and reclaiming independently.
2332
+ */
2333
+ const RUNTIME_HOLDER_KEY = Symbol.for("emdash:runtime-holder");
2334
+ function getRuntimeHolder() {
2335
+ let holder = setupFlagStore[RUNTIME_HOLDER_KEY];
2336
+ if (!holder) {
2337
+ holder = {
2338
+ instance: null,
2339
+ lock: createInitLock()
2340
+ };
2341
+ setupFlagStore[RUNTIME_HOLDER_KEY] = holder;
2342
+ }
2343
+ return holder;
2344
+ }
2345
+ /** Whether i18n config has been initialized from the virtual module */
2346
+ let i18nInitialized = false;
2347
+ /**
2180
2348
  * Get EmDash configuration from virtual module
2181
2349
  */
2182
2350
  function getConfig() {
@@ -2223,20 +2391,19 @@ function buildDependencies(config) {
2223
2391
  * as "warm, nothing to report".
2224
2392
  */
2225
2393
  async function getRuntime(config, initTimings) {
2226
- if (runtimeInstance) return runtimeInstance;
2227
- if (runtimeInitializing) {
2228
- await new Promise((resolve) => setTimeout(resolve, 50));
2229
- return getRuntime(config, initTimings);
2230
- }
2231
- runtimeInitializing = true;
2232
- try {
2394
+ const holder = getRuntimeHolder();
2395
+ return initWithLock(holder.lock, () => holder.instance, async (isCurrentClaim) => {
2233
2396
  const deps = buildDependencies(config);
2234
2397
  const runtime = await EmDashRuntime.create(deps, initTimings);
2235
- runtimeInstance = runtime;
2398
+ if (isCurrentClaim()) holder.instance = runtime;
2399
+ else runtime.stopCron().catch((error) => {
2400
+ console.error("[emdash] failed to stop superseded runtime's cron:", error);
2401
+ });
2236
2402
  return runtime;
2237
- } finally {
2238
- runtimeInitializing = false;
2239
- }
2403
+ }, {
2404
+ deadlineMs: RUNTIME_INIT_DEADLINE_MS,
2405
+ anchor: (promise) => after(() => promise)
2406
+ });
2240
2407
  }
2241
2408
  /**
2242
2409
  * Astro attaches AstroCookies to outgoing responses via a well-known global
@@ -2342,7 +2509,7 @@ const onRequest = defineMiddleware(async (context, next) => {
2342
2509
  if (!isSetupVerified()) {
2343
2510
  const t0 = performance.now();
2344
2511
  try {
2345
- const { getDb } = await import("../loader-BxyvbrZP.mjs").then((n) => n.i);
2512
+ const { getDb } = await import("../loader-Dyx8dhFV.mjs").then((n) => n.i);
2346
2513
  await (await getDb()).selectFrom("_emdash_migrations").selectAll().limit(1).execute();
2347
2514
  markSetupVerified();
2348
2515
  } catch (error) {
@@ -2397,7 +2564,7 @@ const onRequest = defineMiddleware(async (context, next) => {
2397
2564
  desc: "Total middleware"
2398
2565
  });
2399
2566
  pushMetricsTimings(timings, metrics);
2400
- return finalizeResponse(response, timings);
2567
+ return wrapBodyForStreamMetrics(finalizeResponse(response, timings));
2401
2568
  };
2402
2569
  if (anonScoped) {
2403
2570
  const parent = getRequestContext();
@@ -2511,7 +2678,7 @@ const onRequest = defineMiddleware(async (context, next) => {
2511
2678
  desc: "Total middleware"
2512
2679
  });
2513
2680
  pushMetricsTimings(timings, metrics);
2514
- return finalizeResponse(response, timings);
2681
+ return wrapBodyForStreamMetrics(finalizeResponse(response, timings));
2515
2682
  };
2516
2683
  if (scoped) {
2517
2684
  const parent = getRequestContext();