emdash 0.37.0 → 0.38.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 (811) hide show
  1. package/dist/{activation-K0kGBWuJ.mjs → activation-DyNTe_Tl.mjs} +3 -3
  2. package/dist/{activation-K0kGBWuJ.mjs.map → activation-DyNTe_Tl.mjs.map} +1 -1
  3. package/dist/{adapters-BDQwg236.d.mts → adapters-DCEgOBXi.d.mts} +1 -1
  4. package/dist/{adapters-BDQwg236.d.mts.map → adapters-DCEgOBXi.d.mts.map} +1 -1
  5. package/dist/{allowed-origins-BGglilcs.mjs → allowed-origins-GFUVavRj.mjs} +2 -2
  6. package/dist/{allowed-origins-BGglilcs.mjs.map → allowed-origins-GFUVavRj.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +23 -22
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +2 -2
  11. package/dist/api/schemas/index.mjs +5 -5
  12. package/dist/{api-Dz6rgoa3.mjs → api-BvxJmnFY.mjs} +141 -87
  13. package/dist/api-BvxJmnFY.mjs.map +1 -0
  14. package/dist/{api-tokens-BSsQACNe.mjs → api-tokens-xpGqMHrC.mjs} +2 -2
  15. package/dist/{api-tokens-BSsQACNe.mjs.map → api-tokens-xpGqMHrC.mjs.map} +1 -1
  16. package/dist/{apply-B4SIOxR1.mjs → apply-DLmM3R7f.mjs} +25 -21
  17. package/dist/apply-DLmM3R7f.mjs.map +1 -0
  18. package/dist/{config-it29yDLA.mjs → artifact-fetch-P2JXVwOq.mjs} +8 -199
  19. package/dist/artifact-fetch-P2JXVwOq.mjs.map +1 -0
  20. package/dist/astro/index.d.mts +12 -12
  21. package/dist/astro/index.d.mts.map +1 -1
  22. package/dist/astro/index.mjs +37 -11
  23. package/dist/astro/index.mjs.map +1 -1
  24. package/dist/astro/middleware/auth.d.mts +10 -10
  25. package/dist/astro/middleware/auth.mjs +6 -6
  26. package/dist/astro/middleware/media-usage-write-fence.mjs +3 -3
  27. package/dist/astro/middleware/redirect.mjs +7 -5
  28. package/dist/astro/middleware/redirect.mjs.map +1 -1
  29. package/dist/astro/middleware/request-context.mjs +3 -3
  30. package/dist/astro/middleware/setup.mjs +1 -1
  31. package/dist/astro/middleware.d.mts +10 -10
  32. package/dist/astro/middleware.d.mts.map +1 -1
  33. package/dist/astro/middleware.mjs +154 -125
  34. package/dist/astro/middleware.mjs.map +1 -1
  35. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
  36. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
  37. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
  38. package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
  39. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  40. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -9
  41. package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -9
  42. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -9
  43. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +16 -16
  44. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +16 -16
  45. package/dist/astro/routes/api/admin/bylines/index.mjs +16 -16
  46. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +11 -11
  47. package/dist/astro/routes/api/admin/comments/_id_.mjs +3 -3
  48. package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
  49. package/dist/astro/routes/api/admin/comments/counts.mjs +3 -3
  50. package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
  51. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  52. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  53. package/dist/astro/routes/api/admin/media-usage/activation.mjs +13 -13
  54. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +15 -15
  55. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +15 -15
  56. package/dist/astro/routes/api/admin/media-usage/progress.mjs +13 -13
  57. package/dist/astro/routes/api/admin/media-usage/repair.mjs +16 -16
  58. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +15 -15
  59. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +15 -15
  60. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  61. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  62. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +56 -53
  63. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +56 -53
  65. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +54 -51
  67. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
  69. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +54 -51
  70. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +55 -52
  72. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +55 -52
  74. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/index.mjs +54 -51
  76. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +54 -51
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +55 -52
  81. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +54 -51
  83. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +55 -52
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +56 -53
  87. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +5 -4
  89. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +56 -53
  91. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +55 -52
  93. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs +54 -51
  95. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +54 -51
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  99. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +54 -51
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +1 -1
  102. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  103. package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
  104. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  105. package/dist/astro/routes/api/admin/users/index.mjs +6 -6
  106. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  107. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  108. package/dist/astro/routes/api/auth/invite/complete.mjs +11 -11
  109. package/dist/astro/routes/api/auth/invite/index.mjs +8 -8
  110. package/dist/astro/routes/api/auth/invite/register-options.mjs +10 -10
  111. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  112. package/dist/astro/routes/api/auth/magic-link/send.mjs +10 -10
  113. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  114. package/dist/astro/routes/api/auth/me.mjs +7 -7
  115. package/dist/astro/routes/api/auth/mode.mjs +2 -2
  116. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  117. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  118. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
  119. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  120. package/dist/astro/routes/api/auth/passkey/options.mjs +12 -12
  121. package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -10
  122. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -11
  123. package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -11
  124. package/dist/astro/routes/api/auth/signup/complete.mjs +11 -11
  125. package/dist/astro/routes/api/auth/signup/request.mjs +10 -10
  126. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  127. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  128. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +11 -11
  129. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  130. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
  131. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +13 -8
  132. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  133. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  134. package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts +10 -0
  135. package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts.map +1 -0
  136. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +66 -0
  137. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs.map +1 -0
  138. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
  139. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -11
  140. package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts.map +1 -1
  141. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +14 -9
  142. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  143. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +19 -17
  144. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  145. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +19 -17
  146. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  147. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  148. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  149. package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
  150. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +15 -8
  151. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  152. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +15 -14
  153. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  154. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  155. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
  156. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +13 -8
  157. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  158. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  159. package/dist/astro/routes/api/content/_collection_/_id_.mjs +23 -11
  160. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  161. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  162. package/dist/astro/routes/api/content/_collection_/index.mjs +14 -9
  163. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  164. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
  165. package/dist/astro/routes/api/dashboard.mjs +6 -6
  166. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  167. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  168. package/dist/astro/routes/api/import/probe.mjs +16 -16
  169. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  170. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  171. package/dist/astro/routes/api/import/wordpress/execute.mjs +14 -13
  172. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  173. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  174. package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
  175. package/dist/astro/routes/api/import/wordpress/prepare.mjs +10 -10
  176. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  177. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +13 -13
  178. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  179. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +16 -16
  180. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  181. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +27 -26
  182. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  183. package/dist/astro/routes/api/manifest.mjs +4 -4
  184. package/dist/astro/routes/api/mcp.mjs +71 -55
  185. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  186. package/dist/astro/routes/api/media/_id_/confirm.mjs +10 -10
  187. package/dist/astro/routes/api/media/_id_/replace.mjs +8 -8
  188. package/dist/astro/routes/api/media/_id_/upload.mjs +5 -5
  189. package/dist/astro/routes/api/media/_id_/usage.mjs +18 -18
  190. package/dist/astro/routes/api/media/_id_.mjs +17 -17
  191. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  192. package/dist/astro/routes/api/media/folders/_id_.mjs +8 -8
  193. package/dist/astro/routes/api/media/folders/index.mjs +8 -8
  194. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  195. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  196. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  197. package/dist/astro/routes/api/media/upload-url.mjs +9 -9
  198. package/dist/astro/routes/api/media.mjs +21 -21
  199. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -9
  200. package/dist/astro/routes/api/menus/_name_/items.mjs +9 -9
  201. package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -9
  202. package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -9
  203. package/dist/astro/routes/api/menus/_name_.mjs +9 -9
  204. package/dist/astro/routes/api/menus/index.mjs +9 -9
  205. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  206. package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
  207. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  208. package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
  209. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  210. package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
  211. package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
  212. package/dist/astro/routes/api/oauth/token.mjs +5 -5
  213. package/dist/astro/routes/api/openapi.json.mjs +84 -18
  214. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  215. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  216. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -11
  217. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  218. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -11
  219. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  220. package/dist/astro/routes/api/redirects/_id_.mjs +13 -12
  221. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  222. package/dist/astro/routes/api/redirects/index.mjs +13 -12
  223. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  224. package/dist/astro/routes/api/relations/_id_/index.mjs +19 -17
  225. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  226. package/dist/astro/routes/api/relations/_id_/translations.mjs +14 -12
  227. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  228. package/dist/astro/routes/api/relations/index.mjs +19 -17
  229. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  230. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  231. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  232. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +54 -51
  233. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  234. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +54 -51
  235. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  236. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +54 -51
  237. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  238. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +54 -51
  239. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/schema/collections/index.mjs +54 -51
  241. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  242. package/dist/astro/routes/api/schema/collections/reorder.mjs +54 -51
  243. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  244. package/dist/astro/routes/api/schema/index.mjs +13 -11
  245. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  246. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +54 -51
  247. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  248. package/dist/astro/routes/api/schema/orphans/index.mjs +54 -51
  249. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  250. package/dist/astro/routes/api/search/enable.mjs +12 -11
  251. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  252. package/dist/astro/routes/api/search/index.mjs +11 -10
  253. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  254. package/dist/astro/routes/api/search/rebuild.mjs +12 -11
  255. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  256. package/dist/astro/routes/api/search/stats.mjs +7 -6
  257. package/dist/astro/routes/api/search/stats.mjs.map +1 -1
  258. package/dist/astro/routes/api/search/suggest.mjs +11 -10
  259. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  260. package/dist/astro/routes/api/sections/_slug_.mjs +11 -10
  261. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  262. package/dist/astro/routes/api/sections/index.mjs +11 -10
  263. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  264. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -6
  265. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs.map +1 -1
  266. package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -5
  267. package/dist/astro/routes/api/settings/backups/archives/index.mjs.map +1 -1
  268. package/dist/astro/routes/api/settings/backups/export.mjs +7 -6
  269. package/dist/astro/routes/api/settings/backups/export.mjs.map +1 -1
  270. package/dist/astro/routes/api/settings/backups/index.mjs +8 -7
  271. package/dist/astro/routes/api/settings/backups/index.mjs.map +1 -1
  272. package/dist/astro/routes/api/settings/email.mjs +4 -4
  273. package/dist/astro/routes/api/settings.mjs +14 -14
  274. package/dist/astro/routes/api/setup/admin-verify.mjs +12 -12
  275. package/dist/astro/routes/api/setup/admin.mjs +11 -11
  276. package/dist/astro/routes/api/setup/dev-bypass.mjs +33 -31
  277. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  278. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  279. package/dist/astro/routes/api/setup/index.mjs +33 -31
  280. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  281. package/dist/astro/routes/api/setup/status.mjs +3 -3
  282. package/dist/astro/routes/api/snapshot.mjs +8 -7
  283. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  284. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +16 -15
  285. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  286. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -15
  287. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  288. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -15
  289. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  290. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -15
  291. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  292. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +15 -14
  293. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
  294. package/dist/astro/routes/api/taxonomies/_name_.mjs +16 -15
  295. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
  296. package/dist/astro/routes/api/taxonomies/index.mjs +16 -15
  297. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  298. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  299. package/dist/astro/routes/api/typegen.mjs +4 -4
  300. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  301. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  302. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  303. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  304. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +12 -12
  305. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +12 -12
  306. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
  307. package/dist/astro/routes/api/widget-areas/index.mjs +12 -12
  308. package/dist/astro/routes/api/widget-components.mjs +2 -2
  309. package/dist/astro/routes/robots.txt.mjs +6 -6
  310. package/dist/astro/routes/sitemap-_collection_.xml.mjs +11 -10
  311. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  312. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  313. package/dist/astro/types.d.mts +32 -17
  314. package/dist/astro/types.d.mts.map +1 -1
  315. package/dist/auth/providers/github.d.mts +1 -1
  316. package/dist/auth/providers/google.d.mts +1 -1
  317. package/dist/{authorize-Bkf_UHhD.mjs → authorize-C2QHlWSS.mjs} +2 -2
  318. package/dist/{authorize-Bkf_UHhD.mjs.map → authorize-C2QHlWSS.mjs.map} +1 -1
  319. package/dist/{backup-rwVAl9NI.mjs → backup-oS8ft5Cm.mjs} +5 -5
  320. package/dist/{backup-rwVAl9NI.mjs.map → backup-oS8ft5Cm.mjs.map} +1 -1
  321. package/dist/{bundle-C8S2Zl6U.mjs → bundle-CL0JjIPx.mjs} +4 -4
  322. package/dist/{bundle-C8S2Zl6U.mjs.map → bundle-CL0JjIPx.mjs.map} +1 -1
  323. package/dist/{byline-DuhF7NWl.mjs → byline-Vdi85CsZ.mjs} +6 -6
  324. package/dist/{byline-DuhF7NWl.mjs.map → byline-Vdi85CsZ.mjs.map} +1 -1
  325. package/dist/{byline-fields-BovY4KYM.mjs → byline-fields-DPVRFMz2.mjs} +2 -2
  326. package/dist/{byline-fields-BovY4KYM.mjs.map → byline-fields-DPVRFMz2.mjs.map} +1 -1
  327. package/dist/{byline-registry-Bpu9-MVs.mjs → byline-registry-BxDGIO0I.mjs} +2 -2
  328. package/dist/{byline-registry-Bpu9-MVs.mjs.map → byline-registry-BxDGIO0I.mjs.map} +1 -1
  329. package/dist/{bylines-CJ5nd6Lw.mjs → bylines-BX8QhcTk.mjs} +7 -7
  330. package/dist/{bylines-CJ5nd6Lw.mjs.map → bylines-BX8QhcTk.mjs.map} +1 -1
  331. package/dist/{bylines-RwBAeOF1.mjs → bylines-w-E1IEQd.mjs} +3 -3
  332. package/dist/{bylines-RwBAeOF1.mjs.map → bylines-w-E1IEQd.mjs.map} +1 -1
  333. package/dist/{cache-BF5Kvn59.mjs → cache--7HKu5Xm.mjs} +4 -4
  334. package/dist/{cache-BF5Kvn59.mjs.map → cache--7HKu5Xm.mjs.map} +1 -1
  335. package/dist/{capture-triggers-CNW1q3HK.mjs → capture-triggers-CeAsC76Z.mjs} +2 -2
  336. package/dist/{capture-triggers-CNW1q3HK.mjs.map → capture-triggers-CeAsC76Z.mjs.map} +1 -1
  337. package/dist/{challenge-store-DQN_Yrck.mjs → challenge-store-BIOak-tp.mjs} +1 -1
  338. package/dist/{challenge-store-DQN_Yrck.mjs.map → challenge-store-BIOak-tp.mjs.map} +1 -1
  339. package/dist/{chrome-tags-D8fiZG94.mjs → chrome-tags-DzDQBCjX.mjs} +1 -1
  340. package/dist/{chrome-tags-D8fiZG94.mjs.map → chrome-tags-DzDQBCjX.mjs.map} +1 -1
  341. package/dist/{chunks-C4szrD8o.mjs → chunks-VG_tyqnP.mjs} +2 -2
  342. package/dist/{chunks-C4szrD8o.mjs.map → chunks-VG_tyqnP.mjs.map} +1 -1
  343. package/dist/cli/index.mjs +66 -38
  344. package/dist/cli/index.mjs.map +1 -1
  345. package/dist/client/cf-access.d.mts +1 -1
  346. package/dist/client/index.d.mts +17 -7
  347. package/dist/client/index.d.mts.map +1 -1
  348. package/dist/client/index.mjs +17 -12
  349. package/dist/client/index.mjs.map +1 -1
  350. package/dist/{collection-deletion-Bj07NHbj.mjs → collection-deletion-BCwaWTDw.mjs} +4 -4
  351. package/dist/{collection-deletion-Bj07NHbj.mjs.map → collection-deletion-BCwaWTDw.mjs.map} +1 -1
  352. package/dist/collection-slugs-cache-7lTmNzeA.mjs +85 -0
  353. package/dist/collection-slugs-cache-7lTmNzeA.mjs.map +1 -0
  354. package/dist/{comment-reaction-BhrvSHml.mjs → comment-reaction-CDyvPQRj.mjs} +2 -2
  355. package/dist/{comment-reaction-BhrvSHml.mjs.map → comment-reaction-CDyvPQRj.mjs.map} +1 -1
  356. package/dist/{comments-Ct4ensnf.mjs → comments-VzmVLyaC.mjs} +1 -1
  357. package/dist/{comments-Ct4ensnf.mjs.map → comments-VzmVLyaC.mjs.map} +1 -1
  358. package/dist/{components-DJbo1z0S.mjs → components-CL6Wkdk-.mjs} +1 -1
  359. package/dist/{components-DJbo1z0S.mjs.map → components-CL6Wkdk-.mjs.map} +1 -1
  360. package/dist/config--eWjQJE5.mjs +217 -0
  361. package/dist/config--eWjQJE5.mjs.map +1 -0
  362. package/dist/{index-BJNMCWmu.d.mts → config-CGAhyOjP.d.mts} +138 -47
  363. package/dist/config-CGAhyOjP.d.mts.map +1 -0
  364. package/dist/{config-B9eZ340f.d.mts → config-ChFzshGd.d.mts} +1 -1
  365. package/dist/{config-B9eZ340f.d.mts.map → config-ChFzshGd.d.mts.map} +1 -1
  366. package/dist/{content-DjvM0T92.mjs → content-CNfMWuhY.mjs} +121 -5
  367. package/dist/content-CNfMWuhY.mjs.map +1 -0
  368. package/dist/{content-list-query-Btqd4uV2.d.mts → content-list-query-B8d4UQp9.d.mts} +1 -1
  369. package/dist/{content-list-query-Btqd4uV2.d.mts.map → content-list-query-B8d4UQp9.d.mts.map} +1 -1
  370. package/dist/{content-refresh-Bwp-8yGy.mjs → content-refresh-GTMyi2Xy.mjs} +8 -8
  371. package/dist/{content-refresh-Bwp-8yGy.mjs.map → content-refresh-GTMyi2Xy.mjs.map} +1 -1
  372. package/dist/{content-repair-Czdp7jz5.mjs → content-repair-CIMt5C0U.mjs} +4 -4
  373. package/dist/{content-repair-Czdp7jz5.mjs.map → content-repair-CIMt5C0U.mjs.map} +1 -1
  374. package/dist/{context-CX6gxOLW.mjs → context-C9PB8vGd.mjs} +265 -25
  375. package/dist/context-C9PB8vGd.mjs.map +1 -0
  376. package/dist/{cron-C6o7VppJ.mjs → cron-DHAy9oyq.mjs} +1 -1
  377. package/dist/{cron-C6o7VppJ.mjs.map → cron-DHAy9oyq.mjs.map} +1 -1
  378. package/dist/{dashboard-C2kTeeRI.mjs → dashboard-BNSvAN8A.mjs} +4 -4
  379. package/dist/{dashboard-C2kTeeRI.mjs.map → dashboard-BNSvAN8A.mjs.map} +1 -1
  380. package/dist/db/index.d.mts +3 -3
  381. package/dist/db/index.mjs +2 -2
  382. package/dist/db/libsql-migrations.d.mts +1 -1
  383. package/dist/db/libsql-migrations.mjs +5 -5
  384. package/dist/db/libsql.d.mts +1 -1
  385. package/dist/db/postgres-migrations.d.mts +1 -1
  386. package/dist/db/postgres-migrations.mjs +5 -5
  387. package/dist/db/postgres.d.mts +1 -1
  388. package/dist/db/sqlite-migrations.d.mts +1 -1
  389. package/dist/db/sqlite-migrations.mjs +5 -5
  390. package/dist/db/sqlite.d.mts +1 -1
  391. package/dist/db/sqlite.mjs +1 -1
  392. package/dist/{default-Clra32mw.mjs → default-ByZ0JqZo.mjs} +1 -1
  393. package/dist/{default-Clra32mw.mjs.map → default-ByZ0JqZo.mjs.map} +1 -1
  394. package/dist/{deferred-tasks-CvDETTJO.d.mts → deferred-tasks-Cu4NSJpa.d.mts} +1 -1
  395. package/dist/{deferred-tasks-CvDETTJO.d.mts.map → deferred-tasks-Cu4NSJpa.d.mts.map} +1 -1
  396. package/dist/{dev-typegen-DzOPfsNj.mjs → dev-typegen-DHT7lcMU.mjs} +1 -1
  397. package/dist/{dev-typegen-DzOPfsNj.mjs.map → dev-typegen-DHT7lcMU.mjs.map} +1 -1
  398. package/dist/{device-flow-D2oCWvLJ.mjs → device-flow-Cf6bhCCT.mjs} +4 -4
  399. package/dist/{device-flow-D2oCWvLJ.mjs.map → device-flow-Cf6bhCCT.mjs.map} +1 -1
  400. package/dist/{dialect-helpers-BSbfaO3F.mjs → dialect-helpers-BcQvkHgn.mjs} +83 -2
  401. package/dist/dialect-helpers-BcQvkHgn.mjs.map +1 -0
  402. package/dist/{direct-executor-Bfa5_ToE.mjs → direct-executor-yAyUGSqB.mjs} +3 -3
  403. package/dist/{direct-executor-Bfa5_ToE.mjs.map → direct-executor-yAyUGSqB.mjs.map} +1 -1
  404. package/dist/{dist-89xCrGqi.mjs → dist-BAsh8dbf.mjs} +1 -1
  405. package/dist/{dist-89xCrGqi.mjs.map → dist-BAsh8dbf.mjs.map} +1 -1
  406. package/dist/{email-console-Dzb6uGYa.mjs → email-console-DNup1Fku.mjs} +1 -1
  407. package/dist/{email-console-Dzb6uGYa.mjs.map → email-console-DNup1Fku.mjs.map} +1 -1
  408. package/dist/{enrich-BX0IDp4z.mjs → enrich-t2Xvjdqa.mjs} +3 -3
  409. package/dist/{enrich-BX0IDp4z.mjs.map → enrich-t2Xvjdqa.mjs.map} +1 -1
  410. package/dist/entry-lock-BEr8gDkG.mjs +163 -0
  411. package/dist/entry-lock-BEr8gDkG.mjs.map +1 -0
  412. package/dist/{relations-DnRK4YIT.d.mts → entry-lock-CGAtrwAR.d.mts} +92 -37
  413. package/dist/entry-lock-CGAtrwAR.d.mts.map +1 -0
  414. package/dist/{redirects-BLNOWQTn.mjs → entry-lock-DIYHAaSw.mjs} +57 -14
  415. package/dist/entry-lock-DIYHAaSw.mjs.map +1 -0
  416. package/dist/entry-locks-BEcX7ET0.mjs +167 -0
  417. package/dist/entry-locks-BEcX7ET0.mjs.map +1 -0
  418. package/dist/{error-DFrQjppn.mjs → error-BDcFyoRt.mjs} +2 -2
  419. package/dist/{error-DFrQjppn.mjs.map → error-BDcFyoRt.mjs.map} +1 -1
  420. package/dist/{errors-DsVoDUjJ.mjs → errors-DvMdNrgf.mjs} +8 -1
  421. package/dist/errors-DvMdNrgf.mjs.map +1 -0
  422. package/dist/{escape-HmHTC1Is.mjs → escape-B3asJC6W.mjs} +1 -1
  423. package/dist/{escape-HmHTC1Is.mjs.map → escape-B3asJC6W.mjs.map} +1 -1
  424. package/dist/{field-defs-cache-BM4SIRqH.mjs → field-defs-cache-Cf5FHK0M.mjs} +5 -5
  425. package/dist/{field-defs-cache-BM4SIRqH.mjs.map → field-defs-cache-Cf5FHK0M.mjs.map} +1 -1
  426. package/dist/{fts-manager-Do1BlW2r.mjs → fts-manager-iddym8cd.mjs} +4 -4
  427. package/dist/{fts-manager-Do1BlW2r.mjs.map → fts-manager-iddym8cd.mjs.map} +1 -1
  428. package/dist/{hash-3JJPlHF2.mjs → hash-BRweX6jz.mjs} +1 -1
  429. package/dist/{hash-3JJPlHF2.mjs.map → hash-BRweX6jz.mjs.map} +1 -1
  430. package/dist/{hook-result-DCh2WUpe.d.mts → hook-result-BrshYHLx.d.mts} +1 -1
  431. package/dist/{hook-result-DCh2WUpe.d.mts.map → hook-result-BrshYHLx.d.mts.map} +1 -1
  432. package/dist/{hreflang-B6hbAuuO.d.mts → hreflang-CQpu5bMy.d.mts} +2 -2
  433. package/dist/{hreflang-B6hbAuuO.d.mts.map → hreflang-CQpu5bMy.d.mts.map} +1 -1
  434. package/dist/{hreflang-DQbPZliA.mjs → hreflang-DshnweTC.mjs} +9 -8
  435. package/dist/{hreflang-DQbPZliA.mjs.map → hreflang-DshnweTC.mjs.map} +1 -1
  436. package/dist/{identity-DksvEazf.mjs → identity-CjGKDq8J.mjs} +3 -3
  437. package/dist/{identity-DksvEazf.mjs.map → identity-CjGKDq8J.mjs.map} +1 -1
  438. package/dist/{import-CJpaBBBT.mjs → import-D96g2otw.mjs} +5 -5
  439. package/dist/{import-CJpaBBBT.mjs.map → import-D96g2otw.mjs.map} +1 -1
  440. package/dist/{index-Du8K7bWa.d.mts → index-1ECYpfiF.d.mts} +3 -3
  441. package/dist/{index-Du8K7bWa.d.mts.map → index-1ECYpfiF.d.mts.map} +1 -1
  442. package/dist/index.d.mts +22 -22
  443. package/dist/index.mjs +81 -78
  444. package/dist/{init-lock-DJkX6Hto.mjs → init-lock-CFNBe_iH.mjs} +1 -1
  445. package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-CFNBe_iH.mjs.map} +1 -1
  446. package/dist/{load-CawHjTOH.mjs → load-DPtY9cZo.mjs} +2 -2
  447. package/dist/{load-CawHjTOH.mjs.map → load-DPtY9cZo.mjs.map} +1 -1
  448. package/dist/{loader-Z8vl7zTq.mjs → loader-WJi6GFRn.mjs} +46 -8
  449. package/dist/loader-WJi6GFRn.mjs.map +1 -0
  450. package/dist/{manifest-builder-COtzuca2.mjs → manifest-builder-BfNlGQIA.mjs} +2 -2
  451. package/dist/{manifest-builder-COtzuca2.mjs.map → manifest-builder-BfNlGQIA.mjs.map} +1 -1
  452. package/dist/{manifest-schema-BNWwR8Vd.mjs → manifest-schema-CILooI5J.mjs} +1 -1
  453. package/dist/{manifest-schema-BNWwR8Vd.mjs.map → manifest-schema-CILooI5J.mjs.map} +1 -1
  454. package/dist/media/image-endpoint.mjs +1 -1
  455. package/dist/media/index.d.mts +1 -1
  456. package/dist/media/index.mjs +3 -3
  457. package/dist/media/local-runtime.d.mts +12 -12
  458. package/dist/media/local-runtime.mjs +5 -5
  459. package/dist/{media-BHjus86Y.mjs → media-C1EIZKh1.mjs} +1 -1
  460. package/dist/{media-BHjus86Y.mjs.map → media-C1EIZKh1.mjs.map} +1 -1
  461. package/dist/{media-allowlist-CoTBWoDp.mjs → media-allowlist-elXJgb_K.mjs} +2 -2
  462. package/dist/{media-allowlist-CoTBWoDp.mjs.map → media-allowlist-elXJgb_K.mjs.map} +1 -1
  463. package/dist/{media-folders-BGkATs8n.mjs → media-folders-DASfX_DH.mjs} +1 -1
  464. package/dist/{media-folders-BGkATs8n.mjs.map → media-folders-DASfX_DH.mjs.map} +1 -1
  465. package/dist/{media-upload-BCidR-EY.mjs → media-upload-C7_AQJ5v.mjs} +8 -8
  466. package/dist/{media-upload-BCidR-EY.mjs.map → media-upload-C7_AQJ5v.mjs.map} +1 -1
  467. package/dist/{media-url-DHoPr0hq.mjs → media-url-8dVl1loq.mjs} +19 -2
  468. package/dist/media-url-8dVl1loq.mjs.map +1 -0
  469. package/dist/{media-usage-CdY5jhSR.mjs → media-usage-C1EswMTq.mjs} +9 -9
  470. package/dist/{media-usage-CdY5jhSR.mjs.map → media-usage-C1EswMTq.mjs.map} +1 -1
  471. package/dist/{media-usage-activation-BgeMtK5C.mjs → media-usage-activation-CrHNltlL.mjs} +3 -3
  472. package/dist/{media-usage-activation-BgeMtK5C.mjs.map → media-usage-activation-CrHNltlL.mjs.map} +1 -1
  473. package/dist/{media-usage-work-D6D9sMCA.mjs → media-usage-work-C5B1zT1c.mjs} +2 -2
  474. package/dist/{media-usage-work-D6D9sMCA.mjs.map → media-usage-work-C5B1zT1c.mjs.map} +1 -1
  475. package/dist/{media-usage-work-CnGCdHxx.mjs → media-usage-work-IkQx_Yz6.mjs} +4 -4
  476. package/dist/{media-usage-work-CnGCdHxx.mjs.map → media-usage-work-IkQx_Yz6.mjs.map} +1 -1
  477. package/dist/{media-usage-write-fence-hjeD4u7s.mjs → media-usage-write-fence-B9anjOSg.mjs} +3 -3
  478. package/dist/{media-usage-write-fence-hjeD4u7s.mjs.map → media-usage-write-fence-B9anjOSg.mjs.map} +1 -1
  479. package/dist/{menus-6qSwTNxG.mjs → menus-D8mC4eaN.mjs} +115 -136
  480. package/dist/menus-D8mC4eaN.mjs.map +1 -0
  481. package/dist/{menus-uvPLXMZf.mjs → menus-UdwjHZJC.mjs} +11 -3
  482. package/dist/{menus-uvPLXMZf.mjs.map → menus-UdwjHZJC.mjs.map} +1 -1
  483. package/dist/migrations/index.d.mts +1 -1
  484. package/dist/migrations/index.mjs +4 -4
  485. package/dist/{mime-CUIG6x84.mjs → mime-DYpsOAny.mjs} +1 -1
  486. package/dist/{mime-CUIG6x84.mjs.map → mime-DYpsOAny.mjs.map} +1 -1
  487. package/dist/{mode-DN_WneRx.mjs → mode-Dm4BHhRH.mjs} +1 -1
  488. package/dist/{mode-DN_WneRx.mjs.map → mode-Dm4BHhRH.mjs.map} +1 -1
  489. package/dist/{node-sqlite-compat-BuJXIeMz.mjs → node-sqlite-compat-2sezm-Zd.mjs} +1 -1
  490. package/dist/{node-sqlite-compat-BuJXIeMz.mjs.map → node-sqlite-compat-2sezm-Zd.mjs.map} +1 -1
  491. package/dist/{normalize-C2xNjTSG.mjs → normalize-4nkKGsuW.mjs} +1 -1
  492. package/dist/{normalize-C2xNjTSG.mjs.map → normalize-4nkKGsuW.mjs.map} +1 -1
  493. package/dist/{oauth-authorization-Dj6Kwc21.mjs → oauth-authorization-BxE_lURD.mjs} +4 -4
  494. package/dist/{oauth-authorization-Dj6Kwc21.mjs.map → oauth-authorization-BxE_lURD.mjs.map} +1 -1
  495. package/dist/{oauth-clients-FD7I0J8m.mjs → oauth-clients-DJIdOdq0.mjs} +1 -1
  496. package/dist/{oauth-clients-FD7I0J8m.mjs.map → oauth-clients-DJIdOdq0.mjs.map} +1 -1
  497. package/dist/{oauth-state-store-DkmDOmHs.mjs → oauth-state-store-CsdxP57n.mjs} +1 -1
  498. package/dist/{oauth-state-store-DkmDOmHs.mjs.map → oauth-state-store-CsdxP57n.mjs.map} +1 -1
  499. package/dist/{oauth-user-lookup-CvIwGpYd.mjs → oauth-user-lookup-HzzW-dkF.mjs} +1 -1
  500. package/dist/{oauth-user-lookup-CvIwGpYd.mjs.map → oauth-user-lookup-HzzW-dkF.mjs.map} +1 -1
  501. package/dist/object-cache/memory.d.mts +1 -1
  502. package/dist/{options-BHPeIbBd.mjs → options-D1FBiAv1.mjs} +60 -5
  503. package/dist/options-D1FBiAv1.mjs.map +1 -0
  504. package/dist/{options-CYb4y7hM.d.mts → options-D8Y0VHc7.d.mts} +9 -3
  505. package/dist/options-D8Y0VHc7.d.mts.map +1 -0
  506. package/dist/page/index.d.mts +2 -2
  507. package/dist/page/index.d.mts.map +1 -1
  508. package/dist/page/index.mjs +12 -0
  509. package/dist/page/index.mjs.map +1 -1
  510. package/dist/{parse-Ckpg-Qfp.mjs → parse-WRg5C3NX.mjs} +2 -2
  511. package/dist/{parse-Ckpg-Qfp.mjs.map → parse-WRg5C3NX.mjs.map} +1 -1
  512. package/dist/{passkey-config-O_lj3y0k.mjs → passkey-config-qIdO-wF6.mjs} +1 -1
  513. package/dist/{passkey-config-O_lj3y0k.mjs.map → passkey-config-qIdO-wF6.mjs.map} +1 -1
  514. package/dist/{patterns-D9iDO3j8.mjs → patterns-DC8CLptu.mjs} +1 -1
  515. package/dist/{patterns-D9iDO3j8.mjs.map → patterns-DC8CLptu.mjs.map} +1 -1
  516. package/dist/{placeholder-4X9BrRrp.d.mts → placeholder-COrvARyD.d.mts} +1 -1
  517. package/dist/{placeholder-4X9BrRrp.d.mts.map → placeholder-COrvARyD.d.mts.map} +1 -1
  518. package/dist/plugin-types.d.mts +3 -3
  519. package/dist/plugin-types.d.mts.map +1 -1
  520. package/dist/plugin-utils.d.mts +10 -10
  521. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  522. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  523. package/dist/{policy-Dhtwntrt.mjs → policy-XCfb-IE9.mjs} +2 -2
  524. package/dist/{policy-Dhtwntrt.mjs.map → policy-XCfb-IE9.mjs.map} +1 -1
  525. package/dist/{portable-text-U85hOafW.mjs → portable-text-BS3d5n-0.mjs} +1 -1
  526. package/dist/{portable-text-U85hOafW.mjs.map → portable-text-BS3d5n-0.mjs.map} +1 -1
  527. package/dist/{preview-B_vJLvf8.mjs → preview-BxwsGgGp.mjs} +2 -2
  528. package/dist/{preview-B_vJLvf8.mjs.map → preview-BxwsGgGp.mjs.map} +1 -1
  529. package/dist/{protocol-JdD2YhY9.d.mts → protocol-CLn58-nw.d.mts} +2 -2
  530. package/dist/{protocol-JdD2YhY9.d.mts.map → protocol-CLn58-nw.d.mts.map} +1 -1
  531. package/dist/{public-url-CarhZJgf.mjs → public-url-FWWAvnre.mjs} +1 -1
  532. package/dist/{public-url-CarhZJgf.mjs.map → public-url-FWWAvnre.mjs.map} +1 -1
  533. package/dist/{query-BZKZcG5b.mjs → query-DygOte9M.mjs} +25 -16
  534. package/dist/query-DygOte9M.mjs.map +1 -0
  535. package/dist/{query-BndaFxxp.mjs → query-gtXT03Wc.mjs} +4 -4
  536. package/dist/{query-BndaFxxp.mjs.map → query-gtXT03Wc.mjs.map} +1 -1
  537. package/dist/{rate-limit-BZmATC6W.mjs → rate-limit-CQUPm0dh.mjs} +2 -2
  538. package/dist/{rate-limit-BZmATC6W.mjs.map → rate-limit-CQUPm0dh.mjs.map} +1 -1
  539. package/dist/{redirect-CzqnLxK-.mjs → redirect-D1cWafi6.mjs} +1 -1
  540. package/dist/{redirect-CzqnLxK-.mjs.map → redirect-D1cWafi6.mjs.map} +1 -1
  541. package/dist/{redirect-CZkbozu9.mjs → redirect-DId44BS1.mjs} +19 -6
  542. package/dist/redirect-DId44BS1.mjs.map +1 -0
  543. package/dist/{redirects-CqzNM0KM.mjs → redirects-DN-ZE33W.mjs} +5 -5
  544. package/dist/{redirects-CqzNM0KM.mjs.map → redirects-DN-ZE33W.mjs.map} +1 -1
  545. package/dist/{registry-AZAsRsor.mjs → registry-DTqaqxed.mjs} +26 -10
  546. package/dist/registry-DTqaqxed.mjs.map +1 -0
  547. package/dist/{relation-04DfKRTO.mjs → relation-DxgCHOBw.mjs} +2 -2
  548. package/dist/{relation-04DfKRTO.mjs.map → relation-DxgCHOBw.mjs.map} +1 -1
  549. package/dist/{relations-CcFwDJdJ.mjs → relations-KKDSLUwS.mjs} +4 -4
  550. package/dist/{relations-CcFwDJdJ.mjs.map → relations-KKDSLUwS.mjs.map} +1 -1
  551. package/dist/{relations-C4htk5sb.mjs → relations-rOmbndUJ.mjs} +3 -3
  552. package/dist/{relations-C4htk5sb.mjs.map → relations-rOmbndUJ.mjs.map} +1 -1
  553. package/dist/{request-cache-DH9zdCOD.mjs → request-cache-DAZZmesc.mjs} +1 -1
  554. package/dist/{request-cache-DH9zdCOD.mjs.map → request-cache-DAZZmesc.mjs.map} +1 -1
  555. package/dist/request-context.d.mts +1 -1
  556. package/dist/{request-meta-DYxLlnmz.mjs → request-meta-BgjUQLQ-.mjs} +2 -2
  557. package/dist/{request-meta-DYxLlnmz.mjs.map → request-meta-BgjUQLQ-.mjs.map} +1 -1
  558. package/dist/{resolve-prZ3mP7l.mjs → resolve-Cy0aWSRj.mjs} +37 -4
  559. package/dist/resolve-Cy0aWSRj.mjs.map +1 -0
  560. package/dist/{runner-YKfIMnaF.d.mts → runner-CfwysRM0.d.mts} +2 -2
  561. package/dist/{runner-YKfIMnaF.d.mts.map → runner-CfwysRM0.d.mts.map} +1 -1
  562. package/dist/{runner-BLIDKpmA.mjs → runner-nEzvnogG.mjs} +419 -295
  563. package/dist/runner-nEzvnogG.mjs.map +1 -0
  564. package/dist/runtime.d.mts +11 -11
  565. package/dist/runtime.mjs +3 -2
  566. package/dist/runtime.mjs.map +1 -1
  567. package/dist/{schema-CGnBeLiW.mjs → schema-CRu38Pr5.mjs} +3 -3
  568. package/dist/{schema-CGnBeLiW.mjs.map → schema-CRu38Pr5.mjs.map} +1 -1
  569. package/dist/{schema-DYr-Vd-L.mjs → schema-DifxndJx.mjs} +4 -4
  570. package/dist/{schema-DYr-Vd-L.mjs.map → schema-DifxndJx.mjs.map} +1 -1
  571. package/dist/{scopes-BhWvBavj.mjs → scopes-D5A1OZbq.mjs} +3 -3
  572. package/dist/{scopes-BhWvBavj.mjs.map → scopes-D5A1OZbq.mjs.map} +1 -1
  573. package/dist/{search-C-qDk4kx.mjs → search-DEPFSBFq.mjs} +4 -4
  574. package/dist/{search-C-qDk4kx.mjs.map → search-DEPFSBFq.mjs.map} +1 -1
  575. package/dist/{secrets-rEtHt-6z.mjs → secrets-CdfzLdoO.mjs} +3 -3
  576. package/dist/{secrets-rEtHt-6z.mjs.map → secrets-CdfzLdoO.mjs.map} +1 -1
  577. package/dist/{sections-B_nYvlwn.mjs → sections-3X52kmIR.mjs} +2 -2
  578. package/dist/{sections-B_nYvlwn.mjs.map → sections-3X52kmIR.mjs.map} +1 -1
  579. package/dist/seed/index.d.mts +2 -2
  580. package/dist/seed/index.mjs +26 -24
  581. package/dist/seo/index.d.mts +3 -3
  582. package/dist/seo/index.d.mts.map +1 -1
  583. package/dist/seo/index.mjs +18 -19
  584. package/dist/seo/index.mjs.map +1 -1
  585. package/dist/{seo-926NRIgt.mjs → seo-Bw68KxRc.mjs} +2 -2
  586. package/dist/{seo-926NRIgt.mjs.map → seo-Bw68KxRc.mjs.map} +1 -1
  587. package/dist/{seo-CVWkdv6x.mjs → seo-C4AmbsMU.mjs} +3 -2
  588. package/dist/seo-C4AmbsMU.mjs.map +1 -0
  589. package/dist/{service-CJl3ZAYs.mjs → service-J_-Vgo7R.mjs} +2 -2
  590. package/dist/{service-CJl3ZAYs.mjs.map → service-J_-Vgo7R.mjs.map} +1 -1
  591. package/dist/{session-user-BlMgqCHS.mjs → session-user-CbnMMwk6.mjs} +1 -1
  592. package/dist/{session-user-BlMgqCHS.mjs.map → session-user-CbnMMwk6.mjs.map} +1 -1
  593. package/dist/{settings-Cwm6o2jY.mjs → settings-AnEFYICn.mjs} +3 -3
  594. package/dist/{settings-Cwm6o2jY.mjs.map → settings-AnEFYICn.mjs.map} +1 -1
  595. package/dist/{settings--wobrkkC.mjs → settings-DcMjREe5.mjs} +6 -6
  596. package/dist/{settings--wobrkkC.mjs.map → settings-DcMjREe5.mjs.map} +1 -1
  597. package/dist/{setup-complete-DQbClIN2.mjs → setup-complete-BClXXTvr.mjs} +2 -2
  598. package/dist/{setup-complete-DQbClIN2.mjs.map → setup-complete-BClXXTvr.mjs.map} +1 -1
  599. package/dist/{setup-nonce-DZCFS2sn.mjs → setup-nonce-BheRa4RG.mjs} +1 -1
  600. package/dist/{setup-nonce-DZCFS2sn.mjs.map → setup-nonce-BheRa4RG.mjs.map} +1 -1
  601. package/dist/{single-flight-cache-BPuGPdcN.mjs → single-flight-cache-jaswDzmQ.mjs} +2 -2
  602. package/dist/{single-flight-cache-BPuGPdcN.mjs.map → single-flight-cache-jaswDzmQ.mjs.map} +1 -1
  603. package/dist/{site-url-BrxA_E9H.mjs → site-url-Bqf-ea3N.mjs} +3 -3
  604. package/dist/{site-url-BrxA_E9H.mjs.map → site-url-Bqf-ea3N.mjs.map} +1 -1
  605. package/dist/{snapshot--OCDTqdb.mjs → snapshot-C4CtXntb.mjs} +51 -35
  606. package/dist/snapshot-C4CtXntb.mjs.map +1 -0
  607. package/dist/{ssrf-5sIM5jzl.mjs → ssrf-gl4gFNhw.mjs} +148 -91
  608. package/dist/ssrf-gl4gFNhw.mjs.map +1 -0
  609. package/dist/{state-BpFVsJZB.mjs → state-1F6IOhdQ.mjs} +1 -1
  610. package/dist/{state-BpFVsJZB.mjs.map → state-1F6IOhdQ.mjs.map} +1 -1
  611. package/dist/{status-B777-dXz.mjs → status-Cenfk_r5.mjs} +1 -1
  612. package/dist/{status-B777-dXz.mjs.map → status-Cenfk_r5.mjs.map} +1 -1
  613. package/dist/storage/local.d.mts +1 -1
  614. package/dist/storage/local.mjs +1 -1
  615. package/dist/storage/s3.d.mts +1 -1
  616. package/dist/storage/s3.mjs +1 -1
  617. package/dist/{target-BmR0iTwz.mjs → target-CRzeTs8G.mjs} +1 -1
  618. package/dist/{target-BmR0iTwz.mjs.map → target-CRzeTs8G.mjs.map} +1 -1
  619. package/dist/{taxonomies-DkAkMupr.mjs → taxonomies-BOdxuZpV.mjs} +11 -4
  620. package/dist/taxonomies-BOdxuZpV.mjs.map +1 -0
  621. package/dist/{taxonomies-Wfy_Lg12.mjs → taxonomies-NcFDq5Gg.mjs} +23 -14
  622. package/dist/taxonomies-NcFDq5Gg.mjs.map +1 -0
  623. package/dist/{taxonomy-tJepplLL.mjs → taxonomy-DP1vny4K.mjs} +11 -3
  624. package/dist/{taxonomy-tJepplLL.mjs.map → taxonomy-DP1vny4K.mjs.map} +1 -1
  625. package/dist/{tokens-BCO1oruF.mjs → tokens-CDk8ox9p.mjs} +1 -1
  626. package/dist/{tokens-BCO1oruF.mjs.map → tokens-CDk8ox9p.mjs.map} +1 -1
  627. package/dist/{transport-xh6YKW2G.d.mts → transport-BVn4tVb9.d.mts} +1 -1
  628. package/dist/{transport-xh6YKW2G.d.mts.map → transport-BVn4tVb9.d.mts.map} +1 -1
  629. package/dist/{transport-Dr3qtwXC.mjs → transport-DP0JI-8i.mjs} +1 -1
  630. package/dist/{transport-Dr3qtwXC.mjs.map → transport-DP0JI-8i.mjs.map} +1 -1
  631. package/dist/{trusted-proxy-BR5F1Otp.mjs → trusted-proxy-BTM6UxqD.mjs} +1 -1
  632. package/dist/{trusted-proxy-BR5F1Otp.mjs.map → trusted-proxy-BTM6UxqD.mjs.map} +1 -1
  633. package/dist/{types-CXFkwEGC.d.mts → types-2n848aVW.d.mts} +1 -1
  634. package/dist/{types-CXFkwEGC.d.mts.map → types-2n848aVW.d.mts.map} +1 -1
  635. package/dist/{types-75KIqzL9.mjs → types-BMXnRIrX.mjs} +4 -2
  636. package/dist/types-BMXnRIrX.mjs.map +1 -0
  637. package/dist/{types-B6GrPic4.d.mts → types-BouXpOsa.d.mts} +115 -4
  638. package/dist/types-BouXpOsa.d.mts.map +1 -0
  639. package/dist/{types-3qNFPlci.mjs → types-ByG2coLw.mjs} +1 -1
  640. package/dist/{types-3qNFPlci.mjs.map → types-ByG2coLw.mjs.map} +1 -1
  641. package/dist/types-CQPWhPxE.mjs.map +1 -1
  642. package/dist/{types-CDtkNSFQ.d.mts → types-DEfNJ__A.d.mts} +1 -1
  643. package/dist/{types-CDtkNSFQ.d.mts.map → types-DEfNJ__A.d.mts.map} +1 -1
  644. package/dist/{types-xDMtUFnO.d.mts → types-DKcKSbtB.d.mts} +23 -7
  645. package/dist/types-DKcKSbtB.d.mts.map +1 -0
  646. package/dist/{types-C00oyCZp.d.mts → types-DRYs7uTL.d.mts} +1 -1
  647. package/dist/{types-C00oyCZp.d.mts.map → types-DRYs7uTL.d.mts.map} +1 -1
  648. package/dist/{types-DczELMop.d.mts → types-DaEg7KX2.d.mts} +1 -1
  649. package/dist/{types-DczELMop.d.mts.map → types-DaEg7KX2.d.mts.map} +1 -1
  650. package/dist/{types-BuHW4xDE.d.mts → types-LU8utpP_.d.mts} +6 -3
  651. package/dist/types-LU8utpP_.d.mts.map +1 -0
  652. package/dist/{types-CPeXo1wF.d.mts → types-VpYfPUxN.d.mts} +1 -1
  653. package/dist/{types-CPeXo1wF.d.mts.map → types-VpYfPUxN.d.mts.map} +1 -1
  654. package/dist/{types-DM3vioBY.mjs → types-c9GP7Dj5.mjs} +1 -1
  655. package/dist/{types-DM3vioBY.mjs.map → types-c9GP7Dj5.mjs.map} +1 -1
  656. package/dist/{types-FV23hEoW.d.mts → types-tJWDK__M.d.mts} +14 -1
  657. package/dist/types-tJWDK__M.d.mts.map +1 -0
  658. package/dist/{upload-attempts-BsqoQ1fn.mjs → upload-attempts-C6S2y-lp.mjs} +1 -1
  659. package/dist/{upload-attempts-BsqoQ1fn.mjs.map → upload-attempts-C6S2y-lp.mjs.map} +1 -1
  660. package/dist/{url-pattern-D4c2czpJ.mjs → url-pattern-UYtxVTuj.mjs} +1 -1
  661. package/dist/{url-pattern-D4c2czpJ.mjs.map → url-pattern-UYtxVTuj.mjs.map} +1 -1
  662. package/dist/{user-BTZ40aq6.mjs → user-DIsIXogT.mjs} +2 -2
  663. package/dist/{user-BTZ40aq6.mjs.map → user-DIsIXogT.mjs.map} +1 -1
  664. package/dist/{utils-BKvNjjhY.mjs → utils-BicP5Qbg.mjs} +2 -2
  665. package/dist/{utils-BKvNjjhY.mjs.map → utils-BicP5Qbg.mjs.map} +1 -1
  666. package/dist/{validate-DE_LRwo9.mjs → validate-D8VPn4Hv.mjs} +8 -3
  667. package/dist/validate-D8VPn4Hv.mjs.map +1 -0
  668. package/dist/{validate-DUP27OYD.d.mts → validate-Df6Dvwbw.d.mts} +12 -7
  669. package/dist/validate-Df6Dvwbw.d.mts.map +1 -0
  670. package/dist/{validation-BMImFJ11.mjs → validation-CzMJn9Ku.mjs} +13 -11
  671. package/dist/{validation-BMImFJ11.mjs.map → validation-CzMJn9Ku.mjs.map} +1 -1
  672. package/dist/version-CK67_SXX.mjs +7 -0
  673. package/dist/{version-Bii3suaO.mjs.map → version-CK67_SXX.mjs.map} +1 -1
  674. package/dist/{widgets-D3gJ10xU.mjs → widgets-RFVAxQl3.mjs} +5 -5
  675. package/dist/{widgets-D3gJ10xU.mjs.map → widgets-RFVAxQl3.mjs.map} +1 -1
  676. package/dist/{wxr-taxonomies-B2Og_6rU.d.mts → wxr-taxonomies-BX4yQL9s.d.mts} +1 -1
  677. package/dist/{wxr-taxonomies-B2Og_6rU.d.mts.map → wxr-taxonomies-BX4yQL9s.d.mts.map} +1 -1
  678. package/dist/{wxr-taxonomies-Cxngsjwo.mjs → wxr-taxonomies-Csdp7yde.mjs} +4 -4
  679. package/dist/{wxr-taxonomies-Cxngsjwo.mjs.map → wxr-taxonomies-Csdp7yde.mjs.map} +1 -1
  680. package/dist/{zod-generator-BuYSQJB7.mjs → zod-generator-CNRGdnBY.mjs} +3 -3
  681. package/dist/{zod-generator-BuYSQJB7.mjs.map → zod-generator-CNRGdnBY.mjs.map} +1 -1
  682. package/package.json +12 -10
  683. package/src/api/errors.ts +7 -0
  684. package/src/api/handlers/content.ts +66 -79
  685. package/src/api/handlers/entry-lock.ts +206 -0
  686. package/src/api/handlers/manifest.ts +1 -0
  687. package/src/api/handlers/marketplace.ts +28 -20
  688. package/src/api/handlers/menus.ts +9 -0
  689. package/src/api/handlers/registry.ts +13 -8
  690. package/src/api/handlers/revision.ts +2 -1
  691. package/src/api/handlers/seo.ts +10 -1
  692. package/src/api/handlers/snapshot.ts +84 -72
  693. package/src/api/handlers/taxonomies.ts +9 -0
  694. package/src/api/openapi/document.ts +111 -6
  695. package/src/api/schemas/content.ts +8 -0
  696. package/src/api/schemas/entry-lock.ts +48 -0
  697. package/src/api/schemas/index.ts +1 -0
  698. package/src/api/schemas/schema.ts +10 -1
  699. package/src/api/types.ts +2 -0
  700. package/src/astro/integration/index.ts +9 -6
  701. package/src/astro/integration/routes.ts +5 -0
  702. package/src/astro/integration/runtime.ts +13 -5
  703. package/src/astro/integration/vite-config.ts +30 -0
  704. package/src/astro/middleware.ts +16 -0
  705. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +10 -0
  706. package/src/astro/routes/api/content/[collection]/[id]/lock.ts +133 -0
  707. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +11 -1
  708. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +20 -0
  709. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +10 -0
  710. package/src/astro/routes/api/content/[collection]/[id].ts +27 -2
  711. package/src/astro/routes/api/content/[collection]/index.ts +3 -0
  712. package/src/astro/routes/sitemap-[collection].xml.ts +4 -0
  713. package/src/astro/types.ts +13 -3
  714. package/src/cli/commands/content.ts +31 -5
  715. package/src/cli/commands/export-seed.ts +2 -0
  716. package/src/client/index.ts +34 -7
  717. package/src/components/EmDashBodyEnd.astro +4 -1
  718. package/src/components/EmDashBodyStart.astro +4 -1
  719. package/src/components/EmDashHead.astro +35 -16
  720. package/src/components/Gallery.astro +18 -4
  721. package/src/components/InlineEditor.astro +3 -1
  722. package/src/components/InlinePortableTextEditor.tsx +106 -11
  723. package/src/components/PortableText.astro +4 -0
  724. package/src/components/Table.astro +147 -62
  725. package/src/config/errors.ts +13 -0
  726. package/src/content/converters/portable-text-to-prosemirror.ts +26 -2
  727. package/src/content/converters/prosemirror-to-portable-text.ts +35 -6
  728. package/src/content/converters/types.ts +10 -0
  729. package/src/database/dialect-helpers.ts +125 -0
  730. package/src/database/migrations/075_entry_edit_locks.ts +44 -0
  731. package/src/database/migrations/076_collection_nav_group.ts +22 -0
  732. package/src/database/migrations/077_plugin_storage_revisions.ts +89 -0
  733. package/src/database/migrations/runner.ts +6 -0
  734. package/src/database/repositories/content.ts +170 -1
  735. package/src/database/repositories/entry-locks.ts +257 -0
  736. package/src/database/repositories/options.ts +69 -5
  737. package/src/database/repositories/plugin-storage.ts +159 -0
  738. package/src/database/repositories/redirect.ts +17 -6
  739. package/src/database/repositories/taxonomy.ts +8 -0
  740. package/src/database/repositories/types.ts +3 -0
  741. package/src/database/types.ts +15 -1
  742. package/src/emdash-runtime.ts +117 -50
  743. package/src/i18n/resolve.ts +44 -4
  744. package/src/index.ts +14 -0
  745. package/src/loader.ts +35 -4
  746. package/src/mcp/server.ts +23 -5
  747. package/src/media/responsive.ts +23 -0
  748. package/src/media/usage/content-refresh.ts +2 -1
  749. package/src/menus/index.ts +17 -21
  750. package/src/page/seo-contributions.ts +78 -1
  751. package/src/page/seo-panel.ts +47 -0
  752. package/src/plugin-types.ts +9 -0
  753. package/src/plugins/conditional-storage.ts +30 -0
  754. package/src/plugins/context.ts +49 -17
  755. package/src/plugins/hooks.ts +7 -1
  756. package/src/plugins/index.ts +9 -0
  757. package/src/plugins/manager.ts +5 -2
  758. package/src/plugins/sandbox/types.ts +16 -2
  759. package/src/plugins/storage-query.ts +45 -0
  760. package/src/plugins/storage-update.ts +96 -0
  761. package/src/plugins/types.ts +114 -0
  762. package/src/query.ts +29 -3
  763. package/src/registry/config.ts +130 -27
  764. package/src/registry/types.ts +5 -6
  765. package/src/schema/collection-slugs-cache.ts +157 -0
  766. package/src/schema/registry.ts +19 -0
  767. package/src/schema/types.ts +25 -6
  768. package/src/security/ssrf.ts +167 -141
  769. package/src/seed/apply.ts +4 -0
  770. package/src/seed/types.ts +7 -2
  771. package/src/seed/validate.ts +18 -1
  772. package/src/seo/hreflang.ts +1 -0
  773. package/src/seo/index.ts +5 -10
  774. package/src/seo/media-url.ts +26 -0
  775. package/src/taxonomies/term-counts.ts +22 -5
  776. package/dist/api-Dz6rgoa3.mjs.map +0 -1
  777. package/dist/apply-B4SIOxR1.mjs.map +0 -1
  778. package/dist/config-it29yDLA.mjs.map +0 -1
  779. package/dist/content-DjvM0T92.mjs.map +0 -1
  780. package/dist/context-CX6gxOLW.mjs.map +0 -1
  781. package/dist/dialect-helpers-BSbfaO3F.mjs.map +0 -1
  782. package/dist/errors-DsVoDUjJ.mjs.map +0 -1
  783. package/dist/index-BJNMCWmu.d.mts.map +0 -1
  784. package/dist/loader-Z8vl7zTq.mjs.map +0 -1
  785. package/dist/media-url-DHoPr0hq.mjs.map +0 -1
  786. package/dist/menus-6qSwTNxG.mjs.map +0 -1
  787. package/dist/options-BHPeIbBd.mjs.map +0 -1
  788. package/dist/options-CYb4y7hM.d.mts.map +0 -1
  789. package/dist/query-BZKZcG5b.mjs.map +0 -1
  790. package/dist/redirect-CZkbozu9.mjs.map +0 -1
  791. package/dist/redirects-BLNOWQTn.mjs.map +0 -1
  792. package/dist/registry-AZAsRsor.mjs.map +0 -1
  793. package/dist/relations-DnRK4YIT.d.mts.map +0 -1
  794. package/dist/resolve-prZ3mP7l.mjs.map +0 -1
  795. package/dist/runner-BLIDKpmA.mjs.map +0 -1
  796. package/dist/seo-CVWkdv6x.mjs.map +0 -1
  797. package/dist/snapshot--OCDTqdb.mjs.map +0 -1
  798. package/dist/ssrf-5sIM5jzl.mjs.map +0 -1
  799. package/dist/taxonomies-DkAkMupr.mjs.map +0 -1
  800. package/dist/taxonomies-Wfy_Lg12.mjs.map +0 -1
  801. package/dist/types-75KIqzL9.mjs.map +0 -1
  802. package/dist/types-B6GrPic4.d.mts.map +0 -1
  803. package/dist/types-BuHW4xDE.d.mts.map +0 -1
  804. package/dist/types-FV23hEoW.d.mts.map +0 -1
  805. package/dist/types-xDMtUFnO.d.mts.map +0 -1
  806. package/dist/validate-DE_LRwo9.mjs.map +0 -1
  807. package/dist/validate-DUP27OYD.d.mts.map +0 -1
  808. package/dist/version-Bii3suaO.mjs +0 -7
  809. /package/dist/{api-tokens-BfYts-sq.mjs → api-tokens-B_lfpmH3.mjs} +0 -0
  810. /package/dist/{ssrf-Dg3cIT-b.mjs → ssrf-TQhaljuI.mjs} +0 -0
  811. /package/dist/{types-DfuTR6dL.mjs → types-A2cN6a4a.mjs} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"media-BHjus86Y.mjs","names":[],"sources":["../src/api/schemas/common.ts","../src/api/schemas/media-usage.ts","../src/api/schemas/media.ts"],"sourcesContent":["import { z } from \"zod\";\n\nimport { LOCALE_CODE_PATTERN } from \"../../i18n/config.js\";\n\n// ---------------------------------------------------------------------------\n// Role level\n// ---------------------------------------------------------------------------\n\n/** Valid role level values */\nexport const VALID_ROLE_LEVELS = new Set([10, 20, 30, 40, 50]);\n\n/** Role level — coerces string/number to valid RoleLevel (10|20|30|40|50) */\nexport const roleLevel = z.coerce\n\t.number()\n\t.int()\n\t.refine((n): n is 10 | 20 | 30 | 40 | 50 => VALID_ROLE_LEVELS.has(n), {\n\t\tmessage: \"Invalid role level. Must be 10, 20, 30, 40, or 50\",\n\t});\n\n// ---------------------------------------------------------------------------\n// Pagination\n// ---------------------------------------------------------------------------\n\n/** Pagination query params — cursor-based */\nexport const cursorPaginationQuery = z\n\t.object({\n\t\tcursor: z.string().max(2048).optional().meta({ description: \"Opaque cursor for pagination\" }),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50).meta({\n\t\t\tdescription: \"Maximum number of items to return (1-100, default 50)\",\n\t\t}),\n\t})\n\t.meta({ id: \"CursorPaginationQuery\" });\n\n/** Pagination query params — offset-based */\nexport const offsetPaginationQuery = z\n\t.object({\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n\t\toffset: z.coerce.number().int().min(0).optional().default(0),\n\t})\n\t.meta({ id: \"OffsetPaginationQuery\" });\n\n// ---------------------------------------------------------------------------\n// Shared primitives\n// ---------------------------------------------------------------------------\n\n/** Slug pattern: lowercase letters, digits, underscores; starts with letter */\nexport const slugPattern = /^[a-z][a-z0-9_]*$/;\n\n/** Matches http(s) scheme at start of URL */\nconst HTTP_SCHEME_RE = /^https?:\\/\\//i;\n\n/** Validates that a URL string uses http or https scheme. Rejects javascript:/data: URI XSS vectors. */\nexport const httpUrl = z\n\t.url()\n\t.refine((url) => HTTP_SCHEME_RE.test(url), \"URL must use http or https\");\n\n/**\n * BCP 47 locale code — language with optional script/region subtags (e.g. en, en-US, pt-BR, es-419, zh-Hant).\n * Validation is case-insensitive, but the value is preserved verbatim because the site config, stored\n * `locale` columns, and public query path all keep the raw BCP-47 casing.\n */\nexport const localeCode = z.string().regex(LOCALE_CODE_PATTERN, \"Invalid locale code\");\n\n/** Shared `?locale=xx` query shape for endpoints that filter by locale. */\nexport const localeFilterQuery = z\n\t.object({\n\t\tlocale: localeCode.optional(),\n\t})\n\t.meta({ id: \"LocaleFilterQuery\" });\n\n// ---------------------------------------------------------------------------\n// OpenAPI: Shared response schemas\n// ---------------------------------------------------------------------------\n\n/** Standard API error response */\nexport const apiErrorSchema = z\n\t.object({\n\t\tsuccess: z.literal(false).meta({ description: \"Discriminant: always false for errors\" }),\n\t\terror: z.object({\n\t\t\tcode: z\n\t\t\t\t.string()\n\t\t\t\t.meta({ description: \"Machine-readable error code\", examples: [\"NOT_FOUND\"] }),\n\t\t\tmessage: z.string().meta({ description: \"Human-readable error message\" }),\n\t\t}),\n\t})\n\t.meta({ id: \"ApiError\" });\n\n/** Wrap a data schema in the standard success envelope: { success: true, data: T } */\nexport function successEnvelope<T extends z.ZodType>(dataSchema: T) {\n\treturn z.object({\n\t\tsuccess: z.literal(true).meta({ description: \"Discriminant: always true for success\" }),\n\t\tdata: dataSchema,\n\t});\n}\n\n/** Standard delete response */\nexport const deleteResponseSchema = z.object({ deleted: z.literal(true) }).meta({\n\tid: \"DeleteResponse\",\n});\n\n/** Standard count response */\nexport const countResponseSchema = z\n\t.object({ count: z.number().int().min(0) })\n\t.meta({ id: \"CountResponse\" });\n","import { z } from \"zod\";\n\nimport { slugPattern } from \"./common.js\";\n\nexport const mediaUsageCoverageStatusSchema = z\n\t.enum([\"complete\", \"never\", \"running\", \"partial\", \"failed\", \"stale\", \"unknown\"])\n\t.meta({ id: \"MediaUsageCoverageStatus\" });\n\nexport const mediaUsageCoverageSchema = z\n\t.object({\n\t\tscope: z.literal(\"all_content_collections\"),\n\t\tstatus: mediaUsageCoverageStatusSchema,\n\t})\n\t.meta({ id: \"MediaUsageCoverage\" });\n\nexport const mediaUsageProgressSchema = z\n\t.object({\n\t\tstatus: z.enum([\"indexing\", \"ready\", \"needs_attention\"]),\n\t\treadyCollections: z.number().int().min(0),\n\t\ttotalCollections: z.number().int().min(0),\n\t})\n\t.meta({ id: \"MediaUsageProgress\" });\n\nexport const mediaUsageSummarySchema = z\n\t.object({\n\t\tcount: z.number().int().min(0).nullable(),\n\t\tcoverage: mediaUsageCoverageSchema,\n\t})\n\t.meta({ id: \"MediaUsageSummary\" });\n\nexport const mediaUsageDetailsQuery = z.object({\n\tcursor: z.string().min(1).max(2048).optional().meta({\n\t\tdescription: \"Opaque content-entry-group cursor\",\n\t}),\n\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50).meta({\n\t\tdescription: \"Maximum number of content entry groups to return (1-100, default 50)\",\n\t}),\n});\n\nexport const mediaUsageOccurrenceDetailSchema = z\n\t.object({\n\t\tfieldSlug: z.string(),\n\t\tfieldPath: z.string(),\n\t\toccurrenceIndex: z.number().int().min(0),\n\t\treferenceType: z.enum([\"image_field\", \"file_field\", \"portable_text_image\", \"unknown\"]),\n\t})\n\t.meta({ id: \"MediaUsageOccurrenceDetail\" });\n\nexport const mediaUsageSourceDetailSchema = z\n\t.object({\n\t\tvariant: z.enum([\"columns\", \"draft_overlay\"]),\n\t\toccurrences: z.array(mediaUsageOccurrenceDetailSchema),\n\t})\n\t.meta({ id: \"MediaUsageSourceDetail\" });\n\nexport const mediaUsageEntryDetailSchema = z\n\t.object({\n\t\tcollection: z.string(),\n\t\tcontentId: z.string(),\n\t\ttitle: z.string().nullable(),\n\t\tslug: z.string().nullable(),\n\t\tlocale: z.string().nullable(),\n\t\tstatus: z.string().nullable(),\n\t\tscheduledAt: z.string().nullable(),\n\t\tdeletedAt: z.string().nullable(),\n\t\tsources: z.array(mediaUsageSourceDetailSchema),\n\t})\n\t.meta({ id: \"MediaUsageEntryDetail\" });\n\nexport const mediaUsageDetailsResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaUsageEntryDetailSchema),\n\t\tnextCursor: z.string().optional(),\n\t\tcoverage: mediaUsageCoverageSchema,\n\t})\n\t.meta({ id: \"MediaUsageDetailsResponse\" });\n\nexport const mediaUsageRepairStatusSchema = z\n\t.enum([\"complete\", \"partial\", \"failed\", \"stale\"])\n\t.meta({ id: \"MediaUsageRepairStatus\" });\n\nconst mediaUsageRepairCollectionBody = z\n\t.object({\n\t\tscope: z.literal(\"collection\"),\n\t\tcollection: z.string().min(1).max(63).regex(slugPattern, \"Invalid collection slug\"),\n\t})\n\t.strict();\n\nconst mediaUsageRepairAllBody = z.object({ scope: z.literal(\"all\") }).strict();\n\nexport const mediaUsageRepairBody = z\n\t.discriminatedUnion(\"scope\", [mediaUsageRepairCollectionBody, mediaUsageRepairAllBody])\n\t.meta({ id: \"MediaUsageRepairBody\" });\n\nexport const mediaUsageRepairCollectionSummarySchema = z\n\t.object({\n\t\tcollection: z.string(),\n\t\tstatus: mediaUsageRepairStatusSchema,\n\t\tindexedSourceCount: z.number().int().min(0),\n\t\tfailedSourceCount: z.number().int().min(0),\n\t\tskippedSourceCount: z.number().int().min(0),\n\t\tdeletedSourceCount: z.number().int().min(0),\n\t\tlastErrorCode: z.string().nullable(),\n\t\tstartedAt: z.string(),\n\t\tcompletedAt: z.string().nullable(),\n\t})\n\t.meta({ id: \"MediaUsageRepairCollectionSummary\" });\n\nexport const mediaUsageRepairResponseSchema = z\n\t.object({\n\t\tstatus: mediaUsageRepairStatusSchema,\n\t\tindexedSourceCount: z.number().int().min(0),\n\t\tfailedSourceCount: z.number().int().min(0),\n\t\tskippedSourceCount: z.number().int().min(0),\n\t\tdeletedSourceCount: z.number().int().min(0),\n\t\tcollections: z.array(mediaUsageRepairCollectionSummarySchema),\n\t})\n\t.meta({ id: \"MediaUsageRepairResponse\" });\n\nexport const mediaUsageWorkStateSchema = z\n\t.enum([\"pending\", \"retry\", \"leased\", \"failed\"])\n\t.meta({ id: \"MediaUsageWorkState\" });\n\nexport const mediaUsageWorkListQuery = z.object({\n\tcollection: z.string().min(1).max(63).regex(slugPattern, \"Invalid collection slug\"),\n\tstate: mediaUsageWorkStateSchema.optional(),\n\tcursor: z.string().min(1).max(2048).optional().meta({\n\t\tdescription: \"Opaque work-page cursor\",\n\t}),\n\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50).meta({\n\t\tdescription: \"Maximum number of work items to return (1-100, default 50)\",\n\t}),\n});\n\nexport const mediaUsageWorkItemSchema = z\n\t.object({\n\t\tcollectionId: z.string(),\n\t\tcollectionSlug: z.string(),\n\t\tcontentId: z.string(),\n\t\tstate: mediaUsageWorkStateSchema,\n\t\tattemptCount: z.number().int().min(0),\n\t\tnextAttemptAt: z.string(),\n\t\tleaseExpiresAt: z.string().nullable(),\n\t\tlastAttemptedAt: z.string().nullable(),\n\t\tlastErrorCode: z.string().nullable(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUsageWorkItem\" });\n\nexport const mediaUsageWorkListResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaUsageWorkItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"MediaUsageWorkListResponse\" });\n\nconst boundedOpaqueMediaUsageId = z.string().min(1).max(2048);\n\nexport const mediaUsageWorkRetryBody = z\n\t.object({\n\t\tcollectionId: boundedOpaqueMediaUsageId.meta({\n\t\t\tdescription: \"Current immutable collection identity\",\n\t\t}),\n\t\tcontentId: boundedOpaqueMediaUsageId.meta({\n\t\t\tdescription: \"Content entry identity, including a deleted entry\",\n\t\t}),\n\t})\n\t.strict()\n\t.meta({ id: \"MediaUsageWorkRetryBody\" });\n\nexport const mediaUsageWorkRetryResponseSchema = z\n\t.object({\n\t\tchanged: z.boolean(),\n\t\titem: mediaUsageWorkItemSchema,\n\t})\n\t.meta({ id: \"MediaUsageWorkRetryResponse\" });\n\nexport const mediaUsageWorkRetryConflictSchema = z.object({\n\tsuccess: z.literal(false),\n\terror: z.discriminatedUnion(\"code\", [\n\t\tz.object({\n\t\t\tcode: z.literal(\"WORK_LEASE_ACTIVE\"),\n\t\t\tmessage: z.string(),\n\t\t\tdetails: z.object({ leaseExpiresAt: z.string() }),\n\t\t}),\n\t\tz.object({\n\t\t\tcode: z.literal(\"WORK_CHANGED\"),\n\t\t\tmessage: z.string(),\n\t\t}),\n\t]),\n});\n\nexport const mediaUsageActivationStateSchema = z\n\t.enum([\"expanded\", \"activating\", \"active\"])\n\t.meta({ id: \"MediaUsageActivationState\" });\n\nexport const mediaUsageActivationStatusSchema = z\n\t.object({\n\t\tstate: mediaUsageActivationStateSchema,\n\t\tcollectionCursor: z.string().nullable(),\n\t\tattemptCount: z.number().int().min(0),\n\t\tdrainConfirmedAt: z.string().nullable(),\n\t\tlastAttemptedAt: z.string().nullable(),\n\t\tlastErrorCode: z.literal(\"MEDIA_USAGE_ACTIVATION_FAILED\").nullable(),\n\t\tleaseExpiresAt: z.string().nullable(),\n\t\tactivatedAt: z.string().nullable(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUsageActivationStatus\" });\n\nexport const mediaUsageActivationAdvanceBody = z\n\t.object({\n\t\twritersDrained: z.literal(true),\n\t})\n\t.strict()\n\t.meta({ id: \"MediaUsageActivationAdvanceBody\" });\n\nexport const mediaUsageActivationAdvanceResponseSchema = z\n\t.object({\n\t\toutcome: z.enum([\"activating\", \"active\"]),\n\t\tprocessedCollections: z.number().int().min(0).max(1),\n\t\tactivation: mediaUsageActivationStatusSchema,\n\t})\n\t.meta({ id: \"MediaUsageActivationAdvanceResponse\" });\n\nexport const mediaUsageProgressAdvanceResponseSchema = z\n\t.object({\n\t\tactivation: mediaUsageActivationStatusSchema,\n\t\tprogress: mediaUsageProgressSchema.nullable(),\n\t\tnextRequestInMs: z.union([z.literal(0), z.literal(30_000), z.null()]),\n\t})\n\t.meta({ id: \"MediaUsageProgressAdvanceResponse\" });\n\nexport const mediaUsageActivationConflictSchema = z.object({\n\tsuccess: z.literal(false),\n\terror: z.discriminatedUnion(\"code\", [\n\t\tz.object({\n\t\t\tcode: z.literal(\"MEDIA_USAGE_ACTIVATION_BUSY\"),\n\t\t\tmessage: z.string(),\n\t\t\tdetails: z.object({ leaseExpiresAt: z.string() }),\n\t\t}),\n\t\tz.object({\n\t\t\tcode: z.literal(\"MEDIA_USAGE_ACTIVATION_CONFLICT\"),\n\t\t\tmessage: z.string(),\n\t\t}),\n\t\tz.object({\n\t\t\tcode: z.literal(\"MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH\"),\n\t\t\tmessage: z.string(),\n\t\t}),\n\t]),\n});\n\nexport const mediaUsageCollectionDeletionStateSchema = z\n\t.enum([\"pending\", \"retry\", \"leased\", \"failed\"])\n\t.meta({ id: \"MediaUsageCollectionDeletionState\" });\nexport const mediaUsageCollectionDeletionPhaseSchema = z\n\t.enum([\"fence\", \"registry\", \"table\", \"work\", \"sources\", \"status\", \"finalize\"])\n\t.meta({ id: \"MediaUsageCollectionDeletionPhase\" });\nexport const mediaUsageCollectionDeletionListQuery = z\n\t.object({\n\t\tstate: mediaUsageCollectionDeletionStateSchema.optional().default(\"failed\"),\n\t\tcursor: z.string().min(1).max(2048).optional(),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionListQuery\" });\nexport const mediaUsageCollectionDeletionItemSchema = z\n\t.object({\n\t\tcollectionId: z.string(),\n\t\tcollectionSlug: z.string(),\n\t\tstate: mediaUsageCollectionDeletionStateSchema,\n\t\tphase: mediaUsageCollectionDeletionPhaseSchema,\n\t\tattemptCount: z.number().int().min(0),\n\t\tnextAttemptAt: z.string(),\n\t\tleaseExpiresAt: z.string().nullable(),\n\t\tlastErrorCode: z.string().nullable(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionItem\" });\nexport const mediaUsageCollectionDeletionListResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaUsageCollectionDeletionItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionListResponse\" });\nexport const mediaUsageCollectionDeletionRetryBody = z\n\t.object({ collectionId: boundedOpaqueMediaUsageId })\n\t.strict()\n\t.meta({ id: \"MediaUsageCollectionDeletionRetryBody\" });\nexport const mediaUsageCollectionDeletionRetryResponseSchema = z\n\t.object({\n\t\tchanged: z.boolean(),\n\t\titem: mediaUsageCollectionDeletionItemSchema,\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionRetryResponse\" });\n\nexport type MediaUsageRepairRequest = z.infer<typeof mediaUsageRepairBody>;\nexport type MediaUsageRepairResponse = z.infer<typeof mediaUsageRepairResponseSchema>;\nexport type MediaUsageProgress = z.infer<typeof mediaUsageProgressSchema>;\nexport type MediaUsageProgressAdvanceResponse = z.infer<\n\ttypeof mediaUsageProgressAdvanceResponseSchema\n>;\nexport type MediaUsageWorkListQuery = z.infer<typeof mediaUsageWorkListQuery>;\nexport type MediaUsageWorkItem = z.infer<typeof mediaUsageWorkItemSchema>;\nexport type MediaUsageWorkListResponse = z.infer<typeof mediaUsageWorkListResponseSchema>;\nexport type MediaUsageWorkRetryRequest = z.infer<typeof mediaUsageWorkRetryBody>;\nexport type MediaUsageWorkRetryResponse = z.infer<typeof mediaUsageWorkRetryResponseSchema>;\nexport type MediaUsageActivationStatus = z.infer<typeof mediaUsageActivationStatusSchema>;\nexport type MediaUsageActivationAdvanceRequest = z.infer<typeof mediaUsageActivationAdvanceBody>;\nexport type MediaUsageActivationAdvanceResponse = z.infer<\n\ttypeof mediaUsageActivationAdvanceResponseSchema\n>;\nexport type MediaUsageCollectionDeletionListQuery = z.infer<\n\ttypeof mediaUsageCollectionDeletionListQuery\n>;\nexport type MediaUsageCollectionDeletionListResponse = z.infer<\n\ttypeof mediaUsageCollectionDeletionListResponseSchema\n>;\nexport type MediaUsageCollectionDeletionRetryRequest = z.infer<\n\ttypeof mediaUsageCollectionDeletionRetryBody\n>;\nexport type MediaUsageCollectionDeletionRetryResponse = z.infer<\n\ttypeof mediaUsageCollectionDeletionRetryResponseSchema\n>;\nexport type MediaUsageCoverageStatus = z.infer<typeof mediaUsageCoverageStatusSchema>;\nexport type MediaUsageCoverage = z.infer<typeof mediaUsageCoverageSchema>;\nexport type MediaUsageSummary = z.infer<typeof mediaUsageSummarySchema>;\nexport type MediaUsageOccurrenceDetail = z.infer<typeof mediaUsageOccurrenceDetailSchema>;\nexport type MediaUsageSourceDetail = z.infer<typeof mediaUsageSourceDetailSchema>;\nexport type MediaUsageEntryDetail = z.infer<typeof mediaUsageEntryDetailSchema>;\nexport type MediaUsageDetailsResponse = z.infer<typeof mediaUsageDetailsResponseSchema>;\n","import { z } from \"zod\";\n\nimport { isValidFocalPointUpdate } from \"#media/focal-point.js\";\n\nimport { cursorPaginationQuery } from \"./common.js\";\nimport { mediaUsageSummarySchema } from \"./media-usage.js\";\n\n// ---------------------------------------------------------------------------\n// Media: Input schemas\n// ---------------------------------------------------------------------------\n\n/**\n * Accepts a comma-separated string (from URL query params) or an array of\n * strings (from JSON body or programmatic use) and normalises to string[].\n */\nconst mimeTypeFilter = z\n\t.union([z.string(), z.array(z.string())])\n\t.transform((v) => {\n\t\tconst arr = Array.isArray(v) ? v : v.split(\",\");\n\t\treturn arr.map((s) => s.trim()).filter((s) => s.length > 0);\n\t})\n\t.optional();\n\nexport const mediaListQuery = cursorPaginationQuery\n\t.extend({\n\t\tpage: z.coerce.number().int().min(1).max(Number.MAX_SAFE_INTEGER).optional(),\n\t\tmimeType: mimeTypeFilter,\n\t\tfolderId: z\n\t\t\t.union([z.literal(\"unfiled\"), z.string().min(1).max(64)])\n\t\t\t.optional()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Filter by a media folder ID. Use `unfiled` for the Main library; omit for all media.\",\n\t\t\t}),\n\t\t/** Case-insensitive filename substring search (also matches extensions). */\n\t\tq: z.string().trim().min(1).max(200).optional(),\n\t\tincludeUsage: z.literal(\"1\").optional().meta({\n\t\t\tdescription: \"Include a coverage-aware usage summary on each media item\",\n\t\t}),\n\t})\n\t.refine(({ cursor, page }) => cursor === undefined || page === undefined, {\n\t\tmessage: \"cursor and page cannot be used together\",\n\t\tpath: [\"page\"],\n\t})\n\t.meta({ id: \"MediaListQuery\" });\n\nexport const mediaGetQuery = z\n\t.object({\n\t\tincludeUsage: z.literal(\"1\").optional().meta({\n\t\t\tdescription: \"Include a coverage-aware usage summary on the media item\",\n\t\t}),\n\t})\n\t.meta({ id: \"MediaGetQuery\" });\n\nexport const mediaUpdateBody = z\n\t.object({\n\t\talt: z.string().optional(),\n\t\tcaption: z.string().optional(),\n\t\twidth: z.number().int().positive().optional(),\n\t\theight: z.number().int().positive().optional(),\n\t\tfolderId: z\n\t\t\t.union([z.literal(\"unfiled\"), z.string().min(1).max(64)])\n\t\t\t.nullable()\n\t\t\t.optional()\n\t\t\t.transform((value) => (value === \"unfiled\" ? null : value))\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Assign a media folder ID, or use null or `unfiled` to return the item to the Main library.\",\n\t\t\t}),\n\t\tfocalX: z.number().min(0).max(1).nullable().optional(),\n\t\tfocalY: z.number().min(0).max(1).nullable().optional(),\n\t})\n\t.superRefine((value, context) => {\n\t\tif (!isValidFocalPointUpdate(value)) {\n\t\t\tcontext.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: \"focalX and focalY must both be numbers or both be null\",\n\t\t\t\tpath: [\"focalX\"],\n\t\t\t});\n\t\t}\n\t})\n\t.meta({ id: \"MediaUpdateBody\" });\n\nexport const mediaFolderIdSchema = z.string().min(1).max(64);\n\nexport const mediaFolderListQuery = cursorPaginationQuery\n\t.extend({ q: z.string().trim().min(1).max(200).optional() })\n\t.meta({ id: \"MediaFolderListQuery\" });\n\nconst mediaFolderNameSchema = z.string().refine(\n\t(value) => {\n\t\tconst length = value.trim().length;\n\t\treturn length >= 1 && length <= 200;\n\t},\n\t{ message: \"Folder name must be between 1 and 200 characters\" },\n);\n\nexport const mediaFolderBody = z\n\t.object({ name: mediaFolderNameSchema })\n\t.meta({ id: \"MediaFolderBody\" });\n\n/** Default maximum allowed file upload size (50 MB). */\nexport const DEFAULT_MAX_UPLOAD_SIZE = 50 * 1024 * 1024;\n\nexport function formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes}B`;\n\tif (bytes < 1024 * 1024) return `${Math.floor(bytes / 1024)}KB`;\n\treturn `${Math.floor(bytes / 1024 / 1024)}MB`;\n}\n\n// Matches a full MIME type (type/subtype) with an optional semicolon-delimited\n// parameter section. Forbids CR/LF to prevent header injection.\nexport const CONTENT_TYPE_RE = /^[a-z0-9][a-z0-9!#$&^_+\\-.]*\\/[a-z0-9!#$&^_+\\-.]+(\\s*;[^\\r\\n]*)?$/i;\n\nexport function mediaUploadUrlBody(maxSize: number) {\n\tif (!Number.isFinite(maxSize) || maxSize <= 0) {\n\t\tthrow new Error(`EmDash: maxUploadSize must be a positive finite number, got ${maxSize}`);\n\t}\n\treturn z\n\t\t.object({\n\t\t\tfilename: z.string().min(1, \"filename is required\"),\n\t\t\tcontentType: z\n\t\t\t\t.string()\n\t\t\t\t.min(1, \"contentType is required\")\n\t\t\t\t.regex(CONTENT_TYPE_RE, \"Invalid content type\"),\n\t\t\tsize: z\n\t\t\t\t.number()\n\t\t\t\t.int()\n\t\t\t\t.nonnegative()\n\t\t\t\t.max(maxSize, `File size must not exceed ${formatFileSize(maxSize)}`),\n\t\t\tcontentHash: z.string().optional(),\n\t\t\tfieldId: z.string().optional(),\n\t\t\tdeduplicate: z.boolean().optional(),\n\t\t\tensureUniqueFilename: z.boolean().optional(),\n\t\t\tfolderId: mediaFolderIdSchema.nullable().optional(),\n\t\t})\n\t\t.meta({ id: \"MediaUploadUrlBody\" });\n}\n\nexport const mediaUploadDeduplicateForm = z\n\t.enum([\"true\", \"false\"])\n\t.default(\"true\")\n\t.transform((value) => value === \"true\");\n\nexport const mediaUploadEnsureUniqueFilenameForm = z\n\t.enum([\"true\", \"false\"])\n\t.default(\"false\")\n\t.transform((value) => value === \"true\");\n\nexport const mediaReplaceMetadataForm = z.object({\n\twidth: z.coerce.number().int().positive().max(Number.MAX_SAFE_INTEGER),\n\theight: z.coerce.number().int().positive().max(Number.MAX_SAFE_INTEGER),\n});\n\nconst binaryFileSchema = z.string().meta({ format: \"binary\" });\n\nexport const mediaDirectUploadBody = z\n\t.object({\n\t\tfile: binaryFileSchema,\n\t\twidth: z.string().optional(),\n\t\theight: z.string().optional(),\n\t\tthumbnail: binaryFileSchema.optional(),\n\t\tfieldId: z.string().optional(),\n\t\tdeduplicate: z.enum([\"true\", \"false\"]).optional(),\n\t\tensureUniqueFilename: z.enum([\"true\", \"false\"]).optional(),\n\t\tfolderId: z.union([mediaFolderIdSchema, z.literal(\"unfiled\")]).optional(),\n\t})\n\t.meta({ id: \"MediaDirectUploadBody\" });\n\nexport const mediaReplaceBody = z\n\t.object({\n\t\tfile: binaryFileSchema,\n\t\twidth: z.number().int().positive(),\n\t\theight: z.number().int().positive(),\n\t})\n\t.meta({ id: \"MediaReplaceBody\" });\n\nexport const mediaConfirmBody = z\n\t.object({\n\t\tsize: z.number().int().nonnegative().optional(),\n\t\twidth: z.number().int().positive().optional(),\n\t\theight: z.number().int().positive().optional(),\n\t})\n\t.meta({ id: \"MediaConfirmBody\" });\n\nexport const mediaProviderListQuery = cursorPaginationQuery\n\t.extend({\n\t\tquery: z.string().optional(),\n\t\tmimeType: mimeTypeFilter,\n\t})\n\t.meta({ id: \"MediaProviderListQuery\" });\n\n// ---------------------------------------------------------------------------\n// Media: Response schemas\n// ---------------------------------------------------------------------------\n\nconst mediaStatusSchema = z.enum([\"pending\", \"ready\", \"failed\"]);\n\nexport const mediaItemSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tfilename: z.string(),\n\t\tmimeType: z.string(),\n\t\tsize: z.number().nullable(),\n\t\twidth: z.number().nullable(),\n\t\theight: z.number().nullable(),\n\t\tfocalX: z.number().nullable(),\n\t\tfocalY: z.number().nullable(),\n\t\talt: z.string().nullable(),\n\t\tcaption: z.string().nullable(),\n\t\tstorageKey: z.string(),\n\t\tstatus: mediaStatusSchema,\n\t\tcontentHash: z.string().nullable(),\n\t\tblurhash: z.string().nullable(),\n\t\tdominantColor: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t\tauthorId: z.string().nullable(),\n\t\tfolderId: z.string().nullable(),\n\t})\n\t.meta({ id: \"MediaItem\" });\n\nexport const mediaFolderSchema = z\n\t.object({ id: z.string(), name: z.string() })\n\t.meta({ id: \"MediaFolder\" });\n\nexport const mediaFolderResponseSchema = z\n\t.object({ item: mediaFolderSchema })\n\t.meta({ id: \"MediaFolderResponse\" });\n\nexport const mediaFolderListResponseSchema = z\n\t.object({ items: z.array(mediaFolderSchema), nextCursor: z.string().optional() })\n\t.meta({ id: \"MediaFolderListResponse\" });\n\nexport const mediaResponseSchema = z\n\t.object({ item: mediaItemSchema })\n\t.meta({ id: \"MediaResponse\" });\n\nexport const mediaReadItemSchema = mediaItemSchema\n\t.extend({ usage: mediaUsageSummarySchema.optional() })\n\t.meta({ id: \"MediaReadItem\" });\n\nexport const mediaReadResponseSchema = z\n\t.object({ item: mediaReadItemSchema })\n\t.meta({ id: \"MediaReadResponse\" });\n\nexport const mediaListReadItemSchema = mediaReadItemSchema\n\t.extend({ url: z.string() })\n\t.meta({ id: \"MediaListReadItem\" });\n\nexport const mediaListReadResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaListReadItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t\ttotalCount: z.number().int().nonnegative().optional(),\n\t})\n\t.meta({ id: \"MediaListReadResponse\" });\n\nexport const mediaListResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t\ttotalCount: z.number().int().nonnegative().optional(),\n\t})\n\t.meta({ id: \"MediaListResponse\" });\n\nexport const mediaUploadUrlResponseSchema = z\n\t.object({\n\t\tuploadUrl: z.string(),\n\t\tmethod: z.literal(\"PUT\"),\n\t\theaders: z.record(z.string(), z.string()),\n\t\tmediaId: z.string(),\n\t\tstorageKey: z.string(),\n\t\texpiresAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUploadUrlResponse\" });\n\nexport const mediaExistingResponseSchema = z\n\t.object({\n\t\texisting: z.literal(true),\n\t\tmediaId: z.string(),\n\t\tstorageKey: z.string(),\n\t\turl: z.string(),\n\t})\n\t.meta({ id: \"MediaExistingResponse\" });\n\nexport const mediaConfirmResponseSchema = z\n\t.object({\n\t\titem: mediaItemSchema.extend({ url: z.string() }),\n\t})\n\t.meta({ id: \"MediaConfirmResponse\" });\n\nexport const mediaUploadResponseSchema = z\n\t.object({\n\t\titem: mediaItemSchema.extend({ url: z.string() }),\n\t\tdeduplicated: z.literal(true).optional(),\n\t})\n\t.meta({ id: \"MediaUploadResponse\" });\n\nexport const mediaReplaceResponseSchema = z\n\t.object({ item: mediaItemSchema.extend({ url: z.string() }) })\n\t.meta({ id: \"MediaReplaceResponse\" });\n\nexport const mediaStreamUploadResponseSchema = z\n\t.object({\n\t\tuploaded: z.literal(true),\n\t\tsize: z.number().int().nonnegative(),\n\t})\n\t.meta({ id: \"MediaStreamUploadResponse\" });\n"],"mappings":"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"}
1
+ {"version":3,"file":"media-C1EIZKh1.mjs","names":[],"sources":["../src/api/schemas/common.ts","../src/api/schemas/media-usage.ts","../src/api/schemas/media.ts"],"sourcesContent":["import { z } from \"zod\";\n\nimport { LOCALE_CODE_PATTERN } from \"../../i18n/config.js\";\n\n// ---------------------------------------------------------------------------\n// Role level\n// ---------------------------------------------------------------------------\n\n/** Valid role level values */\nexport const VALID_ROLE_LEVELS = new Set([10, 20, 30, 40, 50]);\n\n/** Role level — coerces string/number to valid RoleLevel (10|20|30|40|50) */\nexport const roleLevel = z.coerce\n\t.number()\n\t.int()\n\t.refine((n): n is 10 | 20 | 30 | 40 | 50 => VALID_ROLE_LEVELS.has(n), {\n\t\tmessage: \"Invalid role level. Must be 10, 20, 30, 40, or 50\",\n\t});\n\n// ---------------------------------------------------------------------------\n// Pagination\n// ---------------------------------------------------------------------------\n\n/** Pagination query params — cursor-based */\nexport const cursorPaginationQuery = z\n\t.object({\n\t\tcursor: z.string().max(2048).optional().meta({ description: \"Opaque cursor for pagination\" }),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50).meta({\n\t\t\tdescription: \"Maximum number of items to return (1-100, default 50)\",\n\t\t}),\n\t})\n\t.meta({ id: \"CursorPaginationQuery\" });\n\n/** Pagination query params — offset-based */\nexport const offsetPaginationQuery = z\n\t.object({\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n\t\toffset: z.coerce.number().int().min(0).optional().default(0),\n\t})\n\t.meta({ id: \"OffsetPaginationQuery\" });\n\n// ---------------------------------------------------------------------------\n// Shared primitives\n// ---------------------------------------------------------------------------\n\n/** Slug pattern: lowercase letters, digits, underscores; starts with letter */\nexport const slugPattern = /^[a-z][a-z0-9_]*$/;\n\n/** Matches http(s) scheme at start of URL */\nconst HTTP_SCHEME_RE = /^https?:\\/\\//i;\n\n/** Validates that a URL string uses http or https scheme. Rejects javascript:/data: URI XSS vectors. */\nexport const httpUrl = z\n\t.url()\n\t.refine((url) => HTTP_SCHEME_RE.test(url), \"URL must use http or https\");\n\n/**\n * BCP 47 locale code — language with optional script/region subtags (e.g. en, en-US, pt-BR, es-419, zh-Hant).\n * Validation is case-insensitive, but the value is preserved verbatim because the site config, stored\n * `locale` columns, and public query path all keep the raw BCP-47 casing.\n */\nexport const localeCode = z.string().regex(LOCALE_CODE_PATTERN, \"Invalid locale code\");\n\n/** Shared `?locale=xx` query shape for endpoints that filter by locale. */\nexport const localeFilterQuery = z\n\t.object({\n\t\tlocale: localeCode.optional(),\n\t})\n\t.meta({ id: \"LocaleFilterQuery\" });\n\n// ---------------------------------------------------------------------------\n// OpenAPI: Shared response schemas\n// ---------------------------------------------------------------------------\n\n/** Standard API error response */\nexport const apiErrorSchema = z\n\t.object({\n\t\tsuccess: z.literal(false).meta({ description: \"Discriminant: always false for errors\" }),\n\t\terror: z.object({\n\t\t\tcode: z\n\t\t\t\t.string()\n\t\t\t\t.meta({ description: \"Machine-readable error code\", examples: [\"NOT_FOUND\"] }),\n\t\t\tmessage: z.string().meta({ description: \"Human-readable error message\" }),\n\t\t}),\n\t})\n\t.meta({ id: \"ApiError\" });\n\n/** Wrap a data schema in the standard success envelope: { success: true, data: T } */\nexport function successEnvelope<T extends z.ZodType>(dataSchema: T) {\n\treturn z.object({\n\t\tsuccess: z.literal(true).meta({ description: \"Discriminant: always true for success\" }),\n\t\tdata: dataSchema,\n\t});\n}\n\n/** Standard delete response */\nexport const deleteResponseSchema = z.object({ deleted: z.literal(true) }).meta({\n\tid: \"DeleteResponse\",\n});\n\n/** Standard count response */\nexport const countResponseSchema = z\n\t.object({ count: z.number().int().min(0) })\n\t.meta({ id: \"CountResponse\" });\n","import { z } from \"zod\";\n\nimport { slugPattern } from \"./common.js\";\n\nexport const mediaUsageCoverageStatusSchema = z\n\t.enum([\"complete\", \"never\", \"running\", \"partial\", \"failed\", \"stale\", \"unknown\"])\n\t.meta({ id: \"MediaUsageCoverageStatus\" });\n\nexport const mediaUsageCoverageSchema = z\n\t.object({\n\t\tscope: z.literal(\"all_content_collections\"),\n\t\tstatus: mediaUsageCoverageStatusSchema,\n\t})\n\t.meta({ id: \"MediaUsageCoverage\" });\n\nexport const mediaUsageProgressSchema = z\n\t.object({\n\t\tstatus: z.enum([\"indexing\", \"ready\", \"needs_attention\"]),\n\t\treadyCollections: z.number().int().min(0),\n\t\ttotalCollections: z.number().int().min(0),\n\t})\n\t.meta({ id: \"MediaUsageProgress\" });\n\nexport const mediaUsageSummarySchema = z\n\t.object({\n\t\tcount: z.number().int().min(0).nullable(),\n\t\tcoverage: mediaUsageCoverageSchema,\n\t})\n\t.meta({ id: \"MediaUsageSummary\" });\n\nexport const mediaUsageDetailsQuery = z.object({\n\tcursor: z.string().min(1).max(2048).optional().meta({\n\t\tdescription: \"Opaque content-entry-group cursor\",\n\t}),\n\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50).meta({\n\t\tdescription: \"Maximum number of content entry groups to return (1-100, default 50)\",\n\t}),\n});\n\nexport const mediaUsageOccurrenceDetailSchema = z\n\t.object({\n\t\tfieldSlug: z.string(),\n\t\tfieldPath: z.string(),\n\t\toccurrenceIndex: z.number().int().min(0),\n\t\treferenceType: z.enum([\"image_field\", \"file_field\", \"portable_text_image\", \"unknown\"]),\n\t})\n\t.meta({ id: \"MediaUsageOccurrenceDetail\" });\n\nexport const mediaUsageSourceDetailSchema = z\n\t.object({\n\t\tvariant: z.enum([\"columns\", \"draft_overlay\"]),\n\t\toccurrences: z.array(mediaUsageOccurrenceDetailSchema),\n\t})\n\t.meta({ id: \"MediaUsageSourceDetail\" });\n\nexport const mediaUsageEntryDetailSchema = z\n\t.object({\n\t\tcollection: z.string(),\n\t\tcontentId: z.string(),\n\t\ttitle: z.string().nullable(),\n\t\tslug: z.string().nullable(),\n\t\tlocale: z.string().nullable(),\n\t\tstatus: z.string().nullable(),\n\t\tscheduledAt: z.string().nullable(),\n\t\tdeletedAt: z.string().nullable(),\n\t\tsources: z.array(mediaUsageSourceDetailSchema),\n\t})\n\t.meta({ id: \"MediaUsageEntryDetail\" });\n\nexport const mediaUsageDetailsResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaUsageEntryDetailSchema),\n\t\tnextCursor: z.string().optional(),\n\t\tcoverage: mediaUsageCoverageSchema,\n\t})\n\t.meta({ id: \"MediaUsageDetailsResponse\" });\n\nexport const mediaUsageRepairStatusSchema = z\n\t.enum([\"complete\", \"partial\", \"failed\", \"stale\"])\n\t.meta({ id: \"MediaUsageRepairStatus\" });\n\nconst mediaUsageRepairCollectionBody = z\n\t.object({\n\t\tscope: z.literal(\"collection\"),\n\t\tcollection: z.string().min(1).max(63).regex(slugPattern, \"Invalid collection slug\"),\n\t})\n\t.strict();\n\nconst mediaUsageRepairAllBody = z.object({ scope: z.literal(\"all\") }).strict();\n\nexport const mediaUsageRepairBody = z\n\t.discriminatedUnion(\"scope\", [mediaUsageRepairCollectionBody, mediaUsageRepairAllBody])\n\t.meta({ id: \"MediaUsageRepairBody\" });\n\nexport const mediaUsageRepairCollectionSummarySchema = z\n\t.object({\n\t\tcollection: z.string(),\n\t\tstatus: mediaUsageRepairStatusSchema,\n\t\tindexedSourceCount: z.number().int().min(0),\n\t\tfailedSourceCount: z.number().int().min(0),\n\t\tskippedSourceCount: z.number().int().min(0),\n\t\tdeletedSourceCount: z.number().int().min(0),\n\t\tlastErrorCode: z.string().nullable(),\n\t\tstartedAt: z.string(),\n\t\tcompletedAt: z.string().nullable(),\n\t})\n\t.meta({ id: \"MediaUsageRepairCollectionSummary\" });\n\nexport const mediaUsageRepairResponseSchema = z\n\t.object({\n\t\tstatus: mediaUsageRepairStatusSchema,\n\t\tindexedSourceCount: z.number().int().min(0),\n\t\tfailedSourceCount: z.number().int().min(0),\n\t\tskippedSourceCount: z.number().int().min(0),\n\t\tdeletedSourceCount: z.number().int().min(0),\n\t\tcollections: z.array(mediaUsageRepairCollectionSummarySchema),\n\t})\n\t.meta({ id: \"MediaUsageRepairResponse\" });\n\nexport const mediaUsageWorkStateSchema = z\n\t.enum([\"pending\", \"retry\", \"leased\", \"failed\"])\n\t.meta({ id: \"MediaUsageWorkState\" });\n\nexport const mediaUsageWorkListQuery = z.object({\n\tcollection: z.string().min(1).max(63).regex(slugPattern, \"Invalid collection slug\"),\n\tstate: mediaUsageWorkStateSchema.optional(),\n\tcursor: z.string().min(1).max(2048).optional().meta({\n\t\tdescription: \"Opaque work-page cursor\",\n\t}),\n\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50).meta({\n\t\tdescription: \"Maximum number of work items to return (1-100, default 50)\",\n\t}),\n});\n\nexport const mediaUsageWorkItemSchema = z\n\t.object({\n\t\tcollectionId: z.string(),\n\t\tcollectionSlug: z.string(),\n\t\tcontentId: z.string(),\n\t\tstate: mediaUsageWorkStateSchema,\n\t\tattemptCount: z.number().int().min(0),\n\t\tnextAttemptAt: z.string(),\n\t\tleaseExpiresAt: z.string().nullable(),\n\t\tlastAttemptedAt: z.string().nullable(),\n\t\tlastErrorCode: z.string().nullable(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUsageWorkItem\" });\n\nexport const mediaUsageWorkListResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaUsageWorkItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"MediaUsageWorkListResponse\" });\n\nconst boundedOpaqueMediaUsageId = z.string().min(1).max(2048);\n\nexport const mediaUsageWorkRetryBody = z\n\t.object({\n\t\tcollectionId: boundedOpaqueMediaUsageId.meta({\n\t\t\tdescription: \"Current immutable collection identity\",\n\t\t}),\n\t\tcontentId: boundedOpaqueMediaUsageId.meta({\n\t\t\tdescription: \"Content entry identity, including a deleted entry\",\n\t\t}),\n\t})\n\t.strict()\n\t.meta({ id: \"MediaUsageWorkRetryBody\" });\n\nexport const mediaUsageWorkRetryResponseSchema = z\n\t.object({\n\t\tchanged: z.boolean(),\n\t\titem: mediaUsageWorkItemSchema,\n\t})\n\t.meta({ id: \"MediaUsageWorkRetryResponse\" });\n\nexport const mediaUsageWorkRetryConflictSchema = z.object({\n\tsuccess: z.literal(false),\n\terror: z.discriminatedUnion(\"code\", [\n\t\tz.object({\n\t\t\tcode: z.literal(\"WORK_LEASE_ACTIVE\"),\n\t\t\tmessage: z.string(),\n\t\t\tdetails: z.object({ leaseExpiresAt: z.string() }),\n\t\t}),\n\t\tz.object({\n\t\t\tcode: z.literal(\"WORK_CHANGED\"),\n\t\t\tmessage: z.string(),\n\t\t}),\n\t]),\n});\n\nexport const mediaUsageActivationStateSchema = z\n\t.enum([\"expanded\", \"activating\", \"active\"])\n\t.meta({ id: \"MediaUsageActivationState\" });\n\nexport const mediaUsageActivationStatusSchema = z\n\t.object({\n\t\tstate: mediaUsageActivationStateSchema,\n\t\tcollectionCursor: z.string().nullable(),\n\t\tattemptCount: z.number().int().min(0),\n\t\tdrainConfirmedAt: z.string().nullable(),\n\t\tlastAttemptedAt: z.string().nullable(),\n\t\tlastErrorCode: z.literal(\"MEDIA_USAGE_ACTIVATION_FAILED\").nullable(),\n\t\tleaseExpiresAt: z.string().nullable(),\n\t\tactivatedAt: z.string().nullable(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUsageActivationStatus\" });\n\nexport const mediaUsageActivationAdvanceBody = z\n\t.object({\n\t\twritersDrained: z.literal(true),\n\t})\n\t.strict()\n\t.meta({ id: \"MediaUsageActivationAdvanceBody\" });\n\nexport const mediaUsageActivationAdvanceResponseSchema = z\n\t.object({\n\t\toutcome: z.enum([\"activating\", \"active\"]),\n\t\tprocessedCollections: z.number().int().min(0).max(1),\n\t\tactivation: mediaUsageActivationStatusSchema,\n\t})\n\t.meta({ id: \"MediaUsageActivationAdvanceResponse\" });\n\nexport const mediaUsageProgressAdvanceResponseSchema = z\n\t.object({\n\t\tactivation: mediaUsageActivationStatusSchema,\n\t\tprogress: mediaUsageProgressSchema.nullable(),\n\t\tnextRequestInMs: z.union([z.literal(0), z.literal(30_000), z.null()]),\n\t})\n\t.meta({ id: \"MediaUsageProgressAdvanceResponse\" });\n\nexport const mediaUsageActivationConflictSchema = z.object({\n\tsuccess: z.literal(false),\n\terror: z.discriminatedUnion(\"code\", [\n\t\tz.object({\n\t\t\tcode: z.literal(\"MEDIA_USAGE_ACTIVATION_BUSY\"),\n\t\t\tmessage: z.string(),\n\t\t\tdetails: z.object({ leaseExpiresAt: z.string() }),\n\t\t}),\n\t\tz.object({\n\t\t\tcode: z.literal(\"MEDIA_USAGE_ACTIVATION_CONFLICT\"),\n\t\t\tmessage: z.string(),\n\t\t}),\n\t\tz.object({\n\t\t\tcode: z.literal(\"MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH\"),\n\t\t\tmessage: z.string(),\n\t\t}),\n\t]),\n});\n\nexport const mediaUsageCollectionDeletionStateSchema = z\n\t.enum([\"pending\", \"retry\", \"leased\", \"failed\"])\n\t.meta({ id: \"MediaUsageCollectionDeletionState\" });\nexport const mediaUsageCollectionDeletionPhaseSchema = z\n\t.enum([\"fence\", \"registry\", \"table\", \"work\", \"sources\", \"status\", \"finalize\"])\n\t.meta({ id: \"MediaUsageCollectionDeletionPhase\" });\nexport const mediaUsageCollectionDeletionListQuery = z\n\t.object({\n\t\tstate: mediaUsageCollectionDeletionStateSchema.optional().default(\"failed\"),\n\t\tcursor: z.string().min(1).max(2048).optional(),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionListQuery\" });\nexport const mediaUsageCollectionDeletionItemSchema = z\n\t.object({\n\t\tcollectionId: z.string(),\n\t\tcollectionSlug: z.string(),\n\t\tstate: mediaUsageCollectionDeletionStateSchema,\n\t\tphase: mediaUsageCollectionDeletionPhaseSchema,\n\t\tattemptCount: z.number().int().min(0),\n\t\tnextAttemptAt: z.string(),\n\t\tleaseExpiresAt: z.string().nullable(),\n\t\tlastErrorCode: z.string().nullable(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionItem\" });\nexport const mediaUsageCollectionDeletionListResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaUsageCollectionDeletionItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionListResponse\" });\nexport const mediaUsageCollectionDeletionRetryBody = z\n\t.object({ collectionId: boundedOpaqueMediaUsageId })\n\t.strict()\n\t.meta({ id: \"MediaUsageCollectionDeletionRetryBody\" });\nexport const mediaUsageCollectionDeletionRetryResponseSchema = z\n\t.object({\n\t\tchanged: z.boolean(),\n\t\titem: mediaUsageCollectionDeletionItemSchema,\n\t})\n\t.meta({ id: \"MediaUsageCollectionDeletionRetryResponse\" });\n\nexport type MediaUsageRepairRequest = z.infer<typeof mediaUsageRepairBody>;\nexport type MediaUsageRepairResponse = z.infer<typeof mediaUsageRepairResponseSchema>;\nexport type MediaUsageProgress = z.infer<typeof mediaUsageProgressSchema>;\nexport type MediaUsageProgressAdvanceResponse = z.infer<\n\ttypeof mediaUsageProgressAdvanceResponseSchema\n>;\nexport type MediaUsageWorkListQuery = z.infer<typeof mediaUsageWorkListQuery>;\nexport type MediaUsageWorkItem = z.infer<typeof mediaUsageWorkItemSchema>;\nexport type MediaUsageWorkListResponse = z.infer<typeof mediaUsageWorkListResponseSchema>;\nexport type MediaUsageWorkRetryRequest = z.infer<typeof mediaUsageWorkRetryBody>;\nexport type MediaUsageWorkRetryResponse = z.infer<typeof mediaUsageWorkRetryResponseSchema>;\nexport type MediaUsageActivationStatus = z.infer<typeof mediaUsageActivationStatusSchema>;\nexport type MediaUsageActivationAdvanceRequest = z.infer<typeof mediaUsageActivationAdvanceBody>;\nexport type MediaUsageActivationAdvanceResponse = z.infer<\n\ttypeof mediaUsageActivationAdvanceResponseSchema\n>;\nexport type MediaUsageCollectionDeletionListQuery = z.infer<\n\ttypeof mediaUsageCollectionDeletionListQuery\n>;\nexport type MediaUsageCollectionDeletionListResponse = z.infer<\n\ttypeof mediaUsageCollectionDeletionListResponseSchema\n>;\nexport type MediaUsageCollectionDeletionRetryRequest = z.infer<\n\ttypeof mediaUsageCollectionDeletionRetryBody\n>;\nexport type MediaUsageCollectionDeletionRetryResponse = z.infer<\n\ttypeof mediaUsageCollectionDeletionRetryResponseSchema\n>;\nexport type MediaUsageCoverageStatus = z.infer<typeof mediaUsageCoverageStatusSchema>;\nexport type MediaUsageCoverage = z.infer<typeof mediaUsageCoverageSchema>;\nexport type MediaUsageSummary = z.infer<typeof mediaUsageSummarySchema>;\nexport type MediaUsageOccurrenceDetail = z.infer<typeof mediaUsageOccurrenceDetailSchema>;\nexport type MediaUsageSourceDetail = z.infer<typeof mediaUsageSourceDetailSchema>;\nexport type MediaUsageEntryDetail = z.infer<typeof mediaUsageEntryDetailSchema>;\nexport type MediaUsageDetailsResponse = z.infer<typeof mediaUsageDetailsResponseSchema>;\n","import { z } from \"zod\";\n\nimport { isValidFocalPointUpdate } from \"#media/focal-point.js\";\n\nimport { cursorPaginationQuery } from \"./common.js\";\nimport { mediaUsageSummarySchema } from \"./media-usage.js\";\n\n// ---------------------------------------------------------------------------\n// Media: Input schemas\n// ---------------------------------------------------------------------------\n\n/**\n * Accepts a comma-separated string (from URL query params) or an array of\n * strings (from JSON body or programmatic use) and normalises to string[].\n */\nconst mimeTypeFilter = z\n\t.union([z.string(), z.array(z.string())])\n\t.transform((v) => {\n\t\tconst arr = Array.isArray(v) ? v : v.split(\",\");\n\t\treturn arr.map((s) => s.trim()).filter((s) => s.length > 0);\n\t})\n\t.optional();\n\nexport const mediaListQuery = cursorPaginationQuery\n\t.extend({\n\t\tpage: z.coerce.number().int().min(1).max(Number.MAX_SAFE_INTEGER).optional(),\n\t\tmimeType: mimeTypeFilter,\n\t\tfolderId: z\n\t\t\t.union([z.literal(\"unfiled\"), z.string().min(1).max(64)])\n\t\t\t.optional()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Filter by a media folder ID. Use `unfiled` for the Main library; omit for all media.\",\n\t\t\t}),\n\t\t/** Case-insensitive filename substring search (also matches extensions). */\n\t\tq: z.string().trim().min(1).max(200).optional(),\n\t\tincludeUsage: z.literal(\"1\").optional().meta({\n\t\t\tdescription: \"Include a coverage-aware usage summary on each media item\",\n\t\t}),\n\t})\n\t.refine(({ cursor, page }) => cursor === undefined || page === undefined, {\n\t\tmessage: \"cursor and page cannot be used together\",\n\t\tpath: [\"page\"],\n\t})\n\t.meta({ id: \"MediaListQuery\" });\n\nexport const mediaGetQuery = z\n\t.object({\n\t\tincludeUsage: z.literal(\"1\").optional().meta({\n\t\t\tdescription: \"Include a coverage-aware usage summary on the media item\",\n\t\t}),\n\t})\n\t.meta({ id: \"MediaGetQuery\" });\n\nexport const mediaUpdateBody = z\n\t.object({\n\t\talt: z.string().optional(),\n\t\tcaption: z.string().optional(),\n\t\twidth: z.number().int().positive().optional(),\n\t\theight: z.number().int().positive().optional(),\n\t\tfolderId: z\n\t\t\t.union([z.literal(\"unfiled\"), z.string().min(1).max(64)])\n\t\t\t.nullable()\n\t\t\t.optional()\n\t\t\t.transform((value) => (value === \"unfiled\" ? null : value))\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Assign a media folder ID, or use null or `unfiled` to return the item to the Main library.\",\n\t\t\t}),\n\t\tfocalX: z.number().min(0).max(1).nullable().optional(),\n\t\tfocalY: z.number().min(0).max(1).nullable().optional(),\n\t})\n\t.superRefine((value, context) => {\n\t\tif (!isValidFocalPointUpdate(value)) {\n\t\t\tcontext.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: \"focalX and focalY must both be numbers or both be null\",\n\t\t\t\tpath: [\"focalX\"],\n\t\t\t});\n\t\t}\n\t})\n\t.meta({ id: \"MediaUpdateBody\" });\n\nexport const mediaFolderIdSchema = z.string().min(1).max(64);\n\nexport const mediaFolderListQuery = cursorPaginationQuery\n\t.extend({ q: z.string().trim().min(1).max(200).optional() })\n\t.meta({ id: \"MediaFolderListQuery\" });\n\nconst mediaFolderNameSchema = z.string().refine(\n\t(value) => {\n\t\tconst length = value.trim().length;\n\t\treturn length >= 1 && length <= 200;\n\t},\n\t{ message: \"Folder name must be between 1 and 200 characters\" },\n);\n\nexport const mediaFolderBody = z\n\t.object({ name: mediaFolderNameSchema })\n\t.meta({ id: \"MediaFolderBody\" });\n\n/** Default maximum allowed file upload size (50 MB). */\nexport const DEFAULT_MAX_UPLOAD_SIZE = 50 * 1024 * 1024;\n\nexport function formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes}B`;\n\tif (bytes < 1024 * 1024) return `${Math.floor(bytes / 1024)}KB`;\n\treturn `${Math.floor(bytes / 1024 / 1024)}MB`;\n}\n\n// Matches a full MIME type (type/subtype) with an optional semicolon-delimited\n// parameter section. Forbids CR/LF to prevent header injection.\nexport const CONTENT_TYPE_RE = /^[a-z0-9][a-z0-9!#$&^_+\\-.]*\\/[a-z0-9!#$&^_+\\-.]+(\\s*;[^\\r\\n]*)?$/i;\n\nexport function mediaUploadUrlBody(maxSize: number) {\n\tif (!Number.isFinite(maxSize) || maxSize <= 0) {\n\t\tthrow new Error(`EmDash: maxUploadSize must be a positive finite number, got ${maxSize}`);\n\t}\n\treturn z\n\t\t.object({\n\t\t\tfilename: z.string().min(1, \"filename is required\"),\n\t\t\tcontentType: z\n\t\t\t\t.string()\n\t\t\t\t.min(1, \"contentType is required\")\n\t\t\t\t.regex(CONTENT_TYPE_RE, \"Invalid content type\"),\n\t\t\tsize: z\n\t\t\t\t.number()\n\t\t\t\t.int()\n\t\t\t\t.nonnegative()\n\t\t\t\t.max(maxSize, `File size must not exceed ${formatFileSize(maxSize)}`),\n\t\t\tcontentHash: z.string().optional(),\n\t\t\tfieldId: z.string().optional(),\n\t\t\tdeduplicate: z.boolean().optional(),\n\t\t\tensureUniqueFilename: z.boolean().optional(),\n\t\t\tfolderId: mediaFolderIdSchema.nullable().optional(),\n\t\t})\n\t\t.meta({ id: \"MediaUploadUrlBody\" });\n}\n\nexport const mediaUploadDeduplicateForm = z\n\t.enum([\"true\", \"false\"])\n\t.default(\"true\")\n\t.transform((value) => value === \"true\");\n\nexport const mediaUploadEnsureUniqueFilenameForm = z\n\t.enum([\"true\", \"false\"])\n\t.default(\"false\")\n\t.transform((value) => value === \"true\");\n\nexport const mediaReplaceMetadataForm = z.object({\n\twidth: z.coerce.number().int().positive().max(Number.MAX_SAFE_INTEGER),\n\theight: z.coerce.number().int().positive().max(Number.MAX_SAFE_INTEGER),\n});\n\nconst binaryFileSchema = z.string().meta({ format: \"binary\" });\n\nexport const mediaDirectUploadBody = z\n\t.object({\n\t\tfile: binaryFileSchema,\n\t\twidth: z.string().optional(),\n\t\theight: z.string().optional(),\n\t\tthumbnail: binaryFileSchema.optional(),\n\t\tfieldId: z.string().optional(),\n\t\tdeduplicate: z.enum([\"true\", \"false\"]).optional(),\n\t\tensureUniqueFilename: z.enum([\"true\", \"false\"]).optional(),\n\t\tfolderId: z.union([mediaFolderIdSchema, z.literal(\"unfiled\")]).optional(),\n\t})\n\t.meta({ id: \"MediaDirectUploadBody\" });\n\nexport const mediaReplaceBody = z\n\t.object({\n\t\tfile: binaryFileSchema,\n\t\twidth: z.number().int().positive(),\n\t\theight: z.number().int().positive(),\n\t})\n\t.meta({ id: \"MediaReplaceBody\" });\n\nexport const mediaConfirmBody = z\n\t.object({\n\t\tsize: z.number().int().nonnegative().optional(),\n\t\twidth: z.number().int().positive().optional(),\n\t\theight: z.number().int().positive().optional(),\n\t})\n\t.meta({ id: \"MediaConfirmBody\" });\n\nexport const mediaProviderListQuery = cursorPaginationQuery\n\t.extend({\n\t\tquery: z.string().optional(),\n\t\tmimeType: mimeTypeFilter,\n\t})\n\t.meta({ id: \"MediaProviderListQuery\" });\n\n// ---------------------------------------------------------------------------\n// Media: Response schemas\n// ---------------------------------------------------------------------------\n\nconst mediaStatusSchema = z.enum([\"pending\", \"ready\", \"failed\"]);\n\nexport const mediaItemSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tfilename: z.string(),\n\t\tmimeType: z.string(),\n\t\tsize: z.number().nullable(),\n\t\twidth: z.number().nullable(),\n\t\theight: z.number().nullable(),\n\t\tfocalX: z.number().nullable(),\n\t\tfocalY: z.number().nullable(),\n\t\talt: z.string().nullable(),\n\t\tcaption: z.string().nullable(),\n\t\tstorageKey: z.string(),\n\t\tstatus: mediaStatusSchema,\n\t\tcontentHash: z.string().nullable(),\n\t\tblurhash: z.string().nullable(),\n\t\tdominantColor: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t\tauthorId: z.string().nullable(),\n\t\tfolderId: z.string().nullable(),\n\t})\n\t.meta({ id: \"MediaItem\" });\n\nexport const mediaFolderSchema = z\n\t.object({ id: z.string(), name: z.string() })\n\t.meta({ id: \"MediaFolder\" });\n\nexport const mediaFolderResponseSchema = z\n\t.object({ item: mediaFolderSchema })\n\t.meta({ id: \"MediaFolderResponse\" });\n\nexport const mediaFolderListResponseSchema = z\n\t.object({ items: z.array(mediaFolderSchema), nextCursor: z.string().optional() })\n\t.meta({ id: \"MediaFolderListResponse\" });\n\nexport const mediaResponseSchema = z\n\t.object({ item: mediaItemSchema })\n\t.meta({ id: \"MediaResponse\" });\n\nexport const mediaReadItemSchema = mediaItemSchema\n\t.extend({ usage: mediaUsageSummarySchema.optional() })\n\t.meta({ id: \"MediaReadItem\" });\n\nexport const mediaReadResponseSchema = z\n\t.object({ item: mediaReadItemSchema })\n\t.meta({ id: \"MediaReadResponse\" });\n\nexport const mediaListReadItemSchema = mediaReadItemSchema\n\t.extend({ url: z.string() })\n\t.meta({ id: \"MediaListReadItem\" });\n\nexport const mediaListReadResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaListReadItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t\ttotalCount: z.number().int().nonnegative().optional(),\n\t})\n\t.meta({ id: \"MediaListReadResponse\" });\n\nexport const mediaListResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t\ttotalCount: z.number().int().nonnegative().optional(),\n\t})\n\t.meta({ id: \"MediaListResponse\" });\n\nexport const mediaUploadUrlResponseSchema = z\n\t.object({\n\t\tuploadUrl: z.string(),\n\t\tmethod: z.literal(\"PUT\"),\n\t\theaders: z.record(z.string(), z.string()),\n\t\tmediaId: z.string(),\n\t\tstorageKey: z.string(),\n\t\texpiresAt: z.string(),\n\t})\n\t.meta({ id: \"MediaUploadUrlResponse\" });\n\nexport const mediaExistingResponseSchema = z\n\t.object({\n\t\texisting: z.literal(true),\n\t\tmediaId: z.string(),\n\t\tstorageKey: z.string(),\n\t\turl: z.string(),\n\t})\n\t.meta({ id: \"MediaExistingResponse\" });\n\nexport const mediaConfirmResponseSchema = z\n\t.object({\n\t\titem: mediaItemSchema.extend({ url: z.string() }),\n\t})\n\t.meta({ id: \"MediaConfirmResponse\" });\n\nexport const mediaUploadResponseSchema = z\n\t.object({\n\t\titem: mediaItemSchema.extend({ url: z.string() }),\n\t\tdeduplicated: z.literal(true).optional(),\n\t})\n\t.meta({ id: \"MediaUploadResponse\" });\n\nexport const mediaReplaceResponseSchema = z\n\t.object({ item: mediaItemSchema.extend({ url: z.string() }) })\n\t.meta({ id: \"MediaReplaceResponse\" });\n\nexport const mediaStreamUploadResponseSchema = z\n\t.object({\n\t\tuploaded: z.literal(true),\n\t\tsize: z.number().int().nonnegative(),\n\t})\n\t.meta({ id: \"MediaStreamUploadResponse\" });\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { r as parseAllowedMimeTypes } from "./mime-CUIG6x84.mjs";
1
+ import { r as parseAllowedMimeTypes } from "./mime-DYpsOAny.mjs";
2
2
 
3
3
  //#region src/api/handlers/media-allowlist.ts
4
4
  /**
@@ -41,4 +41,4 @@ async function resolveFieldAllowlist(db, fieldId) {
41
41
 
42
42
  //#endregion
43
43
  export { resolveFieldAllowlist as n, GLOBAL_UPLOAD_ALLOWLIST as t };
44
- //# sourceMappingURL=media-allowlist-CoTBWoDp.mjs.map
44
+ //# sourceMappingURL=media-allowlist-elXJgb_K.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"media-allowlist-CoTBWoDp.mjs","names":[],"sources":["../src/api/handlers/media-allowlist.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { parseAllowedMimeTypes } from \"../../media/mime.js\";\n\n/**\n * MIME types allowed for upload by default (when no field-specific list\n * overrides this). Entries ending with \"/\" are prefix-matched (e.g.\n * \"video/\" matches \"video/mp4\", \"video/webm\", etc.).\n *\n * Image types are enumerated explicitly rather than using a bare \"image/\"\n * prefix so that \"image/svg+xml\" is excluded by default: there is no\n * upload-time content validation for SVG, so an unvalidated bare-prefix\n * allowlist would let a Contributor+ upload an SVG with an embedded\n * `<script>`. Fields that genuinely need SVG uploads can still opt in via\n * their own `allowedMimeTypes` (see `resolveFieldAllowlist` below), which is\n * unaffected by this default.\n */\nexport const GLOBAL_UPLOAD_ALLOWLIST: readonly string[] = [\n\t\"image/png\",\n\t\"image/jpeg\",\n\t\"image/gif\",\n\t\"image/webp\",\n\t\"image/avif\",\n\t\"video/\",\n\t\"audio/\",\n\t\"application/pdf\",\n];\n\n/**\n * Resolve the MIME allowlist for a specific field.\n *\n * Returns the field's `allowedMimeTypes` list when the field exists, is of\n * type \"file\" or \"image\", and has a non-empty list configured. Returns null\n * in all other cases — callers should fall back to GLOBAL_UPLOAD_ALLOWLIST.\n *\n * Authentication is the caller's responsibility (the upload routes already\n * gate on `media:upload`).\n */\nexport async function resolveFieldAllowlist(\n\tdb: Kysely<Database>,\n\tfieldId: string,\n): Promise<string[] | null> {\n\tconst row = await db\n\t\t.selectFrom(\"_emdash_fields\")\n\t\t.select([\"type\", \"validation\"])\n\t\t.where(\"id\", \"=\", fieldId)\n\t\t.where(\"type\", \"in\", [\"file\", \"image\"])\n\t\t.executeTakeFirst();\n\n\treturn row ? parseAllowedMimeTypes(row.validation) : null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,MAAa,0BAA6C;CACzD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;;;;;;;;AAYD,eAAsB,sBACrB,IACA,SAC2B;CAC3B,MAAM,MAAM,MAAM,GAChB,WAAW,iBAAiB,CAC5B,OAAO,CAAC,QAAQ,aAAa,CAAC,CAC9B,MAAM,MAAM,KAAK,QAAQ,CACzB,MAAM,QAAQ,MAAM,CAAC,QAAQ,QAAQ,CAAC,CACtC,kBAAkB;AAEpB,QAAO,MAAM,sBAAsB,IAAI,WAAW,GAAG"}
1
+ {"version":3,"file":"media-allowlist-elXJgb_K.mjs","names":[],"sources":["../src/api/handlers/media-allowlist.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { parseAllowedMimeTypes } from \"../../media/mime.js\";\n\n/**\n * MIME types allowed for upload by default (when no field-specific list\n * overrides this). Entries ending with \"/\" are prefix-matched (e.g.\n * \"video/\" matches \"video/mp4\", \"video/webm\", etc.).\n *\n * Image types are enumerated explicitly rather than using a bare \"image/\"\n * prefix so that \"image/svg+xml\" is excluded by default: there is no\n * upload-time content validation for SVG, so an unvalidated bare-prefix\n * allowlist would let a Contributor+ upload an SVG with an embedded\n * `<script>`. Fields that genuinely need SVG uploads can still opt in via\n * their own `allowedMimeTypes` (see `resolveFieldAllowlist` below), which is\n * unaffected by this default.\n */\nexport const GLOBAL_UPLOAD_ALLOWLIST: readonly string[] = [\n\t\"image/png\",\n\t\"image/jpeg\",\n\t\"image/gif\",\n\t\"image/webp\",\n\t\"image/avif\",\n\t\"video/\",\n\t\"audio/\",\n\t\"application/pdf\",\n];\n\n/**\n * Resolve the MIME allowlist for a specific field.\n *\n * Returns the field's `allowedMimeTypes` list when the field exists, is of\n * type \"file\" or \"image\", and has a non-empty list configured. Returns null\n * in all other cases — callers should fall back to GLOBAL_UPLOAD_ALLOWLIST.\n *\n * Authentication is the caller's responsibility (the upload routes already\n * gate on `media:upload`).\n */\nexport async function resolveFieldAllowlist(\n\tdb: Kysely<Database>,\n\tfieldId: string,\n): Promise<string[] | null> {\n\tconst row = await db\n\t\t.selectFrom(\"_emdash_fields\")\n\t\t.select([\"type\", \"validation\"])\n\t\t.where(\"id\", \"=\", fieldId)\n\t\t.where(\"type\", \"in\", [\"file\", \"image\"])\n\t\t.executeTakeFirst();\n\n\treturn row ? parseAllowedMimeTypes(row.validation) : null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,MAAa,0BAA6C;CACzD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;;;;;;;;AAYD,eAAsB,sBACrB,IACA,SAC2B;CAC3B,MAAM,MAAM,MAAM,GAChB,WAAW,iBAAiB,CAC5B,OAAO,CAAC,QAAQ,aAAa,CAAC,CAC9B,MAAM,MAAM,KAAK,QAAQ,CACzB,MAAM,QAAQ,MAAM,CAAC,QAAQ,QAAQ,CAAC,CACtC,kBAAkB;AAEpB,QAAO,MAAM,sBAAsB,IAAI,WAAW,GAAG"}
@@ -207,4 +207,4 @@ function isUniqueViolation(error) {
207
207
 
208
208
  //#endregion
209
209
  export { handleMediaFolderUpdate as a, handleMediaFolderList as i, handleMediaFolderDelete as n, handleMediaFolderGet as r, handleMediaFolderCreate as t };
210
- //# sourceMappingURL=media-folders-BGkATs8n.mjs.map
210
+ //# sourceMappingURL=media-folders-DASfX_DH.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"media-folders-BGkATs8n.mjs","names":[],"sources":["../src/database/repositories/media-folders.ts","../src/api/handlers/media-folders.ts"],"sourcesContent":["import { sql, type Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport type { Database } from \"../types.js\";\nimport { decodeCursor, EmDashValidationError, encodeCursor, type FindManyResult } from \"./types.js\";\n\nexport interface MediaFolder {\n\tid: string;\n\tname: string;\n}\n\nexport interface FindManyMediaFoldersOptions {\n\tlimit?: number;\n\tcursor?: string;\n\tq?: string;\n}\n\nfunction escapeLike(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"%\", \"\\\\%\").replaceAll(\"_\", \"\\\\_\");\n}\n\nfunction normalizeFolderSearch(value: string): string {\n\treturn value.trim().normalize(\"NFKC\").toLowerCase();\n}\n\nfunction normalizeFolderName(name: string): { name: string; nameKey: string } {\n\tif (typeof name !== \"string\") {\n\t\tthrow new EmDashValidationError(\"Folder name must be a string\");\n\t}\n\tconst trimmed = name.trim();\n\tif (trimmed.length < 1 || trimmed.length > 200) {\n\t\tthrow new EmDashValidationError(\"Folder name must be between 1 and 200 characters\");\n\t}\n\treturn { name: trimmed, nameKey: trimmed.normalize(\"NFKC\").toLowerCase() };\n}\n\nexport class MediaFolderRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\tasync findMany(options: FindManyMediaFoldersOptions = {}): Promise<FindManyResult<MediaFolder>> {\n\t\tconst limit = Math.max(1, Math.min(options.limit ?? 50, 100));\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"media_folders\")\n\t\t\t.select([\"id\", \"name\", \"name_key\"])\n\t\t\t.orderBy(\"name_key\", \"asc\")\n\t\t\t.orderBy(\"id\", \"asc\")\n\t\t\t.limit(limit + 1);\n\n\t\tconst term = normalizeFolderSearch(options.q ?? \"\");\n\t\tif (term) {\n\t\t\tconst pattern = `%${escapeLike(term)}%`;\n\t\t\tquery = query.where(\"name_key\", \"like\", sql<string>`${pattern} escape '\\\\'`);\n\t\t}\n\n\t\tif (options.cursor !== undefined) {\n\t\t\tconst { orderValue: nameKey, id } = decodeCursor(options.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"name_key\", \">\", nameKey),\n\t\t\t\t\teb.and([eb(\"name_key\", \"=\", nameKey), eb(\"id\", \">\", id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst hasMore = rows.length > limit;\n\t\tconst visible = rows.slice(0, limit);\n\t\treturn {\n\t\t\titems: visible.map(({ id, name }) => ({ id, name })),\n\t\t\tnextCursor:\n\t\t\t\thasMore && visible.length > 0\n\t\t\t\t\t? encodeCursor(visible.at(-1)!.name_key, visible.at(-1)!.id)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tasync findById(id: string): Promise<MediaFolder | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"media_folders\")\n\t\t\t.select([\"id\", \"name\"])\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn row ?? null;\n\t}\n\n\tasync create(inputName: string): Promise<MediaFolder> {\n\t\tconst { name, nameKey } = normalizeFolderName(inputName);\n\t\tconst row = await this.db\n\t\t\t.insertInto(\"media_folders\")\n\t\t\t.values({ id: ulid(), name, name_key: nameKey })\n\t\t\t.returning([\"id\", \"name\"])\n\t\t\t.executeTakeFirstOrThrow();\n\t\treturn row;\n\t}\n\n\tasync update(id: string, inputName: string): Promise<MediaFolder | null> {\n\t\tconst { name, nameKey } = normalizeFolderName(inputName);\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"media_folders\")\n\t\t\t.set({ name, name_key: nameKey })\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.returning([\"id\", \"name\"])\n\t\t\t.executeTakeFirst();\n\t\treturn row ?? null;\n\t}\n\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.deleteFrom(\"media_folders\")\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.returning(\"id\")\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n}\n","import type { Kysely } from \"kysely\";\n\nimport {\n\tMediaFolderRepository,\n\ttype MediaFolder,\n} from \"../../database/repositories/media-folders.js\";\nimport { EmDashValidationError, InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport type { ApiResult } from \"../types.js\";\n\nconst UNIQUE_VIOLATION_RE =\n\t/unique constraint failed|duplicate key value violates unique constraint/i;\n\nexport async function handleMediaFolderList(\n\tdb: Kysely<Database>,\n\toptions: { limit?: number; cursor?: string; q?: string } = {},\n): Promise<ApiResult<{ items: MediaFolder[]; nextCursor?: string }>> {\n\ttry {\n\t\tconst result = await new MediaFolderRepository(db).findMany(options);\n\t\treturn { success: true, data: result };\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn { success: false, error: { code: \"INVALID_CURSOR\", message: error.message } };\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MEDIA_FOLDER_LIST_ERROR\", message: \"Failed to list media folders\" },\n\t\t};\n\t}\n}\n\nexport async function handleMediaFolderGet(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ item: MediaFolder }>> {\n\ttry {\n\t\tconst item = await new MediaFolderRepository(db).findById(id);\n\t\tif (!item) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Media folder not found\" } };\n\t\t}\n\t\treturn { success: true, data: { item } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MEDIA_FOLDER_GET_ERROR\", message: \"Failed to get media folder\" },\n\t\t};\n\t}\n}\n\nexport async function handleMediaFolderCreate(\n\tdb: Kysely<Database>,\n\tinput: { name: string },\n): Promise<ApiResult<{ item: MediaFolder }>> {\n\ttry {\n\t\tconst item = await new MediaFolderRepository(db).create(input.name);\n\t\treturn { success: true, data: { item } };\n\t} catch (error) {\n\t\treturn mediaFolderWriteError(\n\t\t\terror,\n\t\t\t\"MEDIA_FOLDER_CREATE_ERROR\",\n\t\t\t\"Failed to create media folder\",\n\t\t);\n\t}\n}\n\nexport async function handleMediaFolderUpdate(\n\tdb: Kysely<Database>,\n\tid: string,\n\tinput: { name: string },\n): Promise<ApiResult<{ item: MediaFolder }>> {\n\ttry {\n\t\tconst item = await new MediaFolderRepository(db).update(id, input.name);\n\t\tif (!item) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Media folder not found\" } };\n\t\t}\n\t\treturn { success: true, data: { item } };\n\t} catch (error) {\n\t\treturn mediaFolderWriteError(\n\t\t\terror,\n\t\t\t\"MEDIA_FOLDER_UPDATE_ERROR\",\n\t\t\t\"Failed to update media folder\",\n\t\t);\n\t}\n}\n\nexport async function handleMediaFolderDelete(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst deleted = await new MediaFolderRepository(db).delete(id);\n\t\tif (!deleted) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Media folder not found\" } };\n\t\t}\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MEDIA_FOLDER_DELETE_ERROR\", message: \"Failed to delete media folder\" },\n\t\t};\n\t}\n}\n\nfunction mediaFolderWriteError(\n\terror: unknown,\n\tcode: \"MEDIA_FOLDER_CREATE_ERROR\" | \"MEDIA_FOLDER_UPDATE_ERROR\",\n\tmessage: string,\n): ApiResult<never> {\n\tif (error instanceof EmDashValidationError) {\n\t\treturn { success: false, error: { code: \"VALIDATION_ERROR\", message: error.message } };\n\t}\n\tif (isUniqueViolation(error)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"CONFLICT\", message: \"A media folder with this name already exists\" },\n\t\t};\n\t}\n\treturn { success: false, error: { code, message } };\n}\n\nfunction isUniqueViolation(error: unknown): boolean {\n\tif (error && typeof error === \"object\") {\n\t\tif (\"code\" in error && error.code === \"23505\") return true;\n\t}\n\tconst message = error instanceof Error ? error.message : \"\";\n\tif (UNIQUE_VIOLATION_RE.test(message)) return true;\n\treturn Boolean(\n\t\terror && typeof error === \"object\" && \"cause\" in error && isUniqueViolation(error.cause),\n\t);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"media-folders-DASfX_DH.mjs","names":[],"sources":["../src/database/repositories/media-folders.ts","../src/api/handlers/media-folders.ts"],"sourcesContent":["import { sql, type Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport type { Database } from \"../types.js\";\nimport { decodeCursor, EmDashValidationError, encodeCursor, type FindManyResult } from \"./types.js\";\n\nexport interface MediaFolder {\n\tid: string;\n\tname: string;\n}\n\nexport interface FindManyMediaFoldersOptions {\n\tlimit?: number;\n\tcursor?: string;\n\tq?: string;\n}\n\nfunction escapeLike(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"%\", \"\\\\%\").replaceAll(\"_\", \"\\\\_\");\n}\n\nfunction normalizeFolderSearch(value: string): string {\n\treturn value.trim().normalize(\"NFKC\").toLowerCase();\n}\n\nfunction normalizeFolderName(name: string): { name: string; nameKey: string } {\n\tif (typeof name !== \"string\") {\n\t\tthrow new EmDashValidationError(\"Folder name must be a string\");\n\t}\n\tconst trimmed = name.trim();\n\tif (trimmed.length < 1 || trimmed.length > 200) {\n\t\tthrow new EmDashValidationError(\"Folder name must be between 1 and 200 characters\");\n\t}\n\treturn { name: trimmed, nameKey: trimmed.normalize(\"NFKC\").toLowerCase() };\n}\n\nexport class MediaFolderRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\tasync findMany(options: FindManyMediaFoldersOptions = {}): Promise<FindManyResult<MediaFolder>> {\n\t\tconst limit = Math.max(1, Math.min(options.limit ?? 50, 100));\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"media_folders\")\n\t\t\t.select([\"id\", \"name\", \"name_key\"])\n\t\t\t.orderBy(\"name_key\", \"asc\")\n\t\t\t.orderBy(\"id\", \"asc\")\n\t\t\t.limit(limit + 1);\n\n\t\tconst term = normalizeFolderSearch(options.q ?? \"\");\n\t\tif (term) {\n\t\t\tconst pattern = `%${escapeLike(term)}%`;\n\t\t\tquery = query.where(\"name_key\", \"like\", sql<string>`${pattern} escape '\\\\'`);\n\t\t}\n\n\t\tif (options.cursor !== undefined) {\n\t\t\tconst { orderValue: nameKey, id } = decodeCursor(options.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"name_key\", \">\", nameKey),\n\t\t\t\t\teb.and([eb(\"name_key\", \"=\", nameKey), eb(\"id\", \">\", id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst hasMore = rows.length > limit;\n\t\tconst visible = rows.slice(0, limit);\n\t\treturn {\n\t\t\titems: visible.map(({ id, name }) => ({ id, name })),\n\t\t\tnextCursor:\n\t\t\t\thasMore && visible.length > 0\n\t\t\t\t\t? encodeCursor(visible.at(-1)!.name_key, visible.at(-1)!.id)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\tasync findById(id: string): Promise<MediaFolder | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"media_folders\")\n\t\t\t.select([\"id\", \"name\"])\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn row ?? null;\n\t}\n\n\tasync create(inputName: string): Promise<MediaFolder> {\n\t\tconst { name, nameKey } = normalizeFolderName(inputName);\n\t\tconst row = await this.db\n\t\t\t.insertInto(\"media_folders\")\n\t\t\t.values({ id: ulid(), name, name_key: nameKey })\n\t\t\t.returning([\"id\", \"name\"])\n\t\t\t.executeTakeFirstOrThrow();\n\t\treturn row;\n\t}\n\n\tasync update(id: string, inputName: string): Promise<MediaFolder | null> {\n\t\tconst { name, nameKey } = normalizeFolderName(inputName);\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"media_folders\")\n\t\t\t.set({ name, name_key: nameKey })\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.returning([\"id\", \"name\"])\n\t\t\t.executeTakeFirst();\n\t\treturn row ?? null;\n\t}\n\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.deleteFrom(\"media_folders\")\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.returning(\"id\")\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n}\n","import type { Kysely } from \"kysely\";\n\nimport {\n\tMediaFolderRepository,\n\ttype MediaFolder,\n} from \"../../database/repositories/media-folders.js\";\nimport { EmDashValidationError, InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport type { ApiResult } from \"../types.js\";\n\nconst UNIQUE_VIOLATION_RE =\n\t/unique constraint failed|duplicate key value violates unique constraint/i;\n\nexport async function handleMediaFolderList(\n\tdb: Kysely<Database>,\n\toptions: { limit?: number; cursor?: string; q?: string } = {},\n): Promise<ApiResult<{ items: MediaFolder[]; nextCursor?: string }>> {\n\ttry {\n\t\tconst result = await new MediaFolderRepository(db).findMany(options);\n\t\treturn { success: true, data: result };\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn { success: false, error: { code: \"INVALID_CURSOR\", message: error.message } };\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MEDIA_FOLDER_LIST_ERROR\", message: \"Failed to list media folders\" },\n\t\t};\n\t}\n}\n\nexport async function handleMediaFolderGet(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ item: MediaFolder }>> {\n\ttry {\n\t\tconst item = await new MediaFolderRepository(db).findById(id);\n\t\tif (!item) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Media folder not found\" } };\n\t\t}\n\t\treturn { success: true, data: { item } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MEDIA_FOLDER_GET_ERROR\", message: \"Failed to get media folder\" },\n\t\t};\n\t}\n}\n\nexport async function handleMediaFolderCreate(\n\tdb: Kysely<Database>,\n\tinput: { name: string },\n): Promise<ApiResult<{ item: MediaFolder }>> {\n\ttry {\n\t\tconst item = await new MediaFolderRepository(db).create(input.name);\n\t\treturn { success: true, data: { item } };\n\t} catch (error) {\n\t\treturn mediaFolderWriteError(\n\t\t\terror,\n\t\t\t\"MEDIA_FOLDER_CREATE_ERROR\",\n\t\t\t\"Failed to create media folder\",\n\t\t);\n\t}\n}\n\nexport async function handleMediaFolderUpdate(\n\tdb: Kysely<Database>,\n\tid: string,\n\tinput: { name: string },\n): Promise<ApiResult<{ item: MediaFolder }>> {\n\ttry {\n\t\tconst item = await new MediaFolderRepository(db).update(id, input.name);\n\t\tif (!item) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Media folder not found\" } };\n\t\t}\n\t\treturn { success: true, data: { item } };\n\t} catch (error) {\n\t\treturn mediaFolderWriteError(\n\t\t\terror,\n\t\t\t\"MEDIA_FOLDER_UPDATE_ERROR\",\n\t\t\t\"Failed to update media folder\",\n\t\t);\n\t}\n}\n\nexport async function handleMediaFolderDelete(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst deleted = await new MediaFolderRepository(db).delete(id);\n\t\tif (!deleted) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Media folder not found\" } };\n\t\t}\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MEDIA_FOLDER_DELETE_ERROR\", message: \"Failed to delete media folder\" },\n\t\t};\n\t}\n}\n\nfunction mediaFolderWriteError(\n\terror: unknown,\n\tcode: \"MEDIA_FOLDER_CREATE_ERROR\" | \"MEDIA_FOLDER_UPDATE_ERROR\",\n\tmessage: string,\n): ApiResult<never> {\n\tif (error instanceof EmDashValidationError) {\n\t\treturn { success: false, error: { code: \"VALIDATION_ERROR\", message: error.message } };\n\t}\n\tif (isUniqueViolation(error)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"CONFLICT\", message: \"A media folder with this name already exists\" },\n\t\t};\n\t}\n\treturn { success: false, error: { code, message } };\n}\n\nfunction isUniqueViolation(error: unknown): boolean {\n\tif (error && typeof error === \"object\") {\n\t\tif (\"code\" in error && error.code === \"23505\") return true;\n\t}\n\tconst message = error instanceof Error ? error.message : \"\";\n\tif (UNIQUE_VIOLATION_RE.test(message)) return true;\n\treturn Boolean(\n\t\terror && typeof error === \"object\" && \"cause\" in error && isUniqueViolation(error.cause),\n\t);\n}\n"],"mappings":"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"}
@@ -2,13 +2,13 @@ import "./config-C3EBstHi.mjs";
2
2
  import { n as decodeBase64Bytes } from "./base64-CvLhUKQv.mjs";
3
3
  import "./types-CQPWhPxE.mjs";
4
4
  import { t as MediaRepository } from "./media-BBm8Wg3f.mjs";
5
- import "./dist-89xCrGqi.mjs";
6
- import { n as normalizeMime, t as matchesMimeAllowlist } from "./mime-CUIG6x84.mjs";
7
- import { t as enrichImageMetadata } from "./enrich-BX0IDp4z.mjs";
8
- import { n as computeContentHash } from "./hash-3JJPlHF2.mjs";
9
- import { a as ssrfSafeFetch, t as SsrfError } from "./ssrf-5sIM5jzl.mjs";
10
- import { n as DEFAULT_MAX_UPLOAD_SIZE, r as formatFileSize, t as CONTENT_TYPE_RE } from "./media-BHjus86Y.mjs";
11
- import { t as GLOBAL_UPLOAD_ALLOWLIST } from "./media-allowlist-CoTBWoDp.mjs";
5
+ import "./dist-BAsh8dbf.mjs";
6
+ import { n as normalizeMime, t as matchesMimeAllowlist } from "./mime-DYpsOAny.mjs";
7
+ import { t as enrichImageMetadata } from "./enrich-t2Xvjdqa.mjs";
8
+ import { n as computeContentHash } from "./hash-BRweX6jz.mjs";
9
+ import { a as ssrfSafeFetch, t as SsrfError } from "./ssrf-gl4gFNhw.mjs";
10
+ import { n as DEFAULT_MAX_UPLOAD_SIZE, r as formatFileSize, t as CONTENT_TYPE_RE } from "./media-C1EIZKh1.mjs";
11
+ import { t as GLOBAL_UPLOAD_ALLOWLIST } from "./media-allowlist-elXJgb_K.mjs";
12
12
  import { ulid } from "ulidx";
13
13
  import * as path from "node:path";
14
14
 
@@ -144,4 +144,4 @@ async function handleMediaUpload(db, storage, input) {
144
144
 
145
145
  //#endregion
146
146
  export { handleMediaUpload };
147
- //# sourceMappingURL=media-upload-BCidR-EY.mjs.map
147
+ //# sourceMappingURL=media-upload-C7_AQJ5v.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"media-upload-BCidR-EY.mjs","names":[],"sources":["../src/api/handlers/media-upload.ts"],"sourcesContent":["/**\n * Programmatic media upload handler (MCP `media_upload` tool).\n *\n * Accepts file bytes as base64 or fetches them from an external URL\n * (SSRF-guarded), then runs the same pipeline as the multipart REST\n * upload route: allowlist + size validation, content-hash deduplication,\n * storage upload, image metadata enrichment, and record creation.\n */\n\nimport * as path from \"node:path\";\n\nimport type { Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { MediaRepository, type MediaItem } from \"../../database/repositories/media.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { enrichImageMetadata } from \"../../media/enrich.js\";\nimport { matchesMimeAllowlist, normalizeMime } from \"../../media/mime.js\";\nimport { SsrfError, ssrfSafeFetch } from \"../../security/ssrf.js\";\nimport type { Storage } from \"../../storage/types.js\";\nimport { decodeBase64Bytes } from \"../../utils/base64.js\";\nimport { computeContentHash } from \"../../utils/hash.js\";\nimport { CONTENT_TYPE_RE, DEFAULT_MAX_UPLOAD_SIZE, formatFileSize } from \"../schemas/media.js\";\nimport type { ApiResult } from \"../types.js\";\nimport { GLOBAL_UPLOAD_ALLOWLIST } from \"./media-allowlist.js\";\n\nexport interface MediaUploadInput {\n\t/** Original filename (e.g. 'logo.png'); the extension is kept on the storage key. */\n\tfilename: string;\n\t/** Base64-encoded file contents. Exactly one of `base64` / `url` must be set. */\n\tbase64?: string;\n\t/** External http(s) URL to fetch the file from. Exactly one of `base64` / `url` must be set. */\n\turl?: string;\n\t/**\n\t * MIME type. Required with `base64`; optional with `url` (falls back to\n\t * the response's Content-Type header).\n\t */\n\tcontentType?: string;\n\t/** Alt text stored on the media record. */\n\talt?: string;\n\tauthorId?: string;\n\t/** Upload size limit in bytes (defaults to DEFAULT_MAX_UPLOAD_SIZE). */\n\tmaxUploadSize?: number;\n}\n\nexport type MediaUploadResult = ApiResult<{\n\titem: MediaItem & { url: string };\n\tdeduplicated?: boolean;\n}>;\n\nfunction fail(code: string, message: string): MediaUploadResult {\n\treturn { success: false, error: { code, message } };\n}\n\n/** Same relative-URL shape the REST media routes return. */\nfunction withUrl(item: MediaItem): MediaItem & { url: string } {\n\treturn { ...item, url: `/_emdash/api/media/file/${item.storageKey}` };\n}\n\n/** Strip parameters from a Content-Type header value (e.g. '; charset=...'). */\nfunction bareMime(headerValue: string): string {\n\treturn (headerValue.split(\";\")[0] ?? \"\").trim();\n}\n\n/**\n * Acquire the file bytes and MIME type from either the base64 payload or\n * the external URL. Returns an error result on any validation failure.\n */\nasync function acquireBytes(\n\tinput: MediaUploadInput,\n\tmaxUploadSize: number,\n): Promise<{ bytes: Uint8Array; mimeType: string } | MediaUploadResult> {\n\tif (input.base64) {\n\t\tif (!input.contentType) {\n\t\t\treturn fail(\"VALIDATION_ERROR\", \"contentType is required when uploading base64 data\");\n\t\t}\n\t\t// Cheap size precheck on the encoded string (decoded size is ~3/4 of\n\t\t// the base64 length) before allocating the decoded buffer.\n\t\tif ((input.base64.length * 3) / 4 > maxUploadSize) {\n\t\t\treturn fail(\n\t\t\t\t\"PAYLOAD_TOO_LARGE\",\n\t\t\t\t`File exceeds maximum size of ${formatFileSize(maxUploadSize)}`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\treturn { bytes: decodeBase64Bytes(input.base64), mimeType: input.contentType };\n\t\t} catch {\n\t\t\treturn fail(\"VALIDATION_ERROR\", \"Invalid base64 data\");\n\t\t}\n\t}\n\n\t// url mode — the caller guarantees exactly one source, so url is set here\n\tconst url = input.url;\n\tif (!url) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Provide exactly one of 'base64' or 'url'\");\n\t}\n\tlet response: Response;\n\ttry {\n\t\tresponse = await ssrfSafeFetch(url, { headers: { accept: \"*/*\" } });\n\t} catch (error) {\n\t\tif (error instanceof SsrfError) {\n\t\t\treturn fail(\"VALIDATION_ERROR\", `URL not allowed: ${error.message}`);\n\t\t}\n\t\treturn fail(\"FETCH_ERROR\", \"Failed to fetch file from URL\");\n\t}\n\tif (!response.ok) {\n\t\treturn fail(\"FETCH_ERROR\", `Failed to fetch file from URL (HTTP ${response.status})`);\n\t}\n\n\tconst contentLength = response.headers.get(\"Content-Length\");\n\tif (contentLength && parseInt(contentLength, 10) > maxUploadSize) {\n\t\treturn fail(\n\t\t\t\"PAYLOAD_TOO_LARGE\",\n\t\t\t`File exceeds maximum size of ${formatFileSize(maxUploadSize)}`,\n\t\t);\n\t}\n\n\tconst mimeType = input.contentType ?? bareMime(response.headers.get(\"Content-Type\") ?? \"\");\n\tif (!mimeType) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Could not determine MIME type — pass contentType explicitly\");\n\t}\n\n\tconst bytes = new Uint8Array(await response.arrayBuffer());\n\treturn { bytes, mimeType };\n}\n\n/**\n * Upload a media file from base64 data or an external URL.\n *\n * Mirrors the REST `POST /_emdash/api/media` route: global MIME allowlist,\n * size limit, content-hash dedupe (returns the existing item with\n * `deduplicated: true`), storage upload with cleanup on failure, and\n * image metadata enrichment (dimensions, blurhash, dominant color).\n */\nexport async function handleMediaUpload(\n\tdb: Kysely<Database>,\n\tstorage: Storage,\n\tinput: MediaUploadInput,\n): Promise<MediaUploadResult> {\n\tif (!input.base64 === !input.url) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Provide exactly one of 'base64' or 'url'\");\n\t}\n\n\tconst rawMax = input.maxUploadSize ?? DEFAULT_MAX_UPLOAD_SIZE;\n\tif (!Number.isFinite(rawMax) || rawMax <= 0) {\n\t\treturn fail(\"CONFIGURATION_ERROR\", \"Invalid maxUploadSize configuration\");\n\t}\n\n\tconst acquired = await acquireBytes(input, rawMax);\n\tif (\"success\" in acquired) return acquired;\n\tconst { bytes } = acquired;\n\n\t// Validate the raw MIME string before normalize/allowlist: normalizeMime\n\t// only strips parameters and matchesMimeAllowlist only checks startsWith,\n\t// so without this a crafted value like \"image/png\\r\\nX-Evil: 1\" would\n\t// reach the storage backend's ContentType header and be echoed by the\n\t// media file serving route.\n\tif (!CONTENT_TYPE_RE.test(acquired.mimeType)) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Invalid content type\");\n\t}\n\tconst mimeType = normalizeMime(acquired.mimeType);\n\n\tif (!matchesMimeAllowlist(mimeType, GLOBAL_UPLOAD_ALLOWLIST)) {\n\t\treturn fail(\"INVALID_TYPE\", \"File type not allowed\");\n\t}\n\tif (bytes.byteLength > rawMax) {\n\t\treturn fail(\"PAYLOAD_TOO_LARGE\", `File exceeds maximum size of ${formatFileSize(rawMax)}`);\n\t}\n\n\ttry {\n\t\tconst contentHash = await computeContentHash(bytes);\n\t\tconst repo = new MediaRepository(db);\n\n\t\tconst existing = await repo.findByContentHash(contentHash);\n\t\tif (existing) {\n\t\t\treturn { success: true, data: { item: withUrl(existing), deduplicated: true } };\n\t\t}\n\n\t\tconst storageKey = `${ulid()}${path.extname(input.filename)}`;\n\t\tawait storage.upload({ key: storageKey, body: bytes, contentType: mimeType });\n\n\t\ttry {\n\t\t\tconst enriched = await enrichImageMetadata(bytes, mimeType);\n\t\t\tconst item = await repo.create({\n\t\t\t\tfilename: input.filename,\n\t\t\t\tmimeType,\n\t\t\t\tsize: bytes.byteLength,\n\t\t\t\twidth: enriched.width,\n\t\t\t\theight: enriched.height,\n\t\t\t\talt: input.alt,\n\t\t\t\tstorageKey,\n\t\t\t\tcontentHash,\n\t\t\t\tblurhash: enriched.blurhash,\n\t\t\t\tdominantColor: enriched.dominantColor,\n\t\t\t\tauthorId: input.authorId,\n\t\t\t});\n\t\t\treturn { success: true, data: { item: withUrl(item) } };\n\t\t} catch (error) {\n\t\t\t// Don't leave an orphaned object in storage when record creation fails\n\t\t\ttry {\n\t\t\t\tawait storage.delete(storageKey);\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup errors\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t} catch {\n\t\treturn fail(\"UPLOAD_ERROR\", \"Upload failed\");\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"media-upload-C7_AQJ5v.mjs","names":[],"sources":["../src/api/handlers/media-upload.ts"],"sourcesContent":["/**\n * Programmatic media upload handler (MCP `media_upload` tool).\n *\n * Accepts file bytes as base64 or fetches them from an external URL\n * (SSRF-guarded), then runs the same pipeline as the multipart REST\n * upload route: allowlist + size validation, content-hash deduplication,\n * storage upload, image metadata enrichment, and record creation.\n */\n\nimport * as path from \"node:path\";\n\nimport type { Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { MediaRepository, type MediaItem } from \"../../database/repositories/media.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { enrichImageMetadata } from \"../../media/enrich.js\";\nimport { matchesMimeAllowlist, normalizeMime } from \"../../media/mime.js\";\nimport { SsrfError, ssrfSafeFetch } from \"../../security/ssrf.js\";\nimport type { Storage } from \"../../storage/types.js\";\nimport { decodeBase64Bytes } from \"../../utils/base64.js\";\nimport { computeContentHash } from \"../../utils/hash.js\";\nimport { CONTENT_TYPE_RE, DEFAULT_MAX_UPLOAD_SIZE, formatFileSize } from \"../schemas/media.js\";\nimport type { ApiResult } from \"../types.js\";\nimport { GLOBAL_UPLOAD_ALLOWLIST } from \"./media-allowlist.js\";\n\nexport interface MediaUploadInput {\n\t/** Original filename (e.g. 'logo.png'); the extension is kept on the storage key. */\n\tfilename: string;\n\t/** Base64-encoded file contents. Exactly one of `base64` / `url` must be set. */\n\tbase64?: string;\n\t/** External http(s) URL to fetch the file from. Exactly one of `base64` / `url` must be set. */\n\turl?: string;\n\t/**\n\t * MIME type. Required with `base64`; optional with `url` (falls back to\n\t * the response's Content-Type header).\n\t */\n\tcontentType?: string;\n\t/** Alt text stored on the media record. */\n\talt?: string;\n\tauthorId?: string;\n\t/** Upload size limit in bytes (defaults to DEFAULT_MAX_UPLOAD_SIZE). */\n\tmaxUploadSize?: number;\n}\n\nexport type MediaUploadResult = ApiResult<{\n\titem: MediaItem & { url: string };\n\tdeduplicated?: boolean;\n}>;\n\nfunction fail(code: string, message: string): MediaUploadResult {\n\treturn { success: false, error: { code, message } };\n}\n\n/** Same relative-URL shape the REST media routes return. */\nfunction withUrl(item: MediaItem): MediaItem & { url: string } {\n\treturn { ...item, url: `/_emdash/api/media/file/${item.storageKey}` };\n}\n\n/** Strip parameters from a Content-Type header value (e.g. '; charset=...'). */\nfunction bareMime(headerValue: string): string {\n\treturn (headerValue.split(\";\")[0] ?? \"\").trim();\n}\n\n/**\n * Acquire the file bytes and MIME type from either the base64 payload or\n * the external URL. Returns an error result on any validation failure.\n */\nasync function acquireBytes(\n\tinput: MediaUploadInput,\n\tmaxUploadSize: number,\n): Promise<{ bytes: Uint8Array; mimeType: string } | MediaUploadResult> {\n\tif (input.base64) {\n\t\tif (!input.contentType) {\n\t\t\treturn fail(\"VALIDATION_ERROR\", \"contentType is required when uploading base64 data\");\n\t\t}\n\t\t// Cheap size precheck on the encoded string (decoded size is ~3/4 of\n\t\t// the base64 length) before allocating the decoded buffer.\n\t\tif ((input.base64.length * 3) / 4 > maxUploadSize) {\n\t\t\treturn fail(\n\t\t\t\t\"PAYLOAD_TOO_LARGE\",\n\t\t\t\t`File exceeds maximum size of ${formatFileSize(maxUploadSize)}`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\treturn { bytes: decodeBase64Bytes(input.base64), mimeType: input.contentType };\n\t\t} catch {\n\t\t\treturn fail(\"VALIDATION_ERROR\", \"Invalid base64 data\");\n\t\t}\n\t}\n\n\t// url mode — the caller guarantees exactly one source, so url is set here\n\tconst url = input.url;\n\tif (!url) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Provide exactly one of 'base64' or 'url'\");\n\t}\n\tlet response: Response;\n\ttry {\n\t\tresponse = await ssrfSafeFetch(url, { headers: { accept: \"*/*\" } });\n\t} catch (error) {\n\t\tif (error instanceof SsrfError) {\n\t\t\treturn fail(\"VALIDATION_ERROR\", `URL not allowed: ${error.message}`);\n\t\t}\n\t\treturn fail(\"FETCH_ERROR\", \"Failed to fetch file from URL\");\n\t}\n\tif (!response.ok) {\n\t\treturn fail(\"FETCH_ERROR\", `Failed to fetch file from URL (HTTP ${response.status})`);\n\t}\n\n\tconst contentLength = response.headers.get(\"Content-Length\");\n\tif (contentLength && parseInt(contentLength, 10) > maxUploadSize) {\n\t\treturn fail(\n\t\t\t\"PAYLOAD_TOO_LARGE\",\n\t\t\t`File exceeds maximum size of ${formatFileSize(maxUploadSize)}`,\n\t\t);\n\t}\n\n\tconst mimeType = input.contentType ?? bareMime(response.headers.get(\"Content-Type\") ?? \"\");\n\tif (!mimeType) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Could not determine MIME type — pass contentType explicitly\");\n\t}\n\n\tconst bytes = new Uint8Array(await response.arrayBuffer());\n\treturn { bytes, mimeType };\n}\n\n/**\n * Upload a media file from base64 data or an external URL.\n *\n * Mirrors the REST `POST /_emdash/api/media` route: global MIME allowlist,\n * size limit, content-hash dedupe (returns the existing item with\n * `deduplicated: true`), storage upload with cleanup on failure, and\n * image metadata enrichment (dimensions, blurhash, dominant color).\n */\nexport async function handleMediaUpload(\n\tdb: Kysely<Database>,\n\tstorage: Storage,\n\tinput: MediaUploadInput,\n): Promise<MediaUploadResult> {\n\tif (!input.base64 === !input.url) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Provide exactly one of 'base64' or 'url'\");\n\t}\n\n\tconst rawMax = input.maxUploadSize ?? DEFAULT_MAX_UPLOAD_SIZE;\n\tif (!Number.isFinite(rawMax) || rawMax <= 0) {\n\t\treturn fail(\"CONFIGURATION_ERROR\", \"Invalid maxUploadSize configuration\");\n\t}\n\n\tconst acquired = await acquireBytes(input, rawMax);\n\tif (\"success\" in acquired) return acquired;\n\tconst { bytes } = acquired;\n\n\t// Validate the raw MIME string before normalize/allowlist: normalizeMime\n\t// only strips parameters and matchesMimeAllowlist only checks startsWith,\n\t// so without this a crafted value like \"image/png\\r\\nX-Evil: 1\" would\n\t// reach the storage backend's ContentType header and be echoed by the\n\t// media file serving route.\n\tif (!CONTENT_TYPE_RE.test(acquired.mimeType)) {\n\t\treturn fail(\"VALIDATION_ERROR\", \"Invalid content type\");\n\t}\n\tconst mimeType = normalizeMime(acquired.mimeType);\n\n\tif (!matchesMimeAllowlist(mimeType, GLOBAL_UPLOAD_ALLOWLIST)) {\n\t\treturn fail(\"INVALID_TYPE\", \"File type not allowed\");\n\t}\n\tif (bytes.byteLength > rawMax) {\n\t\treturn fail(\"PAYLOAD_TOO_LARGE\", `File exceeds maximum size of ${formatFileSize(rawMax)}`);\n\t}\n\n\ttry {\n\t\tconst contentHash = await computeContentHash(bytes);\n\t\tconst repo = new MediaRepository(db);\n\n\t\tconst existing = await repo.findByContentHash(contentHash);\n\t\tif (existing) {\n\t\t\treturn { success: true, data: { item: withUrl(existing), deduplicated: true } };\n\t\t}\n\n\t\tconst storageKey = `${ulid()}${path.extname(input.filename)}`;\n\t\tawait storage.upload({ key: storageKey, body: bytes, contentType: mimeType });\n\n\t\ttry {\n\t\t\tconst enriched = await enrichImageMetadata(bytes, mimeType);\n\t\t\tconst item = await repo.create({\n\t\t\t\tfilename: input.filename,\n\t\t\t\tmimeType,\n\t\t\t\tsize: bytes.byteLength,\n\t\t\t\twidth: enriched.width,\n\t\t\t\theight: enriched.height,\n\t\t\t\talt: input.alt,\n\t\t\t\tstorageKey,\n\t\t\t\tcontentHash,\n\t\t\t\tblurhash: enriched.blurhash,\n\t\t\t\tdominantColor: enriched.dominantColor,\n\t\t\t\tauthorId: input.authorId,\n\t\t\t});\n\t\t\treturn { success: true, data: { item: withUrl(item) } };\n\t\t} catch (error) {\n\t\t\t// Don't leave an orphaned object in storage when record creation fails\n\t\t\ttry {\n\t\t\t\tawait storage.delete(storageKey);\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup errors\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t} catch {\n\t\treturn fail(\"UPLOAD_ERROR\", \"Upload failed\");\n\t}\n}\n"],"mappings":"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"}
@@ -16,11 +16,28 @@ const TRAILING_SLASH_RE = /\/$/;
16
16
  const ABSOLUTE_URL_RE = /^https?:\/\//i;
17
17
  function buildSeoImageUrl(imageRef, siteUrl) {
18
18
  if (ABSOLUTE_URL_RE.test(imageRef)) return imageRef;
19
+ if (imageRef.startsWith("//")) return imageRef;
19
20
  if (imageRef.startsWith("/")) return siteUrl ? `${siteUrl.replace(TRAILING_SLASH_RE, "")}${imageRef}` : imageRef;
20
21
  const mediaPath = `/_emdash/api/media/file/${imageRef}`;
21
22
  return siteUrl ? `${siteUrl.replace(TRAILING_SLASH_RE, "")}${mediaPath}` : mediaPath;
22
23
  }
24
+ /**
25
+ * Resolve a stored SEO canonical value to a URL.
26
+ *
27
+ * The SEO panel accepts absolute URLs, root-relative paths, and bare
28
+ * relative paths. Relative paths are joined with `siteUrl` (adding a
29
+ * leading slash when missing, so we never produce
30
+ * `https://example.composts/x`). Without a `siteUrl` the value is
31
+ * returned as-is. Absolute output matters here: the resolved value feeds
32
+ * `<link rel="canonical">` and `og:url`, both of which search engines and
33
+ * scrapers expect fully qualified.
34
+ */
35
+ function resolveSeoCanonicalUrl(canonical, siteUrl) {
36
+ if (!siteUrl || ABSOLUTE_URL_RE.test(canonical) || canonical.startsWith("//")) return canonical;
37
+ const path = canonical.startsWith("/") ? canonical : `/${canonical}`;
38
+ return `${siteUrl.replace(TRAILING_SLASH_RE, "")}${path}`;
39
+ }
23
40
 
24
41
  //#endregion
25
- export { buildSeoImageUrl as t };
26
- //# sourceMappingURL=media-url-DHoPr0hq.mjs.map
42
+ export { resolveSeoCanonicalUrl as n, buildSeoImageUrl as t };
43
+ //# sourceMappingURL=media-url-8dVl1loq.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-url-8dVl1loq.mjs","names":[],"sources":["../src/seo/media-url.ts"],"sourcesContent":["/**\n * Resolve a stored SEO image reference to a URL.\n *\n * The CMS SEO panel stores `seo_image` in one of these shapes:\n * - an absolute URL (`https://...`) — returned as-is;\n * - a root-relative path that already includes the media API prefix\n * (`/_emdash/api/media/file/01KS....webp`) — prefixed with `siteUrl`;\n * - a bare media id (`01KS...`) — expanded to the media API path, then\n * prefixed with `siteUrl`.\n *\n * Shared by the SEO meta builder (`og:image`) and the sitemap route\n * (`<image:image>`) so both resolve image references identically.\n */\nconst TRAILING_SLASH_RE = /\\/$/;\nconst ABSOLUTE_URL_RE = /^https?:\\/\\//i;\n\nexport function buildSeoImageUrl(imageRef: string, siteUrl?: string): string {\n\t// Already absolute — use as-is.\n\tif (ABSOLUTE_URL_RE.test(imageRef)) {\n\t\treturn imageRef;\n\t}\n\n\t// `//host/path` is protocol-relative — already qualified, not a path\n\t// to prefix with the site URL.\n\tif (imageRef.startsWith(\"//\")) {\n\t\treturn imageRef;\n\t}\n\n\t// Root-relative path (already includes the media API prefix). Without\n\t// this branch we'd re-prefix and produce a doubled path that 404s.\n\tif (imageRef.startsWith(\"/\")) {\n\t\treturn siteUrl ? `${siteUrl.replace(TRAILING_SLASH_RE, \"\")}${imageRef}` : imageRef;\n\t}\n\n\t// Bare media id — build the full media API path.\n\tconst mediaPath = `/_emdash/api/media/file/${imageRef}`;\n\treturn siteUrl ? `${siteUrl.replace(TRAILING_SLASH_RE, \"\")}${mediaPath}` : mediaPath;\n}\n\n/**\n * Resolve a stored SEO canonical value to a URL.\n *\n * The SEO panel accepts absolute URLs, root-relative paths, and bare\n * relative paths. Relative paths are joined with `siteUrl` (adding a\n * leading slash when missing, so we never produce\n * `https://example.composts/x`). Without a `siteUrl` the value is\n * returned as-is. Absolute output matters here: the resolved value feeds\n * `<link rel=\"canonical\">` and `og:url`, both of which search engines and\n * scrapers expect fully qualified.\n */\nexport function resolveSeoCanonicalUrl(canonical: string, siteUrl?: string): string {\n\t// `//host/path` is protocol-relative — already qualified, not a path.\n\tif (!siteUrl || ABSOLUTE_URL_RE.test(canonical) || canonical.startsWith(\"//\")) {\n\t\treturn canonical;\n\t}\n\tconst path = canonical.startsWith(\"/\") ? canonical : `/${canonical}`;\n\treturn `${siteUrl.replace(TRAILING_SLASH_RE, \"\")}${path}`;\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;AAExB,SAAgB,iBAAiB,UAAkB,SAA0B;AAE5E,KAAI,gBAAgB,KAAK,SAAS,CACjC,QAAO;AAKR,KAAI,SAAS,WAAW,KAAK,CAC5B,QAAO;AAKR,KAAI,SAAS,WAAW,IAAI,CAC3B,QAAO,UAAU,GAAG,QAAQ,QAAQ,mBAAmB,GAAG,GAAG,aAAa;CAI3E,MAAM,YAAY,2BAA2B;AAC7C,QAAO,UAAU,GAAG,QAAQ,QAAQ,mBAAmB,GAAG,GAAG,cAAc;;;;;;;;;;;;;AAc5E,SAAgB,uBAAuB,WAAmB,SAA0B;AAEnF,KAAI,CAAC,WAAW,gBAAgB,KAAK,UAAU,IAAI,UAAU,WAAW,KAAK,CAC5E,QAAO;CAER,MAAM,OAAO,UAAU,WAAW,IAAI,GAAG,YAAY,IAAI;AACzD,QAAO,GAAG,QAAQ,QAAQ,mBAAmB,GAAG,GAAG"}
@@ -1,16 +1,16 @@
1
- import { c as __exportAll } from "./runner-BLIDKpmA.mjs";
1
+ import { c as __exportAll } from "./runner-nEzvnogG.mjs";
2
2
  import { t as validateIdentifier } from "./validate-BpwoDOgt.mjs";
3
- import { p as tableExists, s as isPostgres } from "./dialect-helpers-BSbfaO3F.mjs";
3
+ import { g as tableExists, s as isPostgres } from "./dialect-helpers-BcQvkHgn.mjs";
4
4
  import { getRequestContext } from "./request-context.mjs";
5
5
  import { i as InvalidCursorError } from "./types-CQPWhPxE.mjs";
6
6
  import { t as MediaRepository } from "./media-BBm8Wg3f.mjs";
7
7
  import { t as withTransaction } from "./transaction-0KOpOyMu.mjs";
8
- import { a as continueMediaUsageActivation, n as MediaUsageActivationVersionMismatchError, s as getMediaUsageActivationStatus, t as MEDIA_USAGE_ACTIVATION_RUNTIME_GENERATION } from "./activation-K0kGBWuJ.mjs";
9
- import { n as collectionDeletionCurrentTimestamp, r as deleteActivatedMediaUsageCollection, t as MediaUsageCollectionDeletionRepository } from "./collection-deletion-Bj07NHbj.mjs";
10
- import { _ as buildContentMediaUsageFieldFingerprint, b as jsonTextValues, d as refreshContentMediaUsageForWorkBatch, n as CONTENT_MEDIA_USAGE_COLLECTION_SCOPE, r as contentRefreshKey, t as CONTENT_MEDIA_USAGE_ADAPTER_ID, v as loadContentMediaUsageFields, x as CONTENT_SOURCE_SCHEMA_VERSION, y as MediaUsageRepository } from "./content-refresh-Bwp-8yGy.mjs";
11
- import { t as MediaUsageWorkRepository } from "./media-usage-work-D6D9sMCA.mjs";
12
- import { n as repairContentMediaUsageCollection, t as repairContentMediaUsageAll } from "./content-repair-Czdp7jz5.mjs";
13
- import { t as ErrorCode } from "./errors-DsVoDUjJ.mjs";
8
+ import { a as continueMediaUsageActivation, n as MediaUsageActivationVersionMismatchError, s as getMediaUsageActivationStatus, t as MEDIA_USAGE_ACTIVATION_RUNTIME_GENERATION } from "./activation-DyNTe_Tl.mjs";
9
+ import { n as collectionDeletionCurrentTimestamp, r as deleteActivatedMediaUsageCollection, t as MediaUsageCollectionDeletionRepository } from "./collection-deletion-BCwaWTDw.mjs";
10
+ import { _ as buildContentMediaUsageFieldFingerprint, b as jsonTextValues, d as refreshContentMediaUsageForWorkBatch, n as CONTENT_MEDIA_USAGE_COLLECTION_SCOPE, r as contentRefreshKey, t as CONTENT_MEDIA_USAGE_ADAPTER_ID, v as loadContentMediaUsageFields, x as CONTENT_SOURCE_SCHEMA_VERSION, y as MediaUsageRepository } from "./content-refresh-GTMyi2Xy.mjs";
11
+ import { t as MediaUsageWorkRepository } from "./media-usage-work-C5B1zT1c.mjs";
12
+ import { n as repairContentMediaUsageCollection, t as repairContentMediaUsageAll } from "./content-repair-CIMt5C0U.mjs";
13
+ import { t as ErrorCode } from "./errors-DvMdNrgf.mjs";
14
14
  import { sql } from "kysely";
15
15
  import { ulid } from "ulidx";
16
16
 
@@ -1830,4 +1830,4 @@ function normalizeMediaUsageReferenceType(referenceType) {
1830
1830
 
1831
1831
  //#endregion
1832
1832
  export { handleMediaUsageSummaries as a, handleMediaUsageRepair as i, handleMediaUsageProgress as n, media_usage_exports as o, handleMediaUsageProgressAdvance as r, processMediaUsageWorkAfterWrite as s, handleMediaUsageDetails as t };
1833
- //# sourceMappingURL=media-usage-CdY5jhSR.mjs.map
1833
+ //# sourceMappingURL=media-usage-C1EswMTq.mjs.map