emdash 0.13.0 → 0.15.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 (605) hide show
  1. package/dist/{adapters-9DybjTO6.d.mts → adapters-C4yd_UJR.d.mts} +1 -1
  2. package/dist/{adapters-9DybjTO6.d.mts.map → adapters-C4yd_UJR.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-CDdG-4Gd.mjs → allowed-origins-D0fFk9a6.mjs} +2 -2
  4. package/dist/{allowed-origins-CDdG-4Gd.mjs.map → allowed-origins-D0fFk9a6.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +15 -15
  7. package/dist/api/schemas/index.d.mts +2 -2
  8. package/dist/api/schemas/index.mjs +3 -3
  9. package/dist/{api-ayIQ7rIe.mjs → api-CLwG_3dh.mjs} +523 -59
  10. package/dist/api-CLwG_3dh.mjs.map +1 -0
  11. package/dist/{api-tokens-eYymBhIT.mjs → api-tokens-ucpcNXDt.mjs} +2 -2
  12. package/dist/{api-tokens-eYymBhIT.mjs.map → api-tokens-ucpcNXDt.mjs.map} +1 -1
  13. package/dist/{apply-v4DBgjPw.mjs → apply-wJhM_bwU.mjs} +17 -17
  14. package/dist/{apply-v4DBgjPw.mjs.map → apply-wJhM_bwU.mjs.map} +1 -1
  15. package/dist/astro/index.d.mts +10 -10
  16. package/dist/astro/index.mjs +21 -5
  17. package/dist/astro/index.mjs.map +1 -1
  18. package/dist/astro/middleware/auth.d.mts +9 -9
  19. package/dist/astro/middleware/auth.mjs +6 -6
  20. package/dist/astro/middleware/auth.mjs.map +1 -1
  21. package/dist/astro/middleware/redirect.mjs +4 -4
  22. package/dist/astro/middleware/request-context.mjs +2 -2
  23. package/dist/astro/middleware/request-context.mjs.map +1 -1
  24. package/dist/astro/middleware/setup.mjs +1 -1
  25. package/dist/astro/middleware.d.mts.map +1 -1
  26. package/dist/astro/middleware.mjs +353 -71
  27. package/dist/astro/middleware.mjs.map +1 -1
  28. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -5
  29. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -5
  30. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  31. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  32. package/dist/astro/routes/api/admin/bylines/_id_/index.d.mts.map +1 -1
  33. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -17
  34. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  35. package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts +9 -0
  36. package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts.map +1 -0
  37. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +70 -0
  38. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -0
  39. package/dist/astro/routes/api/admin/bylines/index.d.mts.map +1 -1
  40. package/dist/astro/routes/api/admin/bylines/index.mjs +25 -16
  41. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  42. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +10 -10
  43. package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
  44. package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
  45. package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
  46. package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
  47. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  48. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  49. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  50. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  51. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +32 -31
  52. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +32 -31
  54. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +31 -30
  56. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +31 -30
  58. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +33 -31
  60. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/plugins/index.mjs +31 -30
  62. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  64. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +31 -30
  65. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  66. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +33 -31
  67. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +31 -30
  69. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts +8 -0
  71. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -0
  72. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +59 -0
  73. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -0
  74. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts +8 -0
  75. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -0
  76. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +72 -0
  77. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -0
  78. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +31 -30
  79. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/updates.d.mts.map +1 -1
  81. package/dist/astro/routes/api/admin/plugins/updates.mjs +44 -31
  82. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  83. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +31 -30
  84. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  85. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  86. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +31 -30
  87. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  89. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  90. package/dist/astro/routes/api/admin/users/_id_/index.mjs +5 -5
  91. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  92. package/dist/astro/routes/api/admin/users/index.mjs +5 -5
  93. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
  94. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  95. package/dist/astro/routes/api/auth/invite/complete.mjs +9 -9
  96. package/dist/astro/routes/api/auth/invite/index.mjs +6 -6
  97. package/dist/astro/routes/api/auth/invite/register-options.mjs +8 -8
  98. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  99. package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -8
  100. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  101. package/dist/astro/routes/api/auth/me.mjs +5 -5
  102. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  103. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  104. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs.map +1 -1
  105. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  106. package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
  107. package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -5
  108. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  109. package/dist/astro/routes/api/auth/passkey/options.mjs +10 -10
  110. package/dist/astro/routes/api/auth/passkey/register/options.mjs +8 -8
  111. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +9 -9
  112. package/dist/astro/routes/api/auth/passkey/verify.mjs +9 -9
  113. package/dist/astro/routes/api/auth/signup/complete.mjs +9 -9
  114. package/dist/astro/routes/api/auth/signup/request.mjs +8 -8
  115. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  116. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
  117. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  118. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  119. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  120. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  121. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs.map +1 -1
  122. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  123. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +9 -9
  124. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -6
  125. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  126. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  127. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs.map +1 -1
  128. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  129. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +6 -6
  130. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  131. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +10 -9
  132. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  133. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  134. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs.map +1 -1
  135. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  136. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  137. package/dist/astro/routes/api/content/_collection_/_id_.mjs +6 -6
  138. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  139. package/dist/astro/routes/api/content/_collection_/index.mjs +6 -6
  140. package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -6
  141. package/dist/astro/routes/api/dashboard.mjs +7 -7
  142. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  143. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  144. package/dist/astro/routes/api/import/probe.mjs +10 -10
  145. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  146. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  147. package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -8
  148. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  149. package/dist/astro/routes/api/import/wordpress/media.mjs +8 -8
  150. package/dist/astro/routes/api/import/wordpress/prepare.mjs +8 -8
  151. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  152. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +7 -7
  153. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  154. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  155. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +10 -10
  156. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  157. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +11 -11
  158. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  159. package/dist/astro/routes/api/manifest.mjs +4 -4
  160. package/dist/astro/routes/api/mcp.mjs +29 -29
  161. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  162. package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -6
  163. package/dist/astro/routes/api/media/_id_.mjs +6 -6
  164. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  165. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  166. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  167. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  168. package/dist/astro/routes/api/media/upload-url.mjs +7 -7
  169. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  170. package/dist/astro/routes/api/media.mjs +8 -8
  171. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +7 -7
  172. package/dist/astro/routes/api/menus/_name_/items.mjs +7 -7
  173. package/dist/astro/routes/api/menus/_name_/reorder.mjs +7 -7
  174. package/dist/astro/routes/api/menus/_name_/translations.mjs +7 -7
  175. package/dist/astro/routes/api/menus/_name_.mjs +7 -7
  176. package/dist/astro/routes/api/menus/index.mjs +7 -7
  177. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  178. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  179. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  180. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  181. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  182. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  183. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  184. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  185. package/dist/astro/routes/api/openapi.json.mjs +3 -3
  186. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  187. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  188. package/dist/astro/routes/api/redirects/404s/index.mjs +8 -8
  189. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  190. package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
  191. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  192. package/dist/astro/routes/api/redirects/_id_.mjs +9 -9
  193. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  194. package/dist/astro/routes/api/redirects/index.mjs +9 -9
  195. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  196. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  197. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  198. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +31 -30
  199. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  200. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +31 -30
  201. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  202. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +31 -30
  203. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  204. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +31 -30
  205. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  206. package/dist/astro/routes/api/schema/collections/index.mjs +31 -30
  207. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  208. package/dist/astro/routes/api/schema/index.mjs +6 -6
  209. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  210. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +31 -30
  211. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  212. package/dist/astro/routes/api/schema/orphans/index.mjs +31 -30
  213. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  214. package/dist/astro/routes/api/search/enable.mjs +9 -9
  215. package/dist/astro/routes/api/search/index.mjs +8 -8
  216. package/dist/astro/routes/api/search/rebuild.mjs +9 -9
  217. package/dist/astro/routes/api/search/stats.mjs +6 -6
  218. package/dist/astro/routes/api/search/suggest.mjs +8 -8
  219. package/dist/astro/routes/api/sections/_slug_.mjs +8 -8
  220. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  221. package/dist/astro/routes/api/sections/index.mjs +8 -8
  222. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  223. package/dist/astro/routes/api/settings/email.mjs +4 -4
  224. package/dist/astro/routes/api/settings.mjs +10 -10
  225. package/dist/astro/routes/api/setup/admin-verify.mjs +10 -10
  226. package/dist/astro/routes/api/setup/admin.mjs +9 -9
  227. package/dist/astro/routes/api/setup/dev-bypass.mjs +22 -22
  228. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  229. package/dist/astro/routes/api/setup/index.mjs +22 -22
  230. package/dist/astro/routes/api/setup/status.mjs +4 -4
  231. package/dist/astro/routes/api/snapshot.mjs +5 -5
  232. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +11 -10
  233. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  234. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -10
  235. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  236. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -10
  237. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  238. package/dist/astro/routes/api/taxonomies/index.mjs +11 -10
  239. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  241. package/dist/astro/routes/api/typegen.mjs +5 -5
  242. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  243. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  244. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  245. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -6
  246. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +8 -8
  247. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +8 -8
  248. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  249. package/dist/astro/routes/api/widget-areas/index.mjs +8 -8
  250. package/dist/astro/routes/api/widget-components.mjs +3 -3
  251. package/dist/astro/routes/robots.txt.mjs +5 -5
  252. package/dist/astro/routes/sitemap-_collection_.xml.mjs +4 -4
  253. package/dist/astro/routes/sitemap.xml.mjs +5 -5
  254. package/dist/astro/types.d.mts +13 -12
  255. package/dist/astro/types.d.mts.map +1 -1
  256. package/dist/auth/providers/github.d.mts +1 -1
  257. package/dist/auth/providers/google.d.mts +1 -1
  258. package/dist/{authorize-BlyCH-96.mjs → authorize-Bkwe8kuL.mjs} +2 -2
  259. package/dist/{authorize-BlyCH-96.mjs.map → authorize-Bkwe8kuL.mjs.map} +1 -1
  260. package/dist/byline-CTaWkMh5.mjs +404 -0
  261. package/dist/byline-CTaWkMh5.mjs.map +1 -0
  262. package/dist/bylines-BYHWU3T7.mjs +174 -0
  263. package/dist/bylines-BYHWU3T7.mjs.map +1 -0
  264. package/dist/{bylines-C6eYUWlZ.d.mts → bylines-DtDRNF1n.d.mts} +63 -18
  265. package/dist/bylines-DtDRNF1n.d.mts.map +1 -0
  266. package/dist/bylines-H0Xh5TMy.mjs +118 -0
  267. package/dist/bylines-H0Xh5TMy.mjs.map +1 -0
  268. package/dist/{cache-CXCpjWiL.mjs → cache-CNk1jIxp.mjs} +2 -2
  269. package/dist/{cache-CXCpjWiL.mjs.map → cache-CNk1jIxp.mjs.map} +1 -1
  270. package/dist/{challenge-store-CJ0OOHOr.mjs → challenge-store-Dng1SxKT.mjs} +1 -1
  271. package/dist/{challenge-store-CJ0OOHOr.mjs.map → challenge-store-Dng1SxKT.mjs.map} +1 -1
  272. package/dist/{chunks-DyGtu1Bv.mjs → chunks-BkfVdD-3.mjs} +2 -2
  273. package/dist/{chunks-DyGtu1Bv.mjs.map → chunks-BkfVdD-3.mjs.map} +1 -1
  274. package/dist/cli/index.mjs +21 -29
  275. package/dist/cli/index.mjs.map +1 -1
  276. package/dist/client/cf-access.d.mts +1 -1
  277. package/dist/client/index.d.mts +1 -1
  278. package/dist/client/index.mjs +1 -1
  279. package/dist/client/index.mjs.map +1 -1
  280. package/dist/{comment-Dd9MI82-.mjs → comment-_yzlBYPx.mjs} +2 -2
  281. package/dist/{comment-Dd9MI82-.mjs.map → comment-_yzlBYPx.mjs.map} +1 -1
  282. package/dist/{comments-koGI0FrK.mjs → comments-DxID-rsd.mjs} +3 -3
  283. package/dist/{comments-koGI0FrK.mjs.map → comments-DxID-rsd.mjs.map} +1 -1
  284. package/dist/{components-mZem7pbe.mjs → components-Dx3DM0gg.mjs} +1 -1
  285. package/dist/{components-mZem7pbe.mjs.map → components-Dx3DM0gg.mjs.map} +1 -1
  286. package/dist/config-CVssduLe.mjs.map +1 -1
  287. package/dist/{content-D6YG26WG.mjs → content-C0ooIs-f.mjs} +3 -3
  288. package/dist/{content-D6YG26WG.mjs.map → content-C0ooIs-f.mjs.map} +1 -1
  289. package/dist/{context-qF8d3IPR.mjs → context-sAnCaUIR.mjs} +10 -10
  290. package/dist/context-sAnCaUIR.mjs.map +1 -0
  291. package/dist/{cron-H8eJ46dv.mjs → cron-Bd3b3iuj.mjs} +1 -1
  292. package/dist/{cron-H8eJ46dv.mjs.map → cron-Bd3b3iuj.mjs.map} +1 -1
  293. package/dist/{dashboard-BmWSIUwY.mjs → dashboard-Cqw3ay2X.mjs} +4 -4
  294. package/dist/{dashboard-BmWSIUwY.mjs.map → dashboard-Cqw3ay2X.mjs.map} +1 -1
  295. package/dist/db/index.d.mts +3 -3
  296. package/dist/db/index.mjs +1 -1
  297. package/dist/db/libsql.d.mts +1 -1
  298. package/dist/db/postgres.d.mts +1 -1
  299. package/dist/db/sqlite.d.mts +1 -1
  300. package/dist/{default-Dbs22Gg4.mjs → default-BvTAYCzx.mjs} +1 -1
  301. package/dist/{default-Dbs22Gg4.mjs.map → default-BvTAYCzx.mjs.map} +1 -1
  302. package/dist/{device-flow-BqJRxa0Q.mjs → device-flow-B9oG8PwP.mjs} +4 -4
  303. package/dist/{device-flow-BqJRxa0Q.mjs.map → device-flow-B9oG8PwP.mjs.map} +1 -1
  304. package/dist/{email-console-Dmp5Q-P2.mjs → email-console-CubRll9q.mjs} +1 -1
  305. package/dist/email-console-CubRll9q.mjs.map +1 -0
  306. package/dist/{error-tSQWIl5U.mjs → error-CPh_8eLq.mjs} +16 -8
  307. package/dist/error-CPh_8eLq.mjs.map +1 -0
  308. package/dist/{escape-B8bdIryO.mjs → escape-Cg6kMELH.mjs} +1 -1
  309. package/dist/{escape-B8bdIryO.mjs.map → escape-Cg6kMELH.mjs.map} +1 -1
  310. package/dist/{fts-manager-B633C-kQ.mjs → fts-manager-Mnrtn-r2.mjs} +2 -2
  311. package/dist/{fts-manager-B633C-kQ.mjs.map → fts-manager-Mnrtn-r2.mjs.map} +1 -1
  312. package/dist/{import-CNfLOgDE.mjs → import-DG80rC_I.mjs} +3 -3
  313. package/dist/{import-CNfLOgDE.mjs.map → import-DG80rC_I.mjs.map} +1 -1
  314. package/dist/{index-UmOMt9T-.d.mts → index-Bv1Wf1zB.d.mts} +235 -18
  315. package/dist/index-Bv1Wf1zB.d.mts.map +1 -0
  316. package/dist/{index-D2gvztOP.d.mts → index-CC42STEm.d.mts} +3 -3
  317. package/dist/{index-D2gvztOP.d.mts.map → index-CC42STEm.d.mts.map} +1 -1
  318. package/dist/index.d.mts +17 -17
  319. package/dist/index.mjs +50 -49
  320. package/dist/{load-QzYRpVN3.mjs → load-DmXNVhst.mjs} +2 -2
  321. package/dist/{load-QzYRpVN3.mjs.map → load-DmXNVhst.mjs.map} +1 -1
  322. package/dist/{loader-Cs6-Bqe6.mjs → loader-Chm5h7Gr.mjs} +3 -3
  323. package/dist/loader-Chm5h7Gr.mjs.map +1 -0
  324. package/dist/{manifest-schema-HCtSh4Jq.mjs → manifest-schema-Czqf0TLu.mjs} +1 -1
  325. package/dist/{manifest-schema-HCtSh4Jq.mjs.map → manifest-schema-Czqf0TLu.mjs.map} +1 -1
  326. package/dist/media/index.d.mts +1 -1
  327. package/dist/media/local-runtime.d.mts +11 -11
  328. package/dist/media/local-runtime.mjs +4 -4
  329. package/dist/{media-allowlist-B8EX01DH.mjs → media-allowlist-BNloC69x.mjs} +1 -1
  330. package/dist/{media-allowlist-B8EX01DH.mjs.map → media-allowlist-BNloC69x.mjs.map} +1 -1
  331. package/dist/{media-Dg7he9uK.mjs → media-oqRcNiQf.mjs} +2 -2
  332. package/dist/media-oqRcNiQf.mjs.map +1 -0
  333. package/dist/{menus-DOzIecHi.mjs → menus-Bjf5R1Qq.mjs} +2 -2
  334. package/dist/menus-Bjf5R1Qq.mjs.map +1 -0
  335. package/dist/{menus-X4Z-eBA1.mjs → menus-C75SSmRy.mjs} +30 -11
  336. package/dist/menus-C75SSmRy.mjs.map +1 -0
  337. package/dist/mime-KV5TqkMN.mjs.map +1 -1
  338. package/dist/{mode-DPRPvJYm.mjs → mode-CaaiebZI.mjs} +1 -1
  339. package/dist/{mode-DPRPvJYm.mjs.map → mode-CaaiebZI.mjs.map} +1 -1
  340. package/dist/{oauth-authorization-62GmpGIH.mjs → oauth-authorization-CTMeVfvj.mjs} +4 -4
  341. package/dist/{oauth-authorization-62GmpGIH.mjs.map → oauth-authorization-CTMeVfvj.mjs.map} +1 -1
  342. package/dist/{oauth-clients-D_B0_-Bz.mjs → oauth-clients-eJCbkVSG.mjs} +1 -1
  343. package/dist/oauth-clients-eJCbkVSG.mjs.map +1 -0
  344. package/dist/{oauth-state-store-DpsZViTu.mjs → oauth-state-store-vOSdOeGe.mjs} +1 -1
  345. package/dist/{oauth-state-store-DpsZViTu.mjs.map → oauth-state-store-vOSdOeGe.mjs.map} +1 -1
  346. package/dist/{oauth-user-lookup-meyS2oB1.mjs → oauth-user-lookup-3JwsVw6N.mjs} +1 -1
  347. package/dist/{oauth-user-lookup-meyS2oB1.mjs.map → oauth-user-lookup-3JwsVw6N.mjs.map} +1 -1
  348. package/dist/options-BL4X94qY.mjs.map +1 -1
  349. package/dist/{options-Cq64Wx0O.d.mts → options-DhV-gwJb.d.mts} +4 -4
  350. package/dist/options-DhV-gwJb.d.mts.map +1 -0
  351. package/dist/page/index.d.mts +2 -2
  352. package/dist/{parse-BFTPon-J.mjs → parse-3-caTKgt.mjs} +2 -2
  353. package/dist/{parse-BFTPon-J.mjs.map → parse-3-caTKgt.mjs.map} +1 -1
  354. package/dist/{passkey-config-Cg86_ISa.mjs → passkey-config-BloQOT3y.mjs} +1 -1
  355. package/dist/{passkey-config-Cg86_ISa.mjs.map → passkey-config-BloQOT3y.mjs.map} +1 -1
  356. package/dist/{placeholder-D3cFCU9y.d.mts → placeholder-KCkkCtgQ.d.mts} +1 -1
  357. package/dist/{placeholder-D3cFCU9y.d.mts.map → placeholder-KCkkCtgQ.d.mts.map} +1 -1
  358. package/dist/plugin-types.d.mts +1 -1
  359. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  360. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  361. package/dist/plugins/adapt-sandbox-entry.mjs +26 -15
  362. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  363. package/dist/{preview-C1LOEbWZ.mjs → preview-D4z0WONU.mjs} +2 -2
  364. package/dist/{preview-C1LOEbWZ.mjs.map → preview-D4z0WONU.mjs.map} +1 -1
  365. package/dist/{public-url-CseXl9Fv.mjs → public-url-CUWWFME2.mjs} +1 -1
  366. package/dist/{public-url-CseXl9Fv.mjs.map → public-url-CUWWFME2.mjs.map} +1 -1
  367. package/dist/{query-axZmO6Tn.mjs → query-BJn8TOPk.mjs} +16 -13
  368. package/dist/{query-axZmO6Tn.mjs.map → query-BJn8TOPk.mjs.map} +1 -1
  369. package/dist/{rate-limit-t5CVjCO6.mjs → rate-limit-D_-gAeJ0.mjs} +2 -2
  370. package/dist/{rate-limit-t5CVjCO6.mjs.map → rate-limit-D_-gAeJ0.mjs.map} +1 -1
  371. package/dist/{redirect-DGRsLO2I.mjs → redirect-BINiRYq4.mjs} +1 -1
  372. package/dist/{redirect-DGRsLO2I.mjs.map → redirect-BINiRYq4.mjs.map} +1 -1
  373. package/dist/{redirect-DkaDxq8e.mjs → redirect-CNv4mHX2.mjs} +2 -2
  374. package/dist/{redirect-DkaDxq8e.mjs.map → redirect-CNv4mHX2.mjs.map} +1 -1
  375. package/dist/{redirects-D1fdd68T.mjs → redirects-B-CUZ1Xh.mjs} +3 -3
  376. package/dist/{redirects-D1fdd68T.mjs.map → redirects-B-CUZ1Xh.mjs.map} +1 -1
  377. package/dist/{redirects-Dmj6KRU3.mjs → redirects-COMLwsV5.mjs} +19 -5
  378. package/dist/redirects-COMLwsV5.mjs.map +1 -0
  379. package/dist/{registry-BnCeHYsf.mjs → registry-DqrAQDXH.mjs} +4 -4
  380. package/dist/{registry-BnCeHYsf.mjs.map → registry-DqrAQDXH.mjs.map} +1 -1
  381. package/dist/request-cache-dzCt8TZB.mjs.map +1 -1
  382. package/dist/request-context.mjs.map +1 -1
  383. package/dist/{request-meta-CLCwSQOS.mjs → request-meta-C_Cjii-T.mjs} +2 -2
  384. package/dist/{request-meta-CLCwSQOS.mjs.map → request-meta-C_Cjii-T.mjs.map} +1 -1
  385. package/dist/resolve-Cj98DuqN.mjs +39 -0
  386. package/dist/resolve-Cj98DuqN.mjs.map +1 -0
  387. package/dist/{runner-DdnQIwz_.mjs → runner-CGlojznK.mjs} +472 -165
  388. package/dist/runner-CGlojznK.mjs.map +1 -0
  389. package/dist/{runner-DcfZewkO.d.mts → runner-CNHRo1mT.d.mts} +2 -2
  390. package/dist/{runner-DcfZewkO.d.mts.map → runner-CNHRo1mT.d.mts.map} +1 -1
  391. package/dist/runtime.d.mts +10 -10
  392. package/dist/runtime.mjs +2 -2
  393. package/dist/{schema-BmqagCwG.mjs → schema-Djdlfi5G.mjs} +4 -4
  394. package/dist/{schema-BmqagCwG.mjs.map → schema-Djdlfi5G.mjs.map} +1 -1
  395. package/dist/{search-CPrvO5u8.mjs → search-By-NN3da.mjs} +4 -4
  396. package/dist/{search-CPrvO5u8.mjs.map → search-By-NN3da.mjs.map} +1 -1
  397. package/dist/{secrets-6pgZyq0K.mjs → secrets-rPdhEBkD.mjs} +1 -1
  398. package/dist/{secrets-6pgZyq0K.mjs.map → secrets-rPdhEBkD.mjs.map} +1 -1
  399. package/dist/{sections-Cm-zb-gZ.mjs → sections-DcBIlOq1.mjs} +3 -3
  400. package/dist/{sections-Cm-zb-gZ.mjs.map → sections-DcBIlOq1.mjs.map} +1 -1
  401. package/dist/seed/index.d.mts +2 -2
  402. package/dist/seed/index.mjs +16 -16
  403. package/dist/seo/index.d.mts +1 -1
  404. package/dist/{seo-DRq9-EPP.mjs → seo-bjDoq9Eg.mjs} +2 -2
  405. package/dist/{seo-DRq9-EPP.mjs.map → seo-bjDoq9Eg.mjs.map} +1 -1
  406. package/dist/{service-vByySp-2.mjs → service-BuuTdGAT.mjs} +3 -3
  407. package/dist/{service-vByySp-2.mjs.map → service-BuuTdGAT.mjs.map} +1 -1
  408. package/dist/{settings-CBBj7HUd.mjs → settings-CJnKiWuR.mjs} +3 -3
  409. package/dist/{settings-CBBj7HUd.mjs.map → settings-CJnKiWuR.mjs.map} +1 -1
  410. package/dist/{settings-xQKsWnzQ.mjs → settings-hcubRfkr.mjs} +3 -3
  411. package/dist/settings-hcubRfkr.mjs.map +1 -0
  412. package/dist/{setup-BGAJ2uXs.mjs → setup-Cf_TyOv5.mjs} +2 -2
  413. package/dist/{setup-BGAJ2uXs.mjs.map → setup-Cf_TyOv5.mjs.map} +1 -1
  414. package/dist/{setup-complete-C6ZCLhKo.mjs → setup-complete-MzzN9u0b.mjs} +1 -1
  415. package/dist/{setup-complete-C6ZCLhKo.mjs.map → setup-complete-MzzN9u0b.mjs.map} +1 -1
  416. package/dist/{setup-nonce-CY1gQiAU.mjs → setup-nonce-DXuriHsg.mjs} +1 -1
  417. package/dist/{setup-nonce-CY1gQiAU.mjs.map → setup-nonce-DXuriHsg.mjs.map} +1 -1
  418. package/dist/{site-url-D-M4Fd8O.mjs → site-url-xkhw1tcz.mjs} +1 -1
  419. package/dist/{site-url-D-M4Fd8O.mjs.map → site-url-xkhw1tcz.mjs.map} +1 -1
  420. package/dist/{ssrf-DzFN_qV-.mjs → ssrf-MZ-zrG6-.mjs} +1 -1
  421. package/dist/{ssrf-DzFN_qV-.mjs.map → ssrf-MZ-zrG6-.mjs.map} +1 -1
  422. package/dist/storage/local.d.mts +1 -1
  423. package/dist/storage/local.mjs +1 -1
  424. package/dist/storage/local.mjs.map +1 -1
  425. package/dist/storage/s3.d.mts +1 -1
  426. package/dist/storage/s3.mjs +1 -1
  427. package/dist/storage/s3.mjs.map +1 -1
  428. package/dist/{taxonomies-Dc0mzlms.mjs → taxonomies-CLs9HPE2.mjs} +4 -4
  429. package/dist/{taxonomies-Dc0mzlms.mjs.map → taxonomies-CLs9HPE2.mjs.map} +1 -1
  430. package/dist/{taxonomies-Cn9UpaR2.mjs → taxonomies-WamPVA2x.mjs} +7 -42
  431. package/dist/taxonomies-WamPVA2x.mjs.map +1 -0
  432. package/dist/{taxonomy-wPfusMK9.mjs → taxonomy-D4Uc2LsZ.mjs} +3 -3
  433. package/dist/{taxonomy-wPfusMK9.mjs.map → taxonomy-D4Uc2LsZ.mjs.map} +1 -1
  434. package/dist/{tokens-DILYNZMi.mjs → tokens-N8otWMmj.mjs} +1 -1
  435. package/dist/{tokens-DILYNZMi.mjs.map → tokens-N8otWMmj.mjs.map} +1 -1
  436. package/dist/{transport-fw-mKJzT.mjs → transport-B6CHddbu.mjs} +1 -1
  437. package/dist/{transport-fw-mKJzT.mjs.map → transport-B6CHddbu.mjs.map} +1 -1
  438. package/dist/{transport-GeXlLscf.d.mts → transport-DOxLfUir.d.mts} +1 -1
  439. package/dist/{transport-GeXlLscf.d.mts.map → transport-DOxLfUir.d.mts.map} +1 -1
  440. package/dist/{trusted-proxy-CJhQIk65.mjs → trusted-proxy-97pajC2f.mjs} +1 -1
  441. package/dist/{trusted-proxy-CJhQIk65.mjs.map → trusted-proxy-97pajC2f.mjs.map} +1 -1
  442. package/dist/{types-CwXMEPRr.mjs → types-ByV5sgsv.mjs} +2 -2
  443. package/dist/types-ByV5sgsv.mjs.map +1 -0
  444. package/dist/{types-Dz9CGX_d.mjs → types-Cd9UCu3t.mjs} +1 -1
  445. package/dist/{types-Dz9CGX_d.mjs.map → types-Cd9UCu3t.mjs.map} +1 -1
  446. package/dist/{types-DmxPPXGf.d.mts → types-CkDSF81F.d.mts} +1 -1
  447. package/dist/{types-DmxPPXGf.d.mts.map → types-CkDSF81F.d.mts.map} +1 -1
  448. package/dist/{types-BWhaSS7U.d.mts → types-CpUuGcd5.d.mts} +1 -1
  449. package/dist/{types-BWhaSS7U.d.mts.map → types-CpUuGcd5.d.mts.map} +1 -1
  450. package/dist/{types-DFowNO60.d.mts → types-D599-ruj.d.mts} +1 -1
  451. package/dist/{types-DFowNO60.d.mts.map → types-D599-ruj.d.mts.map} +1 -1
  452. package/dist/{types-B05e2naf.d.mts → types-DGHWRQgr.d.mts} +3 -3
  453. package/dist/{types-B05e2naf.d.mts.map → types-DGHWRQgr.d.mts.map} +1 -1
  454. package/dist/{types-CzvJd1ND.d.mts → types-DaYDYW6g.d.mts} +14 -1
  455. package/dist/types-DaYDYW6g.d.mts.map +1 -0
  456. package/dist/{types-C1KKK4VP.d.mts → types-DaqNzqVt.d.mts} +16 -1
  457. package/dist/{types-C1KKK4VP.d.mts.map → types-DaqNzqVt.d.mts.map} +1 -1
  458. package/dist/{types-DW1l0gCv.d.mts → types-Dgo6y-Ut.d.mts} +1 -1
  459. package/dist/{types-DW1l0gCv.d.mts.map → types-Dgo6y-Ut.d.mts.map} +1 -1
  460. package/dist/{types-Cb2UCDJg.d.mts → types-bYmRn_Uy.d.mts} +1 -1
  461. package/dist/{types-Cb2UCDJg.d.mts.map → types-bYmRn_Uy.d.mts.map} +1 -1
  462. package/dist/{user-Dr1bOCqS.mjs → user-D3BD5zdT.mjs} +2 -2
  463. package/dist/{user-Dr1bOCqS.mjs.map → user-D3BD5zdT.mjs.map} +1 -1
  464. package/dist/{utils-_F-rWBTN.mjs → utils-C3wTAP-P.mjs} +1 -1
  465. package/dist/{utils-_F-rWBTN.mjs.map → utils-C3wTAP-P.mjs.map} +1 -1
  466. package/dist/{validate-BpQGsmd7.d.mts → validate-DQtHw9NT.d.mts} +5 -5
  467. package/dist/{validate-BpQGsmd7.d.mts.map → validate-DQtHw9NT.d.mts.map} +1 -1
  468. package/dist/{validate-DlFxcVVK.mjs → validate-mz87i8_1.mjs} +2 -2
  469. package/dist/{validate-DlFxcVVK.mjs.map → validate-mz87i8_1.mjs.map} +1 -1
  470. package/dist/{validation-BiFJqUp5.mjs → validation-DKHhXjPr.mjs} +5 -5
  471. package/dist/{validation-BiFJqUp5.mjs.map → validation-DKHhXjPr.mjs.map} +1 -1
  472. package/dist/version-Ct7C6RSo.mjs +7 -0
  473. package/dist/{version-Dw7Z5PVU.mjs.map → version-Ct7C6RSo.mjs.map} +1 -1
  474. package/dist/{widgets-B9j_yzlk.mjs → widgets-lShIQXU5.mjs} +3 -3
  475. package/dist/widgets-lShIQXU5.mjs.map +1 -0
  476. package/dist/{zod-generator-DSyz01KE.mjs → zod-generator-dvxgmd1M.mjs} +2 -2
  477. package/dist/{zod-generator-DSyz01KE.mjs.map → zod-generator-dvxgmd1M.mjs.map} +1 -1
  478. package/package.json +10 -8
  479. package/src/api/error.ts +18 -3
  480. package/src/api/errors.ts +6 -0
  481. package/src/api/handlers/bylines.ts +161 -0
  482. package/src/api/handlers/content.ts +125 -43
  483. package/src/api/handlers/index.ts +6 -0
  484. package/src/api/handlers/marketplace.ts +27 -5
  485. package/src/api/handlers/oauth-clients.ts +1 -1
  486. package/src/api/handlers/registry.ts +568 -22
  487. package/src/api/openapi/document.ts +1 -1
  488. package/src/api/schemas/bylines.ts +46 -0
  489. package/src/astro/integration/index.ts +1 -1
  490. package/src/astro/integration/routes.ts +5 -0
  491. package/src/astro/integration/runtime.ts +12 -1
  492. package/src/astro/integration/virtual-modules.ts +19 -2
  493. package/src/astro/integration/vite-config.ts +2 -2
  494. package/src/astro/middleware/auth.ts +7 -7
  495. package/src/astro/middleware/request-context.ts +1 -1
  496. package/src/astro/middleware.ts +31 -20
  497. package/src/astro/routes/api/admin/bylines/[id]/index.ts +3 -12
  498. package/src/astro/routes/api/admin/bylines/[id]/translations.ts +99 -0
  499. package/src/astro/routes/api/admin/bylines/index.ts +22 -11
  500. package/src/astro/routes/api/admin/plugins/[id]/update.ts +1 -0
  501. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +6 -1
  502. package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +51 -0
  503. package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +79 -0
  504. package/src/astro/routes/api/admin/plugins/updates.ts +43 -6
  505. package/src/astro/routes/api/admin/themes/marketplace/index.ts +1 -1
  506. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +2 -2
  507. package/src/astro/routes/api/auth/oauth/[provider].ts +2 -2
  508. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +2 -2
  509. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +2 -2
  510. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +2 -2
  511. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +2 -2
  512. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +2 -2
  513. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +6 -6
  514. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
  515. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +2 -2
  516. package/src/astro/routes/api/content/[collection]/[id].ts +6 -6
  517. package/src/astro/routes/api/import/wordpress/execute.ts +1 -1
  518. package/src/astro/routes/api/import/wordpress/prepare.ts +2 -2
  519. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +3 -3
  520. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +2 -2
  521. package/src/astro/routes/api/media/upload-url.ts +1 -1
  522. package/src/astro/routes/api/redirects/404s/index.ts +3 -3
  523. package/src/astro/routes/api/redirects/404s/summary.ts +1 -1
  524. package/src/astro/routes/api/redirects/[id].ts +3 -3
  525. package/src/astro/routes/api/redirects/index.ts +2 -2
  526. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +4 -4
  527. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +2 -6
  528. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +1 -1
  529. package/src/astro/routes/api/schema/collections/[slug]/index.ts +6 -6
  530. package/src/astro/routes/api/schema/collections/index.ts +4 -4
  531. package/src/astro/routes/api/schema/index.ts +1 -1
  532. package/src/astro/routes/api/schema/orphans/[slug].ts +1 -1
  533. package/src/astro/routes/api/schema/orphans/index.ts +1 -1
  534. package/src/astro/routes/api/sections/[slug].ts +3 -3
  535. package/src/astro/routes/api/sections/index.ts +2 -2
  536. package/src/astro/types.ts +4 -0
  537. package/src/auth/rate-limit.ts +1 -1
  538. package/src/auth/trusted-proxy.ts +1 -1
  539. package/src/bylines/index.ts +154 -55
  540. package/src/cli/commands/init.ts +4 -8
  541. package/src/client/index.ts +1 -1
  542. package/src/components/InlinePortableTextEditor.tsx +5 -1
  543. package/src/components/inline-code-block.tsx +343 -0
  544. package/src/config/secrets.ts +3 -3
  545. package/src/database/migrations/006_taxonomy_defs.ts +1 -1
  546. package/src/database/migrations/014_draft_revisions.ts +6 -6
  547. package/src/database/migrations/040_byline_i18n.ts +497 -0
  548. package/src/database/migrations/runner.ts +4 -1
  549. package/src/database/repositories/audit.ts +2 -2
  550. package/src/database/repositories/byline.ts +320 -50
  551. package/src/database/repositories/media.ts +2 -2
  552. package/src/database/repositories/menu.ts +1 -1
  553. package/src/database/repositories/options.ts +3 -3
  554. package/src/database/repositories/plugin-storage.ts +3 -3
  555. package/src/database/repositories/types.ts +13 -0
  556. package/src/database/types.ts +15 -0
  557. package/src/emdash-runtime.ts +492 -20
  558. package/src/i18n/config.ts +1 -1
  559. package/src/index.ts +7 -0
  560. package/src/loader.ts +1 -1
  561. package/src/mcp/server.ts +3 -3
  562. package/src/media/mime.ts +1 -1
  563. package/src/page/absolute-url.ts +1 -1
  564. package/src/plugins/adapt-sandbox-entry.ts +45 -40
  565. package/src/plugins/email-console.ts +1 -1
  566. package/src/plugins/index.ts +1 -0
  567. package/src/plugins/marketplace.ts +1 -1
  568. package/src/plugins/sandbox/index.ts +1 -0
  569. package/src/plugins/sandbox/noop.ts +11 -3
  570. package/src/plugins/sandbox/types.ts +28 -0
  571. package/src/query.ts +17 -2
  572. package/src/registry/config.ts +1 -1
  573. package/src/request-cache.ts +3 -3
  574. package/src/request-context.ts +1 -1
  575. package/src/settings/index.ts +4 -4
  576. package/src/storage/local.ts +1 -1
  577. package/src/storage/s3.ts +3 -3
  578. package/src/widgets/index.ts +1 -1
  579. package/dist/api-ayIQ7rIe.mjs.map +0 -1
  580. package/dist/byline-D09BaS4j.mjs +0 -220
  581. package/dist/byline-D09BaS4j.mjs.map +0 -1
  582. package/dist/bylines-BTM2xtP8.mjs +0 -113
  583. package/dist/bylines-BTM2xtP8.mjs.map +0 -1
  584. package/dist/bylines-C6eYUWlZ.d.mts.map +0 -1
  585. package/dist/context-qF8d3IPR.mjs.map +0 -1
  586. package/dist/email-console-Dmp5Q-P2.mjs.map +0 -1
  587. package/dist/error-tSQWIl5U.mjs.map +0 -1
  588. package/dist/index-UmOMt9T-.d.mts.map +0 -1
  589. package/dist/loader-Cs6-Bqe6.mjs.map +0 -1
  590. package/dist/media-Dg7he9uK.mjs.map +0 -1
  591. package/dist/menus-DOzIecHi.mjs.map +0 -1
  592. package/dist/menus-X4Z-eBA1.mjs.map +0 -1
  593. package/dist/oauth-clients-D_B0_-Bz.mjs.map +0 -1
  594. package/dist/options-Cq64Wx0O.d.mts.map +0 -1
  595. package/dist/redirects-Dmj6KRU3.mjs.map +0 -1
  596. package/dist/runner-DdnQIwz_.mjs.map +0 -1
  597. package/dist/settings-xQKsWnzQ.mjs.map +0 -1
  598. package/dist/taxonomies-Cn9UpaR2.mjs.map +0 -1
  599. package/dist/types-CwXMEPRr.mjs.map +0 -1
  600. package/dist/types-CzvJd1ND.d.mts.map +0 -1
  601. package/dist/version-Dw7Z5PVU.mjs +0 -7
  602. package/dist/widgets-B9j_yzlk.mjs.map +0 -1
  603. /package/dist/{api-tokens-D3C9v02m.mjs → api-tokens-iPIHAY8N.mjs} +0 -0
  604. /package/dist/{ssrf-CTul4uQi.mjs → ssrf-BIcd-aXW.mjs} +0 -0
  605. /package/dist/{types-Db67HHlU.mjs → types-1NNkmTIn.mjs} +0 -0
@@ -247,11 +247,21 @@ export interface RuntimeDependencies {
247
247
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
248
248
  createStorage: ((config: any) => Storage) | null;
249
249
  sandboxEnabled: boolean;
250
+ /** sandbox: false escape hatch - load sandboxed plugins in-process */
251
+ sandboxBypassed?: boolean;
250
252
  /** Media provider entries from virtual module */
251
253
  mediaProviderEntries?: MediaProviderEntry[];
252
254
  sandboxedPluginEntries: SandboxedPluginEntry[];
253
255
  /** Factory function matching SandboxRunnerFactory signature */
254
- createSandboxRunner: ((opts: { db: Kysely<Database> }) => SandboxRunner) | null;
256
+ createSandboxRunner:
257
+ | ((opts: {
258
+ db: Kysely<Database>;
259
+ mediaStorage?: {
260
+ upload(options: { key: string; body: Uint8Array; contentType: string }): Promise<unknown>;
261
+ delete(key: string): Promise<unknown>;
262
+ };
263
+ }) => SandboxRunner)
264
+ | null;
255
265
  }
256
266
 
257
267
  /**
@@ -393,7 +403,7 @@ export class EmDashRuntime {
393
403
  get db(): Kysely<Database> {
394
404
  const ctx = getRequestContext();
395
405
  if (ctx?.db) {
396
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- db in context is set by middleware with correct type
406
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- db in context is set by middleware with correct type
397
407
  return ctx.db as Kysely<Database>;
398
408
  }
399
409
  return this._db;
@@ -428,6 +438,16 @@ export class EmDashRuntime {
428
438
  return sandboxRunner;
429
439
  }
430
440
 
441
+ /**
442
+ * Whether the sandbox bypass mode (sandbox: false) is active.
443
+ * Marketplace install/update handlers use this to skip the
444
+ * SANDBOX_NOT_AVAILABLE gate, since the bypass path loads
445
+ * marketplace plugins in-process via syncMarketplacePlugins().
446
+ */
447
+ isSandboxBypassed(): boolean {
448
+ return this.runtimeDeps.sandboxBypassed === true;
449
+ }
450
+
431
451
  /**
432
452
  * Tick the cron system from request context (piggyback mode).
433
453
  * Call this from middleware on each request to ensure cron tasks
@@ -519,6 +539,17 @@ export class EmDashRuntime {
519
539
  */
520
540
  async syncMarketplacePlugins(): Promise<void> {
521
541
  if (!this.config.marketplace) return;
542
+
543
+ // In sandbox bypass mode (sandbox: false), the noop runner reports
544
+ // unavailable but we still want admin metadata for newly installed
545
+ // marketplace plugins to refresh in-process. Hooks/routes still won't
546
+ // execute (matches the cold-start bypass behavior), but Configure
547
+ // links and admin pages appear immediately.
548
+ if (this.runtimeDeps.sandboxBypassed) {
549
+ await this.syncMarketplacePluginsBypassed();
550
+ return;
551
+ }
552
+
522
553
  await this.syncSandboxedSourcePlugins("marketplace");
523
554
  }
524
555
 
@@ -537,8 +568,8 @@ export class EmDashRuntime {
537
568
  /**
538
569
  * Internal: reconcile in-memory sandboxed-plugin state with the
539
570
  * `_plugin_state` table for the given source tier. Shared
540
- * implementation behind `syncMarketplacePlugins` and
541
- * `syncRegistryPlugins`.
571
+ * implementation behind {@link syncMarketplacePlugins} and
572
+ * {@link syncRegistryPlugins}.
542
573
  *
543
574
  * Each source tier has its own key set in `${source}PluginKeys` so a
544
575
  * sync for one tier doesn't invalidate the other.
@@ -652,6 +683,173 @@ export class EmDashRuntime {
652
683
  }
653
684
  }
654
685
 
686
+ /**
687
+ * Remove a plugin from the in-memory pipeline lists by ID.
688
+ * Mutates allPipelinePlugins and configuredPlugins in place.
689
+ */
690
+ private removePluginFromLists(pluginId: string): void {
691
+ const allIdx = this.allPipelinePlugins.findIndex((p) => p.id === pluginId);
692
+ if (allIdx !== -1) this.allPipelinePlugins.splice(allIdx, 1);
693
+ const configIdx = this.configuredPlugins.findIndex((p) => p.id === pluginId);
694
+ if (configIdx !== -1) this.configuredPlugins.splice(configIdx, 1);
695
+ }
696
+
697
+ /**
698
+ * Sync marketplace plugin metadata in sandbox: false bypass mode.
699
+ *
700
+ * In bypass mode the noop runner can't load plugins, but admin pages,
701
+ * widgets, and route metadata still need to refresh in-process when an
702
+ * admin installs/updates/uninstalls a marketplace plugin. Otherwise the
703
+ * admin UI shows stale data until the server restarts.
704
+ *
705
+ * Hooks and routes still won't execute under bypass (matches the
706
+ * cold-start bypass behavior in loadMarketplacePluginsBypassed).
707
+ *
708
+ * Known limitation: bypass plugins are loaded via `import(dataUrl)`,
709
+ * which Node's ESM cache keys on the full URL. Updates create fresh
710
+ * module objects, but old ones remain cached for the worker's lifetime.
711
+ * In practice this is a few KB per update — only matters for sites with
712
+ * very frequent marketplace updates running long-lived processes. The
713
+ * fix would be vm.SourceTextModule for explicit lifecycle management.
714
+ */
715
+ private async syncMarketplacePluginsBypassed(): Promise<void> {
716
+ if (!this.storage) return;
717
+ try {
718
+ const stateRepo = new PluginStateRepository(this.db);
719
+ const marketplaceStates = await stateRepo.getMarketplacePlugins();
720
+
721
+ const desired = new Map<string, string>();
722
+ for (const state of marketplaceStates) {
723
+ this.pluginStates.set(state.pluginId, state.status);
724
+ if (state.status === "active") {
725
+ this.enabledPlugins.add(state.pluginId);
726
+ } else {
727
+ this.enabledPlugins.delete(state.pluginId);
728
+ }
729
+ if (state.status !== "active") continue;
730
+ desired.set(state.pluginId, state.marketplaceVersion ?? state.version);
731
+ }
732
+
733
+ // Drop metadata for plugins no longer active.
734
+ const toRemove: string[] = [];
735
+ for (const pluginId of marketplaceManifestCache.keys()) {
736
+ if (!desired.has(pluginId)) toRemove.push(pluginId);
737
+ }
738
+ for (const pluginId of toRemove) {
739
+ // Fire plugin:deactivate hook before removal
740
+ const resolved = this.allPipelinePlugins.find((p) => p.id === pluginId);
741
+ if (resolved) {
742
+ try {
743
+ const deactivateHook = resolved.hooks?.["plugin:deactivate"];
744
+ if (deactivateHook) {
745
+ const handler =
746
+ typeof deactivateHook === "function" ? deactivateHook : deactivateHook.handler;
747
+ if (typeof handler === "function") {
748
+ // Sandbox-bypass cleanup: the plugin context isn't constructable
749
+ // here (no DB binding, no media, etc.), but well-behaved
750
+ // deactivate hooks should be no-op safe. If a hook does require
751
+ // ctx, it throws and the surrounding catch logs it.
752
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- best-effort cleanup; see comment above
753
+ await handler({ pluginId }, {} as never);
754
+ }
755
+ }
756
+ } catch (err) {
757
+ console.warn(`[emdash] plugin:deactivate hook failed for ${pluginId}:`, err);
758
+ }
759
+ }
760
+ marketplaceManifestCache.delete(pluginId);
761
+ sandboxedRouteMetaCache.delete(pluginId);
762
+ // Remove from pipeline lists too (mutate in place since the
763
+ // arrays are readonly references but mutable contents)
764
+ this.removePluginFromLists(pluginId);
765
+ this.enabledPlugins.delete(pluginId);
766
+ }
767
+
768
+ // Load plugin code, adapt as trusted plugins, and add to pipeline lists
769
+ const { adaptSandboxEntry } = await import("./plugins/adapt-sandbox-entry.js");
770
+ const newPlugins: ResolvedPlugin[] = [];
771
+ for (const [pluginId, version] of desired) {
772
+ const bundle = await loadBundleFromR2(this.storage, pluginId, version);
773
+ if (!bundle) {
774
+ console.warn(`EmDash: Marketplace plugin ${pluginId}@${version} not found in R2`);
775
+ continue;
776
+ }
777
+ marketplaceManifestCache.set(pluginId, {
778
+ id: bundle.manifest.id,
779
+ version: bundle.manifest.version,
780
+ admin: bundle.manifest.admin,
781
+ });
782
+ if (bundle.manifest.routes.length > 0) {
783
+ const routeMetaMap = new Map<string, RouteMeta>();
784
+ for (const entry of bundle.manifest.routes) {
785
+ const normalized = normalizeManifestRoute(entry);
786
+ routeMetaMap.set(normalized.name, { public: normalized.public === true });
787
+ }
788
+ sandboxedRouteMetaCache.set(pluginId, routeMetaMap);
789
+ } else {
790
+ sandboxedRouteMetaCache.delete(pluginId);
791
+ }
792
+
793
+ // Skip if already in the pipeline at this version
794
+ const existing = this.allPipelinePlugins.find((p) => p.id === pluginId);
795
+ if (existing && existing.version === bundle.manifest.version) continue;
796
+
797
+ // Remove any older version
798
+ if (existing) {
799
+ this.removePluginFromLists(pluginId);
800
+ }
801
+
802
+ try {
803
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(bundle.backendCode).toString("base64")}`;
804
+ // Dynamic data: import returns `any` from a base64-encoded module.
805
+ // We trust the bundle to be shaped like a plugin (built by plugin-cli);
806
+ // adaptSandboxEntry then validates fields it cares about.
807
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- dynamic module from trusted bundle
808
+ const pluginModule = (await import(/* @vite-ignore */ dataUrl)) as Record<
809
+ string,
810
+ unknown
811
+ >;
812
+ const pluginDef = (pluginModule.default ?? pluginModule) as Parameters<
813
+ typeof adaptSandboxEntry
814
+ >[0];
815
+ const adapted = adaptSandboxEntry(pluginDef, {
816
+ id: bundle.manifest.id,
817
+ version: bundle.manifest.version,
818
+ entrypoint: "",
819
+ capabilities: bundle.manifest.capabilities ?? [],
820
+ allowedHosts: bundle.manifest.allowedHosts ?? [],
821
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- adaptSandboxEntry copies storage through
822
+ storage: (bundle.manifest.storage ?? {}) as never,
823
+ adminPages: bundle.manifest.admin?.pages,
824
+ adminWidgets: bundle.manifest.admin?.widgets?.map((w) => ({
825
+ id: w.id,
826
+ title: w.title,
827
+ size:
828
+ w.size === "full" || w.size === "half" || w.size === "third" ? w.size : undefined,
829
+ })),
830
+ });
831
+ newPlugins.push(adapted);
832
+ this.allPipelinePlugins.push(adapted);
833
+ this.configuredPlugins.push(adapted);
834
+ this.enabledPlugins.add(adapted.id);
835
+ } catch (error) {
836
+ console.error(
837
+ `EmDash: Failed to load marketplace plugin ${pluginId}@${version} in-process:`,
838
+ error,
839
+ );
840
+ }
841
+ }
842
+
843
+ // If anything changed, rebuild the hook pipeline so new/removed
844
+ // plugins take effect immediately without a server restart.
845
+ if (toRemove.length > 0 || newPlugins.length > 0) {
846
+ await this.rebuildHookPipeline();
847
+ }
848
+ } catch (error) {
849
+ console.error("EmDash: Failed to sync marketplace plugins (bypass):", error);
850
+ }
851
+ }
852
+
655
853
  /**
656
854
  * Create and initialize the runtime
657
855
  */
@@ -737,6 +935,11 @@ export class EmDashRuntime {
737
935
  // rebuildHookPipeline() filters this to only enabled plugins.
738
936
  const allPipelinePlugins: ResolvedPlugin[] = [...deps.plugins];
739
937
 
938
+ // Collected bypassed plugins (sandbox: false escape hatch).
939
+ // These need to be added to BOTH the pipeline (for hooks) AND the
940
+ // configuredPlugins list (for route dispatch).
941
+ const bypassedPluginsList: ResolvedPlugin[] = [];
942
+
740
943
  // In dev mode, register a built-in console email provider.
741
944
  // It participates in exclusive hook resolution like any other plugin —
742
945
  // auto-selected when it's the sole provider, overridden when a real one is configured.
@@ -784,6 +987,53 @@ export class EmDashRuntime {
784
987
  console.warn("[comments] Failed to register default moderator:", error);
785
988
  }
786
989
 
990
+ // sandbox: false escape hatch - load sandboxed plugin entries in-process
991
+ // as trusted plugins (no isolation) so they participate in the hook pipeline.
992
+ // Block this on Cloudflare Workers where dynamic import(dataUrl) is not
993
+ // available and running untrusted code in-process is a security risk.
994
+ if (deps.sandboxBypassed && deps.sandboxedPluginEntries.length > 0) {
995
+ const isCfWorkers =
996
+ typeof navigator !== "undefined" &&
997
+ typeof navigator.userAgent === "string" &&
998
+ navigator.userAgent.includes("Cloudflare-Workers");
999
+ if (isCfWorkers) {
1000
+ throw new Error(
1001
+ "sandbox: false is not supported in Cloudflare Workers. " +
1002
+ "Remove the sandbox: false option or use the Cloudflare sandbox runner.",
1003
+ );
1004
+ }
1005
+ console.info(
1006
+ "EmDash: Sandbox disabled (sandbox: false). " +
1007
+ "Sandboxed plugins will run in-process without isolation.",
1008
+ );
1009
+ const bypassedPlugins = await EmDashRuntime.loadBypassedPlugins(deps.sandboxedPluginEntries);
1010
+ for (const plugin of bypassedPlugins) {
1011
+ allPipelinePlugins.push(plugin);
1012
+ bypassedPluginsList.push(plugin);
1013
+ // Respect plugin state: only enable if active or no record exists.
1014
+ // Plugins an admin previously disabled should stay disabled.
1015
+ const status = pluginStates.get(plugin.id);
1016
+ if (status === undefined || status === "active") {
1017
+ enabledPlugins.add(plugin.id);
1018
+ }
1019
+ }
1020
+ }
1021
+
1022
+ // In bypass mode, also load marketplace plugins from R2 as trusted
1023
+ // in-process plugins BEFORE pipeline creation. They need to be in the
1024
+ // pipeline to participate in hook dispatch.
1025
+ if (deps.sandboxBypassed && deps.config.marketplace && storage) {
1026
+ const marketplaceBypassed = await EmDashRuntime.loadMarketplacePluginsBypassed(db, storage);
1027
+ for (const plugin of marketplaceBypassed) {
1028
+ allPipelinePlugins.push(plugin);
1029
+ bypassedPluginsList.push(plugin);
1030
+ const status = pluginStates.get(plugin.id);
1031
+ if (status === undefined || status === "active") {
1032
+ enabledPlugins.add(plugin.id);
1033
+ }
1034
+ }
1035
+ }
1036
+
787
1037
  // Filter to currently enabled plugins for the initial pipeline
788
1038
  const enabledPluginList = allPipelinePlugins.filter((p) => enabledPlugins.has(p.id));
789
1039
 
@@ -795,13 +1045,14 @@ export class EmDashRuntime {
795
1045
  };
796
1046
  const pipeline = createHookPipeline(enabledPluginList, pipelineFactoryOptions);
797
1047
 
798
- // Load sandboxed plugins (build-time)
1048
+ // Load sandboxed plugins (build-time, sandbox runner path)
799
1049
  const sandboxedPlugins = await phase("rt.sandbox", "Sandboxed plugins", () =>
800
- EmDashRuntime.loadSandboxedPlugins(deps, db),
1050
+ EmDashRuntime.loadSandboxedPlugins(deps, db, storage),
801
1051
  );
802
1052
 
803
- // Cold-start: load marketplace-installed plugins from site R2
804
- if (deps.config.marketplace && storage) {
1053
+ // Cold-start: load marketplace-installed plugins from site R2 via
1054
+ // the sandbox runner. In bypass mode this was already handled above.
1055
+ if (deps.config.marketplace && storage && !deps.sandboxBypassed) {
805
1056
  await phase("rt.market", "Marketplace plugins", () =>
806
1057
  EmDashRuntime.loadInstalledSandboxedPlugins(
807
1058
  "marketplace",
@@ -942,7 +1193,10 @@ export class EmDashRuntime {
942
1193
  return new EmDashRuntime({
943
1194
  db,
944
1195
  storage,
945
- configuredPlugins: deps.plugins,
1196
+ // Include bypassed sandboxed plugins in configuredPlugins so route
1197
+ // dispatch can find them under sandbox: false (they're treated as
1198
+ // trusted plugins for the duration of the bypass).
1199
+ configuredPlugins: [...deps.plugins, ...bypassedPluginsList],
946
1200
  sandboxedPlugins,
947
1201
  sandboxedPluginEntries: deps.sandboxedPluginEntries,
948
1202
  hooks: pipeline,
@@ -997,7 +1251,7 @@ export class EmDashRuntime {
997
1251
  // path gives us a fresh singleton instead.
998
1252
  const ctx = getRequestContext();
999
1253
  if (ctx?.dbIsIsolated && ctx.db) {
1000
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- db in context is typed as unknown to avoid circular deps
1254
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- db in context is typed as unknown to avoid circular deps
1001
1255
  return ctx.db as Kysely<Database>;
1002
1256
  }
1003
1257
 
@@ -1115,12 +1369,84 @@ export class EmDashRuntime {
1115
1369
  return storage;
1116
1370
  }
1117
1371
 
1372
+ /**
1373
+ * Load sandboxed plugin entries as trusted in-process plugins.
1374
+ * Used by the sandbox: false debugging escape hatch.
1375
+ *
1376
+ * Imports each plugin's bundled ESM code via a data URL, adapts it
1377
+ * with adaptSandboxEntry, and returns ResolvedPlugin objects ready
1378
+ * to be merged into the pipeline plugin list.
1379
+ */
1380
+ private static async loadBypassedPlugins(
1381
+ entries: SandboxedPluginEntry[],
1382
+ ): Promise<ResolvedPlugin[]> {
1383
+ const { adaptSandboxEntry } = await import("./plugins/adapt-sandbox-entry.js");
1384
+ const plugins: ResolvedPlugin[] = [];
1385
+ for (const entry of entries) {
1386
+ try {
1387
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(entry.code).toString("base64")}`;
1388
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- dynamic module from trusted bundle (built by plugin-cli); adaptSandboxEntry validates required fields.
1389
+ const pluginModule = (await import(/* @vite-ignore */ dataUrl)) as Record<string, unknown>;
1390
+ const pluginDef = (pluginModule.default ?? pluginModule) as Parameters<
1391
+ typeof adaptSandboxEntry
1392
+ >[0];
1393
+ // PluginDescriptor.storage's TypeScript type is narrower than what
1394
+ // adaptSandboxEntry actually accepts at runtime — it copies indexes
1395
+ // through to PluginStorageConfig which supports composite indexes
1396
+ // (string[][]). Pass the raw entry.storage with a structural cast
1397
+ // to preserve composite index declarations.
1398
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- adaptSandboxEntry copies storage through to PluginStorageConfig which supports composite indexes
1399
+ // Preserve admin metadata so plugin-management APIs can derive
1400
+ // hasAdminPages / hasDashboardWidgets correctly. Without this,
1401
+ // the admin UI hides Configure links and dashboard widgets for
1402
+ // bypassed plugins even though they declared them.
1403
+ // SandboxedPluginEntry uses looser types than PluginDescriptor
1404
+ // (label?, size: string), so coerce to the descriptor shape.
1405
+ const adminPages = entry.adminPages?.map((p) => ({
1406
+ path: p.path,
1407
+ label: p.label ?? p.path,
1408
+ icon: p.icon,
1409
+ }));
1410
+ const adminWidgets:
1411
+ | Array<{
1412
+ id: string;
1413
+ title?: string;
1414
+ size?: "full" | "half" | "third";
1415
+ }>
1416
+ | undefined = entry.adminWidgets?.map((w) => {
1417
+ const size: "full" | "half" | "third" | undefined =
1418
+ w.size === "full" || w.size === "half" || w.size === "third" ? w.size : undefined;
1419
+ return { id: w.id, title: w.title, size };
1420
+ });
1421
+ const resolved = adaptSandboxEntry(pluginDef, {
1422
+ id: entry.id,
1423
+ version: entry.version,
1424
+ entrypoint: "",
1425
+ capabilities: entry.capabilities,
1426
+ allowedHosts: entry.allowedHosts,
1427
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- adaptSandboxEntry copies storage through
1428
+ storage: entry.storage as never,
1429
+ adminPages,
1430
+ adminWidgets,
1431
+ });
1432
+ plugins.push(resolved);
1433
+ console.log(
1434
+ `EmDash: Loaded plugin ${entry.id}:${entry.version} in-process (sandbox bypassed)`,
1435
+ );
1436
+ } catch (error) {
1437
+ console.error(`EmDash: Failed to load sandboxed plugin ${entry.id} in-process:`, error);
1438
+ }
1439
+ }
1440
+ return plugins;
1441
+ }
1442
+
1118
1443
  /**
1119
1444
  * Load sandboxed plugins using SandboxRunner
1120
1445
  */
1121
1446
  private static async loadSandboxedPlugins(
1122
1447
  deps: RuntimeDependencies,
1123
1448
  db: Kysely<Database>,
1449
+ mediaStorage?: Storage | null,
1124
1450
  ): Promise<Map<string, SandboxedPluginInstance>> {
1125
1451
  // Return cached plugins if already loaded
1126
1452
  if (sandboxedPluginCache.size > 0) {
@@ -1128,26 +1454,56 @@ export class EmDashRuntime {
1128
1454
  }
1129
1455
 
1130
1456
  // Check if sandboxing is enabled
1131
- if (!deps.sandboxEnabled || deps.sandboxedPluginEntries.length === 0) {
1457
+ if (!deps.sandboxEnabled) {
1132
1458
  return sandboxedPluginCache;
1133
1459
  }
1134
1460
 
1135
1461
  // Create sandbox runner if not exists
1136
1462
  if (!sandboxRunner && deps.createSandboxRunner) {
1137
- sandboxRunner = deps.createSandboxRunner({ db });
1463
+ sandboxRunner = deps.createSandboxRunner({
1464
+ db,
1465
+ mediaStorage: mediaStorage
1466
+ ? {
1467
+ upload: (opts) =>
1468
+ mediaStorage.upload({
1469
+ key: opts.key,
1470
+ body: opts.body,
1471
+ contentType: opts.contentType,
1472
+ }),
1473
+ delete: (key) => mediaStorage.delete(key),
1474
+ }
1475
+ : undefined,
1476
+ });
1138
1477
  }
1139
1478
 
1140
1479
  if (!sandboxRunner) {
1141
1480
  return sandboxedPluginCache;
1142
1481
  }
1143
1482
 
1144
- // Check if the runner is actually available (has required bindings)
1483
+ // Check if the runner is actually available (has required bindings).
1484
+ // Warn regardless of whether there are plugins to load, so operators
1485
+ // see the issue even if no marketplace plugins are installed yet.
1145
1486
  if (!sandboxRunner.isAvailable()) {
1146
- console.debug("EmDash: Sandbox runner not available (missing bindings), skipping sandbox");
1487
+ console.warn(
1488
+ "EmDash: Plugin sandbox is configured but not available on this platform. " +
1489
+ "Sandboxed plugins will not be loaded. " +
1490
+ "If using @emdash-cms/sandbox-workerd/sandbox, ensure workerd is installed.",
1491
+ );
1492
+ return sandboxedPluginCache;
1493
+ }
1494
+
1495
+ if (deps.sandboxedPluginEntries.length === 0) {
1496
+ return sandboxedPluginCache;
1497
+ }
1498
+
1499
+ // sandbox: false escape hatch is handled separately (before pipeline
1500
+ // creation) via loadBypassedPlugins. If we somehow reach here with the
1501
+ // flag set, just return — the plugins are already in the trusted pipeline.
1502
+ if (deps.sandboxBypassed) {
1147
1503
  return sandboxedPluginCache;
1148
1504
  }
1149
1505
 
1150
- // Load each sandboxed plugin
1506
+ // Load each sandboxed plugin via sandbox runner
1151
1507
  for (const entry of deps.sandboxedPluginEntries) {
1152
1508
  const pluginKey = `${entry.id}:${entry.version}`;
1153
1509
  if (sandboxedPluginCache.has(pluginKey)) {
@@ -1201,10 +1557,26 @@ export class EmDashRuntime {
1201
1557
  deps: RuntimeDependencies,
1202
1558
  cache: Map<string, SandboxedPluginInstance>,
1203
1559
  ): Promise<void> {
1204
- // Ensure sandbox runner exists
1560
+ // Ensure sandbox runner exists with media storage wired up.
1561
+ // (storage here is the media Storage adapter from the runtime.)
1205
1562
  if (!sandboxRunner && deps.createSandboxRunner) {
1206
- sandboxRunner = deps.createSandboxRunner({ db });
1563
+ sandboxRunner = deps.createSandboxRunner({
1564
+ db,
1565
+ mediaStorage: {
1566
+ upload: (opts) =>
1567
+ storage.upload({
1568
+ key: opts.key,
1569
+ body: opts.body,
1570
+ contentType: opts.contentType,
1571
+ }),
1572
+ delete: (key) => storage.delete(key),
1573
+ },
1574
+ });
1207
1575
  }
1576
+ // In sandbox bypass mode, marketplace plugins are loaded in-process
1577
+ // BEFORE pipeline creation by EmDashRuntime.create(). Skip here.
1578
+ if (deps.sandboxBypassed) return;
1579
+
1208
1580
  if (!sandboxRunner || !sandboxRunner.isAvailable()) {
1209
1581
  return;
1210
1582
  }
@@ -1270,6 +1642,106 @@ export class EmDashRuntime {
1270
1642
  }
1271
1643
  }
1272
1644
 
1645
+ /**
1646
+ * Cold-start: load marketplace plugins in bypass mode (sandbox: false).
1647
+ *
1648
+ * Each active marketplace bundle is read, evaluated via data URL, adapted
1649
+ * with adaptSandboxEntry, and returned as a ResolvedPlugin. The caller is
1650
+ * responsible for merging these into allPipelinePlugins / configuredPlugins
1651
+ * BEFORE the hook pipeline is created, so hooks and routes register in
1652
+ * the trusted pipeline.
1653
+ *
1654
+ * Also caches manifest and route metadata so admin UI / getManifest() work.
1655
+ *
1656
+ * Returns ResolvedPlugins to be merged into the pipeline.
1657
+ */
1658
+ private static async loadMarketplacePluginsBypassed(
1659
+ db: Kysely<Database>,
1660
+ storage: Storage,
1661
+ ): Promise<ResolvedPlugin[]> {
1662
+ const resolved: ResolvedPlugin[] = [];
1663
+ try {
1664
+ const stateRepo = new PluginStateRepository(db);
1665
+ const marketplacePlugins = await stateRepo.getMarketplacePlugins();
1666
+ if (marketplacePlugins.length === 0) return resolved;
1667
+
1668
+ console.info(
1669
+ "EmDash: Sandbox disabled (sandbox: false). " +
1670
+ "Marketplace plugins will run in-process without isolation.",
1671
+ );
1672
+
1673
+ const { adaptSandboxEntry } = await import("./plugins/adapt-sandbox-entry.js");
1674
+
1675
+ for (const plugin of marketplacePlugins) {
1676
+ if (plugin.status !== "active") continue;
1677
+ const version = plugin.marketplaceVersion ?? plugin.version;
1678
+ try {
1679
+ const bundle = await loadBundleFromR2(storage, plugin.pluginId, version);
1680
+ if (!bundle) {
1681
+ console.warn(
1682
+ `EmDash: Marketplace plugin ${plugin.pluginId}@${version} not found in R2`,
1683
+ );
1684
+ continue;
1685
+ }
1686
+
1687
+ // Cache manifest and route metadata for admin UI and route auth
1688
+ marketplaceManifestCache.set(plugin.pluginId, {
1689
+ id: bundle.manifest.id,
1690
+ version: bundle.manifest.version,
1691
+ admin: bundle.manifest.admin,
1692
+ });
1693
+ if (bundle.manifest.routes.length > 0) {
1694
+ const routeMeta = new Map<string, RouteMeta>();
1695
+ for (const entry of bundle.manifest.routes) {
1696
+ const normalized = normalizeManifestRoute(entry);
1697
+ routeMeta.set(normalized.name, { public: normalized.public === true });
1698
+ }
1699
+ sandboxedRouteMetaCache.set(plugin.pluginId, routeMeta);
1700
+ }
1701
+
1702
+ // Evaluate the bundled ESM and adapt it as a trusted plugin
1703
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(bundle.backendCode).toString("base64")}`;
1704
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- dynamic module from trusted bundle (built by plugin-cli); adaptSandboxEntry validates required fields.
1705
+ const pluginModule = (await import(/* @vite-ignore */ dataUrl)) as Record<
1706
+ string,
1707
+ unknown
1708
+ >;
1709
+ const pluginDef = (pluginModule.default ?? pluginModule) as Parameters<
1710
+ typeof adaptSandboxEntry
1711
+ >[0];
1712
+ const adapted = adaptSandboxEntry(pluginDef, {
1713
+ id: bundle.manifest.id,
1714
+ version: bundle.manifest.version,
1715
+ entrypoint: "",
1716
+ capabilities: bundle.manifest.capabilities ?? [],
1717
+ allowedHosts: bundle.manifest.allowedHosts ?? [],
1718
+ // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- adaptSandboxEntry copies storage through
1719
+ storage: (bundle.manifest.storage ?? {}) as never,
1720
+ adminPages: bundle.manifest.admin?.pages,
1721
+ adminWidgets: bundle.manifest.admin?.widgets?.map((w) => ({
1722
+ id: w.id,
1723
+ title: w.title,
1724
+ size:
1725
+ w.size === "full" || w.size === "half" || w.size === "third" ? w.size : undefined,
1726
+ })),
1727
+ });
1728
+ resolved.push(adapted);
1729
+ console.log(
1730
+ `EmDash: Loaded marketplace plugin ${plugin.pluginId}@${version} in-process (sandbox bypassed)`,
1731
+ );
1732
+ } catch (error) {
1733
+ console.error(
1734
+ `EmDash: Failed to load marketplace plugin ${plugin.pluginId} in-process:`,
1735
+ error,
1736
+ );
1737
+ }
1738
+ }
1739
+ } catch {
1740
+ // _plugin_state table may not exist yet
1741
+ }
1742
+ return resolved;
1743
+ }
1744
+
1273
1745
  /**
1274
1746
  * Resolve exclusive hook selections on startup.
1275
1747
  *
@@ -1676,7 +2148,7 @@ export class EmDashRuntime {
1676
2148
  */
1677
2149
  private async hydrateDraftData<T>(result: T): Promise<T> {
1678
2150
  if (!result || typeof result !== "object") return result;
1679
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- shape probed below
2151
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- shape probed below
1680
2152
  const r = result as {
1681
2153
  success?: boolean;
1682
2154
  data?: { item?: Record<string, unknown> };
@@ -1690,7 +2162,7 @@ export class EmDashRuntime {
1690
2162
  if (!revision) return result;
1691
2163
  const liveData =
1692
2164
  item.data && typeof item.data === "object"
1693
- ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowed to object above
2165
+ ? // eslint-disable-next-line typescript/no-unsafe-type-assertion -- narrowed to object above
1694
2166
  (item.data as Record<string, unknown>)
1695
2167
  : {};
1696
2168
  // Strip leading-underscore keys (`_slug`, `_rev`, etc.) from the
@@ -1711,7 +2183,7 @@ export class EmDashRuntime {
1711
2183
  // hydrated item without going back through `unknown`.
1712
2184
  return {
1713
2185
  ...result,
1714
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- shape preserved; result has been narrowed to the {success,data:{item}} envelope
2186
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- shape preserved; result has been narrowed to the {success,data:{item}} envelope
1715
2187
  data: {
1716
2188
  ...r.data,
1717
2189
  item: { ...item, data: mergedData, liveData },
@@ -51,7 +51,7 @@ export function getFallbackChain(locale: string): string[] {
51
51
  const visited = new Set<string>([locale]);
52
52
 
53
53
  while (_config.fallback?.[current]) {
54
- // eslint-disable-next-line typescript-eslint(no-unnecessary-type-assertion) -- noUncheckedIndexedAccess
54
+ // eslint-disable-next-line typescript/no-unnecessary-type-assertion -- noUncheckedIndexedAccess
55
55
  const next = _config.fallback[current]!;
56
56
  if (visited.has(next)) break; // prevent cycles
57
57
  chain.push(next);
package/src/index.ts CHANGED
@@ -12,6 +12,9 @@ export type {
12
12
  export {
13
13
  ContentRepository,
14
14
  MediaRepository,
15
+ PluginStorageRepository,
16
+ UserRepository,
17
+ OptionsRepository,
15
18
  EmDashValidationError,
16
19
  InvalidCursorError,
17
20
  } from "./database/repositories/index.js";
@@ -198,7 +201,11 @@ export {
198
201
  // Sandbox
199
202
  NoopSandboxRunner,
200
203
  SandboxNotAvailableError,
204
+ SandboxUnavailableError,
201
205
  createNoopSandboxRunner,
206
+ // HTTP access for plugins (shared between in-process, Cloudflare, and workerd runners)
207
+ createHttpAccess,
208
+ createUnrestrictedHttpAccess,
202
209
  } from "./plugins/index.js";
203
210
  export type {
204
211
  PluginDefinition,