emdash 0.32.0 → 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 (681) 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 +22 -22
  10. package/dist/api/schemas/index.d.mts +2 -2
  11. package/dist/api/schemas/index.mjs +5 -5
  12. package/dist/{api-DgPbMlng.mjs → api-D2hunekQ.mjs} +247 -45
  13. package/dist/api-D2hunekQ.mjs.map +1 -0
  14. package/dist/{api-tokens-p-iMzvXR.mjs → api-tokens-CSND0i1z.mjs} +2 -2
  15. package/dist/{api-tokens-p-iMzvXR.mjs.map → api-tokens-CSND0i1z.mjs.map} +1 -1
  16. package/dist/{apply-1_6ra7NP.mjs → apply-kwNEJW2l.mjs} +35 -22
  17. package/dist/apply-kwNEJW2l.mjs.map +1 -0
  18. package/dist/astro/index.d.mts +12 -12
  19. package/dist/astro/index.mjs +13 -3
  20. package/dist/astro/index.mjs.map +1 -1
  21. package/dist/astro/middleware/auth.d.mts +10 -10
  22. package/dist/astro/middleware/auth.mjs +8 -8
  23. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  24. package/dist/astro/middleware/redirect.mjs +8 -8
  25. package/dist/astro/middleware/redirect.mjs.map +1 -1
  26. package/dist/astro/middleware/request-context.mjs +4 -4
  27. package/dist/astro/middleware/setup.mjs +1 -1
  28. package/dist/astro/middleware.d.mts +10 -10
  29. package/dist/astro/middleware.d.mts.map +1 -1
  30. package/dist/astro/middleware.mjs +344 -173
  31. package/dist/astro/middleware.mjs.map +1 -1
  32. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  33. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  34. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  35. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  36. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +5 -5
  37. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
  38. package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
  39. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
  40. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +18 -18
  41. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +18 -18
  42. package/dist/astro/routes/api/admin/bylines/index.mjs +18 -18
  43. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +16 -16
  44. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
  46. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -12
  47. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
  48. package/dist/astro/routes/api/admin/comments/index.mjs +12 -12
  49. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
  50. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
  51. package/dist/astro/routes/api/admin/media-usage/repair.mjs +12 -12
  52. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  53. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  54. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +46 -45
  55. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +46 -45
  57. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  58. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +45 -44
  59. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  60. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +5 -5
  61. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +45 -44
  62. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +45 -44
  64. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  65. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +45 -44
  66. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/index.mjs +45 -44
  68. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  70. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +45 -44
  71. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +45 -44
  73. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +45 -44
  75. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +45 -44
  77. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +46 -45
  79. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +45 -44
  81. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +46 -45
  83. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/updates.mjs +45 -44
  85. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +45 -44
  87. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  89. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +45 -44
  90. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
  92. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  93. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
  94. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  95. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  97. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  98. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  99. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  100. package/dist/astro/routes/api/auth/invite/index.mjs +10 -10
  101. package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
  102. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  103. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  104. package/dist/astro/routes/api/auth/magic-link/send.mjs +12 -12
  105. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  106. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  107. package/dist/astro/routes/api/auth/me.mjs +8 -8
  108. package/dist/astro/routes/api/auth/mode.mjs +3 -3
  109. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  110. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  111. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  112. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  113. package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
  114. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  115. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  116. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  117. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  118. package/dist/astro/routes/api/auth/signup/request.mjs +12 -12
  119. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  120. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  121. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +18 -18
  122. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  123. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +15 -15
  124. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  125. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
  126. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  127. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  128. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -13
  129. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +9 -9
  130. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +18 -18
  131. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +18 -18
  132. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  133. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  134. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +9 -9
  135. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +16 -16
  136. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  137. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
  138. package/dist/astro/routes/api/content/_collection_/_id_.mjs +9 -9
  139. package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
  140. package/dist/astro/routes/api/content/_collection_/index.mjs +9 -9
  141. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  142. package/dist/astro/routes/api/dashboard.mjs +9 -9
  143. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  144. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  145. package/dist/astro/routes/api/import/probe.mjs +19 -19
  146. package/dist/astro/routes/api/import/wordpress/analyze.mjs +4 -4
  147. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  148. package/dist/astro/routes/api/import/wordpress/execute.mjs +15 -15
  149. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  150. package/dist/astro/routes/api/import/wordpress/media.mjs +10 -10
  151. package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
  152. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  153. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +12 -12
  154. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  155. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +19 -19
  156. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  157. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +27 -27
  158. package/dist/astro/routes/api/manifest.mjs +5 -5
  159. package/dist/astro/routes/api/mcp.mjs +42 -42
  160. package/dist/astro/routes/api/media/_id_/confirm.mjs +10 -10
  161. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  162. package/dist/astro/routes/api/media/_id_/usage.mjs +14 -14
  163. package/dist/astro/routes/api/media/_id_.mjs +13 -13
  164. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  165. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  166. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  167. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  168. package/dist/astro/routes/api/media/upload-url.mjs +9 -9
  169. package/dist/astro/routes/api/media.mjs +13 -13
  170. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -11
  171. package/dist/astro/routes/api/menus/_name_/items.mjs +11 -11
  172. package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -11
  173. package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -11
  174. package/dist/astro/routes/api/menus/_name_.mjs +11 -11
  175. package/dist/astro/routes/api/menus/index.mjs +11 -11
  176. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  177. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  178. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  179. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  180. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  181. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  182. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  183. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  184. package/dist/astro/routes/api/openapi.json.mjs +36 -5
  185. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  186. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
  187. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -12
  188. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -12
  189. package/dist/astro/routes/api/redirects/_id_.mjs +14 -13
  190. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  191. package/dist/astro/routes/api/redirects/index.mjs +14 -13
  192. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  193. package/dist/astro/routes/api/relations/_id_/index.mjs +18 -18
  194. package/dist/astro/routes/api/relations/_id_/translations.mjs +13 -13
  195. package/dist/astro/routes/api/relations/index.mjs +18 -18
  196. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  197. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
  198. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +45 -44
  199. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  200. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +45 -44
  201. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  202. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +45 -44
  203. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  204. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +45 -44
  205. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  206. package/dist/astro/routes/api/schema/collections/index.mjs +45 -44
  207. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  208. package/dist/astro/routes/api/schema/collections/reorder.d.mts +8 -0
  209. package/dist/astro/routes/api/schema/collections/reorder.d.mts.map +1 -0
  210. package/dist/astro/routes/api/schema/collections/reorder.mjs +66 -0
  211. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -0
  212. package/dist/astro/routes/api/schema/index.mjs +11 -9
  213. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  214. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +45 -44
  215. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  216. package/dist/astro/routes/api/schema/orphans/index.mjs +45 -44
  217. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  218. package/dist/astro/routes/api/search/enable.d.mts +1 -0
  219. package/dist/astro/routes/api/search/enable.d.mts.map +1 -1
  220. package/dist/astro/routes/api/search/enable.mjs +17 -13
  221. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  222. package/dist/astro/routes/api/search/index.mjs +11 -11
  223. package/dist/astro/routes/api/search/rebuild.mjs +13 -13
  224. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  225. package/dist/astro/routes/api/search/stats.mjs +7 -7
  226. package/dist/astro/routes/api/search/suggest.mjs +11 -11
  227. package/dist/astro/routes/api/sections/_slug_.mjs +11 -11
  228. package/dist/astro/routes/api/sections/index.mjs +11 -11
  229. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  230. package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -6
  231. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  232. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  233. package/dist/astro/routes/api/settings/email.mjs +5 -5
  234. package/dist/astro/routes/api/settings.mjs +16 -16
  235. package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
  236. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  237. package/dist/astro/routes/api/setup/dev-bypass.mjs +30 -30
  238. package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
  239. package/dist/astro/routes/api/setup/index.mjs +32 -32
  240. package/dist/astro/routes/api/setup/status.mjs +4 -4
  241. package/dist/astro/routes/api/snapshot.mjs +9 -9
  242. package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts +8 -0
  243. package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -0
  244. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +43 -0
  245. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -0
  246. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -16
  247. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -16
  248. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -16
  249. package/dist/astro/routes/api/taxonomies/index.mjs +16 -16
  250. package/dist/astro/routes/api/themes/preview.mjs +7 -7
  251. package/dist/astro/routes/api/typegen.mjs +5 -5
  252. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  253. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  254. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  255. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  256. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -11
  257. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -11
  258. package/dist/astro/routes/api/widget-areas/_name_.mjs +6 -6
  259. package/dist/astro/routes/api/widget-areas/index.mjs +11 -11
  260. package/dist/astro/routes/api/widget-components.mjs +3 -3
  261. package/dist/astro/routes/robots.txt.mjs +9 -9
  262. package/dist/astro/routes/sitemap-_collection_.xml.mjs +12 -12
  263. package/dist/astro/routes/sitemap.xml.mjs +10 -10
  264. package/dist/astro/types.d.mts +19 -13
  265. package/dist/astro/types.d.mts.map +1 -1
  266. package/dist/auth/providers/github.d.mts +1 -1
  267. package/dist/auth/providers/google.d.mts +1 -1
  268. package/dist/{authorize-R5iYYrpa.mjs → authorize-qRhWQnel.mjs} +2 -2
  269. package/dist/{authorize-R5iYYrpa.mjs.map → authorize-qRhWQnel.mjs.map} +1 -1
  270. package/dist/{backup-LpQ1V_sR.mjs → backup-CtA6LDNw.mjs} +5 -5
  271. package/dist/{backup-LpQ1V_sR.mjs.map → backup-CtA6LDNw.mjs.map} +1 -1
  272. package/dist/{byline-C5TAqs8N.mjs → byline-Cp6csL84.mjs} +9 -9
  273. package/dist/{byline-C5TAqs8N.mjs.map → byline-Cp6csL84.mjs.map} +1 -1
  274. package/dist/{byline-fields-T9ZLZMxJ.mjs → byline-fields-CNc0Yq5i.mjs} +2 -2
  275. package/dist/{byline-fields-T9ZLZMxJ.mjs.map → byline-fields-CNc0Yq5i.mjs.map} +1 -1
  276. package/dist/{byline-registry-BCuOp4UF.mjs → byline-registry-ZkPKqEwC.mjs} +4 -4
  277. package/dist/{byline-registry-BCuOp4UF.mjs.map → byline-registry-ZkPKqEwC.mjs.map} +1 -1
  278. package/dist/{bylines-B8-WGdja.mjs → bylines-CEj5CdT4.mjs} +7 -7
  279. package/dist/{bylines-B8-WGdja.mjs.map → bylines-CEj5CdT4.mjs.map} +1 -1
  280. package/dist/{bylines-DGuqBLjV.mjs → bylines-cf-C9lmF.mjs} +4 -4
  281. package/dist/{bylines-DGuqBLjV.mjs.map → bylines-cf-C9lmF.mjs.map} +1 -1
  282. package/dist/cache-C9FptTFR.mjs +108 -0
  283. package/dist/cache-C9FptTFR.mjs.map +1 -0
  284. package/dist/{challenge-store-BFzgFRog.mjs → challenge-store-D9VNKELo.mjs} +1 -1
  285. package/dist/{challenge-store-BFzgFRog.mjs.map → challenge-store-D9VNKELo.mjs.map} +1 -1
  286. package/dist/{chunks-D5dlPeRb.mjs → chunks-DbYzib_k.mjs} +2 -2
  287. package/dist/{chunks-D5dlPeRb.mjs.map → chunks-DbYzib_k.mjs.map} +1 -1
  288. package/dist/cli/index.mjs +40 -32
  289. package/dist/cli/index.mjs.map +1 -1
  290. package/dist/client/cf-access.d.mts +1 -1
  291. package/dist/client/index.d.mts +1 -1
  292. package/dist/client/index.mjs +2 -2
  293. package/dist/{comment-DnTxxVHv.mjs → comment-BIkJ6Fil.mjs} +3 -3
  294. package/dist/{comment-DnTxxVHv.mjs.map → comment-BIkJ6Fil.mjs.map} +1 -1
  295. package/dist/{comment-reaction-BUlUz2bh.mjs → comment-reaction-D-laEceb.mjs} +2 -2
  296. package/dist/{comment-reaction-BUlUz2bh.mjs.map → comment-reaction-D-laEceb.mjs.map} +1 -1
  297. package/dist/{comments-QPKgK3nk.mjs → comments-0_w6KChA.mjs} +3 -3
  298. package/dist/{comments-QPKgK3nk.mjs.map → comments-0_w6KChA.mjs.map} +1 -1
  299. package/dist/{components-DZkL4Fx0.mjs → components-BPxrRjpE.mjs} +1 -1
  300. package/dist/{components-DZkL4Fx0.mjs.map → components-BPxrRjpE.mjs.map} +1 -1
  301. package/dist/{content-CpfKV9QE.mjs → content-CJ94NEx5.mjs} +165 -112
  302. package/dist/content-CJ94NEx5.mjs.map +1 -0
  303. package/dist/{content-refresh-DgqUBeTv.mjs → content-refresh-Xw7aKmou.mjs} +6 -6
  304. package/dist/{content-refresh-DgqUBeTv.mjs.map → content-refresh-Xw7aKmou.mjs.map} +1 -1
  305. package/dist/{context-kO4YZB03.mjs → context-C_1nrqnW.mjs} +14 -14
  306. package/dist/{context-kO4YZB03.mjs.map → context-C_1nrqnW.mjs.map} +1 -1
  307. package/dist/{cron-BlKIMD_e.mjs → cron-DRV-UC4K.mjs} +1 -1
  308. package/dist/{cron-BlKIMD_e.mjs.map → cron-DRV-UC4K.mjs.map} +1 -1
  309. package/dist/{dashboard-DoBwPnON.mjs → dashboard-DINnNVVU.mjs} +5 -5
  310. package/dist/{dashboard-DoBwPnON.mjs.map → dashboard-DINnNVVU.mjs.map} +1 -1
  311. package/dist/db/index.d.mts +3 -3
  312. package/dist/db/index.mjs +2 -2
  313. package/dist/db/index.mjs.map +1 -1
  314. package/dist/db/libsql.d.mts +1 -1
  315. package/dist/db/postgres.d.mts +1 -1
  316. package/dist/db/sqlite.d.mts +1 -1
  317. package/dist/{default-C4v9KP56.mjs → default-BD2FG0xV.mjs} +1 -1
  318. package/dist/{default-C4v9KP56.mjs.map → default-BD2FG0xV.mjs.map} +1 -1
  319. package/dist/deferred-tasks-C-WRCcKo.d.mts +9 -0
  320. package/dist/deferred-tasks-C-WRCcKo.d.mts.map +1 -0
  321. package/dist/{device-flow-DhUsyJU6.mjs → device-flow-CTqd8mud.mjs} +5 -5
  322. package/dist/{device-flow-DhUsyJU6.mjs.map → device-flow-CTqd8mud.mjs.map} +1 -1
  323. package/dist/{dialect-helpers-DFwyWjTM.mjs → dialect-helpers-BSbfaO3F.mjs} +24 -16
  324. package/dist/dialect-helpers-BSbfaO3F.mjs.map +1 -0
  325. package/dist/{email-console-C-9Ng8DM.mjs → email-console-C6WdcWbL.mjs} +1 -1
  326. package/dist/{email-console-C-9Ng8DM.mjs.map → email-console-C6WdcWbL.mjs.map} +1 -1
  327. package/dist/{error-DmmN74gW.mjs → error-oh_9i6bR.mjs} +3 -3
  328. package/dist/{error-DmmN74gW.mjs.map → error-oh_9i6bR.mjs.map} +1 -1
  329. package/dist/{errors-DtEXIQQV.mjs → errors-BucQ8VYz.mjs} +2 -1
  330. package/dist/errors-BucQ8VYz.mjs.map +1 -0
  331. package/dist/{escape-CdW31WsG.mjs → escape-CXps5F_v.mjs} +1 -1
  332. package/dist/{escape-CdW31WsG.mjs.map → escape-CXps5F_v.mjs.map} +1 -1
  333. package/dist/{field-defs-cache-QMVnzTH6.mjs → field-defs-cache-WD82dMQq.mjs} +4 -4
  334. package/dist/{field-defs-cache-QMVnzTH6.mjs.map → field-defs-cache-WD82dMQq.mjs.map} +1 -1
  335. package/dist/{fts-manager-vncsZIJm.mjs → fts-manager-BITakW_R.mjs} +37 -13
  336. package/dist/fts-manager-BITakW_R.mjs.map +1 -0
  337. package/dist/{hash-Cb7U1b5M.mjs → hash-Cg0TXJPV.mjs} +1 -1
  338. package/dist/{hash-Cb7U1b5M.mjs.map → hash-Cg0TXJPV.mjs.map} +1 -1
  339. package/dist/{hreflang-CZbSx6Bg.d.mts → hreflang-BaLCNcDx.d.mts} +2 -2
  340. package/dist/{hreflang-CZbSx6Bg.d.mts.map → hreflang-BaLCNcDx.d.mts.map} +1 -1
  341. package/dist/{hreflang-Bg-zMpkr.mjs → hreflang-BdZuVBhL.mjs} +6 -6
  342. package/dist/{hreflang-Bg-zMpkr.mjs.map → hreflang-BdZuVBhL.mjs.map} +1 -1
  343. package/dist/{import-PKhLeXvn.mjs → import-C-9uqyT3.mjs} +6 -6
  344. package/dist/{import-PKhLeXvn.mjs.map → import-C-9uqyT3.mjs.map} +1 -1
  345. package/dist/{index-j9rTh3cp.d.mts → index-M37iz29I.d.mts} +75 -35
  346. package/dist/index-M37iz29I.d.mts.map +1 -0
  347. package/dist/{index-BeNto_Vs.d.mts → index-MGw47uWq.d.mts} +3 -3
  348. package/dist/{index-BeNto_Vs.d.mts.map → index-MGw47uWq.d.mts.map} +1 -1
  349. package/dist/index.d.mts +19 -19
  350. package/dist/index.mjs +68 -66
  351. package/dist/{load-BwTdWE8B.mjs → load-DV1DZuUJ.mjs} +2 -2
  352. package/dist/{load-BwTdWE8B.mjs.map → load-DV1DZuUJ.mjs.map} +1 -1
  353. package/dist/{loader-C1XOLV5b.mjs → loader-CGugY7Zl.mjs} +29 -15
  354. package/dist/loader-CGugY7Zl.mjs.map +1 -0
  355. package/dist/{manifest-schema-bCq54i7F.mjs → manifest-schema-Da7kj23y.mjs} +1 -1
  356. package/dist/{manifest-schema-bCq54i7F.mjs.map → manifest-schema-Da7kj23y.mjs.map} +1 -1
  357. package/dist/media/index.d.mts +1 -1
  358. package/dist/media/local-runtime.d.mts +12 -12
  359. package/dist/media/local-runtime.mjs +8 -8
  360. package/dist/{media-tQDZEdu7.mjs → media-BP7S-nHT.mjs} +2 -2
  361. package/dist/{media-tQDZEdu7.mjs.map → media-BP7S-nHT.mjs.map} +1 -1
  362. package/dist/{media-DWIzoVFL.mjs → media-OhYL-7Io.mjs} +1 -1
  363. package/dist/{media-DWIzoVFL.mjs.map → media-OhYL-7Io.mjs.map} +1 -1
  364. package/dist/{media-allowlist-B7TPD6aq.mjs → media-allowlist-D-peH1H5.mjs} +1 -1
  365. package/dist/{media-allowlist-B7TPD6aq.mjs.map → media-allowlist-D-peH1H5.mjs.map} +1 -1
  366. package/dist/{media-upload-Bc9Nc5Zf.mjs → media-upload-DtrwU2B0.mjs} +7 -7
  367. package/dist/{media-upload-Bc9Nc5Zf.mjs.map → media-upload-DtrwU2B0.mjs.map} +1 -1
  368. package/dist/{media-url-BCm5vBn6.mjs → media-url-DYs_YLOx.mjs} +1 -1
  369. package/dist/{media-url-BCm5vBn6.mjs.map → media-url-DYs_YLOx.mjs.map} +1 -1
  370. package/dist/{media-usage-DPJcNaAq.mjs → media-usage-BlxfTkN0.mjs} +8 -8
  371. package/dist/{media-usage-DPJcNaAq.mjs.map → media-usage-BlxfTkN0.mjs.map} +1 -1
  372. package/dist/{menus-BxPLFfIc.mjs → menus-BcQWxeXu.mjs} +4 -4
  373. package/dist/{menus-BxPLFfIc.mjs.map → menus-BcQWxeXu.mjs.map} +1 -1
  374. package/dist/{menus-C6qhqP4X.mjs → menus-Y54RDPIN.mjs} +215 -38
  375. package/dist/menus-Y54RDPIN.mjs.map +1 -0
  376. package/dist/{mode-fiXRMfeA.mjs → mode-BWyTBe3I.mjs} +1 -1
  377. package/dist/{mode-fiXRMfeA.mjs.map → mode-BWyTBe3I.mjs.map} +1 -1
  378. package/dist/{oauth-authorization-C9tFinly.mjs → oauth-authorization-ClvktmrL.mjs} +5 -5
  379. package/dist/{oauth-authorization-C9tFinly.mjs.map → oauth-authorization-ClvktmrL.mjs.map} +1 -1
  380. package/dist/{oauth-clients-BwTxE1aE.mjs → oauth-clients-8ao-U66l.mjs} +1 -1
  381. package/dist/{oauth-clients-BwTxE1aE.mjs.map → oauth-clients-8ao-U66l.mjs.map} +1 -1
  382. package/dist/{oauth-state-store-DaRUwPWO.mjs → oauth-state-store-B1ofdTiQ.mjs} +1 -1
  383. package/dist/{oauth-state-store-DaRUwPWO.mjs.map → oauth-state-store-B1ofdTiQ.mjs.map} +1 -1
  384. package/dist/{oauth-user-lookup-CzuzOSlF.mjs → oauth-user-lookup-CscEuIiR.mjs} +1 -1
  385. package/dist/{oauth-user-lookup-CzuzOSlF.mjs.map → oauth-user-lookup-CscEuIiR.mjs.map} +1 -1
  386. package/dist/object-cache/memory.d.mts +1 -1
  387. package/dist/{object-cache-Bok5j2ae.mjs → object-cache-71tPfV4A.mjs} +106 -5
  388. package/dist/object-cache-71tPfV4A.mjs.map +1 -0
  389. package/dist/{options-aeIs8WFu.d.mts → options-CA4eVX6P.d.mts} +3 -3
  390. package/dist/{options-aeIs8WFu.d.mts.map → options-CA4eVX6P.d.mts.map} +1 -1
  391. package/dist/{options-BlmBHTvX.mjs → options-CBXIHUoT.mjs} +1 -1
  392. package/dist/{options-BlmBHTvX.mjs.map → options-CBXIHUoT.mjs.map} +1 -1
  393. package/dist/page/index.d.mts +2 -2
  394. package/dist/{parse-BL49yb9D.mjs → parse-CJKNuewM.mjs} +2 -2
  395. package/dist/{parse-BL49yb9D.mjs.map → parse-CJKNuewM.mjs.map} +1 -1
  396. package/dist/{passkey-config-KMhgFjdQ.mjs → passkey-config-D-zrzMJI.mjs} +1 -1
  397. package/dist/{passkey-config-KMhgFjdQ.mjs.map → passkey-config-D-zrzMJI.mjs.map} +1 -1
  398. package/dist/{placeholder-Dxo5Zt58.d.mts → placeholder-DaeNS-VG.d.mts} +1 -1
  399. package/dist/{placeholder-Dxo5Zt58.d.mts.map → placeholder-DaeNS-VG.d.mts.map} +1 -1
  400. package/dist/plugin-types.d.mts +1 -1
  401. package/dist/plugin-utils.d.mts +10 -10
  402. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  403. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  404. package/dist/{portable-text-CNahFfj6.mjs → portable-text-B_kqBmXB.mjs} +1 -1
  405. package/dist/{portable-text-CNahFfj6.mjs.map → portable-text-B_kqBmXB.mjs.map} +1 -1
  406. package/dist/{preview-D4Jnbfx7.mjs → preview-BU6PaLpM.mjs} +2 -2
  407. package/dist/{preview-D4Jnbfx7.mjs.map → preview-BU6PaLpM.mjs.map} +1 -1
  408. package/dist/{public-url-DSGTnJFw.mjs → public-url-Ox9oOlgp.mjs} +14 -3
  409. package/dist/public-url-Ox9oOlgp.mjs.map +1 -0
  410. package/dist/{query-DCiXI7OZ.mjs → query-C5w7PsRQ.mjs} +20 -41
  411. package/dist/query-C5w7PsRQ.mjs.map +1 -0
  412. package/dist/{query-1xOcEy18.mjs → query-rC9HKv1N.mjs} +4 -4
  413. package/dist/{query-1xOcEy18.mjs.map → query-rC9HKv1N.mjs.map} +1 -1
  414. package/dist/{rate-limit-Vkp9gQ1Y.mjs → rate-limit-kug6q99V.mjs} +2 -2
  415. package/dist/{rate-limit-Vkp9gQ1Y.mjs.map → rate-limit-kug6q99V.mjs.map} +1 -1
  416. package/dist/{redirect-BJ6d1yHh.mjs → redirect-DIJxXKOG.mjs} +3 -3
  417. package/dist/{redirect-BJ6d1yHh.mjs.map → redirect-DIJxXKOG.mjs.map} +1 -1
  418. package/dist/{redirect-CDgfv9vh.mjs → redirect-Egf2R9yP.mjs} +1 -1
  419. package/dist/{redirect-CDgfv9vh.mjs.map → redirect-Egf2R9yP.mjs.map} +1 -1
  420. package/dist/{redirects-Cwkq2H-G.mjs → redirects-Bzm812bY.mjs} +5 -5
  421. package/dist/{redirects-Cwkq2H-G.mjs.map → redirects-Bzm812bY.mjs.map} +1 -1
  422. package/dist/{redirects-BOn2DIUs.mjs → redirects-G8wAhWAf.mjs} +20 -6
  423. package/dist/redirects-G8wAhWAf.mjs.map +1 -0
  424. package/dist/{registry-BP1JK2xh.mjs → registry-Dbodb4Uo.mjs} +59 -14
  425. package/dist/registry-Dbodb4Uo.mjs.map +1 -0
  426. package/dist/{relation-DJ5DZh7B.mjs → relation-Cbe3Sd3m.mjs} +3 -3
  427. package/dist/{relation-DJ5DZh7B.mjs.map → relation-Cbe3Sd3m.mjs.map} +1 -1
  428. package/dist/{relations-C4duJnwI.mjs → relations-Bw_E1TXo.mjs} +3 -3
  429. package/dist/{relations-C4duJnwI.mjs.map → relations-Bw_E1TXo.mjs.map} +1 -1
  430. package/dist/{relations-DHFQGX0h.d.mts → relations-G2ta7GIl.d.mts} +36 -9
  431. package/dist/relations-G2ta7GIl.d.mts.map +1 -0
  432. package/dist/{relations-DpTjftCl.mjs → relations-qHwpUe66.mjs} +5 -5
  433. package/dist/{relations-DpTjftCl.mjs.map → relations-qHwpUe66.mjs.map} +1 -1
  434. package/dist/request-context.d.mts +3 -0
  435. package/dist/request-context.d.mts.map +1 -1
  436. package/dist/request-context.mjs.map +1 -1
  437. package/dist/{request-meta-DzXYYI-n.mjs → request-meta-Df-jFbAd.mjs} +2 -2
  438. package/dist/{request-meta-DzXYYI-n.mjs.map → request-meta-Df-jFbAd.mjs.map} +1 -1
  439. package/dist/{resolve-BUvFE0Lr.mjs → resolve-DZzG4HqM.mjs} +1 -1
  440. package/dist/{resolve-BUvFE0Lr.mjs.map → resolve-DZzG4HqM.mjs.map} +1 -1
  441. package/dist/{runner-BsI18UgP.mjs → runner-BFTrkYhu.mjs} +482 -216
  442. package/dist/runner-BFTrkYhu.mjs.map +1 -0
  443. package/dist/{runner-CHdkERbt.d.mts → runner-BaADli8l.d.mts} +2 -2
  444. package/dist/{runner-CHdkERbt.d.mts.map → runner-BaADli8l.d.mts.map} +1 -1
  445. package/dist/runtime.d.mts +11 -11
  446. package/dist/runtime.mjs +3 -3
  447. package/dist/{schema-eqZhkR0S.mjs → schema-CiQXr6_F.mjs} +3 -3
  448. package/dist/{schema-eqZhkR0S.mjs.map → schema-CiQXr6_F.mjs.map} +1 -1
  449. package/dist/{scopes-Be2d8bSb.mjs → scopes-CNJVT5i5.mjs} +3 -3
  450. package/dist/{scopes-Be2d8bSb.mjs.map → scopes-CNJVT5i5.mjs.map} +1 -1
  451. package/dist/{search-CeO678cp.mjs → search-FZhx5dDU.mjs} +6 -6
  452. package/dist/{search-CeO678cp.mjs.map → search-FZhx5dDU.mjs.map} +1 -1
  453. package/dist/{secrets-870d-7yA.mjs → secrets-DLd8RXee.mjs} +4 -4
  454. package/dist/{secrets-870d-7yA.mjs.map → secrets-DLd8RXee.mjs.map} +1 -1
  455. package/dist/{sections-DSuEfirn.mjs → sections-BrIrMUCn.mjs} +3 -3
  456. package/dist/{sections-DSuEfirn.mjs.map → sections-BrIrMUCn.mjs.map} +1 -1
  457. package/dist/seed/index.d.mts +2 -2
  458. package/dist/seed/index.mjs +24 -24
  459. package/dist/seo/index.d.mts +3 -3
  460. package/dist/seo/index.mjs +17 -17
  461. package/dist/{seo-C3GDfT0V.mjs → seo-CobNfOvb.mjs} +2 -2
  462. package/dist/{seo-C3GDfT0V.mjs.map → seo-CobNfOvb.mjs.map} +1 -1
  463. package/dist/{seo-BAPKiED8.mjs → seo-DTHRntNC.mjs} +3 -3
  464. package/dist/{seo-BAPKiED8.mjs.map → seo-DTHRntNC.mjs.map} +1 -1
  465. package/dist/{service-DyFT-k-R.mjs → service-B-pYGPgR.mjs} +4 -4
  466. package/dist/{service-DyFT-k-R.mjs.map → service-B-pYGPgR.mjs.map} +1 -1
  467. package/dist/{session-user-BrK2zz7S.mjs → session-user-BvM9-zNl.mjs} +2 -2
  468. package/dist/{session-user-BrK2zz7S.mjs.map → session-user-BvM9-zNl.mjs.map} +1 -1
  469. package/dist/{settings-CREKyj8I.mjs → settings-DPHau-WH.mjs} +3 -3
  470. package/dist/{settings-CREKyj8I.mjs.map → settings-DPHau-WH.mjs.map} +1 -1
  471. package/dist/{settings-DgKouY2S.mjs → settings-kJhGiQ4z.mjs} +7 -7
  472. package/dist/{settings-DgKouY2S.mjs.map → settings-kJhGiQ4z.mjs.map} +1 -1
  473. package/dist/{setup-complete-L7bMK2VI.mjs → setup-complete-u50Qm8rY.mjs} +2 -2
  474. package/dist/{setup-complete-L7bMK2VI.mjs.map → setup-complete-u50Qm8rY.mjs.map} +1 -1
  475. package/dist/{setup-nonce-Ct5tjWcq.mjs → setup-nonce-DCjiiOD2.mjs} +1 -1
  476. package/dist/{setup-nonce-Ct5tjWcq.mjs.map → setup-nonce-DCjiiOD2.mjs.map} +1 -1
  477. package/dist/{single-flight-cache-C2exrGAi.mjs → single-flight-cache-DW3w11Pu.mjs} +1 -1
  478. package/dist/{single-flight-cache-C2exrGAi.mjs.map → single-flight-cache-DW3w11Pu.mjs.map} +1 -1
  479. package/dist/site-url-I-lJ5kma.mjs +16 -0
  480. package/dist/site-url-I-lJ5kma.mjs.map +1 -0
  481. package/dist/{snapshot-BdpUJKD-.mjs → snapshot-I_fjLDaD.mjs} +2 -2
  482. package/dist/{snapshot-BdpUJKD-.mjs.map → snapshot-I_fjLDaD.mjs.map} +1 -1
  483. package/dist/{ssrf-CviKqWmq.mjs → ssrf-CTa6v21i.mjs} +1 -1
  484. package/dist/{ssrf-CviKqWmq.mjs.map → ssrf-CTa6v21i.mjs.map} +1 -1
  485. package/dist/{state-xxv6ZTMv.mjs → state-CQvoefYP.mjs} +1 -1
  486. package/dist/{state-xxv6ZTMv.mjs.map → state-CQvoefYP.mjs.map} +1 -1
  487. package/dist/{status-COfycGIU.mjs → status-CIsmlC1E.mjs} +1 -1
  488. package/dist/{status-COfycGIU.mjs.map → status-CIsmlC1E.mjs.map} +1 -1
  489. package/dist/storage/local.d.mts +1 -1
  490. package/dist/storage/local.mjs +1 -1
  491. package/dist/storage/s3.d.mts +1 -1
  492. package/dist/storage/s3.mjs +1 -1
  493. package/dist/{taxonomies-Dbdki3Un.mjs → taxonomies-CKuaZER5.mjs} +85 -5
  494. package/dist/taxonomies-CKuaZER5.mjs.map +1 -0
  495. package/dist/{taxonomies-B61CRSha.mjs → taxonomies-CLN1N92E.mjs} +16 -17
  496. package/dist/taxonomies-CLN1N92E.mjs.map +1 -0
  497. package/dist/{taxonomy-DvwWAPvA.mjs → taxonomy-pOrB2kZe.mjs} +142 -15
  498. package/dist/taxonomy-pOrB2kZe.mjs.map +1 -0
  499. package/dist/{tokens-DVltpO2D.mjs → tokens-DagaJGK8.mjs} +1 -1
  500. package/dist/{tokens-DVltpO2D.mjs.map → tokens-DagaJGK8.mjs.map} +1 -1
  501. package/dist/{transaction-D0FOsb3X.mjs → transaction-NQj4VJ7Z.mjs} +1 -1
  502. package/dist/{transaction-D0FOsb3X.mjs.map → transaction-NQj4VJ7Z.mjs.map} +1 -1
  503. package/dist/{transport-DokJOScS.d.mts → transport-CAwTaTp_.d.mts} +1 -1
  504. package/dist/{transport-DokJOScS.d.mts.map → transport-CAwTaTp_.d.mts.map} +1 -1
  505. package/dist/{transport-BWQo0Foy.mjs → transport-DVsa5YYo.mjs} +1 -1
  506. package/dist/{transport-BWQo0Foy.mjs.map → transport-DVsa5YYo.mjs.map} +1 -1
  507. package/dist/{trusted-proxy-CwjQj0YG.mjs → trusted-proxy-D20_7fyX.mjs} +1 -1
  508. package/dist/{trusted-proxy-CwjQj0YG.mjs.map → trusted-proxy-D20_7fyX.mjs.map} +1 -1
  509. package/dist/{types-DqZVPILm.d.mts → types-BGWPMiBO.d.mts} +2 -2
  510. package/dist/{types-DqZVPILm.d.mts.map → types-BGWPMiBO.d.mts.map} +1 -1
  511. package/dist/{types-DsAMyD_o.d.mts → types-BK6U01Ro.d.mts} +1 -1
  512. package/dist/{types-DsAMyD_o.d.mts.map → types-BK6U01Ro.d.mts.map} +1 -1
  513. package/dist/{types-BD40g7zz.mjs → types-BjxTKxrZ.mjs} +1 -1
  514. package/dist/{types-BD40g7zz.mjs.map → types-BjxTKxrZ.mjs.map} +1 -1
  515. package/dist/{types-jISEalTX.d.mts → types-BnFP1M3J.d.mts} +22 -1
  516. package/dist/types-BnFP1M3J.d.mts.map +1 -0
  517. package/dist/{types-Dr2GLlwu.d.mts → types-C8oz_ayJ.d.mts} +1 -1
  518. package/dist/{types-Dr2GLlwu.d.mts.map → types-C8oz_ayJ.d.mts.map} +1 -1
  519. package/dist/{types-C9P3ysxq.d.mts → types-CbUcuxxc.d.mts} +1 -1
  520. package/dist/{types-C9P3ysxq.d.mts.map → types-CbUcuxxc.d.mts.map} +1 -1
  521. package/dist/{types-XrQQ-Aex.mjs → types-Cd8iuS1J.mjs} +10 -3
  522. package/dist/{types-XrQQ-Aex.mjs.map → types-Cd8iuS1J.mjs.map} +1 -1
  523. package/dist/types-CtzytVXn.mjs +18 -0
  524. package/dist/types-CtzytVXn.mjs.map +1 -0
  525. package/dist/{types-BQY7VYw6.d.mts → types-Cz8hNch2.d.mts} +5 -5
  526. package/dist/{types-BQY7VYw6.d.mts.map → types-Cz8hNch2.d.mts.map} +1 -1
  527. package/dist/{types-CcSZCcF1.d.mts → types-DLG4IFEQ.d.mts} +1 -1
  528. package/dist/{types-CcSZCcF1.d.mts.map → types-DLG4IFEQ.d.mts.map} +1 -1
  529. package/dist/{types-84Bque3-.d.mts → types-Dc4ntQjQ.d.mts} +10 -1
  530. package/dist/types-Dc4ntQjQ.d.mts.map +1 -0
  531. package/dist/{types-DQLZ58GV.d.mts → types-LoagAGzH.d.mts} +1 -1
  532. package/dist/{types-DQLZ58GV.d.mts.map → types-LoagAGzH.d.mts.map} +1 -1
  533. package/dist/{types-o7xo7VgH.mjs → types-NBI3rF-_.mjs} +3 -2
  534. package/dist/types-NBI3rF-_.mjs.map +1 -0
  535. package/dist/{upload-attempts-C5yd6Gae.mjs → upload-attempts-D8QAFLUJ.mjs} +1 -1
  536. package/dist/{upload-attempts-C5yd6Gae.mjs.map → upload-attempts-D8QAFLUJ.mjs.map} +1 -1
  537. package/dist/{user-BAumEmpA.mjs → user-DBrq4UVq.mjs} +3 -3
  538. package/dist/{user-BAumEmpA.mjs.map → user-DBrq4UVq.mjs.map} +1 -1
  539. package/dist/{utils-BbUgmeZG.mjs → utils-hLzi_2Fn.mjs} +2 -2
  540. package/dist/{utils-BbUgmeZG.mjs.map → utils-hLzi_2Fn.mjs.map} +1 -1
  541. package/dist/{validate-VPnKoIzW.mjs → validate-BpwoDOgt.mjs} +25 -2
  542. package/dist/validate-BpwoDOgt.mjs.map +1 -0
  543. package/dist/{validate-CdYcY-Ln.d.mts → validate-C3oSmA7F.d.mts} +15 -5
  544. package/dist/validate-C3oSmA7F.d.mts.map +1 -0
  545. package/dist/{validate-Bs_wT2ul.mjs → validate-mKo3RxBM.mjs} +3 -3
  546. package/dist/{validate-Bs_wT2ul.mjs.map → validate-mKo3RxBM.mjs.map} +1 -1
  547. package/dist/{validation-BngR0nit.mjs → validation-BgpucsvF.mjs} +10 -10
  548. package/dist/{validation-BngR0nit.mjs.map → validation-BgpucsvF.mjs.map} +1 -1
  549. package/dist/version-C4PnpmoV.mjs +7 -0
  550. package/dist/{version-Bdfb34kk.mjs.map → version-C4PnpmoV.mjs.map} +1 -1
  551. package/dist/{widgets-L-VndTKD.mjs → widgets-CJJtkiKh.mjs} +3 -3
  552. package/dist/{widgets-L-VndTKD.mjs.map → widgets-CJJtkiKh.mjs.map} +1 -1
  553. package/dist/{wxr-taxonomies-BexjtNid.mjs → wxr-taxonomies-9PPSy8X6.mjs} +4 -4
  554. package/dist/{wxr-taxonomies-BexjtNid.mjs.map → wxr-taxonomies-9PPSy8X6.mjs.map} +1 -1
  555. package/dist/{wxr-taxonomies-DueaLFd9.d.mts → wxr-taxonomies-Bkpp_2tK.d.mts} +1 -1
  556. package/dist/{wxr-taxonomies-DueaLFd9.d.mts.map → wxr-taxonomies-Bkpp_2tK.d.mts.map} +1 -1
  557. package/dist/{zod-generator-DMzfga3g.mjs → zod-generator-CG64Hnbh.mjs} +3 -3
  558. package/dist/{zod-generator-DMzfga3g.mjs.map → zod-generator-CG64Hnbh.mjs.map} +1 -1
  559. package/package.json +11 -8
  560. package/src/after.ts +6 -1
  561. package/src/api/errors.ts +1 -0
  562. package/src/api/handlers/content.ts +45 -4
  563. package/src/api/handlers/marketplace.ts +14 -0
  564. package/src/api/handlers/registry.ts +14 -0
  565. package/src/api/handlers/revision.ts +19 -5
  566. package/src/api/handlers/schema.ts +37 -0
  567. package/src/api/handlers/snapshot.ts +1 -1
  568. package/src/api/handlers/taxonomies.ts +101 -1
  569. package/src/api/openapi/document.ts +48 -0
  570. package/src/api/public-url.ts +14 -2
  571. package/src/api/schemas/schema.ts +13 -0
  572. package/src/api/schemas/search.ts +2 -0
  573. package/src/api/schemas/taxonomies.ts +18 -0
  574. package/src/api/site-url.ts +16 -6
  575. package/src/astro/integration/routes.ts +14 -0
  576. package/src/astro/integration/runtime.ts +13 -0
  577. package/src/astro/integration/virtual-modules.ts +2 -0
  578. package/src/astro/middleware/redirect.ts +2 -10
  579. package/src/astro/middleware/scoped-db.ts +35 -4
  580. package/src/astro/middleware.ts +56 -22
  581. package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -1
  582. package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +2 -2
  583. package/src/astro/routes/api/auth/invite/index.ts +2 -2
  584. package/src/astro/routes/api/auth/magic-link/send.ts +2 -2
  585. package/src/astro/routes/api/auth/signup/request.ts +2 -2
  586. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +1 -1
  587. package/src/astro/routes/api/schema/collections/reorder.ts +31 -0
  588. package/src/astro/routes/api/schema/index.ts +2 -0
  589. package/src/astro/routes/api/search/enable.ts +5 -1
  590. package/src/astro/routes/api/search/rebuild.ts +6 -1
  591. package/src/astro/routes/api/taxonomies/[name]/reorder.ts +41 -0
  592. package/src/astro/types.ts +6 -0
  593. package/src/cleanup.ts +31 -26
  594. package/src/cli/commands/dev.ts +13 -3
  595. package/src/cli/commands/export-seed.ts +2 -0
  596. package/src/cli/index.ts +1 -1
  597. package/src/components/CommentForm.astro +1 -1
  598. package/src/components/Comments.astro +1 -1
  599. package/src/components/InlinePortableTextEditor.tsx +171 -31
  600. package/src/components/OrderedList.astro +14 -0
  601. package/src/components/PortableText.astro +26 -4
  602. package/src/components/index.ts +12 -1
  603. package/src/components/ordered-list.ts +549 -0
  604. package/src/content/converters/numbered-list.ts +148 -0
  605. package/src/content/converters/portable-text-to-prosemirror.ts +59 -9
  606. package/src/content/converters/prosemirror-to-portable-text.ts +23 -12
  607. package/src/content/converters/types.ts +2 -0
  608. package/src/content/portable-text-lists.ts +205 -0
  609. package/src/database/dialect-helpers.ts +3 -22
  610. package/src/database/migrations/055_content_translation_group_locale_index.ts +67 -0
  611. package/src/database/migrations/056_taxonomy_term_sort_order.ts +189 -0
  612. package/src/database/migrations/057_collection_hidden.ts +24 -0
  613. package/src/database/migrations/058_collection_sort_order.ts +20 -0
  614. package/src/database/migrations/059_revision_prune_queue.ts +36 -0
  615. package/src/database/migrations/runner.ts +10 -0
  616. package/src/database/repositories/content.ts +191 -178
  617. package/src/database/repositories/revision.ts +82 -17
  618. package/src/database/repositories/taxonomy.ts +202 -7
  619. package/src/database/repositories/types.ts +7 -0
  620. package/src/database/types.ts +13 -1
  621. package/src/database/validate.ts +39 -0
  622. package/src/db/adapters.ts +8 -0
  623. package/src/deferred-tasks.ts +71 -0
  624. package/src/emdash-runtime.ts +268 -92
  625. package/src/index.ts +2 -0
  626. package/src/loader.ts +46 -24
  627. package/src/media/usage/gc.ts +50 -0
  628. package/src/object-cache/index.ts +160 -3
  629. package/src/plugins/routes.ts +34 -0
  630. package/src/plugins/storage-indexes.ts +50 -11
  631. package/src/query.ts +21 -42
  632. package/src/redirects/cache.ts +79 -19
  633. package/src/request-context.ts +3 -0
  634. package/src/scheduled-publish.ts +6 -1
  635. package/src/schema/registry.ts +95 -3
  636. package/src/schema/types.ts +24 -0
  637. package/src/search/fts-manager.ts +50 -10
  638. package/src/search/index.ts +2 -0
  639. package/src/search/types.ts +6 -0
  640. package/src/seed/apply.ts +22 -2
  641. package/src/seed/types.ts +10 -0
  642. package/src/taxonomies/index.ts +11 -7
  643. package/src/taxonomies/term-counts.ts +2 -4
  644. package/src/ui-comments.ts +19 -0
  645. package/src/ui.ts +11 -3
  646. package/src/virtual-modules.d.ts +8 -0
  647. package/dist/adapters-C0ONzkUP.d.mts.map +0 -1
  648. package/dist/after-B1IIdH3Y.mjs +0 -29
  649. package/dist/after-B1IIdH3Y.mjs.map +0 -1
  650. package/dist/api-DgPbMlng.mjs.map +0 -1
  651. package/dist/apply-1_6ra7NP.mjs.map +0 -1
  652. package/dist/cache-B26cufFd.mjs +0 -65
  653. package/dist/cache-B26cufFd.mjs.map +0 -1
  654. package/dist/content-CpfKV9QE.mjs.map +0 -1
  655. package/dist/dialect-helpers-DFwyWjTM.mjs.map +0 -1
  656. package/dist/errors-DtEXIQQV.mjs.map +0 -1
  657. package/dist/fts-manager-vncsZIJm.mjs.map +0 -1
  658. package/dist/index-j9rTh3cp.d.mts.map +0 -1
  659. package/dist/loader-C1XOLV5b.mjs.map +0 -1
  660. package/dist/menus-C6qhqP4X.mjs.map +0 -1
  661. package/dist/object-cache-Bok5j2ae.mjs.map +0 -1
  662. package/dist/public-url-DSGTnJFw.mjs.map +0 -1
  663. package/dist/query-DCiXI7OZ.mjs.map +0 -1
  664. package/dist/redirects-BOn2DIUs.mjs.map +0 -1
  665. package/dist/registry-BP1JK2xh.mjs.map +0 -1
  666. package/dist/relations-DHFQGX0h.d.mts.map +0 -1
  667. package/dist/runner-BsI18UgP.mjs.map +0 -1
  668. package/dist/site-url-8N3kSyVZ.mjs +0 -13
  669. package/dist/site-url-8N3kSyVZ.mjs.map +0 -1
  670. package/dist/taxonomies-B61CRSha.mjs.map +0 -1
  671. package/dist/taxonomies-Dbdki3Un.mjs.map +0 -1
  672. package/dist/taxonomy-DvwWAPvA.mjs.map +0 -1
  673. package/dist/types-84Bque3-.d.mts.map +0 -1
  674. package/dist/types-jISEalTX.d.mts.map +0 -1
  675. package/dist/types-o7xo7VgH.mjs.map +0 -1
  676. package/dist/validate-CdYcY-Ln.d.mts.map +0 -1
  677. package/dist/validate-VPnKoIzW.mjs.map +0 -1
  678. package/dist/version-Bdfb34kk.mjs +0 -7
  679. /package/dist/{api-tokens-CEsW_jCg.mjs → api-tokens-Dai9dND0.mjs} +0 -0
  680. /package/dist/{ssrf-BB__xfNM.mjs → ssrf-Cj568Dgs.mjs} +0 -0
  681. /package/dist/{types-CK0LxPUQ.mjs → types-DKuWPYV5.mjs} +0 -0
package/src/query.ts CHANGED
@@ -29,6 +29,7 @@ import { getFallbackChain, getI18nConfig, isI18nEnabled } from "./i18n/config.js
29
29
  import {
30
30
  CURSOR_RAW_VALUES,
31
31
  FOLDED_BYLINES,
32
+ FOLDED_BYLINES_EXIST,
32
33
  FOLDED_TERMS,
33
34
  type WhereRange,
34
35
  type WhereValue,
@@ -310,17 +311,6 @@ function dataStr(data: Record<string, unknown>, key: string, fallback = ""): str
310
311
  return typeof val === "string" ? val : fallback;
311
312
  }
312
313
 
313
- /** Safely read a date-like field from a Record */
314
- function dataDate(data: Record<string, unknown>, key: string): Date | undefined {
315
- const val = data[key];
316
- if (val instanceof Date) {
317
- return Number.isNaN(val.getTime()) ? undefined : val;
318
- }
319
- if (typeof val !== "string" && typeof val !== "number") return undefined;
320
- const date = new Date(val);
321
- return Number.isNaN(date.getTime()) ? undefined : date;
322
- }
323
-
324
314
  /** Type guard for Record<string, unknown> */
325
315
  function isRecord(value: unknown): value is Record<string, unknown> {
326
316
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -828,23 +818,9 @@ export async function getEmDashEntry<T extends string, D = InferCollectionData<T
828
818
  };
829
819
  }
830
820
 
831
- /** Check if an entry is publicly visible (published or scheduled past its time) */
821
+ /** Check if an entry has completed publication. */
832
822
  function isVisible(entry: ContentEntry<D>): boolean {
833
- const data = entryData(entry);
834
- const status = dataStr(data, "status");
835
- const scheduledAt = dataDate(data, "scheduledAt");
836
- const isPublished = status === "published";
837
- const isScheduledAndReady =
838
- status === "scheduled" && scheduledAt !== undefined && scheduledAt.getTime() <= Date.now();
839
- return isPublished || !!isScheduledAndReady;
840
- }
841
-
842
- /** True when an entry is scheduled to become visible at a future time. */
843
- function isPendingScheduled(entry: ContentEntry<D>): boolean {
844
- const data = entryData(entry);
845
- if (dataStr(data, "status") !== "scheduled") return false;
846
- const scheduledAt = dataDate(data, "scheduledAt");
847
- return scheduledAt !== undefined && scheduledAt.getTime() > Date.now();
823
+ return dataStr(entryData(entry), "status") === "published";
848
824
  }
849
825
 
850
826
  // Build the fallback chain: [requestedLocale, fallback1, ..., defaultLocale]
@@ -954,11 +930,6 @@ export async function getEmDashEntry<T extends string, D = InferCollectionData<T
954
930
  // hydration) is wrapped in the distributed L2 cache, keyed by the requested
955
931
  // locale. Preview/edit requests took the `serveDrafts` branch above and
956
932
  // never reach here; the object cache additionally bypasses them.
957
- // A scheduled entry becomes visible on a future clock tick, not on a write,
958
- // so an L2 snapshot taken before its time would keep it hidden past go-live
959
- // (until the publish sweep bumps the epoch or the TTL lapses). Mark such a
960
- // resolution time-sensitive and skip caching it.
961
- let timeSensitive = false;
962
933
 
963
934
  const resolveNormal = async (): Promise<EntryResult<D>> => {
964
935
  for (let i = 0; i < localeChain.length; i++) {
@@ -977,9 +948,6 @@ export async function getEmDashEntry<T extends string, D = InferCollectionData<T
977
948
  cacheHint: cacheHint ?? {},
978
949
  });
979
950
  }
980
- if (entry && isPendingScheduled(entry)) {
981
- timeSensitive = true;
982
- }
983
951
  // Entry not found or not visible in this locale — try next
984
952
  }
985
953
  return { entry: null, isPreview: false, cacheHint: {} };
@@ -1003,7 +971,7 @@ export async function getEmDashEntry<T extends string, D = InferCollectionData<T
1003
971
  },
1004
972
  };
1005
973
  },
1006
- cacheable: (snap) => snap.ok && !timeSensitive,
974
+ cacheable: (snap) => snap.ok,
1007
975
  });
1008
976
 
1009
977
  if (!snapshot.ok) {
@@ -1063,18 +1031,29 @@ async function hydrateEntryBylines<D>(type: string, entries: ContentEntry<D>[]):
1063
1031
  return { data, credits };
1064
1032
  });
1065
1033
 
1034
+ // An empty `_emdash_bylines` table makes an empty fold authoritative: no
1035
+ // credit can exist in any locale and the author fallback has no byline
1036
+ // to resolve to, so skip the query path and the custom-fields probe
1037
+ // entirely. A missing marker (older cached rows) means "unknown" and
1038
+ // keeps the conservative fallback below.
1039
+ const knownEmpty = entries.every(
1040
+ (e) => Reflect.get(entryData(e), FOLDED_BYLINES_EXIST) === false,
1041
+ );
1042
+
1066
1043
  // Fall back to the full query path when the fold can't be trusted to be
1067
1044
  // complete: an entry with a byline reference (explicit primary, or an
1068
1045
  // author for the author-fallback) but no folded credits — e.g. a credit
1069
1046
  // in a different locale than the row, which the locale-correlated subquery
1070
1047
  // skips, or the author-fallback path which the fold doesn't express.
1071
- let needsQueryPath = parsed.some(
1072
- (p) =>
1073
- p.credits.length === 0 &&
1074
- (dataStr(p.data, "authorId") !== "" || dataStr(p.data, "primaryBylineId") !== ""),
1075
- );
1048
+ let needsQueryPath =
1049
+ !knownEmpty &&
1050
+ parsed.some(
1051
+ (p) =>
1052
+ p.credits.length === 0 &&
1053
+ (dataStr(p.data, "authorId") !== "" || dataStr(p.data, "primaryBylineId") !== ""),
1054
+ );
1076
1055
  let hasCustomFields = false;
1077
- if (!needsQueryPath) {
1056
+ if (!needsQueryPath && !knownEmpty) {
1078
1057
  try {
1079
1058
  const { getDb } = await import("./loader.js");
1080
1059
  const db = await getDb();
@@ -1,19 +1,27 @@
1
1
  /**
2
2
  * Redirect rule cache.
3
3
  *
4
- * Module-level cache for enabled redirect rules. The middleware populates this
5
- * on first request; route handlers invalidate it on writes.
4
+ * Worker-isolate cache for enabled redirect rules. The middleware populates
5
+ * this on first request; route handlers invalidate it on writes. Cached rules
6
+ * expire so writes handled by another isolate become visible here too.
6
7
  *
7
8
  * Both exact-match and pattern rules are loaded from one query and cached
8
9
  * together: exact rules indexed by source path in a Map, pattern rules
9
10
  * pre-compiled into an array. A single warm request issues zero database
10
- * queries; a cold isolate issues one.
11
+ * queries; a cold or expired isolate issues one.
11
12
  *
12
13
  * This module deliberately has NO Astro imports so it can be safely imported
13
14
  * from handlers, seed, CLI, and tests without dragging in `astro:middleware`.
14
15
  */
15
16
 
17
+ import { after } from "../after.js";
16
18
  import type { Redirect } from "../database/repositories/redirect.js";
19
+ import {
20
+ createSingleFlightCache,
21
+ type SingleFlightCache,
22
+ invalidateSingleFlightCache,
23
+ singleFlightCached,
24
+ } from "../utils/single-flight-cache.js";
17
25
  import type { CompiledPattern } from "./patterns.js";
18
26
  import { compilePattern, interpolateDestination, matchPattern } from "./patterns.js";
19
27
 
@@ -29,33 +37,54 @@ export interface CachedRedirects {
29
37
  patterns: CachedRedirectRule[];
30
38
  }
31
39
 
32
- /**
33
- * Cached enabled redirects.
34
- * null = not yet populated, object = cached.
35
- */
36
- let cachedRedirects: CachedRedirects | null = null;
40
+ interface RedirectCacheState {
41
+ redirects: CachedRedirects | null;
42
+ expiresAt: number;
43
+ generation: number;
44
+ refresh: SingleFlightCache<CachedRedirects>;
45
+ }
46
+
47
+ const REDIRECT_CACHE_TTL_MS = 30_000;
48
+ const REDIRECT_CACHE_MAX_REFRESH_ATTEMPTS = 3;
49
+ const REDIRECT_CACHE_KEY = Symbol.for("emdash:redirect-cache");
50
+ const g = globalThis as Record<symbol, unknown>;
51
+ const cacheState: RedirectCacheState =
52
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see request-context.ts)
53
+ (g[REDIRECT_CACHE_KEY] as RedirectCacheState | undefined) ??
54
+ (() => {
55
+ const state: RedirectCacheState = {
56
+ redirects: null,
57
+ expiresAt: 0,
58
+ generation: 0,
59
+ refresh: createSingleFlightCache<CachedRedirects>(),
60
+ };
61
+ g[REDIRECT_CACHE_KEY] = state;
62
+ return state;
63
+ })();
37
64
 
38
65
  /**
39
66
  * Invalidate the cached redirects (both exact and pattern).
40
67
  * Call when redirects are created, updated, or deleted.
41
68
  */
42
69
  export function invalidateRedirectCache(): void {
43
- cachedRedirects = null;
70
+ cacheState.generation++;
71
+ cacheState.redirects = null;
72
+ cacheState.expiresAt = 0;
73
+ invalidateSingleFlightCache(cacheState.refresh);
44
74
  }
45
75
 
46
76
  /**
47
77
  * Get the cached redirects, or null if the cache is cold.
48
78
  */
49
- export function getCachedRedirects(): CachedRedirects | null {
50
- return cachedRedirects;
79
+ function getCachedRedirects(): CachedRedirects | null {
80
+ if (cacheState.redirects && Date.now() >= cacheState.expiresAt) {
81
+ invalidateRedirectCache();
82
+ }
83
+ return cacheState.redirects;
51
84
  }
52
85
 
53
- /**
54
- * Populate the cache from a list of enabled redirects (both exact and
55
- * pattern). The caller is responsible for passing only enabled rows — the
56
- * cache stores them as-is.
57
- */
58
- export function setCachedRedirects(redirects: Redirect[]): CachedRedirects {
86
+ /** Compile enabled database rows into the in-memory lookup structures. */
87
+ function compileRedirects(redirects: Redirect[]): CachedRedirects {
59
88
  const exact = new Map<string, Redirect>();
60
89
  const patterns: CachedRedirectRule[] = [];
61
90
  for (const r of redirects) {
@@ -65,8 +94,39 @@ export function setCachedRedirects(redirects: Redirect[]): CachedRedirects {
65
94
  exact.set(r.source, r);
66
95
  }
67
96
  }
68
- cachedRedirects = { exact, patterns };
69
- return cachedRedirects;
97
+ return { exact, patterns };
98
+ }
99
+
100
+ function installCachedRedirects(redirects: CachedRedirects): CachedRedirects {
101
+ cacheState.redirects = redirects;
102
+ cacheState.expiresAt = Date.now() + REDIRECT_CACHE_TTL_MS;
103
+ return cacheState.redirects;
104
+ }
105
+
106
+ export async function loadCachedRedirects(
107
+ load: () => Promise<Redirect[]>,
108
+ ): Promise<CachedRedirects> {
109
+ for (let attempt = 0; attempt < REDIRECT_CACHE_MAX_REFRESH_ATTEMPTS; attempt++) {
110
+ const cached = getCachedRedirects();
111
+ if (cached) return cached;
112
+
113
+ const generation = cacheState.generation;
114
+ const loaded = await singleFlightCached(
115
+ cacheState.refresh,
116
+ async () => compileRedirects(await load()),
117
+ { anchor: (promise) => after(() => promise), ownerTimeoutMs: 30_000 },
118
+ );
119
+
120
+ if (generation === cacheState.generation) {
121
+ return installCachedRedirects(loaded);
122
+ }
123
+
124
+ if (attempt === REDIRECT_CACHE_MAX_REFRESH_ATTEMPTS - 1) {
125
+ return loaded;
126
+ }
127
+ }
128
+
129
+ throw new Error("Redirect cache refresh exhausted without loading rules");
70
130
  }
71
131
 
72
132
  /**
@@ -20,6 +20,7 @@
20
20
  import { AsyncLocalStorage } from "node:async_hooks";
21
21
 
22
22
  import type { QueryRecorder } from "./database/instrumentation.js";
23
+ import type { DeferredTaskTracker } from "./deferred-tasks.js";
23
24
 
24
25
  /**
25
26
  * Lightweight always-on counters surfaced in Server-Timing.
@@ -102,6 +103,8 @@ export interface EmDashRequestContext {
102
103
  * and `requestCached`.
103
104
  */
104
105
  metrics?: RequestMetrics;
106
+ /** Deferred work that owns resources scoped to this request. */
107
+ deferredTasks?: DeferredTaskTracker;
105
108
  }
106
109
 
107
110
  const ALS_KEY = Symbol.for("emdash:request-context");
@@ -40,7 +40,11 @@ export const SCHEDULED_PUBLISH_BATCH_LIMIT = 100;
40
40
  export type ScheduledPublishFn = (
41
41
  collection: string,
42
42
  id: string,
43
- options: { publishedAt?: string; requireScheduledDue?: boolean },
43
+ options: {
44
+ publishedAt?: string;
45
+ requireScheduledDue?: boolean;
46
+ expectedScheduledAt?: string;
47
+ },
44
48
  ) => Promise<{ success: boolean; error?: { code?: string } }>;
45
49
 
46
50
  export interface PublishDueContentOptions {
@@ -114,6 +118,7 @@ export async function publishDueContent(
114
118
  const result = await doPublish(collection.slug, item.id, {
115
119
  publishedAt,
116
120
  requireScheduledDue: true,
121
+ expectedScheduledAt: item.scheduledAt ?? undefined,
117
122
  });
118
123
  if (result.success) {
119
124
  batch.push({ collection: collection.slug, id: item.id });
@@ -73,6 +73,19 @@ const VALID_COLLECTION_SUPPORTS: ReadonlySet<string> = new Set<CollectionSupport
73
73
  // multi-row INSERT below D1's 100-parameter statement limit.
74
74
  const SEED_FIELD_INSERT_BATCH_SIZE = 6;
75
75
 
76
+ /**
77
+ * Rank given to collections without an explicit `sort_order`. SQLite sorts
78
+ * NULL first on ASC while Postgres sorts it last, so the fallback is
79
+ * materialised with COALESCE rather than left to the dialect.
80
+ */
81
+ const UNORDERED_COLLECTION_RANK = 2147483647;
82
+
83
+ /**
84
+ * Collection ordering shared by every list read: explicit `sort_order`
85
+ * first (ascending), then alphabetically by slug.
86
+ */
87
+ const collectionOrder = sql<number>`coalesce(sort_order, ${sql.lit(UNORDERED_COLLECTION_RANK)})`;
88
+
76
89
  function isCollectionSupport(value: unknown): value is CollectionSupport {
77
90
  return typeof value === "string" && VALID_COLLECTION_SUPPORTS.has(value);
78
91
  }
@@ -126,6 +139,7 @@ export class SchemaRegistry {
126
139
  const rows = await this.db
127
140
  .selectFrom("_emdash_collections")
128
141
  .selectAll()
142
+ .orderBy(collectionOrder, "asc")
129
143
  .orderBy("slug", "asc")
130
144
  .execute();
131
145
 
@@ -177,6 +191,7 @@ export class SchemaRegistry {
177
191
  const collectionRows = await this.db
178
192
  .selectFrom("_emdash_collections")
179
193
  .selectAll()
194
+ .orderBy(collectionOrder, "asc")
180
195
  .orderBy("slug", "asc")
181
196
  .execute();
182
197
 
@@ -256,6 +271,8 @@ export class SchemaRegistry {
256
271
  supports: JSON.stringify(supports),
257
272
  source: input.source ?? "manual",
258
273
  has_seo: hasSeo ? 1 : 0,
274
+ hidden: input.hidden ? 1 : 0,
275
+ sort_order: input.sortOrder ?? null,
259
276
  comments_enabled: input.commentsEnabled ? 1 : 0,
260
277
  url_pattern: input.urlPattern ?? null,
261
278
  })
@@ -354,6 +371,8 @@ export class SchemaRegistry {
354
371
  supports: JSON.stringify(supports),
355
372
  source: "seed",
356
373
  has_seo: hasSeo ? 1 : 0,
374
+ hidden: input.hidden ? 1 : 0,
375
+ sort_order: input.sortOrder ?? null,
357
376
  comments_enabled: input.commentsEnabled ? 1 : 0,
358
377
  url_pattern: input.urlPattern ?? null,
359
378
  })
@@ -416,6 +435,9 @@ export class SchemaRegistry {
416
435
  ? (input.urlPattern ?? null)
417
436
  : (existing.urlPattern ?? null),
418
437
  has_seo: hasSeo ? 1 : 0,
438
+ hidden: input.hidden !== undefined ? (input.hidden ? 1 : 0) : existing.hidden ? 1 : 0,
439
+ sort_order:
440
+ input.sortOrder !== undefined ? input.sortOrder : (existing.sortOrder ?? null),
419
441
  comments_enabled:
420
442
  input.commentsEnabled !== undefined
421
443
  ? input.commentsEnabled
@@ -822,7 +844,12 @@ export class SchemaRegistry {
822
844
  const ftsActive = config?.enabled === true;
823
845
 
824
846
  if (wantsSearch && searchableFields.length > 0 && ftsActive) {
825
- await ftsManager.rebuildIndex(collectionSlug, searchableFields, config?.weights);
847
+ await ftsManager.rebuildIndex(
848
+ collectionSlug,
849
+ searchableFields,
850
+ config?.weights,
851
+ config?.tokenize,
852
+ );
826
853
  } else if (ftsActive && (!wantsSearch || searchableFields.length === 0)) {
827
854
  await ftsManager.disableSearch(collectionSlug);
828
855
  }
@@ -876,6 +903,60 @@ export class SchemaRegistry {
876
903
  }
877
904
  }
878
905
 
906
+ /**
907
+ * Reorder collections in the admin sidebar.
908
+ *
909
+ * `slugs` is the full desired order: every listed collection gets its
910
+ * index as `sort_order`, and any collection left out has its explicit
911
+ * position cleared, dropping it back to the alphabetical tail. Unknown or
912
+ * duplicate slugs throw before anything is written.
913
+ */
914
+ async reorderCollections(slugs: string[]): Promise<void> {
915
+ const known = new Set((await this.listCollections()).map((collection) => collection.slug));
916
+
917
+ const unknown = slugs.filter((slug) => !known.has(slug));
918
+ if (unknown.length > 0) {
919
+ throw new SchemaError(
920
+ `Unknown collection${unknown.length > 1 ? "s" : ""}: ${unknown.join(", ")}`,
921
+ "COLLECTION_NOT_FOUND",
922
+ { slugs: unknown },
923
+ );
924
+ }
925
+
926
+ const duplicates = slugs.filter((slug, index) => slugs.indexOf(slug) !== index);
927
+ if (duplicates.length > 0) {
928
+ throw new SchemaError(
929
+ `Duplicate collection${duplicates.length > 1 ? "s" : ""}: ${[...new Set(duplicates)].join(", ")}`,
930
+ "DUPLICATE_SLUG",
931
+ { slugs: [...new Set(duplicates)] },
932
+ );
933
+ }
934
+
935
+ const now = new Date().toISOString();
936
+ const ordered = new Set(slugs);
937
+
938
+ await withTransaction(this.db, async (trx) => {
939
+ for (const [index, slug] of slugs.entries()) {
940
+ await trx
941
+ .updateTable("_emdash_collections")
942
+ .set({ sort_order: index, updated_at: now })
943
+ .where("slug", "=", slug)
944
+ .execute();
945
+ }
946
+
947
+ const cleared = [...known].filter((slug) => !ordered.has(slug));
948
+ // Chunked to stay under D1's bound-parameter limit; typical sites
949
+ // clear far fewer than one chunk.
950
+ for (const slugChunk of chunks(cleared, SQL_BATCH_SIZE)) {
951
+ await trx
952
+ .updateTable("_emdash_collections")
953
+ .set({ sort_order: null, updated_at: now })
954
+ .where("slug", "in", slugChunk)
955
+ .execute();
956
+ }
957
+ });
958
+ }
959
+
879
960
  /**
880
961
  * Reorder fields
881
962
  */
@@ -984,9 +1065,18 @@ export class SchemaRegistry {
984
1065
  ON ${sql.ref(tableName)} (locale)
985
1066
  `.execute(conn);
986
1067
 
1068
+ // Names must stay identical to migration 055, which creates these indexes
1069
+ // on tables that already exist. Lookups that don't constrain `deleted_at`
1070
+ // (menu and reference resolution) need the first; reads that do need the
1071
+ // second.
1072
+ await sql`
1073
+ CREATE INDEX ${sql.ref(`idx_${tableName}_tg_locale`)}
1074
+ ON ${sql.ref(tableName)} (translation_group, locale)
1075
+ `.execute(conn);
1076
+
987
1077
  await sql`
988
- CREATE INDEX ${sql.ref(`idx_${tableName}_translation_group`)}
989
- ON ${sql.ref(tableName)} (translation_group)
1078
+ CREATE INDEX ${sql.ref(`idx_${tableName}_del_tg_locale`)}
1079
+ ON ${sql.ref(tableName)} (deleted_at, translation_group, locale)
990
1080
  `.execute(conn);
991
1081
 
992
1082
  // Composite indexes for optimized query performance (see migration 033)
@@ -1228,6 +1318,8 @@ export class SchemaRegistry {
1228
1318
  source: row.source && isCollectionSource(row.source) ? row.source : undefined,
1229
1319
  hasSeo: row.has_seo === 1,
1230
1320
  urlPattern: row.url_pattern ?? undefined,
1321
+ hidden: row.hidden === 1,
1322
+ sortOrder: row.sort_order ?? undefined,
1231
1323
  commentsEnabled: row.comments_enabled === 1,
1232
1324
  commentsModeration:
1233
1325
  moderation === "all" || moderation === "first_time" || moderation === "none"
@@ -171,6 +171,19 @@ export interface Collection {
171
171
  hasSeo: boolean;
172
172
  /** URL pattern with {slug} placeholder (e.g. "/{slug}", "/blog/{slug}") */
173
173
  urlPattern?: string;
174
+ /**
175
+ * Omit this collection's auto-generated entry from the admin sidebar.
176
+ * The collection stays fully functional everywhere else (API, MCP, hooks,
177
+ * direct `/content/:collection` URLs) — this only hides the nav link, so a
178
+ * plugin that owns the collection can point editors at its own admin UI.
179
+ */
180
+ hidden: boolean;
181
+ /**
182
+ * Explicit position in the admin sidebar. Collections with a `sortOrder`
183
+ * come first, in ascending order; the rest keep the alphabetical-by-slug
184
+ * order and follow. `undefined` means "no explicit position".
185
+ */
186
+ sortOrder?: number;
174
187
  /** Whether comments are enabled for this collection */
175
188
  commentsEnabled: boolean;
176
189
  /** Moderation strategy: "all" | "first_time" | "none" */
@@ -219,6 +232,10 @@ export interface CreateCollectionInput {
219
232
  source?: CollectionSource;
220
233
  urlPattern?: string;
221
234
  hasSeo?: boolean;
235
+ /** Omit the auto-generated admin sidebar entry (defaults to false) */
236
+ hidden?: boolean;
237
+ /** Explicit admin sidebar position (omit for the alphabetical fallback) */
238
+ sortOrder?: number | null;
222
239
  commentsEnabled?: boolean;
223
240
  }
224
241
 
@@ -233,6 +250,10 @@ export interface UpdateCollectionInput {
233
250
  supports?: CollectionSupport[];
234
251
  urlPattern?: string;
235
252
  hasSeo?: boolean;
253
+ /** Omit the auto-generated admin sidebar entry */
254
+ hidden?: boolean;
255
+ /** Explicit admin sidebar position; `null` clears it back to alphabetical */
256
+ sortOrder?: number | null;
236
257
  commentsEnabled?: boolean;
237
258
  commentsModeration?: "all" | "first_time" | "none";
238
259
  commentsClosedAfterDays?: number;
@@ -331,6 +352,9 @@ export const RESERVED_COLLECTION_SLUGS = [
331
352
  "taxonomies",
332
353
  "options",
333
354
  "audit_logs",
355
+ // Shadowed by the static POST /schema/collections/reorder route: a
356
+ // collection with this slug could never be addressed at its own URL.
357
+ "reorder",
334
358
  ];
335
359
 
336
360
  /**
@@ -10,7 +10,22 @@ import { sql } from "kysely";
10
10
  import { isSqlite, tableExists as dialectTableExists } from "../database/dialect-helpers.js";
11
11
  import type { Database } from "../database/types.js";
12
12
  import { validateIdentifier } from "../database/validate.js";
13
- import type { SearchConfig } from "./types.js";
13
+ import { SEARCH_TOKENIZERS } from "./types.js";
14
+ import type { SearchConfig, SearchTokenizer } from "./types.js";
15
+
16
+ const DEFAULT_SEARCH_TOKENIZER: SearchTokenizer = "porter unicode61";
17
+
18
+ function isSearchTokenizer(value: unknown): value is SearchTokenizer {
19
+ return SEARCH_TOKENIZERS.some((tokenizer) => tokenizer === value);
20
+ }
21
+
22
+ function resolveSearchTokenizer(tokenize?: SearchTokenizer): SearchTokenizer {
23
+ if (tokenize === undefined) return DEFAULT_SEARCH_TOKENIZER;
24
+ if (!isSearchTokenizer(tokenize)) {
25
+ throw new Error(`Unsupported FTS5 tokenizer: "${String(tokenize)}"`);
26
+ }
27
+ return tokenize;
28
+ }
14
29
 
15
30
  /**
16
31
  * FTS5 Manager
@@ -66,12 +81,15 @@ export class FTSManager {
66
81
  * @param collectionSlug - The collection slug
67
82
  * @param searchableFields - Array of field names to index
68
83
  * @param weights - Optional field weights for ranking
84
+ * @param tokenize - Optional FTS5 tokenizer configuration
69
85
  */
70
86
  async createFtsTable(
71
87
  collectionSlug: string,
72
88
  searchableFields: string[],
73
89
  _weights?: Record<string, number>,
90
+ tokenize?: SearchTokenizer,
74
91
  ): Promise<void> {
92
+ const tokenizer = resolveSearchTokenizer(tokenize);
75
93
  if (!isSqlite(this.db)) return;
76
94
  this.validateInputs(collectionSlug, searchableFields);
77
95
  const ftsTable = this.getFtsTableName(collectionSlug);
@@ -88,14 +106,13 @@ export class FTSManager {
88
106
  // `createTriggers` keep the index in sync; they MUST use the
89
107
  // external-content-safe `'delete'` command (see notes there) to
90
108
  // avoid `SQLITE_CORRUPT_VTAB` on UPDATE/DELETE.
91
- // tokenize='porter unicode61' enables stemming (run matches running, ran, etc.)
92
109
  await sql
93
110
  .raw(`
94
111
  CREATE VIRTUAL TABLE IF NOT EXISTS "${ftsTable}" USING fts5(
95
112
  ${columns},
96
113
  content='${contentTable}',
97
114
  content_rowid='rowid',
98
- tokenize='porter unicode61'
115
+ tokenize='${tokenizer}'
99
116
  )
100
117
  `)
101
118
  .execute(this.db);
@@ -247,13 +264,15 @@ export class FTSManager {
247
264
  collectionSlug: string,
248
265
  searchableFields: string[],
249
266
  weights?: Record<string, number>,
267
+ tokenize?: SearchTokenizer,
250
268
  ): Promise<void> {
269
+ resolveSearchTokenizer(tokenize);
251
270
  if (!isSqlite(this.db)) return;
252
271
  // Drop existing table and triggers
253
272
  await this.dropFtsTable(collectionSlug);
254
273
 
255
274
  // Recreate table and triggers
256
- await this.createFtsTable(collectionSlug, searchableFields, weights);
275
+ await this.createFtsTable(collectionSlug, searchableFields, weights, tokenize);
257
276
 
258
277
  // Populate from existing content
259
278
  await this.populateFromContent(collectionSlug, searchableFields);
@@ -314,6 +333,12 @@ export class FTSManager {
314
333
  }
315
334
  config.weights = weights;
316
335
  }
336
+ if ("tokenize" in parsed) {
337
+ if (!isSearchTokenizer(parsed.tokenize)) {
338
+ return null;
339
+ }
340
+ config.tokenize = parsed.tokenize;
341
+ }
317
342
  return config;
318
343
  } catch {
319
344
  return null;
@@ -324,6 +349,9 @@ export class FTSManager {
324
349
  * Update the search configuration for a collection
325
350
  */
326
351
  async setSearchConfig(collectionSlug: string, config: SearchConfig): Promise<void> {
352
+ if (config.tokenize !== undefined) {
353
+ resolveSearchTokenizer(config.tokenize);
354
+ }
327
355
  await this.db
328
356
  .updateTable("_emdash_collections")
329
357
  .set({ search_config: JSON.stringify(config) })
@@ -399,8 +427,11 @@ export class FTSManager {
399
427
  */
400
428
  async enableSearch(
401
429
  collectionSlug: string,
402
- options?: { weights?: Record<string, number> },
430
+ options?: { weights?: Record<string, number>; tokenize?: SearchTokenizer },
403
431
  ): Promise<void> {
432
+ if (options?.tokenize !== undefined) {
433
+ resolveSearchTokenizer(options.tokenize);
434
+ }
404
435
  if (!isSqlite(this.db)) {
405
436
  throw new Error("Full-text search is only available with SQLite databases");
406
437
  }
@@ -414,13 +445,18 @@ export class FTSManager {
414
445
  );
415
446
  }
416
447
 
448
+ const existing = await this.getSearchConfig(collectionSlug);
449
+ const weights = options?.weights ?? existing?.weights;
450
+ const tokenize = options?.tokenize ?? existing?.tokenize;
451
+
417
452
  // Rebuild from scratch to ensure clean state (no duplicate rows)
418
- await this.rebuildIndex(collectionSlug, searchableFields, options?.weights);
453
+ await this.rebuildIndex(collectionSlug, searchableFields, weights, tokenize);
419
454
 
420
455
  // Update search config
421
456
  await this.setSearchConfig(collectionSlug, {
422
457
  enabled: true,
423
- weights: options?.weights,
458
+ weights,
459
+ tokenize,
424
460
  });
425
461
  }
426
462
 
@@ -433,7 +469,11 @@ export class FTSManager {
433
469
  if (!isSqlite(this.db)) return;
434
470
  await this.dropFtsTable(collectionSlug);
435
471
  const existing = await this.getSearchConfig(collectionSlug);
436
- await this.setSearchConfig(collectionSlug, { enabled: false, weights: existing?.weights });
472
+ await this.setSearchConfig(collectionSlug, {
473
+ enabled: false,
474
+ weights: existing?.weights,
475
+ tokenize: existing?.tokenize,
476
+ });
437
477
  }
438
478
 
439
479
  /**
@@ -490,7 +530,7 @@ export class FTSManager {
490
530
  }
491
531
 
492
532
  console.warn(`FTS index for "${collectionSlug}" is missing. Rebuilding.`);
493
- await this.rebuildIndex(collectionSlug, fields, config.weights);
533
+ await this.rebuildIndex(collectionSlug, fields, config.weights, config.tokenize);
494
534
  return true;
495
535
  }
496
536
 
@@ -515,7 +555,7 @@ export class FTSManager {
515
555
  `FTS index for "${collectionSlug}" has ${ftsRows} rows but content table has ${contentRows}. Rebuilding.`,
516
556
  );
517
557
  if (fields.length > 0) {
518
- await this.rebuildIndex(collectionSlug, fields, config?.weights);
558
+ await this.rebuildIndex(collectionSlug, fields, config?.weights, config?.tokenize);
519
559
  }
520
560
  return true;
521
561
  }
@@ -7,6 +7,7 @@
7
7
  // Types
8
8
  export type {
9
9
  SearchConfig,
10
+ SearchTokenizer,
10
11
  SearchOptions,
11
12
  CollectionSearchOptions,
12
13
  SearchResult,
@@ -15,6 +16,7 @@ export type {
15
16
  Suggestion,
16
17
  SearchStats,
17
18
  } from "./types.js";
19
+ export { SEARCH_TOKENIZERS } from "./types.js";
18
20
 
19
21
  // FTS Manager
20
22
  export { FTSManager } from "./fts-manager.js";