emdash 0.14.0 → 0.16.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 (650) 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-BMLZuwM4.mjs → api-BNKqxyFX.mjs} +560 -56
  10. package/dist/api-BNKqxyFX.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-BOPaD-s9.mjs} +17 -17
  14. package/dist/{apply-v4DBgjPw.mjs.map → apply-BOPaD-s9.mjs.map} +1 -1
  15. package/dist/astro/index.d.mts +10 -10
  16. package/dist/astro/index.d.mts.map +1 -1
  17. package/dist/astro/index.mjs +53 -5
  18. package/dist/astro/index.mjs.map +1 -1
  19. package/dist/astro/middleware/auth.d.mts +9 -9
  20. package/dist/astro/middleware/auth.mjs +6 -6
  21. package/dist/astro/middleware/auth.mjs.map +1 -1
  22. package/dist/astro/middleware/redirect.mjs +4 -4
  23. package/dist/astro/middleware/request-context.mjs +3 -3
  24. package/dist/astro/middleware/request-context.mjs.map +1 -1
  25. package/dist/astro/middleware/setup.mjs +1 -1
  26. package/dist/astro/middleware.d.mts.map +1 -1
  27. package/dist/astro/middleware.mjs +377 -75
  28. package/dist/astro/middleware.mjs.map +1 -1
  29. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -5
  30. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -5
  31. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  32. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  33. package/dist/astro/routes/api/admin/bylines/_id_/index.d.mts.map +1 -1
  34. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -17
  35. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  36. package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts +9 -0
  37. package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts.map +1 -0
  38. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +70 -0
  39. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -0
  40. package/dist/astro/routes/api/admin/bylines/index.d.mts.map +1 -1
  41. package/dist/astro/routes/api/admin/bylines/index.mjs +25 -16
  42. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  43. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +10 -10
  44. package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
  45. package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
  46. package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
  47. package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
  48. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  49. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  50. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  51. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  52. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +33 -32
  53. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  54. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +33 -32
  55. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +32 -31
  57. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  58. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +32 -31
  59. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  60. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +34 -32
  61. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  62. package/dist/astro/routes/api/admin/plugins/index.mjs +32 -31
  63. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  65. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +32 -31
  66. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +34 -32
  68. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +32 -31
  70. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts +8 -0
  72. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -0
  73. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +59 -0
  74. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -0
  75. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts +8 -0
  76. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -0
  77. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +85 -0
  78. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -0
  79. package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts +8 -0
  80. package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts.map +1 -0
  81. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +301 -0
  82. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -0
  83. package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +51 -32
  85. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/updates.d.mts.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/updates.mjs +45 -32
  88. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +32 -31
  90. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  92. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +32 -31
  93. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  95. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  96. package/dist/astro/routes/api/admin/users/_id_/index.mjs +5 -5
  97. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  98. package/dist/astro/routes/api/admin/users/index.mjs +5 -5
  99. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
  100. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  101. package/dist/astro/routes/api/auth/invite/complete.mjs +9 -9
  102. package/dist/astro/routes/api/auth/invite/index.mjs +6 -6
  103. package/dist/astro/routes/api/auth/invite/register-options.mjs +8 -8
  104. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  105. package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -8
  106. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  107. package/dist/astro/routes/api/auth/me.mjs +5 -5
  108. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  109. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  110. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs.map +1 -1
  111. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  112. package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
  113. package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -5
  114. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  115. package/dist/astro/routes/api/auth/passkey/options.mjs +10 -10
  116. package/dist/astro/routes/api/auth/passkey/register/options.mjs +8 -8
  117. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +9 -9
  118. package/dist/astro/routes/api/auth/passkey/verify.mjs +9 -9
  119. package/dist/astro/routes/api/auth/signup/complete.mjs +9 -9
  120. package/dist/astro/routes/api/auth/signup/request.mjs +8 -8
  121. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  122. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
  123. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  124. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  125. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  126. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  127. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs.map +1 -1
  128. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  129. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +9 -9
  130. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -6
  131. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  132. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  133. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs.map +1 -1
  134. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  135. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +6 -6
  136. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  137. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +10 -9
  138. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  139. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  140. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs.map +1 -1
  141. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  142. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  143. package/dist/astro/routes/api/content/_collection_/_id_.mjs +6 -6
  144. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  145. package/dist/astro/routes/api/content/_collection_/index.mjs +6 -6
  146. package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -6
  147. package/dist/astro/routes/api/dashboard.mjs +7 -7
  148. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  149. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  150. package/dist/astro/routes/api/import/probe.mjs +10 -10
  151. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  152. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  153. package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -8
  154. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  155. package/dist/astro/routes/api/import/wordpress/media.mjs +8 -8
  156. package/dist/astro/routes/api/import/wordpress/prepare.mjs +8 -8
  157. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  158. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.d.mts +11 -1
  159. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.d.mts.map +1 -1
  160. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.mjs +17 -1
  161. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.mjs.map +1 -1
  162. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
  163. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +9 -9
  164. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  165. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  166. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +10 -10
  167. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  168. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +11 -11
  169. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  170. package/dist/astro/routes/api/manifest.mjs +4 -4
  171. package/dist/astro/routes/api/mcp.mjs +29 -29
  172. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  173. package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -6
  174. package/dist/astro/routes/api/media/_id_.mjs +6 -6
  175. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  176. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  177. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  178. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  179. package/dist/astro/routes/api/media/upload-url.mjs +7 -7
  180. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  181. package/dist/astro/routes/api/media.mjs +8 -8
  182. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +7 -7
  183. package/dist/astro/routes/api/menus/_name_/items.mjs +7 -7
  184. package/dist/astro/routes/api/menus/_name_/reorder.mjs +7 -7
  185. package/dist/astro/routes/api/menus/_name_/translations.mjs +7 -7
  186. package/dist/astro/routes/api/menus/_name_.mjs +7 -7
  187. package/dist/astro/routes/api/menus/index.mjs +7 -7
  188. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  189. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  190. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  191. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  192. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  193. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  194. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  195. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  196. package/dist/astro/routes/api/openapi.json.mjs +3 -3
  197. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  198. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  199. package/dist/astro/routes/api/redirects/404s/index.mjs +8 -8
  200. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  201. package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
  202. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  203. package/dist/astro/routes/api/redirects/_id_.mjs +9 -9
  204. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  205. package/dist/astro/routes/api/redirects/index.mjs +9 -9
  206. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  207. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  208. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  209. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +32 -31
  210. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  211. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +32 -31
  212. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  213. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +32 -31
  214. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  215. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +32 -31
  216. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  217. package/dist/astro/routes/api/schema/collections/index.mjs +32 -31
  218. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  219. package/dist/astro/routes/api/schema/index.mjs +6 -6
  220. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  221. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +32 -31
  222. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  223. package/dist/astro/routes/api/schema/orphans/index.mjs +32 -31
  224. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  225. package/dist/astro/routes/api/search/enable.mjs +9 -9
  226. package/dist/astro/routes/api/search/index.mjs +8 -8
  227. package/dist/astro/routes/api/search/rebuild.mjs +9 -9
  228. package/dist/astro/routes/api/search/stats.mjs +6 -6
  229. package/dist/astro/routes/api/search/suggest.mjs +8 -8
  230. package/dist/astro/routes/api/sections/_slug_.mjs +8 -8
  231. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  232. package/dist/astro/routes/api/sections/index.mjs +8 -8
  233. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  234. package/dist/astro/routes/api/settings/email.mjs +4 -4
  235. package/dist/astro/routes/api/settings.mjs +10 -10
  236. package/dist/astro/routes/api/setup/admin-verify.mjs +10 -10
  237. package/dist/astro/routes/api/setup/admin.mjs +9 -9
  238. package/dist/astro/routes/api/setup/dev-bypass.mjs +22 -22
  239. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  240. package/dist/astro/routes/api/setup/index.mjs +22 -22
  241. package/dist/astro/routes/api/setup/status.mjs +4 -4
  242. package/dist/astro/routes/api/snapshot.mjs +6 -6
  243. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  244. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +11 -10
  245. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  246. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -10
  247. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  248. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -10
  249. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  250. package/dist/astro/routes/api/taxonomies/index.mjs +11 -10
  251. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  252. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  253. package/dist/astro/routes/api/typegen.mjs +5 -5
  254. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  255. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  256. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  257. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -6
  258. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +8 -8
  259. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +8 -8
  260. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  261. package/dist/astro/routes/api/widget-areas/index.mjs +8 -8
  262. package/dist/astro/routes/api/widget-components.mjs +3 -3
  263. package/dist/astro/routes/robots.txt.mjs +5 -5
  264. package/dist/astro/routes/sitemap-_collection_.xml.d.mts.map +1 -1
  265. package/dist/astro/routes/sitemap-_collection_.xml.mjs +58 -13
  266. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  267. package/dist/astro/routes/sitemap.xml.mjs +6 -6
  268. package/dist/astro/types.d.mts +20 -12
  269. package/dist/astro/types.d.mts.map +1 -1
  270. package/dist/auth/providers/github.d.mts +1 -1
  271. package/dist/auth/providers/google.d.mts +1 -1
  272. package/dist/{authorize-BlyCH-96.mjs → authorize-Bn4S4DUT.mjs} +2 -2
  273. package/dist/{authorize-BlyCH-96.mjs.map → authorize-Bn4S4DUT.mjs.map} +1 -1
  274. package/dist/byline-BDylH_m4.mjs +404 -0
  275. package/dist/byline-BDylH_m4.mjs.map +1 -0
  276. package/dist/{bylines-BdUP8NuI.d.mts → bylines-B2_XmnSU.d.mts} +73 -28
  277. package/dist/bylines-B2_XmnSU.d.mts.map +1 -0
  278. package/dist/bylines-B7TFEvFf.mjs +118 -0
  279. package/dist/bylines-B7TFEvFf.mjs.map +1 -0
  280. package/dist/bylines-n6nykUyI.mjs +174 -0
  281. package/dist/bylines-n6nykUyI.mjs.map +1 -0
  282. package/dist/{cache-CXCpjWiL.mjs → cache-BcI1yUjR.mjs} +2 -2
  283. package/dist/{cache-CXCpjWiL.mjs.map → cache-BcI1yUjR.mjs.map} +1 -1
  284. package/dist/{challenge-store-CJ0OOHOr.mjs → challenge-store-Dng1SxKT.mjs} +1 -1
  285. package/dist/{challenge-store-CJ0OOHOr.mjs.map → challenge-store-Dng1SxKT.mjs.map} +1 -1
  286. package/dist/{chunks-DyGtu1Bv.mjs → chunks-cYG4SnIP.mjs} +2 -2
  287. package/dist/{chunks-DyGtu1Bv.mjs.map → chunks-cYG4SnIP.mjs.map} +1 -1
  288. package/dist/cli/index.mjs +68 -30
  289. package/dist/cli/index.mjs.map +1 -1
  290. package/dist/client/cf-access.d.mts +1 -1
  291. package/dist/client/index.d.mts +1 -1
  292. package/dist/client/index.mjs +1 -1
  293. package/dist/client/index.mjs.map +1 -1
  294. package/dist/{comment-Dd9MI82-.mjs → comment-C76G-9tz.mjs} +2 -2
  295. package/dist/{comment-Dd9MI82-.mjs.map → comment-C76G-9tz.mjs.map} +1 -1
  296. package/dist/{comments-koGI0FrK.mjs → comments-CCxFFGY1.mjs} +3 -3
  297. package/dist/{comments-koGI0FrK.mjs.map → comments-CCxFFGY1.mjs.map} +1 -1
  298. package/dist/{components-mZem7pbe.mjs → components-Dx3DM0gg.mjs} +1 -1
  299. package/dist/{components-mZem7pbe.mjs.map → components-Dx3DM0gg.mjs.map} +1 -1
  300. package/dist/config-CVssduLe.mjs.map +1 -1
  301. package/dist/{content-D6YG26WG.mjs → content-8voQNTXX.mjs} +3 -3
  302. package/dist/{content-D6YG26WG.mjs.map → content-8voQNTXX.mjs.map} +1 -1
  303. package/dist/{context-qF8d3IPR.mjs → context-B7qiYrz2.mjs} +10 -10
  304. package/dist/context-B7qiYrz2.mjs.map +1 -0
  305. package/dist/{cron-H8eJ46dv.mjs → cron-Bd3b3iuj.mjs} +1 -1
  306. package/dist/{cron-H8eJ46dv.mjs.map → cron-Bd3b3iuj.mjs.map} +1 -1
  307. package/dist/{dashboard-BmWSIUwY.mjs → dashboard-BeaFSPpx.mjs} +4 -4
  308. package/dist/{dashboard-BmWSIUwY.mjs.map → dashboard-BeaFSPpx.mjs.map} +1 -1
  309. package/dist/db/index.d.mts +3 -3
  310. package/dist/db/index.mjs +1 -1
  311. package/dist/db/libsql.d.mts +1 -1
  312. package/dist/db/postgres.d.mts +1 -1
  313. package/dist/db/sqlite.d.mts +1 -1
  314. package/dist/db/sqlite.mjs +1 -1
  315. package/dist/{db-errors-CGN9kJfo.mjs → db-errors-BiYqoX-n.mjs} +14 -2
  316. package/dist/db-errors-BiYqoX-n.mjs.map +1 -0
  317. package/dist/{default-Dbs22Gg4.mjs → default-BvTAYCzx.mjs} +1 -1
  318. package/dist/{default-Dbs22Gg4.mjs.map → default-BvTAYCzx.mjs.map} +1 -1
  319. package/dist/{device-flow-BqJRxa0Q.mjs → device-flow-B9oG8PwP.mjs} +4 -4
  320. package/dist/{device-flow-BqJRxa0Q.mjs.map → device-flow-B9oG8PwP.mjs.map} +1 -1
  321. package/dist/{email-console-Dmp5Q-P2.mjs → email-console-CubRll9q.mjs} +1 -1
  322. package/dist/email-console-CubRll9q.mjs.map +1 -0
  323. package/dist/{error-tSQWIl5U.mjs → error-ChfADBuu.mjs} +19 -9
  324. package/dist/error-ChfADBuu.mjs.map +1 -0
  325. package/dist/errors-9P_FDrJ_.mjs +17 -0
  326. package/dist/errors-9P_FDrJ_.mjs.map +1 -0
  327. package/dist/{escape-B8bdIryO.mjs → escape-Cg6kMELH.mjs} +1 -1
  328. package/dist/{escape-B8bdIryO.mjs.map → escape-Cg6kMELH.mjs.map} +1 -1
  329. package/dist/{fts-manager-B633C-kQ.mjs → fts-manager-C_b-4x8u.mjs} +2 -2
  330. package/dist/{fts-manager-B633C-kQ.mjs.map → fts-manager-C_b-4x8u.mjs.map} +1 -1
  331. package/dist/{import-CNfLOgDE.mjs → import-DG80rC_I.mjs} +3 -3
  332. package/dist/{import-CNfLOgDE.mjs.map → import-DG80rC_I.mjs.map} +1 -1
  333. package/dist/{index-BV8iJ-6s.d.mts → index-BPZFAcgE.d.mts} +384 -123
  334. package/dist/index-BPZFAcgE.d.mts.map +1 -0
  335. package/dist/{index-D2gvztOP.d.mts → index-CC42STEm.d.mts} +3 -3
  336. package/dist/{index-D2gvztOP.d.mts.map → index-CC42STEm.d.mts.map} +1 -1
  337. package/dist/index.d.mts +17 -17
  338. package/dist/index.mjs +53 -52
  339. package/dist/{load-QzYRpVN3.mjs → load-CLFRjk9r.mjs} +2 -2
  340. package/dist/{load-QzYRpVN3.mjs.map → load-CLFRjk9r.mjs.map} +1 -1
  341. package/dist/{loader-Cs6-Bqe6.mjs → loader-D-vIJjfY.mjs} +86 -46
  342. package/dist/loader-D-vIJjfY.mjs.map +1 -0
  343. package/dist/{manifest-schema-HCtSh4Jq.mjs → manifest-schema-Czqf0TLu.mjs} +1 -1
  344. package/dist/{manifest-schema-HCtSh4Jq.mjs.map → manifest-schema-Czqf0TLu.mjs.map} +1 -1
  345. package/dist/media/index.d.mts +1 -1
  346. package/dist/media/local-runtime.d.mts +11 -11
  347. package/dist/media/local-runtime.mjs +4 -4
  348. package/dist/{media-Dg7he9uK.mjs → media-CKQd8AYU.mjs} +2 -2
  349. package/dist/media-CKQd8AYU.mjs.map +1 -0
  350. package/dist/{media-allowlist-B8EX01DH.mjs → media-allowlist-BNloC69x.mjs} +1 -1
  351. package/dist/{media-allowlist-B8EX01DH.mjs.map → media-allowlist-BNloC69x.mjs.map} +1 -1
  352. package/dist/{menus-X4Z-eBA1.mjs → menus-C-nWT5Tu.mjs} +42 -17
  353. package/dist/menus-C-nWT5Tu.mjs.map +1 -0
  354. package/dist/{menus-DOzIecHi.mjs → menus-arUNspyU.mjs} +2 -2
  355. package/dist/menus-arUNspyU.mjs.map +1 -0
  356. package/dist/mime-KV5TqkMN.mjs.map +1 -1
  357. package/dist/{mode-DPRPvJYm.mjs → mode-CaaiebZI.mjs} +1 -1
  358. package/dist/{mode-DPRPvJYm.mjs.map → mode-CaaiebZI.mjs.map} +1 -1
  359. package/dist/{oauth-authorization-62GmpGIH.mjs → oauth-authorization-CTMeVfvj.mjs} +4 -4
  360. package/dist/{oauth-authorization-62GmpGIH.mjs.map → oauth-authorization-CTMeVfvj.mjs.map} +1 -1
  361. package/dist/{oauth-clients-D_B0_-Bz.mjs → oauth-clients-eJCbkVSG.mjs} +1 -1
  362. package/dist/oauth-clients-eJCbkVSG.mjs.map +1 -0
  363. package/dist/{oauth-state-store-DpsZViTu.mjs → oauth-state-store-vOSdOeGe.mjs} +1 -1
  364. package/dist/{oauth-state-store-DpsZViTu.mjs.map → oauth-state-store-vOSdOeGe.mjs.map} +1 -1
  365. package/dist/{oauth-user-lookup-meyS2oB1.mjs → oauth-user-lookup-3JwsVw6N.mjs} +1 -1
  366. package/dist/{oauth-user-lookup-meyS2oB1.mjs.map → oauth-user-lookup-3JwsVw6N.mjs.map} +1 -1
  367. package/dist/options-BL4X94qY.mjs.map +1 -1
  368. package/dist/{options-Cq64Wx0O.d.mts → options-DhV-gwJb.d.mts} +4 -4
  369. package/dist/options-DhV-gwJb.d.mts.map +1 -0
  370. package/dist/page/index.d.mts +2 -2
  371. package/dist/{parse-BFTPon-J.mjs → parse-DHbXfvxO.mjs} +2 -2
  372. package/dist/{parse-BFTPon-J.mjs.map → parse-DHbXfvxO.mjs.map} +1 -1
  373. package/dist/{passkey-config-Cg86_ISa.mjs → passkey-config-BloQOT3y.mjs} +1 -1
  374. package/dist/{passkey-config-Cg86_ISa.mjs.map → passkey-config-BloQOT3y.mjs.map} +1 -1
  375. package/dist/{placeholder-D3cFCU9y.d.mts → placeholder-KCkkCtgQ.d.mts} +1 -1
  376. package/dist/{placeholder-D3cFCU9y.d.mts.map → placeholder-KCkkCtgQ.d.mts.map} +1 -1
  377. package/dist/plugin-types.d.mts +1 -1
  378. package/dist/plugin-utils.d.mts +25 -10
  379. package/dist/plugin-utils.d.mts.map +1 -1
  380. package/dist/plugin-utils.mjs +11 -10
  381. package/dist/plugin-utils.mjs.map +1 -1
  382. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  383. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  384. package/dist/plugins/adapt-sandbox-entry.mjs +26 -15
  385. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  386. package/dist/{preview-C1LOEbWZ.mjs → preview-D4z0WONU.mjs} +2 -2
  387. package/dist/{preview-C1LOEbWZ.mjs.map → preview-D4z0WONU.mjs.map} +1 -1
  388. package/dist/{public-url-CseXl9Fv.mjs → public-url-CUWWFME2.mjs} +1 -1
  389. package/dist/{public-url-CseXl9Fv.mjs.map → public-url-CUWWFME2.mjs.map} +1 -1
  390. package/dist/{query-axZmO6Tn.mjs → query-7m6-l0f_.mjs} +27 -17
  391. package/dist/query-7m6-l0f_.mjs.map +1 -0
  392. package/dist/{rate-limit-t5CVjCO6.mjs → rate-limit-D8RAXN8b.mjs} +2 -2
  393. package/dist/{rate-limit-t5CVjCO6.mjs.map → rate-limit-D8RAXN8b.mjs.map} +1 -1
  394. package/dist/{redirect-DGRsLO2I.mjs → redirect-BINiRYq4.mjs} +1 -1
  395. package/dist/{redirect-DGRsLO2I.mjs.map → redirect-BINiRYq4.mjs.map} +1 -1
  396. package/dist/{redirect-DkaDxq8e.mjs → redirect-CjfDGrTd.mjs} +2 -2
  397. package/dist/{redirect-DkaDxq8e.mjs.map → redirect-CjfDGrTd.mjs.map} +1 -1
  398. package/dist/{redirects-Dmj6KRU3.mjs → redirects-COMLwsV5.mjs} +19 -5
  399. package/dist/redirects-COMLwsV5.mjs.map +1 -0
  400. package/dist/{redirects-D1fdd68T.mjs → redirects-CowoEHdE.mjs} +3 -3
  401. package/dist/{redirects-D1fdd68T.mjs.map → redirects-CowoEHdE.mjs.map} +1 -1
  402. package/dist/{registry-BnCeHYsf.mjs → registry-Cyp-dx6J.mjs} +4 -4
  403. package/dist/{registry-BnCeHYsf.mjs.map → registry-Cyp-dx6J.mjs.map} +1 -1
  404. package/dist/request-cache-dzCt8TZB.mjs.map +1 -1
  405. package/dist/request-context.mjs.map +1 -1
  406. package/dist/{request-meta-CLCwSQOS.mjs → request-meta-C_Cjii-T.mjs} +2 -2
  407. package/dist/{request-meta-CLCwSQOS.mjs.map → request-meta-C_Cjii-T.mjs.map} +1 -1
  408. package/dist/resolve-D6sM-SgF.mjs +143 -0
  409. package/dist/resolve-D6sM-SgF.mjs.map +1 -0
  410. package/dist/{runner-DcfZewkO.d.mts → runner-DSQBurMS.d.mts} +8 -5
  411. package/dist/runner-DSQBurMS.d.mts.map +1 -0
  412. package/dist/{runner-DdnQIwz_.mjs → runner-Drnvs96u.mjs} +491 -188
  413. package/dist/runner-Drnvs96u.mjs.map +1 -0
  414. package/dist/runtime.d.mts +10 -10
  415. package/dist/runtime.mjs +2 -2
  416. package/dist/{schema-BmqagCwG.mjs → schema-CI9mYPX3.mjs} +4 -4
  417. package/dist/{schema-BmqagCwG.mjs.map → schema-CI9mYPX3.mjs.map} +1 -1
  418. package/dist/{search-CPrvO5u8.mjs → search-DKz_mGBP.mjs} +4 -4
  419. package/dist/{search-CPrvO5u8.mjs.map → search-DKz_mGBP.mjs.map} +1 -1
  420. package/dist/{secrets-6pgZyq0K.mjs → secrets-rPdhEBkD.mjs} +1 -1
  421. package/dist/{secrets-6pgZyq0K.mjs.map → secrets-rPdhEBkD.mjs.map} +1 -1
  422. package/dist/{sections-Cm-zb-gZ.mjs → sections-DBbCDIAT.mjs} +3 -3
  423. package/dist/{sections-Cm-zb-gZ.mjs.map → sections-DBbCDIAT.mjs.map} +1 -1
  424. package/dist/seed/index.d.mts +2 -2
  425. package/dist/seed/index.mjs +16 -16
  426. package/dist/seo/index.d.mts +1 -1
  427. package/dist/{seo-DRq9-EPP.mjs → seo-BGCyDlkb.mjs} +2 -2
  428. package/dist/{seo-DRq9-EPP.mjs.map → seo-BGCyDlkb.mjs.map} +1 -1
  429. package/dist/{seo-BoR4wCUh.mjs → seo-Dq707mNQ.mjs} +5 -3
  430. package/dist/seo-Dq707mNQ.mjs.map +1 -0
  431. package/dist/{service-vByySp-2.mjs → service-B0H7U1Y9.mjs} +3 -3
  432. package/dist/{service-vByySp-2.mjs.map → service-B0H7U1Y9.mjs.map} +1 -1
  433. package/dist/{settings-xQKsWnzQ.mjs → settings-BSXRtTzk.mjs} +3 -3
  434. package/dist/settings-BSXRtTzk.mjs.map +1 -0
  435. package/dist/{settings-CBBj7HUd.mjs → settings-DfwNyQkf.mjs} +3 -3
  436. package/dist/{settings-CBBj7HUd.mjs.map → settings-DfwNyQkf.mjs.map} +1 -1
  437. package/dist/{setup-BGAJ2uXs.mjs → setup-Cf_TyOv5.mjs} +2 -2
  438. package/dist/{setup-BGAJ2uXs.mjs.map → setup-Cf_TyOv5.mjs.map} +1 -1
  439. package/dist/{setup-complete-C6ZCLhKo.mjs → setup-complete-MzzN9u0b.mjs} +1 -1
  440. package/dist/{setup-complete-C6ZCLhKo.mjs.map → setup-complete-MzzN9u0b.mjs.map} +1 -1
  441. package/dist/{setup-nonce-CY1gQiAU.mjs → setup-nonce-DXuriHsg.mjs} +1 -1
  442. package/dist/{setup-nonce-CY1gQiAU.mjs.map → setup-nonce-DXuriHsg.mjs.map} +1 -1
  443. package/dist/{site-url-D-M4Fd8O.mjs → site-url-xkhw1tcz.mjs} +1 -1
  444. package/dist/{site-url-D-M4Fd8O.mjs.map → site-url-xkhw1tcz.mjs.map} +1 -1
  445. package/dist/{ssrf-DzFN_qV-.mjs → ssrf-MZ-zrG6-.mjs} +1 -1
  446. package/dist/{ssrf-DzFN_qV-.mjs.map → ssrf-MZ-zrG6-.mjs.map} +1 -1
  447. package/dist/storage/local.d.mts +1 -1
  448. package/dist/storage/local.mjs +1 -1
  449. package/dist/storage/local.mjs.map +1 -1
  450. package/dist/storage/s3.d.mts +1 -1
  451. package/dist/storage/s3.mjs +1 -1
  452. package/dist/storage/s3.mjs.map +1 -1
  453. package/dist/{taxonomies-Dc0mzlms.mjs → taxonomies-4vx0nmMr.mjs} +4 -4
  454. package/dist/{taxonomies-Dc0mzlms.mjs.map → taxonomies-4vx0nmMr.mjs.map} +1 -1
  455. package/dist/{taxonomies-Cn9UpaR2.mjs → taxonomies-CcvrMLbR.mjs} +8 -43
  456. package/dist/taxonomies-CcvrMLbR.mjs.map +1 -0
  457. package/dist/{taxonomy-wPfusMK9.mjs → taxonomy-zqGQUqgu.mjs} +3 -3
  458. package/dist/{taxonomy-wPfusMK9.mjs.map → taxonomy-zqGQUqgu.mjs.map} +1 -1
  459. package/dist/{tokens-DILYNZMi.mjs → tokens-N8otWMmj.mjs} +1 -1
  460. package/dist/{tokens-DILYNZMi.mjs.map → tokens-N8otWMmj.mjs.map} +1 -1
  461. package/dist/{transport-fw-mKJzT.mjs → transport-B6CHddbu.mjs} +1 -1
  462. package/dist/{transport-fw-mKJzT.mjs.map → transport-B6CHddbu.mjs.map} +1 -1
  463. package/dist/{transport-GeXlLscf.d.mts → transport-C2MGqtL6.d.mts} +1 -1
  464. package/dist/{transport-GeXlLscf.d.mts.map → transport-C2MGqtL6.d.mts.map} +1 -1
  465. package/dist/{trusted-proxy-CJhQIk65.mjs → trusted-proxy-97pajC2f.mjs} +1 -1
  466. package/dist/{trusted-proxy-CJhQIk65.mjs.map → trusted-proxy-97pajC2f.mjs.map} +1 -1
  467. package/dist/{types-CwXMEPRr.mjs → types-B0bmgwMG.mjs} +2 -2
  468. package/dist/types-B0bmgwMG.mjs.map +1 -0
  469. package/dist/{types-Dz9CGX_d.mjs → types-Cd9UCu3t.mjs} +1 -1
  470. package/dist/{types-Dz9CGX_d.mjs.map → types-Cd9UCu3t.mjs.map} +1 -1
  471. package/dist/{types-DmxPPXGf.d.mts → types-CkDSF81F.d.mts} +1 -1
  472. package/dist/{types-DmxPPXGf.d.mts.map → types-CkDSF81F.d.mts.map} +1 -1
  473. package/dist/{types-BWhaSS7U.d.mts → types-CpUuGcd5.d.mts} +1 -1
  474. package/dist/{types-BWhaSS7U.d.mts.map → types-CpUuGcd5.d.mts.map} +1 -1
  475. package/dist/{types-DFowNO60.d.mts → types-D599-ruj.d.mts} +1 -1
  476. package/dist/{types-DFowNO60.d.mts.map → types-D599-ruj.d.mts.map} +1 -1
  477. package/dist/{types-B05e2naf.d.mts → types-DGHWRQgr.d.mts} +3 -3
  478. package/dist/{types-B05e2naf.d.mts.map → types-DGHWRQgr.d.mts.map} +1 -1
  479. package/dist/{types-CzvJd1ND.d.mts → types-DaYDYW6g.d.mts} +14 -1
  480. package/dist/types-DaYDYW6g.d.mts.map +1 -0
  481. package/dist/{types-C1KKK4VP.d.mts → types-DaqNzqVt.d.mts} +16 -1
  482. package/dist/{types-C1KKK4VP.d.mts.map → types-DaqNzqVt.d.mts.map} +1 -1
  483. package/dist/{types-DW1l0gCv.d.mts → types-Dgo6y-Ut.d.mts} +1 -1
  484. package/dist/{types-DW1l0gCv.d.mts.map → types-Dgo6y-Ut.d.mts.map} +1 -1
  485. package/dist/{types-Cb2UCDJg.d.mts → types-bYmRn_Uy.d.mts} +1 -1
  486. package/dist/{types-Cb2UCDJg.d.mts.map → types-bYmRn_Uy.d.mts.map} +1 -1
  487. package/dist/{user-Dr1bOCqS.mjs → user-hUSOaIJy.mjs} +2 -2
  488. package/dist/{user-Dr1bOCqS.mjs.map → user-hUSOaIJy.mjs.map} +1 -1
  489. package/dist/{utils-_F-rWBTN.mjs → utils-C3wTAP-P.mjs} +1 -1
  490. package/dist/{utils-_F-rWBTN.mjs.map → utils-C3wTAP-P.mjs.map} +1 -1
  491. package/dist/{validate-BpQGsmd7.d.mts → validate-DQtHw9NT.d.mts} +5 -5
  492. package/dist/{validate-BpQGsmd7.d.mts.map → validate-DQtHw9NT.d.mts.map} +1 -1
  493. package/dist/{validate-DlFxcVVK.mjs → validate-IGltez8n.mjs} +2 -2
  494. package/dist/{validate-DlFxcVVK.mjs.map → validate-IGltez8n.mjs.map} +1 -1
  495. package/dist/{validation-BiFJqUp5.mjs → validation-Bmymau7y.mjs} +6 -6
  496. package/dist/{validation-BiFJqUp5.mjs.map → validation-Bmymau7y.mjs.map} +1 -1
  497. package/dist/version-BTc87L3L.mjs +7 -0
  498. package/dist/{version-DNmQakZO.mjs.map → version-BTc87L3L.mjs.map} +1 -1
  499. package/dist/{widgets-B9j_yzlk.mjs → widgets-yHQa4c6c.mjs} +3 -3
  500. package/dist/widgets-yHQa4c6c.mjs.map +1 -0
  501. package/dist/{zod-generator-DSyz01KE.mjs → zod-generator-B80aap1J.mjs} +2 -2
  502. package/dist/{zod-generator-DSyz01KE.mjs.map → zod-generator-B80aap1J.mjs.map} +1 -1
  503. package/package.json +12 -10
  504. package/src/api/error.ts +18 -3
  505. package/src/api/errors.ts +8 -0
  506. package/src/api/handlers/bylines.ts +161 -0
  507. package/src/api/handlers/content.ts +125 -43
  508. package/src/api/handlers/index.ts +8 -0
  509. package/src/api/handlers/marketplace.ts +27 -5
  510. package/src/api/handlers/oauth-clients.ts +1 -1
  511. package/src/api/handlers/registry.ts +622 -5
  512. package/src/api/handlers/seo.ts +16 -1
  513. package/src/api/handlers/snapshot.ts +1 -1
  514. package/src/api/openapi/document.ts +1 -1
  515. package/src/api/schemas/bylines.ts +46 -0
  516. package/src/astro/integration/index.ts +27 -1
  517. package/src/astro/integration/routes.ts +10 -0
  518. package/src/astro/integration/runtime.ts +20 -1
  519. package/src/astro/integration/virtual-modules.ts +19 -2
  520. package/src/astro/integration/vite-config.ts +2 -2
  521. package/src/astro/middleware/auth.ts +7 -7
  522. package/src/astro/middleware/request-context.ts +1 -1
  523. package/src/astro/middleware.ts +35 -20
  524. package/src/astro/public-plugin-api-routes.ts +41 -0
  525. package/src/astro/routes/api/admin/bylines/[id]/index.ts +3 -12
  526. package/src/astro/routes/api/admin/bylines/[id]/translations.ts +99 -0
  527. package/src/astro/routes/api/admin/bylines/index.ts +22 -11
  528. package/src/astro/routes/api/admin/plugins/[id]/update.ts +1 -0
  529. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +6 -1
  530. package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +51 -0
  531. package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +83 -0
  532. package/src/astro/routes/api/admin/plugins/registry/artifact.ts +388 -0
  533. package/src/astro/routes/api/admin/plugins/registry/install.ts +7 -1
  534. package/src/astro/routes/api/admin/plugins/updates.ts +43 -6
  535. package/src/astro/routes/api/admin/themes/marketplace/index.ts +1 -1
  536. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +2 -2
  537. package/src/astro/routes/api/auth/oauth/[provider].ts +2 -2
  538. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +2 -2
  539. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +2 -2
  540. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +2 -2
  541. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +2 -2
  542. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +2 -2
  543. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +6 -6
  544. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
  545. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +2 -2
  546. package/src/astro/routes/api/content/[collection]/[id].ts +6 -6
  547. package/src/astro/routes/api/import/wordpress/execute.ts +1 -1
  548. package/src/astro/routes/api/import/wordpress/prepare.ts +2 -2
  549. package/src/astro/routes/api/import/wordpress/rewrite-url-helpers.ts +22 -0
  550. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +8 -5
  551. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +2 -2
  552. package/src/astro/routes/api/media/upload-url.ts +1 -1
  553. package/src/astro/routes/api/redirects/404s/index.ts +3 -3
  554. package/src/astro/routes/api/redirects/404s/summary.ts +1 -1
  555. package/src/astro/routes/api/redirects/[id].ts +3 -3
  556. package/src/astro/routes/api/redirects/index.ts +2 -2
  557. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +4 -4
  558. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +2 -6
  559. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +1 -1
  560. package/src/astro/routes/api/schema/collections/[slug]/index.ts +6 -6
  561. package/src/astro/routes/api/schema/collections/index.ts +4 -4
  562. package/src/astro/routes/api/schema/index.ts +1 -1
  563. package/src/astro/routes/api/schema/orphans/[slug].ts +1 -1
  564. package/src/astro/routes/api/schema/orphans/index.ts +1 -1
  565. package/src/astro/routes/api/sections/[slug].ts +3 -3
  566. package/src/astro/routes/api/sections/index.ts +2 -2
  567. package/src/astro/routes/sitemap-[collection].xml.ts +114 -14
  568. package/src/astro/types.ts +18 -0
  569. package/src/auth/rate-limit.ts +1 -1
  570. package/src/auth/trusted-proxy.ts +1 -1
  571. package/src/bylines/index.ts +154 -55
  572. package/src/cli/commands/init.ts +4 -8
  573. package/src/client/index.ts +1 -1
  574. package/src/components/InlinePortableTextEditor.tsx +5 -1
  575. package/src/components/inline-code-block.tsx +343 -0
  576. package/src/config/secrets.ts +3 -3
  577. package/src/content/converters/portable-text-to-prosemirror.ts +35 -11
  578. package/src/database/connection.ts +3 -10
  579. package/src/database/errors.ts +14 -0
  580. package/src/database/index.ts +3 -1
  581. package/src/database/migrations/006_taxonomy_defs.ts +1 -1
  582. package/src/database/migrations/014_draft_revisions.ts +6 -6
  583. package/src/database/migrations/040_byline_i18n.ts +497 -0
  584. package/src/database/migrations/runner.ts +33 -22
  585. package/src/database/repositories/audit.ts +2 -2
  586. package/src/database/repositories/byline.ts +320 -50
  587. package/src/database/repositories/media.ts +2 -2
  588. package/src/database/repositories/menu.ts +1 -1
  589. package/src/database/repositories/options.ts +3 -3
  590. package/src/database/repositories/plugin-storage.ts +3 -3
  591. package/src/database/repositories/types.ts +13 -0
  592. package/src/database/types.ts +15 -0
  593. package/src/emdash-runtime.ts +493 -20
  594. package/src/i18n/config.ts +1 -1
  595. package/src/i18n/resolve.ts +152 -0
  596. package/src/index.ts +9 -0
  597. package/src/loader.ts +134 -60
  598. package/src/mcp/server.ts +3 -3
  599. package/src/media/mime.ts +1 -1
  600. package/src/page/absolute-url.ts +1 -1
  601. package/src/plugin-utils.ts +23 -0
  602. package/src/plugins/adapt-sandbox-entry.ts +45 -40
  603. package/src/plugins/email-console.ts +1 -1
  604. package/src/plugins/index.ts +1 -0
  605. package/src/plugins/marketplace.ts +1 -1
  606. package/src/plugins/sandbox/index.ts +1 -0
  607. package/src/plugins/sandbox/noop.ts +11 -3
  608. package/src/plugins/sandbox/types.ts +28 -0
  609. package/src/query.ts +41 -7
  610. package/src/registry/config.ts +1 -1
  611. package/src/request-cache.ts +3 -3
  612. package/src/request-context.ts +1 -1
  613. package/src/settings/index.ts +4 -4
  614. package/src/storage/local.ts +1 -1
  615. package/src/storage/s3.ts +3 -3
  616. package/src/utils/db-errors.ts +24 -0
  617. package/src/widgets/index.ts +1 -1
  618. package/dist/api-BMLZuwM4.mjs.map +0 -1
  619. package/dist/byline-D09BaS4j.mjs +0 -220
  620. package/dist/byline-D09BaS4j.mjs.map +0 -1
  621. package/dist/bylines-BTM2xtP8.mjs +0 -113
  622. package/dist/bylines-BTM2xtP8.mjs.map +0 -1
  623. package/dist/bylines-BdUP8NuI.d.mts.map +0 -1
  624. package/dist/connection-2igzM-AT.mjs +0 -57
  625. package/dist/connection-2igzM-AT.mjs.map +0 -1
  626. package/dist/context-qF8d3IPR.mjs.map +0 -1
  627. package/dist/db-errors-CGN9kJfo.mjs.map +0 -1
  628. package/dist/email-console-Dmp5Q-P2.mjs.map +0 -1
  629. package/dist/error-tSQWIl5U.mjs.map +0 -1
  630. package/dist/index-BV8iJ-6s.d.mts.map +0 -1
  631. package/dist/loader-Cs6-Bqe6.mjs.map +0 -1
  632. package/dist/media-Dg7he9uK.mjs.map +0 -1
  633. package/dist/menus-DOzIecHi.mjs.map +0 -1
  634. package/dist/menus-X4Z-eBA1.mjs.map +0 -1
  635. package/dist/oauth-clients-D_B0_-Bz.mjs.map +0 -1
  636. package/dist/options-Cq64Wx0O.d.mts.map +0 -1
  637. package/dist/query-axZmO6Tn.mjs.map +0 -1
  638. package/dist/redirects-Dmj6KRU3.mjs.map +0 -1
  639. package/dist/runner-DcfZewkO.d.mts.map +0 -1
  640. package/dist/runner-DdnQIwz_.mjs.map +0 -1
  641. package/dist/seo-BoR4wCUh.mjs.map +0 -1
  642. package/dist/settings-xQKsWnzQ.mjs.map +0 -1
  643. package/dist/taxonomies-Cn9UpaR2.mjs.map +0 -1
  644. package/dist/types-CwXMEPRr.mjs.map +0 -1
  645. package/dist/types-CzvJd1ND.d.mts.map +0 -1
  646. package/dist/version-DNmQakZO.mjs +0 -7
  647. package/dist/widgets-B9j_yzlk.mjs.map +0 -1
  648. /package/dist/{api-tokens-D3C9v02m.mjs → api-tokens-iPIHAY8N.mjs} +0 -0
  649. /package/dist/{ssrf-CTul4uQi.mjs → ssrf-BIcd-aXW.mjs} +0 -0
  650. /package/dist/{types-Db67HHlU.mjs → types-1NNkmTIn.mjs} +0 -0
@@ -18,6 +18,17 @@ export interface SitemapContentEntry {
18
18
  slug: string | null;
19
19
  /** ISO date of last modification */
20
20
  updatedAt: string;
21
+ /**
22
+ * Locale of this row (e.g. `"en"`, `"fr"`). Always present — rows in
23
+ * pre-i18n databases are backfilled to the configured `defaultLocale`.
24
+ */
25
+ locale: string;
26
+ /**
27
+ * `translation_group` ULID shared across all locale variants of the
28
+ * same content. Used by the sitemap route to emit `hreflang`
29
+ * alternates between siblings.
30
+ */
31
+ translationGroup: string | null;
21
32
  }
22
33
 
23
34
  /** Per-collection sitemap data with entries and URL pattern */
@@ -93,8 +104,10 @@ export async function handleSitemapData(
93
104
  slug: string | null;
94
105
  id: string;
95
106
  updated_at: string;
107
+ locale: string;
108
+ translation_group: string | null;
96
109
  }>`
97
- SELECT c.slug, c.id, c.updated_at
110
+ SELECT c.slug, c.id, c.updated_at, c.locale, c.translation_group
98
111
  FROM ${sql.ref(tableName)} c
99
112
  LEFT JOIN _emdash_seo s
100
113
  ON s.collection = ${col.slug}
@@ -114,6 +127,8 @@ export async function handleSitemapData(
114
127
  id: row.id,
115
128
  slug: row.slug,
116
129
  updatedAt: row.updated_at,
130
+ locale: row.locale,
131
+ translationGroup: row.translation_group,
117
132
  });
118
133
  }
119
134
 
@@ -294,7 +294,7 @@ export async function generateSnapshot(
294
294
  await sql<Record<string, unknown>>`
295
295
  SELECT * FROM ${sql.raw(`"${tableName}"`)}
296
296
  WHERE deleted_at IS NULL
297
- AND (status = 'published' OR (status = 'scheduled' AND scheduled_at <= datetime('now')))
297
+ AND (status = 'published' OR (status = 'scheduled' AND scheduled_at <= strftime('%Y-%m-%dT%H:%M:%fZ', 'now')))
298
298
  `.execute(db)
299
299
  ).rows;
300
300
  }
@@ -2379,7 +2379,7 @@ export function generateOpenApiDocument(
2379
2379
  },
2380
2380
  },
2381
2381
  security: [{ session: [] }, { bearer: [] }],
2382
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- readonly const paths are compatible at runtime
2382
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- readonly const paths are compatible at runtime
2383
2383
  paths: buildAllPaths(maxUploadSize) as unknown as ZodOpenApiPathsObject,
2384
2384
  });
2385
2385
  }
@@ -17,6 +17,14 @@ export const bylineSummarySchema = z
17
17
  isGuest: z.boolean(),
18
18
  createdAt: z.string(),
19
19
  updatedAt: z.string(),
20
+ /** Locale this byline row is presented in (migration 040). */
21
+ locale: z.string(),
22
+ /**
23
+ * Shared across translations of the same byline (migration 040).
24
+ * Equals `id` for the anchor row; siblings inherit it from their
25
+ * source. Nullable in storage for backwards compatibility.
26
+ */
27
+ translationGroup: z.string().nullable(),
20
28
  })
21
29
  .meta({ id: "BylineSummary" });
22
30
 
@@ -43,6 +51,12 @@ export const bylinesListQuery = cursorPaginationQuery
43
51
  search: z.string().optional(),
44
52
  isGuest: z.coerce.boolean().optional(),
45
53
  userId: z.string().optional(),
54
+ /**
55
+ * Filter by locale (strict per-locale matching, post-migration 040).
56
+ * Rejects empty strings so the picker can't silently fetch the
57
+ * unfiltered list when the admin URL has `?locale=` with no value.
58
+ */
59
+ locale: z.string().min(1).optional(),
46
60
  })
47
61
  .meta({ id: "BylinesListQuery" });
48
62
 
@@ -58,9 +72,41 @@ export const bylineCreateBody = z
58
72
  websiteUrl: httpUrl.nullish(),
59
73
  userId: z.string().nullish(),
60
74
  isGuest: z.boolean().optional(),
75
+ /**
76
+ * Locale this byline row belongs to. When omitted, the DB DEFAULT (the
77
+ * configured `defaultLocale`) is used. Rejects empty strings — an
78
+ * empty locale would create rows no resolver requests.
79
+ */
80
+ locale: z.string().min(1).optional(),
81
+ /**
82
+ * When set, the new row joins the source byline's translation_group
83
+ * rather than minting a fresh one. Requires `locale`.
84
+ */
85
+ translationOf: z.string().min(1).optional(),
61
86
  })
62
87
  .meta({ id: "BylineCreateBody" });
63
88
 
89
+ export const bylineTranslationCreateBody = z
90
+ .object({
91
+ locale: z.string().min(1),
92
+ slug: z
93
+ .string()
94
+ .min(1)
95
+ .regex(bylineSlugPattern, "Slug must contain only lowercase letters, digits, and hyphens")
96
+ .optional(),
97
+ displayName: z.string().min(1).optional(),
98
+ bio: z.string().nullish(),
99
+ avatarMediaId: z.string().nullish(),
100
+ websiteUrl: httpUrl.nullish(),
101
+ })
102
+ .meta({ id: "BylineTranslationCreateBody" });
103
+
104
+ export const bylineTranslationsResponseSchema = z
105
+ .object({
106
+ items: z.array(bylineSummarySchema),
107
+ })
108
+ .meta({ id: "BylineTranslationsResponse" });
109
+
64
110
  export const bylineUpdateBody = z
65
111
  .object({
66
112
  slug: z
@@ -10,6 +10,8 @@
10
10
  * to avoid bundling Node.js-only code into the production build.
11
11
  */
12
12
 
13
+ import { createRequire } from "node:module";
14
+
13
15
  import type { AstroIntegration, AstroIntegrationLogger } from "astro";
14
16
 
15
17
  import { validateAllowedOrigins, validateOriginShape } from "../../auth/allowed-origins.js";
@@ -22,7 +24,7 @@ import {
22
24
  injectAuthProviderRoutes,
23
25
  injectMcpRoute,
24
26
  } from "./routes.js";
25
- import type { EmDashConfig, PluginDescriptor } from "./runtime.js";
27
+ import type { EmDashConfig } from "./runtime.js";
26
28
  import { createViteConfig } from "./vite-config.js";
27
29
 
28
30
  // Re-export runtime types and functions
@@ -34,6 +36,23 @@ export type {
34
36
  } from "./runtime.js";
35
37
  export { getStoredConfig } from "./runtime.js";
36
38
 
39
+ /**
40
+ * Resolve the version of Astro the host project is building with, by reading
41
+ * `astro/package.json` from the project's own dependency tree. Surfaced to the
42
+ * admin and the registry install gate so a plugin's `env:astro` constraint can
43
+ * be evaluated against the real host version. Returns `undefined` if Astro
44
+ * can't be resolved (shouldn't happen in a real build, but never throw here).
45
+ */
46
+ function resolveAstroVersion(): string | undefined {
47
+ try {
48
+ const require = createRequire(import.meta.url);
49
+ const pkg = require("astro/package.json") as { version?: unknown };
50
+ return typeof pkg.version === "string" ? pkg.version : undefined;
51
+ } catch {
52
+ return undefined;
53
+ }
54
+ }
55
+
37
56
  /** Default storage: Local filesystem in .emdash directory */
38
57
  const DEFAULT_STORAGE = local({
39
58
  directory: "./.emdash/uploads",
@@ -204,6 +223,13 @@ export function emdash(config: EmDashConfig = {}): AstroIntegration {
204
223
  command,
205
224
  }) => {
206
225
  printBanner(logger);
226
+ // Capture the host's Astro version so the runtime can expose it
227
+ // to the admin and the registry install gate for `env:astro`
228
+ // constraint checks.
229
+ const astroVersion = resolveAstroVersion();
230
+ if (astroVersion !== undefined) {
231
+ serializableConfig.astroVersion = astroVersion;
232
+ }
207
233
  // Extract i18n config from Astro config
208
234
  // Astro locales can be strings OR { path, codes } objects — normalize to paths
209
235
  if (astroConfig.i18n) {
@@ -382,6 +382,11 @@ export function injectCoreRoutes(injectRoute: InjectRoute): void {
382
382
  entrypoint: resolveRoute("api/admin/plugins/registry/install.ts"),
383
383
  });
384
384
 
385
+ injectRoute({
386
+ pattern: "/_emdash/api/admin/plugins/registry/artifact",
387
+ entrypoint: resolveRoute("api/admin/plugins/registry/artifact.ts"),
388
+ });
389
+
385
390
  injectRoute({
386
391
  pattern: "/_emdash/api/admin/plugins/[id]/update",
387
392
  entrypoint: resolveRoute("api/admin/plugins/[id]/update.ts"),
@@ -447,6 +452,11 @@ export function injectCoreRoutes(injectRoute: InjectRoute): void {
447
452
  entrypoint: resolveRoute("api/admin/bylines/[id]/index.ts"),
448
453
  });
449
454
 
455
+ injectRoute({
456
+ pattern: "/_emdash/api/admin/bylines/[id]/translations",
457
+ entrypoint: resolveRoute("api/admin/bylines/[id]/translations.ts"),
458
+ });
459
+
450
460
  injectRoute({
451
461
  pattern: "/_emdash/api/admin/users/[id]",
452
462
  entrypoint: resolveRoute("api/admin/users/[id]/index.ts"),
@@ -199,6 +199,17 @@ export interface EmDashConfig {
199
199
  */
200
200
  sandboxRunner?: string;
201
201
 
202
+ /**
203
+ * Explicitly disable plugin sandboxing, even if a sandbox runner is configured.
204
+ * Use this as a debugging escape hatch to determine whether a bug is in your
205
+ * plugin code or in the sandbox runtime.
206
+ *
207
+ * When set to `false`, all plugins run in-process without isolation.
208
+ *
209
+ * @default true (sandboxing enabled if sandboxRunner is configured)
210
+ */
211
+ sandbox?: boolean;
212
+
202
213
  /**
203
214
  * Authentication configuration
204
215
  *
@@ -516,6 +527,14 @@ export interface EmDashConfig {
516
527
  /** URL or path to a custom favicon for the admin panel. */
517
528
  favicon?: string;
518
529
  };
530
+
531
+ /**
532
+ * Version of Astro the host project is building with. Populated by the
533
+ * integration's `astro:config:setup` hook (not authored by the user) and
534
+ * surfaced to the admin and the registry install gate so a plugin's
535
+ * `env:astro` requirement can be evaluated against the real host version.
536
+ */
537
+ astroVersion?: string;
519
538
  }
520
539
 
521
540
  const STORED_CONFIG_KEY = Symbol.for("emdash:stored-config");
@@ -526,7 +545,7 @@ const configHolder = globalThis as Record<symbol, unknown>;
526
545
  * This is set by the virtual module at build time
527
546
  */
528
547
  export function getStoredConfig(): EmDashConfig | null {
529
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- globalThis singleton pattern (see request-context.ts)
548
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see request-context.ts)
530
549
  return (configHolder[STORED_CONFIG_KEY] as EmDashConfig | undefined) ?? null;
531
550
  }
532
551
 
@@ -283,10 +283,14 @@ ${entries.join("\n")}
283
283
  /**
284
284
  * Generates the sandbox runner module.
285
285
  * Imports the configured sandbox runner factory or provides a noop default.
286
+ *
287
+ * When sandbox is explicitly false (debugging escape hatch), we still mark
288
+ * sandboxEnabled = true so sandboxed plugin entries are loaded, but we use
289
+ * the noop runner which falls through to in-process loading via adaptSandboxEntry.
286
290
  */
287
- export function generateSandboxRunnerModule(sandboxRunner?: string): string {
291
+ export function generateSandboxRunnerModule(sandboxRunner?: string, sandbox?: boolean): string {
288
292
  if (!sandboxRunner) {
289
- // No sandbox runner configured - use noop
293
+ // No sandbox runner configured - sandboxed plugins disabled
290
294
  return `
291
295
  // No sandbox runner configured - sandboxed plugins disabled
292
296
  import { createNoopSandboxRunner } from "emdash";
@@ -296,6 +300,19 @@ export const sandboxEnabled = false;
296
300
  `;
297
301
  }
298
302
 
303
+ if (sandbox === false) {
304
+ // sandbox: false escape hatch - plugins are loaded but run in-process
305
+ // (no isolation, for debugging)
306
+ return `
307
+ // Sandbox explicitly disabled (sandbox: false) - plugins run in-process
308
+ import { createNoopSandboxRunner } from "emdash";
309
+
310
+ export const createSandboxRunner = createNoopSandboxRunner;
311
+ export const sandboxEnabled = true;
312
+ export const sandboxBypassed = true;
313
+ `;
314
+ }
315
+
299
316
  return `
300
317
  // Auto-generated sandbox runner module
301
318
  import { createSandboxRunner as _createSandboxRunner } from "${sandboxRunner}";
@@ -233,7 +233,7 @@ export function createVirtualModulesPlugin(options: VitePluginOptions): Plugin {
233
233
  }
234
234
  // Generate sandbox runner module
235
235
  if (id === RESOLVED_VIRTUAL_SANDBOX_RUNNER_ID) {
236
- return generateSandboxRunnerModule(resolvedConfig.sandboxRunner);
236
+ return generateSandboxRunnerModule(resolvedConfig.sandboxRunner, resolvedConfig.sandbox);
237
237
  }
238
238
  // Generate sandboxed plugins config module
239
239
  if (id === RESOLVED_VIRTUAL_SANDBOXED_PLUGINS_ID) {
@@ -346,7 +346,7 @@ export function createViteConfig(
346
346
  { find: "use-sync-external-store/shim", replacement: "use-sync-external-store" },
347
347
  ],
348
348
  },
349
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Monorepo has both vite 6 (docs) and vite 7 (core). tsgo resolves correctly.
349
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- Monorepo has both vite 6 (docs) and vite 7 (core). tsgo resolves correctly.
350
350
  plugins: [
351
351
  createVirtualModulesPlugin(options),
352
352
  // In dev mode with source alias, compile Lingui macros on the fly
@@ -475,11 +475,11 @@ async function handleExternalAuth(
475
475
  const authResult = await virtualAuthenticate(request, authMode.config);
476
476
 
477
477
  // Get external auth config for auto-provision settings
478
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowing AuthModeConfig to ExternalAuthConfig after provider check
478
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- narrowing AuthModeConfig to ExternalAuthConfig after provider check
479
479
  const externalConfig = authMode.config as ExternalAuthConfig;
480
480
 
481
481
  // Find or create user
482
- const adapter = createKyselyAdapter(emdash!.db);
482
+ const adapter = createKyselyAdapter(emdash.db);
483
483
  let user = await adapter.getUserByEmail(authResult.email);
484
484
 
485
485
  if (!user) {
@@ -492,9 +492,9 @@ async function handleExternalAuth(
492
492
  }
493
493
 
494
494
  // Check if this is the first user (they become admin)
495
- const userCount = await emdash!.db
495
+ const userCount = await emdash.db
496
496
  .selectFrom("users")
497
- .select(emdash!.db.fn.count("id").as("count"))
497
+ .select(emdash.db.fn.count("id").as("count"))
498
498
  .executeTakeFirst();
499
499
 
500
500
  const isFirstUser = Number(userCount?.count ?? 0) === 0;
@@ -512,7 +512,7 @@ async function handleExternalAuth(
512
512
  updated_at: now,
513
513
  };
514
514
 
515
- await emdash!.db.insertInto("users").values(newUser).execute();
515
+ await emdash.db.insertInto("users").values(newUser).execute();
516
516
 
517
517
  user = await adapter.getUserByEmail(authResult.email);
518
518
 
@@ -539,7 +539,7 @@ async function handleExternalAuth(
539
539
 
540
540
  if (Object.keys(updates).length > 0) {
541
541
  updates.updated_at = new Date().toISOString();
542
- await emdash!.db.updateTable("users").set(updates).where("id", "=", user.id).execute();
542
+ await emdash.db.updateTable("users").set(updates).where("id", "=", user.id).execute();
543
543
 
544
544
  user = {
545
545
  ...user,
@@ -665,7 +665,7 @@ async function handlePasskeyAuth(
665
665
  }
666
666
 
667
667
  // Get full user from database
668
- const adapter = createKyselyAdapter(emdash!.db);
668
+ const adapter = createKyselyAdapter(emdash.db);
669
669
  const user = await adapter.getUserById(sessionUser.id);
670
670
 
671
671
  if (!user) {
@@ -78,7 +78,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
78
78
  const editMode = hasEditCookie && isEditor;
79
79
 
80
80
  // Read locale from Astro's i18n routing
81
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Astro context includes currentLocale when i18n is configured
81
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- Astro context includes currentLocale when i18n is configured
82
82
  const locale = (context as { currentLocale?: string }).currentLocale;
83
83
 
84
84
  // Verify preview token if present.
@@ -20,11 +20,8 @@ import type { RequestScopedDbOpts } from "virtual:emdash/dialect";
20
20
  import { mediaProviders as virtualMediaProviders } from "virtual:emdash/media-providers";
21
21
  // @ts-ignore - virtual module
22
22
  import { plugins as virtualPlugins } from "virtual:emdash/plugins";
23
- import {
24
- createSandboxRunner as virtualCreateSandboxRunner,
25
- sandboxEnabled as virtualSandboxEnabled,
26
- // @ts-ignore - virtual module
27
- } from "virtual:emdash/sandbox-runner";
23
+ // @ts-ignore - virtual module
24
+ import * as virtualSandboxRunnerModule from "virtual:emdash/sandbox-runner";
28
25
  // @ts-ignore - virtual module
29
26
  import { sandboxedPlugins as virtualSandboxedPlugins } from "virtual:emdash/sandboxed-plugins";
30
27
  // @ts-ignore - virtual module
@@ -54,6 +51,7 @@ import {
54
51
  runWithContext,
55
52
  } from "../request-context.js";
56
53
  import type { EmDashConfig } from "./integration/runtime.js";
54
+ import { createPublicPluginApiRouteHandler } from "./public-plugin-api-routes.js";
57
55
  import type { EmDashHandlers } from "./types.js";
58
56
 
59
57
  // Cached runtime instance (persists across requests within worker)
@@ -82,11 +80,11 @@ function getConfig(): EmDashConfig | null {
82
80
  // Initialize i18n config on first access (once per worker lifetime)
83
81
  if (!i18nInitialized) {
84
82
  i18nInitialized = true;
85
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module checked as object above
83
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- virtual module checked as object above
86
84
  const config = virtualConfig as Record<string, unknown>;
87
85
  if (config.i18n && typeof config.i18n === "object") {
88
86
  setI18nConfig(
89
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- runtime-checked above
87
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- runtime-checked above
90
88
  config.i18n as {
91
89
  defaultLocale: string;
92
90
  locales: string[];
@@ -98,7 +96,7 @@ function getConfig(): EmDashConfig | null {
98
96
  }
99
97
  }
100
98
 
101
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
99
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- virtual module import is untyped (@ts-ignore above)
102
100
  return virtualConfig as EmDashConfig;
103
101
  }
104
102
  return null;
@@ -108,7 +106,7 @@ function getConfig(): EmDashConfig | null {
108
106
  * Get plugins from virtual module
109
107
  */
110
108
  function getPlugins(): ResolvedPlugin[] {
111
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
109
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- virtual module import is untyped (@ts-ignore above)
112
110
  return (virtualPlugins as ResolvedPlugin[]) || [];
113
111
  }
114
112
 
@@ -116,24 +114,37 @@ function getPlugins(): ResolvedPlugin[] {
116
114
  * Build runtime dependencies from virtual modules
117
115
  */
118
116
  function buildDependencies(config: EmDashConfig): RuntimeDependencies {
117
+ /* eslint-disable typescript-eslint/no-unsafe-type-assertion --
118
+ The virtual:emdash/* imports above use @ts-ignore because tsgo/IDE
119
+ resolution can't see virtual-modules.d.ts in every consumer setup,
120
+ so they arrive as `any`. The casts here line each entry up with
121
+ RuntimeDependencies's expected shape. The contract is enforced by
122
+ the integration that populates these virtual modules. */
123
+ const sandboxModule = virtualSandboxRunnerModule as Record<string, unknown>;
119
124
  return {
120
125
  config,
121
126
  plugins: getPlugins(),
122
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
123
127
  createDialect: virtualCreateDialect as (config: Record<string, unknown>) => unknown,
124
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
125
128
  createStorage: virtualCreateStorage as ((config: Record<string, unknown>) => Storage) | null,
126
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
127
- sandboxEnabled: virtualSandboxEnabled as boolean,
128
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
129
+ sandboxEnabled: sandboxModule.sandboxEnabled as boolean,
130
+ sandboxBypassed: (sandboxModule.sandboxBypassed as boolean) ?? false,
129
131
  sandboxedPluginEntries: (virtualSandboxedPlugins as SandboxedPluginEntry[]) || [],
130
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
131
- createSandboxRunner: virtualCreateSandboxRunner as
132
- | ((opts: { db: Kysely<Database> }) => SandboxRunner)
132
+ createSandboxRunner: sandboxModule.createSandboxRunner as
133
+ | ((opts: {
134
+ db: Kysely<Database>;
135
+ mediaStorage?: {
136
+ upload(options: {
137
+ key: string;
138
+ body: Uint8Array;
139
+ contentType: string;
140
+ }): Promise<unknown>;
141
+ delete(key: string): Promise<unknown>;
142
+ };
143
+ }) => SandboxRunner)
133
144
  | null,
134
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
135
145
  mediaProviderEntries: (virtualMediaProviders as MediaProviderEntry[]) || [],
136
146
  };
147
+ /* eslint-enable typescript-eslint/no-unsafe-type-assertion */
137
148
  }
138
149
 
139
150
  /**
@@ -255,7 +266,7 @@ function createRequestScopedDb(
255
266
  opts: RequestScopedDbOpts,
256
267
  ): { db: Kysely<Database>; commit: () => void } | null {
257
268
  if (typeof virtualCreateRequestScopedDb !== "function") return null;
258
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- adapter returns Kysely<unknown>; cast to Database since core owns that type
269
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- adapter returns Kysely<unknown>; cast to Database since core owns that type
259
270
  const fn = virtualCreateRequestScopedDb as (
260
271
  o: RequestScopedDbOpts,
261
272
  ) => { db: Kysely<Database>; commit: () => void } | null;
@@ -358,8 +369,10 @@ export const onRequest = defineMiddleware(async (context, next) => {
358
369
  try {
359
370
  const runtime = await getRuntime(config, initSubTimings);
360
371
  setupVerified = true;
361
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- partial object; getPageRuntime() only checks for the page-contribution methods
372
+ const handlePublicPluginApiRoute = createPublicPluginApiRouteHandler(runtime);
373
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- partial object; getPageRuntime() only checks for the page-contribution methods
362
374
  locals.emdash = {
375
+ handlePublicPluginApiRoute,
363
376
  collectPageMetadata: runtime.collectPageMetadata.bind(runtime),
364
377
  collectPageFragments: runtime.collectPageFragments.bind(runtime),
365
378
  getPublicMediaUrl: createPublicMediaUrlResolver(runtime.storage),
@@ -486,6 +499,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
486
499
 
487
500
  // Plugin routes
488
501
  handlePluginApiRoute: runtime.handlePluginApiRoute.bind(runtime),
502
+ handlePublicPluginApiRoute: createPublicPluginApiRouteHandler(runtime),
489
503
  getPluginRouteMeta: runtime.getPluginRouteMeta.bind(runtime),
490
504
 
491
505
  // Media provider methods
@@ -523,6 +537,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
523
537
 
524
538
  // Sandbox runner (for marketplace plugin install/update)
525
539
  getSandboxRunner: runtime.getSandboxRunner.bind(runtime),
540
+ isSandboxBypassed: runtime.isSandboxBypassed.bind(runtime),
526
541
 
527
542
  // Sync marketplace plugin states (after install/update/uninstall)
528
543
  syncMarketplacePlugins: runtime.syncMarketplacePlugins.bind(runtime),
@@ -0,0 +1,41 @@
1
+ import type { HandlerResponse } from "./types.js";
2
+
3
+ export type PublicPluginApiRouteHandler = (
4
+ pluginId: string,
5
+ method: string,
6
+ path: string,
7
+ request: Request,
8
+ ) => Promise<HandlerResponse>;
9
+
10
+ interface PublicPluginApiRouteRuntime {
11
+ getPluginRouteMeta(pluginId: string, path: string): { public: boolean } | null;
12
+ handlePluginApiRoute(
13
+ pluginId: string,
14
+ method: string,
15
+ path: string,
16
+ request: Request,
17
+ ): Promise<HandlerResponse>;
18
+ }
19
+
20
+ function pluginRouteNotFound(): HandlerResponse {
21
+ return {
22
+ success: false,
23
+ error: {
24
+ code: "NOT_FOUND",
25
+ message: "Plugin route not found",
26
+ },
27
+ };
28
+ }
29
+
30
+ export function createPublicPluginApiRouteHandler(
31
+ runtime: PublicPluginApiRouteRuntime,
32
+ ): PublicPluginApiRouteHandler {
33
+ return async (pluginId, method, path, request) => {
34
+ const meta = runtime.getPluginRouteMeta(pluginId, path);
35
+ if (meta?.public !== true) {
36
+ return pluginRouteNotFound();
37
+ }
38
+
39
+ return runtime.handlePluginApiRoute(pluginId, method, path, request);
40
+ };
41
+ }
@@ -1,4 +1,3 @@
1
- import { Role } from "@emdash-cms/auth";
2
1
  import type { APIRoute } from "astro";
3
2
 
4
3
  import { requirePerm } from "#api/authorize.js";
@@ -10,17 +9,9 @@ import { BylineRepository } from "#db/repositories/byline.js";
10
9
 
11
10
  export const prerender = false;
12
11
 
13
- function requireEditor(user: { role: number } | undefined): Response | null {
14
- if (!user || user.role < Role.EDITOR) {
15
- return apiError("FORBIDDEN", "Editor privileges required", 403);
16
- }
17
- return null;
18
- }
19
-
20
12
  export const GET: APIRoute = async ({ params, locals }) => {
21
13
  const { emdash, user } = locals;
22
- // Read access uses content:read so all authenticated roles can view byline data
23
- const denied = requirePerm(user, "content:read");
14
+ const denied = requirePerm(user, "bylines:read");
24
15
  if (denied) return denied;
25
16
 
26
17
  if (!emdash?.db) {
@@ -39,7 +30,7 @@ export const GET: APIRoute = async ({ params, locals }) => {
39
30
 
40
31
  export const PUT: APIRoute = async ({ params, request, locals }) => {
41
32
  const { emdash, user } = locals;
42
- const denied = requireEditor(user);
33
+ const denied = requirePerm(user, "bylines:manage");
43
34
  if (denied) return denied;
44
35
 
45
36
  if (!emdash?.db) {
@@ -71,7 +62,7 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
71
62
 
72
63
  export const DELETE: APIRoute = async ({ params, locals }) => {
73
64
  const { emdash, user } = locals;
74
- const denied = requireEditor(user);
65
+ const denied = requirePerm(user, "bylines:manage");
75
66
  if (denied) return denied;
76
67
 
77
68
  if (!emdash?.db) {