emdash 1.0.1 → 1.2.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 (1439) hide show
  1. package/dist/action-token-BdWad2YG.mjs +26 -0
  2. package/dist/action-token-BdWad2YG.mjs.map +1 -0
  3. package/dist/activation-xomsCMJg.mjs +387 -0
  4. package/dist/activation-xomsCMJg.mjs.map +1 -0
  5. package/dist/adapters-B4-nbElt.d.mts +173 -0
  6. package/dist/adapters-B4-nbElt.d.mts.map +1 -0
  7. package/dist/allowed-origins-CLpHGGlc.mjs +116 -0
  8. package/dist/allowed-origins-CLpHGGlc.mjs.map +1 -0
  9. package/dist/api/route-utils.d.mts +4 -4
  10. package/dist/api/route-utils.d.mts.map +1 -1
  11. package/dist/api/route-utils.mjs +49 -48
  12. package/dist/api/route-utils.mjs.map +1 -1
  13. package/dist/api/schemas/index.d.mts +2 -2
  14. package/dist/api/schemas/index.mjs +10 -10
  15. package/dist/api-DBw_IWoi.mjs +5024 -0
  16. package/dist/api-DBw_IWoi.mjs.map +1 -0
  17. package/dist/api-tokens-B0ZipcZ-.mjs +173 -0
  18. package/dist/api-tokens-B0ZipcZ-.mjs.map +1 -0
  19. package/dist/apply-Cx48saFC.mjs +1680 -0
  20. package/dist/apply-Cx48saFC.mjs.map +1 -0
  21. package/dist/approvals-BXgtXA2s.mjs +460 -0
  22. package/dist/approvals-BXgtXA2s.mjs.map +1 -0
  23. package/dist/artifact-fetch-DsRczRGG.mjs +659 -0
  24. package/dist/artifact-fetch-DsRczRGG.mjs.map +1 -0
  25. package/dist/artifacts-D-O-qj9C.mjs +307 -0
  26. package/dist/artifacts-D-O-qj9C.mjs.map +1 -0
  27. package/dist/astro/image-endpoint.d.mts.map +1 -1
  28. package/dist/astro/image-endpoint.mjs +26 -6
  29. package/dist/astro/image-endpoint.mjs.map +1 -1
  30. package/dist/astro/index.d.mts +14 -14
  31. package/dist/astro/index.d.mts.map +1 -1
  32. package/dist/astro/index.mjs +253 -17
  33. package/dist/astro/index.mjs.map +1 -1
  34. package/dist/astro/middleware/auth.d.mts +12 -12
  35. package/dist/astro/middleware/auth.d.mts.map +1 -1
  36. package/dist/astro/middleware/auth.mjs +18 -13
  37. package/dist/astro/middleware/auth.mjs.map +1 -1
  38. package/dist/astro/middleware/media-usage-write-fence.mjs +6 -6
  39. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  40. package/dist/astro/middleware/redirect.mjs +34 -32
  41. package/dist/astro/middleware/redirect.mjs.map +1 -1
  42. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  43. package/dist/astro/middleware/request-context.mjs +99 -60
  44. package/dist/astro/middleware/request-context.mjs.map +1 -1
  45. package/dist/astro/middleware/setup.mjs +1 -1
  46. package/dist/astro/middleware.d.mts +12 -12
  47. package/dist/astro/middleware.d.mts.map +1 -1
  48. package/dist/astro/middleware.mjs +233 -128
  49. package/dist/astro/middleware.mjs.map +1 -1
  50. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +15 -15
  51. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +15 -15
  52. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +8 -7
  53. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs.map +1 -1
  54. package/dist/astro/routes/api/admin/api-tokens/index.mjs +9 -8
  55. package/dist/astro/routes/api/admin/api-tokens/index.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +7 -7
  57. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +17 -17
  58. package/dist/astro/routes/api/admin/byline-fields/index.mjs +17 -17
  59. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +17 -17
  60. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +22 -22
  61. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +22 -23
  62. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/bylines/index.mjs +23 -23
  64. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  65. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +19 -19
  66. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
  67. package/dist/astro/routes/api/admin/comments/bulk.mjs +18 -18
  68. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
  69. package/dist/astro/routes/api/admin/comments/index.mjs +18 -18
  70. package/dist/astro/routes/api/admin/core-update.mjs +8 -8
  71. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +7 -7
  72. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +6 -6
  73. package/dist/astro/routes/api/admin/media-usage/activation.mjs +21 -21
  74. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +22 -22
  75. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +22 -22
  76. package/dist/astro/routes/api/admin/media-usage/progress.mjs +23 -23
  77. package/dist/astro/routes/api/admin/media-usage/repair.mjs +29 -29
  78. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +22 -22
  79. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +22 -22
  80. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +7 -7
  81. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +7 -7
  82. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +9 -9
  83. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +9 -9
  84. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +73 -72
  85. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +8 -8
  87. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +71 -70
  88. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +72 -71
  90. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +82 -81
  92. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/index.mjs +72 -71
  94. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +8 -8
  96. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +71 -70
  97. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +81 -80
  99. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +71 -70
  101. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +72 -71
  103. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  104. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +83 -82
  105. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  106. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +10 -10
  107. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +74 -73
  108. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  109. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +8 -8
  110. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +72 -71
  111. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  112. package/dist/astro/routes/api/admin/plugins/updates.mjs +71 -70
  113. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  114. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +6 -6
  115. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +71 -70
  116. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  117. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +8 -8
  118. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +71 -70
  119. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  120. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +5 -5
  121. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +39 -39
  122. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +39 -39
  123. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +41 -41
  124. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +41 -41
  125. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +41 -41
  126. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +42 -42
  127. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +42 -42
  128. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +41 -41
  129. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +42 -42
  130. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +43 -43
  131. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +41 -41
  132. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +41 -41
  133. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +43 -43
  134. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +41 -41
  135. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +43 -43
  136. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +41 -41
  137. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +41 -41
  138. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +43 -43
  139. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +41 -41
  140. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +41 -41
  141. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +43 -43
  142. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +5 -5
  143. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +5 -5
  144. package/dist/astro/routes/api/admin/users/_id_/index.mjs +15 -15
  145. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +7 -7
  146. package/dist/astro/routes/api/admin/users/index.mjs +15 -15
  147. package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -7
  148. package/dist/astro/routes/api/auth/handover.d.mts +8 -0
  149. package/dist/astro/routes/api/auth/handover.d.mts.map +1 -0
  150. package/dist/astro/routes/api/auth/handover.mjs +49 -0
  151. package/dist/astro/routes/api/auth/handover.mjs.map +1 -0
  152. package/dist/astro/routes/api/auth/invite/accept.mjs +5 -5
  153. package/dist/astro/routes/api/auth/invite/complete.mjs +20 -20
  154. package/dist/astro/routes/api/auth/invite/index.mjs +17 -17
  155. package/dist/astro/routes/api/auth/invite/register-options.mjs +18 -18
  156. package/dist/astro/routes/api/auth/logout.mjs +6 -6
  157. package/dist/astro/routes/api/auth/magic-link/send.mjs +20 -19
  158. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  159. package/dist/astro/routes/api/auth/magic-link/verify.d.mts.map +1 -1
  160. package/dist/astro/routes/api/auth/magic-link/verify.mjs +24 -18
  161. package/dist/astro/routes/api/auth/magic-link/verify.mjs.map +1 -1
  162. package/dist/astro/routes/api/auth/me.mjs +16 -16
  163. package/dist/astro/routes/api/auth/mode.mjs +6 -6
  164. package/dist/astro/routes/api/auth/oauth/_provider_/callback.d.mts.map +1 -1
  165. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +36 -13
  166. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs.map +1 -1
  167. package/dist/astro/routes/api/auth/oauth/_provider_.d.mts.map +1 -1
  168. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +20 -5
  169. package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
  170. package/dist/astro/routes/api/auth/passkey/_id_.mjs +15 -15
  171. package/dist/astro/routes/api/auth/passkey/index.mjs +5 -5
  172. package/dist/astro/routes/api/auth/passkey/options.d.mts.map +1 -1
  173. package/dist/astro/routes/api/auth/passkey/options.mjs +28 -21
  174. package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
  175. package/dist/astro/routes/api/auth/passkey/register/options.mjs +18 -18
  176. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +19 -19
  177. package/dist/astro/routes/api/auth/passkey/verify.mjs +20 -20
  178. package/dist/astro/routes/api/auth/signup/complete.mjs +20 -20
  179. package/dist/astro/routes/api/auth/signup/request.mjs +19 -18
  180. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  181. package/dist/astro/routes/api/auth/signup/verify.mjs +5 -5
  182. package/dist/astro/routes/api/calendar.d.mts +8 -0
  183. package/dist/astro/routes/api/calendar.d.mts.map +1 -0
  184. package/dist/astro/routes/api/calendar.mjs +204 -0
  185. package/dist/astro/routes/api/calendar.mjs.map +1 -0
  186. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +14 -14
  187. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +20 -20
  188. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +6 -6
  189. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -17
  190. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +6 -6
  191. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +17 -17
  192. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +6 -6
  193. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +12 -12
  194. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +31 -31
  195. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +17 -17
  196. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +35 -35
  197. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +35 -35
  198. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +6 -6
  199. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +6 -6
  200. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +17 -17
  201. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +25 -25
  202. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +6 -6
  203. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +17 -17
  204. package/dist/astro/routes/api/content/_collection_/_id_.mjs +17 -17
  205. package/dist/astro/routes/api/content/_collection_/authors.mjs +6 -6
  206. package/dist/astro/routes/api/content/_collection_/index.mjs +16 -16
  207. package/dist/astro/routes/api/content/_collection_/trash.mjs +16 -16
  208. package/dist/astro/routes/api/dashboard.mjs +12 -12
  209. package/dist/astro/routes/api/dev/emails.mjs +6 -6
  210. package/dist/astro/routes/api/health.mjs +7 -7
  211. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  212. package/dist/astro/routes/api/import/probe.mjs +25 -25
  213. package/dist/astro/routes/api/import/wordpress/analyze.mjs +6 -6
  214. package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -13
  215. package/dist/astro/routes/api/import/wordpress/execute.mjs +31 -24
  216. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  217. package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -12
  218. package/dist/astro/routes/api/import/wordpress/media.mjs +20 -20
  219. package/dist/astro/routes/api/import/wordpress/prepare.mjs +18 -18
  220. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.d.mts +8 -0
  221. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.d.mts.map +1 -1
  222. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.mjs +67 -31
  223. package/dist/astro/routes/api/import/wordpress/rewrite-url-helpers.mjs.map +1 -1
  224. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -13
  225. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +27 -27
  226. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  227. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +25 -25
  228. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  229. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -13
  230. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +40 -33
  231. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  232. package/dist/astro/routes/api/manifest.mjs +10 -7
  233. package/dist/astro/routes/api/manifest.mjs.map +1 -1
  234. package/dist/astro/routes/api/mcp.mjs +94 -94
  235. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  236. package/dist/astro/routes/api/media/_id_/confirm.d.mts.map +1 -1
  237. package/dist/astro/routes/api/media/_id_/confirm.mjs +36 -20
  238. package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
  239. package/dist/astro/routes/api/media/_id_/replace.mjs +17 -17
  240. package/dist/astro/routes/api/media/_id_/upload.mjs +10 -10
  241. package/dist/astro/routes/api/media/_id_/usage.mjs +31 -31
  242. package/dist/astro/routes/api/media/_id_.mjs +29 -29
  243. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +7 -7
  244. package/dist/astro/routes/api/media/file/_...key_.d.mts.map +1 -1
  245. package/dist/astro/routes/api/media/file/_...key_.mjs +46 -16
  246. package/dist/astro/routes/api/media/file/_...key_.mjs.map +1 -1
  247. package/dist/astro/routes/api/media/folders/_id_.mjs +17 -17
  248. package/dist/astro/routes/api/media/folders/index.mjs +17 -17
  249. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +6 -6
  250. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +6 -6
  251. package/dist/astro/routes/api/media/providers/index.mjs +6 -6
  252. package/dist/astro/routes/api/media/upload-url.mjs +45 -25
  253. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  254. package/dist/astro/routes/api/media.d.mts.map +1 -1
  255. package/dist/astro/routes/api/media.mjs +47 -36
  256. package/dist/astro/routes/api/media.mjs.map +1 -1
  257. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +18 -18
  258. package/dist/astro/routes/api/menus/_name_/items.mjs +18 -18
  259. package/dist/astro/routes/api/menus/_name_/reorder.mjs +18 -18
  260. package/dist/astro/routes/api/menus/_name_/translations.mjs +18 -18
  261. package/dist/astro/routes/api/menus/_name_.mjs +18 -18
  262. package/dist/astro/routes/api/menus/index.mjs +18 -18
  263. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  264. package/dist/astro/routes/api/oauth/device/authorize.mjs +9 -9
  265. package/dist/astro/routes/api/oauth/device/code.mjs +13 -12
  266. package/dist/astro/routes/api/oauth/device/code.mjs.map +1 -1
  267. package/dist/astro/routes/api/oauth/device/token.mjs +12 -11
  268. package/dist/astro/routes/api/oauth/device/token.mjs.map +1 -1
  269. package/dist/astro/routes/api/oauth/register.mjs +9 -8
  270. package/dist/astro/routes/api/oauth/register.mjs.map +1 -1
  271. package/dist/astro/routes/api/oauth/token/refresh.mjs +9 -9
  272. package/dist/astro/routes/api/oauth/token/revoke.mjs +9 -9
  273. package/dist/astro/routes/api/oauth/token.mjs +9 -9
  274. package/dist/astro/routes/api/openapi.json.mjs +23 -23
  275. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  276. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +12 -12
  277. package/dist/astro/routes/api/redirects/404s/index.mjs +20 -19
  278. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  279. package/dist/astro/routes/api/redirects/404s/summary.mjs +20 -19
  280. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  281. package/dist/astro/routes/api/redirects/_id_.mjs +20 -19
  282. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  283. package/dist/astro/routes/api/redirects/index.mjs +20 -19
  284. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  285. package/dist/astro/routes/api/relations/_id_/index.mjs +35 -35
  286. package/dist/astro/routes/api/relations/index.mjs +35 -35
  287. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +6 -6
  288. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +17 -17
  289. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +71 -70
  290. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  291. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +71 -70
  292. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  293. package/dist/astro/routes/api/schema/block-types/index.mjs +71 -70
  294. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  295. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +71 -70
  296. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  297. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +71 -70
  298. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  299. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +71 -70
  300. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  301. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +71 -70
  302. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  303. package/dist/astro/routes/api/schema/collections/index.mjs +71 -70
  304. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  305. package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -70
  306. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  307. package/dist/astro/routes/api/schema/index.mjs +17 -17
  308. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  309. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +71 -70
  310. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  311. package/dist/astro/routes/api/schema/orphans/index.mjs +71 -70
  312. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  313. package/dist/astro/routes/api/search/enable.mjs +19 -19
  314. package/dist/astro/routes/api/search/index.mjs +18 -18
  315. package/dist/astro/routes/api/search/rebuild.mjs +19 -19
  316. package/dist/astro/routes/api/search/stats.mjs +9 -9
  317. package/dist/astro/routes/api/search/suggest.mjs +18 -18
  318. package/dist/astro/routes/api/sections/_slug_.mjs +18 -18
  319. package/dist/astro/routes/api/sections/index.mjs +18 -18
  320. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +8 -8
  321. package/dist/astro/routes/api/settings/backups/archives/index.mjs +8 -8
  322. package/dist/astro/routes/api/settings/backups/export.mjs +8 -8
  323. package/dist/astro/routes/api/settings/backups/index.mjs +9 -9
  324. package/dist/astro/routes/api/settings/domain-notify.d.mts +8 -0
  325. package/dist/astro/routes/api/settings/domain-notify.d.mts.map +1 -0
  326. package/dist/astro/routes/api/settings/domain-notify.mjs +125 -0
  327. package/dist/astro/routes/api/settings/domain-notify.mjs.map +1 -0
  328. package/dist/astro/routes/api/settings/domain.d.mts +9 -0
  329. package/dist/astro/routes/api/settings/domain.d.mts.map +1 -0
  330. package/dist/astro/routes/api/settings/domain.mjs +61 -0
  331. package/dist/astro/routes/api/settings/domain.mjs.map +1 -0
  332. package/dist/astro/routes/api/settings/email.mjs +7 -7
  333. package/dist/astro/routes/api/settings.mjs +22 -22
  334. package/dist/astro/routes/api/setup/admin-verify.mjs +21 -21
  335. package/dist/astro/routes/api/setup/admin.mjs +19 -19
  336. package/dist/astro/routes/api/setup/dev-bypass.mjs +43 -43
  337. package/dist/astro/routes/api/setup/dev-reset.mjs +5 -5
  338. package/dist/astro/routes/api/setup/index.d.mts.map +1 -1
  339. package/dist/astro/routes/api/setup/index.mjs +59 -50
  340. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  341. package/dist/astro/routes/api/setup/status.mjs +7 -7
  342. package/dist/astro/routes/api/site/domain-proof.d.mts +8 -0
  343. package/dist/astro/routes/api/site/domain-proof.d.mts.map +1 -0
  344. package/dist/astro/routes/api/site/domain-proof.mjs +33 -0
  345. package/dist/astro/routes/api/site/domain-proof.mjs.map +1 -0
  346. package/dist/astro/routes/api/snapshot.mjs +10 -10
  347. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -23
  348. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -23
  349. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -23
  350. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -23
  351. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -22
  352. package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -23
  353. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +36 -36
  354. package/dist/astro/routes/api/taxonomies/index.mjs +23 -23
  355. package/dist/astro/routes/api/themes/preview.mjs +8 -8
  356. package/dist/astro/routes/api/typegen.mjs +7 -7
  357. package/dist/astro/routes/api/visual-editing/action-token.mjs +8 -8
  358. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +20 -20
  359. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +5 -5
  360. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  361. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  362. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  363. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +17 -17
  364. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +19 -19
  365. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +19 -19
  366. package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -9
  367. package/dist/astro/routes/api/widget-areas/index.mjs +19 -19
  368. package/dist/astro/routes/api/widget-components.mjs +6 -6
  369. package/dist/astro/routes/robots.txt.mjs +7 -7
  370. package/dist/astro/routes/sitemap-_collection_.xml.d.mts.map +1 -1
  371. package/dist/astro/routes/sitemap-_collection_.xml.mjs +30 -13
  372. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  373. package/dist/astro/routes/sitemap.xml.d.mts.map +1 -1
  374. package/dist/astro/routes/sitemap.xml.mjs +14 -13
  375. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  376. package/dist/astro/types.d.mts +30 -18
  377. package/dist/astro/types.d.mts.map +1 -1
  378. package/dist/audit-CCH3MA4Y.mjs +127 -0
  379. package/dist/audit-CCH3MA4Y.mjs.map +1 -0
  380. package/dist/auth/providers/github.d.mts +1 -1
  381. package/dist/auth/providers/google.d.mts +1 -1
  382. package/dist/auth/providers/microsoft.d.mts +27 -0
  383. package/dist/auth/providers/microsoft.d.mts.map +1 -0
  384. package/dist/auth/providers/microsoft.mjs +20 -0
  385. package/dist/auth/providers/microsoft.mjs.map +1 -0
  386. package/dist/authoritative-records-Dcs7l2H5.mjs +5183 -0
  387. package/dist/authoritative-records-Dcs7l2H5.mjs.map +1 -0
  388. package/dist/authorize-TdIGpRSE.mjs +49 -0
  389. package/dist/authorize-TdIGpRSE.mjs.map +1 -0
  390. package/dist/backup-CZt5Mzwx.mjs +246 -0
  391. package/dist/backup-CZt5Mzwx.mjs.map +1 -0
  392. package/dist/base64-BQBZwXCx.mjs +63 -0
  393. package/dist/base64-BQBZwXCx.mjs.map +1 -0
  394. package/dist/block-types-DHnkzE6u.mjs +132 -0
  395. package/dist/block-types-DHnkzE6u.mjs.map +1 -0
  396. package/dist/block-values-C4N_F2-G.mjs +175 -0
  397. package/dist/block-values-C4N_F2-G.mjs.map +1 -0
  398. package/dist/byline-BmVKOQ8l.mjs +909 -0
  399. package/dist/byline-BmVKOQ8l.mjs.map +1 -0
  400. package/dist/byline-fields-B8SDs3M_.mjs +123 -0
  401. package/dist/byline-fields-B8SDs3M_.mjs.map +1 -0
  402. package/dist/byline-fields-Bze3ZdAw.mjs +280 -0
  403. package/dist/byline-fields-Bze3ZdAw.mjs.map +1 -0
  404. package/dist/bylines-CHhR28r9.mjs +150 -0
  405. package/dist/bylines-CHhR28r9.mjs.map +1 -0
  406. package/dist/bylines-DZS4OflA.mjs +234 -0
  407. package/dist/bylines-DZS4OflA.mjs.map +1 -0
  408. package/dist/cache-x0z8t_m9.mjs +133 -0
  409. package/dist/cache-x0z8t_m9.mjs.map +1 -0
  410. package/dist/canonical-BUcKRYpG.mjs +174 -0
  411. package/dist/canonical-BUcKRYpG.mjs.map +1 -0
  412. package/dist/capture-triggers-C9JKoIdT.mjs +362 -0
  413. package/dist/capture-triggers-C9JKoIdT.mjs.map +1 -0
  414. package/dist/challenge-store-BHgdPVze.mjs +51 -0
  415. package/dist/challenge-store-BHgdPVze.mjs.map +1 -0
  416. package/dist/checksum-BYR5i7qe.mjs +162 -0
  417. package/dist/checksum-BYR5i7qe.mjs.map +1 -0
  418. package/dist/chrome-tags-BIKBMZYO.mjs +24 -0
  419. package/dist/chrome-tags-BIKBMZYO.mjs.map +1 -0
  420. package/dist/chunks-Dr5Vr0zA.mjs +25 -0
  421. package/dist/chunks-Dr5Vr0zA.mjs.map +1 -0
  422. package/dist/cli/index.mjs +54 -52
  423. package/dist/cli/index.mjs.map +1 -1
  424. package/dist/client/cf-access.d.mts +1 -1
  425. package/dist/client/index.d.mts +34 -34
  426. package/dist/client/index.d.mts.map +1 -1
  427. package/dist/client/index.mjs +2 -2
  428. package/dist/client/index.mjs.map +1 -1
  429. package/dist/collection-slugs-cache-B2Gs9Jwx.mjs +85 -0
  430. package/dist/collection-slugs-cache-B2Gs9Jwx.mjs.map +1 -0
  431. package/dist/comment-CWla6OHV.mjs +325 -0
  432. package/dist/comment-CWla6OHV.mjs.map +1 -0
  433. package/dist/comment-reaction-RZrcs5cW.mjs +85 -0
  434. package/dist/comment-reaction-RZrcs5cW.mjs.map +1 -0
  435. package/dist/comments-BzmIKVb2.mjs +99 -0
  436. package/dist/comments-BzmIKVb2.mjs.map +1 -0
  437. package/dist/comments-Da_dI2O1.mjs +195 -0
  438. package/dist/comments-Da_dI2O1.mjs.map +1 -0
  439. package/dist/components-oFXumpf5.mjs +112 -0
  440. package/dist/components-oFXumpf5.mjs.map +1 -0
  441. package/dist/config--wamYxBW.d.mts +39 -0
  442. package/dist/config--wamYxBW.d.mts.map +1 -0
  443. package/dist/config-Bo4eOOdV.mjs +228 -0
  444. package/dist/config-Bo4eOOdV.mjs.map +1 -0
  445. package/dist/config-C4-UxIk7.d.mts +6790 -0
  446. package/dist/config-C4-UxIk7.d.mts.map +1 -0
  447. package/dist/connection-UpzYxtE2.mjs +36 -0
  448. package/dist/connection-UpzYxtE2.mjs.map +1 -0
  449. package/dist/content-CcHrqkgp.mjs +2072 -0
  450. package/dist/content-CcHrqkgp.mjs.map +1 -0
  451. package/dist/content-list-query-Bxxdd9fv.d.mts +26 -0
  452. package/dist/content-list-query-Bxxdd9fv.d.mts.map +1 -0
  453. package/dist/content-repair-havk1F0-.mjs +442 -0
  454. package/dist/content-repair-havk1F0-.mjs.map +1 -0
  455. package/dist/context-CvhgHgSH.mjs +2043 -0
  456. package/dist/context-CvhgHgSH.mjs.map +1 -0
  457. package/dist/credits-CygUrPOi.mjs +110 -0
  458. package/dist/credits-CygUrPOi.mjs.map +1 -0
  459. package/dist/cron-C6ytTOLw.mjs +306 -0
  460. package/dist/cron-C6ytTOLw.mjs.map +1 -0
  461. package/dist/dashboard-7_FYfafc.mjs +151 -0
  462. package/dist/dashboard-7_FYfafc.mjs.map +1 -0
  463. package/dist/db/index.d.mts +3 -3
  464. package/dist/db/index.mjs +1 -1
  465. package/dist/db/index.mjs.map +1 -1
  466. package/dist/db/libsql-migrations.d.mts +1 -1
  467. package/dist/db/libsql-migrations.mjs +5 -5
  468. package/dist/db/libsql.d.mts +1 -1
  469. package/dist/db/postgres-migrations.d.mts +1 -1
  470. package/dist/db/postgres-migrations.mjs +4 -4
  471. package/dist/db/postgres.d.mts +1 -1
  472. package/dist/db/sqlite-migrations.d.mts +1 -1
  473. package/dist/db/sqlite-migrations.mjs +4 -4
  474. package/dist/db/sqlite.d.mts +1 -1
  475. package/dist/db/sqlite.mjs +1 -1
  476. package/dist/default-CHCUkV4Z.mjs +81 -0
  477. package/dist/default-CHCUkV4Z.mjs.map +1 -0
  478. package/dist/deferred-tasks-G0xhcJTl.d.mts +9 -0
  479. package/dist/deferred-tasks-G0xhcJTl.d.mts.map +1 -0
  480. package/dist/dev-typegen-Dtl8AfS6.mjs +29 -0
  481. package/dist/dev-typegen-Dtl8AfS6.mjs.map +1 -0
  482. package/dist/device-flow-CzDJmQ1q.mjs +521 -0
  483. package/dist/device-flow-CzDJmQ1q.mjs.map +1 -0
  484. package/dist/digest-xJmyPv2r.mjs +194 -0
  485. package/dist/digest-xJmyPv2r.mjs.map +1 -0
  486. package/dist/direct-executor-BXiYIVJ9.mjs +104 -0
  487. package/dist/direct-executor-BXiYIVJ9.mjs.map +1 -0
  488. package/dist/email-console-7ZPApLlm.mjs +50 -0
  489. package/dist/email-console-7ZPApLlm.mjs.map +1 -0
  490. package/dist/email-locale-DFdUA6UF.mjs +25 -0
  491. package/dist/email-locale-DFdUA6UF.mjs.map +1 -0
  492. package/dist/emdash-runtime-C4oFeVpN.mjs +4363 -0
  493. package/dist/emdash-runtime-C4oFeVpN.mjs.map +1 -0
  494. package/dist/enrich-Duu4sV3a.mjs +194 -0
  495. package/dist/enrich-Duu4sV3a.mjs.map +1 -0
  496. package/dist/entry-lock-B4n0HdQ_.mjs +163 -0
  497. package/dist/entry-lock-B4n0HdQ_.mjs.map +1 -0
  498. package/dist/entry-lock-BAAlKYrz.d.mts +4566 -0
  499. package/dist/entry-lock-BAAlKYrz.d.mts.map +1 -0
  500. package/dist/entry-lock-Cjz0h45X.mjs +1209 -0
  501. package/dist/entry-lock-Cjz0h45X.mjs.map +1 -0
  502. package/dist/env-types-4bkF6Bqg.mjs +38 -0
  503. package/dist/env-types-4bkF6Bqg.mjs.map +1 -0
  504. package/dist/error-DxgQdaZ_.mjs +90 -0
  505. package/dist/error-DxgQdaZ_.mjs.map +1 -0
  506. package/dist/errors-CjtE5aWF.mjs +120 -0
  507. package/dist/errors-CjtE5aWF.mjs.map +1 -0
  508. package/dist/errors-hskQ0C8G.mjs +479 -0
  509. package/dist/errors-hskQ0C8G.mjs.map +1 -0
  510. package/dist/escape-ESFhYzwG.mjs +9 -0
  511. package/dist/escape-ESFhYzwG.mjs.map +1 -0
  512. package/dist/fence-vc3aHgRA.mjs +162 -0
  513. package/dist/fence-vc3aHgRA.mjs.map +1 -0
  514. package/dist/field-defs-cache-zoow36nz.mjs +77 -0
  515. package/dist/field-defs-cache-zoow36nz.mjs.map +1 -0
  516. package/dist/field-map-JD1wG0Tq.mjs +83 -0
  517. package/dist/field-map-JD1wG0Tq.mjs.map +1 -0
  518. package/dist/fts-manager-WJCN8uU6.mjs +443 -0
  519. package/dist/fts-manager-WJCN8uU6.mjs.map +1 -0
  520. package/dist/gc-CsGZiKdH.mjs +75 -0
  521. package/dist/gc-CsGZiKdH.mjs.map +1 -0
  522. package/dist/hash-C4DFoJ7Z.mjs +37 -0
  523. package/dist/hash-C4DFoJ7Z.mjs.map +1 -0
  524. package/dist/hook-result-CXjtMk7Q.d.mts +31 -0
  525. package/dist/hook-result-CXjtMk7Q.d.mts.map +1 -0
  526. package/dist/hreflang-BAma7iRr.mjs +105 -0
  527. package/dist/hreflang-BAma7iRr.mjs.map +1 -0
  528. package/dist/hreflang-BsYo4x_M.d.mts +50 -0
  529. package/dist/hreflang-BsYo4x_M.d.mts.map +1 -0
  530. package/dist/http-route-dispatch-C8G7hAK6.mjs +342 -0
  531. package/dist/http-route-dispatch-C8G7hAK6.mjs.map +1 -0
  532. package/dist/identity-BwBKM1fH.mjs +35 -0
  533. package/dist/identity-BwBKM1fH.mjs.map +1 -0
  534. package/dist/import-DJ3Z2wxE.mjs +2021 -0
  535. package/dist/import-DJ3Z2wxE.mjs.map +1 -0
  536. package/dist/index-DYsn97dY.d.mts +623 -0
  537. package/dist/index-DYsn97dY.d.mts.map +1 -0
  538. package/dist/index.d.mts +24 -24
  539. package/dist/index.mjs +99 -98
  540. package/dist/init-lock-BGmew3r1.mjs +56 -0
  541. package/dist/init-lock-BGmew3r1.mjs.map +1 -0
  542. package/dist/install-finalization-DCFnFSHv.mjs +58 -0
  543. package/dist/install-finalization-DCFnFSHv.mjs.map +1 -0
  544. package/dist/keys-CGvAndSp.mjs +61 -0
  545. package/dist/keys-CGvAndSp.mjs.map +1 -0
  546. package/dist/kinds-DT1W4T4Y.mjs +974 -0
  547. package/dist/kinds-DT1W4T4Y.mjs.map +1 -0
  548. package/dist/lifecycle-BzglCSY0.mjs +25 -0
  549. package/dist/lifecycle-BzglCSY0.mjs.map +1 -0
  550. package/dist/load-DjUqmf3s.mjs +28 -0
  551. package/dist/load-DjUqmf3s.mjs.map +1 -0
  552. package/dist/loader-CetY659y.mjs +1355 -0
  553. package/dist/loader-CetY659y.mjs.map +1 -0
  554. package/dist/loops-DkT1zkPH.mjs +205 -0
  555. package/dist/loops-DkT1zkPH.mjs.map +1 -0
  556. package/dist/manifest-builder-BOFCd9rX.mjs +189 -0
  557. package/dist/manifest-builder-BOFCd9rX.mjs.map +1 -0
  558. package/dist/manifest-schema-BiFBPEsp.mjs +497 -0
  559. package/dist/manifest-schema-BiFBPEsp.mjs.map +1 -0
  560. package/dist/marketplace-CUlenvZm.mjs +257 -0
  561. package/dist/marketplace-CUlenvZm.mjs.map +1 -0
  562. package/dist/media/image-endpoint.d.mts +26 -2
  563. package/dist/media/image-endpoint.d.mts.map +1 -1
  564. package/dist/media/image-endpoint.mjs +73 -3
  565. package/dist/media/image-endpoint.mjs.map +1 -1
  566. package/dist/media/index.d.mts +1 -1
  567. package/dist/media/index.mjs +1 -1
  568. package/dist/media/local-runtime.d.mts +14 -14
  569. package/dist/media/local-runtime.mjs +7 -7
  570. package/dist/media-CRKsKlfK.mjs +416 -0
  571. package/dist/media-CRKsKlfK.mjs.map +1 -0
  572. package/dist/media-C_z7sRuC.mjs +294 -0
  573. package/dist/media-C_z7sRuC.mjs.map +1 -0
  574. package/dist/media-IT8hQleU.mjs +373 -0
  575. package/dist/media-IT8hQleU.mjs.map +1 -0
  576. package/dist/media-allowlist-Ct6wvnT2.mjs +45 -0
  577. package/dist/media-allowlist-Ct6wvnT2.mjs.map +1 -0
  578. package/dist/media-folders-DtMt-vAA.mjs +210 -0
  579. package/dist/media-folders-DtMt-vAA.mjs.map +1 -0
  580. package/dist/media-url-BpXLqCmf.mjs +43 -0
  581. package/dist/media-url-BpXLqCmf.mjs.map +1 -0
  582. package/dist/media-usage-DEPHZZ9X.mjs +282 -0
  583. package/dist/media-usage-DEPHZZ9X.mjs.map +1 -0
  584. package/dist/media-usage-activation-V2Siabtw.mjs +78 -0
  585. package/dist/media-usage-activation-V2Siabtw.mjs.map +1 -0
  586. package/dist/media-usage-work-Cv1OE59F.mjs +151 -0
  587. package/dist/media-usage-work-Cv1OE59F.mjs.map +1 -0
  588. package/dist/media-usage-work-cgDYGvrt.mjs +1015 -0
  589. package/dist/media-usage-work-cgDYGvrt.mjs.map +1 -0
  590. package/dist/menus-CvVYfsuk.mjs +753 -0
  591. package/dist/menus-CvVYfsuk.mjs.map +1 -0
  592. package/dist/menus-D1HC8npj.mjs +92 -0
  593. package/dist/menus-D1HC8npj.mjs.map +1 -0
  594. package/dist/menus-DL8IPIcm.mjs +3721 -0
  595. package/dist/menus-DL8IPIcm.mjs.map +1 -0
  596. package/dist/migrations/index.d.mts +1 -1
  597. package/dist/migrations/index.mjs +3 -3
  598. package/dist/mime-B5M9R53H.mjs +81 -0
  599. package/dist/mime-B5M9R53H.mjs.map +1 -0
  600. package/dist/mode-eieqAWLe.mjs +23 -0
  601. package/dist/mode-eieqAWLe.mjs.map +1 -0
  602. package/dist/node-sqlite-compat-VuyzJw1b.mjs +63 -0
  603. package/dist/node-sqlite-compat-VuyzJw1b.mjs.map +1 -0
  604. package/dist/oauth-authorization-B6ZJbMd2.mjs +274 -0
  605. package/dist/oauth-authorization-B6ZJbMd2.mjs.map +1 -0
  606. package/dist/oauth-clients-DVjRc9v3.mjs +266 -0
  607. package/dist/oauth-clients-DVjRc9v3.mjs.map +1 -0
  608. package/dist/oauth-state-store-CnmYYsVQ.mjs +50 -0
  609. package/dist/oauth-state-store-CnmYYsVQ.mjs.map +1 -0
  610. package/dist/oauth-user-lookup-Dz1_R5vT.mjs +26 -0
  611. package/dist/oauth-user-lookup-Dz1_R5vT.mjs.map +1 -0
  612. package/dist/object-cache/memory.d.mts +1 -1
  613. package/dist/options-BR9XZl7h.d.mts +81 -0
  614. package/dist/options-BR9XZl7h.d.mts.map +1 -0
  615. package/dist/ownership-COPyVysP.mjs +12 -0
  616. package/dist/ownership-COPyVysP.mjs.map +1 -0
  617. package/dist/page/index.d.mts +2 -2
  618. package/dist/page/index.mjs +6 -6
  619. package/dist/parse-BOGhrwSq.d.mts +174 -0
  620. package/dist/parse-BOGhrwSq.d.mts.map +1 -0
  621. package/dist/parse-Cn5aSk1N.mjs +81 -0
  622. package/dist/parse-Cn5aSk1N.mjs.map +1 -0
  623. package/dist/passkey-config-mMFRQUCj.mjs +46 -0
  624. package/dist/passkey-config-mMFRQUCj.mjs.map +1 -0
  625. package/dist/paths-BmcAdBo9.mjs +77 -0
  626. package/dist/paths-BmcAdBo9.mjs.map +1 -0
  627. package/dist/patterns-CMNnYCgf.mjs +159 -0
  628. package/dist/patterns-CMNnYCgf.mjs.map +1 -0
  629. package/dist/placeholder-nOep3_Gn.d.mts +306 -0
  630. package/dist/placeholder-nOep3_Gn.d.mts.map +1 -0
  631. package/dist/plan-CDY4K8CH.mjs +135 -0
  632. package/dist/plan-CDY4K8CH.mjs.map +1 -0
  633. package/dist/plugin-test-runtime.d.mts +14 -14
  634. package/dist/plugin-test-runtime.d.mts.map +1 -1
  635. package/dist/plugin-test-runtime.mjs +111 -110
  636. package/dist/plugin-types.d.mts +2 -2
  637. package/dist/plugin-utils.d.mts +12 -12
  638. package/dist/plugin-utils.mjs +1 -1
  639. package/dist/plugin-utils.mjs.map +1 -1
  640. package/dist/plugins/adapt-sandbox-entry.d.mts +12 -12
  641. package/dist/plugins/adapt-sandbox-entry.mjs +3 -3
  642. package/dist/plugins/host.d.mts +5 -5
  643. package/dist/plugins/host.mjs +45 -44
  644. package/dist/plugins-DFBpfbO3.mjs +261 -0
  645. package/dist/plugins-DFBpfbO3.mjs.map +1 -0
  646. package/dist/policy-B_2qnHSy.mjs +45 -0
  647. package/dist/policy-B_2qnHSy.mjs.map +1 -0
  648. package/dist/portable-text-Dc2YAusw.mjs +307 -0
  649. package/dist/portable-text-Dc2YAusw.mjs.map +1 -0
  650. package/dist/preview-BtzikJ9O.mjs +107 -0
  651. package/dist/preview-BtzikJ9O.mjs.map +1 -0
  652. package/dist/protocol-M268ox8L.d.mts +61 -0
  653. package/dist/protocol-M268ox8L.d.mts.map +1 -0
  654. package/dist/public-submission-BQZavgZU.mjs +251 -0
  655. package/dist/public-submission-BQZavgZU.mjs.map +1 -0
  656. package/dist/public-url-uT1Ok2Tu.mjs +101 -0
  657. package/dist/public-url-uT1Ok2Tu.mjs.map +1 -0
  658. package/dist/query-BGG3sDEd.mjs +1127 -0
  659. package/dist/query-BGG3sDEd.mjs.map +1 -0
  660. package/dist/query-C_CWlifp.mjs +41 -0
  661. package/dist/query-C_CWlifp.mjs.map +1 -0
  662. package/dist/range-CXK_kDbI.mjs +51 -0
  663. package/dist/range-CXK_kDbI.mjs.map +1 -0
  664. package/dist/rate-limit-Dvamvay-.mjs +127 -0
  665. package/dist/rate-limit-Dvamvay-.mjs.map +1 -0
  666. package/dist/receipt-BmQGzquP.mjs +43 -0
  667. package/dist/receipt-BmQGzquP.mjs.map +1 -0
  668. package/dist/redirect-B39kTQ_0.mjs +423 -0
  669. package/dist/redirect-B39kTQ_0.mjs.map +1 -0
  670. package/dist/redirect-BguJ00Pv.mjs +19 -0
  671. package/dist/redirect-BguJ00Pv.mjs.map +1 -0
  672. package/dist/redirects-C8G4BsfP.mjs +446 -0
  673. package/dist/redirects-C8G4BsfP.mjs.map +1 -0
  674. package/dist/redirects-DFT7Wr-e.mjs +148 -0
  675. package/dist/redirects-DFT7Wr-e.mjs.map +1 -0
  676. package/dist/registry/testing.mjs +3 -3
  677. package/dist/registry-DeZ27gVi.mjs +8374 -0
  678. package/dist/registry-DeZ27gVi.mjs.map +1 -0
  679. package/dist/relations-DBB1bRJW.mjs +776 -0
  680. package/dist/relations-DBB1bRJW.mjs.map +1 -0
  681. package/dist/request-context.d.mts +2 -2
  682. package/dist/request-context.mjs.map +1 -1
  683. package/dist/request-meta-BSvkhIBX.mjs +141 -0
  684. package/dist/request-meta-BSvkhIBX.mjs.map +1 -0
  685. package/dist/resolve-BxH64HN9.mjs +100 -0
  686. package/dist/resolve-BxH64HN9.mjs.map +1 -0
  687. package/dist/revision-BWEH2qQB.mjs +368 -0
  688. package/dist/revision-BWEH2qQB.mjs.map +1 -0
  689. package/dist/route-wire-CwbWB_6O.mjs +197 -0
  690. package/dist/route-wire-CwbWB_6O.mjs.map +1 -0
  691. package/dist/routes-BfIxc7ft.mjs +272 -0
  692. package/dist/routes-BfIxc7ft.mjs.map +1 -0
  693. package/dist/runner-DkeafPBA.d.mts +68 -0
  694. package/dist/runner-DkeafPBA.d.mts.map +1 -0
  695. package/dist/runner-wqt4BrIW.mjs +6383 -0
  696. package/dist/runner-wqt4BrIW.mjs.map +1 -0
  697. package/dist/runtime.d.mts +13 -13
  698. package/dist/runtime.mjs +3 -3
  699. package/dist/schema/project-env-types.mjs +38 -38
  700. package/dist/schema-BXIW-JHi.mjs +815 -0
  701. package/dist/schema-BXIW-JHi.mjs.map +1 -0
  702. package/dist/schema-I74JwYte.mjs +13 -0
  703. package/dist/schema-I74JwYte.mjs.map +1 -0
  704. package/dist/scopes-RWZ5ft_Z.mjs +34 -0
  705. package/dist/scopes-RWZ5ft_Z.mjs.map +1 -0
  706. package/dist/search-DxwagyWS.mjs +450 -0
  707. package/dist/search-DxwagyWS.mjs.map +1 -0
  708. package/dist/secrets-Cc_O3Kp-.mjs +369 -0
  709. package/dist/secrets-Cc_O3Kp-.mjs.map +1 -0
  710. package/dist/sections-Ccq9ZgyD.mjs +346 -0
  711. package/dist/sections-Ccq9ZgyD.mjs.map +1 -0
  712. package/dist/seed/index.d.mts +2 -2
  713. package/dist/seed/index.mjs +36 -36
  714. package/dist/seo/index.d.mts +3 -3
  715. package/dist/seo/index.mjs +23 -23
  716. package/dist/seo-CCnfPWAQ.mjs +133 -0
  717. package/dist/seo-CCnfPWAQ.mjs.map +1 -0
  718. package/dist/seo-QCtJ1jjV.mjs +188 -0
  719. package/dist/seo-QCtJ1jjV.mjs.map +1 -0
  720. package/dist/service-DX84s2rw.mjs +150 -0
  721. package/dist/service-DX84s2rw.mjs.map +1 -0
  722. package/dist/session-user-1dtJc2zv.mjs +61 -0
  723. package/dist/session-user-1dtJc2zv.mjs.map +1 -0
  724. package/dist/settings-B1jOxAIl.mjs +443 -0
  725. package/dist/settings-B1jOxAIl.mjs.map +1 -0
  726. package/dist/settings-Bc1IBl1t.mjs +66 -0
  727. package/dist/settings-Bc1IBl1t.mjs.map +1 -0
  728. package/dist/settings-GaZ5sVgg.mjs +73 -0
  729. package/dist/settings-GaZ5sVgg.mjs.map +1 -0
  730. package/dist/setup-complete-DidMAWJS.mjs +65 -0
  731. package/dist/setup-complete-DidMAWJS.mjs.map +1 -0
  732. package/dist/setup-nonce-DKl4S4c6.mjs +25 -0
  733. package/dist/setup-nonce-DKl4S4c6.mjs.map +1 -0
  734. package/dist/single-flight-cache-D0EaGbN1.mjs +104 -0
  735. package/dist/single-flight-cache-D0EaGbN1.mjs.map +1 -0
  736. package/dist/site-domain-CbI51Pc2.mjs +113 -0
  737. package/dist/site-domain-CbI51Pc2.mjs.map +1 -0
  738. package/dist/site-settings-CDdT4mVm.mjs +50 -0
  739. package/dist/site-settings-CDdT4mVm.mjs.map +1 -0
  740. package/dist/site-url-CrDZaAvo.mjs +45 -0
  741. package/dist/site-url-CrDZaAvo.mjs.map +1 -0
  742. package/dist/sitemap-name-W3BTor6X.mjs +26 -0
  743. package/dist/sitemap-name-W3BTor6X.mjs.map +1 -0
  744. package/dist/slug-BJhHKoOH.mjs +16 -0
  745. package/dist/slug-BJhHKoOH.mjs.map +1 -0
  746. package/dist/slugify-bu2-jKia.mjs +22 -0
  747. package/dist/slugify-bu2-jKia.mjs.map +1 -0
  748. package/dist/snapshot-BuI_2uDe.mjs +414 -0
  749. package/dist/snapshot-BuI_2uDe.mjs.map +1 -0
  750. package/dist/ssrf-LM_0wpGA.mjs +406 -0
  751. package/dist/ssrf-LM_0wpGA.mjs.map +1 -0
  752. package/dist/stage-DhzZuYaT.mjs +662 -0
  753. package/dist/stage-DhzZuYaT.mjs.map +1 -0
  754. package/dist/staged-DboEaWsV.mjs +686 -0
  755. package/dist/staged-DboEaWsV.mjs.map +1 -0
  756. package/dist/state-DCXDzjHq.mjs +178 -0
  757. package/dist/state-DCXDzjHq.mjs.map +1 -0
  758. package/dist/status-Dl85BK39.mjs +30 -0
  759. package/dist/status-Dl85BK39.mjs.map +1 -0
  760. package/dist/storage/local.d.mts +2 -2
  761. package/dist/storage/local.d.mts.map +1 -1
  762. package/dist/storage/local.mjs +12 -5
  763. package/dist/storage/local.mjs.map +1 -1
  764. package/dist/storage/s3.d.mts +4 -2
  765. package/dist/storage/s3.d.mts.map +1 -1
  766. package/dist/storage/s3.mjs +56 -9
  767. package/dist/storage/s3.mjs.map +1 -1
  768. package/dist/storage-query-BOBmeDMD.d.mts +1615 -0
  769. package/dist/storage-query-BOBmeDMD.d.mts.map +1 -0
  770. package/dist/tar-K40edFMt.mjs +449 -0
  771. package/dist/tar-K40edFMt.mjs.map +1 -0
  772. package/dist/target-BOighEY1.mjs +27 -0
  773. package/dist/target-BOighEY1.mjs.map +1 -0
  774. package/dist/taxonomies-DQSywBvX.mjs +697 -0
  775. package/dist/taxonomies-DQSywBvX.mjs.map +1 -0
  776. package/dist/taxonomies-Dj5eaobC.mjs +939 -0
  777. package/dist/taxonomies-Dj5eaobC.mjs.map +1 -0
  778. package/dist/taxonomy-QrNmTfIZ.mjs +550 -0
  779. package/dist/taxonomy-QrNmTfIZ.mjs.map +1 -0
  780. package/dist/tokens-j5L0as2H.mjs +171 -0
  781. package/dist/tokens-j5L0as2H.mjs.map +1 -0
  782. package/dist/transfer-CYEw8Tu4.mjs +8873 -0
  783. package/dist/transfer-CYEw8Tu4.mjs.map +1 -0
  784. package/dist/transfer-DDX10hkD.mjs +166 -0
  785. package/dist/transfer-DDX10hkD.mjs.map +1 -0
  786. package/dist/transfer-download-BAqq6GJv.mjs +33 -0
  787. package/dist/transfer-download-BAqq6GJv.mjs.map +1 -0
  788. package/dist/transformations-De44wqV_.mjs +196 -0
  789. package/dist/transformations-De44wqV_.mjs.map +1 -0
  790. package/dist/transport-1QjUhCRO.d.mts +42 -0
  791. package/dist/transport-1QjUhCRO.d.mts.map +1 -0
  792. package/dist/transport-Ds5pVX7p.mjs +136 -0
  793. package/dist/transport-Ds5pVX7p.mjs.map +1 -0
  794. package/dist/trusted-proxy-d4Tk6biT.mjs +51 -0
  795. package/dist/trusted-proxy-d4Tk6biT.mjs.map +1 -0
  796. package/dist/turnstile-DaFLtyrs.mjs +58 -0
  797. package/dist/turnstile-DaFLtyrs.mjs.map +1 -0
  798. package/dist/types-B4-1P2DK.d.mts +227 -0
  799. package/dist/types-B4-1P2DK.d.mts.map +1 -0
  800. package/dist/types-BKXA0f-c.mjs +16 -0
  801. package/dist/types-BKXA0f-c.mjs.map +1 -0
  802. package/dist/types-BiHcpUoO.d.mts +374 -0
  803. package/dist/types-BiHcpUoO.d.mts.map +1 -0
  804. package/dist/types-BihhvkyN.d.mts +85 -0
  805. package/dist/types-BihhvkyN.d.mts.map +1 -0
  806. package/dist/types-Bq9Wohd7.d.mts +363 -0
  807. package/dist/types-Bq9Wohd7.d.mts.map +1 -0
  808. package/dist/types-C-Xp0CcN.mjs +103 -0
  809. package/dist/types-C-Xp0CcN.mjs.map +1 -0
  810. package/dist/types-C4P7F1Vq.d.mts +1741 -0
  811. package/dist/types-C4P7F1Vq.d.mts.map +1 -0
  812. package/dist/types-CGaqwHw4.mjs +37 -0
  813. package/dist/types-CGaqwHw4.mjs.map +1 -0
  814. package/dist/types-Cj0_yZkn.mjs +18 -0
  815. package/dist/types-Cj0_yZkn.mjs.map +1 -0
  816. package/dist/types-D4ECCE4X.mjs +77 -0
  817. package/dist/types-D4ECCE4X.mjs.map +1 -0
  818. package/dist/types-DcRJp0vS.d.mts +125 -0
  819. package/dist/types-DcRJp0vS.d.mts.map +1 -0
  820. package/dist/types-Ff85fTzU.d.mts +289 -0
  821. package/dist/types-Ff85fTzU.d.mts.map +1 -0
  822. package/dist/types-UKr5Sf4y.d.mts +916 -0
  823. package/dist/types-UKr5Sf4y.d.mts.map +1 -0
  824. package/dist/types-YpN8hZW7.d.mts +204 -0
  825. package/dist/types-YpN8hZW7.d.mts.map +1 -0
  826. package/dist/update-check-DrlsK-tt.mjs +161 -0
  827. package/dist/update-check-DrlsK-tt.mjs.map +1 -0
  828. package/dist/upload-attempts-D8CPPvRU.mjs +32 -0
  829. package/dist/upload-attempts-D8CPPvRU.mjs.map +1 -0
  830. package/dist/url-pattern-Di4Nn3vP.mjs +41 -0
  831. package/dist/url-pattern-Di4Nn3vP.mjs.map +1 -0
  832. package/dist/user-B-ZdGjhI.mjs +171 -0
  833. package/dist/user-B-ZdGjhI.mjs.map +1 -0
  834. package/dist/utils-D7wL3r6-.mjs +437 -0
  835. package/dist/utils-D7wL3r6-.mjs.map +1 -0
  836. package/dist/validate-BSZbSUDk.mjs +524 -0
  837. package/dist/validate-BSZbSUDk.mjs.map +1 -0
  838. package/dist/validate-Dfv0DpZi.d.mts +468 -0
  839. package/dist/validate-Dfv0DpZi.d.mts.map +1 -0
  840. package/dist/validation-DRyC_Vm5.mjs +219 -0
  841. package/dist/validation-DRyC_Vm5.mjs.map +1 -0
  842. package/dist/version-C4kz0PcO.mjs +7 -0
  843. package/dist/version-C4kz0PcO.mjs.map +1 -0
  844. package/dist/version-jhs2BRtl.mjs +9 -0
  845. package/dist/version-jhs2BRtl.mjs.map +1 -0
  846. package/dist/video-DReZ48Un.mjs +54 -0
  847. package/dist/video-DReZ48Un.mjs.map +1 -0
  848. package/dist/virtual-modules-D0e6VbEv.mjs +516 -0
  849. package/dist/virtual-modules-D0e6VbEv.mjs.map +1 -0
  850. package/dist/widgets-BkcMzKct.mjs +121 -0
  851. package/dist/widgets-BkcMzKct.mjs.map +1 -0
  852. package/dist/wxr-taxonomies-BxI0CbTg.mjs +453 -0
  853. package/dist/wxr-taxonomies-BxI0CbTg.mjs.map +1 -0
  854. package/dist/wxr-taxonomies-Dad33GJi.d.mts +34 -0
  855. package/dist/wxr-taxonomies-Dad33GJi.d.mts.map +1 -0
  856. package/dist/zod-generator-BQilAboC.mjs +424 -0
  857. package/dist/zod-generator-BQilAboC.mjs.map +1 -0
  858. package/package.json +19 -10
  859. package/src/api/errors.ts +12 -0
  860. package/src/api/handlers/api-tokens.ts +12 -6
  861. package/src/api/handlers/bylines.ts +24 -3
  862. package/src/api/handlers/calendar.ts +246 -0
  863. package/src/api/handlers/content.ts +69 -13
  864. package/src/api/handlers/domain-move-notice.ts +94 -0
  865. package/src/api/handlers/index.ts +2 -0
  866. package/src/api/handlers/manifest.ts +5 -0
  867. package/src/api/handlers/media-allowlist.ts +1 -0
  868. package/src/api/handlers/media-upload.ts +13 -10
  869. package/src/api/handlers/media-usage.ts +2 -1
  870. package/src/api/handlers/media.ts +1 -0
  871. package/src/api/handlers/plugins.ts +21 -29
  872. package/src/api/handlers/redirects.ts +6 -6
  873. package/src/api/handlers/seo.ts +155 -59
  874. package/src/api/handlers/settings.ts +31 -1
  875. package/src/api/handlers/site-domain.ts +143 -0
  876. package/src/api/openapi/document.ts +2 -2
  877. package/src/api/public-url.ts +1 -1
  878. package/src/api/schemas/bylines.ts +3 -1
  879. package/src/api/schemas/content.ts +36 -0
  880. package/src/api/schemas/media-usage.ts +7 -1
  881. package/src/api/schemas/media.ts +12 -0
  882. package/src/api/site-url.ts +53 -5
  883. package/src/api/types.ts +2 -0
  884. package/src/astro/image-endpoint.ts +46 -4
  885. package/src/astro/integration/admin-locales.ts +168 -0
  886. package/src/astro/integration/dev-env.ts +84 -0
  887. package/src/astro/integration/index.ts +67 -10
  888. package/src/astro/integration/routes.ts +25 -0
  889. package/src/astro/integration/runtime.ts +15 -0
  890. package/src/astro/integration/vite-config.ts +29 -1
  891. package/src/astro/middleware/auth.ts +16 -3
  892. package/src/astro/middleware/csp.ts +2 -0
  893. package/src/astro/middleware/redirect.ts +47 -21
  894. package/src/astro/middleware/request-context.ts +64 -31
  895. package/src/astro/middleware.ts +150 -26
  896. package/src/astro/prefetch.ts +10 -3
  897. package/src/astro/routes/api/admin/bylines/[id]/translations.ts +0 -5
  898. package/src/astro/routes/api/admin/bylines/index.ts +1 -1
  899. package/src/astro/routes/api/admin/plugins/[id]/index.ts +1 -0
  900. package/src/astro/routes/api/auth/handover.ts +58 -0
  901. package/src/astro/routes/api/auth/magic-link/verify.ts +11 -3
  902. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +56 -4
  903. package/src/astro/routes/api/auth/oauth/[provider].ts +37 -4
  904. package/src/astro/routes/api/auth/passkey/options.ts +10 -2
  905. package/src/astro/routes/api/calendar.ts +35 -0
  906. package/src/astro/routes/api/import/wordpress/execute.ts +19 -0
  907. package/src/astro/routes/api/import/wordpress/rewrite-url-helpers.ts +80 -42
  908. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +15 -0
  909. package/src/astro/routes/api/manifest.ts +10 -0
  910. package/src/astro/routes/api/media/[id]/confirm.ts +19 -0
  911. package/src/astro/routes/api/media/file/[...key].ts +60 -12
  912. package/src/astro/routes/api/media/upload-url.ts +35 -7
  913. package/src/astro/routes/api/media.ts +24 -5
  914. package/src/astro/routes/api/schema/index.ts +1 -1
  915. package/src/astro/routes/api/settings/domain-notify.ts +76 -0
  916. package/src/astro/routes/api/settings/domain.ts +63 -0
  917. package/src/astro/routes/api/setup/index.ts +21 -2
  918. package/src/astro/routes/api/site/domain-proof.ts +28 -0
  919. package/src/astro/routes/sitemap-[collection].xml.ts +31 -8
  920. package/src/astro/routes/sitemap.xml.ts +12 -10
  921. package/src/astro/types.ts +13 -1
  922. package/src/auth/providers/microsoft-admin.tsx +31 -0
  923. package/src/auth/providers/microsoft.ts +47 -0
  924. package/src/auth/rate-limit.ts +18 -13
  925. package/src/auth/types.ts +7 -0
  926. package/src/aws-sdk.d.ts +2 -1
  927. package/src/cleanup.ts +26 -0
  928. package/src/cli/commands/export-seed.ts +2 -0
  929. package/src/cli/commands/seed.ts +5 -4
  930. package/src/client/index.ts +6 -1
  931. package/src/comments/public-submission.ts +15 -8
  932. package/src/comments/turnstile.ts +6 -1
  933. package/src/components/CommentForm.astro +48 -8
  934. package/src/components/Comments.astro +50 -28
  935. package/src/components/EmDashImage.astro +6 -4
  936. package/src/components/Gallery.astro +4 -3
  937. package/src/components/HtmlBlock.astro +17 -6
  938. package/src/components/HtmlBlockFrame.astro +63 -0
  939. package/src/components/Iframe.astro +141 -0
  940. package/src/components/Image.astro +4 -3
  941. package/src/components/InlinePortableTextEditor.tsx +156 -33
  942. package/src/components/Video.astro +100 -0
  943. package/src/components/WebMcpSearch.astro +80 -0
  944. package/src/components/index.ts +8 -2
  945. package/src/components/inline-code-block.tsx +8 -0
  946. package/src/components/webmcp-search.ts +138 -0
  947. package/src/components/widgets/RecentPosts.astro +57 -17
  948. package/src/config/secrets.ts +27 -15
  949. package/src/content/converters/mark-safety.ts +3 -3
  950. package/src/content/converters/portable-text-identity.ts +2 -0
  951. package/src/content/converters/portable-text-to-prosemirror.ts +43 -2
  952. package/src/content/converters/prosemirror-to-portable-text.ts +44 -2
  953. package/src/content/converters/types.ts +46 -0
  954. package/src/content/converters/video.ts +77 -0
  955. package/src/database/content-datetime.ts +11 -4
  956. package/src/database/datetime-storage.ts +1 -1
  957. package/src/database/migrations/090_redirect_enable_loop_guard.ts +70 -0
  958. package/src/database/migrations/091_redirect_artifacts.ts +141 -0
  959. package/src/database/migrations/runner.ts +17 -1
  960. package/src/database/repositories/comment.ts +17 -3
  961. package/src/database/repositories/content.ts +103 -29
  962. package/src/database/repositories/plugin-storage.ts +28 -19
  963. package/src/database/repositories/redirect.ts +30 -3
  964. package/src/database/repositories/taxonomy.ts +61 -46
  965. package/src/database/repositories/types.ts +2 -0
  966. package/src/database/request-scoped.ts +34 -0
  967. package/src/database/types.ts +23 -0
  968. package/src/db/adapters.ts +2 -0
  969. package/src/emdash-runtime.ts +245 -71
  970. package/src/import/menus.ts +3 -0
  971. package/src/import/sources/wordpress-plugin.ts +3 -2
  972. package/src/import/utils.ts +2 -3
  973. package/src/index.ts +4 -0
  974. package/src/loader.ts +360 -98
  975. package/src/mcp/server.ts +12 -4
  976. package/src/media/image-endpoint.ts +101 -1
  977. package/src/media/mime.ts +21 -0
  978. package/src/media/responsive.ts +14 -7
  979. package/src/media/usage/extractor.ts +19 -2
  980. package/src/media/usage/types.ts +5 -1
  981. package/src/menus/index.ts +30 -26
  982. package/src/plugin-utils.ts +1 -1
  983. package/src/plugins/context.ts +3 -7
  984. package/src/plugins/hooks.ts +11 -1
  985. package/src/plugins/http-route-dispatch.ts +5 -1
  986. package/src/plugins/manager.ts +12 -2
  987. package/src/plugins/manifest-schema.ts +1 -0
  988. package/src/plugins/route-error.ts +14 -0
  989. package/src/plugins/routes.ts +2 -2
  990. package/src/plugins/state.ts +36 -0
  991. package/src/plugins/types.ts +22 -0
  992. package/src/query.ts +20 -29
  993. package/src/redirects/artifacts.ts +460 -0
  994. package/src/redirects/cache.ts +76 -41
  995. package/src/redirects/patterns.ts +26 -2
  996. package/src/request-context.ts +1 -1
  997. package/src/schema/registry.ts +7 -4
  998. package/src/schema/slug.ts +19 -0
  999. package/src/search/text-extraction.ts +6 -1
  1000. package/src/seed/apply.ts +65 -57
  1001. package/src/seed/validate.ts +31 -0
  1002. package/src/seo/sitemap-name.ts +22 -0
  1003. package/src/settings/index.ts +17 -12
  1004. package/src/storage/index.ts +2 -0
  1005. package/src/storage/local.ts +10 -2
  1006. package/src/storage/range.ts +54 -0
  1007. package/src/storage/s3.ts +52 -8
  1008. package/src/storage/types.ts +30 -3
  1009. package/src/transfer/format/columns.ts +3 -0
  1010. package/src/transfer/import/rebuild.ts +17 -2
  1011. package/src/transfer/import/scaffold.ts +16 -9
  1012. package/src/ui.ts +2 -0
  1013. package/src/utils/sanitize.ts +14 -9
  1014. package/src/utils/slugify.ts +6 -1
  1015. package/src/virtual-modules.d.ts +3 -0
  1016. package/src/visual-editing/toolbar.ts +80 -35
  1017. package/src/widgets/components.ts +4 -0
  1018. package/src/widgets/index.ts +74 -82
  1019. package/src/widgets/recent-posts.ts +62 -0
  1020. package/dist/action-token-D2KE1Rqf.mjs +0 -26
  1021. package/dist/action-token-D2KE1Rqf.mjs.map +0 -1
  1022. package/dist/activation-DDuqAat2.mjs +0 -387
  1023. package/dist/activation-DDuqAat2.mjs.map +0 -1
  1024. package/dist/adapters-Ds-1Pmkm.d.mts +0 -171
  1025. package/dist/adapters-Ds-1Pmkm.d.mts.map +0 -1
  1026. package/dist/allowed-origins-D78QvbTO.mjs +0 -116
  1027. package/dist/allowed-origins-D78QvbTO.mjs.map +0 -1
  1028. package/dist/api-BBZlif0y.mjs +0 -4974
  1029. package/dist/api-BBZlif0y.mjs.map +0 -1
  1030. package/dist/api-tokens-BGbfWZVO.mjs +0 -166
  1031. package/dist/api-tokens-BGbfWZVO.mjs.map +0 -1
  1032. package/dist/apply-CDNV4JJ-.mjs +0 -1672
  1033. package/dist/apply-CDNV4JJ-.mjs.map +0 -1
  1034. package/dist/approvals-CVvJSEBF.mjs +0 -460
  1035. package/dist/approvals-CVvJSEBF.mjs.map +0 -1
  1036. package/dist/artifact-fetch-CGK0DQLj.mjs +0 -659
  1037. package/dist/artifact-fetch-CGK0DQLj.mjs.map +0 -1
  1038. package/dist/audit-BszbE_BP.mjs +0 -127
  1039. package/dist/audit-BszbE_BP.mjs.map +0 -1
  1040. package/dist/authoritative-records-ChM8dTeV.mjs +0 -5172
  1041. package/dist/authoritative-records-ChM8dTeV.mjs.map +0 -1
  1042. package/dist/authorize-CTGywswM.mjs +0 -49
  1043. package/dist/authorize-CTGywswM.mjs.map +0 -1
  1044. package/dist/backup-CDrPP8fI.mjs +0 -246
  1045. package/dist/backup-CDrPP8fI.mjs.map +0 -1
  1046. package/dist/base64-DvnNgP7e.mjs +0 -63
  1047. package/dist/base64-DvnNgP7e.mjs.map +0 -1
  1048. package/dist/block-types-nNEaPkvx.mjs +0 -132
  1049. package/dist/block-types-nNEaPkvx.mjs.map +0 -1
  1050. package/dist/block-values-Bho1nsZF.mjs +0 -175
  1051. package/dist/block-values-Bho1nsZF.mjs.map +0 -1
  1052. package/dist/byline-02tu_Uc-.mjs +0 -909
  1053. package/dist/byline-02tu_Uc-.mjs.map +0 -1
  1054. package/dist/byline-fields-BYbTptTU.mjs +0 -280
  1055. package/dist/byline-fields-BYbTptTU.mjs.map +0 -1
  1056. package/dist/byline-fields-BjQH-1z9.mjs +0 -123
  1057. package/dist/byline-fields-BjQH-1z9.mjs.map +0 -1
  1058. package/dist/bylines-VytjeHBI.mjs +0 -214
  1059. package/dist/bylines-VytjeHBI.mjs.map +0 -1
  1060. package/dist/bylines-gyWBWUUc.mjs +0 -150
  1061. package/dist/bylines-gyWBWUUc.mjs.map +0 -1
  1062. package/dist/cache-CPanL9IO.mjs +0 -114
  1063. package/dist/cache-CPanL9IO.mjs.map +0 -1
  1064. package/dist/canonical-CAecl1UQ.mjs +0 -174
  1065. package/dist/canonical-CAecl1UQ.mjs.map +0 -1
  1066. package/dist/capture-triggers-CdZfvHtF.mjs +0 -362
  1067. package/dist/capture-triggers-CdZfvHtF.mjs.map +0 -1
  1068. package/dist/challenge-store-VePApay4.mjs +0 -51
  1069. package/dist/challenge-store-VePApay4.mjs.map +0 -1
  1070. package/dist/checksum-BSIhEAYW.mjs +0 -162
  1071. package/dist/checksum-BSIhEAYW.mjs.map +0 -1
  1072. package/dist/chrome-tags-CKELm-bo.mjs +0 -24
  1073. package/dist/chrome-tags-CKELm-bo.mjs.map +0 -1
  1074. package/dist/chunks-DBmkKmBH.mjs +0 -25
  1075. package/dist/chunks-DBmkKmBH.mjs.map +0 -1
  1076. package/dist/collection-slugs-cache-BNRAPNiu.mjs +0 -85
  1077. package/dist/collection-slugs-cache-BNRAPNiu.mjs.map +0 -1
  1078. package/dist/comment-Cq1UYN8_.mjs +0 -313
  1079. package/dist/comment-Cq1UYN8_.mjs.map +0 -1
  1080. package/dist/comment-reaction-B5sZzSoA.mjs +0 -85
  1081. package/dist/comment-reaction-B5sZzSoA.mjs.map +0 -1
  1082. package/dist/comments-B3F-ETyh.mjs +0 -195
  1083. package/dist/comments-B3F-ETyh.mjs.map +0 -1
  1084. package/dist/comments-zrTgWBSg.mjs +0 -99
  1085. package/dist/comments-zrTgWBSg.mjs.map +0 -1
  1086. package/dist/components-Dbf4Eq16.mjs +0 -108
  1087. package/dist/components-Dbf4Eq16.mjs.map +0 -1
  1088. package/dist/config-BCM5sQP7.d.mts +0 -6688
  1089. package/dist/config-BCM5sQP7.d.mts.map +0 -1
  1090. package/dist/config-CXPcy2iY.mjs +0 -228
  1091. package/dist/config-CXPcy2iY.mjs.map +0 -1
  1092. package/dist/config-CZkZBuBK.d.mts +0 -39
  1093. package/dist/config-CZkZBuBK.d.mts.map +0 -1
  1094. package/dist/connection-C5GIciX9.mjs +0 -36
  1095. package/dist/connection-C5GIciX9.mjs.map +0 -1
  1096. package/dist/content-RzEXY3QX.mjs +0 -2020
  1097. package/dist/content-RzEXY3QX.mjs.map +0 -1
  1098. package/dist/content-list-query-B6P37Ug_.d.mts +0 -26
  1099. package/dist/content-list-query-B6P37Ug_.d.mts.map +0 -1
  1100. package/dist/content-repair-BDVsYXWK.mjs +0 -442
  1101. package/dist/content-repair-BDVsYXWK.mjs.map +0 -1
  1102. package/dist/context-BpTIzY5h.mjs +0 -2026
  1103. package/dist/context-BpTIzY5h.mjs.map +0 -1
  1104. package/dist/credits-JOE92Gr7.mjs +0 -110
  1105. package/dist/credits-JOE92Gr7.mjs.map +0 -1
  1106. package/dist/cron-ktyapbdB.mjs +0 -306
  1107. package/dist/cron-ktyapbdB.mjs.map +0 -1
  1108. package/dist/dashboard-BoV4pwPP.mjs +0 -151
  1109. package/dist/dashboard-BoV4pwPP.mjs.map +0 -1
  1110. package/dist/default-B7KnYwtQ.mjs +0 -81
  1111. package/dist/default-B7KnYwtQ.mjs.map +0 -1
  1112. package/dist/deferred-tasks-eaUIqXj8.d.mts +0 -9
  1113. package/dist/deferred-tasks-eaUIqXj8.d.mts.map +0 -1
  1114. package/dist/dev-typegen-8JlYYFno.mjs +0 -29
  1115. package/dist/dev-typegen-8JlYYFno.mjs.map +0 -1
  1116. package/dist/device-flow-BlV_z24g.mjs +0 -521
  1117. package/dist/device-flow-BlV_z24g.mjs.map +0 -1
  1118. package/dist/digest-DiYAoZpf.mjs +0 -194
  1119. package/dist/digest-DiYAoZpf.mjs.map +0 -1
  1120. package/dist/direct-executor-Db8xA3zg.mjs +0 -104
  1121. package/dist/direct-executor-Db8xA3zg.mjs.map +0 -1
  1122. package/dist/email-console-Dm78wSmg.mjs +0 -50
  1123. package/dist/email-console-Dm78wSmg.mjs.map +0 -1
  1124. package/dist/email-locale-B4X9LXe9.mjs +0 -25
  1125. package/dist/email-locale-B4X9LXe9.mjs.map +0 -1
  1126. package/dist/emdash-runtime-BakQ6io7.mjs +0 -4239
  1127. package/dist/emdash-runtime-BakQ6io7.mjs.map +0 -1
  1128. package/dist/enrich-BDdVNeDK.mjs +0 -194
  1129. package/dist/enrich-BDdVNeDK.mjs.map +0 -1
  1130. package/dist/entry-lock-DY8B-xcr.d.mts +0 -4544
  1131. package/dist/entry-lock-DY8B-xcr.d.mts.map +0 -1
  1132. package/dist/entry-lock-DrUAdTzf.mjs +0 -163
  1133. package/dist/entry-lock-DrUAdTzf.mjs.map +0 -1
  1134. package/dist/entry-lock-yIkBduqJ.mjs +0 -1180
  1135. package/dist/entry-lock-yIkBduqJ.mjs.map +0 -1
  1136. package/dist/env-types-DkHYR2pl.mjs +0 -38
  1137. package/dist/env-types-DkHYR2pl.mjs.map +0 -1
  1138. package/dist/error-DIYXAVk4.mjs +0 -90
  1139. package/dist/error-DIYXAVk4.mjs.map +0 -1
  1140. package/dist/errors-CNvATh_7.mjs +0 -469
  1141. package/dist/errors-CNvATh_7.mjs.map +0 -1
  1142. package/dist/errors-CjXd1LgH.mjs +0 -120
  1143. package/dist/errors-CjXd1LgH.mjs.map +0 -1
  1144. package/dist/escape-B1GM0yJU.mjs +0 -9
  1145. package/dist/escape-B1GM0yJU.mjs.map +0 -1
  1146. package/dist/fence-8MaKKWhp.mjs +0 -162
  1147. package/dist/fence-8MaKKWhp.mjs.map +0 -1
  1148. package/dist/field-defs-cache-DEkFYCDE.mjs +0 -77
  1149. package/dist/field-defs-cache-DEkFYCDE.mjs.map +0 -1
  1150. package/dist/field-map-D7ioN0r0.mjs +0 -83
  1151. package/dist/field-map-D7ioN0r0.mjs.map +0 -1
  1152. package/dist/fts-manager-DU03MxWu.mjs +0 -443
  1153. package/dist/fts-manager-DU03MxWu.mjs.map +0 -1
  1154. package/dist/gc-DMiE7ezk.mjs +0 -75
  1155. package/dist/gc-DMiE7ezk.mjs.map +0 -1
  1156. package/dist/hash-CY4QdeMJ.mjs +0 -37
  1157. package/dist/hash-CY4QdeMJ.mjs.map +0 -1
  1158. package/dist/hook-result-Cb67D3P3.d.mts +0 -31
  1159. package/dist/hook-result-Cb67D3P3.d.mts.map +0 -1
  1160. package/dist/hreflang-Bterc3b7.mjs +0 -105
  1161. package/dist/hreflang-Bterc3b7.mjs.map +0 -1
  1162. package/dist/hreflang-uIBOE5yg.d.mts +0 -50
  1163. package/dist/hreflang-uIBOE5yg.d.mts.map +0 -1
  1164. package/dist/http-route-dispatch-DubjTibD.mjs +0 -339
  1165. package/dist/http-route-dispatch-DubjTibD.mjs.map +0 -1
  1166. package/dist/identity-DJ-5AcdG.mjs +0 -35
  1167. package/dist/identity-DJ-5AcdG.mjs.map +0 -1
  1168. package/dist/import-DEfuIgRz.mjs +0 -2020
  1169. package/dist/import-DEfuIgRz.mjs.map +0 -1
  1170. package/dist/index-xCy3j0f6.d.mts +0 -623
  1171. package/dist/index-xCy3j0f6.d.mts.map +0 -1
  1172. package/dist/init-lock-4eRRB4Le.mjs +0 -56
  1173. package/dist/init-lock-4eRRB4Le.mjs.map +0 -1
  1174. package/dist/install-finalization-DeGRbaVa.mjs +0 -58
  1175. package/dist/install-finalization-DeGRbaVa.mjs.map +0 -1
  1176. package/dist/keys-DWwMxdZh.mjs +0 -61
  1177. package/dist/keys-DWwMxdZh.mjs.map +0 -1
  1178. package/dist/kinds-D1A-00-F.mjs +0 -974
  1179. package/dist/kinds-D1A-00-F.mjs.map +0 -1
  1180. package/dist/lifecycle-BWtBGNEn.mjs +0 -25
  1181. package/dist/lifecycle-BWtBGNEn.mjs.map +0 -1
  1182. package/dist/load-BR1NEa_3.mjs +0 -28
  1183. package/dist/load-BR1NEa_3.mjs.map +0 -1
  1184. package/dist/loader-D4edocWH.mjs +0 -1197
  1185. package/dist/loader-D4edocWH.mjs.map +0 -1
  1186. package/dist/loops-DLaHFrvI.mjs +0 -205
  1187. package/dist/loops-DLaHFrvI.mjs.map +0 -1
  1188. package/dist/manifest-builder-8jsSLR7s.mjs +0 -189
  1189. package/dist/manifest-builder-8jsSLR7s.mjs.map +0 -1
  1190. package/dist/manifest-schema-DcZjRNEv.mjs +0 -496
  1191. package/dist/manifest-schema-DcZjRNEv.mjs.map +0 -1
  1192. package/dist/marketplace-CNxjq10S.mjs +0 -257
  1193. package/dist/marketplace-CNxjq10S.mjs.map +0 -1
  1194. package/dist/media-3v7mqAVX.mjs +0 -294
  1195. package/dist/media-3v7mqAVX.mjs.map +0 -1
  1196. package/dist/media-Bs6qmlVl.mjs +0 -408
  1197. package/dist/media-Bs6qmlVl.mjs.map +0 -1
  1198. package/dist/media-CputjGE1.mjs +0 -373
  1199. package/dist/media-CputjGE1.mjs.map +0 -1
  1200. package/dist/media-allowlist-isqF1gAh.mjs +0 -44
  1201. package/dist/media-allowlist-isqF1gAh.mjs.map +0 -1
  1202. package/dist/media-folders-D2VdVBf6.mjs +0 -210
  1203. package/dist/media-folders-D2VdVBf6.mjs.map +0 -1
  1204. package/dist/media-url-DbkMY3y6.mjs +0 -43
  1205. package/dist/media-url-DbkMY3y6.mjs.map +0 -1
  1206. package/dist/media-usage-activation-BaT4AlNI.mjs +0 -78
  1207. package/dist/media-usage-activation-BaT4AlNI.mjs.map +0 -1
  1208. package/dist/media-usage-v43L0kR_.mjs +0 -282
  1209. package/dist/media-usage-v43L0kR_.mjs.map +0 -1
  1210. package/dist/media-usage-work-CY8gIeU-.mjs +0 -151
  1211. package/dist/media-usage-work-CY8gIeU-.mjs.map +0 -1
  1212. package/dist/media-usage-work-VO108Q9E.mjs +0 -1015
  1213. package/dist/media-usage-work-VO108Q9E.mjs.map +0 -1
  1214. package/dist/menus-BYyeRemR.mjs +0 -3647
  1215. package/dist/menus-BYyeRemR.mjs.map +0 -1
  1216. package/dist/menus-mC_XTxD7.mjs +0 -92
  1217. package/dist/menus-mC_XTxD7.mjs.map +0 -1
  1218. package/dist/menus-trvc6_fW.mjs +0 -753
  1219. package/dist/menus-trvc6_fW.mjs.map +0 -1
  1220. package/dist/mime-IZf-LHIS.mjs +0 -36
  1221. package/dist/mime-IZf-LHIS.mjs.map +0 -1
  1222. package/dist/mode-B9-gMXL9.mjs +0 -23
  1223. package/dist/mode-B9-gMXL9.mjs.map +0 -1
  1224. package/dist/node-sqlite-compat-DztcWs4y.mjs +0 -63
  1225. package/dist/node-sqlite-compat-DztcWs4y.mjs.map +0 -1
  1226. package/dist/oauth-authorization-BIHy9SGU.mjs +0 -274
  1227. package/dist/oauth-authorization-BIHy9SGU.mjs.map +0 -1
  1228. package/dist/oauth-clients-BZWZvKXa.mjs +0 -266
  1229. package/dist/oauth-clients-BZWZvKXa.mjs.map +0 -1
  1230. package/dist/oauth-state-store-CxXTjXdI.mjs +0 -50
  1231. package/dist/oauth-state-store-CxXTjXdI.mjs.map +0 -1
  1232. package/dist/oauth-user-lookup-GWojfxRl.mjs +0 -26
  1233. package/dist/oauth-user-lookup-GWojfxRl.mjs.map +0 -1
  1234. package/dist/options-DRF6dlXY.d.mts +0 -81
  1235. package/dist/options-DRF6dlXY.d.mts.map +0 -1
  1236. package/dist/ownership-Bd77AmJz.mjs +0 -12
  1237. package/dist/ownership-Bd77AmJz.mjs.map +0 -1
  1238. package/dist/parse-5Y0W39xR.mjs +0 -81
  1239. package/dist/parse-5Y0W39xR.mjs.map +0 -1
  1240. package/dist/parse-BPblgoa-.d.mts +0 -172
  1241. package/dist/parse-BPblgoa-.d.mts.map +0 -1
  1242. package/dist/passkey-config-PiQ5cBnt.mjs +0 -46
  1243. package/dist/passkey-config-PiQ5cBnt.mjs.map +0 -1
  1244. package/dist/paths-DkS74lBM.mjs +0 -77
  1245. package/dist/paths-DkS74lBM.mjs.map +0 -1
  1246. package/dist/patterns-DyZJ67I7.mjs +0 -140
  1247. package/dist/patterns-DyZJ67I7.mjs.map +0 -1
  1248. package/dist/placeholder-Bez2282x.d.mts +0 -306
  1249. package/dist/placeholder-Bez2282x.d.mts.map +0 -1
  1250. package/dist/plan-Lw7iGnGD.mjs +0 -135
  1251. package/dist/plan-Lw7iGnGD.mjs.map +0 -1
  1252. package/dist/plugins-D7xSh1Lu.mjs +0 -277
  1253. package/dist/plugins-D7xSh1Lu.mjs.map +0 -1
  1254. package/dist/policy-DMRiMdLn.mjs +0 -45
  1255. package/dist/policy-DMRiMdLn.mjs.map +0 -1
  1256. package/dist/portable-text-kcyN3F-a.mjs +0 -307
  1257. package/dist/portable-text-kcyN3F-a.mjs.map +0 -1
  1258. package/dist/preview--2VDLaND.mjs +0 -107
  1259. package/dist/preview--2VDLaND.mjs.map +0 -1
  1260. package/dist/protocol-FvwLA8P-.d.mts +0 -61
  1261. package/dist/protocol-FvwLA8P-.d.mts.map +0 -1
  1262. package/dist/public-submission-BRyK76U8.mjs +0 -250
  1263. package/dist/public-submission-BRyK76U8.mjs.map +0 -1
  1264. package/dist/public-url-7j0cpCFc.mjs +0 -101
  1265. package/dist/public-url-7j0cpCFc.mjs.map +0 -1
  1266. package/dist/query-BRNTde3V.mjs +0 -41
  1267. package/dist/query-BRNTde3V.mjs.map +0 -1
  1268. package/dist/query-DyYYWOKk.mjs +0 -1161
  1269. package/dist/query-DyYYWOKk.mjs.map +0 -1
  1270. package/dist/rate-limit-D0BcE76H.mjs +0 -120
  1271. package/dist/rate-limit-D0BcE76H.mjs.map +0 -1
  1272. package/dist/receipt-C4icyHlC.mjs +0 -43
  1273. package/dist/receipt-C4icyHlC.mjs.map +0 -1
  1274. package/dist/redirect-9DbtxSNG.mjs +0 -19
  1275. package/dist/redirect-9DbtxSNG.mjs.map +0 -1
  1276. package/dist/redirect-BvFKh8Sz.mjs +0 -416
  1277. package/dist/redirect-BvFKh8Sz.mjs.map +0 -1
  1278. package/dist/redirects-1nhdEaTq.mjs +0 -148
  1279. package/dist/redirects-1nhdEaTq.mjs.map +0 -1
  1280. package/dist/redirects-D1yMnSR9.mjs +0 -446
  1281. package/dist/redirects-D1yMnSR9.mjs.map +0 -1
  1282. package/dist/registry-CzPJNu3H.mjs +0 -8366
  1283. package/dist/registry-CzPJNu3H.mjs.map +0 -1
  1284. package/dist/relations-C8JpSkU6.mjs +0 -776
  1285. package/dist/relations-C8JpSkU6.mjs.map +0 -1
  1286. package/dist/request-meta-Bs60XW1m.mjs +0 -141
  1287. package/dist/request-meta-Bs60XW1m.mjs.map +0 -1
  1288. package/dist/resolve-BHWgMU_X.mjs +0 -100
  1289. package/dist/resolve-BHWgMU_X.mjs.map +0 -1
  1290. package/dist/revision-CGkQA0e5.mjs +0 -366
  1291. package/dist/revision-CGkQA0e5.mjs.map +0 -1
  1292. package/dist/route-wire-ClUVQduA.mjs +0 -197
  1293. package/dist/route-wire-ClUVQduA.mjs.map +0 -1
  1294. package/dist/routes-D2GFl3B7.mjs +0 -272
  1295. package/dist/routes-D2GFl3B7.mjs.map +0 -1
  1296. package/dist/runner-CLpxmhl8.mjs +0 -6197
  1297. package/dist/runner-CLpxmhl8.mjs.map +0 -1
  1298. package/dist/runner-CWl76CH3.d.mts +0 -68
  1299. package/dist/runner-CWl76CH3.d.mts.map +0 -1
  1300. package/dist/schema-27XefSYG.mjs +0 -13
  1301. package/dist/schema-27XefSYG.mjs.map +0 -1
  1302. package/dist/schema-Btvj3BMh.mjs +0 -815
  1303. package/dist/schema-Btvj3BMh.mjs.map +0 -1
  1304. package/dist/scopes-DGCj6K4p.mjs +0 -34
  1305. package/dist/scopes-DGCj6K4p.mjs.map +0 -1
  1306. package/dist/search-pZRRmWjh.mjs +0 -448
  1307. package/dist/search-pZRRmWjh.mjs.map +0 -1
  1308. package/dist/secrets-CIi0nFiR.mjs +0 -341
  1309. package/dist/secrets-CIi0nFiR.mjs.map +0 -1
  1310. package/dist/sections-CIhqs3Ao.mjs +0 -346
  1311. package/dist/sections-CIhqs3Ao.mjs.map +0 -1
  1312. package/dist/seo-DifeiGdl.mjs +0 -114
  1313. package/dist/seo-DifeiGdl.mjs.map +0 -1
  1314. package/dist/seo-DpYxmGaL.mjs +0 -133
  1315. package/dist/seo-DpYxmGaL.mjs.map +0 -1
  1316. package/dist/service-COVdVpSK.mjs +0 -150
  1317. package/dist/service-COVdVpSK.mjs.map +0 -1
  1318. package/dist/session-user-C6IEjuty.mjs +0 -61
  1319. package/dist/session-user-C6IEjuty.mjs.map +0 -1
  1320. package/dist/settings-CwcrX-Ay.mjs +0 -61
  1321. package/dist/settings-CwcrX-Ay.mjs.map +0 -1
  1322. package/dist/settings-D_cJtT48.mjs +0 -439
  1323. package/dist/settings-D_cJtT48.mjs.map +0 -1
  1324. package/dist/settings-tnPQN3Z2.mjs +0 -51
  1325. package/dist/settings-tnPQN3Z2.mjs.map +0 -1
  1326. package/dist/setup-complete-BOrI10UY.mjs +0 -65
  1327. package/dist/setup-complete-BOrI10UY.mjs.map +0 -1
  1328. package/dist/setup-nonce-0XTBLTsX.mjs +0 -25
  1329. package/dist/setup-nonce-0XTBLTsX.mjs.map +0 -1
  1330. package/dist/single-flight-cache-B5O2qhO1.mjs +0 -104
  1331. package/dist/single-flight-cache-B5O2qhO1.mjs.map +0 -1
  1332. package/dist/site-settings-B7vGFRDT.mjs +0 -50
  1333. package/dist/site-settings-B7vGFRDT.mjs.map +0 -1
  1334. package/dist/site-url-wEYRMHBv.mjs +0 -16
  1335. package/dist/site-url-wEYRMHBv.mjs.map +0 -1
  1336. package/dist/slugify-T5GHH42D.mjs +0 -17
  1337. package/dist/slugify-T5GHH42D.mjs.map +0 -1
  1338. package/dist/snapshot-W36KbLmc.mjs +0 -414
  1339. package/dist/snapshot-W36KbLmc.mjs.map +0 -1
  1340. package/dist/ssrf-CRJ-xom5.mjs +0 -406
  1341. package/dist/ssrf-CRJ-xom5.mjs.map +0 -1
  1342. package/dist/stage-DA0NrTRZ.mjs +0 -662
  1343. package/dist/stage-DA0NrTRZ.mjs.map +0 -1
  1344. package/dist/staged-Bw5eHbKS.mjs +0 -686
  1345. package/dist/staged-Bw5eHbKS.mjs.map +0 -1
  1346. package/dist/state-BTlprvUF.mjs +0 -153
  1347. package/dist/state-BTlprvUF.mjs.map +0 -1
  1348. package/dist/status-C6IrSLMT.mjs +0 -30
  1349. package/dist/status-C6IrSLMT.mjs.map +0 -1
  1350. package/dist/storage-query-CdVF2bng.d.mts +0 -1614
  1351. package/dist/storage-query-CdVF2bng.d.mts.map +0 -1
  1352. package/dist/tar-BGOZARjy.mjs +0 -449
  1353. package/dist/tar-BGOZARjy.mjs.map +0 -1
  1354. package/dist/target-YhYH_0uc.mjs +0 -27
  1355. package/dist/target-YhYH_0uc.mjs.map +0 -1
  1356. package/dist/taxonomies-DK_XBrmT.mjs +0 -697
  1357. package/dist/taxonomies-DK_XBrmT.mjs.map +0 -1
  1358. package/dist/taxonomies-S1M3rUC0.mjs +0 -939
  1359. package/dist/taxonomies-S1M3rUC0.mjs.map +0 -1
  1360. package/dist/taxonomy-BesdHIwi.mjs +0 -525
  1361. package/dist/taxonomy-BesdHIwi.mjs.map +0 -1
  1362. package/dist/tokens-B_ffPF1q.mjs +0 -171
  1363. package/dist/tokens-B_ffPF1q.mjs.map +0 -1
  1364. package/dist/transfer-9fVSxyrV.mjs +0 -166
  1365. package/dist/transfer-9fVSxyrV.mjs.map +0 -1
  1366. package/dist/transfer-B7LUTaYD.mjs +0 -8855
  1367. package/dist/transfer-B7LUTaYD.mjs.map +0 -1
  1368. package/dist/transfer-download-BdNq4VWN.mjs +0 -33
  1369. package/dist/transfer-download-BdNq4VWN.mjs.map +0 -1
  1370. package/dist/transformations-BtQdvyly.mjs +0 -196
  1371. package/dist/transformations-BtQdvyly.mjs.map +0 -1
  1372. package/dist/transport-CriYXY1c.mjs +0 -136
  1373. package/dist/transport-CriYXY1c.mjs.map +0 -1
  1374. package/dist/transport-SnhS6xku.d.mts +0 -42
  1375. package/dist/transport-SnhS6xku.d.mts.map +0 -1
  1376. package/dist/trusted-proxy-C0eHXPd-.mjs +0 -51
  1377. package/dist/trusted-proxy-C0eHXPd-.mjs.map +0 -1
  1378. package/dist/turnstile-BNPrWd1e.mjs +0 -53
  1379. package/dist/turnstile-BNPrWd1e.mjs.map +0 -1
  1380. package/dist/types-B8sF_kE5.d.mts +0 -287
  1381. package/dist/types-B8sF_kE5.d.mts.map +0 -1
  1382. package/dist/types-BYVIYOlD.d.mts +0 -1720
  1383. package/dist/types-BYVIYOlD.d.mts.map +0 -1
  1384. package/dist/types-Bs4bi95j.d.mts +0 -374
  1385. package/dist/types-Bs4bi95j.d.mts.map +0 -1
  1386. package/dist/types-CGuODCZi.d.mts +0 -198
  1387. package/dist/types-CGuODCZi.d.mts.map +0 -1
  1388. package/dist/types-CVsmpTcU.mjs +0 -18
  1389. package/dist/types-CVsmpTcU.mjs.map +0 -1
  1390. package/dist/types-ClFEExxn.mjs +0 -37
  1391. package/dist/types-ClFEExxn.mjs.map +0 -1
  1392. package/dist/types-D994zUWB.d.mts +0 -85
  1393. package/dist/types-D994zUWB.d.mts.map +0 -1
  1394. package/dist/types-DAj1ByJQ.d.mts +0 -125
  1395. package/dist/types-DAj1ByJQ.d.mts.map +0 -1
  1396. package/dist/types-Dlv6esp4.mjs +0 -77
  1397. package/dist/types-Dlv6esp4.mjs.map +0 -1
  1398. package/dist/types-Dr1LVwL7.d.mts +0 -363
  1399. package/dist/types-Dr1LVwL7.d.mts.map +0 -1
  1400. package/dist/types-MN9bOQ1g.d.mts +0 -198
  1401. package/dist/types-MN9bOQ1g.d.mts.map +0 -1
  1402. package/dist/types-d2Szb1oz.mjs +0 -16
  1403. package/dist/types-d2Szb1oz.mjs.map +0 -1
  1404. package/dist/types-ibtP7GEA.d.mts +0 -896
  1405. package/dist/types-ibtP7GEA.d.mts.map +0 -1
  1406. package/dist/types-j6MBDjlZ.mjs +0 -103
  1407. package/dist/types-j6MBDjlZ.mjs.map +0 -1
  1408. package/dist/update-check-D8No-E5s.mjs +0 -161
  1409. package/dist/update-check-D8No-E5s.mjs.map +0 -1
  1410. package/dist/upload-attempts-BodUoFBu.mjs +0 -32
  1411. package/dist/upload-attempts-BodUoFBu.mjs.map +0 -1
  1412. package/dist/url-pattern-DGAG6ZP2.mjs +0 -41
  1413. package/dist/url-pattern-DGAG6ZP2.mjs.map +0 -1
  1414. package/dist/user-BOvuF1sQ.mjs +0 -171
  1415. package/dist/user-BOvuF1sQ.mjs.map +0 -1
  1416. package/dist/utils-Dr01wRKt.mjs +0 -439
  1417. package/dist/utils-Dr01wRKt.mjs.map +0 -1
  1418. package/dist/validate-BttYU7NK.mjs +0 -516
  1419. package/dist/validate-BttYU7NK.mjs.map +0 -1
  1420. package/dist/validate-Df09inbC.d.mts +0 -468
  1421. package/dist/validate-Df09inbC.d.mts.map +0 -1
  1422. package/dist/validation-DH2WRwWO.mjs +0 -219
  1423. package/dist/validation-DH2WRwWO.mjs.map +0 -1
  1424. package/dist/version-BbygH8CT.mjs +0 -7
  1425. package/dist/version-BbygH8CT.mjs.map +0 -1
  1426. package/dist/version-CseoDDOd.mjs +0 -9
  1427. package/dist/version-CseoDDOd.mjs.map +0 -1
  1428. package/dist/virtual-modules-82GlnQyG.mjs +0 -516
  1429. package/dist/virtual-modules-82GlnQyG.mjs.map +0 -1
  1430. package/dist/widgets-DMAgGcQt.mjs +0 -126
  1431. package/dist/widgets-DMAgGcQt.mjs.map +0 -1
  1432. package/dist/wxr-taxonomies-Bi5kFSxQ.mjs +0 -453
  1433. package/dist/wxr-taxonomies-Bi5kFSxQ.mjs.map +0 -1
  1434. package/dist/wxr-taxonomies-y_FpYlDn.d.mts +0 -34
  1435. package/dist/wxr-taxonomies-y_FpYlDn.d.mts.map +0 -1
  1436. package/dist/zod-generator-DnfG5sGQ.mjs +0 -424
  1437. package/dist/zod-generator-DnfG5sGQ.mjs.map +0 -1
  1438. /package/dist/{api-tokens-B4COohsb.mjs → api-tokens-D2zgAIEt.mjs} +0 -0
  1439. /package/dist/{ssrf-sC4_5rxm.mjs → ssrf-BvNItdxk.mjs} +0 -0
@@ -0,0 +1,257 @@
1
+ import { a as pluginManifestSchema, o as reconcileManifestAccess } from "./manifest-schema-BiFBPEsp.mjs";
2
+ import { createGzipDecoder, unpackTar } from "modern-tar";
3
+
4
+ //#region src/plugins/marketplace.ts
5
+ /**
6
+ * MarketplaceClient — HTTP client for the EmDash Plugin Marketplace
7
+ *
8
+ * Used by the install/update/proxy endpoints in EmDash core to communicate
9
+ * with the marketplace Worker. The marketplace is a distribution channel,
10
+ * not a runtime dependency — bundles are copied to site-local R2 at install time.
11
+ */
12
+ const TRAILING_SLASHES = /\/+$/;
13
+ const LEADING_DOT_SLASH = /^\.\//;
14
+ var MarketplaceError = class extends Error {
15
+ constructor(message, status, code) {
16
+ super(message);
17
+ this.status = status;
18
+ this.code = code;
19
+ this.name = "MarketplaceError";
20
+ }
21
+ };
22
+ var MarketplaceUnavailableError = class extends MarketplaceError {
23
+ constructor(cause) {
24
+ super("Plugin marketplace is unavailable", void 0, "MARKETPLACE_UNAVAILABLE");
25
+ if (cause) this.cause = cause;
26
+ }
27
+ };
28
+ const MAX_REDIRECTS = 5;
29
+ /**
30
+ * Fetches a marketplace URL, following redirects only while they stay on
31
+ * that URL's origin. Throws a `MarketplaceError` coded
32
+ * `${codePrefix}_REDIRECT_UNTRUSTED` or `${codePrefix}_TOO_MANY_REDIRECTS`.
33
+ */
34
+ async function fetchWithinOrigin(url, label, codePrefix) {
35
+ const origin = new URL(url).origin;
36
+ let currentUrl = url;
37
+ let response = await fetch(currentUrl, { redirect: "manual" });
38
+ for (let i = 0; i < MAX_REDIRECTS; i++) {
39
+ if (response.status < 300 || response.status >= 400) break;
40
+ const location = response.headers.get("location");
41
+ if (!location) break;
42
+ const target = new URL(location, currentUrl);
43
+ if (target.origin !== origin) throw new MarketplaceError(`${label} redirected to untrusted host: ${target.origin}`, response.status, `${codePrefix}_REDIRECT_UNTRUSTED`);
44
+ currentUrl = target.href;
45
+ response = await fetch(currentUrl, { redirect: "manual" });
46
+ }
47
+ if (response.status >= 300 && response.status < 400) throw new MarketplaceError(`${label} exceeded maximum redirects (${MAX_REDIRECTS})`, response.status, `${codePrefix}_TOO_MANY_REDIRECTS`);
48
+ return response;
49
+ }
50
+ var MarketplaceClientImpl = class {
51
+ baseUrl;
52
+ siteOrigin;
53
+ constructor(baseUrl, siteOrigin) {
54
+ this.baseUrl = baseUrl.replace(TRAILING_SLASHES, "");
55
+ this.siteOrigin = siteOrigin;
56
+ }
57
+ async search(query, opts) {
58
+ const params = new URLSearchParams();
59
+ if (query) params.set("q", query);
60
+ if (opts?.category) params.set("category", opts.category);
61
+ if (opts?.capability) params.set("capability", opts.capability);
62
+ if (opts?.sort) params.set("sort", opts.sort);
63
+ if (opts?.cursor) params.set("cursor", opts.cursor);
64
+ if (opts?.limit) params.set("limit", String(opts.limit));
65
+ const qs = params.toString();
66
+ const url = `${this.baseUrl}/api/v1/plugins${qs ? `?${qs}` : ""}`;
67
+ return await this.fetchJson(url);
68
+ }
69
+ async getPlugin(id) {
70
+ const url = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}`;
71
+ return this.fetchJson(url);
72
+ }
73
+ async getVersions(id) {
74
+ const url = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}/versions`;
75
+ return (await this.fetchJson(url)).items;
76
+ }
77
+ async downloadBundle(id, version) {
78
+ const bundleUrl = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}/versions/${encodeURIComponent(version)}/bundle`;
79
+ let response;
80
+ try {
81
+ response = await fetchWithinOrigin(bundleUrl, "Bundle download", "BUNDLE");
82
+ } catch (err) {
83
+ if (err instanceof MarketplaceError) throw err;
84
+ throw new MarketplaceUnavailableError(err);
85
+ }
86
+ if (!response.ok) throw new MarketplaceError(`Failed to download bundle: ${response.status} ${response.statusText}`, response.status, "BUNDLE_DOWNLOAD_FAILED");
87
+ const tarballBytes = new Uint8Array(await response.arrayBuffer());
88
+ try {
89
+ return await extractBundle(tarballBytes);
90
+ } catch (err) {
91
+ if (err instanceof MarketplaceError) throw err;
92
+ throw new MarketplaceError("Failed to extract plugin bundle", void 0, "BUNDLE_EXTRACT_FAILED");
93
+ }
94
+ }
95
+ async reportInstall(id, version) {
96
+ const siteHash = await generateSiteHash(this.siteOrigin);
97
+ const url = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}/installs`;
98
+ try {
99
+ await fetch(url, {
100
+ method: "POST",
101
+ headers: { "Content-Type": "application/json" },
102
+ body: JSON.stringify({
103
+ siteHash,
104
+ version
105
+ })
106
+ });
107
+ } catch {}
108
+ }
109
+ async searchThemes(query, opts) {
110
+ const params = new URLSearchParams();
111
+ if (query) params.set("q", query);
112
+ if (opts?.keyword) params.set("keyword", opts.keyword);
113
+ if (opts?.sort) params.set("sort", opts.sort);
114
+ if (opts?.cursor) params.set("cursor", opts.cursor);
115
+ if (opts?.limit) params.set("limit", String(opts.limit));
116
+ const qs = params.toString();
117
+ const url = `${this.baseUrl}/api/v1/themes${qs ? `?${qs}` : ""}`;
118
+ return this.fetchJson(url);
119
+ }
120
+ async getTheme(id) {
121
+ const url = `${this.baseUrl}/api/v1/themes/${encodeURIComponent(id)}`;
122
+ return this.fetchJson(url);
123
+ }
124
+ async fetchJson(url) {
125
+ let response;
126
+ try {
127
+ response = await fetch(url, { headers: { Accept: "application/json" } });
128
+ } catch (err) {
129
+ throw new MarketplaceUnavailableError(err);
130
+ }
131
+ if (!response.ok) {
132
+ let errorMessage = `Marketplace request failed: ${response.status}`;
133
+ try {
134
+ const body = await response.json();
135
+ if (body.error) errorMessage = body.error;
136
+ } catch {}
137
+ throw new MarketplaceError(errorMessage, response.status);
138
+ }
139
+ return await response.json();
140
+ }
141
+ };
142
+ /**
143
+ * Extract manifest + code files from a tarball.
144
+ *
145
+ * The tarball is a gzipped tar archive containing:
146
+ * - manifest.json
147
+ * - backend.js
148
+ * - admin.js (optional)
149
+ *
150
+ * We use a minimal tar parser since we only need to read a few small files.
151
+ */
152
+ /**
153
+ * Exported so the experimental registry install handler can reuse the
154
+ * same parse / validate / hash primitive. Despite the file name, this
155
+ * function predates the marketplace-vs-registry split and is generic
156
+ * over plugin bundle tarballs regardless of distribution channel.
157
+ */
158
+ const MAX_DECOMPRESSED_BUNDLE_BYTES = 256 * 1024;
159
+ const MAX_BUNDLE_TAR_ENTRIES = 32;
160
+ async function extractBundle(tarballBytes) {
161
+ const reader = new ReadableStream({ start(controller) {
162
+ controller.enqueue(tarballBytes);
163
+ controller.close();
164
+ } }).pipeThrough(createGzipDecoder()).getReader();
165
+ const chunks = [];
166
+ let total = 0;
167
+ while (true) {
168
+ const { done, value } = await reader.read();
169
+ if (done) break;
170
+ if (!value) continue;
171
+ total += value.byteLength;
172
+ if (total > MAX_DECOMPRESSED_BUNDLE_BYTES) {
173
+ try {
174
+ await reader.cancel();
175
+ } catch {}
176
+ throw new MarketplaceError(`Bundle decompressed size exceeds limit (${MAX_DECOMPRESSED_BUNDLE_BYTES} bytes)`, void 0, "INVALID_BUNDLE");
177
+ }
178
+ chunks.push(value);
179
+ }
180
+ const decompressedBytes = new Uint8Array(total);
181
+ {
182
+ let offset = 0;
183
+ for (const chunk of chunks) {
184
+ decompressedBytes.set(chunk, offset);
185
+ offset += chunk.byteLength;
186
+ }
187
+ }
188
+ const entries = await unpackTar(new ReadableStream({ start(controller) {
189
+ controller.enqueue(decompressedBytes);
190
+ controller.close();
191
+ } }));
192
+ if (entries.length > MAX_BUNDLE_TAR_ENTRIES) throw new MarketplaceError(`Bundle has too many tar entries (${entries.length} > ${MAX_BUNDLE_TAR_ENTRIES})`, void 0, "INVALID_BUNDLE");
193
+ const decoder = new TextDecoder();
194
+ const files = /* @__PURE__ */ new Map();
195
+ for (const entry of entries) if (entry.data && entry.header.type === "file") {
196
+ const name = entry.header.name.replace(LEADING_DOT_SLASH, "");
197
+ files.set(name, decoder.decode(entry.data));
198
+ }
199
+ const manifestJson = files.get("manifest.json");
200
+ const backendCode = files.get("backend.js");
201
+ if (!manifestJson) throw new MarketplaceError("Invalid bundle: missing manifest.json", void 0, "INVALID_BUNDLE");
202
+ if (!backendCode) throw new MarketplaceError("Invalid bundle: missing backend.js", void 0, "INVALID_BUNDLE");
203
+ let manifest;
204
+ try {
205
+ const parsed = JSON.parse(manifestJson);
206
+ const result = pluginManifestSchema.safeParse(parsed);
207
+ if (!result.success) throw new MarketplaceError("Invalid bundle: manifest.json failed validation", void 0, "INVALID_BUNDLE");
208
+ manifest = reconcileManifestAccess(result.data);
209
+ } catch (err) {
210
+ if (err instanceof MarketplaceError) throw err;
211
+ throw new MarketplaceError("Invalid bundle: malformed manifest.json", void 0, "INVALID_BUNDLE");
212
+ }
213
+ const hashBuffer = await crypto.subtle.digest("SHA-256", tarballBytes);
214
+ const hashArray = new Uint8Array(hashBuffer);
215
+ const checksum = Array.from(hashArray, (b) => b.toString(16).padStart(2, "0")).join("");
216
+ return {
217
+ manifest,
218
+ backendCode,
219
+ adminCode: files.get("admin.js"),
220
+ checksum
221
+ };
222
+ }
223
+ /**
224
+ * Generate a stable non-identifying site hash from the site origin.
225
+ * The same origin always produces the same hash, so the marketplace
226
+ * installs table deduplicates correctly per (plugin_id, site_hash).
227
+ */
228
+ async function generateSiteHash(siteOrigin) {
229
+ const seed = siteOrigin ? `emdash-site:${siteOrigin}` : `emdash-anonymous`;
230
+ try {
231
+ const hash = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(seed));
232
+ const arr = new Uint8Array(hash);
233
+ return Array.from(arr.slice(0, 8), (b) => b.toString(16).padStart(2, "0")).join("");
234
+ } catch {
235
+ let h = 2166136261;
236
+ for (let i = 0; i < seed.length; i++) {
237
+ h ^= seed.charCodeAt(i);
238
+ h = Math.imul(h, 16777619);
239
+ }
240
+ const h2 = h ^ h >>> 16;
241
+ return (h >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
242
+ }
243
+ }
244
+ /**
245
+ * Create a MarketplaceClient for the given marketplace URL.
246
+ *
247
+ * @param baseUrl - The marketplace API base URL (e.g. "https://marketplace.emdashcms.com")
248
+ * @param siteOrigin - The origin of the EmDash site (e.g. "https://myblog.example.com").
249
+ * Used to generate a stable, non-identifying site hash for install deduplication.
250
+ */
251
+ function createMarketplaceClient(baseUrl, siteOrigin) {
252
+ return new MarketplaceClientImpl(baseUrl, siteOrigin);
253
+ }
254
+
255
+ //#endregion
256
+ export { fetchWithinOrigin as i, MarketplaceUnavailableError as n, createMarketplaceClient as r, MarketplaceError as t };
257
+ //# sourceMappingURL=marketplace-CUlenvZm.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace-CUlenvZm.mjs","names":[],"sources":["../src/plugins/marketplace.ts"],"sourcesContent":["/**\n * MarketplaceClient — HTTP client for the EmDash Plugin Marketplace\n *\n * Used by the install/update/proxy endpoints in EmDash core to communicate\n * with the marketplace Worker. The marketplace is a distribution channel,\n * not a runtime dependency — bundles are copied to site-local R2 at install time.\n */\n\nimport { createGzipDecoder, unpackTar } from \"modern-tar\";\n\nimport { pluginManifestSchema, reconcileManifestAccess } from \"./manifest-schema.js\";\nimport type { PluginManifest } from \"./types.js\";\n\n// ── Module-level regex patterns ───────────────────────────────────\n\nconst TRAILING_SLASHES = /\\/+$/;\nconst LEADING_DOT_SLASH = /^\\.\\//;\n\n// ── Types ──────────────────────────────────────────────────────────\n\nexport interface MarketplacePluginSummary {\n\tid: string;\n\tname: string;\n\tdescription: string | null;\n\tauthor: {\n\t\tname: string;\n\t\tverified: boolean;\n\t\tavatarUrl: string | null;\n\t};\n\tcapabilities: string[];\n\tkeywords: string[];\n\tinstallCount: number;\n\thasIcon: boolean;\n\ticonUrl: string;\n\tlatestVersion?: {\n\t\tversion: string;\n\t\taudit?: {\n\t\t\tverdict: string;\n\t\t\triskScore: number;\n\t\t};\n\t\timageAudit?: {\n\t\t\tverdict: string;\n\t\t};\n\t};\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface MarketplaceVersionSummary {\n\tversion: string;\n\tminEmDashVersion: string | null;\n\tbundleSize: number;\n\tchecksum: string;\n\tchangelog: string | null;\n\tcapabilities: string[];\n\tstatus: string;\n\tauditVerdict: string | null;\n\timageAuditVerdict: string | null;\n\tpublishedAt: string;\n}\n\nexport interface MarketplacePluginDetail extends MarketplacePluginSummary {\n\trepositoryUrl: string | null;\n\thomepageUrl: string | null;\n\tlicense: string | null;\n\tlatestVersion?: {\n\t\tversion: string;\n\t\tminEmDashVersion: string | null;\n\t\tbundleSize: number;\n\t\tchecksum: string;\n\t\tchangelog: string | null;\n\t\treadme: string | null;\n\t\thasIcon: boolean;\n\t\tscreenshotCount: number;\n\t\tscreenshotUrls: string[];\n\t\tcapabilities: string[];\n\t\tstatus: string;\n\t\taudit?: {\n\t\t\tverdict: string;\n\t\t\triskScore: number;\n\t\t};\n\t\timageAudit?: {\n\t\t\tverdict: string;\n\t\t};\n\t\tpublishedAt: string;\n\t};\n}\n\nexport interface MarketplaceSearchOpts {\n\tcategory?: string;\n\tcapability?: string;\n\tsort?: \"installs\" | \"updated\" | \"created\" | \"name\";\n\tcursor?: string;\n\tlimit?: number;\n}\n\nexport interface MarketplaceSearchResult {\n\titems: MarketplacePluginSummary[];\n\tnextCursor?: string;\n}\n\n// ── Theme types ───────────────────────────────────────────────────\n\nexport interface MarketplaceThemeSummary {\n\tid: string;\n\tname: string;\n\tdescription: string | null;\n\tauthor: {\n\t\tname: string;\n\t\tverified: boolean;\n\t\tavatarUrl: string | null;\n\t};\n\tkeywords: string[];\n\tpreviewUrl: string;\n\tdemoUrl: string | null;\n\thasThumbnail: boolean;\n\tthumbnailUrl: string | null;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface MarketplaceThemeDetail extends MarketplaceThemeSummary {\n\tauthor: {\n\t\tid: string;\n\t\tname: string;\n\t\tverified: boolean;\n\t\tavatarUrl: string | null;\n\t};\n\trepositoryUrl: string | null;\n\thomepageUrl: string | null;\n\tlicense: string | null;\n\tscreenshotCount: number;\n\tscreenshotUrls: string[];\n}\n\nexport interface MarketplaceThemeSearchOpts {\n\tkeyword?: string;\n\tsort?: \"name\" | \"created\" | \"updated\";\n\tcursor?: string;\n\tlimit?: number;\n}\n\nexport interface MarketplaceThemeSearchResult {\n\titems: MarketplaceThemeSummary[];\n\tnextCursor?: string;\n}\n\nexport interface PluginBundle {\n\tmanifest: PluginManifest;\n\tbackendCode: string;\n\tadminCode?: string;\n\tchecksum: string;\n}\n\n// ── Interface ──────────────────────────────────────────────────────\n\nexport interface MarketplaceClient {\n\t/** Search the marketplace catalog */\n\tsearch(query?: string, opts?: MarketplaceSearchOpts): Promise<MarketplaceSearchResult>;\n\n\t/** Get full plugin detail */\n\tgetPlugin(id: string): Promise<MarketplacePluginDetail>;\n\n\t/** Get version history for a plugin */\n\tgetVersions(id: string): Promise<MarketplaceVersionSummary[]>;\n\n\t/** Download and extract a plugin bundle */\n\tdownloadBundle(id: string, version: string): Promise<PluginBundle>;\n\n\t/** Fire-and-forget install stat (never throws) */\n\treportInstall(id: string, version: string): Promise<void>;\n\n\t/** Search theme listings */\n\tsearchThemes(\n\t\tquery?: string,\n\t\topts?: MarketplaceThemeSearchOpts,\n\t): Promise<MarketplaceThemeSearchResult>;\n\n\t/** Get full theme detail */\n\tgetTheme(id: string): Promise<MarketplaceThemeDetail>;\n}\n\n// ── Errors ─────────────────────────────────────────────────────────\n\nexport class MarketplaceError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly status?: number,\n\t\tpublic readonly code?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"MarketplaceError\";\n\t}\n}\n\nexport class MarketplaceUnavailableError extends MarketplaceError {\n\tconstructor(cause?: unknown) {\n\t\tsuper(\"Plugin marketplace is unavailable\", undefined, \"MARKETPLACE_UNAVAILABLE\");\n\t\tif (cause) this.cause = cause;\n\t}\n}\n\nconst MAX_REDIRECTS = 5;\n\n/**\n * Fetches a marketplace URL, following redirects only while they stay on\n * that URL's origin. Throws a `MarketplaceError` coded\n * `${codePrefix}_REDIRECT_UNTRUSTED` or `${codePrefix}_TOO_MANY_REDIRECTS`.\n */\nexport async function fetchWithinOrigin(\n\turl: string,\n\tlabel: string,\n\tcodePrefix: string,\n): Promise<Response> {\n\tconst origin = new URL(url).origin;\n\tlet currentUrl = url;\n\tlet response = await fetch(currentUrl, { redirect: \"manual\" });\n\n\tfor (let i = 0; i < MAX_REDIRECTS; i++) {\n\t\tif (response.status < 300 || response.status >= 400) break;\n\n\t\tconst location = response.headers.get(\"location\");\n\t\tif (!location) break;\n\n\t\tconst target = new URL(location, currentUrl);\n\t\tif (target.origin !== origin) {\n\t\t\tthrow new MarketplaceError(\n\t\t\t\t`${label} redirected to untrusted host: ${target.origin}`,\n\t\t\t\tresponse.status,\n\t\t\t\t`${codePrefix}_REDIRECT_UNTRUSTED`,\n\t\t\t);\n\t\t}\n\t\tcurrentUrl = target.href;\n\t\tresponse = await fetch(currentUrl, { redirect: \"manual\" });\n\t}\n\n\tif (response.status >= 300 && response.status < 400) {\n\t\tthrow new MarketplaceError(\n\t\t\t`${label} exceeded maximum redirects (${MAX_REDIRECTS})`,\n\t\t\tresponse.status,\n\t\t\t`${codePrefix}_TOO_MANY_REDIRECTS`,\n\t\t);\n\t}\n\treturn response;\n}\n\n// ── Implementation ─────────────────────────────────────────────────\n\nclass MarketplaceClientImpl implements MarketplaceClient {\n\tprivate readonly baseUrl: string;\n\tprivate readonly siteOrigin: string | undefined;\n\n\tconstructor(baseUrl: string, siteOrigin?: string) {\n\t\t// Strip trailing slash\n\t\tthis.baseUrl = baseUrl.replace(TRAILING_SLASHES, \"\");\n\t\tthis.siteOrigin = siteOrigin;\n\t}\n\n\tasync search(query?: string, opts?: MarketplaceSearchOpts): Promise<MarketplaceSearchResult> {\n\t\tconst params = new URLSearchParams();\n\t\tif (query) params.set(\"q\", query);\n\t\tif (opts?.category) params.set(\"category\", opts.category);\n\t\tif (opts?.capability) params.set(\"capability\", opts.capability);\n\t\tif (opts?.sort) params.set(\"sort\", opts.sort);\n\t\tif (opts?.cursor) params.set(\"cursor\", opts.cursor);\n\t\tif (opts?.limit) params.set(\"limit\", String(opts.limit));\n\n\t\tconst qs = params.toString();\n\t\tconst url = `${this.baseUrl}/api/v1/plugins${qs ? `?${qs}` : \"\"}`;\n\t\tconst data = await this.fetchJson<MarketplaceSearchResult>(url);\n\t\treturn data;\n\t}\n\n\tasync getPlugin(id: string): Promise<MarketplacePluginDetail> {\n\t\tconst url = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}`;\n\t\treturn this.fetchJson<MarketplacePluginDetail>(url);\n\t}\n\n\tasync getVersions(id: string): Promise<MarketplaceVersionSummary[]> {\n\t\tconst url = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}/versions`;\n\t\tconst data = await this.fetchJson<{ items: MarketplaceVersionSummary[] }>(url);\n\t\treturn data.items;\n\t}\n\n\tasync downloadBundle(id: string, version: string): Promise<PluginBundle> {\n\t\tconst bundleUrl = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}/versions/${encodeURIComponent(version)}/bundle`;\n\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetchWithinOrigin(bundleUrl, \"Bundle download\", \"BUNDLE\");\n\t\t} catch (err) {\n\t\t\tif (err instanceof MarketplaceError) throw err;\n\t\t\tthrow new MarketplaceUnavailableError(err);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tthrow new MarketplaceError(\n\t\t\t\t`Failed to download bundle: ${response.status} ${response.statusText}`,\n\t\t\t\tresponse.status,\n\t\t\t\t\"BUNDLE_DOWNLOAD_FAILED\",\n\t\t\t);\n\t\t}\n\n\t\tconst tarballBytes = new Uint8Array(await response.arrayBuffer());\n\t\ttry {\n\t\t\treturn await extractBundle(tarballBytes);\n\t\t} catch (err) {\n\t\t\tif (err instanceof MarketplaceError) throw err;\n\t\t\tthrow new MarketplaceError(\n\t\t\t\t\"Failed to extract plugin bundle\",\n\t\t\t\tundefined,\n\t\t\t\t\"BUNDLE_EXTRACT_FAILED\",\n\t\t\t);\n\t\t}\n\t}\n\n\tasync reportInstall(id: string, version: string): Promise<void> {\n\t\t// Generate a stable site hash from the site origin (best-effort, non-identifying)\n\t\tconst siteHash = await generateSiteHash(this.siteOrigin);\n\t\tconst url = `${this.baseUrl}/api/v1/plugins/${encodeURIComponent(id)}/installs`;\n\n\t\ttry {\n\t\t\tawait fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ siteHash, version }),\n\t\t\t});\n\t\t} catch {\n\t\t\t// Fire-and-forget — never throw\n\t\t}\n\t}\n\n\tasync searchThemes(\n\t\tquery?: string,\n\t\topts?: MarketplaceThemeSearchOpts,\n\t): Promise<MarketplaceThemeSearchResult> {\n\t\tconst params = new URLSearchParams();\n\t\tif (query) params.set(\"q\", query);\n\t\tif (opts?.keyword) params.set(\"keyword\", opts.keyword);\n\t\tif (opts?.sort) params.set(\"sort\", opts.sort);\n\t\tif (opts?.cursor) params.set(\"cursor\", opts.cursor);\n\t\tif (opts?.limit) params.set(\"limit\", String(opts.limit));\n\n\t\tconst qs = params.toString();\n\t\tconst url = `${this.baseUrl}/api/v1/themes${qs ? `?${qs}` : \"\"}`;\n\t\treturn this.fetchJson<MarketplaceThemeSearchResult>(url);\n\t}\n\n\tasync getTheme(id: string): Promise<MarketplaceThemeDetail> {\n\t\tconst url = `${this.baseUrl}/api/v1/themes/${encodeURIComponent(id)}`;\n\t\treturn this.fetchJson<MarketplaceThemeDetail>(url);\n\t}\n\n\tprivate async fetchJson<T>(url: string): Promise<T> {\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(url, {\n\t\t\t\theaders: { Accept: \"application/json\" },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tthrow new MarketplaceUnavailableError(err);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tlet errorMessage = `Marketplace request failed: ${response.status}`;\n\t\t\ttry {\n\t\t\t\tconst body: { error?: string } = await response.json();\n\t\t\t\tif (body.error) errorMessage = body.error;\n\t\t\t} catch {\n\t\t\t\t// use default message\n\t\t\t}\n\t\t\tthrow new MarketplaceError(errorMessage, response.status);\n\t\t}\n\n\t\tconst data: T = await response.json();\n\t\treturn data;\n\t}\n}\n\n// ── Bundle extraction ──────────────────────────────────────────────\n\n/**\n * Extract manifest + code files from a tarball.\n *\n * The tarball is a gzipped tar archive containing:\n * - manifest.json\n * - backend.js\n * - admin.js (optional)\n *\n * We use a minimal tar parser since we only need to read a few small files.\n */\n/**\n * Exported so the experimental registry install handler can reuse the\n * same parse / validate / hash primitive. Despite the file name, this\n * function predates the marketplace-vs-registry split and is generic\n * over plugin bundle tarballs regardless of distribution channel.\n */\n// Aligns with RFC 0001 §\"Bundle size limits\" (256 KiB decompressed,\n// 20 files). Matches `MAX_BUNDLE_SIZE` in @emdash-cms/plugin-cli. We\n// don't import that constant to keep this runtime module independent\n// of the authoring CLI; the two values must stay in sync.\n//\n// Tar adds per-file headers (~512 bytes each) plus directory entries,\n// so the entry count cap is set comfortably above RFC's 20-file limit.\n// Going over either is a strong signal the bundle isn't a legitimate\n// sandboxed plugin.\nconst MAX_DECOMPRESSED_BUNDLE_BYTES = 256 * 1024;\nconst MAX_BUNDLE_TAR_ENTRIES = 32;\n\nexport async function extractBundle(tarballBytes: Uint8Array): Promise<PluginBundle> {\n\t// Decompress fully into memory first, then parse the tar.\n\t// Passing a pipeThrough() stream directly to unpackTar causes a backpressure\n\t// deadlock in workerd: the tar decoder's body-stream pull() needs more\n\t// decompressed data, but the upstream pipe is stalled waiting for the\n\t// decoder's writable side to drain — a circular dependency.\n\tconst decompressedStream = new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tcontroller.enqueue(tarballBytes);\n\t\t\tcontroller.close();\n\t\t},\n\t}).pipeThrough(createGzipDecoder());\n\n\t// Collect decompressed bytes with a hard cap. A gzip-bomb -- a small\n\t// tarball that decompresses to gigabytes -- otherwise exhausts\n\t// worker / Node memory before we know to reject it. The cap matches\n\t// RFC 0001's publish-time bundle size limit (MAX_DECOMPRESSED_BUNDLE_BYTES);\n\t// anything past that isn't a legitimate sandboxed plugin.\n\tconst reader = decompressedStream.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) continue;\n\t\ttotal += value.byteLength;\n\t\tif (total > MAX_DECOMPRESSED_BUNDLE_BYTES) {\n\t\t\ttry {\n\t\t\t\tawait reader.cancel();\n\t\t\t} catch {\n\t\t\t\t// nothing to do\n\t\t\t}\n\t\t\tthrow new MarketplaceError(\n\t\t\t\t`Bundle decompressed size exceeds limit (${MAX_DECOMPRESSED_BUNDLE_BYTES} bytes)`,\n\t\t\t\tundefined,\n\t\t\t\t\"INVALID_BUNDLE\",\n\t\t\t);\n\t\t}\n\t\tchunks.push(value);\n\t}\n\tconst decompressedBytes = new Uint8Array(total);\n\t{\n\t\tlet offset = 0;\n\t\tfor (const chunk of chunks) {\n\t\t\tdecompressedBytes.set(chunk, offset);\n\t\t\toffset += chunk.byteLength;\n\t\t}\n\t}\n\n\tconst decompressed = new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tcontroller.enqueue(decompressedBytes);\n\t\t\tcontroller.close();\n\t\t},\n\t});\n\n\tconst entries = await unpackTar(decompressed);\n\tif (entries.length > MAX_BUNDLE_TAR_ENTRIES) {\n\t\tthrow new MarketplaceError(\n\t\t\t`Bundle has too many tar entries (${entries.length} > ${MAX_BUNDLE_TAR_ENTRIES})`,\n\t\t\tundefined,\n\t\t\t\"INVALID_BUNDLE\",\n\t\t);\n\t}\n\n\tconst decoder = new TextDecoder();\n\tconst files = new Map<string, string>();\n\tfor (const entry of entries) {\n\t\tif (entry.data && entry.header.type === \"file\") {\n\t\t\t// Strip leading ./ prefix that tar tools commonly add\n\t\t\tconst name = entry.header.name.replace(LEADING_DOT_SLASH, \"\");\n\t\t\tfiles.set(name, decoder.decode(entry.data));\n\t\t}\n\t}\n\n\tconst manifestJson = files.get(\"manifest.json\");\n\tconst backendCode = files.get(\"backend.js\");\n\n\tif (!manifestJson) {\n\t\tthrow new MarketplaceError(\n\t\t\t\"Invalid bundle: missing manifest.json\",\n\t\t\tundefined,\n\t\t\t\"INVALID_BUNDLE\",\n\t\t);\n\t}\n\tif (!backendCode) {\n\t\tthrow new MarketplaceError(\"Invalid bundle: missing backend.js\", undefined, \"INVALID_BUNDLE\");\n\t}\n\n\tlet manifest: PluginManifest;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(manifestJson);\n\t\tconst result = pluginManifestSchema.safeParse(parsed);\n\t\tif (!result.success) {\n\t\t\tthrow new MarketplaceError(\n\t\t\t\t\"Invalid bundle: manifest.json failed validation\",\n\t\t\t\tundefined,\n\t\t\t\t\"INVALID_BUNDLE\",\n\t\t\t);\n\t\t}\n\t\tmanifest = reconcileManifestAccess(result.data);\n\t} catch (err) {\n\t\tif (err instanceof MarketplaceError) throw err;\n\t\tthrow new MarketplaceError(\n\t\t\t\"Invalid bundle: malformed manifest.json\",\n\t\t\tundefined,\n\t\t\t\"INVALID_BUNDLE\",\n\t\t);\n\t}\n\n\t// Compute SHA-256 checksum of the tarball for verification\n\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- Uint8Array is a valid BufferSource at runtime; TS lib mismatch\n\tconst hashBuffer = await crypto.subtle.digest(\"SHA-256\", tarballBytes as unknown as BufferSource);\n\tconst hashArray = new Uint8Array(hashBuffer);\n\tconst checksum = Array.from(hashArray, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\n\treturn {\n\t\tmanifest,\n\t\tbackendCode,\n\t\tadminCode: files.get(\"admin.js\"),\n\t\tchecksum,\n\t};\n}\n\n// ── Helpers ────────────────────────────────────────────────────────\n\n/**\n * Generate a stable non-identifying site hash from the site origin.\n * The same origin always produces the same hash, so the marketplace\n * installs table deduplicates correctly per (plugin_id, site_hash).\n */\nasync function generateSiteHash(siteOrigin?: string): Promise<string> {\n\tconst seed = siteOrigin ? `emdash-site:${siteOrigin}` : `emdash-anonymous`;\n\ttry {\n\t\tconst hash = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(seed));\n\t\tconst arr = new Uint8Array(hash);\n\t\treturn Array.from(arr.slice(0, 8), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\t} catch {\n\t\t// Fallback for environments without crypto.subtle: FNV-1a hash encoded as hex.\n\t\t// Deterministic, uniform distribution, no origin leakage.\n\t\tlet h = 0x811c9dc5;\n\t\tfor (let i = 0; i < seed.length; i++) {\n\t\t\th ^= seed.charCodeAt(i);\n\t\t\th = Math.imul(h, 0x01000193);\n\t\t}\n\t\tconst h2 = h ^ (h >>> 16);\n\t\treturn (h >>> 0).toString(16).padStart(8, \"0\") + (h2 >>> 0).toString(16).padStart(8, \"0\");\n\t}\n}\n\n// ── Factory ────────────────────────────────────────────────────────\n\n/**\n * Create a MarketplaceClient for the given marketplace URL.\n *\n * @param baseUrl - The marketplace API base URL (e.g. \"https://marketplace.emdashcms.com\")\n * @param siteOrigin - The origin of the EmDash site (e.g. \"https://myblog.example.com\").\n * Used to generate a stable, non-identifying site hash for install deduplication.\n */\nexport function createMarketplaceClient(baseUrl: string, siteOrigin?: string): MarketplaceClient {\n\treturn new MarketplaceClientImpl(baseUrl, siteOrigin);\n}\n"],"mappings":";;;;;;;;;;;AAeA,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAwK1B,IAAa,mBAAb,cAAsC,MAAM;CAC3C,YACC,SACA,AAAgB,QAChB,AAAgB,MACf;AACD,QAAM,QAAQ;EAHE;EACA;AAGhB,OAAK,OAAO;;;AAId,IAAa,8BAAb,cAAiD,iBAAiB;CACjE,YAAY,OAAiB;AAC5B,QAAM,qCAAqC,QAAW,0BAA0B;AAChF,MAAI,MAAO,MAAK,QAAQ;;;AAI1B,MAAM,gBAAgB;;;;;;AAOtB,eAAsB,kBACrB,KACA,OACA,YACoB;CACpB,MAAM,SAAS,IAAI,IAAI,IAAI,CAAC;CAC5B,IAAI,aAAa;CACjB,IAAI,WAAW,MAAM,MAAM,YAAY,EAAE,UAAU,UAAU,CAAC;AAE9D,MAAK,IAAI,IAAI,GAAG,IAAI,eAAe,KAAK;AACvC,MAAI,SAAS,SAAS,OAAO,SAAS,UAAU,IAAK;EAErD,MAAM,WAAW,SAAS,QAAQ,IAAI,WAAW;AACjD,MAAI,CAAC,SAAU;EAEf,MAAM,SAAS,IAAI,IAAI,UAAU,WAAW;AAC5C,MAAI,OAAO,WAAW,OACrB,OAAM,IAAI,iBACT,GAAG,MAAM,iCAAiC,OAAO,UACjD,SAAS,QACT,GAAG,WAAW,qBACd;AAEF,eAAa,OAAO;AACpB,aAAW,MAAM,MAAM,YAAY,EAAE,UAAU,UAAU,CAAC;;AAG3D,KAAI,SAAS,UAAU,OAAO,SAAS,SAAS,IAC/C,OAAM,IAAI,iBACT,GAAG,MAAM,+BAA+B,cAAc,IACtD,SAAS,QACT,GAAG,WAAW,qBACd;AAEF,QAAO;;AAKR,IAAM,wBAAN,MAAyD;CACxD,AAAiB;CACjB,AAAiB;CAEjB,YAAY,SAAiB,YAAqB;AAEjD,OAAK,UAAU,QAAQ,QAAQ,kBAAkB,GAAG;AACpD,OAAK,aAAa;;CAGnB,MAAM,OAAO,OAAgB,MAAgE;EAC5F,MAAM,SAAS,IAAI,iBAAiB;AACpC,MAAI,MAAO,QAAO,IAAI,KAAK,MAAM;AACjC,MAAI,MAAM,SAAU,QAAO,IAAI,YAAY,KAAK,SAAS;AACzD,MAAI,MAAM,WAAY,QAAO,IAAI,cAAc,KAAK,WAAW;AAC/D,MAAI,MAAM,KAAM,QAAO,IAAI,QAAQ,KAAK,KAAK;AAC7C,MAAI,MAAM,OAAQ,QAAO,IAAI,UAAU,KAAK,OAAO;AACnD,MAAI,MAAM,MAAO,QAAO,IAAI,SAAS,OAAO,KAAK,MAAM,CAAC;EAExD,MAAM,KAAK,OAAO,UAAU;EAC5B,MAAM,MAAM,GAAG,KAAK,QAAQ,iBAAiB,KAAK,IAAI,OAAO;AAE7D,SADa,MAAM,KAAK,UAAmC,IAAI;;CAIhE,MAAM,UAAU,IAA8C;EAC7D,MAAM,MAAM,GAAG,KAAK,QAAQ,kBAAkB,mBAAmB,GAAG;AACpE,SAAO,KAAK,UAAmC,IAAI;;CAGpD,MAAM,YAAY,IAAkD;EACnE,MAAM,MAAM,GAAG,KAAK,QAAQ,kBAAkB,mBAAmB,GAAG,CAAC;AAErE,UADa,MAAM,KAAK,UAAkD,IAAI,EAClE;;CAGb,MAAM,eAAe,IAAY,SAAwC;EACxE,MAAM,YAAY,GAAG,KAAK,QAAQ,kBAAkB,mBAAmB,GAAG,CAAC,YAAY,mBAAmB,QAAQ,CAAC;EAEnH,IAAI;AACJ,MAAI;AACH,cAAW,MAAM,kBAAkB,WAAW,mBAAmB,SAAS;WAClE,KAAK;AACb,OAAI,eAAe,iBAAkB,OAAM;AAC3C,SAAM,IAAI,4BAA4B,IAAI;;AAG3C,MAAI,CAAC,SAAS,GACb,OAAM,IAAI,iBACT,8BAA8B,SAAS,OAAO,GAAG,SAAS,cAC1D,SAAS,QACT,yBACA;EAGF,MAAM,eAAe,IAAI,WAAW,MAAM,SAAS,aAAa,CAAC;AACjE,MAAI;AACH,UAAO,MAAM,cAAc,aAAa;WAChC,KAAK;AACb,OAAI,eAAe,iBAAkB,OAAM;AAC3C,SAAM,IAAI,iBACT,mCACA,QACA,wBACA;;;CAIH,MAAM,cAAc,IAAY,SAAgC;EAE/D,MAAM,WAAW,MAAM,iBAAiB,KAAK,WAAW;EACxD,MAAM,MAAM,GAAG,KAAK,QAAQ,kBAAkB,mBAAmB,GAAG,CAAC;AAErE,MAAI;AACH,SAAM,MAAM,KAAK;IAChB,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAC/C,MAAM,KAAK,UAAU;KAAE;KAAU;KAAS,CAAC;IAC3C,CAAC;UACK;;CAKT,MAAM,aACL,OACA,MACwC;EACxC,MAAM,SAAS,IAAI,iBAAiB;AACpC,MAAI,MAAO,QAAO,IAAI,KAAK,MAAM;AACjC,MAAI,MAAM,QAAS,QAAO,IAAI,WAAW,KAAK,QAAQ;AACtD,MAAI,MAAM,KAAM,QAAO,IAAI,QAAQ,KAAK,KAAK;AAC7C,MAAI,MAAM,OAAQ,QAAO,IAAI,UAAU,KAAK,OAAO;AACnD,MAAI,MAAM,MAAO,QAAO,IAAI,SAAS,OAAO,KAAK,MAAM,CAAC;EAExD,MAAM,KAAK,OAAO,UAAU;EAC5B,MAAM,MAAM,GAAG,KAAK,QAAQ,gBAAgB,KAAK,IAAI,OAAO;AAC5D,SAAO,KAAK,UAAwC,IAAI;;CAGzD,MAAM,SAAS,IAA6C;EAC3D,MAAM,MAAM,GAAG,KAAK,QAAQ,iBAAiB,mBAAmB,GAAG;AACnE,SAAO,KAAK,UAAkC,IAAI;;CAGnD,MAAc,UAAa,KAAyB;EACnD,IAAI;AACJ,MAAI;AACH,cAAW,MAAM,MAAM,KAAK,EAC3B,SAAS,EAAE,QAAQ,oBAAoB,EACvC,CAAC;WACM,KAAK;AACb,SAAM,IAAI,4BAA4B,IAAI;;AAG3C,MAAI,CAAC,SAAS,IAAI;GACjB,IAAI,eAAe,+BAA+B,SAAS;AAC3D,OAAI;IACH,MAAM,OAA2B,MAAM,SAAS,MAAM;AACtD,QAAI,KAAK,MAAO,gBAAe,KAAK;WAC7B;AAGR,SAAM,IAAI,iBAAiB,cAAc,SAAS,OAAO;;AAI1D,SADgB,MAAM,SAAS,MAAM;;;;;;;;;;;;;;;;;;;AAgCvC,MAAM,gCAAgC,MAAM;AAC5C,MAAM,yBAAyB;AAE/B,eAAsB,cAAc,cAAiD;CAkBpF,MAAM,SAZqB,IAAI,eAA2B,EACzD,MAAM,YAAY;AACjB,aAAW,QAAQ,aAAa;AAChC,aAAW,OAAO;IAEnB,CAAC,CAAC,YAAY,mBAAmB,CAAC,CAOD,WAAW;CAC7C,MAAM,SAAuB,EAAE;CAC/B,IAAI,QAAQ;AACZ,QAAO,MAAM;EACZ,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,MAAI,KAAM;AACV,MAAI,CAAC,MAAO;AACZ,WAAS,MAAM;AACf,MAAI,QAAQ,+BAA+B;AAC1C,OAAI;AACH,UAAM,OAAO,QAAQ;WACd;AAGR,SAAM,IAAI,iBACT,2CAA2C,8BAA8B,UACzE,QACA,iBACA;;AAEF,SAAO,KAAK,MAAM;;CAEnB,MAAM,oBAAoB,IAAI,WAAW,MAAM;CAC/C;EACC,IAAI,SAAS;AACb,OAAK,MAAM,SAAS,QAAQ;AAC3B,qBAAkB,IAAI,OAAO,OAAO;AACpC,aAAU,MAAM;;;CAWlB,MAAM,UAAU,MAAM,UAPD,IAAI,eAA2B,EACnD,MAAM,YAAY;AACjB,aAAW,QAAQ,kBAAkB;AACrC,aAAW,OAAO;IAEnB,CAAC,CAE2C;AAC7C,KAAI,QAAQ,SAAS,uBACpB,OAAM,IAAI,iBACT,oCAAoC,QAAQ,OAAO,KAAK,uBAAuB,IAC/E,QACA,iBACA;CAGF,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,wBAAQ,IAAI,KAAqB;AACvC,MAAK,MAAM,SAAS,QACnB,KAAI,MAAM,QAAQ,MAAM,OAAO,SAAS,QAAQ;EAE/C,MAAM,OAAO,MAAM,OAAO,KAAK,QAAQ,mBAAmB,GAAG;AAC7D,QAAM,IAAI,MAAM,QAAQ,OAAO,MAAM,KAAK,CAAC;;CAI7C,MAAM,eAAe,MAAM,IAAI,gBAAgB;CAC/C,MAAM,cAAc,MAAM,IAAI,aAAa;AAE3C,KAAI,CAAC,aACJ,OAAM,IAAI,iBACT,yCACA,QACA,iBACA;AAEF,KAAI,CAAC,YACJ,OAAM,IAAI,iBAAiB,sCAAsC,QAAW,iBAAiB;CAG9F,IAAI;AACJ,KAAI;EACH,MAAM,SAAkB,KAAK,MAAM,aAAa;EAChD,MAAM,SAAS,qBAAqB,UAAU,OAAO;AACrD,MAAI,CAAC,OAAO,QACX,OAAM,IAAI,iBACT,mDACA,QACA,iBACA;AAEF,aAAW,wBAAwB,OAAO,KAAK;UACvC,KAAK;AACb,MAAI,eAAe,iBAAkB,OAAM;AAC3C,QAAM,IAAI,iBACT,2CACA,QACA,iBACA;;CAKF,MAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,aAAwC;CACjG,MAAM,YAAY,IAAI,WAAW,WAAW;CAC5C,MAAM,WAAW,MAAM,KAAK,YAAY,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG;AAEvF,QAAO;EACN;EACA;EACA,WAAW,MAAM,IAAI,WAAW;EAChC;EACA;;;;;;;AAUF,eAAe,iBAAiB,YAAsC;CACrE,MAAM,OAAO,aAAa,eAAe,eAAe;AACxD,KAAI;EACH,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI,aAAa,CAAC,OAAO,KAAK,CAAC;EAClF,MAAM,MAAM,IAAI,WAAW,KAAK;AAChC,SAAO,MAAM,KAAK,IAAI,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG;SAC5E;EAGP,IAAI,IAAI;AACR,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,QAAK,KAAK,WAAW,EAAE;AACvB,OAAI,KAAK,KAAK,GAAG,SAAW;;EAE7B,MAAM,KAAK,IAAK,MAAM;AACtB,UAAQ,MAAM,GAAG,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,OAAO,GAAG,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI;;;;;;;;;;AAa3F,SAAgB,wBAAwB,SAAiB,YAAwC;AAChG,QAAO,IAAI,sBAAsB,SAAS,WAAW"}
@@ -46,6 +46,30 @@ interface ImageTransformOptions {
46
46
  declare const IMMUTABLE_IMAGE_CACHE = "public, max-age=31536000, immutable";
47
47
  /** Cache policy for media keys that Replace original may overwrite. */
48
48
  declare const MUTABLE_MEDIA_CACHE_CONTROL = "public, max-age=0, must-revalidate";
49
+ /**
50
+ * Format a Date as an HTTP-date (RFC 7231).
51
+ */
52
+ declare function formatHttpDate(date: Date): string;
53
+ /**
54
+ * Build a weak validator from representation metadata. Weak because it is based
55
+ * on size and modification time rather than a content hash. Keeps the same
56
+ * shape for stored files and derived transforms so replacements change the tag.
57
+ */
58
+ declare function makeWeakEtag(size: number, lastModified?: Date, suffix?: string): string;
59
+ /**
60
+ * Build a canonical fingerprint of the transform query params that affect the
61
+ * derived /_image bytes. Used as the suffix of a transform's weak ETag.
62
+ */
63
+ declare function getTransformFingerprint(params: URLSearchParams): string;
64
+ /**
65
+ * Check whether a request's preconditions are satisfied for the given
66
+ * representation. Returns true when the client already has the current version.
67
+ */
68
+ declare function isNotModified(request: Request, size: number, lastModified?: Date, suffix?: string): boolean;
69
+ /**
70
+ * Headers that make a mutable representation conditionally cacheable.
71
+ */
72
+ declare function validatorHeaders(size: number, lastModified?: Date, suffix?: string): Record<string, string>;
49
73
  /**
50
74
  * Headers for streaming **original** stored bytes (the no-transform fallback).
51
75
  * Carries the same stored-XSS protections as the media file route: a sandbox
@@ -53,7 +77,7 @@ declare const MUTABLE_MEDIA_CACHE_CONTROL = "public, max-age=0, must-revalidate"
53
77
  * inline raster allowlist (so a stored SVG can't run scripts in the site
54
78
  * origin). Transformed output is always generated raster and doesn't need this.
55
79
  */
56
- declare function originalMediaHeaders(contentType: string): Record<string, string>;
80
+ declare function originalMediaHeaders(contentType: string, size?: number, lastModified?: Date): Record<string, string>;
57
81
  /** Whether a storage key is safe to resolve against the storage backend. */
58
82
  declare function isSafeTransformKey(key: string): boolean;
59
83
  /**
@@ -100,5 +124,5 @@ declare function resolveTransformQuality(format: ImageTransformFormat, requested
100
124
  */
101
125
  declare function parseTransformParams(params: URLSearchParams): ParsedTransformParams;
102
126
  //#endregion
103
- export { ALLOWED_TRANSFORM_FORMATS, DEFAULT_TRANSFORM_FORMAT, DEFAULT_TRANSFORM_QUALITY, IMMUTABLE_IMAGE_CACHE, ImageTransformFormat, ImageTransformOptions, MAX_TRANSFORM_DIMENSION, MUTABLE_MEDIA_CACHE_CONTROL, ParsedTransformParams, isSafeTransformKey, isTransformFormat, matchInternalMediaKey, originalMediaHeaders, parseTransformParams, resolveTransformQuality };
127
+ export { ALLOWED_TRANSFORM_FORMATS, DEFAULT_TRANSFORM_FORMAT, DEFAULT_TRANSFORM_QUALITY, IMMUTABLE_IMAGE_CACHE, ImageTransformFormat, ImageTransformOptions, MAX_TRANSFORM_DIMENSION, MUTABLE_MEDIA_CACHE_CONTROL, ParsedTransformParams, formatHttpDate, getTransformFingerprint, isNotModified, isSafeTransformKey, isTransformFormat, makeWeakEtag, matchInternalMediaKey, originalMediaHeaders, parseTransformParams, resolveTransformQuality, validatorHeaders };
104
128
  //# sourceMappingURL=image-endpoint.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-endpoint.d.mts","names":[],"sources":["../../src/media/image-endpoint.ts"],"mappings":";;AAiBA;;;;;AAGA;;;;;AAWA;;;cAda,yBAAA;;cAGA,wBAAA,EAA0B,oBAAA;;;;;AAiBvC;;;;;cANa,yBAAA;;cAGA,uBAAA;;KAGD,oBAAA,WAA+B,yBAAA;;UAG1B,qBAAA;EAChB,KAAA;EACA,MAAA;EACA,MAAA,EAAQ,oBAAA;EAMD;AAIR;;;;EAJC,OAAA;AAAA;;cAIY,qBAAA;;cAGA,2BAAA;AAuBb;;;;;AAkBA;;AAlBA,iBAAgB,oBAAA,CAAqB,WAAA,WAAsB,MAAA;;iBAkB3C,kBAAA,CAAmB,GAAA;AAiBnC;;;;;AAeA;;;;;;;;AAfA,iBAAgB,qBAAA,CAAsB,IAAA;AAoBtC;AAAA,iBALgB,iBAAA,CAAkB,KAAA,WAAgB,KAAA,IAAS,oBAAA;;KAK/C,qBAAA;EACP,EAAA;EAAU,OAAA,EAAS,qBAAA;AAAA;EACnB,EAAA;EAAW,OAAA;AAAA;;AAUhB;;;;;;;iBAAgB,uBAAA,CACf,MAAA,EAAQ,oBAAA,EACR,SAAA;;AAeD;;;;;;;;iBAAgB,oBAAA,CAAqB,MAAA,EAAQ,eAAA,GAAkB,qBAAA"}
1
+ {"version":3,"file":"image-endpoint.d.mts","names":[],"sources":["../../src/media/image-endpoint.ts"],"mappings":";;AAiBA;;;;;AAGA;;;;;AAWA;;;cAda,yBAAA;;cAGA,wBAAA,EAA0B,oBAAA;;;;;AA4BvC;;;;;cAjBa,yBAAA;;cAGA,uBAAA;;KAcD,oBAAA,WAA+B,yBAAA;;UAG1B,qBAAA;EAChB,KAAA;EACA,MAAA;EACA,MAAA,EAAQ,oBAAA;EAMD;AAIR;;;;EAJC,OAAA;AAAA;;cAIY,qBAAA;;cAGA,2BAAA;AAKb;;;AAAA,iBAAgB,cAAA,CAAe,IAAA,EAAM,IAAA;;AASrC;;;;iBAAgB,YAAA,CAAa,IAAA,UAAc,YAAA,GAAe,IAAA,EAAM,MAAA;;;;;iBAWhD,uBAAA,CAAwB,MAAA,EAAQ,eAAA;AAAhD;;;;AAAA,iBAkBgB,aAAA,CACf,OAAA,EAAS,OAAA,EACT,IAAA,UACA,YAAA,GAAe,IAAA,EACf,MAAA;AAJD;;;AAAA,iBA6BgB,gBAAA,CACf,IAAA,UACA,YAAA,GAAe,IAAA,EACf,MAAA,YACE,MAAA;;;;;;;;iBA+Ba,oBAAA,CACf,WAAA,UACA,IAAA,WACA,YAAA,GAAe,IAAA,GACb,MAAA;AAvCH;AAAA,iBA0DgB,kBAAA,CAAmB,GAAA;;;;;;;;;;AAvBnC;;;;iBAwCgB,qBAAA,CAAsB,IAAA;;iBAetB,iBAAA,CAAkB,KAAA,WAAgB,KAAA,IAAS,oBAAA;;KAK/C,qBAAA;EACP,EAAA;EAAU,OAAA,EAAS,qBAAA;AAAA;EACnB,EAAA;EAAW,OAAA;AAAA;;AAtBhB;;;;;AAeA;;iBAiBgB,uBAAA,CACf,MAAA,EAAQ,oBAAA,EACR,SAAA;;;;;;;AAdD;;;iBA6BgB,oBAAA,CAAqB,MAAA,EAAQ,eAAA,GAAkB,qBAAA"}
@@ -35,11 +35,80 @@ const DEFAULT_TRANSFORM_FORMAT = "webp";
35
35
  const DEFAULT_TRANSFORM_QUALITY = 85;
36
36
  /** Upper bound for a requested dimension; caps the work a single request asks for. */
37
37
  const MAX_TRANSFORM_DIMENSION = 4e3;
38
+ /** Weak prefix on an ETag, stripped for weak comparison per RFC 7232. */
39
+ const WEAK_ETAG_PREFIX = /^W\//;
40
+ /**
41
+ * Strip surrounding whitespace and the weak prefix from an ETag value for
42
+ * weak comparison. Defined at module scope so it is not recreated per request.
43
+ */
44
+ function stripWeakEtagPrefix(value) {
45
+ return value.trim().replace(WEAK_ETAG_PREFIX, "");
46
+ }
38
47
  /** Long-lived cache for content-addressed image URLs. */
39
48
  const IMMUTABLE_IMAGE_CACHE = "public, max-age=31536000, immutable";
40
49
  /** Cache policy for media keys that Replace original may overwrite. */
41
50
  const MUTABLE_MEDIA_CACHE_CONTROL = "public, max-age=0, must-revalidate";
42
51
  /**
52
+ * Format a Date as an HTTP-date (RFC 7231).
53
+ */
54
+ function formatHttpDate(date) {
55
+ return date.toUTCString();
56
+ }
57
+ /**
58
+ * Build a weak validator from representation metadata. Weak because it is based
59
+ * on size and modification time rather than a content hash. Keeps the same
60
+ * shape for stored files and derived transforms so replacements change the tag.
61
+ */
62
+ function makeWeakEtag(size, lastModified, suffix) {
63
+ let value = String(size);
64
+ if (lastModified) value += `-${lastModified.getTime()}`;
65
+ if (suffix) value += `-${suffix}`;
66
+ return `W/"${value}"`;
67
+ }
68
+ /**
69
+ * Build a canonical fingerprint of the transform query params that affect the
70
+ * derived /_image bytes. Used as the suffix of a transform's weak ETag.
71
+ */
72
+ function getTransformFingerprint(params) {
73
+ const parts = [];
74
+ const append = (name) => {
75
+ const value = params.get(name);
76
+ if (value !== null) parts.push(`${name}=${value}`);
77
+ };
78
+ append("w");
79
+ append("h");
80
+ append("f");
81
+ append("q");
82
+ append("fit");
83
+ return parts.join("&");
84
+ }
85
+ /**
86
+ * Check whether a request's preconditions are satisfied for the given
87
+ * representation. Returns true when the client already has the current version.
88
+ */
89
+ function isNotModified(request, size, lastModified, suffix) {
90
+ const etag = makeWeakEtag(size, lastModified, suffix);
91
+ const ifNoneMatch = request.headers.get("If-None-Match");
92
+ if (ifNoneMatch !== null) {
93
+ if (ifNoneMatch.trim() === "*") return true;
94
+ return ifNoneMatch.split(",").map(stripWeakEtagPrefix).includes(stripWeakEtagPrefix(etag));
95
+ }
96
+ const ifModifiedSince = request.headers.get("If-Modified-Since");
97
+ if (ifModifiedSince !== null && lastModified) {
98
+ const since = Date.parse(ifModifiedSince);
99
+ if (!Number.isNaN(since)) return Math.floor(lastModified.getTime() / 1e3) * 1e3 <= since;
100
+ }
101
+ return false;
102
+ }
103
+ /**
104
+ * Headers that make a mutable representation conditionally cacheable.
105
+ */
106
+ function validatorHeaders(size, lastModified, suffix) {
107
+ const headers = { ETag: makeWeakEtag(size, lastModified, suffix) };
108
+ if (lastModified) headers["Last-Modified"] = formatHttpDate(lastModified);
109
+ return headers;
110
+ }
111
+ /**
43
112
  * Raster types safe to render inline. Anything else (SVG, PDF, ...) is served
44
113
  * as an attachment so it can't execute as an active document. Mirrors the
45
114
  * `/_emdash/api/media/file/{key}` route's allowlist.
@@ -59,13 +128,14 @@ const SAFE_INLINE_IMAGE_TYPES = new Set([
59
128
  * inline raster allowlist (so a stored SVG can't run scripts in the site
60
129
  * origin). Transformed output is always generated raster and doesn't need this.
61
130
  */
62
- function originalMediaHeaders(contentType) {
131
+ function originalMediaHeaders(contentType, size, lastModified) {
63
132
  return {
64
133
  "Content-Type": contentType,
65
134
  "Cache-Control": MUTABLE_MEDIA_CACHE_CONTROL,
66
135
  "X-Content-Type-Options": "nosniff",
67
136
  "Content-Security-Policy": "sandbox; default-src 'none'; img-src 'self'; style-src 'unsafe-inline'",
68
- "Content-Disposition": SAFE_INLINE_IMAGE_TYPES.has(contentType) ? "inline" : "attachment"
137
+ "Content-Disposition": SAFE_INLINE_IMAGE_TYPES.has(contentType) ? "inline" : "attachment",
138
+ ...size !== void 0 ? validatorHeaders(size, lastModified) : {}
69
139
  };
70
140
  }
71
141
  /** Storage keys safe to serve: the flat `{ulid}{ext}` shape, no slashes/traversal. */
@@ -186,5 +256,5 @@ function parseDimension(raw) {
186
256
  }
187
257
 
188
258
  //#endregion
189
- export { ALLOWED_TRANSFORM_FORMATS, DEFAULT_TRANSFORM_FORMAT, DEFAULT_TRANSFORM_QUALITY, IMMUTABLE_IMAGE_CACHE, MAX_TRANSFORM_DIMENSION, MUTABLE_MEDIA_CACHE_CONTROL, isSafeTransformKey, isTransformFormat, matchInternalMediaKey, originalMediaHeaders, parseTransformParams, resolveTransformQuality };
259
+ export { ALLOWED_TRANSFORM_FORMATS, DEFAULT_TRANSFORM_FORMAT, DEFAULT_TRANSFORM_QUALITY, IMMUTABLE_IMAGE_CACHE, MAX_TRANSFORM_DIMENSION, MUTABLE_MEDIA_CACHE_CONTROL, formatHttpDate, getTransformFingerprint, isNotModified, isSafeTransformKey, isTransformFormat, makeWeakEtag, matchInternalMediaKey, originalMediaHeaders, parseTransformParams, resolveTransformQuality, validatorHeaders };
190
260
  //# sourceMappingURL=image-endpoint.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-endpoint.mjs","names":[],"sources":["../../src/media/image-endpoint.ts"],"sourcesContent":["/**\n * Portable helpers shared by the platform image-endpoint modules.\n *\n * EmDash wraps Astro's image endpoint (`image.endpoint`) so that source bytes\n * for EmDash media are read straight from the storage adapter instead of being\n * fetched over HTTP. The platform endpoint modules (Node: sharp via\n * `astro:assets`; Cloudflare: the `IMAGES` binding) do the actual transform;\n * this module holds the platform-agnostic bits they share: recognizing an\n * EmDash media URL and validating transform query params.\n *\n * Kept free of `astro:*` / `virtual:emdash/*` imports so it stays in the\n * precompiled package and can be unit-tested directly.\n */\n\nimport { INTERNAL_MEDIA_PREFIX } from \"./normalize.js\";\n\n/** Output formats the wrapped endpoint can produce on Cloudflare. */\nexport const ALLOWED_TRANSFORM_FORMATS = [\"webp\", \"avif\", \"jpeg\", \"png\"] as const;\n\n/** Default output format -- broad support, strong compression. */\nexport const DEFAULT_TRANSFORM_FORMAT: ImageTransformFormat = \"webp\";\n\n/**\n * Default output quality for lossy formats (WebP/AVIF/JPEG) when the request\n * doesn't specify one. Matches the default Cloudflare applies to URL-based\n * image transformations. The Images *binding* applies no default of its own\n * and encodes near-losslessly when quality is omitted (a 2048px WebP comes\n * out ~900 KB instead of ~100 KB), so the endpoint sends an explicit quality\n * for lossy output. PNG is exempt: an explicit PNG quality switches the\n * binding to lossy PNG8, which is not a safe default for a lossless format.\n */\nexport const DEFAULT_TRANSFORM_QUALITY = 85;\n\n/** Upper bound for a requested dimension; caps the work a single request asks for. */\nexport const MAX_TRANSFORM_DIMENSION = 4000;\n\n/** A format string accepted by {@link ImageTransformOptions.format}. */\nexport type ImageTransformFormat = (typeof ALLOWED_TRANSFORM_FORMATS)[number];\n\n/** Validated options for a single transform. */\nexport interface ImageTransformOptions {\n\twidth?: number;\n\theight?: number;\n\tformat: ImageTransformFormat;\n\t/**\n\t * Explicitly-requested quality (1-100), or `undefined` when the request\n\t * carried no `q`. Callers apply their own default per format (see\n\t * {@link DEFAULT_TRANSFORM_QUALITY}); lossless PNG deliberately gets none.\n\t */\n\tquality?: number;\n}\n\n/** Long-lived cache for content-addressed image URLs. */\nexport const IMMUTABLE_IMAGE_CACHE = \"public, max-age=31536000, immutable\";\n\n/** Cache policy for media keys that Replace original may overwrite. */\nexport const MUTABLE_MEDIA_CACHE_CONTROL = \"public, max-age=0, must-revalidate\";\n\n/**\n * Raster types safe to render inline. Anything else (SVG, PDF, ...) is served\n * as an attachment so it can't execute as an active document. Mirrors the\n * `/_emdash/api/media/file/{key}` route's allowlist.\n */\nconst SAFE_INLINE_IMAGE_TYPES = new Set([\n\t\"image/jpeg\",\n\t\"image/png\",\n\t\"image/gif\",\n\t\"image/webp\",\n\t\"image/avif\",\n\t\"image/x-icon\",\n]);\n\n/**\n * Headers for streaming **original** stored bytes (the no-transform fallback).\n * Carries the same stored-XSS protections as the media file route: a sandbox\n * CSP, `nosniff`, and `Content-Disposition: attachment` for anything not on the\n * inline raster allowlist (so a stored SVG can't run scripts in the site\n * origin). Transformed output is always generated raster and doesn't need this.\n */\nexport function originalMediaHeaders(contentType: string): Record<string, string> {\n\treturn {\n\t\t\"Content-Type\": contentType,\n\t\t\"Cache-Control\": MUTABLE_MEDIA_CACHE_CONTROL,\n\t\t\"X-Content-Type-Options\": \"nosniff\",\n\t\t\"Content-Security-Policy\":\n\t\t\t\"sandbox; default-src 'none'; img-src 'self'; style-src 'unsafe-inline'\",\n\t\t\"Content-Disposition\": SAFE_INLINE_IMAGE_TYPES.has(contentType) ? \"inline\" : \"attachment\",\n\t};\n}\n\n/** Storage keys safe to serve: the flat `{ulid}{ext}` shape, no slashes/traversal. */\nconst SAFE_STORAGE_KEY = /^[A-Za-z0-9._-]+$/;\n\n/** Plain decimal digits only -- rejects \"1e3\", \"0x10\", \"+5\", whitespace. */\nconst DECIMAL_DIGITS = /^\\d+$/;\n\n/** Whether a storage key is safe to resolve against the storage backend. */\nexport function isSafeTransformKey(key: string): boolean {\n\treturn SAFE_STORAGE_KEY.test(key);\n}\n\n/**\n * If `href` points at the internal EmDash media route\n * (`/_emdash/api/media/file/{key}`) with a safe key, return the key; otherwise\n * `null` (the endpoint then delegates to the stock image endpoint for bundled\n * assets, allowed remote, and `publicUrl` media).\n *\n * The component absolutizes same-origin media (Astro only optimizes absolute,\n * remote-allowed URLs), so `href` is typically `https://site/_emdash/...` but\n * may be relative. We match on the **pathname** only and never fetch `href` —\n * the key is read from our own storage — so the host is irrelevant and can't be\n * an SSRF vector. A dummy base resolves both absolute and relative forms and\n * strips any query/fragment.\n */\nexport function matchInternalMediaKey(href: string | null | undefined): string | null {\n\tif (!href) return null;\n\tlet pathname: string;\n\ttry {\n\t\tpathname = new URL(href, \"http://localhost\").pathname;\n\t} catch {\n\t\treturn null;\n\t}\n\tif (!pathname.startsWith(INTERNAL_MEDIA_PREFIX)) return null;\n\tconst key = pathname.slice(INTERNAL_MEDIA_PREFIX.length);\n\tif (!key || !isSafeTransformKey(key)) return null;\n\treturn key;\n}\n\n/** Type guard for {@link ImageTransformFormat}. */\nexport function isTransformFormat(value: string): value is ImageTransformFormat {\n\treturn (ALLOWED_TRANSFORM_FORMATS as readonly string[]).includes(value);\n}\n\n/** Outcome of parsing transform query params: validated options or an error. */\nexport type ParsedTransformParams =\n\t| { ok: true; options: ImageTransformOptions }\n\t| { ok: false; message: string };\n\n/**\n * Resolve the quality to send to the image binding for a transform. An\n * explicitly-requested quality always wins. Otherwise lossy formats\n * (WebP/AVIF/JPEG) get {@link DEFAULT_TRANSFORM_QUALITY} because the Images\n * binding encodes near-losslessly when quality is omitted; lossless PNG gets\n * `undefined` because an explicit PNG quality switches the binding to lossy\n * PNG8, which is not a safe default for a lossless format.\n */\nexport function resolveTransformQuality(\n\tformat: ImageTransformFormat,\n\trequested: number | undefined,\n): number | undefined {\n\tif (requested !== undefined) return requested;\n\treturn format === \"png\" ? undefined : DEFAULT_TRANSFORM_QUALITY;\n}\n\n/**\n * Parse and validate `?w=&h=&f=&q=` query params. Width is required (it sizes\n * the rendition); dimensions are bounded so a request can't ask for an\n * unbounded or nonsensical transform. Format falls back to\n * {@link DEFAULT_TRANSFORM_FORMAT} when not requested. `q` is validated when\n * present but otherwise left `undefined` so the caller can apply a per-format\n * default (lossy formats get one, lossless PNG does not — see\n * {@link DEFAULT_TRANSFORM_QUALITY}).\n */\nexport function parseTransformParams(params: URLSearchParams): ParsedTransformParams {\n\tconst width = parseDimension(params.get(\"w\"));\n\tif (width === null) return { ok: false, message: \"Invalid 'w' (width)\" };\n\tif (width === undefined) return { ok: false, message: \"Missing 'w' (width)\" };\n\n\tconst height = parseDimension(params.get(\"h\"));\n\tif (height === null) return { ok: false, message: \"Invalid 'h' (height)\" };\n\n\tconst formatRaw = params.get(\"f\");\n\tlet format: ImageTransformFormat = DEFAULT_TRANSFORM_FORMAT;\n\tif (formatRaw !== null) {\n\t\tif (!isTransformFormat(formatRaw)) {\n\t\t\treturn { ok: false, message: `Unsupported 'f' (format): ${formatRaw}` };\n\t\t}\n\t\tformat = formatRaw;\n\t}\n\n\tlet quality: number | undefined;\n\tconst qualityRaw = params.get(\"q\");\n\tif (qualityRaw !== null) {\n\t\tconst q = Number(qualityRaw);\n\t\tif (!Number.isInteger(q) || q < 1 || q > 100) {\n\t\t\treturn { ok: false, message: \"Invalid 'q' (quality), expected 1-100\" };\n\t\t}\n\t\tquality = q;\n\t}\n\n\treturn { ok: true, options: { width, height, format, quality } };\n}\n\n/**\n * Parse a dimension query value.\n * - `undefined`: param absent\n * - `null`: present but invalid (non-integer, out of range)\n * - `number`: valid, within [1, MAX_TRANSFORM_DIMENSION]\n */\nfunction parseDimension(raw: string | null): number | undefined | null {\n\tif (raw === null) return undefined;\n\tif (!DECIMAL_DIGITS.test(raw)) return null;\n\tconst n = Number(raw);\n\tif (n < 1 || n > MAX_TRANSFORM_DIMENSION) return null;\n\treturn n;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,MAAa,4BAA4B;CAAC;CAAQ;CAAQ;CAAQ;CAAM;;AAGxE,MAAa,2BAAiD;;;;;;;;;;AAW9D,MAAa,4BAA4B;;AAGzC,MAAa,0BAA0B;;AAmBvC,MAAa,wBAAwB;;AAGrC,MAAa,8BAA8B;;;;;;AAO3C,MAAM,0BAA0B,IAAI,IAAI;CACvC;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;;;;;;;;AASF,SAAgB,qBAAqB,aAA6C;AACjF,QAAO;EACN,gBAAgB;EAChB,iBAAiB;EACjB,0BAA0B;EAC1B,2BACC;EACD,uBAAuB,wBAAwB,IAAI,YAAY,GAAG,WAAW;EAC7E;;;AAIF,MAAM,mBAAmB;;AAGzB,MAAM,iBAAiB;;AAGvB,SAAgB,mBAAmB,KAAsB;AACxD,QAAO,iBAAiB,KAAK,IAAI;;;;;;;;;;;;;;;AAgBlC,SAAgB,sBAAsB,MAAgD;AACrF,KAAI,CAAC,KAAM,QAAO;CAClB,IAAI;AACJ,KAAI;AACH,aAAW,IAAI,IAAI,MAAM,mBAAmB,CAAC;SACtC;AACP,SAAO;;AAER,KAAI,CAAC,SAAS,WAAW,sBAAsB,CAAE,QAAO;CACxD,MAAM,MAAM,SAAS,MAAM,sBAAsB,OAAO;AACxD,KAAI,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAE,QAAO;AAC7C,QAAO;;;AAIR,SAAgB,kBAAkB,OAA8C;AAC/E,QAAQ,0BAAgD,SAAS,MAAM;;;;;;;;;;AAgBxE,SAAgB,wBACf,QACA,WACqB;AACrB,KAAI,cAAc,OAAW,QAAO;AACpC,QAAO,WAAW,QAAQ,SAAY;;;;;;;;;;;AAYvC,SAAgB,qBAAqB,QAAgD;CACpF,MAAM,QAAQ,eAAe,OAAO,IAAI,IAAI,CAAC;AAC7C,KAAI,UAAU,KAAM,QAAO;EAAE,IAAI;EAAO,SAAS;EAAuB;AACxE,KAAI,UAAU,OAAW,QAAO;EAAE,IAAI;EAAO,SAAS;EAAuB;CAE7E,MAAM,SAAS,eAAe,OAAO,IAAI,IAAI,CAAC;AAC9C,KAAI,WAAW,KAAM,QAAO;EAAE,IAAI;EAAO,SAAS;EAAwB;CAE1E,MAAM,YAAY,OAAO,IAAI,IAAI;CACjC,IAAI,SAA+B;AACnC,KAAI,cAAc,MAAM;AACvB,MAAI,CAAC,kBAAkB,UAAU,CAChC,QAAO;GAAE,IAAI;GAAO,SAAS,6BAA6B;GAAa;AAExE,WAAS;;CAGV,IAAI;CACJ,MAAM,aAAa,OAAO,IAAI,IAAI;AAClC,KAAI,eAAe,MAAM;EACxB,MAAM,IAAI,OAAO,WAAW;AAC5B,MAAI,CAAC,OAAO,UAAU,EAAE,IAAI,IAAI,KAAK,IAAI,IACxC,QAAO;GAAE,IAAI;GAAO,SAAS;GAAyC;AAEvE,YAAU;;AAGX,QAAO;EAAE,IAAI;EAAM,SAAS;GAAE;GAAO;GAAQ;GAAQ;GAAS;EAAE;;;;;;;;AASjE,SAAS,eAAe,KAA+C;AACtE,KAAI,QAAQ,KAAM,QAAO;AACzB,KAAI,CAAC,eAAe,KAAK,IAAI,CAAE,QAAO;CACtC,MAAM,IAAI,OAAO,IAAI;AACrB,KAAI,IAAI,KAAK,IAAI,wBAAyB,QAAO;AACjD,QAAO"}
1
+ {"version":3,"file":"image-endpoint.mjs","names":[],"sources":["../../src/media/image-endpoint.ts"],"sourcesContent":["/**\n * Portable helpers shared by the platform image-endpoint modules.\n *\n * EmDash wraps Astro's image endpoint (`image.endpoint`) so that source bytes\n * for EmDash media are read straight from the storage adapter instead of being\n * fetched over HTTP. The platform endpoint modules (Node: sharp via\n * `astro:assets`; Cloudflare: the `IMAGES` binding) do the actual transform;\n * this module holds the platform-agnostic bits they share: recognizing an\n * EmDash media URL and validating transform query params.\n *\n * Kept free of `astro:*` / `virtual:emdash/*` imports so it stays in the\n * precompiled package and can be unit-tested directly.\n */\n\nimport { INTERNAL_MEDIA_PREFIX } from \"./normalize.js\";\n\n/** Output formats the wrapped endpoint can produce on Cloudflare. */\nexport const ALLOWED_TRANSFORM_FORMATS = [\"webp\", \"avif\", \"jpeg\", \"png\"] as const;\n\n/** Default output format -- broad support, strong compression. */\nexport const DEFAULT_TRANSFORM_FORMAT: ImageTransformFormat = \"webp\";\n\n/**\n * Default output quality for lossy formats (WebP/AVIF/JPEG) when the request\n * doesn't specify one. Matches the default Cloudflare applies to URL-based\n * image transformations. The Images *binding* applies no default of its own\n * and encodes near-losslessly when quality is omitted (a 2048px WebP comes\n * out ~900 KB instead of ~100 KB), so the endpoint sends an explicit quality\n * for lossy output. PNG is exempt: an explicit PNG quality switches the\n * binding to lossy PNG8, which is not a safe default for a lossless format.\n */\nexport const DEFAULT_TRANSFORM_QUALITY = 85;\n\n/** Upper bound for a requested dimension; caps the work a single request asks for. */\nexport const MAX_TRANSFORM_DIMENSION = 4000;\n\n/** Weak prefix on an ETag, stripped for weak comparison per RFC 7232. */\nconst WEAK_ETAG_PREFIX = /^W\\//;\n\n/**\n * Strip surrounding whitespace and the weak prefix from an ETag value for\n * weak comparison. Defined at module scope so it is not recreated per request.\n */\nfunction stripWeakEtagPrefix(value: string): string {\n\treturn value.trim().replace(WEAK_ETAG_PREFIX, \"\");\n}\n\n/** A format string accepted by {@link ImageTransformOptions.format}. */\nexport type ImageTransformFormat = (typeof ALLOWED_TRANSFORM_FORMATS)[number];\n\n/** Validated options for a single transform. */\nexport interface ImageTransformOptions {\n\twidth?: number;\n\theight?: number;\n\tformat: ImageTransformFormat;\n\t/**\n\t * Explicitly-requested quality (1-100), or `undefined` when the request\n\t * carried no `q`. Callers apply their own default per format (see\n\t * {@link DEFAULT_TRANSFORM_QUALITY}); lossless PNG deliberately gets none.\n\t */\n\tquality?: number;\n}\n\n/** Long-lived cache for content-addressed image URLs. */\nexport const IMMUTABLE_IMAGE_CACHE = \"public, max-age=31536000, immutable\";\n\n/** Cache policy for media keys that Replace original may overwrite. */\nexport const MUTABLE_MEDIA_CACHE_CONTROL = \"public, max-age=0, must-revalidate\";\n\n/**\n * Format a Date as an HTTP-date (RFC 7231).\n */\nexport function formatHttpDate(date: Date): string {\n\treturn date.toUTCString();\n}\n\n/**\n * Build a weak validator from representation metadata. Weak because it is based\n * on size and modification time rather than a content hash. Keeps the same\n * shape for stored files and derived transforms so replacements change the tag.\n */\nexport function makeWeakEtag(size: number, lastModified?: Date, suffix?: string): string {\n\tlet value = String(size);\n\tif (lastModified) value += `-${lastModified.getTime()}`;\n\tif (suffix) value += `-${suffix}`;\n\treturn `W/\"${value}\"`;\n}\n\n/**\n * Build a canonical fingerprint of the transform query params that affect the\n * derived /_image bytes. Used as the suffix of a transform's weak ETag.\n */\nexport function getTransformFingerprint(params: URLSearchParams): string {\n\tconst parts: string[] = [];\n\tconst append = (name: string) => {\n\t\tconst value = params.get(name);\n\t\tif (value !== null) parts.push(`${name}=${value}`);\n\t};\n\tappend(\"w\");\n\tappend(\"h\");\n\tappend(\"f\");\n\tappend(\"q\");\n\tappend(\"fit\");\n\treturn parts.join(\"&\");\n}\n\n/**\n * Check whether a request's preconditions are satisfied for the given\n * representation. Returns true when the client already has the current version.\n */\nexport function isNotModified(\n\trequest: Request,\n\tsize: number,\n\tlastModified?: Date,\n\tsuffix?: string,\n): boolean {\n\tconst etag = makeWeakEtag(size, lastModified, suffix);\n\tconst ifNoneMatch = request.headers.get(\"If-None-Match\");\n\tif (ifNoneMatch !== null) {\n\t\tif (ifNoneMatch.trim() === \"*\") return true;\n\t\t// If-None-Match uses weak comparison: \"W/\" prefixes are ignored.\n\t\tconst requestedTags = ifNoneMatch.split(\",\").map(stripWeakEtagPrefix);\n\t\treturn requestedTags.includes(stripWeakEtagPrefix(etag));\n\t}\n\tconst ifModifiedSince = request.headers.get(\"If-Modified-Since\");\n\tif (ifModifiedSince !== null && lastModified) {\n\t\tconst since = Date.parse(ifModifiedSince);\n\t\tif (!Number.isNaN(since)) {\n\t\t\t// HTTP-date has one-second precision; round the stored time down so\n\t\t\t// a Last-Modified header replayed as If-Modified-Since always matches.\n\t\t\treturn Math.floor(lastModified.getTime() / 1000) * 1000 <= since;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Headers that make a mutable representation conditionally cacheable.\n */\nexport function validatorHeaders(\n\tsize: number,\n\tlastModified?: Date,\n\tsuffix?: string,\n): Record<string, string> {\n\tconst headers: Record<string, string> = {\n\t\tETag: makeWeakEtag(size, lastModified, suffix),\n\t};\n\tif (lastModified) {\n\t\theaders[\"Last-Modified\"] = formatHttpDate(lastModified);\n\t}\n\treturn headers;\n}\n\n/**\n * Raster types safe to render inline. Anything else (SVG, PDF, ...) is served\n * as an attachment so it can't execute as an active document. Mirrors the\n * `/_emdash/api/media/file/{key}` route's allowlist.\n */\nconst SAFE_INLINE_IMAGE_TYPES = new Set([\n\t\"image/jpeg\",\n\t\"image/png\",\n\t\"image/gif\",\n\t\"image/webp\",\n\t\"image/avif\",\n\t\"image/x-icon\",\n]);\n\n/**\n * Headers for streaming **original** stored bytes (the no-transform fallback).\n * Carries the same stored-XSS protections as the media file route: a sandbox\n * CSP, `nosniff`, and `Content-Disposition: attachment` for anything not on the\n * inline raster allowlist (so a stored SVG can't run scripts in the site\n * origin). Transformed output is always generated raster and doesn't need this.\n */\nexport function originalMediaHeaders(\n\tcontentType: string,\n\tsize?: number,\n\tlastModified?: Date,\n): Record<string, string> {\n\treturn {\n\t\t\"Content-Type\": contentType,\n\t\t\"Cache-Control\": MUTABLE_MEDIA_CACHE_CONTROL,\n\t\t\"X-Content-Type-Options\": \"nosniff\",\n\t\t\"Content-Security-Policy\":\n\t\t\t\"sandbox; default-src 'none'; img-src 'self'; style-src 'unsafe-inline'\",\n\t\t\"Content-Disposition\": SAFE_INLINE_IMAGE_TYPES.has(contentType) ? \"inline\" : \"attachment\",\n\t\t...(size !== undefined ? validatorHeaders(size, lastModified) : {}),\n\t};\n}\n\n/** Storage keys safe to serve: the flat `{ulid}{ext}` shape, no slashes/traversal. */\nconst SAFE_STORAGE_KEY = /^[A-Za-z0-9._-]+$/;\n\n/** Plain decimal digits only -- rejects \"1e3\", \"0x10\", \"+5\", whitespace. */\nconst DECIMAL_DIGITS = /^\\d+$/;\n\n/** Whether a storage key is safe to resolve against the storage backend. */\nexport function isSafeTransformKey(key: string): boolean {\n\treturn SAFE_STORAGE_KEY.test(key);\n}\n\n/**\n * If `href` points at the internal EmDash media route\n * (`/_emdash/api/media/file/{key}`) with a safe key, return the key; otherwise\n * `null` (the endpoint then delegates to the stock image endpoint for bundled\n * assets, allowed remote, and `publicUrl` media).\n *\n * The component absolutizes same-origin media (Astro only optimizes absolute,\n * remote-allowed URLs), so `href` is typically `https://site/_emdash/...` but\n * may be relative. We match on the **pathname** only and never fetch `href` —\n * the key is read from our own storage — so the host is irrelevant and can't be\n * an SSRF vector. A dummy base resolves both absolute and relative forms and\n * strips any query/fragment.\n */\nexport function matchInternalMediaKey(href: string | null | undefined): string | null {\n\tif (!href) return null;\n\tlet pathname: string;\n\ttry {\n\t\tpathname = new URL(href, \"http://localhost\").pathname;\n\t} catch {\n\t\treturn null;\n\t}\n\tif (!pathname.startsWith(INTERNAL_MEDIA_PREFIX)) return null;\n\tconst key = pathname.slice(INTERNAL_MEDIA_PREFIX.length);\n\tif (!key || !isSafeTransformKey(key)) return null;\n\treturn key;\n}\n\n/** Type guard for {@link ImageTransformFormat}. */\nexport function isTransformFormat(value: string): value is ImageTransformFormat {\n\treturn (ALLOWED_TRANSFORM_FORMATS as readonly string[]).includes(value);\n}\n\n/** Outcome of parsing transform query params: validated options or an error. */\nexport type ParsedTransformParams =\n\t| { ok: true; options: ImageTransformOptions }\n\t| { ok: false; message: string };\n\n/**\n * Resolve the quality to send to the image binding for a transform. An\n * explicitly-requested quality always wins. Otherwise lossy formats\n * (WebP/AVIF/JPEG) get {@link DEFAULT_TRANSFORM_QUALITY} because the Images\n * binding encodes near-losslessly when quality is omitted; lossless PNG gets\n * `undefined` because an explicit PNG quality switches the binding to lossy\n * PNG8, which is not a safe default for a lossless format.\n */\nexport function resolveTransformQuality(\n\tformat: ImageTransformFormat,\n\trequested: number | undefined,\n): number | undefined {\n\tif (requested !== undefined) return requested;\n\treturn format === \"png\" ? undefined : DEFAULT_TRANSFORM_QUALITY;\n}\n\n/**\n * Parse and validate `?w=&h=&f=&q=` query params. Width is required (it sizes\n * the rendition); dimensions are bounded so a request can't ask for an\n * unbounded or nonsensical transform. Format falls back to\n * {@link DEFAULT_TRANSFORM_FORMAT} when not requested. `q` is validated when\n * present but otherwise left `undefined` so the caller can apply a per-format\n * default (lossy formats get one, lossless PNG does not — see\n * {@link DEFAULT_TRANSFORM_QUALITY}).\n */\nexport function parseTransformParams(params: URLSearchParams): ParsedTransformParams {\n\tconst width = parseDimension(params.get(\"w\"));\n\tif (width === null) return { ok: false, message: \"Invalid 'w' (width)\" };\n\tif (width === undefined) return { ok: false, message: \"Missing 'w' (width)\" };\n\n\tconst height = parseDimension(params.get(\"h\"));\n\tif (height === null) return { ok: false, message: \"Invalid 'h' (height)\" };\n\n\tconst formatRaw = params.get(\"f\");\n\tlet format: ImageTransformFormat = DEFAULT_TRANSFORM_FORMAT;\n\tif (formatRaw !== null) {\n\t\tif (!isTransformFormat(formatRaw)) {\n\t\t\treturn { ok: false, message: `Unsupported 'f' (format): ${formatRaw}` };\n\t\t}\n\t\tformat = formatRaw;\n\t}\n\n\tlet quality: number | undefined;\n\tconst qualityRaw = params.get(\"q\");\n\tif (qualityRaw !== null) {\n\t\tconst q = Number(qualityRaw);\n\t\tif (!Number.isInteger(q) || q < 1 || q > 100) {\n\t\t\treturn { ok: false, message: \"Invalid 'q' (quality), expected 1-100\" };\n\t\t}\n\t\tquality = q;\n\t}\n\n\treturn { ok: true, options: { width, height, format, quality } };\n}\n\n/**\n * Parse a dimension query value.\n * - `undefined`: param absent\n * - `null`: present but invalid (non-integer, out of range)\n * - `number`: valid, within [1, MAX_TRANSFORM_DIMENSION]\n */\nfunction parseDimension(raw: string | null): number | undefined | null {\n\tif (raw === null) return undefined;\n\tif (!DECIMAL_DIGITS.test(raw)) return null;\n\tconst n = Number(raw);\n\tif (n < 1 || n > MAX_TRANSFORM_DIMENSION) return null;\n\treturn n;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { _ as MediaValue, a as ComponentEmbed, b as mediaItemToValue, c as EmbedResult, d as MediaListResult, f as MediaProvider, g as MediaUploadInput, h as MediaProviderItem, i as AudioEmbed, l as ImageEmbed, m as MediaProviderDescriptor, n as generatePlaceholder, o as CreateMediaProviderFn, p as MediaProviderCapabilities, r as normalizeMediaValue, s as EmbedOptions, t as PlaceholderData, u as MediaListOptions, v as ThumbnailOptions, y as VideoEmbed } from "../placeholder-Bez2282x.mjs";
1
+ import { _ as MediaValue, a as ComponentEmbed, b as mediaItemToValue, c as EmbedResult, d as MediaListResult, f as MediaProvider, g as MediaUploadInput, h as MediaProviderItem, i as AudioEmbed, l as ImageEmbed, m as MediaProviderDescriptor, n as generatePlaceholder, o as CreateMediaProviderFn, p as MediaProviderCapabilities, r as normalizeMediaValue, s as EmbedOptions, t as PlaceholderData, u as MediaListOptions, v as ThumbnailOptions, y as VideoEmbed } from "../placeholder-nOep3_Gn.mjs";
2
2
 
3
3
  //#region src/media/enrich.d.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
1
  import { n as normalizeFocalPoint } from "../focal-point-JX8kcOTQ.mjs";
2
2
  import { n as normalizeMediaValue } from "../normalize-BuWa0lvd.mjs";
3
3
  import "../dist-Cfu8mMBs.mjs";
4
- import { n as generatePlaceholder, t as enrichImageMetadata } from "../enrich-BDdVNeDK.mjs";
4
+ import { n as generatePlaceholder, t as enrichImageMetadata } from "../enrich-Duu4sV3a.mjs";
5
5
 
6
6
  //#region src/media/types.ts
7
7
  /**
@@ -1,17 +1,17 @@
1
- import "../parse-BPblgoa-.mjs";
2
- import { t as Database } from "../types-ibtP7GEA.mjs";
3
- import "../types-BYVIYOlD.mjs";
4
- import "../options-DRF6dlXY.mjs";
5
- import "../entry-lock-DY8B-xcr.mjs";
6
- import { h as MediaProviderItem, o as CreateMediaProviderFn } from "../placeholder-Bez2282x.mjs";
7
- import "../config-BCM5sQP7.mjs";
8
- import "../runner-CWl76CH3.mjs";
9
- import "../storage-query-CdVF2bng.mjs";
10
- import "../index-xCy3j0f6.mjs";
11
- import { d as Storage } from "../types-MN9bOQ1g.mjs";
12
- import "../types-Dr1LVwL7.mjs";
13
- import "../hreflang-uIBOE5yg.mjs";
14
- import "../validate-Df09inbC.mjs";
1
+ import "../parse-BOGhrwSq.mjs";
2
+ import { t as Database } from "../types-UKr5Sf4y.mjs";
3
+ import "../types-C4P7F1Vq.mjs";
4
+ import "../options-BR9XZl7h.mjs";
5
+ import "../entry-lock-BAAlKYrz.mjs";
6
+ import { h as MediaProviderItem, o as CreateMediaProviderFn } from "../placeholder-nOep3_Gn.mjs";
7
+ import "../config-C4-UxIk7.mjs";
8
+ import "../runner-DkeafPBA.mjs";
9
+ import "../storage-query-BOBmeDMD.mjs";
10
+ import "../index-DYsn97dY.mjs";
11
+ import { p as Storage } from "../types-B4-1P2DK.mjs";
12
+ import "../types-Bq9Wohd7.mjs";
13
+ import "../hreflang-BsYo4x_M.mjs";
14
+ import "../validate-Dfv0DpZi.mjs";
15
15
  import "../index.mjs";
16
16
  import { Kysely } from "kysely";
17
17
 
@@ -2,15 +2,15 @@ import "../dialect-helpers-7_IqPdh9.mjs";
2
2
  import "../config-CvmjJcVw.mjs";
3
3
  import "../after-PcEvMY_6.mjs";
4
4
  import "../options-DhrI7eMv.mjs";
5
- import "../base64-DvnNgP7e.mjs";
6
- import "../secrets-CIi0nFiR.mjs";
5
+ import "../secrets-Cc_O3Kp-.mjs";
6
+ import "../base64-BQBZwXCx.mjs";
7
7
  import "../object-cache-Bo6DGaC9.mjs";
8
8
  import "../request-cache-C4CIo5ad.mjs";
9
- import "../types-j6MBDjlZ.mjs";
10
- import { t as MediaRepository } from "../media-CputjGE1.mjs";
11
- import "../loader-D4edocWH.mjs";
12
- import { n as handleMediaDelete } from "../media-3v7mqAVX.mjs";
13
- import { s as invalidateSiteSettingsCache } from "../settings-D_cJtT48.mjs";
9
+ import "../types-C-Xp0CcN.mjs";
10
+ import { t as MediaRepository } from "../media-IT8hQleU.mjs";
11
+ import "../loader-CetY659y.mjs";
12
+ import { n as handleMediaDelete } from "../media-C_z7sRuC.mjs";
13
+ import { c as invalidateSiteSettingsCache } from "../settings-B1jOxAIl.mjs";
14
14
 
15
15
  //#region src/media/local-runtime.ts
16
16
  /**