emdash 0.18.0 → 0.19.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 (408) hide show
  1. package/dist/api/route-utils.d.mts +2 -2
  2. package/dist/api/route-utils.mjs +14 -14
  3. package/dist/api/schemas/index.d.mts +2 -2
  4. package/dist/api/schemas/index.mjs +3 -3
  5. package/dist/{api-Cs7DAACP.mjs → api-BZ6bhjYs.mjs} +88 -16
  6. package/dist/api-BZ6bhjYs.mjs.map +1 -0
  7. package/dist/{apply-BWMV4Zmw.mjs → apply-hQkKKBCf.mjs} +23 -23
  8. package/dist/apply-hQkKKBCf.mjs.map +1 -0
  9. package/dist/astro/index.d.mts +8 -8
  10. package/dist/astro/index.d.mts.map +1 -1
  11. package/dist/astro/index.mjs +113 -23
  12. package/dist/astro/index.mjs.map +1 -1
  13. package/dist/astro/middleware/auth.d.mts +7 -7
  14. package/dist/astro/middleware/auth.mjs +2 -2
  15. package/dist/astro/middleware/redirect.mjs +4 -4
  16. package/dist/astro/middleware/request-context.mjs +2 -2
  17. package/dist/astro/middleware.d.mts +26 -4
  18. package/dist/astro/middleware.d.mts.map +1 -1
  19. package/dist/astro/middleware.mjs +205 -173
  20. package/dist/astro/middleware.mjs.map +1 -1
  21. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -5
  22. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -5
  23. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +2 -2
  24. package/dist/astro/routes/api/admin/api-tokens/index.mjs +3 -3
  25. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +5 -5
  26. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -8
  27. package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -8
  28. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -8
  29. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +12 -12
  30. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +12 -12
  31. package/dist/astro/routes/api/admin/bylines/index.mjs +12 -12
  32. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +11 -11
  33. package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
  34. package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
  35. package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
  36. package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
  37. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
  38. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
  39. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  40. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  41. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +31 -31
  42. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +31 -31
  43. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +30 -30
  44. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +30 -30
  45. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +30 -30
  46. package/dist/astro/routes/api/admin/plugins/index.mjs +30 -30
  47. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  48. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +30 -30
  49. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +30 -30
  50. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +30 -30
  51. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +30 -30
  52. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +31 -31
  53. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +30 -30
  54. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +31 -31
  55. package/dist/astro/routes/api/admin/plugins/updates.mjs +30 -30
  56. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +30 -30
  57. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  58. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +30 -30
  59. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
  60. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  61. package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
  62. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
  63. package/dist/astro/routes/api/admin/users/index.mjs +5 -5
  64. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  65. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  66. package/dist/astro/routes/api/auth/invite/complete.mjs +6 -6
  67. package/dist/astro/routes/api/auth/invite/index.mjs +7 -7
  68. package/dist/astro/routes/api/auth/invite/register-options.mjs +6 -6
  69. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  70. package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -8
  71. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  72. package/dist/astro/routes/api/auth/me.mjs +6 -6
  73. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +2 -2
  74. package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -5
  75. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  76. package/dist/astro/routes/api/auth/passkey/options.mjs +7 -7
  77. package/dist/astro/routes/api/auth/passkey/register/options.mjs +6 -6
  78. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +6 -6
  79. package/dist/astro/routes/api/auth/passkey/verify.mjs +6 -6
  80. package/dist/astro/routes/api/auth/signup/complete.mjs +6 -6
  81. package/dist/astro/routes/api/auth/signup/request.mjs +8 -8
  82. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  83. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
  84. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  85. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +6 -5
  86. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  87. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  88. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  89. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +8 -8
  90. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +9 -8
  91. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  92. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  93. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  94. package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
  95. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +12 -10
  96. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  97. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +11 -11
  98. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  99. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +6 -5
  100. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  101. package/dist/astro/routes/api/content/_collection_/_id_.mjs +9 -8
  102. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  103. package/dist/astro/routes/api/content/_collection_/authors.d.mts +8 -0
  104. package/dist/astro/routes/api/content/_collection_/authors.d.mts.map +1 -0
  105. package/dist/astro/routes/api/content/_collection_/authors.mjs +19 -0
  106. package/dist/astro/routes/api/content/_collection_/authors.mjs.map +1 -0
  107. package/dist/astro/routes/api/content/_collection_/index.mjs +6 -6
  108. package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -6
  109. package/dist/astro/routes/api/dashboard.mjs +7 -7
  110. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  111. package/dist/astro/routes/api/import/probe.d.mts +2 -2
  112. package/dist/astro/routes/api/import/probe.mjs +6 -6
  113. package/dist/astro/routes/api/import/wordpress/analyze.mjs +4 -4
  114. package/dist/astro/routes/api/import/wordpress/execute.d.mts +7 -7
  115. package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -9
  116. package/dist/astro/routes/api/import/wordpress/media.mjs +6 -6
  117. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
  118. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +8 -8
  119. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +6 -6
  120. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +9 -9
  121. package/dist/astro/routes/api/manifest.mjs +3 -3
  122. package/dist/astro/routes/api/mcp.mjs +28 -28
  123. package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -6
  124. package/dist/astro/routes/api/media/_id_.mjs +6 -6
  125. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  126. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  127. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  128. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  129. package/dist/astro/routes/api/media/upload-url.mjs +6 -6
  130. package/dist/astro/routes/api/media.mjs +7 -7
  131. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +7 -7
  132. package/dist/astro/routes/api/menus/_name_/items.mjs +7 -7
  133. package/dist/astro/routes/api/menus/_name_/reorder.mjs +7 -7
  134. package/dist/astro/routes/api/menus/_name_/translations.mjs +7 -7
  135. package/dist/astro/routes/api/menus/_name_.mjs +7 -7
  136. package/dist/astro/routes/api/menus/index.mjs +7 -7
  137. package/dist/astro/routes/api/oauth/authorize.mjs +1 -1
  138. package/dist/astro/routes/api/oauth/device/authorize.mjs +4 -4
  139. package/dist/astro/routes/api/oauth/device/code.mjs +5 -5
  140. package/dist/astro/routes/api/oauth/device/token.mjs +5 -5
  141. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  142. package/dist/astro/routes/api/oauth/token/refresh.mjs +4 -4
  143. package/dist/astro/routes/api/oauth/token/revoke.mjs +4 -4
  144. package/dist/astro/routes/api/oauth/token.mjs +4 -4
  145. package/dist/astro/routes/api/openapi.json.mjs +17 -3
  146. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  147. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
  148. package/dist/astro/routes/api/redirects/404s/index.mjs +9 -9
  149. package/dist/astro/routes/api/redirects/404s/summary.mjs +9 -9
  150. package/dist/astro/routes/api/redirects/_id_.mjs +10 -10
  151. package/dist/astro/routes/api/redirects/index.mjs +10 -10
  152. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  153. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  154. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +30 -30
  155. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +30 -30
  156. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +30 -30
  157. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +30 -30
  158. package/dist/astro/routes/api/schema/collections/index.mjs +30 -30
  159. package/dist/astro/routes/api/schema/index.mjs +6 -6
  160. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +30 -30
  161. package/dist/astro/routes/api/schema/orphans/index.mjs +30 -30
  162. package/dist/astro/routes/api/search/enable.mjs +9 -9
  163. package/dist/astro/routes/api/search/index.mjs +8 -8
  164. package/dist/astro/routes/api/search/rebuild.mjs +9 -9
  165. package/dist/astro/routes/api/search/stats.mjs +6 -6
  166. package/dist/astro/routes/api/search/suggest.mjs +8 -8
  167. package/dist/astro/routes/api/sections/_slug_.mjs +8 -8
  168. package/dist/astro/routes/api/sections/index.mjs +8 -8
  169. package/dist/astro/routes/api/settings/email.mjs +5 -5
  170. package/dist/astro/routes/api/settings.mjs +12 -12
  171. package/dist/astro/routes/api/setup/admin-verify.mjs +6 -6
  172. package/dist/astro/routes/api/setup/admin.mjs +6 -6
  173. package/dist/astro/routes/api/setup/dev-bypass.mjs +18 -18
  174. package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
  175. package/dist/astro/routes/api/setup/index.mjs +21 -21
  176. package/dist/astro/routes/api/setup/status.mjs +3 -3
  177. package/dist/astro/routes/api/snapshot.mjs +5 -5
  178. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +11 -11
  179. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -11
  180. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -11
  181. package/dist/astro/routes/api/taxonomies/index.mjs +11 -11
  182. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  183. package/dist/astro/routes/api/typegen.mjs +5 -5
  184. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  185. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -6
  186. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +8 -8
  187. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +8 -8
  188. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  189. package/dist/astro/routes/api/widget-areas/index.mjs +8 -8
  190. package/dist/astro/routes/api/widget-components.mjs +2 -2
  191. package/dist/astro/routes/robots.txt.mjs +6 -6
  192. package/dist/astro/routes/sitemap-_collection_.xml.mjs +6 -6
  193. package/dist/astro/routes/sitemap.xml.mjs +6 -6
  194. package/dist/astro/types.d.mts +15 -8
  195. package/dist/astro/types.d.mts.map +1 -1
  196. package/dist/{authorize-CotM4Yiu.mjs → authorize-C_8t2KGa.mjs} +2 -2
  197. package/dist/{authorize-CotM4Yiu.mjs.map → authorize-C_8t2KGa.mjs.map} +1 -1
  198. package/dist/{byline-CWQ9aSoz.mjs → byline-DUx48sJp.mjs} +6 -6
  199. package/dist/{byline-CWQ9aSoz.mjs.map → byline-DUx48sJp.mjs.map} +1 -1
  200. package/dist/{byline-fields-Dr-xcb6S.mjs → byline-fields-51kg6Vuv.mjs} +3 -3
  201. package/dist/{byline-fields-Dr-xcb6S.mjs.map → byline-fields-51kg6Vuv.mjs.map} +1 -1
  202. package/dist/{byline-fields-DC3Wkk-U.mjs → byline-fields-C_OsR-KF.mjs} +2 -2
  203. package/dist/{byline-fields-DC3Wkk-U.mjs.map → byline-fields-C_OsR-KF.mjs.map} +1 -1
  204. package/dist/{byline-fields-BNy7Ng1U.d.mts → byline-fields-DYXKDuNX.d.mts} +26 -2
  205. package/dist/byline-fields-DYXKDuNX.d.mts.map +1 -0
  206. package/dist/{byline-registry-CxK5g559.mjs → byline-registry-CWP7I71B.mjs} +3 -3
  207. package/dist/{byline-registry-CxK5g559.mjs.map → byline-registry-CWP7I71B.mjs.map} +1 -1
  208. package/dist/{bylines-LJMgENMI.mjs → bylines-Cx5n-WqP.mjs} +3 -3
  209. package/dist/{bylines-LJMgENMI.mjs.map → bylines-Cx5n-WqP.mjs.map} +1 -1
  210. package/dist/{bylines-BJSva1Un.mjs → bylines-wurS258E.mjs} +50 -6
  211. package/dist/{bylines-BJSva1Un.mjs.map → bylines-wurS258E.mjs.map} +1 -1
  212. package/dist/{cache-lZL7SgVb.mjs → cache-B_HzASVT.mjs} +3 -3
  213. package/dist/{cache-lZL7SgVb.mjs.map → cache-B_HzASVT.mjs.map} +1 -1
  214. package/dist/{chunks-BU-vP9Dh.mjs → chunks-BerYVuve.mjs} +2 -2
  215. package/dist/{chunks-BU-vP9Dh.mjs.map → chunks-BerYVuve.mjs.map} +1 -1
  216. package/dist/cli/index.mjs +40 -27
  217. package/dist/cli/index.mjs.map +1 -1
  218. package/dist/client/cf-access.d.mts +1 -1
  219. package/dist/client/index.d.mts +1 -1
  220. package/dist/{comment-C4jVbCM8.mjs → comment-sqQxNpN3.mjs} +2 -2
  221. package/dist/{comment-C4jVbCM8.mjs.map → comment-sqQxNpN3.mjs.map} +1 -1
  222. package/dist/{comments-BTAbC0Ek.mjs → comments-CJ0RZsYR.mjs} +3 -3
  223. package/dist/{comments-BTAbC0Ek.mjs.map → comments-CJ0RZsYR.mjs.map} +1 -1
  224. package/dist/{content-CyqOmOzm.mjs → content-BIlVx-RX.mjs} +132 -43
  225. package/dist/content-BIlVx-RX.mjs.map +1 -0
  226. package/dist/{context-DZ7bEh5-.mjs → context-GG52SPgh.mjs} +10 -10
  227. package/dist/{context-DZ7bEh5-.mjs.map → context-GG52SPgh.mjs.map} +1 -1
  228. package/dist/{cron-DZovZUnC.mjs → cron-BJ2ClIlj.mjs} +4 -3
  229. package/dist/cron-BJ2ClIlj.mjs.map +1 -0
  230. package/dist/{dashboard-B5WQpNTP.mjs → dashboard-2JgAMWxK.mjs} +4 -4
  231. package/dist/{dashboard-B5WQpNTP.mjs.map → dashboard-2JgAMWxK.mjs.map} +1 -1
  232. package/dist/db/index.d.mts +2 -2
  233. package/dist/db/index.mjs +1 -1
  234. package/dist/{device-flow-ptLrVINd.mjs → device-flow-s6_q3T7A.mjs} +2 -2
  235. package/dist/{device-flow-ptLrVINd.mjs.map → device-flow-s6_q3T7A.mjs.map} +1 -1
  236. package/dist/{error-DJOsMVSt.mjs → error-RwM4dD35.mjs} +2 -2
  237. package/dist/{error-DJOsMVSt.mjs.map → error-RwM4dD35.mjs.map} +1 -1
  238. package/dist/{fts-manager-DR1ERA0c.mjs → fts-manager-1RgHmopc.mjs} +2 -2
  239. package/dist/{fts-manager-DR1ERA0c.mjs.map → fts-manager-1RgHmopc.mjs.map} +1 -1
  240. package/dist/{index-D60_SzHG.d.mts → index-BpYeJO1E.d.mts} +2 -2
  241. package/dist/{index-D60_SzHG.d.mts.map → index-BpYeJO1E.d.mts.map} +1 -1
  242. package/dist/{index-CjKdMZ3U.d.mts → index-FfiTQJq2.d.mts} +199 -17
  243. package/dist/index-FfiTQJq2.d.mts.map +1 -0
  244. package/dist/index.d.mts +9 -9
  245. package/dist/index.mjs +43 -43
  246. package/dist/{load-6ZrRhepW.mjs → load-B84ohfBk.mjs} +2 -2
  247. package/dist/{load-6ZrRhepW.mjs.map → load-B84ohfBk.mjs.map} +1 -1
  248. package/dist/{loader-Dyx8dhFV.mjs → loader-CpZKpFz0.mjs} +32 -30
  249. package/dist/loader-CpZKpFz0.mjs.map +1 -0
  250. package/dist/media/index.mjs +1 -1
  251. package/dist/media/local-runtime.d.mts +7 -7
  252. package/dist/media/local-runtime.mjs +6 -6
  253. package/dist/{media-C-oovGCG.mjs → media-JOf3pNkw.mjs} +2 -2
  254. package/dist/{media-C-oovGCG.mjs.map → media-JOf3pNkw.mjs.map} +1 -1
  255. package/dist/{menus-DugoYwTX.mjs → menus-DX4_E01q.mjs} +3 -3
  256. package/dist/{menus-DugoYwTX.mjs.map → menus-DX4_E01q.mjs.map} +1 -1
  257. package/dist/{menus-BKkxXCmd.mjs → menus-Dp9xporj.mjs} +86 -9
  258. package/dist/menus-Dp9xporj.mjs.map +1 -0
  259. package/dist/{normalize-DVV8nbrL.mjs → normalize-CK5o04zr.mjs} +2 -2
  260. package/dist/{normalize-DVV8nbrL.mjs.map → normalize-CK5o04zr.mjs.map} +1 -1
  261. package/dist/{oauth-authorization-DvBAL75d.mjs → oauth-authorization-1aPAYjiC.mjs} +2 -2
  262. package/dist/{oauth-authorization-DvBAL75d.mjs.map → oauth-authorization-1aPAYjiC.mjs.map} +1 -1
  263. package/dist/{options-BL4X94qY.mjs → options-BPCVnesz.mjs} +1 -1
  264. package/dist/{options-BL4X94qY.mjs.map → options-BPCVnesz.mjs.map} +1 -1
  265. package/dist/{options-tb7DJROi.d.mts → options-D4MnavW_.d.mts} +3 -3
  266. package/dist/{options-tb7DJROi.d.mts.map → options-D4MnavW_.d.mts.map} +1 -1
  267. package/dist/{parse-BBkFmLVr.mjs → parse-CrGndy1A.mjs} +2 -2
  268. package/dist/{parse-BBkFmLVr.mjs.map → parse-CrGndy1A.mjs.map} +1 -1
  269. package/dist/{patterns-CqG5Ya3i.mjs → patterns-p-RBdTbM.mjs} +1 -1
  270. package/dist/{patterns-CqG5Ya3i.mjs.map → patterns-p-RBdTbM.mjs.map} +1 -1
  271. package/dist/plugin-utils.d.mts +7 -7
  272. package/dist/plugins/adapt-sandbox-entry.d.mts +7 -7
  273. package/dist/{query-Ctlq1aOk.mjs → query-BFQ029Ts.mjs} +21 -15
  274. package/dist/query-BFQ029Ts.mjs.map +1 -0
  275. package/dist/{rate-limit-CH6W6ikK.mjs → rate-limit-ClFFUga6.mjs} +2 -2
  276. package/dist/{rate-limit-CH6W6ikK.mjs.map → rate-limit-ClFFUga6.mjs.map} +1 -1
  277. package/dist/{redirect-C6tJA7tk.mjs → redirect-CRWIt8Zj.mjs} +3 -3
  278. package/dist/{redirect-C6tJA7tk.mjs.map → redirect-CRWIt8Zj.mjs.map} +1 -1
  279. package/dist/{redirects-C0L9JUk4.mjs → redirects-DEygMrRO.mjs} +25 -3
  280. package/dist/redirects-DEygMrRO.mjs.map +1 -0
  281. package/dist/{redirects-CacE9eQa.mjs → redirects-OIu6vQ2i.mjs} +5 -5
  282. package/dist/{redirects-CacE9eQa.mjs.map → redirects-OIu6vQ2i.mjs.map} +1 -1
  283. package/dist/{registry-CIDxZbhh.mjs → registry-brYh-rAT.mjs} +6 -6
  284. package/dist/{registry-CIDxZbhh.mjs.map → registry-brYh-rAT.mjs.map} +1 -1
  285. package/dist/{request-cache-BYMs-BGX.mjs → request-cache-D32LpnmI.mjs} +1 -1
  286. package/dist/{request-cache-BYMs-BGX.mjs.map → request-cache-D32LpnmI.mjs.map} +1 -1
  287. package/dist/{runner-pt6Wl-l-.mjs → runner--4wMWwKM.mjs} +217 -166
  288. package/dist/runner--4wMWwKM.mjs.map +1 -0
  289. package/dist/{runner-DM1yR5qd.d.mts → runner-BcRuXq_h.d.mts} +2 -2
  290. package/dist/{runner-DM1yR5qd.d.mts.map → runner-BcRuXq_h.d.mts.map} +1 -1
  291. package/dist/runtime.d.mts +7 -7
  292. package/dist/runtime.mjs +2 -2
  293. package/dist/{schema-B4tk0HAG.mjs → schema-CS7Eg5gh.mjs} +5 -5
  294. package/dist/{schema-B4tk0HAG.mjs.map → schema-CS7Eg5gh.mjs.map} +1 -1
  295. package/dist/{search-f-fNfwab.mjs → search-o-aQzHI1.mjs} +4 -4
  296. package/dist/{search-f-fNfwab.mjs.map → search-o-aQzHI1.mjs.map} +1 -1
  297. package/dist/{secrets-YYbTgB1w.mjs → secrets-C_ZtRos3.mjs} +2 -2
  298. package/dist/{secrets-YYbTgB1w.mjs.map → secrets-C_ZtRos3.mjs.map} +1 -1
  299. package/dist/{sections-biElLfT9.mjs → sections-DhsZ0ns9.mjs} +3 -3
  300. package/dist/{sections-biElLfT9.mjs.map → sections-DhsZ0ns9.mjs.map} +1 -1
  301. package/dist/seed/index.d.mts +2 -2
  302. package/dist/seed/index.mjs +16 -16
  303. package/dist/seo/index.d.mts +1 -1
  304. package/dist/{seo-BR39kvTF.mjs → seo-B5e6y9Wk.mjs} +2 -2
  305. package/dist/{seo-BR39kvTF.mjs.map → seo-B5e6y9Wk.mjs.map} +1 -1
  306. package/dist/{service-BhR2acnc.mjs → service-DAxg8RPR.mjs} +2 -2
  307. package/dist/{service-BhR2acnc.mjs.map → service-DAxg8RPR.mjs.map} +1 -1
  308. package/dist/{settings-b5zW1R1T.mjs → settings-B1p-gPUK.mjs} +5 -5
  309. package/dist/{settings-b5zW1R1T.mjs.map → settings-B1p-gPUK.mjs.map} +1 -1
  310. package/dist/{settings-D_NJvjgN.mjs → settings-DIsbHTRE.mjs} +3 -3
  311. package/dist/{settings-D_NJvjgN.mjs.map → settings-DIsbHTRE.mjs.map} +1 -1
  312. package/dist/{setup-complete-VoEZfasi.mjs → setup-complete-Yuv78yua.mjs} +2 -2
  313. package/dist/{setup-complete-VoEZfasi.mjs.map → setup-complete-Yuv78yua.mjs.map} +1 -1
  314. package/dist/{site-url-Cm8-sJy7.mjs → site-url-mEVmwIFi.mjs} +2 -2
  315. package/dist/{site-url-Cm8-sJy7.mjs.map → site-url-mEVmwIFi.mjs.map} +1 -1
  316. package/dist/{taxonomies-Crtzy4MT.mjs → taxonomies-BEW7S5AI.mjs} +7 -6
  317. package/dist/taxonomies-BEW7S5AI.mjs.map +1 -0
  318. package/dist/{taxonomies-Mhn9rjTQ.mjs → taxonomies-UusDXv3C.mjs} +4 -4
  319. package/dist/{taxonomies-Mhn9rjTQ.mjs.map → taxonomies-UusDXv3C.mjs.map} +1 -1
  320. package/dist/{taxonomy-DTZrIQpi.mjs → taxonomy-CdllE4oq.mjs} +3 -3
  321. package/dist/{taxonomy-DTZrIQpi.mjs.map → taxonomy-CdllE4oq.mjs.map} +1 -1
  322. package/dist/{transaction-NQj4VJ7Z.mjs → transaction-x2tJQ-A1.mjs} +1 -1
  323. package/dist/{transaction-NQj4VJ7Z.mjs.map → transaction-x2tJQ-A1.mjs.map} +1 -1
  324. package/dist/{transport-OnMNbsIA.d.mts → transport-BwQeeY2p.d.mts} +1 -1
  325. package/dist/{transport-OnMNbsIA.d.mts.map → transport-BwQeeY2p.d.mts.map} +1 -1
  326. package/dist/{types-K3MDsxpy.mjs → types-BXSUSAjt.mjs} +16 -3
  327. package/dist/{types-K3MDsxpy.mjs.map → types-BXSUSAjt.mjs.map} +1 -1
  328. package/dist/{types-D8bhH891.mjs → types-DZk_y-MU.mjs} +1 -1
  329. package/dist/{types-D8bhH891.mjs.map → types-DZk_y-MU.mjs.map} +1 -1
  330. package/dist/{types-DawhLFwy.d.mts → types-OT_Es5mp.d.mts} +26 -1
  331. package/dist/{types-DawhLFwy.d.mts.map → types-OT_Es5mp.d.mts.map} +1 -1
  332. package/dist/{types-i8_uzhMD.d.mts → types-WVmpZBJV.d.mts} +18 -3
  333. package/dist/types-WVmpZBJV.d.mts.map +1 -0
  334. package/dist/{user-DzEUl5zA.mjs → user-C0um7wrg.mjs} +18 -2
  335. package/dist/user-C0um7wrg.mjs.map +1 -0
  336. package/dist/{validate-Dy6nkNls.d.mts → validate-BPAHUSge.d.mts} +10 -2
  337. package/dist/validate-BPAHUSge.d.mts.map +1 -0
  338. package/dist/{validate-JCXcsqiY.mjs → validate-ZP9Dvg0P.mjs} +6 -3
  339. package/dist/validate-ZP9Dvg0P.mjs.map +1 -0
  340. package/dist/{validation-Bq-VyKJg.mjs → validation-CE5i4q0c.mjs} +5 -5
  341. package/dist/{validation-Bq-VyKJg.mjs.map → validation-CE5i4q0c.mjs.map} +1 -1
  342. package/dist/version-Dw0JXu45.mjs +7 -0
  343. package/dist/{version-CnS-Cr8A.mjs.map → version-Dw0JXu45.mjs.map} +1 -1
  344. package/dist/{widgets-Bap1eS1X.mjs → widgets-ClEnYQCH.mjs} +2 -2
  345. package/dist/{widgets-Bap1eS1X.mjs.map → widgets-ClEnYQCH.mjs.map} +1 -1
  346. package/dist/{zod-generator-BSDpkqSH.mjs → zod-generator-Djo_VHCt.mjs} +2 -2
  347. package/dist/{zod-generator-BSDpkqSH.mjs.map → zod-generator-Djo_VHCt.mjs.map} +1 -1
  348. package/package.json +5 -5
  349. package/src/api/handlers/content.ts +107 -8
  350. package/src/api/handlers/index.ts +2 -0
  351. package/src/api/openapi/document.ts +25 -0
  352. package/src/api/schemas/content.ts +33 -0
  353. package/src/astro/integration/index.ts +98 -0
  354. package/src/astro/integration/routes.ts +6 -0
  355. package/src/astro/integration/virtual-modules.ts +39 -0
  356. package/src/astro/integration/vite-config.ts +12 -0
  357. package/src/astro/middleware.ts +28 -0
  358. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
  359. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +4 -2
  360. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +8 -4
  361. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +4 -2
  362. package/src/astro/routes/api/content/[collection]/[id].ts +4 -2
  363. package/src/astro/routes/api/content/[collection]/authors.ts +34 -0
  364. package/src/astro/types.ts +8 -1
  365. package/src/bylines/index.ts +57 -0
  366. package/src/cli/commands/export-seed.ts +28 -12
  367. package/src/components/EmDashImage.astro +22 -4
  368. package/src/components/Image.astro +20 -3
  369. package/src/database/migrations/043_content_references.ts +121 -0
  370. package/src/database/migrations/runner.ts +2 -0
  371. package/src/database/repositories/content.ts +225 -67
  372. package/src/database/repositories/index.ts +7 -0
  373. package/src/database/repositories/relation.ts +467 -0
  374. package/src/database/repositories/types.ts +31 -0
  375. package/src/database/repositories/user.ts +18 -0
  376. package/src/database/types.ts +34 -0
  377. package/src/emdash-runtime.ts +141 -42
  378. package/src/index.ts +8 -1
  379. package/src/loader.ts +67 -34
  380. package/src/media/responsive.ts +125 -0
  381. package/src/plugins/cron.ts +3 -2
  382. package/src/plugins/index.ts +5 -0
  383. package/src/plugins/scheduler/node.ts +9 -2
  384. package/src/query.ts +32 -5
  385. package/src/scheduled-publish.ts +153 -0
  386. package/src/seed/apply.ts +16 -6
  387. package/src/seed/types.ts +9 -0
  388. package/src/seed/validate.ts +15 -0
  389. package/src/taxonomies/index.ts +1 -0
  390. package/src/virtual-modules.d.ts +11 -0
  391. package/dist/api-Cs7DAACP.mjs.map +0 -1
  392. package/dist/apply-BWMV4Zmw.mjs.map +0 -1
  393. package/dist/byline-fields-BNy7Ng1U.d.mts.map +0 -1
  394. package/dist/content-CyqOmOzm.mjs.map +0 -1
  395. package/dist/cron-DZovZUnC.mjs.map +0 -1
  396. package/dist/index-CjKdMZ3U.d.mts.map +0 -1
  397. package/dist/loader-Dyx8dhFV.mjs.map +0 -1
  398. package/dist/menus-BKkxXCmd.mjs.map +0 -1
  399. package/dist/query-Ctlq1aOk.mjs.map +0 -1
  400. package/dist/redirects-C0L9JUk4.mjs.map +0 -1
  401. package/dist/runner-pt6Wl-l-.mjs.map +0 -1
  402. package/dist/taxonomies-Crtzy4MT.mjs.map +0 -1
  403. package/dist/types-i8_uzhMD.d.mts.map +0 -1
  404. package/dist/user-DzEUl5zA.mjs.map +0 -1
  405. package/dist/validate-Dy6nkNls.d.mts.map +0 -1
  406. package/dist/validate-JCXcsqiY.mjs.map +0 -1
  407. package/dist/version-CnS-Cr8A.mjs +0 -7
  408. package/src/plugins/scheduler/piggyback.ts +0 -71
@@ -1,6 +1,6 @@
1
1
  import { i as currentTimestampValue } from "./dialect-helpers-DRI5pyY3.mjs";
2
- import { i as encodeCursor, r as decodeCursor } from "./types-K3MDsxpy.mjs";
3
- import { i as matchPattern, n as interpolateDestination, r as isPattern, t as compilePattern } from "./patterns-CqG5Ya3i.mjs";
2
+ import { a as encodeCursor, i as decodeCursor } from "./types-BXSUSAjt.mjs";
3
+ import { i as matchPattern, n as interpolateDestination, r as isPattern, t as compilePattern } from "./patterns-p-RBdTbM.mjs";
4
4
  import { sql } from "kysely";
5
5
  import { ulid } from "ulidx";
6
6
 
@@ -304,4 +304,4 @@ var RedirectRepository = class {
304
304
 
305
305
  //#endregion
306
306
  export { RedirectRepository as t };
307
- //# sourceMappingURL=redirect-C6tJA7tk.mjs.map
307
+ //# sourceMappingURL=redirect-CRWIt8Zj.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"redirect-C6tJA7tk.mjs","names":[],"sources":["../src/database/repositories/redirect.ts"],"sourcesContent":["import { sql, type Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport {\n\tcompilePattern,\n\tmatchPattern,\n\tinterpolateDestination,\n\tisPattern,\n} from \"../../redirects/patterns.js\";\nimport { currentTimestampValue } from \"../dialect-helpers.js\";\nimport type { Database, RedirectTable } from \"../types.js\";\nimport { encodeCursor, decodeCursor, type FindManyResult } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Bounded 404 logging\n// ---------------------------------------------------------------------------\n\n/**\n * Hard cap on rows stored in `_emdash_404_log`. When exceeded, the oldest\n * rows (by `last_seen_at`) are evicted on insert. Prevents an unauthenticated\n * attacker from growing the table without bound by requesting unique URLs.\n */\nexport const MAX_404_LOG_ROWS = 10_000;\n\n/** Max stored length for the `Referer` header — truncated on insert. */\nexport const REFERRER_MAX_LENGTH = 512;\n\n/** Max stored length for the `User-Agent` header — truncated on insert. */\nexport const USER_AGENT_MAX_LENGTH = 256;\n\n/** Pattern to escape LIKE wildcards: %, _, and backslash */\nconst LIKE_ESCAPE_RE = /[\\\\%_]/g;\n\n/**\n * Truncate a header-derived string to `max` chars, preserving `null`/`undefined`\n * as `null`. Empty strings stay empty (the caller decides whether to coerce).\n */\nfunction truncateOrNull(value: string | null | undefined, max: number): string | null {\n\tif (value === null || value === undefined) return null;\n\treturn value.length > max ? value.slice(0, max) : value;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface Redirect {\n\tid: string;\n\tsource: string;\n\tdestination: string;\n\ttype: number;\n\tisPattern: boolean;\n\tenabled: boolean;\n\thits: number;\n\tlastHitAt: string | null;\n\tgroupName: string | null;\n\tauto: boolean;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface CreateRedirectInput {\n\tsource: string;\n\tdestination: string;\n\ttype?: number;\n\tisPattern?: boolean;\n\tenabled?: boolean;\n\tgroupName?: string | null;\n\tauto?: boolean;\n}\n\nexport interface UpdateRedirectInput {\n\tsource?: string;\n\tdestination?: string;\n\ttype?: number;\n\tisPattern?: boolean;\n\tenabled?: boolean;\n\tgroupName?: string | null;\n}\n\nexport interface NotFoundEntry {\n\tid: string;\n\tpath: string;\n\treferrer: string | null;\n\tuserAgent: string | null;\n\tip: string | null;\n\tcreatedAt: string;\n}\n\nexport interface NotFoundSummary {\n\tpath: string;\n\tcount: number;\n\tlastSeen: string;\n\ttopReferrer: string | null;\n}\n\nexport interface RedirectMatch {\n\tredirect: Redirect;\n\tresolvedDestination: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row mapping\n// ---------------------------------------------------------------------------\n\nfunction rowToRedirect(row: RedirectTable): Redirect {\n\treturn {\n\t\tid: row.id,\n\t\tsource: row.source,\n\t\tdestination: row.destination,\n\t\ttype: row.type,\n\t\tisPattern: row.is_pattern === 1,\n\t\tenabled: row.enabled === 1,\n\t\thits: row.hits,\n\t\tlastHitAt: row.last_hit_at,\n\t\tgroupName: row.group_name,\n\t\tauto: row.auto === 1,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Repository\n// ---------------------------------------------------------------------------\n\nexport class RedirectRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t// --- CRUD ---------------------------------------------------------------\n\n\tasync findById(id: string): Promise<Redirect | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToRedirect(row) : null;\n\t}\n\n\tasync findBySource(source: string): Promise<Redirect | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"source\", \"=\", source)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToRedirect(row) : null;\n\t}\n\n\tasync findMany(opts: {\n\t\tcursor?: string;\n\t\tlimit?: number;\n\t\tsearch?: string;\n\t\tgroup?: string;\n\t\tenabled?: boolean;\n\t\tauto?: boolean;\n\t}): Promise<FindManyResult<Redirect>> {\n\t\tconst limit = Math.min(Math.max(opts.limit ?? 50, 1), 100);\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.orderBy(\"id\", \"desc\")\n\t\t\t.limit(limit + 1);\n\n\t\tif (opts.search) {\n\t\t\t// Escape LIKE wildcards in the search term to prevent injection.\n\t\t\t// Must include ESCAPE clause for SQLite to recognize backslash as escape char.\n\t\t\tconst escaped = opts.search.replace(LIKE_ESCAPE_RE, (c) => `\\\\${c}`);\n\t\t\tconst term = `%${escaped}%`;\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\tsql<boolean>`source LIKE ${term} ESCAPE '\\\\'`,\n\t\t\t\t\tsql<boolean>`destination LIKE ${term} ESCAPE '\\\\'`,\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tif (opts.group !== undefined) {\n\t\t\tquery = query.where(\"group_name\", \"=\", opts.group);\n\t\t}\n\n\t\tif (opts.enabled !== undefined) {\n\t\t\tquery = query.where(\"enabled\", \"=\", opts.enabled ? 1 : 0);\n\t\t}\n\n\t\tif (opts.auto !== undefined) {\n\t\t\tquery = query.where(\"auto\", \"=\", opts.auto ? 1 : 0);\n\t\t}\n\n\t\tif (opts.cursor) {\n\t\t\tconst decoded = decodeCursor(opts.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"created_at\", \"<\", decoded.orderValue),\n\t\t\t\t\teb.and([eb(\"created_at\", \"=\", decoded.orderValue), eb(\"id\", \"<\", decoded.id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst items = rows.slice(0, limit).map(rowToRedirect);\n\t\tconst result: FindManyResult<Redirect> = { items };\n\n\t\tif (rows.length > limit) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.createdAt, last.id);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync create(input: CreateRedirectInput): Promise<Redirect> {\n\t\tconst id = ulid();\n\t\tconst now = new Date().toISOString();\n\t\tconst patternFlag = input.isPattern ?? isPattern(input.source);\n\n\t\tawait this.db\n\t\t\t.insertInto(\"_emdash_redirects\")\n\t\t\t.values({\n\t\t\t\tid,\n\t\t\t\tsource: input.source,\n\t\t\t\tdestination: input.destination,\n\t\t\t\ttype: input.type ?? 301,\n\t\t\t\tis_pattern: patternFlag ? 1 : 0,\n\t\t\t\tenabled: input.enabled !== false ? 1 : 0,\n\t\t\t\thits: 0,\n\t\t\t\tlast_hit_at: null,\n\t\t\t\tgroup_name: input.groupName ?? null,\n\t\t\t\tauto: input.auto ? 1 : 0,\n\t\t\t\tcreated_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.execute();\n\n\t\treturn (await this.findById(id))!;\n\t}\n\n\tasync update(id: string, input: UpdateRedirectInput): Promise<Redirect | null> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return null;\n\n\t\tconst now = new Date().toISOString();\n\t\tconst values: Record<string, unknown> = { updated_at: now };\n\n\t\tif (input.source !== undefined) {\n\t\t\tvalues.source = input.source;\n\t\t\tvalues.is_pattern =\n\t\t\t\tinput.isPattern !== undefined ? (input.isPattern ? 1 : 0) : isPattern(input.source) ? 1 : 0;\n\t\t} else if (input.isPattern !== undefined) {\n\t\t\tvalues.is_pattern = input.isPattern ? 1 : 0;\n\t\t}\n\n\t\tif (input.destination !== undefined) values.destination = input.destination;\n\t\tif (input.type !== undefined) values.type = input.type;\n\t\tif (input.enabled !== undefined) values.enabled = input.enabled ? 1 : 0;\n\t\tif (input.groupName !== undefined) values.group_name = input.groupName;\n\n\t\tawait this.db.updateTable(\"_emdash_redirects\").set(values).where(\"id\", \"=\", id).execute();\n\n\t\treturn (await this.findById(id))!;\n\t}\n\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_redirects\")\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn BigInt(result.numDeletedRows) > 0n;\n\t}\n\n\t/**\n\t * Fetch all enabled redirects (for loop detection graph building).\n\t * Not paginated — returns the full set.\n\t */\n\tasync findAllEnabled(): Promise<Redirect[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"enabled\", \"=\", 1)\n\t\t\t.execute();\n\t\treturn rows.map(rowToRedirect);\n\t}\n\n\t// --- Matching -----------------------------------------------------------\n\n\tasync findExactMatch(path: string): Promise<Redirect | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"source\", \"=\", path)\n\t\t\t.where(\"enabled\", \"=\", 1)\n\t\t\t.where(\"is_pattern\", \"=\", 0)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToRedirect(row) : null;\n\t}\n\n\tasync findEnabledPatternRules(): Promise<Redirect[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"enabled\", \"=\", 1)\n\t\t\t.where(\"is_pattern\", \"=\", 1)\n\t\t\t.execute();\n\t\treturn rows.map(rowToRedirect);\n\t}\n\n\t/**\n\t * Match a request path against all enabled redirect rules.\n\t * Checks exact matches first (indexed), then pattern rules.\n\t * Returns the matched redirect and the resolved destination URL.\n\t */\n\tasync matchPath(path: string): Promise<RedirectMatch | null> {\n\t\t// 1. Exact match (fast, indexed)\n\t\tconst exact = await this.findExactMatch(path);\n\t\tif (exact) {\n\t\t\treturn { redirect: exact, resolvedDestination: exact.destination };\n\t\t}\n\n\t\t// 2. Pattern match\n\t\tconst patterns = await this.findEnabledPatternRules();\n\t\tfor (const redirect of patterns) {\n\t\t\tconst compiled = compilePattern(redirect.source);\n\t\t\tconst params = matchPattern(compiled, path);\n\t\t\tif (params) {\n\t\t\t\tconst resolved = interpolateDestination(redirect.destination, params);\n\t\t\t\treturn { redirect, resolvedDestination: resolved };\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// --- Hit tracking -------------------------------------------------------\n\n\tasync recordHit(id: string): Promise<void> {\n\t\tawait sql`\n\t\t\tUPDATE _emdash_redirects\n\t\t\tSET hits = hits + 1, last_hit_at = ${currentTimestampValue(this.db)}, updated_at = ${currentTimestampValue(this.db)}\n\t\t\tWHERE id = ${id}\n\t\t`.execute(this.db);\n\t}\n\n\t// --- Auto-redirects (slug change) ---------------------------------------\n\n\t/**\n\t * Create an auto-redirect when a content slug changes.\n\t * Uses the collection's URL pattern to compute old/new URLs.\n\t * Collapses existing redirect chains pointing to the old URL.\n\t */\n\tasync createAutoRedirect(\n\t\tcollection: string,\n\t\toldSlug: string,\n\t\tnewSlug: string,\n\t\tcontentId: string,\n\t\turlPattern: string | null,\n\t): Promise<Redirect> {\n\t\tconst oldUrl = urlPattern\n\t\t\t? urlPattern.replace(\"{slug}\", oldSlug).replace(\"{id}\", contentId)\n\t\t\t: `/${collection}/${oldSlug}`;\n\t\tconst newUrl = urlPattern\n\t\t\t? urlPattern.replace(\"{slug}\", newSlug).replace(\"{id}\", contentId)\n\t\t\t: `/${collection}/${newSlug}`;\n\n\t\t// Collapse chains: update any existing redirects pointing to the old URL\n\t\tawait this.collapseChains(oldUrl, newUrl);\n\n\t\t// Check if a redirect from this source already exists\n\t\tconst existing = await this.findBySource(oldUrl);\n\t\tif (existing) {\n\t\t\t// Update the existing redirect to point to the new URL\n\t\t\treturn (await this.update(existing.id, { destination: newUrl }))!;\n\t\t}\n\n\t\treturn this.create({\n\t\t\tsource: oldUrl,\n\t\t\tdestination: newUrl,\n\t\t\ttype: 301,\n\t\t\tisPattern: false,\n\t\t\tauto: true,\n\t\t\tgroupName: \"Auto: slug change\",\n\t\t});\n\t}\n\n\t/**\n\t * Update all redirects whose destination matches oldDestination\n\t * to point to newDestination instead. Prevents redirect chains.\n\t * Returns the number of updated rows.\n\t */\n\tasync collapseChains(oldDestination: string, newDestination: string): Promise<number> {\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_redirects\")\n\t\t\t.set({\n\t\t\t\tdestination: newDestination,\n\t\t\t\tupdated_at: new Date().toISOString(),\n\t\t\t})\n\t\t\t.where(\"destination\", \"=\", oldDestination)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows);\n\t}\n\n\t// --- 404 log ------------------------------------------------------------\n\n\t/**\n\t * Record a 404 hit for `entry.path`.\n\t *\n\t * Dedups by path: repeat hits increment `hits` and refresh `last_seen_at`\n\t * on the existing row instead of inserting a new one. Referrer and\n\t * user-agent are truncated to bounded lengths so a malicious client can't\n\t * blow up storage with huge headers. When the table would exceed\n\t * MAX_404_LOG_ROWS, the oldest entries (by `last_seen_at`) are evicted.\n\t *\n\t * This is called from the public redirect middleware on every 404 and\n\t * must never throw for an unauthenticated caller — failures bubble up to\n\t * the middleware, which swallows them.\n\t */\n\tasync log404(entry: {\n\t\tpath: string;\n\t\treferrer?: string | null;\n\t\tuserAgent?: string | null;\n\t\tip?: string | null;\n\t}): Promise<void> {\n\t\tconst now = new Date().toISOString();\n\t\tconst referrer = truncateOrNull(entry.referrer, REFERRER_MAX_LENGTH);\n\t\tconst userAgent = truncateOrNull(entry.userAgent, USER_AGENT_MAX_LENGTH);\n\t\tconst ip = entry.ip ?? null;\n\n\t\t// Atomic upsert by path. The UNIQUE index on `path` makes this safe\n\t\t// under concurrency: two requests for the same new path can't both\n\t\t// insert — the second one hits the conflict branch and increments\n\t\t// hits instead of failing with a uniqueness error.\n\t\tawait this.db\n\t\t\t.insertInto(\"_emdash_404_log\")\n\t\t\t.values({\n\t\t\t\tid: ulid(),\n\t\t\t\tpath: entry.path,\n\t\t\t\treferrer,\n\t\t\t\tuser_agent: userAgent,\n\t\t\t\tip,\n\t\t\t\thits: 1,\n\t\t\t\tlast_seen_at: now,\n\t\t\t\tcreated_at: now,\n\t\t\t})\n\t\t\t.onConflict((oc) =>\n\t\t\t\toc.column(\"path\").doUpdateSet({\n\t\t\t\t\thits: sql`hits + 1`,\n\t\t\t\t\tlast_seen_at: now,\n\t\t\t\t\treferrer,\n\t\t\t\t\tuser_agent: userAgent,\n\t\t\t\t\tip,\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.execute();\n\n\t\t// Enforce the row cap. Cheap when the table is under cap (single\n\t\t// COUNT(*) query); evicts oldest rows if we're over. Updates (dedup\n\t\t// hits) don't grow the table so this is a no-op for repeat paths.\n\t\tawait this.enforce404Cap();\n\t}\n\n\t/**\n\t * Delete the oldest rows from `_emdash_404_log` if the row count exceeds\n\t * MAX_404_LOG_ROWS. \"Oldest\" is by `last_seen_at`, so a path that keeps\n\t * getting hit stays in the table even if it was first seen long ago.\n\t *\n\t * Private — callers use `log404`, which invokes this after every upsert.\n\t */\n\tprivate async enforce404Cap(): Promise<void> {\n\t\tconst countRow = await this.db\n\t\t\t.selectFrom(\"_emdash_404_log\")\n\t\t\t.select((eb) => eb.fn.countAll<number>().as(\"c\"))\n\t\t\t.executeTakeFirst();\n\t\tconst count = Number(countRow?.c ?? 0);\n\t\tif (count <= MAX_404_LOG_ROWS) return;\n\n\t\tconst excess = count - MAX_404_LOG_ROWS;\n\n\t\t// Evict the oldest rows in a single SQL statement. Using a subquery\n\t\t// (rather than materialising the victim IDs in JS and passing them\n\t\t// back as bind parameters) keeps the statement bounded regardless of\n\t\t// how far over cap the table is — important for existing installs\n\t\t// that crossed the threshold before this cap was introduced.\n\t\tawait this.db\n\t\t\t.deleteFrom(\"_emdash_404_log\")\n\t\t\t.where(\n\t\t\t\t\"id\",\n\t\t\t\t\"in\",\n\t\t\t\tthis.db\n\t\t\t\t\t.selectFrom(\"_emdash_404_log\")\n\t\t\t\t\t.select(\"id\")\n\t\t\t\t\t.orderBy(\"last_seen_at\", \"asc\")\n\t\t\t\t\t.orderBy(\"id\", \"asc\")\n\t\t\t\t\t.limit(excess),\n\t\t\t)\n\t\t\t.execute();\n\t}\n\n\tasync find404s(opts: {\n\t\tcursor?: string;\n\t\tlimit?: number;\n\t\tsearch?: string;\n\t}): Promise<FindManyResult<NotFoundEntry>> {\n\t\tconst limit = Math.min(Math.max(opts.limit ?? 50, 1), 100);\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_404_log\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.orderBy(\"id\", \"desc\")\n\t\t\t.limit(limit + 1);\n\n\t\tif (opts.search) {\n\t\t\tconst escaped = opts.search.replace(LIKE_ESCAPE_RE, (c) => `\\\\${c}`);\n\t\t\tconst term = `%${escaped}%`;\n\t\t\tquery = query.where(sql<boolean>`path LIKE ${term} ESCAPE '\\\\'`);\n\t\t}\n\n\t\tif (opts.cursor) {\n\t\t\tconst decoded = decodeCursor(opts.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"created_at\", \"<\", decoded.orderValue),\n\t\t\t\t\teb.and([eb(\"created_at\", \"=\", decoded.orderValue), eb(\"id\", \"<\", decoded.id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst items: NotFoundEntry[] = rows.slice(0, limit).map((row) => ({\n\t\t\tid: row.id,\n\t\t\tpath: row.path,\n\t\t\treferrer: row.referrer,\n\t\t\tuserAgent: row.user_agent,\n\t\t\tip: row.ip,\n\t\t\tcreatedAt: row.created_at,\n\t\t}));\n\n\t\tconst result: FindManyResult<NotFoundEntry> = { items };\n\t\tif (rows.length > limit) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.createdAt, last.id);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync get404Summary(limit = 50): Promise<NotFoundSummary[]> {\n\t\t// Since rows are now deduped by path, each path has exactly one row\n\t\t// with `hits` as the running count and `last_seen_at` as the latest\n\t\t// timestamp. The subquery for `top_referrer` collapses to a simple\n\t\t// pick of the row's stored referrer (the most recent one seen).\n\t\tconst rows = await sql<{\n\t\t\tpath: string;\n\t\t\tcount: number;\n\t\t\tlast_seen: string;\n\t\t\ttop_referrer: string | null;\n\t\t}>`\n\t\t\tSELECT\n\t\t\t\tpath,\n\t\t\t\tSUM(hits) as count,\n\t\t\t\tMAX(last_seen_at) as last_seen,\n\t\t\t\t(\n\t\t\t\t\tSELECT referrer FROM _emdash_404_log AS inner_log\n\t\t\t\t\tWHERE inner_log.path = _emdash_404_log.path\n\t\t\t\t\t\tAND referrer IS NOT NULL AND referrer != ''\n\t\t\t\t\tLIMIT 1\n\t\t\t\t) as top_referrer\n\t\t\tFROM _emdash_404_log\n\t\t\tGROUP BY path\n\t\t\tORDER BY count DESC\n\t\t\tLIMIT ${limit}\n\t\t`.execute(this.db);\n\n\t\treturn rows.rows.map((row) => ({\n\t\t\tpath: row.path,\n\t\t\tcount: Number(row.count),\n\t\t\tlastSeen: row.last_seen,\n\t\t\ttopReferrer: row.top_referrer,\n\t\t}));\n\t}\n\n\tasync delete404(id: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_404_log\")\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn BigInt(result.numDeletedRows) > 0n;\n\t}\n\n\tasync clear404s(): Promise<number> {\n\t\tconst result = await this.db.deleteFrom(\"_emdash_404_log\").executeTakeFirst();\n\t\treturn Number(result.numDeletedRows);\n\t}\n\n\tasync prune404s(olderThan: string): Promise<number> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_404_log\")\n\t\t\t.where(\"created_at\", \"<\", olderThan)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows);\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"redirect-CRWIt8Zj.mjs","names":[],"sources":["../src/database/repositories/redirect.ts"],"sourcesContent":["import { sql, type Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport {\n\tcompilePattern,\n\tmatchPattern,\n\tinterpolateDestination,\n\tisPattern,\n} from \"../../redirects/patterns.js\";\nimport { currentTimestampValue } from \"../dialect-helpers.js\";\nimport type { Database, RedirectTable } from \"../types.js\";\nimport { encodeCursor, decodeCursor, type FindManyResult } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Bounded 404 logging\n// ---------------------------------------------------------------------------\n\n/**\n * Hard cap on rows stored in `_emdash_404_log`. When exceeded, the oldest\n * rows (by `last_seen_at`) are evicted on insert. Prevents an unauthenticated\n * attacker from growing the table without bound by requesting unique URLs.\n */\nexport const MAX_404_LOG_ROWS = 10_000;\n\n/** Max stored length for the `Referer` header — truncated on insert. */\nexport const REFERRER_MAX_LENGTH = 512;\n\n/** Max stored length for the `User-Agent` header — truncated on insert. */\nexport const USER_AGENT_MAX_LENGTH = 256;\n\n/** Pattern to escape LIKE wildcards: %, _, and backslash */\nconst LIKE_ESCAPE_RE = /[\\\\%_]/g;\n\n/**\n * Truncate a header-derived string to `max` chars, preserving `null`/`undefined`\n * as `null`. Empty strings stay empty (the caller decides whether to coerce).\n */\nfunction truncateOrNull(value: string | null | undefined, max: number): string | null {\n\tif (value === null || value === undefined) return null;\n\treturn value.length > max ? value.slice(0, max) : value;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface Redirect {\n\tid: string;\n\tsource: string;\n\tdestination: string;\n\ttype: number;\n\tisPattern: boolean;\n\tenabled: boolean;\n\thits: number;\n\tlastHitAt: string | null;\n\tgroupName: string | null;\n\tauto: boolean;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface CreateRedirectInput {\n\tsource: string;\n\tdestination: string;\n\ttype?: number;\n\tisPattern?: boolean;\n\tenabled?: boolean;\n\tgroupName?: string | null;\n\tauto?: boolean;\n}\n\nexport interface UpdateRedirectInput {\n\tsource?: string;\n\tdestination?: string;\n\ttype?: number;\n\tisPattern?: boolean;\n\tenabled?: boolean;\n\tgroupName?: string | null;\n}\n\nexport interface NotFoundEntry {\n\tid: string;\n\tpath: string;\n\treferrer: string | null;\n\tuserAgent: string | null;\n\tip: string | null;\n\tcreatedAt: string;\n}\n\nexport interface NotFoundSummary {\n\tpath: string;\n\tcount: number;\n\tlastSeen: string;\n\ttopReferrer: string | null;\n}\n\nexport interface RedirectMatch {\n\tredirect: Redirect;\n\tresolvedDestination: string;\n}\n\n// ---------------------------------------------------------------------------\n// Row mapping\n// ---------------------------------------------------------------------------\n\nfunction rowToRedirect(row: RedirectTable): Redirect {\n\treturn {\n\t\tid: row.id,\n\t\tsource: row.source,\n\t\tdestination: row.destination,\n\t\ttype: row.type,\n\t\tisPattern: row.is_pattern === 1,\n\t\tenabled: row.enabled === 1,\n\t\thits: row.hits,\n\t\tlastHitAt: row.last_hit_at,\n\t\tgroupName: row.group_name,\n\t\tauto: row.auto === 1,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Repository\n// ---------------------------------------------------------------------------\n\nexport class RedirectRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t// --- CRUD ---------------------------------------------------------------\n\n\tasync findById(id: string): Promise<Redirect | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToRedirect(row) : null;\n\t}\n\n\tasync findBySource(source: string): Promise<Redirect | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"source\", \"=\", source)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToRedirect(row) : null;\n\t}\n\n\tasync findMany(opts: {\n\t\tcursor?: string;\n\t\tlimit?: number;\n\t\tsearch?: string;\n\t\tgroup?: string;\n\t\tenabled?: boolean;\n\t\tauto?: boolean;\n\t}): Promise<FindManyResult<Redirect>> {\n\t\tconst limit = Math.min(Math.max(opts.limit ?? 50, 1), 100);\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.orderBy(\"id\", \"desc\")\n\t\t\t.limit(limit + 1);\n\n\t\tif (opts.search) {\n\t\t\t// Escape LIKE wildcards in the search term to prevent injection.\n\t\t\t// Must include ESCAPE clause for SQLite to recognize backslash as escape char.\n\t\t\tconst escaped = opts.search.replace(LIKE_ESCAPE_RE, (c) => `\\\\${c}`);\n\t\t\tconst term = `%${escaped}%`;\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\tsql<boolean>`source LIKE ${term} ESCAPE '\\\\'`,\n\t\t\t\t\tsql<boolean>`destination LIKE ${term} ESCAPE '\\\\'`,\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tif (opts.group !== undefined) {\n\t\t\tquery = query.where(\"group_name\", \"=\", opts.group);\n\t\t}\n\n\t\tif (opts.enabled !== undefined) {\n\t\t\tquery = query.where(\"enabled\", \"=\", opts.enabled ? 1 : 0);\n\t\t}\n\n\t\tif (opts.auto !== undefined) {\n\t\t\tquery = query.where(\"auto\", \"=\", opts.auto ? 1 : 0);\n\t\t}\n\n\t\tif (opts.cursor) {\n\t\t\tconst decoded = decodeCursor(opts.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"created_at\", \"<\", decoded.orderValue),\n\t\t\t\t\teb.and([eb(\"created_at\", \"=\", decoded.orderValue), eb(\"id\", \"<\", decoded.id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst items = rows.slice(0, limit).map(rowToRedirect);\n\t\tconst result: FindManyResult<Redirect> = { items };\n\n\t\tif (rows.length > limit) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.createdAt, last.id);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync create(input: CreateRedirectInput): Promise<Redirect> {\n\t\tconst id = ulid();\n\t\tconst now = new Date().toISOString();\n\t\tconst patternFlag = input.isPattern ?? isPattern(input.source);\n\n\t\tawait this.db\n\t\t\t.insertInto(\"_emdash_redirects\")\n\t\t\t.values({\n\t\t\t\tid,\n\t\t\t\tsource: input.source,\n\t\t\t\tdestination: input.destination,\n\t\t\t\ttype: input.type ?? 301,\n\t\t\t\tis_pattern: patternFlag ? 1 : 0,\n\t\t\t\tenabled: input.enabled !== false ? 1 : 0,\n\t\t\t\thits: 0,\n\t\t\t\tlast_hit_at: null,\n\t\t\t\tgroup_name: input.groupName ?? null,\n\t\t\t\tauto: input.auto ? 1 : 0,\n\t\t\t\tcreated_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.execute();\n\n\t\treturn (await this.findById(id))!;\n\t}\n\n\tasync update(id: string, input: UpdateRedirectInput): Promise<Redirect | null> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return null;\n\n\t\tconst now = new Date().toISOString();\n\t\tconst values: Record<string, unknown> = { updated_at: now };\n\n\t\tif (input.source !== undefined) {\n\t\t\tvalues.source = input.source;\n\t\t\tvalues.is_pattern =\n\t\t\t\tinput.isPattern !== undefined ? (input.isPattern ? 1 : 0) : isPattern(input.source) ? 1 : 0;\n\t\t} else if (input.isPattern !== undefined) {\n\t\t\tvalues.is_pattern = input.isPattern ? 1 : 0;\n\t\t}\n\n\t\tif (input.destination !== undefined) values.destination = input.destination;\n\t\tif (input.type !== undefined) values.type = input.type;\n\t\tif (input.enabled !== undefined) values.enabled = input.enabled ? 1 : 0;\n\t\tif (input.groupName !== undefined) values.group_name = input.groupName;\n\n\t\tawait this.db.updateTable(\"_emdash_redirects\").set(values).where(\"id\", \"=\", id).execute();\n\n\t\treturn (await this.findById(id))!;\n\t}\n\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_redirects\")\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn BigInt(result.numDeletedRows) > 0n;\n\t}\n\n\t/**\n\t * Fetch all enabled redirects (for loop detection graph building).\n\t * Not paginated — returns the full set.\n\t */\n\tasync findAllEnabled(): Promise<Redirect[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"enabled\", \"=\", 1)\n\t\t\t.execute();\n\t\treturn rows.map(rowToRedirect);\n\t}\n\n\t// --- Matching -----------------------------------------------------------\n\n\tasync findExactMatch(path: string): Promise<Redirect | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"source\", \"=\", path)\n\t\t\t.where(\"enabled\", \"=\", 1)\n\t\t\t.where(\"is_pattern\", \"=\", 0)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToRedirect(row) : null;\n\t}\n\n\tasync findEnabledPatternRules(): Promise<Redirect[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_redirects\")\n\t\t\t.selectAll()\n\t\t\t.where(\"enabled\", \"=\", 1)\n\t\t\t.where(\"is_pattern\", \"=\", 1)\n\t\t\t.execute();\n\t\treturn rows.map(rowToRedirect);\n\t}\n\n\t/**\n\t * Match a request path against all enabled redirect rules.\n\t * Checks exact matches first (indexed), then pattern rules.\n\t * Returns the matched redirect and the resolved destination URL.\n\t */\n\tasync matchPath(path: string): Promise<RedirectMatch | null> {\n\t\t// 1. Exact match (fast, indexed)\n\t\tconst exact = await this.findExactMatch(path);\n\t\tif (exact) {\n\t\t\treturn { redirect: exact, resolvedDestination: exact.destination };\n\t\t}\n\n\t\t// 2. Pattern match\n\t\tconst patterns = await this.findEnabledPatternRules();\n\t\tfor (const redirect of patterns) {\n\t\t\tconst compiled = compilePattern(redirect.source);\n\t\t\tconst params = matchPattern(compiled, path);\n\t\t\tif (params) {\n\t\t\t\tconst resolved = interpolateDestination(redirect.destination, params);\n\t\t\t\treturn { redirect, resolvedDestination: resolved };\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// --- Hit tracking -------------------------------------------------------\n\n\tasync recordHit(id: string): Promise<void> {\n\t\tawait sql`\n\t\t\tUPDATE _emdash_redirects\n\t\t\tSET hits = hits + 1, last_hit_at = ${currentTimestampValue(this.db)}, updated_at = ${currentTimestampValue(this.db)}\n\t\t\tWHERE id = ${id}\n\t\t`.execute(this.db);\n\t}\n\n\t// --- Auto-redirects (slug change) ---------------------------------------\n\n\t/**\n\t * Create an auto-redirect when a content slug changes.\n\t * Uses the collection's URL pattern to compute old/new URLs.\n\t * Collapses existing redirect chains pointing to the old URL.\n\t */\n\tasync createAutoRedirect(\n\t\tcollection: string,\n\t\toldSlug: string,\n\t\tnewSlug: string,\n\t\tcontentId: string,\n\t\turlPattern: string | null,\n\t): Promise<Redirect> {\n\t\tconst oldUrl = urlPattern\n\t\t\t? urlPattern.replace(\"{slug}\", oldSlug).replace(\"{id}\", contentId)\n\t\t\t: `/${collection}/${oldSlug}`;\n\t\tconst newUrl = urlPattern\n\t\t\t? urlPattern.replace(\"{slug}\", newSlug).replace(\"{id}\", contentId)\n\t\t\t: `/${collection}/${newSlug}`;\n\n\t\t// Collapse chains: update any existing redirects pointing to the old URL\n\t\tawait this.collapseChains(oldUrl, newUrl);\n\n\t\t// Check if a redirect from this source already exists\n\t\tconst existing = await this.findBySource(oldUrl);\n\t\tif (existing) {\n\t\t\t// Update the existing redirect to point to the new URL\n\t\t\treturn (await this.update(existing.id, { destination: newUrl }))!;\n\t\t}\n\n\t\treturn this.create({\n\t\t\tsource: oldUrl,\n\t\t\tdestination: newUrl,\n\t\t\ttype: 301,\n\t\t\tisPattern: false,\n\t\t\tauto: true,\n\t\t\tgroupName: \"Auto: slug change\",\n\t\t});\n\t}\n\n\t/**\n\t * Update all redirects whose destination matches oldDestination\n\t * to point to newDestination instead. Prevents redirect chains.\n\t * Returns the number of updated rows.\n\t */\n\tasync collapseChains(oldDestination: string, newDestination: string): Promise<number> {\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_redirects\")\n\t\t\t.set({\n\t\t\t\tdestination: newDestination,\n\t\t\t\tupdated_at: new Date().toISOString(),\n\t\t\t})\n\t\t\t.where(\"destination\", \"=\", oldDestination)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows);\n\t}\n\n\t// --- 404 log ------------------------------------------------------------\n\n\t/**\n\t * Record a 404 hit for `entry.path`.\n\t *\n\t * Dedups by path: repeat hits increment `hits` and refresh `last_seen_at`\n\t * on the existing row instead of inserting a new one. Referrer and\n\t * user-agent are truncated to bounded lengths so a malicious client can't\n\t * blow up storage with huge headers. When the table would exceed\n\t * MAX_404_LOG_ROWS, the oldest entries (by `last_seen_at`) are evicted.\n\t *\n\t * This is called from the public redirect middleware on every 404 and\n\t * must never throw for an unauthenticated caller — failures bubble up to\n\t * the middleware, which swallows them.\n\t */\n\tasync log404(entry: {\n\t\tpath: string;\n\t\treferrer?: string | null;\n\t\tuserAgent?: string | null;\n\t\tip?: string | null;\n\t}): Promise<void> {\n\t\tconst now = new Date().toISOString();\n\t\tconst referrer = truncateOrNull(entry.referrer, REFERRER_MAX_LENGTH);\n\t\tconst userAgent = truncateOrNull(entry.userAgent, USER_AGENT_MAX_LENGTH);\n\t\tconst ip = entry.ip ?? null;\n\n\t\t// Atomic upsert by path. The UNIQUE index on `path` makes this safe\n\t\t// under concurrency: two requests for the same new path can't both\n\t\t// insert — the second one hits the conflict branch and increments\n\t\t// hits instead of failing with a uniqueness error.\n\t\tawait this.db\n\t\t\t.insertInto(\"_emdash_404_log\")\n\t\t\t.values({\n\t\t\t\tid: ulid(),\n\t\t\t\tpath: entry.path,\n\t\t\t\treferrer,\n\t\t\t\tuser_agent: userAgent,\n\t\t\t\tip,\n\t\t\t\thits: 1,\n\t\t\t\tlast_seen_at: now,\n\t\t\t\tcreated_at: now,\n\t\t\t})\n\t\t\t.onConflict((oc) =>\n\t\t\t\toc.column(\"path\").doUpdateSet({\n\t\t\t\t\thits: sql`hits + 1`,\n\t\t\t\t\tlast_seen_at: now,\n\t\t\t\t\treferrer,\n\t\t\t\t\tuser_agent: userAgent,\n\t\t\t\t\tip,\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.execute();\n\n\t\t// Enforce the row cap. Cheap when the table is under cap (single\n\t\t// COUNT(*) query); evicts oldest rows if we're over. Updates (dedup\n\t\t// hits) don't grow the table so this is a no-op for repeat paths.\n\t\tawait this.enforce404Cap();\n\t}\n\n\t/**\n\t * Delete the oldest rows from `_emdash_404_log` if the row count exceeds\n\t * MAX_404_LOG_ROWS. \"Oldest\" is by `last_seen_at`, so a path that keeps\n\t * getting hit stays in the table even if it was first seen long ago.\n\t *\n\t * Private — callers use `log404`, which invokes this after every upsert.\n\t */\n\tprivate async enforce404Cap(): Promise<void> {\n\t\tconst countRow = await this.db\n\t\t\t.selectFrom(\"_emdash_404_log\")\n\t\t\t.select((eb) => eb.fn.countAll<number>().as(\"c\"))\n\t\t\t.executeTakeFirst();\n\t\tconst count = Number(countRow?.c ?? 0);\n\t\tif (count <= MAX_404_LOG_ROWS) return;\n\n\t\tconst excess = count - MAX_404_LOG_ROWS;\n\n\t\t// Evict the oldest rows in a single SQL statement. Using a subquery\n\t\t// (rather than materialising the victim IDs in JS and passing them\n\t\t// back as bind parameters) keeps the statement bounded regardless of\n\t\t// how far over cap the table is — important for existing installs\n\t\t// that crossed the threshold before this cap was introduced.\n\t\tawait this.db\n\t\t\t.deleteFrom(\"_emdash_404_log\")\n\t\t\t.where(\n\t\t\t\t\"id\",\n\t\t\t\t\"in\",\n\t\t\t\tthis.db\n\t\t\t\t\t.selectFrom(\"_emdash_404_log\")\n\t\t\t\t\t.select(\"id\")\n\t\t\t\t\t.orderBy(\"last_seen_at\", \"asc\")\n\t\t\t\t\t.orderBy(\"id\", \"asc\")\n\t\t\t\t\t.limit(excess),\n\t\t\t)\n\t\t\t.execute();\n\t}\n\n\tasync find404s(opts: {\n\t\tcursor?: string;\n\t\tlimit?: number;\n\t\tsearch?: string;\n\t}): Promise<FindManyResult<NotFoundEntry>> {\n\t\tconst limit = Math.min(Math.max(opts.limit ?? 50, 1), 100);\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_404_log\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.orderBy(\"id\", \"desc\")\n\t\t\t.limit(limit + 1);\n\n\t\tif (opts.search) {\n\t\t\tconst escaped = opts.search.replace(LIKE_ESCAPE_RE, (c) => `\\\\${c}`);\n\t\t\tconst term = `%${escaped}%`;\n\t\t\tquery = query.where(sql<boolean>`path LIKE ${term} ESCAPE '\\\\'`);\n\t\t}\n\n\t\tif (opts.cursor) {\n\t\t\tconst decoded = decodeCursor(opts.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"created_at\", \"<\", decoded.orderValue),\n\t\t\t\t\teb.and([eb(\"created_at\", \"=\", decoded.orderValue), eb(\"id\", \"<\", decoded.id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst items: NotFoundEntry[] = rows.slice(0, limit).map((row) => ({\n\t\t\tid: row.id,\n\t\t\tpath: row.path,\n\t\t\treferrer: row.referrer,\n\t\t\tuserAgent: row.user_agent,\n\t\t\tip: row.ip,\n\t\t\tcreatedAt: row.created_at,\n\t\t}));\n\n\t\tconst result: FindManyResult<NotFoundEntry> = { items };\n\t\tif (rows.length > limit) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.createdAt, last.id);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tasync get404Summary(limit = 50): Promise<NotFoundSummary[]> {\n\t\t// Since rows are now deduped by path, each path has exactly one row\n\t\t// with `hits` as the running count and `last_seen_at` as the latest\n\t\t// timestamp. The subquery for `top_referrer` collapses to a simple\n\t\t// pick of the row's stored referrer (the most recent one seen).\n\t\tconst rows = await sql<{\n\t\t\tpath: string;\n\t\t\tcount: number;\n\t\t\tlast_seen: string;\n\t\t\ttop_referrer: string | null;\n\t\t}>`\n\t\t\tSELECT\n\t\t\t\tpath,\n\t\t\t\tSUM(hits) as count,\n\t\t\t\tMAX(last_seen_at) as last_seen,\n\t\t\t\t(\n\t\t\t\t\tSELECT referrer FROM _emdash_404_log AS inner_log\n\t\t\t\t\tWHERE inner_log.path = _emdash_404_log.path\n\t\t\t\t\t\tAND referrer IS NOT NULL AND referrer != ''\n\t\t\t\t\tLIMIT 1\n\t\t\t\t) as top_referrer\n\t\t\tFROM _emdash_404_log\n\t\t\tGROUP BY path\n\t\t\tORDER BY count DESC\n\t\t\tLIMIT ${limit}\n\t\t`.execute(this.db);\n\n\t\treturn rows.rows.map((row) => ({\n\t\t\tpath: row.path,\n\t\t\tcount: Number(row.count),\n\t\t\tlastSeen: row.last_seen,\n\t\t\ttopReferrer: row.top_referrer,\n\t\t}));\n\t}\n\n\tasync delete404(id: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_404_log\")\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn BigInt(result.numDeletedRows) > 0n;\n\t}\n\n\tasync clear404s(): Promise<number> {\n\t\tconst result = await this.db.deleteFrom(\"_emdash_404_log\").executeTakeFirst();\n\t\treturn Number(result.numDeletedRows);\n\t}\n\n\tasync prune404s(olderThan: string): Promise<number> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_404_log\")\n\t\t\t.where(\"created_at\", \"<\", olderThan)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows);\n\t}\n}\n"],"mappings":"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"}
@@ -135,12 +135,25 @@ const contentSeoInput = z.object({
135
135
  canonical: httpUrl.nullish(),
136
136
  noIndex: z.boolean().optional()
137
137
  }).meta({ id: "ContentSeoInput" });
138
+ /** ISO 8601 date or datetime bound for the content-list date range filter. */
139
+ const contentDateBound = z.union([z.iso.datetime({
140
+ offset: true,
141
+ message: "must be an ISO 8601 datetime"
142
+ }), z.iso.date({ message: "must be an ISO 8601 date" })]).optional();
138
143
  const contentListQuery = cursorPaginationQuery.extend({
139
144
  status: z.string().optional(),
140
145
  orderBy: z.string().optional(),
141
146
  order: z.enum(["asc", "desc"]).optional(),
142
147
  locale: localeCode.optional(),
143
- q: z.string().trim().min(1).max(200).optional()
148
+ q: z.string().trim().min(1).max(200).optional(),
149
+ authorId: z.string().min(1).max(64).optional(),
150
+ dateField: z.enum([
151
+ "createdAt",
152
+ "updatedAt",
153
+ "publishedAt"
154
+ ]).optional(),
155
+ dateFrom: contentDateBound,
156
+ dateTo: contentDateBound
144
157
  }).meta({ id: "ContentListQuery" });
145
158
  /** ISO 8601 datetime for `publishedAt` / `createdAt`. Routes gate writes behind `content:publish_any`. */
146
159
  const contentDateOverride = z.iso.datetime({
@@ -224,6 +237,15 @@ const contentListResponseSchema = z.object({
224
237
  nextCursor: z.string().optional(),
225
238
  total: z.number().int().nonnegative().optional()
226
239
  }).meta({ id: "ContentListResponse" });
240
+ /** A distinct content author for the admin author filter */
241
+ const contentAuthorSchema = z.object({
242
+ id: z.string(),
243
+ name: z.string().nullable(),
244
+ email: z.string(),
245
+ avatarUrl: z.string().nullable()
246
+ }).meta({ id: "ContentAuthor" });
247
+ /** Response for the content authors endpoint */
248
+ const contentAuthorsResponseSchema = z.object({ items: z.array(contentAuthorSchema) }).meta({ id: "ContentAuthorsResponse" });
227
249
  /** Trashed content item */
228
250
  const trashedContentItemSchema = z.object({
229
251
  id: z.string(),
@@ -1164,5 +1186,5 @@ const notFoundSummarySchema = z.object({
1164
1186
  const notFoundSummaryResponseSchema = z.object({ items: z.array(notFoundSummarySchema) }).meta({ id: "NotFoundSummaryResponse" });
1165
1187
 
1166
1188
  //#endregion
1167
- export { createMenuBody as $, contentCreateBody as $t, searchRebuildBody as A, httpUrl as An, fieldReorderBody as At, updateSectionBody as B, formatFileSize as Bt, userDetailSchema as C, bylinesListQuery as Cn, collectionListResponseSchema as Ct, usersListQuery as D, countResponseSchema as Dn, createCollectionBody as Dt, userUpdateBody as E, apiErrorSchema as En, collectionWithFieldsResponseSchema as Et, siteSettingsSchema as F, slugPattern as Fn, orphanedTableSchema as Ft, taxonomyListResponseSchema as G, mediaListQuery as Gt, createTermBody as H, mediaConfirmResponseSchema as Ht, createSectionBody as I, successEnvelope as In, schemaExportQuery as It, termResponseSchema as J, mediaResponseSchema as Jt, termGetResponseSchema as K, mediaListResponseSchema as Kt, sectionListResponseSchema as L, updateCollectionBody as Lt, searchResultSchema as M, localeFilterQuery as Mn, fieldSchema as Mt, searchSuggestQuery as N, offsetPaginationQuery as Nn, orphanRegisterBody as Nt, searchEnableBody as O, cursorPaginationQuery as On, createFieldBody as Ot, settingsUpdateBody as P, roleLevel as Pn, orphanedTableListResponseSchema as Pt, updateTermBody as Q, contentCompareResponseSchema as Qt, sectionSchema as R, updateFieldBody as Rt, allowedDomainUpdateBody as S, bylineUpdateBody as Sn, collectionGetQuery as St, userSchema as T, VALID_ROLE_LEVELS as Tn, collectionSchema as Tt, taxonomyDefSchema as U, mediaExistingResponseSchema as Ut, createTaxonomyDefBody as V, mediaConfirmBody as Vt, taxonomyDefTranslationsSchema as W, mediaItemSchema as Wt, termTranslationsSchema as X, mediaUploadUrlBody as Xt, termSchema as Y, mediaUpdateBody as Yt, termWithCountSchema as Z, mediaUploadUrlResponseSchema as Zt, widgetAreaSchema as _, bylineCreditSchema as _n, commentSchema as _t, notFoundPruneBody as a, contentResponseSchema as an, menuTranslationsSchema as at, widgetSchema as b, bylineTranslationCreateBody as bn, publicCommentListResponseSchema as bt, notFoundSummarySchema as c, contentSeoSchema as cn, updateMenuBody as ct, redirectsListQuery as d, contentTranslationsResponseSchema as dn, sanitizeHref as dt, contentItemSchema as en, createMenuItemBody as et, updateRedirectBody as f, contentTrashQuery as fn, adminCommentListResponseSchema as ft, updateWidgetBody as g, bylineCreateBody as gn, commentListQuery as gt, reorderWidgetsBody as h, trashedContentListResponseSchema as hn, commentCountsResponseSchema as ht, notFoundListResponseSchema as i, contentPublishBody as in, menuSchema as it, searchResponseSchema as j, localeCode as jn, fieldResponseSchema as jt, searchQuery as k, deleteResponseSchema as kn, fieldListResponseSchema as kt, redirectListResponseSchema as l, contentTermsBody as ln, updateMenuItemBody as lt, createWidgetBody as m, trashedContentItemSchema as mn, commentBulkResponseSchema as mt, notFoundEntrySchema as n, contentListResponseSchema as nn, menuItemTypeEnum as nt, notFoundSummaryQuery as o, contentScheduleBody as on, menuWithItemsSchema as ot, createWidgetAreaBody as p, contentUpdateBody as pn, commentBulkBody as pt, termListResponseSchema as q, mediaProviderListQuery as qt, notFoundListQuery as r, contentPreviewUrlBody as rn, menuListItemSchema as rt, notFoundSummaryResponseSchema as s, contentSeoInput as sn, reorderMenuItemsBody as st, createRedirectBody as t, contentListQuery as tn, menuItemSchema as tt, redirectSchema as u, contentTranslationSchema as un, isSafeHref as ut, widgetAreaWithWidgetsAndCountSchema as v, bylineListResponseSchema as vn, commentStatusBody as vt, userListResponseSchema as w, contentBylineInputSchema as wn, collectionResponseSchema as wt, allowedDomainCreateBody as x, bylineTranslationsResponseSchema as xn, publicCommentSchema as xt, widgetAreaWithWidgetsSchema as y, bylineSummarySchema as yn, createCommentBody as yt, sectionsListQuery as z, DEFAULT_MAX_UPLOAD_SIZE as zt };
1168
- //# sourceMappingURL=redirects-C0L9JUk4.mjs.map
1189
+ export { createMenuBody as $, contentAuthorsResponseSchema as $t, searchRebuildBody as A, cursorPaginationQuery as An, fieldReorderBody as At, updateSectionBody as B, formatFileSize as Bt, userDetailSchema as C, bylineTranslationsResponseSchema as Cn, collectionListResponseSchema as Ct, usersListQuery as D, VALID_ROLE_LEVELS as Dn, createCollectionBody as Dt, userUpdateBody as E, contentBylineInputSchema as En, collectionWithFieldsResponseSchema as Et, siteSettingsSchema as F, offsetPaginationQuery as Fn, orphanedTableSchema as Ft, taxonomyListResponseSchema as G, mediaListQuery as Gt, createTermBody as H, mediaConfirmResponseSchema as Ht, createSectionBody as I, roleLevel as In, schemaExportQuery as It, termResponseSchema as J, mediaResponseSchema as Jt, termGetResponseSchema as K, mediaListResponseSchema as Kt, sectionListResponseSchema as L, slugPattern as Ln, updateCollectionBody as Lt, searchResultSchema as M, httpUrl as Mn, fieldSchema as Mt, searchSuggestQuery as N, localeCode as Nn, orphanRegisterBody as Nt, searchEnableBody as O, apiErrorSchema as On, createFieldBody as Ot, settingsUpdateBody as P, localeFilterQuery as Pn, orphanedTableListResponseSchema as Pt, updateTermBody as Q, contentAuthorSchema as Qt, sectionSchema as R, successEnvelope as Rn, updateFieldBody as Rt, allowedDomainUpdateBody as S, bylineTranslationCreateBody as Sn, collectionGetQuery as St, userSchema as T, bylinesListQuery as Tn, collectionSchema as Tt, taxonomyDefSchema as U, mediaExistingResponseSchema as Ut, createTaxonomyDefBody as V, mediaConfirmBody as Vt, taxonomyDefTranslationsSchema as W, mediaItemSchema as Wt, termTranslationsSchema as X, mediaUploadUrlBody as Xt, termSchema as Y, mediaUpdateBody as Yt, termWithCountSchema as Z, mediaUploadUrlResponseSchema as Zt, widgetAreaSchema as _, trashedContentListResponseSchema as _n, commentSchema as _t, notFoundPruneBody as a, contentPreviewUrlBody as an, menuTranslationsSchema as at, widgetSchema as b, bylineListResponseSchema as bn, publicCommentListResponseSchema as bt, notFoundSummarySchema as c, contentScheduleBody as cn, updateMenuBody as ct, redirectsListQuery as d, contentTermsBody as dn, sanitizeHref as dt, contentCompareResponseSchema as en, createMenuItemBody as et, updateRedirectBody as f, contentTranslationSchema as fn, adminCommentListResponseSchema as ft, updateWidgetBody as g, trashedContentItemSchema as gn, commentListQuery as gt, reorderWidgetsBody as h, contentUpdateBody as hn, commentCountsResponseSchema as ht, notFoundListResponseSchema as i, contentListResponseSchema as in, menuSchema as it, searchResponseSchema as j, deleteResponseSchema as jn, fieldResponseSchema as jt, searchQuery as k, countResponseSchema as kn, fieldListResponseSchema as kt, redirectListResponseSchema as l, contentSeoInput as ln, updateMenuItemBody as lt, createWidgetBody as m, contentTrashQuery as mn, commentBulkResponseSchema as mt, notFoundEntrySchema as n, contentItemSchema as nn, menuItemTypeEnum as nt, notFoundSummaryQuery as o, contentPublishBody as on, menuWithItemsSchema as ot, createWidgetAreaBody as p, contentTranslationsResponseSchema as pn, commentBulkBody as pt, termListResponseSchema as q, mediaProviderListQuery as qt, notFoundListQuery as r, contentListQuery as rn, menuListItemSchema as rt, notFoundSummaryResponseSchema as s, contentResponseSchema as sn, reorderMenuItemsBody as st, createRedirectBody as t, contentCreateBody as tn, menuItemSchema as tt, redirectSchema as u, contentSeoSchema as un, isSafeHref as ut, widgetAreaWithWidgetsAndCountSchema as v, bylineCreateBody as vn, commentStatusBody as vt, userListResponseSchema as w, bylineUpdateBody as wn, collectionResponseSchema as wt, allowedDomainCreateBody as x, bylineSummarySchema as xn, publicCommentSchema as xt, widgetAreaWithWidgetsSchema as y, bylineCreditSchema as yn, createCommentBody as yt, sectionsListQuery as z, DEFAULT_MAX_UPLOAD_SIZE as zt };
1190
+ //# sourceMappingURL=redirects-DEygMrRO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects-DEygMrRO.mjs","names":[],"sources":["../src/api/schemas/common.ts","../src/api/schemas/bylines.ts","../src/api/schemas/content.ts","../src/api/schemas/media.ts","../src/api/schemas/schema.ts","../src/api/schemas/comments.ts","../src/utils/url.ts","../src/api/schemas/menus.ts","../src/api/schemas/taxonomies.ts","../src/api/schemas/sections.ts","../src/api/schemas/settings.ts","../src/api/schemas/search.ts","../src/api/schemas/users.ts","../src/api/schemas/widgets.ts","../src/api/schemas/redirects.ts"],"sourcesContent":["import { z } from \"zod\";\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.string()\n\t.url()\n\t.refine((url) => HTTP_SCHEME_RE.test(url), \"URL must use http or https\");\n\n/** BCP 47 locale code — language with optional script/region subtags (e.g. en, en-US, pt-BR, es-419, zh-Hant) */\nexport const localeCode = z\n\t.string()\n\t.regex(/^[a-z]{2,3}(-[a-z0-9]{2,8})*$/i, \"Invalid locale code\")\n\t.transform((v) => v.toLowerCase());\n\n/** Shared `?locale=xx` query shape for endpoints that filter by locale. */\nexport const localeFilterQuery = z\n\t.object({\n\t\tlocale: z.string().min(1).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\terror: z.object({\n\t\t\tcode: z.string().meta({ description: \"Machine-readable error code\", example: \"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: { data: T } */\nexport function successEnvelope<T extends z.ZodType>(dataSchema: T) {\n\treturn z.object({ data: dataSchema });\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 { cursorPaginationQuery, httpUrl } from \"./common.js\";\n\n/** Slug pattern: lowercase letters, digits, and hyphens; must start with a letter */\nconst bylineSlugPattern = /^[a-z][a-z0-9-]*$/;\n\nexport const bylineSummarySchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tslug: z.string(),\n\t\tdisplayName: z.string(),\n\t\tbio: z.string().nullable(),\n\t\tavatarMediaId: z.string().nullable(),\n\t\t/**\n\t\t * Avatar media storage key + alt, folded in by the media join during\n\t\t * content byline hydration. Null on the plain byline finders, which\n\t\t * don't join media.\n\t\t */\n\t\tavatarStorageKey: z.string().nullish(),\n\t\tavatarAlt: z.string().nullish(),\n\t\twebsiteUrl: z.string().nullable(),\n\t\tuserId: z.string().nullable(),\n\t\tisGuest: z.boolean(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t\t/** Locale this byline row is presented in (migration 040). */\n\t\tlocale: z.string(),\n\t\t/**\n\t\t * Shared across translations of the same byline (migration 040).\n\t\t * Equals `id` for the anchor row; siblings inherit it from their\n\t\t * source. Nullable in storage for backwards compatibility.\n\t\t */\n\t\ttranslationGroup: z.string().nullable(),\n\t\t/**\n\t\t * Byline custom-field values (Discussion #1174). Keys are slugs\n\t\t * registered via the byline-fields admin API; values follow\n\t\t * `CustomFieldValue` (`string | boolean | null`). Always present\n\t\t * on hydrated responses — empty `{}` when no fields are\n\t\t * registered (Phase 3 AC #6). Marked optional in the schema for\n\t\t * historic-payload compatibility with pre-Phase-3 clients that\n\t\t * may not send the key on writes; hydration always populates it.\n\t\t */\n\t\tcustomFields: z.record(z.string(), z.union([z.string(), z.boolean(), z.null()])).optional(),\n\t})\n\t.meta({ id: \"BylineSummary\" });\n\nexport const bylineCreditSchema = z\n\t.object({\n\t\tbyline: bylineSummarySchema,\n\t\tsortOrder: z.number().int(),\n\t\troleLabel: z.string().nullable(),\n\t\tsource: z.enum([\"explicit\", \"inferred\"]).optional().meta({\n\t\t\tdescription: \"Whether this credit was explicitly assigned or inferred from authorId\",\n\t\t}),\n\t})\n\t.meta({ id: \"BylineCredit\" });\n\nexport const contentBylineInputSchema = z\n\t.object({\n\t\tbylineId: z.string().min(1),\n\t\troleLabel: z.string().nullish(),\n\t})\n\t.meta({ id: \"ContentBylineInput\" });\n\nexport const bylinesListQuery = cursorPaginationQuery\n\t.extend({\n\t\tsearch: z.string().optional(),\n\t\tisGuest: z.coerce.boolean().optional(),\n\t\tuserId: z.string().optional(),\n\t\t/**\n\t\t * Filter by locale (strict per-locale matching, post-migration 040).\n\t\t * Rejects empty strings so the picker can't silently fetch the\n\t\t * unfiltered list when the admin URL has `?locale=` with no value.\n\t\t */\n\t\tlocale: z.string().min(1).optional(),\n\t})\n\t.meta({ id: \"BylinesListQuery\" });\n\nexport const bylineCreateBody = z\n\t.object({\n\t\tslug: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.regex(bylineSlugPattern, \"Slug must contain only lowercase letters, digits, and hyphens\"),\n\t\tdisplayName: z.string().min(1),\n\t\tbio: z.string().nullish(),\n\t\tavatarMediaId: z.string().nullish(),\n\t\twebsiteUrl: httpUrl.nullish(),\n\t\tuserId: z.string().nullish(),\n\t\tisGuest: z.boolean().optional(),\n\t\t/**\n\t\t * Locale this byline row belongs to. When omitted, the DB DEFAULT (the\n\t\t * configured `defaultLocale`) is used. Rejects empty strings — an\n\t\t * empty locale would create rows no resolver requests.\n\t\t */\n\t\tlocale: z.string().min(1).optional(),\n\t\t/**\n\t\t * When set, the new row joins the source byline's translation_group\n\t\t * rather than minting a fresh one. Requires `locale`.\n\t\t */\n\t\ttranslationOf: z.string().min(1).optional(),\n\t\t/**\n\t\t * Byline custom-field values (Discussion #1174, Phase 6 — create-flow\n\t\t * parity with update). Keys are field slugs; values are unknown at\n\t\t * the API layer because the per-field type contract lives in the\n\t\t * registry and would require an extra query to enforce here. The\n\t\t * repository's `coerceFieldValue` validates against the field's\n\t\t * type and throws `EmDashValidationError` on mismatch — the route\n\t\t * maps that to a 400 `VALIDATION_ERROR`. Reserved-slug write\n\t\t * attempts fall out as `EmDashValidationError(\"Unknown byline\n\t\t * custom field …\")` because no registered field claims a reserved\n\t\t * slug.\n\t\t */\n\t\tcustomFields: z.record(z.string(), z.unknown()).optional(),\n\t})\n\t.meta({ id: \"BylineCreateBody\" });\n\nexport const bylineTranslationCreateBody = z\n\t.object({\n\t\tlocale: z.string().min(1),\n\t\tslug: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.regex(bylineSlugPattern, \"Slug must contain only lowercase letters, digits, and hyphens\")\n\t\t\t.optional(),\n\t\tdisplayName: z.string().min(1).optional(),\n\t\tbio: z.string().nullish(),\n\t\tavatarMediaId: z.string().nullish(),\n\t\twebsiteUrl: httpUrl.nullish(),\n\t})\n\t.meta({ id: \"BylineTranslationCreateBody\" });\n\nexport const bylineTranslationsResponseSchema = z\n\t.object({\n\t\titems: z.array(bylineSummarySchema),\n\t})\n\t.meta({ id: \"BylineTranslationsResponse\" });\n\nexport const bylineUpdateBody = z\n\t.object({\n\t\tslug: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.regex(bylineSlugPattern, \"Slug must contain only lowercase letters, digits, and hyphens\")\n\t\t\t.optional(),\n\t\tdisplayName: z.string().min(1).optional(),\n\t\tbio: z.string().nullish(),\n\t\tavatarMediaId: z.string().nullish(),\n\t\twebsiteUrl: httpUrl.nullish(),\n\t\tuserId: z.string().nullish(),\n\t\tisGuest: z.boolean().optional(),\n\t\t/**\n\t\t * Byline custom-field values (Discussion #1174, Phase 3+4). Keys\n\t\t * are field slugs; values are unknown at the API layer because\n\t\t * the per-field type contract lives in the registry and would\n\t\t * require an extra query to enforce here. The repository's\n\t\t * `coerceFieldValue` validates against the field's type and\n\t\t * throws `EmDashValidationError` on mismatch — the route maps\n\t\t * that to a 400 `VALIDATION_ERROR`. Reserved-slug write attempts\n\t\t * fall out as `EmDashValidationError(\"Unknown byline custom\n\t\t * field …\")` because no registered field claims a reserved slug.\n\t\t */\n\t\tcustomFields: z.record(z.string(), z.unknown()).optional(),\n\t})\n\t.meta({ id: \"BylineUpdateBody\" });\n\nexport const bylineListResponseSchema = z\n\t.object({\n\t\titems: z.array(bylineSummarySchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"BylineListResponse\" });\n","import { z } from \"zod\";\n\nimport { bylineSummarySchema, bylineCreditSchema, contentBylineInputSchema } from \"./bylines.js\";\nimport { cursorPaginationQuery, httpUrl, localeCode } from \"./common.js\";\n\n// ---------------------------------------------------------------------------\n// Content: Input schemas\n// ---------------------------------------------------------------------------\n\n/** SEO input — per-content meta fields */\nexport const contentSeoInput = z\n\t.object({\n\t\ttitle: z.string().max(200).nullish(),\n\t\tdescription: z.string().max(500).nullish(),\n\t\timage: z.string().nullish(),\n\t\tcanonical: httpUrl.nullish(),\n\t\tnoIndex: z.boolean().optional(),\n\t})\n\t.meta({ id: \"ContentSeoInput\" });\n\n/** ISO 8601 date or datetime bound for the content-list date range filter. */\nconst contentDateBound = z\n\t.union([\n\t\tz.iso.datetime({ offset: true, message: \"must be an ISO 8601 datetime\" }),\n\t\tz.iso.date({ message: \"must be an ISO 8601 date\" }),\n\t])\n\t.optional();\n\nexport const contentListQuery = cursorPaginationQuery\n\t.extend({\n\t\tstatus: z.string().optional(),\n\t\torderBy: z.string().optional(),\n\t\torder: z.enum([\"asc\", \"desc\"]).optional(),\n\t\tlocale: localeCode.optional(),\n\t\t/** Case-insensitive substring search across the collection's title/name/slug. */\n\t\tq: z.string().trim().min(1).max(200).optional(),\n\t\t/** Filter to entries authored by this user (the `author_id` column). */\n\t\tauthorId: z.string().min(1).max(64).optional(),\n\t\t/** Which timestamp column the `dateFrom`/`dateTo` range applies to. */\n\t\tdateField: z.enum([\"createdAt\", \"updatedAt\", \"publishedAt\"]).optional(),\n\t\t/** Inclusive lower bound for the date range. Requires `dateField`. */\n\t\tdateFrom: contentDateBound,\n\t\t/** Inclusive upper bound for the date range. Requires `dateField`. */\n\t\tdateTo: contentDateBound,\n\t})\n\t.meta({ id: \"ContentListQuery\" });\n\n/** ISO 8601 datetime for `publishedAt` / `createdAt`. Routes gate writes behind `content:publish_any`. */\nconst contentDateOverride = z.iso\n\t.datetime({ offset: true, message: \"must be an ISO 8601 datetime\" })\n\t.nullish();\n\nexport const contentCreateBody = z\n\t.object({\n\t\tdata: z.record(z.string(), z.unknown()),\n\t\tslug: z.string().nullish(),\n\t\tstatus: z.enum([\"draft\"]).optional(),\n\t\tbylines: z.array(contentBylineInputSchema).optional(),\n\t\tlocale: localeCode.optional(),\n\t\ttranslationOf: z.string().optional(),\n\t\tseo: contentSeoInput.optional(),\n\t\tpublishedAt: contentDateOverride,\n\t\tcreatedAt: contentDateOverride,\n\t})\n\t.meta({ id: \"ContentCreateBody\" });\n\nexport const contentUpdateBody = z\n\t.object({\n\t\tdata: z.record(z.string(), z.unknown()).optional(),\n\t\tslug: z.string().nullish(),\n\t\tstatus: z.enum([\"draft\"]).optional(),\n\t\tauthorId: z.string().nullish(),\n\t\tbylines: z.array(contentBylineInputSchema).optional(),\n\t\t_rev: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.meta({ description: \"Opaque revision token for optimistic concurrency\" }),\n\t\tskipRevision: z.boolean().optional(),\n\t\tseo: contentSeoInput.optional(),\n\t\tpublishedAt: contentDateOverride,\n\t})\n\t.meta({ id: \"ContentUpdateBody\" });\n\nexport const contentScheduleBody = z\n\t.object({\n\t\tscheduledAt: z.string().min(1, \"scheduledAt is required\").meta({\n\t\t\tdescription: \"ISO 8601 datetime for scheduled publishing\",\n\t\t\texample: \"2025-06-15T09:00:00Z\",\n\t\t}),\n\t})\n\t.meta({ id: \"ContentScheduleBody\" });\n\nexport const contentPublishBody = z\n\t.object({\n\t\t// .optional() rather than .nullish(): publishing has no semantic\n\t\t// meaning for `null` (you can't \"clear\" a publish timestamp by\n\t\t// publishing). Tightening the schema here means callers either\n\t\t// pass a valid datetime or omit the field, and the route doesn't\n\t\t// have to silently drop a null that snuck through.\n\t\tpublishedAt: z.iso\n\t\t\t.datetime({ offset: true, message: \"must be an ISO 8601 datetime\" })\n\t\t\t.optional()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Optional ISO 8601 datetime to backdate the publish (e.g. when migrating content). Requires content:publish_any permission. Without this, existing published_at is preserved on re-publish.\",\n\t\t\t}),\n\t})\n\t.meta({ id: \"ContentPublishBody\" });\n\nexport const contentPreviewUrlBody = z\n\t.object({\n\t\texpiresIn: z.union([z.string(), z.number()]).optional(),\n\t\tpathPattern: z.string().optional(),\n\t})\n\t.meta({ id: \"ContentPreviewUrlBody\" });\n\nexport const contentTermsBody = z\n\t.object({\n\t\ttermIds: z.array(z.string()),\n\t})\n\t.meta({ id: \"ContentTermsBody\" });\n\nexport const contentTrashQuery = cursorPaginationQuery;\n\n// ---------------------------------------------------------------------------\n// Content: Response schemas\n// ---------------------------------------------------------------------------\n\n/** SEO metadata on a content item */\nexport const contentSeoSchema = z\n\t.object({\n\t\ttitle: z.string().nullable(),\n\t\tdescription: z.string().nullable(),\n\t\timage: z.string().nullable(),\n\t\tcanonical: z.string().nullable(),\n\t\tnoIndex: z.boolean(),\n\t})\n\t.meta({ id: \"ContentSeo\" });\n\n/** A single content item as returned by the API */\nexport const contentItemSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\ttype: z.string().meta({ description: \"Collection slug this item belongs to\" }),\n\t\tslug: z.string().nullable(),\n\t\tstatus: z.string().meta({ description: \"draft, published, or scheduled\" }),\n\t\tdata: z.record(z.string(), z.unknown()).meta({\n\t\t\tdescription: \"User-defined field values\",\n\t\t}),\n\t\tauthorId: z.string().nullable(),\n\t\tprimaryBylineId: z.string().nullable(),\n\t\tbyline: bylineSummarySchema.nullable().optional(),\n\t\tbylines: z.array(bylineCreditSchema).optional(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t\tpublishedAt: z.string().nullable(),\n\t\tscheduledAt: z.string().nullable(),\n\t\tliveRevisionId: z.string().nullable(),\n\t\tdraftRevisionId: z.string().nullable(),\n\t\tversion: z.number().int(),\n\t\tlocale: z.string().nullable(),\n\t\ttranslationGroup: z.string().nullable(),\n\t\tseo: contentSeoSchema.optional(),\n\t})\n\t.meta({ id: \"ContentItem\" });\n\n/** Response for single content item endpoints (get, create, update) */\nexport const contentResponseSchema = z\n\t.object({\n\t\titem: contentItemSchema,\n\t\t_rev: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.meta({ description: \"Opaque revision token for optimistic concurrency\" }),\n\t})\n\t.meta({ id: \"ContentResponse\" });\n\n/** Response for content list endpoints */\nexport const contentListResponseSchema = z\n\t.object({\n\t\titems: z.array(contentItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t\ttotal: z.number().int().nonnegative().optional(),\n\t})\n\t.meta({ id: \"ContentListResponse\" });\n\n/** A distinct content author for the admin author filter */\nexport const contentAuthorSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tname: z.string().nullable(),\n\t\temail: z.string(),\n\t\tavatarUrl: z.string().nullable(),\n\t})\n\t.meta({ id: \"ContentAuthor\" });\n\n/** Response for the content authors endpoint */\nexport const contentAuthorsResponseSchema = z\n\t.object({\n\t\titems: z.array(contentAuthorSchema),\n\t})\n\t.meta({ id: \"ContentAuthorsResponse\" });\n\n/** Trashed content item */\nexport const trashedContentItemSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\ttype: z.string(),\n\t\tslug: z.string().nullable(),\n\t\tstatus: z.string(),\n\t\tdata: z.record(z.string(), z.unknown()),\n\t\tauthorId: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t\tpublishedAt: z.string().nullable(),\n\t\tdeletedAt: z.string(),\n\t})\n\t.meta({ id: \"TrashedContentItem\" });\n\n/** Response for trashed content list */\nexport const trashedContentListResponseSchema = z\n\t.object({\n\t\titems: z.array(trashedContentItemSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"TrashedContentListResponse\" });\n\n/** Response for content compare (live vs draft) */\nexport const contentCompareResponseSchema = z\n\t.object({\n\t\thasChanges: z.boolean(),\n\t\tlive: z.record(z.string(), z.unknown()).nullable(),\n\t\tdraft: z.record(z.string(), z.unknown()).nullable(),\n\t})\n\t.meta({ id: \"ContentCompareResponse\" });\n\n/** Translation summary for a content item */\nexport const contentTranslationSchema = z.object({\n\tid: z.string(),\n\tlocale: z.string().nullable(),\n\tslug: z.string().nullable(),\n\tstatus: z.string(),\n\tupdatedAt: z.string(),\n});\n\n/** Response for content translations endpoint */\nexport const contentTranslationsResponseSchema = z\n\t.object({\n\t\ttranslationGroup: z.string(),\n\t\ttranslations: z.array(contentTranslationSchema),\n\t})\n\t.meta({ id: \"ContentTranslationsResponse\" });\n","import { z } from \"zod\";\n\nimport { cursorPaginationQuery } from \"./common.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\tmimeType: mimeTypeFilter,\n\t\t/** Case-insensitive filename substring search (also matches extensions). */\n\t\tq: z.string().trim().min(1).max(200).optional(),\n\t})\n\t.meta({ id: \"MediaListQuery\" });\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})\n\t.meta({ id: \"MediaUpdateBody\" });\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.\nconst 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.positive()\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})\n\t\t.meta({ id: \"MediaUploadUrlBody\" });\n}\n\nexport const mediaConfirmBody = z\n\t.object({\n\t\tsize: z.number().int().positive().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\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})\n\t.meta({ id: \"MediaItem\" });\n\nexport const mediaResponseSchema = z\n\t.object({ item: mediaItemSchema })\n\t.meta({ id: \"MediaResponse\" });\n\nexport const mediaListResponseSchema = z\n\t.object({\n\t\titems: z.array(mediaItemSchema),\n\t\tnextCursor: z.string().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","import { z } from \"zod\";\n\nimport { slugPattern } from \"./common.js\";\n\n// ---------------------------------------------------------------------------\n// Schema (collections & fields): Input schemas\n// ---------------------------------------------------------------------------\n\nconst collectionSupportValues = z.enum([\"drafts\", \"revisions\", \"preview\", \"scheduling\", \"search\"]);\n\nconst collectionSourcePattern = /^(template:.+|import:.+|manual|discovered|seed)$/;\n\nconst fieldTypeValues = z.enum([\n\t\"string\",\n\t\"text\",\n\t\"url\",\n\t\"number\",\n\t\"integer\",\n\t\"boolean\",\n\t\"datetime\",\n\t\"select\",\n\t\"multiSelect\",\n\t\"portableText\",\n\t\"image\",\n\t\"file\",\n\t\"reference\",\n\t\"json\",\n\t\"slug\",\n\t\"repeater\",\n]);\n\nconst repeaterSubFieldSchema = z.object({\n\tslug: z.string().min(1).max(63).regex(slugPattern, \"Invalid slug format\"),\n\ttype: z.enum([\"string\", \"text\", \"number\", \"integer\", \"boolean\", \"datetime\", \"select\"]),\n\tlabel: z.string().min(1),\n\trequired: z.boolean().optional(),\n\toptions: z.array(z.string()).optional(),\n});\n\nconst fieldValidation = z\n\t.object({\n\t\trequired: z.boolean().optional(),\n\t\tmin: z.number().optional(),\n\t\tmax: z.number().optional(),\n\t\tminLength: z.number().int().min(0).optional(),\n\t\tmaxLength: z.number().int().min(0).optional(),\n\t\tpattern: z.string().optional(),\n\t\toptions: z.array(z.string()).optional(),\n\t\tsubFields: z.array(repeaterSubFieldSchema).min(1).optional(),\n\t\tminItems: z.number().int().min(0).optional(),\n\t\tmaxItems: z.number().int().min(1).optional(),\n\t\tallowedMimeTypes: z\n\t\t\t.array(\n\t\t\t\tz\n\t\t\t\t\t.string()\n\t\t\t\t\t.regex(/^[a-z0-9][a-z0-9!#$&^_+\\-.]*\\/[a-z0-9!#$&^_+\\-.]*$/i, \"Invalid MIME type\"),\n\t\t\t)\n\t\t\t.min(1, \"allowedMimeTypes must not be empty — omit the field to allow all types\")\n\t\t\t.max(64, \"allowedMimeTypes may contain at most 64 entries\")\n\t\t\t.optional(),\n\t})\n\t.optional();\n\nconst fieldWidgetOptions = z.record(z.string(), z.unknown()).optional();\n\nexport const createCollectionBody = z\n\t.object({\n\t\tslug: z.string().min(1).max(63).regex(slugPattern, \"Invalid slug format\"),\n\t\tlabel: z.string().min(1),\n\t\tlabelSingular: z.string().optional(),\n\t\tdescription: z.string().optional(),\n\t\ticon: z.string().optional(),\n\t\tsupports: z.array(collectionSupportValues).optional(),\n\t\tsource: z.string().regex(collectionSourcePattern).optional(),\n\t\turlPattern: z.string().optional(),\n\t\thasSeo: z.boolean().optional(),\n\t})\n\t.meta({ id: \"CreateCollectionBody\" });\n\nexport const updateCollectionBody = z\n\t.object({\n\t\tlabel: z.string().min(1).optional(),\n\t\tlabelSingular: z.string().optional(),\n\t\tdescription: z.string().optional(),\n\t\ticon: z.string().optional(),\n\t\tsupports: z.array(collectionSupportValues).optional(),\n\t\turlPattern: z.string().nullish(),\n\t\thasSeo: z.boolean().optional(),\n\t\tcommentsEnabled: z.boolean().optional(),\n\t\tcommentsModeration: z.enum([\"all\", \"first_time\", \"none\"]).optional(),\n\t\tcommentsClosedAfterDays: z.number().int().min(0).optional(),\n\t\tcommentsAutoApproveUsers: z.boolean().optional(),\n\t})\n\t.meta({ id: \"UpdateCollectionBody\" });\n\nexport const createFieldBody = z\n\t.object({\n\t\tslug: z.string().min(1).max(63).regex(slugPattern, \"Invalid slug format\"),\n\t\tlabel: z.string().min(1),\n\t\ttype: fieldTypeValues,\n\t\trequired: z.boolean().optional(),\n\t\tunique: z.boolean().optional(),\n\t\tdefaultValue: z.unknown().optional(),\n\t\tvalidation: fieldValidation.nullable(),\n\t\twidget: z.string().optional(),\n\t\toptions: fieldWidgetOptions,\n\t\tsortOrder: z.number().int().min(0).optional(),\n\t\tsearchable: z.boolean().optional(),\n\t\ttranslatable: z.boolean().optional(),\n\t})\n\t.meta({ id: \"CreateFieldBody\" });\n\nexport const updateFieldBody = z\n\t.object({\n\t\tlabel: z.string().min(1).optional(),\n\t\trequired: z.boolean().optional(),\n\t\tunique: z.boolean().optional(),\n\t\tdefaultValue: z.unknown().optional(),\n\t\tvalidation: fieldValidation.nullable(),\n\t\twidget: z.string().optional(),\n\t\toptions: fieldWidgetOptions,\n\t\tsortOrder: z.number().int().min(0).optional(),\n\t\tsearchable: z.boolean().optional(),\n\t\ttranslatable: z.boolean().optional(),\n\t})\n\t.meta({ id: \"UpdateFieldBody\" });\n\nexport const fieldReorderBody = z\n\t.object({\n\t\tfieldSlugs: z.array(z.string().min(1)),\n\t})\n\t.meta({ id: \"FieldReorderBody\" });\n\nexport const orphanRegisterBody = z\n\t.object({\n\t\tlabel: z.string().optional(),\n\t\tlabelSingular: z.string().optional(),\n\t\tdescription: z.string().optional(),\n\t})\n\t.meta({ id: \"OrphanRegisterBody\" });\n\nexport const schemaExportQuery = z.object({\n\tformat: z.string().optional(),\n});\n\nexport const collectionGetQuery = z.object({\n\tincludeFields: z\n\t\t.string()\n\t\t.transform((v) => v === \"true\")\n\t\t.optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Schema: Response schemas\n// ---------------------------------------------------------------------------\n\nexport const collectionSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tslug: z.string(),\n\t\tlabel: z.string(),\n\t\tlabelSingular: z.string().nullable(),\n\t\tdescription: z.string().nullable(),\n\t\ticon: z.string().nullable(),\n\t\tsupports: z.array(z.string()),\n\t\tsource: z.string().nullable(),\n\t\turlPattern: z.string().nullable(),\n\t\thasSeo: z.boolean(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"Collection\" });\n\nexport const fieldSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tcollectionId: z.string(),\n\t\tslug: z.string(),\n\t\tlabel: z.string(),\n\t\ttype: fieldTypeValues,\n\t\trequired: z.boolean(),\n\t\tunique: z.boolean(),\n\t\tdefaultValue: z.unknown().nullable(),\n\t\tvalidation: z.record(z.string(), z.unknown()).nullable(),\n\t\twidget: z.string().nullable(),\n\t\toptions: z.record(z.string(), z.unknown()).nullable(),\n\t\tsortOrder: z.number().int(),\n\t\tsearchable: z.boolean(),\n\t\ttranslatable: z.boolean(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"Field\" });\n\nexport const collectionResponseSchema = z\n\t.object({ item: collectionSchema })\n\t.meta({ id: \"CollectionResponse\" });\n\nexport const collectionWithFieldsResponseSchema = z\n\t.object({\n\t\titem: collectionSchema.extend({ fields: z.array(fieldSchema) }),\n\t})\n\t.meta({ id: \"CollectionWithFieldsResponse\" });\n\nexport const collectionListResponseSchema = z\n\t.object({ items: z.array(collectionSchema) })\n\t.meta({ id: \"CollectionListResponse\" });\n\nexport const fieldResponseSchema = z.object({ item: fieldSchema }).meta({ id: \"FieldResponse\" });\n\nexport const fieldListResponseSchema = z\n\t.object({ items: z.array(fieldSchema) })\n\t.meta({ id: \"FieldListResponse\" });\n\nexport const orphanedTableSchema = z\n\t.object({\n\t\tslug: z.string(),\n\t\ttableName: z.string(),\n\t\trowCount: z.number().int(),\n\t})\n\t.meta({ id: \"OrphanedTable\" });\n\nexport const orphanedTableListResponseSchema = z\n\t.object({ items: z.array(orphanedTableSchema) })\n\t.meta({ id: \"OrphanedTableListResponse\" });\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Comments: Input schemas\n// ---------------------------------------------------------------------------\n\nexport const createCommentBody = z\n\t.object({\n\t\tauthorName: z.string().min(1).max(100),\n\t\tauthorEmail: z.string().email(),\n\t\tbody: z.string().min(1).max(5000),\n\t\tparentId: z.string().optional(),\n\t\t/** Honeypot field — hidden in the form, filled only by bots */\n\t\twebsite_url: z.string().optional(),\n\t})\n\t.meta({ id: \"CreateCommentBody\" });\n\nexport const commentStatusBody = z\n\t.object({\n\t\tstatus: z.enum([\"approved\", \"pending\", \"spam\", \"trash\"]),\n\t})\n\t.meta({ id: \"CommentStatusBody\" });\n\nexport const commentBulkBody = z\n\t.object({\n\t\tids: z.array(z.string().min(1)).min(1).max(100),\n\t\taction: z.enum([\"approve\", \"spam\", \"trash\", \"delete\"]),\n\t})\n\t.meta({ id: \"CommentBulkBody\" });\n\nexport const commentListQuery = z\n\t.object({\n\t\tstatus: z.enum([\"pending\", \"approved\", \"spam\", \"trash\"]).optional(),\n\t\tcollection: z.string().optional(),\n\t\tsearch: z.string().optional(),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n\t\tcursor: z.string().max(2048).optional(),\n\t})\n\t.meta({ id: \"CommentListQuery\" });\n\n// ---------------------------------------------------------------------------\n// Comments: Response schemas\n// ---------------------------------------------------------------------------\n\nconst commentStatusValues = z.enum([\"pending\", \"approved\", \"spam\", \"trash\"]);\n\n/**\n * Public-facing comment (no email/IP).\n *\n * `replies` is recursive in practice (each reply can have replies), but we\n * model it as a single level here to avoid circular type inference issues\n * with tsgo. OpenAPI consumers should treat replies as the same shape.\n */\nexport const publicCommentSchema: z.ZodObject<{\n\tid: z.ZodString;\n\tauthorName: z.ZodString;\n\tisRegisteredUser: z.ZodBoolean;\n\tbody: z.ZodString;\n\tparentId: z.ZodNullable<z.ZodString>;\n\tcreatedAt: z.ZodString;\n\treplies: z.ZodOptional<z.ZodArray<z.ZodAny>>;\n}> = z\n\t.object({\n\t\tid: z.string(),\n\t\tauthorName: z.string(),\n\t\tisRegisteredUser: z.boolean(),\n\t\tbody: z.string(),\n\t\tparentId: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t\treplies: z.array(z.any()).optional(),\n\t})\n\t.meta({ id: \"PublicComment\" });\n\n/** Admin comment with full details */\nexport const commentSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tcollection: z.string(),\n\t\tcontentId: z.string(),\n\t\tauthorName: z.string(),\n\t\tauthorEmail: z.string(),\n\t\tbody: z.string(),\n\t\tstatus: commentStatusValues,\n\t\tparentId: z.string().nullable(),\n\t\tipHash: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"Comment\" });\n\nexport const publicCommentListResponseSchema = z\n\t.object({\n\t\titems: z.array(publicCommentSchema),\n\t\tnextCursor: z.string().optional(),\n\t\ttotal: z.number().int(),\n\t})\n\t.meta({ id: \"PublicCommentListResponse\" });\n\nexport const adminCommentListResponseSchema = z\n\t.object({\n\t\titems: z.array(commentSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"AdminCommentListResponse\" });\n\nexport const commentCountsResponseSchema = z\n\t.object({\n\t\tpending: z.number().int(),\n\t\tapproved: z.number().int(),\n\t\tspam: z.number().int(),\n\t\ttrash: z.number().int(),\n\t})\n\t.meta({ id: \"CommentCountsResponse\" });\n\nexport const commentBulkResponseSchema = z\n\t.object({ affected: z.number().int() })\n\t.meta({ id: \"CommentBulkResponse\" });\n","/**\n * URL scheme validation utilities\n *\n * Prevents XSS via dangerous URL schemes (javascript:, data:, vbscript:, etc.)\n * by allowlisting known-safe schemes before rendering into href attributes.\n */\n\n/**\n * Matches URLs that are safe to render in href attributes.\n *\n * Allowed:\n * - http:// and https://\n * - mailto: and tel:\n * - Relative paths (starting with /)\n * - Fragment links (starting with #)\n * - Protocol-relative URLs are NOT allowed (starting with //) as they can\n * redirect to attacker-controlled hosts.\n */\nconst SAFE_URL_SCHEME_RE = /^(https?:|mailto:|tel:|\\/(?!\\/)|#)/i;\n\n/**\n * Returns the URL unchanged if it uses a safe scheme, otherwise returns \"#\".\n *\n * Use this at the render layer as the primary defense against XSS via\n * dangerous URL schemes like `javascript:`, `data:`, or `vbscript:`.\n *\n * @example\n * ```ts\n * sanitizeHref(\"https://example.com\") // \"https://example.com\"\n * sanitizeHref(\"/about\") // \"/about\"\n * sanitizeHref(\"#section\") // \"#section\"\n * sanitizeHref(\"mailto:a@b.com\") // \"mailto:a@b.com\"\n * sanitizeHref(\"javascript:alert(1)\") // \"#\"\n * sanitizeHref(\"data:text/html,<script>\") // \"#\"\n * sanitizeHref(\"\") // \"#\"\n * ```\n */\nexport function sanitizeHref(url: string | undefined | null): string {\n\tif (!url) return \"#\";\n\treturn SAFE_URL_SCHEME_RE.test(url) ? url : \"#\";\n}\n\n/**\n * Returns true if the URL uses a safe scheme for rendering in href attributes.\n */\nexport function isSafeHref(url: string): boolean {\n\treturn SAFE_URL_SCHEME_RE.test(url);\n}\n","import { z } from \"zod\";\n\nimport { isSafeHref } from \"../../utils/url.js\";\n\n// ---------------------------------------------------------------------------\n// Menus: Input schemas\n// ---------------------------------------------------------------------------\n\n/**\n * Allowed menu item types. `custom` uses `customUrl`; the others resolve a URL\n * from `referenceCollection` + `referenceId` (a translation_group id).\n */\nexport const menuItemTypeEnum = z.enum([\"custom\", \"page\", \"post\", \"taxonomy\", \"collection\"]);\n\nconst safeHref = z\n\t.string()\n\t.trim()\n\t.refine(\n\t\tisSafeHref,\n\t\t\"URL must use http, https, mailto, tel, a relative path, or a fragment identifier\",\n\t);\n\nexport const createMenuBody = z\n\t.object({\n\t\tname: z.string().min(1),\n\t\tlabel: z.string().min(1),\n\t\tlocale: z.string().min(1).optional(),\n\t\t/** When set, clones the items from the source menu. The new menu joins\n\t\t * the source's translation_group. */\n\t\ttranslationOf: z.string().min(1).optional(),\n\t})\n\t.strict()\n\t.meta({ id: \"CreateMenuBody\" });\n\nexport const updateMenuBody = z\n\t.object({\n\t\tlabel: z.string().min(1).optional(),\n\t})\n\t.strict()\n\t.meta({ id: \"UpdateMenuBody\" });\n\nexport const createMenuItemBody = z\n\t.object({\n\t\ttype: menuItemTypeEnum,\n\t\tlabel: z.string().min(1),\n\t\treferenceCollection: z.string().optional(),\n\t\treferenceId: z.string().optional(),\n\t\tcustomUrl: safeHref.optional(),\n\t\ttarget: z.string().optional(),\n\t\ttitleAttr: z.string().optional(),\n\t\tcssClasses: z.string().optional(),\n\t\tparentId: z.string().optional(),\n\t\tsortOrder: z.number().int().min(0).optional(),\n\t})\n\t.strict()\n\t.meta({ id: \"CreateMenuItemBody\" });\n\nexport const updateMenuItemBody = z\n\t.object({\n\t\tlabel: z.string().min(1).optional(),\n\t\tcustomUrl: safeHref.optional(),\n\t\ttarget: z.string().optional(),\n\t\ttitleAttr: z.string().optional(),\n\t\tcssClasses: z.string().optional(),\n\t\tparentId: z.string().nullish(),\n\t\tsortOrder: z.number().int().min(0).optional(),\n\t})\n\t.strict()\n\t.meta({ id: \"UpdateMenuItemBody\" });\n\nexport const reorderMenuItemsBody = z\n\t.object({\n\t\titems: z.array(\n\t\t\tz.object({\n\t\t\t\tid: z.string().min(1),\n\t\t\t\tparentId: z.string().nullable(),\n\t\t\t\tsortOrder: z.number().int().min(0),\n\t\t\t}),\n\t\t),\n\t})\n\t.meta({ id: \"ReorderMenuItemsBody\" });\n\n// ---------------------------------------------------------------------------\n// Menus: Response schemas\n//\n// All responses are camelCase to align with the rest of the EmDash REST API\n// (content, taxonomies, redirects, etc.). The DB columns are snake_case;\n// handlers hydrate rows into the shapes below before returning.\n// ---------------------------------------------------------------------------\n\nexport const menuSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tlabel: z.string(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t\tlocale: z.string(),\n\t\ttranslationGroup: z.string().nullable(),\n\t})\n\t.meta({ id: \"Menu\" });\n\nexport const menuItemSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tmenuId: z.string(),\n\t\tparentId: z.string().nullable(),\n\t\tsortOrder: z.number().int(),\n\t\ttype: z.string(),\n\t\treferenceCollection: z.string().nullable(),\n\t\treferenceId: z.string().nullable(),\n\t\tcustomUrl: z.string().nullable(),\n\t\tlabel: z.string(),\n\t\ttitleAttr: z.string().nullable(),\n\t\ttarget: z.string().nullable(),\n\t\tcssClasses: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t\tlocale: z.string(),\n\t\ttranslationGroup: z.string().nullable(),\n\t})\n\t.meta({ id: \"MenuItem\" });\n\nexport const menuTranslationsSchema = z\n\t.object({\n\t\ttranslationGroup: z.string().nullable(),\n\t\ttranslations: z.array(\n\t\t\tz.object({\n\t\t\t\tid: z.string(),\n\t\t\t\tname: z.string(),\n\t\t\t\tlabel: z.string(),\n\t\t\t\tlocale: z.string(),\n\t\t\t\tupdatedAt: z.string(),\n\t\t\t}),\n\t\t),\n\t})\n\t.meta({ id: \"MenuTranslations\" });\n\nexport const menuListItemSchema = menuSchema\n\t.extend({\n\t\titemCount: z.number().int(),\n\t})\n\t.meta({ id: \"MenuListItem\" });\n\nexport const menuWithItemsSchema = menuSchema\n\t.extend({\n\t\titems: z.array(menuItemSchema),\n\t})\n\t.meta({ id: \"MenuWithItems\" });\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Taxonomy definitions: Input schemas\n// ---------------------------------------------------------------------------\n\n/** Collection slug format: lowercase alphanumeric + underscores, starts with letter */\nconst collectionSlugPattern = /^[a-z][a-z0-9_]*$/;\n\nexport const createTaxonomyDefBody = z\n\t.object({\n\t\tname: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.max(63)\n\t\t\t.regex(/^[a-z][a-z0-9_]*$/, \"Name must be lowercase alphanumeric with underscores\"),\n\t\tlabel: z.string().min(1).max(200),\n\t\tlabelSingular: z.string().min(1).max(200).optional(),\n\t\thierarchical: z.boolean().optional().default(false),\n\t\tcollections: z\n\t\t\t.array(\n\t\t\t\tz.string().min(1).max(63).regex(collectionSlugPattern, \"Invalid collection slug format\"),\n\t\t\t)\n\t\t\t.max(100)\n\t\t\t.optional()\n\t\t\t.default([]),\n\t\tlocale: z.string().min(1).optional(),\n\t\ttranslationOf: z.string().min(1).optional(),\n\t})\n\t.meta({ id: \"CreateTaxonomyDefBody\" });\n\n// ---------------------------------------------------------------------------\n// Taxonomy terms: Input schemas\n// ---------------------------------------------------------------------------\n\nexport const createTermBody = z\n\t.object({\n\t\tslug: z.string().min(1),\n\t\tlabel: z.string().min(1),\n\t\tparentId: z.string().nullish(),\n\t\tdescription: z.string().optional(),\n\t\tlocale: z.string().min(1).optional(),\n\t\ttranslationOf: z.string().min(1).optional(),\n\t})\n\t.meta({ id: \"CreateTermBody\" });\n\nexport const updateTermBody = z\n\t.object({\n\t\tslug: z.string().min(1).optional(),\n\t\tlabel: z.string().min(1).optional(),\n\t\tparentId: z.string().nullish(),\n\t\tdescription: z.string().optional(),\n\t})\n\t.meta({ id: \"UpdateTermBody\" });\n\n// ---------------------------------------------------------------------------\n// Taxonomies: Response schemas\n// ---------------------------------------------------------------------------\n\nexport const taxonomyDefSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tlabel: z.string(),\n\t\tlabelSingular: z.string().optional(),\n\t\thierarchical: z.boolean(),\n\t\tcollections: z.array(z.string()),\n\t\tlocale: z.string(),\n\t\ttranslationGroup: z.string().nullable(),\n\t})\n\t.meta({ id: \"TaxonomyDef\" });\n\nexport const taxonomyDefTranslationsSchema = z\n\t.object({\n\t\ttranslationGroup: z.string().nullable(),\n\t\ttranslations: z.array(\n\t\t\tz.object({\n\t\t\t\tid: z.string(),\n\t\t\t\tname: z.string(),\n\t\t\t\tlabel: z.string(),\n\t\t\t\tlocale: z.string(),\n\t\t\t}),\n\t\t),\n\t})\n\t.meta({ id: \"TaxonomyDefTranslations\" });\n\nexport const taxonomyListResponseSchema = z\n\t.object({ taxonomies: z.array(taxonomyDefSchema) })\n\t.meta({ id: \"TaxonomyListResponse\" });\n\nexport const termSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tslug: z.string(),\n\t\tlabel: z.string(),\n\t\tparentId: z.string().nullable(),\n\t\tdescription: z.string().optional(),\n\t\tlocale: z.string(),\n\t\ttranslationGroup: z.string().nullable(),\n\t})\n\t.meta({ id: \"Term\" });\n\nexport const termTranslationsSchema = z\n\t.object({\n\t\ttranslationGroup: z.string().nullable(),\n\t\ttranslations: z.array(\n\t\t\tz.object({\n\t\t\t\tid: z.string(),\n\t\t\t\tslug: z.string(),\n\t\t\t\tlabel: z.string(),\n\t\t\t\tlocale: z.string(),\n\t\t\t}),\n\t\t),\n\t})\n\t.meta({ id: \"TermTranslations\" });\n\nexport const termWithCountSchema: z.ZodType = z\n\t.object({\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tslug: z.string(),\n\t\tlabel: z.string(),\n\t\tparentId: z.string().nullable(),\n\t\tdescription: z.string().optional(),\n\t\tcount: z.number().int(),\n\t\tchildren: z.array(z.lazy(() => termWithCountSchema)),\n\t\tlocale: z.string(),\n\t\ttranslationGroup: z.string().nullable(),\n\t})\n\t.meta({ id: \"TermWithCount\" });\n\nexport const termListResponseSchema = z\n\t.object({ terms: z.array(termWithCountSchema) })\n\t.meta({ id: \"TermListResponse\" });\n\nexport const termResponseSchema = z.object({ term: termSchema }).meta({ id: \"TermResponse\" });\n\nexport const termGetResponseSchema = z\n\t.object({\n\t\tterm: termSchema.extend({\n\t\t\tcount: z.number().int(),\n\t\t\tchildren: z.array(\n\t\t\t\tz.object({\n\t\t\t\t\tid: z.string(),\n\t\t\t\t\tslug: z.string(),\n\t\t\t\t\tlabel: z.string(),\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t})\n\t.meta({ id: \"TermGetResponse\" });\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Sections: Input schemas\n// ---------------------------------------------------------------------------\n\nconst sectionSource = z.enum([\"theme\", \"user\", \"import\"]);\n\nexport const sectionsListQuery = z\n\t.object({\n\t\tsource: sectionSource.optional(),\n\t\tsearch: z.string().optional(),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n\t\tcursor: z.string().max(2048).optional(),\n\t})\n\t.meta({ id: \"SectionsListQuery\" });\n\nexport const createSectionBody = z\n\t.object({\n\t\tslug: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional(),\n\t\tkeywords: z.array(z.string()).optional(),\n\t\tcontent: z.array(z.record(z.string(), z.unknown())),\n\t\tpreviewMediaId: z.string().optional(),\n\t\tsource: z.enum([\"user\", \"import\"]).optional(),\n\t\tthemeId: z.string().optional(),\n\t})\n\t.meta({ id: \"CreateSectionBody\" });\n\nexport const updateSectionBody = z\n\t.object({\n\t\tslug: z.string().min(1).optional(),\n\t\ttitle: z.string().min(1).optional(),\n\t\tdescription: z.string().optional(),\n\t\tkeywords: z.array(z.string()).optional(),\n\t\tcontent: z.array(z.record(z.string(), z.unknown())).optional(),\n\t\tpreviewMediaId: z.string().nullish(),\n\t})\n\t.meta({ id: \"UpdateSectionBody\" });\n\n// ---------------------------------------------------------------------------\n// Sections: Response schemas\n// ---------------------------------------------------------------------------\n\nexport const sectionSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tslug: z.string(),\n\t\ttitle: z.string(),\n\t\tdescription: z.string().nullable(),\n\t\tkeywords: z.array(z.string()).nullable(),\n\t\tcontent: z.array(z.record(z.string(), z.unknown())),\n\t\tpreviewMediaId: z.string().nullable(),\n\t\tsource: z.string(),\n\t\tthemeId: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"Section\" });\n\nexport const sectionListResponseSchema = z\n\t.object({\n\t\titems: z.array(sectionSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"SectionListResponse\" });\n","import { z } from \"zod\";\n\nimport { httpUrl } from \"./common.js\";\n\n// ---------------------------------------------------------------------------\n// Settings: Input schemas\n//\n// Media references on write are just `{ mediaId, alt? }` -- the resolved\n// fields (`url`, `contentType`, `width`, `height`) are server-computed and\n// stripped from any submitted body via Zod's default strip mode. See\n// `packages/core/src/settings/types.ts` for the in-memory shape.\n// ---------------------------------------------------------------------------\n\nconst mediaReferenceInput = z.object({\n\tmediaId: z.string(),\n\talt: z.string().optional(),\n});\n\nconst socialSettings = z.object({\n\ttwitter: z.string().optional(),\n\tgithub: z.string().optional(),\n\tfacebook: z.string().optional(),\n\tinstagram: z.string().optional(),\n\tlinkedin: z.string().optional(),\n\tyoutube: z.string().optional(),\n});\n\nconst seoSettingsInput = z.object({\n\ttitleSeparator: z.string().max(10).optional(),\n\tdefaultOgImage: mediaReferenceInput.optional(),\n\trobotsTxt: z.string().max(5000).optional(),\n\tgoogleVerification: z.string().max(100).optional(),\n\tbingVerification: z.string().max(100).optional(),\n});\n\nexport const settingsUpdateBody = z\n\t.object({\n\t\ttitle: z.string().optional(),\n\t\ttagline: z.string().optional(),\n\t\tlogo: mediaReferenceInput.optional(),\n\t\tfavicon: mediaReferenceInput.optional(),\n\t\turl: z.union([httpUrl, z.literal(\"\")]).optional(),\n\t\tpostsPerPage: z.number().int().min(1).max(100).optional(),\n\t\tdateFormat: z.string().optional(),\n\t\ttimezone: z.string().optional(),\n\t\tsocial: socialSettings.optional(),\n\t\tseo: seoSettingsInput.optional(),\n\t})\n\t.meta({ id: \"SettingsUpdateBody\" });\n\n// ---------------------------------------------------------------------------\n// Settings: Response schemas\n//\n// Responses carry the resolved fields populated by `resolveMediaReference`\n// in `settings/index.ts`. Generated OpenAPI clients need to see them so\n// they don't have to re-resolve the URL on the client. Fields stay\n// optional because the resolver returns the bare ref if the underlying\n// media row was deleted (orphaned reference).\n// ---------------------------------------------------------------------------\n\nconst mediaReferenceResponse = z.object({\n\tmediaId: z.string(),\n\talt: z.string().optional(),\n\t/** Resolved media file URL; absent if the underlying row is missing. */\n\turl: z.string().optional(),\n\t/** Stored MIME type (e.g. `image/svg+xml`). Populated alongside `url`. */\n\tcontentType: z.string().optional(),\n\t/** Pixel width if known. Populated alongside `url`. */\n\twidth: z.number().int().optional(),\n\t/** Pixel height if known. Populated alongside `url`. */\n\theight: z.number().int().optional(),\n});\n\nconst seoSettingsResponse = z.object({\n\ttitleSeparator: z.string().max(10).optional(),\n\tdefaultOgImage: mediaReferenceResponse.optional(),\n\trobotsTxt: z.string().max(5000).optional(),\n\tgoogleVerification: z.string().max(100).optional(),\n\tbingVerification: z.string().max(100).optional(),\n});\n\nexport const siteSettingsSchema = z\n\t.object({\n\t\ttitle: z.string().optional(),\n\t\ttagline: z.string().optional(),\n\t\tlogo: mediaReferenceResponse.optional(),\n\t\tfavicon: mediaReferenceResponse.optional(),\n\t\turl: z.string().optional(),\n\t\tpostsPerPage: z.number().int().optional(),\n\t\tdateFormat: z.string().optional(),\n\t\ttimezone: z.string().optional(),\n\t\tsocial: socialSettings.optional(),\n\t\tseo: seoSettingsResponse.optional(),\n\t})\n\t.meta({ id: \"SiteSettings\" });\n","import { z } from \"zod\";\n\nimport { localeCode } from \"./common.js\";\n\n// ---------------------------------------------------------------------------\n// Search: Input schemas\n// ---------------------------------------------------------------------------\n\nexport const searchQuery = z\n\t.object({\n\t\tq: z.string().min(1),\n\t\tcollections: z.string().optional(),\n\t\tstatus: z.string().optional(),\n\t\tlocale: localeCode.optional(),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional(),\n\t})\n\t.meta({ id: \"SearchQuery\" });\n\nexport const searchSuggestQuery = z\n\t.object({\n\t\tq: z.string().min(1),\n\t\tcollections: z.string().optional(),\n\t\tlocale: localeCode.optional(),\n\t\tlimit: z.coerce.number().int().min(1).max(20).optional(),\n\t})\n\t.meta({ id: \"SearchSuggestQuery\" });\n\nexport const searchRebuildBody = z\n\t.object({\n\t\tcollection: z.string().min(1),\n\t})\n\t.meta({ id: \"SearchRebuildBody\" });\n\nexport const searchEnableBody = z\n\t.object({\n\t\tcollection: z.string().min(1),\n\t\tenabled: z.boolean(),\n\t\tweights: z.record(z.string(), z.number()).optional(),\n\t})\n\t.meta({ id: \"SearchEnableBody\" });\n\n// ---------------------------------------------------------------------------\n// Search: Response schemas\n// ---------------------------------------------------------------------------\n\nexport const searchResultSchema = z\n\t.object({\n\t\tcollection: z.string(),\n\t\tid: z.string(),\n\t\tslug: z.string().nullable(),\n\t\tlocale: z.string(),\n\t\ttitle: z.string().optional(),\n\t\tsnippet: z.string().optional(),\n\t\tscore: z.number(),\n\t})\n\t.meta({ id: \"SearchResult\" });\n\nexport const searchResponseSchema = z\n\t.object({\n\t\titems: z.array(searchResultSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"SearchResponse\" });\n","import { z } from \"zod\";\n\nimport { roleLevel } from \"./common.js\";\n\n// ---------------------------------------------------------------------------\n// Admin / Users: Input schemas\n// ---------------------------------------------------------------------------\n\nexport const usersListQuery = z\n\t.object({\n\t\tsearch: z.string().optional(),\n\t\trole: z.string().optional(),\n\t\tcursor: z.string().max(2048).optional(),\n\t\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n\t})\n\t.meta({ id: \"UsersListQuery\" });\n\nexport const userUpdateBody = z\n\t.object({\n\t\tname: z.string().optional(),\n\t\temail: z.string().email().optional(),\n\t\trole: roleLevel.optional(),\n\t})\n\t.meta({ id: \"UserUpdateBody\" });\n\nexport const allowedDomainCreateBody = z\n\t.object({\n\t\tdomain: z.string().min(1),\n\t\tdefaultRole: roleLevel,\n\t})\n\t.meta({ id: \"AllowedDomainCreateBody\" });\n\nexport const allowedDomainUpdateBody = z\n\t.object({\n\t\tenabled: z.boolean().optional(),\n\t\tdefaultRole: roleLevel.optional(),\n\t})\n\t.meta({ id: \"AllowedDomainUpdateBody\" });\n\n// ---------------------------------------------------------------------------\n// Admin / Users: Response schemas\n// ---------------------------------------------------------------------------\n\nexport const userSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\temail: z.string(),\n\t\tname: z.string().nullable(),\n\t\tavatarUrl: z.string().nullable(),\n\t\trole: z.number().int(),\n\t\temailVerified: z.boolean(),\n\t\tdisabled: z.boolean(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t\tlastLogin: z.string().nullable(),\n\t\tcredentialCount: z.number().int().optional(),\n\t\toauthProviders: z.array(z.string()).optional(),\n\t})\n\t.meta({ id: \"User\" });\n\nexport const userListResponseSchema = z\n\t.object({\n\t\titems: z.array(userSchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"UserListResponse\" });\n\nexport const userDetailSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\temail: z.string(),\n\t\tname: z.string().nullable(),\n\t\tavatarUrl: z.string().nullable(),\n\t\trole: z.number().int(),\n\t\temailVerified: z.boolean(),\n\t\tdisabled: z.boolean(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t\tlastLogin: z.string().nullable(),\n\t\tcredentials: z.array(\n\t\t\tz.object({\n\t\t\t\tid: z.string(),\n\t\t\t\tname: z.string().nullable(),\n\t\t\t\tdeviceType: z.string().nullable(),\n\t\t\t\tcreatedAt: z.string(),\n\t\t\t\tlastUsedAt: z.string(),\n\t\t\t}),\n\t\t),\n\t\toauthAccounts: z.array(\n\t\t\tz.object({\n\t\t\t\tprovider: z.string(),\n\t\t\t\tcreatedAt: z.string(),\n\t\t\t}),\n\t\t),\n\t})\n\t.meta({ id: \"UserDetail\" });\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Widgets: Input schemas\n// ---------------------------------------------------------------------------\n\nconst widgetType = z.enum([\"content\", \"menu\", \"component\"]);\n\nexport const createWidgetAreaBody = z\n\t.object({\n\t\tname: z.string().min(1),\n\t\tlabel: z.string().min(1),\n\t\tdescription: z.string().optional(),\n\t})\n\t.meta({ id: \"CreateWidgetAreaBody\" });\n\nexport const createWidgetBody = z\n\t.object({\n\t\ttype: widgetType,\n\t\ttitle: z.string().optional(),\n\t\tcontent: z.array(z.record(z.string(), z.unknown())).optional(),\n\t\tmenuName: z.string().optional(),\n\t\tcomponentId: z.string().optional(),\n\t\tcomponentProps: z.record(z.string(), z.unknown()).optional(),\n\t})\n\t.meta({ id: \"CreateWidgetBody\" });\n\nexport const updateWidgetBody = z\n\t.object({\n\t\ttype: widgetType.optional(),\n\t\ttitle: z.string().optional(),\n\t\tcontent: z.array(z.record(z.string(), z.unknown())).optional(),\n\t\tmenuName: z.string().optional(),\n\t\tcomponentId: z.string().optional(),\n\t\tcomponentProps: z.record(z.string(), z.unknown()).optional(),\n\t})\n\t.meta({ id: \"UpdateWidgetBody\" });\n\nexport const reorderWidgetsBody = z\n\t.object({\n\t\twidgetIds: z.array(z.string().min(1)),\n\t})\n\t.meta({ id: \"ReorderWidgetsBody\" });\n\n// ---------------------------------------------------------------------------\n// Widgets: Response schemas\n// ---------------------------------------------------------------------------\n\nexport const widgetAreaSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tlabel: z.string(),\n\t\tdescription: z.string().nullable(),\n\t\tcreated_at: z.string(),\n\t\tupdated_at: z.string(),\n\t})\n\t.meta({ id: \"WidgetArea\" });\n\nexport const widgetSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\ttype: widgetType,\n\t\ttitle: z.string().optional(),\n\t\tcontent: z.array(z.record(z.string(), z.unknown())).optional(),\n\t\tmenuName: z.string().optional(),\n\t\tcomponentId: z.string().optional(),\n\t\tcomponentProps: z.record(z.string(), z.unknown()).optional(),\n\t})\n\t.meta({ id: \"Widget\" });\n\nexport const widgetAreaWithWidgetsSchema = widgetAreaSchema\n\t.extend({\n\t\twidgets: z.array(widgetSchema),\n\t})\n\t.meta({ id: \"WidgetAreaWithWidgets\" });\n\nexport const widgetAreaWithWidgetsAndCountSchema = widgetAreaWithWidgetsSchema\n\t.extend({\n\t\twidgetCount: z.number().int(),\n\t})\n\t.meta({ id: \"WidgetAreaWithWidgetsAndCount\" });\n","import { z } from \"zod\";\n\nimport { cursorPaginationQuery } from \"./common.js\";\n\n// ---------------------------------------------------------------------------\n// Redirects: Input schemas\n// ---------------------------------------------------------------------------\n\nconst redirectType = z.coerce\n\t.number()\n\t.int()\n\t.refine((n) => [301, 302, 307, 308].includes(n), {\n\t\tmessage: \"Redirect type must be 301, 302, 307, or 308\",\n\t});\n\n/** Matches CR or LF characters */\nconst CRLF = /[\\r\\n]/;\n\n/** Path must start with / and not be protocol-relative, contain no CRLF, and no path traversal */\nconst urlPath = z\n\t.string()\n\t.min(1)\n\t.refine((s) => s.startsWith(\"/\") && !s.startsWith(\"//\"), {\n\t\tmessage: \"Must be a path starting with / (no protocol-relative URLs)\",\n\t})\n\t.refine((s) => !CRLF.test(s), {\n\t\tmessage: \"URL must not contain newline characters\",\n\t})\n\t.refine(\n\t\t(s) => {\n\t\t\ttry {\n\t\t\t\treturn !decodeURIComponent(s).split(\"/\").includes(\"..\");\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\t{ message: \"URL must not contain path traversal segments\" },\n\t);\n\nexport const createRedirectBody = z\n\t.object({\n\t\tsource: urlPath,\n\t\tdestination: urlPath,\n\t\ttype: redirectType.optional().default(301),\n\t\tenabled: z.boolean().optional().default(true),\n\t\tgroupName: z.string().nullish(),\n\t})\n\t.meta({ id: \"CreateRedirectBody\" });\n\nexport const updateRedirectBody = z\n\t.object({\n\t\tsource: urlPath.optional(),\n\t\tdestination: urlPath.optional(),\n\t\ttype: redirectType.optional(),\n\t\tenabled: z.boolean().optional(),\n\t\tgroupName: z.string().nullish(),\n\t})\n\t.refine((o) => Object.values(o).some((v) => v !== undefined), {\n\t\tmessage: \"At least one field must be provided\",\n\t})\n\t.meta({ id: \"UpdateRedirectBody\" });\n\nexport const redirectsListQuery = cursorPaginationQuery\n\t.extend({\n\t\tsearch: z.string().optional(),\n\t\tgroup: z.string().optional(),\n\t\tenabled: z\n\t\t\t.enum([\"true\", \"false\"])\n\t\t\t.transform((v) => v === \"true\")\n\t\t\t.optional(),\n\t\tauto: z\n\t\t\t.enum([\"true\", \"false\"])\n\t\t\t.transform((v) => v === \"true\")\n\t\t\t.optional(),\n\t})\n\t.meta({ id: \"RedirectsListQuery\" });\n\n// ---------------------------------------------------------------------------\n// 404 Log: Input schemas\n// ---------------------------------------------------------------------------\n\nexport const notFoundListQuery = cursorPaginationQuery\n\t.extend({\n\t\tsearch: z.string().optional(),\n\t})\n\t.meta({ id: \"NotFoundListQuery\" });\n\nexport const notFoundSummaryQuery = z.object({\n\tlimit: z.coerce.number().int().min(1).max(100).optional().default(50),\n});\n\nexport const notFoundPruneBody = z\n\t.object({\n\t\tolderThan: z.string().datetime({ message: \"olderThan must be an ISO 8601 datetime\" }),\n\t})\n\t.meta({ id: \"NotFoundPruneBody\" });\n\n// ---------------------------------------------------------------------------\n// Redirects: Response schemas\n// ---------------------------------------------------------------------------\n\nexport const redirectSchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tsource: z.string(),\n\t\tdestination: z.string(),\n\t\ttype: z.number().int(),\n\t\tisPattern: z.boolean(),\n\t\tenabled: z.boolean(),\n\t\thits: z.number().int(),\n\t\tlastHitAt: z.string().nullable(),\n\t\tgroupName: z.string().nullable(),\n\t\tauto: z.boolean(),\n\t\tcreatedAt: z.string(),\n\t\tupdatedAt: z.string(),\n\t})\n\t.meta({ id: \"Redirect\" });\n\nexport const redirectListResponseSchema = z\n\t.object({\n\t\titems: z.array(redirectSchema),\n\t\tnextCursor: z.string().optional(),\n\t\tloopRedirectIds: z.array(z.string()).optional(),\n\t})\n\t.meta({ id: \"RedirectListResponse\" });\n\nexport const notFoundEntrySchema = z\n\t.object({\n\t\tid: z.string(),\n\t\tpath: z.string(),\n\t\treferrer: z.string().nullable(),\n\t\tuserAgent: z.string().nullable(),\n\t\tip: z.string().nullable(),\n\t\tcreatedAt: z.string(),\n\t})\n\t.meta({ id: \"NotFoundEntry\" });\n\nexport const notFoundListResponseSchema = z\n\t.object({\n\t\titems: z.array(notFoundEntrySchema),\n\t\tnextCursor: z.string().optional(),\n\t})\n\t.meta({ id: \"NotFoundListResponse\" });\n\nexport const notFoundSummarySchema = z\n\t.object({\n\t\tpath: z.string(),\n\t\tcount: z.number().int(),\n\t\tlastSeen: z.string(),\n\t\ttopReferrer: z.string().nullable(),\n\t})\n\t.meta({ id: \"NotFoundSummary\" });\n\nexport const notFoundSummaryResponseSchema = z\n\t.object({ items: z.array(notFoundSummarySchema) })\n\t.meta({ id: \"NotFoundSummaryResponse\" });\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { n as InvalidCursorError } from "./types-K3MDsxpy.mjs";
2
- import { t as OptionsRepository } from "./options-BL4X94qY.mjs";
3
- import { a as validateDestinationParams, i as matchPattern, n as interpolateDestination, o as validatePattern, r as isPattern, t as compilePattern } from "./patterns-CqG5Ya3i.mjs";
4
- import { t as RedirectRepository } from "./redirect-C6tJA7tk.mjs";
1
+ import { n as InvalidCursorError } from "./types-BXSUSAjt.mjs";
2
+ import { t as OptionsRepository } from "./options-BPCVnesz.mjs";
3
+ import { a as validateDestinationParams, i as matchPattern, n as interpolateDestination, o as validatePattern, r as isPattern, t as compilePattern } from "./patterns-p-RBdTbM.mjs";
4
+ import { t as RedirectRepository } from "./redirect-CRWIt8Zj.mjs";
5
5
 
6
6
  //#region src/redirects/loops.ts
7
7
  /**
@@ -570,4 +570,4 @@ async function handleNotFoundPrune(db, olderThan) {
570
570
 
571
571
  //#endregion
572
572
  export { handleRedirectCreate as a, handleRedirectList as c, handleNotFoundSummary as i, handleRedirectUpdate as l, handleNotFoundList as n, handleRedirectDelete as o, handleNotFoundPrune as r, handleRedirectGet as s, handleNotFoundClear as t };
573
- //# sourceMappingURL=redirects-CacE9eQa.mjs.map
573
+ //# sourceMappingURL=redirects-OIu6vQ2i.mjs.map