emdash 0.21.0 → 0.23.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 (655) hide show
  1. package/dist/{adapters-BxSmgtbF.d.mts → adapters-DAAjOID4.d.mts} +1 -1
  2. package/dist/{adapters-BxSmgtbF.d.mts.map → adapters-DAAjOID4.d.mts.map} +1 -1
  3. package/dist/after-B1IIdH3Y.mjs +29 -0
  4. package/dist/after-B1IIdH3Y.mjs.map +1 -0
  5. package/dist/{allowed-origins-BqC8cul8.mjs → allowed-origins-D5FxMUo8.mjs} +2 -2
  6. package/dist/{allowed-origins-BqC8cul8.mjs.map → allowed-origins-D5FxMUo8.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +20 -19
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +2 -2
  11. package/dist/api/schemas/index.mjs +4 -4
  12. package/dist/{api-DxjIV2o8.mjs → api-BQ_yKRdG.mjs} +31 -25
  13. package/dist/api-BQ_yKRdG.mjs.map +1 -0
  14. package/dist/{api-tokens-BFFkB0jB.mjs → api-tokens-D6ppjIVi.mjs} +13 -3
  15. package/dist/api-tokens-D6ppjIVi.mjs.map +1 -0
  16. package/dist/{apply-CLjxheyb.mjs → apply-CWRyxIoO.mjs} +18 -18
  17. package/dist/{apply-CLjxheyb.mjs.map → apply-CWRyxIoO.mjs.map} +1 -1
  18. package/dist/astro/image-endpoint.d.mts +8 -0
  19. package/dist/astro/image-endpoint.d.mts.map +1 -0
  20. package/dist/astro/image-endpoint.mjs +55 -0
  21. package/dist/astro/image-endpoint.mjs.map +1 -0
  22. package/dist/astro/index.d.mts +36 -11
  23. package/dist/astro/index.d.mts.map +1 -1
  24. package/dist/astro/index.mjs +122 -26
  25. package/dist/astro/index.mjs.map +1 -1
  26. package/dist/astro/middleware/auth.d.mts +9 -9
  27. package/dist/astro/middleware/auth.d.mts.map +1 -1
  28. package/dist/astro/middleware/auth.mjs +12 -10
  29. package/dist/astro/middleware/auth.mjs.map +1 -1
  30. package/dist/astro/middleware/redirect.mjs +6 -6
  31. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  32. package/dist/astro/middleware/request-context.mjs +8 -6
  33. package/dist/astro/middleware/request-context.mjs.map +1 -1
  34. package/dist/astro/middleware/setup.mjs +1 -1
  35. package/dist/astro/middleware.d.mts +1 -1
  36. package/dist/astro/middleware.d.mts.map +1 -1
  37. package/dist/astro/middleware.mjs +444 -149
  38. package/dist/astro/middleware.mjs.map +1 -1
  39. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  40. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  41. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  42. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  43. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  44. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
  45. package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
  46. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
  47. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +18 -16
  48. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  49. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +18 -16
  50. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  51. package/dist/astro/routes/api/admin/bylines/index.mjs +18 -16
  52. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +15 -13
  54. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -6
  56. package/dist/astro/routes/api/admin/comments/_id_.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -10
  58. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -6
  60. package/dist/astro/routes/api/admin/comments/counts.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/comments/index.mjs +12 -10
  62. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  64. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  65. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  66. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  67. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +41 -39
  68. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +41 -39
  70. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +40 -38
  72. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +40 -38
  74. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +40 -38
  76. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/index.mjs +40 -38
  78. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +40 -38
  81. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +40 -38
  83. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +40 -38
  85. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +40 -38
  87. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +41 -39
  89. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +40 -38
  91. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +41 -39
  93. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs +40 -38
  95. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +40 -38
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  99. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +40 -38
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  102. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  103. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
  104. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  105. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  106. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  107. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  108. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  109. package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
  110. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  111. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  112. package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -11
  113. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  114. package/dist/astro/routes/api/auth/me.mjs +8 -8
  115. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  116. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  117. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  118. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  119. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  120. package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
  121. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  122. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  123. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  124. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  125. package/dist/astro/routes/api/auth/signup/request.mjs +11 -11
  126. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  127. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +16 -15
  128. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  129. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts +9 -0
  130. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts.map +1 -0
  131. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +179 -0
  132. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -0
  133. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  134. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
  135. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  136. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  137. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -13
  138. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
  139. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  140. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  141. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  142. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -15
  143. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  144. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  145. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
  146. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  147. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  148. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  149. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  150. package/dist/astro/routes/api/dashboard.mjs +10 -8
  151. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  152. package/dist/astro/routes/api/dev/emails.mjs +4 -4
  153. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  154. package/dist/astro/routes/api/import/probe.mjs +12 -12
  155. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  156. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  157. package/dist/astro/routes/api/import/wordpress/execute.mjs +17 -15
  158. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  159. package/dist/astro/routes/api/import/wordpress/media.mjs +10 -10
  160. package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
  161. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +10 -10
  162. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  163. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +12 -12
  164. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  165. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  166. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +19 -17
  167. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  168. package/dist/astro/routes/api/manifest.mjs +5 -5
  169. package/dist/astro/routes/api/mcp.mjs +213 -46
  170. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  171. package/dist/astro/routes/api/media/_id_/confirm.mjs +8 -8
  172. package/dist/astro/routes/api/media/_id_.mjs +8 -8
  173. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  174. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  175. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  176. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  177. package/dist/astro/routes/api/media/upload-url.mjs +10 -10
  178. package/dist/astro/routes/api/media.mjs +13 -13
  179. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -9
  180. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  181. package/dist/astro/routes/api/menus/_name_/items.mjs +11 -9
  182. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  183. package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -9
  184. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  185. package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -9
  186. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  187. package/dist/astro/routes/api/menus/_name_.mjs +11 -9
  188. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  189. package/dist/astro/routes/api/menus/index.mjs +11 -9
  190. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  191. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  192. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
  193. package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
  194. package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
  195. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  196. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
  197. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
  198. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  199. package/dist/astro/routes/api/openapi.json.mjs +5 -5
  200. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
  201. package/dist/astro/routes/api/redirects/404s/index.mjs +11 -11
  202. package/dist/astro/routes/api/redirects/404s/summary.mjs +11 -11
  203. package/dist/astro/routes/api/redirects/_id_.mjs +12 -12
  204. package/dist/astro/routes/api/redirects/index.mjs +12 -12
  205. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  206. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
  207. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +40 -38
  208. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  209. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +40 -38
  210. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  211. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +40 -38
  212. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  213. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +40 -38
  214. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  215. package/dist/astro/routes/api/schema/collections/index.mjs +40 -38
  216. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  217. package/dist/astro/routes/api/schema/index.mjs +9 -8
  218. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  219. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +40 -38
  220. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  221. package/dist/astro/routes/api/schema/orphans/index.mjs +40 -38
  222. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  223. package/dist/astro/routes/api/search/enable.mjs +11 -11
  224. package/dist/astro/routes/api/search/index.mjs +10 -10
  225. package/dist/astro/routes/api/search/rebuild.mjs +11 -11
  226. package/dist/astro/routes/api/search/stats.mjs +7 -7
  227. package/dist/astro/routes/api/search/suggest.mjs +10 -10
  228. package/dist/astro/routes/api/sections/_slug_.mjs +10 -10
  229. package/dist/astro/routes/api/sections/index.mjs +10 -10
  230. package/dist/astro/routes/api/settings/email.mjs +6 -6
  231. package/dist/astro/routes/api/settings.mjs +16 -15
  232. package/dist/astro/routes/api/settings.mjs.map +1 -1
  233. package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
  234. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  235. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  236. package/dist/astro/routes/api/setup/dev-bypass.mjs +30 -27
  237. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  238. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  239. package/dist/astro/routes/api/setup/index.mjs +30 -28
  240. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  241. package/dist/astro/routes/api/setup/status.mjs +5 -5
  242. package/dist/astro/routes/api/snapshot.d.mts.map +1 -1
  243. package/dist/astro/routes/api/snapshot.mjs +10 -9
  244. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  245. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -14
  246. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  247. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -14
  248. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  249. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -14
  250. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  251. package/dist/astro/routes/api/taxonomies/index.mjs +16 -14
  252. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  253. package/dist/astro/routes/api/themes/preview.mjs +8 -8
  254. package/dist/astro/routes/api/typegen.mjs +6 -6
  255. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  256. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  257. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  258. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  259. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -11
  260. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -11
  261. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
  262. package/dist/astro/routes/api/widget-areas/index.mjs +11 -11
  263. package/dist/astro/routes/api/widget-components.mjs +4 -4
  264. package/dist/astro/routes/robots.txt.mjs +10 -9
  265. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  266. package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -12
  267. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  268. package/dist/astro/routes/sitemap.xml.mjs +11 -10
  269. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  270. package/dist/astro/types.d.mts +16 -12
  271. package/dist/astro/types.d.mts.map +1 -1
  272. package/dist/auth/providers/github.d.mts +1 -1
  273. package/dist/auth/providers/google.d.mts +1 -1
  274. package/dist/{authorize-D5gfBVU5.mjs → authorize-Cse0k7B0.mjs} +2 -2
  275. package/dist/{authorize-D5gfBVU5.mjs.map → authorize-Cse0k7B0.mjs.map} +1 -1
  276. package/dist/{base64-CqR-7kqF.mjs → base64-CmWvODNW.mjs} +1 -1
  277. package/dist/{base64-CqR-7kqF.mjs.map → base64-CmWvODNW.mjs.map} +1 -1
  278. package/dist/{byline-V_Qp1Ziw.mjs → byline-DVo-liaP.mjs} +27 -76
  279. package/dist/byline-DVo-liaP.mjs.map +1 -0
  280. package/dist/{byline-fields-B0NO1yUB.mjs → byline-fields-B-KXkg5R.mjs} +3 -3
  281. package/dist/{byline-fields-B0NO1yUB.mjs.map → byline-fields-B-KXkg5R.mjs.map} +1 -1
  282. package/dist/{byline-fields-nBVqK_Ff.mjs → byline-fields-DaMKzkhO.mjs} +2 -2
  283. package/dist/{byline-fields-nBVqK_Ff.mjs.map → byline-fields-DaMKzkhO.mjs.map} +1 -1
  284. package/dist/{byline-fields-CQJRIQkn.d.mts → byline-fields-RFPkDLRw.d.mts} +56 -31
  285. package/dist/byline-fields-RFPkDLRw.d.mts.map +1 -0
  286. package/dist/{byline-registry-DedidtqC.mjs → byline-registry-BOjqDOim.mjs} +3 -3
  287. package/dist/{byline-registry-DedidtqC.mjs.map → byline-registry-BOjqDOim.mjs.map} +1 -1
  288. package/dist/{bylines-DfGDnred.mjs → bylines-f5ppBpD5.mjs} +8 -8
  289. package/dist/{bylines-DfGDnred.mjs.map → bylines-f5ppBpD5.mjs.map} +1 -1
  290. package/dist/{bylines-B2NWnIwS.mjs → bylines-pIKgc_TL.mjs} +10 -4
  291. package/dist/{bylines-B2NWnIwS.mjs.map → bylines-pIKgc_TL.mjs.map} +1 -1
  292. package/dist/{cache-DTTHWD8n.mjs → cache-Q6V4U-Xz.mjs} +3 -3
  293. package/dist/{cache-DTTHWD8n.mjs.map → cache-Q6V4U-Xz.mjs.map} +1 -1
  294. package/dist/{challenge-store-woE0bbCf.mjs → challenge-store-LhiqMccz.mjs} +1 -1
  295. package/dist/{challenge-store-woE0bbCf.mjs.map → challenge-store-LhiqMccz.mjs.map} +1 -1
  296. package/dist/{chunks-BerYVuve.mjs → chunks-SyjZaYwV.mjs} +2 -2
  297. package/dist/{chunks-BerYVuve.mjs.map → chunks-SyjZaYwV.mjs.map} +1 -1
  298. package/dist/cli/index.mjs +29 -27
  299. package/dist/cli/index.mjs.map +1 -1
  300. package/dist/client/cf-access.d.mts +1 -1
  301. package/dist/client/index.d.mts +1 -1
  302. package/dist/client/index.mjs +2 -1
  303. package/dist/client/index.mjs.map +1 -1
  304. package/dist/{comment-sqQxNpN3.mjs → comment-80UyJJUR.mjs} +11 -3
  305. package/dist/comment-80UyJJUR.mjs.map +1 -0
  306. package/dist/comment-reaction-Dyb-AutY.mjs +85 -0
  307. package/dist/comment-reaction-Dyb-AutY.mjs.map +1 -0
  308. package/dist/{comments-D2hNuxNa.mjs → comments-Cczx7AvD.mjs} +3 -3
  309. package/dist/{comments-D2hNuxNa.mjs.map → comments-Cczx7AvD.mjs.map} +1 -1
  310. package/dist/{components-DYKp2gmo.mjs → components-CYt4uVK9.mjs} +1 -1
  311. package/dist/{components-DYKp2gmo.mjs.map → components-CYt4uVK9.mjs.map} +1 -1
  312. package/dist/{content-BIlVx-RX.mjs → content-2PTDNnoh.mjs} +22 -7
  313. package/dist/content-2PTDNnoh.mjs.map +1 -0
  314. package/dist/{context-Cm4pt1Ws.mjs → context-B1W8soLv.mjs} +64 -26
  315. package/dist/context-B1W8soLv.mjs.map +1 -0
  316. package/dist/{cron-DdEVrQ2Y.mjs → cron-C5LVoNmP.mjs} +14 -2
  317. package/dist/cron-C5LVoNmP.mjs.map +1 -0
  318. package/dist/{dashboard-C-UYpps0.mjs → dashboard-CYjpQZ6-.mjs} +4 -4
  319. package/dist/{dashboard-C-UYpps0.mjs.map → dashboard-CYjpQZ6-.mjs.map} +1 -1
  320. package/dist/database/instrumentation.d.mts +19 -0
  321. package/dist/database/instrumentation.d.mts.map +1 -1
  322. package/dist/database/instrumentation.mjs +8 -1
  323. package/dist/database/instrumentation.mjs.map +1 -1
  324. package/dist/db/index.d.mts +3 -3
  325. package/dist/db/index.mjs +1 -1
  326. package/dist/db/libsql.d.mts +1 -1
  327. package/dist/db/postgres.d.mts +1 -1
  328. package/dist/db/sqlite.d.mts +1 -1
  329. package/dist/{db-errors-BluWkwGI.mjs → db-errors-UXB1CK42.mjs} +1 -1
  330. package/dist/{db-errors-BluWkwGI.mjs.map → db-errors-UXB1CK42.mjs.map} +1 -1
  331. package/dist/{default-NHGuJzQ3.mjs → default-CeRG-Ot4.mjs} +1 -1
  332. package/dist/{default-NHGuJzQ3.mjs.map → default-CeRG-Ot4.mjs.map} +1 -1
  333. package/dist/{device-flow-BQApWgnW.mjs → device-flow-DENDCQ9F.mjs} +5 -5
  334. package/dist/{device-flow-BQApWgnW.mjs.map → device-flow-DENDCQ9F.mjs.map} +1 -1
  335. package/dist/{email-console-BbU3RbWv.mjs → email-console-DJP32ucW.mjs} +1 -1
  336. package/dist/{email-console-BbU3RbWv.mjs.map → email-console-DJP32ucW.mjs.map} +1 -1
  337. package/dist/{error-CNn_w7jf.mjs → error-Bl6kZgtt.mjs} +2 -2
  338. package/dist/{error-CNn_w7jf.mjs.map → error-Bl6kZgtt.mjs.map} +1 -1
  339. package/dist/{escape-DPgcxcpL.mjs → escape-Bjio4ZsM.mjs} +1 -1
  340. package/dist/{escape-DPgcxcpL.mjs.map → escape-Bjio4ZsM.mjs.map} +1 -1
  341. package/dist/field-defs-cache-ztrdzUGb.mjs +77 -0
  342. package/dist/field-defs-cache-ztrdzUGb.mjs.map +1 -0
  343. package/dist/{fts-manager-Cx5z8jdA.mjs → fts-manager-CQuHt-vS.mjs} +2 -2
  344. package/dist/{fts-manager-Cx5z8jdA.mjs.map → fts-manager-CQuHt-vS.mjs.map} +1 -1
  345. package/dist/{hash-DlvIFn0b.mjs → hash-DrvzIXcz.mjs} +1 -1
  346. package/dist/{hash-DlvIFn0b.mjs.map → hash-DrvzIXcz.mjs.map} +1 -1
  347. package/dist/{import-KyxT1Mbs.mjs → import-Bb1T9WJS.mjs} +4 -4
  348. package/dist/{import-KyxT1Mbs.mjs.map → import-Bb1T9WJS.mjs.map} +1 -1
  349. package/dist/{index-D2VAiumu.d.mts → index-BaIj5hIq.d.mts} +198 -21
  350. package/dist/index-BaIj5hIq.d.mts.map +1 -0
  351. package/dist/{index-uT2yR66F.d.mts → index-qbL02uhs.d.mts} +3 -3
  352. package/dist/{index-uT2yR66F.d.mts.map → index-qbL02uhs.d.mts.map} +1 -1
  353. package/dist/index.d.mts +18 -17
  354. package/dist/index.mjs +64 -61
  355. package/dist/{init-lock-DlBHjf9-.mjs → init-lock-6b309ZrF.mjs} +2 -29
  356. package/dist/init-lock-6b309ZrF.mjs.map +1 -0
  357. package/dist/{load-Dq91b_DK.mjs → load-BNo-ER8C.mjs} +2 -2
  358. package/dist/{load-Dq91b_DK.mjs.map → load-BNo-ER8C.mjs.map} +1 -1
  359. package/dist/{loader-BqWjcH3h.mjs → loader-Dn74CG1b.mjs} +70 -11
  360. package/dist/loader-Dn74CG1b.mjs.map +1 -0
  361. package/dist/{manifest-schema-DFPeqMAn.mjs → manifest-schema-BWKnQYQF.mjs} +1 -1
  362. package/dist/{manifest-schema-DFPeqMAn.mjs.map → manifest-schema-BWKnQYQF.mjs.map} +1 -1
  363. package/dist/media/image-endpoint.d.mts +74 -0
  364. package/dist/media/image-endpoint.d.mts.map +1 -0
  365. package/dist/media/image-endpoint.mjs +162 -0
  366. package/dist/media/image-endpoint.mjs.map +1 -0
  367. package/dist/media/index.d.mts +1 -1
  368. package/dist/media/index.mjs +2 -2
  369. package/dist/media/local-runtime.d.mts +19 -11
  370. package/dist/media/local-runtime.d.mts.map +1 -1
  371. package/dist/media/local-runtime.mjs +16 -13
  372. package/dist/media/local-runtime.mjs.map +1 -1
  373. package/dist/{media-JOf3pNkw.mjs → media-Bw0sA6rb.mjs} +2 -2
  374. package/dist/{media-JOf3pNkw.mjs.map → media-Bw0sA6rb.mjs.map} +1 -1
  375. package/dist/{media-allowlist-_A0SuDn4.mjs → media-allowlist-B77I5_bw.mjs} +2 -2
  376. package/dist/{media-allowlist-_A0SuDn4.mjs.map → media-allowlist-B77I5_bw.mjs.map} +1 -1
  377. package/dist/{media-url-CqLd69IO.mjs → media-url-O4rm9-SQ.mjs} +1 -1
  378. package/dist/{media-url-CqLd69IO.mjs.map → media-url-O4rm9-SQ.mjs.map} +1 -1
  379. package/dist/{menus-DX4_E01q.mjs → menus-CYs0WZoL.mjs} +20 -6
  380. package/dist/menus-CYs0WZoL.mjs.map +1 -0
  381. package/dist/{menus-Ryk9L7fT.mjs → menus-DS8VTZgo.mjs} +167 -24
  382. package/dist/menus-DS8VTZgo.mjs.map +1 -0
  383. package/dist/{mime-YbtlEtvS.mjs → mime-BTzvzJ8M.mjs} +1 -1
  384. package/dist/{mime-YbtlEtvS.mjs.map → mime-BTzvzJ8M.mjs.map} +1 -1
  385. package/dist/{mode-CGXzIbD8.mjs → mode-BB0F8xTC.mjs} +1 -1
  386. package/dist/{mode-CGXzIbD8.mjs.map → mode-BB0F8xTC.mjs.map} +1 -1
  387. package/dist/{normalize-DKsg36ty.mjs → normalize-ClbNIenm.mjs} +1 -1
  388. package/dist/{normalize-DKsg36ty.mjs.map → normalize-ClbNIenm.mjs.map} +1 -1
  389. package/dist/{oauth-authorization-C2kVyjXI.mjs → oauth-authorization-CsvzIp_F.mjs} +5 -5
  390. package/dist/{oauth-authorization-C2kVyjXI.mjs.map → oauth-authorization-CsvzIp_F.mjs.map} +1 -1
  391. package/dist/{oauth-clients-BC873NCV.mjs → oauth-clients-C9SYwEbZ.mjs} +1 -1
  392. package/dist/{oauth-clients-BC873NCV.mjs.map → oauth-clients-C9SYwEbZ.mjs.map} +1 -1
  393. package/dist/{oauth-state-store-Cd--TUaq.mjs → oauth-state-store---zrApfB.mjs} +1 -1
  394. package/dist/{oauth-state-store-Cd--TUaq.mjs.map → oauth-state-store---zrApfB.mjs.map} +1 -1
  395. package/dist/{oauth-user-lookup-e4wOvDud.mjs → oauth-user-lookup-SHsWRlG9.mjs} +1 -1
  396. package/dist/{oauth-user-lookup-e4wOvDud.mjs.map → oauth-user-lookup-SHsWRlG9.mjs.map} +1 -1
  397. package/dist/object-cache/memory.d.mts +15 -0
  398. package/dist/object-cache/memory.d.mts.map +1 -0
  399. package/dist/object-cache/memory.mjs +56 -0
  400. package/dist/object-cache/memory.mjs.map +1 -0
  401. package/dist/object-cache-SEb2IM4Z.mjs +373 -0
  402. package/dist/object-cache-SEb2IM4Z.mjs.map +1 -0
  403. package/dist/{options-9kLgkE8m.d.mts → options-CqECG0gM.d.mts} +3 -3
  404. package/dist/{options-9kLgkE8m.d.mts.map → options-CqECG0gM.d.mts.map} +1 -1
  405. package/dist/{options-BPCVnesz.mjs → options-DTTML-Tx.mjs} +1 -1
  406. package/dist/{options-BPCVnesz.mjs.map → options-DTTML-Tx.mjs.map} +1 -1
  407. package/dist/page/index.d.mts +2 -2
  408. package/dist/{parse-DzSrk1t8.mjs → parse-C9hpjUyY.mjs} +2 -2
  409. package/dist/{parse-DzSrk1t8.mjs.map → parse-C9hpjUyY.mjs.map} +1 -1
  410. package/dist/{passkey-config-BpjbE_Uv.mjs → passkey-config-C0YfSBko.mjs} +1 -1
  411. package/dist/{passkey-config-BpjbE_Uv.mjs.map → passkey-config-C0YfSBko.mjs.map} +1 -1
  412. package/dist/{patterns-p-RBdTbM.mjs → patterns-BKmjvM7K.mjs} +1 -1
  413. package/dist/{patterns-p-RBdTbM.mjs.map → patterns-BKmjvM7K.mjs.map} +1 -1
  414. package/dist/{placeholder-2xumZh4g.mjs → placeholder-B0s2mWu5.mjs} +1 -1
  415. package/dist/{placeholder-2xumZh4g.mjs.map → placeholder-B0s2mWu5.mjs.map} +1 -1
  416. package/dist/{placeholder-BevVKfay.d.mts → placeholder-QoI4gEzP.d.mts} +1 -1
  417. package/dist/{placeholder-BevVKfay.d.mts.map → placeholder-QoI4gEzP.d.mts.map} +1 -1
  418. package/dist/plugin-types.d.mts +1 -1
  419. package/dist/plugin-utils.d.mts +9 -9
  420. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  421. package/dist/plugins/adapt-sandbox-entry.mjs +4 -2
  422. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  423. package/dist/{transport-1cIrOb1Y.mjs → portable-text-BICg8bTk.mjs} +2 -135
  424. package/dist/portable-text-BICg8bTk.mjs.map +1 -0
  425. package/dist/{preview-Dqv2hwXr.mjs → preview-DKGCt2_p.mjs} +2 -2
  426. package/dist/{preview-Dqv2hwXr.mjs.map → preview-DKGCt2_p.mjs.map} +1 -1
  427. package/dist/{public-url-D_zARuvZ.mjs → public-url-CTVqgMmg.mjs} +1 -1
  428. package/dist/{public-url-D_zARuvZ.mjs.map → public-url-CTVqgMmg.mjs.map} +1 -1
  429. package/dist/{query-Crm038Mc.mjs → query-DgUHZLWB.mjs} +230 -31
  430. package/dist/query-DgUHZLWB.mjs.map +1 -0
  431. package/dist/{rate-limit-hRTBqmw1.mjs → rate-limit-BuQ5d4X_.mjs} +2 -2
  432. package/dist/{rate-limit-hRTBqmw1.mjs.map → rate-limit-BuQ5d4X_.mjs.map} +1 -1
  433. package/dist/{redirect-CRWIt8Zj.mjs → redirect-Bifv_yHv.mjs} +3 -3
  434. package/dist/{redirect-CRWIt8Zj.mjs.map → redirect-Bifv_yHv.mjs.map} +1 -1
  435. package/dist/{redirect-C-OOkyku.mjs → redirect-CS-PHtNh.mjs} +1 -1
  436. package/dist/{redirect-C-OOkyku.mjs.map → redirect-CS-PHtNh.mjs.map} +1 -1
  437. package/dist/{redirects-CP3TnTLO.mjs → redirects-BZ8Mxn8H.mjs} +6 -6
  438. package/dist/{redirects-CP3TnTLO.mjs.map → redirects-BZ8Mxn8H.mjs.map} +1 -1
  439. package/dist/{redirects-6Zg2SoYo.mjs → redirects-x9eFPeyi.mjs} +10 -3
  440. package/dist/redirects-x9eFPeyi.mjs.map +1 -0
  441. package/dist/{registry-diMzD1Wf.mjs → registry-CK1SS6pi.mjs} +6 -6
  442. package/dist/{registry-diMzD1Wf.mjs.map → registry-CK1SS6pi.mjs.map} +1 -1
  443. package/dist/{request-cache-UwmBAiUK.mjs → request-cache-KCNHp_RJ.mjs} +1 -1
  444. package/dist/{request-cache-UwmBAiUK.mjs.map → request-cache-KCNHp_RJ.mjs.map} +1 -1
  445. package/dist/{request-meta-DPechd0W.mjs → request-meta-CmS1tDFf.mjs} +2 -2
  446. package/dist/{request-meta-DPechd0W.mjs.map → request-meta-CmS1tDFf.mjs.map} +1 -1
  447. package/dist/{resolve-B3NUUtVY.mjs → resolve-C7I0qiR0.mjs} +1 -1
  448. package/dist/{resolve-B3NUUtVY.mjs.map → resolve-C7I0qiR0.mjs.map} +1 -1
  449. package/dist/{runner-C8vcbvCe.d.mts → runner-CEtq-6Sm.d.mts} +2 -2
  450. package/dist/{runner-C8vcbvCe.d.mts.map → runner-CEtq-6Sm.d.mts.map} +1 -1
  451. package/dist/{runner--4wMWwKM.mjs → runner-DYYnW530.mjs} +201 -170
  452. package/dist/runner-DYYnW530.mjs.map +1 -0
  453. package/dist/runtime.d.mts +10 -10
  454. package/dist/runtime.mjs +3 -3
  455. package/dist/{schema-BDOkd3OU.mjs → schema-CbFRFoM7.mjs} +13 -8
  456. package/dist/schema-CbFRFoM7.mjs.map +1 -0
  457. package/dist/{search-Bs_J_EW-.mjs → search-C-waE_YW.mjs} +4 -4
  458. package/dist/{search-Bs_J_EW-.mjs.map → search-C-waE_YW.mjs.map} +1 -1
  459. package/dist/{secrets-C8xmE6mR.mjs → secrets-BSf9pRRY.mjs} +5 -5
  460. package/dist/{secrets-C8xmE6mR.mjs.map → secrets-BSf9pRRY.mjs.map} +1 -1
  461. package/dist/{sections-P0zuBlyz.mjs → sections-osX9U-YJ.mjs} +3 -3
  462. package/dist/{sections-P0zuBlyz.mjs.map → sections-osX9U-YJ.mjs.map} +1 -1
  463. package/dist/seed/index.d.mts +2 -2
  464. package/dist/seed/index.mjs +23 -21
  465. package/dist/seo/index.d.mts +1 -1
  466. package/dist/seo/index.mjs +1 -1
  467. package/dist/{seo-DpNgGQjF.mjs → seo-4FovMwNS.mjs} +5 -2
  468. package/dist/seo-4FovMwNS.mjs.map +1 -0
  469. package/dist/{seo-CLhm-Fmb.mjs → seo-DCEF-AVr.mjs} +1 -1
  470. package/dist/{seo-CLhm-Fmb.mjs.map → seo-DCEF-AVr.mjs.map} +1 -1
  471. package/dist/{service-CDQQnT8W.mjs → service-jby1RRmU.mjs} +3 -3
  472. package/dist/{service-CDQQnT8W.mjs.map → service-jby1RRmU.mjs.map} +1 -1
  473. package/dist/session-user-B8aLtKAH.mjs +51 -0
  474. package/dist/session-user-B8aLtKAH.mjs.map +1 -0
  475. package/dist/{settings-sO0Fif4p.mjs → settings-4bRT2NIf.mjs} +3 -3
  476. package/dist/{settings-sO0Fif4p.mjs.map → settings-4bRT2NIf.mjs.map} +1 -1
  477. package/dist/{settings-BjBsmVAo.mjs → settings-t-H2jPuJ.mjs} +18 -10
  478. package/dist/settings-t-H2jPuJ.mjs.map +1 -0
  479. package/dist/{setup-complete-CMMr-oZU.mjs → setup-complete-gEiySUc-.mjs} +2 -2
  480. package/dist/{setup-complete-CMMr-oZU.mjs.map → setup-complete-gEiySUc-.mjs.map} +1 -1
  481. package/dist/{setup-nonce-169xl4fV.mjs → setup-nonce-DzS50zme.mjs} +1 -1
  482. package/dist/{setup-nonce-169xl4fV.mjs.map → setup-nonce-DzS50zme.mjs.map} +1 -1
  483. package/dist/{single-flight-cache-C0UV1Npg.mjs → single-flight-cache-Cdfkic3t.mjs} +2 -2
  484. package/dist/{single-flight-cache-C0UV1Npg.mjs.map → single-flight-cache-Cdfkic3t.mjs.map} +1 -1
  485. package/dist/{site-url-vtsuOvSD.mjs → site-url-BLebyON8.mjs} +2 -2
  486. package/dist/{site-url-vtsuOvSD.mjs.map → site-url-BLebyON8.mjs.map} +1 -1
  487. package/dist/{slugify-Cjh1ssOZ.mjs → slugify-Cce3dTdg.mjs} +1 -1
  488. package/dist/{slugify-Cjh1ssOZ.mjs.map → slugify-Cce3dTdg.mjs.map} +1 -1
  489. package/dist/{ssrf-XO05Voq6.mjs → ssrf-BRKb343l.mjs} +1 -1
  490. package/dist/{ssrf-XO05Voq6.mjs.map → ssrf-BRKb343l.mjs.map} +1 -1
  491. package/dist/{status-2gZklYuj.mjs → status-vUK0SA17.mjs} +1 -1
  492. package/dist/{status-2gZklYuj.mjs.map → status-vUK0SA17.mjs.map} +1 -1
  493. package/dist/storage/local.d.mts +1 -1
  494. package/dist/storage/local.mjs +1 -1
  495. package/dist/storage/s3.d.mts +1 -1
  496. package/dist/storage/s3.mjs +1 -1
  497. package/dist/{taxonomies-DuESHWKI.mjs → taxonomies-BBB8O-CU.mjs} +7 -7
  498. package/dist/{taxonomies-DuESHWKI.mjs.map → taxonomies-BBB8O-CU.mjs.map} +1 -1
  499. package/dist/{taxonomies-BBxYA38v.mjs → taxonomies-Dxrc_szG.mjs} +177 -123
  500. package/dist/taxonomies-Dxrc_szG.mjs.map +1 -0
  501. package/dist/{taxonomy-CdllE4oq.mjs → taxonomy-B2HQuVf5.mjs} +19 -6
  502. package/dist/taxonomy-B2HQuVf5.mjs.map +1 -0
  503. package/dist/{tokens-DMkVjxrx.mjs → tokens-LeuXF9gG.mjs} +2 -2
  504. package/dist/{tokens-DMkVjxrx.mjs.map → tokens-LeuXF9gG.mjs.map} +1 -1
  505. package/dist/{transaction-x2tJQ-A1.mjs → transaction-qfqpPVpu.mjs} +1 -1
  506. package/dist/{transaction-x2tJQ-A1.mjs.map → transaction-qfqpPVpu.mjs.map} +1 -1
  507. package/dist/{transport-jdvsZEIt.d.mts → transport-BZ-03aFT.d.mts} +1 -1
  508. package/dist/{transport-jdvsZEIt.d.mts.map → transport-BZ-03aFT.d.mts.map} +1 -1
  509. package/dist/transport-_2nBz7e9.mjs +135 -0
  510. package/dist/transport-_2nBz7e9.mjs.map +1 -0
  511. package/dist/{trusted-proxy-CHp41Fjj.mjs → trusted-proxy-DZY5WCn2.mjs} +1 -1
  512. package/dist/{trusted-proxy-CHp41Fjj.mjs.map → trusted-proxy-DZY5WCn2.mjs.map} +1 -1
  513. package/dist/{types-Del0VMij.d.mts → types-B-gIxFCE.d.mts} +9 -1
  514. package/dist/{types-Del0VMij.d.mts.map → types-B-gIxFCE.d.mts.map} +1 -1
  515. package/dist/{types-DdkL6fyv.d.mts → types-BG8_XTLj.d.mts} +1 -1
  516. package/dist/{types-DdkL6fyv.d.mts.map → types-BG8_XTLj.d.mts.map} +1 -1
  517. package/dist/{types-BTnnBYVX.d.mts → types-BWh2MjmA.d.mts} +15 -2
  518. package/dist/types-BWh2MjmA.d.mts.map +1 -0
  519. package/dist/{types-CkEuk-Zr.d.mts → types-BWqGVhFn.d.mts} +1 -1
  520. package/dist/{types-CkEuk-Zr.d.mts.map → types-BWqGVhFn.d.mts.map} +1 -1
  521. package/dist/{types-DejCHqWT.mjs → types-CQAugunJ.mjs} +1 -1
  522. package/dist/{types-DejCHqWT.mjs.map → types-CQAugunJ.mjs.map} +1 -1
  523. package/dist/{types-Bzfk2yC8.d.mts → types-CTLJYMhN.d.mts} +1 -1
  524. package/dist/{types-Bzfk2yC8.d.mts.map → types-CTLJYMhN.d.mts.map} +1 -1
  525. package/dist/{types-BFgYtuKd.d.mts → types-CUsXGRVj.d.mts} +1 -1
  526. package/dist/{types-BFgYtuKd.d.mts.map → types-CUsXGRVj.d.mts.map} +1 -1
  527. package/dist/{types-BXSUSAjt.mjs → types-DXOIbece.mjs} +3 -3
  528. package/dist/types-DXOIbece.mjs.map +1 -0
  529. package/dist/{types-u_XxjbS8.d.mts → types-DrYMm9s5.d.mts} +1 -1
  530. package/dist/{types-u_XxjbS8.d.mts.map → types-DrYMm9s5.d.mts.map} +1 -1
  531. package/dist/{types-DO7whVYU.d.mts → types-TTx8uP7V.d.mts} +2 -2
  532. package/dist/{types-DO7whVYU.d.mts.map → types-TTx8uP7V.d.mts.map} +1 -1
  533. package/dist/types-fS7-VTdR.d.mts +124 -0
  534. package/dist/types-fS7-VTdR.d.mts.map +1 -0
  535. package/dist/{types-BIduXPJk.mjs → types-tM44hEcf.mjs} +1 -1
  536. package/dist/{types-BIduXPJk.mjs.map → types-tM44hEcf.mjs.map} +1 -1
  537. package/dist/{user-C0um7wrg.mjs → user-Db-Rti_z.mjs} +3 -3
  538. package/dist/{user-C0um7wrg.mjs.map → user-Db-Rti_z.mjs.map} +1 -1
  539. package/dist/{utils-C4M981Br.mjs → utils-B7A57fm9.mjs} +2 -2
  540. package/dist/{utils-C4M981Br.mjs.map → utils-B7A57fm9.mjs.map} +1 -1
  541. package/dist/{validate-DGhQPXzI.mjs → validate-0Utjspbs.mjs} +3 -3
  542. package/dist/{validate-DGhQPXzI.mjs.map → validate-0Utjspbs.mjs.map} +1 -1
  543. package/dist/{validate-cJOiOvT2.d.mts → validate-DOFrIb-c.d.mts} +5 -5
  544. package/dist/{validate-cJOiOvT2.d.mts.map → validate-DOFrIb-c.d.mts.map} +1 -1
  545. package/dist/{validation-DVHjPM1M.mjs → validation-D9EnzH1T.mjs} +6 -6
  546. package/dist/{validation-DVHjPM1M.mjs.map → validation-D9EnzH1T.mjs.map} +1 -1
  547. package/dist/version-BgVM_1MU.mjs +7 -0
  548. package/dist/{version-BOjj_cfz.mjs.map → version-BgVM_1MU.mjs.map} +1 -1
  549. package/dist/{widgets-Ci6hLwfO.mjs → widgets-BSTzPUYa.mjs} +4 -4
  550. package/dist/{widgets-Ci6hLwfO.mjs.map → widgets-BSTzPUYa.mjs.map} +1 -1
  551. package/dist/{zod-generator-CarzgPAu.mjs → zod-generator-ElVQOav7.mjs} +51 -15
  552. package/dist/zod-generator-ElVQOav7.mjs.map +1 -0
  553. package/package.json +19 -6
  554. package/src/api/handlers/api-tokens.ts +19 -0
  555. package/src/api/handlers/comment-reactions.ts +165 -0
  556. package/src/api/handlers/schema.ts +8 -0
  557. package/src/api/schemas/bylines.ts +8 -0
  558. package/src/api/schemas/comments.ts +10 -0
  559. package/src/astro/image-endpoint.ts +84 -0
  560. package/src/astro/index.ts +6 -0
  561. package/src/astro/integration/index.ts +83 -22
  562. package/src/astro/integration/routes.ts +5 -0
  563. package/src/astro/integration/runtime.ts +65 -1
  564. package/src/astro/integration/virtual-modules.ts +40 -0
  565. package/src/astro/integration/vite-config.ts +25 -1
  566. package/src/astro/middleware/auth.ts +4 -3
  567. package/src/astro/middleware/request-context.ts +6 -1
  568. package/src/astro/middleware/scoped-db.ts +131 -0
  569. package/src/astro/middleware/stream-end-metrics.ts +15 -9
  570. package/src/astro/middleware.ts +131 -31
  571. package/src/astro/object-cache/adapters.ts +50 -0
  572. package/src/astro/prefetch.ts +77 -0
  573. package/src/astro/routes/admin.astro +5 -1
  574. package/src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts +97 -0
  575. package/src/astro/routes/api/schema/index.ts +9 -3
  576. package/src/astro/routes/api/setup/dev-bypass.ts +5 -1
  577. package/src/astro/routes/api/snapshot.ts +3 -1
  578. package/src/astro/session-user.ts +57 -0
  579. package/src/astro/types.ts +1 -0
  580. package/src/cli/commands/export-seed.ts +10 -7
  581. package/src/comments/query.ts +78 -7
  582. package/src/comments/ranking.ts +58 -0
  583. package/src/components/Block.astro +71 -0
  584. package/src/components/Comments.astro +136 -1
  585. package/src/components/EmDashMedia.astro +1 -2
  586. package/src/components/Image.astro +36 -2
  587. package/src/components/InlinePortableTextEditor.tsx +10 -2
  588. package/src/components/index.ts +5 -0
  589. package/src/components/portable-text-text-align.ts +38 -0
  590. package/src/content/converters/portable-text-to-prosemirror.ts +5 -1
  591. package/src/content/converters/prosemirror-to-portable-text.ts +8 -0
  592. package/src/content/converters/types.ts +1 -0
  593. package/src/database/instrumentation.ts +21 -1
  594. package/src/database/migrations/044_comment_reactions.ts +56 -0
  595. package/src/database/migrations/runner.ts +2 -0
  596. package/src/database/repositories/byline.ts +27 -0
  597. package/src/database/repositories/comment-reaction.ts +132 -0
  598. package/src/database/repositories/comment.ts +10 -0
  599. package/src/database/repositories/content.ts +25 -3
  600. package/src/database/repositories/menu.ts +13 -1
  601. package/src/database/repositories/seo.ts +3 -0
  602. package/src/database/repositories/taxonomy.ts +13 -1
  603. package/src/database/repositories/types.ts +13 -0
  604. package/src/database/types.ts +9 -0
  605. package/src/emdash-runtime.ts +244 -75
  606. package/src/index.ts +22 -0
  607. package/src/loader.ts +97 -5
  608. package/src/mcp/server.ts +307 -20
  609. package/src/media/image-endpoint.ts +167 -0
  610. package/src/media/local-runtime.ts +18 -5
  611. package/src/menus/index.ts +11 -4
  612. package/src/object-cache/codec.ts +73 -0
  613. package/src/object-cache/index.ts +495 -0
  614. package/src/object-cache/memory.ts +91 -0
  615. package/src/object-cache/types.ts +124 -0
  616. package/src/plugins/adapt-sandbox-entry.ts +11 -1
  617. package/src/plugins/context.ts +94 -22
  618. package/src/plugins/cron.ts +18 -2
  619. package/src/plugins/routes.ts +40 -1
  620. package/src/query.ts +304 -18
  621. package/src/schema/query.ts +11 -4
  622. package/src/schema/zod-generator.ts +53 -8
  623. package/src/settings/index.ts +18 -5
  624. package/src/taxonomies/index.ts +263 -165
  625. package/src/ui.ts +5 -0
  626. package/src/virtual-modules.d.ts +24 -0
  627. package/dist/api-DxjIV2o8.mjs.map +0 -1
  628. package/dist/api-tokens-BFFkB0jB.mjs.map +0 -1
  629. package/dist/byline-V_Qp1Ziw.mjs.map +0 -1
  630. package/dist/byline-fields-CQJRIQkn.d.mts.map +0 -1
  631. package/dist/comment-sqQxNpN3.mjs.map +0 -1
  632. package/dist/content-BIlVx-RX.mjs.map +0 -1
  633. package/dist/context-Cm4pt1Ws.mjs.map +0 -1
  634. package/dist/cron-DdEVrQ2Y.mjs.map +0 -1
  635. package/dist/index-D2VAiumu.d.mts.map +0 -1
  636. package/dist/init-lock-DlBHjf9-.mjs.map +0 -1
  637. package/dist/loader-BqWjcH3h.mjs.map +0 -1
  638. package/dist/menus-DX4_E01q.mjs.map +0 -1
  639. package/dist/menus-Ryk9L7fT.mjs.map +0 -1
  640. package/dist/query-Crm038Mc.mjs.map +0 -1
  641. package/dist/redirects-6Zg2SoYo.mjs.map +0 -1
  642. package/dist/runner--4wMWwKM.mjs.map +0 -1
  643. package/dist/schema-BDOkd3OU.mjs.map +0 -1
  644. package/dist/seo-DpNgGQjF.mjs.map +0 -1
  645. package/dist/settings-BjBsmVAo.mjs.map +0 -1
  646. package/dist/taxonomies-BBxYA38v.mjs.map +0 -1
  647. package/dist/taxonomy-CdllE4oq.mjs.map +0 -1
  648. package/dist/transport-1cIrOb1Y.mjs.map +0 -1
  649. package/dist/types-BTnnBYVX.d.mts.map +0 -1
  650. package/dist/types-BXSUSAjt.mjs.map +0 -1
  651. package/dist/version-BOjj_cfz.mjs +0 -7
  652. package/dist/zod-generator-CarzgPAu.mjs.map +0 -1
  653. /package/dist/{api-tokens-C7ywRx7l.mjs → api-tokens-B4BQybOp.mjs} +0 -0
  654. /package/dist/{ssrf-CRZGzjdL.mjs → ssrf-CcX9zvMK.mjs} +0 -0
  655. /package/dist/{types-BoRm8-pp.mjs → types-BvbeGEtr.mjs} +0 -0
@@ -41,6 +41,8 @@ import type {
41
41
  PublicPageContext,
42
42
  PageMetadataContribution,
43
43
  PageFragmentContribution,
44
+ PortableTextBlockConfig,
45
+ FieldWidgetConfig,
44
46
  } from "./plugins/types.js";
45
47
  import type { FieldType } from "./schema/types.js";
46
48
  import { hashString } from "./utils/hash.js";
@@ -212,6 +214,10 @@ export interface SandboxedPluginEntry {
212
214
  adminPages?: Array<{ path: string; label?: string; icon?: string }>;
213
215
  /** Dashboard widgets */
214
216
  adminWidgets?: Array<{ id: string; title?: string; size?: string }>;
217
+ /** Portable Text block types contributed to the editor (declarative Block Kit) */
218
+ portableTextBlocks?: PortableTextBlockConfig[];
219
+ /** Field widget types contributed for schema-field editing UIs */
220
+ fieldWidgets?: FieldWidgetConfig[];
215
221
  /** Admin entry module */
216
222
  adminEntry?: string;
217
223
  /**
@@ -238,6 +244,15 @@ export interface MediaProviderEntry {
238
244
  */
239
245
  export interface MediaProviderContext {
240
246
  db: Kysely<Database>;
247
+ /**
248
+ * Resolver for the live connection, preferred over `db` by providers that
249
+ * query EmDash's database. Resolves the current request/event-scoped
250
+ * connection from ALS so connection-backed adapters (Postgres over
251
+ * Hyperdrive) don't reuse the per-isolate singleton's socket across events.
252
+ * Providers should resolve per operation rather than capturing `db` once.
253
+ * Omitted-safe: falls back to `db` for stateless adapters (D1, Node SQLite).
254
+ */
255
+ getDb?: () => Kysely<Database>;
241
256
  storage: Storage | null;
242
257
  }
243
258
 
@@ -256,6 +271,16 @@ export interface RuntimeDependencies {
256
271
  plugins: ResolvedPlugin[];
257
272
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
258
273
  createDialect: (config: any) => Dialect;
274
+ /**
275
+ * Factory for a dialect that batches same-turn reads into one round trip
276
+ * ({@link EmDashRuntime.create} uses it for the cold-start read phase).
277
+ * Present only on batching backends (D1, DO); absent backends fall back to
278
+ * the singleton. Returns a fresh connection each call — it must never be the
279
+ * long-lived singleton, whose coalescing buffer would be shared across
280
+ * requests.
281
+ */
282
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
283
+ createCoalescingDialect?: (config: any) => Dialect | null;
259
284
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
260
285
  createStorage: ((config: any) => Storage) | null;
261
286
  sandboxEnabled: boolean;
@@ -317,6 +342,7 @@ export interface EmDashRuntimeParts {
317
342
  allPipelinePlugins: ResolvedPlugin[];
318
343
  pipelineFactoryOptions: {
319
344
  db: Kysely<Database>;
345
+ getDb?: () => Kysely<Database>;
320
346
  storage?: Storage;
321
347
  siteInfo?: { siteName?: string; siteUrl?: string; locale?: string };
322
348
  };
@@ -364,6 +390,28 @@ function getDbHolder(): DbHolder {
364
390
  }
365
391
  return holder;
366
392
  }
393
+
394
+ /**
395
+ * Auto-seed runs at most once per isolate per database. Its lock + "done" set
396
+ * live on globalThis (same bundler-duplication reasoning as the db cache) so a
397
+ * reclaimed-and-rerun `create()` can't seed a second time concurrently. The
398
+ * lock polls rather than sharing a promise, so it is safe to await across a
399
+ * cancelled owner in workerd.
400
+ */
401
+ const SEED_HOLDER_KEY = Symbol.for("emdash:seed-state");
402
+ interface SeedHolder {
403
+ done: Set<string>;
404
+ lock: InitLock;
405
+ }
406
+ function getSeedHolder(): SeedHolder {
407
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis symbol slot, written only below
408
+ let holder = globalSymbolStore[SEED_HOLDER_KEY] as SeedHolder | undefined;
409
+ if (!holder) {
410
+ holder = { done: new Set<string>(), lock: createInitLock() };
411
+ globalSymbolStore[SEED_HOLDER_KEY] = holder;
412
+ }
413
+ return holder;
414
+ }
367
415
  const storageCache = new Map<string, Storage>();
368
416
  const sandboxedPluginCache = new Map<string, SandboxedPluginInstance>();
369
417
  /**
@@ -384,7 +432,10 @@ const marketplaceManifestCache = new Map<
384
432
  {
385
433
  id: string;
386
434
  version: string;
387
- admin?: { pages?: PluginAdminPage[]; widgets?: PluginDashboardWidget[] };
435
+ admin?: {
436
+ pages?: PluginAdminPage[];
437
+ widgets?: PluginDashboardWidget[];
438
+ };
388
439
  }
389
440
  >();
390
441
  /** Route metadata for sandboxed plugins: pluginId -> routeName -> RouteMeta */
@@ -405,7 +456,20 @@ export class EmDashRuntime {
405
456
  readonly configuredPlugins: ResolvedPlugin[];
406
457
  readonly sandboxedPlugins: Map<string, SandboxedPluginInstance>;
407
458
  readonly sandboxedPluginEntries: SandboxedPluginEntry[];
408
- readonly schemaRegistry: SchemaRegistry;
459
+ /**
460
+ * Schema registry bound to the current request/event-scoped connection.
461
+ * Built per access (SchemaRegistry just wraps a db) against `this.db`, the
462
+ * ALS-aware getter — never a captured snapshot of the singleton. On a
463
+ * connection-backed adapter (Postgres over Hyperdrive) a captured singleton
464
+ * would query a socket opened by an earlier event and trip workerd's
465
+ * cross-request I/O guard; the catch in handlers like handleContentUpdate
466
+ * would then silently treat a revision-enabled collection as non-revisioned
467
+ * and write draft edits to live columns. Same reasoning as the per-call
468
+ * registry in _buildManifest().
469
+ */
470
+ get schemaRegistry(): SchemaRegistry {
471
+ return new SchemaRegistry(this.db);
472
+ }
409
473
  private _hooks!: HookPipeline;
410
474
  readonly config: EmDashConfig;
411
475
  readonly mediaProviders: Map<string, MediaProvider>;
@@ -436,6 +500,7 @@ export class EmDashRuntime {
436
500
  /** Factory options for the hook pipeline context factory */
437
501
  private pipelineFactoryOptions: {
438
502
  db: Kysely<Database>;
503
+ getDb?: () => Kysely<Database>;
439
504
  storage?: Storage;
440
505
  siteInfo?: { siteName?: string; siteUrl?: string; locale?: string };
441
506
  };
@@ -466,7 +531,6 @@ export class EmDashRuntime {
466
531
  this.configuredPlugins = parts.configuredPlugins;
467
532
  this.sandboxedPlugins = parts.sandboxedPlugins;
468
533
  this.sandboxedPluginEntries = parts.sandboxedPluginEntries;
469
- this.schemaRegistry = new SchemaRegistry(parts.db);
470
534
  this._hooks = parts.hooks;
471
535
  this.enabledPlugins = parts.enabledPlugins;
472
536
  this.pluginStates = parts.pluginStates;
@@ -612,7 +676,9 @@ export class EmDashRuntime {
612
676
  // The old pipeline's contextFactoryOptions were built up incrementally
613
677
  // via setContextFactory calls during create(). We replay them here.
614
678
  if (this.email) {
615
- newPipeline.setContextFactory({ db: this.db, emailPipeline: this.email });
679
+ // db/getDb are already wired by createHookPipeline above (they live in
680
+ // pipelineFactoryOptions), so the merge only adds emailPipeline.
681
+ newPipeline.setContextFactory({ emailPipeline: this.email });
616
682
  }
617
683
  if (this.cronScheduler) {
618
684
  const scheduler = this.cronScheduler;
@@ -976,6 +1042,22 @@ export class EmDashRuntime {
976
1042
  // Initialize database (connects, runs migrations if needed)
977
1043
  const db = await phase("rt.db", "DB init + migrations", () => EmDashRuntime.getDatabase(deps));
978
1044
 
1045
+ // Resolver for the live connection, mirroring the `get db()` getter
1046
+ // below (which can't be used here — the runtime instance doesn't exist
1047
+ // yet). Long-lived subsystems built during create() (cron executor,
1048
+ // plugin context factory, media providers) capture this resolver rather
1049
+ // than the `db` snapshot, so a connection-backed adapter (Postgres over
1050
+ // Hyperdrive) serves their queries from the current request/event-scoped
1051
+ // connection in ALS instead of the per-isolate singleton — whose socket
1052
+ // belongs to an earlier request and would trip workerd's cross-request
1053
+ // I/O guard. Stateless adapters (D1, Node SQLite) set no ALS db on most
1054
+ // paths, so this falls back to the singleton: unchanged behavior.
1055
+ const resolveDb = (): Kysely<Database> => {
1056
+ const ctx = getRequestContext();
1057
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- ALS db is typed unknown to avoid a circular import; middleware always sets a Kysely<Database>
1058
+ return (ctx?.db as Kysely<Database> | undefined) ?? db;
1059
+ };
1060
+
979
1061
  // Validate EMDASH_ENCRYPTION_KEY once here so a malformed value
980
1062
  // surfaces in startup logs instead of as request-time 500s. The key
981
1063
  // itself is not yet consumed (a follow-up PR adds plugin-secret
@@ -989,47 +1071,156 @@ export class EmDashRuntime {
989
1071
  // Initialize storage (sync)
990
1072
  const storage = EmDashRuntime.getStorage(deps);
991
1073
 
992
- // Fetch plugin states and site info concurrently — independent reads
993
- // against different tables (_plugin_state vs options), so they share
994
- // one round-trip window instead of paying two sequential ones. Each
995
- // phase() wrapper still records that phase's own duration, and each
996
- // body keeps its own non-fatal catch.
997
1074
  let pluginStates: Map<string, string> = new Map();
998
1075
  let siteInfo: { siteName?: string; siteUrl?: string; locale?: string } | undefined;
999
- await Promise.all([
1000
- // Fetch plugin states from database
1076
+ // "Already set up" by default so a read failure (e.g. tables absent on a
1077
+ // pre-migration db) skips seeding rather than seeding a half-built db.
1078
+ let seedGate = { collectionCount: 1, setupDone: true };
1079
+
1080
+ // Seeding must only touch the configured singleton, never a borrowed
1081
+ // per-request db (playground / DO preview) or the loader-fallback db.
1082
+ const reqCtx = getRequestContext();
1083
+ const ownsConfiguredDb = !!deps.config.database && !(reqCtx?.dbIsIsolated && reqCtx.db);
1084
+
1085
+ // Run the init reads on a coalescing connection so the concurrent
1086
+ // same-turn reads flush as one batch() round trip. The singleton can't:
1087
+ // its plain SqliteAdapter reports supportsMultipleConnections=false, so
1088
+ // Kysely's connection mutex serializes concurrent reads into N round
1089
+ // trips. The connection is per-init and discarded — the long-lived
1090
+ // singleton must never coalesce or one request's reads could land in
1091
+ // another's batch. Backends without a coalescing dialect (Node/SQLite)
1092
+ // fall back to the singleton, where serialization costs nothing.
1093
+ let readDb = db;
1094
+ let readDbDisposable: Kysely<Database> | undefined;
1095
+ if (ownsConfiguredDb && deps.createCoalescingDialect && deps.config.database) {
1096
+ try {
1097
+ const dialect = deps.createCoalescingDialect(deps.config.database.config);
1098
+ if (dialect) {
1099
+ readDb = new Kysely<Database>({ dialect, log: kyselyLogOption() });
1100
+ readDbDisposable = readDb;
1101
+ }
1102
+ } catch {
1103
+ readDb = db;
1104
+ }
1105
+ }
1106
+ const optionsRepo = new OptionsRepository(readDb);
1107
+
1108
+ const readSiteInfo = async () => {
1109
+ const siteOpts = await optionsRepo.getMany<string>([
1110
+ "emdash:site_title",
1111
+ "emdash:site_url",
1112
+ "emdash:locale",
1113
+ ]);
1114
+ return {
1115
+ siteName: siteOpts.get("emdash:site_title") ?? undefined,
1116
+ siteUrl: siteOpts.get("emdash:site_url") ?? undefined,
1117
+ locale: siteOpts.get("emdash:locale") ?? undefined,
1118
+ };
1119
+ };
1120
+
1121
+ const coldStartReads: Array<Promise<void>> = [
1001
1122
  phase("rt.plugins", "Plugin states", async () => {
1002
1123
  try {
1003
- const states = await db
1124
+ const states = await readDb
1004
1125
  .selectFrom("_plugin_state")
1005
1126
  .select(["plugin_id", "status"])
1006
1127
  .execute();
1007
1128
  pluginStates = new Map(states.map((s) => [s.plugin_id, s.status]));
1008
1129
  } catch {
1009
- // Plugin state table may not exist yet
1130
+ // _plugin_state may not exist yet on a pre-migration db.
1010
1131
  }
1011
1132
  }),
1012
- // Load site info for plugin context extensions (1 batch query instead of 3)
1013
1133
  phase("rt.site", "Site info options", async () => {
1014
1134
  try {
1015
- const optionsRepo = new OptionsRepository(db);
1016
- const siteOpts = await optionsRepo.getMany<string>([
1017
- "emdash:site_title",
1018
- "emdash:site_url",
1019
- "emdash:locale",
1020
- ]);
1021
- siteInfo = {
1022
- siteName: siteOpts.get("emdash:site_title") ?? undefined,
1023
- siteUrl: siteOpts.get("emdash:site_url") ?? undefined,
1024
- locale: siteOpts.get("emdash:locale") ?? undefined,
1025
- };
1135
+ siteInfo = await readSiteInfo();
1026
1136
  } catch {
1027
- // Options table may not exist yet (pre-setup)
1137
+ // options may not exist yet on a pre-migration db.
1028
1138
  }
1029
1139
  }),
1030
- ]);
1140
+ ];
1141
+
1142
+ if (ownsConfiguredDb) {
1143
+ coldStartReads.push(
1144
+ phase("rt.seedcheck", "Auto-seed gate", async () => {
1145
+ try {
1146
+ const [collectionCount, setupOption] = await Promise.all([
1147
+ readDb
1148
+ .selectFrom("_emdash_collections")
1149
+ .select((eb) => eb.fn.countAll<number>().as("count"))
1150
+ .executeTakeFirstOrThrow(),
1151
+ readDb
1152
+ .selectFrom("options")
1153
+ .select("value")
1154
+ .where("name", "=", "emdash:setup_complete")
1155
+ .executeTakeFirst(),
1156
+ ]);
1157
+ const setupDone = (() => {
1158
+ try {
1159
+ return !!setupOption && JSON.parse(setupOption.value) === true;
1160
+ } catch {
1161
+ return false;
1162
+ }
1163
+ })();
1164
+ seedGate = { collectionCount: collectionCount.count, setupDone };
1165
+ } catch {
1166
+ // Leave the "already set up" default so a read failure never
1167
+ // triggers a seed onto a half-built db.
1168
+ }
1169
+ }),
1170
+ );
1171
+ }
1172
+
1173
+ await Promise.all(coldStartReads);
1174
+
1175
+ // Auto-seed the default schema for a first load that skipped the setup
1176
+ // wizard (the wizard and dev-bypass apply seeds explicitly). Run under a
1177
+ // per-isolate lock keyed by the configured db so a reclaimed-and-rerun
1178
+ // create() can't apply the seed a second time concurrently.
1179
+ if (seedGate.collectionCount === 0 && !seedGate.setupDone) {
1180
+ const seedKey = deps.config.database?.entrypoint ?? "default";
1181
+ const seedHolder = getSeedHolder();
1182
+ try {
1183
+ await initWithLock(
1184
+ seedHolder.lock,
1185
+ () => (seedHolder.done.has(seedKey) ? true : undefined),
1186
+ async () => {
1187
+ const { applySeed } = await import("./seed/apply.js");
1188
+ const { loadSeed } = await import("./seed/load.js");
1189
+ const { validateSeed } = await import("./seed/validate.js");
1190
+
1191
+ const seed = await loadSeed();
1192
+ const validation = validateSeed(seed);
1193
+ if (validation.valid) {
1194
+ await applySeed(db, seed, { onConflict: "skip" });
1195
+ console.log("Auto-seeded default collections");
1196
+ }
1197
+ seedHolder.done.add(seedKey);
1198
+ return true;
1199
+ },
1200
+ { deadlineMs: DB_INIT_DEADLINE_MS, anchor: (promise) => after(() => promise) },
1201
+ );
1202
+ // The site-info read ran before the seed wrote its defaults, so
1203
+ // refresh the snapshot the plugin context sees.
1204
+ try {
1205
+ siteInfo = await readSiteInfo();
1206
+ } catch {
1207
+ // Non-fatal — plugin context falls back to undefined fields.
1208
+ }
1209
+ } catch {
1210
+ // Non-fatal — a failed seed (e.g. missing seed module) leaves the
1211
+ // site un-seeded; a later request retries.
1212
+ }
1213
+ }
1214
+
1215
+ // The read connection is single-use; everything below uses the singleton.
1216
+ if (readDbDisposable) {
1217
+ try {
1218
+ await readDbDisposable.destroy();
1219
+ } catch {
1220
+ // Non-fatal — the underlying binding is shared and needs no teardown.
1221
+ }
1222
+ }
1031
1223
 
1032
- // Build set of enabled plugins
1033
1224
  const enabledPlugins = new Set<string>();
1034
1225
  for (const plugin of deps.plugins) {
1035
1226
  const status = pluginStates.get(plugin.id);
@@ -1145,9 +1336,15 @@ export class EmDashRuntime {
1145
1336
  // Filter to currently enabled plugins for the initial pipeline
1146
1337
  const enabledPluginList = allPipelinePlugins.filter((p) => enabledPlugins.has(p.id));
1147
1338
 
1148
- // Create hook pipeline
1339
+ // Create hook pipeline. getDb travels here (not just via the email
1340
+ // setContextFactory call below) so it survives rebuildHookPipeline(),
1341
+ // which reconstructs the factory from pipelineFactoryOptions. Without it,
1342
+ // toggling a plugin on an email-less deployment would silently revert
1343
+ // plugin contexts to the singleton db — re-breaking connection-backed
1344
+ // adapters. See #1622.
1149
1345
  const pipelineFactoryOptions = {
1150
1346
  db,
1347
+ getDb: resolveDb,
1151
1348
  storage: storage ?? undefined,
1152
1349
  siteInfo,
1153
1350
  };
@@ -1199,7 +1396,7 @@ export class EmDashRuntime {
1199
1396
  // Initialize media providers
1200
1397
  const mediaProviders = new Map<string, MediaProvider>();
1201
1398
  const mediaProviderEntries = deps.mediaProviderEntries ?? [];
1202
- const providerContext: MediaProviderContext = { db, storage };
1399
+ const providerContext: MediaProviderContext = { db, storage, getDb: resolveDb };
1203
1400
 
1204
1401
  for (const entry of mediaProviderEntries) {
1205
1402
  try {
@@ -1240,8 +1437,10 @@ export class EmDashRuntime {
1240
1437
  };
1241
1438
 
1242
1439
  // Wire email pipeline into context factory (independent of cron —
1243
- // must not be inside the cron try/catch or ctx.email breaks when cron fails)
1244
- pipeline.setContextFactory({ db, emailPipeline });
1440
+ // must not be inside the cron try/catch or ctx.email breaks when cron fails).
1441
+ // db/getDb were already set via pipelineFactoryOptions above; merge only
1442
+ // adds emailPipeline.
1443
+ pipeline.setContextFactory({ emailPipeline });
1245
1444
 
1246
1445
  let cronExecutor: CronExecutor | null = null;
1247
1446
  let cronScheduler: CronScheduler | null = null;
@@ -1253,7 +1452,7 @@ export class EmDashRuntime {
1253
1452
 
1254
1453
  await phase("rt.cron", "Cron init (recovery deferred post-response)", async () => {
1255
1454
  try {
1256
- cronExecutor = new CronExecutor(db, invokeCronHook);
1455
+ cronExecutor = new CronExecutor(resolveDb, invokeCronHook);
1257
1456
 
1258
1457
  // Recover stale locks from previous crashes. Pure bookkeeping
1259
1458
  // against the _emdash_cron_tasks table — no request needs the
@@ -1435,45 +1634,9 @@ export class EmDashRuntime {
1435
1634
  // cleanup-flag check costs an extra `options.get()` on every
1436
1635
  // isolate cold boot forever. Cheaper to leave it.
1437
1636
 
1438
- // Auto-seed schema if no collections exist and setup hasn't run.
1439
- // This covers first-load on sites that skip the setup wizard.
1440
- // Dev-bypass and the wizard apply seeds explicitly.
1441
- try {
1442
- const [collectionCount, setupOption] = await Promise.all([
1443
- db
1444
- .selectFrom("_emdash_collections")
1445
- .select((eb) => eb.fn.countAll<number>().as("count"))
1446
- .executeTakeFirstOrThrow(),
1447
- db
1448
- .selectFrom("options")
1449
- .select("value")
1450
- .where("name", "=", "emdash:setup_complete")
1451
- .executeTakeFirst(),
1452
- ]);
1453
-
1454
- const setupDone = (() => {
1455
- try {
1456
- return setupOption && JSON.parse(setupOption.value) === true;
1457
- } catch {
1458
- return false;
1459
- }
1460
- })();
1461
-
1462
- if (collectionCount.count === 0 && !setupDone) {
1463
- const { applySeed } = await import("./seed/apply.js");
1464
- const { loadSeed } = await import("./seed/load.js");
1465
- const { validateSeed } = await import("./seed/validate.js");
1466
-
1467
- const seed = await loadSeed();
1468
- const validation = validateSeed(seed);
1469
- if (validation.valid) {
1470
- await applySeed(db, seed, { onConflict: "skip" });
1471
- console.log("Auto-seeded default collections");
1472
- }
1473
- }
1474
- } catch {
1475
- // Tables may not exist yet. Non-fatal.
1476
- }
1637
+ // This returns a migrated but possibly unseeded db; create() runs
1638
+ // the seed gate and applies the seed, batched with its other init
1639
+ // reads.
1477
1640
 
1478
1641
  // Publish only while still the current owner: a reclaimed slow
1479
1642
  // init must not flip the cached Kysely identity back after the
@@ -1570,6 +1733,8 @@ export class EmDashRuntime {
1570
1733
  storage: entry.storage as never,
1571
1734
  adminPages,
1572
1735
  adminWidgets,
1736
+ portableTextBlocks: entry.portableTextBlocks,
1737
+ fieldWidgets: entry.fieldWidgets,
1573
1738
  });
1574
1739
  plugins.push(resolved);
1575
1740
  console.log(
@@ -2096,9 +2261,6 @@ export class EmDashRuntime {
2096
2261
  }
2097
2262
 
2098
2263
  // Add sandboxed plugins (use entries for admin config)
2099
- // TODO: sandboxed plugins need fieldWidgets extracted from their manifest
2100
- // to support Block Kit field widgets. Currently only trusted plugins carry
2101
- // fieldWidgets through the admin.fieldWidgets path.
2102
2264
  for (const entry of this.sandboxedPluginEntries) {
2103
2265
  const status = this.pluginStates.get(entry.id);
2104
2266
  const enabled = status === undefined || status === "active";
@@ -2110,9 +2272,15 @@ export class EmDashRuntime {
2110
2272
  version: entry.version,
2111
2273
  enabled,
2112
2274
  sandboxed: true,
2275
+ // `adminMode` reflects only admin pages/widgets. A plugin can
2276
+ // contribute portableTextBlocks/fieldWidgets with adminMode "none" —
2277
+ // the admin reads those from the manifest regardless, so don't gate
2278
+ // admin contributions on `adminMode`.
2113
2279
  adminMode: hasAdminPages || hasWidgets ? "blocks" : "none",
2114
2280
  adminPages: entry.adminPages ?? [],
2115
2281
  dashboardWidgets: entry.adminWidgets ?? [],
2282
+ portableTextBlocks: entry.portableTextBlocks,
2283
+ fieldWidgets: entry.fieldWidgets,
2116
2284
  };
2117
2285
  }
2118
2286
 
@@ -2951,6 +3119,7 @@ export class EmDashRuntime {
2951
3119
  if (trustedPlugin && this.enabledPlugins.has(trustedPlugin.id)) {
2952
3120
  const routeRegistry = new PluginRouteRegistry({
2953
3121
  db: this.db,
3122
+ storage: this.storage ?? undefined,
2954
3123
  emailPipeline: this.email ?? undefined,
2955
3124
  trustedProxyHeaders: getTrustedProxyHeaders(this.config),
2956
3125
  });
package/src/index.ts CHANGED
@@ -192,6 +192,28 @@ export type {
192
192
  } from "./storage/types.js";
193
193
  export { EmDashStorageError } from "./storage/types.js";
194
194
 
195
+ // Object cache (distributed read-through query cache)
196
+ export {
197
+ cachedQuery,
198
+ invalidateObjectCache,
199
+ invalidateCollectionCache,
200
+ invalidateTaxonomyObjectCache,
201
+ invalidateBylineObjectCache,
202
+ invalidateMenuObjectCache,
203
+ invalidateSchemaObjectCache,
204
+ invalidateCommentObjectCache,
205
+ contentNamespace,
206
+ contentNamespaces,
207
+ CacheNamespace,
208
+ } from "./object-cache/index.js";
209
+ export type { CachedQueryOptions } from "./object-cache/index.js";
210
+ export type {
211
+ ObjectCacheBackend,
212
+ ObjectCacheDescriptor,
213
+ ObjectCacheRuntimeConfig,
214
+ CreateObjectCacheBackendFn,
215
+ } from "./object-cache/types.js";
216
+
195
217
  // Plugin system
196
218
  export {
197
219
  definePlugin,
package/src/loader.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  */
13
13
 
14
14
  import type { LiveLoader } from "astro/loaders";
15
- import { Kysely, sql, type Dialect } from "kysely";
15
+ import { Kysely, type RawBuilder, sql, type Dialect } from "kysely";
16
16
 
17
17
  import { currentTimestampValue, isPostgres } from "./database/dialect-helpers.js";
18
18
  import { kyselyLogOption } from "./database/instrumentation.js";
@@ -72,8 +72,83 @@ const SYSTEM_COLUMNS = new Set([
72
72
  // fields. The aliases are _emdash_-prefixed so they can't shadow a user
73
73
  // field named e.g. `seo_title`.
74
74
  ...SEO_ALIAS_COLUMNS,
75
+ // Folded hydration JSON columns (see foldedHydrationSelects) — surfaced via
76
+ // the FOLDED_* markers, never as flat fields.
77
+ "_emdash_terms",
78
+ "_emdash_bylines",
75
79
  ]);
76
80
 
81
+ /** Markers for byline/taxonomy hydration folded into the content query. */
82
+ export const FOLDED_TERMS = Symbol.for("emdash:foldedTerms");
83
+ export const FOLDED_BYLINES = Symbol.for("emdash:foldedBylines");
84
+
85
+ /**
86
+ * Correlated JSON-array subqueries that fold taxonomy-term and byline hydration
87
+ * into the content query, removing the two separate hydration round trips per
88
+ * fetch. `outer` is the content table's alias/name; each subquery correlates on
89
+ * `<outer>.id`, so the base query stays one row per entry (no join fan-out, no
90
+ * duplicated content payload). Order is NOT applied in the aggregate (it differs
91
+ * across dialects) — the consumer sorts terms by label and credits by sortOrder.
92
+ *
93
+ * Dialect-specific aggregation: SQLite `json_group_array`/`json_object` returns
94
+ * a JSON *string*; Postgres `json_agg`/`json_build_object` (coalesced to `[]`)
95
+ * returns parsed JSON. {@link stashFolded} handles both.
96
+ */
97
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- any Kysely instance
98
+ function foldedHydrationSelects(db: Kysely<any>, type: string, outer: string) {
99
+ const o = sql.ref(outer);
100
+ const pg = isPostgres(db);
101
+ const obj = (pairs: string) =>
102
+ pg ? sql.raw(`json_build_object(${pairs})`) : sql.raw(`json_object(${pairs})`);
103
+ const agg = (inner: RawBuilder<unknown>) =>
104
+ pg ? sql`coalesce(json_agg(${inner}), '[]'::json)` : sql`json_group_array(${inner})`;
105
+
106
+ const termObj = obj(
107
+ "'id', t.id, 'name', t.name, 'slug', t.slug, 'label', t.label, 'parent_id', t.parent_id, 'locale', t.locale, 'translation_group', t.translation_group",
108
+ );
109
+ // Filter terms to the entry's own locale (matches #1441: terms render in the
110
+ // entry's resolved locale, not all locale variants of the attached group).
111
+ const terms = sql`(SELECT ${agg(termObj)} FROM ${sql.ref("content_taxonomies")} AS ct JOIN ${sql.ref("taxonomies")} AS t ON t.translation_group = ct.taxonomy_id WHERE ct.collection = ${type} AND ct.entry_id = ${o}.id AND t.locale = ${o}.locale) AS ${sql.ref("_emdash_terms")}`;
112
+
113
+ const bylineInner = obj(
114
+ "'id', b.id, 'slug', b.slug, 'displayName', b.display_name, 'bio', b.bio, 'avatarMediaId', b.avatar_media_id, 'avatarStorageKey', m.storage_key, 'avatarAlt', m.alt, 'avatarBlurhash', m.blurhash, 'avatarDominantColor', m.dominant_color, 'websiteUrl', b.website_url, 'userId', b.user_id, 'isGuest', b.is_guest, 'createdAt', b.created_at, 'updatedAt', b.updated_at, 'locale', b.locale, 'translationGroup', b.translation_group",
115
+ );
116
+ const creditObj = pg
117
+ ? sql.raw(
118
+ "json_build_object('roleLabel', cb.role_label, 'sortOrder', cb.sort_order, 'byline', ",
119
+ )
120
+ : sql.raw("json_object('roleLabel', cb.role_label, 'sortOrder', cb.sort_order, 'byline', ");
121
+ const credit = sql`${creditObj}${bylineInner})`;
122
+ const bylines = sql`(SELECT ${agg(credit)} FROM ${sql.ref("_emdash_content_bylines")} AS cb JOIN ${sql.ref("_emdash_bylines")} AS b ON b.translation_group = cb.byline_id LEFT JOIN ${sql.ref("media")} AS m ON m.id = b.avatar_media_id WHERE cb.collection_slug = ${type} AND cb.content_id = ${o}.id AND b.locale = ${o}.locale) AS ${sql.ref("_emdash_bylines")}`;
123
+ return { terms, bylines };
124
+ }
125
+
126
+ /**
127
+ * Stash folded hydration JSON (non-enumerable) for the query.ts fast paths.
128
+ * SQLite returns a JSON string (parse it); Postgres returns already-parsed JSON.
129
+ */
130
+ function stashFolded(data: Record<string, unknown>, row: Record<string, unknown>): void {
131
+ for (const [col, sym] of [
132
+ ["_emdash_terms", FOLDED_TERMS],
133
+ ["_emdash_bylines", FOLDED_BYLINES],
134
+ ] as const) {
135
+ const raw = row[col];
136
+ let value: unknown;
137
+ if (typeof raw === "string") {
138
+ try {
139
+ value = JSON.parse(raw);
140
+ } catch {
141
+ continue; // malformed: fall back to the query path
142
+ }
143
+ } else if (Array.isArray(raw)) {
144
+ value = raw; // Postgres json/jsonb already parsed by the driver
145
+ } else {
146
+ continue;
147
+ }
148
+ Object.defineProperty(data, sym, { value, enumerable: false, configurable: true });
149
+ }
150
+ }
151
+
77
152
  /** Resolved SEO shape attached to `entry.data.seo`. Mirrors `ContentSeo`. */
78
153
  interface EntrySeo {
79
154
  title: string | null;
@@ -785,8 +860,14 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
785
860
  )`
786
861
  : sql``;
787
862
 
863
+ // Fold byline + taxonomy hydration into the list query.
864
+ const { terms: termsSelect, bylines: bylinesSelect } = foldedHydrationSelects(
865
+ db,
866
+ type,
867
+ tableName,
868
+ );
788
869
  result = await sql<Record<string, unknown>>`
789
- SELECT * FROM ${sql.ref(tableName)}
870
+ SELECT *, ${termsSelect}, ${bylinesSelect} FROM ${sql.ref(tableName)}
790
871
  WHERE deleted_at IS NULL
791
872
  AND ${statusCondition}
792
873
  ${localeFilter}
@@ -814,11 +895,13 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
814
895
  rowLocale !== "" &&
815
896
  (rowLocale !== i18nConfig.defaultLocale || i18nConfig.prefixDefaultLocale);
816
897
  const id = shouldPrefix ? `${rowLocale}/${slug}` : slug;
898
+ const data = mapRowToData(row);
899
+ stashFolded(data, row);
817
900
  return {
818
901
  id,
819
902
  slug: rowStr(row, "slug"),
820
903
  status: rowStr(row, "status", "draft"),
821
- data: mapRowToData(row),
904
+ data,
822
905
  cacheHint: {
823
906
  tags: [rowStr(row, "id")],
824
907
  lastModified: row.updated_at ? new Date(rowStr(row, "updated_at")) : undefined,
@@ -922,9 +1005,17 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
922
1005
  ([col, alias]) => sql`${sql.ref(`s.${col}`)} AS ${sql.ref(alias)}`,
923
1006
  ),
924
1007
  );
1008
+ // Fold byline + taxonomy hydration into the content query (see
1009
+ // foldedHydrationSelects), removing the two separate hydration
1010
+ // round trips per fetch.
1011
+ const { terms: termsSelect, bylines: bylinesSelect } = foldedHydrationSelects(
1012
+ db,
1013
+ type,
1014
+ "c",
1015
+ );
925
1016
  const result = locale
926
1017
  ? await sql<Record<string, unknown>>`
927
- SELECT c.*, ${seoSelect}
1018
+ SELECT c.*, ${seoSelect}, ${termsSelect}, ${bylinesSelect}
928
1019
  FROM ${sql.ref(tableName)} AS c
929
1020
  LEFT JOIN ${sql.ref("_emdash_seo")} AS s
930
1021
  ON s.collection = ${type} AND s.content_id = c.id
@@ -933,7 +1024,7 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
933
1024
  LIMIT 1
934
1025
  `.execute(db)
935
1026
  : await sql<Record<string, unknown>>`
936
- SELECT c.*, ${seoSelect}
1027
+ SELECT c.*, ${seoSelect}, ${termsSelect}, ${bylinesSelect}
937
1028
  FROM ${sql.ref(tableName)} AS c
938
1029
  LEFT JOIN ${sql.ref("_emdash_seo")} AS s
939
1030
  ON s.collection = ${type} AND s.content_id = c.id
@@ -1015,6 +1106,7 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
1015
1106
  const entryData = mapRowToData(row);
1016
1107
  const entrySeo = extractSeo(row);
1017
1108
  if (entrySeo) entryData.seo = entrySeo;
1109
+ stashFolded(entryData, row);
1018
1110
  return {
1019
1111
  id: entryId,
1020
1112
  slug: rowStr(row, "slug"),