emdash 0.26.0 → 0.28.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 (564) hide show
  1. package/dist/{adapters-DAAjOID4.d.mts → adapters-hUy8vOB-.d.mts} +1 -1
  2. package/dist/{adapters-DAAjOID4.d.mts.map → adapters-hUy8vOB-.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-D5FxMUo8.mjs → allowed-origins-CRsJ6BPM.mjs} +2 -2
  4. package/dist/{allowed-origins-D5FxMUo8.mjs.map → allowed-origins-CRsJ6BPM.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +17 -16
  7. package/dist/api/route-utils.mjs.map +1 -1
  8. package/dist/api/schemas/index.d.mts +1 -1
  9. package/dist/api/schemas/index.mjs +3 -3
  10. package/dist/{api-BMfveMoB.mjs → api-BFURZn1i.mjs} +104 -38
  11. package/dist/api-BFURZn1i.mjs.map +1 -0
  12. package/dist/{api-tokens-D6ppjIVi.mjs → api-tokens-DvqeZmVq.mjs} +2 -2
  13. package/dist/{api-tokens-D6ppjIVi.mjs.map → api-tokens-DvqeZmVq.mjs.map} +1 -1
  14. package/dist/{apply--IVNSdXn.mjs → apply-Bu-8nYHL.mjs} +113 -76
  15. package/dist/apply-Bu-8nYHL.mjs.map +1 -0
  16. package/dist/astro/index.d.mts +12 -11
  17. package/dist/astro/index.d.mts.map +1 -1
  18. package/dist/astro/index.mjs +13 -5
  19. package/dist/astro/index.mjs.map +1 -1
  20. package/dist/astro/middleware/auth.d.mts +10 -9
  21. package/dist/astro/middleware/auth.d.mts.map +1 -1
  22. package/dist/astro/middleware/auth.mjs +52 -12
  23. package/dist/astro/middleware/auth.mjs.map +1 -1
  24. package/dist/astro/middleware/redirect.mjs +5 -5
  25. package/dist/astro/middleware/request-context.mjs +2 -2
  26. package/dist/astro/middleware/setup.mjs +1 -1
  27. package/dist/astro/middleware.d.mts +2 -9
  28. package/dist/astro/middleware.d.mts.map +1 -1
  29. package/dist/astro/middleware.mjs +125 -71
  30. package/dist/astro/middleware.mjs.map +1 -1
  31. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
  32. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
  33. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  34. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  35. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  36. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -8
  37. package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -8
  38. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -8
  39. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -14
  40. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +14 -14
  41. package/dist/astro/routes/api/admin/bylines/index.mjs +14 -14
  42. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +12 -12
  43. package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
  44. package/dist/astro/routes/api/admin/comments/bulk.mjs +10 -10
  45. package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
  46. package/dist/astro/routes/api/admin/comments/index.mjs +10 -10
  47. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  48. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  49. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  50. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  51. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +38 -37
  52. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +38 -37
  54. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +37 -36
  56. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +36 -35
  58. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +36 -35
  60. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/plugins/index.mjs +37 -36
  62. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  64. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +36 -35
  65. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  66. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +36 -35
  67. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +36 -35
  69. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +36 -35
  71. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +37 -36
  73. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +36 -35
  75. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +37 -36
  77. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/plugins/updates.mjs +36 -35
  79. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +36 -35
  81. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  83. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +36 -35
  84. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  85. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  86. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  87. package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
  88. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  89. package/dist/astro/routes/api/admin/users/index.mjs +6 -6
  90. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
  91. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  92. package/dist/astro/routes/api/auth/invite/complete.mjs +10 -10
  93. package/dist/astro/routes/api/auth/invite/index.mjs +7 -7
  94. package/dist/astro/routes/api/auth/invite/register-options.mjs +9 -9
  95. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  96. package/dist/astro/routes/api/auth/magic-link/send.mjs +9 -9
  97. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  98. package/dist/astro/routes/api/auth/me.mjs +7 -7
  99. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  100. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  101. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  102. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
  103. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  104. package/dist/astro/routes/api/auth/passkey/options.mjs +11 -11
  105. package/dist/astro/routes/api/auth/passkey/register/options.mjs +9 -9
  106. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +10 -10
  107. package/dist/astro/routes/api/auth/passkey/verify.mjs +10 -10
  108. package/dist/astro/routes/api/auth/signup/complete.mjs +10 -10
  109. package/dist/astro/routes/api/auth/signup/request.mjs +9 -9
  110. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  111. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +13 -13
  112. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +12 -12
  113. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  114. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  115. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  116. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  117. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +10 -10
  118. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +7 -7
  119. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  120. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  121. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +7 -7
  122. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +13 -13
  123. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  124. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  125. package/dist/astro/routes/api/content/_collection_/_id_.mjs +7 -7
  126. package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
  127. package/dist/astro/routes/api/content/_collection_/index.mjs +7 -7
  128. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
  129. package/dist/astro/routes/api/dashboard.mjs +8 -8
  130. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  131. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  132. package/dist/astro/routes/api/import/probe.mjs +19 -11
  133. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  134. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  135. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -40
  136. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  137. package/dist/astro/routes/api/import/wordpress/execute.mjs +12 -407
  138. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  139. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -9
  140. package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
  141. package/dist/astro/routes/api/import/wordpress/media.mjs +9 -9
  142. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
  143. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +19 -1
  144. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
  145. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +97 -79
  146. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  147. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  148. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +19 -11
  149. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  150. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +40 -2
  151. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
  152. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +519 -39
  153. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  154. package/dist/astro/routes/api/manifest.d.mts.map +1 -1
  155. package/dist/astro/routes/api/manifest.mjs +14 -5
  156. package/dist/astro/routes/api/manifest.mjs.map +1 -1
  157. package/dist/astro/routes/api/mcp.mjs +39 -39
  158. package/dist/astro/routes/api/media/_id_/confirm.mjs +7 -7
  159. package/dist/astro/routes/api/media/_id_.mjs +7 -7
  160. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  161. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  162. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  163. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  164. package/dist/astro/routes/api/media/upload-url.mjs +8 -8
  165. package/dist/astro/routes/api/media.mjs +9 -9
  166. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -9
  167. package/dist/astro/routes/api/menus/_name_/items.mjs +9 -9
  168. package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -9
  169. package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -9
  170. package/dist/astro/routes/api/menus/_name_.mjs +9 -9
  171. package/dist/astro/routes/api/menus/index.mjs +9 -9
  172. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  173. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  174. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  175. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  176. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  177. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  178. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  179. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  180. package/dist/astro/routes/api/openapi.json.mjs +4 -4
  181. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  182. package/dist/astro/routes/api/redirects/404s/index.mjs +9 -9
  183. package/dist/astro/routes/api/redirects/404s/summary.mjs +9 -9
  184. package/dist/astro/routes/api/redirects/_id_.mjs +10 -10
  185. package/dist/astro/routes/api/redirects/index.mjs +10 -10
  186. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  187. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  188. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +36 -35
  189. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  190. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +36 -35
  191. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  192. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +36 -35
  193. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  194. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +36 -35
  195. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  196. package/dist/astro/routes/api/schema/collections/index.mjs +36 -35
  197. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  198. package/dist/astro/routes/api/schema/index.mjs +7 -6
  199. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  200. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +36 -35
  201. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  202. package/dist/astro/routes/api/schema/orphans/index.mjs +36 -35
  203. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  204. package/dist/astro/routes/api/search/enable.mjs +10 -10
  205. package/dist/astro/routes/api/search/index.mjs +9 -9
  206. package/dist/astro/routes/api/search/rebuild.mjs +10 -10
  207. package/dist/astro/routes/api/search/stats.mjs +6 -6
  208. package/dist/astro/routes/api/search/suggest.mjs +9 -9
  209. package/dist/astro/routes/api/sections/_slug_.mjs +9 -9
  210. package/dist/astro/routes/api/sections/index.mjs +9 -9
  211. package/dist/astro/routes/api/settings/email.mjs +4 -4
  212. package/dist/astro/routes/api/settings.mjs +12 -12
  213. package/dist/astro/routes/api/setup/admin-verify.mjs +11 -11
  214. package/dist/astro/routes/api/setup/admin.mjs +10 -10
  215. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  216. package/dist/astro/routes/api/setup/dev-bypass.mjs +28 -25
  217. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  218. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  219. package/dist/astro/routes/api/setup/index.mjs +26 -25
  220. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  221. package/dist/astro/routes/api/setup/status.mjs +4 -4
  222. package/dist/astro/routes/api/snapshot.mjs +6 -6
  223. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +13 -13
  224. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +13 -13
  225. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +13 -13
  226. package/dist/astro/routes/api/taxonomies/index.mjs +13 -13
  227. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  228. package/dist/astro/routes/api/typegen.mjs +5 -5
  229. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  230. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  231. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  232. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +7 -7
  233. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +9 -9
  234. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +9 -9
  235. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  236. package/dist/astro/routes/api/widget-areas/index.mjs +9 -9
  237. package/dist/astro/routes/api/widget-components.mjs +3 -3
  238. package/dist/astro/routes/robots.txt.mjs +6 -6
  239. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  240. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  241. package/dist/astro/types.d.mts +14 -12
  242. package/dist/astro/types.d.mts.map +1 -1
  243. package/dist/auth/providers/github.d.mts +1 -1
  244. package/dist/auth/providers/google.d.mts +1 -1
  245. package/dist/{authorize-BZnOGJFo.mjs → authorize-Dz88F_Fw.mjs} +2 -2
  246. package/dist/{authorize-BZnOGJFo.mjs.map → authorize-Dz88F_Fw.mjs.map} +1 -1
  247. package/dist/{byline-LL8lyqdb.mjs → byline-Bm8ZgUP9.mjs} +6 -6
  248. package/dist/{byline-LL8lyqdb.mjs.map → byline-Bm8ZgUP9.mjs.map} +1 -1
  249. package/dist/{byline-fields-eyJMblSr.mjs → byline-fields-2Lp5Hbgf.mjs} +18 -3
  250. package/dist/byline-fields-2Lp5Hbgf.mjs.map +1 -0
  251. package/dist/{byline-fields-DaMKzkhO.mjs → byline-fields-CIx_GuN4.mjs} +1 -1
  252. package/dist/{byline-fields-DaMKzkhO.mjs.map → byline-fields-CIx_GuN4.mjs.map} +1 -1
  253. package/dist/{byline-fields-KD3JFRuH.d.mts → byline-fields-Cgrt9-aL.d.mts} +18 -3
  254. package/dist/{byline-fields-KD3JFRuH.d.mts.map → byline-fields-Cgrt9-aL.d.mts.map} +1 -1
  255. package/dist/{bylines-BmJ7Vg7J.mjs → bylines-6tm9mgQb.mjs} +4 -4
  256. package/dist/{bylines-BmJ7Vg7J.mjs.map → bylines-6tm9mgQb.mjs.map} +1 -1
  257. package/dist/{bylines-DE47vP8d.mjs → bylines-Woq87129.mjs} +6 -6
  258. package/dist/{bylines-DE47vP8d.mjs.map → bylines-Woq87129.mjs.map} +1 -1
  259. package/dist/{cache-D9jF5bYw.mjs → cache-CEBAZjir.mjs} +2 -2
  260. package/dist/{cache-D9jF5bYw.mjs.map → cache-CEBAZjir.mjs.map} +1 -1
  261. package/dist/{challenge-store-LhiqMccz.mjs → challenge-store-anhwVER0.mjs} +1 -1
  262. package/dist/{challenge-store-LhiqMccz.mjs.map → challenge-store-anhwVER0.mjs.map} +1 -1
  263. package/dist/{chunks-OCG163rN.mjs → chunks-B2isWQhr.mjs} +2 -2
  264. package/dist/{chunks-OCG163rN.mjs.map → chunks-B2isWQhr.mjs.map} +1 -1
  265. package/dist/cli/index.mjs +23 -22
  266. package/dist/cli/index.mjs.map +1 -1
  267. package/dist/client/cf-access.d.mts +1 -1
  268. package/dist/client/index.d.mts +1 -1
  269. package/dist/client/index.mjs +2 -2
  270. package/dist/{comment-D9BLDpZI.mjs → comment-CzeatwBV.mjs} +3 -3
  271. package/dist/{comment-D9BLDpZI.mjs.map → comment-CzeatwBV.mjs.map} +1 -1
  272. package/dist/{comment-reaction-Drl9SkNu.mjs → comment-reaction-Cj9QJY7I.mjs} +2 -2
  273. package/dist/{comment-reaction-Drl9SkNu.mjs.map → comment-reaction-Cj9QJY7I.mjs.map} +1 -1
  274. package/dist/{comments-BjJ9SKGU.mjs → comments-BLE-jv5k.mjs} +3 -3
  275. package/dist/{comments-BjJ9SKGU.mjs.map → comments-BLE-jv5k.mjs.map} +1 -1
  276. package/dist/{components-CYt4uVK9.mjs → components-B_sATNUc.mjs} +1 -1
  277. package/dist/{components-CYt4uVK9.mjs.map → components-B_sATNUc.mjs.map} +1 -1
  278. package/dist/{content-ncUWWjna.mjs → content-DhgEth4k.mjs} +4 -4
  279. package/dist/{content-ncUWWjna.mjs.map → content-DhgEth4k.mjs.map} +1 -1
  280. package/dist/content-refresh-CA4uKwzH.mjs +1531 -0
  281. package/dist/content-refresh-CA4uKwzH.mjs.map +1 -0
  282. package/dist/{context-C_g-iJVA.mjs → context-CUsR9dXL.mjs} +76 -54
  283. package/dist/context-CUsR9dXL.mjs.map +1 -0
  284. package/dist/{cron-C5LVoNmP.mjs → cron-v4FTEFR_.mjs} +1 -1
  285. package/dist/{cron-C5LVoNmP.mjs.map → cron-v4FTEFR_.mjs.map} +1 -1
  286. package/dist/{dashboard-CotyqQrW.mjs → dashboard-EvEKF5en.mjs} +4 -4
  287. package/dist/{dashboard-CotyqQrW.mjs.map → dashboard-EvEKF5en.mjs.map} +1 -1
  288. package/dist/db/index.d.mts +3 -3
  289. package/dist/db/index.mjs +1 -1
  290. package/dist/db/libsql.d.mts +1 -1
  291. package/dist/db/postgres.d.mts +1 -1
  292. package/dist/db/sqlite.d.mts +1 -1
  293. package/dist/{default-CeRG-Ot4.mjs → default-CM_D83Mg.mjs} +1 -1
  294. package/dist/{default-CeRG-Ot4.mjs.map → default-CM_D83Mg.mjs.map} +1 -1
  295. package/dist/{device-flow-DENDCQ9F.mjs → device-flow-CfGP18Uw.mjs} +4 -4
  296. package/dist/{device-flow-DENDCQ9F.mjs.map → device-flow-CfGP18Uw.mjs.map} +1 -1
  297. package/dist/{email-console-DJP32ucW.mjs → email-console-CIf4Lfvv.mjs} +1 -1
  298. package/dist/{email-console-DJP32ucW.mjs.map → email-console-CIf4Lfvv.mjs.map} +1 -1
  299. package/dist/{error-rVGiqWDt.mjs → error-CkAseSqZ.mjs} +2 -2
  300. package/dist/{error-rVGiqWDt.mjs.map → error-CkAseSqZ.mjs.map} +1 -1
  301. package/dist/{escape-Bjio4ZsM.mjs → escape-DqD0aCKu.mjs} +1 -1
  302. package/dist/{escape-Bjio4ZsM.mjs.map → escape-DqD0aCKu.mjs.map} +1 -1
  303. package/dist/{field-defs-cache-ljXzJCfc.mjs → field-defs-cache-WUI88LX5.mjs} +2 -2
  304. package/dist/{field-defs-cache-ljXzJCfc.mjs.map → field-defs-cache-WUI88LX5.mjs.map} +1 -1
  305. package/dist/{fts-manager-BbCCbEKA.mjs → fts-manager-BbFaF_V8.mjs} +2 -2
  306. package/dist/{fts-manager-BbCCbEKA.mjs.map → fts-manager-BbFaF_V8.mjs.map} +1 -1
  307. package/dist/{import-Bb1T9WJS.mjs → import-fYLf14Co.mjs} +514 -25
  308. package/dist/import-fYLf14Co.mjs.map +1 -0
  309. package/dist/{index-BRNabKrx.d.mts → index-B9sIxwe4.d.mts} +2420 -2379
  310. package/dist/index-B9sIxwe4.d.mts.map +1 -0
  311. package/dist/{index-Dt0OKJB4.d.mts → index-Bm-Gy8Mh.d.mts} +25 -4
  312. package/dist/index-Bm-Gy8Mh.d.mts.map +1 -0
  313. package/dist/index.d.mts +18 -17
  314. package/dist/index.mjs +54 -53
  315. package/dist/{load-DMjXghbZ.mjs → load-Djn3HWQS.mjs} +2 -2
  316. package/dist/{load-DMjXghbZ.mjs.map → load-Djn3HWQS.mjs.map} +1 -1
  317. package/dist/{loader-BA_zhkS_.mjs → loader-CB6YHeul.mjs} +6 -5
  318. package/dist/loader-CB6YHeul.mjs.map +1 -0
  319. package/dist/{manifest-schema-kPGX7VS-.mjs → manifest-schema-BHlgZM1W.mjs} +1 -1
  320. package/dist/{manifest-schema-kPGX7VS-.mjs.map → manifest-schema-BHlgZM1W.mjs.map} +1 -1
  321. package/dist/media/index.d.mts +1 -1
  322. package/dist/media/local-runtime.d.mts +12 -11
  323. package/dist/media/local-runtime.d.mts.map +1 -1
  324. package/dist/media/local-runtime.mjs +5 -5
  325. package/dist/{media-C5t_eCnk.mjs → media-BrXIaMFN.mjs} +2 -2
  326. package/dist/{media-C5t_eCnk.mjs.map → media-BrXIaMFN.mjs.map} +1 -1
  327. package/dist/{media-allowlist-Du8t1u6a.mjs → media-allowlist-CRHEeJ_i.mjs} +1 -1
  328. package/dist/{media-allowlist-Du8t1u6a.mjs.map → media-allowlist-CRHEeJ_i.mjs.map} +1 -1
  329. package/dist/{media-url-O4rm9-SQ.mjs → media-url-CKi5XSw4.mjs} +1 -1
  330. package/dist/{media-url-O4rm9-SQ.mjs.map → media-url-CKi5XSw4.mjs.map} +1 -1
  331. package/dist/{menus-CBb6UrMU.mjs → menus-Cfivc2Ad.mjs} +3 -3
  332. package/dist/{menus-CBb6UrMU.mjs.map → menus-Cfivc2Ad.mjs.map} +1 -1
  333. package/dist/{menus-CYH09a41.mjs → menus-CsZ2ZEK2.mjs} +16 -12
  334. package/dist/{menus-CYH09a41.mjs.map → menus-CsZ2ZEK2.mjs.map} +1 -1
  335. package/dist/{mode-BB0F8xTC.mjs → mode-BM9QgEmt.mjs} +1 -1
  336. package/dist/{mode-BB0F8xTC.mjs.map → mode-BM9QgEmt.mjs.map} +1 -1
  337. package/dist/{oauth-authorization-CsvzIp_F.mjs → oauth-authorization-CXWkIGT4.mjs} +4 -4
  338. package/dist/{oauth-authorization-CsvzIp_F.mjs.map → oauth-authorization-CXWkIGT4.mjs.map} +1 -1
  339. package/dist/{oauth-clients-C9SYwEbZ.mjs → oauth-clients-BmTI5rsl.mjs} +1 -1
  340. package/dist/{oauth-clients-C9SYwEbZ.mjs.map → oauth-clients-BmTI5rsl.mjs.map} +1 -1
  341. package/dist/{oauth-state-store---zrApfB.mjs → oauth-state-store-YLFLcH5F.mjs} +1 -1
  342. package/dist/{oauth-state-store---zrApfB.mjs.map → oauth-state-store-YLFLcH5F.mjs.map} +1 -1
  343. package/dist/{oauth-user-lookup-SHsWRlG9.mjs → oauth-user-lookup-Bsc_GsX-.mjs} +1 -1
  344. package/dist/{oauth-user-lookup-SHsWRlG9.mjs.map → oauth-user-lookup-Bsc_GsX-.mjs.map} +1 -1
  345. package/dist/object-cache/memory.d.mts +1 -1
  346. package/dist/{object-cache-CHbHv83-.mjs → object-cache-Bok5j2ae.mjs} +43 -3
  347. package/dist/object-cache-Bok5j2ae.mjs.map +1 -0
  348. package/dist/{options-41nCWqi9.d.mts → options-iMpRRxIe.d.mts} +3 -3
  349. package/dist/{options-41nCWqi9.d.mts.map → options-iMpRRxIe.d.mts.map} +1 -1
  350. package/dist/page/index.d.mts +2 -2
  351. package/dist/{parse-BwAdS7FZ.mjs → parse-GmjecGct.mjs} +2 -2
  352. package/dist/{parse-BwAdS7FZ.mjs.map → parse-GmjecGct.mjs.map} +1 -1
  353. package/dist/{passkey-config-C0YfSBko.mjs → passkey-config-De0ahnRg.mjs} +1 -1
  354. package/dist/{passkey-config-C0YfSBko.mjs.map → passkey-config-De0ahnRg.mjs.map} +1 -1
  355. package/dist/{placeholder-Cuce9U-m.d.mts → placeholder-BSKwzRe4.d.mts} +1 -1
  356. package/dist/{placeholder-Cuce9U-m.d.mts.map → placeholder-BSKwzRe4.d.mts.map} +1 -1
  357. package/dist/plugin-types.d.mts +1 -1
  358. package/dist/plugin-utils.d.mts +10 -9
  359. package/dist/plugin-utils.d.mts.map +1 -1
  360. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -9
  361. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  362. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  363. package/dist/{portable-text-BICg8bTk.mjs → portable-text-cCa0cGV6.mjs} +1 -1
  364. package/dist/{portable-text-BICg8bTk.mjs.map → portable-text-cCa0cGV6.mjs.map} +1 -1
  365. package/dist/{preview-DKGCt2_p.mjs → preview-SSXNVPAC.mjs} +2 -2
  366. package/dist/{preview-DKGCt2_p.mjs.map → preview-SSXNVPAC.mjs.map} +1 -1
  367. package/dist/{public-url-CTVqgMmg.mjs → public-url-Danv47cS.mjs} +1 -1
  368. package/dist/{public-url-CTVqgMmg.mjs.map → public-url-Danv47cS.mjs.map} +1 -1
  369. package/dist/{query-BpQb-blG.mjs → query-ByGq6ver.mjs} +14 -14
  370. package/dist/{query-BpQb-blG.mjs.map → query-ByGq6ver.mjs.map} +1 -1
  371. package/dist/{rate-limit-Dap6HMNM.mjs → rate-limit-C_Lf63Dd.mjs} +2 -2
  372. package/dist/{rate-limit-Dap6HMNM.mjs.map → rate-limit-C_Lf63Dd.mjs.map} +1 -1
  373. package/dist/{redirect-CS-PHtNh.mjs → redirect-CoW3G-0U.mjs} +1 -1
  374. package/dist/{redirect-CS-PHtNh.mjs.map → redirect-CoW3G-0U.mjs.map} +1 -1
  375. package/dist/{redirect-_M0trWoo.mjs → redirect-IyfNirgS.mjs} +2 -2
  376. package/dist/{redirect-_M0trWoo.mjs.map → redirect-IyfNirgS.mjs.map} +1 -1
  377. package/dist/{redirects-w0V9vj_j.mjs → redirects-Bs1g42Ri.mjs} +4 -4
  378. package/dist/{redirects-w0V9vj_j.mjs.map → redirects-Bs1g42Ri.mjs.map} +1 -1
  379. package/dist/{redirects-Dcbuisoj.mjs → redirects-DXEXBAII.mjs} +2 -2
  380. package/dist/{redirects-Dcbuisoj.mjs.map → redirects-DXEXBAII.mjs.map} +1 -1
  381. package/dist/{registry-g8yYt4cC.mjs → registry-B65mUtPa.mjs} +122 -79
  382. package/dist/registry-B65mUtPa.mjs.map +1 -0
  383. package/dist/{request-meta-CmS1tDFf.mjs → request-meta-DbvXaAvU.mjs} +2 -2
  384. package/dist/{request-meta-CmS1tDFf.mjs.map → request-meta-DbvXaAvU.mjs.map} +1 -1
  385. package/dist/{resolve-C7I0qiR0.mjs → resolve-DR3wqMTy.mjs} +1 -1
  386. package/dist/{resolve-C7I0qiR0.mjs.map → resolve-DR3wqMTy.mjs.map} +1 -1
  387. package/dist/{runner-BbR3DfrL.d.mts → runner-DvFWoz8-.d.mts} +2 -2
  388. package/dist/{runner-BbR3DfrL.d.mts.map → runner-DvFWoz8-.d.mts.map} +1 -1
  389. package/dist/{runner-DPdt_Wpa.mjs → runner-K8XK101B.mjs} +351 -199
  390. package/dist/runner-K8XK101B.mjs.map +1 -0
  391. package/dist/runtime.d.mts +11 -10
  392. package/dist/runtime.d.mts.map +1 -1
  393. package/dist/runtime.mjs +2 -2
  394. package/dist/scheduled-publish-Drffrf2a.d.mts +11 -0
  395. package/dist/scheduled-publish-Drffrf2a.d.mts.map +1 -0
  396. package/dist/{schema-DoLd3j2e.mjs → schema-Blhoxp3P.mjs} +5 -5
  397. package/dist/{schema-DoLd3j2e.mjs.map → schema-Blhoxp3P.mjs.map} +1 -1
  398. package/dist/{search-BR0ZeZmh.mjs → search-DZN2HZ-V.mjs} +6 -4
  399. package/dist/search-DZN2HZ-V.mjs.map +1 -0
  400. package/dist/{secrets-BSf9pRRY.mjs → secrets-kp760LlD.mjs} +2 -2
  401. package/dist/{secrets-BSf9pRRY.mjs.map → secrets-kp760LlD.mjs.map} +1 -1
  402. package/dist/{sections-5J2YJPqJ.mjs → sections-CpF5SaGr.mjs} +3 -3
  403. package/dist/{sections-5J2YJPqJ.mjs.map → sections-CpF5SaGr.mjs.map} +1 -1
  404. package/dist/seed/index.d.mts +2 -2
  405. package/dist/seed/index.mjs +19 -18
  406. package/dist/seo/index.d.mts +1 -1
  407. package/dist/seo/index.mjs +1 -1
  408. package/dist/{seo-BkhuuaaE.mjs → seo-89-53DDs.mjs} +1 -1
  409. package/dist/{seo-BkhuuaaE.mjs.map → seo-89-53DDs.mjs.map} +1 -1
  410. package/dist/{seo-DKeXHkzE.mjs → seo-DXu2UQnC.mjs} +3 -3
  411. package/dist/{seo-DKeXHkzE.mjs.map → seo-DXu2UQnC.mjs.map} +1 -1
  412. package/dist/{service-BbO2s8gT.mjs → service-DQmiBMzt.mjs} +3 -3
  413. package/dist/{service-BbO2s8gT.mjs.map → service-DQmiBMzt.mjs.map} +1 -1
  414. package/dist/{session-user-B8aLtKAH.mjs → session-user-Cascbax7.mjs} +1 -1
  415. package/dist/{session-user-B8aLtKAH.mjs.map → session-user-Cascbax7.mjs.map} +1 -1
  416. package/dist/{settings-BMNr9Dmi.mjs → settings-rZyHEcNT.mjs} +3 -3
  417. package/dist/{settings-BMNr9Dmi.mjs.map → settings-rZyHEcNT.mjs.map} +1 -1
  418. package/dist/{settings-DJeki-97.mjs → settings-zhmdKyJQ.mjs} +5 -5
  419. package/dist/{settings-DJeki-97.mjs.map → settings-zhmdKyJQ.mjs.map} +1 -1
  420. package/dist/{setup-complete-gEiySUc-.mjs → setup-complete-Cb3LRyzy.mjs} +1 -1
  421. package/dist/{setup-complete-gEiySUc-.mjs.map → setup-complete-Cb3LRyzy.mjs.map} +1 -1
  422. package/dist/{setup-nonce-DzS50zme.mjs → setup-nonce-Z8x0tHf8.mjs} +1 -1
  423. package/dist/{setup-nonce-DzS50zme.mjs.map → setup-nonce-Z8x0tHf8.mjs.map} +1 -1
  424. package/dist/{single-flight-cache-Cdfkic3t.mjs → single-flight-cache-BG3B_GhN.mjs} +1 -1
  425. package/dist/{single-flight-cache-Cdfkic3t.mjs.map → single-flight-cache-BG3B_GhN.mjs.map} +1 -1
  426. package/dist/{site-url-BLebyON8.mjs → site-url-BBfDTgZB.mjs} +1 -1
  427. package/dist/{site-url-BLebyON8.mjs.map → site-url-BBfDTgZB.mjs.map} +1 -1
  428. package/dist/{ssrf-BRKb343l.mjs → ssrf-1g7usGBg.mjs} +1 -1
  429. package/dist/{ssrf-BRKb343l.mjs.map → ssrf-1g7usGBg.mjs.map} +1 -1
  430. package/dist/{status-vUK0SA17.mjs → status-CqJQX1QN.mjs} +1 -1
  431. package/dist/{status-vUK0SA17.mjs.map → status-CqJQX1QN.mjs.map} +1 -1
  432. package/dist/storage/local.d.mts +1 -1
  433. package/dist/storage/local.mjs +1 -1
  434. package/dist/storage/s3.d.mts +1 -1
  435. package/dist/storage/s3.mjs +1 -1
  436. package/dist/{taxonomies-CM_fUqLU.mjs → taxonomies-BGBd16Eu.mjs} +4 -4
  437. package/dist/{taxonomies-CM_fUqLU.mjs.map → taxonomies-BGBd16Eu.mjs.map} +1 -1
  438. package/dist/{taxonomies-D13i2ctt.mjs → taxonomies-Cnb4F-Pb.mjs} +7 -7
  439. package/dist/{taxonomies-D13i2ctt.mjs.map → taxonomies-Cnb4F-Pb.mjs.map} +1 -1
  440. package/dist/{taxonomy-BU0LjdVb.mjs → taxonomy-BxGxZZdu.mjs} +4 -4
  441. package/dist/{taxonomy-BU0LjdVb.mjs.map → taxonomy-BxGxZZdu.mjs.map} +1 -1
  442. package/dist/{tokens-LeuXF9gG.mjs → tokens-BGT0TUUo.mjs} +1 -1
  443. package/dist/{tokens-LeuXF9gG.mjs.map → tokens-BGT0TUUo.mjs.map} +1 -1
  444. package/dist/{transport-BZ-03aFT.d.mts → transport-BMDWHSgZ.d.mts} +1 -1
  445. package/dist/{transport-BZ-03aFT.d.mts.map → transport-BMDWHSgZ.d.mts.map} +1 -1
  446. package/dist/{transport-_2nBz7e9.mjs → transport-DPefPMcz.mjs} +1 -1
  447. package/dist/{transport-_2nBz7e9.mjs.map → transport-DPefPMcz.mjs.map} +1 -1
  448. package/dist/{trusted-proxy-DZY5WCn2.mjs → trusted-proxy-VTPRiX2s.mjs} +1 -1
  449. package/dist/{trusted-proxy-DZY5WCn2.mjs.map → trusted-proxy-VTPRiX2s.mjs.map} +1 -1
  450. package/dist/{types-ETmO_jQr.d.mts → types-BcLUUbbR.d.mts} +2 -2
  451. package/dist/{types-ETmO_jQr.d.mts.map → types-BcLUUbbR.d.mts.map} +1 -1
  452. package/dist/{types-BYnDBVwe.d.mts → types-CGbYowGQ.d.mts} +2 -2
  453. package/dist/{types-BYnDBVwe.d.mts.map → types-CGbYowGQ.d.mts.map} +1 -1
  454. package/dist/{types-BWqGVhFn.d.mts → types-CgvhU-hF.d.mts} +1 -1
  455. package/dist/{types-BWqGVhFn.d.mts.map → types-CgvhU-hF.d.mts.map} +1 -1
  456. package/dist/{types-fS7-VTdR.d.mts → types-ClUkdbWb.d.mts} +1 -1
  457. package/dist/{types-fS7-VTdR.d.mts.map → types-ClUkdbWb.d.mts.map} +1 -1
  458. package/dist/{types-CZgK3EMW.mjs → types-CuW0zWDA.mjs} +2 -2
  459. package/dist/{types-CZgK3EMW.mjs.map → types-CuW0zWDA.mjs.map} +1 -1
  460. package/dist/{types-BG8_XTLj.d.mts → types-DmHk7vAt.d.mts} +1 -1
  461. package/dist/{types-BG8_XTLj.d.mts.map → types-DmHk7vAt.d.mts.map} +1 -1
  462. package/dist/{types-CQAugunJ.mjs → types-Jo3UYd6b.mjs} +1 -1
  463. package/dist/{types-CQAugunJ.mjs.map → types-Jo3UYd6b.mjs.map} +1 -1
  464. package/dist/{types-xIfVRNLp.d.mts → types-_HFLRzTn.d.mts} +22 -1
  465. package/dist/types-_HFLRzTn.d.mts.map +1 -0
  466. package/dist/{types-DrYMm9s5.d.mts → types-ea9sAPck.d.mts} +1 -1
  467. package/dist/{types-DrYMm9s5.d.mts.map → types-ea9sAPck.d.mts.map} +1 -1
  468. package/dist/{types-CNlaBFzx.d.mts → types-g_aFIdW0.d.mts} +1 -1
  469. package/dist/{types-CNlaBFzx.d.mts.map → types-g_aFIdW0.d.mts.map} +1 -1
  470. package/dist/{types-CUsXGRVj.d.mts → types-vgEWF18A.d.mts} +19 -1
  471. package/dist/{types-CUsXGRVj.d.mts.map → types-vgEWF18A.d.mts.map} +1 -1
  472. package/dist/{user-DkG2jKCp.mjs → user-BjAOvU3Z.mjs} +3 -3
  473. package/dist/{user-DkG2jKCp.mjs.map → user-BjAOvU3Z.mjs.map} +1 -1
  474. package/dist/{utils-B7A57fm9.mjs → utils-BJXElxdw.mjs} +156 -7
  475. package/dist/utils-BJXElxdw.mjs.map +1 -0
  476. package/dist/{validate-CuJ1Ps9j.mjs → validate-CWSnKVIJ.mjs} +2 -2
  477. package/dist/{validate-CuJ1Ps9j.mjs.map → validate-CWSnKVIJ.mjs.map} +1 -1
  478. package/dist/{validate-CG0V0wNR.d.mts → validate-Z1b86_3B.d.mts} +11 -6
  479. package/dist/{validate-CG0V0wNR.d.mts.map → validate-Z1b86_3B.d.mts.map} +1 -1
  480. package/dist/{validation-CwUfTdGF.mjs → validation-c8WjhH8z.mjs} +8 -5
  481. package/dist/{validation-CwUfTdGF.mjs.map → validation-c8WjhH8z.mjs.map} +1 -1
  482. package/dist/version-CaccU7DM.mjs +7 -0
  483. package/dist/{version-BoNBItP_.mjs.map → version-CaccU7DM.mjs.map} +1 -1
  484. package/dist/{widgets-BfOZ-ajY.mjs → widgets-hWcIicX8.mjs} +3 -3
  485. package/dist/{widgets-BfOZ-ajY.mjs.map → widgets-hWcIicX8.mjs.map} +1 -1
  486. package/dist/wxr-taxonomies-0_uxSrmf.d.mts +34 -0
  487. package/dist/wxr-taxonomies-0_uxSrmf.d.mts.map +1 -0
  488. package/dist/wxr-taxonomies-BC3OYpvx.mjs +425 -0
  489. package/dist/wxr-taxonomies-BC3OYpvx.mjs.map +1 -0
  490. package/dist/{zod-generator-gFsRuNNy.mjs → zod-generator-CacrR-i8.mjs} +2 -2
  491. package/dist/{zod-generator-gFsRuNNy.mjs.map → zod-generator-CacrR-i8.mjs.map} +1 -1
  492. package/package.json +6 -6
  493. package/src/api/handlers/content.ts +69 -23
  494. package/src/api/handlers/plugins.ts +77 -10
  495. package/src/api/schemas/import.ts +19 -0
  496. package/src/astro/integration/runtime.ts +3 -6
  497. package/src/astro/integration/vite-config.ts +19 -1
  498. package/src/astro/middleware/auth.ts +10 -3
  499. package/src/astro/middleware/csp.ts +54 -3
  500. package/src/astro/middleware.ts +1 -0
  501. package/src/astro/routes/admin.astro +9 -0
  502. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +6 -1
  503. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +6 -1
  504. package/src/astro/routes/api/admin/plugins/[id]/index.ts +1 -0
  505. package/src/astro/routes/api/admin/plugins/index.ts +1 -0
  506. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +122 -98
  507. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +794 -44
  508. package/src/astro/routes/api/manifest.ts +20 -1
  509. package/src/astro/routes/api/setup/dev-bypass.ts +7 -2
  510. package/src/astro/types.ts +4 -0
  511. package/src/cli/commands/seed.ts +1 -1
  512. package/src/components/EmDashImage.astro +59 -23
  513. package/src/components/Image.astro +36 -35
  514. package/src/components/LiveSearch.astro +40 -4
  515. package/src/components/live-search-routing.ts +30 -0
  516. package/src/database/migrations/036_i18n_menus_and_taxonomies.ts +23 -18
  517. package/src/database/migrations/048_restore_content_taxonomies_term_index.ts +32 -0
  518. package/src/database/migrations/049_taxonomies_name_locale_index.ts +42 -0
  519. package/src/database/migrations/050_media_usage_index_status.ts +142 -0
  520. package/src/database/migrations/runner.ts +6 -0
  521. package/src/database/repositories/media-usage.ts +932 -58
  522. package/src/database/types.ts +22 -0
  523. package/src/emdash-runtime.ts +123 -3
  524. package/src/import/comments.ts +159 -0
  525. package/src/import/index.ts +8 -1
  526. package/src/import/settings.ts +65 -189
  527. package/src/import/sources/wordpress-plugin.ts +338 -42
  528. package/src/import/sources/wxr.ts +4 -1
  529. package/src/import/types.ts +12 -0
  530. package/src/import/utils.ts +207 -0
  531. package/src/import/wxr-taxonomies.ts +39 -0
  532. package/src/loader.ts +13 -2
  533. package/src/media/usage/content-fields.ts +119 -0
  534. package/src/media/usage/content-refresh.ts +524 -0
  535. package/src/media/usage/content-repair.ts +491 -0
  536. package/src/media/usage/content-snapshots.ts +435 -0
  537. package/src/media/usage/extractor.ts +4 -4
  538. package/src/media/usage/source-key.ts +22 -0
  539. package/src/menus/index.ts +17 -1
  540. package/src/object-cache/index.ts +82 -7
  541. package/src/plugins/context.ts +100 -71
  542. package/src/schema/registry.ts +240 -154
  543. package/src/search/query.ts +3 -0
  544. package/src/search/types.ts +2 -0
  545. package/src/seed/apply.ts +158 -101
  546. package/src/seed/types.ts +6 -1
  547. package/dist/api-BMfveMoB.mjs.map +0 -1
  548. package/dist/apply--IVNSdXn.mjs.map +0 -1
  549. package/dist/byline-fields-eyJMblSr.mjs.map +0 -1
  550. package/dist/context-C_g-iJVA.mjs.map +0 -1
  551. package/dist/import-Bb1T9WJS.mjs.map +0 -1
  552. package/dist/index-BRNabKrx.d.mts.map +0 -1
  553. package/dist/index-Dt0OKJB4.d.mts.map +0 -1
  554. package/dist/loader-BA_zhkS_.mjs.map +0 -1
  555. package/dist/object-cache-CHbHv83-.mjs.map +0 -1
  556. package/dist/registry-g8yYt4cC.mjs.map +0 -1
  557. package/dist/runner-DPdt_Wpa.mjs.map +0 -1
  558. package/dist/search-BR0ZeZmh.mjs.map +0 -1
  559. package/dist/types-xIfVRNLp.d.mts.map +0 -1
  560. package/dist/utils-B7A57fm9.mjs.map +0 -1
  561. package/dist/version-BoNBItP_.mjs +0 -7
  562. /package/dist/{api-tokens-B4BQybOp.mjs → api-tokens-DsvvCtdh.mjs} +0 -0
  563. /package/dist/{ssrf-CcX9zvMK.mjs → ssrf-CmuGgCq3.mjs} +0 -0
  564. /package/dist/{types-BvbeGEtr.mjs → types-DROWRxYV.mjs} +0 -0
@@ -11,6 +11,7 @@ import type { APIRoute } from "astro";
11
11
 
12
12
  import { handleError } from "#api/error.js";
13
13
  import { getAuthMode } from "#auth/mode.js";
14
+ import { OptionsRepository } from "#db/repositories/options.js";
14
15
 
15
16
  import { COMMIT, VERSION } from "../../../version.js";
16
17
  import type { EmDashManifest } from "../../types.js";
@@ -39,7 +40,25 @@ export const GET: APIRoute = async ({ locals }) => {
39
40
  // doesn't assign it to globalThis, so getStoredConfig() always returned
40
41
  // null and the React SPA never received custom logo/siteName/favicon.
41
42
  // See issue #835.
42
- const adminBranding = emdash?.config?.admin;
43
+ let adminBranding = emdash?.config?.admin;
44
+
45
+ // When no build-time `admin.siteName` is configured, brand the admin with
46
+ // the site's own title so multi-site operators can tell backends apart
47
+ // (WordPress-style: wp-admin always shows the site name). Precedence:
48
+ // explicit `admin.siteName` → Site Title (Settings → General) → the title
49
+ // captured by the setup wizard → the bundled "EmDash" default in the SPA.
50
+ if (!adminBranding?.siteName && emdash?.db) {
51
+ try {
52
+ const options = new OptionsRepository(emdash.db);
53
+ const titles = await options.getMany<string>(["site:title", "emdash:site_title"]);
54
+ const siteTitle = titles.get("site:title") || titles.get("emdash:site_title");
55
+ if (siteTitle) {
56
+ adminBranding = { ...adminBranding, siteName: siteTitle };
57
+ }
58
+ } catch {
59
+ // options table may not exist yet (pre-setup) — keep the default.
60
+ }
61
+ }
43
62
 
44
63
  // Check if self-signup is enabled (any allowed domain with enabled = 1)
45
64
  // Only relevant for passkey auth — external auth providers handle their own signup
@@ -10,6 +10,8 @@
10
10
  * Usage:
11
11
  * - GET with redirect: /_emdash/api/setup/dev-bypass?redirect=/_emdash/admin
12
12
  * - POST for API: Returns JSON with setup info
13
+ * - ?content=0 (or ?content=false): apply schema/structure only, skipping
14
+ * sample content entries, bylines, and taxonomy terms
13
15
  *
14
16
  * For agent/browser testing, navigate to:
15
17
  * /_emdash/api/setup/dev-bypass?redirect=/_emdash/admin
@@ -57,12 +59,15 @@ async function handleDevBypass(context: Parameters<APIRoute>[0]): Promise<Respon
57
59
  const migrations = await runMigrations(emdash.db);
58
60
  console.log("[setup-dev-bypass] Migrations applied:", migrations.applied);
59
61
 
60
- // Apply seed (user seed or built-in default)
62
+ // Apply seed (user seed or built-in default). `?content=0` (or `false`)
63
+ // applies schema/structure only — no sample content, bylines, or terms.
64
+ const contentParam = url.searchParams.get("content");
65
+ const includeContent = contentParam !== "0" && contentParam !== "false";
61
66
  const seed = await loadSeed();
62
67
  const validation = validateSeed(seed);
63
68
  if (validation.valid) {
64
69
  const seedResult = await applySeed(emdash.db, seed, {
65
- includeContent: true,
70
+ includeContent,
66
71
  onConflict: "skip",
67
72
  storage: emdash.storage ?? undefined,
68
73
  });
@@ -434,6 +434,10 @@ export interface EmDashHandlers {
434
434
  // Configured plugins (for plugin management)
435
435
  configuredPlugins: import("../plugins/types.js").ResolvedPlugin[];
436
436
 
437
+ // Statically-sandboxed plugin entries (registered via `sandboxed: []`),
438
+ // surfaced through the admin plugin management API alongside configured plugins.
439
+ sandboxedPluginEntries: import("../emdash-runtime.js").SandboxedPluginEntry[];
440
+
437
441
  // Configuration (for checking database type, auth mode, etc.)
438
442
  config: import("./integration/runtime.js").EmDashConfig;
439
443
 
@@ -108,7 +108,7 @@ export const seedCommand = defineCommand({
108
108
  },
109
109
  "no-content": {
110
110
  type: "boolean",
111
- description: "Skip sample content",
111
+ description: "Skip sample data (content entries, bylines, taxonomy terms)",
112
112
  default: false,
113
113
  },
114
114
  "on-conflict": {
@@ -18,7 +18,7 @@
18
18
  */
19
19
  import type { MediaValue } from "../fields/types.js";
20
20
  import type { HTMLAttributes } from "astro/types";
21
- import { getImage } from "astro:assets";
21
+ import { Image as AstroImage, getImage } from "astro:assets";
22
22
  import type { ImageEmbed } from "../media/types.js";
23
23
  import { getMediaProvider } from "../media/provider-loader.js";
24
24
  import { buildRenderMediaUrl } from "../media/url.js";
@@ -43,9 +43,20 @@ interface Props extends Omit<
43
43
  height?: number;
44
44
  /** Priority loading (disables lazy loading) */
45
45
  priority?: boolean;
46
+ /** Render the LQIP placeholder as an inline background. Disable for strict CSP. */
47
+ placeholder?: boolean;
46
48
  }
47
49
 
48
- const { image, alt, width, height, priority, ...attrs } = Astro.props;
50
+ const {
51
+ image,
52
+ alt,
53
+ width,
54
+ height,
55
+ priority,
56
+ placeholder = true,
57
+ class: className,
58
+ ...attrs
59
+ } = Astro.props;
49
60
 
50
61
  // Normalize string URLs to object form
51
62
  function normalizeImage(
@@ -98,25 +109,28 @@ const aspectRatio =
98
109
  let src = "";
99
110
  let srcset: string | undefined;
100
111
  let sizes: string | undefined;
112
+ let astroImageSrc = "";
101
113
 
102
114
  if (img) {
103
115
  const providerId = img.provider ?? "local";
104
116
 
105
117
  if (providerId === "local" || img.src) {
106
- // Local provider or direct src URL. Route through Astro's image service
107
- // (`astro:assets`) to generate a responsive srcset; on Cloudflare this is
108
- // the Images binding, on Node it is sharp. Falls back to a plain <img>
109
- // when the service is unavailable or the source can't be optimized.
110
118
  src = img.src || buildLocalImageUrl(img);
111
- const optimized = await buildResponsiveImage(getImage, {
112
- src: toAbsoluteMediaUrl(src, getPublicOrigin(Astro.url, Astro.locals.emdash?.config)),
113
- width: finalWidth,
114
- height: finalHeight,
115
- });
116
- if (optimized) {
117
- src = optimized.src;
118
- srcset = optimized.srcset;
119
- sizes = optimized.sizes;
119
+ const publicOrigin = getPublicOrigin(Astro.url, Astro.locals.emdash?.config);
120
+ const absoluteSrc = toAbsoluteMediaUrl(src, publicOrigin);
121
+ if (finalWidth && finalHeight && absoluteSrc.startsWith(`${publicOrigin}/`)) {
122
+ astroImageSrc = absoluteSrc;
123
+ } else {
124
+ const optimized = await buildResponsiveImage(getImage, {
125
+ src: absoluteSrc,
126
+ width: finalWidth,
127
+ height: finalHeight,
128
+ });
129
+ if (optimized) {
130
+ src = optimized.src;
131
+ srcset = optimized.srcset;
132
+ sizes = optimized.sizes;
133
+ }
120
134
  }
121
135
  } else {
122
136
  // External provider
@@ -166,17 +180,13 @@ const dominantColor =
166
180
  img?.dominantColor ?? (img?.meta?.dominantColor as string | undefined);
167
181
 
168
182
  let placeholderStyle = "";
169
- if (blurhash) {
183
+ if (placeholder && blurhash) {
170
184
  const { blurhashToImageCssString } = await import("@unpic/placeholder");
171
185
  placeholderStyle = blurhashToImageCssString(blurhash);
172
- } else if (dominantColor) {
186
+ } else if (placeholder && dominantColor) {
173
187
  placeholderStyle = `background-color: ${dominantColor};`;
174
188
  }
175
189
 
176
- const baseStyle = aspectRatio
177
- ? `aspect-ratio: ${aspectRatio}; max-width: 100%; height: auto;`
178
- : "max-width: 100%; height: auto;";
179
-
180
190
  const imgProps: Record<string, unknown> = {
181
191
  src,
182
192
  srcset,
@@ -187,9 +197,35 @@ const imgProps: Record<string, unknown> = {
187
197
  loading: priority ? "eager" : "lazy",
188
198
  fetchpriority: priority ? "high" : undefined,
189
199
  decoding: "async",
190
- style: placeholderStyle ? `${baseStyle} ${placeholderStyle}` : baseStyle,
200
+ style: placeholderStyle || undefined,
201
+ class: ["emdash-image-media", className].filter(Boolean).join(" "),
191
202
  ...attrs,
192
203
  };
193
204
  ---
194
205
 
195
- {img && src ? <img {...imgProps} /> : null}
206
+ {
207
+ img && astroImageSrc ? (
208
+ <AstroImage
209
+ src={astroImageSrc}
210
+ alt={finalAlt}
211
+ width={finalWidth}
212
+ height={finalHeight}
213
+ priority={priority}
214
+ layout="constrained"
215
+ loading={priority ? "eager" : "lazy"}
216
+ decoding="async"
217
+ class={className}
218
+ style={placeholderStyle || undefined}
219
+ {...attrs}
220
+ />
221
+ ) : img && src ? (
222
+ <img {...imgProps} />
223
+ ) : null
224
+ }
225
+
226
+ <style>
227
+ .emdash-image-media {
228
+ max-width: 100%;
229
+ height: auto;
230
+ }
231
+ </style>
@@ -5,15 +5,11 @@
5
5
  * Renders image blocks from WordPress imports and EmDash media.
6
6
  * Uses the provider's getSrc function for responsive srcset generation.
7
7
  */
8
- import { getImage } from "astro:assets";
8
+ import { Image as AstroImage } from "astro:assets";
9
9
  import type { ImageEmbed } from "../media/types.js";
10
10
  import { getMediaProvider } from "../media/provider-loader.js";
11
11
  import { buildRenderMediaUrl } from "../media/url.js";
12
- import {
13
- buildResponsiveImage,
14
- toAbsoluteMediaUrl,
15
- RESPONSIVE_BREAKPOINTS,
16
- } from "../media/responsive.js";
12
+ import { toAbsoluteMediaUrl, RESPONSIVE_BREAKPOINTS } from "../media/responsive.js";
17
13
  import { getPublicOrigin } from "../api/public-url.js";
18
14
 
19
15
  export interface Props {
@@ -46,6 +42,8 @@ export interface Props {
46
42
  /** Alignment for this image instance (e.g. from a WordPress import) */
47
43
  alignment?: "left" | "center" | "right" | "wide" | "full";
48
44
  };
45
+ /** Render the LQIP placeholder as an inline background. Disable for strict CSP. */
46
+ placeholder?: boolean;
49
47
  }
50
48
 
51
49
  /**
@@ -64,7 +62,7 @@ function generateSrcset(
64
62
  .join(", ");
65
63
  }
66
64
 
67
- const { node } = Astro.props;
65
+ const { node, placeholder = true } = Astro.props;
68
66
 
69
67
  if (!node?.asset) {
70
68
  return null;
@@ -97,6 +95,7 @@ if (displayWidth && displayHeight) {
97
95
  let src = "";
98
96
  let srcset: string | undefined;
99
97
  let sizes: string | undefined;
98
+ let astroImageSrc = "";
100
99
  const providerId = asset.provider;
101
100
 
102
101
  if (providerId && providerId !== "local") {
@@ -143,17 +142,8 @@ if (!src) {
143
142
  url: asset.url,
144
143
  id: asset._ref,
145
144
  });
146
- // Generate a responsive srcset via Astro's image service for local/R2 media.
147
- // Falls back to the plain URL when optimization isn't possible.
148
- const optimized = await buildResponsiveImage(getImage, {
149
- src: toAbsoluteMediaUrl(src, getPublicOrigin(Astro.url, Astro.locals.emdash?.config)),
150
- width: renderWidth,
151
- height: renderHeight,
152
- });
153
- if (optimized) {
154
- src = optimized.src;
155
- srcset = optimized.srcset;
156
- sizes = optimized.sizes;
145
+ if (renderWidth && renderHeight) {
146
+ astroImageSrc = toAbsoluteMediaUrl(src, getPublicOrigin(Astro.url, Astro.locals.emdash?.config));
157
147
  }
158
148
  }
159
149
 
@@ -167,31 +157,42 @@ const dominantColor = (node.dominantColor ?? (asset.meta?.dominantColor as strin
167
157
  | undefined;
168
158
 
169
159
  let placeholderStyle = "";
170
- if (blurhash) {
160
+ if (placeholder && blurhash) {
171
161
  const { blurhashToImageCssString } = await import("@unpic/placeholder");
172
162
  placeholderStyle = blurhashToImageCssString(blurhash);
173
- } else if (dominantColor) {
163
+ } else if (placeholder && dominantColor) {
174
164
  placeholderStyle = `background-color: ${dominantColor};`;
175
165
  }
176
166
 
177
- const baseStyle = aspectRatio
178
- ? `aspect-ratio: ${aspectRatio}; max-width: 100%; height: auto;`
179
- : "max-width: 100%; height: auto;";
180
- const imgStyle = placeholderStyle ? `${baseStyle} ${placeholderStyle}` : baseStyle;
181
167
  ---
182
168
 
183
169
  <figure class:list={["emdash-image", alignment && `emdash-image--align-${alignment}`]}>
184
- <img
185
- src={src}
186
- srcset={srcset}
187
- sizes={sizes}
188
- alt={alt}
189
- width={renderWidth}
190
- height={renderHeight}
191
- loading="lazy"
192
- decoding="async"
193
- style={imgStyle}
194
- />
170
+ {
171
+ astroImageSrc ? (
172
+ <AstroImage
173
+ src={astroImageSrc}
174
+ alt={alt}
175
+ width={renderWidth}
176
+ height={renderHeight}
177
+ layout="constrained"
178
+ loading="lazy"
179
+ decoding="async"
180
+ style={placeholderStyle || undefined}
181
+ />
182
+ ) : (
183
+ <img
184
+ src={src}
185
+ srcset={srcset}
186
+ sizes={sizes}
187
+ alt={alt}
188
+ width={renderWidth}
189
+ height={renderHeight}
190
+ loading="lazy"
191
+ decoding="async"
192
+ style={placeholderStyle || undefined}
193
+ />
194
+ )
195
+ }
195
196
  {caption && <figcaption>{caption}</figcaption>}
196
197
  </figure>
197
198
 
@@ -34,6 +34,8 @@ export interface Props {
34
34
  limit?: number;
35
35
  /** CSS class for the container */
36
36
  class?: string;
37
+ /** Inline style for the container */
38
+ style?: string;
37
39
  /** CSS class for the input */
38
40
  inputClass?: string;
39
41
  /** CSS class for the results container */
@@ -48,6 +50,10 @@ export interface Props {
48
50
  suggestMode?: boolean;
49
51
  /** Expand input width on focus (provide collapsed and expanded widths) */
50
52
  expandOnFocus?: { collapsed: string; expanded: string };
53
+ /** Search results page to navigate to when pressing Enter without a focused result */
54
+ searchPage?: string;
55
+ /** Per-collection URL templates, e.g. { posts: "/blog/:path" } */
56
+ routeMap?: Record<string, string>;
51
57
  }
52
58
 
53
59
  const {
@@ -57,6 +63,7 @@ const {
57
63
  debounce = 300,
58
64
  limit = 10,
59
65
  class: className = "",
66
+ style: styleAttr = "",
60
67
  inputClass = "",
61
68
  resultsClass = "",
62
69
  resultClass = "",
@@ -64,6 +71,8 @@ const {
64
71
  autofocus = false,
65
72
  suggestMode = false,
66
73
  expandOnFocus,
74
+ searchPage = "",
75
+ routeMap = {},
67
76
  } = Astro.props;
68
77
 
69
78
  const config = {
@@ -74,11 +83,14 @@ const config = {
74
83
  showSnippets,
75
84
  suggestMode,
76
85
  expandOnFocus: expandOnFocus ?? null,
86
+ searchPage,
87
+ routeMap,
77
88
  };
78
89
  ---
79
90
 
80
91
  <emdash-live-search
81
92
  class:list={["emdash-live-search", className]}
93
+ style={styleAttr}
82
94
  data-config={JSON.stringify(config)}
83
95
  >
84
96
  <input
@@ -109,6 +121,12 @@ const config = {
109
121
  </emdash-live-search>
110
122
 
111
123
  <script>
124
+ import {
125
+ buildLiveSearchResultUrl,
126
+ type LiveSearchRouteMap,
127
+ type LiveSearchRoutableResult,
128
+ } from "./live-search-routing.js";
129
+
112
130
  interface SearchResult {
113
131
  collection: string;
114
132
  id: string;
@@ -121,6 +139,7 @@ const config = {
121
139
  interface Suggestion {
122
140
  collection: string;
123
141
  id: string;
142
+ slug?: string | null;
124
143
  title: string;
125
144
  }
126
145
 
@@ -132,6 +151,8 @@ const config = {
132
151
  showSnippets: boolean;
133
152
  suggestMode: boolean;
134
153
  expandOnFocus: { collapsed: string; expanded: string } | null;
154
+ searchPage: string;
155
+ routeMap: LiveSearchRouteMap;
135
156
  }
136
157
 
137
158
  class EmDashLiveSearch extends HTMLElement {
@@ -149,6 +170,8 @@ const config = {
149
170
  showSnippets: true,
150
171
  suggestMode: false,
151
172
  expandOnFocus: null,
173
+ searchPage: "",
174
+ routeMap: {},
152
175
  };
153
176
  private debounceTimer: ReturnType<typeof setTimeout> | null = null;
154
177
  private abortController: AbortController | null = null;
@@ -268,11 +291,25 @@ const config = {
268
291
  ".emdash-live-search-result:focus, .emdash-live-search-result.focused"
269
292
  ) as HTMLAnchorElement | null;
270
293
  if (focused?.href) {
294
+ e.preventDefault();
271
295
  window.location.href = focused.href;
296
+ return;
297
+ }
298
+
299
+ const query = this.input?.value.trim();
300
+ if (query && this.config.searchPage) {
301
+ e.preventDefault();
302
+ const url = new URL(this.config.searchPage, window.location.origin);
303
+ url.searchParams.set("q", query);
304
+ window.location.href = url.toString();
272
305
  }
273
306
  }
274
307
  }
275
308
 
309
+ private buildResultUrl(result: LiveSearchRoutableResult): string {
310
+ return buildLiveSearchResultUrl(result, this.config.routeMap);
311
+ }
312
+
276
313
  private navigateResults(direction: number) {
277
314
  if (!this.resultsList) return;
278
315
 
@@ -369,9 +406,7 @@ const config = {
369
406
  const link = clone.querySelector("a");
370
407
 
371
408
  if (link) {
372
- // Build URL - use slug if available, otherwise id
373
- const path = result.slug ?? result.id;
374
- link.href = `/${result.collection}/${path}`;
409
+ link.href = this.buildResultUrl(result);
375
410
 
376
411
  // Fill in title
377
412
  const titleEl = link.querySelector(
@@ -430,7 +465,7 @@ const config = {
430
465
  const link = clone.querySelector("a");
431
466
 
432
467
  if (link) {
433
- link.href = `/${suggestion.collection}/${suggestion.id}`;
468
+ link.href = this.buildResultUrl(suggestion);
434
469
 
435
470
  const titleEl = link.querySelector(
436
471
  ".emdash-live-search-result-title"
@@ -456,6 +491,7 @@ const config = {
456
491
 
457
492
  link.dataset.id = suggestion.id;
458
493
  link.dataset.collection = suggestion.collection;
494
+ link.dataset.slug = suggestion.slug ?? "";
459
495
  }
460
496
 
461
497
  this.resultsList.appendChild(clone);
@@ -0,0 +1,30 @@
1
+ export interface LiveSearchRoutableResult {
2
+ collection: string;
3
+ id: string;
4
+ slug?: string | null;
5
+ }
6
+
7
+ export type LiveSearchRouteMap = Record<string, string>;
8
+
9
+ function replaceRouteToken(template: string, token: string, value: string): string {
10
+ return template.split(token).join(value);
11
+ }
12
+
13
+ export function buildLiveSearchResultUrl(
14
+ result: LiveSearchRoutableResult,
15
+ routeMap: LiveSearchRouteMap = {},
16
+ ): string {
17
+ const path = result.slug ?? result.id;
18
+ const template = routeMap[result.collection];
19
+
20
+ if (!template) {
21
+ return `/${result.collection}/${path}`;
22
+ }
23
+
24
+ return [
25
+ [":collection", result.collection],
26
+ [":id", result.id],
27
+ [":slug", result.slug ?? result.id],
28
+ [":path", path],
29
+ ].reduce((url, [token, value]) => replaceRouteToken(url, token, value), template);
30
+ }
@@ -259,27 +259,32 @@ async function rebuildContentTaxonomies(db: Kysely<unknown>): Promise<void> {
259
259
  // is load-bearing — if the translation_group seed ever changes, this needs
260
260
  // an explicit remap *after* `rebuildTaxonomies` runs.
261
261
  const fks = await sql<{ id: number }>`PRAGMA foreign_key_list(content_taxonomies)`.execute(db);
262
- if (fks.rows.length === 0) return;
262
+ if (fks.rows.length > 0) {
263
+ await sql.raw(`DROP TABLE IF EXISTS "content_taxonomies_new"`).execute(db);
264
+ await db.schema
265
+ .createTable("content_taxonomies_new")
266
+ .addColumn("collection", "text", (c) => c.notNull())
267
+ .addColumn("entry_id", "text", (c) => c.notNull())
268
+ .addColumn("taxonomy_id", "text", (c) => c.notNull())
269
+ .addPrimaryKeyConstraint("content_taxonomies_pk", ["collection", "entry_id", "taxonomy_id"])
270
+ .execute();
263
271
 
264
- await sql.raw(`DROP TABLE IF EXISTS "content_taxonomies_new"`).execute(db);
265
- await db.schema
266
- .createTable("content_taxonomies_new")
267
- .addColumn("collection", "text", (c) => c.notNull())
268
- .addColumn("entry_id", "text", (c) => c.notNull())
269
- .addColumn("taxonomy_id", "text", (c) => c.notNull())
270
- .addPrimaryKeyConstraint("content_taxonomies_pk", ["collection", "entry_id", "taxonomy_id"])
271
- .execute();
272
-
273
- await sql`
274
- INSERT OR IGNORE INTO content_taxonomies_new (collection, entry_id, taxonomy_id)
275
- SELECT collection, entry_id, taxonomy_id FROM content_taxonomies
276
- `.execute(db);
272
+ await sql`
273
+ INSERT OR IGNORE INTO content_taxonomies_new (collection, entry_id, taxonomy_id)
274
+ SELECT collection, entry_id, taxonomy_id FROM content_taxonomies
275
+ `.execute(db);
277
276
 
278
- await db.schema.dropTable("content_taxonomies").execute();
279
- await sql`ALTER TABLE content_taxonomies_new RENAME TO content_taxonomies`.execute(db);
277
+ await db.schema.dropTable("content_taxonomies").execute();
278
+ await sql`ALTER TABLE content_taxonomies_new RENAME TO content_taxonomies`.execute(db);
279
+ }
280
280
 
281
- // SQLite drops indexes when the underlying table is dropped. Restore the
282
- // taxonomy_id index from migration 015.
281
+ // Recreate the taxonomy_id index from migration 015 unconditionally, OUTSIDE
282
+ // the FK-presence guard above. The rebuild both strips the FK and drops the
283
+ // old table's indexes, but D1 auto-commits each DDL statement — so a first
284
+ // run that failed after the drop leaves the table with no FK and no index.
285
+ // The retry then finds zero FKs and skips the rebuild; if the index recreate
286
+ // lived inside that guard it would never run and the index would be lost for
287
+ // good (#1701). `IF NOT EXISTS` keeps this a no-op once present.
283
288
  await sql`CREATE INDEX IF NOT EXISTS idx_content_taxonomies_term ON content_taxonomies(taxonomy_id)`.execute(
284
289
  db,
285
290
  );
@@ -0,0 +1,32 @@
1
+ import type { Kysely } from "kysely";
2
+
3
+ /**
4
+ * Restore `idx_content_taxonomies_term` on `content_taxonomies(taxonomy_id)` (#1701).
5
+ *
6
+ * Migration 015 created this index. 036's SQLite/D1 table rebuild recreated it,
7
+ * but the recreate was gated behind an FK-presence early-return: if a first run
8
+ * committed the rebuild (stripping the FK and dropping the old index) and then
9
+ * failed before the recreate, the retry saw zero FKs, skipped the whole body,
10
+ * and never restored the index — while 036 was still recorded as applied. The
11
+ * result was an install missing only this one index, with no forward migration
12
+ * to recover it (the sibling `idx_taxonomies_parent` case was fixed by 047).
13
+ *
14
+ * 036 has since been fixed to recreate the index unconditionally, so fresh
15
+ * installs are fine. This recovers the index on installs that hit the trap
16
+ * before that fix. The Postgres path in 036 alters in place and keeps its
17
+ * indexes, so it is unaffected; `ifNotExists` makes this a no-op there.
18
+ *
19
+ * Forward-only.
20
+ */
21
+ export async function up(db: Kysely<unknown>): Promise<void> {
22
+ await db.schema
23
+ .createIndex("idx_content_taxonomies_term")
24
+ .ifNotExists()
25
+ .on("content_taxonomies")
26
+ .column("taxonomy_id")
27
+ .execute();
28
+ }
29
+
30
+ export async function down(db: Kysely<unknown>): Promise<void> {
31
+ await db.schema.dropIndex("idx_content_taxonomies_term").ifExists().execute();
32
+ }
@@ -0,0 +1,42 @@
1
+ import type { Kysely } from "kysely";
2
+
3
+ /**
4
+ * Add composite `idx_taxonomies_name_locale` on `taxonomies(name, locale)` (#1723).
5
+ *
6
+ * `TaxonomyRepository.findByName` filters `WHERE name = ? AND locale = ?`, but
7
+ * the only indexes were the single-column `idx_taxonomies_name(name)` and
8
+ * `idx_taxonomies_locale(locale)`. On SQLite/D1 with no `sqlite_stat1` the
9
+ * planner picks `idx_taxonomies_locale` and reads *every* term in the locale,
10
+ * filtering `name` in memory — once per facet rendered. On a site where one
11
+ * taxonomy dominates a locale, each small facet still walks the whole locale.
12
+ *
13
+ * The composite resolves both equalities, so the planner searches only the one
14
+ * taxonomy's terms. Its leftmost prefix (`name`) also serves every name-only
15
+ * lookup, so it supersedes `idx_taxonomies_name`, which we drop. The
16
+ * single-column `idx_taxonomies_locale` stays for locale-only lookups.
17
+ *
18
+ * Strictly additive: no query changes, and the dropped index is fully covered
19
+ * by the new composite's prefix. Create-before-drop keeps name lookups indexed
20
+ * at every point. Both statements are idempotent so a partial apply can retry.
21
+ */
22
+ export async function up(db: Kysely<unknown>): Promise<void> {
23
+ await db.schema
24
+ .createIndex("idx_taxonomies_name_locale")
25
+ .ifNotExists()
26
+ .on("taxonomies")
27
+ .columns(["name", "locale"])
28
+ .execute();
29
+
30
+ await db.schema.dropIndex("idx_taxonomies_name").ifExists().execute();
31
+ }
32
+
33
+ export async function down(db: Kysely<unknown>): Promise<void> {
34
+ await db.schema
35
+ .createIndex("idx_taxonomies_name")
36
+ .ifNotExists()
37
+ .on("taxonomies")
38
+ .column("name")
39
+ .execute();
40
+
41
+ await db.schema.dropIndex("idx_taxonomies_name_locale").ifExists().execute();
42
+ }