emdash 0.33.0 → 0.35.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 (916) hide show
  1. package/dist/{adapters-BMyNSSZi.d.mts → adapters-Bb1vG41D.d.mts} +33 -2
  2. package/dist/adapters-Bb1vG41D.d.mts.map +1 -0
  3. package/dist/{allowed-origins-CG1pACtS.mjs → allowed-origins-DW7sYyqg.mjs} +2 -2
  4. package/dist/{allowed-origins-CG1pACtS.mjs.map → allowed-origins-DW7sYyqg.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +22 -21
  7. package/dist/api/route-utils.mjs.map +1 -1
  8. package/dist/api/schemas/index.d.mts +2 -2
  9. package/dist/api/schemas/index.mjs +6 -5
  10. package/dist/{api-D2hunekQ.mjs → api-BeBglVxU.mjs} +98 -407
  11. package/dist/api-BeBglVxU.mjs.map +1 -0
  12. package/dist/{api-tokens-CSND0i1z.mjs → api-tokens-KO24G1Fd.mjs} +2 -2
  13. package/dist/{api-tokens-CSND0i1z.mjs.map → api-tokens-KO24G1Fd.mjs.map} +1 -1
  14. package/dist/{apply-kwNEJW2l.mjs → apply-kUDt80-G.mjs} +131 -107
  15. package/dist/apply-kUDt80-G.mjs.map +1 -0
  16. package/dist/astro/index.d.mts +12 -12
  17. package/dist/astro/index.d.mts.map +1 -1
  18. package/dist/astro/index.mjs +163 -49
  19. package/dist/astro/index.mjs.map +1 -1
  20. package/dist/astro/middleware/auth.d.mts +10 -10
  21. package/dist/astro/middleware/auth.mjs +8 -8
  22. package/dist/astro/middleware/media-usage-write-fence.d.mts +7 -0
  23. package/dist/astro/middleware/media-usage-write-fence.d.mts.map +1 -0
  24. package/dist/astro/middleware/media-usage-write-fence.mjs +35 -0
  25. package/dist/astro/middleware/media-usage-write-fence.mjs.map +1 -0
  26. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  27. package/dist/astro/middleware/redirect.mjs +10 -7
  28. package/dist/astro/middleware/redirect.mjs.map +1 -1
  29. package/dist/astro/middleware/request-context.mjs +3 -3
  30. package/dist/astro/middleware/setup.mjs +1 -1
  31. package/dist/astro/middleware.d.mts +12 -11
  32. package/dist/astro/middleware.d.mts.map +1 -1
  33. package/dist/astro/middleware.mjs +1763 -173
  34. package/dist/astro/middleware.mjs.map +1 -1
  35. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +9 -8
  36. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
  37. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +9 -8
  38. package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
  39. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  40. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  42. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +12 -11
  43. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
  44. package/dist/astro/routes/api/admin/byline-fields/index.mjs +12 -11
  45. package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
  46. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +12 -11
  47. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
  48. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -17
  49. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -17
  50. package/dist/astro/routes/api/admin/bylines/index.mjs +17 -17
  51. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +14 -13
  52. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
  54. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -11
  55. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
  57. package/dist/astro/routes/api/admin/comments/index.mjs +12 -11
  58. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
  60. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
  61. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.d.mts +8 -0
  62. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.d.mts.map +1 -0
  63. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +36 -0
  64. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -0
  65. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts +8 -0
  66. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts.map +1 -0
  67. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +36 -0
  68. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -0
  69. package/dist/astro/routes/api/admin/media-usage/repair.mjs +15 -14
  70. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/media-usage/work/index.d.mts +8 -0
  72. package/dist/astro/routes/api/admin/media-usage/work/index.d.mts.map +1 -0
  73. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +37 -0
  74. package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -0
  75. package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts +8 -0
  76. package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts.map +1 -0
  77. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +37 -0
  78. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -0
  79. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  80. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  81. package/dist/astro/routes/api/admin/plugins/_id_/disable.d.mts.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +51 -43
  83. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/_id_/enable.d.mts.map +1 -1
  85. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +51 -43
  86. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +47 -42
  88. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +6 -6
  90. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +47 -42
  91. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.d.mts.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +50 -42
  94. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/plugins/_id_/update.d.mts.map +1 -1
  96. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +50 -42
  97. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/index.mjs +47 -42
  99. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  101. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +47 -42
  102. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  103. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.d.mts.map +1 -1
  104. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +50 -42
  105. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  106. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +47 -42
  107. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  108. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -1
  109. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +50 -42
  110. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  111. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
  112. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +51 -43
  113. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  114. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +47 -42
  115. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  116. package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
  117. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +51 -43
  118. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  119. package/dist/astro/routes/api/admin/plugins/updates.mjs +47 -42
  120. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  121. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +47 -42
  122. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  123. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  124. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +47 -42
  125. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  126. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
  127. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  128. package/dist/astro/routes/api/admin/users/_id_/index.mjs +9 -8
  129. package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
  130. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
  131. package/dist/astro/routes/api/admin/users/index.mjs +9 -8
  132. package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
  133. package/dist/astro/routes/api/auth/dev-bypass.d.mts.map +1 -1
  134. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -9
  135. package/dist/astro/routes/api/auth/dev-bypass.mjs.map +1 -1
  136. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  137. package/dist/astro/routes/api/auth/invite/complete.mjs +13 -12
  138. package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
  139. package/dist/astro/routes/api/auth/invite/index.mjs +10 -9
  140. package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
  141. package/dist/astro/routes/api/auth/invite/register-options.mjs +12 -11
  142. package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
  143. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  144. package/dist/astro/routes/api/auth/magic-link/send.mjs +12 -11
  145. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  146. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  147. package/dist/astro/routes/api/auth/me.mjs +10 -9
  148. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  149. package/dist/astro/routes/api/auth/mode.mjs +4 -4
  150. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  151. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  152. package/dist/astro/routes/api/auth/passkey/_id_.mjs +9 -8
  153. package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
  154. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  155. package/dist/astro/routes/api/auth/passkey/options.mjs +14 -13
  156. package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
  157. package/dist/astro/routes/api/auth/passkey/register/options.mjs +12 -11
  158. package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
  159. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +13 -12
  160. package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
  161. package/dist/astro/routes/api/auth/passkey/verify.mjs +13 -12
  162. package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
  163. package/dist/astro/routes/api/auth/signup/complete.mjs +13 -12
  164. package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
  165. package/dist/astro/routes/api/auth/signup/request.mjs +12 -11
  166. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  167. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  168. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +15 -14
  169. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  170. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +14 -13
  171. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -1
  172. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  173. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +5 -5
  174. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
  175. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  176. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -13
  177. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +11 -10
  178. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  179. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +18 -17
  180. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  181. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +18 -17
  182. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  183. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
  184. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  185. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +11 -10
  186. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  187. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
  188. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +44 -31
  189. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  190. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  191. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +5 -5
  192. package/dist/astro/routes/api/content/_collection_/_id_.mjs +11 -10
  193. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  194. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  195. package/dist/astro/routes/api/content/_collection_/index.mjs +11 -10
  196. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  197. package/dist/astro/routes/api/content/_collection_/trash.mjs +10 -9
  198. package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
  199. package/dist/astro/routes/api/dashboard.mjs +10 -8
  200. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  201. package/dist/astro/routes/api/dev/emails.mjs +4 -4
  202. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  203. package/dist/astro/routes/api/import/probe.mjs +18 -16
  204. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  205. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  206. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  207. package/dist/astro/routes/api/import/wordpress/execute.mjs +15 -15
  208. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  209. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  210. package/dist/astro/routes/api/import/wordpress/media.mjs +14 -12
  211. package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
  212. package/dist/astro/routes/api/import/wordpress/prepare.mjs +13 -12
  213. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  214. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  215. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +14 -14
  216. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  217. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +18 -16
  218. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  219. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  220. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  221. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +28 -27
  222. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  223. package/dist/astro/routes/api/manifest.mjs +5 -5
  224. package/dist/astro/routes/api/mcp.d.mts.map +1 -1
  225. package/dist/astro/routes/api/mcp.mjs +174 -72
  226. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  227. package/dist/astro/routes/api/media/_id_/confirm.mjs +13 -11
  228. package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
  229. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  230. package/dist/astro/routes/api/media/_id_/usage.mjs +17 -16
  231. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  232. package/dist/astro/routes/api/media/_id_.mjs +16 -15
  233. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  234. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  235. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  236. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  237. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  238. package/dist/astro/routes/api/media/upload-url.mjs +11 -10
  239. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  240. package/dist/astro/routes/api/media.mjs +18 -15
  241. package/dist/astro/routes/api/media.mjs.map +1 -1
  242. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -11
  243. package/dist/astro/routes/api/menus/_name_/items.mjs +11 -11
  244. package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -11
  245. package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -11
  246. package/dist/astro/routes/api/menus/_name_.mjs +11 -11
  247. package/dist/astro/routes/api/menus/index.mjs +11 -11
  248. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  249. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
  250. package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
  251. package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
  252. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  253. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
  254. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
  255. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  256. package/dist/astro/routes/api/openapi.json.mjs +152 -6
  257. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  258. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
  259. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +8 -7
  260. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
  261. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -11
  262. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  263. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -11
  264. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  265. package/dist/astro/routes/api/redirects/_id_.mjs +13 -12
  266. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  267. package/dist/astro/routes/api/redirects/index.mjs +13 -12
  268. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  269. package/dist/astro/routes/api/relations/_id_/index.mjs +18 -17
  270. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  271. package/dist/astro/routes/api/relations/_id_/translations.mjs +13 -12
  272. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  273. package/dist/astro/routes/api/relations/index.mjs +18 -17
  274. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  275. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  276. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
  277. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +47 -42
  278. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  279. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +47 -42
  280. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  281. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +47 -42
  282. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  283. package/dist/astro/routes/api/schema/collections/_slug_/index.d.mts.map +1 -1
  284. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +47 -42
  285. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  286. package/dist/astro/routes/api/schema/collections/index.mjs +47 -42
  287. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  288. package/dist/astro/routes/api/schema/collections/reorder.mjs +47 -42
  289. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  290. package/dist/astro/routes/api/schema/index.mjs +10 -9
  291. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  292. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +47 -42
  293. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  294. package/dist/astro/routes/api/schema/orphans/index.mjs +47 -42
  295. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  296. package/dist/astro/routes/api/search/enable.mjs +13 -13
  297. package/dist/astro/routes/api/search/index.mjs +12 -12
  298. package/dist/astro/routes/api/search/rebuild.mjs +13 -13
  299. package/dist/astro/routes/api/search/stats.mjs +8 -8
  300. package/dist/astro/routes/api/search/suggest.mjs +12 -12
  301. package/dist/astro/routes/api/sections/_slug_.mjs +12 -11
  302. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  303. package/dist/astro/routes/api/sections/index.mjs +12 -11
  304. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  305. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  306. package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -6
  307. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  308. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  309. package/dist/astro/routes/api/settings/email.mjs +5 -5
  310. package/dist/astro/routes/api/settings.mjs +14 -13
  311. package/dist/astro/routes/api/settings.mjs.map +1 -1
  312. package/dist/astro/routes/api/setup/admin-verify.mjs +14 -13
  313. package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
  314. package/dist/astro/routes/api/setup/admin.mjs +13 -12
  315. package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
  316. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  317. package/dist/astro/routes/api/setup/dev-bypass.mjs +30 -31
  318. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  319. package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
  320. package/dist/astro/routes/api/setup/index.d.mts.map +1 -1
  321. package/dist/astro/routes/api/setup/index.mjs +31 -35
  322. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  323. package/dist/astro/routes/api/setup/status.mjs +5 -5
  324. package/dist/astro/routes/api/snapshot.mjs +8 -8
  325. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +16 -15
  326. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  327. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -15
  328. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  329. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -15
  330. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  331. package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
  332. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +18 -16
  333. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  334. package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts +8 -0
  335. package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts.map +1 -0
  336. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +46 -0
  337. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -0
  338. package/dist/astro/routes/api/taxonomies/_name_.d.mts +19 -0
  339. package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -0
  340. package/dist/astro/routes/api/taxonomies/_name_.mjs +88 -0
  341. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -0
  342. package/dist/astro/routes/api/taxonomies/index.mjs +16 -15
  343. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  344. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  345. package/dist/astro/routes/api/typegen.mjs +6 -6
  346. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  347. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  348. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  349. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +10 -9
  350. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  351. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +12 -11
  352. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  353. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +12 -11
  354. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  355. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -6
  356. package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
  357. package/dist/astro/routes/api/widget-areas/index.mjs +12 -11
  358. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  359. package/dist/astro/routes/api/widget-components.mjs +4 -4
  360. package/dist/astro/routes/robots.txt.mjs +7 -6
  361. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  362. package/dist/astro/routes/sitemap-_collection_.xml.mjs +10 -10
  363. package/dist/astro/routes/sitemap.xml.mjs +8 -7
  364. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  365. package/dist/astro/types.d.mts +35 -17
  366. package/dist/astro/types.d.mts.map +1 -1
  367. package/dist/auth/providers/github.d.mts +1 -1
  368. package/dist/auth/providers/google.d.mts +1 -1
  369. package/dist/{authorize-qRhWQnel.mjs → authorize-DUElxgOQ.mjs} +2 -2
  370. package/dist/{authorize-qRhWQnel.mjs.map → authorize-DUElxgOQ.mjs.map} +1 -1
  371. package/dist/{backup-CtA6LDNw.mjs → backup-DWYpJlLj.mjs} +4 -4
  372. package/dist/{backup-CtA6LDNw.mjs.map → backup-DWYpJlLj.mjs.map} +1 -1
  373. package/dist/{base64-B-PsqheR.mjs → base64-CvLhUKQv.mjs} +1 -1
  374. package/dist/{base64-B-PsqheR.mjs.map → base64-CvLhUKQv.mjs.map} +1 -1
  375. package/dist/bundle-vn56sLos.mjs +663 -0
  376. package/dist/bundle-vn56sLos.mjs.map +1 -0
  377. package/dist/{byline-fields-CNc0Yq5i.mjs → byline-fields-txaLGoME.mjs} +2 -2
  378. package/dist/{byline-fields-CNc0Yq5i.mjs.map → byline-fields-txaLGoME.mjs.map} +1 -1
  379. package/dist/{byline-registry-ZkPKqEwC.mjs → byline-registry-DDun8sxh.mjs} +2 -2
  380. package/dist/{byline-registry-ZkPKqEwC.mjs.map → byline-registry-DDun8sxh.mjs.map} +1 -1
  381. package/dist/{byline-Cp6csL84.mjs → byline-yjvWq4ip.mjs} +5 -5
  382. package/dist/{byline-Cp6csL84.mjs.map → byline-yjvWq4ip.mjs.map} +1 -1
  383. package/dist/{bylines-cf-C9lmF.mjs → bylines-Bu7pchQ4.mjs} +5 -5
  384. package/dist/{bylines-cf-C9lmF.mjs.map → bylines-Bu7pchQ4.mjs.map} +1 -1
  385. package/dist/{bylines-CEj5CdT4.mjs → bylines-DjXS5p0P.mjs} +7 -7
  386. package/dist/{bylines-CEj5CdT4.mjs.map → bylines-DjXS5p0P.mjs.map} +1 -1
  387. package/dist/{cache-C9FptTFR.mjs → cache-C46-3Irl.mjs} +3 -3
  388. package/dist/{cache-C9FptTFR.mjs.map → cache-C46-3Irl.mjs.map} +1 -1
  389. package/dist/{challenge-store-D9VNKELo.mjs → challenge-store-SIL5DsF2.mjs} +1 -1
  390. package/dist/{challenge-store-D9VNKELo.mjs.map → challenge-store-SIL5DsF2.mjs.map} +1 -1
  391. package/dist/{chunks-DbYzib_k.mjs → chunks-fiZ8G9RJ.mjs} +2 -2
  392. package/dist/{chunks-DbYzib_k.mjs.map → chunks-fiZ8G9RJ.mjs.map} +1 -1
  393. package/dist/cli/index.mjs +655 -677
  394. package/dist/cli/index.mjs.map +1 -1
  395. package/dist/client/cf-access.d.mts +1 -1
  396. package/dist/client/index.d.mts +74 -4
  397. package/dist/client/index.d.mts.map +1 -1
  398. package/dist/client/index.mjs +25 -2
  399. package/dist/client/index.mjs.map +1 -1
  400. package/dist/collection-deletion-DQPvMD8R.mjs +779 -0
  401. package/dist/collection-deletion-DQPvMD8R.mjs.map +1 -0
  402. package/dist/{comment-BIkJ6Fil.mjs → comment-Dxlep6cE.mjs} +2 -2
  403. package/dist/{comment-BIkJ6Fil.mjs.map → comment-Dxlep6cE.mjs.map} +1 -1
  404. package/dist/{comment-reaction-D-laEceb.mjs → comment-reaction-D-2J84UE.mjs} +2 -2
  405. package/dist/{comment-reaction-D-laEceb.mjs.map → comment-reaction-D-2J84UE.mjs.map} +1 -1
  406. package/dist/{comments-0_w6KChA.mjs → comments-CTfZtLmM.mjs} +3 -3
  407. package/dist/{comments-0_w6KChA.mjs.map → comments-CTfZtLmM.mjs.map} +1 -1
  408. package/dist/{components-BPxrRjpE.mjs → components-CQy3lh9x.mjs} +1 -1
  409. package/dist/{components-BPxrRjpE.mjs.map → components-CQy3lh9x.mjs.map} +1 -1
  410. package/dist/{config-DyF3OKg_.mjs → config-C3EBstHi.mjs} +18 -2
  411. package/dist/config-C3EBstHi.mjs.map +1 -0
  412. package/dist/config-COQzTe5Q.d.mts +34 -0
  413. package/dist/config-COQzTe5Q.d.mts.map +1 -0
  414. package/dist/{content-CJ94NEx5.mjs → content-ZHCc1ngN.mjs} +509 -78
  415. package/dist/content-ZHCc1ngN.mjs.map +1 -0
  416. package/dist/content-list-query-wJ2WN8Vp.d.mts +26 -0
  417. package/dist/content-list-query-wJ2WN8Vp.d.mts.map +1 -0
  418. package/dist/content-refresh-B_8SJzuU.mjs +2560 -0
  419. package/dist/content-refresh-B_8SJzuU.mjs.map +1 -0
  420. package/dist/{context-C_1nrqnW.mjs → context-ZldbZcle.mjs} +25 -17
  421. package/dist/context-ZldbZcle.mjs.map +1 -0
  422. package/dist/{cron-DRV-UC4K.mjs → cron-Y9aLtgrA.mjs} +1 -1
  423. package/dist/{cron-DRV-UC4K.mjs.map → cron-Y9aLtgrA.mjs.map} +1 -1
  424. package/dist/{dashboard-DINnNVVU.mjs → dashboard-DvHbk_cv.mjs} +44 -10
  425. package/dist/dashboard-DvHbk_cv.mjs.map +1 -0
  426. package/dist/db/index.d.mts +4 -4
  427. package/dist/db/index.mjs +31 -8
  428. package/dist/db/index.mjs.map +1 -1
  429. package/dist/db/libsql-migrations.d.mts +11 -0
  430. package/dist/db/libsql-migrations.d.mts.map +1 -0
  431. package/dist/db/libsql-migrations.mjs +57 -0
  432. package/dist/db/libsql-migrations.mjs.map +1 -0
  433. package/dist/db/libsql.d.mts +1 -1
  434. package/dist/db/postgres-migrations.d.mts +10 -0
  435. package/dist/db/postgres-migrations.d.mts.map +1 -0
  436. package/dist/db/postgres-migrations.mjs +47 -0
  437. package/dist/db/postgres-migrations.mjs.map +1 -0
  438. package/dist/db/postgres.d.mts +1 -1
  439. package/dist/db/sqlite-migrations.d.mts +10 -0
  440. package/dist/db/sqlite-migrations.d.mts.map +1 -0
  441. package/dist/db/sqlite-migrations.mjs +28 -0
  442. package/dist/db/sqlite-migrations.mjs.map +1 -0
  443. package/dist/db/sqlite.d.mts +1 -1
  444. package/dist/{db-errors-CcWLaRiR.mjs → db-errors-Cl-sKYTm.mjs} +1 -1
  445. package/dist/{db-errors-CcWLaRiR.mjs.map → db-errors-Cl-sKYTm.mjs.map} +1 -1
  446. package/dist/{default-BD2FG0xV.mjs → default-DdDl3fxv.mjs} +1 -1
  447. package/dist/{default-BD2FG0xV.mjs.map → default-DdDl3fxv.mjs.map} +1 -1
  448. package/dist/{deferred-tasks-C-WRCcKo.d.mts → deferred-tasks-SDWxrgzJ.d.mts} +1 -1
  449. package/dist/{deferred-tasks-C-WRCcKo.d.mts.map → deferred-tasks-SDWxrgzJ.d.mts.map} +1 -1
  450. package/dist/{device-flow-CTqd8mud.mjs → device-flow-C0GdD_z8.mjs} +4 -4
  451. package/dist/{device-flow-CTqd8mud.mjs.map → device-flow-C0GdD_z8.mjs.map} +1 -1
  452. package/dist/direct-executor-CDXeJCSs.mjs +85 -0
  453. package/dist/direct-executor-CDXeJCSs.mjs.map +1 -0
  454. package/dist/dist-D_6CKR8z.mjs +810 -0
  455. package/dist/dist-D_6CKR8z.mjs.map +1 -0
  456. package/dist/{email-console-C6WdcWbL.mjs → email-console-BHNjIwiB.mjs} +1 -1
  457. package/dist/{email-console-C6WdcWbL.mjs.map → email-console-BHNjIwiB.mjs.map} +1 -1
  458. package/dist/{enrich-CFJJgxs_.mjs → enrich-_ySMEvEE.mjs} +2 -2
  459. package/dist/{enrich-CFJJgxs_.mjs.map → enrich-_ySMEvEE.mjs.map} +1 -1
  460. package/dist/{error-oh_9i6bR.mjs → error-DupyJZE2.mjs} +3 -3
  461. package/dist/{error-oh_9i6bR.mjs.map → error-DupyJZE2.mjs.map} +1 -1
  462. package/dist/{errors-BucQ8VYz.mjs → errors-CLUPm7aD.mjs} +14 -2
  463. package/dist/errors-CLUPm7aD.mjs.map +1 -0
  464. package/dist/{escape-CXps5F_v.mjs → escape-DUY2r2Zs.mjs} +1 -1
  465. package/dist/{escape-CXps5F_v.mjs.map → escape-DUY2r2Zs.mjs.map} +1 -1
  466. package/dist/{field-defs-cache-WD82dMQq.mjs → field-defs-cache-BzwBlJrR.mjs} +4 -4
  467. package/dist/{field-defs-cache-WD82dMQq.mjs.map → field-defs-cache-BzwBlJrR.mjs.map} +1 -1
  468. package/dist/{fts-manager-BITakW_R.mjs → fts-manager-DyZEohZC.mjs} +76 -50
  469. package/dist/fts-manager-DyZEohZC.mjs.map +1 -0
  470. package/dist/{hreflang-BdZuVBhL.mjs → hreflang-BBe83kKa.mjs} +7 -7
  471. package/dist/{hreflang-BdZuVBhL.mjs.map → hreflang-BBe83kKa.mjs.map} +1 -1
  472. package/dist/{hreflang-BaLCNcDx.d.mts → hreflang-DwT2E0Sa.d.mts} +2 -2
  473. package/dist/{hreflang-BaLCNcDx.d.mts.map → hreflang-DwT2E0Sa.d.mts.map} +1 -1
  474. package/dist/identity-Ys6Dlc9C.mjs +35 -0
  475. package/dist/identity-Ys6Dlc9C.mjs.map +1 -0
  476. package/dist/{import-C-9uqyT3.mjs → import-DPkLmeXO.mjs} +5 -5
  477. package/dist/{import-C-9uqyT3.mjs.map → import-DPkLmeXO.mjs.map} +1 -1
  478. package/dist/{index-M37iz29I.d.mts → index-BVBZj4-7.d.mts} +236 -104
  479. package/dist/index-BVBZj4-7.d.mts.map +1 -0
  480. package/dist/{index-MGw47uWq.d.mts → index-C9KuQyO-.d.mts} +5 -10
  481. package/dist/index-C9KuQyO-.d.mts.map +1 -0
  482. package/dist/index.d.mts +21 -19
  483. package/dist/index.mjs +73 -67
  484. package/dist/{init-lock-DJkX6Hto.mjs → init-lock-6b309ZrF.mjs} +1 -1
  485. package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-6b309ZrF.mjs.map} +1 -1
  486. package/dist/{load-DV1DZuUJ.mjs → load-YJ2xl3ra.mjs} +2 -2
  487. package/dist/{load-DV1DZuUJ.mjs.map → load-YJ2xl3ra.mjs.map} +1 -1
  488. package/dist/{loader-CGugY7Zl.mjs → loader-CdG_Ci3H.mjs} +95 -53
  489. package/dist/loader-CdG_Ci3H.mjs.map +1 -0
  490. package/dist/manifest-builder-B252yQUf.mjs +189 -0
  491. package/dist/manifest-builder-B252yQUf.mjs.map +1 -0
  492. package/dist/{manifest-schema-Da7kj23y.mjs → manifest-schema-BXbUAHod.mjs} +1 -1
  493. package/dist/{manifest-schema-Da7kj23y.mjs.map → manifest-schema-BXbUAHod.mjs.map} +1 -1
  494. package/dist/media/image-endpoint.mjs +1 -1
  495. package/dist/media/index.d.mts +1 -1
  496. package/dist/media/index.mjs +3 -2
  497. package/dist/media/index.mjs.map +1 -1
  498. package/dist/media/local-runtime.d.mts +12 -12
  499. package/dist/media/local-runtime.mjs +6 -5
  500. package/dist/media/local-runtime.mjs.map +1 -1
  501. package/dist/{media-OhYL-7Io.mjs → media-BWWWb8kg.mjs} +92 -3
  502. package/dist/media-BWWWb8kg.mjs.map +1 -0
  503. package/dist/{media-BP7S-nHT.mjs → media-CzhAn2--.mjs} +2 -2
  504. package/dist/{media-BP7S-nHT.mjs.map → media-CzhAn2--.mjs.map} +1 -1
  505. package/dist/{media-allowlist-D-peH1H5.mjs → media-allowlist-D6x-Us02.mjs} +14 -3
  506. package/dist/media-allowlist-D6x-Us02.mjs.map +1 -0
  507. package/dist/{media-upload-DtrwU2B0.mjs → media-upload-CHBVn6m-.mjs} +10 -8
  508. package/dist/{media-upload-DtrwU2B0.mjs.map → media-upload-CHBVn6m-.mjs.map} +1 -1
  509. package/dist/{media-url-DYs_YLOx.mjs → media-url-BvoX88FA.mjs} +1 -1
  510. package/dist/{media-url-DYs_YLOx.mjs.map → media-url-BvoX88FA.mjs.map} +1 -1
  511. package/dist/{media-usage-BlxfTkN0.mjs → media-usage-BZCydfvu.mjs} +137 -60
  512. package/dist/media-usage-BZCydfvu.mjs.map +1 -0
  513. package/dist/media-usage-work-CLo_6tct.mjs +152 -0
  514. package/dist/media-usage-work-CLo_6tct.mjs.map +1 -0
  515. package/dist/media-usage-work-DrCbqBcl.mjs +424 -0
  516. package/dist/media-usage-work-DrCbqBcl.mjs.map +1 -0
  517. package/dist/media-usage-write-fence-aHEgN1zB.mjs +42 -0
  518. package/dist/media-usage-write-fence-aHEgN1zB.mjs.map +1 -0
  519. package/dist/{menus-Y54RDPIN.mjs → menus-DSo5QeW0.mjs} +351 -95
  520. package/dist/menus-DSo5QeW0.mjs.map +1 -0
  521. package/dist/{menus-BcQWxeXu.mjs → menus-TCNSd2vp.mjs} +3 -3
  522. package/dist/{menus-BcQWxeXu.mjs.map → menus-TCNSd2vp.mjs.map} +1 -1
  523. package/dist/migrations/index.d.mts +22 -0
  524. package/dist/migrations/index.d.mts.map +1 -0
  525. package/dist/migrations/index.mjs +7 -0
  526. package/dist/{mode-BWyTBe3I.mjs → mode-BDoH_WcF.mjs} +1 -1
  527. package/dist/{mode-BWyTBe3I.mjs.map → mode-BDoH_WcF.mjs.map} +1 -1
  528. package/dist/{normalize-C-SHXmra.mjs → normalize-Bc-s_r-a.mjs} +1 -1
  529. package/dist/{normalize-C-SHXmra.mjs.map → normalize-Bc-s_r-a.mjs.map} +1 -1
  530. package/dist/{oauth-authorization-ClvktmrL.mjs → oauth-authorization-iOikmrJd.mjs} +4 -4
  531. package/dist/{oauth-authorization-ClvktmrL.mjs.map → oauth-authorization-iOikmrJd.mjs.map} +1 -1
  532. package/dist/{oauth-clients-8ao-U66l.mjs → oauth-clients-CvI0nHMJ.mjs} +1 -1
  533. package/dist/{oauth-clients-8ao-U66l.mjs.map → oauth-clients-CvI0nHMJ.mjs.map} +1 -1
  534. package/dist/{oauth-state-store-B1ofdTiQ.mjs → oauth-state-store-Ba8KZlwW.mjs} +1 -1
  535. package/dist/{oauth-state-store-B1ofdTiQ.mjs.map → oauth-state-store-Ba8KZlwW.mjs.map} +1 -1
  536. package/dist/{oauth-user-lookup-CscEuIiR.mjs → oauth-user-lookup-C5SQwGYC.mjs} +1 -1
  537. package/dist/{oauth-user-lookup-CscEuIiR.mjs.map → oauth-user-lookup-C5SQwGYC.mjs.map} +1 -1
  538. package/dist/object-cache/memory.d.mts +1 -1
  539. package/dist/{options-CA4eVX6P.d.mts → options--hhz-jZ1.d.mts} +4 -3
  540. package/dist/options--hhz-jZ1.d.mts.map +1 -0
  541. package/dist/page/index.d.mts +2 -2
  542. package/dist/{parse-CJKNuewM.mjs → parse-DFbuc-Fh.mjs} +2 -2
  543. package/dist/{parse-CJKNuewM.mjs.map → parse-DFbuc-Fh.mjs.map} +1 -1
  544. package/dist/{passkey-config-D-zrzMJI.mjs → passkey-config-DFAmUyuE.mjs} +1 -1
  545. package/dist/{passkey-config-D-zrzMJI.mjs.map → passkey-config-DFAmUyuE.mjs.map} +1 -1
  546. package/dist/{placeholder-DaeNS-VG.d.mts → placeholder-Dp0K3RkD.d.mts} +1 -1
  547. package/dist/{placeholder-DaeNS-VG.d.mts.map → placeholder-Dp0K3RkD.d.mts.map} +1 -1
  548. package/dist/plugin-types.d.mts +8 -1
  549. package/dist/plugin-types.d.mts.map +1 -1
  550. package/dist/plugin-utils.d.mts +10 -10
  551. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  552. package/dist/plugins/adapt-sandbox-entry.mjs +7 -4
  553. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  554. package/dist/policy-TluUIxuu.mjs +45 -0
  555. package/dist/policy-TluUIxuu.mjs.map +1 -0
  556. package/dist/{portable-text-B_kqBmXB.mjs → portable-text-imBW5cHK.mjs} +1 -1
  557. package/dist/{portable-text-B_kqBmXB.mjs.map → portable-text-imBW5cHK.mjs.map} +1 -1
  558. package/dist/{preview-BU6PaLpM.mjs → preview-PW-nOnq4.mjs} +2 -2
  559. package/dist/{preview-BU6PaLpM.mjs.map → preview-PW-nOnq4.mjs.map} +1 -1
  560. package/dist/protocol-DjsJHTlK.d.mts +52 -0
  561. package/dist/protocol-DjsJHTlK.d.mts.map +1 -0
  562. package/dist/{public-url-Ox9oOlgp.mjs → public-url-CWoFhQT8.mjs} +1 -1
  563. package/dist/{public-url-Ox9oOlgp.mjs.map → public-url-CWoFhQT8.mjs.map} +1 -1
  564. package/dist/{query-rC9HKv1N.mjs → query-BWs7O5Il.mjs} +3 -3
  565. package/dist/{query-rC9HKv1N.mjs.map → query-BWs7O5Il.mjs.map} +1 -1
  566. package/dist/{query-C5w7PsRQ.mjs → query-zTVAR1Sl.mjs} +31 -49
  567. package/dist/query-zTVAR1Sl.mjs.map +1 -0
  568. package/dist/{rate-limit-kug6q99V.mjs → rate-limit-Bx4g9m3p.mjs} +2 -2
  569. package/dist/{rate-limit-kug6q99V.mjs.map → rate-limit-Bx4g9m3p.mjs.map} +1 -1
  570. package/dist/{redirect-Egf2R9yP.mjs → redirect-BgAOGHDq.mjs} +1 -1
  571. package/dist/{redirect-Egf2R9yP.mjs.map → redirect-BgAOGHDq.mjs.map} +1 -1
  572. package/dist/{redirect-DIJxXKOG.mjs → redirect-COsS6SWJ.mjs} +2 -2
  573. package/dist/{redirect-DIJxXKOG.mjs.map → redirect-COsS6SWJ.mjs.map} +1 -1
  574. package/dist/{redirects-G8wAhWAf.mjs → redirects-DTDHWH31.mjs} +133 -14
  575. package/dist/redirects-DTDHWH31.mjs.map +1 -0
  576. package/dist/{redirects-Bzm812bY.mjs → redirects-DyChwDkG.mjs} +4 -4
  577. package/dist/{redirects-Bzm812bY.mjs.map → redirects-DyChwDkG.mjs.map} +1 -1
  578. package/dist/registry-Cqa2I749.mjs +1275 -0
  579. package/dist/registry-Cqa2I749.mjs.map +1 -0
  580. package/dist/{relation-Cbe3Sd3m.mjs → relation-BnHB0T4J.mjs} +3 -3
  581. package/dist/{relation-Cbe3Sd3m.mjs.map → relation-BnHB0T4J.mjs.map} +1 -1
  582. package/dist/{relations-Bw_E1TXo.mjs → relations-BBApI4e2.mjs} +3 -3
  583. package/dist/{relations-Bw_E1TXo.mjs.map → relations-BBApI4e2.mjs.map} +1 -1
  584. package/dist/{relations-G2ta7GIl.d.mts → relations-BHo5A8Zf.d.mts} +367 -33
  585. package/dist/relations-BHo5A8Zf.d.mts.map +1 -0
  586. package/dist/{relations-qHwpUe66.mjs → relations-D5sM5fW0.mjs} +6 -6
  587. package/dist/{relations-qHwpUe66.mjs.map → relations-D5sM5fW0.mjs.map} +1 -1
  588. package/dist/request-context.d.mts +1 -1
  589. package/dist/{request-meta-Df-jFbAd.mjs → request-meta-DgZJh3zG.mjs} +2 -2
  590. package/dist/{request-meta-Df-jFbAd.mjs.map → request-meta-DgZJh3zG.mjs.map} +1 -1
  591. package/dist/{resolve-DZzG4HqM.mjs → resolve-DOhVEvty.mjs} +2 -2
  592. package/dist/{resolve-DZzG4HqM.mjs.map → resolve-DOhVEvty.mjs.map} +1 -1
  593. package/dist/{runner-BaADli8l.d.mts → runner-BYHZn3Jy.d.mts} +16 -3
  594. package/dist/runner-BYHZn3Jy.d.mts.map +1 -0
  595. package/dist/{runner-BFTrkYhu.mjs → runner-C1T11CfC.mjs} +1190 -257
  596. package/dist/runner-C1T11CfC.mjs.map +1 -0
  597. package/dist/runtime.d.mts +11 -11
  598. package/dist/runtime.mjs +4 -3
  599. package/dist/runtime.mjs.map +1 -1
  600. package/dist/schema-2AOsSn2v.mjs +390 -0
  601. package/dist/schema-2AOsSn2v.mjs.map +1 -0
  602. package/dist/{schema-CiQXr6_F.mjs → schema-DZ5YVVZj.mjs} +3 -3
  603. package/dist/{schema-CiQXr6_F.mjs.map → schema-DZ5YVVZj.mjs.map} +1 -1
  604. package/dist/{scopes-CNJVT5i5.mjs → scopes-8ClPF2bC.mjs} +3 -3
  605. package/dist/{scopes-CNJVT5i5.mjs.map → scopes-8ClPF2bC.mjs.map} +1 -1
  606. package/dist/{search-FZhx5dDU.mjs → search-u1QYdOCG.mjs} +25 -15
  607. package/dist/search-u1QYdOCG.mjs.map +1 -0
  608. package/dist/{secrets-DLd8RXee.mjs → secrets-BEgsAQEU.mjs} +3 -3
  609. package/dist/{secrets-DLd8RXee.mjs.map → secrets-BEgsAQEU.mjs.map} +1 -1
  610. package/dist/{sections-BrIrMUCn.mjs → sections-DmHviGyM.mjs} +3 -3
  611. package/dist/{sections-BrIrMUCn.mjs.map → sections-DmHviGyM.mjs.map} +1 -1
  612. package/dist/seed/index.d.mts +2 -2
  613. package/dist/seed/index.mjs +24 -22
  614. package/dist/seo/index.d.mts +3 -3
  615. package/dist/seo/index.mjs +16 -15
  616. package/dist/seo/index.mjs.map +1 -1
  617. package/dist/{seo-CobNfOvb.mjs → seo-AFpVvTqr.mjs} +5 -3
  618. package/dist/seo-AFpVvTqr.mjs.map +1 -0
  619. package/dist/{seo-DTHRntNC.mjs → seo-Dq4G-RrO.mjs} +2 -2
  620. package/dist/{seo-DTHRntNC.mjs.map → seo-Dq4G-RrO.mjs.map} +1 -1
  621. package/dist/{service-B-pYGPgR.mjs → service-BpArayPr.mjs} +3 -3
  622. package/dist/{service-B-pYGPgR.mjs.map → service-BpArayPr.mjs.map} +1 -1
  623. package/dist/{session-user-BvM9-zNl.mjs → session-user-BEorKVT-.mjs} +1 -1
  624. package/dist/{session-user-BvM9-zNl.mjs.map → session-user-BEorKVT-.mjs.map} +1 -1
  625. package/dist/{settings-DPHau-WH.mjs → settings-DE9xtzqd.mjs} +3 -3
  626. package/dist/{settings-DPHau-WH.mjs.map → settings-DE9xtzqd.mjs.map} +1 -1
  627. package/dist/{settings-kJhGiQ4z.mjs → settings-xRdoUZr0.mjs} +4 -4
  628. package/dist/{settings-kJhGiQ4z.mjs.map → settings-xRdoUZr0.mjs.map} +1 -1
  629. package/dist/{setup-complete-u50Qm8rY.mjs → setup-complete-BnT8pq_C.mjs} +1 -1
  630. package/dist/{setup-complete-u50Qm8rY.mjs.map → setup-complete-BnT8pq_C.mjs.map} +1 -1
  631. package/dist/{setup-nonce-DCjiiOD2.mjs → setup-nonce-CBitf_oQ.mjs} +1 -1
  632. package/dist/{setup-nonce-DCjiiOD2.mjs.map → setup-nonce-CBitf_oQ.mjs.map} +1 -1
  633. package/dist/{single-flight-cache-DW3w11Pu.mjs → single-flight-cache-B0eLKS6K.mjs} +2 -2
  634. package/dist/{single-flight-cache-DW3w11Pu.mjs.map → single-flight-cache-B0eLKS6K.mjs.map} +1 -1
  635. package/dist/{site-url-I-lJ5kma.mjs → site-url-DjpIXMXJ.mjs} +2 -2
  636. package/dist/{site-url-I-lJ5kma.mjs.map → site-url-DjpIXMXJ.mjs.map} +1 -1
  637. package/dist/slugify-B994zkXC.mjs +17 -0
  638. package/dist/slugify-B994zkXC.mjs.map +1 -0
  639. package/dist/{snapshot-I_fjLDaD.mjs → snapshot-BBlGkb2q.mjs} +1 -1
  640. package/dist/{snapshot-I_fjLDaD.mjs.map → snapshot-BBlGkb2q.mjs.map} +1 -1
  641. package/dist/{ssrf-CTa6v21i.mjs → ssrf-Cpvg_n3A.mjs} +1 -1
  642. package/dist/{ssrf-CTa6v21i.mjs.map → ssrf-Cpvg_n3A.mjs.map} +1 -1
  643. package/dist/{state-CQvoefYP.mjs → state-DYwPue40.mjs} +1 -1
  644. package/dist/{state-CQvoefYP.mjs.map → state-DYwPue40.mjs.map} +1 -1
  645. package/dist/{status-CIsmlC1E.mjs → status-CWVYpbD8.mjs} +1 -1
  646. package/dist/{status-CIsmlC1E.mjs.map → status-CWVYpbD8.mjs.map} +1 -1
  647. package/dist/storage/local.d.mts +1 -1
  648. package/dist/storage/local.mjs +3 -3
  649. package/dist/storage/s3.d.mts +1 -1
  650. package/dist/storage/s3.mjs +1 -1
  651. package/dist/target-DixqqV5i.mjs +27 -0
  652. package/dist/target-DixqqV5i.mjs.map +1 -0
  653. package/dist/{taxonomies-CLN1N92E.mjs → taxonomies-BlrncHi9.mjs} +75 -64
  654. package/dist/taxonomies-BlrncHi9.mjs.map +1 -0
  655. package/dist/{taxonomies-CKuaZER5.mjs → taxonomies-OHUIiIpI.mjs} +280 -56
  656. package/dist/taxonomies-OHUIiIpI.mjs.map +1 -0
  657. package/dist/{taxonomy-pOrB2kZe.mjs → taxonomy-BqCZ1TdU.mjs} +131 -78
  658. package/dist/taxonomy-BqCZ1TdU.mjs.map +1 -0
  659. package/dist/{tokens-DagaJGK8.mjs → tokens-C39klX8R.mjs} +2 -2
  660. package/dist/{tokens-DagaJGK8.mjs.map → tokens-C39klX8R.mjs.map} +1 -1
  661. package/dist/{transport-DVsa5YYo.mjs → transport-DBJwa-Si.mjs} +1 -1
  662. package/dist/{transport-DVsa5YYo.mjs.map → transport-DBJwa-Si.mjs.map} +1 -1
  663. package/dist/{transport-CAwTaTp_.d.mts → transport-RQE36APG.d.mts} +1 -1
  664. package/dist/{transport-CAwTaTp_.d.mts.map → transport-RQE36APG.d.mts.map} +1 -1
  665. package/dist/{trusted-proxy-D20_7fyX.mjs → trusted-proxy-CEVekpby.mjs} +1 -1
  666. package/dist/{trusted-proxy-D20_7fyX.mjs.map → trusted-proxy-CEVekpby.mjs.map} +1 -1
  667. package/dist/{types-NBI3rF-_.mjs → types-75KIqzL9.mjs} +18 -2
  668. package/dist/types-75KIqzL9.mjs.map +1 -0
  669. package/dist/{types-BjxTKxrZ.mjs → types-BW1syrlw.mjs} +1 -1
  670. package/dist/{types-BjxTKxrZ.mjs.map → types-BW1syrlw.mjs.map} +1 -1
  671. package/dist/{types-DLG4IFEQ.d.mts → types-BcqdcT-r.d.mts} +1 -1
  672. package/dist/{types-DLG4IFEQ.d.mts.map → types-BcqdcT-r.d.mts.map} +1 -1
  673. package/dist/{types-LoagAGzH.d.mts → types-BntycPTF.d.mts} +1 -1
  674. package/dist/{types-LoagAGzH.d.mts.map → types-BntycPTF.d.mts.map} +1 -1
  675. package/dist/{types-BnFP1M3J.d.mts → types-C2pMvO62.d.mts} +32 -10
  676. package/dist/types-C2pMvO62.d.mts.map +1 -0
  677. package/dist/{types-Cd8iuS1J.mjs → types-CQPWhPxE.mjs} +9 -12
  678. package/dist/types-CQPWhPxE.mjs.map +1 -0
  679. package/dist/{types-C8oz_ayJ.d.mts → types-CXnOzDe1.d.mts} +1 -1
  680. package/dist/{types-C8oz_ayJ.d.mts.map → types-CXnOzDe1.d.mts.map} +1 -1
  681. package/dist/types-CtzytVXn.mjs.map +1 -1
  682. package/dist/{types-BGWPMiBO.d.mts → types-DN64_zzZ.d.mts} +44 -5
  683. package/dist/types-DN64_zzZ.d.mts.map +1 -0
  684. package/dist/{types-Dc4ntQjQ.d.mts → types-DQIDRKF2.d.mts} +124 -1
  685. package/dist/types-DQIDRKF2.d.mts.map +1 -0
  686. package/dist/{types-CbUcuxxc.d.mts → types-DWRhk9xZ.d.mts} +1 -1
  687. package/dist/{types-CbUcuxxc.d.mts.map → types-DWRhk9xZ.d.mts.map} +1 -1
  688. package/dist/{types-BK6U01Ro.d.mts → types-Dfk8KI5R.d.mts} +1 -1
  689. package/dist/{types-BK6U01Ro.d.mts.map → types-Dfk8KI5R.d.mts.map} +1 -1
  690. package/dist/{types-Cz8hNch2.d.mts → types-DrJrVCT1.d.mts} +25 -5
  691. package/dist/types-DrJrVCT1.d.mts.map +1 -0
  692. package/dist/{upload-attempts-D8QAFLUJ.mjs → upload-attempts-D4FS8LT6.mjs} +1 -1
  693. package/dist/{upload-attempts-D8QAFLUJ.mjs.map → upload-attempts-D4FS8LT6.mjs.map} +1 -1
  694. package/dist/url-pattern-BHS0V5Ng.mjs +33 -0
  695. package/dist/url-pattern-BHS0V5Ng.mjs.map +1 -0
  696. package/dist/{user-DBrq4UVq.mjs → user-DJZfUJVE.mjs} +3 -3
  697. package/dist/{user-DBrq4UVq.mjs.map → user-DJZfUJVE.mjs.map} +1 -1
  698. package/dist/{utils-hLzi_2Fn.mjs → utils-D4vD_Y98.mjs} +3 -3
  699. package/dist/{utils-hLzi_2Fn.mjs.map → utils-D4vD_Y98.mjs.map} +1 -1
  700. package/dist/{validate-mKo3RxBM.mjs → validate-BMLBvxOC.mjs} +24 -5
  701. package/dist/validate-BMLBvxOC.mjs.map +1 -0
  702. package/dist/{validate-C3oSmA7F.d.mts → validate-CTqt5nuE.d.mts} +15 -7
  703. package/dist/validate-CTqt5nuE.d.mts.map +1 -0
  704. package/dist/{validation-BgpucsvF.mjs → validation-npvENUCB.mjs} +11 -10
  705. package/dist/{validation-BgpucsvF.mjs.map → validation-npvENUCB.mjs.map} +1 -1
  706. package/dist/version-DB_fqCSI.mjs +7 -0
  707. package/dist/{version-C4PnpmoV.mjs.map → version-DB_fqCSI.mjs.map} +1 -1
  708. package/dist/{widgets-CJJtkiKh.mjs → widgets-BD3ho7Rq.mjs} +3 -3
  709. package/dist/{widgets-CJJtkiKh.mjs.map → widgets-BD3ho7Rq.mjs.map} +1 -1
  710. package/dist/{wxr-taxonomies-9PPSy8X6.mjs → wxr-taxonomies-B1R3vBoD.mjs} +13 -32
  711. package/dist/{wxr-taxonomies-9PPSy8X6.mjs.map → wxr-taxonomies-B1R3vBoD.mjs.map} +1 -1
  712. package/dist/{wxr-taxonomies-Bkpp_2tK.d.mts → wxr-taxonomies-Ca68766D.d.mts} +1 -1
  713. package/dist/{wxr-taxonomies-Bkpp_2tK.d.mts.map → wxr-taxonomies-Ca68766D.d.mts.map} +1 -1
  714. package/dist/{zod-generator-CG64Hnbh.mjs → zod-generator-LC-on_Vb.mjs} +52 -5
  715. package/dist/zod-generator-LC-on_Vb.mjs.map +1 -0
  716. package/package.json +32 -8
  717. package/src/api/errors.ts +12 -0
  718. package/src/api/handlers/content.ts +127 -29
  719. package/src/api/handlers/dashboard.ts +12 -2
  720. package/src/api/handlers/index.ts +16 -0
  721. package/src/api/handlers/manifest.ts +2 -0
  722. package/src/api/handlers/media-allowlist.ts +13 -2
  723. package/src/api/handlers/media-usage-work.ts +188 -0
  724. package/src/api/handlers/media-usage.ts +5 -3
  725. package/src/api/handlers/schema.ts +9 -3
  726. package/src/api/handlers/seo.ts +5 -2
  727. package/src/api/handlers/taxonomies.ts +345 -82
  728. package/src/api/media-usage-write-fence.ts +64 -0
  729. package/src/api/openapi/document.ts +199 -0
  730. package/src/api/schemas/common.ts +3 -1
  731. package/src/api/schemas/content.ts +122 -1
  732. package/src/api/schemas/media-usage.ts +133 -0
  733. package/src/api/schemas/schema.ts +78 -3
  734. package/src/api/schemas/taxonomies.ts +40 -8
  735. package/src/api/types.ts +1 -0
  736. package/src/astro/integration/index.ts +101 -56
  737. package/src/astro/integration/routes.ts +34 -4
  738. package/src/astro/integration/runtime.ts +18 -0
  739. package/src/astro/integration/virtual-modules.ts +25 -1
  740. package/src/astro/integration/vite-config.ts +16 -1
  741. package/src/astro/middleware/media-usage-write-fence.ts +30 -0
  742. package/src/astro/middleware/redirect.ts +12 -2
  743. package/src/astro/middleware/scoped-db.ts +21 -0
  744. package/src/astro/middleware.ts +140 -16
  745. package/src/astro/routes/api/admin/media-usage/collection-deletions/index.ts +22 -0
  746. package/src/astro/routes/api/admin/media-usage/collection-deletions/retry.ts +22 -0
  747. package/src/astro/routes/api/admin/media-usage/work/index.ts +26 -0
  748. package/src/astro/routes/api/admin/media-usage/work/retry.ts +26 -0
  749. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +4 -0
  750. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +4 -0
  751. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +4 -0
  752. package/src/astro/routes/api/admin/plugins/[id]/update.ts +4 -0
  753. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +4 -0
  754. package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +4 -0
  755. package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +4 -0
  756. package/src/astro/routes/api/admin/plugins/registry/install.ts +4 -0
  757. package/src/astro/routes/api/auth/dev-bypass.ts +0 -4
  758. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +67 -31
  759. package/src/astro/routes/api/import/wordpress/execute.ts +3 -10
  760. package/src/astro/routes/api/mcp.ts +1 -0
  761. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +7 -1
  762. package/src/astro/routes/api/schema/collections/[slug]/index.ts +1 -7
  763. package/src/astro/routes/api/setup/dev-bypass.ts +2 -7
  764. package/src/astro/routes/api/setup/index.ts +5 -13
  765. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +1 -0
  766. package/src/astro/routes/api/taxonomies/[name]/translations.ts +48 -0
  767. package/src/astro/routes/api/taxonomies/[name].ts +102 -0
  768. package/src/astro/types.ts +25 -4
  769. package/src/cleanup.ts +6 -12
  770. package/src/cli/commands/doctor.ts +193 -6
  771. package/src/cli/commands/export-seed.ts +4 -1
  772. package/src/cli/commands/migrate.ts +593 -0
  773. package/src/cli/index.ts +2 -23
  774. package/src/client/index.ts +119 -0
  775. package/src/components/Block.astro +12 -0
  776. package/src/components/InlinePortableTextEditor.tsx +89 -1
  777. package/src/content/converters/mark-safety.ts +120 -0
  778. package/src/content/converters/portable-text-to-prosemirror.ts +25 -16
  779. package/src/content/converters/prosemirror-to-portable-text.ts +12 -2
  780. package/src/content-list-query.ts +29 -0
  781. package/src/database/index.ts +8 -2
  782. package/src/database/migrations/060_collection_admin_config.ts +16 -0
  783. package/src/database/migrations/061_media_usage_cleanup.ts +77 -0
  784. package/src/database/migrations/062_media_usage_cleanup_fence.ts +295 -0
  785. package/src/database/migrations/063_media_usage_incremental_work.ts +397 -0
  786. package/src/database/migrations/064_fts_plain_text.ts +253 -0
  787. package/src/database/migrations/065_media_usage_collection_deletion.ts +85 -0
  788. package/src/database/migrations/066_media_usage_reconciliation.ts +115 -0
  789. package/src/database/migrations/067_indexed_content_fields.ts +39 -0
  790. package/src/database/migrations/068_content_taxonomy_entry_groups.ts +61 -0
  791. package/src/database/migrations/069_collection_title_date_fields.ts +45 -0
  792. package/src/database/migrations/070_collection_routable.ts +18 -0
  793. package/src/database/migrations/policy.ts +70 -0
  794. package/src/database/migrations/runner.ts +71 -3
  795. package/src/database/repositories/content.ts +861 -96
  796. package/src/database/repositories/media-usage-work.ts +848 -0
  797. package/src/database/repositories/media-usage.ts +1502 -138
  798. package/src/database/repositories/revision.ts +17 -6
  799. package/src/database/repositories/taxonomy.ts +234 -103
  800. package/src/database/repositories/types.ts +51 -2
  801. package/src/database/types.ts +134 -16
  802. package/src/db/adapters.ts +78 -2
  803. package/src/db/index.ts +6 -1
  804. package/src/db/libsql-migrations.ts +72 -0
  805. package/src/db/postgres-migrations.ts +59 -0
  806. package/src/db/sqlite-migrations.ts +37 -0
  807. package/src/emdash-runtime.ts +271 -35
  808. package/src/fields/file.ts +7 -4
  809. package/src/fields/image.ts +8 -1
  810. package/src/fields/types.ts +18 -5
  811. package/src/i18n/config.ts +32 -0
  812. package/src/i18n/normalize.ts +31 -0
  813. package/src/i18n/repair-locale-casing.ts +0 -14
  814. package/src/i18n/taxonomy-locale-diagnostic.ts +47 -0
  815. package/src/import/wxr-taxonomies.ts +7 -47
  816. package/src/index.ts +32 -3
  817. package/src/loader.ts +119 -65
  818. package/src/mcp/server.ts +242 -34
  819. package/src/media/usage/activation.ts +626 -0
  820. package/src/media/usage/capture-triggers.ts +543 -0
  821. package/src/media/usage/cleanup.ts +305 -0
  822. package/src/media/usage/collection-deletion-processor.ts +356 -0
  823. package/src/media/usage/collection-deletion.ts +836 -0
  824. package/src/media/usage/content-fields.ts +40 -3
  825. package/src/media/usage/content-refresh.ts +356 -47
  826. package/src/media/usage/content-repair.ts +180 -61
  827. package/src/media/usage/content-snapshots.ts +85 -105
  828. package/src/media/usage/projection-fingerprint.ts +129 -0
  829. package/src/media/usage/reconciliation-processor.ts +372 -0
  830. package/src/media/usage/reconciliation.ts +1117 -0
  831. package/src/media/usage/source-key.ts +4 -0
  832. package/src/media/usage/types.ts +2 -0
  833. package/src/media/usage/work-processor.ts +248 -0
  834. package/src/menus/index.ts +246 -141
  835. package/src/migrations/config-loader.ts +205 -0
  836. package/src/migrations/direct-executor.ts +141 -0
  837. package/src/migrations/identity.ts +46 -0
  838. package/src/migrations/index.ts +19 -0
  839. package/src/migrations/integration-metadata.ts +67 -0
  840. package/src/migrations/manifest-builder.ts +55 -0
  841. package/src/migrations/manifest-writer.ts +63 -0
  842. package/src/migrations/manifest.ts +197 -0
  843. package/src/migrations/protocol.ts +59 -0
  844. package/src/migrations/target.ts +35 -0
  845. package/src/plugin-types.ts +8 -0
  846. package/src/plugins/adapt-sandbox-entry.ts +24 -5
  847. package/src/plugins/context.ts +24 -7
  848. package/src/plugins/index.ts +9 -0
  849. package/src/plugins/routes.ts +43 -1
  850. package/src/plugins/sandbox/index.ts +10 -1
  851. package/src/plugins/sandbox/types.ts +78 -1
  852. package/src/plugins/scheduler/node.ts +13 -1
  853. package/src/plugins/scheduler/types.ts +2 -0
  854. package/src/plugins/types.ts +39 -2
  855. package/src/query.ts +29 -37
  856. package/src/scheduler-health.ts +46 -0
  857. package/src/schema/registry.ts +777 -255
  858. package/src/schema/types.ts +50 -8
  859. package/src/schema/url-pattern.ts +33 -0
  860. package/src/schema/zod-generator.ts +77 -5
  861. package/src/search/fts-manager.ts +117 -76
  862. package/src/search/query.ts +32 -11
  863. package/src/search/types.ts +2 -0
  864. package/src/seed/apply.ts +68 -15
  865. package/src/seed/types.ts +11 -3
  866. package/src/seed/validate.ts +52 -2
  867. package/src/taxonomies/index.ts +77 -75
  868. package/src/taxonomies/term-counts.ts +21 -8
  869. package/src/utils/slugify.ts +1 -29
  870. package/src/virtual-modules.d.ts +24 -0
  871. package/dist/adapters-BMyNSSZi.d.mts.map +0 -1
  872. package/dist/api-D2hunekQ.mjs.map +0 -1
  873. package/dist/apply-kwNEJW2l.mjs.map +0 -1
  874. package/dist/config-DyF3OKg_.mjs.map +0 -1
  875. package/dist/content-CJ94NEx5.mjs.map +0 -1
  876. package/dist/content-refresh-Xw7aKmou.mjs +0 -1629
  877. package/dist/content-refresh-Xw7aKmou.mjs.map +0 -1
  878. package/dist/context-C_1nrqnW.mjs.map +0 -1
  879. package/dist/dashboard-DINnNVVU.mjs.map +0 -1
  880. package/dist/errors-BucQ8VYz.mjs.map +0 -1
  881. package/dist/fts-manager-BITakW_R.mjs.map +0 -1
  882. package/dist/index-M37iz29I.d.mts.map +0 -1
  883. package/dist/index-MGw47uWq.d.mts.map +0 -1
  884. package/dist/loader-CGugY7Zl.mjs.map +0 -1
  885. package/dist/media-OhYL-7Io.mjs.map +0 -1
  886. package/dist/media-allowlist-D-peH1H5.mjs.map +0 -1
  887. package/dist/media-usage-BlxfTkN0.mjs.map +0 -1
  888. package/dist/menus-Y54RDPIN.mjs.map +0 -1
  889. package/dist/options-CA4eVX6P.d.mts.map +0 -1
  890. package/dist/query-C5w7PsRQ.mjs.map +0 -1
  891. package/dist/redirects-G8wAhWAf.mjs.map +0 -1
  892. package/dist/registry-Dbodb4Uo.mjs +0 -840
  893. package/dist/registry-Dbodb4Uo.mjs.map +0 -1
  894. package/dist/relations-G2ta7GIl.d.mts.map +0 -1
  895. package/dist/runner-BFTrkYhu.mjs.map +0 -1
  896. package/dist/runner-BaADli8l.d.mts.map +0 -1
  897. package/dist/search-FZhx5dDU.mjs.map +0 -1
  898. package/dist/seo-CobNfOvb.mjs.map +0 -1
  899. package/dist/slugify-C_tqlU4G.mjs +0 -30
  900. package/dist/slugify-C_tqlU4G.mjs.map +0 -1
  901. package/dist/taxonomies-CKuaZER5.mjs.map +0 -1
  902. package/dist/taxonomies-CLN1N92E.mjs.map +0 -1
  903. package/dist/taxonomy-pOrB2kZe.mjs.map +0 -1
  904. package/dist/types-BGWPMiBO.d.mts.map +0 -1
  905. package/dist/types-BnFP1M3J.d.mts.map +0 -1
  906. package/dist/types-Cd8iuS1J.mjs.map +0 -1
  907. package/dist/types-Cz8hNch2.d.mts.map +0 -1
  908. package/dist/types-Dc4ntQjQ.d.mts.map +0 -1
  909. package/dist/types-NBI3rF-_.mjs.map +0 -1
  910. package/dist/validate-C3oSmA7F.d.mts.map +0 -1
  911. package/dist/validate-mKo3RxBM.mjs.map +0 -1
  912. package/dist/version-C4PnpmoV.mjs +0 -7
  913. package/dist/zod-generator-CG64Hnbh.mjs.map +0 -1
  914. /package/dist/{api-tokens-Dai9dND0.mjs → api-tokens-rIXC6LdE.mjs} +0 -0
  915. /package/dist/{ssrf-Cj568Dgs.mjs → ssrf-DpXgKsna.mjs} +0 -0
  916. /package/dist/{types-DKuWPYV5.mjs → types-CP1CflWf.mjs} +0 -0
@@ -1,10 +1,11 @@
1
- import { o as __exportAll } from "./runner-BFTrkYhu.mjs";
1
+ import { c as __exportAll } from "./runner-C1T11CfC.mjs";
2
2
  import { t as validateIdentifier } from "./validate-BpwoDOgt.mjs";
3
3
  import { c as invalidateCollectionCache } from "./object-cache-71tPfV4A.mjs";
4
- import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-DbYzib_k.mjs";
5
- import { n as isMissingTableError } from "./db-errors-CcWLaRiR.mjs";
6
- import { n as slugify } from "./slugify-C_tqlU4G.mjs";
7
- import { a as decodeCursor, i as ScheduledNotDueError, n as EmDashValidationError, o as encodeCursor, t as ContentMutationConflictError } from "./types-Cd8iuS1J.mjs";
4
+ import { c as isIndexableFieldType } from "./types-75KIqzL9.mjs";
5
+ import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-fiZ8G9RJ.mjs";
6
+ import { n as isMissingTableError } from "./db-errors-Cl-sKYTm.mjs";
7
+ import { n as slugify } from "./slugify-B994zkXC.mjs";
8
+ import { a as ScheduledNotDueError, i as InvalidCursorError, n as ContentMutationConflictError, o as decodeCursor, r as EmDashValidationError, s as encodeCursor, t as ContentCollectionNotFoundError } from "./types-CQPWhPxE.mjs";
8
9
  import { sql } from "kysely";
9
10
  import { monotonicFactory, ulid } from "ulidx";
10
11
 
@@ -134,15 +135,18 @@ var RevisionRepository = class {
134
135
  /**
135
136
  * Delete old revisions, keeping the most recent N
136
137
  */
137
- async pruneOldRevisions(collection, entryId, keepCount) {
138
+ async pruneOldRevisions(collection, entryId, keepCount, throughRevisionId) {
138
139
  validateIdentifier(collection, "collection");
139
140
  const tableName = `ec_${collection}`;
140
- const keepIds = (await this.db.selectFrom("revisions").select("id").where("collection", "=", collection).where("entry_id", "=", entryId).orderBy("created_at", "desc").orderBy("id", "desc").limit(keepCount).execute()).map((r) => r.id);
141
+ let keepQuery = this.db.selectFrom("revisions").select("id").where("collection", "=", collection).where("entry_id", "=", entryId).orderBy("created_at", "desc").orderBy("id", "desc").limit(keepCount);
142
+ if (throughRevisionId) keepQuery = keepQuery.where("id", "<=", throughRevisionId);
143
+ const keepIds = (await keepQuery.execute()).map((r) => r.id);
141
144
  if (keepIds.length === 0) return 0;
142
145
  const result = await sql`
143
146
  DELETE FROM revisions
144
147
  WHERE collection = ${collection}
145
148
  AND entry_id = ${entryId}
149
+ ${throughRevisionId ? sql`AND id <= ${throughRevisionId}` : sql``}
146
150
  AND id NOT IN (${sql.join(keepIds.map((id) => sql`${id}`))})
147
151
  AND NOT EXISTS (
148
152
  SELECT 1 FROM ${sql.ref(tableName)} AS content
@@ -153,7 +157,7 @@ var RevisionRepository = class {
153
157
  return Number(result.numAffectedRows ?? 0);
154
158
  }
155
159
  async pruneQueuedEntry(collection, entryId, queuedRevisionId, keepCount) {
156
- const pruned = await this.pruneOldRevisions(collection, entryId, keepCount);
160
+ const pruned = await this.pruneOldRevisions(collection, entryId, keepCount, queuedRevisionId);
157
161
  await this.db.deleteFrom("_emdash_revision_prune_queue").where("collection", "=", collection).where("entry_id", "=", entryId).where("revision_id", "=", queuedRevisionId).execute();
158
162
  return pruned;
159
163
  }
@@ -189,10 +193,17 @@ var RevisionRepository = class {
189
193
 
190
194
  //#endregion
191
195
  //#region src/database/repositories/content.ts
192
- var content_exports = /* @__PURE__ */ __exportAll({ ContentRepository: () => ContentRepository });
196
+ var content_exports = /* @__PURE__ */ __exportAll({
197
+ ContentRepository: () => ContentRepository,
198
+ isSystemOrderField: () => isSystemOrderField
199
+ });
193
200
  const ULID_PATTERN = /^[0-9A-Z]{26}$/;
194
201
  const SQLSTATE_PATTERN = /^[0-9A-Z]{5}$/;
202
+ const MAX_DRAFT_STAGE_ATTEMPTS = 32;
195
203
  const LIKE_WILDCARD_RE = /[\\%_]/g;
204
+ const MAX_INDEXED_FIELD_FILTERS = 20;
205
+ const MAX_IN_FILTER_VALUES = SQL_BATCH_SIZE;
206
+ const MAX_FILTER_STRING_LENGTH = 2048;
196
207
  function nullableColumnMatch(column, value) {
197
208
  validateIdentifier(column, "content column");
198
209
  return value === null ? sql`${sql.ref(column)} IS NULL` : sql`${sql.ref(column)} = ${value}`;
@@ -204,6 +215,10 @@ function matchesPublication(observed, existing, revision, revisionId, slug, publ
204
215
  if (observed.version !== existing.version + 1 || observed.status !== "published" || observed.slug !== slug || observed.liveRevisionId !== revisionId || observed.draftRevisionId !== null || observed.scheduledAt !== null || observed.publishedAt !== publishedAt || observed.updatedAt !== updatedAt) return false;
205
216
  return Object.entries(revision.data).every(([key, value]) => SYSTEM_COLUMNS.has(key) || key.startsWith("_") || sameStoredValue(observed.data[key], value));
206
217
  }
218
+ function matchesLifecyclePublication(observed, existing, liveRevisionId, publishedAt, updatedAt) {
219
+ if (observed.version !== existing.version + 1 || observed.status !== "published" || observed.slug !== existing.slug || observed.liveRevisionId !== liveRevisionId || observed.draftRevisionId !== null || observed.scheduledAt !== null || observed.publishedAt !== publishedAt || observed.updatedAt !== updatedAt) return false;
220
+ return Object.entries(existing.data).every(([key, value]) => sameStoredValue(observed.data[key], value));
221
+ }
207
222
  function matchesPublicationFence(observed, existing) {
208
223
  return observed.version === existing.version && observed.status === existing.status && observed.liveRevisionId === existing.liveRevisionId && observed.draftRevisionId === existing.draftRevisionId && observed.scheduledAt === existing.scheduledAt;
209
224
  }
@@ -212,6 +227,31 @@ function isConfirmedStatementFailure(error) {
212
227
  const code = error.code;
213
228
  return typeof code === "string" && (code.startsWith("SQLITE_") || SQLSTATE_PATTERN.test(code));
214
229
  }
230
+ function encodeIndexedFieldCursor(field, value, id) {
231
+ const payload = {
232
+ version: 1,
233
+ field,
234
+ value
235
+ };
236
+ return encodeCursor(JSON.stringify(payload), id);
237
+ }
238
+ function decodeIndexedFieldCursor(cursor, field) {
239
+ const { orderValue, id } = decodeCursor(cursor);
240
+ let payload;
241
+ try {
242
+ payload = JSON.parse(orderValue);
243
+ } catch {
244
+ throw new InvalidCursorError(cursor);
245
+ }
246
+ if (payload === null || typeof payload !== "object") throw new InvalidCursorError(cursor);
247
+ const candidate = payload;
248
+ const validValue = candidate.value === null || typeof candidate.value === "string" || typeof candidate.value === "number";
249
+ if (candidate.version !== 1 || candidate.field !== field || !validValue) throw new InvalidCursorError(cursor);
250
+ return {
251
+ value: candidate.value,
252
+ id
253
+ };
254
+ }
215
255
  /**
216
256
  * Whitelist mapping a public date-filter field to its physical column. Keeping
217
257
  * this separate from `mapOrderField` makes the filterable set explicit and
@@ -223,6 +263,27 @@ const DATE_FILTER_COLUMNS = {
223
263
  publishedAt: "published_at"
224
264
  };
225
265
  /**
266
+ * Built-in sort fields → their physical columns. A closed set that blocks
267
+ * sorting by arbitrary columns; per-collection fields are allowed
268
+ * separately via `mapOrderField`'s `sortableExtras`.
269
+ */
270
+ const ORDER_FIELD_COLUMNS = {
271
+ createdAt: "created_at",
272
+ updatedAt: "updated_at",
273
+ publishedAt: "published_at",
274
+ scheduledAt: "scheduled_at",
275
+ deletedAt: "deleted_at",
276
+ title: "title",
277
+ name: "name",
278
+ slug: "slug",
279
+ status: "status",
280
+ locale: "locale"
281
+ };
282
+ /** True when `field` maps to a system column and needs no per-collection resolution. */
283
+ function isSystemOrderField(field) {
284
+ return field in ORDER_FIELD_COLUMNS;
285
+ }
286
+ /**
226
287
  * System columns that exist in every ec_* table
227
288
  */
228
289
  const SYSTEM_COLUMNS = new Set([
@@ -260,6 +321,15 @@ function serializeValue(value) {
260
321
  if (typeof value === "object") return JSON.stringify(value);
261
322
  return value;
262
323
  }
324
+ function writableContentData(data) {
325
+ const writable = {};
326
+ for (const [key, value] of Object.entries(data)) {
327
+ if (SYSTEM_COLUMNS.has(key)) continue;
328
+ validateIdentifier(key, "content field name");
329
+ writable[key] = value;
330
+ }
331
+ return writable;
332
+ }
263
333
  /**
264
334
  * Deserialize a value from database storage
265
335
  * Attempts to parse JSON strings that look like objects/arrays
@@ -296,7 +366,7 @@ var ContentRepository = class {
296
366
  * Create a new content item
297
367
  */
298
368
  async create(input) {
299
- const id = ulid();
369
+ const id = input.id ?? ulid();
300
370
  const now = (/* @__PURE__ */ new Date()).toISOString();
301
371
  const { type, slug, data, status = "draft", authorId, primaryBylineId, locale, translationOf, publishedAt, createdAt } = input;
302
372
  if (!type) throw new EmDashValidationError("Content type is required");
@@ -358,7 +428,7 @@ var ContentRepository = class {
358
428
  * (optionally scoped to a locale) and appends a numeric suffix (`-1`,
359
429
  * `-2`, etc.) on collision to guarantee uniqueness.
360
430
  *
361
- * Returns `null` if `baseSlug` is empty after slugification.
431
+ * Returns null when slug normalization cannot produce a value.
362
432
  */
363
433
  async generateUniqueSlug(type, text, locale) {
364
434
  const baseSlug = slugify(text);
@@ -521,7 +591,9 @@ var ContentRepository = class {
521
591
  const limit = Math.min(options.limit || 50, 100);
522
592
  const orderField = options.orderBy?.field || "createdAt";
523
593
  const orderDirection = options.orderBy?.direction || "desc";
524
- const dbField = this.mapOrderField(orderField);
594
+ const resolvedOrderField = await this.resolveOrderField(type, orderField, options.sortableExtras);
595
+ const dbField = resolvedOrderField.column;
596
+ const resolvedFieldFilters = await this.resolveFieldFilters(type, options.where?.fieldFilters);
525
597
  const safeOrderDirection = orderDirection.toLowerCase() === "asc" ? "ASC" : "DESC";
526
598
  let query = this.db.selectFrom(tableName).selectAll().where("deleted_at", "is", null);
527
599
  if (options.where?.status) query = query.where("status", "=", options.where.status);
@@ -529,13 +601,42 @@ var ContentRepository = class {
529
601
  if (options.where?.locale) query = query.where("locale", "=", options.where.locale);
530
602
  query = this.applySearchFilter(query, options.where, type);
531
603
  query = this.applyDateFilter(query, options.where);
532
- if (options.cursor) {
604
+ query = this.applyBylineFilter(query, options.where, type);
605
+ query = this.applyFieldFilters(query, resolvedFieldFilters);
606
+ if (options.cursor) if (resolvedOrderField.indexedCustomField) {
607
+ const { value, id: cursorId } = decodeIndexedFieldCursor(options.cursor, orderField);
608
+ const isPresent = sql`${sql.ref(dbField)} IS NOT NULL`;
609
+ const falseLiteral = sql`FALSE`;
610
+ const trueLiteral = sql`TRUE`;
611
+ if (safeOrderDirection === "ASC" && value === null) query = query.where(sql`
612
+ (${isPresent}) > ${falseLiteral}
613
+ OR ((${isPresent}) = ${falseLiteral} AND ${sql.ref("id")} > ${cursorId})
614
+ `);
615
+ else if (safeOrderDirection === "DESC" && value === null) query = query.where(sql`
616
+ (${isPresent}) = ${falseLiteral} AND ${sql.ref("id")} < ${cursorId}
617
+ `);
618
+ else if (safeOrderDirection === "ASC") query = query.where(sql`
619
+ (${isPresent}, ${sql.ref(dbField)}, ${sql.ref("id")})
620
+ > (${trueLiteral}, ${value}, ${cursorId})
621
+ `);
622
+ else query = query.where(sql`
623
+ (${isPresent}, ${sql.ref(dbField)}, ${sql.ref("id")})
624
+ < (${trueLiteral}, ${value}, ${cursorId})
625
+ `);
626
+ } else {
533
627
  const { orderValue, id: cursorId } = decodeCursor(options.cursor);
534
628
  if (safeOrderDirection === "DESC") query = query.where((eb) => eb.or([eb(dbField, "<", orderValue), eb.and([eb(dbField, "=", orderValue), eb("id", "<", cursorId)])]));
535
629
  else query = query.where((eb) => eb.or([eb(dbField, ">", orderValue), eb.and([eb(dbField, "=", orderValue), eb("id", ">", cursorId)])]));
536
630
  }
537
- query = query.orderBy(dbField, safeOrderDirection === "ASC" ? "asc" : "desc").orderBy("id", safeOrderDirection === "ASC" ? "asc" : "desc").limit(limit + 1);
538
- const [rows, total] = await Promise.all([query.execute(), this.count(type, options.where)]);
631
+ const indexedOrderFilter = resolvedOrderField.indexedCustomField ? resolvedFieldFilters.find((filter) => filter.column === dbField) : void 0;
632
+ if (resolvedOrderField.indexedCustomField && !indexedOrderFilter) query = query.orderBy(sql`${sql.ref(dbField)} IS NOT NULL`, safeOrderDirection === "ASC" ? "asc" : "desc");
633
+ if (indexedOrderFilter?.kind !== "null") query = query.orderBy(dbField, safeOrderDirection === "ASC" ? "asc" : "desc");
634
+ query = query.orderBy("id", safeOrderDirection === "ASC" ? "asc" : "desc").limit(limit + 1);
635
+ const [rowsResult, countResult] = await Promise.allSettled([query.execute(), this.countWithResolvedFilters(type, options.where, resolvedFieldFilters)]);
636
+ if (rowsResult.status === "rejected") throw rowsResult.reason;
637
+ if (countResult.status === "rejected") throw countResult.reason;
638
+ const rows = rowsResult.value;
639
+ const total = countResult.value;
539
640
  const hasMore = rows.length > limit;
540
641
  const items = rows.slice(0, limit);
541
642
  const mappedResult = {
@@ -545,7 +646,10 @@ var ContentRepository = class {
545
646
  if (hasMore && items.length > 0) {
546
647
  const lastRow = items.at(-1);
547
648
  const lastOrderValue = lastRow[dbField];
548
- mappedResult.nextCursor = encodeCursor(typeof lastOrderValue === "string" || typeof lastOrderValue === "number" ? String(lastOrderValue) : "", String(lastRow.id));
649
+ if (resolvedOrderField.indexedCustomField) {
650
+ if (lastOrderValue !== null && typeof lastOrderValue !== "string" && typeof lastOrderValue !== "number") throw new EmDashValidationError(`Invalid indexed value for order field: ${orderField}`);
651
+ mappedResult.nextCursor = encodeIndexedFieldCursor(orderField, lastOrderValue, String(lastRow.id));
652
+ } else mappedResult.nextCursor = encodeCursor(typeof lastOrderValue === "string" || typeof lastOrderValue === "number" ? String(lastOrderValue) : "", String(lastRow.id));
549
653
  }
550
654
  return mappedResult;
551
655
  }
@@ -562,23 +666,137 @@ var ContentRepository = class {
562
666
  if (input.scheduledAt !== void 0) updates.scheduled_at = input.scheduledAt;
563
667
  if (input.authorId !== void 0) updates.author_id = input.authorId;
564
668
  if (input.primaryBylineId !== void 0) updates.primary_byline_id = input.primaryBylineId;
565
- if (input.data !== void 0 && typeof input.data === "object") {
566
- for (const [key, value] of Object.entries(input.data)) if (!SYSTEM_COLUMNS.has(key)) {
567
- validateIdentifier(key, "content field name");
568
- updates[key] = serializeValue(value);
569
- }
570
- }
669
+ if (input.data !== void 0 && typeof input.data === "object") for (const [key, value] of Object.entries(writableContentData(input.data))) updates[key] = serializeValue(value);
571
670
  const hasColumnWrites = Object.keys(updates).length > 0;
572
671
  if (hasColumnWrites) updates.updated_at = now;
573
672
  updates.version = sql`version + 1`;
574
673
  await this.db.updateTable(tableName).set(updates).where("id", "=", id).where("deleted_at", "is", null).execute();
575
- if (input.status !== void 0 || input.publishedAt !== void 0 || input.scheduledAt !== void 0) await this.restampEntryPivot(type, id);
576
674
  if (hasColumnWrites) invalidateCollectionCache(type);
577
675
  const updated = await this.findById(type, id);
578
676
  if (!updated) throw new Error("Content not found");
579
677
  return updated;
580
678
  }
581
679
  /**
680
+ * Update plugin-authored fields without letting content columns diverge
681
+ * from the revision pointers that publication promotes.
682
+ */
683
+ async updateDraftAware(type, id, input) {
684
+ const data = input.data ? writableContentData(input.data) : {};
685
+ const stagedSlug = typeof input.slug === "string" ? input.slug : void 0;
686
+ if (!(Object.keys(data).length > 0 || stagedSlug !== void 0)) return this.update(type, id, {
687
+ ...input,
688
+ data
689
+ });
690
+ const collectionRows = await this.db.selectFrom("_emdash_collections as collection").leftJoin("_emdash_fields as field", "field.collection_id", "collection.id").select(["collection.supports", "field.slug as fieldSlug"]).where("collection.slug", "=", type).execute();
691
+ const supportsRaw = collectionRows[0]?.supports;
692
+ const supports = supportsRaw ? JSON.parse(supportsRaw) : [];
693
+ if (!Array.isArray(supports) || !supports.includes("revisions")) return this.update(type, id, {
694
+ ...input,
695
+ data
696
+ });
697
+ const fieldSlugs = new Set(collectionRows.map((row) => row.fieldSlug).filter(Boolean));
698
+ for (const field of Object.keys(data)) if (!fieldSlugs.has(field)) throw new EmDashValidationError(`Unknown field '${field}' in collection '${type}'`);
699
+ const revisionRepo = new RevisionRepository(this.db);
700
+ let existing = await this.findById(type, id);
701
+ for (let attempt = 0; existing && attempt < MAX_DRAFT_STAGE_ATTEMPTS; attempt++) {
702
+ let baseData = existing.data;
703
+ if (existing.draftRevisionId) {
704
+ const draft = await revisionRepo.findById(existing.draftRevisionId);
705
+ if (draft) baseData = draft.data;
706
+ }
707
+ const mergedData = {
708
+ ...baseData,
709
+ ...data
710
+ };
711
+ if (stagedSlug !== void 0) mergedData._slug = stagedSlug;
712
+ const revision = await revisionRepo.create({
713
+ collection: type,
714
+ entryId: id,
715
+ data: mergedData,
716
+ ...input.authorId ? { authorId: input.authorId } : {}
717
+ });
718
+ let staged;
719
+ try {
720
+ staged = await this.replaceDraftRevisionForUpdate(type, id, revision.id, existing, input);
721
+ } catch (error) {
722
+ await this.deleteUnstagedRevision(revisionRepo, type, id, revision.id);
723
+ throw error;
724
+ }
725
+ if (staged) {
726
+ const updated = await this.findById(type, id);
727
+ if (!updated) throw new Error("Content not found");
728
+ const draftData = {};
729
+ for (const [key, value] of Object.entries(mergedData)) if (!key.startsWith("_")) draftData[key] = value;
730
+ return {
731
+ ...updated,
732
+ data: {
733
+ ...updated.data,
734
+ ...draftData
735
+ }
736
+ };
737
+ }
738
+ await this.deleteUnstagedRevision(revisionRepo, type, id, revision.id);
739
+ existing = await this.findById(type, id);
740
+ }
741
+ if (!existing) throw new Error("Content not found");
742
+ throw new ContentMutationConflictError();
743
+ }
744
+ async deleteUnstagedRevision(revisionRepo, type, id, revisionId) {
745
+ try {
746
+ await revisionRepo.deleteIfUnreferenced(type, id, revisionId);
747
+ } catch (error) {
748
+ console.error(`[content] Failed to clean up unstaged revision ${revisionId}:`, error);
749
+ }
750
+ }
751
+ async replaceDraftRevisionForUpdate(type, id, revisionId, expected, input) {
752
+ const tableName = getTableName(type);
753
+ const assignments = [sql`draft_revision_id = ${revisionId}`];
754
+ let liveMetadataChanged = false;
755
+ if (input.status !== void 0) {
756
+ assignments.push(sql`status = ${input.status}`);
757
+ liveMetadataChanged = true;
758
+ }
759
+ if (input.slug === null) {
760
+ assignments.push(sql`slug = NULL`);
761
+ liveMetadataChanged = true;
762
+ }
763
+ if (input.publishedAt !== void 0) {
764
+ assignments.push(sql`published_at = ${input.publishedAt}`);
765
+ liveMetadataChanged = true;
766
+ }
767
+ if (input.scheduledAt !== void 0) {
768
+ assignments.push(sql`scheduled_at = ${input.scheduledAt}`);
769
+ liveMetadataChanged = true;
770
+ }
771
+ if (input.authorId !== void 0) {
772
+ assignments.push(sql`author_id = ${input.authorId}`);
773
+ liveMetadataChanged = true;
774
+ }
775
+ if (input.primaryBylineId !== void 0) {
776
+ assignments.push(sql`primary_byline_id = ${input.primaryBylineId}`);
777
+ liveMetadataChanged = true;
778
+ }
779
+ if (liveMetadataChanged) assignments.push(sql`updated_at = ${(/* @__PURE__ */ new Date()).toISOString()}`);
780
+ assignments.push(sql`version = version + 1`);
781
+ const changed = ((await sql`
782
+ UPDATE ${sql.ref(tableName)}
783
+ SET ${sql.join(assignments, sql`, `)}
784
+ WHERE id = ${id}
785
+ AND deleted_at IS NULL
786
+ AND version = ${expected.version}
787
+ AND ${nullableColumnMatch("live_revision_id", expected.liveRevisionId)}
788
+ AND ${nullableColumnMatch("draft_revision_id", expected.draftRevisionId)}
789
+ AND EXISTS (
790
+ SELECT 1 FROM revisions
791
+ WHERE revisions.id = ${revisionId}
792
+ AND revisions.collection = ${type}
793
+ AND revisions.entry_id = ${id}
794
+ )
795
+ `.execute(this.db)).numAffectedRows ?? 0n) > 0n;
796
+ if (changed && liveMetadataChanged) invalidateCollectionCache(type);
797
+ return changed;
798
+ }
799
+ /**
582
800
  * Delete content (soft delete - moves to trash)
583
801
  */
584
802
  async delete(type, id) {
@@ -590,10 +808,7 @@ var ContentRepository = class {
590
808
  WHERE id = ${id}
591
809
  AND deleted_at IS NULL
592
810
  `.execute(this.db)).numAffectedRows ?? 0n) > 0n;
593
- if (changed) {
594
- await this.restampEntryPivot(type, id);
595
- invalidateCollectionCache(type);
596
- }
811
+ if (changed) invalidateCollectionCache(type);
597
812
  return changed;
598
813
  }
599
814
  /**
@@ -609,35 +824,10 @@ var ContentRepository = class {
609
824
  RETURNING *
610
825
  `.execute(this.db)).rows[0];
611
826
  if (!restored) return null;
612
- await this.restampEntryPivot(type, id);
613
827
  invalidateCollectionCache(type);
614
828
  return this.mapRow(type, restored);
615
829
  }
616
830
  /**
617
- * Re-stamp the denormalized filter + sort columns on every
618
- * `content_taxonomies` pivot row for an entry from its authoritative `ec_*`
619
- * row (migration 051). Called after any mutation that moves one of those
620
- * columns so a taxonomy-filtered listing can seek the entry directly.
621
- *
622
- * A single correlated `UPDATE` reads the post-mutation values from `ec_*`, so
623
- * the pivot converges to the authoritative row. This is NOT atomic with the
624
- * `ec_*` mutation on D1 (no transactions), which is why the read path
625
- * re-checks the real predicates on the joined `ec_*` row. Untagged entries
626
- * have no pivot rows, so the statement is a cheap no-op for them.
627
- */
628
- async restampEntryPivot(type, id) {
629
- const tableName = getTableName(type);
630
- await sql`
631
- UPDATE content_taxonomies
632
- SET (status, scheduled_at, deleted_at, locale, published_at, created_at) = (
633
- SELECT status, scheduled_at, deleted_at, locale, published_at, created_at
634
- FROM ${sql.ref(tableName)}
635
- WHERE ${sql.ref(tableName)}.id = ${id}
636
- )
637
- WHERE collection = ${type} AND entry_id = ${id}
638
- `.execute(this.db);
639
- }
640
- /**
641
831
  * Permanently delete content (cannot be undone)
642
832
  */
643
833
  /**
@@ -734,7 +924,7 @@ var ContentRepository = class {
734
924
  const pattern = `%${term.replace(LIKE_WILDCARD_RE, (c) => `\\${c}`)}%`;
735
925
  return query.where((eb) => eb.or(columns.map((col) => {
736
926
  validateIdentifier(col, "search column");
737
- return eb(sql`lower(${sql.ref(col)})`, "like", sql`lower(${pattern}) escape '\\'`);
927
+ return sql`lower(CAST(${sql.ref(col)} AS TEXT)) LIKE lower(${pattern}) ESCAPE '\\'`;
738
928
  })));
739
929
  }
740
930
  /**
@@ -756,9 +946,57 @@ var ContentRepository = class {
756
946
  return next;
757
947
  }
758
948
  /**
949
+ * Apply the optional byline filter as a correlated (NOT) EXISTS against
950
+ * `_emdash_content_bylines`.
951
+ *
952
+ * Correlating from the content table preserves the outer sort index so
953
+ * `LIMIT` can short-circuit. `mode: "none"` tests the junction rather than
954
+ * `primary_byline_id` because the two are written in the same call but
955
+ * are not atomically consistent, so the junction is authoritative.
956
+ *
957
+ * Whether a credit *renders* is locale-scoped; whether one *exists* is
958
+ * not. Both are needed: the first decides what the filter matches, the
959
+ * second decides whether the author fallback applies at all.
960
+ */
961
+ applyBylineFilter(query, where, type) {
962
+ const filter = where?.bylineFilter;
963
+ if (!filter) return query;
964
+ const tableName = getTableName(type);
965
+ const idColumn = `${tableName}.id`;
966
+ const authorColumn = `${tableName}.author_id`;
967
+ const localeColumn = `${tableName}.locale`;
968
+ const creditRenders = (eb, bylineIds) => {
969
+ let sub = eb.selectFrom("_emdash_content_bylines as cb").innerJoin("_emdash_bylines as b", "b.translation_group", "cb.byline_id").select("cb.id").where("cb.collection_slug", "=", type).whereRef("cb.content_id", "=", idColumn);
970
+ sub = filter.locale ? sub.where("b.locale", "=", filter.locale) : sub.whereRef("b.locale", "=", localeColumn);
971
+ if (bylineIds) sub = sub.where("cb.byline_id", "in", bylineIds);
972
+ return eb.exists(sub);
973
+ };
974
+ const hasExplicitCredit = (eb) => eb.exists(eb.selectFrom("_emdash_content_bylines as cb").select("cb.id").where("cb.collection_slug", "=", type).whereRef("cb.content_id", "=", idColumn));
975
+ const authorHasByline = (eb, bylineIds) => {
976
+ let sub = eb.selectFrom("_emdash_bylines as b").select("b.id").whereRef("b.user_id", "=", authorColumn);
977
+ sub = filter.locale ? sub.where("b.locale", "=", filter.locale) : sub.whereRef("b.locale", "=", localeColumn);
978
+ if (bylineIds) sub = sub.where("b.translation_group", "in", bylineIds);
979
+ return eb.exists(sub);
980
+ };
981
+ if (filter.mode === "none") return query.where((eb) => {
982
+ const uncredited = eb.not(creditRenders(eb));
983
+ return filter.includeInferred ? eb.and([uncredited, eb.or([hasExplicitCredit(eb), eb.not(authorHasByline(eb))])]) : uncredited;
984
+ });
985
+ const bylineIds = filter.bylineIds ?? [];
986
+ if (bylineIds.length === 0) return query.where(() => sql`1 = 0`);
987
+ return query.where((eb) => {
988
+ if (!filter.includeInferred) return creditRenders(eb, bylineIds);
989
+ return eb.or([creditRenders(eb, bylineIds), eb.and([eb.not(hasExplicitCredit(eb)), authorHasByline(eb, bylineIds)])]);
990
+ });
991
+ }
992
+ /**
759
993
  * Count content items
760
994
  */
761
995
  async count(type, where) {
996
+ const resolvedFieldFilters = await this.resolveFieldFilters(type, where?.fieldFilters);
997
+ return this.countWithResolvedFilters(type, where, resolvedFieldFilters);
998
+ }
999
+ async countWithResolvedFilters(type, where, resolvedFieldFilters) {
762
1000
  const tableName = getTableName(type);
763
1001
  let query = this.db.selectFrom(tableName).select((eb) => eb.fn.count("id").as("count")).where("deleted_at", "is", null);
764
1002
  if (where?.status) query = query.where("status", "=", where.status);
@@ -766,6 +1004,8 @@ var ContentRepository = class {
766
1004
  if (where?.locale) query = query.where("locale", "=", where.locale);
767
1005
  query = this.applySearchFilter(query, where, type);
768
1006
  query = this.applyDateFilter(query, where);
1007
+ query = this.applyBylineFilter(query, where, type);
1008
+ query = this.applyFieldFilters(query, resolvedFieldFilters);
769
1009
  const result = await query.executeTakeFirst();
770
1010
  return Number(result?.count || 0);
771
1011
  }
@@ -779,19 +1019,22 @@ var ContentRepository = class {
779
1019
  const tableName = getTableName(type);
780
1020
  return (await this.db.selectFrom(tableName).select("author_id").distinct().where("deleted_at", "is", null).where("author_id", "is not", null).execute()).map((row) => row.author_id).filter((id) => id !== null);
781
1021
  }
782
- async getStats(type) {
1022
+ async getStats(type, now = /* @__PURE__ */ new Date()) {
783
1023
  const tableName = getTableName(type);
1024
+ const nowIso = now.toISOString();
784
1025
  const result = await this.db.selectFrom(tableName).select((eb) => [
785
1026
  eb.fn.count("id").as("total"),
786
1027
  eb.fn.sum(eb.case().when("status", "=", "published").then(1).else(0).end()).as("published"),
787
1028
  eb.fn.sum(eb.case().when("status", "=", "draft").then(1).else(0).end()).as("draft"),
788
- sql`SUM(CASE WHEN scheduled_at IS NOT NULL THEN 1 ELSE 0 END)`.as("scheduled")
1029
+ sql`SUM(CASE WHEN scheduled_at IS NOT NULL THEN 1 ELSE 0 END)`.as("scheduled"),
1030
+ sql`SUM(CASE WHEN scheduled_at IS NOT NULL AND scheduled_at <= ${nowIso} THEN 1 ELSE 0 END)`.as("overdue_scheduled")
789
1031
  ]).where("deleted_at", "is", null).executeTakeFirst();
790
1032
  return {
791
1033
  total: Number(result?.total || 0),
792
1034
  published: Number(result?.published || 0),
793
1035
  draft: Number(result?.draft || 0),
794
- scheduled: Number(result?.scheduled || 0)
1036
+ scheduled: Number(result?.scheduled || 0),
1037
+ overdueScheduled: Number(result?.overdue_scheduled || 0)
795
1038
  };
796
1039
  }
797
1040
  /**
@@ -817,7 +1060,6 @@ var ContentRepository = class {
817
1060
  WHERE id = ${id}
818
1061
  AND deleted_at IS NULL
819
1062
  `.execute(this.db);
820
- await this.restampEntryPivot(type, id);
821
1063
  invalidateCollectionCache(type);
822
1064
  const updated = await this.findById(type, id);
823
1065
  if (!updated) throw new Error("Content not found");
@@ -844,7 +1086,6 @@ var ContentRepository = class {
844
1086
  AND scheduled_at IS NOT NULL
845
1087
  AND deleted_at IS NULL
846
1088
  `.execute(this.db);
847
- await this.restampEntryPivot(type, id);
848
1089
  invalidateCollectionCache(type);
849
1090
  const updated = await this.findById(type, id);
850
1091
  if (!updated) throw new Error("Content not found");
@@ -988,6 +1229,8 @@ var ContentRepository = class {
988
1229
  * Syncs the draft revision's data into the content table columns so the
989
1230
  * content table always reflects the published version.
990
1231
  * If no draft revision exists, creates one from current data and publishes it.
1232
+ * When `promoteRevision` is false, publishes the current content-table data
1233
+ * by changing lifecycle metadata only.
991
1234
  *
992
1235
  * `publishedAt` (optional) overrides the publication timestamp. If omitted,
993
1236
  * the existing `published_at` is preserved (idempotent re-publish keeps the
@@ -999,12 +1242,76 @@ var ContentRepository = class {
999
1242
  * `expectedScheduledAt` additionally fences changes made after a sweep
1000
1243
  * selected the row but before publication preparation began.
1001
1244
  */
1002
- async publish(type, id, publishedAt, requireDue = false, expectedScheduledAt) {
1245
+ async publish(type, id, publishedAt, requireDue = false, expectedScheduledAt, promoteRevision = true, requireSlug = true) {
1003
1246
  const tableName = getTableName(type);
1004
1247
  const now = (/* @__PURE__ */ new Date()).toISOString();
1005
1248
  const existing = await this.findById(type, id);
1006
1249
  if (!existing) throw new EmDashValidationError("Content item not found");
1007
1250
  if (requireDue && expectedScheduledAt !== void 0 && existing.scheduledAt !== expectedScheduledAt) throw new ScheduledNotDueError();
1251
+ if (!promoteRevision && requireSlug && !existing.slug?.trim()) throw new EmDashValidationError("Cannot publish routable content without a slug");
1252
+ if (!promoteRevision) {
1253
+ const revisionRepo = new RevisionRepository(this.db);
1254
+ let provisionalRevisionId = null;
1255
+ try {
1256
+ let liveRevisionId = existing.liveRevisionId;
1257
+ if (!liveRevisionId) {
1258
+ const revision = await revisionRepo.create({
1259
+ collection: type,
1260
+ entryId: id,
1261
+ data: existing.data
1262
+ });
1263
+ liveRevisionId = revision.id;
1264
+ provisionalRevisionId = revision.id;
1265
+ }
1266
+ const intendedPublishedAt = publishedAt ?? existing.publishedAt ?? now;
1267
+ const duePredicate = requireDue ? sql`AND scheduled_at IS NOT NULL AND scheduled_at <= ${now}` : sql``;
1268
+ let published = false;
1269
+ try {
1270
+ published = ((await sql`
1271
+ UPDATE ${sql.ref(tableName)}
1272
+ SET live_revision_id = ${liveRevisionId},
1273
+ draft_revision_id = NULL,
1274
+ status = 'published',
1275
+ scheduled_at = NULL,
1276
+ published_at = ${intendedPublishedAt},
1277
+ updated_at = ${now},
1278
+ version = version + 1
1279
+ WHERE id = ${id}
1280
+ AND deleted_at IS NULL
1281
+ AND version = ${existing.version}
1282
+ AND status = ${existing.status}
1283
+ AND ${nullableColumnMatch("live_revision_id", existing.liveRevisionId)}
1284
+ AND ${nullableColumnMatch("draft_revision_id", existing.draftRevisionId)}
1285
+ AND ${nullableColumnMatch("scheduled_at", existing.scheduledAt)}
1286
+ ${duePredicate}
1287
+ `.execute(this.db)).numAffectedRows ?? 0n) > 0n;
1288
+ } catch (error) {
1289
+ if (isConfirmedStatementFailure(error)) throw error;
1290
+ let observed;
1291
+ try {
1292
+ observed = await this.findById(type, id);
1293
+ } catch (reconciliationError) {
1294
+ throw new Error("Unable to confirm whether content publication completed", { cause: reconciliationError });
1295
+ }
1296
+ if (!observed) throw new Error("Unable to confirm whether content publication completed", { cause: error });
1297
+ published = matchesLifecyclePublication(observed, existing, liveRevisionId, intendedPublishedAt, now);
1298
+ if (!published && matchesPublicationFence(observed, existing)) throw error;
1299
+ if (!published) throw new Error("Unable to confirm whether content publication completed", { cause: error });
1300
+ }
1301
+ if (!published) throw requireDue ? new ScheduledNotDueError() : new ContentMutationConflictError();
1302
+ invalidateCollectionCache(type);
1303
+ const updated = await this.findById(type, id);
1304
+ if (!updated) throw new Error("Content not found");
1305
+ return updated;
1306
+ } catch (error) {
1307
+ if (provisionalRevisionId) try {
1308
+ await revisionRepo.deleteIfUnreferenced(type, id, provisionalRevisionId);
1309
+ } catch (cleanupError) {
1310
+ console.error(`[content] Failed to clean up provisional revision ${provisionalRevisionId}:`, cleanupError);
1311
+ }
1312
+ throw error;
1313
+ }
1314
+ }
1008
1315
  const revisionRepo = new RevisionRepository(this.db);
1009
1316
  let provisionalRevisionId = null;
1010
1317
  try {
@@ -1022,6 +1329,7 @@ var ContentRepository = class {
1022
1329
  if (!revision || revision.collection !== type || revision.entryId !== id) throw new EmDashValidationError("Revision does not belong to the specified content item");
1023
1330
  const stagedSlug = typeof revision.data._slug === "string" ? revision.data._slug : null;
1024
1331
  const intendedSlug = stagedSlug ?? existing.slug;
1332
+ if (requireSlug && !intendedSlug?.trim()) throw new EmDashValidationError("Cannot publish routable content without a slug");
1025
1333
  const intendedPublishedAt = publishedAt ?? existing.publishedAt ?? now;
1026
1334
  if (stagedSlug !== null && stagedSlug !== existing.slug && existing.locale !== null) {
1027
1335
  const conflict = await this.findBySlugIncludingTrashed(type, stagedSlug, existing.locale);
@@ -1071,7 +1379,6 @@ var ContentRepository = class {
1071
1379
  }
1072
1380
  if (!promoted) throw requireDue ? new ScheduledNotDueError() : new ContentMutationConflictError();
1073
1381
  invalidateCollectionCache(type);
1074
- await this.restampEntryPivot(type, id);
1075
1382
  const updated = await this.findById(type, id);
1076
1383
  if (!updated) throw new Error("Content not found");
1077
1384
  return updated;
@@ -1120,7 +1427,6 @@ var ContentRepository = class {
1120
1427
  WHERE id = ${id}
1121
1428
  AND deleted_at IS NULL
1122
1429
  `.execute(this.db);
1123
- await this.restampEntryPivot(type, id);
1124
1430
  invalidateCollectionCache(type);
1125
1431
  const updated = await this.findById(type, id);
1126
1432
  if (!updated) throw new Error("Content not found");
@@ -1226,28 +1532,153 @@ var ContentRepository = class {
1226
1532
  translationGroup: row.translation_group ?? null
1227
1533
  };
1228
1534
  }
1535
+ normalizeFilterScalar(field, type, value) {
1536
+ if (type === "number" || type === "integer") {
1537
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new EmDashValidationError(`Filter for field "${field}" must use a finite number`);
1538
+ if (type === "integer" && !Number.isInteger(value)) throw new EmDashValidationError(`Filter for field "${field}" must use an integer`);
1539
+ return value;
1540
+ }
1541
+ if (type === "boolean") {
1542
+ if (typeof value !== "boolean") throw new EmDashValidationError(`Filter for field "${field}" must use a boolean`);
1543
+ return value ? 1 : 0;
1544
+ }
1545
+ if (typeof value !== "string") throw new EmDashValidationError(`Filter for field "${field}" must use a string`);
1546
+ if (value.length > MAX_FILTER_STRING_LENGTH) throw new EmDashValidationError(`Filter value for field "${field}" exceeds ${MAX_FILTER_STRING_LENGTH} characters`);
1547
+ return value;
1548
+ }
1549
+ normalizeFieldFilter(field, type, value) {
1550
+ if (value === null) return {
1551
+ column: field,
1552
+ kind: "null"
1553
+ };
1554
+ if (typeof value !== "object") return {
1555
+ column: field,
1556
+ kind: "exact",
1557
+ value: this.normalizeFilterScalar(field, type, value)
1558
+ };
1559
+ if (Array.isArray(value)) throw new EmDashValidationError(`Invalid filter for field "${field}"`);
1560
+ const record = value;
1561
+ const keys = Object.keys(record);
1562
+ if (keys.length === 1 && keys[0] === "in") {
1563
+ if (!Array.isArray(record.in) || record.in.length === 0) throw new EmDashValidationError(`IN filter for field "${field}" must not be empty`);
1564
+ if (record.in.length > MAX_IN_FILTER_VALUES) throw new EmDashValidationError(`IN filter for field "${field}" exceeds ${MAX_IN_FILTER_VALUES} values`);
1565
+ return {
1566
+ column: field,
1567
+ kind: "in",
1568
+ values: record.in.map((entry) => this.normalizeFilterScalar(field, type, entry))
1569
+ };
1570
+ }
1571
+ const rangeKeys = new Set([
1572
+ "gt",
1573
+ "gte",
1574
+ "lt",
1575
+ "lte"
1576
+ ]);
1577
+ if (keys.length === 0 || keys.some((key) => !rangeKeys.has(key))) throw new EmDashValidationError(`Invalid filter operator for field "${field}"`);
1578
+ if (type === "boolean") throw new EmDashValidationError(`Boolean field "${field}" does not support range filters`);
1579
+ const bounds = {};
1580
+ for (const key of keys) {
1581
+ if (record[key] === void 0) continue;
1582
+ bounds[key] = this.normalizeFilterScalar(field, type, record[key]);
1583
+ }
1584
+ if (Object.keys(bounds).length === 0) throw new EmDashValidationError(`Range filter for field "${field}" has no bounds`);
1585
+ return {
1586
+ column: field,
1587
+ kind: "range",
1588
+ bounds
1589
+ };
1590
+ }
1591
+ async collectionExists(type) {
1592
+ return await this.db.selectFrom("_emdash_collections").where("slug", "=", type).select("id").executeTakeFirst() !== void 0;
1593
+ }
1594
+ async resolveFieldFilters(type, filters) {
1595
+ const resolvedFilters = filters ?? {};
1596
+ const fields = Object.keys(resolvedFilters);
1597
+ if (fields.length === 0) return [];
1598
+ if (fields.length > MAX_INDEXED_FIELD_FILTERS) {
1599
+ if (!await this.collectionExists(type)) return [];
1600
+ throw new EmDashValidationError(`Content list queries support at most ${MAX_INDEXED_FIELD_FILTERS} indexed field filters`);
1601
+ }
1602
+ const rows = await this.db.selectFrom("_emdash_fields as field").innerJoin("_emdash_collections as collection", "collection.id", "field.collection_id").where("collection.slug", "=", type).where("field.slug", "in", fields).where("field.indexed", "=", 1).select(["field.slug", "field.type"]).execute();
1603
+ const metadata = new Map(rows.map((row) => [row.slug, row.type]));
1604
+ if (metadata.size === 0 && !await this.collectionExists(type)) return [];
1605
+ for (const field of fields) try {
1606
+ validateIdentifier(field, "content filter field");
1607
+ } catch {
1608
+ throw new EmDashValidationError(`Invalid content filter field: ${field}`);
1609
+ }
1610
+ const normalized = fields.map((field) => {
1611
+ const fieldType = metadata.get(field);
1612
+ if (!fieldType || !isIndexableFieldType(fieldType)) throw new EmDashValidationError(`Cannot filter by field "${field}". Custom fields must be indexed before filtering.`);
1613
+ return this.normalizeFieldFilter(field, fieldType, resolvedFilters[field]);
1614
+ });
1615
+ if (normalized.reduce((total, filter) => {
1616
+ if (filter.kind === "null") return total;
1617
+ if (filter.kind === "exact") return total + 1;
1618
+ if (filter.kind === "in") return total + filter.values.length;
1619
+ return total + Object.keys(filter.bounds).length;
1620
+ }, 0) > SQL_BATCH_SIZE) throw new EmDashValidationError(`Indexed field filters have a total operand budget of ${SQL_BATCH_SIZE}`);
1621
+ return normalized;
1622
+ }
1623
+ applyFieldFilters(query, filters) {
1624
+ let next = query;
1625
+ for (const filter of filters) {
1626
+ const column = sql.ref(filter.column);
1627
+ const isPresent = sql`${column} IS NOT NULL`;
1628
+ if (filter.kind === "null") {
1629
+ next = next.where(() => sql`(${isPresent}) = FALSE AND ${column} IS NULL`);
1630
+ continue;
1631
+ }
1632
+ if (filter.kind === "exact") {
1633
+ next = next.where(() => sql`(${isPresent}) = TRUE AND ${column} = ${filter.value}`);
1634
+ continue;
1635
+ }
1636
+ if (filter.kind === "in") {
1637
+ const values = sql.join(filter.values.map((value) => sql`${value}`), sql`, `);
1638
+ next = next.where(() => sql`(${isPresent}) = TRUE AND ${column} IN (${values})`);
1639
+ continue;
1640
+ }
1641
+ next = next.where(() => sql`(${isPresent}) = TRUE`);
1642
+ if (filter.bounds.gt !== void 0) next = next.where(() => sql`${column} > ${filter.bounds.gt}`);
1643
+ if (filter.bounds.gte !== void 0) next = next.where(() => sql`${column} >= ${filter.bounds.gte}`);
1644
+ if (filter.bounds.lt !== void 0) next = next.where(() => sql`${column} < ${filter.bounds.lt}`);
1645
+ if (filter.bounds.lte !== void 0) next = next.where(() => sql`${column} <= ${filter.bounds.lte}`);
1646
+ }
1647
+ return next;
1648
+ }
1229
1649
  /**
1230
1650
  * Map order field names to database columns.
1231
1651
  * Only allows known fields to prevent column enumeration via crafted orderBy values.
1232
1652
  */
1233
- mapOrderField(field) {
1234
- const mapped = {
1235
- createdAt: "created_at",
1236
- updatedAt: "updated_at",
1237
- publishedAt: "published_at",
1238
- scheduledAt: "scheduled_at",
1239
- deletedAt: "deleted_at",
1240
- title: "title",
1241
- name: "name",
1242
- slug: "slug",
1243
- status: "status",
1244
- locale: "locale"
1245
- }[field];
1246
- if (!mapped) throw new EmDashValidationError(`Invalid order field: ${field}`);
1247
- return mapped;
1653
+ mapOrderField(field, sortableExtras = []) {
1654
+ const mapped = ORDER_FIELD_COLUMNS[field];
1655
+ if (mapped) return mapped;
1656
+ if (sortableExtras.includes(field)) {
1657
+ validateIdentifier(field, "order field");
1658
+ return field;
1659
+ }
1660
+ throw new EmDashValidationError(`Invalid order field: ${field}`);
1661
+ }
1662
+ async resolveOrderField(type, field, sortableExtras = []) {
1663
+ try {
1664
+ return {
1665
+ column: this.mapOrderField(field, sortableExtras),
1666
+ indexedCustomField: false
1667
+ };
1668
+ } catch (error) {
1669
+ if (!(error instanceof EmDashValidationError)) throw error;
1670
+ }
1671
+ const customField = await this.db.selectFrom("_emdash_collections as collection").leftJoin("_emdash_fields as field", (join) => join.onRef("field.collection_id", "=", "collection.id").on("field.slug", "=", field).on("field.indexed", "=", 1)).where("collection.slug", "=", type).select(["collection.id as collectionId", "field.slug as fieldSlug"]).executeTakeFirst();
1672
+ if (!customField) throw new ContentCollectionNotFoundError(type);
1673
+ if (!customField.fieldSlug) throw new EmDashValidationError(`Invalid order field: ${field}. Custom fields must be indexed before sorting.`);
1674
+ validateIdentifier(customField.fieldSlug, "content order field");
1675
+ return {
1676
+ column: customField.fieldSlug,
1677
+ indexedCustomField: true
1678
+ };
1248
1679
  }
1249
1680
  };
1250
1681
 
1251
1682
  //#endregion
1252
- export { content_exports as n, RevisionRepository as r, ContentRepository as t };
1253
- //# sourceMappingURL=content-CJ94NEx5.mjs.map
1683
+ export { RevisionRepository as i, content_exports as n, isSystemOrderField as r, ContentRepository as t };
1684
+ //# sourceMappingURL=content-ZHCc1ngN.mjs.map