emdash 0.21.0 → 0.22.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 (620) hide show
  1. package/dist/{adapters-BxSmgtbF.d.mts → adapters-hUy8vOB-.d.mts} +1 -1
  2. package/dist/{adapters-BxSmgtbF.d.mts.map → adapters-hUy8vOB-.d.mts.map} +1 -1
  3. package/dist/after-B1IIdH3Y.mjs +29 -0
  4. package/dist/after-B1IIdH3Y.mjs.map +1 -0
  5. package/dist/{allowed-origins-BqC8cul8.mjs → allowed-origins-DjlhyfNN.mjs} +2 -2
  6. package/dist/{allowed-origins-BqC8cul8.mjs.map → allowed-origins-DjlhyfNN.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +20 -19
  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 +4 -4
  12. package/dist/{api-DxjIV2o8.mjs → api-BDuM4bEy.mjs} +31 -25
  13. package/dist/api-BDuM4bEy.mjs.map +1 -0
  14. package/dist/{api-tokens-BFFkB0jB.mjs → api-tokens-ViYKeIp9.mjs} +13 -3
  15. package/dist/api-tokens-ViYKeIp9.mjs.map +1 -0
  16. package/dist/{apply-CLjxheyb.mjs → apply-wDqQoxX4.mjs} +18 -18
  17. package/dist/{apply-CLjxheyb.mjs.map → apply-wDqQoxX4.mjs.map} +1 -1
  18. package/dist/astro/image-endpoint.d.mts +8 -0
  19. package/dist/astro/image-endpoint.d.mts.map +1 -0
  20. package/dist/astro/image-endpoint.mjs +55 -0
  21. package/dist/astro/image-endpoint.mjs.map +1 -0
  22. package/dist/astro/index.d.mts +36 -11
  23. package/dist/astro/index.d.mts.map +1 -1
  24. package/dist/astro/index.mjs +114 -24
  25. package/dist/astro/index.mjs.map +1 -1
  26. package/dist/astro/middleware/auth.d.mts +9 -9
  27. package/dist/astro/middleware/auth.d.mts.map +1 -1
  28. package/dist/astro/middleware/auth.mjs +12 -10
  29. package/dist/astro/middleware/auth.mjs.map +1 -1
  30. package/dist/astro/middleware/redirect.mjs +6 -6
  31. package/dist/astro/middleware/request-context.mjs +5 -5
  32. package/dist/astro/middleware/setup.mjs +1 -1
  33. package/dist/astro/middleware.d.mts +1 -1
  34. package/dist/astro/middleware.d.mts.map +1 -1
  35. package/dist/astro/middleware.mjs +153 -79
  36. package/dist/astro/middleware.mjs.map +1 -1
  37. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  38. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  39. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  40. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  42. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
  43. package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
  44. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
  45. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -16
  46. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  47. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -16
  48. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  49. package/dist/astro/routes/api/admin/bylines/index.mjs +17 -16
  50. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  51. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +15 -13
  52. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -6
  54. package/dist/astro/routes/api/admin/comments/_id_.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -10
  56. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -6
  58. package/dist/astro/routes/api/admin/comments/counts.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/comments/index.mjs +12 -10
  60. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  62. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  63. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  64. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  65. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +40 -39
  66. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +40 -39
  68. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +39 -38
  70. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +39 -38
  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 +39 -38
  74. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/index.mjs +39 -38
  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 +4 -4
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +39 -38
  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 +39 -38
  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 +39 -38
  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 +39 -38
  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 +40 -39
  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 +39 -38
  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 +40 -39
  91. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/updates.mjs +39 -38
  93. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +39 -38
  95. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  97. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +39 -38
  98. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  99. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  100. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  101. package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
  102. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
  103. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  104. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  105. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  106. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  107. package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
  108. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  109. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  110. package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -11
  111. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  112. package/dist/astro/routes/api/auth/me.mjs +8 -8
  113. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  114. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  115. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  116. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  117. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  118. package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
  119. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  120. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  121. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  122. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  123. package/dist/astro/routes/api/auth/signup/request.mjs +11 -11
  124. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  125. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +16 -15
  126. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  127. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts +9 -0
  128. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts.map +1 -0
  129. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +179 -0
  130. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -0
  131. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  132. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
  133. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  134. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  135. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -13
  136. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
  137. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  138. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  139. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  140. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -15
  141. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  142. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  143. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
  144. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  145. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  146. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  147. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  148. package/dist/astro/routes/api/dashboard.mjs +10 -8
  149. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  150. package/dist/astro/routes/api/dev/emails.mjs +4 -4
  151. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  152. package/dist/astro/routes/api/import/probe.mjs +12 -12
  153. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  154. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  155. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -15
  156. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  157. package/dist/astro/routes/api/import/wordpress/media.mjs +10 -10
  158. package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
  159. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +10 -10
  160. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  161. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +12 -12
  162. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  163. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  164. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +18 -17
  165. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  166. package/dist/astro/routes/api/manifest.mjs +5 -5
  167. package/dist/astro/routes/api/mcp.mjs +213 -46
  168. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  169. package/dist/astro/routes/api/media/_id_/confirm.mjs +8 -8
  170. package/dist/astro/routes/api/media/_id_.mjs +8 -8
  171. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  172. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  173. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  174. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  175. package/dist/astro/routes/api/media/upload-url.mjs +10 -10
  176. package/dist/astro/routes/api/media.mjs +13 -13
  177. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -9
  178. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  179. package/dist/astro/routes/api/menus/_name_/items.mjs +11 -9
  180. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  181. package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -9
  182. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  183. package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -9
  184. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  185. package/dist/astro/routes/api/menus/_name_.mjs +11 -9
  186. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  187. package/dist/astro/routes/api/menus/index.mjs +11 -9
  188. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  189. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  190. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
  191. package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
  192. package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
  193. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  194. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
  195. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
  196. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  197. package/dist/astro/routes/api/openapi.json.mjs +5 -5
  198. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
  199. package/dist/astro/routes/api/redirects/404s/index.mjs +11 -11
  200. package/dist/astro/routes/api/redirects/404s/summary.mjs +11 -11
  201. package/dist/astro/routes/api/redirects/_id_.mjs +12 -12
  202. package/dist/astro/routes/api/redirects/index.mjs +12 -12
  203. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  204. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
  205. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +39 -38
  206. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  207. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +39 -38
  208. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  209. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +39 -38
  210. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  211. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +39 -38
  212. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  213. package/dist/astro/routes/api/schema/collections/index.mjs +39 -38
  214. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  215. package/dist/astro/routes/api/schema/index.mjs +7 -7
  216. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +39 -38
  217. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  218. package/dist/astro/routes/api/schema/orphans/index.mjs +39 -38
  219. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  220. package/dist/astro/routes/api/search/enable.mjs +11 -11
  221. package/dist/astro/routes/api/search/index.mjs +10 -10
  222. package/dist/astro/routes/api/search/rebuild.mjs +11 -11
  223. package/dist/astro/routes/api/search/stats.mjs +7 -7
  224. package/dist/astro/routes/api/search/suggest.mjs +10 -10
  225. package/dist/astro/routes/api/sections/_slug_.mjs +10 -10
  226. package/dist/astro/routes/api/sections/index.mjs +10 -10
  227. package/dist/astro/routes/api/settings/email.mjs +6 -6
  228. package/dist/astro/routes/api/settings.mjs +16 -15
  229. package/dist/astro/routes/api/settings.mjs.map +1 -1
  230. package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
  231. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  232. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  233. package/dist/astro/routes/api/setup/dev-bypass.mjs +29 -27
  234. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  235. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  236. package/dist/astro/routes/api/setup/index.mjs +29 -28
  237. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  238. package/dist/astro/routes/api/setup/status.mjs +5 -5
  239. package/dist/astro/routes/api/snapshot.d.mts.map +1 -1
  240. package/dist/astro/routes/api/snapshot.mjs +10 -9
  241. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  242. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -14
  243. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  244. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -14
  245. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  246. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -14
  247. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  248. package/dist/astro/routes/api/taxonomies/index.mjs +16 -14
  249. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  250. package/dist/astro/routes/api/themes/preview.mjs +8 -8
  251. package/dist/astro/routes/api/typegen.mjs +6 -6
  252. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  253. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  254. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  255. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
  256. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -11
  257. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -11
  258. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
  259. package/dist/astro/routes/api/widget-areas/index.mjs +11 -11
  260. package/dist/astro/routes/api/widget-components.mjs +4 -4
  261. package/dist/astro/routes/robots.txt.mjs +10 -9
  262. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  263. package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -12
  264. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  265. package/dist/astro/routes/sitemap.xml.mjs +11 -10
  266. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  267. package/dist/astro/types.d.mts +16 -12
  268. package/dist/astro/types.d.mts.map +1 -1
  269. package/dist/auth/providers/github.d.mts +1 -1
  270. package/dist/auth/providers/google.d.mts +1 -1
  271. package/dist/{authorize-D5gfBVU5.mjs → authorize-C0EYoUeV.mjs} +2 -2
  272. package/dist/{authorize-D5gfBVU5.mjs.map → authorize-C0EYoUeV.mjs.map} +1 -1
  273. package/dist/{base64-CqR-7kqF.mjs → base64-CmWvODNW.mjs} +1 -1
  274. package/dist/{base64-CqR-7kqF.mjs.map → base64-CmWvODNW.mjs.map} +1 -1
  275. package/dist/{byline-V_Qp1Ziw.mjs → byline-CC0WS4Gu.mjs} +17 -8
  276. package/dist/byline-CC0WS4Gu.mjs.map +1 -0
  277. package/dist/{byline-fields-B0NO1yUB.mjs → byline-fields-53i9Et0x.mjs} +3 -3
  278. package/dist/{byline-fields-B0NO1yUB.mjs.map → byline-fields-53i9Et0x.mjs.map} +1 -1
  279. package/dist/{byline-fields-nBVqK_Ff.mjs → byline-fields-DNp0HNKc.mjs} +2 -2
  280. package/dist/{byline-fields-nBVqK_Ff.mjs.map → byline-fields-DNp0HNKc.mjs.map} +1 -1
  281. package/dist/{byline-fields-CQJRIQkn.d.mts → byline-fields-jy07PZJM.d.mts} +36 -31
  282. package/dist/byline-fields-jy07PZJM.d.mts.map +1 -0
  283. package/dist/{byline-registry-DedidtqC.mjs → byline-registry-BOjqDOim.mjs} +3 -3
  284. package/dist/{byline-registry-DedidtqC.mjs.map → byline-registry-BOjqDOim.mjs.map} +1 -1
  285. package/dist/{bylines-DfGDnred.mjs → bylines-CCO1CYnH.mjs} +8 -8
  286. package/dist/{bylines-DfGDnred.mjs.map → bylines-CCO1CYnH.mjs.map} +1 -1
  287. package/dist/{bylines-B2NWnIwS.mjs → bylines-DGekMGGm.mjs} +10 -4
  288. package/dist/{bylines-B2NWnIwS.mjs.map → bylines-DGekMGGm.mjs.map} +1 -1
  289. package/dist/{cache-DTTHWD8n.mjs → cache-pXTpun6s.mjs} +3 -3
  290. package/dist/{cache-DTTHWD8n.mjs.map → cache-pXTpun6s.mjs.map} +1 -1
  291. package/dist/{challenge-store-woE0bbCf.mjs → challenge-store-C6E_kWTs.mjs} +1 -1
  292. package/dist/{challenge-store-woE0bbCf.mjs.map → challenge-store-C6E_kWTs.mjs.map} +1 -1
  293. package/dist/{chunks-BerYVuve.mjs → chunks-SyjZaYwV.mjs} +2 -2
  294. package/dist/{chunks-BerYVuve.mjs.map → chunks-SyjZaYwV.mjs.map} +1 -1
  295. package/dist/cli/index.mjs +27 -26
  296. package/dist/cli/index.mjs.map +1 -1
  297. package/dist/client/cf-access.d.mts +1 -1
  298. package/dist/client/index.d.mts +1 -1
  299. package/dist/client/index.mjs +2 -1
  300. package/dist/client/index.mjs.map +1 -1
  301. package/dist/{comment-sqQxNpN3.mjs → comment-80UyJJUR.mjs} +11 -3
  302. package/dist/comment-80UyJJUR.mjs.map +1 -0
  303. package/dist/comment-reaction-B6AdcpXw.mjs +85 -0
  304. package/dist/comment-reaction-B6AdcpXw.mjs.map +1 -0
  305. package/dist/{comments-D2hNuxNa.mjs → comments-CtPkT2tp.mjs} +3 -3
  306. package/dist/{comments-D2hNuxNa.mjs.map → comments-CtPkT2tp.mjs.map} +1 -1
  307. package/dist/{components-DYKp2gmo.mjs → components-D6ZnrzbB.mjs} +1 -1
  308. package/dist/{components-DYKp2gmo.mjs.map → components-D6ZnrzbB.mjs.map} +1 -1
  309. package/dist/{content-BIlVx-RX.mjs → content-2PTDNnoh.mjs} +22 -7
  310. package/dist/content-2PTDNnoh.mjs.map +1 -0
  311. package/dist/{context-Cm4pt1Ws.mjs → context-f1__jpzF.mjs} +11 -11
  312. package/dist/{context-Cm4pt1Ws.mjs.map → context-f1__jpzF.mjs.map} +1 -1
  313. package/dist/{cron-DdEVrQ2Y.mjs → cron-CQPxBjYs.mjs} +1 -1
  314. package/dist/{cron-DdEVrQ2Y.mjs.map → cron-CQPxBjYs.mjs.map} +1 -1
  315. package/dist/{dashboard-C-UYpps0.mjs → dashboard-BOESNcwE.mjs} +4 -4
  316. package/dist/{dashboard-C-UYpps0.mjs.map → dashboard-BOESNcwE.mjs.map} +1 -1
  317. package/dist/database/instrumentation.d.mts +19 -0
  318. package/dist/database/instrumentation.d.mts.map +1 -1
  319. package/dist/database/instrumentation.mjs +8 -1
  320. package/dist/database/instrumentation.mjs.map +1 -1
  321. package/dist/db/index.d.mts +3 -3
  322. package/dist/db/index.mjs +1 -1
  323. package/dist/db/libsql.d.mts +1 -1
  324. package/dist/db/postgres.d.mts +1 -1
  325. package/dist/db/sqlite.d.mts +1 -1
  326. package/dist/{db-errors-BluWkwGI.mjs → db-errors-CrC5w3Jz.mjs} +1 -1
  327. package/dist/{db-errors-BluWkwGI.mjs.map → db-errors-CrC5w3Jz.mjs.map} +1 -1
  328. package/dist/{default-NHGuJzQ3.mjs → default-CpBEPn6a.mjs} +1 -1
  329. package/dist/{default-NHGuJzQ3.mjs.map → default-CpBEPn6a.mjs.map} +1 -1
  330. package/dist/{device-flow-BQApWgnW.mjs → device-flow-Bn-qiDrw.mjs} +5 -5
  331. package/dist/{device-flow-BQApWgnW.mjs.map → device-flow-Bn-qiDrw.mjs.map} +1 -1
  332. package/dist/{email-console-BbU3RbWv.mjs → email-console-B9VS6eN4.mjs} +1 -1
  333. package/dist/{email-console-BbU3RbWv.mjs.map → email-console-B9VS6eN4.mjs.map} +1 -1
  334. package/dist/{error-CNn_w7jf.mjs → error-BQ1pxs0L.mjs} +2 -2
  335. package/dist/{error-CNn_w7jf.mjs.map → error-BQ1pxs0L.mjs.map} +1 -1
  336. package/dist/{escape-DPgcxcpL.mjs → escape-BtbJWyaW.mjs} +1 -1
  337. package/dist/{escape-DPgcxcpL.mjs.map → escape-BtbJWyaW.mjs.map} +1 -1
  338. package/dist/{fts-manager-Cx5z8jdA.mjs → fts-manager-DtiWqwNJ.mjs} +2 -2
  339. package/dist/{fts-manager-Cx5z8jdA.mjs.map → fts-manager-DtiWqwNJ.mjs.map} +1 -1
  340. package/dist/{hash-DlvIFn0b.mjs → hash-BowcuPwv.mjs} +1 -1
  341. package/dist/{hash-DlvIFn0b.mjs.map → hash-BowcuPwv.mjs.map} +1 -1
  342. package/dist/{import-KyxT1Mbs.mjs → import-DqSGOlmR.mjs} +4 -4
  343. package/dist/{import-KyxT1Mbs.mjs.map → import-DqSGOlmR.mjs.map} +1 -1
  344. package/dist/{index-D2VAiumu.d.mts → index-C2dLNT6S.d.mts} +172 -17
  345. package/dist/index-C2dLNT6S.d.mts.map +1 -0
  346. package/dist/{index-uT2yR66F.d.mts → index-ZDEwR7qW.d.mts} +3 -3
  347. package/dist/{index-uT2yR66F.d.mts.map → index-ZDEwR7qW.d.mts.map} +1 -1
  348. package/dist/index.d.mts +18 -17
  349. package/dist/index.mjs +63 -61
  350. package/dist/{init-lock-DlBHjf9-.mjs → init-lock-6b309ZrF.mjs} +2 -29
  351. package/dist/init-lock-6b309ZrF.mjs.map +1 -0
  352. package/dist/{load-Dq91b_DK.mjs → load-Dtoo7KcJ.mjs} +2 -2
  353. package/dist/{load-Dq91b_DK.mjs.map → load-Dtoo7KcJ.mjs.map} +1 -1
  354. package/dist/{loader-BqWjcH3h.mjs → loader-C8Z48Uof.mjs} +4 -4
  355. package/dist/{loader-BqWjcH3h.mjs.map → loader-C8Z48Uof.mjs.map} +1 -1
  356. package/dist/{manifest-schema-DFPeqMAn.mjs → manifest-schema-DDSbwkAL.mjs} +1 -1
  357. package/dist/{manifest-schema-DFPeqMAn.mjs.map → manifest-schema-DDSbwkAL.mjs.map} +1 -1
  358. package/dist/media/image-endpoint.d.mts +74 -0
  359. package/dist/media/image-endpoint.d.mts.map +1 -0
  360. package/dist/media/image-endpoint.mjs +162 -0
  361. package/dist/media/image-endpoint.mjs.map +1 -0
  362. package/dist/media/index.d.mts +1 -1
  363. package/dist/media/index.mjs +2 -2
  364. package/dist/media/local-runtime.d.mts +11 -11
  365. package/dist/media/local-runtime.mjs +9 -8
  366. package/dist/media/local-runtime.mjs.map +1 -1
  367. package/dist/{media-JOf3pNkw.mjs → media-Bw0sA6rb.mjs} +2 -2
  368. package/dist/{media-JOf3pNkw.mjs.map → media-Bw0sA6rb.mjs.map} +1 -1
  369. package/dist/{media-allowlist-_A0SuDn4.mjs → media-allowlist-DunzrKFM.mjs} +2 -2
  370. package/dist/{media-allowlist-_A0SuDn4.mjs.map → media-allowlist-DunzrKFM.mjs.map} +1 -1
  371. package/dist/{media-url-CqLd69IO.mjs → media-url-S22B6aPr.mjs} +1 -1
  372. package/dist/{media-url-CqLd69IO.mjs.map → media-url-S22B6aPr.mjs.map} +1 -1
  373. package/dist/{menus-DX4_E01q.mjs → menus-CYs0WZoL.mjs} +20 -6
  374. package/dist/menus-CYs0WZoL.mjs.map +1 -0
  375. package/dist/{menus-Ryk9L7fT.mjs → menus-DOs1MQJg.mjs} +120 -20
  376. package/dist/menus-DOs1MQJg.mjs.map +1 -0
  377. package/dist/{mime-YbtlEtvS.mjs → mime-DYpsOAny.mjs} +1 -1
  378. package/dist/{mime-YbtlEtvS.mjs.map → mime-DYpsOAny.mjs.map} +1 -1
  379. package/dist/{mode-CGXzIbD8.mjs → mode-CFh8Dw8G.mjs} +1 -1
  380. package/dist/{mode-CGXzIbD8.mjs.map → mode-CFh8Dw8G.mjs.map} +1 -1
  381. package/dist/{normalize-DKsg36ty.mjs → normalize-Uam4_Vkr.mjs} +1 -1
  382. package/dist/{normalize-DKsg36ty.mjs.map → normalize-Uam4_Vkr.mjs.map} +1 -1
  383. package/dist/{oauth-authorization-C2kVyjXI.mjs → oauth-authorization-BN-t83Uy.mjs} +5 -5
  384. package/dist/{oauth-authorization-C2kVyjXI.mjs.map → oauth-authorization-BN-t83Uy.mjs.map} +1 -1
  385. package/dist/{oauth-clients-BC873NCV.mjs → oauth-clients-R6I_V0qz.mjs} +1 -1
  386. package/dist/{oauth-clients-BC873NCV.mjs.map → oauth-clients-R6I_V0qz.mjs.map} +1 -1
  387. package/dist/{oauth-state-store-Cd--TUaq.mjs → oauth-state-store-Csoc6kkR.mjs} +1 -1
  388. package/dist/{oauth-state-store-Cd--TUaq.mjs.map → oauth-state-store-Csoc6kkR.mjs.map} +1 -1
  389. package/dist/{oauth-user-lookup-e4wOvDud.mjs → oauth-user-lookup-d7VYjTpx.mjs} +1 -1
  390. package/dist/{oauth-user-lookup-e4wOvDud.mjs.map → oauth-user-lookup-d7VYjTpx.mjs.map} +1 -1
  391. package/dist/object-cache/memory.d.mts +15 -0
  392. package/dist/object-cache/memory.d.mts.map +1 -0
  393. package/dist/object-cache/memory.mjs +56 -0
  394. package/dist/object-cache/memory.mjs.map +1 -0
  395. package/dist/object-cache-SEb2IM4Z.mjs +373 -0
  396. package/dist/object-cache-SEb2IM4Z.mjs.map +1 -0
  397. package/dist/{options-9kLgkE8m.d.mts → options-DFFpvNJU.d.mts} +3 -3
  398. package/dist/{options-9kLgkE8m.d.mts.map → options-DFFpvNJU.d.mts.map} +1 -1
  399. package/dist/{options-BPCVnesz.mjs → options-DTTML-Tx.mjs} +1 -1
  400. package/dist/{options-BPCVnesz.mjs.map → options-DTTML-Tx.mjs.map} +1 -1
  401. package/dist/page/index.d.mts +2 -2
  402. package/dist/{parse-DzSrk1t8.mjs → parse-qrHlnzTy.mjs} +2 -2
  403. package/dist/{parse-DzSrk1t8.mjs.map → parse-qrHlnzTy.mjs.map} +1 -1
  404. package/dist/{passkey-config-BpjbE_Uv.mjs → passkey-config-BJTbcnI5.mjs} +1 -1
  405. package/dist/{passkey-config-BpjbE_Uv.mjs.map → passkey-config-BJTbcnI5.mjs.map} +1 -1
  406. package/dist/{patterns-p-RBdTbM.mjs → patterns-BKmjvM7K.mjs} +1 -1
  407. package/dist/{patterns-p-RBdTbM.mjs.map → patterns-BKmjvM7K.mjs.map} +1 -1
  408. package/dist/{placeholder-2xumZh4g.mjs → placeholder-CIDCpyEY.mjs} +1 -1
  409. package/dist/{placeholder-2xumZh4g.mjs.map → placeholder-CIDCpyEY.mjs.map} +1 -1
  410. package/dist/{placeholder-BevVKfay.d.mts → placeholder-CirPauNG.d.mts} +1 -1
  411. package/dist/{placeholder-BevVKfay.d.mts.map → placeholder-CirPauNG.d.mts.map} +1 -1
  412. package/dist/plugin-types.d.mts +1 -1
  413. package/dist/plugin-utils.d.mts +9 -9
  414. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  415. package/dist/plugins/adapt-sandbox-entry.mjs +4 -2
  416. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  417. package/dist/{transport-1cIrOb1Y.mjs → portable-text-BIFhrU6T.mjs} +2 -135
  418. package/dist/portable-text-BIFhrU6T.mjs.map +1 -0
  419. package/dist/{preview-Dqv2hwXr.mjs → preview-IDye9SPQ.mjs} +2 -2
  420. package/dist/{preview-Dqv2hwXr.mjs.map → preview-IDye9SPQ.mjs.map} +1 -1
  421. package/dist/{public-url-D_zARuvZ.mjs → public-url-8lFyQ8ZF.mjs} +1 -1
  422. package/dist/{public-url-D_zARuvZ.mjs.map → public-url-8lFyQ8ZF.mjs.map} +1 -1
  423. package/dist/{query-Crm038Mc.mjs → query-B1RVFUNM.mjs} +159 -31
  424. package/dist/query-B1RVFUNM.mjs.map +1 -0
  425. package/dist/{rate-limit-hRTBqmw1.mjs → rate-limit-DfNAqIWW.mjs} +2 -2
  426. package/dist/{rate-limit-hRTBqmw1.mjs.map → rate-limit-DfNAqIWW.mjs.map} +1 -1
  427. package/dist/{redirect-C-OOkyku.mjs → redirect-B4wuX2A5.mjs} +1 -1
  428. package/dist/{redirect-C-OOkyku.mjs.map → redirect-B4wuX2A5.mjs.map} +1 -1
  429. package/dist/{redirect-CRWIt8Zj.mjs → redirect-Bifv_yHv.mjs} +3 -3
  430. package/dist/{redirect-CRWIt8Zj.mjs.map → redirect-Bifv_yHv.mjs.map} +1 -1
  431. package/dist/{redirects-CP3TnTLO.mjs → redirects-CT_vb3NV.mjs} +6 -6
  432. package/dist/{redirects-CP3TnTLO.mjs.map → redirects-CT_vb3NV.mjs.map} +1 -1
  433. package/dist/{redirects-6Zg2SoYo.mjs → redirects-DUvXgzCX.mjs} +8 -3
  434. package/dist/redirects-DUvXgzCX.mjs.map +1 -0
  435. package/dist/{registry-diMzD1Wf.mjs → registry-CjK96fHD.mjs} +6 -6
  436. package/dist/{registry-diMzD1Wf.mjs.map → registry-CjK96fHD.mjs.map} +1 -1
  437. package/dist/{request-cache-UwmBAiUK.mjs → request-cache-KCNHp_RJ.mjs} +1 -1
  438. package/dist/{request-cache-UwmBAiUK.mjs.map → request-cache-KCNHp_RJ.mjs.map} +1 -1
  439. package/dist/{request-meta-DPechd0W.mjs → request-meta-ei3ATilC.mjs} +2 -2
  440. package/dist/{request-meta-DPechd0W.mjs.map → request-meta-ei3ATilC.mjs.map} +1 -1
  441. package/dist/{resolve-B3NUUtVY.mjs → resolve-CpbBglV0.mjs} +1 -1
  442. package/dist/{resolve-B3NUUtVY.mjs.map → resolve-CpbBglV0.mjs.map} +1 -1
  443. package/dist/{runner--4wMWwKM.mjs → runner-DYYnW530.mjs} +201 -170
  444. package/dist/runner-DYYnW530.mjs.map +1 -0
  445. package/dist/{runner-C8vcbvCe.d.mts → runner-jdXtFEd3.d.mts} +2 -2
  446. package/dist/{runner-C8vcbvCe.d.mts.map → runner-jdXtFEd3.d.mts.map} +1 -1
  447. package/dist/runtime.d.mts +10 -10
  448. package/dist/runtime.mjs +3 -3
  449. package/dist/{schema-BDOkd3OU.mjs → schema-5z2Jfnbm.mjs} +13 -8
  450. package/dist/schema-5z2Jfnbm.mjs.map +1 -0
  451. package/dist/{search-Bs_J_EW-.mjs → search-D9FkoM-k.mjs} +4 -4
  452. package/dist/{search-Bs_J_EW-.mjs.map → search-D9FkoM-k.mjs.map} +1 -1
  453. package/dist/{secrets-C8xmE6mR.mjs → secrets-BUE5UQys.mjs} +5 -5
  454. package/dist/{secrets-C8xmE6mR.mjs.map → secrets-BUE5UQys.mjs.map} +1 -1
  455. package/dist/{sections-P0zuBlyz.mjs → sections-DWYZo6HK.mjs} +3 -3
  456. package/dist/{sections-P0zuBlyz.mjs.map → sections-DWYZo6HK.mjs.map} +1 -1
  457. package/dist/seed/index.d.mts +2 -2
  458. package/dist/seed/index.mjs +22 -21
  459. package/dist/seo/index.d.mts +1 -1
  460. package/dist/seo/index.mjs +1 -1
  461. package/dist/{seo-DpNgGQjF.mjs → seo-Cu47j3mJ.mjs} +5 -2
  462. package/dist/seo-Cu47j3mJ.mjs.map +1 -0
  463. package/dist/{seo-CLhm-Fmb.mjs → seo-DRnqnstF.mjs} +1 -1
  464. package/dist/{seo-CLhm-Fmb.mjs.map → seo-DRnqnstF.mjs.map} +1 -1
  465. package/dist/{service-CDQQnT8W.mjs → service-DTmtqCnw.mjs} +3 -3
  466. package/dist/{service-CDQQnT8W.mjs.map → service-DTmtqCnw.mjs.map} +1 -1
  467. package/dist/session-user-DmtPMNa1.mjs +51 -0
  468. package/dist/session-user-DmtPMNa1.mjs.map +1 -0
  469. package/dist/{settings-sO0Fif4p.mjs → settings-DUrVDN0c.mjs} +3 -3
  470. package/dist/{settings-sO0Fif4p.mjs.map → settings-DUrVDN0c.mjs.map} +1 -1
  471. package/dist/{settings-BjBsmVAo.mjs → settings-yaxu9mU-.mjs} +18 -10
  472. package/dist/settings-yaxu9mU-.mjs.map +1 -0
  473. package/dist/{setup-complete-CMMr-oZU.mjs → setup-complete-BWFHzgvZ.mjs} +2 -2
  474. package/dist/{setup-complete-CMMr-oZU.mjs.map → setup-complete-BWFHzgvZ.mjs.map} +1 -1
  475. package/dist/{setup-nonce-169xl4fV.mjs → setup-nonce-DFWG-J5c.mjs} +1 -1
  476. package/dist/{setup-nonce-169xl4fV.mjs.map → setup-nonce-DFWG-J5c.mjs.map} +1 -1
  477. package/dist/{single-flight-cache-C0UV1Npg.mjs → single-flight-cache-B5p5cNOL.mjs} +2 -2
  478. package/dist/{single-flight-cache-C0UV1Npg.mjs.map → single-flight-cache-B5p5cNOL.mjs.map} +1 -1
  479. package/dist/{site-url-vtsuOvSD.mjs → site-url-BOTPgmeM.mjs} +2 -2
  480. package/dist/{site-url-vtsuOvSD.mjs.map → site-url-BOTPgmeM.mjs.map} +1 -1
  481. package/dist/{slugify-Cjh1ssOZ.mjs → slugify-Cce3dTdg.mjs} +1 -1
  482. package/dist/{slugify-Cjh1ssOZ.mjs.map → slugify-Cce3dTdg.mjs.map} +1 -1
  483. package/dist/{ssrf-XO05Voq6.mjs → ssrf-B0VeRLrp.mjs} +1 -1
  484. package/dist/{ssrf-XO05Voq6.mjs.map → ssrf-B0VeRLrp.mjs.map} +1 -1
  485. package/dist/{status-2gZklYuj.mjs → status-CB2basWJ.mjs} +1 -1
  486. package/dist/{status-2gZklYuj.mjs.map → status-CB2basWJ.mjs.map} +1 -1
  487. package/dist/storage/local.d.mts +1 -1
  488. package/dist/storage/local.mjs +1 -1
  489. package/dist/storage/s3.d.mts +1 -1
  490. package/dist/storage/s3.mjs +1 -1
  491. package/dist/{taxonomies-BBxYA38v.mjs → taxonomies-Be9B1jEj.mjs} +156 -122
  492. package/dist/taxonomies-Be9B1jEj.mjs.map +1 -0
  493. package/dist/{taxonomies-DuESHWKI.mjs → taxonomies-CJmkEpdS.mjs} +7 -7
  494. package/dist/{taxonomies-DuESHWKI.mjs.map → taxonomies-CJmkEpdS.mjs.map} +1 -1
  495. package/dist/{taxonomy-CdllE4oq.mjs → taxonomy-B2HQuVf5.mjs} +19 -6
  496. package/dist/taxonomy-B2HQuVf5.mjs.map +1 -0
  497. package/dist/{tokens-DMkVjxrx.mjs → tokens-BvrJvIB6.mjs} +2 -2
  498. package/dist/{tokens-DMkVjxrx.mjs.map → tokens-BvrJvIB6.mjs.map} +1 -1
  499. package/dist/{transaction-x2tJQ-A1.mjs → transaction-qfqpPVpu.mjs} +1 -1
  500. package/dist/{transaction-x2tJQ-A1.mjs.map → transaction-qfqpPVpu.mjs.map} +1 -1
  501. package/dist/transport-B4rXnSTf.mjs +135 -0
  502. package/dist/transport-B4rXnSTf.mjs.map +1 -0
  503. package/dist/{transport-jdvsZEIt.d.mts → transport-k7YjfmEn.d.mts} +1 -1
  504. package/dist/{transport-jdvsZEIt.d.mts.map → transport-k7YjfmEn.d.mts.map} +1 -1
  505. package/dist/{trusted-proxy-CHp41Fjj.mjs → trusted-proxy-DY1_UqHr.mjs} +1 -1
  506. package/dist/{trusted-proxy-CHp41Fjj.mjs.map → trusted-proxy-DY1_UqHr.mjs.map} +1 -1
  507. package/dist/{types-DO7whVYU.d.mts → types-CIKX2HO5.d.mts} +2 -2
  508. package/dist/{types-DO7whVYU.d.mts.map → types-CIKX2HO5.d.mts.map} +1 -1
  509. package/dist/{types-u_XxjbS8.d.mts → types-CKNXt63n.d.mts} +1 -1
  510. package/dist/{types-u_XxjbS8.d.mts.map → types-CKNXt63n.d.mts.map} +1 -1
  511. package/dist/{types-BTnnBYVX.d.mts → types-CWGYDYqF.d.mts} +2 -2
  512. package/dist/{types-BTnnBYVX.d.mts.map → types-CWGYDYqF.d.mts.map} +1 -1
  513. package/dist/{types-CkEuk-Zr.d.mts → types-CgvhU-hF.d.mts} +1 -1
  514. package/dist/{types-CkEuk-Zr.d.mts.map → types-CgvhU-hF.d.mts.map} +1 -1
  515. package/dist/{types-BFgYtuKd.d.mts → types-CmivgZbp.d.mts} +1 -1
  516. package/dist/{types-BFgYtuKd.d.mts.map → types-CmivgZbp.d.mts.map} +1 -1
  517. package/dist/{types-Del0VMij.d.mts → types-Czg1S3gB.d.mts} +9 -1
  518. package/dist/{types-Del0VMij.d.mts.map → types-Czg1S3gB.d.mts.map} +1 -1
  519. package/dist/types-DCNNfeCv.d.mts +124 -0
  520. package/dist/types-DCNNfeCv.d.mts.map +1 -0
  521. package/dist/{types-Bzfk2yC8.d.mts → types-DPCpkzvS.d.mts} +1 -1
  522. package/dist/{types-Bzfk2yC8.d.mts.map → types-DPCpkzvS.d.mts.map} +1 -1
  523. package/dist/{types-DdkL6fyv.d.mts → types-DXLVzV2w.d.mts} +1 -1
  524. package/dist/{types-DdkL6fyv.d.mts.map → types-DXLVzV2w.d.mts.map} +1 -1
  525. package/dist/{types-BXSUSAjt.mjs → types-DXOIbece.mjs} +3 -3
  526. package/dist/{types-BXSUSAjt.mjs.map → types-DXOIbece.mjs.map} +1 -1
  527. package/dist/{types-DejCHqWT.mjs → types-DYF2_Vf4.mjs} +1 -1
  528. package/dist/{types-DejCHqWT.mjs.map → types-DYF2_Vf4.mjs.map} +1 -1
  529. package/dist/{types-BIduXPJk.mjs → types-tM44hEcf.mjs} +1 -1
  530. package/dist/{types-BIduXPJk.mjs.map → types-tM44hEcf.mjs.map} +1 -1
  531. package/dist/{user-C0um7wrg.mjs → user-Db-Rti_z.mjs} +3 -3
  532. package/dist/{user-C0um7wrg.mjs.map → user-Db-Rti_z.mjs.map} +1 -1
  533. package/dist/{utils-C4M981Br.mjs → utils-LbHcSRTj.mjs} +2 -2
  534. package/dist/{utils-C4M981Br.mjs.map → utils-LbHcSRTj.mjs.map} +1 -1
  535. package/dist/{validate-DGhQPXzI.mjs → validate-Bwl64sxv.mjs} +3 -3
  536. package/dist/{validate-DGhQPXzI.mjs.map → validate-Bwl64sxv.mjs.map} +1 -1
  537. package/dist/{validate-cJOiOvT2.d.mts → validate-CE2M0nvx.d.mts} +5 -5
  538. package/dist/{validate-cJOiOvT2.d.mts.map → validate-CE2M0nvx.d.mts.map} +1 -1
  539. package/dist/{validation-DVHjPM1M.mjs → validation-C_yOvFaO.mjs} +6 -6
  540. package/dist/{validation-DVHjPM1M.mjs.map → validation-C_yOvFaO.mjs.map} +1 -1
  541. package/dist/version-RnYXYjzD.mjs +7 -0
  542. package/dist/{version-BOjj_cfz.mjs.map → version-RnYXYjzD.mjs.map} +1 -1
  543. package/dist/{widgets-Ci6hLwfO.mjs → widgets-8GONuRHo.mjs} +4 -4
  544. package/dist/{widgets-Ci6hLwfO.mjs.map → widgets-8GONuRHo.mjs.map} +1 -1
  545. package/dist/{zod-generator-CarzgPAu.mjs → zod-generator-D481JjzD.mjs} +3 -3
  546. package/dist/{zod-generator-CarzgPAu.mjs.map → zod-generator-D481JjzD.mjs.map} +1 -1
  547. package/package.json +18 -6
  548. package/src/api/handlers/api-tokens.ts +19 -0
  549. package/src/api/handlers/comment-reactions.ts +165 -0
  550. package/src/api/handlers/schema.ts +8 -0
  551. package/src/api/schemas/comments.ts +10 -0
  552. package/src/astro/image-endpoint.ts +84 -0
  553. package/src/astro/index.ts +6 -0
  554. package/src/astro/integration/index.ts +83 -22
  555. package/src/astro/integration/routes.ts +5 -0
  556. package/src/astro/integration/runtime.ts +65 -1
  557. package/src/astro/integration/virtual-modules.ts +32 -0
  558. package/src/astro/integration/vite-config.ts +16 -0
  559. package/src/astro/middleware/auth.ts +4 -3
  560. package/src/astro/middleware/stream-end-metrics.ts +11 -1
  561. package/src/astro/middleware.ts +41 -3
  562. package/src/astro/object-cache/adapters.ts +50 -0
  563. package/src/astro/prefetch.ts +77 -0
  564. package/src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts +97 -0
  565. package/src/astro/routes/api/setup/dev-bypass.ts +5 -1
  566. package/src/astro/routes/api/snapshot.ts +3 -1
  567. package/src/astro/session-user.ts +57 -0
  568. package/src/astro/types.ts +1 -0
  569. package/src/comments/query.ts +78 -7
  570. package/src/comments/ranking.ts +58 -0
  571. package/src/components/Comments.astro +136 -1
  572. package/src/database/instrumentation.ts +21 -1
  573. package/src/database/migrations/044_comment_reactions.ts +56 -0
  574. package/src/database/migrations/runner.ts +2 -0
  575. package/src/database/repositories/byline.ts +13 -0
  576. package/src/database/repositories/comment-reaction.ts +132 -0
  577. package/src/database/repositories/comment.ts +10 -0
  578. package/src/database/repositories/content.ts +25 -3
  579. package/src/database/repositories/menu.ts +13 -1
  580. package/src/database/repositories/seo.ts +3 -0
  581. package/src/database/repositories/taxonomy.ts +13 -1
  582. package/src/database/types.ts +9 -0
  583. package/src/emdash-runtime.ts +18 -4
  584. package/src/index.ts +22 -0
  585. package/src/mcp/server.ts +307 -20
  586. package/src/media/image-endpoint.ts +167 -0
  587. package/src/menus/index.ts +11 -4
  588. package/src/object-cache/codec.ts +73 -0
  589. package/src/object-cache/index.ts +495 -0
  590. package/src/object-cache/memory.ts +91 -0
  591. package/src/object-cache/types.ts +124 -0
  592. package/src/plugins/adapt-sandbox-entry.ts +11 -1
  593. package/src/query.ts +196 -17
  594. package/src/schema/query.ts +11 -4
  595. package/src/settings/index.ts +18 -5
  596. package/src/taxonomies/index.ts +237 -165
  597. package/src/virtual-modules.d.ts +11 -0
  598. package/dist/api-DxjIV2o8.mjs.map +0 -1
  599. package/dist/api-tokens-BFFkB0jB.mjs.map +0 -1
  600. package/dist/byline-V_Qp1Ziw.mjs.map +0 -1
  601. package/dist/byline-fields-CQJRIQkn.d.mts.map +0 -1
  602. package/dist/comment-sqQxNpN3.mjs.map +0 -1
  603. package/dist/content-BIlVx-RX.mjs.map +0 -1
  604. package/dist/index-D2VAiumu.d.mts.map +0 -1
  605. package/dist/init-lock-DlBHjf9-.mjs.map +0 -1
  606. package/dist/menus-DX4_E01q.mjs.map +0 -1
  607. package/dist/menus-Ryk9L7fT.mjs.map +0 -1
  608. package/dist/query-Crm038Mc.mjs.map +0 -1
  609. package/dist/redirects-6Zg2SoYo.mjs.map +0 -1
  610. package/dist/runner--4wMWwKM.mjs.map +0 -1
  611. package/dist/schema-BDOkd3OU.mjs.map +0 -1
  612. package/dist/seo-DpNgGQjF.mjs.map +0 -1
  613. package/dist/settings-BjBsmVAo.mjs.map +0 -1
  614. package/dist/taxonomies-BBxYA38v.mjs.map +0 -1
  615. package/dist/taxonomy-CdllE4oq.mjs.map +0 -1
  616. package/dist/transport-1cIrOb1Y.mjs.map +0 -1
  617. package/dist/version-BOjj_cfz.mjs +0 -7
  618. /package/dist/{api-tokens-C7ywRx7l.mjs → api-tokens-BVH-H8Z9.mjs} +0 -0
  619. /package/dist/{ssrf-CRZGzjdL.mjs → ssrf-Cz1e2QPn.mjs} +0 -0
  620. /package/dist/{types-BoRm8-pp.mjs → types-Bfr2Pj6z.mjs} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"init-lock-DlBHjf9-.mjs","names":[],"sources":["../src/after.ts","../src/utils/init-lock.ts"],"sourcesContent":["/**\n * Defer work past the HTTP response.\n *\n * Use for bookkeeping that doesn't need to complete before the client\n * gets bytes — writes that record state, maintenance queries, cache\n * refreshes. `after()` hands the promise to the host's lifetime\n * extender when one is available (Cloudflare's `waitUntil` under\n * workerd), or fires-and-forgets on Node (the process lives for the\n * next request anyway).\n *\n * Host binding is resolved lazily via a dynamic import of the\n * `virtual:emdash/wait-until` virtual module. Lazy — rather than a\n * static top-level import — so tools that walk the dist in a plain\n * Node loader (`astro check`, Vitest, etc.) don't trip over the\n * `virtual:` scheme: they'd only fail if they actually called\n * `after()`, which they don't during type-checking.\n */\n\nexport type WaitUntilFn = (promise: Promise<unknown>) => void;\n\n// Resolves to the host's waitUntil if the adapter provided one, or\n// null otherwise. Kicked off once at module load; subsequent `after()`\n// calls see the cached result without re-importing.\nconst waitUntilReady: Promise<WaitUntilFn | null> = (async () => {\n\ttry {\n\t\t// @ts-ignore - virtual module, generated by the Astro integration\n\t\tconst mod = (await import(\"virtual:emdash/wait-until\")) as {\n\t\t\twaitUntil?: WaitUntilFn;\n\t\t};\n\t\treturn mod.waitUntil ?? null;\n\t} catch {\n\t\t// No virtual module available (Node-side tooling, tests without the\n\t\t// integration in scope). Fire-and-forget is the safe fallback.\n\t\treturn null;\n\t}\n})();\n// Surface rejections without making the module-load fail.\nwaitUntilReady.catch(() => {});\n\n/**\n * Schedule `fn` to run without blocking the response.\n *\n * Errors are caught and logged — a deferred task should never surface\n * as an unhandled rejection because the response is long gone. Callers\n * that care about errors should handle them inside `fn`.\n */\nexport function after(fn: () => void | Promise<void>): void {\n\tconst promise = Promise.resolve()\n\t\t.then(fn)\n\t\t.catch((error) => {\n\t\t\tconsole.error(\"[emdash] deferred task failed:\", error);\n\t\t});\n\n\t// Defer the lifetime-extender handoff to the microtask that resolves\n\t// waitUntilReady. On workerd this is effectively instant (the virtual\n\t// module is already loaded in the bundle); on Node the promise\n\t// resolves to null, so this is just one extra microtask and no-op.\n\tvoid waitUntilReady.then((waitUntil) => {\n\t\tif (waitUntil) waitUntil(promise);\n\t\treturn null;\n\t});\n}\n","/**\n * Reclaimable initialization lock for isolate-lifetime singletons.\n *\n * Guards \"first request initializes, everyone else waits\" sections\n * (runtime creation, database init) against a workerd failure mode: if the\n * request that owns the initialization is cancelled mid-await (client\n * disconnect, context teardown), its continuation — including any `finally`\n * that would release the lock — never runs. A plain boolean or shared\n * promise then stays stuck forever and every subsequent request in the\n * isolate hangs until the platform kills it (observed as 524s at the\n * 100-second wall limit, with the isolate poisoned until eviction).\n *\n * This lock instead records *when* the owner started. Waiters poll — we\n * deliberately never await a promise created by another request, which\n * workerd flags — and if the owner has held the lock past `deadlineMs`,\n * the next waiter assumes the owner is dead, reclaims the lock, and runs\n * the initialization itself. Waiters also give up after `maxWaitMs` so a\n * request degrades to an error response rather than hanging.\n */\n\nexport interface InitLock {\n\t/** Epoch ms when the current owner claimed the lock, or null when free. */\n\townerStartedAt: number | null;\n\t/**\n\t * Monotonic claim counter identifying the current owner. Release is\n\t * gated on it: a slow owner that finishes after a waiter has reclaimed\n\t * the lock must not clear the reclaimer's claim — that would let yet\n\t * another caller claim the lock and start a third concurrent init.\n\t */\n\tgeneration: number;\n}\n\nexport function createInitLock(): InitLock {\n\treturn { ownerStartedAt: null, generation: 0 };\n}\n\nexport interface InitLockOptions {\n\t/**\n\t * Reclaim the lock if the owner has held it longer than this. Must be\n\t * comfortably above the slowest legitimate init (cold migrations on a\n\t * contended D1, including the concurrent-migrator wait) — a too-short\n\t * deadline risks two concurrent inits, a too-long one delays recovery\n\t * of a poisoned isolate. Nested locks must compose: an outer lock's\n\t * deadline must exceed the deadline of any lock its init acquires.\n\t */\n\tdeadlineMs?: number;\n\t/** Waiter poll interval. */\n\tpollMs?: number;\n\t/**\n\t * Give up waiting after this long and throw instead of hanging.\n\t * Defaults to `deadlineMs` plus headroom so a waiter always survives\n\t * long enough to reclaim a dead owner before giving up.\n\t */\n\tmaxWaitMs?: number;\n\t/**\n\t * Called with the in-flight init promise (errors pre-swallowed) so the\n\t * caller can hand it to the host's lifetime extender (waitUntil via\n\t * `after()`). If the owning request is cancelled mid-init, the anchored\n\t * promise keeps the context alive: init completes, populates the cache,\n\t * and the `finally` below releases the lock — preventing the poisoning\n\t * instead of merely recovering from it via reclaim.\n\t */\n\tanchor?: (promise: Promise<void>) => void;\n}\n\nconst DEFAULT_DEADLINE_MS = 15_000;\nconst DEFAULT_POLL_MS = 50;\nconst MAX_WAIT_HEADROOM_MS = 15_000;\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Return the cached value if present, otherwise initialize it under the\n * lock. `init` is responsible for storing the value so that `getCached`\n * returns it on subsequent calls — waiters re-check `getCached` after the\n * owner finishes rather than sharing the owner's promise.\n *\n * `init` receives an `isCurrentClaim` predicate and must gate its cache\n * publication on it: a slow init that was reclaimed past the deadline\n * must not overwrite the value published by the reclaimer (for the\n * runtime singleton that would orphan the reclaimer's active cron\n * scheduler). A losing init should also tear down any side resources it\n * started, since its result will never be published.\n */\nexport async function initWithLock<T>(\n\tlock: InitLock,\n\tgetCached: () => T | null | undefined,\n\tinit: (isCurrentClaim: () => boolean) => Promise<T>,\n\toptions?: InitLockOptions,\n): Promise<T> {\n\tconst deadlineMs = options?.deadlineMs ?? DEFAULT_DEADLINE_MS;\n\tconst pollMs = options?.pollMs ?? DEFAULT_POLL_MS;\n\tconst maxWaitMs = options?.maxWaitMs ?? deadlineMs + MAX_WAIT_HEADROOM_MS;\n\t// Date.now() is deliberate and only works because every loop iteration\n\t// awaits: in workerd the clock only advances across I/O, so a sync spin\n\t// would never observe the deadline. Don't \"optimize\" away the sleep.\n\tconst waitStart = Date.now();\n\n\tfor (;;) {\n\t\tconst cached = getCached();\n\t\tif (cached !== null && cached !== undefined) {\n\t\t\treturn cached;\n\t\t}\n\n\t\tconst ownerStartedAt = lock.ownerStartedAt;\n\t\tif (ownerStartedAt === null || Date.now() - ownerStartedAt > deadlineMs) {\n\t\t\t// Free, or the owner has been gone past the deadline — claim it.\n\t\t\t// Synchronous between awaits, so two waiters can't both claim.\n\t\t\tlock.generation += 1;\n\t\t\tconst claim = lock.generation;\n\t\t\tlock.ownerStartedAt = Date.now();\n\t\t\ttry {\n\t\t\t\t// Promise.resolve().then(...) so a synchronous throw from\n\t\t\t\t// init still becomes a rejection after the anchor attaches.\n\t\t\t\tconst isCurrentClaim = () => lock.generation === claim;\n\t\t\t\tconst initPromise = Promise.resolve().then(() => init(isCurrentClaim));\n\t\t\t\toptions?.anchor?.(\n\t\t\t\t\tinitPromise.then(\n\t\t\t\t\t\t() => undefined,\n\t\t\t\t\t\t() => undefined,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn await initPromise;\n\t\t\t} finally {\n\t\t\t\t// If this request dies mid-init unanchored this never runs;\n\t\t\t\t// the next waiter reclaims after deadlineMs instead. Release\n\t\t\t\t// only while still the current owner: a reclaimer may have\n\t\t\t\t// taken the lock while this (slow) init was running, and\n\t\t\t\t// clearing its claim would admit a third concurrent init.\n\t\t\t\tif (lock.generation === claim) {\n\t\t\t\t\tlock.ownerStartedAt = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Date.now() - waitStart > maxWaitMs) {\n\t\t\tthrow new Error(`initWithLock: timed out after ${maxWaitMs}ms waiting for initialization`);\n\t\t}\n\t\tawait sleep(pollMs);\n\t}\n}\n"],"mappings":";AAuBA,MAAM,kBAA+C,YAAY;AAChE,KAAI;AAKH,UAHa,MAAM,OAAO,8BAGf,aAAa;SACjB;AAGP,SAAO;;IAEL;AAEJ,eAAe,YAAY,GAAG;;;;;;;;AAS9B,SAAgB,MAAM,IAAsC;CAC3D,MAAM,UAAU,QAAQ,SAAS,CAC/B,KAAK,GAAG,CACR,OAAO,UAAU;AACjB,UAAQ,MAAM,kCAAkC,MAAM;GACrD;AAMH,CAAK,eAAe,MAAM,cAAc;AACvC,MAAI,UAAW,WAAU,QAAQ;AACjC,SAAO;GACN;;;;;AC5BH,SAAgB,iBAA2B;AAC1C,QAAO;EAAE,gBAAgB;EAAM,YAAY;EAAG;;AAgC/C,MAAM,sBAAsB;AAC5B,MAAM,kBAAkB;AACxB,MAAM,uBAAuB;AAE7B,SAAS,MAAM,IAA2B;AACzC,QAAO,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;;;;;;;;;;;;;;AAgBzD,eAAsB,aACrB,MACA,WACA,MACA,SACa;CACb,MAAM,aAAa,SAAS,cAAc;CAC1C,MAAM,SAAS,SAAS,UAAU;CAClC,MAAM,YAAY,SAAS,aAAa,aAAa;CAIrD,MAAM,YAAY,KAAK,KAAK;AAE5B,UAAS;EACR,MAAM,SAAS,WAAW;AAC1B,MAAI,WAAW,QAAQ,WAAW,OACjC,QAAO;EAGR,MAAM,iBAAiB,KAAK;AAC5B,MAAI,mBAAmB,QAAQ,KAAK,KAAK,GAAG,iBAAiB,YAAY;AAGxE,QAAK,cAAc;GACnB,MAAM,QAAQ,KAAK;AACnB,QAAK,iBAAiB,KAAK,KAAK;AAChC,OAAI;IAGH,MAAM,uBAAuB,KAAK,eAAe;IACjD,MAAM,cAAc,QAAQ,SAAS,CAAC,WAAW,KAAK,eAAe,CAAC;AACtE,aAAS,SACR,YAAY,WACL,cACA,OACN,CACD;AACD,WAAO,MAAM;aACJ;AAMT,QAAI,KAAK,eAAe,MACvB,MAAK,iBAAiB;;;AAKzB,MAAI,KAAK,KAAK,GAAG,YAAY,UAC5B,OAAM,IAAI,MAAM,iCAAiC,UAAU,+BAA+B;AAE3F,QAAM,MAAM,OAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"menus-DX4_E01q.mjs","names":[],"sources":["../src/database/repositories/menu.ts","../src/api/handlers/menus.ts"],"sourcesContent":["/**\n * Menu repository\n *\n * Owns every SQL touch for `_emdash_menus` and `_emdash_menu_items`, plus the\n * row→entity mapping. Matches the architecture used by every other resource\n * (content, taxonomies, redirects, comments, media): handlers stay thin and\n * orchestrate; the repository is the single place where snake_case DB columns\n * become camelCase entities (and vice versa).\n *\n * i18n: menus are per-locale. `(name, locale)` is unique. Translations of the\n * same menu share a `translation_group` ULID. Menu item `reference_id` stores\n * the referenced content's translation_group (not a specific row id) so a\n * single menu item survives content translations.\n */\n\nimport type { Kysely, Selectable } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { withTransaction } from \"../transaction.js\";\nimport type { Database, MenuItemTable, MenuTable } from \"../types.js\";\n\n/**\n * Thrown from inside a repository transaction when the menu the caller\n * resolved earlier has since been deleted. Handlers translate this to a\n * `NOT_FOUND` API response. Necessary because D1 disables FK enforcement\n * (so `ON DELETE CASCADE` won't fire), and an unchecked `setItems` would\n * happily insert items whose `menu_id` no longer exists, leaving orphans.\n */\nexport class MenuGoneError extends Error {\n\tconstructor(public readonly menuId: string) {\n\t\tsuper(`Menu ${menuId} was deleted while being modified`);\n\t\tthis.name = \"MenuGoneError\";\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Entity shapes (camelCase — what the API returns)\n// ---------------------------------------------------------------------------\n\nexport interface Menu {\n\tid: string;\n\tname: string;\n\tlabel: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlocale: string;\n\ttranslationGroup: string | null;\n}\n\nexport interface MenuItem {\n\tid: string;\n\tmenuId: string;\n\tparentId: string | null;\n\tsortOrder: number;\n\ttype: string;\n\treferenceCollection: string | null;\n\treferenceId: string | null;\n\tcustomUrl: string | null;\n\tlabel: string;\n\ttitleAttr: string | null;\n\ttarget: string | null;\n\tcssClasses: string | null;\n\tcreatedAt: string;\n\tlocale: string;\n\ttranslationGroup: string | null;\n}\n\nexport interface MenuListItem extends Menu {\n\titemCount: number;\n}\n\nexport interface MenuWithItems extends Menu {\n\titems: MenuItem[];\n}\n\nexport interface MenuTranslation {\n\tid: string;\n\tname: string;\n\tlabel: string;\n\tlocale: string;\n\tupdatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Input shapes\n// ---------------------------------------------------------------------------\n\nexport interface CreateMenuInput {\n\tname: string;\n\tlabel: string;\n\tlocale?: string;\n\t/**\n\t * When set, the new menu joins the source menu's translation_group and\n\t * inherits its items (cloned, with new ULIDs but the same translation_group\n\t * per item so nav entries stay logically identified across translations).\n\t */\n\ttranslationOf?: string;\n}\n\nexport interface UpdateMenuInput {\n\tlabel?: string;\n}\n\nexport interface CreateMenuItemInput {\n\ttype: string;\n\tlabel: string;\n\treferenceCollection?: string;\n\treferenceId?: string;\n\tcustomUrl?: string;\n\ttarget?: string;\n\ttitleAttr?: string;\n\tcssClasses?: string;\n\tparentId?: string;\n\tsortOrder?: number;\n}\n\nexport interface UpdateMenuItemInput {\n\tlabel?: string;\n\tcustomUrl?: string;\n\ttarget?: string;\n\ttitleAttr?: string;\n\tcssClasses?: string;\n\tparentId?: string | null;\n\tsortOrder?: number;\n}\n\n/**\n * Item shape used by `setItems()`. Items are placed by array order. Children\n * point at parents via `parentIndex` (must reference an earlier index, so the\n * insert can resolve parents before children). The validation of that ordering\n * lives at the API boundary (`handleMenuSetItems`) so REST/MCP callers receive\n * the same error shape.\n */\nexport interface SetMenuItem {\n\tlabel: string;\n\ttype: \"custom\" | \"page\" | \"post\" | \"taxonomy\" | \"collection\";\n\tcustomUrl?: string;\n\treferenceCollection?: string;\n\treferenceId?: string;\n\ttitleAttr?: string;\n\ttarget?: string;\n\tcssClasses?: string;\n\tparentIndex?: number;\n}\n\nexport interface ReorderItem {\n\tid: string;\n\tparentId: string | null;\n\tsortOrder: number;\n}\n\n// ---------------------------------------------------------------------------\n// Row → entity mappers\n// ---------------------------------------------------------------------------\n\nfunction rowToMenu(row: Selectable<MenuTable>): Menu {\n\treturn {\n\t\tid: row.id,\n\t\tname: row.name,\n\t\tlabel: row.label,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t\tlocale: row.locale,\n\t\ttranslationGroup: row.translation_group,\n\t};\n}\n\nfunction rowToMenuItem(row: Selectable<MenuItemTable>): MenuItem {\n\treturn {\n\t\tid: row.id,\n\t\tmenuId: row.menu_id,\n\t\tparentId: row.parent_id,\n\t\tsortOrder: row.sort_order,\n\t\ttype: row.type,\n\t\treferenceCollection: row.reference_collection,\n\t\treferenceId: row.reference_id,\n\t\tcustomUrl: row.custom_url,\n\t\tlabel: row.label,\n\t\ttitleAttr: row.title_attr,\n\t\ttarget: row.target,\n\t\tcssClasses: row.css_classes,\n\t\tcreatedAt: row.created_at,\n\t\tlocale: row.locale,\n\t\ttranslationGroup: row.translation_group,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Repository\n// ---------------------------------------------------------------------------\n\nexport class MenuRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t// --- Menus -------------------------------------------------------------\n\n\t/**\n\t * List menus with their item counts. When `locale` is omitted, returns\n\t * every locale variant as its own row (consistent with the admin listing\n\t * model: each translation is its own menu for editing purposes).\n\t */\n\tasync findMany(options: { locale?: string } = {}): Promise<MenuListItem[]> {\n\t\t// Single LEFT JOIN + GROUP BY for the per-menu count. Avoids N+1.\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_menus as m\")\n\t\t\t.leftJoin(\"_emdash_menu_items as i\", \"i.menu_id\", \"m.id\")\n\t\t\t.select(({ fn }) => [\n\t\t\t\t\"m.id\",\n\t\t\t\t\"m.name\",\n\t\t\t\t\"m.label\",\n\t\t\t\t\"m.created_at\",\n\t\t\t\t\"m.updated_at\",\n\t\t\t\t\"m.locale\",\n\t\t\t\t\"m.translation_group\",\n\t\t\t\tfn.count<number>(\"i.id\").as(\"itemCount\"),\n\t\t\t])\n\t\t\t.groupBy([\n\t\t\t\t\"m.id\",\n\t\t\t\t\"m.name\",\n\t\t\t\t\"m.label\",\n\t\t\t\t\"m.created_at\",\n\t\t\t\t\"m.updated_at\",\n\t\t\t\t\"m.locale\",\n\t\t\t\t\"m.translation_group\",\n\t\t\t])\n\t\t\t.orderBy(\"m.name\", \"asc\");\n\t\tif (options.locale !== undefined) query = query.where(\"m.locale\", \"=\", options.locale);\n\t\tconst rows = await query.execute();\n\n\t\treturn rows.map((row) => ({\n\t\t\t// Postgres returns count() as `string`; SQLite as `number`. Normalize.\n\t\t\titemCount: typeof row.itemCount === \"string\" ? Number(row.itemCount) : row.itemCount,\n\t\t\t...rowToMenu({\n\t\t\t\tid: row.id,\n\t\t\t\tname: row.name,\n\t\t\t\tlabel: row.label,\n\t\t\t\tcreated_at: row.created_at,\n\t\t\t\tupdated_at: row.updated_at,\n\t\t\t\tlocale: row.locale,\n\t\t\t\ttranslation_group: row.translation_group,\n\t\t\t}),\n\t\t}));\n\t}\n\n\t/**\n\t * Find every menu row matching `name` (one per locale on multi-locale\n\t * installs). Callers use this both to look up a single menu (when locale\n\t * is supplied) and to detect AMBIGUOUS_LOCALE situations (`length > 1`).\n\t */\n\tasync findByName(name: string, options: { locale?: string } = {}): Promise<Menu[]> {\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where(\"name\", \"=\", name)\n\t\t\t.orderBy(\"locale\", \"asc\");\n\t\tif (options.locale !== undefined) query = query.where(\"locale\", \"=\", options.locale);\n\t\tconst rows = await query.execute();\n\t\treturn rows.map(rowToMenu);\n\t}\n\n\tasync findById(id: string): Promise<Menu | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToMenu(row) : null;\n\t}\n\n\t/** Fetch a menu plus its items, ordered by `sort_order`. */\n\tasync findWithItems(menuId: string): Promise<MenuWithItems | null> {\n\t\tconst menu = await this.findById(menuId);\n\t\tif (!menu) return null;\n\t\tconst items = await this.findItems(menuId);\n\t\treturn { ...menu, items };\n\t}\n\n\tasync findItems(menuId: string): Promise<MenuItem[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t.execute();\n\t\treturn rows.map(rowToMenuItem);\n\t}\n\n\t/**\n\t * Returns true when a menu already exists for the given `(name, locale)`.\n\t * Used by the handler to surface a CONFLICT before attempting the insert.\n\t */\n\tasync existsByNameAndLocale(name: string, locale: string): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"name\", \"=\", name)\n\t\t\t.where(\"locale\", \"=\", locale)\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n\n\t/**\n\t * Create a menu. When `translationOf` is supplied the new menu joins the\n\t * source menu's translation_group and clones its items (each clone gets a\n\t * fresh ULID, but inherits the source item's `translation_group` so a\n\t * given nav entry resolves to \"the same item\" across menu translations).\n\t *\n\t * If the source menu is missing this throws — callers should validate\n\t * existence via `findById` first to return a clean NOT_FOUND.\n\t */\n\tasync create(input: CreateMenuInput): Promise<Menu> {\n\t\tconst id = ulid();\n\n\t\tlet translationGroup: string = id;\n\t\tlet sourceMenuId: string | null = null;\n\t\tif (input.translationOf) {\n\t\t\tconst source = await this.findById(input.translationOf);\n\t\t\tif (!source) throw new Error(\"Source menu for translation not found\");\n\t\t\ttranslationGroup = source.translationGroup ?? source.id;\n\t\t\tsourceMenuId = source.id;\n\t\t}\n\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tawait trx\n\t\t\t\t.insertInto(\"_emdash_menus\")\n\t\t\t\t.values({\n\t\t\t\t\tid,\n\t\t\t\t\tname: input.name,\n\t\t\t\t\tlabel: input.label,\n\t\t\t\t\t...(input.locale !== undefined ? { locale: input.locale } : {}),\n\t\t\t\t\ttranslation_group: translationGroup,\n\t\t\t\t})\n\t\t\t\t.execute();\n\n\t\t\tif (sourceMenuId) {\n\t\t\t\tconst sourceItems = await trx\n\t\t\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t\t\t.selectAll()\n\t\t\t\t\t.where(\"menu_id\", \"=\", sourceMenuId)\n\t\t\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t\t\t.execute();\n\t\t\t\tif (sourceItems.length > 0) {\n\t\t\t\t\t// old-id → new-id map so parent pointers land on the clones.\n\t\t\t\t\tconst idMap = new Map<string, string>();\n\t\t\t\t\tfor (const item of sourceItems) idMap.set(item.id, ulid());\n\n\t\t\t\t\tawait trx\n\t\t\t\t\t\t.insertInto(\"_emdash_menu_items\")\n\t\t\t\t\t\t.values(\n\t\t\t\t\t\t\tsourceItems.map((item) => ({\n\t\t\t\t\t\t\t\tid: idMap.get(item.id)!,\n\t\t\t\t\t\t\t\tmenu_id: id,\n\t\t\t\t\t\t\t\tparent_id: item.parent_id ? (idMap.get(item.parent_id) ?? null) : null,\n\t\t\t\t\t\t\t\tsort_order: item.sort_order,\n\t\t\t\t\t\t\t\ttype: item.type,\n\t\t\t\t\t\t\t\treference_collection: item.reference_collection,\n\t\t\t\t\t\t\t\treference_id: item.reference_id,\n\t\t\t\t\t\t\t\tcustom_url: item.custom_url,\n\t\t\t\t\t\t\t\tlabel: item.label,\n\t\t\t\t\t\t\t\ttitle_attr: item.title_attr,\n\t\t\t\t\t\t\t\ttarget: item.target,\n\t\t\t\t\t\t\t\tcss_classes: item.css_classes,\n\t\t\t\t\t\t\t\t...(input.locale !== undefined ? { locale: input.locale } : {}),\n\t\t\t\t\t\t\t\ttranslation_group: item.translation_group ?? item.id,\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.execute();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tconst created = await this.findById(id);\n\t\tif (!created) throw new Error(\"Failed to create menu\");\n\t\treturn created;\n\t}\n\n\tasync update(id: string, input: UpdateMenuInput): Promise<Menu | null> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return null;\n\n\t\tconst values: Record<string, unknown> = {};\n\t\tif (input.label !== undefined) values.label = input.label;\n\n\t\tif (Object.keys(values).length > 0) {\n\t\t\tawait this.db.updateTable(\"_emdash_menus\").set(values).where(\"id\", \"=\", id).execute();\n\t\t}\n\n\t\treturn (await this.findById(id))!;\n\t}\n\n\t/**\n\t * Delete a menu. Items are deleted explicitly to avoid relying on the\n\t * `ON DELETE CASCADE` FK declared in migration 005, which migration 036\n\t * removed: that FK is what made #1021 destructive on D1 (the cascade\n\t * fired when the i18n migration dropped `_emdash_menus`), so dropping\n\t * the FK was the fix. The explicit delete keeps the runtime working\n\t * the same way before and after the migration.\n\t */\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return false;\n\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tawait trx.deleteFrom(\"_emdash_menu_items\").where(\"menu_id\", \"=\", id).execute();\n\t\t\tawait trx.deleteFrom(\"_emdash_menus\").where(\"id\", \"=\", id).execute();\n\t\t});\n\t\treturn true;\n\t}\n\n\t/**\n\t * List every translation of a menu (by id or translation_group).\n\t *\n\t * Returns `null` when neither the id nor the group resolves to a menu,\n\t * mapped to NOT_FOUND by the handler.\n\t */\n\tasync listTranslations(\n\t\tidOrGroup: string,\n\t): Promise<{ translationGroup: string | null; translations: MenuTranslation[] } | null> {\n\t\tconst anchor = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where((eb) => eb.or([eb(\"id\", \"=\", idOrGroup), eb(\"translation_group\", \"=\", idOrGroup)]))\n\t\t\t.executeTakeFirst();\n\t\tif (!anchor) return null;\n\n\t\tconst group = anchor.translation_group ?? anchor.id;\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where(\"translation_group\", \"=\", group)\n\t\t\t.orderBy(\"locale\", \"asc\")\n\t\t\t.execute();\n\n\t\treturn {\n\t\t\ttranslationGroup: group,\n\t\t\ttranslations: rows.map((row) => ({\n\t\t\t\tid: row.id,\n\t\t\t\tname: row.name,\n\t\t\t\tlocale: row.locale,\n\t\t\t\tlabel: row.label,\n\t\t\t\tupdatedAt: row.updated_at,\n\t\t\t})),\n\t\t};\n\t}\n\n\t// --- Items -------------------------------------------------------------\n\n\t/**\n\t * Insert a menu item. `locale` is propagated from the parent menu so\n\t * `_emdash_menu_items.locale` mirrors the menu's locale (queries can scope\n\t * by locale without a join).\n\t *\n\t * When `sortOrder` is omitted, the next position within the same parent\n\t * scope is used (max + 1). The fresh `translation_group` defaults to the\n\t * item's own id, matching the migration 036 backfill.\n\t */\n\tasync createItem(menuId: string, locale: string, input: CreateMenuItemInput): Promise<MenuItem> {\n\t\tlet sortOrder = input.sortOrder ?? 0;\n\t\tif (input.sortOrder === undefined) {\n\t\t\tconst maxOrder = await this.db\n\t\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t\t.select(({ fn }) => fn.max(\"sort_order\").as(\"max\"))\n\t\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t\t.where(\"parent_id\", \"is\", input.parentId ?? null)\n\t\t\t\t.executeTakeFirst();\n\t\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- Kysely fn.max returns unknown; always a number for sort_order column\n\t\t\tsortOrder = ((maxOrder?.max as number) ?? -1) + 1;\n\t\t}\n\n\t\tconst id = ulid();\n\t\tawait this.db\n\t\t\t.insertInto(\"_emdash_menu_items\")\n\t\t\t.values({\n\t\t\t\tid,\n\t\t\t\tmenu_id: menuId,\n\t\t\t\tparent_id: input.parentId ?? null,\n\t\t\t\tsort_order: sortOrder,\n\t\t\t\ttype: input.type,\n\t\t\t\treference_collection: input.referenceCollection ?? null,\n\t\t\t\treference_id: input.referenceId ?? null,\n\t\t\t\tcustom_url: input.customUrl ?? null,\n\t\t\t\tlabel: input.label,\n\t\t\t\ttitle_attr: input.titleAttr ?? null,\n\t\t\t\ttarget: input.target ?? null,\n\t\t\t\tcss_classes: input.cssClasses ?? null,\n\t\t\t\tlocale,\n\t\t\t\ttranslation_group: id,\n\t\t\t})\n\t\t\t.execute();\n\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirstOrThrow();\n\t\treturn rowToMenuItem(row);\n\t}\n\n\t/**\n\t * Update a menu item. Caller must ensure the item belongs to the menu —\n\t * the `where(\"menu_id\", \"=\", menuId)` guard prevents cross-menu writes.\n\t * Returns `null` if the item is not found within the menu.\n\t */\n\tasync updateItem(\n\t\tmenuId: string,\n\t\titemId: string,\n\t\tinput: UpdateMenuItemInput,\n\t): Promise<MenuItem | null> {\n\t\tconst existing = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t.executeTakeFirst();\n\t\tif (!existing) return null;\n\n\t\tconst values: Record<string, unknown> = {};\n\t\tif (input.label !== undefined) values.label = input.label;\n\t\tif (input.customUrl !== undefined) values.custom_url = input.customUrl;\n\t\tif (input.target !== undefined) values.target = input.target;\n\t\tif (input.titleAttr !== undefined) values.title_attr = input.titleAttr;\n\t\tif (input.cssClasses !== undefined) values.css_classes = input.cssClasses;\n\t\tif (input.parentId !== undefined) values.parent_id = input.parentId;\n\t\tif (input.sortOrder !== undefined) values.sort_order = input.sortOrder;\n\n\t\tif (Object.keys(values).length > 0) {\n\t\t\tawait this.db\n\t\t\t\t.updateTable(\"_emdash_menu_items\")\n\t\t\t\t.set(values)\n\t\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t\t.execute();\n\t\t}\n\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t.executeTakeFirstOrThrow();\n\t\treturn rowToMenuItem(row);\n\t}\n\n\t/** Delete an item scoped to its menu. Returns false if nothing was deleted. */\n\tasync deleteItem(menuId: string, itemId: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_menu_items\")\n\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t.execute();\n\t\treturn result[0]?.numDeletedRows !== 0n;\n\t}\n\n\t/**\n\t * Atomic replace: delete every existing item and re-insert in order.\n\t * `parentIndex` (validated by the caller) is resolved against the live\n\t * insert order so children always reference real parent ids.\n\t *\n\t * Returns the count of inserted items (matches the existing handler API).\n\t */\n\tasync setItems(\n\t\tmenuId: string,\n\t\tlocale: string,\n\t\titems: SetMenuItem[],\n\t): Promise<{ itemCount: number }> {\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t// Re-check menu existence INSIDE the transaction. The handler\n\t\t\t// resolved by (name, locale) before this call; if a concurrent\n\t\t\t// menu_delete landed in between, inserting new items would\n\t\t\t// silently orphan them. The FK from migration 005 was removed\n\t\t\t// by migration 036 (#1021) and not restored, so nothing at the\n\t\t\t// schema level stops the orphans. Throw a MenuGoneError so the\n\t\t\t// rollback fires and the handler returns NOT_FOUND with the\n\t\t\t// original menu name in the message.\n\t\t\tconst stillThere = await trx\n\t\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t\t.select(\"id\")\n\t\t\t\t.where(\"id\", \"=\", menuId)\n\t\t\t\t.executeTakeFirst();\n\t\t\tif (!stillThere) throw new MenuGoneError(menuId);\n\n\t\t\tawait trx.deleteFrom(\"_emdash_menu_items\").where(\"menu_id\", \"=\", menuId).execute();\n\n\t\t\tconst insertedIds: string[] = [];\n\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\tconst item = items[i];\n\t\t\t\tif (!item) continue;\n\t\t\t\tconst id = ulid();\n\t\t\t\tconst parentId =\n\t\t\t\t\titem.parentIndex !== undefined ? (insertedIds[item.parentIndex] ?? null) : null;\n\t\t\t\tawait trx\n\t\t\t\t\t.insertInto(\"_emdash_menu_items\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tmenu_id: menuId,\n\t\t\t\t\t\tparent_id: parentId,\n\t\t\t\t\t\tsort_order: i,\n\t\t\t\t\t\ttype: item.type,\n\t\t\t\t\t\treference_collection: item.referenceCollection ?? null,\n\t\t\t\t\t\treference_id: item.referenceId ?? null,\n\t\t\t\t\t\tcustom_url: item.customUrl ?? null,\n\t\t\t\t\t\tlabel: item.label,\n\t\t\t\t\t\ttitle_attr: item.titleAttr ?? null,\n\t\t\t\t\t\ttarget: item.target ?? null,\n\t\t\t\t\t\tcss_classes: item.cssClasses ?? null,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t})\n\t\t\t\t\t.execute();\n\t\t\t\tinsertedIds.push(id);\n\t\t\t}\n\n\t\t\tawait trx\n\t\t\t\t.updateTable(\"_emdash_menus\")\n\t\t\t\t.set({ updated_at: new Date().toISOString() })\n\t\t\t\t.where(\"id\", \"=\", menuId)\n\t\t\t\t.execute();\n\t\t});\n\n\t\treturn { itemCount: items.length };\n\t}\n\n\t/**\n\t * Batch reorder items. Each entry is applied scoped to the menu so a\n\t * malicious payload cannot move foreign items into this menu's siblings.\n\t */\n\tasync reorderItems(menuId: string, items: ReorderItem[]): Promise<MenuItem[]> {\n\t\treturn withTransaction(this.db, async (trx) => {\n\t\t\tfor (const item of items) {\n\t\t\t\tawait trx\n\t\t\t\t\t.updateTable(\"_emdash_menu_items\")\n\t\t\t\t\t.set({ parent_id: item.parentId, sort_order: item.sortOrder })\n\t\t\t\t\t.where(\"id\", \"=\", item.id)\n\t\t\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t\t\t.execute();\n\t\t\t}\n\n\t\t\tconst rows = await trx\n\t\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t\t.selectAll()\n\t\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t\t.execute();\n\t\t\treturn rows.map(rowToMenuItem);\n\t\t});\n\t}\n}\n","/**\n * Menu CRUD handlers.\n *\n * Business logic for menu and menu-item endpoints. Routes are thin wrappers\n * that parse input, check auth, and call these.\n *\n * i18n: Menus are per-locale. `(name, locale)` is unique, so the same `name`\n * (e.g. \"primary\") can exist in several locales within one translation_group.\n * Menu items carry a `locale` + `translation_group` as well, and their\n * `reference_id` points at the referenced content's translation_group (not a\n * specific row id), so a single menu item target survives content translations.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport {\n\tMenuGoneError,\n\tMenuRepository,\n\ttype CreateMenuItemInput as CreateMenuItemRepoInput,\n\ttype Menu,\n\ttype MenuItem,\n\ttype MenuListItem,\n\ttype MenuWithItems,\n\ttype SetMenuItem,\n\ttype UpdateMenuItemInput as UpdateMenuItemRepoInput,\n} from \"../../database/repositories/menu.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { getI18nConfig } from \"../../i18n/config.js\";\nimport type { ApiResult } from \"../types.js\";\n\n// Re-export entity types so route files and tests can import them from the\n// handler module without having to know about the repository layout.\nexport type {\n\tMenu,\n\tMenuItem,\n\tMenuListItem,\n\tMenuTranslation,\n\tMenuWithItems,\n} from \"../../database/repositories/menu.js\";\n\nexport interface MenuTranslationsResponse {\n\ttranslationGroup: string | null;\n\ttranslations: Array<{\n\t\tid: string;\n\t\tname: string;\n\t\tlocale: string;\n\t\tlabel: string;\n\t\tupdatedAt: string;\n\t}>;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Error returned when a menu lookup by `name` matches multiple locale\n * variants and the caller did not pass `locale` to disambiguate. Maps to\n * HTTP 400 via `mapErrorStatus`. The available locales are surfaced in the\n * message so MCP/REST callers can recover by re-issuing with `locale`.\n */\nfunction ambiguousMenuLocaleError(\n\tname: string,\n\tlocales: readonly string[],\n): { success: false; error: { code: \"AMBIGUOUS_LOCALE\"; message: string } } {\n\tconst sortedLocales = locales.toSorted();\n\treturn {\n\t\tsuccess: false,\n\t\terror: {\n\t\t\tcode: \"AMBIGUOUS_LOCALE\",\n\t\t\tmessage: `Menu '${name}' exists in multiple locales (${sortedLocales.join(\n\t\t\t\t\", \",\n\t\t\t)}); pass 'locale' to disambiguate.`,\n\t\t},\n\t};\n}\n\ntype ResolveMenuResult =\n\t| { success: true; menu: Menu }\n\t| { success: false; error: { code: \"NOT_FOUND\" | \"AMBIGUOUS_LOCALE\"; message: string } };\n\n/**\n * Resolve a menu by name + optional locale to a single Menu, surfacing the\n * canonical NOT_FOUND / AMBIGUOUS_LOCALE errors. Every item handler relies on\n * this to translate (name, locale) into an unambiguous menu row.\n */\nasync function resolveMenu(\n\trepo: MenuRepository,\n\tname: string,\n\toptions: { locale?: string },\n): Promise<ResolveMenuResult> {\n\tconst matches = await repo.findByName(name, options);\n\tif (matches.length === 0) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\tmessage: `Menu '${name}' not found${options.locale ? ` in locale '${options.locale}'` : \"\"}`,\n\t\t\t},\n\t\t};\n\t}\n\tif (matches.length > 1) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: ambiguousMenuLocaleError(\n\t\t\t\tname,\n\t\t\t\tmatches.map((m) => m.locale),\n\t\t\t).error,\n\t\t};\n\t}\n\treturn { success: true, menu: matches[0] };\n}\n\n// ---------------------------------------------------------------------------\n// Menu handlers\n// ---------------------------------------------------------------------------\n\n/**\n * List menus with item counts. Filter by `locale` when provided.\n */\nexport async function handleMenuList(\n\tdb: Kysely<Database>,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuListItem[]>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst items = await repo.findMany(options);\n\t\treturn { success: true, data: items };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_LIST_ERROR\", message: \"Failed to fetch menus\" },\n\t\t};\n\t}\n}\n\n/**\n * Create a new menu. When `translationOf` is supplied the new menu joins the\n * source menu's translation_group (and gets the source's items cloned by the\n * repository).\n */\nexport async function handleMenuCreate(\n\tdb: Kysely<Database>,\n\tinput: { name: string; label: string; locale?: string; translationOf?: string },\n): Promise<ApiResult<Menu>> {\n\ttry {\n\t\t// Translating from a source menu only makes sense when the caller\n\t\t// names the target locale: otherwise we'd silently clone into the\n\t\t// configured default, which is almost never what's intended (and\n\t\t// will collide if the source is already the default-locale menu).\n\t\t// Enforced here so REST/SDK callers get the same guard as MCP.\n\t\tif (input.translationOf && !input.locale) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\t\tmessage: \"`locale` is required when `translationOf` is provided\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst repo = new MenuRepository(db);\n\n\t\t// Existence check up front so the repo's \"Source not found\" throw\n\t\t// becomes a clean NOT_FOUND on the API.\n\t\tif (input.translationOf) {\n\t\t\tconst source = await repo.findById(input.translationOf);\n\t\t\tif (!source) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Source menu for translation not found\" },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Duplicate guard: same (name, locale). Falls back to the configured\n\t\t// defaultLocale to match the column DEFAULT set by migration 036.\n\t\tconst effectiveLocale = input.locale ?? getI18nConfig()?.defaultLocale ?? \"en\";\n\t\tif (await repo.existsByNameAndLocale(input.name, effectiveLocale)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"CONFLICT\",\n\t\t\t\t\tmessage: `Menu \"${input.name}\" already exists${\n\t\t\t\t\t\tinput.locale ? ` in locale \"${input.locale}\"` : \"\"\n\t\t\t\t\t}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst menu = await repo.create(input);\n\t\treturn { success: true, data: menu };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_CREATE_ERROR\", message: \"Failed to create menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Get a single menu by name. Honours an optional `locale` filter; when two\n * menus share a name across locales, the locale distinguishes them.\n *\n * Historical behaviour: when `locale` is omitted, returns the lowest-locale\n * match (deterministic). Mirrors the pre-repo handler.\n */\nexport async function handleMenuGet(\n\tdb: Kysely<Database>,\n\tname: string,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuWithItems>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst matches = await repo.findByName(name, options);\n\t\tif (matches.length === 0) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Menu '${name}' not found` },\n\t\t\t};\n\t\t}\n\t\tconst menu = matches[0];\n\t\tconst items = await repo.findItems(menu.id);\n\t\treturn { success: true, data: { ...menu, items } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_GET_ERROR\", message: \"Failed to fetch menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Get a menu by id. Useful when the caller already has the id (e.g. after\n * creating a translation and navigating to it).\n */\nexport async function handleMenuGetById(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<MenuWithItems>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst menu = await repo.findWithItems(id);\n\t\tif (!menu) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Menu '${id}' not found` },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: menu };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_GET_ERROR\", message: \"Failed to fetch menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Update a menu's label. The name + locale are immutable.\n */\nexport async function handleMenuUpdate(\n\tdb: Kysely<Database>,\n\tname: string,\n\tinput: { label?: string; locale?: string },\n): Promise<ApiResult<Menu>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, name, { locale: input.locale });\n\t\tif (!resolved.success) return resolved;\n\t\tconst updated = await repo.update(resolved.menu.id, { label: input.label });\n\t\tif (!updated) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Menu '${name}' not found` },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: updated };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_UPDATE_ERROR\", message: \"Failed to update menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Delete a menu (and its items, via the repository's explicit cleanup).\n */\nexport async function handleMenuDelete(\n\tdb: Kysely<Database>,\n\tname: string,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, name, options);\n\t\tif (!resolved.success) return resolved;\n\t\tawait repo.delete(resolved.menu.id);\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_DELETE_ERROR\", message: \"Failed to delete menu\" },\n\t\t};\n\t}\n}\n\n/**\n * List every translation of a menu (by id or translation_group).\n */\nexport async function handleMenuTranslations(\n\tdb: Kysely<Database>,\n\tidOrGroup: string,\n): Promise<ApiResult<MenuTranslationsResponse>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst result = await repo.listTranslations(idOrGroup);\n\t\tif (!result) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Menu not found\" },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: result };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_TRANSLATIONS_ERROR\", message: \"Failed to list menu translations\" },\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Menu item handlers\n// ---------------------------------------------------------------------------\n\nexport type CreateMenuItemInput = CreateMenuItemRepoInput;\nexport type UpdateMenuItemInput = UpdateMenuItemRepoInput;\nexport type MenuSetItemsInput = SetMenuItem;\n\n/**\n * Add an item to a menu. The item inherits the menu's locale.\n */\nexport async function handleMenuItemCreate(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\tinput: CreateMenuItemInput,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuItem>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst item = await repo.createItem(resolved.menu.id, resolved.menu.locale, input);\n\t\treturn { success: true, data: item };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_ITEM_CREATE_ERROR\", message: \"Failed to create menu item\" },\n\t\t};\n\t}\n}\n\n/**\n * Update a menu item.\n */\nexport async function handleMenuItemUpdate(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titemId: string,\n\tinput: UpdateMenuItemInput,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuItem>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst updated = await repo.updateItem(resolved.menu.id, itemId, input);\n\t\tif (!updated) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Menu item not found\" },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: updated };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_ITEM_UPDATE_ERROR\", message: \"Failed to update menu item\" },\n\t\t};\n\t}\n}\n\n/**\n * Delete a menu item.\n */\nexport async function handleMenuItemDelete(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titemId: string,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst deleted = await repo.deleteItem(resolved.menu.id, itemId);\n\t\tif (!deleted) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Menu item not found\" },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_ITEM_DELETE_ERROR\", message: \"Failed to delete menu item\" },\n\t\t};\n\t}\n}\n\nexport interface ReorderItem {\n\tid: string;\n\tparentId: string | null;\n\tsortOrder: number;\n}\n\n// ---------------------------------------------------------------------------\n// Atomic-replace menu items (used by the MCP `menu_set_items` tool and admin)\n// ---------------------------------------------------------------------------\n\n/**\n * Replace the entire set of items for a menu in one atomic transaction.\n *\n * Existing items are deleted and the new list is inserted in the order\n * provided. `parentIndex` references resolve to actual parent IDs as the\n * insert proceeds.\n */\nexport async function handleMenuSetItems(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titems: MenuSetItemsInput[],\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<{ name: string; itemCount: number }>> {\n\t// Validate parentIndex references — must be strictly earlier so the array\n\t// can be inserted in order with parents resolved first. Negative indices\n\t// are caught by Zod's `.nonnegative()` at the MCP boundary, but we guard\n\t// explicitly so REST routes / direct handler use get the same error.\n\tfor (let i = 0; i < items.length; i++) {\n\t\tconst item = items[i];\n\t\tif (item?.parentIndex !== undefined) {\n\t\t\tif (item.parentIndex < 0 || item.parentIndex >= i) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\t\t\tmessage: `item[${i}].parentIndex (${item.parentIndex}) must reference an earlier item`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst { itemCount } = await repo.setItems(resolved.menu.id, resolved.menu.locale, items);\n\t\treturn { success: true, data: { name: menuName, itemCount } };\n\t} catch (error) {\n\t\t// `MenuGoneError` is thrown from inside the repository transaction\n\t\t// when the menu was deleted concurrently between `resolveMenu` and the\n\t\t// setItems write. Returning NOT_FOUND mirrors the original handler's\n\t\t// in-transaction `notFoundSentinel` branch and keeps the response\n\t\t// shape stable for REST/MCP callers.\n\t\tif (error instanceof MenuGoneError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\t\tmessage: `Menu '${menuName}' not found${\n\t\t\t\t\t\toptions.locale ? ` in locale '${options.locale}'` : \"\"\n\t\t\t\t\t}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[emdash] handleMenuSetItems failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_SET_ITEMS_ERROR\", message: \"Failed to set menu items\" },\n\t\t};\n\t}\n}\n\n/**\n * Batch reorder menu items.\n */\nexport async function handleMenuItemReorder(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titems: ReorderItem[],\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuItem[]>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst updated = await repo.reorderItems(resolved.menu.id, items);\n\t\treturn { success: true, data: updated };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_REORDER_ERROR\", message: \"Failed to reorder menu items\" },\n\t\t};\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;AA4BA,IAAa,gBAAb,cAAmC,MAAM;CACxC,YAAY,AAAgB,QAAgB;AAC3C,QAAM,QAAQ,OAAO,mCAAmC;EAD7B;AAE3B,OAAK,OAAO;;;AA4Hd,SAAS,UAAU,KAAkC;AACpD,QAAO;EACN,IAAI,IAAI;EACR,MAAM,IAAI;EACV,OAAO,IAAI;EACX,WAAW,IAAI;EACf,WAAW,IAAI;EACf,QAAQ,IAAI;EACZ,kBAAkB,IAAI;EACtB;;AAGF,SAAS,cAAc,KAA0C;AAChE,QAAO;EACN,IAAI,IAAI;EACR,QAAQ,IAAI;EACZ,UAAU,IAAI;EACd,WAAW,IAAI;EACf,MAAM,IAAI;EACV,qBAAqB,IAAI;EACzB,aAAa,IAAI;EACjB,WAAW,IAAI;EACf,OAAO,IAAI;EACX,WAAW,IAAI;EACf,QAAQ,IAAI;EACZ,YAAY,IAAI;EAChB,WAAW,IAAI;EACf,QAAQ,IAAI;EACZ,kBAAkB,IAAI;EACtB;;AAOF,IAAa,iBAAb,MAA4B;CAC3B,YAAY,AAAQ,IAAsB;EAAtB;;;;;;;CASpB,MAAM,SAAS,UAA+B,EAAE,EAA2B;EAE1E,IAAI,QAAQ,KAAK,GACf,WAAW,qBAAqB,CAChC,SAAS,2BAA2B,aAAa,OAAO,CACxD,QAAQ,EAAE,SAAS;GACnB;GACA;GACA;GACA;GACA;GACA;GACA;GACA,GAAG,MAAc,OAAO,CAAC,GAAG,YAAY;GACxC,CAAC,CACD,QAAQ;GACR;GACA;GACA;GACA;GACA;GACA;GACA;GACA,CAAC,CACD,QAAQ,UAAU,MAAM;AAC1B,MAAI,QAAQ,WAAW,OAAW,SAAQ,MAAM,MAAM,YAAY,KAAK,QAAQ,OAAO;AAGtF,UAFa,MAAM,MAAM,SAAS,EAEtB,KAAK,SAAS;GAEzB,WAAW,OAAO,IAAI,cAAc,WAAW,OAAO,IAAI,UAAU,GAAG,IAAI;GAC3E,GAAG,UAAU;IACZ,IAAI,IAAI;IACR,MAAM,IAAI;IACV,OAAO,IAAI;IACX,YAAY,IAAI;IAChB,YAAY,IAAI;IAChB,QAAQ,IAAI;IACZ,mBAAmB,IAAI;IACvB,CAAC;GACF,EAAE;;;;;;;CAQJ,MAAM,WAAW,MAAc,UAA+B,EAAE,EAAmB;EAClF,IAAI,QAAQ,KAAK,GACf,WAAW,gBAAgB,CAC3B,WAAW,CACX,MAAM,QAAQ,KAAK,KAAK,CACxB,QAAQ,UAAU,MAAM;AAC1B,MAAI,QAAQ,WAAW,OAAW,SAAQ,MAAM,MAAM,UAAU,KAAK,QAAQ,OAAO;AAEpF,UADa,MAAM,MAAM,SAAS,EACtB,IAAI,UAAU;;CAG3B,MAAM,SAAS,IAAkC;EAChD,MAAM,MAAM,MAAM,KAAK,GACrB,WAAW,gBAAgB,CAC3B,WAAW,CACX,MAAM,MAAM,KAAK,GAAG,CACpB,kBAAkB;AACpB,SAAO,MAAM,UAAU,IAAI,GAAG;;;CAI/B,MAAM,cAAc,QAA+C;EAClE,MAAM,OAAO,MAAM,KAAK,SAAS,OAAO;AACxC,MAAI,CAAC,KAAM,QAAO;EAClB,MAAM,QAAQ,MAAM,KAAK,UAAU,OAAO;AAC1C,SAAO;GAAE,GAAG;GAAM;GAAO;;CAG1B,MAAM,UAAU,QAAqC;AAOpD,UANa,MAAM,KAAK,GACtB,WAAW,qBAAqB,CAChC,WAAW,CACX,MAAM,WAAW,KAAK,OAAO,CAC7B,QAAQ,cAAc,MAAM,CAC5B,SAAS,EACC,IAAI,cAAc;;;;;;CAO/B,MAAM,sBAAsB,MAAc,QAAkC;AAO3E,SANY,MAAM,KAAK,GACrB,WAAW,gBAAgB,CAC3B,OAAO,KAAK,CACZ,MAAM,QAAQ,KAAK,KAAK,CACxB,MAAM,UAAU,KAAK,OAAO,CAC5B,kBAAkB,KACL;;;;;;;;;;;CAYhB,MAAM,OAAO,OAAuC;EACnD,MAAM,KAAK,MAAM;EAEjB,IAAI,mBAA2B;EAC/B,IAAI,eAA8B;AAClC,MAAI,MAAM,eAAe;GACxB,MAAM,SAAS,MAAM,KAAK,SAAS,MAAM,cAAc;AACvD,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,wCAAwC;AACrE,sBAAmB,OAAO,oBAAoB,OAAO;AACrD,kBAAe,OAAO;;AAGvB,QAAM,gBAAgB,KAAK,IAAI,OAAO,QAAQ;AAC7C,SAAM,IACJ,WAAW,gBAAgB,CAC3B,OAAO;IACP;IACA,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,QAAQ,GAAG,EAAE;IAC9D,mBAAmB;IACnB,CAAC,CACD,SAAS;AAEX,OAAI,cAAc;IACjB,MAAM,cAAc,MAAM,IACxB,WAAW,qBAAqB,CAChC,WAAW,CACX,MAAM,WAAW,KAAK,aAAa,CACnC,QAAQ,cAAc,MAAM,CAC5B,SAAS;AACX,QAAI,YAAY,SAAS,GAAG;KAE3B,MAAM,wBAAQ,IAAI,KAAqB;AACvC,UAAK,MAAM,QAAQ,YAAa,OAAM,IAAI,KAAK,IAAI,MAAM,CAAC;AAE1D,WAAM,IACJ,WAAW,qBAAqB,CAChC,OACA,YAAY,KAAK,UAAU;MAC1B,IAAI,MAAM,IAAI,KAAK,GAAG;MACtB,SAAS;MACT,WAAW,KAAK,YAAa,MAAM,IAAI,KAAK,UAAU,IAAI,OAAQ;MAClE,YAAY,KAAK;MACjB,MAAM,KAAK;MACX,sBAAsB,KAAK;MAC3B,cAAc,KAAK;MACnB,YAAY,KAAK;MACjB,OAAO,KAAK;MACZ,YAAY,KAAK;MACjB,QAAQ,KAAK;MACb,aAAa,KAAK;MAClB,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,QAAQ,GAAG,EAAE;MAC9D,mBAAmB,KAAK,qBAAqB,KAAK;MAClD,EAAE,CACH,CACA,SAAS;;;IAGZ;EAEF,MAAM,UAAU,MAAM,KAAK,SAAS,GAAG;AACvC,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,wBAAwB;AACtD,SAAO;;CAGR,MAAM,OAAO,IAAY,OAA8C;AAEtE,MAAI,CADa,MAAM,KAAK,SAAS,GAAG,CACzB,QAAO;EAEtB,MAAM,SAAkC,EAAE;AAC1C,MAAI,MAAM,UAAU,OAAW,QAAO,QAAQ,MAAM;AAEpD,MAAI,OAAO,KAAK,OAAO,CAAC,SAAS,EAChC,OAAM,KAAK,GAAG,YAAY,gBAAgB,CAAC,IAAI,OAAO,CAAC,MAAM,MAAM,KAAK,GAAG,CAAC,SAAS;AAGtF,SAAQ,MAAM,KAAK,SAAS,GAAG;;;;;;;;;;CAWhC,MAAM,OAAO,IAA8B;AAE1C,MAAI,CADa,MAAM,KAAK,SAAS,GAAG,CACzB,QAAO;AAEtB,QAAM,gBAAgB,KAAK,IAAI,OAAO,QAAQ;AAC7C,SAAM,IAAI,WAAW,qBAAqB,CAAC,MAAM,WAAW,KAAK,GAAG,CAAC,SAAS;AAC9E,SAAM,IAAI,WAAW,gBAAgB,CAAC,MAAM,MAAM,KAAK,GAAG,CAAC,SAAS;IACnE;AACF,SAAO;;;;;;;;CASR,MAAM,iBACL,WACuF;EACvF,MAAM,SAAS,MAAM,KAAK,GACxB,WAAW,gBAAgB,CAC3B,WAAW,CACX,OAAO,OAAO,GAAG,GAAG,CAAC,GAAG,MAAM,KAAK,UAAU,EAAE,GAAG,qBAAqB,KAAK,UAAU,CAAC,CAAC,CAAC,CACzF,kBAAkB;AACpB,MAAI,CAAC,OAAQ,QAAO;EAEpB,MAAM,QAAQ,OAAO,qBAAqB,OAAO;AAQjD,SAAO;GACN,kBAAkB;GAClB,eATY,MAAM,KAAK,GACtB,WAAW,gBAAgB,CAC3B,WAAW,CACX,MAAM,qBAAqB,KAAK,MAAM,CACtC,QAAQ,UAAU,MAAM,CACxB,SAAS,EAIS,KAAK,SAAS;IAChC,IAAI,IAAI;IACR,MAAM,IAAI;IACV,QAAQ,IAAI;IACZ,OAAO,IAAI;IACX,WAAW,IAAI;IACf,EAAE;GACH;;;;;;;;;;;CAcF,MAAM,WAAW,QAAgB,QAAgB,OAA+C;EAC/F,IAAI,YAAY,MAAM,aAAa;AACnC,MAAI,MAAM,cAAc,OAQvB,eAPiB,MAAM,KAAK,GAC1B,WAAW,qBAAqB,CAChC,QAAQ,EAAE,SAAS,GAAG,IAAI,aAAa,CAAC,GAAG,MAAM,CAAC,CAClD,MAAM,WAAW,KAAK,OAAO,CAC7B,MAAM,aAAa,MAAM,MAAM,YAAY,KAAK,CAChD,kBAAkB,GAEI,OAAkB,MAAM;EAGjD,MAAM,KAAK,MAAM;AACjB,QAAM,KAAK,GACT,WAAW,qBAAqB,CAChC,OAAO;GACP;GACA,SAAS;GACT,WAAW,MAAM,YAAY;GAC7B,YAAY;GACZ,MAAM,MAAM;GACZ,sBAAsB,MAAM,uBAAuB;GACnD,cAAc,MAAM,eAAe;GACnC,YAAY,MAAM,aAAa;GAC/B,OAAO,MAAM;GACb,YAAY,MAAM,aAAa;GAC/B,QAAQ,MAAM,UAAU;GACxB,aAAa,MAAM,cAAc;GACjC;GACA,mBAAmB;GACnB,CAAC,CACD,SAAS;AAOX,SAAO,cALK,MAAM,KAAK,GACrB,WAAW,qBAAqB,CAChC,WAAW,CACX,MAAM,MAAM,KAAK,GAAG,CACpB,yBAAyB,CACF;;;;;;;CAQ1B,MAAM,WACL,QACA,QACA,OAC2B;AAO3B,MAAI,CANa,MAAM,KAAK,GAC1B,WAAW,qBAAqB,CAChC,OAAO,KAAK,CACZ,MAAM,MAAM,KAAK,OAAO,CACxB,MAAM,WAAW,KAAK,OAAO,CAC7B,kBAAkB,CACL,QAAO;EAEtB,MAAM,SAAkC,EAAE;AAC1C,MAAI,MAAM,UAAU,OAAW,QAAO,QAAQ,MAAM;AACpD,MAAI,MAAM,cAAc,OAAW,QAAO,aAAa,MAAM;AAC7D,MAAI,MAAM,WAAW,OAAW,QAAO,SAAS,MAAM;AACtD,MAAI,MAAM,cAAc,OAAW,QAAO,aAAa,MAAM;AAC7D,MAAI,MAAM,eAAe,OAAW,QAAO,cAAc,MAAM;AAC/D,MAAI,MAAM,aAAa,OAAW,QAAO,YAAY,MAAM;AAC3D,MAAI,MAAM,cAAc,OAAW,QAAO,aAAa,MAAM;AAE7D,MAAI,OAAO,KAAK,OAAO,CAAC,SAAS,EAChC,OAAM,KAAK,GACT,YAAY,qBAAqB,CACjC,IAAI,OAAO,CACX,MAAM,MAAM,KAAK,OAAO,CACxB,SAAS;AAQZ,SAAO,cALK,MAAM,KAAK,GACrB,WAAW,qBAAqB,CAChC,WAAW,CACX,MAAM,MAAM,KAAK,OAAO,CACxB,yBAAyB,CACF;;;CAI1B,MAAM,WAAW,QAAgB,QAAkC;AAMlE,UALe,MAAM,KAAK,GACxB,WAAW,qBAAqB,CAChC,MAAM,MAAM,KAAK,OAAO,CACxB,MAAM,WAAW,KAAK,OAAO,CAC7B,SAAS,EACG,IAAI,mBAAmB;;;;;;;;;CAUtC,MAAM,SACL,QACA,QACA,OACiC;AACjC,QAAM,gBAAgB,KAAK,IAAI,OAAO,QAAQ;AAc7C,OAAI,CALe,MAAM,IACvB,WAAW,gBAAgB,CAC3B,OAAO,KAAK,CACZ,MAAM,MAAM,KAAK,OAAO,CACxB,kBAAkB,CACH,OAAM,IAAI,cAAc,OAAO;AAEhD,SAAM,IAAI,WAAW,qBAAqB,CAAC,MAAM,WAAW,KAAK,OAAO,CAAC,SAAS;GAElF,MAAM,cAAwB,EAAE;AAChC,QAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACtC,MAAM,OAAO,MAAM;AACnB,QAAI,CAAC,KAAM;IACX,MAAM,KAAK,MAAM;IACjB,MAAM,WACL,KAAK,gBAAgB,SAAa,YAAY,KAAK,gBAAgB,OAAQ;AAC5E,UAAM,IACJ,WAAW,qBAAqB,CAChC,OAAO;KACP;KACA,SAAS;KACT,WAAW;KACX,YAAY;KACZ,MAAM,KAAK;KACX,sBAAsB,KAAK,uBAAuB;KAClD,cAAc,KAAK,eAAe;KAClC,YAAY,KAAK,aAAa;KAC9B,OAAO,KAAK;KACZ,YAAY,KAAK,aAAa;KAC9B,QAAQ,KAAK,UAAU;KACvB,aAAa,KAAK,cAAc;KAChC;KACA,CAAC,CACD,SAAS;AACX,gBAAY,KAAK,GAAG;;AAGrB,SAAM,IACJ,YAAY,gBAAgB,CAC5B,IAAI,EAAE,6BAAY,IAAI,MAAM,EAAC,aAAa,EAAE,CAAC,CAC7C,MAAM,MAAM,KAAK,OAAO,CACxB,SAAS;IACV;AAEF,SAAO,EAAE,WAAW,MAAM,QAAQ;;;;;;CAOnC,MAAM,aAAa,QAAgB,OAA2C;AAC7E,SAAO,gBAAgB,KAAK,IAAI,OAAO,QAAQ;AAC9C,QAAK,MAAM,QAAQ,MAClB,OAAM,IACJ,YAAY,qBAAqB,CACjC,IAAI;IAAE,WAAW,KAAK;IAAU,YAAY,KAAK;IAAW,CAAC,CAC7D,MAAM,MAAM,KAAK,KAAK,GAAG,CACzB,MAAM,WAAW,KAAK,OAAO,CAC7B,SAAS;AASZ,WANa,MAAM,IACjB,WAAW,qBAAqB,CAChC,WAAW,CACX,MAAM,WAAW,KAAK,OAAO,CAC7B,QAAQ,cAAc,MAAM,CAC5B,SAAS,EACC,IAAI,cAAc;IAC7B;;;;;;;;;;;;;;;;;;;;;;;;;ACpkBJ,SAAS,yBACR,MACA,SAC2E;AAE3E,QAAO;EACN,SAAS;EACT,OAAO;GACN,MAAM;GACN,SAAS,SAAS,KAAK,gCALH,QAAQ,UAAU,CAK+B,KACpE,KACA,CAAC;GACF;EACD;;;;;;;AAYF,eAAe,YACd,MACA,MACA,SAC6B;CAC7B,MAAM,UAAU,MAAM,KAAK,WAAW,MAAM,QAAQ;AACpD,KAAI,QAAQ,WAAW,EACtB,QAAO;EACN,SAAS;EACT,OAAO;GACN,MAAM;GACN,SAAS,SAAS,KAAK,aAAa,QAAQ,SAAS,eAAe,QAAQ,OAAO,KAAK;GACxF;EACD;AAEF,KAAI,QAAQ,SAAS,EACpB,QAAO;EACN,SAAS;EACT,OAAO,yBACN,MACA,QAAQ,KAAK,MAAM,EAAE,OAAO,CAC5B,CAAC;EACF;AAEF,QAAO;EAAE,SAAS;EAAM,MAAM,QAAQ;EAAI;;;;;AAU3C,eAAsB,eACrB,IACA,UAA+B,EAAE,EACI;AACrC,KAAI;AAGH,SAAO;GAAE,SAAS;GAAM,MADV,MADD,IAAI,eAAe,GAAG,CACV,SAAS,QAAQ;GACL;SAC9B;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAmB,SAAS;IAAyB;GACpE;;;;;;;;AASH,eAAsB,iBACrB,IACA,OAC2B;AAC3B,KAAI;AAMH,MAAI,MAAM,iBAAiB,CAAC,MAAM,OACjC,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM;IACN,SAAS;IACT;GACD;EAGF,MAAM,OAAO,IAAI,eAAe,GAAG;AAInC,MAAI,MAAM,eAET;OAAI,CADW,MAAM,KAAK,SAAS,MAAM,cAAc,CAEtD,QAAO;IACN,SAAS;IACT,OAAO;KAAE,MAAM;KAAa,SAAS;KAAyC;IAC9E;;EAMH,MAAM,kBAAkB,MAAM,UAAU,eAAe,EAAE,iBAAiB;AAC1E,MAAI,MAAM,KAAK,sBAAsB,MAAM,MAAM,gBAAgB,CAChE,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM;IACN,SAAS,SAAS,MAAM,KAAK,kBAC5B,MAAM,SAAS,eAAe,MAAM,OAAO,KAAK;IAEjD;GACD;AAIF,SAAO;GAAE,SAAS;GAAM,MADX,MAAM,KAAK,OAAO,MAAM;GACD;SAC7B;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAqB,SAAS;IAAyB;GACtE;;;;;;;;;;AAWH,eAAsB,cACrB,IACA,MACA,UAA+B,EAAE,EACG;AACpC,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,UAAU,MAAM,KAAK,WAAW,MAAM,QAAQ;AACpD,MAAI,QAAQ,WAAW,EACtB,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAa,SAAS,SAAS,KAAK;IAAc;GACjE;EAEF,MAAM,OAAO,QAAQ;EACrB,MAAM,QAAQ,MAAM,KAAK,UAAU,KAAK,GAAG;AAC3C,SAAO;GAAE,SAAS;GAAM,MAAM;IAAE,GAAG;IAAM;IAAO;GAAE;SAC3C;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAkB,SAAS;IAAwB;GAClE;;;;;;AAiCH,eAAsB,iBACrB,IACA,MACA,OAC2B;AAC3B,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,WAAW,MAAM,YAAY,MAAM,MAAM,EAAE,QAAQ,MAAM,QAAQ,CAAC;AACxE,MAAI,CAAC,SAAS,QAAS,QAAO;EAC9B,MAAM,UAAU,MAAM,KAAK,OAAO,SAAS,KAAK,IAAI,EAAE,OAAO,MAAM,OAAO,CAAC;AAC3E,MAAI,CAAC,QACJ,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAa,SAAS,SAAS,KAAK;IAAc;GACjE;AAEF,SAAO;GAAE,SAAS;GAAM,MAAM;GAAS;SAChC;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAqB,SAAS;IAAyB;GACtE;;;;;;AAOH,eAAsB,iBACrB,IACA,MACA,UAA+B,EAAE,EACO;AACxC,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,WAAW,MAAM,YAAY,MAAM,MAAM,QAAQ;AACvD,MAAI,CAAC,SAAS,QAAS,QAAO;AAC9B,QAAM,KAAK,OAAO,SAAS,KAAK,GAAG;AACnC,SAAO;GAAE,SAAS;GAAM,MAAM,EAAE,SAAS,MAAM;GAAE;SAC1C;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAqB,SAAS;IAAyB;GACtE;;;;;;AAOH,eAAsB,uBACrB,IACA,WAC+C;AAC/C,KAAI;EAEH,MAAM,SAAS,MADF,IAAI,eAAe,GAAG,CACT,iBAAiB,UAAU;AACrD,MAAI,CAAC,OACJ,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAa,SAAS;IAAkB;GACvD;AAEF,SAAO;GAAE,SAAS;GAAM,MAAM;GAAQ;SAC/B;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAA2B,SAAS;IAAoC;GACvF;;;;;;AAeH,eAAsB,qBACrB,IACA,UACA,OACA,UAA+B,EAAE,EACF;AAC/B,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU,QAAQ;AAC3D,MAAI,CAAC,SAAS,QAAS,QAAO;AAG9B,SAAO;GAAE,SAAS;GAAM,MADX,MAAM,KAAK,WAAW,SAAS,KAAK,IAAI,SAAS,KAAK,QAAQ,MAAM;GAC7C;SAC7B;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAA0B,SAAS;IAA8B;GAChF;;;;;;AAOH,eAAsB,qBACrB,IACA,UACA,QACA,OACA,UAA+B,EAAE,EACF;AAC/B,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU,QAAQ;AAC3D,MAAI,CAAC,SAAS,QAAS,QAAO;EAE9B,MAAM,UAAU,MAAM,KAAK,WAAW,SAAS,KAAK,IAAI,QAAQ,MAAM;AACtE,MAAI,CAAC,QACJ,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAa,SAAS;IAAuB;GAC5D;AAEF,SAAO;GAAE,SAAS;GAAM,MAAM;GAAS;SAChC;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAA0B,SAAS;IAA8B;GAChF;;;;;;AAOH,eAAsB,qBACrB,IACA,UACA,QACA,UAA+B,EAAE,EACO;AACxC,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU,QAAQ;AAC3D,MAAI,CAAC,SAAS,QAAS,QAAO;AAG9B,MAAI,CADY,MAAM,KAAK,WAAW,SAAS,KAAK,IAAI,OAAO,CAE9D,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAa,SAAS;IAAuB;GAC5D;AAEF,SAAO;GAAE,SAAS;GAAM,MAAM,EAAE,SAAS,MAAM;GAAE;SAC1C;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAA0B,SAAS;IAA8B;GAChF;;;;;;;;;;AAqBH,eAAsB,mBACrB,IACA,UACA,OACA,UAA+B,EAAE,EACyB;AAK1D,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACtC,MAAM,OAAO,MAAM;AACnB,MAAI,MAAM,gBAAgB,QACzB;OAAI,KAAK,cAAc,KAAK,KAAK,eAAe,EAC/C,QAAO;IACN,SAAS;IACT,OAAO;KACN,MAAM;KACN,SAAS,QAAQ,EAAE,iBAAiB,KAAK,YAAY;KACrD;IACD;;;AAKJ,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU,QAAQ;AAC3D,MAAI,CAAC,SAAS,QAAS,QAAO;EAE9B,MAAM,EAAE,cAAc,MAAM,KAAK,SAAS,SAAS,KAAK,IAAI,SAAS,KAAK,QAAQ,MAAM;AACxF,SAAO;GAAE,SAAS;GAAM,MAAM;IAAE,MAAM;IAAU;IAAW;GAAE;UACrD,OAAO;AAMf,MAAI,iBAAiB,cACpB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM;IACN,SAAS,SAAS,SAAS,aAC1B,QAAQ,SAAS,eAAe,QAAQ,OAAO,KAAK;IAErD;GACD;AAEF,UAAQ,MAAM,uCAAuC,MAAM;AAC3D,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAwB,SAAS;IAA4B;GAC5E;;;;;;AAOH,eAAsB,sBACrB,IACA,UACA,OACA,UAA+B,EAAE,EACA;AACjC,KAAI;EACH,MAAM,OAAO,IAAI,eAAe,GAAG;EACnC,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU,QAAQ;AAC3D,MAAI,CAAC,SAAS,QAAS,QAAO;AAG9B,SAAO;GAAE,SAAS;GAAM,MADR,MAAM,KAAK,aAAa,SAAS,KAAK,IAAI,MAAM;GACzB;SAChC;AACP,SAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM;IAAsB,SAAS;IAAgC;GAC9E"}