emdash 0.20.0 → 0.21.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 (547) hide show
  1. package/dist/{adapters-BzIHV3sw.d.mts → adapters-BxSmgtbF.d.mts} +1 -1
  2. package/dist/{adapters-BzIHV3sw.d.mts.map → adapters-BxSmgtbF.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-B1u7Qnvg.mjs → allowed-origins-BqC8cul8.mjs} +2 -2
  4. package/dist/{allowed-origins-B1u7Qnvg.mjs.map → allowed-origins-BqC8cul8.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +13 -12
  7. package/dist/api/route-utils.mjs.map +1 -1
  8. package/dist/api/schemas/index.d.mts +1 -1
  9. package/dist/api/schemas/index.mjs +3 -2
  10. package/dist/{api-DStv36ik.mjs → api-DxjIV2o8.mjs} +13 -13
  11. package/dist/{api-DStv36ik.mjs.map → api-DxjIV2o8.mjs.map} +1 -1
  12. package/dist/{api-tokens-DPfhPu5V.mjs → api-tokens-BFFkB0jB.mjs} +2 -2
  13. package/dist/{api-tokens-DPfhPu5V.mjs.map → api-tokens-BFFkB0jB.mjs.map} +1 -1
  14. package/dist/{apply-Dr7snAMT.mjs → apply-CLjxheyb.mjs} +12 -12
  15. package/dist/{apply-Dr7snAMT.mjs.map → apply-CLjxheyb.mjs.map} +1 -1
  16. package/dist/astro/index.d.mts +10 -10
  17. package/dist/astro/index.d.mts.map +1 -1
  18. package/dist/astro/index.mjs +50 -15
  19. package/dist/astro/index.mjs.map +1 -1
  20. package/dist/astro/middleware/auth.d.mts +9 -9
  21. package/dist/astro/middleware/auth.mjs +5 -5
  22. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  23. package/dist/astro/middleware/redirect.mjs +11 -2
  24. package/dist/astro/middleware/redirect.mjs.map +1 -1
  25. package/dist/astro/middleware/request-context.mjs +3 -2
  26. package/dist/astro/middleware/request-context.mjs.map +1 -1
  27. package/dist/astro/middleware/setup.mjs +1 -1
  28. package/dist/astro/middleware.d.mts +1 -1
  29. package/dist/astro/middleware.mjs +63 -60
  30. package/dist/astro/middleware.mjs.map +1 -1
  31. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -4
  32. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
  33. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -4
  34. package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
  35. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
  36. package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
  37. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  38. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -7
  39. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
  40. package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -7
  41. package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
  42. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -7
  43. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
  44. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -12
  45. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  46. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +14 -12
  47. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  48. package/dist/astro/routes/api/admin/bylines/index.mjs +14 -12
  49. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  50. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +9 -8
  51. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  52. package/dist/astro/routes/api/admin/comments/_id_.mjs +3 -3
  53. package/dist/astro/routes/api/admin/comments/bulk.mjs +7 -6
  54. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/comments/counts.mjs +3 -3
  56. package/dist/astro/routes/api/admin/comments/index.mjs +7 -6
  57. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  58. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +3 -3
  59. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +2 -2
  60. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  61. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  62. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +29 -27
  63. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +29 -27
  65. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +28 -26
  67. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +28 -26
  69. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +28 -26
  71. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/plugins/index.mjs +28 -26
  73. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  75. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +28 -26
  76. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +28 -26
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +28 -26
  80. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  81. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +28 -26
  82. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  83. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +29 -27
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  85. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +28 -26
  86. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +29 -27
  88. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/updates.mjs +28 -26
  90. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +28 -26
  92. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  94. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +28 -26
  95. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +1 -1
  97. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  98. package/dist/astro/routes/api/admin/users/_id_/index.mjs +5 -4
  99. package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
  101. package/dist/astro/routes/api/admin/users/index.mjs +5 -4
  102. package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
  103. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  104. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  105. package/dist/astro/routes/api/auth/invite/complete.mjs +9 -8
  106. package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
  107. package/dist/astro/routes/api/auth/invite/index.mjs +6 -5
  108. package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
  109. package/dist/astro/routes/api/auth/invite/register-options.mjs +8 -7
  110. package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
  111. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  112. package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -7
  113. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  114. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  115. package/dist/astro/routes/api/auth/me.mjs +5 -4
  116. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  117. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  118. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  119. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  120. package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -4
  121. package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
  122. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  123. package/dist/astro/routes/api/auth/passkey/options.mjs +10 -9
  124. package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
  125. package/dist/astro/routes/api/auth/passkey/register/options.mjs +8 -7
  126. package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
  127. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +9 -8
  128. package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
  129. package/dist/astro/routes/api/auth/passkey/verify.mjs +9 -8
  130. package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
  131. package/dist/astro/routes/api/auth/signup/complete.mjs +9 -8
  132. package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
  133. package/dist/astro/routes/api/auth/signup/request.mjs +8 -7
  134. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  135. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  136. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -9
  137. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  138. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  139. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +2 -2
  140. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +2 -2
  141. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
  142. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +10 -8
  143. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
  144. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -5
  145. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  146. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +2 -2
  147. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  148. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +6 -5
  149. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  150. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +10 -9
  151. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  152. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  153. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +2 -2
  154. package/dist/astro/routes/api/content/_collection_/_id_.mjs +6 -5
  155. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  156. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  157. package/dist/astro/routes/api/content/_collection_/index.mjs +6 -5
  158. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  159. package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -5
  160. package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
  161. package/dist/astro/routes/api/dashboard.mjs +3 -3
  162. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  163. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  164. package/dist/astro/routes/api/import/probe.mjs +10 -9
  165. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  166. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  167. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  168. package/dist/astro/routes/api/import/wordpress/execute.mjs +10 -9
  169. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  170. package/dist/astro/routes/api/import/wordpress/media.mjs +8 -7
  171. package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
  172. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -8
  173. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  174. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +8 -7
  175. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  176. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  177. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +10 -9
  178. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  179. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  180. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +14 -12
  181. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  182. package/dist/astro/routes/api/manifest.mjs +3 -3
  183. package/dist/astro/routes/api/mcp.mjs +20 -19
  184. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  185. package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -5
  186. package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
  187. package/dist/astro/routes/api/media/_id_.mjs +6 -5
  188. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  189. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  190. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  191. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  192. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  193. package/dist/astro/routes/api/media/upload-url.mjs +8 -7
  194. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  195. package/dist/astro/routes/api/media.mjs +10 -9
  196. package/dist/astro/routes/api/media.mjs.map +1 -1
  197. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +6 -5
  198. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  199. package/dist/astro/routes/api/menus/_name_/items.mjs +6 -5
  200. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  201. package/dist/astro/routes/api/menus/_name_/reorder.mjs +6 -5
  202. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  203. package/dist/astro/routes/api/menus/_name_/translations.mjs +6 -5
  204. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  205. package/dist/astro/routes/api/menus/_name_.mjs +6 -5
  206. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  207. package/dist/astro/routes/api/menus/index.mjs +6 -5
  208. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  209. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  210. package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
  211. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  212. package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
  213. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  214. package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
  215. package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
  216. package/dist/astro/routes/api/oauth/token.mjs +5 -5
  217. package/dist/astro/routes/api/openapi.json.mjs +3 -2
  218. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  219. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
  220. package/dist/astro/routes/api/redirects/404s/index.mjs +7 -6
  221. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  222. package/dist/astro/routes/api/redirects/404s/summary.mjs +7 -6
  223. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  224. package/dist/astro/routes/api/redirects/_id_.mjs +8 -7
  225. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  226. package/dist/astro/routes/api/redirects/index.mjs +8 -7
  227. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  228. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  229. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +2 -2
  230. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +28 -26
  231. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  232. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +28 -26
  233. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  234. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +28 -26
  235. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  236. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +28 -26
  237. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  238. package/dist/astro/routes/api/schema/collections/index.mjs +28 -26
  239. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/schema/index.mjs +5 -5
  241. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +28 -26
  242. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  243. package/dist/astro/routes/api/schema/orphans/index.mjs +28 -26
  244. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  245. package/dist/astro/routes/api/search/enable.mjs +9 -8
  246. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  247. package/dist/astro/routes/api/search/index.mjs +8 -7
  248. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  249. package/dist/astro/routes/api/search/rebuild.mjs +9 -8
  250. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  251. package/dist/astro/routes/api/search/stats.mjs +5 -5
  252. package/dist/astro/routes/api/search/suggest.mjs +8 -7
  253. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  254. package/dist/astro/routes/api/sections/_slug_.mjs +8 -7
  255. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  256. package/dist/astro/routes/api/sections/index.mjs +8 -7
  257. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  258. package/dist/astro/routes/api/settings/email.mjs +3 -3
  259. package/dist/astro/routes/api/settings.mjs +11 -9
  260. package/dist/astro/routes/api/settings.mjs.map +1 -1
  261. package/dist/astro/routes/api/setup/admin-verify.mjs +10 -9
  262. package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
  263. package/dist/astro/routes/api/setup/admin.mjs +9 -8
  264. package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
  265. package/dist/astro/routes/api/setup/dev-bypass.mjs +19 -18
  266. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  267. package/dist/astro/routes/api/setup/dev-reset.mjs +1 -1
  268. package/dist/astro/routes/api/setup/index.mjs +20 -18
  269. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  270. package/dist/astro/routes/api/setup/status.mjs +3 -3
  271. package/dist/astro/routes/api/snapshot.mjs +5 -4
  272. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  273. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +11 -10
  274. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  275. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -10
  276. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  277. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -10
  278. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  279. package/dist/astro/routes/api/taxonomies/index.mjs +11 -10
  280. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  281. package/dist/astro/routes/api/themes/preview.mjs +5 -4
  282. package/dist/astro/routes/api/themes/preview.mjs.map +1 -1
  283. package/dist/astro/routes/api/typegen.mjs +4 -4
  284. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  285. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  286. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  287. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -5
  288. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  289. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +9 -8
  290. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  291. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +9 -8
  292. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  293. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  294. package/dist/astro/routes/api/widget-areas/index.mjs +9 -8
  295. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  296. package/dist/astro/routes/api/widget-components.mjs +2 -2
  297. package/dist/astro/routes/robots.txt.mjs +5 -4
  298. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  299. package/dist/astro/routes/sitemap-_collection_.xml.mjs +8 -7
  300. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  301. package/dist/astro/routes/sitemap.xml.mjs +6 -5
  302. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  303. package/dist/astro/types.d.mts +12 -12
  304. package/dist/auth/providers/github.d.mts +1 -1
  305. package/dist/auth/providers/google.d.mts +1 -1
  306. package/dist/{authorize-DsMSVSaY.mjs → authorize-D5gfBVU5.mjs} +2 -2
  307. package/dist/{authorize-DsMSVSaY.mjs.map → authorize-D5gfBVU5.mjs.map} +1 -1
  308. package/dist/{byline-DUx48sJp.mjs → byline-V_Qp1Ziw.mjs} +27 -14
  309. package/dist/byline-V_Qp1Ziw.mjs.map +1 -0
  310. package/dist/{byline-fields-8TMtkBnH.mjs → byline-fields-B0NO1yUB.mjs} +3 -3
  311. package/dist/{byline-fields-8TMtkBnH.mjs.map → byline-fields-B0NO1yUB.mjs.map} +1 -1
  312. package/dist/{byline-fields-DbibsvTl.d.mts → byline-fields-CQJRIQkn.d.mts} +32 -32
  313. package/dist/{byline-fields-DbibsvTl.d.mts.map → byline-fields-CQJRIQkn.d.mts.map} +1 -1
  314. package/dist/{byline-fields--WxSNS79.mjs → byline-fields-nBVqK_Ff.mjs} +2 -2
  315. package/dist/{byline-fields--WxSNS79.mjs.map → byline-fields-nBVqK_Ff.mjs.map} +1 -1
  316. package/dist/{byline-registry-CWP7I71B.mjs → byline-registry-DedidtqC.mjs} +2 -2
  317. package/dist/{byline-registry-CWP7I71B.mjs.map → byline-registry-DedidtqC.mjs.map} +1 -1
  318. package/dist/{bylines-BdxWCnPL.mjs → bylines-B2NWnIwS.mjs} +2 -2
  319. package/dist/{bylines-BdxWCnPL.mjs.map → bylines-B2NWnIwS.mjs.map} +1 -1
  320. package/dist/{bylines-s8c2DXbH.mjs → bylines-DfGDnred.mjs} +7 -7
  321. package/dist/{bylines-s8c2DXbH.mjs.map → bylines-DfGDnred.mjs.map} +1 -1
  322. package/dist/{cache-B_HzASVT.mjs → cache-DTTHWD8n.mjs} +1 -1
  323. package/dist/{cache-B_HzASVT.mjs.map → cache-DTTHWD8n.mjs.map} +1 -1
  324. package/dist/{challenge-store-DXX3rfdI.mjs → challenge-store-woE0bbCf.mjs} +1 -1
  325. package/dist/{challenge-store-DXX3rfdI.mjs.map → challenge-store-woE0bbCf.mjs.map} +1 -1
  326. package/dist/cli/index.mjs +19 -18
  327. package/dist/cli/index.mjs.map +1 -1
  328. package/dist/client/cf-access.d.mts +1 -1
  329. package/dist/client/index.d.mts +1 -1
  330. package/dist/client/index.mjs +1 -1
  331. package/dist/{comments-Vkivawyl.mjs → comments-D2hNuxNa.mjs} +1 -1
  332. package/dist/{comments-Vkivawyl.mjs.map → comments-D2hNuxNa.mjs.map} +1 -1
  333. package/dist/{components-CK0cuUoH.mjs → components-DYKp2gmo.mjs} +1 -1
  334. package/dist/{components-CK0cuUoH.mjs.map → components-DYKp2gmo.mjs.map} +1 -1
  335. package/dist/{context-Y7BRkWes.mjs → context-Cm4pt1Ws.mjs} +5 -5
  336. package/dist/{context-Y7BRkWes.mjs.map → context-Cm4pt1Ws.mjs.map} +1 -1
  337. package/dist/{cron-BJ2ClIlj.mjs → cron-DdEVrQ2Y.mjs} +1 -1
  338. package/dist/{cron-BJ2ClIlj.mjs.map → cron-DdEVrQ2Y.mjs.map} +1 -1
  339. package/dist/{dashboard-2JgAMWxK.mjs → dashboard-C-UYpps0.mjs} +1 -1
  340. package/dist/{dashboard-2JgAMWxK.mjs.map → dashboard-C-UYpps0.mjs.map} +1 -1
  341. package/dist/db/index.d.mts +3 -3
  342. package/dist/db/libsql.d.mts +1 -1
  343. package/dist/db/postgres.d.mts +1 -1
  344. package/dist/db/sqlite.d.mts +1 -1
  345. package/dist/{db-errors-CtzxKBxe.mjs → db-errors-BluWkwGI.mjs} +1 -1
  346. package/dist/{db-errors-CtzxKBxe.mjs.map → db-errors-BluWkwGI.mjs.map} +1 -1
  347. package/dist/{default-IlBaTFxM.mjs → default-NHGuJzQ3.mjs} +1 -1
  348. package/dist/{default-IlBaTFxM.mjs.map → default-NHGuJzQ3.mjs.map} +1 -1
  349. package/dist/{device-flow-R23SIbQ2.mjs → device-flow-BQApWgnW.mjs} +4 -4
  350. package/dist/{device-flow-R23SIbQ2.mjs.map → device-flow-BQApWgnW.mjs.map} +1 -1
  351. package/dist/{email-console-DHT2Fbpj.mjs → email-console-BbU3RbWv.mjs} +1 -1
  352. package/dist/{email-console-DHT2Fbpj.mjs.map → email-console-BbU3RbWv.mjs.map} +1 -1
  353. package/dist/{error-RwM4dD35.mjs → error-CNn_w7jf.mjs} +1 -1
  354. package/dist/{error-RwM4dD35.mjs.map → error-CNn_w7jf.mjs.map} +1 -1
  355. package/dist/{escape-Ds07EEyu.mjs → escape-DPgcxcpL.mjs} +1 -1
  356. package/dist/{escape-Ds07EEyu.mjs.map → escape-DPgcxcpL.mjs.map} +1 -1
  357. package/dist/{fts-manager-1RgHmopc.mjs → fts-manager-Cx5z8jdA.mjs} +1 -1
  358. package/dist/{fts-manager-1RgHmopc.mjs.map → fts-manager-Cx5z8jdA.mjs.map} +1 -1
  359. package/dist/{hash-9w3pd3-m.mjs → hash-DlvIFn0b.mjs} +1 -1
  360. package/dist/{hash-9w3pd3-m.mjs.map → hash-DlvIFn0b.mjs.map} +1 -1
  361. package/dist/{import-Dh8bWmyq.mjs → import-KyxT1Mbs.mjs} +3 -3
  362. package/dist/{import-Dh8bWmyq.mjs.map → import-KyxT1Mbs.mjs.map} +1 -1
  363. package/dist/{index-B1keaX5Y.d.mts → index-D2VAiumu.d.mts} +15 -15
  364. package/dist/{index-B1keaX5Y.d.mts.map → index-D2VAiumu.d.mts.map} +1 -1
  365. package/dist/{index-DR56od45.d.mts → index-uT2yR66F.d.mts} +3 -3
  366. package/dist/{index-DR56od45.d.mts.map → index-uT2yR66F.d.mts.map} +1 -1
  367. package/dist/index.d.mts +16 -16
  368. package/dist/index.mjs +48 -46
  369. package/dist/init-lock-DlBHjf9-.mjs +83 -0
  370. package/dist/init-lock-DlBHjf9-.mjs.map +1 -0
  371. package/dist/{load-BBetCvLC.mjs → load-Dq91b_DK.mjs} +1 -1
  372. package/dist/{load-BBetCvLC.mjs.map → load-Dq91b_DK.mjs.map} +1 -1
  373. package/dist/{loader-ZN1ll-d-.mjs → loader-BqWjcH3h.mjs} +2 -2
  374. package/dist/{loader-ZN1ll-d-.mjs.map → loader-BqWjcH3h.mjs.map} +1 -1
  375. package/dist/{manifest-schema-BtwbL_vj.mjs → manifest-schema-DFPeqMAn.mjs} +1 -1
  376. package/dist/{manifest-schema-BtwbL_vj.mjs.map → manifest-schema-DFPeqMAn.mjs.map} +1 -1
  377. package/dist/media/index.d.mts +1 -1
  378. package/dist/media/index.mjs +2 -2
  379. package/dist/media/local-runtime.d.mts +11 -11
  380. package/dist/media/local-runtime.mjs +4 -3
  381. package/dist/media/local-runtime.mjs.map +1 -1
  382. package/dist/{media-allowlist-Dknq-OFY.mjs → media-allowlist-_A0SuDn4.mjs} +2 -2
  383. package/dist/{media-allowlist-Dknq-OFY.mjs.map → media-allowlist-_A0SuDn4.mjs.map} +1 -1
  384. package/dist/{media-url-VClf8glU.mjs → media-url-CqLd69IO.mjs} +1 -1
  385. package/dist/{media-url-VClf8glU.mjs.map → media-url-CqLd69IO.mjs.map} +1 -1
  386. package/dist/{menus-DrQLusqj.mjs → menus-Ryk9L7fT.mjs} +9 -9
  387. package/dist/{menus-DrQLusqj.mjs.map → menus-Ryk9L7fT.mjs.map} +1 -1
  388. package/dist/{mime-CCEzze7W.mjs → mime-YbtlEtvS.mjs} +1 -1
  389. package/dist/{mime-CCEzze7W.mjs.map → mime-YbtlEtvS.mjs.map} +1 -1
  390. package/dist/{mode-CO2vQHfq.mjs → mode-CGXzIbD8.mjs} +1 -1
  391. package/dist/{mode-CO2vQHfq.mjs.map → mode-CGXzIbD8.mjs.map} +1 -1
  392. package/dist/{normalize-CK5o04zr.mjs → normalize-DKsg36ty.mjs} +1 -1
  393. package/dist/{normalize-CK5o04zr.mjs.map → normalize-DKsg36ty.mjs.map} +1 -1
  394. package/dist/{oauth-authorization-Bw4NdF_S.mjs → oauth-authorization-C2kVyjXI.mjs} +4 -4
  395. package/dist/{oauth-authorization-Bw4NdF_S.mjs.map → oauth-authorization-C2kVyjXI.mjs.map} +1 -1
  396. package/dist/{oauth-clients-BGGFp57s.mjs → oauth-clients-BC873NCV.mjs} +1 -1
  397. package/dist/{oauth-clients-BGGFp57s.mjs.map → oauth-clients-BC873NCV.mjs.map} +1 -1
  398. package/dist/{oauth-state-store-97x0xtN2.mjs → oauth-state-store-Cd--TUaq.mjs} +1 -1
  399. package/dist/{oauth-state-store-97x0xtN2.mjs.map → oauth-state-store-Cd--TUaq.mjs.map} +1 -1
  400. package/dist/{oauth-user-lookup-B_vnZHKO.mjs → oauth-user-lookup-e4wOvDud.mjs} +1 -1
  401. package/dist/{oauth-user-lookup-B_vnZHKO.mjs.map → oauth-user-lookup-e4wOvDud.mjs.map} +1 -1
  402. package/dist/{options-DyYIYpPd.d.mts → options-9kLgkE8m.d.mts} +3 -3
  403. package/dist/{options-DyYIYpPd.d.mts.map → options-9kLgkE8m.d.mts.map} +1 -1
  404. package/dist/page/index.d.mts +2 -2
  405. package/dist/{parse-CrGndy1A.mjs → parse-DzSrk1t8.mjs} +2 -2
  406. package/dist/{parse-CrGndy1A.mjs.map → parse-DzSrk1t8.mjs.map} +1 -1
  407. package/dist/{passkey-config-C3QgnQnU.mjs → passkey-config-BpjbE_Uv.mjs} +1 -1
  408. package/dist/{passkey-config-C3QgnQnU.mjs.map → passkey-config-BpjbE_Uv.mjs.map} +1 -1
  409. package/dist/{placeholder-BZxr8W1j.mjs → placeholder-2xumZh4g.mjs} +1 -1
  410. package/dist/{placeholder-BZxr8W1j.mjs.map → placeholder-2xumZh4g.mjs.map} +1 -1
  411. package/dist/{placeholder-CVBv5z8k.d.mts → placeholder-BevVKfay.d.mts} +1 -1
  412. package/dist/{placeholder-CVBv5z8k.d.mts.map → placeholder-BevVKfay.d.mts.map} +1 -1
  413. package/dist/plugin-types.d.mts +1 -1
  414. package/dist/plugin-utils.d.mts +9 -9
  415. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  416. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  417. package/dist/{preview-BfuRkVKW.mjs → preview-Dqv2hwXr.mjs} +2 -2
  418. package/dist/{preview-BfuRkVKW.mjs.map → preview-Dqv2hwXr.mjs.map} +1 -1
  419. package/dist/{public-url-BFVC2OTJ.mjs → public-url-D_zARuvZ.mjs} +1 -1
  420. package/dist/{public-url-BFVC2OTJ.mjs.map → public-url-D_zARuvZ.mjs.map} +1 -1
  421. package/dist/{query-CbUcI4Xk.mjs → query-Crm038Mc.mjs} +9 -9
  422. package/dist/{query-CbUcI4Xk.mjs.map → query-Crm038Mc.mjs.map} +1 -1
  423. package/dist/{rate-limit-C7hjdkS5.mjs → rate-limit-hRTBqmw1.mjs} +2 -2
  424. package/dist/{rate-limit-C7hjdkS5.mjs.map → rate-limit-hRTBqmw1.mjs.map} +1 -1
  425. package/dist/{redirect-B_q19j4v.mjs → redirect-C-OOkyku.mjs} +1 -1
  426. package/dist/{redirect-B_q19j4v.mjs.map → redirect-C-OOkyku.mjs.map} +1 -1
  427. package/dist/{redirects-CCbCqCCd.mjs → redirects-6Zg2SoYo.mjs} +8 -9
  428. package/dist/{redirects-CCbCqCCd.mjs.map → redirects-6Zg2SoYo.mjs.map} +1 -1
  429. package/dist/{redirects-DxVoR7PI.mjs → redirects-CP3TnTLO.mjs} +20 -14
  430. package/dist/redirects-CP3TnTLO.mjs.map +1 -0
  431. package/dist/{registry-brYh-rAT.mjs → registry-diMzD1Wf.mjs} +3 -3
  432. package/dist/{registry-brYh-rAT.mjs.map → registry-diMzD1Wf.mjs.map} +1 -1
  433. package/dist/{request-cache-D32LpnmI.mjs → request-cache-UwmBAiUK.mjs} +1 -1
  434. package/dist/{request-cache-D32LpnmI.mjs.map → request-cache-UwmBAiUK.mjs.map} +1 -1
  435. package/dist/{request-meta-7ByVLxB-.mjs → request-meta-DPechd0W.mjs} +2 -2
  436. package/dist/{request-meta-7ByVLxB-.mjs.map → request-meta-DPechd0W.mjs.map} +1 -1
  437. package/dist/{resolve-BqYMVG0D.mjs → resolve-B3NUUtVY.mjs} +1 -1
  438. package/dist/{resolve-BqYMVG0D.mjs.map → resolve-B3NUUtVY.mjs.map} +1 -1
  439. package/dist/{runner-DTdhuI9i.d.mts → runner-C8vcbvCe.d.mts} +2 -2
  440. package/dist/{runner-DTdhuI9i.d.mts.map → runner-C8vcbvCe.d.mts.map} +1 -1
  441. package/dist/runtime.d.mts +10 -10
  442. package/dist/runtime.mjs +1 -1
  443. package/dist/{schema-C1E70ug_.mjs → schema-BDOkd3OU.mjs} +4 -4
  444. package/dist/{schema-C1E70ug_.mjs.map → schema-BDOkd3OU.mjs.map} +1 -1
  445. package/dist/{search-B3SGZw91.mjs → search-Bs_J_EW-.mjs} +3 -3
  446. package/dist/{search-B3SGZw91.mjs.map → search-Bs_J_EW-.mjs.map} +1 -1
  447. package/dist/{secrets-ChPTmy9x.mjs → secrets-C8xmE6mR.mjs} +21 -11
  448. package/dist/secrets-C8xmE6mR.mjs.map +1 -0
  449. package/dist/{sections-D_lVzwRZ.mjs → sections-P0zuBlyz.mjs} +2 -2
  450. package/dist/{sections-D_lVzwRZ.mjs.map → sections-P0zuBlyz.mjs.map} +1 -1
  451. package/dist/seed/index.d.mts +2 -2
  452. package/dist/seed/index.mjs +14 -13
  453. package/dist/seo/index.d.mts +1 -1
  454. package/dist/seo/index.mjs +1 -1
  455. package/dist/{seo-D_LPkOtu.mjs → seo-CLhm-Fmb.mjs} +1 -1
  456. package/dist/{seo-D_LPkOtu.mjs.map → seo-CLhm-Fmb.mjs.map} +1 -1
  457. package/dist/{seo-B5e6y9Wk.mjs → seo-DpNgGQjF.mjs} +1 -1
  458. package/dist/{seo-B5e6y9Wk.mjs.map → seo-DpNgGQjF.mjs.map} +1 -1
  459. package/dist/{service-ChDcsTBs.mjs → service-CDQQnT8W.mjs} +2 -2
  460. package/dist/{service-ChDcsTBs.mjs.map → service-CDQQnT8W.mjs.map} +1 -1
  461. package/dist/{settings-DfxiWY_s.mjs → settings-BjBsmVAo.mjs} +10 -184
  462. package/dist/settings-BjBsmVAo.mjs.map +1 -0
  463. package/dist/{settings-Cv47v9u8.mjs → settings-sO0Fif4p.mjs} +2 -2
  464. package/dist/{settings-Cv47v9u8.mjs.map → settings-sO0Fif4p.mjs.map} +1 -1
  465. package/dist/{setup-complete-yvPE4OsP.mjs → setup-complete-CMMr-oZU.mjs} +1 -1
  466. package/dist/{setup-complete-yvPE4OsP.mjs.map → setup-complete-CMMr-oZU.mjs.map} +1 -1
  467. package/dist/{setup-nonce-C9aFzb94.mjs → setup-nonce-169xl4fV.mjs} +1 -1
  468. package/dist/{setup-nonce-C9aFzb94.mjs.map → setup-nonce-169xl4fV.mjs.map} +1 -1
  469. package/dist/single-flight-cache-C0UV1Npg.mjs +104 -0
  470. package/dist/single-flight-cache-C0UV1Npg.mjs.map +1 -0
  471. package/dist/{site-url-CnHlmAs9.mjs → site-url-vtsuOvSD.mjs} +1 -1
  472. package/dist/{site-url-CnHlmAs9.mjs.map → site-url-vtsuOvSD.mjs.map} +1 -1
  473. package/dist/{ssrf-BsVGIE0Z.mjs → ssrf-XO05Voq6.mjs} +1 -1
  474. package/dist/{ssrf-BsVGIE0Z.mjs.map → ssrf-XO05Voq6.mjs.map} +1 -1
  475. package/dist/status-2gZklYuj.mjs +30 -0
  476. package/dist/status-2gZklYuj.mjs.map +1 -0
  477. package/dist/storage/local.d.mts +1 -1
  478. package/dist/storage/local.mjs +2 -2
  479. package/dist/storage/s3.d.mts +1 -1
  480. package/dist/storage/s3.mjs +1 -1
  481. package/dist/{taxonomies-BdAmbOwx.mjs → taxonomies-BBxYA38v.mjs} +6 -6
  482. package/dist/{taxonomies-BdAmbOwx.mjs.map → taxonomies-BBxYA38v.mjs.map} +1 -1
  483. package/dist/{taxonomies-BILwiyGk.mjs → taxonomies-DuESHWKI.mjs} +2 -2
  484. package/dist/{taxonomies-BILwiyGk.mjs.map → taxonomies-DuESHWKI.mjs.map} +1 -1
  485. package/dist/{tokens-Bx2afeT-.mjs → tokens-DMkVjxrx.mjs} +1 -1
  486. package/dist/{tokens-Bx2afeT-.mjs.map → tokens-DMkVjxrx.mjs.map} +1 -1
  487. package/dist/{transport-CmpLD7W3.mjs → transport-1cIrOb1Y.mjs} +1 -1
  488. package/dist/{transport-CmpLD7W3.mjs.map → transport-1cIrOb1Y.mjs.map} +1 -1
  489. package/dist/{transport-B7PPP2CC.d.mts → transport-jdvsZEIt.d.mts} +1 -1
  490. package/dist/{transport-B7PPP2CC.d.mts.map → transport-jdvsZEIt.d.mts.map} +1 -1
  491. package/dist/{trusted-proxy-B4AfnoAp.mjs → trusted-proxy-CHp41Fjj.mjs} +1 -1
  492. package/dist/{trusted-proxy-B4AfnoAp.mjs.map → trusted-proxy-CHp41Fjj.mjs.map} +1 -1
  493. package/dist/{types-BFgrqwSk.d.mts → types-BFgYtuKd.d.mts} +1 -1
  494. package/dist/{types-BFgrqwSk.d.mts.map → types-BFgYtuKd.d.mts.map} +1 -1
  495. package/dist/{types-DZk_y-MU.mjs → types-BIduXPJk.mjs} +1 -1
  496. package/dist/{types-DZk_y-MU.mjs.map → types-BIduXPJk.mjs.map} +1 -1
  497. package/dist/{types-DTniiNto.d.mts → types-BTnnBYVX.d.mts} +2 -2
  498. package/dist/{types-DTniiNto.d.mts.map → types-BTnnBYVX.d.mts.map} +1 -1
  499. package/dist/{types-BUUVn1zr.d.mts → types-Bzfk2yC8.d.mts} +1 -1
  500. package/dist/{types-BUUVn1zr.d.mts.map → types-Bzfk2yC8.d.mts.map} +1 -1
  501. package/dist/{types-BH8-30hc.d.mts → types-CkEuk-Zr.d.mts} +1 -1
  502. package/dist/{types-BH8-30hc.d.mts.map → types-CkEuk-Zr.d.mts.map} +1 -1
  503. package/dist/{types-CPAPl93j.d.mts → types-DO7whVYU.d.mts} +2 -2
  504. package/dist/{types-CPAPl93j.d.mts.map → types-DO7whVYU.d.mts.map} +1 -1
  505. package/dist/{types-S15DXXNi.d.mts → types-DdkL6fyv.d.mts} +1 -1
  506. package/dist/{types-S15DXXNi.d.mts.map → types-DdkL6fyv.d.mts.map} +1 -1
  507. package/dist/{types-DpFmlNyB.mjs → types-DejCHqWT.mjs} +1 -1
  508. package/dist/{types-DpFmlNyB.mjs.map → types-DejCHqWT.mjs.map} +1 -1
  509. package/dist/{types-BPzXTV9x.d.mts → types-Del0VMij.d.mts} +1 -1
  510. package/dist/{types-BPzXTV9x.d.mts.map → types-Del0VMij.d.mts.map} +1 -1
  511. package/dist/{types-D4kUqbHh.d.mts → types-u_XxjbS8.d.mts} +1 -1
  512. package/dist/{types-D4kUqbHh.d.mts.map → types-u_XxjbS8.d.mts.map} +1 -1
  513. package/dist/{utils-C4Ih4DML.mjs → utils-C4M981Br.mjs} +1 -1
  514. package/dist/{utils-C4Ih4DML.mjs.map → utils-C4M981Br.mjs.map} +1 -1
  515. package/dist/{validate-Bz4vqcX1.mjs → validate-DGhQPXzI.mjs} +2 -2
  516. package/dist/{validate-Bz4vqcX1.mjs.map → validate-DGhQPXzI.mjs.map} +1 -1
  517. package/dist/{validate-CNwkPWzz.d.mts → validate-cJOiOvT2.d.mts} +5 -5
  518. package/dist/{validate-CNwkPWzz.d.mts.map → validate-cJOiOvT2.d.mts.map} +1 -1
  519. package/dist/{validation-DgGTJm3u.mjs → validation-DVHjPM1M.mjs} +5 -5
  520. package/dist/{validation-DgGTJm3u.mjs.map → validation-DVHjPM1M.mjs.map} +1 -1
  521. package/dist/version-BOjj_cfz.mjs +7 -0
  522. package/dist/{version-D-5txk2m.mjs.map → version-BOjj_cfz.mjs.map} +1 -1
  523. package/dist/{widgets-DZfmAbE4.mjs → widgets-Ci6hLwfO.mjs} +4 -4
  524. package/dist/{widgets-DZfmAbE4.mjs.map → widgets-Ci6hLwfO.mjs.map} +1 -1
  525. package/dist/{zod-generator-Djo_VHCt.mjs → zod-generator-CarzgPAu.mjs} +2 -2
  526. package/dist/{zod-generator-Djo_VHCt.mjs.map → zod-generator-CarzgPAu.mjs.map} +1 -1
  527. package/package.json +5 -5
  528. package/src/api/handlers/redirects.ts +24 -13
  529. package/src/api/schemas/redirects.ts +11 -4
  530. package/src/astro/integration/index.ts +44 -8
  531. package/src/astro/integration/routes.ts +46 -9
  532. package/src/astro/middleware/redirect.ts +12 -0
  533. package/src/bylines/field-defs-cache.ts +70 -20
  534. package/src/cli/commands/doctor.ts +1 -1
  535. package/src/config/secrets.ts +28 -14
  536. package/src/emdash-runtime.ts +5 -5
  537. package/src/redirects/status.ts +27 -0
  538. package/src/settings/index.ts +13 -13
  539. package/src/utils/{isolate-cache.ts → single-flight-cache.ts} +26 -21
  540. package/dist/byline-DUx48sJp.mjs.map +0 -1
  541. package/dist/redirects-DxVoR7PI.mjs.map +0 -1
  542. package/dist/secrets-ChPTmy9x.mjs.map +0 -1
  543. package/dist/settings-DfxiWY_s.mjs.map +0 -1
  544. package/dist/version-D-5txk2m.mjs +0 -7
  545. /package/dist/{api-tokens-Oq39ba-Z.mjs → api-tokens-C7ywRx7l.mjs} +0 -0
  546. /package/dist/{ssrf-BvgVcfNQ.mjs → ssrf-CRZGzjdL.mjs} +0 -0
  547. /package/dist/{types-CZI4E3qG.mjs → types-BoRm8-pp.mjs} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"artifact.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/plugins/registry/artifact.ts"],"sourcesContent":["/**\n * Registry artifact proxy\n *\n * GET /_emdash/api/admin/plugins/registry/artifact?did=&slug=&version=&kind=&index=\n *\n * Proxies an icon / screenshot / banner image referenced by a registry\n * release record so the admin UI can display it without cross-origin\n * requests to arbitrary publisher hosting.\n *\n * Trust model (CRITICAL): the proxy never accepts an artifact URL from the\n * client. The caller addresses an artifact by its coordinates\n * `(did, slug, version, kind, index)`; the server resolves the *declared*\n * URL from the validated release record fetched from the configured\n * aggregator. The proxy can therefore only ever fetch a URL the publisher\n * declared in their signed release — not an arbitrary caller-supplied URL.\n *\n * The publisher-declared URL is still untrusted (an attacker who controls a\n * publisher record, or the aggregator, can point it anywhere), so the\n * resolved URL passes through the SSRF defences (`assertSafeArtifactUrl`,\n * re-validated on every redirect hop) before any fetch, and only allowlisted\n * image content types are served back.\n */\n\nimport type { Did } from \"@atcute/lexicons\";\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError } from \"#api/error.js\";\nimport { assertSafeArtifactUrl } from \"#api/index.js\";\n\nimport { coerceRegistryConfig, validateAggregatorUrl } from \"../../../../../../registry/config.js\";\n\nexport const prerender = false;\n\n/**\n * Image content types the proxy will pass through. Anything else is rejected.\n *\n * SVG is deliberately excluded: it is active content (an `<svg><script>`\n * executes when navigated to as a top-level document), and the publisher\n * supplies the bytes. Rather than serve it behind mitigations, we refuse it\n * end-to-end — the publish CLI rejects SVG artifacts too, so a conforming\n * release never references one. AVIF is included.\n */\nconst ALLOWED_IMAGE_TYPES = new Set([\n\t\"image/png\",\n\t\"image/jpeg\",\n\t\"image/webp\",\n\t\"image/gif\",\n\t\"image/avif\",\n]);\n\n/** Artifact kinds the proxy can resolve. `screenshot` additionally needs `index`. */\nconst ALLOWED_KINDS = new Set([\"icon\", \"banner\", \"screenshot\"]);\n\n/** Loose DID shape (`did:method:id`); the aggregator lexicon is authoritative. */\nconst DID_PATTERN = /^did:[a-z]+:.+/;\n/** Slug grammar: ASCII letter then letters / digits / `-` / `_`. Mirrors the install route. */\nconst SLUG_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;\n/** Non-negative integer, for the screenshot index param. */\nconst INDEX_PATTERN = /^\\d+$/;\n\n/** Cap proxied images so a hostile host can't stream an unbounded body. */\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\n\n/** Redirect hops to follow, re-validating each target against SSRF rules. */\nconst MAX_REDIRECTS = 5;\n\n/** Wall-clock budget covering connect + headers + body for the artifact fetch. */\nconst FETCH_TIMEOUT_MS = 15_000;\n\n/** Per-aggregator-request timeout and overall budget for release resolution. */\nconst AGGREGATOR_REQUEST_TIMEOUT_MS = 15_000;\nconst AGGREGATOR_TOTAL_BUDGET_MS = 30_000;\n\n/** Bound the version search: 20 pages * 50 per page = 1000 releases worth. */\nconst MAX_LIST_PAGES = 20;\n\n/** Build a fetch that enforces a per-request and per-budget timeout. Mirrors the install handler. */\nfunction timedFetch(totalDeadline: number): typeof fetch {\n\treturn (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {\n\t\tconst now = Date.now();\n\t\tconst remaining = Math.max(0, totalDeadline - now);\n\t\tif (remaining === 0) {\n\t\t\treturn Promise.reject(new Error(\"Aggregator request budget exhausted\"));\n\t\t}\n\t\tconst timeout = Math.min(AGGREGATOR_REQUEST_TIMEOUT_MS, remaining);\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), timeout);\n\t\tconst callerSignal = init?.signal;\n\t\tif (callerSignal) {\n\t\t\tif (callerSignal.aborted) controller.abort(callerSignal.reason);\n\t\t\telse callerSignal.addEventListener(\"abort\", () => controller.abort(callerSignal.reason));\n\t\t}\n\t\treturn fetch(input, { ...init, signal: controller.signal }).finally(() => {\n\t\t\tclearTimeout(timer);\n\t\t});\n\t};\n}\n\n/**\n * Narrow one entry of a release's `artifacts` map to a usable image URL.\n *\n * The embedded `release` record is lexicon-validated at the DiscoveryClient\n * boundary, but `artifacts` is an aggregator pass-through typed `unknown`, so\n * the entry's shape is not guaranteed. Returns the `url` string only when the\n * value is an object carrying a non-empty string `url`; everything else\n * (missing key, wrong type, no `url`) yields `null`.\n */\nfunction declaredArtifactUrl(value: unknown): string | null {\n\tif (!value || typeof value !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; url checked below\n\tconst entry = value as Record<string, unknown>;\n\tconst url = entry.url;\n\tif (typeof url !== \"string\" || url.length === 0) return null;\n\treturn url;\n}\n\n/**\n * Resolve the declared artifact URL for `(kind, index)` from a release's\n * `artifacts` map. Returns `null` when the requested artifact isn't present\n * or doesn't carry a usable URL.\n */\nfunction resolveDeclaredUrl(artifacts: unknown, kind: string, index: number): string | null {\n\tif (!artifacts || typeof artifacts !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; each entry shape-narrowed by declaredArtifactUrl\n\tconst map = artifacts as Record<string, unknown>;\n\n\tif (kind === \"icon\") return declaredArtifactUrl(map.icon);\n\tif (kind === \"banner\") return declaredArtifactUrl(map.banner);\n\t// kind === \"screenshot\"\n\tconst screenshots = map.screenshots;\n\tif (!Array.isArray(screenshots)) return null;\n\tif (index < 0 || index >= screenshots.length) return null;\n\treturn declaredArtifactUrl(screenshots[index]);\n}\n\nexport const GET: APIRoute = async ({ url, locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tconst did = url.searchParams.get(\"did\");\n\tconst slug = url.searchParams.get(\"slug\");\n\tconst kind = url.searchParams.get(\"kind\");\n\tconst versionParam = url.searchParams.get(\"version\");\n\tconst indexParam = url.searchParams.get(\"index\");\n\n\tif (!did || !slug || !kind) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Missing did, slug, or kind\", 400);\n\t}\n\tif (did.length > 256 || !DID_PATTERN.test(did)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid did\", 400);\n\t}\n\tif (slug.length > 64 || !SLUG_PATTERN.test(slug)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid slug\", 400);\n\t}\n\tif (!ALLOWED_KINDS.has(kind)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid kind\", 400);\n\t}\n\n\tlet index = 0;\n\tif (kind === \"screenshot\") {\n\t\tif (indexParam === null) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Missing index for screenshot\", 400);\n\t\t}\n\t\tif (!INDEX_PATTERN.test(indexParam)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t\tindex = Number(indexParam);\n\t\tif (!Number.isSafeInteger(index)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t}\n\n\tlet version: string | undefined;\n\tif (versionParam !== null && versionParam.length > 0) {\n\t\tif (versionParam.length > 64) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid version\", 400);\n\t\t}\n\t\tversion = versionParam;\n\t}\n\n\tconst registryConfig = coerceRegistryConfig(emdash.config.experimental?.registry);\n\tif (!registryConfig) {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry is not configured\", 400);\n\t}\n\ttry {\n\t\tvalidateAggregatorUrl(registryConfig.aggregatorUrl);\n\t} catch {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry aggregator URL is invalid\", 500);\n\t}\n\n\t// Resolve the publisher-declared artifact URL from the release record.\n\tlet declaredUrl: string;\n\ttry {\n\t\tconst resolved = await resolveArtifactUrl(registryConfig, did, slug, version, kind, index);\n\t\tif (resolved === null) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_FOUND\", \"Artifact not found\", 404);\n\t\t}\n\t\tdeclaredUrl = resolved;\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_RESOLVE_FAILED\", \"Failed to resolve artifact\", 502);\n\t}\n\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\ttry {\n\t\t// `assertSafeArtifactUrl` validates scheme / credentials / loopback +\n\t\t// resolves the hostname and rejects private / link-local / metadata\n\t\t// targets (DNS-rebinding defence). It throws a plain Error on any\n\t\t// block, so a rejection here means the URL is unsafe.\n\t\tlet current: URL;\n\t\ttry {\n\t\t\tcurrent = await assertSafeArtifactUrl(declaredUrl);\n\t\t} catch {\n\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Artifact URL is not allowed\", 400);\n\t\t}\n\n\t\tlet response: Response;\n\t\tfor (let hop = 0; ; hop++) {\n\t\t\tresponse = await fetch(current.href, { redirect: \"manual\", signal: controller.signal });\n\t\t\tif (response.status < 300 || response.status >= 400) break;\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tif (!location) break;\n\t\t\tif (hop === MAX_REDIRECTS) {\n\t\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Too many redirects\", 502);\n\t\t\t}\n\t\t\tlet next: URL;\n\t\t\ttry {\n\t\t\t\tnext = await assertSafeArtifactUrl(new URL(location, current).href);\n\t\t\t} catch {\n\t\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Redirect target is not allowed\", 400);\n\t\t\t}\n\t\t\tcurrent = next;\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n\t\t}\n\n\t\t// Content-Type allowlist: only image types are proxied. A non-image\n\t\t// (HTML error page, JSON, octet-stream) is rejected so the admin\n\t\t// never renders publisher-controlled markup from the EmDash origin.\n\t\tconst rawType = response.headers.get(\"content-type\") ?? \"\";\n\t\tconst contentType = rawType.split(\";\", 1)[0]!.trim().toLowerCase();\n\t\tif (!ALLOWED_IMAGE_TYPES.has(contentType)) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_IMAGE\", \"Artifact is not an allowed image type\", 415);\n\t\t}\n\n\t\tconst declaredLength = response.headers.get(\"content-length\");\n\t\tif (declaredLength) {\n\t\t\tconst declared = Number(declaredLength);\n\t\t\tif (Number.isFinite(declared) && declared > MAX_IMAGE_BYTES) {\n\t\t\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t\t\t}\n\t\t}\n\n\t\tconst bytes = await readCapped(response, MAX_IMAGE_BYTES);\n\t\tif (bytes === null) {\n\t\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t\t}\n\n\t\t// Only the allowlisted Content-Type is forwarded — never copy other\n\t\t// upstream headers. `private, no-store` keeps publisher images out of\n\t\t// shared caches in the authenticated admin origin.\n\t\t//\n\t\t// SVG is not in the allowlist, so active-content bytes never reach\n\t\t// here. `Content-Disposition: attachment`, the sandbox CSP, and\n\t\t// `nosniff` remain as defence-in-depth: they force a download and\n\t\t// neutralise script/plugins for any image type if a client navigates\n\t\t// directly to the proxy URL.\n\t\treturn new Response(bytes, {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": contentType,\n\t\t\t\t\"Cache-Control\": \"private, no-store\",\n\t\t\t\t\"X-Content-Type-Options\": \"nosniff\",\n\t\t\t\t\"Content-Disposition\": \"attachment\",\n\t\t\t\t\"Content-Security-Policy\": \"default-src 'none'; sandbox\",\n\t\t\t},\n\t\t});\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n};\n\n/**\n * Resolve the declared artifact URL for `(did, slug, version, kind, index)`\n * from the aggregator's release record. Mirrors the install handler's release\n * lookup. Returns `null` when the package/release/artifact isn't found.\n *\n * Self-contained to this route: the install/update handlers are intentionally\n * left untouched, so a small amount of resolution-pattern duplication is\n * accepted here.\n */\nasync function resolveArtifactUrl(\n\tregistryConfig: { aggregatorUrl: string; acceptLabelers?: string },\n\tdid: string,\n\tslug: string,\n\tversion: string | undefined,\n\tkind: string,\n\tindex: number,\n): Promise<string | null> {\n\t// Lazy-load the discovery client so the `@atcute/client` dependency only\n\t// loads when the registry path is exercised.\n\tconst { DiscoveryClient } = await import(\"@emdash-cms/registry-client/discovery\");\n\n\tconst aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;\n\tconst discovery = new DiscoveryClient({\n\t\taggregatorUrl: registryConfig.aggregatorUrl,\n\t\tacceptLabelers: registryConfig.acceptLabelers,\n\t\tfetch: timedFetch(aggregatorDeadline),\n\t});\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- DID shape validated by the route before this call\n\tconst publisherDid = did as Did;\n\n\tconst releaseView = await (async () => {\n\t\tif (!version) {\n\t\t\treturn discovery.getLatestRelease({ did: publisherDid, package: slug });\n\t\t}\n\t\tlet cursor: string | undefined;\n\t\tconst seenCursors = new Set<string>();\n\t\tfor (let page = 0; page < MAX_LIST_PAGES; page++) {\n\t\t\tif (cursor !== undefined) {\n\t\t\t\tif (seenCursors.has(cursor)) break;\n\t\t\t\tseenCursors.add(cursor);\n\t\t\t}\n\t\t\tconst result = await discovery.listReleases({\n\t\t\t\tdid: publisherDid,\n\t\t\t\tpackage: slug,\n\t\t\t\tcursor,\n\t\t\t\tlimit: 50,\n\t\t\t});\n\t\t\tfor (const r of result.releases) {\n\t\t\t\tif (r.version === version) return r;\n\t\t\t}\n\t\t\tif (!result.cursor) break;\n\t\t\tcursor = result.cursor;\n\t\t}\n\t\treturn undefined;\n\t})();\n\n\tif (!releaseView?.release) return null;\n\n\treturn resolveDeclaredUrl(releaseView.release.artifacts, kind, index);\n}\n\n/**\n * Read a response body into memory, aborting once it exceeds `limit`. Returns\n * `null` when the cap is breached (the streamed body lied about / omitted\n * Content-Length). The cap is the real defence against an unbounded body.\n */\nasync function readCapped(response: Response, limit: number): Promise<Uint8Array | null> {\n\tconst body = response.body;\n\tif (!body) {\n\t\tconst buf = new Uint8Array(await response.arrayBuffer());\n\t\treturn buf.length > limit ? null : buf;\n\t}\n\tconst reader = body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\twhile (true) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (done) break;\n\t\tif (value) {\n\t\t\ttotal += value.length;\n\t\t\tif (total > limit) {\n\t\t\t\tawait reader.cancel();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t}\n\tconst combined = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tcombined.set(chunk, offset);\n\t\toffset += chunk.length;\n\t}\n\treturn combined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"artifact.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/plugins/registry/artifact.ts"],"sourcesContent":["/**\n * Registry artifact proxy\n *\n * GET /_emdash/api/admin/plugins/registry/artifact?did=&slug=&version=&kind=&index=\n *\n * Proxies an icon / screenshot / banner image referenced by a registry\n * release record so the admin UI can display it without cross-origin\n * requests to arbitrary publisher hosting.\n *\n * Trust model (CRITICAL): the proxy never accepts an artifact URL from the\n * client. The caller addresses an artifact by its coordinates\n * `(did, slug, version, kind, index)`; the server resolves the *declared*\n * URL from the validated release record fetched from the configured\n * aggregator. The proxy can therefore only ever fetch a URL the publisher\n * declared in their signed release — not an arbitrary caller-supplied URL.\n *\n * The publisher-declared URL is still untrusted (an attacker who controls a\n * publisher record, or the aggregator, can point it anywhere), so the\n * resolved URL passes through the SSRF defences (`assertSafeArtifactUrl`,\n * re-validated on every redirect hop) before any fetch, and only allowlisted\n * image content types are served back.\n */\n\nimport type { Did } from \"@atcute/lexicons\";\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError } from \"#api/error.js\";\nimport { assertSafeArtifactUrl } from \"#api/index.js\";\n\nimport { coerceRegistryConfig, validateAggregatorUrl } from \"../../../../../../registry/config.js\";\n\nexport const prerender = false;\n\n/**\n * Image content types the proxy will pass through. Anything else is rejected.\n *\n * SVG is deliberately excluded: it is active content (an `<svg><script>`\n * executes when navigated to as a top-level document), and the publisher\n * supplies the bytes. Rather than serve it behind mitigations, we refuse it\n * end-to-end — the publish CLI rejects SVG artifacts too, so a conforming\n * release never references one. AVIF is included.\n */\nconst ALLOWED_IMAGE_TYPES = new Set([\n\t\"image/png\",\n\t\"image/jpeg\",\n\t\"image/webp\",\n\t\"image/gif\",\n\t\"image/avif\",\n]);\n\n/** Artifact kinds the proxy can resolve. `screenshot` additionally needs `index`. */\nconst ALLOWED_KINDS = new Set([\"icon\", \"banner\", \"screenshot\"]);\n\n/** Loose DID shape (`did:method:id`); the aggregator lexicon is authoritative. */\nconst DID_PATTERN = /^did:[a-z]+:.+/;\n/** Slug grammar: ASCII letter then letters / digits / `-` / `_`. Mirrors the install route. */\nconst SLUG_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;\n/** Non-negative integer, for the screenshot index param. */\nconst INDEX_PATTERN = /^\\d+$/;\n\n/** Cap proxied images so a hostile host can't stream an unbounded body. */\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\n\n/** Redirect hops to follow, re-validating each target against SSRF rules. */\nconst MAX_REDIRECTS = 5;\n\n/** Wall-clock budget covering connect + headers + body for the artifact fetch. */\nconst FETCH_TIMEOUT_MS = 15_000;\n\n/** Per-aggregator-request timeout and overall budget for release resolution. */\nconst AGGREGATOR_REQUEST_TIMEOUT_MS = 15_000;\nconst AGGREGATOR_TOTAL_BUDGET_MS = 30_000;\n\n/** Bound the version search: 20 pages * 50 per page = 1000 releases worth. */\nconst MAX_LIST_PAGES = 20;\n\n/** Build a fetch that enforces a per-request and per-budget timeout. Mirrors the install handler. */\nfunction timedFetch(totalDeadline: number): typeof fetch {\n\treturn (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {\n\t\tconst now = Date.now();\n\t\tconst remaining = Math.max(0, totalDeadline - now);\n\t\tif (remaining === 0) {\n\t\t\treturn Promise.reject(new Error(\"Aggregator request budget exhausted\"));\n\t\t}\n\t\tconst timeout = Math.min(AGGREGATOR_REQUEST_TIMEOUT_MS, remaining);\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), timeout);\n\t\tconst callerSignal = init?.signal;\n\t\tif (callerSignal) {\n\t\t\tif (callerSignal.aborted) controller.abort(callerSignal.reason);\n\t\t\telse callerSignal.addEventListener(\"abort\", () => controller.abort(callerSignal.reason));\n\t\t}\n\t\treturn fetch(input, { ...init, signal: controller.signal }).finally(() => {\n\t\t\tclearTimeout(timer);\n\t\t});\n\t};\n}\n\n/**\n * Narrow one entry of a release's `artifacts` map to a usable image URL.\n *\n * The embedded `release` record is lexicon-validated at the DiscoveryClient\n * boundary, but `artifacts` is an aggregator pass-through typed `unknown`, so\n * the entry's shape is not guaranteed. Returns the `url` string only when the\n * value is an object carrying a non-empty string `url`; everything else\n * (missing key, wrong type, no `url`) yields `null`.\n */\nfunction declaredArtifactUrl(value: unknown): string | null {\n\tif (!value || typeof value !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; url checked below\n\tconst entry = value as Record<string, unknown>;\n\tconst url = entry.url;\n\tif (typeof url !== \"string\" || url.length === 0) return null;\n\treturn url;\n}\n\n/**\n * Resolve the declared artifact URL for `(kind, index)` from a release's\n * `artifacts` map. Returns `null` when the requested artifact isn't present\n * or doesn't carry a usable URL.\n */\nfunction resolveDeclaredUrl(artifacts: unknown, kind: string, index: number): string | null {\n\tif (!artifacts || typeof artifacts !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; each entry shape-narrowed by declaredArtifactUrl\n\tconst map = artifacts as Record<string, unknown>;\n\n\tif (kind === \"icon\") return declaredArtifactUrl(map.icon);\n\tif (kind === \"banner\") return declaredArtifactUrl(map.banner);\n\t// kind === \"screenshot\"\n\tconst screenshots = map.screenshots;\n\tif (!Array.isArray(screenshots)) return null;\n\tif (index < 0 || index >= screenshots.length) return null;\n\treturn declaredArtifactUrl(screenshots[index]);\n}\n\nexport const GET: APIRoute = async ({ url, locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tconst did = url.searchParams.get(\"did\");\n\tconst slug = url.searchParams.get(\"slug\");\n\tconst kind = url.searchParams.get(\"kind\");\n\tconst versionParam = url.searchParams.get(\"version\");\n\tconst indexParam = url.searchParams.get(\"index\");\n\n\tif (!did || !slug || !kind) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Missing did, slug, or kind\", 400);\n\t}\n\tif (did.length > 256 || !DID_PATTERN.test(did)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid did\", 400);\n\t}\n\tif (slug.length > 64 || !SLUG_PATTERN.test(slug)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid slug\", 400);\n\t}\n\tif (!ALLOWED_KINDS.has(kind)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid kind\", 400);\n\t}\n\n\tlet index = 0;\n\tif (kind === \"screenshot\") {\n\t\tif (indexParam === null) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Missing index for screenshot\", 400);\n\t\t}\n\t\tif (!INDEX_PATTERN.test(indexParam)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t\tindex = Number(indexParam);\n\t\tif (!Number.isSafeInteger(index)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t}\n\n\tlet version: string | undefined;\n\tif (versionParam !== null && versionParam.length > 0) {\n\t\tif (versionParam.length > 64) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid version\", 400);\n\t\t}\n\t\tversion = versionParam;\n\t}\n\n\tconst registryConfig = coerceRegistryConfig(emdash.config.experimental?.registry);\n\tif (!registryConfig) {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry is not configured\", 400);\n\t}\n\ttry {\n\t\tvalidateAggregatorUrl(registryConfig.aggregatorUrl);\n\t} catch {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry aggregator URL is invalid\", 500);\n\t}\n\n\t// Resolve the publisher-declared artifact URL from the release record.\n\tlet declaredUrl: string;\n\ttry {\n\t\tconst resolved = await resolveArtifactUrl(registryConfig, did, slug, version, kind, index);\n\t\tif (resolved === null) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_FOUND\", \"Artifact not found\", 404);\n\t\t}\n\t\tdeclaredUrl = resolved;\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_RESOLVE_FAILED\", \"Failed to resolve artifact\", 502);\n\t}\n\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\ttry {\n\t\t// `assertSafeArtifactUrl` validates scheme / credentials / loopback +\n\t\t// resolves the hostname and rejects private / link-local / metadata\n\t\t// targets (DNS-rebinding defence). It throws a plain Error on any\n\t\t// block, so a rejection here means the URL is unsafe.\n\t\tlet current: URL;\n\t\ttry {\n\t\t\tcurrent = await assertSafeArtifactUrl(declaredUrl);\n\t\t} catch {\n\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Artifact URL is not allowed\", 400);\n\t\t}\n\n\t\tlet response: Response;\n\t\tfor (let hop = 0; ; hop++) {\n\t\t\tresponse = await fetch(current.href, { redirect: \"manual\", signal: controller.signal });\n\t\t\tif (response.status < 300 || response.status >= 400) break;\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tif (!location) break;\n\t\t\tif (hop === MAX_REDIRECTS) {\n\t\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Too many redirects\", 502);\n\t\t\t}\n\t\t\tlet next: URL;\n\t\t\ttry {\n\t\t\t\tnext = await assertSafeArtifactUrl(new URL(location, current).href);\n\t\t\t} catch {\n\t\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Redirect target is not allowed\", 400);\n\t\t\t}\n\t\t\tcurrent = next;\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n\t\t}\n\n\t\t// Content-Type allowlist: only image types are proxied. A non-image\n\t\t// (HTML error page, JSON, octet-stream) is rejected so the admin\n\t\t// never renders publisher-controlled markup from the EmDash origin.\n\t\tconst rawType = response.headers.get(\"content-type\") ?? \"\";\n\t\tconst contentType = rawType.split(\";\", 1)[0]!.trim().toLowerCase();\n\t\tif (!ALLOWED_IMAGE_TYPES.has(contentType)) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_IMAGE\", \"Artifact is not an allowed image type\", 415);\n\t\t}\n\n\t\tconst declaredLength = response.headers.get(\"content-length\");\n\t\tif (declaredLength) {\n\t\t\tconst declared = Number(declaredLength);\n\t\t\tif (Number.isFinite(declared) && declared > MAX_IMAGE_BYTES) {\n\t\t\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t\t\t}\n\t\t}\n\n\t\tconst bytes = await readCapped(response, MAX_IMAGE_BYTES);\n\t\tif (bytes === null) {\n\t\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t\t}\n\n\t\t// Only the allowlisted Content-Type is forwarded — never copy other\n\t\t// upstream headers. `private, no-store` keeps publisher images out of\n\t\t// shared caches in the authenticated admin origin.\n\t\t//\n\t\t// SVG is not in the allowlist, so active-content bytes never reach\n\t\t// here. `Content-Disposition: attachment`, the sandbox CSP, and\n\t\t// `nosniff` remain as defence-in-depth: they force a download and\n\t\t// neutralise script/plugins for any image type if a client navigates\n\t\t// directly to the proxy URL.\n\t\treturn new Response(bytes, {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": contentType,\n\t\t\t\t\"Cache-Control\": \"private, no-store\",\n\t\t\t\t\"X-Content-Type-Options\": \"nosniff\",\n\t\t\t\t\"Content-Disposition\": \"attachment\",\n\t\t\t\t\"Content-Security-Policy\": \"default-src 'none'; sandbox\",\n\t\t\t},\n\t\t});\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n};\n\n/**\n * Resolve the declared artifact URL for `(did, slug, version, kind, index)`\n * from the aggregator's release record. Mirrors the install handler's release\n * lookup. Returns `null` when the package/release/artifact isn't found.\n *\n * Self-contained to this route: the install/update handlers are intentionally\n * left untouched, so a small amount of resolution-pattern duplication is\n * accepted here.\n */\nasync function resolveArtifactUrl(\n\tregistryConfig: { aggregatorUrl: string; acceptLabelers?: string },\n\tdid: string,\n\tslug: string,\n\tversion: string | undefined,\n\tkind: string,\n\tindex: number,\n): Promise<string | null> {\n\t// Lazy-load the discovery client so the `@atcute/client` dependency only\n\t// loads when the registry path is exercised.\n\tconst { DiscoveryClient } = await import(\"@emdash-cms/registry-client/discovery\");\n\n\tconst aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;\n\tconst discovery = new DiscoveryClient({\n\t\taggregatorUrl: registryConfig.aggregatorUrl,\n\t\tacceptLabelers: registryConfig.acceptLabelers,\n\t\tfetch: timedFetch(aggregatorDeadline),\n\t});\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- DID shape validated by the route before this call\n\tconst publisherDid = did as Did;\n\n\tconst releaseView = await (async () => {\n\t\tif (!version) {\n\t\t\treturn discovery.getLatestRelease({ did: publisherDid, package: slug });\n\t\t}\n\t\tlet cursor: string | undefined;\n\t\tconst seenCursors = new Set<string>();\n\t\tfor (let page = 0; page < MAX_LIST_PAGES; page++) {\n\t\t\tif (cursor !== undefined) {\n\t\t\t\tif (seenCursors.has(cursor)) break;\n\t\t\t\tseenCursors.add(cursor);\n\t\t\t}\n\t\t\tconst result = await discovery.listReleases({\n\t\t\t\tdid: publisherDid,\n\t\t\t\tpackage: slug,\n\t\t\t\tcursor,\n\t\t\t\tlimit: 50,\n\t\t\t});\n\t\t\tfor (const r of result.releases) {\n\t\t\t\tif (r.version === version) return r;\n\t\t\t}\n\t\t\tif (!result.cursor) break;\n\t\t\tcursor = result.cursor;\n\t\t}\n\t\treturn undefined;\n\t})();\n\n\tif (!releaseView?.release) return null;\n\n\treturn resolveDeclaredUrl(releaseView.release.artifacts, kind, index);\n}\n\n/**\n * Read a response body into memory, aborting once it exceeds `limit`. Returns\n * `null` when the cap is breached (the streamed body lied about / omitted\n * Content-Length). The cap is the real defence against an unbounded body.\n */\nasync function readCapped(response: Response, limit: number): Promise<Uint8Array | null> {\n\tconst body = response.body;\n\tif (!body) {\n\t\tconst buf = new Uint8Array(await response.arrayBuffer());\n\t\treturn buf.length > limit ? null : buf;\n\t}\n\tconst reader = body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\twhile (true) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (done) break;\n\t\tif (value) {\n\t\t\ttotal += value.length;\n\t\t\tif (total > limit) {\n\t\t\t\tawait reader.cancel();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t}\n\tconst combined = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tcombined.set(chunk, offset);\n\t\toffset += chunk.length;\n\t}\n\treturn combined;\n}\n"],"mappings":"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"}
@@ -9,33 +9,35 @@ import "../../../../../../comment-sqQxNpN3.mjs";
9
9
  import "../../../../../../options-BPCVnesz.mjs";
10
10
  import "../../../../../../menus-DX4_E01q.mjs";
11
11
  import "../../../../../../redirect-CRWIt8Zj.mjs";
12
- import "../../../../../../request-cache-D32LpnmI.mjs";
13
- import "../../../../../../byline-registry-CWP7I71B.mjs";
14
- import "../../../../../../byline-DUx48sJp.mjs";
15
- import "../../../../../../seo-B5e6y9Wk.mjs";
16
- import { n as handleRegistryInstall } from "../../../../../../api-DStv36ik.mjs";
17
- import "../../../../../../dashboard-2JgAMWxK.mjs";
18
- import "../../../../../../fts-manager-1RgHmopc.mjs";
19
- import "../../../../../../registry-brYh-rAT.mjs";
20
- import "../../../../../../loader-ZN1ll-d-.mjs";
21
- import "../../../../../../schema-C1E70ug_.mjs";
22
- import "../../../../../../zod-generator-Djo_VHCt.mjs";
23
- import "../../../../../../seo-D_LPkOtu.mjs";
24
- import "../../../../../../sections-D_lVzwRZ.mjs";
25
- import "../../../../../../settings-DfxiWY_s.mjs";
26
- import "../../../../../../settings-Cv47v9u8.mjs";
27
- import "../../../../../../resolve-BqYMVG0D.mjs";
28
- import "../../../../../../taxonomies-BdAmbOwx.mjs";
29
- import "../../../../../../taxonomies-BILwiyGk.mjs";
30
- import "../../../../../../manifest-schema-BtwbL_vj.mjs";
31
- import "../../../../../../types-CZI4E3qG.mjs";
32
- import "../../../../../../ssrf-BsVGIE0Z.mjs";
33
- import { a as unwrapResult, r as handleError, t as apiError } from "../../../../../../error-RwM4dD35.mjs";
34
- import { n as parseBody, t as isParseError } from "../../../../../../parse-CrGndy1A.mjs";
35
- import "../../../../../../redirects-CCbCqCCd.mjs";
36
- import "../../../../../../byline-fields-8TMtkBnH.mjs";
37
- import { n as VERSION } from "../../../../../../version-D-5txk2m.mjs";
38
- import { n as requirePerm } from "../../../../../../authorize-DsMSVSaY.mjs";
12
+ import "../../../../../../init-lock-DlBHjf9-.mjs";
13
+ import "../../../../../../request-cache-UwmBAiUK.mjs";
14
+ import "../../../../../../byline-registry-DedidtqC.mjs";
15
+ import "../../../../../../byline-V_Qp1Ziw.mjs";
16
+ import "../../../../../../seo-DpNgGQjF.mjs";
17
+ import { n as handleRegistryInstall } from "../../../../../../api-DxjIV2o8.mjs";
18
+ import "../../../../../../dashboard-C-UYpps0.mjs";
19
+ import "../../../../../../fts-manager-Cx5z8jdA.mjs";
20
+ import "../../../../../../registry-diMzD1Wf.mjs";
21
+ import "../../../../../../loader-BqWjcH3h.mjs";
22
+ import "../../../../../../schema-BDOkd3OU.mjs";
23
+ import "../../../../../../zod-generator-CarzgPAu.mjs";
24
+ import "../../../../../../seo-CLhm-Fmb.mjs";
25
+ import "../../../../../../sections-P0zuBlyz.mjs";
26
+ import "../../../../../../settings-BjBsmVAo.mjs";
27
+ import "../../../../../../settings-sO0Fif4p.mjs";
28
+ import "../../../../../../resolve-B3NUUtVY.mjs";
29
+ import "../../../../../../taxonomies-BBxYA38v.mjs";
30
+ import "../../../../../../taxonomies-DuESHWKI.mjs";
31
+ import "../../../../../../manifest-schema-DFPeqMAn.mjs";
32
+ import "../../../../../../types-BoRm8-pp.mjs";
33
+ import "../../../../../../ssrf-XO05Voq6.mjs";
34
+ import { a as unwrapResult, r as handleError, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
35
+ import { n as parseBody, t as isParseError } from "../../../../../../parse-DzSrk1t8.mjs";
36
+ import "../../../../../../redirects-6Zg2SoYo.mjs";
37
+ import "../../../../../../byline-fields-B0NO1yUB.mjs";
38
+ import "../../../../../../status-2gZklYuj.mjs";
39
+ import { n as VERSION } from "../../../../../../version-BOjj_cfz.mjs";
40
+ import { n as requirePerm } from "../../../../../../authorize-D5gfBVU5.mjs";
39
41
  import { z } from "zod";
40
42
  import { hostEnvFromVersions } from "@emdash-cms/registry-client/env";
41
43
 
@@ -1 +1 @@
1
- {"version":3,"file":"install.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/plugins/registry/install.ts"],"sourcesContent":["/**\n * Registry plugin install endpoint\n *\n * POST /_emdash/api/admin/plugins/registry/install\n *\n * Installs a plugin from the experimental decentralized plugin registry\n * (see RFC 0001). The browser resolves `(handle, slug) → (did, slug)`\n * via the aggregator before posting and sends the publisher DID\n * directly; the server skips the resolvePackage round-trip and looks\n * up the package by DID. Sending DID rather than handle means installs\n * work for publishers whose handle the aggregator couldn't resolve at\n * view time (handle is best-effort per the lexicon).\n */\n\nimport { hostEnvFromVersions } from \"@emdash-cms/registry-client/env\";\nimport type { APIRoute } from \"astro\";\nimport { z } from \"zod\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, handleError, unwrapResult } from \"#api/error.js\";\nimport { handleRegistryInstall } from \"#api/index.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\n\nimport { VERSION } from \"../../../../../../version.js\";\n\nexport const prerender = false;\n\nconst installBodySchema = z.object({\n\t/**\n\t * Publisher DID. Required. Browser is expected to resolve\n\t * `(handle, slug) → did` against the aggregator before posting.\n\t */\n\tdid: z\n\t\t.string()\n\t\t.min(1)\n\t\t.max(2048)\n\t\t// Loose match -- atproto DID specs allow `did:plc:*` and\n\t\t// `did:web:*` plus future methods. Reject anything that\n\t\t// doesn't even start with `did:` rather than enumerating\n\t\t// methods here; downstream lexicon validation tightens.\n\t\t.regex(/^did:[a-z]+:/, \"Invalid DID\"),\n\t/** Package slug. */\n\tslug: z\n\t\t.string()\n\t\t.min(1)\n\t\t.max(64)\n\t\t// Mirrors the lexicon's slug grammar: ASCII letter followed by\n\t\t// letters / digits / `-` / `_`. Rejects anything that could\n\t\t// confuse the R2 prefix or the URL.\n\t\t.regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/, \"Invalid slug\"),\n\t/** Optional explicit version. Defaults to the aggregator's latest. */\n\tversion: z.string().min(1).max(64).optional(),\n\t/**\n\t * Capabilities the admin acknowledged in the consent dialog, lifted\n\t * from the release record's declaredAccess block at browse time.\n\t * Compared against the bundle's manifest to detect drift between the\n\t * dialog and the install POST.\n\t */\n\tacknowledgedDeclaredAccess: z.unknown().optional(),\n});\n\nexport const POST: APIRoute = async ({ request, locals }) => {\n\ttry {\n\t\tconst { emdash, user } = locals;\n\n\t\tif (!emdash?.db) {\n\t\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t\t}\n\n\t\tconst denied = requirePerm(user, \"plugins:manage\");\n\t\tif (denied) return denied;\n\n\t\tconst body = await parseBody(request, installBodySchema);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Block registry installs whose derived `pluginId` collides with\n\t\t// any build-time-reserved id: configured (in-process) plugins, and\n\t\t// sandboxed plugins declared in `config.sandboxed`. The runtime\n\t\t// caches sandboxed plugins by id; a registry install at the same\n\t\t// id would silently shadow or coexist with the build-time entry.\n\t\tconst reservedPluginIds = new Set<string>([\n\t\t\t...emdash.configuredPlugins.map((p: { id: string }) => p.id),\n\t\t\t...(emdash.config.sandboxed ?? []).map((p: { id: string }) => p.id),\n\t\t]);\n\n\t\tconst result = await handleRegistryInstall(\n\t\t\temdash.db,\n\t\t\temdash.storage,\n\t\t\temdash.getSandboxRunner(),\n\t\t\temdash.config.experimental?.registry,\n\t\t\t{\n\t\t\t\tdid: body.did,\n\t\t\t\tslug: body.slug,\n\t\t\t\tversion: body.version,\n\t\t\t\tacknowledgedDeclaredAccess: body.acknowledgedDeclaredAccess,\n\t\t\t},\n\t\t\t{\n\t\t\t\tconfiguredPluginIds: reservedPluginIds,\n\t\t\t\thostEnv: hostEnvFromVersions(VERSION, emdash.config.astroVersion),\n\t\t\t},\n\t\t);\n\n\t\tif (!result.success) return unwrapResult(result);\n\n\t\t// Sync runtime so the new plugin becomes active without a worker restart.\n\t\tawait emdash.syncRegistryPlugins();\n\n\t\treturn unwrapResult(result, 201);\n\t} catch (error) {\n\t\tconsole.error(\"[registry-install] Unhandled error:\", error);\n\t\treturn handleError(error, \"Failed to install plugin from registry\", \"INSTALL_FAILED\");\n\t}\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,YAAY;AAEzB,MAAM,oBAAoB,EAAE,OAAO;CAKlC,KAAK,EACH,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,KAAK,CAKT,MAAM,gBAAgB,cAAc;CAEtC,MAAM,EACJ,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,GAAG,CAIP,MAAM,4BAA4B,eAAe;CAEnD,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,UAAU;CAO7C,4BAA4B,EAAE,SAAS,CAAC,UAAU;CAClD,CAAC;AAEF,MAAa,OAAiB,OAAO,EAAE,SAAS,aAAa;AAC5D,KAAI;EACH,MAAM,EAAE,QAAQ,SAAS;AAEzB,MAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;EAGpE,MAAM,SAAS,YAAY,MAAM,iBAAiB;AAClD,MAAI,OAAQ,QAAO;EAEnB,MAAM,OAAO,MAAM,UAAU,SAAS,kBAAkB;AACxD,MAAI,aAAa,KAAK,CAAE,QAAO;EAO/B,MAAM,oBAAoB,IAAI,IAAY,CACzC,GAAG,OAAO,kBAAkB,KAAK,MAAsB,EAAE,GAAG,EAC5D,IAAI,OAAO,OAAO,aAAa,EAAE,EAAE,KAAK,MAAsB,EAAE,GAAG,CACnE,CAAC;EAEF,MAAM,SAAS,MAAM,sBACpB,OAAO,IACP,OAAO,SACP,OAAO,kBAAkB,EACzB,OAAO,OAAO,cAAc,UAC5B;GACC,KAAK,KAAK;GACV,MAAM,KAAK;GACX,SAAS,KAAK;GACd,4BAA4B,KAAK;GACjC,EACD;GACC,qBAAqB;GACrB,SAAS,oBAAoB,SAAS,OAAO,OAAO,aAAa;GACjE,CACD;AAED,MAAI,CAAC,OAAO,QAAS,QAAO,aAAa,OAAO;AAGhD,QAAM,OAAO,qBAAqB;AAElC,SAAO,aAAa,QAAQ,IAAI;UACxB,OAAO;AACf,UAAQ,MAAM,uCAAuC,MAAM;AAC3D,SAAO,YAAY,OAAO,0CAA0C,iBAAiB"}
1
+ {"version":3,"file":"install.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/plugins/registry/install.ts"],"sourcesContent":["/**\n * Registry plugin install endpoint\n *\n * POST /_emdash/api/admin/plugins/registry/install\n *\n * Installs a plugin from the experimental decentralized plugin registry\n * (see RFC 0001). The browser resolves `(handle, slug) → (did, slug)`\n * via the aggregator before posting and sends the publisher DID\n * directly; the server skips the resolvePackage round-trip and looks\n * up the package by DID. Sending DID rather than handle means installs\n * work for publishers whose handle the aggregator couldn't resolve at\n * view time (handle is best-effort per the lexicon).\n */\n\nimport { hostEnvFromVersions } from \"@emdash-cms/registry-client/env\";\nimport type { APIRoute } from \"astro\";\nimport { z } from \"zod\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, handleError, unwrapResult } from \"#api/error.js\";\nimport { handleRegistryInstall } from \"#api/index.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\n\nimport { VERSION } from \"../../../../../../version.js\";\n\nexport const prerender = false;\n\nconst installBodySchema = z.object({\n\t/**\n\t * Publisher DID. Required. Browser is expected to resolve\n\t * `(handle, slug) → did` against the aggregator before posting.\n\t */\n\tdid: z\n\t\t.string()\n\t\t.min(1)\n\t\t.max(2048)\n\t\t// Loose match -- atproto DID specs allow `did:plc:*` and\n\t\t// `did:web:*` plus future methods. Reject anything that\n\t\t// doesn't even start with `did:` rather than enumerating\n\t\t// methods here; downstream lexicon validation tightens.\n\t\t.regex(/^did:[a-z]+:/, \"Invalid DID\"),\n\t/** Package slug. */\n\tslug: z\n\t\t.string()\n\t\t.min(1)\n\t\t.max(64)\n\t\t// Mirrors the lexicon's slug grammar: ASCII letter followed by\n\t\t// letters / digits / `-` / `_`. Rejects anything that could\n\t\t// confuse the R2 prefix or the URL.\n\t\t.regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/, \"Invalid slug\"),\n\t/** Optional explicit version. Defaults to the aggregator's latest. */\n\tversion: z.string().min(1).max(64).optional(),\n\t/**\n\t * Capabilities the admin acknowledged in the consent dialog, lifted\n\t * from the release record's declaredAccess block at browse time.\n\t * Compared against the bundle's manifest to detect drift between the\n\t * dialog and the install POST.\n\t */\n\tacknowledgedDeclaredAccess: z.unknown().optional(),\n});\n\nexport const POST: APIRoute = async ({ request, locals }) => {\n\ttry {\n\t\tconst { emdash, user } = locals;\n\n\t\tif (!emdash?.db) {\n\t\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t\t}\n\n\t\tconst denied = requirePerm(user, \"plugins:manage\");\n\t\tif (denied) return denied;\n\n\t\tconst body = await parseBody(request, installBodySchema);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Block registry installs whose derived `pluginId` collides with\n\t\t// any build-time-reserved id: configured (in-process) plugins, and\n\t\t// sandboxed plugins declared in `config.sandboxed`. The runtime\n\t\t// caches sandboxed plugins by id; a registry install at the same\n\t\t// id would silently shadow or coexist with the build-time entry.\n\t\tconst reservedPluginIds = new Set<string>([\n\t\t\t...emdash.configuredPlugins.map((p: { id: string }) => p.id),\n\t\t\t...(emdash.config.sandboxed ?? []).map((p: { id: string }) => p.id),\n\t\t]);\n\n\t\tconst result = await handleRegistryInstall(\n\t\t\temdash.db,\n\t\t\temdash.storage,\n\t\t\temdash.getSandboxRunner(),\n\t\t\temdash.config.experimental?.registry,\n\t\t\t{\n\t\t\t\tdid: body.did,\n\t\t\t\tslug: body.slug,\n\t\t\t\tversion: body.version,\n\t\t\t\tacknowledgedDeclaredAccess: body.acknowledgedDeclaredAccess,\n\t\t\t},\n\t\t\t{\n\t\t\t\tconfiguredPluginIds: reservedPluginIds,\n\t\t\t\thostEnv: hostEnvFromVersions(VERSION, emdash.config.astroVersion),\n\t\t\t},\n\t\t);\n\n\t\tif (!result.success) return unwrapResult(result);\n\n\t\t// Sync runtime so the new plugin becomes active without a worker restart.\n\t\tawait emdash.syncRegistryPlugins();\n\n\t\treturn unwrapResult(result, 201);\n\t} catch (error) {\n\t\tconsole.error(\"[registry-install] Unhandled error:\", error);\n\t\treturn handleError(error, \"Failed to install plugin from registry\", \"INSTALL_FAILED\");\n\t}\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,YAAY;AAEzB,MAAM,oBAAoB,EAAE,OAAO;CAKlC,KAAK,EACH,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,KAAK,CAKT,MAAM,gBAAgB,cAAc;CAEtC,MAAM,EACJ,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,GAAG,CAIP,MAAM,4BAA4B,eAAe;CAEnD,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,UAAU;CAO7C,4BAA4B,EAAE,SAAS,CAAC,UAAU;CAClD,CAAC;AAEF,MAAa,OAAiB,OAAO,EAAE,SAAS,aAAa;AAC5D,KAAI;EACH,MAAM,EAAE,QAAQ,SAAS;AAEzB,MAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;EAGpE,MAAM,SAAS,YAAY,MAAM,iBAAiB;AAClD,MAAI,OAAQ,QAAO;EAEnB,MAAM,OAAO,MAAM,UAAU,SAAS,kBAAkB;AACxD,MAAI,aAAa,KAAK,CAAE,QAAO;EAO/B,MAAM,oBAAoB,IAAI,IAAY,CACzC,GAAG,OAAO,kBAAkB,KAAK,MAAsB,EAAE,GAAG,EAC5D,IAAI,OAAO,OAAO,aAAa,EAAE,EAAE,KAAK,MAAsB,EAAE,GAAG,CACnE,CAAC;EAEF,MAAM,SAAS,MAAM,sBACpB,OAAO,IACP,OAAO,SACP,OAAO,kBAAkB,EACzB,OAAO,OAAO,cAAc,UAC5B;GACC,KAAK,KAAK;GACV,MAAM,KAAK;GACX,SAAS,KAAK;GACd,4BAA4B,KAAK;GACjC,EACD;GACC,qBAAqB;GACrB,SAAS,oBAAoB,SAAS,OAAO,OAAO,aAAa;GACjE,CACD;AAED,MAAI,CAAC,OAAO,QAAS,QAAO,aAAa,OAAO;AAGhD,QAAM,OAAO,qBAAqB;AAElC,SAAO,aAAa,QAAQ,IAAI;UACxB,OAAO;AACf,UAAQ,MAAM,uCAAuC,MAAM;AAC3D,SAAO,YAAY,OAAO,0CAA0C,iBAAiB"}
@@ -9,32 +9,34 @@ import "../../../../../comment-sqQxNpN3.mjs";
9
9
  import "../../../../../options-BPCVnesz.mjs";
10
10
  import "../../../../../menus-DX4_E01q.mjs";
11
11
  import "../../../../../redirect-CRWIt8Zj.mjs";
12
- import "../../../../../request-cache-D32LpnmI.mjs";
13
- import "../../../../../byline-registry-CWP7I71B.mjs";
14
- import "../../../../../byline-DUx48sJp.mjs";
15
- import "../../../../../seo-B5e6y9Wk.mjs";
16
- import { a as handleRegistryUpdateCheck, m as handleMarketplaceUpdateCheck } from "../../../../../api-DStv36ik.mjs";
17
- import "../../../../../dashboard-2JgAMWxK.mjs";
18
- import "../../../../../fts-manager-1RgHmopc.mjs";
19
- import "../../../../../registry-brYh-rAT.mjs";
20
- import "../../../../../loader-ZN1ll-d-.mjs";
21
- import "../../../../../schema-C1E70ug_.mjs";
22
- import "../../../../../zod-generator-Djo_VHCt.mjs";
23
- import "../../../../../seo-D_LPkOtu.mjs";
24
- import "../../../../../sections-D_lVzwRZ.mjs";
25
- import "../../../../../settings-DfxiWY_s.mjs";
26
- import "../../../../../settings-Cv47v9u8.mjs";
27
- import "../../../../../resolve-BqYMVG0D.mjs";
28
- import "../../../../../taxonomies-BdAmbOwx.mjs";
29
- import "../../../../../taxonomies-BILwiyGk.mjs";
30
- import "../../../../../manifest-schema-BtwbL_vj.mjs";
31
- import "../../../../../types-CZI4E3qG.mjs";
32
- import "../../../../../ssrf-BsVGIE0Z.mjs";
33
- import { t as apiError } from "../../../../../error-RwM4dD35.mjs";
34
- import "../../../../../parse-CrGndy1A.mjs";
35
- import "../../../../../redirects-CCbCqCCd.mjs";
36
- import "../../../../../byline-fields-8TMtkBnH.mjs";
37
- import { n as requirePerm } from "../../../../../authorize-DsMSVSaY.mjs";
12
+ import "../../../../../init-lock-DlBHjf9-.mjs";
13
+ import "../../../../../request-cache-UwmBAiUK.mjs";
14
+ import "../../../../../byline-registry-DedidtqC.mjs";
15
+ import "../../../../../byline-V_Qp1Ziw.mjs";
16
+ import "../../../../../seo-DpNgGQjF.mjs";
17
+ import { a as handleRegistryUpdateCheck, m as handleMarketplaceUpdateCheck } from "../../../../../api-DxjIV2o8.mjs";
18
+ import "../../../../../dashboard-C-UYpps0.mjs";
19
+ import "../../../../../fts-manager-Cx5z8jdA.mjs";
20
+ import "../../../../../registry-diMzD1Wf.mjs";
21
+ import "../../../../../loader-BqWjcH3h.mjs";
22
+ import "../../../../../schema-BDOkd3OU.mjs";
23
+ import "../../../../../zod-generator-CarzgPAu.mjs";
24
+ import "../../../../../seo-CLhm-Fmb.mjs";
25
+ import "../../../../../sections-P0zuBlyz.mjs";
26
+ import "../../../../../settings-BjBsmVAo.mjs";
27
+ import "../../../../../settings-sO0Fif4p.mjs";
28
+ import "../../../../../resolve-B3NUUtVY.mjs";
29
+ import "../../../../../taxonomies-BBxYA38v.mjs";
30
+ import "../../../../../taxonomies-DuESHWKI.mjs";
31
+ import "../../../../../manifest-schema-DFPeqMAn.mjs";
32
+ import "../../../../../types-BoRm8-pp.mjs";
33
+ import "../../../../../ssrf-XO05Voq6.mjs";
34
+ import { t as apiError } from "../../../../../error-CNn_w7jf.mjs";
35
+ import "../../../../../parse-DzSrk1t8.mjs";
36
+ import "../../../../../redirects-6Zg2SoYo.mjs";
37
+ import "../../../../../byline-fields-B0NO1yUB.mjs";
38
+ import "../../../../../status-2gZklYuj.mjs";
39
+ import { n as requirePerm } from "../../../../../authorize-D5gfBVU5.mjs";
38
40
 
39
41
  //#region src/astro/routes/api/admin/plugins/updates.ts
40
42
  const prerender = false;
@@ -1 +1 @@
1
- {"version":3,"file":"updates.mjs","names":[],"sources":["../../../../../../src/astro/routes/api/admin/plugins/updates.ts"],"sourcesContent":["/**\n * Plugin update check endpoint\n *\n * GET /_emdash/api/admin/plugins/updates - Check for available updates\n * across every installed plugin source (marketplace + experimental\n * registry). Items are returned in a single flat list; admins correlate\n * items to plugins by `pluginId` and read `source` from the existing\n * `/_emdash/api/admin/plugins` list (the pluginId prefix is not a\n * reliable discriminator on its own).\n *\n * A failure in one source does NOT blank the other — a registry-side\n * aggregator outage still returns marketplace updates and vice versa.\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError } from \"#api/error.js\";\nimport { handleMarketplaceUpdateCheck, handleRegistryUpdateCheck } from \"#api/index.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\t// Run both checks in parallel. Catch each independently so one source's\n\t// failure doesn't blank the other. Both throws and structured `success:\n\t// false` returns are logged with the source name so a misconfigured\n\t// registry doesn't disappear silently from telemetry.\n\tconst [marketplace, registry] = await Promise.all([\n\t\thandleMarketplaceUpdateCheck(emdash.db, emdash.config.marketplace).catch((err) => {\n\t\t\tconsole.warn(\"[plugins/updates] marketplace check threw:\", err);\n\t\t\treturn null;\n\t\t}),\n\t\thandleRegistryUpdateCheck(emdash.db, emdash.config.experimental?.registry).catch((err) => {\n\t\t\tconsole.warn(\"[plugins/updates] registry check threw:\", err);\n\t\t\treturn null;\n\t\t}),\n\t]);\n\tif (marketplace && !marketplace.success) {\n\t\tconsole.warn(\n\t\t\t`[plugins/updates] marketplace check failed: ${marketplace.error.code} ${marketplace.error.message}`,\n\t\t);\n\t}\n\tif (registry && !registry.success) {\n\t\tconsole.warn(\n\t\t\t`[plugins/updates] registry check failed: ${registry.error.code} ${registry.error.message}`,\n\t\t);\n\t}\n\n\tconst items: unknown[] = [];\n\tif (marketplace?.success) items.push(...marketplace.data.items);\n\tif (registry?.success) items.push(...registry.data.items);\n\n\t// Match the rest of the admin API envelope (`{ data: ... }`) so the\n\t// admin client's `parseApiResponse` unwraps `body.data`.\n\treturn Response.json({ data: { items } });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,aAAa;CAClD,MAAM,EAAE,QAAQ,SAAS;AAEzB,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,SAAS,YAAY,MAAM,eAAe;AAChD,KAAI,OAAQ,QAAO;CAMnB,MAAM,CAAC,aAAa,YAAY,MAAM,QAAQ,IAAI,CACjD,6BAA6B,OAAO,IAAI,OAAO,OAAO,YAAY,CAAC,OAAO,QAAQ;AACjF,UAAQ,KAAK,8CAA8C,IAAI;AAC/D,SAAO;GACN,EACF,0BAA0B,OAAO,IAAI,OAAO,OAAO,cAAc,SAAS,CAAC,OAAO,QAAQ;AACzF,UAAQ,KAAK,2CAA2C,IAAI;AAC5D,SAAO;GACN,CACF,CAAC;AACF,KAAI,eAAe,CAAC,YAAY,QAC/B,SAAQ,KACP,+CAA+C,YAAY,MAAM,KAAK,GAAG,YAAY,MAAM,UAC3F;AAEF,KAAI,YAAY,CAAC,SAAS,QACzB,SAAQ,KACP,4CAA4C,SAAS,MAAM,KAAK,GAAG,SAAS,MAAM,UAClF;CAGF,MAAM,QAAmB,EAAE;AAC3B,KAAI,aAAa,QAAS,OAAM,KAAK,GAAG,YAAY,KAAK,MAAM;AAC/D,KAAI,UAAU,QAAS,OAAM,KAAK,GAAG,SAAS,KAAK,MAAM;AAIzD,QAAO,SAAS,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"updates.mjs","names":[],"sources":["../../../../../../src/astro/routes/api/admin/plugins/updates.ts"],"sourcesContent":["/**\n * Plugin update check endpoint\n *\n * GET /_emdash/api/admin/plugins/updates - Check for available updates\n * across every installed plugin source (marketplace + experimental\n * registry). Items are returned in a single flat list; admins correlate\n * items to plugins by `pluginId` and read `source` from the existing\n * `/_emdash/api/admin/plugins` list (the pluginId prefix is not a\n * reliable discriminator on its own).\n *\n * A failure in one source does NOT blank the other — a registry-side\n * aggregator outage still returns marketplace updates and vice versa.\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError } from \"#api/error.js\";\nimport { handleMarketplaceUpdateCheck, handleRegistryUpdateCheck } from \"#api/index.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\t// Run both checks in parallel. Catch each independently so one source's\n\t// failure doesn't blank the other. Both throws and structured `success:\n\t// false` returns are logged with the source name so a misconfigured\n\t// registry doesn't disappear silently from telemetry.\n\tconst [marketplace, registry] = await Promise.all([\n\t\thandleMarketplaceUpdateCheck(emdash.db, emdash.config.marketplace).catch((err) => {\n\t\t\tconsole.warn(\"[plugins/updates] marketplace check threw:\", err);\n\t\t\treturn null;\n\t\t}),\n\t\thandleRegistryUpdateCheck(emdash.db, emdash.config.experimental?.registry).catch((err) => {\n\t\t\tconsole.warn(\"[plugins/updates] registry check threw:\", err);\n\t\t\treturn null;\n\t\t}),\n\t]);\n\tif (marketplace && !marketplace.success) {\n\t\tconsole.warn(\n\t\t\t`[plugins/updates] marketplace check failed: ${marketplace.error.code} ${marketplace.error.message}`,\n\t\t);\n\t}\n\tif (registry && !registry.success) {\n\t\tconsole.warn(\n\t\t\t`[plugins/updates] registry check failed: ${registry.error.code} ${registry.error.message}`,\n\t\t);\n\t}\n\n\tconst items: unknown[] = [];\n\tif (marketplace?.success) items.push(...marketplace.data.items);\n\tif (registry?.success) items.push(...registry.data.items);\n\n\t// Match the rest of the admin API envelope (`{ data: ... }`) so the\n\t// admin client's `parseApiResponse` unwraps `body.data`.\n\treturn Response.json({ data: { items } });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,aAAa;CAClD,MAAM,EAAE,QAAQ,SAAS;AAEzB,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,SAAS,YAAY,MAAM,eAAe;AAChD,KAAI,OAAQ,QAAO;CAMnB,MAAM,CAAC,aAAa,YAAY,MAAM,QAAQ,IAAI,CACjD,6BAA6B,OAAO,IAAI,OAAO,OAAO,YAAY,CAAC,OAAO,QAAQ;AACjF,UAAQ,KAAK,8CAA8C,IAAI;AAC/D,SAAO;GACN,EACF,0BAA0B,OAAO,IAAI,OAAO,OAAO,cAAc,SAAS,CAAC,OAAO,QAAQ;AACzF,UAAQ,KAAK,2CAA2C,IAAI;AAC5D,SAAO;GACN,CACF,CAAC;AACF,KAAI,eAAe,CAAC,YAAY,QAC/B,SAAQ,KACP,+CAA+C,YAAY,MAAM,KAAK,GAAG,YAAY,MAAM,UAC3F;AAEF,KAAI,YAAY,CAAC,SAAS,QACzB,SAAQ,KACP,4CAA4C,SAAS,MAAM,KAAK,GAAG,SAAS,MAAM,UAClF;CAGF,MAAM,QAAmB,EAAE;AAC3B,KAAI,aAAa,QAAS,OAAM,KAAK,GAAG,YAAY,KAAK,MAAM;AAC/D,KAAI,UAAU,QAAS,OAAM,KAAK,GAAG,SAAS,KAAK,MAAM;AAIzD,QAAO,SAAS,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC"}
@@ -9,32 +9,34 @@ import "../../../../../../../comment-sqQxNpN3.mjs";
9
9
  import "../../../../../../../options-BPCVnesz.mjs";
10
10
  import "../../../../../../../menus-DX4_E01q.mjs";
11
11
  import "../../../../../../../redirect-CRWIt8Zj.mjs";
12
- import "../../../../../../../request-cache-D32LpnmI.mjs";
13
- import "../../../../../../../byline-registry-CWP7I71B.mjs";
14
- import "../../../../../../../byline-DUx48sJp.mjs";
15
- import "../../../../../../../seo-B5e6y9Wk.mjs";
16
- import { h as handleThemeGetDetail } from "../../../../../../../api-DStv36ik.mjs";
17
- import "../../../../../../../dashboard-2JgAMWxK.mjs";
18
- import "../../../../../../../fts-manager-1RgHmopc.mjs";
19
- import "../../../../../../../registry-brYh-rAT.mjs";
20
- import "../../../../../../../loader-ZN1ll-d-.mjs";
21
- import "../../../../../../../schema-C1E70ug_.mjs";
22
- import "../../../../../../../zod-generator-Djo_VHCt.mjs";
23
- import "../../../../../../../seo-D_LPkOtu.mjs";
24
- import "../../../../../../../sections-D_lVzwRZ.mjs";
25
- import "../../../../../../../settings-DfxiWY_s.mjs";
26
- import "../../../../../../../settings-Cv47v9u8.mjs";
27
- import "../../../../../../../resolve-BqYMVG0D.mjs";
28
- import "../../../../../../../taxonomies-BdAmbOwx.mjs";
29
- import "../../../../../../../taxonomies-BILwiyGk.mjs";
30
- import "../../../../../../../manifest-schema-BtwbL_vj.mjs";
31
- import "../../../../../../../types-CZI4E3qG.mjs";
32
- import "../../../../../../../ssrf-BsVGIE0Z.mjs";
33
- import { a as unwrapResult, t as apiError } from "../../../../../../../error-RwM4dD35.mjs";
34
- import "../../../../../../../parse-CrGndy1A.mjs";
35
- import "../../../../../../../redirects-CCbCqCCd.mjs";
36
- import "../../../../../../../byline-fields-8TMtkBnH.mjs";
37
- import { n as requirePerm } from "../../../../../../../authorize-DsMSVSaY.mjs";
12
+ import "../../../../../../../init-lock-DlBHjf9-.mjs";
13
+ import "../../../../../../../request-cache-UwmBAiUK.mjs";
14
+ import "../../../../../../../byline-registry-DedidtqC.mjs";
15
+ import "../../../../../../../byline-V_Qp1Ziw.mjs";
16
+ import "../../../../../../../seo-DpNgGQjF.mjs";
17
+ import { h as handleThemeGetDetail } from "../../../../../../../api-DxjIV2o8.mjs";
18
+ import "../../../../../../../dashboard-C-UYpps0.mjs";
19
+ import "../../../../../../../fts-manager-Cx5z8jdA.mjs";
20
+ import "../../../../../../../registry-diMzD1Wf.mjs";
21
+ import "../../../../../../../loader-BqWjcH3h.mjs";
22
+ import "../../../../../../../schema-BDOkd3OU.mjs";
23
+ import "../../../../../../../zod-generator-CarzgPAu.mjs";
24
+ import "../../../../../../../seo-CLhm-Fmb.mjs";
25
+ import "../../../../../../../sections-P0zuBlyz.mjs";
26
+ import "../../../../../../../settings-BjBsmVAo.mjs";
27
+ import "../../../../../../../settings-sO0Fif4p.mjs";
28
+ import "../../../../../../../resolve-B3NUUtVY.mjs";
29
+ import "../../../../../../../taxonomies-BBxYA38v.mjs";
30
+ import "../../../../../../../taxonomies-DuESHWKI.mjs";
31
+ import "../../../../../../../manifest-schema-DFPeqMAn.mjs";
32
+ import "../../../../../../../types-BoRm8-pp.mjs";
33
+ import "../../../../../../../ssrf-XO05Voq6.mjs";
34
+ import { a as unwrapResult, t as apiError } from "../../../../../../../error-CNn_w7jf.mjs";
35
+ import "../../../../../../../parse-DzSrk1t8.mjs";
36
+ import "../../../../../../../redirects-6Zg2SoYo.mjs";
37
+ import "../../../../../../../byline-fields-B0NO1yUB.mjs";
38
+ import "../../../../../../../status-2gZklYuj.mjs";
39
+ import { n as requirePerm } from "../../../../../../../authorize-D5gfBVU5.mjs";
38
40
 
39
41
  //#region src/astro/routes/api/admin/themes/marketplace/[id]/index.ts
40
42
  const prerender = false;
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../../src/astro/routes/api/admin/themes/marketplace/[id]/index.ts"],"sourcesContent":["/**\n * Theme marketplace detail proxy endpoint\n *\n * GET /_emdash/api/admin/themes/marketplace/:id - Get theme details\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, unwrapResult } from \"#api/error.js\";\nimport { handleThemeGetDetail } from \"#api/index.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ params, locals }) => {\n\tconst { emdash, user } = locals;\n\tconst { id } = params;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tif (!id) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Theme ID required\", 400);\n\t}\n\n\tconst result = await handleThemeGetDetail(emdash.config.marketplace, id);\n\n\treturn unwrapResult(result);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,QAAQ,aAAa;CAC1D,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,EAAE,OAAO;AAEf,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,SAAS,YAAY,MAAM,eAAe;AAChD,KAAI,OAAQ,QAAO;AAEnB,KAAI,CAAC,GACJ,QAAO,SAAS,mBAAmB,qBAAqB,IAAI;AAK7D,QAAO,aAFQ,MAAM,qBAAqB,OAAO,OAAO,aAAa,GAAG,CAE7C"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../../src/astro/routes/api/admin/themes/marketplace/[id]/index.ts"],"sourcesContent":["/**\n * Theme marketplace detail proxy endpoint\n *\n * GET /_emdash/api/admin/themes/marketplace/:id - Get theme details\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, unwrapResult } from \"#api/error.js\";\nimport { handleThemeGetDetail } from \"#api/index.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ params, locals }) => {\n\tconst { emdash, user } = locals;\n\tconst { id } = params;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tif (!id) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Theme ID required\", 400);\n\t}\n\n\tconst result = await handleThemeGetDetail(emdash.config.marketplace, id);\n\n\treturn unwrapResult(result);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,QAAQ,aAAa;CAC1D,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,EAAE,OAAO;AAEf,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,SAAS,YAAY,MAAM,eAAe;AAChD,KAAI,OAAQ,QAAO;AAEnB,KAAI,CAAC,GACJ,QAAO,SAAS,mBAAmB,qBAAqB,IAAI;AAK7D,QAAO,aAFQ,MAAM,qBAAqB,OAAO,OAAO,aAAa,GAAG,CAE7C"}
@@ -1,7 +1,7 @@
1
1
  import "../../../../../../../base64-CqR-7kqF.mjs";
2
2
  import "../../../../../../../types-BXSUSAjt.mjs";
3
- import { t as apiError } from "../../../../../../../error-RwM4dD35.mjs";
4
- import { n as requirePerm } from "../../../../../../../authorize-DsMSVSaY.mjs";
3
+ import { t as apiError } from "../../../../../../../error-CNn_w7jf.mjs";
4
+ import { n as requirePerm } from "../../../../../../../authorize-D5gfBVU5.mjs";
5
5
 
6
6
  //#region src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts
7
7
  const prerender = false;
@@ -9,32 +9,34 @@ import "../../../../../../comment-sqQxNpN3.mjs";
9
9
  import "../../../../../../options-BPCVnesz.mjs";
10
10
  import "../../../../../../menus-DX4_E01q.mjs";
11
11
  import "../../../../../../redirect-CRWIt8Zj.mjs";
12
- import "../../../../../../request-cache-D32LpnmI.mjs";
13
- import "../../../../../../byline-registry-CWP7I71B.mjs";
14
- import "../../../../../../byline-DUx48sJp.mjs";
15
- import "../../../../../../seo-B5e6y9Wk.mjs";
16
- import { g as handleThemeSearch } from "../../../../../../api-DStv36ik.mjs";
17
- import "../../../../../../dashboard-2JgAMWxK.mjs";
18
- import "../../../../../../fts-manager-1RgHmopc.mjs";
19
- import "../../../../../../registry-brYh-rAT.mjs";
20
- import "../../../../../../loader-ZN1ll-d-.mjs";
21
- import "../../../../../../schema-C1E70ug_.mjs";
22
- import "../../../../../../zod-generator-Djo_VHCt.mjs";
23
- import "../../../../../../seo-D_LPkOtu.mjs";
24
- import "../../../../../../sections-D_lVzwRZ.mjs";
25
- import "../../../../../../settings-DfxiWY_s.mjs";
26
- import "../../../../../../settings-Cv47v9u8.mjs";
27
- import "../../../../../../resolve-BqYMVG0D.mjs";
28
- import "../../../../../../taxonomies-BdAmbOwx.mjs";
29
- import "../../../../../../taxonomies-BILwiyGk.mjs";
30
- import "../../../../../../manifest-schema-BtwbL_vj.mjs";
31
- import "../../../../../../types-CZI4E3qG.mjs";
32
- import "../../../../../../ssrf-BsVGIE0Z.mjs";
33
- import { a as unwrapResult, t as apiError } from "../../../../../../error-RwM4dD35.mjs";
34
- import "../../../../../../parse-CrGndy1A.mjs";
35
- import "../../../../../../redirects-CCbCqCCd.mjs";
36
- import "../../../../../../byline-fields-8TMtkBnH.mjs";
37
- import { n as requirePerm } from "../../../../../../authorize-DsMSVSaY.mjs";
12
+ import "../../../../../../init-lock-DlBHjf9-.mjs";
13
+ import "../../../../../../request-cache-UwmBAiUK.mjs";
14
+ import "../../../../../../byline-registry-DedidtqC.mjs";
15
+ import "../../../../../../byline-V_Qp1Ziw.mjs";
16
+ import "../../../../../../seo-DpNgGQjF.mjs";
17
+ import { g as handleThemeSearch } from "../../../../../../api-DxjIV2o8.mjs";
18
+ import "../../../../../../dashboard-C-UYpps0.mjs";
19
+ import "../../../../../../fts-manager-Cx5z8jdA.mjs";
20
+ import "../../../../../../registry-diMzD1Wf.mjs";
21
+ import "../../../../../../loader-BqWjcH3h.mjs";
22
+ import "../../../../../../schema-BDOkd3OU.mjs";
23
+ import "../../../../../../zod-generator-CarzgPAu.mjs";
24
+ import "../../../../../../seo-CLhm-Fmb.mjs";
25
+ import "../../../../../../sections-P0zuBlyz.mjs";
26
+ import "../../../../../../settings-BjBsmVAo.mjs";
27
+ import "../../../../../../settings-sO0Fif4p.mjs";
28
+ import "../../../../../../resolve-B3NUUtVY.mjs";
29
+ import "../../../../../../taxonomies-BBxYA38v.mjs";
30
+ import "../../../../../../taxonomies-DuESHWKI.mjs";
31
+ import "../../../../../../manifest-schema-DFPeqMAn.mjs";
32
+ import "../../../../../../types-BoRm8-pp.mjs";
33
+ import "../../../../../../ssrf-XO05Voq6.mjs";
34
+ import { a as unwrapResult, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
35
+ import "../../../../../../parse-DzSrk1t8.mjs";
36
+ import "../../../../../../redirects-6Zg2SoYo.mjs";
37
+ import "../../../../../../byline-fields-B0NO1yUB.mjs";
38
+ import "../../../../../../status-2gZklYuj.mjs";
39
+ import { n as requirePerm } from "../../../../../../authorize-D5gfBVU5.mjs";
38
40
 
39
41
  //#region src/astro/routes/api/admin/themes/marketplace/index.ts
40
42
  const prerender = false;
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/themes/marketplace/index.ts"],"sourcesContent":["/**\n * Theme marketplace search proxy endpoint\n *\n * GET /_emdash/api/admin/themes/marketplace - Search marketplace themes\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, unwrapResult } from \"#api/error.js\";\nimport { handleThemeSearch } from \"#api/index.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ url, locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tconst query = url.searchParams.get(\"q\") ?? undefined;\n\tconst keyword = url.searchParams.get(\"keyword\") ?? undefined;\n\tconst sortParam = url.searchParams.get(\"sort\");\n\tconst validSorts = new Set([\"name\", \"created\", \"updated\"]);\n\tlet sort: \"name\" | \"created\" | \"updated\" | undefined;\n\tif (sortParam && validSorts.has(sortParam)) {\n\t\tsort = sortParam as \"name\" | \"created\" | \"updated\"; // eslint-disable-line typescript/no-unsafe-type-assertion -- validated by Set.has()\n\t}\n\tconst cursor = url.searchParams.get(\"cursor\") ?? undefined;\n\tconst limitParam = url.searchParams.get(\"limit\");\n\tconst limit = limitParam ? Math.min(Math.max(1, parseInt(limitParam, 10) || 50), 100) : undefined;\n\n\tconst result = await handleThemeSearch(emdash.config.marketplace, query, {\n\t\tkeyword,\n\t\tsort,\n\t\tcursor,\n\t\tlimit,\n\t});\n\n\treturn unwrapResult(result);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,KAAK,aAAa;CACvD,MAAM,EAAE,QAAQ,SAAS;AAEzB,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,SAAS,YAAY,MAAM,eAAe;AAChD,KAAI,OAAQ,QAAO;CAEnB,MAAM,QAAQ,IAAI,aAAa,IAAI,IAAI,IAAI;CAC3C,MAAM,UAAU,IAAI,aAAa,IAAI,UAAU,IAAI;CACnD,MAAM,YAAY,IAAI,aAAa,IAAI,OAAO;CAC9C,MAAM,aAAa,IAAI,IAAI;EAAC;EAAQ;EAAW;EAAU,CAAC;CAC1D,IAAI;AACJ,KAAI,aAAa,WAAW,IAAI,UAAU,CACzC,QAAO;CAER,MAAM,SAAS,IAAI,aAAa,IAAI,SAAS,IAAI;CACjD,MAAM,aAAa,IAAI,aAAa,IAAI,QAAQ;CAChD,MAAM,QAAQ,aAAa,KAAK,IAAI,KAAK,IAAI,GAAG,SAAS,YAAY,GAAG,IAAI,GAAG,EAAE,IAAI,GAAG;AASxF,QAAO,aAPQ,MAAM,kBAAkB,OAAO,OAAO,aAAa,OAAO;EACxE;EACA;EACA;EACA;EACA,CAAC,CAEyB"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/themes/marketplace/index.ts"],"sourcesContent":["/**\n * Theme marketplace search proxy endpoint\n *\n * GET /_emdash/api/admin/themes/marketplace - Search marketplace themes\n */\n\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, unwrapResult } from \"#api/error.js\";\nimport { handleThemeSearch } from \"#api/index.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ url, locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tconst query = url.searchParams.get(\"q\") ?? undefined;\n\tconst keyword = url.searchParams.get(\"keyword\") ?? undefined;\n\tconst sortParam = url.searchParams.get(\"sort\");\n\tconst validSorts = new Set([\"name\", \"created\", \"updated\"]);\n\tlet sort: \"name\" | \"created\" | \"updated\" | undefined;\n\tif (sortParam && validSorts.has(sortParam)) {\n\t\tsort = sortParam as \"name\" | \"created\" | \"updated\"; // eslint-disable-line typescript/no-unsafe-type-assertion -- validated by Set.has()\n\t}\n\tconst cursor = url.searchParams.get(\"cursor\") ?? undefined;\n\tconst limitParam = url.searchParams.get(\"limit\");\n\tconst limit = limitParam ? Math.min(Math.max(1, parseInt(limitParam, 10) || 50), 100) : undefined;\n\n\tconst result = await handleThemeSearch(emdash.config.marketplace, query, {\n\t\tkeyword,\n\t\tsort,\n\t\tcursor,\n\t\tlimit,\n\t});\n\n\treturn unwrapResult(result);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,KAAK,aAAa;CACvD,MAAM,EAAE,QAAQ,SAAS;AAEzB,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,SAAS,YAAY,MAAM,eAAe;AAChD,KAAI,OAAQ,QAAO;CAEnB,MAAM,QAAQ,IAAI,aAAa,IAAI,IAAI,IAAI;CAC3C,MAAM,UAAU,IAAI,aAAa,IAAI,UAAU,IAAI;CACnD,MAAM,YAAY,IAAI,aAAa,IAAI,OAAO;CAC9C,MAAM,aAAa,IAAI,IAAI;EAAC;EAAQ;EAAW;EAAU,CAAC;CAC1D,IAAI;AACJ,KAAI,aAAa,WAAW,IAAI,UAAU,CACzC,QAAO;CAER,MAAM,SAAS,IAAI,aAAa,IAAI,SAAS,IAAI;CACjD,MAAM,aAAa,IAAI,aAAa,IAAI,QAAQ;CAChD,MAAM,QAAQ,aAAa,KAAK,IAAI,KAAK,IAAI,GAAG,SAAS,YAAY,GAAG,IAAI,GAAG,EAAE,IAAI,GAAG;AASxF,QAAO,aAPQ,MAAM,kBAAkB,OAAO,OAAO,aAAa,OAAO;EACxE;EACA;EACA;EACA;EACA,CAAC,CAEyB"}
@@ -1,7 +1,7 @@
1
1
  import "../../../../../../base64-CqR-7kqF.mjs";
2
2
  import "../../../../../../types-BXSUSAjt.mjs";
3
3
  import { t as withTransaction } from "../../../../../../transaction-x2tJQ-A1.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-RwM4dD35.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
5
5
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
6
6
  import { Role } from "@emdash-cms/auth";
7
7
 
@@ -1,6 +1,6 @@
1
1
  import "../../../../../../base64-CqR-7kqF.mjs";
2
2
  import "../../../../../../types-BXSUSAjt.mjs";
3
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-RwM4dD35.mjs";
3
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
4
4
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
5
5
  import { Role } from "@emdash-cms/auth";
6
6
 
@@ -1,10 +1,11 @@
1
1
  import "../../../../../../base64-CqR-7kqF.mjs";
2
2
  import "../../../../../../types-BXSUSAjt.mjs";
3
3
  import { t as withTransaction } from "../../../../../../transaction-x2tJQ-A1.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-RwM4dD35.mjs";
5
- import { n as parseBody, t as isParseError } from "../../../../../../parse-CrGndy1A.mjs";
6
- import { E as userUpdateBody } from "../../../../../../redirects-CCbCqCCd.mjs";
7
- import "../../../../../../byline-fields-8TMtkBnH.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
5
+ import { n as parseBody, t as isParseError } from "../../../../../../parse-DzSrk1t8.mjs";
6
+ import { E as userUpdateBody } from "../../../../../../redirects-6Zg2SoYo.mjs";
7
+ import "../../../../../../byline-fields-B0NO1yUB.mjs";
8
+ import "../../../../../../status-2gZklYuj.mjs";
8
9
  import "../../../../../../api/schemas/index.mjs";
9
10
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
10
11
  import { Role } from "@emdash-cms/auth";
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/users/[id]/index.ts"],"sourcesContent":["/**\n * User management detail endpoint\n *\n * GET /_emdash/api/admin/users/:id - Get user details\n * PUT /_emdash/api/admin/users/:id - Update user\n */\n\nimport { Role } from \"@emdash-cms/auth\";\nimport { createKyselyAdapter } from \"@emdash-cms/auth/adapters/kysely\";\nimport type { APIRoute } from \"astro\";\n\nimport { apiError, apiSuccess, handleError } from \"#api/error.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { userUpdateBody } from \"#api/schemas.js\";\nimport { withTransaction } from \"#db/transaction.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ params, locals }) => {\n\tconst { emdash, user: currentUser } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tif (!currentUser || currentUser.role < Role.ADMIN) {\n\t\treturn apiError(\"FORBIDDEN\", \"Admin privileges required\", 403);\n\t}\n\n\tconst adapter = createKyselyAdapter(emdash.db);\n\n\tconst { id } = params;\n\n\tif (!id) {\n\t\treturn apiError(\"MISSING_PARAM\", \"User ID required\", 400);\n\t}\n\n\ttry {\n\t\tconst result = await adapter.getUserWithDetails(id);\n\n\t\tif (!result) {\n\t\t\treturn apiError(\"NOT_FOUND\", \"User not found\", 404);\n\t\t}\n\n\t\t// Transform for JSON serialization\n\t\tconst item = {\n\t\t\tid: result.user.id,\n\t\t\temail: result.user.email,\n\t\t\tname: result.user.name,\n\t\t\tavatarUrl: result.user.avatarUrl,\n\t\t\trole: result.user.role,\n\t\t\temailVerified: result.user.emailVerified,\n\t\t\tdisabled: result.user.disabled,\n\t\t\tcreatedAt: result.user.createdAt.toISOString(),\n\t\t\tupdatedAt: result.user.updatedAt.toISOString(),\n\t\t\tlastLogin: result.lastLogin?.toISOString() ?? null,\n\t\t\tcredentials: result.credentials.map((c) => ({\n\t\t\t\tid: c.id,\n\t\t\t\tname: c.name,\n\t\t\t\tdeviceType: c.deviceType,\n\t\t\t\tcreatedAt: c.createdAt.toISOString(),\n\t\t\t\tlastUsedAt: c.lastUsedAt.toISOString(),\n\t\t\t})),\n\t\t\toauthAccounts: result.oauthAccounts.map((a) => ({\n\t\t\t\tprovider: a.provider,\n\t\t\t\tcreatedAt: a.createdAt.toISOString(),\n\t\t\t})),\n\t\t};\n\n\t\treturn apiSuccess({ item });\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to get user details\", \"USER_DETAIL_ERROR\");\n\t}\n};\n\nexport const PUT: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash, user: currentUser } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tif (!currentUser || currentUser.role < Role.ADMIN) {\n\t\treturn apiError(\"FORBIDDEN\", \"Admin privileges required\", 403);\n\t}\n\n\tconst adapter = createKyselyAdapter(emdash.db);\n\n\tconst { id } = params;\n\n\tif (!id) {\n\t\treturn apiError(\"MISSING_PARAM\", \"User ID required\", 400);\n\t}\n\n\ttry {\n\t\t// Get target user\n\t\tconst targetUser = await adapter.getUserById(id);\n\t\tif (!targetUser) {\n\t\t\treturn apiError(\"NOT_FOUND\", \"User not found\", 404);\n\t\t}\n\n\t\tconst body = await parseBody(request, userUpdateBody);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Role is already validated as RoleLevel by Zod schema\n\t\tconst role = body.role;\n\n\t\t// Prevent editing own role (security: prevents self-demotion/lockout)\n\t\tif (role !== undefined && id === currentUser.id) {\n\t\t\treturn apiError(\"SELF_ROLE_CHANGE\", \"Cannot change your own role\", 400);\n\t\t}\n\n\t\t// Check email uniqueness if changing email\n\t\tif (body.email && body.email !== targetUser.email) {\n\t\t\tconst existing = await adapter.getUserByEmail(body.email);\n\t\t\tif (existing) {\n\t\t\t\treturn apiError(\"EMAIL_IN_USE\", \"Email already in use\", 409);\n\t\t\t}\n\t\t}\n\n\t\t// Wrap admin demotion guard + update in a transaction to prevent\n\t\t// two concurrent demotions from both passing the count check.\n\t\tconst isDemotingAdmin =\n\t\t\trole !== undefined && role < Role.ADMIN && targetUser.role === Role.ADMIN;\n\n\t\tconst lastAdminBlocked = await withTransaction(emdash.db, async (trx) => {\n\t\t\tconst trxAdapter = createKyselyAdapter(trx);\n\t\t\tif (isDemotingAdmin) {\n\t\t\t\tconst adminCount = await trxAdapter.countAdmins();\n\t\t\t\tif (adminCount <= 1) return true;\n\t\t\t}\n\t\t\tawait trxAdapter.updateUser(id, {\n\t\t\t\tname: body.name,\n\t\t\t\temail: body.email,\n\t\t\t\trole,\n\t\t\t});\n\t\t\treturn false;\n\t\t});\n\n\t\tif (lastAdminBlocked) {\n\t\t\treturn apiError(\n\t\t\t\t\"LAST_ADMIN\",\n\t\t\t\t\"Cannot demote the last admin. Promote another user first.\",\n\t\t\t\t400,\n\t\t\t);\n\t\t}\n\n\t\t// Fetch updated user\n\t\tconst updated = await adapter.getUserById(id);\n\n\t\treturn apiSuccess({\n\t\t\titem: {\n\t\t\t\tid: updated!.id,\n\t\t\t\temail: updated!.email,\n\t\t\t\tname: updated!.name,\n\t\t\t\tavatarUrl: updated!.avatarUrl,\n\t\t\t\trole: updated!.role,\n\t\t\t\temailVerified: updated!.emailVerified,\n\t\t\t\tdisabled: updated!.disabled,\n\t\t\t\tcreatedAt: updated!.createdAt.toISOString(),\n\t\t\t\tupdatedAt: updated!.updatedAt.toISOString(),\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to update user\", \"USER_UPDATE_ERROR\");\n\t}\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/users/[id]/index.ts"],"sourcesContent":["/**\n * User management detail endpoint\n *\n * GET /_emdash/api/admin/users/:id - Get user details\n * PUT /_emdash/api/admin/users/:id - Update user\n */\n\nimport { Role } from \"@emdash-cms/auth\";\nimport { createKyselyAdapter } from \"@emdash-cms/auth/adapters/kysely\";\nimport type { APIRoute } from \"astro\";\n\nimport { apiError, apiSuccess, handleError } from \"#api/error.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { userUpdateBody } from \"#api/schemas.js\";\nimport { withTransaction } from \"#db/transaction.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ params, locals }) => {\n\tconst { emdash, user: currentUser } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tif (!currentUser || currentUser.role < Role.ADMIN) {\n\t\treturn apiError(\"FORBIDDEN\", \"Admin privileges required\", 403);\n\t}\n\n\tconst adapter = createKyselyAdapter(emdash.db);\n\n\tconst { id } = params;\n\n\tif (!id) {\n\t\treturn apiError(\"MISSING_PARAM\", \"User ID required\", 400);\n\t}\n\n\ttry {\n\t\tconst result = await adapter.getUserWithDetails(id);\n\n\t\tif (!result) {\n\t\t\treturn apiError(\"NOT_FOUND\", \"User not found\", 404);\n\t\t}\n\n\t\t// Transform for JSON serialization\n\t\tconst item = {\n\t\t\tid: result.user.id,\n\t\t\temail: result.user.email,\n\t\t\tname: result.user.name,\n\t\t\tavatarUrl: result.user.avatarUrl,\n\t\t\trole: result.user.role,\n\t\t\temailVerified: result.user.emailVerified,\n\t\t\tdisabled: result.user.disabled,\n\t\t\tcreatedAt: result.user.createdAt.toISOString(),\n\t\t\tupdatedAt: result.user.updatedAt.toISOString(),\n\t\t\tlastLogin: result.lastLogin?.toISOString() ?? null,\n\t\t\tcredentials: result.credentials.map((c) => ({\n\t\t\t\tid: c.id,\n\t\t\t\tname: c.name,\n\t\t\t\tdeviceType: c.deviceType,\n\t\t\t\tcreatedAt: c.createdAt.toISOString(),\n\t\t\t\tlastUsedAt: c.lastUsedAt.toISOString(),\n\t\t\t})),\n\t\t\toauthAccounts: result.oauthAccounts.map((a) => ({\n\t\t\t\tprovider: a.provider,\n\t\t\t\tcreatedAt: a.createdAt.toISOString(),\n\t\t\t})),\n\t\t};\n\n\t\treturn apiSuccess({ item });\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to get user details\", \"USER_DETAIL_ERROR\");\n\t}\n};\n\nexport const PUT: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash, user: currentUser } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tif (!currentUser || currentUser.role < Role.ADMIN) {\n\t\treturn apiError(\"FORBIDDEN\", \"Admin privileges required\", 403);\n\t}\n\n\tconst adapter = createKyselyAdapter(emdash.db);\n\n\tconst { id } = params;\n\n\tif (!id) {\n\t\treturn apiError(\"MISSING_PARAM\", \"User ID required\", 400);\n\t}\n\n\ttry {\n\t\t// Get target user\n\t\tconst targetUser = await adapter.getUserById(id);\n\t\tif (!targetUser) {\n\t\t\treturn apiError(\"NOT_FOUND\", \"User not found\", 404);\n\t\t}\n\n\t\tconst body = await parseBody(request, userUpdateBody);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Role is already validated as RoleLevel by Zod schema\n\t\tconst role = body.role;\n\n\t\t// Prevent editing own role (security: prevents self-demotion/lockout)\n\t\tif (role !== undefined && id === currentUser.id) {\n\t\t\treturn apiError(\"SELF_ROLE_CHANGE\", \"Cannot change your own role\", 400);\n\t\t}\n\n\t\t// Check email uniqueness if changing email\n\t\tif (body.email && body.email !== targetUser.email) {\n\t\t\tconst existing = await adapter.getUserByEmail(body.email);\n\t\t\tif (existing) {\n\t\t\t\treturn apiError(\"EMAIL_IN_USE\", \"Email already in use\", 409);\n\t\t\t}\n\t\t}\n\n\t\t// Wrap admin demotion guard + update in a transaction to prevent\n\t\t// two concurrent demotions from both passing the count check.\n\t\tconst isDemotingAdmin =\n\t\t\trole !== undefined && role < Role.ADMIN && targetUser.role === Role.ADMIN;\n\n\t\tconst lastAdminBlocked = await withTransaction(emdash.db, async (trx) => {\n\t\t\tconst trxAdapter = createKyselyAdapter(trx);\n\t\t\tif (isDemotingAdmin) {\n\t\t\t\tconst adminCount = await trxAdapter.countAdmins();\n\t\t\t\tif (adminCount <= 1) return true;\n\t\t\t}\n\t\t\tawait trxAdapter.updateUser(id, {\n\t\t\t\tname: body.name,\n\t\t\t\temail: body.email,\n\t\t\t\trole,\n\t\t\t});\n\t\t\treturn false;\n\t\t});\n\n\t\tif (lastAdminBlocked) {\n\t\t\treturn apiError(\n\t\t\t\t\"LAST_ADMIN\",\n\t\t\t\t\"Cannot demote the last admin. Promote another user first.\",\n\t\t\t\t400,\n\t\t\t);\n\t\t}\n\n\t\t// Fetch updated user\n\t\tconst updated = await adapter.getUserById(id);\n\n\t\treturn apiSuccess({\n\t\t\titem: {\n\t\t\t\tid: updated!.id,\n\t\t\t\temail: updated!.email,\n\t\t\t\tname: updated!.name,\n\t\t\t\tavatarUrl: updated!.avatarUrl,\n\t\t\t\trole: updated!.role,\n\t\t\t\temailVerified: updated!.emailVerified,\n\t\t\t\tdisabled: updated!.disabled,\n\t\t\t\tcreatedAt: updated!.createdAt.toISOString(),\n\t\t\t\tupdatedAt: updated!.updatedAt.toISOString(),\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to update user\", \"USER_UPDATE_ERROR\");\n\t}\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAgBA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,QAAQ,aAAa;CAC1D,MAAM,EAAE,QAAQ,MAAM,gBAAgB;AAEtC,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;AAGpE,KAAI,CAAC,eAAe,YAAY,OAAO,KAAK,MAC3C,QAAO,SAAS,aAAa,6BAA6B,IAAI;CAG/D,MAAM,UAAU,oBAAoB,OAAO,GAAG;CAE9C,MAAM,EAAE,OAAO;AAEf,KAAI,CAAC,GACJ,QAAO,SAAS,iBAAiB,oBAAoB,IAAI;AAG1D,KAAI;EACH,MAAM,SAAS,MAAM,QAAQ,mBAAmB,GAAG;AAEnD,MAAI,CAAC,OACJ,QAAO,SAAS,aAAa,kBAAkB,IAAI;AA4BpD,SAAO,WAAW,EAAE,MAxBP;GACZ,IAAI,OAAO,KAAK;GAChB,OAAO,OAAO,KAAK;GACnB,MAAM,OAAO,KAAK;GAClB,WAAW,OAAO,KAAK;GACvB,MAAM,OAAO,KAAK;GAClB,eAAe,OAAO,KAAK;GAC3B,UAAU,OAAO,KAAK;GACtB,WAAW,OAAO,KAAK,UAAU,aAAa;GAC9C,WAAW,OAAO,KAAK,UAAU,aAAa;GAC9C,WAAW,OAAO,WAAW,aAAa,IAAI;GAC9C,aAAa,OAAO,YAAY,KAAK,OAAO;IAC3C,IAAI,EAAE;IACN,MAAM,EAAE;IACR,YAAY,EAAE;IACd,WAAW,EAAE,UAAU,aAAa;IACpC,YAAY,EAAE,WAAW,aAAa;IACtC,EAAE;GACH,eAAe,OAAO,cAAc,KAAK,OAAO;IAC/C,UAAU,EAAE;IACZ,WAAW,EAAE,UAAU,aAAa;IACpC,EAAE;GACH,EAEyB,CAAC;UACnB,OAAO;AACf,SAAO,YAAY,OAAO,8BAA8B,oBAAoB;;;AAI9E,MAAa,MAAgB,OAAO,EAAE,QAAQ,SAAS,aAAa;CACnE,MAAM,EAAE,QAAQ,MAAM,gBAAgB;AAEtC,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;AAGpE,KAAI,CAAC,eAAe,YAAY,OAAO,KAAK,MAC3C,QAAO,SAAS,aAAa,6BAA6B,IAAI;CAG/D,MAAM,UAAU,oBAAoB,OAAO,GAAG;CAE9C,MAAM,EAAE,OAAO;AAEf,KAAI,CAAC,GACJ,QAAO,SAAS,iBAAiB,oBAAoB,IAAI;AAG1D,KAAI;EAEH,MAAM,aAAa,MAAM,QAAQ,YAAY,GAAG;AAChD,MAAI,CAAC,WACJ,QAAO,SAAS,aAAa,kBAAkB,IAAI;EAGpD,MAAM,OAAO,MAAM,UAAU,SAAS,eAAe;AACrD,MAAI,aAAa,KAAK,CAAE,QAAO;EAG/B,MAAM,OAAO,KAAK;AAGlB,MAAI,SAAS,UAAa,OAAO,YAAY,GAC5C,QAAO,SAAS,oBAAoB,+BAA+B,IAAI;AAIxE,MAAI,KAAK,SAAS,KAAK,UAAU,WAAW,OAE3C;OADiB,MAAM,QAAQ,eAAe,KAAK,MAAM,CAExD,QAAO,SAAS,gBAAgB,wBAAwB,IAAI;;EAM9D,MAAM,kBACL,SAAS,UAAa,OAAO,KAAK,SAAS,WAAW,SAAS,KAAK;AAgBrE,MAdyB,MAAM,gBAAgB,OAAO,IAAI,OAAO,QAAQ;GACxE,MAAM,aAAa,oBAAoB,IAAI;AAC3C,OAAI,iBAEH;QADmB,MAAM,WAAW,aAAa,IAC/B,EAAG,QAAO;;AAE7B,SAAM,WAAW,WAAW,IAAI;IAC/B,MAAM,KAAK;IACX,OAAO,KAAK;IACZ;IACA,CAAC;AACF,UAAO;IACN,CAGD,QAAO,SACN,cACA,6DACA,IACA;EAIF,MAAM,UAAU,MAAM,QAAQ,YAAY,GAAG;AAE7C,SAAO,WAAW,EACjB,MAAM;GACL,IAAI,QAAS;GACb,OAAO,QAAS;GAChB,MAAM,QAAS;GACf,WAAW,QAAS;GACpB,MAAM,QAAS;GACf,eAAe,QAAS;GACxB,UAAU,QAAS;GACnB,WAAW,QAAS,UAAU,aAAa;GAC3C,WAAW,QAAS,UAAU,aAAa;GAC3C,EACD,CAAC;UACM,OAAO;AACf,SAAO,YAAY,OAAO,yBAAyB,oBAAoB"}
@@ -1,8 +1,8 @@
1
1
  import "../../../../../../base64-CqR-7kqF.mjs";
2
2
  import "../../../../../../types-BXSUSAjt.mjs";
3
3
  import { t as OptionsRepository } from "../../../../../../options-BPCVnesz.mjs";
4
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-RwM4dD35.mjs";
5
- import { t as getSiteBaseUrl } from "../../../../../../site-url-CnHlmAs9.mjs";
4
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../../error-CNn_w7jf.mjs";
5
+ import { t as getSiteBaseUrl } from "../../../../../../site-url-vtsuOvSD.mjs";
6
6
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
7
7
  import { Role, sendMagicLink } from "@emdash-cms/auth";
8
8
 
@@ -1,9 +1,10 @@
1
1
  import "../../../../../base64-CqR-7kqF.mjs";
2
2
  import "../../../../../types-BXSUSAjt.mjs";
3
- import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-RwM4dD35.mjs";
4
- import { i as parseQuery, t as isParseError } from "../../../../../parse-CrGndy1A.mjs";
5
- import { D as usersListQuery } from "../../../../../redirects-CCbCqCCd.mjs";
6
- import "../../../../../byline-fields-8TMtkBnH.mjs";
3
+ import { n as apiSuccess, r as handleError, t as apiError } from "../../../../../error-CNn_w7jf.mjs";
4
+ import { i as parseQuery, t as isParseError } from "../../../../../parse-DzSrk1t8.mjs";
5
+ import { D as usersListQuery } from "../../../../../redirects-6Zg2SoYo.mjs";
6
+ import "../../../../../byline-fields-B0NO1yUB.mjs";
7
+ import "../../../../../status-2gZklYuj.mjs";
7
8
  import "../../../../../api/schemas/index.mjs";
8
9
  import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
9
10
  import { Role } from "@emdash-cms/auth";