emdash 0.31.1 → 0.33.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 (746) hide show
  1. package/dist/{adapters-C0ONzkUP.d.mts → adapters-BMyNSSZi.d.mts} +9 -1
  2. package/dist/adapters-BMyNSSZi.d.mts.map +1 -0
  3. package/dist/after-CBU2vkoO.mjs +96 -0
  4. package/dist/after-CBU2vkoO.mjs.map +1 -0
  5. package/dist/{allowed-origins-CCEi9bPI.mjs → allowed-origins-CG1pACtS.mjs} +2 -2
  6. package/dist/{allowed-origins-CCEi9bPI.mjs.map → allowed-origins-CG1pACtS.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -4
  8. package/dist/api/route-utils.d.mts.map +1 -1
  9. package/dist/api/route-utils.mjs +23 -21
  10. package/dist/api/route-utils.mjs.map +1 -1
  11. package/dist/api/schemas/index.d.mts +2 -2
  12. package/dist/api/schemas/index.mjs +5 -5
  13. package/dist/{api-BkqFzIu4.mjs → api-D2hunekQ.mjs} +254 -48
  14. package/dist/api-D2hunekQ.mjs.map +1 -0
  15. package/dist/{api-tokens-uPt8UDpx.mjs → api-tokens-CSND0i1z.mjs} +2 -2
  16. package/dist/{api-tokens-uPt8UDpx.mjs.map → api-tokens-CSND0i1z.mjs.map} +1 -1
  17. package/dist/{apply-DuXsqll7.mjs → apply-kwNEJW2l.mjs} +36 -23
  18. package/dist/apply-kwNEJW2l.mjs.map +1 -0
  19. package/dist/astro/index.d.mts +12 -12
  20. package/dist/astro/index.mjs +17 -3
  21. package/dist/astro/index.mjs.map +1 -1
  22. package/dist/astro/middleware/auth.d.mts +10 -10
  23. package/dist/astro/middleware/auth.mjs +8 -8
  24. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  25. package/dist/astro/middleware/redirect.mjs +8 -8
  26. package/dist/astro/middleware/redirect.mjs.map +1 -1
  27. package/dist/astro/middleware/request-context.mjs +4 -4
  28. package/dist/astro/middleware/setup.mjs +1 -1
  29. package/dist/astro/middleware.d.mts +10 -10
  30. package/dist/astro/middleware.d.mts.map +1 -1
  31. package/dist/astro/middleware.mjs +370 -171
  32. package/dist/astro/middleware.mjs.map +1 -1
  33. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  34. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  35. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  36. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  37. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +5 -5
  38. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
  39. package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
  40. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
  41. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +19 -18
  42. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  43. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +19 -18
  44. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/bylines/index.mjs +19 -19
  46. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +16 -16
  47. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  48. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
  49. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -12
  50. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
  51. package/dist/astro/routes/api/admin/comments/index.mjs +12 -12
  52. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
  53. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
  54. package/dist/astro/routes/api/admin/media-usage/repair.mjs +13 -11
  55. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  57. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  58. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +47 -44
  59. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  60. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +47 -44
  61. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  62. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +46 -43
  63. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +5 -5
  65. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +46 -43
  66. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +46 -43
  68. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +46 -43
  70. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/index.mjs +46 -43
  72. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  74. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +46 -43
  75. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +46 -43
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +46 -43
  79. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +46 -43
  81. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +47 -44
  83. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +46 -43
  85. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +47 -44
  87. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/updates.mjs +46 -43
  89. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +46 -43
  91. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  93. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +46 -43
  94. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
  96. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  97. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
  98. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  99. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  101. package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -6
  102. package/dist/astro/routes/api/auth/dev-bypass.mjs.map +1 -1
  103. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  104. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  105. package/dist/astro/routes/api/auth/invite/index.mjs +10 -10
  106. package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
  107. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  108. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  109. package/dist/astro/routes/api/auth/magic-link/send.mjs +12 -12
  110. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  111. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  112. package/dist/astro/routes/api/auth/me.mjs +8 -8
  113. package/dist/astro/routes/api/auth/mode.mjs +3 -3
  114. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  115. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  116. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  117. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  118. package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
  119. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  120. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  121. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  122. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  123. package/dist/astro/routes/api/auth/signup/request.mjs +12 -12
  124. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  125. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  126. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +18 -18
  127. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  128. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +15 -15
  129. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  130. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
  131. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  132. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  133. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +14 -14
  134. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +9 -9
  135. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +19 -17
  136. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  137. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +19 -17
  138. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  139. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  140. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  141. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +9 -9
  142. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -16
  143. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  144. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  145. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
  146. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  147. package/dist/astro/routes/api/content/_collection_/_id_.mjs +10 -10
  148. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  149. package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
  150. package/dist/astro/routes/api/content/_collection_/index.mjs +9 -9
  151. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  152. package/dist/astro/routes/api/dashboard.mjs +9 -9
  153. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  154. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  155. package/dist/astro/routes/api/import/probe.mjs +19 -19
  156. package/dist/astro/routes/api/import/wordpress/analyze.mjs +4 -4
  157. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  158. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -15
  159. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  160. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  161. package/dist/astro/routes/api/import/wordpress/media.mjs +10 -10
  162. package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
  163. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  164. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +13 -11
  165. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  166. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  167. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +19 -19
  168. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  169. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +28 -27
  170. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  171. package/dist/astro/routes/api/manifest.mjs +5 -5
  172. package/dist/astro/routes/api/mcp.mjs +42 -42
  173. package/dist/astro/routes/api/media/_id_/confirm.d.mts.map +1 -1
  174. package/dist/astro/routes/api/media/_id_/confirm.mjs +106 -37
  175. package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
  176. package/dist/astro/routes/api/media/_id_/upload.d.mts +8 -0
  177. package/dist/astro/routes/api/media/_id_/upload.d.mts.map +1 -0
  178. package/dist/astro/routes/api/media/_id_/upload.mjs +168 -0
  179. package/dist/astro/routes/api/media/_id_/upload.mjs.map +1 -0
  180. package/dist/astro/routes/api/media/_id_/usage.mjs +15 -13
  181. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  182. package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
  183. package/dist/astro/routes/api/media/_id_.mjs +22 -15
  184. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  185. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  186. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  187. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  188. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  189. package/dist/astro/routes/api/media/upload-url.d.mts.map +1 -1
  190. package/dist/astro/routes/api/media/upload-url.mjs +35 -24
  191. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  192. package/dist/astro/routes/api/media.mjs +14 -13
  193. package/dist/astro/routes/api/media.mjs.map +1 -1
  194. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +12 -11
  195. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  196. package/dist/astro/routes/api/menus/_name_/items.mjs +12 -11
  197. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  198. package/dist/astro/routes/api/menus/_name_/reorder.mjs +12 -11
  199. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  200. package/dist/astro/routes/api/menus/_name_/translations.mjs +12 -11
  201. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  202. package/dist/astro/routes/api/menus/_name_.mjs +12 -11
  203. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  204. package/dist/astro/routes/api/menus/index.mjs +12 -11
  205. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  206. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  207. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  208. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  209. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  210. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  211. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  212. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  213. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  214. package/dist/astro/routes/api/openapi.json.mjs +62 -9
  215. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  216. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
  217. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -12
  218. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -12
  219. package/dist/astro/routes/api/redirects/_id_.mjs +14 -13
  220. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  221. package/dist/astro/routes/api/redirects/index.mjs +14 -13
  222. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  223. package/dist/astro/routes/api/relations/_id_/index.mjs +19 -17
  224. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  225. package/dist/astro/routes/api/relations/_id_/translations.mjs +14 -12
  226. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  227. package/dist/astro/routes/api/relations/index.mjs +19 -17
  228. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  229. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  230. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
  231. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +46 -43
  232. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  233. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +46 -43
  234. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  235. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +46 -43
  236. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  237. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +46 -43
  238. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  239. package/dist/astro/routes/api/schema/collections/index.mjs +46 -43
  240. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  241. package/dist/astro/routes/api/schema/collections/reorder.d.mts +8 -0
  242. package/dist/astro/routes/api/schema/collections/reorder.d.mts.map +1 -0
  243. package/dist/astro/routes/api/schema/collections/reorder.mjs +66 -0
  244. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -0
  245. package/dist/astro/routes/api/schema/index.mjs +12 -8
  246. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  247. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +46 -43
  248. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  249. package/dist/astro/routes/api/schema/orphans/index.mjs +46 -43
  250. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  251. package/dist/astro/routes/api/search/enable.d.mts +1 -0
  252. package/dist/astro/routes/api/search/enable.d.mts.map +1 -1
  253. package/dist/astro/routes/api/search/enable.mjs +18 -13
  254. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  255. package/dist/astro/routes/api/search/index.mjs +12 -11
  256. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  257. package/dist/astro/routes/api/search/rebuild.mjs +14 -13
  258. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  259. package/dist/astro/routes/api/search/stats.mjs +8 -7
  260. package/dist/astro/routes/api/search/stats.mjs.map +1 -1
  261. package/dist/astro/routes/api/search/suggest.mjs +12 -11
  262. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  263. package/dist/astro/routes/api/sections/_slug_.mjs +11 -11
  264. package/dist/astro/routes/api/sections/index.mjs +11 -11
  265. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  266. package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -6
  267. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  268. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  269. package/dist/astro/routes/api/settings/email.mjs +5 -5
  270. package/dist/astro/routes/api/settings.mjs +16 -16
  271. package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
  272. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  273. package/dist/astro/routes/api/setup/dev-bypass.mjs +31 -29
  274. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  275. package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
  276. package/dist/astro/routes/api/setup/index.mjs +33 -31
  277. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  278. package/dist/astro/routes/api/setup/status.mjs +4 -4
  279. package/dist/astro/routes/api/snapshot.mjs +9 -9
  280. package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts +8 -0
  281. package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -0
  282. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +43 -0
  283. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -0
  284. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +17 -16
  285. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  286. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +17 -16
  287. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  288. package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
  289. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +22 -18
  290. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  291. package/dist/astro/routes/api/taxonomies/index.mjs +17 -16
  292. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  293. package/dist/astro/routes/api/themes/preview.mjs +7 -7
  294. package/dist/astro/routes/api/typegen.mjs +5 -5
  295. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  296. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  297. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  298. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  299. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -11
  300. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -11
  301. package/dist/astro/routes/api/widget-areas/_name_.mjs +6 -6
  302. package/dist/astro/routes/api/widget-areas/index.mjs +11 -11
  303. package/dist/astro/routes/api/widget-components.mjs +3 -3
  304. package/dist/astro/routes/robots.txt.mjs +9 -9
  305. package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -13
  306. package/dist/astro/routes/sitemap.xml.mjs +10 -10
  307. package/dist/astro/types.d.mts +20 -13
  308. package/dist/astro/types.d.mts.map +1 -1
  309. package/dist/auth/providers/github.d.mts +1 -1
  310. package/dist/auth/providers/google.d.mts +1 -1
  311. package/dist/{authorize-6WPZa1xZ.mjs → authorize-qRhWQnel.mjs} +2 -2
  312. package/dist/{authorize-6WPZa1xZ.mjs.map → authorize-qRhWQnel.mjs.map} +1 -1
  313. package/dist/{backup-DoW-H0r4.mjs → backup-CtA6LDNw.mjs} +5 -5
  314. package/dist/{backup-DoW-H0r4.mjs.map → backup-CtA6LDNw.mjs.map} +1 -1
  315. package/dist/{byline-BTOxUlFF.mjs → byline-Cp6csL84.mjs} +9 -9
  316. package/dist/{byline-BTOxUlFF.mjs.map → byline-Cp6csL84.mjs.map} +1 -1
  317. package/dist/{byline-fields-CdU_LTF1.mjs → byline-fields-CNc0Yq5i.mjs} +2 -2
  318. package/dist/{byline-fields-CdU_LTF1.mjs.map → byline-fields-CNc0Yq5i.mjs.map} +1 -1
  319. package/dist/{byline-registry-BCuOp4UF.mjs → byline-registry-ZkPKqEwC.mjs} +4 -4
  320. package/dist/{byline-registry-BCuOp4UF.mjs.map → byline-registry-ZkPKqEwC.mjs.map} +1 -1
  321. package/dist/{bylines-Bc-3xtpz.mjs → bylines-CEj5CdT4.mjs} +7 -7
  322. package/dist/{bylines-Bc-3xtpz.mjs.map → bylines-CEj5CdT4.mjs.map} +1 -1
  323. package/dist/{bylines-oVN0iPwX.mjs → bylines-cf-C9lmF.mjs} +5 -5
  324. package/dist/{bylines-oVN0iPwX.mjs.map → bylines-cf-C9lmF.mjs.map} +1 -1
  325. package/dist/cache-C9FptTFR.mjs +108 -0
  326. package/dist/cache-C9FptTFR.mjs.map +1 -0
  327. package/dist/{challenge-store-BFzgFRog.mjs → challenge-store-D9VNKELo.mjs} +1 -1
  328. package/dist/{challenge-store-BFzgFRog.mjs.map → challenge-store-D9VNKELo.mjs.map} +1 -1
  329. package/dist/{chunks-Bq-5DPrD.mjs → chunks-DbYzib_k.mjs} +2 -2
  330. package/dist/{chunks-Bq-5DPrD.mjs.map → chunks-DbYzib_k.mjs.map} +1 -1
  331. package/dist/cli/index.mjs +41 -32
  332. package/dist/cli/index.mjs.map +1 -1
  333. package/dist/client/cf-access.d.mts +1 -1
  334. package/dist/client/index.d.mts +1 -1
  335. package/dist/client/index.mjs +2 -2
  336. package/dist/{comment-B9cUud8H.mjs → comment-BIkJ6Fil.mjs} +3 -3
  337. package/dist/{comment-B9cUud8H.mjs.map → comment-BIkJ6Fil.mjs.map} +1 -1
  338. package/dist/{comment-reaction-VUXO981F.mjs → comment-reaction-D-laEceb.mjs} +2 -2
  339. package/dist/{comment-reaction-VUXO981F.mjs.map → comment-reaction-D-laEceb.mjs.map} +1 -1
  340. package/dist/{comments-PXj1E9Si.mjs → comments-0_w6KChA.mjs} +3 -3
  341. package/dist/{comments-PXj1E9Si.mjs.map → comments-0_w6KChA.mjs.map} +1 -1
  342. package/dist/{components-DZkL4Fx0.mjs → components-BPxrRjpE.mjs} +1 -1
  343. package/dist/{components-DZkL4Fx0.mjs.map → components-BPxrRjpE.mjs.map} +1 -1
  344. package/dist/{config-B6b_BobR.mjs → config-DyF3OKg_.mjs} +15 -10
  345. package/dist/config-DyF3OKg_.mjs.map +1 -0
  346. package/dist/{content-BC43pICM.mjs → content-CJ94NEx5.mjs} +170 -117
  347. package/dist/content-CJ94NEx5.mjs.map +1 -0
  348. package/dist/{content-refresh-CPMSauD3.mjs → content-refresh-Xw7aKmou.mjs} +7 -7
  349. package/dist/{content-refresh-CPMSauD3.mjs.map → content-refresh-Xw7aKmou.mjs.map} +1 -1
  350. package/dist/{context-DOurRIrb.mjs → context-C_1nrqnW.mjs} +14 -14
  351. package/dist/{context-DOurRIrb.mjs.map → context-C_1nrqnW.mjs.map} +1 -1
  352. package/dist/{cron-BlKIMD_e.mjs → cron-DRV-UC4K.mjs} +1 -1
  353. package/dist/{cron-BlKIMD_e.mjs.map → cron-DRV-UC4K.mjs.map} +1 -1
  354. package/dist/{dashboard-CBm4zhc3.mjs → dashboard-DINnNVVU.mjs} +5 -5
  355. package/dist/{dashboard-CBm4zhc3.mjs.map → dashboard-DINnNVVU.mjs.map} +1 -1
  356. package/dist/db/index.d.mts +3 -3
  357. package/dist/db/index.mjs +3 -2
  358. package/dist/db/index.mjs.map +1 -1
  359. package/dist/db/libsql.d.mts +1 -1
  360. package/dist/db/postgres.d.mts +1 -1
  361. package/dist/db/sqlite.d.mts +1 -1
  362. package/dist/{default-C4v9KP56.mjs → default-BD2FG0xV.mjs} +1 -1
  363. package/dist/{default-C4v9KP56.mjs.map → default-BD2FG0xV.mjs.map} +1 -1
  364. package/dist/deferred-tasks-C-WRCcKo.d.mts +9 -0
  365. package/dist/deferred-tasks-C-WRCcKo.d.mts.map +1 -0
  366. package/dist/{device-flow-BeA6lUS1.mjs → device-flow-CTqd8mud.mjs} +5 -5
  367. package/dist/{device-flow-BeA6lUS1.mjs.map → device-flow-CTqd8mud.mjs.map} +1 -1
  368. package/dist/{dialect-helpers-BtOwo2us.mjs → dialect-helpers-BSbfaO3F.mjs} +43 -16
  369. package/dist/dialect-helpers-BSbfaO3F.mjs.map +1 -0
  370. package/dist/{email-console-C-9Ng8DM.mjs → email-console-C6WdcWbL.mjs} +1 -1
  371. package/dist/{email-console-C-9Ng8DM.mjs.map → email-console-C6WdcWbL.mjs.map} +1 -1
  372. package/dist/{error-DJ98TRbQ.mjs → error-oh_9i6bR.mjs} +3 -3
  373. package/dist/{error-DJ98TRbQ.mjs.map → error-oh_9i6bR.mjs.map} +1 -1
  374. package/dist/{errors-DtEXIQQV.mjs → errors-BucQ8VYz.mjs} +2 -1
  375. package/dist/errors-BucQ8VYz.mjs.map +1 -0
  376. package/dist/{escape-CFedIB1C.mjs → escape-CXps5F_v.mjs} +1 -1
  377. package/dist/{escape-CFedIB1C.mjs.map → escape-CXps5F_v.mjs.map} +1 -1
  378. package/dist/{field-defs-cache-KfNJ_qLQ.mjs → field-defs-cache-WD82dMQq.mjs} +4 -4
  379. package/dist/{field-defs-cache-KfNJ_qLQ.mjs.map → field-defs-cache-WD82dMQq.mjs.map} +1 -1
  380. package/dist/{fts-manager-hyCU9OOp.mjs → fts-manager-BITakW_R.mjs} +37 -13
  381. package/dist/fts-manager-BITakW_R.mjs.map +1 -0
  382. package/dist/{hash-DFFrkivP.mjs → hash-Cg0TXJPV.mjs} +8 -4
  383. package/dist/hash-Cg0TXJPV.mjs.map +1 -0
  384. package/dist/{hreflang-CIxH_LKz.d.mts → hreflang-BaLCNcDx.d.mts} +2 -2
  385. package/dist/{hreflang-CIxH_LKz.d.mts.map → hreflang-BaLCNcDx.d.mts.map} +1 -1
  386. package/dist/{hreflang-CbYeCzl9.mjs → hreflang-BdZuVBhL.mjs} +7 -7
  387. package/dist/{hreflang-CbYeCzl9.mjs.map → hreflang-BdZuVBhL.mjs.map} +1 -1
  388. package/dist/{import-oDYCgNYQ.mjs → import-C-9uqyT3.mjs} +6 -6
  389. package/dist/{import-oDYCgNYQ.mjs.map → import-C-9uqyT3.mjs.map} +1 -1
  390. package/dist/{index-BZJ_5FOX.d.mts → index-M37iz29I.d.mts} +112 -37
  391. package/dist/index-M37iz29I.d.mts.map +1 -0
  392. package/dist/{index-BEui-cRd.d.mts → index-MGw47uWq.d.mts} +3 -3
  393. package/dist/{index-BEui-cRd.d.mts.map → index-MGw47uWq.d.mts.map} +1 -1
  394. package/dist/index.d.mts +19 -19
  395. package/dist/index.mjs +69 -67
  396. package/dist/{load-Dg5gtWma.mjs → load-DV1DZuUJ.mjs} +2 -2
  397. package/dist/{load-Dg5gtWma.mjs.map → load-DV1DZuUJ.mjs.map} +1 -1
  398. package/dist/{loader-D4rigvjR.mjs → loader-CGugY7Zl.mjs} +29 -15
  399. package/dist/loader-CGugY7Zl.mjs.map +1 -0
  400. package/dist/{manifest-schema-bCq54i7F.mjs → manifest-schema-Da7kj23y.mjs} +1 -1
  401. package/dist/{manifest-schema-bCq54i7F.mjs.map → manifest-schema-Da7kj23y.mjs.map} +1 -1
  402. package/dist/media/index.d.mts +1 -1
  403. package/dist/media/local-runtime.d.mts +12 -12
  404. package/dist/media/local-runtime.mjs +8 -8
  405. package/dist/{media-its1WLYv.mjs → media-BP7S-nHT.mjs} +60 -15
  406. package/dist/media-BP7S-nHT.mjs.map +1 -0
  407. package/dist/{media-BJ6SRY3g.mjs → media-OhYL-7Io.mjs} +8 -4
  408. package/dist/{media-BJ6SRY3g.mjs.map → media-OhYL-7Io.mjs.map} +1 -1
  409. package/dist/{media-allowlist-jUppPWFy.mjs → media-allowlist-D-peH1H5.mjs} +1 -1
  410. package/dist/{media-allowlist-jUppPWFy.mjs.map → media-allowlist-D-peH1H5.mjs.map} +1 -1
  411. package/dist/{media-upload-DNu3QySc.mjs → media-upload-DtrwU2B0.mjs} +7 -7
  412. package/dist/{media-upload-DNu3QySc.mjs.map → media-upload-DtrwU2B0.mjs.map} +1 -1
  413. package/dist/{media-url-BCm5vBn6.mjs → media-url-DYs_YLOx.mjs} +1 -1
  414. package/dist/{media-url-BCm5vBn6.mjs.map → media-url-DYs_YLOx.mjs.map} +1 -1
  415. package/dist/{media-usage-DPQ3K4xB.mjs → media-usage-BlxfTkN0.mjs} +8 -8
  416. package/dist/{media-usage-DPQ3K4xB.mjs.map → media-usage-BlxfTkN0.mjs.map} +1 -1
  417. package/dist/{menus-BMGzWyWH.mjs → menus-BcQWxeXu.mjs} +5 -5
  418. package/dist/{menus-BMGzWyWH.mjs.map → menus-BcQWxeXu.mjs.map} +1 -1
  419. package/dist/{menus-CPf_SW7u.mjs → menus-Y54RDPIN.mjs} +215 -38
  420. package/dist/menus-Y54RDPIN.mjs.map +1 -0
  421. package/dist/{mode-fiXRMfeA.mjs → mode-BWyTBe3I.mjs} +1 -1
  422. package/dist/{mode-fiXRMfeA.mjs.map → mode-BWyTBe3I.mjs.map} +1 -1
  423. package/dist/{oauth-authorization-oqfbBuMH.mjs → oauth-authorization-ClvktmrL.mjs} +5 -5
  424. package/dist/{oauth-authorization-oqfbBuMH.mjs.map → oauth-authorization-ClvktmrL.mjs.map} +1 -1
  425. package/dist/{oauth-clients-BlrUHAsf.mjs → oauth-clients-8ao-U66l.mjs} +1 -1
  426. package/dist/{oauth-clients-BlrUHAsf.mjs.map → oauth-clients-8ao-U66l.mjs.map} +1 -1
  427. package/dist/{oauth-state-store-DnvjRMy6.mjs → oauth-state-store-B1ofdTiQ.mjs} +1 -1
  428. package/dist/{oauth-state-store-DnvjRMy6.mjs.map → oauth-state-store-B1ofdTiQ.mjs.map} +1 -1
  429. package/dist/{oauth-user-lookup-oUllxvAv.mjs → oauth-user-lookup-CscEuIiR.mjs} +1 -1
  430. package/dist/{oauth-user-lookup-oUllxvAv.mjs.map → oauth-user-lookup-CscEuIiR.mjs.map} +1 -1
  431. package/dist/object-cache/memory.d.mts +1 -1
  432. package/dist/{object-cache-Bok5j2ae.mjs → object-cache-71tPfV4A.mjs} +106 -5
  433. package/dist/object-cache-71tPfV4A.mjs.map +1 -0
  434. package/dist/{options-BqMkWfYa.d.mts → options-CA4eVX6P.d.mts} +3 -3
  435. package/dist/{options-BqMkWfYa.d.mts.map → options-CA4eVX6P.d.mts.map} +1 -1
  436. package/dist/{options-BlmBHTvX.mjs → options-CBXIHUoT.mjs} +1 -1
  437. package/dist/{options-BlmBHTvX.mjs.map → options-CBXIHUoT.mjs.map} +1 -1
  438. package/dist/page/index.d.mts +2 -2
  439. package/dist/{parse-53zyxlpv.mjs → parse-CJKNuewM.mjs} +2 -2
  440. package/dist/{parse-53zyxlpv.mjs.map → parse-CJKNuewM.mjs.map} +1 -1
  441. package/dist/{passkey-config-C-SKpc0-.mjs → passkey-config-D-zrzMJI.mjs} +1 -1
  442. package/dist/{passkey-config-C-SKpc0-.mjs.map → passkey-config-D-zrzMJI.mjs.map} +1 -1
  443. package/dist/{placeholder-Dop47JMM.d.mts → placeholder-DaeNS-VG.d.mts} +1 -1
  444. package/dist/{placeholder-Dop47JMM.d.mts.map → placeholder-DaeNS-VG.d.mts.map} +1 -1
  445. package/dist/plugin-types.d.mts +1 -1
  446. package/dist/plugin-utils.d.mts +10 -10
  447. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  448. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  449. package/dist/{portable-text-sDj92Kxv.mjs → portable-text-B_kqBmXB.mjs} +1 -1
  450. package/dist/{portable-text-sDj92Kxv.mjs.map → portable-text-B_kqBmXB.mjs.map} +1 -1
  451. package/dist/{preview-D4Jnbfx7.mjs → preview-BU6PaLpM.mjs} +2 -2
  452. package/dist/{preview-D4Jnbfx7.mjs.map → preview-BU6PaLpM.mjs.map} +1 -1
  453. package/dist/{public-url-DSGTnJFw.mjs → public-url-Ox9oOlgp.mjs} +14 -3
  454. package/dist/public-url-Ox9oOlgp.mjs.map +1 -0
  455. package/dist/{query-Bz9bWZfm.mjs → query-C5w7PsRQ.mjs} +43 -44
  456. package/dist/query-C5w7PsRQ.mjs.map +1 -0
  457. package/dist/{query-DdFGHzQF.mjs → query-rC9HKv1N.mjs} +4 -4
  458. package/dist/{query-DdFGHzQF.mjs.map → query-rC9HKv1N.mjs.map} +1 -1
  459. package/dist/{rate-limit-D3IEiUi2.mjs → rate-limit-kug6q99V.mjs} +2 -2
  460. package/dist/{rate-limit-D3IEiUi2.mjs.map → rate-limit-kug6q99V.mjs.map} +1 -1
  461. package/dist/{redirect-BoUac4NT.mjs → redirect-DIJxXKOG.mjs} +3 -3
  462. package/dist/{redirect-BoUac4NT.mjs.map → redirect-DIJxXKOG.mjs.map} +1 -1
  463. package/dist/{redirect-Botom7X6.mjs → redirect-Egf2R9yP.mjs} +1 -1
  464. package/dist/{redirect-Botom7X6.mjs.map → redirect-Egf2R9yP.mjs.map} +1 -1
  465. package/dist/{redirects-ChbpqKiS.mjs → redirects-Bzm812bY.mjs} +5 -5
  466. package/dist/{redirects-ChbpqKiS.mjs.map → redirects-Bzm812bY.mjs.map} +1 -1
  467. package/dist/{redirects-D457qwt0.mjs → redirects-G8wAhWAf.mjs} +25 -7
  468. package/dist/redirects-G8wAhWAf.mjs.map +1 -0
  469. package/dist/{registry-y21kjhfG.mjs → registry-Dbodb4Uo.mjs} +59 -14
  470. package/dist/registry-Dbodb4Uo.mjs.map +1 -0
  471. package/dist/{relation-Du0r04E0.mjs → relation-Cbe3Sd3m.mjs} +3 -3
  472. package/dist/{relation-Du0r04E0.mjs.map → relation-Cbe3Sd3m.mjs.map} +1 -1
  473. package/dist/{relations-CZMpBqEd.mjs → relations-Bw_E1TXo.mjs} +3 -3
  474. package/dist/{relations-CZMpBqEd.mjs.map → relations-Bw_E1TXo.mjs.map} +1 -1
  475. package/dist/{relations-qKmSj9KM.d.mts → relations-G2ta7GIl.d.mts} +50 -12
  476. package/dist/relations-G2ta7GIl.d.mts.map +1 -0
  477. package/dist/{relations-DtX1UMBH.mjs → relations-qHwpUe66.mjs} +6 -6
  478. package/dist/{relations-DtX1UMBH.mjs.map → relations-qHwpUe66.mjs.map} +1 -1
  479. package/dist/request-context.d.mts +3 -0
  480. package/dist/request-context.d.mts.map +1 -1
  481. package/dist/request-context.mjs.map +1 -1
  482. package/dist/{request-meta-DzXYYI-n.mjs → request-meta-Df-jFbAd.mjs} +2 -2
  483. package/dist/{request-meta-DzXYYI-n.mjs.map → request-meta-Df-jFbAd.mjs.map} +1 -1
  484. package/dist/{resolve-DFr4kq72.mjs → resolve-DZzG4HqM.mjs} +2 -2
  485. package/dist/{resolve-DFr4kq72.mjs.map → resolve-DZzG4HqM.mjs.map} +1 -1
  486. package/dist/{runner-BdeLEgad.mjs → runner-BFTrkYhu.mjs} +497 -213
  487. package/dist/runner-BFTrkYhu.mjs.map +1 -0
  488. package/dist/{runner-Dd8m8k9F.d.mts → runner-BaADli8l.d.mts} +2 -2
  489. package/dist/{runner-Dd8m8k9F.d.mts.map → runner-BaADli8l.d.mts.map} +1 -1
  490. package/dist/runtime.d.mts +11 -11
  491. package/dist/runtime.mjs +3 -3
  492. package/dist/{schema-BH8P8vaC.mjs → schema-CiQXr6_F.mjs} +3 -3
  493. package/dist/{schema-BH8P8vaC.mjs.map → schema-CiQXr6_F.mjs.map} +1 -1
  494. package/dist/{scopes-DTIkIaGA.mjs → scopes-CNJVT5i5.mjs} +3 -3
  495. package/dist/{scopes-DTIkIaGA.mjs.map → scopes-CNJVT5i5.mjs.map} +1 -1
  496. package/dist/{search-D-Yhpmvs.mjs → search-FZhx5dDU.mjs} +7 -7
  497. package/dist/{search-D-Yhpmvs.mjs.map → search-FZhx5dDU.mjs.map} +1 -1
  498. package/dist/{secrets-CQ-69kF9.mjs → secrets-DLd8RXee.mjs} +4 -4
  499. package/dist/{secrets-CQ-69kF9.mjs.map → secrets-DLd8RXee.mjs.map} +1 -1
  500. package/dist/{sections-CzVBAKjw.mjs → sections-BrIrMUCn.mjs} +3 -3
  501. package/dist/{sections-CzVBAKjw.mjs.map → sections-BrIrMUCn.mjs.map} +1 -1
  502. package/dist/seed/index.d.mts +2 -2
  503. package/dist/seed/index.mjs +25 -23
  504. package/dist/seo/index.d.mts +3 -3
  505. package/dist/seo/index.mjs +18 -16
  506. package/dist/seo/index.mjs.map +1 -1
  507. package/dist/{seo-C3GDfT0V.mjs → seo-CobNfOvb.mjs} +2 -2
  508. package/dist/{seo-C3GDfT0V.mjs.map → seo-CobNfOvb.mjs.map} +1 -1
  509. package/dist/{seo-kJzVAmmu.mjs → seo-DTHRntNC.mjs} +3 -3
  510. package/dist/{seo-kJzVAmmu.mjs.map → seo-DTHRntNC.mjs.map} +1 -1
  511. package/dist/{service-CQnc276a.mjs → service-B-pYGPgR.mjs} +4 -4
  512. package/dist/{service-CQnc276a.mjs.map → service-B-pYGPgR.mjs.map} +1 -1
  513. package/dist/{session-user-DbHqKDKe.mjs → session-user-BvM9-zNl.mjs} +2 -2
  514. package/dist/{session-user-DbHqKDKe.mjs.map → session-user-BvM9-zNl.mjs.map} +1 -1
  515. package/dist/{settings-Dtc0DU31.mjs → settings-DPHau-WH.mjs} +3 -3
  516. package/dist/{settings-Dtc0DU31.mjs.map → settings-DPHau-WH.mjs.map} +1 -1
  517. package/dist/{settings-C2PaBS49.mjs → settings-kJhGiQ4z.mjs} +7 -7
  518. package/dist/{settings-C2PaBS49.mjs.map → settings-kJhGiQ4z.mjs.map} +1 -1
  519. package/dist/{setup-complete-CdIlqloh.mjs → setup-complete-u50Qm8rY.mjs} +2 -2
  520. package/dist/{setup-complete-CdIlqloh.mjs.map → setup-complete-u50Qm8rY.mjs.map} +1 -1
  521. package/dist/{setup-nonce-DqiIPr-J.mjs → setup-nonce-DCjiiOD2.mjs} +1 -1
  522. package/dist/{setup-nonce-DqiIPr-J.mjs.map → setup-nonce-DCjiiOD2.mjs.map} +1 -1
  523. package/dist/{single-flight-cache-C2exrGAi.mjs → single-flight-cache-DW3w11Pu.mjs} +1 -1
  524. package/dist/{single-flight-cache-C2exrGAi.mjs.map → single-flight-cache-DW3w11Pu.mjs.map} +1 -1
  525. package/dist/site-url-I-lJ5kma.mjs +16 -0
  526. package/dist/site-url-I-lJ5kma.mjs.map +1 -0
  527. package/dist/{snapshot-BdpUJKD-.mjs → snapshot-I_fjLDaD.mjs} +2 -2
  528. package/dist/{snapshot-BdpUJKD-.mjs.map → snapshot-I_fjLDaD.mjs.map} +1 -1
  529. package/dist/{ssrf-CviKqWmq.mjs → ssrf-CTa6v21i.mjs} +1 -1
  530. package/dist/{ssrf-CviKqWmq.mjs.map → ssrf-CTa6v21i.mjs.map} +1 -1
  531. package/dist/{state-xxv6ZTMv.mjs → state-CQvoefYP.mjs} +1 -1
  532. package/dist/{state-xxv6ZTMv.mjs.map → state-CQvoefYP.mjs.map} +1 -1
  533. package/dist/{status-COfycGIU.mjs → status-CIsmlC1E.mjs} +1 -1
  534. package/dist/{status-COfycGIU.mjs.map → status-CIsmlC1E.mjs.map} +1 -1
  535. package/dist/storage/local.d.mts +1 -1
  536. package/dist/storage/local.mjs +1 -1
  537. package/dist/storage/s3.d.mts +1 -1
  538. package/dist/storage/s3.mjs +2 -2
  539. package/dist/storage/s3.mjs.map +1 -1
  540. package/dist/{taxonomies-BN6M9Nrv.mjs → taxonomies-CKuaZER5.mjs} +90 -9
  541. package/dist/taxonomies-CKuaZER5.mjs.map +1 -0
  542. package/dist/{taxonomies-r7pqLBCn.mjs → taxonomies-CLN1N92E.mjs} +57 -32
  543. package/dist/taxonomies-CLN1N92E.mjs.map +1 -0
  544. package/dist/{taxonomy-0mCI25HN.mjs → taxonomy-pOrB2kZe.mjs} +142 -15
  545. package/dist/taxonomy-pOrB2kZe.mjs.map +1 -0
  546. package/dist/{tokens-DVltpO2D.mjs → tokens-DagaJGK8.mjs} +1 -1
  547. package/dist/{tokens-DVltpO2D.mjs.map → tokens-DagaJGK8.mjs.map} +1 -1
  548. package/dist/{transaction-D0FOsb3X.mjs → transaction-NQj4VJ7Z.mjs} +1 -1
  549. package/dist/{transaction-D0FOsb3X.mjs.map → transaction-NQj4VJ7Z.mjs.map} +1 -1
  550. package/dist/{transport-Vd7VdqHv.d.mts → transport-CAwTaTp_.d.mts} +1 -1
  551. package/dist/{transport-Vd7VdqHv.d.mts.map → transport-CAwTaTp_.d.mts.map} +1 -1
  552. package/dist/{transport-CKrlqSpD.mjs → transport-DVsa5YYo.mjs} +1 -1
  553. package/dist/{transport-CKrlqSpD.mjs.map → transport-DVsa5YYo.mjs.map} +1 -1
  554. package/dist/{trusted-proxy-CwjQj0YG.mjs → trusted-proxy-D20_7fyX.mjs} +1 -1
  555. package/dist/{trusted-proxy-CwjQj0YG.mjs.map → trusted-proxy-D20_7fyX.mjs.map} +1 -1
  556. package/dist/{types-BfYUPJdP.d.mts → types-BGWPMiBO.d.mts} +2 -2
  557. package/dist/{types-BfYUPJdP.d.mts.map → types-BGWPMiBO.d.mts.map} +1 -1
  558. package/dist/{types-iVeZ5g6N.d.mts → types-BK6U01Ro.d.mts} +1 -1
  559. package/dist/{types-iVeZ5g6N.d.mts.map → types-BK6U01Ro.d.mts.map} +1 -1
  560. package/dist/{types-BD40g7zz.mjs → types-BjxTKxrZ.mjs} +1 -1
  561. package/dist/{types-BD40g7zz.mjs.map → types-BjxTKxrZ.mjs.map} +1 -1
  562. package/dist/{types-Kmaxdarz.d.mts → types-BnFP1M3J.d.mts} +22 -1
  563. package/dist/types-BnFP1M3J.d.mts.map +1 -0
  564. package/dist/{types-C7U0HlEr.d.mts → types-C8oz_ayJ.d.mts} +1 -1
  565. package/dist/{types-C7U0HlEr.d.mts.map → types-C8oz_ayJ.d.mts.map} +1 -1
  566. package/dist/{types-B4vm81VH.d.mts → types-CbUcuxxc.d.mts} +1 -1
  567. package/dist/{types-B4vm81VH.d.mts.map → types-CbUcuxxc.d.mts.map} +1 -1
  568. package/dist/{types-CrRUFdej.mjs → types-Cd8iuS1J.mjs} +10 -3
  569. package/dist/{types-CrRUFdej.mjs.map → types-Cd8iuS1J.mjs.map} +1 -1
  570. package/dist/types-CtzytVXn.mjs +18 -0
  571. package/dist/types-CtzytVXn.mjs.map +1 -0
  572. package/dist/{types-BvB7gDOD.d.mts → types-Cz8hNch2.d.mts} +5 -5
  573. package/dist/{types-BvB7gDOD.d.mts.map → types-Cz8hNch2.d.mts.map} +1 -1
  574. package/dist/{types-B97jg3aW.d.mts → types-DLG4IFEQ.d.mts} +1 -1
  575. package/dist/{types-B97jg3aW.d.mts.map → types-DLG4IFEQ.d.mts.map} +1 -1
  576. package/dist/{types-DPKhI5ib.d.mts → types-Dc4ntQjQ.d.mts} +18 -1
  577. package/dist/types-Dc4ntQjQ.d.mts.map +1 -0
  578. package/dist/{types-BNfPHfay.d.mts → types-LoagAGzH.d.mts} +1 -1
  579. package/dist/{types-BNfPHfay.d.mts.map → types-LoagAGzH.d.mts.map} +1 -1
  580. package/dist/{types-o7xo7VgH.mjs → types-NBI3rF-_.mjs} +3 -2
  581. package/dist/types-NBI3rF-_.mjs.map +1 -0
  582. package/dist/upload-attempts-D8QAFLUJ.mjs +27 -0
  583. package/dist/upload-attempts-D8QAFLUJ.mjs.map +1 -0
  584. package/dist/{user-aTXqmXBz.mjs → user-DBrq4UVq.mjs} +3 -3
  585. package/dist/{user-aTXqmXBz.mjs.map → user-DBrq4UVq.mjs.map} +1 -1
  586. package/dist/{utils-BbUgmeZG.mjs → utils-hLzi_2Fn.mjs} +2 -2
  587. package/dist/{utils-BbUgmeZG.mjs.map → utils-hLzi_2Fn.mjs.map} +1 -1
  588. package/dist/{validate-VPnKoIzW.mjs → validate-BpwoDOgt.mjs} +25 -2
  589. package/dist/validate-BpwoDOgt.mjs.map +1 -0
  590. package/dist/{validate-DULfgpJP.d.mts → validate-C3oSmA7F.d.mts} +15 -5
  591. package/dist/validate-C3oSmA7F.d.mts.map +1 -0
  592. package/dist/{validate-CDT1jl6_.mjs → validate-mKo3RxBM.mjs} +4 -4
  593. package/dist/{validate-CDT1jl6_.mjs.map → validate-mKo3RxBM.mjs.map} +1 -1
  594. package/dist/{validation-DlD0E35W.mjs → validation-BgpucsvF.mjs} +11 -9
  595. package/dist/{validation-DlD0E35W.mjs.map → validation-BgpucsvF.mjs.map} +1 -1
  596. package/dist/version-C4PnpmoV.mjs +7 -0
  597. package/dist/{version-BRMngh9I.mjs.map → version-C4PnpmoV.mjs.map} +1 -1
  598. package/dist/{widgets-5fipNkMT.mjs → widgets-CJJtkiKh.mjs} +3 -3
  599. package/dist/{widgets-5fipNkMT.mjs.map → widgets-CJJtkiKh.mjs.map} +1 -1
  600. package/dist/{wxr-taxonomies-DrihupaC.mjs → wxr-taxonomies-9PPSy8X6.mjs} +4 -4
  601. package/dist/{wxr-taxonomies-DrihupaC.mjs.map → wxr-taxonomies-9PPSy8X6.mjs.map} +1 -1
  602. package/dist/{wxr-taxonomies-B4tMuN5T.d.mts → wxr-taxonomies-Bkpp_2tK.d.mts} +1 -1
  603. package/dist/{wxr-taxonomies-B4tMuN5T.d.mts.map → wxr-taxonomies-Bkpp_2tK.d.mts.map} +1 -1
  604. package/dist/{zod-generator-CwkHWz4f.mjs → zod-generator-CG64Hnbh.mjs} +3 -3
  605. package/dist/{zod-generator-CwkHWz4f.mjs.map → zod-generator-CG64Hnbh.mjs.map} +1 -1
  606. package/package.json +12 -8
  607. package/src/after.ts +6 -1
  608. package/src/api/errors.ts +1 -0
  609. package/src/api/handlers/content.ts +45 -4
  610. package/src/api/handlers/marketplace.ts +14 -0
  611. package/src/api/handlers/media.ts +4 -4
  612. package/src/api/handlers/registry.ts +14 -0
  613. package/src/api/handlers/revision.ts +19 -5
  614. package/src/api/handlers/schema.ts +37 -0
  615. package/src/api/handlers/snapshot.ts +1 -1
  616. package/src/api/handlers/taxonomies.ts +111 -10
  617. package/src/api/openapi/document.ts +84 -3
  618. package/src/api/public-url.ts +14 -2
  619. package/src/api/schemas/media.ts +9 -2
  620. package/src/api/schemas/schema.ts +13 -0
  621. package/src/api/schemas/search.ts +2 -0
  622. package/src/api/schemas/taxonomies.ts +34 -1
  623. package/src/api/site-url.ts +16 -6
  624. package/src/astro/integration/routes.ts +19 -0
  625. package/src/astro/integration/runtime.ts +13 -0
  626. package/src/astro/integration/virtual-modules.ts +2 -0
  627. package/src/astro/middleware/redirect.ts +2 -10
  628. package/src/astro/middleware/scoped-db.ts +35 -4
  629. package/src/astro/middleware.ts +56 -22
  630. package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -1
  631. package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +2 -2
  632. package/src/astro/routes/api/auth/invite/index.ts +2 -2
  633. package/src/astro/routes/api/auth/magic-link/send.ts +2 -2
  634. package/src/astro/routes/api/auth/signup/request.ts +2 -2
  635. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +1 -1
  636. package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
  637. package/src/astro/routes/api/media/[id]/confirm.ts +148 -59
  638. package/src/astro/routes/api/media/[id]/upload.ts +262 -0
  639. package/src/astro/routes/api/media/[id].ts +19 -10
  640. package/src/astro/routes/api/media/upload-url.ts +28 -31
  641. package/src/astro/routes/api/schema/collections/reorder.ts +31 -0
  642. package/src/astro/routes/api/schema/index.ts +2 -0
  643. package/src/astro/routes/api/search/enable.ts +5 -1
  644. package/src/astro/routes/api/search/rebuild.ts +6 -1
  645. package/src/astro/routes/api/taxonomies/[name]/reorder.ts +41 -0
  646. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +6 -3
  647. package/src/astro/types.ts +7 -0
  648. package/src/cleanup.ts +54 -26
  649. package/src/cli/commands/dev.ts +13 -3
  650. package/src/cli/commands/export-seed.ts +2 -0
  651. package/src/cli/index.ts +1 -1
  652. package/src/components/CommentForm.astro +1 -1
  653. package/src/components/Comments.astro +1 -1
  654. package/src/components/InlinePortableTextEditor.tsx +175 -31
  655. package/src/components/OrderedList.astro +14 -0
  656. package/src/components/PortableText.astro +26 -4
  657. package/src/components/code-mark.ts +11 -0
  658. package/src/components/index.ts +12 -1
  659. package/src/components/ordered-list.ts +549 -0
  660. package/src/content/converters/numbered-list.ts +148 -0
  661. package/src/content/converters/portable-text-to-prosemirror.ts +59 -9
  662. package/src/content/converters/prosemirror-to-portable-text.ts +23 -12
  663. package/src/content/converters/types.ts +2 -0
  664. package/src/content/portable-text-lists.ts +205 -0
  665. package/src/database/dialect-helpers.ts +41 -22
  666. package/src/database/migrations/054_media_upload_attempts.ts +41 -0
  667. package/src/database/migrations/055_content_translation_group_locale_index.ts +67 -0
  668. package/src/database/migrations/056_taxonomy_term_sort_order.ts +189 -0
  669. package/src/database/migrations/057_collection_hidden.ts +24 -0
  670. package/src/database/migrations/058_collection_sort_order.ts +20 -0
  671. package/src/database/migrations/059_revision_prune_queue.ts +36 -0
  672. package/src/database/migrations/runner.ts +12 -0
  673. package/src/database/repositories/content.ts +193 -183
  674. package/src/database/repositories/media.ts +158 -28
  675. package/src/database/repositories/revision.ts +82 -17
  676. package/src/database/repositories/taxonomy.ts +202 -7
  677. package/src/database/repositories/types.ts +7 -0
  678. package/src/database/types.ts +23 -1
  679. package/src/database/validate.ts +39 -0
  680. package/src/db/adapters.ts +8 -0
  681. package/src/deferred-tasks.ts +71 -0
  682. package/src/emdash-runtime.ts +277 -88
  683. package/src/i18n/config.ts +17 -10
  684. package/src/index.ts +3 -0
  685. package/src/loader.ts +46 -24
  686. package/src/media/upload-attempts.ts +33 -0
  687. package/src/media/usage/gc.ts +50 -0
  688. package/src/object-cache/index.ts +160 -3
  689. package/src/plugins/routes.ts +34 -0
  690. package/src/plugins/storage-indexes.ts +50 -11
  691. package/src/query.ts +50 -44
  692. package/src/redirects/cache.ts +79 -19
  693. package/src/request-context.ts +3 -0
  694. package/src/scheduled-publish.ts +6 -1
  695. package/src/schema/registry.ts +95 -3
  696. package/src/schema/types.ts +24 -0
  697. package/src/search/fts-manager.ts +50 -10
  698. package/src/search/index.ts +2 -0
  699. package/src/search/types.ts +6 -0
  700. package/src/seed/apply.ts +22 -2
  701. package/src/seed/types.ts +10 -0
  702. package/src/storage/s3.ts +1 -1
  703. package/src/taxonomies/index.ts +11 -7
  704. package/src/taxonomies/term-counts.ts +56 -28
  705. package/src/ui-comments.ts +19 -0
  706. package/src/ui.ts +11 -3
  707. package/src/utils/hash.ts +14 -3
  708. package/src/virtual-modules.d.ts +8 -0
  709. package/dist/adapters-C0ONzkUP.d.mts.map +0 -1
  710. package/dist/after-B1IIdH3Y.mjs +0 -29
  711. package/dist/after-B1IIdH3Y.mjs.map +0 -1
  712. package/dist/api-BkqFzIu4.mjs.map +0 -1
  713. package/dist/apply-DuXsqll7.mjs.map +0 -1
  714. package/dist/cache-DDwy3JDW.mjs +0 -65
  715. package/dist/cache-DDwy3JDW.mjs.map +0 -1
  716. package/dist/config-B6b_BobR.mjs.map +0 -1
  717. package/dist/content-BC43pICM.mjs.map +0 -1
  718. package/dist/dialect-helpers-BtOwo2us.mjs.map +0 -1
  719. package/dist/errors-DtEXIQQV.mjs.map +0 -1
  720. package/dist/fts-manager-hyCU9OOp.mjs.map +0 -1
  721. package/dist/hash-DFFrkivP.mjs.map +0 -1
  722. package/dist/index-BZJ_5FOX.d.mts.map +0 -1
  723. package/dist/loader-D4rigvjR.mjs.map +0 -1
  724. package/dist/media-its1WLYv.mjs.map +0 -1
  725. package/dist/menus-CPf_SW7u.mjs.map +0 -1
  726. package/dist/object-cache-Bok5j2ae.mjs.map +0 -1
  727. package/dist/public-url-DSGTnJFw.mjs.map +0 -1
  728. package/dist/query-Bz9bWZfm.mjs.map +0 -1
  729. package/dist/redirects-D457qwt0.mjs.map +0 -1
  730. package/dist/registry-y21kjhfG.mjs.map +0 -1
  731. package/dist/relations-qKmSj9KM.d.mts.map +0 -1
  732. package/dist/runner-BdeLEgad.mjs.map +0 -1
  733. package/dist/site-url-NGJT6NTU.mjs +0 -13
  734. package/dist/site-url-NGJT6NTU.mjs.map +0 -1
  735. package/dist/taxonomies-BN6M9Nrv.mjs.map +0 -1
  736. package/dist/taxonomies-r7pqLBCn.mjs.map +0 -1
  737. package/dist/taxonomy-0mCI25HN.mjs.map +0 -1
  738. package/dist/types-DPKhI5ib.d.mts.map +0 -1
  739. package/dist/types-Kmaxdarz.d.mts.map +0 -1
  740. package/dist/types-o7xo7VgH.mjs.map +0 -1
  741. package/dist/validate-DULfgpJP.d.mts.map +0 -1
  742. package/dist/validate-VPnKoIzW.mjs.map +0 -1
  743. package/dist/version-BRMngh9I.mjs +0 -7
  744. /package/dist/{api-tokens-Cvmixds7.mjs → api-tokens-Dai9dND0.mjs} +0 -0
  745. /package/dist/{ssrf-BB__xfNM.mjs → ssrf-Cj568Dgs.mjs} +0 -0
  746. /package/dist/{types-CK0LxPUQ.mjs → types-DKuWPYV5.mjs} +0 -0
@@ -18,6 +18,7 @@ import type {
18
18
  ContentDateField,
19
19
  } from "./types.js";
20
20
  import {
21
+ ContentMutationConflictError,
21
22
  EmDashValidationError,
22
23
  ScheduledNotDueError,
23
24
  encodeCursor,
@@ -26,10 +27,64 @@ import {
26
27
 
27
28
  // Regex pattern for ULID validation
28
29
  const ULID_PATTERN = /^[0-9A-Z]{26}$/;
30
+ const SQLSTATE_PATTERN = /^[0-9A-Z]{5}$/;
29
31
 
30
32
  // LIKE wildcards that must be escaped so user search input is matched literally.
31
33
  const LIKE_WILDCARD_RE = /[\\%_]/g;
32
34
 
35
+ function nullableColumnMatch(column: string, value: string | null): ReturnType<typeof sql> {
36
+ validateIdentifier(column, "content column");
37
+ return value === null ? sql`${sql.ref(column)} IS NULL` : sql`${sql.ref(column)} = ${value}`;
38
+ }
39
+
40
+ function sameStoredValue(left: unknown, right: unknown): boolean {
41
+ return Object.is(serializeValue(left), serializeValue(right));
42
+ }
43
+
44
+ function matchesPublication(
45
+ observed: ContentItem,
46
+ existing: ContentItem,
47
+ revision: { data: Record<string, unknown> },
48
+ revisionId: string,
49
+ slug: string | null,
50
+ publishedAt: string,
51
+ updatedAt: string,
52
+ ): boolean {
53
+ if (
54
+ observed.version !== existing.version + 1 ||
55
+ observed.status !== "published" ||
56
+ observed.slug !== slug ||
57
+ observed.liveRevisionId !== revisionId ||
58
+ observed.draftRevisionId !== null ||
59
+ observed.scheduledAt !== null ||
60
+ observed.publishedAt !== publishedAt ||
61
+ observed.updatedAt !== updatedAt
62
+ ) {
63
+ return false;
64
+ }
65
+
66
+ return Object.entries(revision.data).every(
67
+ ([key, value]) =>
68
+ SYSTEM_COLUMNS.has(key) || key.startsWith("_") || sameStoredValue(observed.data[key], value),
69
+ );
70
+ }
71
+
72
+ function matchesPublicationFence(observed: ContentItem, existing: ContentItem): boolean {
73
+ return (
74
+ observed.version === existing.version &&
75
+ observed.status === existing.status &&
76
+ observed.liveRevisionId === existing.liveRevisionId &&
77
+ observed.draftRevisionId === existing.draftRevisionId &&
78
+ observed.scheduledAt === existing.scheduledAt
79
+ );
80
+ }
81
+
82
+ function isConfirmedStatementFailure(error: unknown): boolean {
83
+ if (typeof error !== "object" || error === null || !("code" in error)) return false;
84
+ const code = (error as { code?: unknown }).code;
85
+ return typeof code === "string" && (code.startsWith("SQLITE_") || SQLSTATE_PATTERN.test(code));
86
+ }
87
+
33
88
  /**
34
89
  * Whitelist mapping a public date-filter field to its physical column. Keeping
35
90
  * this separate from `mapOrderField` makes the filterable set explicit and
@@ -322,6 +377,7 @@ export class ContentRepository {
322
377
  data: newData,
323
378
  status: "draft",
324
379
  authorId: authorId || original.authorId || undefined,
380
+ locale: original.locale ?? undefined,
325
381
  });
326
382
  }
327
383
 
@@ -590,15 +646,8 @@ export class ContentRepository {
590
646
  const tableName = getTableName(type);
591
647
  const now = new Date().toISOString();
592
648
 
593
- // Build update object with parameterized values. `version` bumps on
594
- // every update so the _rev optimistic-concurrency token
595
- // (version:updated_at) always moves — concurrent editors still get a
596
- // 409 on stale saves. `updated_at` is stamped only when the request
597
- // actually carries column writes: a draft-only save on a
598
- // revision-supporting collection resolves to a column no-op here (all
599
- // data went into draft storage), and stamping it anyway would register
600
- // a phantom modification for public "last modified" consumers like
601
- // sitemap <lastmod> and JSON-LD dateModified (#2143).
649
+ // Every update advances the optimistic-concurrency version. updated_at
650
+ // advances only when a content-row column actually changes.
602
651
  const updates: Record<string, unknown> = {};
603
652
 
604
653
  if (input.status !== undefined) {
@@ -660,7 +709,7 @@ export class ContentRepository {
660
709
  await this.restampEntryPivot(type, id);
661
710
  }
662
711
 
663
- invalidateCollectionCache(type);
712
+ if (hasColumnWrites) invalidateCollectionCache(type);
664
713
 
665
714
  const updated = await this.findById(type, id);
666
715
  if (!updated) {
@@ -1157,6 +1206,10 @@ export class ContentRepository {
1157
1206
  * Lets callers resolve many edge groups without an N+1 per group. The caller
1158
1207
  * groups the flat result by `translationGroup` itself.
1159
1208
  *
1209
+ * `translation_group` leads the sort so the ordering follows
1210
+ * `idx_{table}_del_tg_locale` past its `deleted_at` equality; callers group by
1211
+ * `translationGroup`, so the per-group locale order they rely on is preserved.
1212
+ *
1160
1213
  * `publishedOnly` restricts the result to `status = 'published'` — reference
1161
1214
  * reads pass this for callers without `content:read_drafts` so draft/scheduled
1162
1215
  * entries never leak through an edge traversal.
@@ -1183,7 +1236,7 @@ export class ContentRepository {
1183
1236
  WHERE translation_group IN (${sql.join(chunk)})
1184
1237
  AND deleted_at IS NULL
1185
1238
  ${publishedFilter}
1186
- ORDER BY locale ASC
1239
+ ORDER BY translation_group ASC, locale ASC
1187
1240
  `.execute(this.db);
1188
1241
  for (const row of result.rows) items.push(this.mapRow(type, row));
1189
1242
  }
@@ -1273,19 +1326,16 @@ export class ContentRepository {
1273
1326
  * an explicit value to backdate a publish (e.g. when migrating content from
1274
1327
  * another CMS).
1275
1328
  *
1276
- * `requireDue` (optional) gates the publish on the row still being due:
1277
- * `scheduled_at` non-null and in the past. Used by the scheduled-publishing
1278
- * sweep to avoid publishing content an editor unscheduled or rescheduled
1279
- * between selection and publish. It claims the row with a single conditional
1280
- * UPDATE (clearing `scheduled_at`) before any other write, so it is atomic
1281
- * even on D1 (no multi-statement transactions) and serialises against
1282
- * `unschedule()` and concurrent sweeps — no TOCTOU and no double publish.
1329
+ * `requireDue` gates the final update on the row still being due.
1330
+ * `expectedScheduledAt` additionally fences changes made after a sweep
1331
+ * selected the row but before publication preparation began.
1283
1332
  */
1284
1333
  async publish(
1285
1334
  type: string,
1286
1335
  id: string,
1287
1336
  publishedAt?: string,
1288
1337
  requireDue = false,
1338
+ expectedScheduledAt?: string,
1289
1339
  ): Promise<ContentItem> {
1290
1340
  const tableName = getTableName(type);
1291
1341
  const now = new Date().toISOString();
@@ -1294,128 +1344,126 @@ export class ContentRepository {
1294
1344
  if (!existing) {
1295
1345
  throw new EmDashValidationError("Content item not found");
1296
1346
  }
1297
-
1298
- // Scheduled sweep: atomically claim the row before any other write. A
1299
- // single conditional UPDATE is atomic per-statement on every dialect
1300
- // (it doesn't depend on a wrapping transaction, which D1 lacks). If the
1301
- // schedule was cleared or pushed to the future (unschedule/reschedule)
1302
- // or another sweep already claimed it, this affects 0 rows and we bail
1303
- // before promoting any revision — so the row can't be double-published.
1304
- let claimedScheduledAt: string | null = null;
1305
- let claimedUpdatedAt: string | null = null;
1306
- if (requireDue) {
1307
- const claim = await sql`
1308
- UPDATE ${sql.ref(tableName)}
1309
- SET scheduled_at = NULL,
1310
- updated_at = ${now}
1311
- WHERE id = ${id}
1312
- AND scheduled_at IS NOT NULL
1313
- AND scheduled_at <= ${now}
1314
- AND deleted_at IS NULL
1315
- `.execute(this.db);
1316
- if ((claim.numAffectedRows ?? 0n) === 0n) {
1317
- throw new ScheduledNotDueError();
1318
- }
1319
- // Remember what we cleared so we can put it back if the publish work
1320
- // below fails on a driver without transactions (see catch). Both
1321
- // values come from the pre-claim snapshot: if a concurrent
1322
- // reschedule-to-a-different-past-time landed between findById and the
1323
- // claim, the restore writes the snapshot value rather than the one the
1324
- // claim actually cleared. That window is tiny and the restore is
1325
- // best-effort retry bookkeeping, so the imprecision is acceptable.
1326
- claimedScheduledAt = existing.scheduledAt;
1327
- claimedUpdatedAt = existing.updatedAt;
1347
+ if (
1348
+ requireDue &&
1349
+ expectedScheduledAt !== undefined &&
1350
+ existing.scheduledAt !== expectedScheduledAt
1351
+ ) {
1352
+ throw new ScheduledNotDueError();
1328
1353
  }
1329
1354
 
1330
- // Track whether the final publish write committed. On D1 the claim above
1331
- // is already durable (withTransaction is a no-op there), so if a later
1332
- // step throws we must restore the schedule — otherwise the row is left
1333
- // `scheduled` with `scheduled_at = NULL` and no sweep ever retries it.
1334
- let publishCommitted = false;
1355
+ const revisionRepo = new RevisionRepository(this.db);
1356
+ let provisionalRevisionId: string | null = null;
1335
1357
  try {
1336
- const revisionRepo = new RevisionRepository(this.db);
1337
1358
  let revisionToPublish = existing.draftRevisionId || existing.liveRevisionId;
1338
1359
 
1339
1360
  if (!revisionToPublish) {
1340
- // No revision exists - create one from current data
1341
1361
  const revision = await revisionRepo.create({
1342
1362
  collection: type,
1343
1363
  entryId: id,
1344
1364
  data: existing.data,
1345
1365
  });
1346
1366
  revisionToPublish = revision.id;
1367
+ provisionalRevisionId = revision.id;
1347
1368
  }
1348
1369
 
1349
- // Sync the revision's data into the content table columns
1350
- // so the content table always holds the published version
1351
1370
  const revision = await revisionRepo.findById(revisionToPublish);
1352
- if (revision) {
1353
- // A staged slug lands on the live column only here — it never
1354
- // passes through update(), so its uniqueness was never checked.
1355
- // Validate before any write: the `(slug, locale)` unique index
1356
- // covers every row (drafts and trashed entries included), and
1357
- // letting the constraint fire mid-publish would surface as an
1358
- // opaque 500 after draft data already hit the live columns.
1359
- // A NULL locale never collides (unique indexes treat NULLs as
1360
- // distinct), so the check only applies to localized rows.
1361
- const stagedSlug = typeof revision.data._slug === "string" ? revision.data._slug : null;
1362
- if (stagedSlug !== null && stagedSlug !== existing.slug && existing.locale !== null) {
1363
- const conflict = await this.findBySlugIncludingTrashed(type, stagedSlug, existing.locale);
1364
- if (conflict && conflict.id !== id) {
1365
- throw new EmDashValidationError(
1366
- `Cannot publish: slug '${stagedSlug}' is already used by another entry` +
1367
- ` in this collection (id: ${conflict.id}). Choose a different slug.`,
1368
- { code: "SLUG_CONFLICT" },
1369
- );
1370
- }
1371
- }
1371
+ if (!revision || revision.collection !== type || revision.entryId !== id) {
1372
+ throw new EmDashValidationError("Revision does not belong to the specified content item");
1373
+ }
1372
1374
 
1373
- // Write the slug before the data columns: the slug UPDATE is the
1374
- // only statement here that can hit the unique constraint (if a
1375
- // concurrent write took the slug after the check above), and on
1376
- // D1 there is no transaction to roll back earlier statements.
1377
- if (stagedSlug !== null) {
1378
- await sql`
1379
- UPDATE ${sql.ref(tableName)}
1380
- SET slug = ${stagedSlug}
1381
- WHERE id = ${id}
1382
- `.execute(this.db);
1375
+ const stagedSlug = typeof revision.data._slug === "string" ? revision.data._slug : null;
1376
+ const intendedSlug = stagedSlug ?? existing.slug;
1377
+ const intendedPublishedAt = publishedAt ?? existing.publishedAt ?? now;
1378
+ if (stagedSlug !== null && stagedSlug !== existing.slug && existing.locale !== null) {
1379
+ const conflict = await this.findBySlugIncludingTrashed(type, stagedSlug, existing.locale);
1380
+ if (conflict && conflict.id !== id) {
1381
+ throw new EmDashValidationError(
1382
+ `Cannot publish: slug '${stagedSlug}' is already used by another entry` +
1383
+ ` in this collection (id: ${conflict.id}). Choose a different slug.`,
1384
+ { code: "SLUG_CONFLICT" },
1385
+ );
1383
1386
  }
1384
-
1385
- await this.syncDataColumns(type, id, revision.data);
1386
1387
  }
1387
1388
 
1388
- if (publishedAt !== undefined) {
1389
- // Caller supplied an explicit timestamp, so we overwrite published_at
1390
- // directly (used to backdate a publish, e.g. for content migrations).
1391
- await sql`
1392
- UPDATE ${sql.ref(tableName)}
1393
- SET live_revision_id = ${revisionToPublish},
1394
- draft_revision_id = NULL,
1395
- status = 'published',
1396
- scheduled_at = NULL,
1397
- published_at = ${publishedAt},
1398
- updated_at = ${now}
1399
- WHERE id = ${id}
1400
- AND deleted_at IS NULL
1401
- `.execute(this.db);
1402
- } else {
1403
- // No timestamp supplied — preserve existing published_at on
1404
- // idempotent re-publish, fall back to `now` on first publish.
1405
- await sql`
1389
+ const assignments: ReturnType<typeof sql>[] = [];
1390
+ if (stagedSlug !== null) assignments.push(sql`slug = ${stagedSlug}`);
1391
+ for (const [key, value] of Object.entries(revision.data)) {
1392
+ if (SYSTEM_COLUMNS.has(key) || key.startsWith("_")) continue;
1393
+ validateIdentifier(key, "content field name");
1394
+ assignments.push(sql`${sql.ref(key)} = ${serializeValue(value)}`);
1395
+ }
1396
+ assignments.push(
1397
+ sql`live_revision_id = ${revisionToPublish}`,
1398
+ sql`draft_revision_id = NULL`,
1399
+ sql`status = 'published'`,
1400
+ sql`scheduled_at = NULL`,
1401
+ sql`published_at = ${intendedPublishedAt}`,
1402
+ sql`updated_at = ${now}`,
1403
+ sql`version = version + 1`,
1404
+ );
1405
+
1406
+ const duePredicate = requireDue
1407
+ ? sql`AND scheduled_at IS NOT NULL AND scheduled_at <= ${now}`
1408
+ : sql``;
1409
+ let promoted = false;
1410
+ try {
1411
+ const result = await sql`
1406
1412
  UPDATE ${sql.ref(tableName)}
1407
- SET live_revision_id = ${revisionToPublish},
1408
- draft_revision_id = NULL,
1409
- status = 'published',
1410
- scheduled_at = NULL,
1411
- published_at = COALESCE(published_at, ${now}),
1412
- updated_at = ${now}
1413
+ SET ${sql.join(assignments, sql`, `)}
1413
1414
  WHERE id = ${id}
1414
1415
  AND deleted_at IS NULL
1416
+ AND version = ${existing.version}
1417
+ AND status = ${existing.status}
1418
+ AND ${nullableColumnMatch("live_revision_id", existing.liveRevisionId)}
1419
+ AND ${nullableColumnMatch("draft_revision_id", existing.draftRevisionId)}
1420
+ AND ${nullableColumnMatch("scheduled_at", existing.scheduledAt)}
1421
+ ${duePredicate}
1422
+ AND EXISTS (
1423
+ SELECT 1 FROM revisions
1424
+ WHERE revisions.id = ${revisionToPublish}
1425
+ AND revisions.collection = ${type}
1426
+ AND revisions.entry_id = ${id}
1427
+ )
1415
1428
  `.execute(this.db);
1429
+ promoted = (result.numAffectedRows ?? 0n) > 0n;
1430
+ } catch (error) {
1431
+ if (isConfirmedStatementFailure(error)) throw error;
1432
+ let observed: ContentItem | null;
1433
+ try {
1434
+ observed = await this.findById(type, id);
1435
+ } catch (reconciliationError) {
1436
+ throw new Error("Unable to confirm whether content publication completed", {
1437
+ cause: reconciliationError,
1438
+ });
1439
+ }
1440
+ if (!observed) {
1441
+ throw new Error("Unable to confirm whether content publication completed", {
1442
+ cause: error,
1443
+ });
1444
+ }
1445
+ promoted = matchesPublication(
1446
+ observed,
1447
+ existing,
1448
+ revision,
1449
+ revisionToPublish,
1450
+ intendedSlug,
1451
+ intendedPublishedAt,
1452
+ now,
1453
+ );
1454
+ if (!promoted && matchesPublicationFence(observed, existing)) throw error;
1455
+ if (!promoted) {
1456
+ throw new Error("Unable to confirm whether content publication completed", {
1457
+ cause: error,
1458
+ });
1459
+ }
1416
1460
  }
1417
- publishCommitted = true;
1418
1461
 
1462
+ if (!promoted) {
1463
+ throw requireDue ? new ScheduledNotDueError() : new ContentMutationConflictError();
1464
+ }
1465
+
1466
+ invalidateCollectionCache(type);
1419
1467
  await this.restampEntryPivot(type, id);
1420
1468
 
1421
1469
  const updated = await this.findById(type, id);
@@ -1423,38 +1471,15 @@ export class ContentRepository {
1423
1471
  throw new Error("Content not found");
1424
1472
  }
1425
1473
 
1426
- invalidateCollectionCache(type);
1427
1474
  return updated;
1428
1475
  } catch (error) {
1429
- // Best-effort schedule restore for the no-transaction (D1) case so a
1430
- // failed publish stays retryable. Skipped when the publish actually
1431
- // committed (the failure was afterwards). On SQLite/Postgres the
1432
- // enclosing transaction rolls the claim back, so this restore also
1433
- // rolls back — a harmless no-op. Never mask the original error.
1434
- if (requireDue && claimedScheduledAt && !publishCommitted) {
1476
+ if (provisionalRevisionId) {
1435
1477
  try {
1436
- // Only restore if the row still has pending work: either it's not
1437
- // published, or it's a published row that still has a draft change
1438
- // queued. This avoids re-adding a stale schedule (and triggering a
1439
- // redundant republish) when another actor fully published the row
1440
- // in the failure window — that publish clears draft_revision_id.
1441
- // Restore updated_at to its pre-claim value too — the claim bumped
1442
- // it to `now`, and a failed publish made no real change, so leaving
1443
- // it advanced would be a phantom modification for "changed since"
1444
- // consumers (sync, ETags, incremental indexers).
1445
- await sql`
1446
- UPDATE ${sql.ref(tableName)}
1447
- SET scheduled_at = ${claimedScheduledAt},
1448
- updated_at = ${claimedUpdatedAt ?? now}
1449
- WHERE id = ${id}
1450
- AND scheduled_at IS NULL
1451
- AND deleted_at IS NULL
1452
- AND (status != 'published' OR draft_revision_id IS NOT NULL)
1453
- `.execute(this.db);
1454
- } catch (restoreError) {
1478
+ await revisionRepo.deleteIfUnreferenced(type, id, provisionalRevisionId);
1479
+ } catch (cleanupError) {
1455
1480
  console.error(
1456
- `[content] Failed to restore schedule for ${type}/${id} after publish failure:`,
1457
- restoreError,
1481
+ `[content] Failed to clean up provisional revision ${provisionalRevisionId}:`,
1482
+ cleanupError,
1458
1483
  );
1459
1484
  }
1460
1485
  }
@@ -1529,8 +1554,6 @@ export class ContentRepository {
1529
1554
  * content row pointing at a missing or unrelated revision.
1530
1555
  */
1531
1556
  async setDraftRevision(type: string, id: string, revisionId: string): Promise<void> {
1532
- const tableName = getTableName(type);
1533
-
1534
1557
  const existing = await this.findById(type, id);
1535
1558
  if (!existing) {
1536
1559
  throw new EmDashValidationError("Content item not found");
@@ -1546,17 +1569,35 @@ export class ContentRepository {
1546
1569
  throw new EmDashValidationError("Revision does not belong to the specified content item");
1547
1570
  }
1548
1571
 
1549
- // Draft staging leaves live content untouched, so it must not bump
1550
- // updated_at — public "content last modified" consumers (sitemap
1551
- // <lastmod>, dateModified) would see a phantom modification (#2143).
1552
- await sql`
1572
+ if (!(await this.replaceDraftRevision(type, id, revisionId, existing))) {
1573
+ throw new ContentMutationConflictError();
1574
+ }
1575
+ }
1576
+
1577
+ async replaceDraftRevision(
1578
+ type: string,
1579
+ id: string,
1580
+ revisionId: string,
1581
+ expected: Pick<ContentItem, "version" | "liveRevisionId" | "draftRevisionId">,
1582
+ ): Promise<boolean> {
1583
+ const tableName = getTableName(type);
1584
+ const result = await sql`
1553
1585
  UPDATE ${sql.ref(tableName)}
1554
- SET draft_revision_id = ${revisionId}
1586
+ SET draft_revision_id = ${revisionId},
1587
+ version = version + 1
1555
1588
  WHERE id = ${id}
1556
1589
  AND deleted_at IS NULL
1590
+ AND version = ${expected.version}
1591
+ AND ${nullableColumnMatch("live_revision_id", expected.liveRevisionId)}
1592
+ AND ${nullableColumnMatch("draft_revision_id", expected.draftRevisionId)}
1593
+ AND EXISTS (
1594
+ SELECT 1 FROM revisions
1595
+ WHERE revisions.id = ${revisionId}
1596
+ AND revisions.collection = ${type}
1597
+ AND revisions.entry_id = ${id}
1598
+ )
1557
1599
  `.execute(this.db);
1558
-
1559
- invalidateCollectionCache(type);
1600
+ return (result.numAffectedRows ?? 0n) > 0n;
1560
1601
  }
1561
1602
 
1562
1603
  /**
@@ -1588,8 +1629,6 @@ export class ContentRepository {
1588
1629
  AND deleted_at IS NULL
1589
1630
  `.execute(this.db);
1590
1631
 
1591
- invalidateCollectionCache(type);
1592
-
1593
1632
  const updated = await this.findById(type, id);
1594
1633
  if (!updated) {
1595
1634
  throw new Error("Content not found");
@@ -1598,35 +1637,6 @@ export class ContentRepository {
1598
1637
  return updated;
1599
1638
  }
1600
1639
 
1601
- /**
1602
- * Sync data columns in the content table from a data object.
1603
- * Used to promote revision data into the content table on publish.
1604
- * Keys starting with _ are revision metadata (e.g. _slug) and are skipped.
1605
- */
1606
- private async syncDataColumns(
1607
- type: string,
1608
- id: string,
1609
- data: Record<string, unknown>,
1610
- ): Promise<void> {
1611
- const tableName = getTableName(type);
1612
- const updates: Record<string, unknown> = {};
1613
-
1614
- for (const [key, value] of Object.entries(data)) {
1615
- if (SYSTEM_COLUMNS.has(key)) continue;
1616
- if (key.startsWith("_")) continue; // revision metadata
1617
- validateIdentifier(key, "content field name");
1618
- updates[key] = serializeValue(value);
1619
- }
1620
-
1621
- if (Object.keys(updates).length === 0) return;
1622
-
1623
- await this.db
1624
- .updateTable(tableName as keyof Database)
1625
- .set(updates)
1626
- .where("id", "=", id)
1627
- .execute();
1628
- }
1629
-
1630
1640
  /**
1631
1641
  * Count content items with a pending schedule.
1632
1642
  * Includes both draft-scheduled (status='scheduled') and published