emdash 0.25.1 → 0.27.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 (418) hide show
  1. package/dist/{adapters-DAAjOID4.d.mts → adapters-u037EnTR.d.mts} +1 -1
  2. package/dist/{adapters-DAAjOID4.d.mts.map → adapters-u037EnTR.d.mts.map} +1 -1
  3. package/dist/api/route-utils.d.mts +3 -3
  4. package/dist/api/route-utils.mjs +11 -11
  5. package/dist/api/schemas/index.d.mts +1 -1
  6. package/dist/{api-D2_sbavn.mjs → api-80kycR9o.mjs} +86 -30
  7. package/dist/api-80kycR9o.mjs.map +1 -0
  8. package/dist/{apply-Bk2mAuLn.mjs → apply-DSypk6Iu.mjs} +20 -18
  9. package/dist/apply-DSypk6Iu.mjs.map +1 -0
  10. package/dist/astro/index.d.mts +11 -10
  11. package/dist/astro/index.d.mts.map +1 -1
  12. package/dist/astro/index.mjs +12 -3
  13. package/dist/astro/index.mjs.map +1 -1
  14. package/dist/astro/middleware/auth.d.mts +10 -9
  15. package/dist/astro/middleware/auth.d.mts.map +1 -1
  16. package/dist/astro/middleware/auth.mjs +4 -3
  17. package/dist/astro/middleware/auth.mjs.map +1 -1
  18. package/dist/astro/middleware/redirect.mjs +4 -4
  19. package/dist/astro/middleware.d.mts +2 -9
  20. package/dist/astro/middleware.d.mts.map +1 -1
  21. package/dist/astro/middleware.mjs +86 -85
  22. package/dist/astro/middleware.mjs.map +1 -1
  23. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +3 -3
  24. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +3 -3
  25. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +2 -2
  26. package/dist/astro/routes/api/admin/api-tokens/index.mjs +3 -3
  27. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +3 -3
  28. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +4 -4
  29. package/dist/astro/routes/api/admin/byline-fields/index.mjs +4 -4
  30. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +4 -4
  31. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +10 -10
  32. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +10 -10
  33. package/dist/astro/routes/api/admin/bylines/index.mjs +10 -10
  34. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +8 -8
  35. package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
  36. package/dist/astro/routes/api/admin/comments/bulk.mjs +7 -7
  37. package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
  38. package/dist/astro/routes/api/admin/comments/index.mjs +7 -7
  39. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  40. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  41. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  42. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  43. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +29 -29
  44. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +29 -29
  46. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  47. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +29 -29
  48. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  49. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +28 -28
  50. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +28 -28
  51. package/dist/astro/routes/api/admin/plugins/index.mjs +29 -29
  52. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  54. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +28 -28
  55. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +28 -28
  56. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +28 -28
  57. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +28 -28
  58. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +29 -29
  59. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +28 -28
  60. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +29 -29
  61. package/dist/astro/routes/api/admin/plugins/updates.mjs +28 -28
  62. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +28 -28
  63. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  64. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +28 -28
  65. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  66. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  67. package/dist/astro/routes/api/admin/users/_id_/index.mjs +3 -3
  68. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
  69. package/dist/astro/routes/api/admin/users/index.mjs +3 -3
  70. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  71. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  72. package/dist/astro/routes/api/auth/invite/complete.mjs +3 -3
  73. package/dist/astro/routes/api/auth/invite/index.mjs +3 -3
  74. package/dist/astro/routes/api/auth/invite/register-options.mjs +3 -3
  75. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  76. package/dist/astro/routes/api/auth/magic-link/send.mjs +4 -4
  77. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  78. package/dist/astro/routes/api/auth/me.mjs +4 -4
  79. package/dist/astro/routes/api/auth/passkey/_id_.mjs +3 -3
  80. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  81. package/dist/astro/routes/api/auth/passkey/options.mjs +4 -4
  82. package/dist/astro/routes/api/auth/passkey/register/options.mjs +3 -3
  83. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +3 -3
  84. package/dist/astro/routes/api/auth/passkey/verify.mjs +3 -3
  85. package/dist/astro/routes/api/auth/signup/complete.mjs +3 -3
  86. package/dist/astro/routes/api/auth/signup/request.mjs +4 -4
  87. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  88. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +7 -7
  89. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +7 -7
  90. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  91. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  92. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  93. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  94. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +4 -4
  95. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +4 -4
  96. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  97. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  98. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +4 -4
  99. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +9 -9
  100. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  101. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  102. package/dist/astro/routes/api/content/_collection_/_id_.mjs +4 -4
  103. package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
  104. package/dist/astro/routes/api/content/_collection_/index.mjs +4 -4
  105. package/dist/astro/routes/api/content/_collection_/trash.mjs +4 -4
  106. package/dist/astro/routes/api/dashboard.mjs +8 -8
  107. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  108. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  109. package/dist/astro/routes/api/import/probe.mjs +4 -4
  110. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  111. package/dist/astro/routes/api/import/wordpress/execute.d.mts +10 -9
  112. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  113. package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -9
  114. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -9
  115. package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
  116. package/dist/astro/routes/api/import/wordpress/media.mjs +4 -4
  117. package/dist/astro/routes/api/import/wordpress/prepare.mjs +6 -6
  118. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +5 -5
  119. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  120. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +4 -4
  121. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  122. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +7 -7
  123. package/dist/astro/routes/api/manifest.d.mts.map +1 -1
  124. package/dist/astro/routes/api/manifest.mjs +13 -4
  125. package/dist/astro/routes/api/manifest.mjs.map +1 -1
  126. package/dist/astro/routes/api/mcp.mjs +34 -34
  127. package/dist/astro/routes/api/media/_id_/confirm.mjs +4 -4
  128. package/dist/astro/routes/api/media/_id_.mjs +4 -4
  129. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  130. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  131. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  132. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  133. package/dist/astro/routes/api/media/upload-url.mjs +4 -4
  134. package/dist/astro/routes/api/media.mjs +5 -5
  135. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +6 -6
  136. package/dist/astro/routes/api/menus/_name_/items.mjs +6 -6
  137. package/dist/astro/routes/api/menus/_name_/reorder.mjs +6 -6
  138. package/dist/astro/routes/api/menus/_name_/translations.mjs +6 -6
  139. package/dist/astro/routes/api/menus/_name_.mjs +6 -6
  140. package/dist/astro/routes/api/menus/index.mjs +6 -6
  141. package/dist/astro/routes/api/oauth/device/authorize.mjs +3 -3
  142. package/dist/astro/routes/api/oauth/device/code.mjs +4 -4
  143. package/dist/astro/routes/api/oauth/device/token.mjs +4 -4
  144. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  145. package/dist/astro/routes/api/oauth/token/refresh.mjs +3 -3
  146. package/dist/astro/routes/api/oauth/token/revoke.mjs +3 -3
  147. package/dist/astro/routes/api/oauth/token.mjs +2 -2
  148. package/dist/astro/routes/api/openapi.json.mjs +2 -2
  149. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
  150. package/dist/astro/routes/api/redirects/404s/index.mjs +6 -6
  151. package/dist/astro/routes/api/redirects/404s/summary.mjs +6 -6
  152. package/dist/astro/routes/api/redirects/_id_.mjs +7 -7
  153. package/dist/astro/routes/api/redirects/index.mjs +7 -7
  154. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  155. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  156. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +28 -28
  157. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +28 -28
  158. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +28 -28
  159. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +28 -28
  160. package/dist/astro/routes/api/schema/collections/index.mjs +28 -28
  161. package/dist/astro/routes/api/schema/index.mjs +6 -6
  162. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +28 -28
  163. package/dist/astro/routes/api/schema/orphans/index.mjs +28 -28
  164. package/dist/astro/routes/api/search/enable.mjs +7 -7
  165. package/dist/astro/routes/api/search/index.mjs +6 -6
  166. package/dist/astro/routes/api/search/rebuild.mjs +7 -7
  167. package/dist/astro/routes/api/search/stats.mjs +6 -6
  168. package/dist/astro/routes/api/search/suggest.mjs +6 -6
  169. package/dist/astro/routes/api/sections/_slug_.mjs +6 -6
  170. package/dist/astro/routes/api/sections/index.mjs +6 -6
  171. package/dist/astro/routes/api/settings/email.mjs +4 -4
  172. package/dist/astro/routes/api/settings.mjs +9 -9
  173. package/dist/astro/routes/api/setup/admin-verify.mjs +3 -3
  174. package/dist/astro/routes/api/setup/admin.mjs +3 -3
  175. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  176. package/dist/astro/routes/api/setup/dev-bypass.mjs +20 -18
  177. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  178. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  179. package/dist/astro/routes/api/setup/index.mjs +18 -18
  180. package/dist/astro/routes/api/setup/status.mjs +3 -3
  181. package/dist/astro/routes/api/snapshot.mjs +3 -3
  182. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +9 -9
  183. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +9 -9
  184. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +9 -9
  185. package/dist/astro/routes/api/taxonomies/index.mjs +9 -9
  186. package/dist/astro/routes/api/themes/preview.mjs +3 -3
  187. package/dist/astro/routes/api/typegen.mjs +5 -5
  188. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +4 -4
  189. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +6 -6
  190. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +6 -6
  191. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  192. package/dist/astro/routes/api/widget-areas/index.mjs +6 -6
  193. package/dist/astro/routes/api/widget-components.mjs +2 -2
  194. package/dist/astro/routes/robots.txt.mjs +5 -5
  195. package/dist/astro/routes/sitemap-_collection_.xml.mjs +10 -9
  196. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  197. package/dist/astro/routes/sitemap.xml.mjs +5 -5
  198. package/dist/astro/types.d.mts +12 -10
  199. package/dist/astro/types.d.mts.map +1 -1
  200. package/dist/auth/providers/github.d.mts +1 -1
  201. package/dist/auth/providers/google.d.mts +1 -1
  202. package/dist/{authorize-CuxZ0i2t.mjs → authorize-C3a_zGsM.mjs} +2 -2
  203. package/dist/{authorize-CuxZ0i2t.mjs.map → authorize-C3a_zGsM.mjs.map} +1 -1
  204. package/dist/{byline-C-YajfV7.mjs → byline-DEKSVPTy.mjs} +6 -6
  205. package/dist/{byline-C-YajfV7.mjs.map → byline-DEKSVPTy.mjs.map} +1 -1
  206. package/dist/{byline-fields-KD3JFRuH.d.mts → byline-fields-CtQ6blXd.d.mts} +32 -32
  207. package/dist/{byline-fields-KD3JFRuH.d.mts.map → byline-fields-CtQ6blXd.d.mts.map} +1 -1
  208. package/dist/{bylines-CPc_q2Vd.mjs → bylines-CiqgTHWF.mjs} +5 -5
  209. package/dist/{bylines-CPc_q2Vd.mjs.map → bylines-CiqgTHWF.mjs.map} +1 -1
  210. package/dist/{bylines-D4KADDAi.mjs → bylines-Ds4-otXl.mjs} +4 -4
  211. package/dist/{bylines-D4KADDAi.mjs.map → bylines-Ds4-otXl.mjs.map} +1 -1
  212. package/dist/{cache-C35VWD5D.mjs → cache-Ciu3e3AF.mjs} +2 -2
  213. package/dist/{cache-C35VWD5D.mjs.map → cache-Ciu3e3AF.mjs.map} +1 -1
  214. package/dist/{chunks-BHgcHh2C.mjs → chunks-CZFiauig.mjs} +2 -2
  215. package/dist/{chunks-BHgcHh2C.mjs.map → chunks-CZFiauig.mjs.map} +1 -1
  216. package/dist/cli/index.mjs +17 -17
  217. package/dist/cli/index.mjs.map +1 -1
  218. package/dist/client/cf-access.d.mts +1 -1
  219. package/dist/client/index.d.mts +1 -1
  220. package/dist/{comment-BDx50EX5.mjs → comment-CH1IrFFs.mjs} +3 -3
  221. package/dist/{comment-BDx50EX5.mjs.map → comment-CH1IrFFs.mjs.map} +1 -1
  222. package/dist/{comment-reaction-Gv_pgfI3.mjs → comment-reaction-kruNY-kP.mjs} +2 -2
  223. package/dist/{comment-reaction-Gv_pgfI3.mjs.map → comment-reaction-kruNY-kP.mjs.map} +1 -1
  224. package/dist/{comments-CXHuQ6jI.mjs → comments-BUJyXbgq.mjs} +3 -3
  225. package/dist/{comments-CXHuQ6jI.mjs.map → comments-BUJyXbgq.mjs.map} +1 -1
  226. package/dist/{content-B43-YrIq.mjs → content-RmfHoWqK.mjs} +4 -4
  227. package/dist/{content-B43-YrIq.mjs.map → content-RmfHoWqK.mjs.map} +1 -1
  228. package/dist/{context-BW3N7wyt.mjs → context-CzUU_WzL.mjs} +7 -7
  229. package/dist/{context-BW3N7wyt.mjs.map → context-CzUU_WzL.mjs.map} +1 -1
  230. package/dist/{dashboard-FIe0S512.mjs → dashboard-CVyGhift.mjs} +4 -4
  231. package/dist/{dashboard-FIe0S512.mjs.map → dashboard-CVyGhift.mjs.map} +1 -1
  232. package/dist/db/index.d.mts +3 -3
  233. package/dist/db/index.mjs +1 -1
  234. package/dist/db/libsql.d.mts +1 -1
  235. package/dist/db/postgres.d.mts +1 -1
  236. package/dist/db/sqlite.d.mts +1 -1
  237. package/dist/{error-DXnK2wF4.mjs → error-BHkLZk-w.mjs} +2 -2
  238. package/dist/{error-DXnK2wF4.mjs.map → error-BHkLZk-w.mjs.map} +1 -1
  239. package/dist/{field-defs-cache-CYYx8xlG.mjs → field-defs-cache-BA-8ZPiT.mjs} +2 -2
  240. package/dist/{field-defs-cache-CYYx8xlG.mjs.map → field-defs-cache-BA-8ZPiT.mjs.map} +1 -1
  241. package/dist/{fts-manager-DW_NR-Fs.mjs → fts-manager-Db9jGavf.mjs} +2 -2
  242. package/dist/{fts-manager-DW_NR-Fs.mjs.map → fts-manager-Db9jGavf.mjs.map} +1 -1
  243. package/dist/{index-Cz6_JBL3.d.mts → index-CDZZjrLT.d.mts} +2430 -2363
  244. package/dist/index-CDZZjrLT.d.mts.map +1 -0
  245. package/dist/{index-qbL02uhs.d.mts → index-DGIjmUXQ.d.mts} +3 -3
  246. package/dist/{index-qbL02uhs.d.mts.map → index-DGIjmUXQ.d.mts.map} +1 -1
  247. package/dist/index.d.mts +16 -15
  248. package/dist/index.mjs +38 -38
  249. package/dist/{load-DMFi4n1p.mjs → load-DpHICVPh.mjs} +2 -2
  250. package/dist/{load-DMFi4n1p.mjs.map → load-DpHICVPh.mjs.map} +1 -1
  251. package/dist/{loader-DrpofRon.mjs → loader-4K37qA-y.mjs} +81 -18
  252. package/dist/loader-4K37qA-y.mjs.map +1 -0
  253. package/dist/{manifest-schema-BOfPXse0.mjs → manifest-schema-kPGX7VS-.mjs} +3 -1
  254. package/dist/manifest-schema-kPGX7VS-.mjs.map +1 -0
  255. package/dist/media/local-runtime.d.mts +11 -10
  256. package/dist/media/local-runtime.d.mts.map +1 -1
  257. package/dist/media/local-runtime.mjs +5 -5
  258. package/dist/{media-BjKxjzk8.mjs → media-C0nRRfs1.mjs} +2 -2
  259. package/dist/{media-BjKxjzk8.mjs.map → media-C0nRRfs1.mjs.map} +1 -1
  260. package/dist/{menus-CxqJ-z-N.mjs → menus-DzRyC1ID.mjs} +50 -68
  261. package/dist/menus-DzRyC1ID.mjs.map +1 -0
  262. package/dist/{menus-8O6xNcYW.mjs → menus-SL2K0xq2.mjs} +3 -3
  263. package/dist/{menus-8O6xNcYW.mjs.map → menus-SL2K0xq2.mjs.map} +1 -1
  264. package/dist/object-cache/memory.d.mts +1 -1
  265. package/dist/{object-cache-SEb2IM4Z.mjs → object-cache-CHbHv83-.mjs} +8 -4
  266. package/dist/object-cache-CHbHv83-.mjs.map +1 -0
  267. package/dist/{options-BvClpP5Q.d.mts → options-41nCWqi9.d.mts} +2 -2
  268. package/dist/{options-BvClpP5Q.d.mts.map → options-41nCWqi9.d.mts.map} +1 -1
  269. package/dist/page/index.d.mts +6 -3
  270. package/dist/page/index.d.mts.map +1 -1
  271. package/dist/page/index.mjs +3 -2
  272. package/dist/page/index.mjs.map +1 -1
  273. package/dist/{parse-DqMWHQ8x.mjs → parse-CqyZj3Hp.mjs} +2 -2
  274. package/dist/{parse-DqMWHQ8x.mjs.map → parse-CqyZj3Hp.mjs.map} +1 -1
  275. package/dist/plugin-types.d.mts +4 -2
  276. package/dist/plugin-types.d.mts.map +1 -1
  277. package/dist/plugin-utils.d.mts +10 -9
  278. package/dist/plugin-utils.d.mts.map +1 -1
  279. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -9
  280. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  281. package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
  282. package/dist/{query-34pfm02Q.mjs → query-B0M-9LYR.mjs} +14 -14
  283. package/dist/{query-34pfm02Q.mjs.map → query-B0M-9LYR.mjs.map} +1 -1
  284. package/dist/{rate-limit-CBQK4ygJ.mjs → rate-limit-BwoUdIpC.mjs} +2 -2
  285. package/dist/{rate-limit-CBQK4ygJ.mjs.map → rate-limit-BwoUdIpC.mjs.map} +1 -1
  286. package/dist/{redirect-C1KVGYWe.mjs → redirect-lMOzG04S.mjs} +2 -2
  287. package/dist/{redirect-C1KVGYWe.mjs.map → redirect-lMOzG04S.mjs.map} +1 -1
  288. package/dist/{redirects-DgnypVir.mjs → redirects-9218MmYl.mjs} +3 -3
  289. package/dist/{redirects-DgnypVir.mjs.map → redirects-9218MmYl.mjs.map} +1 -1
  290. package/dist/{registry-3aOAS4My.mjs → registry-DP-iEtdR.mjs} +4 -4
  291. package/dist/{registry-3aOAS4My.mjs.map → registry-DP-iEtdR.mjs.map} +1 -1
  292. package/dist/{runner-CEtq-6Sm.d.mts → runner-BbR3DfrL.d.mts} +2 -2
  293. package/dist/{runner-CEtq-6Sm.d.mts.map → runner-BbR3DfrL.d.mts.map} +1 -1
  294. package/dist/{runner-BsquExlK.mjs → runner-CFngB4WZ.mjs} +296 -191
  295. package/dist/runner-CFngB4WZ.mjs.map +1 -0
  296. package/dist/runtime.d.mts +10 -9
  297. package/dist/runtime.d.mts.map +1 -1
  298. package/dist/runtime.mjs +2 -2
  299. package/dist/scheduled-publish-BMljtY5G.d.mts +11 -0
  300. package/dist/scheduled-publish-BMljtY5G.d.mts.map +1 -0
  301. package/dist/{schema-BGwx8AQY.mjs → schema-BfJ7bIXH.mjs} +5 -5
  302. package/dist/{schema-BGwx8AQY.mjs.map → schema-BfJ7bIXH.mjs.map} +1 -1
  303. package/dist/{search-Gl747zMP.mjs → search-C7t3PH1J.mjs} +6 -4
  304. package/dist/search-C7t3PH1J.mjs.map +1 -0
  305. package/dist/{sections-C-umuuLj.mjs → sections-Dm0CVX23.mjs} +3 -3
  306. package/dist/{sections-C-umuuLj.mjs.map → sections-Dm0CVX23.mjs.map} +1 -1
  307. package/dist/seed/index.d.mts +2 -2
  308. package/dist/seed/index.mjs +15 -15
  309. package/dist/{seo-BNzkiK_W.mjs → seo-Dd3tbY_k.mjs} +3 -3
  310. package/dist/{seo-BNzkiK_W.mjs.map → seo-Dd3tbY_k.mjs.map} +1 -1
  311. package/dist/{service-CQHK_10l.mjs → service-CTrqp_Jy.mjs} +2 -2
  312. package/dist/{service-CQHK_10l.mjs.map → service-CTrqp_Jy.mjs.map} +1 -1
  313. package/dist/{settings-C4tXRYiG.mjs → settings-BX8cWBus.mjs} +4 -4
  314. package/dist/{settings-C4tXRYiG.mjs.map → settings-BX8cWBus.mjs.map} +1 -1
  315. package/dist/{settings-fPSR6dJa.mjs → settings-CZ7ZP9cW.mjs} +3 -3
  316. package/dist/{settings-fPSR6dJa.mjs.map → settings-CZ7ZP9cW.mjs.map} +1 -1
  317. package/dist/storage/local.d.mts +1 -1
  318. package/dist/storage/s3.d.mts +1 -1
  319. package/dist/{taxonomies-DbAtL6m4.mjs → taxonomies-DChKcVxf.mjs} +5 -4
  320. package/dist/taxonomies-DChKcVxf.mjs.map +1 -0
  321. package/dist/{taxonomies-n8w72lLQ.mjs → taxonomies-ckPjz-6d.mjs} +75 -20
  322. package/dist/taxonomies-ckPjz-6d.mjs.map +1 -0
  323. package/dist/{taxonomy-BBUlGug5.mjs → taxonomy-Cru-he6s.mjs} +4 -4
  324. package/dist/{taxonomy-BBUlGug5.mjs.map → taxonomy-Cru-he6s.mjs.map} +1 -1
  325. package/dist/{transport-BZ-03aFT.d.mts → transport-Blrl2k_o.d.mts} +1 -1
  326. package/dist/{transport-BZ-03aFT.d.mts.map → transport-Blrl2k_o.d.mts.map} +1 -1
  327. package/dist/{types-h2Cwbzi2.d.mts → types-BYnDBVwe.d.mts} +24 -5
  328. package/dist/{types-h2Cwbzi2.d.mts.map → types-BYnDBVwe.d.mts.map} +1 -1
  329. package/dist/{types-BG8_XTLj.d.mts → types-BkZ8DUEI.d.mts} +1 -1
  330. package/dist/{types-BG8_XTLj.d.mts.map → types-BkZ8DUEI.d.mts.map} +1 -1
  331. package/dist/{types-DrYMm9s5.d.mts → types-ByChcBgE.d.mts} +1 -1
  332. package/dist/{types-DrYMm9s5.d.mts.map → types-ByChcBgE.d.mts.map} +1 -1
  333. package/dist/{types-BWqGVhFn.d.mts → types-CvuKO5Pn.d.mts} +1 -1
  334. package/dist/{types-BWqGVhFn.d.mts.map → types-CvuKO5Pn.d.mts.map} +1 -1
  335. package/dist/{types-CmI1OyQg.mjs → types-DU4TSFS5.mjs} +2 -2
  336. package/dist/{types-CmI1OyQg.mjs.map → types-DU4TSFS5.mjs.map} +1 -1
  337. package/dist/{types-CUsXGRVj.d.mts → types-Dbqff978.d.mts} +1 -1
  338. package/dist/{types-CUsXGRVj.d.mts.map → types-Dbqff978.d.mts.map} +1 -1
  339. package/dist/{types-fS7-VTdR.d.mts → types-Y09-wtyU.d.mts} +1 -1
  340. package/dist/{types-fS7-VTdR.d.mts.map → types-Y09-wtyU.d.mts.map} +1 -1
  341. package/dist/{types-B-gIxFCE.d.mts → types-xIfVRNLp.d.mts} +38 -1
  342. package/dist/types-xIfVRNLp.d.mts.map +1 -0
  343. package/dist/{user-JAuc8VUf.mjs → user-DgGbKL9s.mjs} +3 -3
  344. package/dist/{user-JAuc8VUf.mjs.map → user-DgGbKL9s.mjs.map} +1 -1
  345. package/dist/{validate-Va_An3qb.d.mts → validate-9ECmtEpJ.d.mts} +10 -5
  346. package/dist/{validate-Va_An3qb.d.mts.map → validate-9ECmtEpJ.d.mts.map} +1 -1
  347. package/dist/{validate-BzXHWnkV.mjs → validate-CRkcYZAR.mjs} +2 -2
  348. package/dist/{validate-BzXHWnkV.mjs.map → validate-CRkcYZAR.mjs.map} +1 -1
  349. package/dist/{validation-B6DKPTtU.mjs → validation-sR26SOwD.mjs} +5 -5
  350. package/dist/{validation-B6DKPTtU.mjs.map → validation-sR26SOwD.mjs.map} +1 -1
  351. package/dist/version-CrqhKGWn.mjs +7 -0
  352. package/dist/{version-DHdCA24u.mjs.map → version-CrqhKGWn.mjs.map} +1 -1
  353. package/dist/{widgets-C2RbFN0G.mjs → widgets-DRgtn7Cl.mjs} +2 -2
  354. package/dist/{widgets-C2RbFN0G.mjs.map → widgets-DRgtn7Cl.mjs.map} +1 -1
  355. package/dist/{zod-generator-xEHODMJf.mjs → zod-generator-C5JaV--i.mjs} +6 -3
  356. package/dist/zod-generator-C5JaV--i.mjs.map +1 -0
  357. package/package.json +8 -8
  358. package/src/api/handlers/content.ts +59 -16
  359. package/src/api/handlers/plugins.ts +77 -10
  360. package/src/api/handlers/taxonomies.ts +5 -1
  361. package/src/astro/integration/virtual-modules.ts +15 -0
  362. package/src/astro/integration/vite-config.ts +19 -1
  363. package/src/astro/middleware/auth.ts +1 -0
  364. package/src/astro/middleware.ts +1 -0
  365. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +6 -1
  366. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +6 -1
  367. package/src/astro/routes/api/admin/plugins/[id]/index.ts +1 -0
  368. package/src/astro/routes/api/admin/plugins/index.ts +1 -0
  369. package/src/astro/routes/api/manifest.ts +20 -1
  370. package/src/astro/routes/api/setup/dev-bypass.ts +7 -2
  371. package/src/astro/routes/sitemap-[collection].xml.ts +5 -4
  372. package/src/astro/types.ts +4 -0
  373. package/src/cli/commands/seed.ts +1 -1
  374. package/src/components/EmDashHead.astro +23 -3
  375. package/src/components/JsonLdScript.astro +9 -0
  376. package/src/components/LiveSearch.astro +40 -4
  377. package/src/components/live-search-routing.ts +30 -0
  378. package/src/database/migrations/036_i18n_menus_and_taxonomies.ts +39 -18
  379. package/src/database/migrations/046_media_usage_index.ts +115 -0
  380. package/src/database/migrations/047_restore_taxonomy_parent_index.ts +29 -0
  381. package/src/database/migrations/048_restore_content_taxonomies_term_index.ts +32 -0
  382. package/src/database/migrations/runner.ts +6 -0
  383. package/src/database/repositories/media-usage.ts +444 -0
  384. package/src/database/types.ts +39 -0
  385. package/src/emdash-runtime.ts +61 -52
  386. package/src/index.ts +3 -0
  387. package/src/loader.ts +110 -31
  388. package/src/media/usage/extractor.ts +302 -0
  389. package/src/media/usage/types.ts +46 -0
  390. package/src/object-cache/index.ts +8 -2
  391. package/src/page/metadata.ts +23 -3
  392. package/src/plugin-types.ts +10 -0
  393. package/src/plugins/define-plugin.ts +14 -5
  394. package/src/plugins/hooks.ts +53 -65
  395. package/src/plugins/index.ts +5 -0
  396. package/src/plugins/manager.ts +22 -0
  397. package/src/plugins/manifest-schema.ts +2 -0
  398. package/src/plugins/types.ts +35 -3
  399. package/src/schema/zod-generator.ts +9 -1
  400. package/src/search/query.ts +3 -0
  401. package/src/search/types.ts +2 -0
  402. package/src/seed/apply.ts +8 -2
  403. package/src/seed/types.ts +6 -1
  404. package/src/taxonomies/index.ts +121 -18
  405. package/dist/api-D2_sbavn.mjs.map +0 -1
  406. package/dist/apply-Bk2mAuLn.mjs.map +0 -1
  407. package/dist/index-Cz6_JBL3.d.mts.map +0 -1
  408. package/dist/loader-DrpofRon.mjs.map +0 -1
  409. package/dist/manifest-schema-BOfPXse0.mjs.map +0 -1
  410. package/dist/menus-CxqJ-z-N.mjs.map +0 -1
  411. package/dist/object-cache-SEb2IM4Z.mjs.map +0 -1
  412. package/dist/runner-BsquExlK.mjs.map +0 -1
  413. package/dist/search-Gl747zMP.mjs.map +0 -1
  414. package/dist/taxonomies-DbAtL6m4.mjs.map +0 -1
  415. package/dist/taxonomies-n8w72lLQ.mjs.map +0 -1
  416. package/dist/types-B-gIxFCE.d.mts.map +0 -1
  417. package/dist/version-DHdCA24u.mjs +0 -7
  418. package/dist/zod-generator-xEHODMJf.mjs.map +0 -1
@@ -22,11 +22,6 @@ import type {
22
22
  PluginStorageConfig,
23
23
  } from "./types.js";
24
24
 
25
- // Plugin ID validation patterns
26
- const SIMPLE_ID = /^[a-z0-9-]+$/;
27
- const SCOPED_ID = /^@[a-z0-9-]+\/[a-z0-9-]+$/;
28
- const SEMVER_PATTERN = /^\d+\.\d+\.\d+/;
29
-
30
25
  /**
31
26
  * Define a native EmDash plugin.
32
27
  *
@@ -94,6 +89,20 @@ export function definePlugin<TStorage extends PluginStorageConfig>(
94
89
  function defineNativePlugin<TStorage extends PluginStorageConfig>(
95
90
  definition: PluginDefinition<TStorage>,
96
91
  ): ResolvedPlugin<TStorage> {
92
+ // Declared function-local (not module scope) on purpose. Under
93
+ // `ssr.noExternal` the worker entry can instantiate native plugins during a
94
+ // circular module init, reaching this function before module-scope consts
95
+ // initialize -> "Cannot access 'SIMPLE_ID' before initialization" -> every
96
+ // route 500s on Cloudflare Workers. Call-time consts evaluate after the
97
+ // literals are parsed, so the temporal dead zone cannot occur regardless of
98
+ // bundle ordering. See #1370.
99
+ // oxlint-disable-next-line e18e/prefer-static-regex -- call-time on purpose (see #1370)
100
+ const SIMPLE_ID = /^[a-z0-9-]+$/;
101
+ // oxlint-disable-next-line e18e/prefer-static-regex -- call-time on purpose (see #1370)
102
+ const SCOPED_ID = /^@[a-z0-9-]+\/[a-z0-9-]+$/;
103
+ // oxlint-disable-next-line e18e/prefer-static-regex -- call-time on purpose (see #1370)
104
+ const SEMVER_PATTERN = /^\d+\.\d+\.\d+/;
105
+
97
106
  const {
98
107
  id,
99
108
  version,
@@ -17,7 +17,7 @@ import type {
17
17
  PluginContext,
18
18
  ContentHookEvent,
19
19
  ContentDeleteEvent,
20
- ContentPublishStateChangeEvent,
20
+ ContentStateChangeEvent,
21
21
  MediaUploadEvent,
22
22
  MediaAfterUploadEvent,
23
23
  LifecycleEvent,
@@ -33,7 +33,9 @@ import type {
33
33
  ContentAfterDeleteHandler,
34
34
  ContentAfterPublishHandler,
35
35
  ContentAfterRestoreHandler,
36
+ ContentAfterScheduleHandler,
36
37
  ContentAfterUnpublishHandler,
38
+ ContentAfterUnscheduleHandler,
37
39
  MediaBeforeUploadHandler,
38
40
  MediaAfterUploadHandler,
39
41
  LifecycleHandler,
@@ -68,6 +70,8 @@ type HookNameV2 =
68
70
  | "content:afterPublish"
69
71
  | "content:afterUnpublish"
70
72
  | "content:afterRestore"
73
+ | "content:afterSchedule"
74
+ | "content:afterUnschedule"
71
75
  | "media:beforeUpload"
72
76
  | "media:afterUpload"
73
77
  | "cron"
@@ -84,6 +88,13 @@ type HookNameV2 =
84
88
  /**
85
89
  * Map from hook name to handler type — used for type-safe hook retrieval
86
90
  */
91
+ type ContentStateChangeHookName =
92
+ | "content:afterPublish"
93
+ | "content:afterUnpublish"
94
+ | "content:afterRestore"
95
+ | "content:afterSchedule"
96
+ | "content:afterUnschedule";
97
+
87
98
  interface HookHandlerMap {
88
99
  "plugin:install": LifecycleHandler;
89
100
  "plugin:activate": LifecycleHandler;
@@ -96,6 +107,8 @@ interface HookHandlerMap {
96
107
  "content:afterPublish": ContentAfterPublishHandler;
97
108
  "content:afterUnpublish": ContentAfterUnpublishHandler;
98
109
  "content:afterRestore": ContentAfterRestoreHandler;
110
+ "content:afterSchedule": ContentAfterScheduleHandler;
111
+ "content:afterUnschedule": ContentAfterUnscheduleHandler;
99
112
  "media:beforeUpload": MediaBeforeUploadHandler;
100
113
  "media:afterUpload": MediaAfterUploadHandler;
101
114
  cron: CronHandler;
@@ -224,6 +237,8 @@ export class HookPipeline {
224
237
  this.registerPluginHook(plugin, "content:afterPublish");
225
238
  this.registerPluginHook(plugin, "content:afterUnpublish");
226
239
  this.registerPluginHook(plugin, "content:afterRestore");
240
+ this.registerPluginHook(plugin, "content:afterSchedule");
241
+ this.registerPluginHook(plugin, "content:afterUnschedule");
227
242
  this.registerPluginHook(plugin, "media:beforeUpload");
228
243
  this.registerPluginHook(plugin, "media:afterUpload");
229
244
  this.registerPluginHook(plugin, "cron");
@@ -269,6 +284,8 @@ export class HookPipeline {
269
284
  ["content:afterPublish", "content:read"],
270
285
  ["content:afterUnpublish", "content:read"],
271
286
  ["content:afterRestore", "content:read"],
287
+ ["content:afterSchedule", "content:read"],
288
+ ["content:afterUnschedule", "content:read"],
272
289
  // Media
273
290
  ["media:beforeUpload", "media:write"],
274
291
  ["media:afterUpload", "media:read"],
@@ -653,18 +670,19 @@ export class HookPipeline {
653
670
  }
654
671
 
655
672
  /**
656
- * Run content:afterPublish hooks (fire-and-forget).
673
+ * Run content state-change hooks that all share the same event shape.
657
674
  */
658
- async runContentAfterPublish(
675
+ private async runContentStateChangeHook(
676
+ name: ContentStateChangeHookName,
659
677
  content: Record<string, unknown>,
660
678
  collection: string,
661
679
  ): Promise<HookResult<void>[]> {
662
- const hooks = this.getTypedHooks("content:afterPublish");
680
+ const hooks = this.getTypedHooks(name);
663
681
  const results: HookResult<void>[] = [];
664
682
 
665
683
  for (const hook of hooks) {
666
684
  const { handler } = hook;
667
- const event: ContentPublishStateChangeEvent = { content, collection };
685
+ const event: ContentStateChangeEvent = { content, collection };
668
686
  const ctx = this.getContext(hook.pluginId);
669
687
  const start = Date.now();
670
688
 
@@ -692,6 +710,16 @@ export class HookPipeline {
692
710
  return results;
693
711
  }
694
712
 
713
+ /**
714
+ * Run content:afterPublish hooks (fire-and-forget).
715
+ */
716
+ async runContentAfterPublish(
717
+ content: Record<string, unknown>,
718
+ collection: string,
719
+ ): Promise<HookResult<void>[]> {
720
+ return this.runContentStateChangeHook("content:afterPublish", content, collection);
721
+ }
722
+
695
723
  /**
696
724
  * Run content:afterUnpublish hooks (fire-and-forget).
697
725
  */
@@ -699,37 +727,7 @@ export class HookPipeline {
699
727
  content: Record<string, unknown>,
700
728
  collection: string,
701
729
  ): Promise<HookResult<void>[]> {
702
- const hooks = this.getTypedHooks("content:afterUnpublish");
703
- const results: HookResult<void>[] = [];
704
-
705
- for (const hook of hooks) {
706
- const { handler } = hook;
707
- const event: ContentPublishStateChangeEvent = { content, collection };
708
- const ctx = this.getContext(hook.pluginId);
709
- const start = Date.now();
710
-
711
- try {
712
- await this.executeWithTimeout(() => handler(event, ctx), hook.timeout);
713
- results.push({
714
- success: true,
715
- pluginId: hook.pluginId,
716
- duration: Date.now() - start,
717
- });
718
- } catch (error) {
719
- results.push({
720
- success: false,
721
- error: error instanceof Error ? error : new Error(String(error)),
722
- pluginId: hook.pluginId,
723
- duration: Date.now() - start,
724
- });
725
-
726
- if (hook.errorPolicy === "abort") {
727
- throw error;
728
- }
729
- }
730
- }
731
-
732
- return results;
730
+ return this.runContentStateChangeHook("content:afterUnpublish", content, collection);
733
731
  }
734
732
 
735
733
  /**
@@ -739,37 +737,27 @@ export class HookPipeline {
739
737
  content: Record<string, unknown>,
740
738
  collection: string,
741
739
  ): Promise<HookResult<void>[]> {
742
- const hooks = this.getTypedHooks("content:afterRestore");
743
- const results: HookResult<void>[] = [];
744
-
745
- for (const hook of hooks) {
746
- const { handler } = hook;
747
- const event: ContentPublishStateChangeEvent = { content, collection };
748
- const ctx = this.getContext(hook.pluginId);
749
- const start = Date.now();
750
-
751
- try {
752
- await this.executeWithTimeout(() => handler(event, ctx), hook.timeout);
753
- results.push({
754
- success: true,
755
- pluginId: hook.pluginId,
756
- duration: Date.now() - start,
757
- });
758
- } catch (error) {
759
- results.push({
760
- success: false,
761
- error: error instanceof Error ? error : new Error(String(error)),
762
- pluginId: hook.pluginId,
763
- duration: Date.now() - start,
764
- });
740
+ return this.runContentStateChangeHook("content:afterRestore", content, collection);
741
+ }
765
742
 
766
- if (hook.errorPolicy === "abort") {
767
- throw error;
768
- }
769
- }
770
- }
743
+ /**
744
+ * Run content:afterSchedule hooks (fire-and-forget).
745
+ */
746
+ async runContentAfterSchedule(
747
+ content: Record<string, unknown>,
748
+ collection: string,
749
+ ): Promise<HookResult<void>[]> {
750
+ return this.runContentStateChangeHook("content:afterSchedule", content, collection);
751
+ }
771
752
 
772
- return results;
753
+ /**
754
+ * Run content:afterUnschedule hooks (fire-and-forget).
755
+ */
756
+ async runContentAfterUnschedule(
757
+ content: Record<string, unknown>,
758
+ collection: string,
759
+ ): Promise<HookResult<void>[]> {
760
+ return this.runContentStateChangeHook("content:afterUnschedule", content, collection);
773
761
  }
774
762
 
775
763
  // =========================================================================
@@ -128,6 +128,9 @@ export type {
128
128
  ContentHookEvent,
129
129
  ContentDeleteEvent,
130
130
  ContentPublishStateChangeEvent,
131
+ ContentRestoreStateChangeEvent,
132
+ ContentScheduleStateChangeEvent,
133
+ ContentStateChangeEvent,
131
134
  MediaUploadEvent,
132
135
  MediaAfterUploadEvent,
133
136
  LifecycleEvent,
@@ -149,6 +152,8 @@ export type {
149
152
  ContentBeforeDeleteHandler,
150
153
  ContentAfterDeleteHandler,
151
154
  ContentAfterRestoreHandler,
155
+ ContentAfterScheduleHandler,
156
+ ContentAfterUnscheduleHandler,
152
157
  MediaBeforeUploadHandler,
153
158
  MediaAfterUploadHandler,
154
159
  LifecycleHandler,
@@ -381,6 +381,28 @@ export class PluginManager {
381
381
  return this.hookPipeline!.runContentAfterRestore(content, collection);
382
382
  }
383
383
 
384
+ /**
385
+ * Run content:afterSchedule hooks across all active plugins
386
+ */
387
+ async runContentAfterSchedule(
388
+ content: Record<string, unknown>,
389
+ collection: string,
390
+ ): Promise<HookResult<void>[]> {
391
+ this.ensureInitialized();
392
+ return this.hookPipeline!.runContentAfterSchedule(content, collection);
393
+ }
394
+
395
+ /**
396
+ * Run content:afterUnschedule hooks across all active plugins
397
+ */
398
+ async runContentAfterUnschedule(
399
+ content: Record<string, unknown>,
400
+ collection: string,
401
+ ): Promise<HookResult<void>[]> {
402
+ this.ensureInitialized();
403
+ return this.hookPipeline!.runContentAfterUnschedule(content, collection);
404
+ }
405
+
384
406
  /**
385
407
  * Run media:beforeUpload hooks across all active plugins
386
408
  */
@@ -98,6 +98,8 @@ export const HOOK_NAMES = [
98
98
  "content:afterPublish",
99
99
  "content:afterUnpublish",
100
100
  "content:afterRestore",
101
+ "content:afterSchedule",
102
+ "content:afterUnschedule",
101
103
  "media:beforeUpload",
102
104
  "media:afterUpload",
103
105
  "cron",
@@ -725,13 +725,29 @@ export interface ContentDeleteEvent {
725
725
  }
726
726
 
727
727
  /**
728
- * Content publish state change hook event (fired after publish or unpublish)
728
+ * Content state-change hook event (fired after publish, unpublish, restore,
729
+ * schedule, or unschedule).
729
730
  */
730
- export interface ContentPublishStateChangeEvent {
731
+ export interface ContentStateChangeEvent {
731
732
  content: Record<string, unknown>;
732
733
  collection: string;
733
734
  }
734
735
 
736
+ /**
737
+ * Content publish/unpublish hook event.
738
+ */
739
+ export type ContentPublishStateChangeEvent = ContentStateChangeEvent;
740
+
741
+ /**
742
+ * Content restore hook event.
743
+ */
744
+ export type ContentRestoreStateChangeEvent = ContentStateChangeEvent;
745
+
746
+ /**
747
+ * Content schedule/unschedule hook event.
748
+ */
749
+ export type ContentScheduleStateChangeEvent = ContentStateChangeEvent;
750
+
735
751
  /**
736
752
  * Media hook event
737
753
  */
@@ -792,7 +808,17 @@ export type ContentAfterUnpublishHandler = (
792
808
  ) => Promise<void>;
793
809
 
794
810
  export type ContentAfterRestoreHandler = (
795
- event: ContentPublishStateChangeEvent,
811
+ event: ContentRestoreStateChangeEvent,
812
+ ctx: PluginContext,
813
+ ) => Promise<void>;
814
+
815
+ export type ContentAfterScheduleHandler = (
816
+ event: ContentScheduleStateChangeEvent,
817
+ ctx: PluginContext,
818
+ ) => Promise<void>;
819
+
820
+ export type ContentAfterUnscheduleHandler = (
821
+ event: ContentScheduleStateChangeEvent,
796
822
  ctx: PluginContext,
797
823
  ) => Promise<void>;
798
824
 
@@ -982,6 +1008,10 @@ export interface PluginHooks {
982
1008
  | HookConfig<ContentAfterUnpublishHandler>
983
1009
  | ContentAfterUnpublishHandler;
984
1010
  "content:afterRestore"?: HookConfig<ContentAfterRestoreHandler> | ContentAfterRestoreHandler;
1011
+ "content:afterSchedule"?: HookConfig<ContentAfterScheduleHandler> | ContentAfterScheduleHandler;
1012
+ "content:afterUnschedule"?:
1013
+ | HookConfig<ContentAfterUnscheduleHandler>
1014
+ | ContentAfterUnscheduleHandler;
985
1015
 
986
1016
  // Media hooks
987
1017
  "media:beforeUpload"?: HookConfig<MediaBeforeUploadHandler> | MediaBeforeUploadHandler;
@@ -1302,6 +1332,8 @@ export interface ResolvedPluginHooks {
1302
1332
  "content:afterPublish"?: ResolvedHook<ContentAfterPublishHandler>;
1303
1333
  "content:afterUnpublish"?: ResolvedHook<ContentAfterUnpublishHandler>;
1304
1334
  "content:afterRestore"?: ResolvedHook<ContentAfterRestoreHandler>;
1335
+ "content:afterSchedule"?: ResolvedHook<ContentAfterScheduleHandler>;
1336
+ "content:afterUnschedule"?: ResolvedHook<ContentAfterUnscheduleHandler>;
1305
1337
  "media:beforeUpload"?: ResolvedHook<MediaBeforeUploadHandler>;
1306
1338
  "media:afterUpload"?: ResolvedHook<MediaAfterUploadHandler>;
1307
1339
  cron?: ResolvedHook<CronHandler>;
@@ -86,7 +86,15 @@ function getBaseSchema(type: FieldType, field: Field): ZodTypeAny {
86
86
  return z.preprocess((v) => (v === 0 || v === 1 ? Boolean(v) : v), z.boolean());
87
87
 
88
88
  case "datetime":
89
- return z.string().datetime().or(z.string().date());
89
+ // Accept every value that legitimately round-trips through the admin
90
+ // and seeds: ISO with `Z`, ISO with a timezone offset, a naive
91
+ // datetime (`YYYY-MM-DDTHH:mm[:ss]` -- what `<input type="datetime-local">`
92
+ // and many seeds produce), and a date-only value. The admin re-sends
93
+ // every loaded field on autosave, so a stored naive datetime must
94
+ // validate or the entry becomes unsavable through its own editor
95
+ // (#1368; same class as #867). `z.iso.*` retains semantic validation,
96
+ // so impossible dates are still rejected.
97
+ return z.iso.datetime({ offset: true, local: true }).or(z.iso.date());
90
98
 
91
99
  case "select": {
92
100
  const options = field.validation?.options;
@@ -359,10 +359,12 @@ export async function getSuggestions(
359
359
  try {
360
360
  results = await sql<{
361
361
  id: string;
362
+ slug: string | null;
362
363
  title: string;
363
364
  }>`
364
365
  SELECT
365
366
  c.id,
367
+ c.slug,
366
368
  c.title
367
369
  FROM "${sql.raw(ftsTable)}" f
368
370
  JOIN "${sql.raw(contentTable)}" c ON f.id = c.id
@@ -389,6 +391,7 @@ export async function getSuggestions(
389
391
  suggestions.push({
390
392
  collection,
391
393
  id: row.id,
394
+ slug: row.slug,
392
395
  title: row.title,
393
396
  });
394
397
  }
@@ -101,6 +101,8 @@ export interface Suggestion {
101
101
  collection: string;
102
102
  /** Entry ID */
103
103
  id: string;
104
+ /** Entry slug, when available */
105
+ slug?: string | null;
104
106
  /** Entry title */
105
107
  title: string;
106
108
  }
package/src/seed/apply.ts CHANGED
@@ -296,7 +296,7 @@ export async function applySeed(
296
296
  defSeedIdMap.set(taxonomy.id, { id: defId, translationGroup: defTranslationGroup });
297
297
 
298
298
  // Create terms (if provided)
299
- if (taxonomy.terms && taxonomy.terms.length > 0) {
299
+ if (includeContent && taxonomy.terms && taxonomy.terms.length > 0) {
300
300
  const termRepo = new TaxonomyRepository(db);
301
301
 
302
302
  if (taxonomy.hierarchical) {
@@ -346,10 +346,16 @@ export async function applySeed(
346
346
  }
347
347
  }
348
348
  }
349
+
350
+ // Seeded/updated defs change which taxonomies exist — clear the
351
+ // isolate-wide defs + names caches so later reads in this isolate
352
+ // (e.g. an auto-seed triggered mid-request) reflect them immediately.
353
+ const { invalidateTaxonomyDefsCache } = await import("../taxonomies/index.js");
354
+ invalidateTaxonomyDefsCache();
349
355
  }
350
356
 
351
357
  // 6. Bylines
352
- if (seed.bylines) {
358
+ if (includeContent && seed.bylines) {
353
359
  const bylineRepo = new BylineRepository(db);
354
360
  for (const byline of seed.bylines) {
355
361
  const existing = await bylineRepo.findBySlug(byline.slug);
package/src/seed/types.ts CHANGED
@@ -288,7 +288,12 @@ export interface SeedBylineCredit {
288
288
  * Options for applying a seed
289
289
  */
290
290
  export interface SeedApplyOptions {
291
- /** Include sample content (default: false) */
291
+ /**
292
+ * Include sample data: content entries, bylines, and taxonomy terms
293
+ * (default: false). Schema and structure (collections, fields, taxonomy
294
+ * definitions, menus, settings, redirects, widget areas, sections) are
295
+ * always applied.
296
+ */
292
297
  includeContent?: boolean;
293
298
 
294
299
  /** How to handle conflicts (default: "skip") */
@@ -12,14 +12,16 @@
12
12
  */
13
13
 
14
14
  import { resolveLocale, resolveLocaleChain } from "../i18n/resolve.js";
15
- import { getDb } from "../loader.js";
15
+ import { getDb, resetTaxonomyNamesCache } from "../loader.js";
16
16
  import {
17
17
  cachedQuery,
18
18
  CacheNamespace,
19
19
  contentNamespace,
20
20
  invalidateTaxonomyObjectCache,
21
+ isObjectCacheActive,
21
22
  } from "../object-cache/index.js";
22
23
  import { peekRequestCache, requestCached, setRequestCacheEntry } from "../request-cache.js";
24
+ import { getRequestContext } from "../request-context.js";
23
25
  import { chunks, SQL_BATCH_SIZE } from "../utils/chunks.js";
24
26
  import { isMissingTableError } from "../utils/db-errors.js";
25
27
  import type { TaxonomyDef, TaxonomyTerm, TaxonomyTermRow } from "./types.js";
@@ -28,35 +30,136 @@ export interface TaxonomyQueryOptions {
28
30
  locale?: string;
29
31
  }
30
32
 
33
+ /** Invalidate cached taxonomy term data and any content that hydrates terms. */
34
+ export function invalidateTermCache(): void {
35
+ invalidateTaxonomyObjectCache();
36
+ }
37
+
31
38
  /**
32
- * Invalidate cached taxonomy data in the distributed object cache (and any
33
- * content that hydrates taxonomy terms). The legacy in-isolate term cache was
34
- * removed, so this used to be a no-op; it now drives object-cache invalidation.
39
+ * Worker-isolate cache for taxonomy definitions, keyed by resolved locale.
40
+ *
41
+ * Taxonomy *definitions* (the "category"/"tag" taxonomies themselves, not
42
+ * their terms) are read on every public render that hydrates entry terms —
43
+ * `getAllTermsForEntries` → `getCollectionTaxonomyNames` → `getTaxonomyDefs` —
44
+ * but change extremely rarely: they're created via the admin API or applied
45
+ * from a seed, and there is no edit/delete-def path. Caching them across the
46
+ * isolate lifetime drops the per-render `SELECT * FROM _emdash_taxonomy_defs`
47
+ * to once-per-isolate.
48
+ *
49
+ * Stored on globalThis behind a Symbol key (same pattern as
50
+ * `settings/index.ts`) so the bundler duplicating this module across SSR
51
+ * chunks can't produce two independent caches.
52
+ *
53
+ * When the distributed object cache is configured, it is authoritative and this
54
+ * fallback is bypassed so cross-isolate epoch invalidation cannot be undercut
55
+ * by stale per-isolate data on an object-cache miss.
56
+ *
57
+ * **Isolated databases bypass the cache.** Playground / DO preview requests
58
+ * set `requestContext.dbIsIsolated`; they point at a divergent schema, so we
59
+ * skip both reading and writing the global holder and fall back to the
60
+ * per-request cache (same precedent as `getTaxonomyNames` / byline field defs).
35
61
  */
36
- export function invalidateTermCache(): void {
62
+ interface TaxonomyDefsHolder {
63
+ version: number;
64
+ /** locale key ("*" for "all locales") → { version it was fetched at, promise }. */
65
+ cache: Map<string, { version: number; promise: Promise<TaxonomyDef[]> }>;
66
+ }
67
+
68
+ const TAXONOMY_DEFS_CACHE_KEY = Symbol.for("emdash:taxonomy-defs");
69
+ const taxonomyDefsStore = globalThis as Record<symbol, unknown>;
70
+ const defsHolder: TaxonomyDefsHolder =
71
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see settings/index.ts)
72
+ (taxonomyDefsStore[TAXONOMY_DEFS_CACHE_KEY] as TaxonomyDefsHolder | undefined) ??
73
+ (() => {
74
+ const h: TaxonomyDefsHolder = { version: 0, cache: new Map() };
75
+ taxonomyDefsStore[TAXONOMY_DEFS_CACHE_KEY] = h;
76
+ return h;
77
+ })();
78
+
79
+ /**
80
+ * Invalidate the isolate-wide taxonomy-definitions cache (and the related
81
+ * loader taxonomy-names cache). Called from every taxonomy-def write path
82
+ * (`handleTaxonomyCreate`, seed application). Other isolates refresh on their
83
+ * next recycle — staleness bounded by isolate lifetime.
84
+ */
85
+ export function invalidateTaxonomyDefsCache(): void {
86
+ defsHolder.version++;
87
+ defsHolder.cache.clear();
88
+ resetTaxonomyNamesCache();
37
89
  invalidateTaxonomyObjectCache();
38
90
  }
39
91
 
92
+ /**
93
+ * Test/internal helper: clear the per-isolate taxonomy-defs cache. Useful for
94
+ * unit tests that insert defs directly and need to force a refetch without
95
+ * going through a write path. Production code should rely on
96
+ * `invalidateTaxonomyDefsCache()`.
97
+ */
98
+ export function resetTaxonomyDefsCacheForTests(): void {
99
+ defsHolder.version++;
100
+ defsHolder.cache.clear();
101
+ }
102
+
103
+ /**
104
+ * Fetch taxonomy definitions straight from the database (no caching).
105
+ */
106
+ async function fetchTaxonomyDefs(locale: string | undefined): Promise<TaxonomyDef[]> {
107
+ const db = await getDb();
108
+ let query = db.selectFrom("_emdash_taxonomy_defs").selectAll();
109
+ if (locale !== undefined) query = query.where("locale", "=", locale);
110
+ const rows = await query.execute();
111
+ return rows.map(rowToTaxonomyDef);
112
+ }
113
+
114
+ /**
115
+ * Resolve taxonomy defs through the isolate fallback cache, bypassing it for
116
+ * isolated databases. The returned promise is cached (not the resolved value)
117
+ * so concurrent cold-isolate readers share one in-flight query; a rejection
118
+ * evicts the entry so the next caller retries.
119
+ */
120
+ function loadTaxonomyDefs(localeKey: string, locale: string | undefined): Promise<TaxonomyDef[]> {
121
+ if (getRequestContext()?.dbIsIsolated === true) {
122
+ return fetchTaxonomyDefs(locale);
123
+ }
124
+ const existing = defsHolder.cache.get(localeKey);
125
+ if (existing && existing.version === defsHolder.version) {
126
+ return existing.promise;
127
+ }
128
+ const version = defsHolder.version;
129
+ const promise = fetchTaxonomyDefs(locale).catch((error: unknown) => {
130
+ const current = defsHolder.cache.get(localeKey);
131
+ if (current && current.promise === promise) {
132
+ defsHolder.cache.delete(localeKey);
133
+ }
134
+ throw error;
135
+ });
136
+ defsHolder.cache.set(localeKey, { version, promise });
137
+ return promise;
138
+ }
139
+
40
140
  /**
41
141
  * Get every taxonomy definition. Definitions are per-locale (one row per
42
142
  * locale inside the same translation_group) — by default we resolve to the
43
143
  * active locale.
144
+ *
145
+ * Two-tier cache: per-request via `requestCached` (so a single render that
146
+ * hydrates terms for several collections pays at most one call), then
147
+ * per-isolate via the global holder (so warm renders issue zero queries).
148
+ * The `requestCached` key is unchanged so `getTaxonomyDef`'s peek still hits.
44
149
  */
45
150
  export async function getTaxonomyDefs(options: TaxonomyQueryOptions = {}): Promise<TaxonomyDef[]> {
46
151
  const locale = resolveLocale(options.locale);
47
- return requestCached(`taxonomy-defs:${locale ?? "*"}`, () =>
48
- cachedQuery({
49
- namespace: CacheNamespace.TAXONOMIES,
50
- key: `defs:${locale ?? "*"}`,
51
- load: async () => {
52
- const db = await getDb();
53
- let query = db.selectFrom("_emdash_taxonomy_defs").selectAll();
54
- if (locale !== undefined) query = query.where("locale", "=", locale);
55
- const rows = await query.execute();
56
- return rows.map(rowToTaxonomyDef);
57
- },
58
- }),
59
- );
152
+ const localeKey = locale ?? "*";
153
+ return requestCached(`taxonomy-defs:${localeKey}`, async () => {
154
+ if (await isObjectCacheActive()) {
155
+ return cachedQuery({
156
+ namespace: CacheNamespace.TAXONOMIES,
157
+ key: `defs:${localeKey}`,
158
+ load: () => fetchTaxonomyDefs(locale),
159
+ });
160
+ }
161
+ return loadTaxonomyDefs(localeKey, locale);
162
+ });
60
163
  }
61
164
 
62
165
  /**