emdash 0.37.0 → 0.38.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 (811) hide show
  1. package/dist/{activation-K0kGBWuJ.mjs → activation-DyNTe_Tl.mjs} +3 -3
  2. package/dist/{activation-K0kGBWuJ.mjs.map → activation-DyNTe_Tl.mjs.map} +1 -1
  3. package/dist/{adapters-BDQwg236.d.mts → adapters-DCEgOBXi.d.mts} +1 -1
  4. package/dist/{adapters-BDQwg236.d.mts.map → adapters-DCEgOBXi.d.mts.map} +1 -1
  5. package/dist/{allowed-origins-BGglilcs.mjs → allowed-origins-GFUVavRj.mjs} +2 -2
  6. package/dist/{allowed-origins-BGglilcs.mjs.map → allowed-origins-GFUVavRj.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +23 -22
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +2 -2
  11. package/dist/api/schemas/index.mjs +5 -5
  12. package/dist/{api-Dz6rgoa3.mjs → api-BvxJmnFY.mjs} +141 -87
  13. package/dist/api-BvxJmnFY.mjs.map +1 -0
  14. package/dist/{api-tokens-BSsQACNe.mjs → api-tokens-xpGqMHrC.mjs} +2 -2
  15. package/dist/{api-tokens-BSsQACNe.mjs.map → api-tokens-xpGqMHrC.mjs.map} +1 -1
  16. package/dist/{apply-B4SIOxR1.mjs → apply-DLmM3R7f.mjs} +25 -21
  17. package/dist/apply-DLmM3R7f.mjs.map +1 -0
  18. package/dist/{config-it29yDLA.mjs → artifact-fetch-P2JXVwOq.mjs} +8 -199
  19. package/dist/artifact-fetch-P2JXVwOq.mjs.map +1 -0
  20. package/dist/astro/index.d.mts +12 -12
  21. package/dist/astro/index.d.mts.map +1 -1
  22. package/dist/astro/index.mjs +37 -11
  23. package/dist/astro/index.mjs.map +1 -1
  24. package/dist/astro/middleware/auth.d.mts +10 -10
  25. package/dist/astro/middleware/auth.mjs +6 -6
  26. package/dist/astro/middleware/media-usage-write-fence.mjs +3 -3
  27. package/dist/astro/middleware/redirect.mjs +7 -5
  28. package/dist/astro/middleware/redirect.mjs.map +1 -1
  29. package/dist/astro/middleware/request-context.mjs +3 -3
  30. package/dist/astro/middleware/setup.mjs +1 -1
  31. package/dist/astro/middleware.d.mts +10 -10
  32. package/dist/astro/middleware.d.mts.map +1 -1
  33. package/dist/astro/middleware.mjs +154 -125
  34. package/dist/astro/middleware.mjs.map +1 -1
  35. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
  36. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
  37. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
  38. package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
  39. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  40. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -9
  41. package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -9
  42. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -9
  43. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +16 -16
  44. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +16 -16
  45. package/dist/astro/routes/api/admin/bylines/index.mjs +16 -16
  46. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +11 -11
  47. package/dist/astro/routes/api/admin/comments/_id_.mjs +3 -3
  48. package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
  49. package/dist/astro/routes/api/admin/comments/counts.mjs +3 -3
  50. package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
  51. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  52. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  53. package/dist/astro/routes/api/admin/media-usage/activation.mjs +13 -13
  54. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +15 -15
  55. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +15 -15
  56. package/dist/astro/routes/api/admin/media-usage/progress.mjs +13 -13
  57. package/dist/astro/routes/api/admin/media-usage/repair.mjs +16 -16
  58. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +15 -15
  59. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +15 -15
  60. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  61. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  62. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +56 -53
  63. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +56 -53
  65. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +54 -51
  67. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
  69. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +54 -51
  70. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +55 -52
  72. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +55 -52
  74. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/index.mjs +54 -51
  76. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +54 -51
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +55 -52
  81. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +54 -51
  83. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +55 -52
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +56 -53
  87. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +5 -4
  89. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +56 -53
  91. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +55 -52
  93. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs +54 -51
  95. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +54 -51
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  99. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +54 -51
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +1 -1
  102. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  103. package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
  104. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  105. package/dist/astro/routes/api/admin/users/index.mjs +6 -6
  106. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  107. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  108. package/dist/astro/routes/api/auth/invite/complete.mjs +11 -11
  109. package/dist/astro/routes/api/auth/invite/index.mjs +8 -8
  110. package/dist/astro/routes/api/auth/invite/register-options.mjs +10 -10
  111. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  112. package/dist/astro/routes/api/auth/magic-link/send.mjs +10 -10
  113. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  114. package/dist/astro/routes/api/auth/me.mjs +7 -7
  115. package/dist/astro/routes/api/auth/mode.mjs +2 -2
  116. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  117. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  118. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
  119. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  120. package/dist/astro/routes/api/auth/passkey/options.mjs +12 -12
  121. package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -10
  122. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -11
  123. package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -11
  124. package/dist/astro/routes/api/auth/signup/complete.mjs +11 -11
  125. package/dist/astro/routes/api/auth/signup/request.mjs +10 -10
  126. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  127. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  128. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +11 -11
  129. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  130. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
  131. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +13 -8
  132. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  133. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  134. package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts +10 -0
  135. package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts.map +1 -0
  136. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +66 -0
  137. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs.map +1 -0
  138. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
  139. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -11
  140. package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts.map +1 -1
  141. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +14 -9
  142. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  143. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +19 -17
  144. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  145. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +19 -17
  146. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  147. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  148. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  149. package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
  150. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +15 -8
  151. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  152. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +15 -14
  153. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  154. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  155. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
  156. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +13 -8
  157. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  158. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  159. package/dist/astro/routes/api/content/_collection_/_id_.mjs +23 -11
  160. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  161. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  162. package/dist/astro/routes/api/content/_collection_/index.mjs +14 -9
  163. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  164. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
  165. package/dist/astro/routes/api/dashboard.mjs +6 -6
  166. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  167. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  168. package/dist/astro/routes/api/import/probe.mjs +16 -16
  169. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  170. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  171. package/dist/astro/routes/api/import/wordpress/execute.mjs +14 -13
  172. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  173. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  174. package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
  175. package/dist/astro/routes/api/import/wordpress/prepare.mjs +10 -10
  176. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  177. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +13 -13
  178. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  179. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +16 -16
  180. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  181. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +27 -26
  182. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  183. package/dist/astro/routes/api/manifest.mjs +4 -4
  184. package/dist/astro/routes/api/mcp.mjs +71 -55
  185. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  186. package/dist/astro/routes/api/media/_id_/confirm.mjs +10 -10
  187. package/dist/astro/routes/api/media/_id_/replace.mjs +8 -8
  188. package/dist/astro/routes/api/media/_id_/upload.mjs +5 -5
  189. package/dist/astro/routes/api/media/_id_/usage.mjs +18 -18
  190. package/dist/astro/routes/api/media/_id_.mjs +17 -17
  191. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  192. package/dist/astro/routes/api/media/folders/_id_.mjs +8 -8
  193. package/dist/astro/routes/api/media/folders/index.mjs +8 -8
  194. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  195. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  196. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  197. package/dist/astro/routes/api/media/upload-url.mjs +9 -9
  198. package/dist/astro/routes/api/media.mjs +21 -21
  199. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -9
  200. package/dist/astro/routes/api/menus/_name_/items.mjs +9 -9
  201. package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -9
  202. package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -9
  203. package/dist/astro/routes/api/menus/_name_.mjs +9 -9
  204. package/dist/astro/routes/api/menus/index.mjs +9 -9
  205. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  206. package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
  207. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  208. package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
  209. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  210. package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
  211. package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
  212. package/dist/astro/routes/api/oauth/token.mjs +5 -5
  213. package/dist/astro/routes/api/openapi.json.mjs +84 -18
  214. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  215. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  216. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -11
  217. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  218. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -11
  219. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  220. package/dist/astro/routes/api/redirects/_id_.mjs +13 -12
  221. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  222. package/dist/astro/routes/api/redirects/index.mjs +13 -12
  223. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  224. package/dist/astro/routes/api/relations/_id_/index.mjs +19 -17
  225. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  226. package/dist/astro/routes/api/relations/_id_/translations.mjs +14 -12
  227. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  228. package/dist/astro/routes/api/relations/index.mjs +19 -17
  229. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  230. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  231. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  232. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +54 -51
  233. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  234. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +54 -51
  235. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  236. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +54 -51
  237. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  238. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +54 -51
  239. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/schema/collections/index.mjs +54 -51
  241. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  242. package/dist/astro/routes/api/schema/collections/reorder.mjs +54 -51
  243. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  244. package/dist/astro/routes/api/schema/index.mjs +13 -11
  245. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  246. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +54 -51
  247. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  248. package/dist/astro/routes/api/schema/orphans/index.mjs +54 -51
  249. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  250. package/dist/astro/routes/api/search/enable.mjs +12 -11
  251. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  252. package/dist/astro/routes/api/search/index.mjs +11 -10
  253. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  254. package/dist/astro/routes/api/search/rebuild.mjs +12 -11
  255. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  256. package/dist/astro/routes/api/search/stats.mjs +7 -6
  257. package/dist/astro/routes/api/search/stats.mjs.map +1 -1
  258. package/dist/astro/routes/api/search/suggest.mjs +11 -10
  259. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  260. package/dist/astro/routes/api/sections/_slug_.mjs +11 -10
  261. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  262. package/dist/astro/routes/api/sections/index.mjs +11 -10
  263. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  264. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -6
  265. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs.map +1 -1
  266. package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -5
  267. package/dist/astro/routes/api/settings/backups/archives/index.mjs.map +1 -1
  268. package/dist/astro/routes/api/settings/backups/export.mjs +7 -6
  269. package/dist/astro/routes/api/settings/backups/export.mjs.map +1 -1
  270. package/dist/astro/routes/api/settings/backups/index.mjs +8 -7
  271. package/dist/astro/routes/api/settings/backups/index.mjs.map +1 -1
  272. package/dist/astro/routes/api/settings/email.mjs +4 -4
  273. package/dist/astro/routes/api/settings.mjs +14 -14
  274. package/dist/astro/routes/api/setup/admin-verify.mjs +12 -12
  275. package/dist/astro/routes/api/setup/admin.mjs +11 -11
  276. package/dist/astro/routes/api/setup/dev-bypass.mjs +33 -31
  277. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  278. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  279. package/dist/astro/routes/api/setup/index.mjs +33 -31
  280. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  281. package/dist/astro/routes/api/setup/status.mjs +3 -3
  282. package/dist/astro/routes/api/snapshot.mjs +8 -7
  283. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  284. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +16 -15
  285. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  286. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -15
  287. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  288. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -15
  289. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  290. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -15
  291. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  292. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +15 -14
  293. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
  294. package/dist/astro/routes/api/taxonomies/_name_.mjs +16 -15
  295. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
  296. package/dist/astro/routes/api/taxonomies/index.mjs +16 -15
  297. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  298. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  299. package/dist/astro/routes/api/typegen.mjs +4 -4
  300. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  301. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  302. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  303. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  304. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +12 -12
  305. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +12 -12
  306. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
  307. package/dist/astro/routes/api/widget-areas/index.mjs +12 -12
  308. package/dist/astro/routes/api/widget-components.mjs +2 -2
  309. package/dist/astro/routes/robots.txt.mjs +6 -6
  310. package/dist/astro/routes/sitemap-_collection_.xml.mjs +11 -10
  311. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  312. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  313. package/dist/astro/types.d.mts +32 -17
  314. package/dist/astro/types.d.mts.map +1 -1
  315. package/dist/auth/providers/github.d.mts +1 -1
  316. package/dist/auth/providers/google.d.mts +1 -1
  317. package/dist/{authorize-Bkf_UHhD.mjs → authorize-C2QHlWSS.mjs} +2 -2
  318. package/dist/{authorize-Bkf_UHhD.mjs.map → authorize-C2QHlWSS.mjs.map} +1 -1
  319. package/dist/{backup-rwVAl9NI.mjs → backup-oS8ft5Cm.mjs} +5 -5
  320. package/dist/{backup-rwVAl9NI.mjs.map → backup-oS8ft5Cm.mjs.map} +1 -1
  321. package/dist/{bundle-C8S2Zl6U.mjs → bundle-CL0JjIPx.mjs} +4 -4
  322. package/dist/{bundle-C8S2Zl6U.mjs.map → bundle-CL0JjIPx.mjs.map} +1 -1
  323. package/dist/{byline-DuhF7NWl.mjs → byline-Vdi85CsZ.mjs} +6 -6
  324. package/dist/{byline-DuhF7NWl.mjs.map → byline-Vdi85CsZ.mjs.map} +1 -1
  325. package/dist/{byline-fields-BovY4KYM.mjs → byline-fields-DPVRFMz2.mjs} +2 -2
  326. package/dist/{byline-fields-BovY4KYM.mjs.map → byline-fields-DPVRFMz2.mjs.map} +1 -1
  327. package/dist/{byline-registry-Bpu9-MVs.mjs → byline-registry-BxDGIO0I.mjs} +2 -2
  328. package/dist/{byline-registry-Bpu9-MVs.mjs.map → byline-registry-BxDGIO0I.mjs.map} +1 -1
  329. package/dist/{bylines-CJ5nd6Lw.mjs → bylines-BX8QhcTk.mjs} +7 -7
  330. package/dist/{bylines-CJ5nd6Lw.mjs.map → bylines-BX8QhcTk.mjs.map} +1 -1
  331. package/dist/{bylines-RwBAeOF1.mjs → bylines-w-E1IEQd.mjs} +3 -3
  332. package/dist/{bylines-RwBAeOF1.mjs.map → bylines-w-E1IEQd.mjs.map} +1 -1
  333. package/dist/{cache-BF5Kvn59.mjs → cache--7HKu5Xm.mjs} +4 -4
  334. package/dist/{cache-BF5Kvn59.mjs.map → cache--7HKu5Xm.mjs.map} +1 -1
  335. package/dist/{capture-triggers-CNW1q3HK.mjs → capture-triggers-CeAsC76Z.mjs} +2 -2
  336. package/dist/{capture-triggers-CNW1q3HK.mjs.map → capture-triggers-CeAsC76Z.mjs.map} +1 -1
  337. package/dist/{challenge-store-DQN_Yrck.mjs → challenge-store-BIOak-tp.mjs} +1 -1
  338. package/dist/{challenge-store-DQN_Yrck.mjs.map → challenge-store-BIOak-tp.mjs.map} +1 -1
  339. package/dist/{chrome-tags-D8fiZG94.mjs → chrome-tags-DzDQBCjX.mjs} +1 -1
  340. package/dist/{chrome-tags-D8fiZG94.mjs.map → chrome-tags-DzDQBCjX.mjs.map} +1 -1
  341. package/dist/{chunks-C4szrD8o.mjs → chunks-VG_tyqnP.mjs} +2 -2
  342. package/dist/{chunks-C4szrD8o.mjs.map → chunks-VG_tyqnP.mjs.map} +1 -1
  343. package/dist/cli/index.mjs +66 -38
  344. package/dist/cli/index.mjs.map +1 -1
  345. package/dist/client/cf-access.d.mts +1 -1
  346. package/dist/client/index.d.mts +17 -7
  347. package/dist/client/index.d.mts.map +1 -1
  348. package/dist/client/index.mjs +17 -12
  349. package/dist/client/index.mjs.map +1 -1
  350. package/dist/{collection-deletion-Bj07NHbj.mjs → collection-deletion-BCwaWTDw.mjs} +4 -4
  351. package/dist/{collection-deletion-Bj07NHbj.mjs.map → collection-deletion-BCwaWTDw.mjs.map} +1 -1
  352. package/dist/collection-slugs-cache-7lTmNzeA.mjs +85 -0
  353. package/dist/collection-slugs-cache-7lTmNzeA.mjs.map +1 -0
  354. package/dist/{comment-reaction-BhrvSHml.mjs → comment-reaction-CDyvPQRj.mjs} +2 -2
  355. package/dist/{comment-reaction-BhrvSHml.mjs.map → comment-reaction-CDyvPQRj.mjs.map} +1 -1
  356. package/dist/{comments-Ct4ensnf.mjs → comments-VzmVLyaC.mjs} +1 -1
  357. package/dist/{comments-Ct4ensnf.mjs.map → comments-VzmVLyaC.mjs.map} +1 -1
  358. package/dist/{components-DJbo1z0S.mjs → components-CL6Wkdk-.mjs} +1 -1
  359. package/dist/{components-DJbo1z0S.mjs.map → components-CL6Wkdk-.mjs.map} +1 -1
  360. package/dist/config--eWjQJE5.mjs +217 -0
  361. package/dist/config--eWjQJE5.mjs.map +1 -0
  362. package/dist/{index-BJNMCWmu.d.mts → config-CGAhyOjP.d.mts} +138 -47
  363. package/dist/config-CGAhyOjP.d.mts.map +1 -0
  364. package/dist/{config-B9eZ340f.d.mts → config-ChFzshGd.d.mts} +1 -1
  365. package/dist/{config-B9eZ340f.d.mts.map → config-ChFzshGd.d.mts.map} +1 -1
  366. package/dist/{content-DjvM0T92.mjs → content-CNfMWuhY.mjs} +121 -5
  367. package/dist/content-CNfMWuhY.mjs.map +1 -0
  368. package/dist/{content-list-query-Btqd4uV2.d.mts → content-list-query-B8d4UQp9.d.mts} +1 -1
  369. package/dist/{content-list-query-Btqd4uV2.d.mts.map → content-list-query-B8d4UQp9.d.mts.map} +1 -1
  370. package/dist/{content-refresh-Bwp-8yGy.mjs → content-refresh-GTMyi2Xy.mjs} +8 -8
  371. package/dist/{content-refresh-Bwp-8yGy.mjs.map → content-refresh-GTMyi2Xy.mjs.map} +1 -1
  372. package/dist/{content-repair-Czdp7jz5.mjs → content-repair-CIMt5C0U.mjs} +4 -4
  373. package/dist/{content-repair-Czdp7jz5.mjs.map → content-repair-CIMt5C0U.mjs.map} +1 -1
  374. package/dist/{context-CX6gxOLW.mjs → context-C9PB8vGd.mjs} +265 -25
  375. package/dist/context-C9PB8vGd.mjs.map +1 -0
  376. package/dist/{cron-C6o7VppJ.mjs → cron-DHAy9oyq.mjs} +1 -1
  377. package/dist/{cron-C6o7VppJ.mjs.map → cron-DHAy9oyq.mjs.map} +1 -1
  378. package/dist/{dashboard-C2kTeeRI.mjs → dashboard-BNSvAN8A.mjs} +4 -4
  379. package/dist/{dashboard-C2kTeeRI.mjs.map → dashboard-BNSvAN8A.mjs.map} +1 -1
  380. package/dist/db/index.d.mts +3 -3
  381. package/dist/db/index.mjs +2 -2
  382. package/dist/db/libsql-migrations.d.mts +1 -1
  383. package/dist/db/libsql-migrations.mjs +5 -5
  384. package/dist/db/libsql.d.mts +1 -1
  385. package/dist/db/postgres-migrations.d.mts +1 -1
  386. package/dist/db/postgres-migrations.mjs +5 -5
  387. package/dist/db/postgres.d.mts +1 -1
  388. package/dist/db/sqlite-migrations.d.mts +1 -1
  389. package/dist/db/sqlite-migrations.mjs +5 -5
  390. package/dist/db/sqlite.d.mts +1 -1
  391. package/dist/db/sqlite.mjs +1 -1
  392. package/dist/{default-Clra32mw.mjs → default-ByZ0JqZo.mjs} +1 -1
  393. package/dist/{default-Clra32mw.mjs.map → default-ByZ0JqZo.mjs.map} +1 -1
  394. package/dist/{deferred-tasks-CvDETTJO.d.mts → deferred-tasks-Cu4NSJpa.d.mts} +1 -1
  395. package/dist/{deferred-tasks-CvDETTJO.d.mts.map → deferred-tasks-Cu4NSJpa.d.mts.map} +1 -1
  396. package/dist/{dev-typegen-DzOPfsNj.mjs → dev-typegen-DHT7lcMU.mjs} +1 -1
  397. package/dist/{dev-typegen-DzOPfsNj.mjs.map → dev-typegen-DHT7lcMU.mjs.map} +1 -1
  398. package/dist/{device-flow-D2oCWvLJ.mjs → device-flow-Cf6bhCCT.mjs} +4 -4
  399. package/dist/{device-flow-D2oCWvLJ.mjs.map → device-flow-Cf6bhCCT.mjs.map} +1 -1
  400. package/dist/{dialect-helpers-BSbfaO3F.mjs → dialect-helpers-BcQvkHgn.mjs} +83 -2
  401. package/dist/dialect-helpers-BcQvkHgn.mjs.map +1 -0
  402. package/dist/{direct-executor-Bfa5_ToE.mjs → direct-executor-yAyUGSqB.mjs} +3 -3
  403. package/dist/{direct-executor-Bfa5_ToE.mjs.map → direct-executor-yAyUGSqB.mjs.map} +1 -1
  404. package/dist/{dist-89xCrGqi.mjs → dist-BAsh8dbf.mjs} +1 -1
  405. package/dist/{dist-89xCrGqi.mjs.map → dist-BAsh8dbf.mjs.map} +1 -1
  406. package/dist/{email-console-Dzb6uGYa.mjs → email-console-DNup1Fku.mjs} +1 -1
  407. package/dist/{email-console-Dzb6uGYa.mjs.map → email-console-DNup1Fku.mjs.map} +1 -1
  408. package/dist/{enrich-BX0IDp4z.mjs → enrich-t2Xvjdqa.mjs} +3 -3
  409. package/dist/{enrich-BX0IDp4z.mjs.map → enrich-t2Xvjdqa.mjs.map} +1 -1
  410. package/dist/entry-lock-BEr8gDkG.mjs +163 -0
  411. package/dist/entry-lock-BEr8gDkG.mjs.map +1 -0
  412. package/dist/{relations-DnRK4YIT.d.mts → entry-lock-CGAtrwAR.d.mts} +92 -37
  413. package/dist/entry-lock-CGAtrwAR.d.mts.map +1 -0
  414. package/dist/{redirects-BLNOWQTn.mjs → entry-lock-DIYHAaSw.mjs} +57 -14
  415. package/dist/entry-lock-DIYHAaSw.mjs.map +1 -0
  416. package/dist/entry-locks-BEcX7ET0.mjs +167 -0
  417. package/dist/entry-locks-BEcX7ET0.mjs.map +1 -0
  418. package/dist/{error-DFrQjppn.mjs → error-BDcFyoRt.mjs} +2 -2
  419. package/dist/{error-DFrQjppn.mjs.map → error-BDcFyoRt.mjs.map} +1 -1
  420. package/dist/{errors-DsVoDUjJ.mjs → errors-DvMdNrgf.mjs} +8 -1
  421. package/dist/errors-DvMdNrgf.mjs.map +1 -0
  422. package/dist/{escape-HmHTC1Is.mjs → escape-B3asJC6W.mjs} +1 -1
  423. package/dist/{escape-HmHTC1Is.mjs.map → escape-B3asJC6W.mjs.map} +1 -1
  424. package/dist/{field-defs-cache-BM4SIRqH.mjs → field-defs-cache-Cf5FHK0M.mjs} +5 -5
  425. package/dist/{field-defs-cache-BM4SIRqH.mjs.map → field-defs-cache-Cf5FHK0M.mjs.map} +1 -1
  426. package/dist/{fts-manager-Do1BlW2r.mjs → fts-manager-iddym8cd.mjs} +4 -4
  427. package/dist/{fts-manager-Do1BlW2r.mjs.map → fts-manager-iddym8cd.mjs.map} +1 -1
  428. package/dist/{hash-3JJPlHF2.mjs → hash-BRweX6jz.mjs} +1 -1
  429. package/dist/{hash-3JJPlHF2.mjs.map → hash-BRweX6jz.mjs.map} +1 -1
  430. package/dist/{hook-result-DCh2WUpe.d.mts → hook-result-BrshYHLx.d.mts} +1 -1
  431. package/dist/{hook-result-DCh2WUpe.d.mts.map → hook-result-BrshYHLx.d.mts.map} +1 -1
  432. package/dist/{hreflang-B6hbAuuO.d.mts → hreflang-CQpu5bMy.d.mts} +2 -2
  433. package/dist/{hreflang-B6hbAuuO.d.mts.map → hreflang-CQpu5bMy.d.mts.map} +1 -1
  434. package/dist/{hreflang-DQbPZliA.mjs → hreflang-DshnweTC.mjs} +9 -8
  435. package/dist/{hreflang-DQbPZliA.mjs.map → hreflang-DshnweTC.mjs.map} +1 -1
  436. package/dist/{identity-DksvEazf.mjs → identity-CjGKDq8J.mjs} +3 -3
  437. package/dist/{identity-DksvEazf.mjs.map → identity-CjGKDq8J.mjs.map} +1 -1
  438. package/dist/{import-CJpaBBBT.mjs → import-D96g2otw.mjs} +5 -5
  439. package/dist/{import-CJpaBBBT.mjs.map → import-D96g2otw.mjs.map} +1 -1
  440. package/dist/{index-Du8K7bWa.d.mts → index-1ECYpfiF.d.mts} +3 -3
  441. package/dist/{index-Du8K7bWa.d.mts.map → index-1ECYpfiF.d.mts.map} +1 -1
  442. package/dist/index.d.mts +22 -22
  443. package/dist/index.mjs +81 -78
  444. package/dist/{init-lock-DJkX6Hto.mjs → init-lock-CFNBe_iH.mjs} +1 -1
  445. package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-CFNBe_iH.mjs.map} +1 -1
  446. package/dist/{load-CawHjTOH.mjs → load-DPtY9cZo.mjs} +2 -2
  447. package/dist/{load-CawHjTOH.mjs.map → load-DPtY9cZo.mjs.map} +1 -1
  448. package/dist/{loader-Z8vl7zTq.mjs → loader-WJi6GFRn.mjs} +46 -8
  449. package/dist/loader-WJi6GFRn.mjs.map +1 -0
  450. package/dist/{manifest-builder-COtzuca2.mjs → manifest-builder-BfNlGQIA.mjs} +2 -2
  451. package/dist/{manifest-builder-COtzuca2.mjs.map → manifest-builder-BfNlGQIA.mjs.map} +1 -1
  452. package/dist/{manifest-schema-BNWwR8Vd.mjs → manifest-schema-CILooI5J.mjs} +1 -1
  453. package/dist/{manifest-schema-BNWwR8Vd.mjs.map → manifest-schema-CILooI5J.mjs.map} +1 -1
  454. package/dist/media/image-endpoint.mjs +1 -1
  455. package/dist/media/index.d.mts +1 -1
  456. package/dist/media/index.mjs +3 -3
  457. package/dist/media/local-runtime.d.mts +12 -12
  458. package/dist/media/local-runtime.mjs +5 -5
  459. package/dist/{media-BHjus86Y.mjs → media-C1EIZKh1.mjs} +1 -1
  460. package/dist/{media-BHjus86Y.mjs.map → media-C1EIZKh1.mjs.map} +1 -1
  461. package/dist/{media-allowlist-CoTBWoDp.mjs → media-allowlist-elXJgb_K.mjs} +2 -2
  462. package/dist/{media-allowlist-CoTBWoDp.mjs.map → media-allowlist-elXJgb_K.mjs.map} +1 -1
  463. package/dist/{media-folders-BGkATs8n.mjs → media-folders-DASfX_DH.mjs} +1 -1
  464. package/dist/{media-folders-BGkATs8n.mjs.map → media-folders-DASfX_DH.mjs.map} +1 -1
  465. package/dist/{media-upload-BCidR-EY.mjs → media-upload-C7_AQJ5v.mjs} +8 -8
  466. package/dist/{media-upload-BCidR-EY.mjs.map → media-upload-C7_AQJ5v.mjs.map} +1 -1
  467. package/dist/{media-url-DHoPr0hq.mjs → media-url-8dVl1loq.mjs} +19 -2
  468. package/dist/media-url-8dVl1loq.mjs.map +1 -0
  469. package/dist/{media-usage-CdY5jhSR.mjs → media-usage-C1EswMTq.mjs} +9 -9
  470. package/dist/{media-usage-CdY5jhSR.mjs.map → media-usage-C1EswMTq.mjs.map} +1 -1
  471. package/dist/{media-usage-activation-BgeMtK5C.mjs → media-usage-activation-CrHNltlL.mjs} +3 -3
  472. package/dist/{media-usage-activation-BgeMtK5C.mjs.map → media-usage-activation-CrHNltlL.mjs.map} +1 -1
  473. package/dist/{media-usage-work-D6D9sMCA.mjs → media-usage-work-C5B1zT1c.mjs} +2 -2
  474. package/dist/{media-usage-work-D6D9sMCA.mjs.map → media-usage-work-C5B1zT1c.mjs.map} +1 -1
  475. package/dist/{media-usage-work-CnGCdHxx.mjs → media-usage-work-IkQx_Yz6.mjs} +4 -4
  476. package/dist/{media-usage-work-CnGCdHxx.mjs.map → media-usage-work-IkQx_Yz6.mjs.map} +1 -1
  477. package/dist/{media-usage-write-fence-hjeD4u7s.mjs → media-usage-write-fence-B9anjOSg.mjs} +3 -3
  478. package/dist/{media-usage-write-fence-hjeD4u7s.mjs.map → media-usage-write-fence-B9anjOSg.mjs.map} +1 -1
  479. package/dist/{menus-6qSwTNxG.mjs → menus-D8mC4eaN.mjs} +115 -136
  480. package/dist/menus-D8mC4eaN.mjs.map +1 -0
  481. package/dist/{menus-uvPLXMZf.mjs → menus-UdwjHZJC.mjs} +11 -3
  482. package/dist/{menus-uvPLXMZf.mjs.map → menus-UdwjHZJC.mjs.map} +1 -1
  483. package/dist/migrations/index.d.mts +1 -1
  484. package/dist/migrations/index.mjs +4 -4
  485. package/dist/{mime-CUIG6x84.mjs → mime-DYpsOAny.mjs} +1 -1
  486. package/dist/{mime-CUIG6x84.mjs.map → mime-DYpsOAny.mjs.map} +1 -1
  487. package/dist/{mode-DN_WneRx.mjs → mode-Dm4BHhRH.mjs} +1 -1
  488. package/dist/{mode-DN_WneRx.mjs.map → mode-Dm4BHhRH.mjs.map} +1 -1
  489. package/dist/{node-sqlite-compat-BuJXIeMz.mjs → node-sqlite-compat-2sezm-Zd.mjs} +1 -1
  490. package/dist/{node-sqlite-compat-BuJXIeMz.mjs.map → node-sqlite-compat-2sezm-Zd.mjs.map} +1 -1
  491. package/dist/{normalize-C2xNjTSG.mjs → normalize-4nkKGsuW.mjs} +1 -1
  492. package/dist/{normalize-C2xNjTSG.mjs.map → normalize-4nkKGsuW.mjs.map} +1 -1
  493. package/dist/{oauth-authorization-Dj6Kwc21.mjs → oauth-authorization-BxE_lURD.mjs} +4 -4
  494. package/dist/{oauth-authorization-Dj6Kwc21.mjs.map → oauth-authorization-BxE_lURD.mjs.map} +1 -1
  495. package/dist/{oauth-clients-FD7I0J8m.mjs → oauth-clients-DJIdOdq0.mjs} +1 -1
  496. package/dist/{oauth-clients-FD7I0J8m.mjs.map → oauth-clients-DJIdOdq0.mjs.map} +1 -1
  497. package/dist/{oauth-state-store-DkmDOmHs.mjs → oauth-state-store-CsdxP57n.mjs} +1 -1
  498. package/dist/{oauth-state-store-DkmDOmHs.mjs.map → oauth-state-store-CsdxP57n.mjs.map} +1 -1
  499. package/dist/{oauth-user-lookup-CvIwGpYd.mjs → oauth-user-lookup-HzzW-dkF.mjs} +1 -1
  500. package/dist/{oauth-user-lookup-CvIwGpYd.mjs.map → oauth-user-lookup-HzzW-dkF.mjs.map} +1 -1
  501. package/dist/object-cache/memory.d.mts +1 -1
  502. package/dist/{options-BHPeIbBd.mjs → options-D1FBiAv1.mjs} +60 -5
  503. package/dist/options-D1FBiAv1.mjs.map +1 -0
  504. package/dist/{options-CYb4y7hM.d.mts → options-D8Y0VHc7.d.mts} +9 -3
  505. package/dist/options-D8Y0VHc7.d.mts.map +1 -0
  506. package/dist/page/index.d.mts +2 -2
  507. package/dist/page/index.d.mts.map +1 -1
  508. package/dist/page/index.mjs +12 -0
  509. package/dist/page/index.mjs.map +1 -1
  510. package/dist/{parse-Ckpg-Qfp.mjs → parse-WRg5C3NX.mjs} +2 -2
  511. package/dist/{parse-Ckpg-Qfp.mjs.map → parse-WRg5C3NX.mjs.map} +1 -1
  512. package/dist/{passkey-config-O_lj3y0k.mjs → passkey-config-qIdO-wF6.mjs} +1 -1
  513. package/dist/{passkey-config-O_lj3y0k.mjs.map → passkey-config-qIdO-wF6.mjs.map} +1 -1
  514. package/dist/{patterns-D9iDO3j8.mjs → patterns-DC8CLptu.mjs} +1 -1
  515. package/dist/{patterns-D9iDO3j8.mjs.map → patterns-DC8CLptu.mjs.map} +1 -1
  516. package/dist/{placeholder-4X9BrRrp.d.mts → placeholder-COrvARyD.d.mts} +1 -1
  517. package/dist/{placeholder-4X9BrRrp.d.mts.map → placeholder-COrvARyD.d.mts.map} +1 -1
  518. package/dist/plugin-types.d.mts +3 -3
  519. package/dist/plugin-types.d.mts.map +1 -1
  520. package/dist/plugin-utils.d.mts +10 -10
  521. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  522. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  523. package/dist/{policy-Dhtwntrt.mjs → policy-XCfb-IE9.mjs} +2 -2
  524. package/dist/{policy-Dhtwntrt.mjs.map → policy-XCfb-IE9.mjs.map} +1 -1
  525. package/dist/{portable-text-U85hOafW.mjs → portable-text-BS3d5n-0.mjs} +1 -1
  526. package/dist/{portable-text-U85hOafW.mjs.map → portable-text-BS3d5n-0.mjs.map} +1 -1
  527. package/dist/{preview-B_vJLvf8.mjs → preview-BxwsGgGp.mjs} +2 -2
  528. package/dist/{preview-B_vJLvf8.mjs.map → preview-BxwsGgGp.mjs.map} +1 -1
  529. package/dist/{protocol-JdD2YhY9.d.mts → protocol-CLn58-nw.d.mts} +2 -2
  530. package/dist/{protocol-JdD2YhY9.d.mts.map → protocol-CLn58-nw.d.mts.map} +1 -1
  531. package/dist/{public-url-CarhZJgf.mjs → public-url-FWWAvnre.mjs} +1 -1
  532. package/dist/{public-url-CarhZJgf.mjs.map → public-url-FWWAvnre.mjs.map} +1 -1
  533. package/dist/{query-BZKZcG5b.mjs → query-DygOte9M.mjs} +25 -16
  534. package/dist/query-DygOte9M.mjs.map +1 -0
  535. package/dist/{query-BndaFxxp.mjs → query-gtXT03Wc.mjs} +4 -4
  536. package/dist/{query-BndaFxxp.mjs.map → query-gtXT03Wc.mjs.map} +1 -1
  537. package/dist/{rate-limit-BZmATC6W.mjs → rate-limit-CQUPm0dh.mjs} +2 -2
  538. package/dist/{rate-limit-BZmATC6W.mjs.map → rate-limit-CQUPm0dh.mjs.map} +1 -1
  539. package/dist/{redirect-CzqnLxK-.mjs → redirect-D1cWafi6.mjs} +1 -1
  540. package/dist/{redirect-CzqnLxK-.mjs.map → redirect-D1cWafi6.mjs.map} +1 -1
  541. package/dist/{redirect-CZkbozu9.mjs → redirect-DId44BS1.mjs} +19 -6
  542. package/dist/redirect-DId44BS1.mjs.map +1 -0
  543. package/dist/{redirects-CqzNM0KM.mjs → redirects-DN-ZE33W.mjs} +5 -5
  544. package/dist/{redirects-CqzNM0KM.mjs.map → redirects-DN-ZE33W.mjs.map} +1 -1
  545. package/dist/{registry-AZAsRsor.mjs → registry-DTqaqxed.mjs} +26 -10
  546. package/dist/registry-DTqaqxed.mjs.map +1 -0
  547. package/dist/{relation-04DfKRTO.mjs → relation-DxgCHOBw.mjs} +2 -2
  548. package/dist/{relation-04DfKRTO.mjs.map → relation-DxgCHOBw.mjs.map} +1 -1
  549. package/dist/{relations-CcFwDJdJ.mjs → relations-KKDSLUwS.mjs} +4 -4
  550. package/dist/{relations-CcFwDJdJ.mjs.map → relations-KKDSLUwS.mjs.map} +1 -1
  551. package/dist/{relations-C4htk5sb.mjs → relations-rOmbndUJ.mjs} +3 -3
  552. package/dist/{relations-C4htk5sb.mjs.map → relations-rOmbndUJ.mjs.map} +1 -1
  553. package/dist/{request-cache-DH9zdCOD.mjs → request-cache-DAZZmesc.mjs} +1 -1
  554. package/dist/{request-cache-DH9zdCOD.mjs.map → request-cache-DAZZmesc.mjs.map} +1 -1
  555. package/dist/request-context.d.mts +1 -1
  556. package/dist/{request-meta-DYxLlnmz.mjs → request-meta-BgjUQLQ-.mjs} +2 -2
  557. package/dist/{request-meta-DYxLlnmz.mjs.map → request-meta-BgjUQLQ-.mjs.map} +1 -1
  558. package/dist/{resolve-prZ3mP7l.mjs → resolve-Cy0aWSRj.mjs} +37 -4
  559. package/dist/resolve-Cy0aWSRj.mjs.map +1 -0
  560. package/dist/{runner-YKfIMnaF.d.mts → runner-CfwysRM0.d.mts} +2 -2
  561. package/dist/{runner-YKfIMnaF.d.mts.map → runner-CfwysRM0.d.mts.map} +1 -1
  562. package/dist/{runner-BLIDKpmA.mjs → runner-nEzvnogG.mjs} +419 -295
  563. package/dist/runner-nEzvnogG.mjs.map +1 -0
  564. package/dist/runtime.d.mts +11 -11
  565. package/dist/runtime.mjs +3 -2
  566. package/dist/runtime.mjs.map +1 -1
  567. package/dist/{schema-CGnBeLiW.mjs → schema-CRu38Pr5.mjs} +3 -3
  568. package/dist/{schema-CGnBeLiW.mjs.map → schema-CRu38Pr5.mjs.map} +1 -1
  569. package/dist/{schema-DYr-Vd-L.mjs → schema-DifxndJx.mjs} +4 -4
  570. package/dist/{schema-DYr-Vd-L.mjs.map → schema-DifxndJx.mjs.map} +1 -1
  571. package/dist/{scopes-BhWvBavj.mjs → scopes-D5A1OZbq.mjs} +3 -3
  572. package/dist/{scopes-BhWvBavj.mjs.map → scopes-D5A1OZbq.mjs.map} +1 -1
  573. package/dist/{search-C-qDk4kx.mjs → search-DEPFSBFq.mjs} +4 -4
  574. package/dist/{search-C-qDk4kx.mjs.map → search-DEPFSBFq.mjs.map} +1 -1
  575. package/dist/{secrets-rEtHt-6z.mjs → secrets-CdfzLdoO.mjs} +3 -3
  576. package/dist/{secrets-rEtHt-6z.mjs.map → secrets-CdfzLdoO.mjs.map} +1 -1
  577. package/dist/{sections-B_nYvlwn.mjs → sections-3X52kmIR.mjs} +2 -2
  578. package/dist/{sections-B_nYvlwn.mjs.map → sections-3X52kmIR.mjs.map} +1 -1
  579. package/dist/seed/index.d.mts +2 -2
  580. package/dist/seed/index.mjs +26 -24
  581. package/dist/seo/index.d.mts +3 -3
  582. package/dist/seo/index.d.mts.map +1 -1
  583. package/dist/seo/index.mjs +18 -19
  584. package/dist/seo/index.mjs.map +1 -1
  585. package/dist/{seo-926NRIgt.mjs → seo-Bw68KxRc.mjs} +2 -2
  586. package/dist/{seo-926NRIgt.mjs.map → seo-Bw68KxRc.mjs.map} +1 -1
  587. package/dist/{seo-CVWkdv6x.mjs → seo-C4AmbsMU.mjs} +3 -2
  588. package/dist/seo-C4AmbsMU.mjs.map +1 -0
  589. package/dist/{service-CJl3ZAYs.mjs → service-J_-Vgo7R.mjs} +2 -2
  590. package/dist/{service-CJl3ZAYs.mjs.map → service-J_-Vgo7R.mjs.map} +1 -1
  591. package/dist/{session-user-BlMgqCHS.mjs → session-user-CbnMMwk6.mjs} +1 -1
  592. package/dist/{session-user-BlMgqCHS.mjs.map → session-user-CbnMMwk6.mjs.map} +1 -1
  593. package/dist/{settings-Cwm6o2jY.mjs → settings-AnEFYICn.mjs} +3 -3
  594. package/dist/{settings-Cwm6o2jY.mjs.map → settings-AnEFYICn.mjs.map} +1 -1
  595. package/dist/{settings--wobrkkC.mjs → settings-DcMjREe5.mjs} +6 -6
  596. package/dist/{settings--wobrkkC.mjs.map → settings-DcMjREe5.mjs.map} +1 -1
  597. package/dist/{setup-complete-DQbClIN2.mjs → setup-complete-BClXXTvr.mjs} +2 -2
  598. package/dist/{setup-complete-DQbClIN2.mjs.map → setup-complete-BClXXTvr.mjs.map} +1 -1
  599. package/dist/{setup-nonce-DZCFS2sn.mjs → setup-nonce-BheRa4RG.mjs} +1 -1
  600. package/dist/{setup-nonce-DZCFS2sn.mjs.map → setup-nonce-BheRa4RG.mjs.map} +1 -1
  601. package/dist/{single-flight-cache-BPuGPdcN.mjs → single-flight-cache-jaswDzmQ.mjs} +2 -2
  602. package/dist/{single-flight-cache-BPuGPdcN.mjs.map → single-flight-cache-jaswDzmQ.mjs.map} +1 -1
  603. package/dist/{site-url-BrxA_E9H.mjs → site-url-Bqf-ea3N.mjs} +3 -3
  604. package/dist/{site-url-BrxA_E9H.mjs.map → site-url-Bqf-ea3N.mjs.map} +1 -1
  605. package/dist/{snapshot--OCDTqdb.mjs → snapshot-C4CtXntb.mjs} +51 -35
  606. package/dist/snapshot-C4CtXntb.mjs.map +1 -0
  607. package/dist/{ssrf-5sIM5jzl.mjs → ssrf-gl4gFNhw.mjs} +148 -91
  608. package/dist/ssrf-gl4gFNhw.mjs.map +1 -0
  609. package/dist/{state-BpFVsJZB.mjs → state-1F6IOhdQ.mjs} +1 -1
  610. package/dist/{state-BpFVsJZB.mjs.map → state-1F6IOhdQ.mjs.map} +1 -1
  611. package/dist/{status-B777-dXz.mjs → status-Cenfk_r5.mjs} +1 -1
  612. package/dist/{status-B777-dXz.mjs.map → status-Cenfk_r5.mjs.map} +1 -1
  613. package/dist/storage/local.d.mts +1 -1
  614. package/dist/storage/local.mjs +1 -1
  615. package/dist/storage/s3.d.mts +1 -1
  616. package/dist/storage/s3.mjs +1 -1
  617. package/dist/{target-BmR0iTwz.mjs → target-CRzeTs8G.mjs} +1 -1
  618. package/dist/{target-BmR0iTwz.mjs.map → target-CRzeTs8G.mjs.map} +1 -1
  619. package/dist/{taxonomies-DkAkMupr.mjs → taxonomies-BOdxuZpV.mjs} +11 -4
  620. package/dist/taxonomies-BOdxuZpV.mjs.map +1 -0
  621. package/dist/{taxonomies-Wfy_Lg12.mjs → taxonomies-NcFDq5Gg.mjs} +23 -14
  622. package/dist/taxonomies-NcFDq5Gg.mjs.map +1 -0
  623. package/dist/{taxonomy-tJepplLL.mjs → taxonomy-DP1vny4K.mjs} +11 -3
  624. package/dist/{taxonomy-tJepplLL.mjs.map → taxonomy-DP1vny4K.mjs.map} +1 -1
  625. package/dist/{tokens-BCO1oruF.mjs → tokens-CDk8ox9p.mjs} +1 -1
  626. package/dist/{tokens-BCO1oruF.mjs.map → tokens-CDk8ox9p.mjs.map} +1 -1
  627. package/dist/{transport-xh6YKW2G.d.mts → transport-BVn4tVb9.d.mts} +1 -1
  628. package/dist/{transport-xh6YKW2G.d.mts.map → transport-BVn4tVb9.d.mts.map} +1 -1
  629. package/dist/{transport-Dr3qtwXC.mjs → transport-DP0JI-8i.mjs} +1 -1
  630. package/dist/{transport-Dr3qtwXC.mjs.map → transport-DP0JI-8i.mjs.map} +1 -1
  631. package/dist/{trusted-proxy-BR5F1Otp.mjs → trusted-proxy-BTM6UxqD.mjs} +1 -1
  632. package/dist/{trusted-proxy-BR5F1Otp.mjs.map → trusted-proxy-BTM6UxqD.mjs.map} +1 -1
  633. package/dist/{types-CXFkwEGC.d.mts → types-2n848aVW.d.mts} +1 -1
  634. package/dist/{types-CXFkwEGC.d.mts.map → types-2n848aVW.d.mts.map} +1 -1
  635. package/dist/{types-75KIqzL9.mjs → types-BMXnRIrX.mjs} +4 -2
  636. package/dist/types-BMXnRIrX.mjs.map +1 -0
  637. package/dist/{types-B6GrPic4.d.mts → types-BouXpOsa.d.mts} +115 -4
  638. package/dist/types-BouXpOsa.d.mts.map +1 -0
  639. package/dist/{types-3qNFPlci.mjs → types-ByG2coLw.mjs} +1 -1
  640. package/dist/{types-3qNFPlci.mjs.map → types-ByG2coLw.mjs.map} +1 -1
  641. package/dist/types-CQPWhPxE.mjs.map +1 -1
  642. package/dist/{types-CDtkNSFQ.d.mts → types-DEfNJ__A.d.mts} +1 -1
  643. package/dist/{types-CDtkNSFQ.d.mts.map → types-DEfNJ__A.d.mts.map} +1 -1
  644. package/dist/{types-xDMtUFnO.d.mts → types-DKcKSbtB.d.mts} +23 -7
  645. package/dist/types-DKcKSbtB.d.mts.map +1 -0
  646. package/dist/{types-C00oyCZp.d.mts → types-DRYs7uTL.d.mts} +1 -1
  647. package/dist/{types-C00oyCZp.d.mts.map → types-DRYs7uTL.d.mts.map} +1 -1
  648. package/dist/{types-DczELMop.d.mts → types-DaEg7KX2.d.mts} +1 -1
  649. package/dist/{types-DczELMop.d.mts.map → types-DaEg7KX2.d.mts.map} +1 -1
  650. package/dist/{types-BuHW4xDE.d.mts → types-LU8utpP_.d.mts} +6 -3
  651. package/dist/types-LU8utpP_.d.mts.map +1 -0
  652. package/dist/{types-CPeXo1wF.d.mts → types-VpYfPUxN.d.mts} +1 -1
  653. package/dist/{types-CPeXo1wF.d.mts.map → types-VpYfPUxN.d.mts.map} +1 -1
  654. package/dist/{types-DM3vioBY.mjs → types-c9GP7Dj5.mjs} +1 -1
  655. package/dist/{types-DM3vioBY.mjs.map → types-c9GP7Dj5.mjs.map} +1 -1
  656. package/dist/{types-FV23hEoW.d.mts → types-tJWDK__M.d.mts} +14 -1
  657. package/dist/types-tJWDK__M.d.mts.map +1 -0
  658. package/dist/{upload-attempts-BsqoQ1fn.mjs → upload-attempts-C6S2y-lp.mjs} +1 -1
  659. package/dist/{upload-attempts-BsqoQ1fn.mjs.map → upload-attempts-C6S2y-lp.mjs.map} +1 -1
  660. package/dist/{url-pattern-D4c2czpJ.mjs → url-pattern-UYtxVTuj.mjs} +1 -1
  661. package/dist/{url-pattern-D4c2czpJ.mjs.map → url-pattern-UYtxVTuj.mjs.map} +1 -1
  662. package/dist/{user-BTZ40aq6.mjs → user-DIsIXogT.mjs} +2 -2
  663. package/dist/{user-BTZ40aq6.mjs.map → user-DIsIXogT.mjs.map} +1 -1
  664. package/dist/{utils-BKvNjjhY.mjs → utils-BicP5Qbg.mjs} +2 -2
  665. package/dist/{utils-BKvNjjhY.mjs.map → utils-BicP5Qbg.mjs.map} +1 -1
  666. package/dist/{validate-DE_LRwo9.mjs → validate-D8VPn4Hv.mjs} +8 -3
  667. package/dist/validate-D8VPn4Hv.mjs.map +1 -0
  668. package/dist/{validate-DUP27OYD.d.mts → validate-Df6Dvwbw.d.mts} +12 -7
  669. package/dist/validate-Df6Dvwbw.d.mts.map +1 -0
  670. package/dist/{validation-BMImFJ11.mjs → validation-CzMJn9Ku.mjs} +13 -11
  671. package/dist/{validation-BMImFJ11.mjs.map → validation-CzMJn9Ku.mjs.map} +1 -1
  672. package/dist/version-CK67_SXX.mjs +7 -0
  673. package/dist/{version-Bii3suaO.mjs.map → version-CK67_SXX.mjs.map} +1 -1
  674. package/dist/{widgets-D3gJ10xU.mjs → widgets-RFVAxQl3.mjs} +5 -5
  675. package/dist/{widgets-D3gJ10xU.mjs.map → widgets-RFVAxQl3.mjs.map} +1 -1
  676. package/dist/{wxr-taxonomies-B2Og_6rU.d.mts → wxr-taxonomies-BX4yQL9s.d.mts} +1 -1
  677. package/dist/{wxr-taxonomies-B2Og_6rU.d.mts.map → wxr-taxonomies-BX4yQL9s.d.mts.map} +1 -1
  678. package/dist/{wxr-taxonomies-Cxngsjwo.mjs → wxr-taxonomies-Csdp7yde.mjs} +4 -4
  679. package/dist/{wxr-taxonomies-Cxngsjwo.mjs.map → wxr-taxonomies-Csdp7yde.mjs.map} +1 -1
  680. package/dist/{zod-generator-BuYSQJB7.mjs → zod-generator-CNRGdnBY.mjs} +3 -3
  681. package/dist/{zod-generator-BuYSQJB7.mjs.map → zod-generator-CNRGdnBY.mjs.map} +1 -1
  682. package/package.json +12 -10
  683. package/src/api/errors.ts +7 -0
  684. package/src/api/handlers/content.ts +66 -79
  685. package/src/api/handlers/entry-lock.ts +206 -0
  686. package/src/api/handlers/manifest.ts +1 -0
  687. package/src/api/handlers/marketplace.ts +28 -20
  688. package/src/api/handlers/menus.ts +9 -0
  689. package/src/api/handlers/registry.ts +13 -8
  690. package/src/api/handlers/revision.ts +2 -1
  691. package/src/api/handlers/seo.ts +10 -1
  692. package/src/api/handlers/snapshot.ts +84 -72
  693. package/src/api/handlers/taxonomies.ts +9 -0
  694. package/src/api/openapi/document.ts +111 -6
  695. package/src/api/schemas/content.ts +8 -0
  696. package/src/api/schemas/entry-lock.ts +48 -0
  697. package/src/api/schemas/index.ts +1 -0
  698. package/src/api/schemas/schema.ts +10 -1
  699. package/src/api/types.ts +2 -0
  700. package/src/astro/integration/index.ts +9 -6
  701. package/src/astro/integration/routes.ts +5 -0
  702. package/src/astro/integration/runtime.ts +13 -5
  703. package/src/astro/integration/vite-config.ts +30 -0
  704. package/src/astro/middleware.ts +16 -0
  705. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +10 -0
  706. package/src/astro/routes/api/content/[collection]/[id]/lock.ts +133 -0
  707. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +11 -1
  708. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +20 -0
  709. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +10 -0
  710. package/src/astro/routes/api/content/[collection]/[id].ts +27 -2
  711. package/src/astro/routes/api/content/[collection]/index.ts +3 -0
  712. package/src/astro/routes/sitemap-[collection].xml.ts +4 -0
  713. package/src/astro/types.ts +13 -3
  714. package/src/cli/commands/content.ts +31 -5
  715. package/src/cli/commands/export-seed.ts +2 -0
  716. package/src/client/index.ts +34 -7
  717. package/src/components/EmDashBodyEnd.astro +4 -1
  718. package/src/components/EmDashBodyStart.astro +4 -1
  719. package/src/components/EmDashHead.astro +35 -16
  720. package/src/components/Gallery.astro +18 -4
  721. package/src/components/InlineEditor.astro +3 -1
  722. package/src/components/InlinePortableTextEditor.tsx +106 -11
  723. package/src/components/PortableText.astro +4 -0
  724. package/src/components/Table.astro +147 -62
  725. package/src/config/errors.ts +13 -0
  726. package/src/content/converters/portable-text-to-prosemirror.ts +26 -2
  727. package/src/content/converters/prosemirror-to-portable-text.ts +35 -6
  728. package/src/content/converters/types.ts +10 -0
  729. package/src/database/dialect-helpers.ts +125 -0
  730. package/src/database/migrations/075_entry_edit_locks.ts +44 -0
  731. package/src/database/migrations/076_collection_nav_group.ts +22 -0
  732. package/src/database/migrations/077_plugin_storage_revisions.ts +89 -0
  733. package/src/database/migrations/runner.ts +6 -0
  734. package/src/database/repositories/content.ts +170 -1
  735. package/src/database/repositories/entry-locks.ts +257 -0
  736. package/src/database/repositories/options.ts +69 -5
  737. package/src/database/repositories/plugin-storage.ts +159 -0
  738. package/src/database/repositories/redirect.ts +17 -6
  739. package/src/database/repositories/taxonomy.ts +8 -0
  740. package/src/database/repositories/types.ts +3 -0
  741. package/src/database/types.ts +15 -1
  742. package/src/emdash-runtime.ts +117 -50
  743. package/src/i18n/resolve.ts +44 -4
  744. package/src/index.ts +14 -0
  745. package/src/loader.ts +35 -4
  746. package/src/mcp/server.ts +23 -5
  747. package/src/media/responsive.ts +23 -0
  748. package/src/media/usage/content-refresh.ts +2 -1
  749. package/src/menus/index.ts +17 -21
  750. package/src/page/seo-contributions.ts +78 -1
  751. package/src/page/seo-panel.ts +47 -0
  752. package/src/plugin-types.ts +9 -0
  753. package/src/plugins/conditional-storage.ts +30 -0
  754. package/src/plugins/context.ts +49 -17
  755. package/src/plugins/hooks.ts +7 -1
  756. package/src/plugins/index.ts +9 -0
  757. package/src/plugins/manager.ts +5 -2
  758. package/src/plugins/sandbox/types.ts +16 -2
  759. package/src/plugins/storage-query.ts +45 -0
  760. package/src/plugins/storage-update.ts +96 -0
  761. package/src/plugins/types.ts +114 -0
  762. package/src/query.ts +29 -3
  763. package/src/registry/config.ts +130 -27
  764. package/src/registry/types.ts +5 -6
  765. package/src/schema/collection-slugs-cache.ts +157 -0
  766. package/src/schema/registry.ts +19 -0
  767. package/src/schema/types.ts +25 -6
  768. package/src/security/ssrf.ts +167 -141
  769. package/src/seed/apply.ts +4 -0
  770. package/src/seed/types.ts +7 -2
  771. package/src/seed/validate.ts +18 -1
  772. package/src/seo/hreflang.ts +1 -0
  773. package/src/seo/index.ts +5 -10
  774. package/src/seo/media-url.ts +26 -0
  775. package/src/taxonomies/term-counts.ts +22 -5
  776. package/dist/api-Dz6rgoa3.mjs.map +0 -1
  777. package/dist/apply-B4SIOxR1.mjs.map +0 -1
  778. package/dist/config-it29yDLA.mjs.map +0 -1
  779. package/dist/content-DjvM0T92.mjs.map +0 -1
  780. package/dist/context-CX6gxOLW.mjs.map +0 -1
  781. package/dist/dialect-helpers-BSbfaO3F.mjs.map +0 -1
  782. package/dist/errors-DsVoDUjJ.mjs.map +0 -1
  783. package/dist/index-BJNMCWmu.d.mts.map +0 -1
  784. package/dist/loader-Z8vl7zTq.mjs.map +0 -1
  785. package/dist/media-url-DHoPr0hq.mjs.map +0 -1
  786. package/dist/menus-6qSwTNxG.mjs.map +0 -1
  787. package/dist/options-BHPeIbBd.mjs.map +0 -1
  788. package/dist/options-CYb4y7hM.d.mts.map +0 -1
  789. package/dist/query-BZKZcG5b.mjs.map +0 -1
  790. package/dist/redirect-CZkbozu9.mjs.map +0 -1
  791. package/dist/redirects-BLNOWQTn.mjs.map +0 -1
  792. package/dist/registry-AZAsRsor.mjs.map +0 -1
  793. package/dist/relations-DnRK4YIT.d.mts.map +0 -1
  794. package/dist/resolve-prZ3mP7l.mjs.map +0 -1
  795. package/dist/runner-BLIDKpmA.mjs.map +0 -1
  796. package/dist/seo-CVWkdv6x.mjs.map +0 -1
  797. package/dist/snapshot--OCDTqdb.mjs.map +0 -1
  798. package/dist/ssrf-5sIM5jzl.mjs.map +0 -1
  799. package/dist/taxonomies-DkAkMupr.mjs.map +0 -1
  800. package/dist/taxonomies-Wfy_Lg12.mjs.map +0 -1
  801. package/dist/types-75KIqzL9.mjs.map +0 -1
  802. package/dist/types-B6GrPic4.d.mts.map +0 -1
  803. package/dist/types-BuHW4xDE.d.mts.map +0 -1
  804. package/dist/types-FV23hEoW.d.mts.map +0 -1
  805. package/dist/types-xDMtUFnO.d.mts.map +0 -1
  806. package/dist/validate-DE_LRwo9.mjs.map +0 -1
  807. package/dist/validate-DUP27OYD.d.mts.map +0 -1
  808. package/dist/version-Bii3suaO.mjs +0 -7
  809. /package/dist/{api-tokens-BfYts-sq.mjs → api-tokens-B_lfpmH3.mjs} +0 -0
  810. /package/dist/{ssrf-Dg3cIT-b.mjs → ssrf-TQhaljuI.mjs} +0 -0
  811. /package/dist/{types-DfuTR6dL.mjs → types-A2cN6a4a.mjs} +0 -0
@@ -1,4 +1,4 @@
1
- import { a as hashApiToken, r as generatePrefixedToken } from "./api-tokens-BfYts-sq.mjs";
1
+ import { a as hashApiToken, r as generatePrefixedToken } from "./api-tokens-B_lfpmH3.mjs";
2
2
  import { ulid } from "ulidx";
3
3
 
4
4
  //#region src/api/handlers/api-tokens.ts
@@ -160,4 +160,4 @@ async function resolveOAuthToken(db, rawToken) {
160
160
 
161
161
  //#endregion
162
162
  export { resolveApiToken as a, handleApiTokenRevoke as i, handleApiTokenCreate as n, resolveOAuthToken as o, handleApiTokenList as r, deleteApiTokensByName as t };
163
- //# sourceMappingURL=api-tokens-BSsQACNe.mjs.map
163
+ //# sourceMappingURL=api-tokens-xpGqMHrC.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-tokens-BSsQACNe.mjs","names":[],"sources":["../src/api/handlers/api-tokens.ts"],"sourcesContent":["/**\n * API token management handlers.\n *\n * Creates, lists, and revokes Personal Access Tokens (PATs).\n * Token format: ec_pat_<base64url>\n * Only the SHA-256 hash is stored — raw token shown once at creation.\n */\n\nimport type { Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { hashApiToken, generatePrefixedToken } from \"../../auth/api-tokens.js\";\nimport type { Database } from \"../../database/types.js\";\nimport type { ApiResult } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ApiTokenInfo {\n\tid: string;\n\tname: string;\n\tprefix: string;\n\tscopes: string[];\n\tuserId: string;\n\texpiresAt: string | null;\n\tlastUsedAt: string | null;\n\tcreatedAt: string;\n}\n\nexport interface ApiTokenCreateResult {\n\t/** The raw token — shown once, never stored */\n\ttoken: string;\n\t/** Token metadata */\n\tinfo: ApiTokenInfo;\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new API token for a user.\n */\nexport async function handleApiTokenCreate(\n\tdb: Kysely<Database>,\n\tuserId: string,\n\tinput: {\n\t\tname: string;\n\t\tscopes: string[];\n\t\texpiresAt?: string;\n\t},\n): Promise<ApiResult<ApiTokenCreateResult>> {\n\ttry {\n\t\tconst id = ulid();\n\t\tconst { raw, hash, prefix } = generatePrefixedToken(\"ec_pat_\");\n\n\t\tawait db\n\t\t\t.insertInto(\"_emdash_api_tokens\")\n\t\t\t.values({\n\t\t\t\tid,\n\t\t\t\tname: input.name,\n\t\t\t\ttoken_hash: hash,\n\t\t\t\tprefix,\n\t\t\t\tuser_id: userId,\n\t\t\t\tscopes: JSON.stringify(input.scopes),\n\t\t\t\texpires_at: input.expiresAt ?? null,\n\t\t\t})\n\t\t\t.execute();\n\n\t\tconst info: ApiTokenInfo = {\n\t\t\tid,\n\t\t\tname: input.name,\n\t\t\tprefix,\n\t\t\tscopes: input.scopes,\n\t\t\tuserId,\n\t\t\texpiresAt: input.expiresAt ?? null,\n\t\t\tlastUsedAt: null,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t};\n\n\t\treturn { success: true, data: { token: raw, info } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"TOKEN_CREATE_ERROR\",\n\t\t\t\tmessage: \"Failed to create API token\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * List all API tokens for a user (never returns the raw token or hash).\n */\nexport async function handleApiTokenList(\n\tdb: Kysely<Database>,\n\tuserId: string,\n): Promise<ApiResult<{ items: ApiTokenInfo[] }>> {\n\ttry {\n\t\tconst rows = await db\n\t\t\t.selectFrom(\"_emdash_api_tokens\")\n\t\t\t.select([\n\t\t\t\t\"id\",\n\t\t\t\t\"name\",\n\t\t\t\t\"prefix\",\n\t\t\t\t\"scopes\",\n\t\t\t\t\"user_id\",\n\t\t\t\t\"expires_at\",\n\t\t\t\t\"last_used_at\",\n\t\t\t\t\"created_at\",\n\t\t\t])\n\t\t\t.where(\"user_id\", \"=\", userId)\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.execute();\n\n\t\tconst items: ApiTokenInfo[] = rows.map((row) => ({\n\t\t\tid: row.id,\n\t\t\tname: row.name,\n\t\t\tprefix: row.prefix,\n\t\t\tscopes: JSON.parse(row.scopes) as string[],\n\t\t\tuserId: row.user_id,\n\t\t\texpiresAt: row.expires_at,\n\t\t\tlastUsedAt: row.last_used_at,\n\t\t\tcreatedAt: row.created_at,\n\t\t}));\n\n\t\treturn { success: true, data: { items } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"TOKEN_LIST_ERROR\",\n\t\t\t\tmessage: \"Failed to list API tokens\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Revoke (delete) an API token.\n */\nexport async function handleApiTokenRevoke(\n\tdb: Kysely<Database>,\n\ttokenId: string,\n\tuserId: string,\n): Promise<ApiResult<{ revoked: boolean }>> {\n\ttry {\n\t\tconst result = await db\n\t\t\t.deleteFrom(\"_emdash_api_tokens\")\n\t\t\t.where(\"id\", \"=\", tokenId)\n\t\t\t.where(\"user_id\", \"=\", userId)\n\t\t\t.executeTakeFirst();\n\n\t\tif (result.numDeletedRows === 0n) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Token not found\" },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: { revoked: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"TOKEN_REVOKE_ERROR\",\n\t\t\t\tmessage: \"Failed to revoke API token\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Delete every token with the given name for a user, returning how many were\n * removed. Token names aren't unique, so this is a bulk delete — used by the\n * dev-bypass flow to keep a single `dev-bypass-token` instead of minting a new\n * one on every reset.\n */\nexport async function deleteApiTokensByName(\n\tdb: Kysely<Database>,\n\tuserId: string,\n\tname: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.deleteFrom(\"_emdash_api_tokens\")\n\t\t.where(\"user_id\", \"=\", userId)\n\t\t.where(\"name\", \"=\", name)\n\t\t.executeTakeFirst();\n\treturn Number(result.numDeletedRows ?? 0n);\n}\n\n/**\n * Resolve a raw API token (ec_pat_...) to a user ID and scopes.\n * Updates last_used_at on successful lookup.\n * Returns null if the token is invalid or expired.\n */\nexport async function resolveApiToken(\n\tdb: Kysely<Database>,\n\trawToken: string,\n): Promise<{ userId: string; scopes: string[] } | null> {\n\tconst hash = hashApiToken(rawToken);\n\n\tconst row = await db\n\t\t.selectFrom(\"_emdash_api_tokens\")\n\t\t.select([\"id\", \"user_id\", \"scopes\", \"expires_at\"])\n\t\t.where(\"token_hash\", \"=\", hash)\n\t\t.executeTakeFirst();\n\n\tif (!row) return null;\n\n\t// Check expiry\n\tif (row.expires_at && new Date(row.expires_at) < new Date()) {\n\t\treturn null;\n\t}\n\n\t// Update last_used_at (fire-and-forget, don't block the request)\n\tdb.updateTable(\"_emdash_api_tokens\")\n\t\t.set({ last_used_at: new Date().toISOString() })\n\t\t.where(\"id\", \"=\", row.id)\n\t\t.execute()\n\t\t.catch(() => {}); // Non-critical, swallow errors\n\n\treturn {\n\t\tuserId: row.user_id,\n\t\tscopes: JSON.parse(row.scopes) as string[],\n\t};\n}\n\n/**\n * Resolve an OAuth access token (ec_oat_...) to a user ID and scopes.\n * Returns null if the token is invalid or expired.\n */\nexport async function resolveOAuthToken(\n\tdb: Kysely<Database>,\n\trawToken: string,\n): Promise<{ userId: string; scopes: string[] } | null> {\n\tconst hash = hashApiToken(rawToken);\n\n\tconst row = await db\n\t\t.selectFrom(\"_emdash_oauth_tokens\")\n\t\t.select([\"user_id\", \"scopes\", \"expires_at\", \"token_type\"])\n\t\t.where(\"token_hash\", \"=\", hash)\n\t\t.where(\"token_type\", \"=\", \"access\")\n\t\t.executeTakeFirst();\n\n\tif (!row) return null;\n\n\t// Check expiry\n\tif (new Date(row.expires_at) < new Date()) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tuserId: row.user_id,\n\t\tscopes: JSON.parse(row.scopes) as string[],\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"api-tokens-xpGqMHrC.mjs","names":[],"sources":["../src/api/handlers/api-tokens.ts"],"sourcesContent":["/**\n * API token management handlers.\n *\n * Creates, lists, and revokes Personal Access Tokens (PATs).\n * Token format: ec_pat_<base64url>\n * Only the SHA-256 hash is stored — raw token shown once at creation.\n */\n\nimport type { Kysely } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { hashApiToken, generatePrefixedToken } from \"../../auth/api-tokens.js\";\nimport type { Database } from \"../../database/types.js\";\nimport type { ApiResult } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ApiTokenInfo {\n\tid: string;\n\tname: string;\n\tprefix: string;\n\tscopes: string[];\n\tuserId: string;\n\texpiresAt: string | null;\n\tlastUsedAt: string | null;\n\tcreatedAt: string;\n}\n\nexport interface ApiTokenCreateResult {\n\t/** The raw token — shown once, never stored */\n\ttoken: string;\n\t/** Token metadata */\n\tinfo: ApiTokenInfo;\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new API token for a user.\n */\nexport async function handleApiTokenCreate(\n\tdb: Kysely<Database>,\n\tuserId: string,\n\tinput: {\n\t\tname: string;\n\t\tscopes: string[];\n\t\texpiresAt?: string;\n\t},\n): Promise<ApiResult<ApiTokenCreateResult>> {\n\ttry {\n\t\tconst id = ulid();\n\t\tconst { raw, hash, prefix } = generatePrefixedToken(\"ec_pat_\");\n\n\t\tawait db\n\t\t\t.insertInto(\"_emdash_api_tokens\")\n\t\t\t.values({\n\t\t\t\tid,\n\t\t\t\tname: input.name,\n\t\t\t\ttoken_hash: hash,\n\t\t\t\tprefix,\n\t\t\t\tuser_id: userId,\n\t\t\t\tscopes: JSON.stringify(input.scopes),\n\t\t\t\texpires_at: input.expiresAt ?? null,\n\t\t\t})\n\t\t\t.execute();\n\n\t\tconst info: ApiTokenInfo = {\n\t\t\tid,\n\t\t\tname: input.name,\n\t\t\tprefix,\n\t\t\tscopes: input.scopes,\n\t\t\tuserId,\n\t\t\texpiresAt: input.expiresAt ?? null,\n\t\t\tlastUsedAt: null,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t};\n\n\t\treturn { success: true, data: { token: raw, info } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"TOKEN_CREATE_ERROR\",\n\t\t\t\tmessage: \"Failed to create API token\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * List all API tokens for a user (never returns the raw token or hash).\n */\nexport async function handleApiTokenList(\n\tdb: Kysely<Database>,\n\tuserId: string,\n): Promise<ApiResult<{ items: ApiTokenInfo[] }>> {\n\ttry {\n\t\tconst rows = await db\n\t\t\t.selectFrom(\"_emdash_api_tokens\")\n\t\t\t.select([\n\t\t\t\t\"id\",\n\t\t\t\t\"name\",\n\t\t\t\t\"prefix\",\n\t\t\t\t\"scopes\",\n\t\t\t\t\"user_id\",\n\t\t\t\t\"expires_at\",\n\t\t\t\t\"last_used_at\",\n\t\t\t\t\"created_at\",\n\t\t\t])\n\t\t\t.where(\"user_id\", \"=\", userId)\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.execute();\n\n\t\tconst items: ApiTokenInfo[] = rows.map((row) => ({\n\t\t\tid: row.id,\n\t\t\tname: row.name,\n\t\t\tprefix: row.prefix,\n\t\t\tscopes: JSON.parse(row.scopes) as string[],\n\t\t\tuserId: row.user_id,\n\t\t\texpiresAt: row.expires_at,\n\t\t\tlastUsedAt: row.last_used_at,\n\t\t\tcreatedAt: row.created_at,\n\t\t}));\n\n\t\treturn { success: true, data: { items } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"TOKEN_LIST_ERROR\",\n\t\t\t\tmessage: \"Failed to list API tokens\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Revoke (delete) an API token.\n */\nexport async function handleApiTokenRevoke(\n\tdb: Kysely<Database>,\n\ttokenId: string,\n\tuserId: string,\n): Promise<ApiResult<{ revoked: boolean }>> {\n\ttry {\n\t\tconst result = await db\n\t\t\t.deleteFrom(\"_emdash_api_tokens\")\n\t\t\t.where(\"id\", \"=\", tokenId)\n\t\t\t.where(\"user_id\", \"=\", userId)\n\t\t\t.executeTakeFirst();\n\n\t\tif (result.numDeletedRows === 0n) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Token not found\" },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: { revoked: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"TOKEN_REVOKE_ERROR\",\n\t\t\t\tmessage: \"Failed to revoke API token\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n/**\n * Delete every token with the given name for a user, returning how many were\n * removed. Token names aren't unique, so this is a bulk delete — used by the\n * dev-bypass flow to keep a single `dev-bypass-token` instead of minting a new\n * one on every reset.\n */\nexport async function deleteApiTokensByName(\n\tdb: Kysely<Database>,\n\tuserId: string,\n\tname: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.deleteFrom(\"_emdash_api_tokens\")\n\t\t.where(\"user_id\", \"=\", userId)\n\t\t.where(\"name\", \"=\", name)\n\t\t.executeTakeFirst();\n\treturn Number(result.numDeletedRows ?? 0n);\n}\n\n/**\n * Resolve a raw API token (ec_pat_...) to a user ID and scopes.\n * Updates last_used_at on successful lookup.\n * Returns null if the token is invalid or expired.\n */\nexport async function resolveApiToken(\n\tdb: Kysely<Database>,\n\trawToken: string,\n): Promise<{ userId: string; scopes: string[] } | null> {\n\tconst hash = hashApiToken(rawToken);\n\n\tconst row = await db\n\t\t.selectFrom(\"_emdash_api_tokens\")\n\t\t.select([\"id\", \"user_id\", \"scopes\", \"expires_at\"])\n\t\t.where(\"token_hash\", \"=\", hash)\n\t\t.executeTakeFirst();\n\n\tif (!row) return null;\n\n\t// Check expiry\n\tif (row.expires_at && new Date(row.expires_at) < new Date()) {\n\t\treturn null;\n\t}\n\n\t// Update last_used_at (fire-and-forget, don't block the request)\n\tdb.updateTable(\"_emdash_api_tokens\")\n\t\t.set({ last_used_at: new Date().toISOString() })\n\t\t.where(\"id\", \"=\", row.id)\n\t\t.execute()\n\t\t.catch(() => {}); // Non-critical, swallow errors\n\n\treturn {\n\t\tuserId: row.user_id,\n\t\tscopes: JSON.parse(row.scopes) as string[],\n\t};\n}\n\n/**\n * Resolve an OAuth access token (ec_oat_...) to a user ID and scopes.\n * Returns null if the token is invalid or expired.\n */\nexport async function resolveOAuthToken(\n\tdb: Kysely<Database>,\n\trawToken: string,\n): Promise<{ userId: string; scopes: string[] } | null> {\n\tconst hash = hashApiToken(rawToken);\n\n\tconst row = await db\n\t\t.selectFrom(\"_emdash_oauth_tokens\")\n\t\t.select([\"user_id\", \"scopes\", \"expires_at\", \"token_type\"])\n\t\t.where(\"token_hash\", \"=\", hash)\n\t\t.where(\"token_type\", \"=\", \"access\")\n\t\t.executeTakeFirst();\n\n\tif (!row) return null;\n\n\t// Check expiry\n\tif (new Date(row.expires_at) < new Date()) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tuserId: row.user_id,\n\t\tscopes: JSON.parse(row.scopes) as string[],\n\t};\n}\n"],"mappings":";;;;;;;AA4CA,eAAsB,qBACrB,IACA,QACA,OAK2C;AAC3C,KAAI;EACH,MAAM,KAAK,MAAM;EACjB,MAAM,EAAE,KAAK,MAAM,WAAW,sBAAsB,UAAU;AAE9D,QAAM,GACJ,WAAW,qBAAqB,CAChC,OAAO;GACP;GACA,MAAM,MAAM;GACZ,YAAY;GACZ;GACA,SAAS;GACT,QAAQ,KAAK,UAAU,MAAM,OAAO;GACpC,YAAY,MAAM,aAAa;GAC/B,CAAC,CACD,SAAS;AAaX,SAAO;GAAE,SAAS;GAAM,MAAM;IAAE,OAAO;IAAK,MAXjB;KAC1B;KACA,MAAM,MAAM;KACZ;KACA,QAAQ,MAAM;KACd;KACA,WAAW,MAAM,aAAa;KAC9B,YAAY;KACZ,4BAAW,IAAI,MAAM,EAAC,aAAa;KACnC;IAEiD;GAAE;SAC7C;AACP,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM;IACN,SAAS;IACT;GACD;;;;;;AAOH,eAAsB,mBACrB,IACA,QACgD;AAChD,KAAI;AA4BH,SAAO;GAAE,SAAS;GAAM,MAAM,EAAE,QA3BnB,MAAM,GACjB,WAAW,qBAAqB,CAChC,OAAO;IACP;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,CAAC,CACD,MAAM,WAAW,KAAK,OAAO,CAC7B,QAAQ,cAAc,OAAO,CAC7B,SAAS,EAEwB,KAAK,SAAS;IAChD,IAAI,IAAI;IACR,MAAM,IAAI;IACV,QAAQ,IAAI;IACZ,QAAQ,KAAK,MAAM,IAAI,OAAO;IAC9B,QAAQ,IAAI;IACZ,WAAW,IAAI;IACf,YAAY,IAAI;IAChB,WAAW,IAAI;IACf,EAAE,EAEoC;GAAE;SAClC;AACP,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM;IACN,SAAS;IACT;GACD;;;;;;AAOH,eAAsB,qBACrB,IACA,SACA,QAC2C;AAC3C,KAAI;AAOH,OANe,MAAM,GACnB,WAAW,qBAAqB,CAChC,MAAM,MAAM,KAAK,QAAQ,CACzB,MAAM,WAAW,KAAK,OAAO,CAC7B,kBAAkB,EAET,mBAAmB,GAC7B,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAa,SAAS;IAAmB;GACxD;AAGF,SAAO;GAAE,SAAS;GAAM,MAAM,EAAE,SAAS,MAAM;GAAE;SAC1C;AACP,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM;IACN,SAAS;IACT;GACD;;;;;;;;;AAUH,eAAsB,sBACrB,IACA,QACA,MACkB;CAClB,MAAM,SAAS,MAAM,GACnB,WAAW,qBAAqB,CAChC,MAAM,WAAW,KAAK,OAAO,CAC7B,MAAM,QAAQ,KAAK,KAAK,CACxB,kBAAkB;AACpB,QAAO,OAAO,OAAO,kBAAkB,GAAG;;;;;;;AAQ3C,eAAsB,gBACrB,IACA,UACuD;CACvD,MAAM,OAAO,aAAa,SAAS;CAEnC,MAAM,MAAM,MAAM,GAChB,WAAW,qBAAqB,CAChC,OAAO;EAAC;EAAM;EAAW;EAAU;EAAa,CAAC,CACjD,MAAM,cAAc,KAAK,KAAK,CAC9B,kBAAkB;AAEpB,KAAI,CAAC,IAAK,QAAO;AAGjB,KAAI,IAAI,cAAc,IAAI,KAAK,IAAI,WAAW,mBAAG,IAAI,MAAM,CAC1D,QAAO;AAIR,IAAG,YAAY,qBAAqB,CAClC,IAAI,EAAE,+BAAc,IAAI,MAAM,EAAC,aAAa,EAAE,CAAC,CAC/C,MAAM,MAAM,KAAK,IAAI,GAAG,CACxB,SAAS,CACT,YAAY,GAAG;AAEjB,QAAO;EACN,QAAQ,IAAI;EACZ,QAAQ,KAAK,MAAM,IAAI,OAAO;EAC9B;;;;;;AAOF,eAAsB,kBACrB,IACA,UACuD;CACvD,MAAM,OAAO,aAAa,SAAS;CAEnC,MAAM,MAAM,MAAM,GAChB,WAAW,uBAAuB,CAClC,OAAO;EAAC;EAAW;EAAU;EAAc;EAAa,CAAC,CACzD,MAAM,cAAc,KAAK,KAAK,CAC9B,MAAM,cAAc,KAAK,SAAS,CAClC,kBAAkB;AAEpB,KAAI,CAAC,IAAK,QAAO;AAGjB,KAAI,IAAI,KAAK,IAAI,WAAW,mBAAG,IAAI,MAAM,CACxC,QAAO;AAGR,QAAO;EACN,QAAQ,IAAI;EACZ,QAAQ,KAAK,MAAM,IAAI,OAAO;EAC9B"}
@@ -1,18 +1,18 @@
1
- import { c as __exportAll } from "./runner-BLIDKpmA.mjs";
1
+ import { c as __exportAll } from "./runner-nEzvnogG.mjs";
2
2
  import { a as resolveConfiguredLocale, r as getI18nConfig } from "./config-C3EBstHi.mjs";
3
- import { i as RevisionRepository, t as ContentRepository } from "./content-DjvM0T92.mjs";
3
+ import { i as RevisionRepository, t as ContentRepository } from "./content-CNfMWuhY.mjs";
4
4
  import { t as MediaRepository } from "./media-BBm8Wg3f.mjs";
5
5
  import { t as withTransaction } from "./transaction-0KOpOyMu.mjs";
6
- import { t as TaxonomyRepository } from "./taxonomy-tJepplLL.mjs";
7
- import { t as RedirectRepository } from "./redirect-CZkbozu9.mjs";
8
- import { t as BylineRepository } from "./byline-DuhF7NWl.mjs";
9
- import { t as imageSize } from "./dist-89xCrGqi.mjs";
10
- import { t as FTSManager } from "./fts-manager-Do1BlW2r.mjs";
11
- import { l as markContentMediaUsageCollectionStaleSafely } from "./content-refresh-Bwp-8yGy.mjs";
12
- import { n as SchemaRegistry } from "./registry-AZAsRsor.mjs";
13
- import { c as setSiteSettings } from "./settings--wobrkkC.mjs";
14
- import { a as ssrfSafeFetch, s as validateExternalUrl } from "./ssrf-5sIM5jzl.mjs";
15
- import { t as validateSeed } from "./validate-DE_LRwo9.mjs";
6
+ import { t as TaxonomyRepository } from "./taxonomy-DP1vny4K.mjs";
7
+ import { t as RedirectRepository } from "./redirect-DId44BS1.mjs";
8
+ import { t as BylineRepository } from "./byline-Vdi85CsZ.mjs";
9
+ import { t as imageSize } from "./dist-BAsh8dbf.mjs";
10
+ import { t as FTSManager } from "./fts-manager-iddym8cd.mjs";
11
+ import { l as markContentMediaUsageCollectionStaleSafely } from "./content-refresh-GTMyi2Xy.mjs";
12
+ import { n as SchemaRegistry } from "./registry-DTqaqxed.mjs";
13
+ import { c as setSiteSettings } from "./settings-DcMjREe5.mjs";
14
+ import { a as ssrfSafeFetch, s as validateExternalUrl } from "./ssrf-gl4gFNhw.mjs";
15
+ import { t as validateSeed } from "./validate-D8VPn4Hv.mjs";
16
16
  import { ulid } from "ulidx";
17
17
  import mime from "mime/lite";
18
18
 
@@ -152,7 +152,9 @@ async function applySeed(db, seed, options = {}) {
152
152
  routable: collection.routable,
153
153
  hidden: collection.hidden,
154
154
  sortOrder: collection.sortOrder,
155
- commentsEnabled: collection.commentsEnabled
155
+ group: collection.group,
156
+ commentsEnabled: collection.commentsEnabled,
157
+ editLocking: collection.editLocking
156
158
  });
157
159
  result.collections.updated++;
158
160
  for (const field of collection.fields) if (await registry.getField(collection.slug, field.slug)) {
@@ -217,7 +219,9 @@ async function applySeed(db, seed, options = {}) {
217
219
  routable: collection.routable,
218
220
  hidden: collection.hidden,
219
221
  sortOrder: collection.sortOrder,
220
- commentsEnabled: collection.commentsEnabled
222
+ group: collection.group,
223
+ commentsEnabled: collection.commentsEnabled,
224
+ editLocking: collection.editLocking
221
225
  }, fields);
222
226
  await applyDisplayDateFields(registry, collection);
223
227
  result.collections.created++;
@@ -298,7 +302,7 @@ async function applySeed(db, seed, options = {}) {
298
302
  }
299
303
  }
300
304
  }
301
- const { invalidateTaxonomyDefsCache } = await import("./taxonomies-Wfy_Lg12.mjs").then((n) => n.f);
305
+ const { invalidateTaxonomyDefsCache } = await import("./taxonomies-NcFDq5Gg.mjs").then((n) => n.f);
302
306
  invalidateTaxonomyDefsCache();
303
307
  }
304
308
  if (includeContent && seed.bylines) {
@@ -589,9 +593,9 @@ async function applySeed(db, seed, options = {}) {
589
593
  }
590
594
  }
591
595
  }
592
- const { invalidateBylineCache } = await import("./bylines-CJ5nd6Lw.mjs").then((n) => n.t);
593
- const { invalidateRedirectCache } = await import("./cache-BF5Kvn59.mjs").then((n) => n.t);
594
- const { invalidateUrlPatternCache } = await import("./query-BZKZcG5b.mjs").then((n) => n.o);
596
+ const { invalidateBylineCache } = await import("./bylines-BX8QhcTk.mjs").then((n) => n.t);
597
+ const { invalidateRedirectCache } = await import("./cache--7HKu5Xm.mjs").then((n) => n.t);
598
+ const { invalidateUrlPatternCache } = await import("./query-DygOte9M.mjs").then((n) => n.o);
595
599
  invalidateBylineCache();
596
600
  invalidateRedirectCache();
597
601
  invalidateUrlPatternCache();
@@ -677,7 +681,7 @@ async function applyContentTaxonomies(db, collectionSlug, contentId, entry, isUp
677
681
  if (isUpdate) await termRepo.clearEntryTerms(collectionSlug, contentId);
678
682
  if (!entry.taxonomies) {
679
683
  if (isUpdate) {
680
- const { invalidateTermCache } = await import("./taxonomies-Wfy_Lg12.mjs").then((n) => n.f);
684
+ const { invalidateTermCache } = await import("./taxonomies-NcFDq5Gg.mjs").then((n) => n.f);
681
685
  invalidateTermCache();
682
686
  }
683
687
  return;
@@ -686,7 +690,7 @@ async function applyContentTaxonomies(db, collectionSlug, contentId, entry, isUp
686
690
  const term = await termRepo.findBySlug(taxonomyName, termSlug);
687
691
  if (term) await termRepo.attachToEntry(collectionSlug, contentId, term.id);
688
692
  }
689
- const { invalidateTermCache } = await import("./taxonomies-Wfy_Lg12.mjs").then((n) => n.f);
693
+ const { invalidateTermCache } = await import("./taxonomies-NcFDq5Gg.mjs").then((n) => n.f);
690
694
  invalidateTermCache();
691
695
  }
692
696
  /**
@@ -977,4 +981,4 @@ function getImageDimensions(buffer) {
977
981
 
978
982
  //#endregion
979
983
  export { apply_exports as n, applySeed as t };
980
- //# sourceMappingURL=apply-B4SIOxR1.mjs.map
984
+ //# sourceMappingURL=apply-DLmM3R7f.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-DLmM3R7f.mjs","names":[],"sources":["../src/seed/apply.ts"],"sourcesContent":["/**\n * Seed engine - applies seed files to database\n *\n * This is the core implementation that bootstraps an EmDash site from a seed file.\n * Apply order is critical for foreign keys and references.\n */\n\nimport { imageSize } from \"image-size\";\nimport type { Kysely } from \"kysely\";\nimport mime from \"mime/lite\";\nimport { ulid } from \"ulidx\";\n\nimport { BylineRepository } from \"../database/repositories/byline.js\";\nimport { ContentRepository } from \"../database/repositories/content.js\";\nimport { MediaRepository } from \"../database/repositories/media.js\";\nimport { RedirectRepository } from \"../database/repositories/redirect.js\";\nimport { RevisionRepository } from \"../database/repositories/revision.js\";\nimport { TaxonomyRepository } from \"../database/repositories/taxonomy.js\";\nimport { withTransaction } from \"../database/transaction.js\";\nimport type { Database } from \"../database/types.js\";\nimport type { MediaValue } from \"../fields/types.js\";\nimport { getI18nConfig, resolveConfiguredLocale } from \"../i18n/config.js\";\nimport { ssrfSafeFetch, validateExternalUrl } from \"../import/ssrf.js\";\nimport { markContentMediaUsageCollectionStaleSafely } from \"../media/usage/content-refresh.js\";\nimport { SchemaRegistry } from \"../schema/registry.js\";\nimport { FTSManager } from \"../search/fts-manager.js\";\nimport { setSiteSettings } from \"../settings/index.js\";\nimport type { Storage } from \"../storage/types.js\";\nimport type {\n\tSeedFile,\n\tSeedApplyOptions,\n\tSeedApplyResult,\n\tSeedCollection,\n\tSeedTaxonomyTerm,\n\tSeedMenuItem,\n\tSeedWidget,\n\tSeedMediaReference,\n\tSeedBylineAvatar,\n} from \"./types.js\";\n\n/**\n * Set a collection's `titleField`/`dateField`: a separate write run after the\n * fields exist, so `updateCollection` can validate them. No-op when neither is set.\n */\nasync function applyDisplayDateFields(\n\tregistry: SchemaRegistry,\n\tcollection: SeedCollection,\n): Promise<void> {\n\tif (collection.titleField === undefined && collection.dateField === undefined) return;\n\tawait registry.updateCollection(collection.slug, {\n\t\ttitleField: collection.titleField,\n\t\tdateField: collection.dateField,\n\t});\n}\n\nconst FILE_EXTENSION_PATTERN = /\\.([a-z0-9]+)(?:\\?|$)/i;\nimport { validateSeed } from \"./validate.js\";\n\n/** Pattern to remove file extensions */\nconst EXTENSION_PATTERN = /\\.[^.]+$/;\n\n/** Pattern to remove query parameters */\nconst QUERY_PARAM_PATTERN = /\\?.*$/;\n\n/** Pattern to remove non-alphanumeric characters (except dash and underscore) */\nconst SANITIZE_PATTERN = /[^a-zA-Z0-9_-]/g;\n\n/** Pattern to collapse multiple hyphens */\nconst MULTIPLE_HYPHENS_PATTERN = /-+/g;\n\n/**\n * Apply a seed file to the database\n *\n * This function is idempotent - safe to run multiple times.\n *\n * @param db - Kysely database instance\n * @param seed - Seed file to apply\n * @param options - Application options\n * @returns Result summary\n */\nexport async function applySeed(\n\tdb: Kysely<Database>,\n\tseed: SeedFile,\n\toptions: SeedApplyOptions = {},\n): Promise<SeedApplyResult> {\n\t// Validate seed first\n\tconst validation = validateSeed(seed);\n\tif (!validation.valid) {\n\t\tthrow new Error(`Invalid seed file:\\n${validation.errors.join(\"\\n\")}`);\n\t}\n\n\tconst {\n\t\tincludeContent = false,\n\t\tstorage,\n\t\tskipMediaDownload = false,\n\t\tonConflict = \"skip\",\n\t} = options;\n\n\t// Result counters\n\tconst result: SeedApplyResult = {\n\t\tcollections: { created: 0, skipped: 0, updated: 0 },\n\t\tfields: { created: 0, skipped: 0, updated: 0 },\n\t\ttaxonomies: { created: 0, terms: 0 },\n\t\tbylines: { created: 0, skipped: 0, updated: 0 },\n\t\tmenus: { created: 0, items: 0 },\n\t\tredirects: { created: 0, skipped: 0, updated: 0 },\n\t\twidgetAreas: { created: 0, widgets: 0 },\n\t\tsections: { created: 0, skipped: 0, updated: 0 },\n\t\tsettings: { applied: 0 },\n\t\tcontent: { created: 0, skipped: 0, updated: 0 },\n\t\tmedia: { created: 0, skipped: 0 },\n\t};\n\n\t// Media context for $media resolution\n\tconst mediaContext: MediaContext = {\n\t\tdb,\n\t\tstorage: storage ?? null,\n\t\tskipMediaDownload,\n\t\tmediaCache: new Map(), // Cache downloaded media by URL to avoid re-downloading\n\t};\n\n\t// Apply order (critical for foreign keys and references):\n\t// 1. Site settings\n\t// 2. Collections + Fields\n\t// 3. Taxonomy definitions + Terms\n\t// 4. Content (so menu refs can resolve)\n\t// 5. Menus + Menu items (can now resolve content refs)\n\t// 6. Redirects\n\t// 7. Widget areas + Widgets\n\n\t// Track seed content IDs for reference resolution (shared across content and menus)\n\tconst seedIdMap = new Map<string, string>(); // seed id -> real entry id\n\tconst seedBylineIdMap = new Map<string, string>(); // seed byline id -> real byline id\n\tconst staleMarkedContentCollections = new Set<string>();\n\tconst failedStaleContentCollections = new Set<string>();\n\n\t// Fallback locale for rows that omit an explicit `locale`. Prefer the runtime\n\t// config (runtime-driven seeds), then the seed's self-described `defaultLocale`\n\t// (CLI exports run outside the runtime), and only then `en`. Without the\n\t// seed-carried default, a non-`en` single-locale project would be rewritten to\n\t// `en` on apply (#1421).\n\tconst defaultLocale = getI18nConfig()?.defaultLocale ?? seed.defaultLocale ?? \"en\";\n\tconst markSeedContentCollectionStale = async (collectionSlug: string): Promise<void> => {\n\t\tif (staleMarkedContentCollections.has(collectionSlug)) return;\n\t\tconst marked = await markContentMediaUsageCollectionStaleSafely(\n\t\t\tdb,\n\t\t\tcollectionSlug,\n\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t);\n\t\tif (marked) {\n\t\t\tstaleMarkedContentCollections.add(collectionSlug);\n\t\t\tfailedStaleContentCollections.delete(collectionSlug);\n\t\t} else {\n\t\t\tfailedStaleContentCollections.add(collectionSlug);\n\t\t}\n\t};\n\tconst retryFailedSeedContentStaleMarks = async (): Promise<void> => {\n\t\tfor (const collectionSlug of failedStaleContentCollections) {\n\t\t\tconst marked = await markContentMediaUsageCollectionStaleSafely(\n\t\t\t\tdb,\n\t\t\t\tcollectionSlug,\n\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t);\n\t\t\tif (marked) {\n\t\t\t\tstaleMarkedContentCollections.add(collectionSlug);\n\t\t\t\tfailedStaleContentCollections.delete(collectionSlug);\n\t\t\t}\n\t\t}\n\t};\n\n\t// 1. Site settings\n\tif (seed.settings) {\n\t\tawait setSiteSettings(seed.settings, db);\n\t\tresult.settings.applied = Object.keys(seed.settings).length;\n\t}\n\n\t// 2-3. Collections and Fields\n\tif (seed.collections) {\n\t\tconst registry = new SchemaRegistry(db);\n\n\t\tfor (const collection of seed.collections) {\n\t\t\t// Check if collection exists\n\t\t\tconst existing = await registry.getCollection(collection.slug);\n\n\t\t\tif (existing) {\n\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\tthrow new Error(`Conflict: collection \"${collection.slug}\" already exists`);\n\t\t\t\t}\n\n\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\tawait registry.updateCollection(collection.slug, {\n\t\t\t\t\t\tlabel: collection.label,\n\t\t\t\t\t\tlabelSingular: collection.labelSingular,\n\t\t\t\t\t\tdescription: collection.description,\n\t\t\t\t\t\ticon: collection.icon,\n\t\t\t\t\t\tadmin: collection.admin,\n\t\t\t\t\t\tsupports: collection.supports || [],\n\t\t\t\t\t\turlPattern: collection.urlPattern,\n\t\t\t\t\t\troutable: collection.routable,\n\t\t\t\t\t\thidden: collection.hidden,\n\t\t\t\t\t\tsortOrder: collection.sortOrder,\n\t\t\t\t\t\tgroup: collection.group,\n\t\t\t\t\t\tcommentsEnabled: collection.commentsEnabled,\n\t\t\t\t\t\teditLocking: collection.editLocking,\n\t\t\t\t\t});\n\t\t\t\t\tresult.collections.updated++;\n\n\t\t\t\t\t// Update or create fields\n\t\t\t\t\tfor (const field of collection.fields) {\n\t\t\t\t\t\tconst existingField = await registry.getField(collection.slug, field.slug);\n\t\t\t\t\t\tif (existingField) {\n\t\t\t\t\t\t\tawait registry.updateField(collection.slug, field.slug, {\n\t\t\t\t\t\t\t\tlabel: field.label,\n\t\t\t\t\t\t\t\ttype: field.type,\n\t\t\t\t\t\t\t\trequired: field.required || false,\n\t\t\t\t\t\t\t\tunique: field.unique || false,\n\t\t\t\t\t\t\t\tsearchable: field.searchable || false,\n\t\t\t\t\t\t\t\tindexed: field.indexed || false,\n\t\t\t\t\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\t\t\t\t\tvalidation: field.validation,\n\t\t\t\t\t\t\t\twidget: field.widget,\n\t\t\t\t\t\t\t\toptions: field.options,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tresult.fields.updated++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tawait registry.createField(collection.slug, {\n\t\t\t\t\t\t\t\tslug: field.slug,\n\t\t\t\t\t\t\t\tlabel: field.label,\n\t\t\t\t\t\t\t\ttype: field.type,\n\t\t\t\t\t\t\t\trequired: field.required || false,\n\t\t\t\t\t\t\t\tunique: field.unique || false,\n\t\t\t\t\t\t\t\tsearchable: field.searchable || false,\n\t\t\t\t\t\t\t\tindexed: field.indexed || false,\n\t\t\t\t\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\t\t\t\t\tvalidation: field.validation,\n\t\t\t\t\t\t\t\twidget: field.widget,\n\t\t\t\t\t\t\t\toptions: field.options,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tresult.fields.created++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Second write: display/date fields, now that fields exist.\n\t\t\t\t\tawait applyDisplayDateFields(registry, collection);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// skip\n\t\t\t\tresult.collections.skipped++;\n\t\t\t\tresult.fields.skipped += collection.fields.length;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fields = collection.fields.map((field) => ({\n\t\t\t\tslug: field.slug,\n\t\t\t\tlabel: field.label,\n\t\t\t\ttype: field.type,\n\t\t\t\trequired: field.required || false,\n\t\t\t\tunique: field.unique || false,\n\t\t\t\tsearchable: field.searchable || false,\n\t\t\t\tindexed: field.indexed || false,\n\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\tvalidation: field.validation,\n\t\t\t\twidget: field.widget,\n\t\t\t\toptions: field.options,\n\t\t\t}));\n\n\t\t\t// Create a fresh seed schema in bulk to stay within D1's query budget.\n\t\t\tawait registry.createSeedCollection(\n\t\t\t\t{\n\t\t\t\t\tslug: collection.slug,\n\t\t\t\t\tlabel: collection.label,\n\t\t\t\t\tlabelSingular: collection.labelSingular,\n\t\t\t\t\tdescription: collection.description,\n\t\t\t\t\ticon: collection.icon,\n\t\t\t\t\tadmin: collection.admin,\n\t\t\t\t\tsupports: collection.supports || [],\n\t\t\t\t\turlPattern: collection.urlPattern,\n\t\t\t\t\troutable: collection.routable,\n\t\t\t\t\thidden: collection.hidden,\n\t\t\t\t\tsortOrder: collection.sortOrder,\n\t\t\t\t\tgroup: collection.group,\n\t\t\t\t\tcommentsEnabled: collection.commentsEnabled,\n\t\t\t\t\teditLocking: collection.editLocking,\n\t\t\t\t},\n\t\t\t\tfields,\n\t\t\t);\n\t\t\t// titleField/dateField reference existing fields, so set them after\n\t\t\t// the schema exists.\n\t\t\tawait applyDisplayDateFields(registry, collection);\n\t\t\tresult.collections.created++;\n\t\t\tresult.fields.created += fields.length;\n\t\t}\n\t}\n\n\t// 4-5. Taxonomies\n\tif (seed.taxonomies) {\n\t\t// seed-local id -> resolved info, used to wire `translationOf` refs.\n\t\tconst defSeedIdMap = new Map<string, { id: string; translationGroup: string }>();\n\t\tconst termSeedIdMap = new Map<string, string>();\n\n\t\tfor (const taxonomy of seed.taxonomies) {\n\t\t\tconst defLocale = resolveConfiguredLocale(taxonomy.locale ?? defaultLocale);\n\n\t\t\t// (name, locale) is the UNIQUE key after migration 036.\n\t\t\tconst existingDef = await db\n\t\t\t\t.selectFrom(\"_emdash_taxonomy_defs\")\n\t\t\t\t.selectAll()\n\t\t\t\t.where(\"name\", \"=\", taxonomy.name)\n\t\t\t\t.where(\"locale\", \"=\", defLocale)\n\t\t\t\t.executeTakeFirst();\n\n\t\t\tlet defId: string;\n\t\t\tlet defTranslationGroup: string;\n\n\t\t\tif (existingDef) {\n\t\t\t\tdefId = existingDef.id;\n\t\t\t\tdefTranslationGroup = existingDef.translation_group ?? existingDef.id;\n\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\tthrow new Error(`Conflict: taxonomy \"${taxonomy.name}\" (${defLocale}) already exists`);\n\t\t\t\t}\n\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\tawait db\n\t\t\t\t\t\t.updateTable(\"_emdash_taxonomy_defs\")\n\t\t\t\t\t\t.set({\n\t\t\t\t\t\t\tlabel: taxonomy.label,\n\t\t\t\t\t\t\tlabel_singular: taxonomy.labelSingular ?? null,\n\t\t\t\t\t\t\thierarchical: taxonomy.hierarchical ? 1 : 0,\n\t\t\t\t\t\t\tcollections: JSON.stringify(taxonomy.collections),\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.where(\"id\", \"=\", existingDef.id)\n\t\t\t\t\t\t.execute();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdefId = ulid();\n\t\t\t\tdefTranslationGroup = defId;\n\t\t\t\tif (taxonomy.translationOf) {\n\t\t\t\t\tconst source = defSeedIdMap.get(taxonomy.translationOf);\n\t\t\t\t\tif (source) defTranslationGroup = source.translationGroup;\n\t\t\t\t\telse\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`taxonomy \"${taxonomy.name}\" (${defLocale}): translationOf \"${taxonomy.translationOf}\" not found yet; minting a fresh group.`,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait db\n\t\t\t\t\t.insertInto(\"_emdash_taxonomy_defs\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tid: defId,\n\t\t\t\t\t\tname: taxonomy.name,\n\t\t\t\t\t\tlabel: taxonomy.label,\n\t\t\t\t\t\tlabel_singular: taxonomy.labelSingular ?? null,\n\t\t\t\t\t\thierarchical: taxonomy.hierarchical ? 1 : 0,\n\t\t\t\t\t\tcollections: JSON.stringify(taxonomy.collections),\n\t\t\t\t\t\tlocale: defLocale,\n\t\t\t\t\t\ttranslation_group: defTranslationGroup,\n\t\t\t\t\t})\n\t\t\t\t\t.execute();\n\t\t\t\tresult.taxonomies.created++;\n\t\t\t}\n\n\t\t\tif (taxonomy.id)\n\t\t\t\tdefSeedIdMap.set(taxonomy.id, { id: defId, translationGroup: defTranslationGroup });\n\n\t\t\t// Create terms (if provided)\n\t\t\tif (includeContent && taxonomy.terms && taxonomy.terms.length > 0) {\n\t\t\t\tconst termRepo = new TaxonomyRepository(db);\n\n\t\t\t\tif (taxonomy.hierarchical) {\n\t\t\t\t\tawait applyHierarchicalTerms(\n\t\t\t\t\t\ttermRepo,\n\t\t\t\t\t\ttaxonomy.name,\n\t\t\t\t\t\tdefLocale,\n\t\t\t\t\t\ttaxonomy.terms,\n\t\t\t\t\t\ttermSeedIdMap,\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\tonConflict,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tfor (const term of taxonomy.terms) {\n\t\t\t\t\t\tconst termLocale = resolveConfiguredLocale(term.locale ?? defLocale);\n\t\t\t\t\t\tconst existing = await termRepo.findBySlug(taxonomy.name, term.slug, termLocale);\n\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t`Conflict: taxonomy term \"${term.slug}\" in \"${taxonomy.name}\" (${termLocale}) already exists`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\t\t\t\tawait termRepo.update(existing.id, {\n\t\t\t\t\t\t\t\t\tlabel: term.label,\n\t\t\t\t\t\t\t\t\tdata: term.description ? { description: term.description } : {},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tresult.taxonomies.terms++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (term.id) termSeedIdMap.set(term.id, existing.id);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst translationOf = term.translationOf\n\t\t\t\t\t\t\t\t? termSeedIdMap.get(term.translationOf)\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tconst created = await termRepo.create({\n\t\t\t\t\t\t\t\tname: taxonomy.name,\n\t\t\t\t\t\t\t\tslug: term.slug,\n\t\t\t\t\t\t\t\tlabel: term.label,\n\t\t\t\t\t\t\t\tdata: term.description ? { description: term.description } : undefined,\n\t\t\t\t\t\t\t\tlocale: termLocale,\n\t\t\t\t\t\t\t\ttranslationOf,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (term.id) termSeedIdMap.set(term.id, created.id);\n\t\t\t\t\t\t\tresult.taxonomies.terms++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Seeded/updated defs change which taxonomies exist — clear the\n\t\t// isolate-wide defs + names caches so later reads in this isolate\n\t\t// (e.g. an auto-seed triggered mid-request) reflect them immediately.\n\t\tconst { invalidateTaxonomyDefsCache } = await import(\"../taxonomies/index.js\");\n\t\tinvalidateTaxonomyDefsCache();\n\t}\n\n\t// 6. Bylines\n\tif (includeContent && seed.bylines) {\n\t\tconst bylineRepo = new BylineRepository(db);\n\t\tfor (const byline of seed.bylines) {\n\t\t\tconst existing = await bylineRepo.findBySlug(byline.slug);\n\t\t\tif (existing) {\n\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\tthrow new Error(`Conflict: byline \"${byline.slug}\" already exists`);\n\t\t\t\t}\n\n\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\t// Resolve the avatar (reusing an existing media row by storage\n\t\t\t\t\t// key, so re-running an update stays idempotent). Only relink\n\t\t\t\t\t// when the seed supplies an avatar; otherwise leave the existing\n\t\t\t\t\t// one untouched.\n\t\t\t\t\tconst avatar = byline.avatar ? await resolveSeedBylineAvatar(db, byline.avatar) : null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst updated = await bylineRepo.update(existing.id, {\n\t\t\t\t\t\t\tdisplayName: byline.displayName,\n\t\t\t\t\t\t\tbio: byline.bio ?? null,\n\t\t\t\t\t\t\twebsiteUrl: byline.websiteUrl ?? null,\n\t\t\t\t\t\t\tisGuest: byline.isGuest,\n\t\t\t\t\t\t\t...(avatar ? { avatarMediaId: avatar.id } : {}),\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// update() returns null (no throw) if the row vanished between\n\t\t\t\t\t\t// findBySlug and here; treat that as a failure so the catch\n\t\t\t\t\t\t// cleans up any freshly-created avatar media instead of leaking it.\n\t\t\t\t\t\tif (!updated) {\n\t\t\t\t\t\t\tthrow new Error(`Byline \"${byline.slug}\" disappeared during update`);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// withTransaction is a no-op on D1, so undo a freshly-created\n\t\t\t\t\t\t// media row by hand to avoid orphaning it.\n\t\t\t\t\t\tif (avatar?.created) await deleteMediaRow(db, avatar.id);\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tseedBylineIdMap.set(byline.id, existing.id);\n\t\t\t\t\tresult.bylines.updated++;\n\t\t\t\t\tif (avatar?.created) result.media.created++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// skip\n\t\t\t\tseedBylineIdMap.set(byline.id, existing.id);\n\t\t\t\tresult.bylines.skipped++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst avatar = byline.avatar ? await resolveSeedBylineAvatar(db, byline.avatar) : null;\n\t\t\tlet createdId: string;\n\t\t\ttry {\n\t\t\t\tconst created = await bylineRepo.create({\n\t\t\t\t\tslug: byline.slug,\n\t\t\t\t\tdisplayName: byline.displayName,\n\t\t\t\t\tbio: byline.bio ?? null,\n\t\t\t\t\twebsiteUrl: byline.websiteUrl ?? null,\n\t\t\t\t\tisGuest: byline.isGuest,\n\t\t\t\t\tavatarMediaId: avatar?.id ?? null,\n\t\t\t\t});\n\t\t\t\tcreatedId = created.id;\n\t\t\t} catch (error) {\n\t\t\t\tif (avatar?.created) await deleteMediaRow(db, avatar.id);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tseedBylineIdMap.set(byline.id, createdId);\n\t\t\tresult.bylines.created++;\n\t\t\tif (avatar?.created) result.media.created++;\n\t\t}\n\t}\n\n\t// 7. Content (created before menus so refs can resolve)\n\tif (includeContent && seed.content) {\n\t\tconst contentRepo = new ContentRepository(db);\n\t\tconst schemaRegistry = new SchemaRegistry(db);\n\n\t\ttry {\n\t\t\t// Create content entries\n\t\t\tfor (const [collectionSlug, entries] of Object.entries(seed.content)) {\n\t\t\t\tconst collectionRoutable =\n\t\t\t\t\t(await schemaRegistry.getCollection(collectionSlug))?.routable !== false;\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst entrySlug =\n\t\t\t\t\t\ttypeof entry.slug === \"string\" && entry.slug.trim().length > 0 ? entry.slug : null;\n\t\t\t\t\t// Resolve the entry's locale up front so a non-`en` single-locale\n\t\t\t\t\t// export (which omits `locale`) is filed under the project default\n\t\t\t\t\t// rather than `en` (#1421).\n\t\t\t\t\tconst entryLocale = resolveConfiguredLocale(entry.locale ?? defaultLocale);\n\n\t\t\t\t\t// Slugful entries use the existing locale-aware key. Slugless seed\n\t\t\t\t\t// entries persist their seed ID, which keeps re-application idempotent.\n\t\t\t\t\tconst existing = entrySlug\n\t\t\t\t\t\t? await contentRepo.findBySlug(collectionSlug, entrySlug, entryLocale)\n\t\t\t\t\t\t: await contentRepo.findById(collectionSlug, entry.id);\n\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Conflict: content \"${entrySlug ?? entry.id}\" in \"${collectionSlug}\" already exists`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\t\t\t// Resolve $ref and $media in data\n\t\t\t\t\t\t\tconst resolvedData = await resolveReferences(\n\t\t\t\t\t\t\t\tentry.data,\n\t\t\t\t\t\t\t\tseedIdMap,\n\t\t\t\t\t\t\t\tmediaContext,\n\t\t\t\t\t\t\t\tresult,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Update content + bylines + taxonomies atomically\n\t\t\t\t\t\t\tconst status = entry.status || \"published\";\n\t\t\t\t\t\t\tlet contentMutated = false;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait withTransaction(db, async (trx) => {\n\t\t\t\t\t\t\t\t\tconst trxContentRepo = new ContentRepository(trx);\n\t\t\t\t\t\t\t\t\tconst trxBylineRepo = new BylineRepository(trx);\n\t\t\t\t\t\t\t\t\tconst trxRevisionRepo = new RevisionRepository(trx);\n\n\t\t\t\t\t\t\t\t\tawait trxContentRepo.update(collectionSlug, existing.id, {\n\t\t\t\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\t\t\t\tdata: resolvedData,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tcontentMutated = true;\n\n\t\t\t\t\t\t\t\t\tawait applyContentBylines(\n\t\t\t\t\t\t\t\t\t\ttrxBylineRepo,\n\t\t\t\t\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\t\t\t\texisting.id,\n\t\t\t\t\t\t\t\t\t\tentry,\n\t\t\t\t\t\t\t\t\t\tseedBylineIdMap,\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait applyContentTaxonomies(trx, collectionSlug, existing.id, entry, true);\n\n\t\t\t\t\t\t\t\t\t// Seed is declarative — when status is \"published\", promote to a live\n\t\t\t\t\t\t\t\t\t// revision so the admin UI shows \"Unpublish\" instead of \"Save & Publish\"\n\t\t\t\t\t\t\t\t\t// and `live_revision_id` is populated for downstream queries.\n\t\t\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t\t\t// Create a fresh revision from the updated data and stage it as the\n\t\t\t\t\t\t\t\t\t// draft so `publish()` picks it up instead of re-syncing stale data\n\t\t\t\t\t\t\t\t\t// from an existing live revision.\n\t\t\t\t\t\t\t\t\tif (status === \"published\") {\n\t\t\t\t\t\t\t\t\t\tconst draft = await trxRevisionRepo.create({\n\t\t\t\t\t\t\t\t\t\t\tcollection: collectionSlug,\n\t\t\t\t\t\t\t\t\t\t\tentryId: existing.id,\n\t\t\t\t\t\t\t\t\t\t\tdata: resolvedData,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tawait trxContentRepo.setDraftRevision(collectionSlug, existing.id, draft.id);\n\t\t\t\t\t\t\t\t\t\t\tawait trxContentRepo.publish(\n\t\t\t\t\t\t\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\t\t\t\t\t\texisting.id,\n\t\t\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t\t\tcollectionRoutable,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\tawait trxRevisionRepo.deleteIfUnreferenced(\n\t\t\t\t\t\t\t\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\t\t\t\t\t\t\texisting.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdraft.id,\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\t\t\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t\t\t\t\t\t\t`[seed] Failed to clean up unstaged revision ${draft.id}:`,\n\t\t\t\t\t\t\t\t\t\t\t\t\tcleanupError,\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tif (contentMutated) await markSeedContentCollectionStale(collectionSlug);\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tseedIdMap.set(entry.id, existing.id);\n\t\t\t\t\t\t\tresult.content.updated++;\n\t\t\t\t\t\t\tawait markSeedContentCollectionStale(collectionSlug);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// skip\n\t\t\t\t\t\tresult.content.skipped++;\n\t\t\t\t\t\tseedIdMap.set(entry.id, existing.id);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Resolve $ref and $media in data\n\t\t\t\t\tconst resolvedData = await resolveReferences(entry.data, seedIdMap, mediaContext, result);\n\n\t\t\t\t\t// Resolve translationOf: map from seed-local ID to real EmDash ID\n\t\t\t\t\tlet translationOf: string | undefined;\n\t\t\t\t\tif (entry.translationOf) {\n\t\t\t\t\t\tconst sourceId = seedIdMap.get(entry.translationOf);\n\t\t\t\t\t\tif (!sourceId) {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`content.${collectionSlug}: translationOf \"${entry.translationOf}\" not found (not yet created or missing). Skipping translation link.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttranslationOf = sourceId;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create entry + bylines + taxonomies atomically\n\t\t\t\t\tconst status = entry.status || \"published\";\n\t\t\t\t\tlet contentMutated = false;\n\t\t\t\t\tlet created: Awaited<ReturnType<ContentRepository[\"create\"]>>;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcreated = await withTransaction(db, async (trx) => {\n\t\t\t\t\t\t\tconst trxContentRepo = new ContentRepository(trx);\n\t\t\t\t\t\t\tconst trxBylineRepo = new BylineRepository(trx);\n\n\t\t\t\t\t\t\tconst item = await trxContentRepo.create({\n\t\t\t\t\t\t\t\t...(entrySlug ? {} : { id: entry.id }),\n\t\t\t\t\t\t\t\ttype: collectionSlug,\n\t\t\t\t\t\t\t\tslug: entrySlug,\n\t\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\t\tdata: resolvedData,\n\t\t\t\t\t\t\t\tlocale: entryLocale,\n\t\t\t\t\t\t\t\ttranslationOf,\n\t\t\t\t\t\t\t\tpublishedAt: status === \"published\" ? new Date().toISOString() : null,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tcontentMutated = true;\n\n\t\t\t\t\t\t\tawait applyContentBylines(\n\t\t\t\t\t\t\t\ttrxBylineRepo,\n\t\t\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\t\titem.id,\n\t\t\t\t\t\t\t\tentry,\n\t\t\t\t\t\t\t\tseedBylineIdMap,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait applyContentTaxonomies(trx, collectionSlug, item.id, entry, false);\n\n\t\t\t\t\t\t\t// Seed is declarative — when status is \"published\", promote to a live\n\t\t\t\t\t\t\t// revision so the admin UI shows \"Unpublish\" instead of \"Save & Publish\"\n\t\t\t\t\t\t\t// and `live_revision_id` is populated for downstream queries.\n\t\t\t\t\t\t\tif (status === \"published\") {\n\t\t\t\t\t\t\t\tawait trxContentRepo.publish(\n\t\t\t\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\t\t\titem.id,\n\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\tcollectionRoutable,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn item;\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (contentMutated) await markSeedContentCollectionStale(collectionSlug);\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\n\t\t\t\t\tseedIdMap.set(entry.id, created.id);\n\t\t\t\t\tresult.content.created++;\n\t\t\t\t\tawait markSeedContentCollectionStale(collectionSlug);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tawait retryFailedSeedContentStaleMarks();\n\t\t}\n\t}\n\n\t// 8. Menus and Menu Items (after content so refs can resolve)\n\tif (seed.menus) {\n\t\t// seed-local id -> resolved info, used to wire `translationOf` refs.\n\t\tconst menuSeedIdMap = new Map<string, { id: string; translationGroup: string }>();\n\t\t// Shared across menus: translated items reference anchor items in sibling menus.\n\t\tconst itemSeedIdMap = new Map<string, { id: string; translationGroup: string }>();\n\n\t\tfor (const menu of seed.menus) {\n\t\t\tconst locale = resolveConfiguredLocale(menu.locale ?? defaultLocale);\n\t\t\tlet lookup = db\n\t\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t\t.selectAll()\n\t\t\t\t.where(\"name\", \"=\", menu.name)\n\t\t\t\t.where(\"locale\", \"=\", locale);\n\t\t\tconst existingMenu = await lookup.executeTakeFirst();\n\n\t\t\tlet menuId: string;\n\t\t\tlet translationGroup: string;\n\n\t\t\tif (existingMenu) {\n\t\t\t\tmenuId = existingMenu.id;\n\t\t\t\ttranslationGroup = existingMenu.translation_group ?? existingMenu.id;\n\t\t\t\t// Clear existing items (menus are recreated)\n\t\t\t\tawait db.deleteFrom(\"_emdash_menu_items\").where(\"menu_id\", \"=\", menuId).execute();\n\t\t\t} else {\n\t\t\t\tmenuId = ulid();\n\t\t\t\t// Resolve translationOf to the source menu's translation_group.\n\t\t\t\ttranslationGroup = menuId;\n\t\t\t\tif (menu.translationOf) {\n\t\t\t\t\tconst source = menuSeedIdMap.get(menu.translationOf);\n\t\t\t\t\tif (source) translationGroup = source.translationGroup;\n\t\t\t\t\telse\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`menu \"${menu.name}\" (${locale}): translationOf \"${menu.translationOf}\" not found yet; minting a fresh group.`,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait db\n\t\t\t\t\t.insertInto(\"_emdash_menus\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tid: menuId,\n\t\t\t\t\t\tname: menu.name,\n\t\t\t\t\t\tlabel: menu.label,\n\t\t\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\t\t\tupdated_at: new Date().toISOString(),\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\ttranslation_group: translationGroup,\n\t\t\t\t\t})\n\t\t\t\t\t.execute();\n\t\t\t\tresult.menus.created++;\n\t\t\t}\n\n\t\t\tif (menu.id) menuSeedIdMap.set(menu.id, { id: menuId, translationGroup });\n\n\t\t\t// Create menu items\n\t\t\tconst itemCount = await applyMenuItems(\n\t\t\t\tdb,\n\t\t\t\tmenuId,\n\t\t\t\tlocale,\n\t\t\t\tmenu.items,\n\t\t\t\tnull, // parent_id\n\t\t\t\t0, // sort_order\n\t\t\t\tseedIdMap,\n\t\t\t\titemSeedIdMap,\n\t\t\t);\n\t\t\tresult.menus.items += itemCount;\n\t\t}\n\t}\n\n\t// 9. Redirects\n\tif (seed.redirects) {\n\t\tconst redirectRepo = new RedirectRepository(db);\n\n\t\tfor (const redirect of seed.redirects) {\n\t\t\tconst existing = await redirectRepo.findBySource(redirect.source);\n\t\t\tif (existing) {\n\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\tthrow new Error(`Conflict: redirect \"${redirect.source}\" already exists`);\n\t\t\t\t}\n\n\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\tawait redirectRepo.update(existing.id, {\n\t\t\t\t\t\tdestination: redirect.destination,\n\t\t\t\t\t\ttype: redirect.type,\n\t\t\t\t\t\tenabled: redirect.enabled,\n\t\t\t\t\t\tgroupName: redirect.groupName,\n\t\t\t\t\t});\n\t\t\t\t\tresult.redirects.updated++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// skip\n\t\t\t\tresult.redirects.skipped++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tawait redirectRepo.create({\n\t\t\t\tsource: redirect.source,\n\t\t\t\tdestination: redirect.destination,\n\t\t\t\ttype: redirect.type,\n\t\t\t\tenabled: redirect.enabled,\n\t\t\t\tgroupName: redirect.groupName,\n\t\t\t});\n\t\t\tresult.redirects.created++;\n\t\t}\n\t}\n\n\t// 10. Widget Areas and Widgets\n\tif (seed.widgetAreas) {\n\t\tfor (const area of seed.widgetAreas) {\n\t\t\t// Check if area exists\n\t\t\tconst existingArea = await db\n\t\t\t\t.selectFrom(\"_emdash_widget_areas\")\n\t\t\t\t.selectAll()\n\t\t\t\t.where(\"name\", \"=\", area.name)\n\t\t\t\t.executeTakeFirst();\n\n\t\t\tlet areaId: string;\n\n\t\t\tif (existingArea) {\n\t\t\t\tareaId = existingArea.id;\n\t\t\t\t// Clear existing widgets (areas are recreated)\n\t\t\t\tawait db.deleteFrom(\"_emdash_widgets\").where(\"area_id\", \"=\", areaId).execute();\n\t\t\t} else {\n\t\t\t\t// Create area\n\t\t\t\tareaId = ulid();\n\t\t\t\tawait db\n\t\t\t\t\t.insertInto(\"_emdash_widget_areas\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tid: areaId,\n\t\t\t\t\t\tname: area.name,\n\t\t\t\t\t\tlabel: area.label,\n\t\t\t\t\t\tdescription: area.description ?? null,\n\t\t\t\t\t})\n\t\t\t\t\t.execute();\n\t\t\t\tresult.widgetAreas.created++;\n\t\t\t}\n\n\t\t\t// Create widgets\n\t\t\tfor (let i = 0; i < area.widgets.length; i++) {\n\t\t\t\tconst widget = area.widgets[i];\n\t\t\t\tawait applyWidget(db, areaId, widget, i);\n\t\t\t\tresult.widgetAreas.widgets++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// 11. Sections\n\tif (seed.sections) {\n\t\tfor (const section of seed.sections) {\n\t\t\t// Check if section exists\n\t\t\tconst existing = await db\n\t\t\t\t.selectFrom(\"_emdash_sections\")\n\t\t\t\t.select(\"id\")\n\t\t\t\t.where(\"slug\", \"=\", section.slug)\n\t\t\t\t.executeTakeFirst();\n\n\t\t\tif (existing) {\n\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\tthrow new Error(`Conflict: section \"${section.slug}\" already exists`);\n\t\t\t\t}\n\n\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\tawait db\n\t\t\t\t\t\t.updateTable(\"_emdash_sections\")\n\t\t\t\t\t\t.set({\n\t\t\t\t\t\t\ttitle: section.title,\n\t\t\t\t\t\t\tdescription: section.description ?? null,\n\t\t\t\t\t\t\tkeywords: section.keywords ? JSON.stringify(section.keywords) : null,\n\t\t\t\t\t\t\tcontent: JSON.stringify(section.content),\n\t\t\t\t\t\t\tsource: section.source || \"theme\",\n\t\t\t\t\t\t\tupdated_at: new Date().toISOString(),\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.where(\"id\", \"=\", existing.id)\n\t\t\t\t\t\t.execute();\n\t\t\t\t\tresult.sections.updated++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// skip\n\t\t\t\tresult.sections.skipped++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst id = ulid();\n\t\t\tconst now = new Date().toISOString();\n\n\t\t\tawait db\n\t\t\t\t.insertInto(\"_emdash_sections\")\n\t\t\t\t.values({\n\t\t\t\t\tid,\n\t\t\t\t\tslug: section.slug,\n\t\t\t\t\ttitle: section.title,\n\t\t\t\t\tdescription: section.description ?? null,\n\t\t\t\t\tkeywords: section.keywords ? JSON.stringify(section.keywords) : null,\n\t\t\t\t\tcontent: JSON.stringify(section.content),\n\t\t\t\t\tpreview_media_id: null,\n\t\t\t\t\tsource: section.source || \"theme\",\n\t\t\t\t\ttheme_id: section.source === \"theme\" ? section.slug : null,\n\t\t\t\t\tcreated_at: now,\n\t\t\t\t\tupdated_at: now,\n\t\t\t\t})\n\t\t\t\t.execute();\n\n\t\t\tresult.sections.created++;\n\t\t}\n\t}\n\n\t// 11. Enable search for collections that have `search` in supports\n\tif (seed.collections) {\n\t\tconst ftsManager = new FTSManager(db);\n\n\t\tfor (const collection of seed.collections) {\n\t\t\tif (collection.supports?.includes(\"search\")) {\n\t\t\t\t// Check if there are searchable fields\n\t\t\t\tconst searchableFields = await ftsManager.getSearchableFields(collection.slug);\n\t\t\t\tif (searchableFields.length > 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ftsManager.enableSearch(collection.slug);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t// Log but don't fail - search can be enabled manually later\n\t\t\t\t\t\tconsole.warn(`Failed to enable search for ${collection.slug}:`, err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Invalidate caches that may have been affected by seed data.\n\t// Seed creates bylines, redirects, and collections, all of which\n\t// have module-level caches in the hot path.\n\tconst { invalidateBylineCache } = await import(\"../bylines/index.js\");\n\tconst { invalidateRedirectCache } = await import(\"../redirects/cache.js\");\n\tconst { invalidateUrlPatternCache } = await import(\"../query.js\");\n\tinvalidateBylineCache();\n\tinvalidateRedirectCache();\n\tinvalidateUrlPatternCache();\n\n\treturn result;\n}\n\n/**\n * Apply hierarchical taxonomy terms (parents before children)\n */\nasync function applyHierarchicalTerms(\n\ttermRepo: TaxonomyRepository,\n\ttaxonomyName: string,\n\tdefLocale: string,\n\tterms: SeedTaxonomyTerm[],\n\ttermSeedIdMap: Map<string, string>,\n\tresult: SeedApplyResult,\n\tonConflict: \"skip\" | \"update\" | \"error\" = \"skip\",\n): Promise<void> {\n\t// \"locale::slug\" -> id, so the same slug can resolve per locale.\n\tconst slugToId = new Map<string, string>();\n\tconst resolveTermLocale = (term: SeedTaxonomyTerm) =>\n\t\tresolveConfiguredLocale(term.locale ?? defLocale);\n\n\t// Multiple passes — handles deep nesting and translationOf forward refs.\n\tlet remaining = [...terms];\n\tlet maxPasses = 10;\n\n\twhile (remaining.length > 0 && maxPasses > 0) {\n\t\tconst processedThisPass: string[] = [];\n\n\t\tfor (const term of remaining) {\n\t\t\tconst termLocale = resolveTermLocale(term);\n\t\t\tconst parentReady = !term.parent || slugToId.has(`${termLocale}::${term.parent}`);\n\t\t\tconst translationReady = !term.translationOf || termSeedIdMap.has(term.translationOf);\n\n\t\t\tif (!parentReady || !translationReady) continue;\n\n\t\t\tconst parentId = term.parent ? slugToId.get(`${termLocale}::${term.parent}`) : undefined;\n\t\t\tconst translationOf = term.translationOf ? termSeedIdMap.get(term.translationOf) : undefined;\n\n\t\t\tconst existing = await termRepo.findBySlug(taxonomyName, term.slug, termLocale);\n\t\t\tif (existing) {\n\t\t\t\tif (onConflict === \"error\") {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Conflict: taxonomy term \"${term.slug}\" in \"${taxonomyName}\" (${termLocale}) already exists`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (onConflict === \"update\") {\n\t\t\t\t\tawait termRepo.update(existing.id, {\n\t\t\t\t\t\tlabel: term.label,\n\t\t\t\t\t\tparentId,\n\t\t\t\t\t\tdata: term.description ? { description: term.description } : {},\n\t\t\t\t\t});\n\t\t\t\t\tresult.taxonomies.terms++;\n\t\t\t\t}\n\t\t\t\tslugToId.set(`${termLocale}::${term.slug}`, existing.id);\n\t\t\t\tif (term.id) termSeedIdMap.set(term.id, existing.id);\n\t\t\t} else {\n\t\t\t\tconst created = await termRepo.create({\n\t\t\t\t\tname: taxonomyName,\n\t\t\t\t\tslug: term.slug,\n\t\t\t\t\tlabel: term.label,\n\t\t\t\t\tparentId,\n\t\t\t\t\tdata: term.description ? { description: term.description } : undefined,\n\t\t\t\t\tlocale: termLocale,\n\t\t\t\t\ttranslationOf,\n\t\t\t\t});\n\t\t\t\tslugToId.set(`${termLocale}::${term.slug}`, created.id);\n\t\t\t\tif (term.id) termSeedIdMap.set(term.id, created.id);\n\t\t\t\tresult.taxonomies.terms++;\n\t\t\t}\n\n\t\t\tprocessedThisPass.push(term.slug + \"::\" + termLocale);\n\t\t}\n\n\t\tremaining = remaining.filter(\n\t\t\t(term) => !processedThisPass.includes(term.slug + \"::\" + resolveTermLocale(term)),\n\t\t);\n\t\tmaxPasses--;\n\t}\n\n\tif (remaining.length > 0) {\n\t\tconsole.warn(`Could not process ${remaining.length} terms due to missing parents/translations`);\n\t}\n}\n\n/**\n * Apply byline credits to a content entry.\n * In update mode, clears existing credits even if the seed has none.\n */\nasync function applyContentBylines(\n\tbylineRepo: BylineRepository,\n\tcollectionSlug: string,\n\tcontentId: string,\n\tentry: {\n\t\tid: string;\n\t\tslug?: string | null;\n\t\tbylines?: Array<{ byline: string; roleLabel?: string }>;\n\t},\n\tseedBylineIdMap: Map<string, string>,\n\tisUpdate = false,\n): Promise<void> {\n\tif (!entry.bylines || entry.bylines.length === 0) {\n\t\t// In update mode, clear existing bylines when the seed entry has none\n\t\tif (isUpdate) {\n\t\t\tawait bylineRepo.setContentBylines(collectionSlug, contentId, []);\n\t\t}\n\t\treturn;\n\t}\n\n\tconst credits = entry.bylines\n\t\t.map((credit) => {\n\t\t\tconst bylineId = seedBylineIdMap.get(credit.byline);\n\t\t\tif (!bylineId) return null;\n\t\t\treturn {\n\t\t\t\tbylineId,\n\t\t\t\troleLabel: credit.roleLabel ?? null,\n\t\t\t};\n\t\t})\n\t\t.filter((credit): credit is { bylineId: string; roleLabel: string | null } => Boolean(credit));\n\n\tif (credits.length !== entry.bylines.length) {\n\t\tconsole.warn(\n\t\t\t`content.${collectionSlug}.${entry.slug ?? entry.id}: one or more byline refs could not be resolved`,\n\t\t);\n\t}\n\n\t// In update mode, always call setContentBylines (even with empty credits)\n\t// to clear stale assignments when all byline refs fail to resolve.\n\t// In create mode, only call if there are credits to assign.\n\tif (credits.length > 0 || isUpdate) {\n\t\tawait bylineRepo.setContentBylines(collectionSlug, contentId, credits);\n\t}\n}\n\n/**\n * Apply taxonomy term assignments to a content entry.\n * In update mode, clears existing assignments before re-attaching.\n */\nasync function applyContentTaxonomies(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n\tentry: { taxonomies?: Record<string, string[]> },\n\tisUpdate: boolean,\n): Promise<void> {\n\tconst termRepo = new TaxonomyRepository(db);\n\t// In update mode, clear existing taxonomy assignments first\n\tif (isUpdate) {\n\t\tawait termRepo.clearEntryTerms(collectionSlug, contentId);\n\t}\n\n\tif (!entry.taxonomies) {\n\t\t// In update mode we may have just deleted rows above; invalidate so\n\t\t// hydration doesn't serve stale \"has terms\" cached value.\n\t\tif (isUpdate) {\n\t\t\tconst { invalidateTermCache } = await import(\"../taxonomies/index.js\");\n\t\t\tinvalidateTermCache();\n\t\t}\n\t\treturn;\n\t}\n\n\tfor (const [taxonomyName, termSlugs] of Object.entries(entry.taxonomies)) {\n\t\tfor (const termSlug of termSlugs) {\n\t\t\tconst term = await termRepo.findBySlug(taxonomyName, termSlug);\n\t\t\tif (term) {\n\t\t\t\tawait termRepo.attachToEntry(collectionSlug, contentId, term.id);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Seed writes directly to content_taxonomies. Clear the cache so\n\t// the worker lifetime cached \"has any term assignments\" probe\n\t// re-runs on the next read.\n\tconst { invalidateTermCache } = await import(\"../taxonomies/index.js\");\n\tinvalidateTermCache();\n}\n\n/**\n * Apply menu items recursively.\n *\n * When a `SeedMenuItem` carries `id`/`translationOf`, the import resolves the\n * source item's `translation_group` so cross-locale \"same nav entry\" links\n * survive export → apply. Items without `translationOf` get a fresh group\n * (= their own id).\n */\nasync function applyMenuItems(\n\tdb: Kysely<Database>,\n\tmenuId: string,\n\tlocale: string,\n\titems: SeedMenuItem[],\n\tparentId: string | null,\n\tstartOrder: number,\n\tseedIdMap: Map<string, string>,\n\titemSeedIdMap: Map<string, { id: string; translationGroup: string }>,\n): Promise<number> {\n\tlet count = 0;\n\tlet order = startOrder;\n\n\tfor (const item of items) {\n\t\tconst itemId = ulid();\n\t\tconst itemLocale = item.locale ?? locale;\n\n\t\t// Resolve reference if needed\n\t\tlet referenceId: string | null = null;\n\t\tlet referenceCollection: string | null = null;\n\n\t\tif (item.type === \"page\" || item.type === \"post\") {\n\t\t\t// Try to resolve from seedIdMap\n\t\t\tif (item.ref && seedIdMap.has(item.ref)) {\n\t\t\t\treferenceId = seedIdMap.get(item.ref)!;\n\t\t\t\t// Default to plural collection name (pages/posts) if not specified\n\t\t\t\treferenceCollection = item.collection || `${item.type}s`;\n\t\t\t}\n\t\t\t// If not in map, the content might not exist yet (will be broken link)\n\t\t}\n\n\t\tlet translationGroup = itemId;\n\t\tif (item.translationOf) {\n\t\t\tconst source = itemSeedIdMap.get(item.translationOf);\n\t\t\tif (source) translationGroup = source.translationGroup;\n\t\t\telse\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`menu item \"${item.label ?? item.url ?? item.ref ?? \"(unlabeled)\"}\" (${itemLocale}): translationOf \"${item.translationOf}\" not found yet; minting a fresh group.`,\n\t\t\t\t);\n\t\t}\n\n\t\tawait db\n\t\t\t.insertInto(\"_emdash_menu_items\")\n\t\t\t.values({\n\t\t\t\tid: itemId,\n\t\t\t\tmenu_id: menuId,\n\t\t\t\tparent_id: parentId,\n\t\t\t\tsort_order: order,\n\t\t\t\ttype: item.type,\n\t\t\t\treference_collection: referenceCollection,\n\t\t\t\treference_id: referenceId,\n\t\t\t\tcustom_url: item.url ?? null,\n\t\t\t\tlabel: item.label || \"\",\n\t\t\t\ttitle_attr: item.titleAttr ?? null,\n\t\t\t\ttarget: item.target ?? null,\n\t\t\t\tcss_classes: item.cssClasses ?? null,\n\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\tlocale: itemLocale,\n\t\t\t\ttranslation_group: translationGroup,\n\t\t\t})\n\t\t\t.execute();\n\n\t\tif (item.id) itemSeedIdMap.set(item.id, { id: itemId, translationGroup });\n\n\t\tcount++;\n\t\torder++;\n\n\t\tif (item.children && item.children.length > 0) {\n\t\t\tconst childCount = await applyMenuItems(\n\t\t\t\tdb,\n\t\t\t\tmenuId,\n\t\t\t\titemLocale,\n\t\t\t\titem.children,\n\t\t\t\titemId,\n\t\t\t\t0,\n\t\t\t\tseedIdMap,\n\t\t\t\titemSeedIdMap,\n\t\t\t);\n\t\t\tcount += childCount;\n\t\t}\n\t}\n\n\treturn count;\n}\n\n/**\n * Apply a widget\n */\nasync function applyWidget(\n\tdb: Kysely<Database>,\n\tareaId: string,\n\twidget: SeedWidget,\n\tsortOrder: number,\n): Promise<void> {\n\tawait db\n\t\t.insertInto(\"_emdash_widgets\")\n\t\t.values({\n\t\t\tid: ulid(),\n\t\t\tarea_id: areaId,\n\t\t\tsort_order: sortOrder,\n\t\t\ttype: widget.type,\n\t\t\ttitle: widget.title ?? null,\n\t\t\t// `widget.content` is Portable Text for content-type widgets;\n\t\t\t// for other widget kinds it's null.\n\t\t\tcontent: widget.content ? JSON.stringify(widget.content) : null,\n\t\t\tmenu_name: widget.menuName ?? null,\n\t\t\tcomponent_id: widget.componentId ?? null,\n\t\t\tcomponent_props: widget.props ? JSON.stringify(widget.props) : null,\n\t\t})\n\t\t.execute();\n}\n\n/**\n * Context for media resolution during seed application\n */\ninterface MediaContext {\n\tdb: Kysely<Database>;\n\tstorage: Storage | null;\n\tskipMediaDownload: boolean;\n\tmediaCache: Map<string, MediaValue>; // URL -> resolved MediaValue\n}\n\n/**\n * Type guard for $media reference\n */\nfunction isSeedMediaReference(value: unknown): value is SeedMediaReference {\n\tif (typeof value !== \"object\" || value === null || !(\"$media\" in value)) {\n\t\treturn false;\n\t}\n\tconst media = (value as Record<string, unknown>).$media;\n\treturn (\n\t\ttypeof media === \"object\" &&\n\t\tmedia !== null &&\n\t\t\"url\" in media &&\n\t\ttypeof (media as Record<string, unknown>).url === \"string\"\n\t);\n}\n\n/**\n * Resolve $ref: and $media references in content data\n */\nasync function resolveReferences(\n\tdata: Record<string, unknown>,\n\tseedIdMap: Map<string, string>,\n\tmediaContext: MediaContext,\n\tresult: SeedApplyResult,\n): Promise<Record<string, unknown>> {\n\tconst resolved: Record<string, unknown> = {};\n\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tresolved[key] = await resolveValue(value, seedIdMap, mediaContext, result);\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Resolve a single value recursively\n */\nasync function resolveValue(\n\tvalue: unknown,\n\tseedIdMap: Map<string, string>,\n\tmediaContext: MediaContext,\n\tresult: SeedApplyResult,\n): Promise<unknown> {\n\t// Handle $ref: syntax\n\tif (typeof value === \"string\" && value.startsWith(\"$ref:\")) {\n\t\tconst seedId = value.slice(5);\n\t\treturn seedIdMap.get(seedId) ?? value; // Return unresolved if not found\n\t}\n\n\t// Handle $media syntax\n\tif (isSeedMediaReference(value)) {\n\t\treturn resolveMedia(value, mediaContext, result);\n\t}\n\n\t// Handle arrays\n\tif (Array.isArray(value)) {\n\t\treturn Promise.all(value.map((item) => resolveValue(item, seedIdMap, mediaContext, result)));\n\t}\n\n\t// Handle objects recursively\n\tif (typeof value === \"object\" && value !== null) {\n\t\tconst resolved: Record<string, unknown> = {};\n\t\tfor (const [k, v] of Object.entries(value)) {\n\t\t\tresolved[k] = await resolveValue(v, seedIdMap, mediaContext, result);\n\t\t}\n\t\treturn resolved;\n\t}\n\n\treturn value;\n}\n\n/**\n * Resolve a seeded byline avatar to a `media` row id. The file is assumed to\n * already exist in storage (the caller supplies its `storageKey`), so nothing\n * is downloaded or uploaded.\n *\n * Idempotent: if a media row with the same `storageKey` already exists it is\n * reused rather than duplicated, so re-applying a seed in `update` mode does\n * not leak rows. `created` reports whether a new row was inserted, so the\n * caller can both account for it and delete it if the subsequent byline write\n * fails (the only cross-dialect way to avoid an orphan — `withTransaction`\n * is a no-op on D1).\n */\nasync function resolveSeedBylineAvatar(\n\tdb: Kysely<Database>,\n\tavatar: SeedBylineAvatar,\n): Promise<{ id: string; created: boolean }> {\n\t// `media.storage_key` has no unique constraint, so order deterministically\n\t// to reuse the same row across runs if duplicates already exist. (Concurrent\n\t// seed applies against one DB are out of scope; seeding is a single-shot\n\t// init operation.)\n\tconst existing = await db\n\t\t.selectFrom(\"media\")\n\t\t.select(\"id\")\n\t\t.where(\"storage_key\", \"=\", avatar.storageKey)\n\t\t.orderBy(\"id\", \"asc\")\n\t\t.executeTakeFirst();\n\tif (existing) return { id: existing.id, created: false };\n\n\tconst basename = avatar.storageKey.split(\"/\").pop();\n\tconst filename =\n\t\tavatar.filename ?? (basename && basename.length > 0 ? basename : avatar.storageKey);\n\tconst created = await new MediaRepository(db).create({\n\t\tfilename,\n\t\tmimeType: avatar.mimeType ?? \"image/jpeg\",\n\t\tstorageKey: avatar.storageKey,\n\t\talt: avatar.alt,\n\t\twidth: avatar.width,\n\t\theight: avatar.height,\n\t\tstatus: \"ready\",\n\t});\n\treturn { id: created.id, created: true };\n}\n\n/**\n * Delete a media row by id. Best-effort cleanup for a failed byline write: a\n * failure here must not mask the original error that triggered the cleanup, so\n * it is logged and swallowed rather than thrown.\n */\nasync function deleteMediaRow(db: Kysely<Database>, id: string): Promise<void> {\n\ttry {\n\t\tawait db.deleteFrom(\"media\").where(\"id\", \"=\", id).execute();\n\t} catch (error) {\n\t\tconsole.warn(`[seed] failed to clean up orphaned avatar media ${id}:`, error);\n\t}\n}\n\n/**\n * Resolve a $media reference by downloading and uploading the media\n */\nasync function resolveMedia(\n\tref: SeedMediaReference,\n\tctx: MediaContext,\n\tresult: SeedApplyResult,\n): Promise<MediaValue | null> {\n\tconst { url, alt, filename, caption } = ref.$media;\n\n\t// Check cache first\n\tconst cached = ctx.mediaCache.get(url);\n\tif (cached) {\n\t\tresult.media.skipped++;\n\t\treturn { ...cached, alt: alt ?? cached.alt };\n\t}\n\n\t// When skipMediaDownload is set, resolve $media to an external URL reference\n\t// without downloading or storing anything. Used by playground mode.\n\tif (ctx.skipMediaDownload) {\n\t\tconst mediaValue: MediaValue = {\n\t\t\tprovider: \"external\",\n\t\t\tid: ulid(),\n\t\t\tsrc: url,\n\t\t\talt: alt ?? undefined,\n\t\t\tfilename: filename ?? undefined,\n\t\t};\n\t\tctx.mediaCache.set(url, mediaValue);\n\t\tresult.media.created++;\n\t\treturn mediaValue;\n\t}\n\n\t// Storage is required for $media resolution\n\tif (!ctx.storage) {\n\t\tconsole.warn(`Skipping $media reference (no storage configured): ${url}`);\n\t\tresult.media.skipped++;\n\t\treturn null;\n\t}\n\n\ttry {\n\t\t// SSRF protection: validate URL before downloading\n\t\tvalidateExternalUrl(url);\n\n\t\t// Download the media (ssrfSafeFetch re-validates redirect targets)\n\t\tconsole.log(` 📥 Downloading: ${url}`);\n\t\tconst response = await ssrfSafeFetch(url, {\n\t\t\theaders: {\n\t\t\t\t// Some services like Unsplash require a user-agent\n\t\t\t\t\"User-Agent\": \"EmDash-CMS/1.0\",\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconsole.warn(` ⚠️ Failed to download ${url}: ${response.status}`);\n\t\t\tresult.media.skipped++;\n\t\t\treturn null;\n\t\t}\n\n\t\t// Get content type and determine extension\n\t\tconst contentType = response.headers.get(\"content-type\") || \"application/octet-stream\";\n\t\tconst ext = getExtensionFromContentType(contentType) || getExtensionFromUrl(url) || \".bin\";\n\n\t\t// Generate filename and storage key\n\t\tconst storageId = ulid();\n\t\tconst finalFilename = filename || generateFilename(url, ext);\n\t\tconst storageKey = `${storageId}${ext}`;\n\n\t\t// Get the body as buffer\n\t\tconst arrayBuffer = await response.arrayBuffer();\n\t\tconst body = new Uint8Array(arrayBuffer);\n\n\t\t// Get image dimensions if it's an image\n\t\tlet width: number | undefined;\n\t\tlet height: number | undefined;\n\t\tif (contentType.startsWith(\"image/\")) {\n\t\t\tconst dimensions = getImageDimensions(body);\n\t\t\twidth = dimensions?.width;\n\t\t\theight = dimensions?.height;\n\t\t}\n\n\t\t// Upload to storage\n\t\tawait ctx.storage.upload({\n\t\t\tkey: storageKey,\n\t\t\tbody,\n\t\t\tcontentType,\n\t\t});\n\n\t\t// Create media record\n\t\tconst mediaRepo = new MediaRepository(ctx.db);\n\t\tconst media = await mediaRepo.create({\n\t\t\tfilename: finalFilename,\n\t\t\tmimeType: contentType,\n\t\t\tsize: body.length,\n\t\t\twidth,\n\t\t\theight,\n\t\t\talt,\n\t\t\tcaption,\n\t\t\tstorageKey,\n\t\t\tstatus: \"ready\",\n\t\t});\n\n\t\t// Create the MediaValue - only store id, URL is built at runtime by EmDashMedia\n\t\tconst mediaValue: MediaValue = {\n\t\t\tprovider: \"local\",\n\t\t\tid: media.id,\n\t\t\talt: alt ?? undefined,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tmimeType: contentType,\n\t\t\tfilename: finalFilename,\n\t\t\tmeta: { storageKey },\n\t\t};\n\n\t\t// Cache for reuse\n\t\tctx.mediaCache.set(url, mediaValue);\n\t\tresult.media.created++;\n\n\t\tconsole.log(` ✅ Uploaded: ${finalFilename}`);\n\t\treturn mediaValue;\n\t} catch (error) {\n\t\tconsole.warn(\n\t\t\t` ⚠️ Error processing $media ${url}:`,\n\t\t\terror instanceof Error ? error.message : error,\n\t\t);\n\t\tresult.media.skipped++;\n\t\treturn null;\n\t}\n}\n\n/**\n * Get file extension from content type\n */\nfunction getExtensionFromContentType(contentType: string): string | null {\n\t// Handle content-type with parameters like \"image/jpeg; charset=utf-8\"\n\tconst baseMime = contentType.split(\";\")[0].trim();\n\tconst ext = mime.getExtension(baseMime);\n\treturn ext ? `.${ext}` : null;\n}\n\n/**\n * Get file extension from URL\n */\nfunction getExtensionFromUrl(url: string): string | null {\n\ttry {\n\t\tconst pathname = new URL(url).pathname;\n\t\tconst match = pathname.match(FILE_EXTENSION_PATTERN);\n\t\treturn match ? `.${match[1]}` : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Generate a filename from URL\n */\nfunction generateFilename(url: string, ext: string): string {\n\ttry {\n\t\tconst pathname = new URL(url).pathname;\n\t\tconst basename = pathname.split(\"/\").pop() || \"media\";\n\t\t// Remove any existing extension and query params\n\t\tconst name = basename.replace(EXTENSION_PATTERN, \"\").replace(QUERY_PARAM_PATTERN, \"\");\n\t\t// Sanitize: only alphanumeric, dash, underscore\n\t\tconst sanitized = name.replace(SANITIZE_PATTERN, \"-\").replace(MULTIPLE_HYPHENS_PATTERN, \"-\");\n\t\treturn `${sanitized || \"media\"}${ext}`;\n\t} catch {\n\t\treturn `media${ext}`;\n\t}\n}\n\n/**\n * Get image dimensions from buffer using image-size.\n * Supports PNG, JPEG, GIF, WebP, AVIF, SVG, TIFF, and more.\n */\nfunction getImageDimensions(buffer: Uint8Array): { width: number; height: number } | null {\n\ttry {\n\t\tconst result = imageSize(buffer);\n\t\tif (result.width != null && result.height != null) {\n\t\t\treturn { width: result.width, height: result.height };\n\t\t}\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
- import { i as resolveAndValidateExternalUrlTarget, t as SsrfError } from "./ssrf-5sIM5jzl.mjs";
1
+ import { i as resolveAndValidateExternalUrlTarget, t as SsrfError } from "./ssrf-gl4gFNhw.mjs";
2
2
  import { RECORD_SCOPED_BLOB_CACHE_TYPE } from "@emdash-cms/registry-lexicons";
3
- import { isDid } from "@atcute/lexicons/syntax";
4
3
 
5
4
  //#region ../registry-verification/dist/auth-B730dpJ4.js
6
5
  const UNSUPPORTED_AUTH_MESSAGE = "This release requires an authentication method the client does not support.";
@@ -167,7 +166,7 @@ const DIGITS = /^\d+$/;
167
166
  const IPV4_LITERAL = /^\d{1,3}(?:\.\d{1,3}){3}$/;
168
167
  const IPV4_PART = /^\d{1,3}$/;
169
168
  const IPV6_PART = /^[0-9a-f]{1,4}$/i;
170
- const TRAILING_DOT$2 = /\.+$/;
169
+ const TRAILING_DOT$1 = /\.+$/;
171
170
  const DEFAULT_FETCH_LIMITS = {
172
171
  headerTimeoutMs: 1e4,
173
172
  totalTimeoutMs: 3e4,
@@ -237,7 +236,7 @@ function parseAndValidateUrl(value, base, allowHttpLocalhost = false) {
237
236
  }
238
237
  function isAllowedLoopback(url, enabled) {
239
238
  if (!enabled || url.protocol !== "http:" && url.protocol !== "https:") return false;
240
- const hostname = url.hostname.toLowerCase().replace(TRAILING_DOT$2, "");
239
+ const hostname = url.hostname.toLowerCase().replace(TRAILING_DOT$1, "");
241
240
  return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
242
241
  }
243
242
  async function validateHost(url, resolver, timeoutMs) {
@@ -620,7 +619,7 @@ function isSafePathSegment(value) {
620
619
 
621
620
  //#endregion
622
621
  //#region src/registry/artifact-fetch.ts
623
- const TRAILING_DOT$1 = /\.+$/;
622
+ const TRAILING_DOT = /\.+$/;
624
623
  const HEADER_END = new Uint8Array([
625
624
  13,
626
625
  10,
@@ -642,7 +641,7 @@ const LOCALHOST_HOSTNAMES = new Set([
642
641
  ]);
643
642
  let defaultTransport = null;
644
643
  function isLocalhostHostname(hostname) {
645
- const normalized = hostname.toLowerCase().replace(TRAILING_DOT$1, "");
644
+ const normalized = hostname.toLowerCase().replace(TRAILING_DOT, "");
646
645
  return LOCALHOST_HOSTNAMES.has(normalized) || normalized.endsWith(".localhost") || normalized === "127.0.0.1" || normalized === "::1" || normalized === "[::1]" || normalized.startsWith("::ffff:127.") || normalized.startsWith("::ffff:7f00:");
647
646
  }
648
647
  async function resolveSafeArtifactTarget(urlString) {
@@ -654,7 +653,7 @@ async function resolveSafeArtifactTarget(urlString) {
654
653
  }
655
654
  if (url.protocol !== "https:" && url.protocol !== "http:") throw new Error(`Artifact URL protocol not allowed: ${url.protocol}`);
656
655
  if (url.username || url.password) throw new Error("Artifact URL must not contain embedded credentials");
657
- const hostname = stripIpv6Brackets(url.hostname.toLowerCase().replace(TRAILING_DOT$1, ""));
656
+ const hostname = stripIpv6Brackets(url.hostname.toLowerCase().replace(TRAILING_DOT, ""));
658
657
  const localhost = isLocalhostHostname(hostname);
659
658
  if (!import.meta.env.DEV) {
660
659
  if (url.protocol === "http:") throw new Error("Artifact URL must use https");
@@ -969,195 +968,5 @@ async function abortable(operation, signal, onAbort) {
969
968
  }
970
969
 
971
970
  //#endregion
972
- //#region src/registry/config.ts
973
- /**
974
- * Helpers for normalizing the experimental registry integration option
975
- * (`config.experimental.registry` in `astro.config.mjs`) into the shape
976
- * exposed on the admin manifest.
977
- *
978
- * The integration option accepts a human-friendly duration string for
979
- * `policy.minimumReleaseAge` (`"48h"`, `"7d"`); the manifest exposes
980
- * seconds so the browser doesn't need a duration parser.
981
- */
982
- /**
983
- * Canonicalize a capabilities list for set-style comparison.
984
- *
985
- * Capabilities (the legacy declared-access shape used by the current
986
- * sandbox enforcer) are conceptually a *set*: order, duplicates, and
987
- * non-string entries don't carry meaning. The install handler's drift
988
- * check compares the admin's acknowledged set against the bundle
989
- * manifest's set; both sides pass through this canonicalizer first so
990
- * an aggregator-supplied array with unstable order or junk entries
991
- * can't cause a spurious drift rejection.
992
- *
993
- * Filters non-strings, deduplicates, and sorts lexically. Named to
994
- * avoid shadowing `@emdash-cms/plugin-types`'s existing
995
- * `normalizeCapabilities` (which dedupes + applies the deprecated →
996
- * current alias map but does not filter junk or sort).
997
- *
998
- * Exported so the same shape is produced by the browser before sending
999
- * the `acknowledgedDeclaredAccess` payload and by the server before
1000
- * comparing against the bundle.
1001
- */
1002
- function canonicalCapabilitiesForDriftCheck(value) {
1003
- if (!Array.isArray(value)) return [];
1004
- const seen = /* @__PURE__ */ new Set();
1005
- for (const entry of value) if (typeof entry === "string" && entry.length > 0) seen.add(entry);
1006
- return [...seen].toSorted();
1007
- }
1008
- /**
1009
- * Returns whether a `(publisher_did, slug)` pair is on the
1010
- * minimum-release-age exemption list. Exported so the same matcher is
1011
- * used by the browser policy filter and the server-side install
1012
- * enforcement.
1013
- *
1014
- * Matching is DID-only. Handles are aggregator-supplied envelope data
1015
- * (mutable, controlled by an attacker who compromises the aggregator)
1016
- * and cannot be used as a trust input -- a compromised aggregator
1017
- * could claim any handle for any package and bypass the holdback. DIDs
1018
- * are part of the AT URI of the package record and are independently
1019
- * resolvable, so even a compromised aggregator can't lie about the
1020
- * publisher DID without also breaking checksum verification downstream.
1021
- *
1022
- * Entries from config are already lowercased at manifest-build time.
1023
- * Runtime values are lowercased here at compare time.
1024
- */
1025
- function releaseExemptFromMinimumAge(exclude, publisherDid, slug) {
1026
- if (!exclude || exclude.length === 0) return false;
1027
- const didLower = publisherDid.toLowerCase();
1028
- const fullDid = `${didLower}/${slug.toLowerCase()}`;
1029
- for (const entry of exclude) {
1030
- if (entry === didLower) return true;
1031
- if (entry === fullDid) return true;
1032
- }
1033
- return false;
1034
- }
1035
- const DURATION_PATTERN = /^(\d+)(s|m|h|d|w)$/;
1036
- /** Trailing slashes on the aggregator URL, stripped during normalization. */
1037
- const TRAILING_SLASHES = /\/+$/;
1038
- /** Trailing dot on a hostname, stripped before URL host comparisons. */
1039
- const TRAILING_DOT = /\.$/;
1040
- const REGISTRY_PACKAGE_SLUG_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
1041
- /**
1042
- * Parse a duration string or raw second count into a non-negative
1043
- * integer count of seconds. Throws on unrecognised input so config
1044
- * mistakes fail at startup rather than silently disabling the policy.
1045
- */
1046
- function parseDurationSeconds(duration) {
1047
- if (typeof duration === "number") {
1048
- if (!Number.isFinite(duration) || duration < 0) throw new Error(`Invalid duration: ${duration} (must be a non-negative finite number)`);
1049
- return Math.floor(duration);
1050
- }
1051
- const match = duration.match(DURATION_PATTERN);
1052
- if (!match) throw new Error(`Invalid duration format: "${duration}". Use a duration string like "48h", "7d", "30m", or a number of seconds.`);
1053
- const value = parseInt(match[1], 10);
1054
- const unit = match[2];
1055
- switch (unit) {
1056
- case "s": return value;
1057
- case "m": return value * 60;
1058
- case "h": return value * 60 * 60;
1059
- case "d": return value * 24 * 60 * 60;
1060
- case "w": return value * 7 * 24 * 60 * 60;
1061
- default: throw new Error(`Unknown duration unit: ${unit}`);
1062
- }
1063
- }
1064
- /**
1065
- * Validate that `aggregatorUrl` is a safe outbound target for the
1066
- * registry's XRPC calls. Same posture as artifact downloads: HTTPS
1067
- * required in production; `http://localhost` allowed only in dev.
1068
- *
1069
- * The aggregator's responses are the trust source for release records,
1070
- * checksums, labels, artifact cache descriptors, and `indexedAt` (until full MST
1071
- * verification lands). Allowing plain HTTP here would let a network
1072
- * attacker swap a release record and point the artifact URL at their
1073
- * own HTTPS bundle, defeating the checksum trust chain because the
1074
- * attacker controls the unsigned transport that supplied the checksum.
1075
- */
1076
- function validateAggregatorUrl(aggregatorUrl) {
1077
- let parsed;
1078
- try {
1079
- parsed = new URL(aggregatorUrl);
1080
- } catch {
1081
- throw new Error(`registry.aggregatorUrl is not a valid URL: ${aggregatorUrl}`);
1082
- }
1083
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error(`registry.aggregatorUrl must use http or https: ${aggregatorUrl}`);
1084
- if (parsed.username || parsed.password) throw new Error("registry.aggregatorUrl must not contain embedded credentials (user:pass@)");
1085
- const rawHostname = parsed.hostname.toLowerCase().replace(TRAILING_DOT, "");
1086
- const hostname = rawHostname.startsWith("[") && rawHostname.endsWith("]") ? rawHostname.slice(1, -1) : rawHostname;
1087
- const isLocalhost = hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "::1" || hostname.startsWith("::ffff:127.") || hostname.startsWith("::ffff:7f00:");
1088
- if (!import.meta.env.DEV) {
1089
- if (parsed.protocol === "http:") throw new Error(`registry.aggregatorUrl must use https in production: ${aggregatorUrl}`);
1090
- if (isLocalhost) throw new Error(`registry.aggregatorUrl points at localhost; allowed only in dev: ${aggregatorUrl}`);
1091
- } else if (parsed.protocol === "http:" && !isLocalhost) throw new Error(`registry.aggregatorUrl must use https (http allowed only for localhost in dev): ${aggregatorUrl}`);
1092
- return parsed;
1093
- }
1094
- /**
1095
- * Expand the `RegistryConfigInput` shorthand into the full
1096
- * `RegistryConfig` object shape.
1097
- *
1098
- * Users can pass a bare aggregator URL string for the common case
1099
- * (`experimental.registry: "https://registry.emdashcms.com"`); the
1100
- * normalizer handles either form transparently.
1101
- *
1102
- * Returns `undefined` for `undefined` input so callers can chain with
1103
- * optional chaining.
1104
- */
1105
- function coerceRegistryConfig(input) {
1106
- if (input === void 0) return void 0;
1107
- if (typeof input === "string") return { aggregatorUrl: input };
1108
- return input;
1109
- }
1110
- /**
1111
- * Normalize the user-supplied `RegistryConfigInput` into the shape that
1112
- * ships to the admin browser via the manifest endpoint.
1113
- *
1114
- * Accepts either the shorthand string form
1115
- * (`"https://registry.emdashcms.com"`) or the full `RegistryConfig`
1116
- * object. Returns `null` when `input` is undefined so callers can
1117
- * spread the result directly into the manifest object.
1118
- *
1119
- * Throws if the aggregator URL is malformed, points at a forbidden host,
1120
- * or `policy.minimumReleaseAge` is unparseable. These surface at
1121
- * runtime startup as 500s from the manifest endpoint -- intended,
1122
- * because the alternative is silently disabling the registry on
1123
- * misconfigured sites.
1124
- *
1125
- * TODO: switch to a Zod schema for richer per-field error messages and
1126
- * to surface misconfigurations to the admin UI as a banner instead of
1127
- * a manifest 500.
1128
- */
1129
- function normalizeRegistryConfig(input) {
1130
- const config = coerceRegistryConfig(input);
1131
- if (!config) return null;
1132
- const aggregatorUrl = config.aggregatorUrl?.trim();
1133
- if (!aggregatorUrl) throw new Error("registry.aggregatorUrl is required when registry is configured");
1134
- validateAggregatorUrl(aggregatorUrl);
1135
- const out = { aggregatorUrl: aggregatorUrl.replace(TRAILING_SLASHES, "") };
1136
- if (config.acceptLabelers) out.acceptLabelers = config.acceptLabelers;
1137
- const policy = {};
1138
- let hasPolicy = false;
1139
- if (config.policy?.minimumReleaseAge !== void 0) {
1140
- policy.minimumReleaseAgeSeconds = parseDurationSeconds(config.policy.minimumReleaseAge);
1141
- hasPolicy = true;
1142
- }
1143
- if (config.policy?.minimumReleaseAgeExclude !== void 0) {
1144
- const list = config.policy.minimumReleaseAgeExclude.map((entry) => {
1145
- const trimmed = entry.trim();
1146
- if (!trimmed) throw new Error("registry.policy.minimumReleaseAgeExclude entries cannot be empty");
1147
- const lower = trimmed.toLowerCase();
1148
- const [did, slug, ...extra] = lower.split("/");
1149
- if (!did || !isDid(did) || extra.length > 0 || slug !== void 0 && !REGISTRY_PACKAGE_SLUG_PATTERN.test(slug)) throw new Error(`registry.policy.minimumReleaseAgeExclude entry must be a DID or <did>/<slug>: ${trimmed}`);
1150
- return lower;
1151
- });
1152
- if (list.length > 0) {
1153
- policy.minimumReleaseAgeExclude = list;
1154
- hasPolicy = true;
1155
- }
1156
- }
1157
- if (hasPolicy) out.policy = policy;
1158
- return out;
1159
- }
1160
-
1161
- //#endregion
1162
- export { releaseExemptFromMinimumAge as a, fetchReleaseArtifact as c, fetchVerifiedResource as d, computeArtifactDigestCandidates as f, verificationError as h, parseDurationSeconds as i, recordScopedImageCacheUrl as l, verifyMultihash as m, coerceRegistryConfig as n, validateAggregatorUrl as o, multihashFromBlobCid as p, normalizeRegistryConfig as r, fetchRegistryArtifactUrl as s, canonicalCapabilitiesForDriftCheck as t, resolvePublisherPdsEndpoint as u };
1163
- //# sourceMappingURL=config-it29yDLA.mjs.map
971
+ export { fetchVerifiedResource as a, verifyMultihash as c, resolvePublisherPdsEndpoint as i, verificationError as l, fetchReleaseArtifact as n, computeArtifactDigestCandidates as o, recordScopedImageCacheUrl as r, multihashFromBlobCid as s, fetchRegistryArtifactUrl as t };
972
+ //# sourceMappingURL=artifact-fetch-P2JXVwOq.mjs.map