emdash 0.40.0 → 0.41.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 (1258) hide show
  1. package/dist/action-token-CbKDcPJi.mjs +26 -0
  2. package/dist/action-token-CbKDcPJi.mjs.map +1 -0
  3. package/dist/activation-PtniBLt9.mjs +382 -0
  4. package/dist/activation-PtniBLt9.mjs.map +1 -0
  5. package/dist/adapters-C_Tf5x90.d.mts +171 -0
  6. package/dist/adapters-C_Tf5x90.d.mts.map +1 -0
  7. package/dist/allowed-origins-U1z4TdEZ.mjs +116 -0
  8. package/dist/allowed-origins-U1z4TdEZ.mjs.map +1 -0
  9. package/dist/api/route-utils.d.mts +4 -4
  10. package/dist/api/route-utils.mjs +46 -45
  11. package/dist/api/route-utils.mjs.map +1 -1
  12. package/dist/api/schemas/index.d.mts +2 -2
  13. package/dist/api/schemas/index.mjs +10 -10
  14. package/dist/api-CXwQkV_m.mjs +5122 -0
  15. package/dist/api-CXwQkV_m.mjs.map +1 -0
  16. package/dist/api-tokens-89WlohEN.mjs +166 -0
  17. package/dist/api-tokens-89WlohEN.mjs.map +1 -0
  18. package/dist/apply-Do3KNnUk.mjs +1659 -0
  19. package/dist/apply-Do3KNnUk.mjs.map +1 -0
  20. package/dist/approvals-CAX9Yw33.mjs +460 -0
  21. package/dist/approvals-CAX9Yw33.mjs.map +1 -0
  22. package/dist/artifact-fetch-B9W4CEST.mjs +659 -0
  23. package/dist/artifact-fetch-B9W4CEST.mjs.map +1 -0
  24. package/dist/astro/index.d.mts +14 -14
  25. package/dist/astro/index.mjs +26 -30
  26. package/dist/astro/index.mjs.map +1 -1
  27. package/dist/astro/middleware/auth.d.mts +12 -12
  28. package/dist/astro/middleware/auth.mjs +10 -10
  29. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  30. package/dist/astro/middleware/redirect.mjs +7 -7
  31. package/dist/astro/middleware/request-context.mjs +3 -3
  32. package/dist/astro/middleware/setup.mjs +1 -1
  33. package/dist/astro/middleware.d.mts +12 -12
  34. package/dist/astro/middleware.d.mts.map +1 -1
  35. package/dist/astro/middleware.mjs +110 -106
  36. package/dist/astro/middleware.mjs.map +1 -1
  37. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +14 -14
  38. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +14 -14
  39. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
  40. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +7 -7
  42. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +17 -17
  43. package/dist/astro/routes/api/admin/byline-fields/index.mjs +17 -17
  44. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +17 -17
  45. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +23 -23
  46. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +23 -23
  47. package/dist/astro/routes/api/admin/bylines/index.mjs +23 -23
  48. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -18
  49. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
  50. package/dist/astro/routes/api/admin/comments/bulk.mjs +17 -17
  51. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
  52. package/dist/astro/routes/api/admin/comments/index.mjs +17 -17
  53. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  54. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  55. package/dist/astro/routes/api/admin/media-usage/activation.mjs +20 -20
  56. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +22 -22
  57. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +22 -22
  58. package/dist/astro/routes/api/admin/media-usage/progress.mjs +25 -25
  59. package/dist/astro/routes/api/admin/media-usage/repair.mjs +31 -31
  60. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +22 -22
  61. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +22 -22
  62. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
  63. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
  64. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +8 -8
  65. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +8 -8
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +72 -68
  67. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +7 -7
  69. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +71 -67
  70. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +72 -68
  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 +82 -78
  74. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/index.mjs +72 -68
  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 +5 -5
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +71 -67
  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 +81 -77
  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 +71 -67
  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 +72 -68
  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 +83 -79
  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 +9 -9
  89. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +74 -70
  90. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +7 -7
  92. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +72 -68
  93. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs +71 -67
  95. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +6 -6
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +71 -67
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  99. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +5 -5
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +71 -67
  101. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +4 -4
  103. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +40 -40
  104. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +40 -40
  105. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +42 -42
  106. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +42 -42
  107. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +42 -42
  108. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +43 -43
  109. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +43 -43
  110. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +42 -42
  111. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +43 -43
  112. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +44 -44
  113. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +42 -42
  114. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +42 -42
  115. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +44 -44
  116. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +42 -42
  117. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +44 -44
  118. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +42 -42
  119. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +42 -42
  120. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +44 -44
  121. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +42 -42
  122. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +42 -42
  123. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +44 -44
  124. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +5 -5
  125. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +4 -4
  126. package/dist/astro/routes/api/admin/users/_id_/index.mjs +15 -15
  127. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
  128. package/dist/astro/routes/api/admin/users/index.mjs +14 -14
  129. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  130. package/dist/astro/routes/api/auth/invite/accept.mjs +4 -4
  131. package/dist/astro/routes/api/auth/invite/complete.mjs +18 -18
  132. package/dist/astro/routes/api/auth/invite/index.mjs +16 -16
  133. package/dist/astro/routes/api/auth/invite/register-options.mjs +17 -17
  134. package/dist/astro/routes/api/auth/logout.mjs +5 -5
  135. package/dist/astro/routes/api/auth/magic-link/send.mjs +18 -18
  136. package/dist/astro/routes/api/auth/magic-link/verify.mjs +14 -14
  137. package/dist/astro/routes/api/auth/me.mjs +15 -15
  138. package/dist/astro/routes/api/auth/mode.mjs +5 -5
  139. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  140. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  141. package/dist/astro/routes/api/auth/passkey/_id_.mjs +14 -14
  142. package/dist/astro/routes/api/auth/passkey/index.mjs +4 -4
  143. package/dist/astro/routes/api/auth/passkey/options.mjs +19 -19
  144. package/dist/astro/routes/api/auth/passkey/register/options.mjs +17 -17
  145. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +18 -18
  146. package/dist/astro/routes/api/auth/passkey/verify.mjs +18 -18
  147. package/dist/astro/routes/api/auth/signup/complete.mjs +18 -18
  148. package/dist/astro/routes/api/auth/signup/request.mjs +17 -17
  149. package/dist/astro/routes/api/auth/signup/verify.mjs +4 -4
  150. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  151. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -18
  152. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +5 -5
  153. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -17
  154. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
  155. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +17 -17
  156. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +5 -5
  157. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +11 -11
  158. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +31 -31
  159. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +17 -17
  160. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +1 -2
  161. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -1
  162. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +42 -53
  163. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  164. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +34 -29
  165. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  166. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
  167. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +5 -5
  168. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +17 -17
  169. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +25 -24
  170. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  171. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +5 -5
  172. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +17 -17
  173. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  174. package/dist/astro/routes/api/content/_collection_/_id_.mjs +18 -18
  175. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  176. package/dist/astro/routes/api/content/_collection_/authors.mjs +5 -5
  177. package/dist/astro/routes/api/content/_collection_/index.mjs +15 -15
  178. package/dist/astro/routes/api/content/_collection_/trash.mjs +15 -15
  179. package/dist/astro/routes/api/dashboard.mjs +10 -9
  180. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  181. package/dist/astro/routes/api/dev/emails.mjs +5 -5
  182. package/dist/astro/routes/api/health.mjs +6 -6
  183. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  184. package/dist/astro/routes/api/import/probe.mjs +23 -23
  185. package/dist/astro/routes/api/import/wordpress/analyze.mjs +6 -6
  186. package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -13
  187. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
  188. package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -12
  189. package/dist/astro/routes/api/import/wordpress/media.mjs +19 -19
  190. package/dist/astro/routes/api/import/wordpress/prepare.mjs +18 -18
  191. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -13
  192. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +28 -28
  193. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  194. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +23 -23
  195. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -13
  196. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +34 -34
  197. package/dist/astro/routes/api/manifest.mjs +6 -6
  198. package/dist/astro/routes/api/mcp.mjs +98 -118
  199. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  200. package/dist/astro/routes/api/media/_id_/confirm.mjs +19 -19
  201. package/dist/astro/routes/api/media/_id_/replace.mjs +16 -16
  202. package/dist/astro/routes/api/media/_id_/upload.mjs +9 -9
  203. package/dist/astro/routes/api/media/_id_/usage.mjs +33 -33
  204. package/dist/astro/routes/api/media/_id_.mjs +31 -31
  205. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +6 -6
  206. package/dist/astro/routes/api/media/file/_...key_.mjs +9 -9
  207. package/dist/astro/routes/api/media/folders/_id_.mjs +16 -16
  208. package/dist/astro/routes/api/media/folders/index.mjs +16 -16
  209. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +5 -5
  210. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +5 -5
  211. package/dist/astro/routes/api/media/providers/index.mjs +5 -5
  212. package/dist/astro/routes/api/media/upload-url.mjs +18 -18
  213. package/dist/astro/routes/api/media.mjs +35 -35
  214. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -17
  215. package/dist/astro/routes/api/menus/_name_/items.mjs +17 -17
  216. package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -17
  217. package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -17
  218. package/dist/astro/routes/api/menus/_name_.mjs +17 -17
  219. package/dist/astro/routes/api/menus/index.mjs +17 -17
  220. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  221. package/dist/astro/routes/api/oauth/device/authorize.d.mts +2 -1
  222. package/dist/astro/routes/api/oauth/device/authorize.d.mts.map +1 -1
  223. package/dist/astro/routes/api/oauth/device/authorize.mjs +23 -9
  224. package/dist/astro/routes/api/oauth/device/authorize.mjs.map +1 -1
  225. package/dist/astro/routes/api/oauth/device/code.mjs +11 -11
  226. package/dist/astro/routes/api/oauth/device/token.mjs +10 -10
  227. package/dist/astro/routes/api/oauth/register.mjs +5 -5
  228. package/dist/astro/routes/api/oauth/token/refresh.mjs +8 -8
  229. package/dist/astro/routes/api/oauth/token/revoke.mjs +8 -8
  230. package/dist/astro/routes/api/oauth/token.mjs +8 -8
  231. package/dist/astro/routes/api/openapi.json.mjs +20 -20
  232. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +11 -11
  233. package/dist/astro/routes/api/redirects/404s/index.mjs +19 -19
  234. package/dist/astro/routes/api/redirects/404s/summary.mjs +19 -19
  235. package/dist/astro/routes/api/redirects/_id_.mjs +19 -19
  236. package/dist/astro/routes/api/redirects/index.mjs +19 -19
  237. package/dist/astro/routes/api/relations/_id_/index.mjs +34 -29
  238. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  239. package/dist/astro/routes/api/relations/index.mjs +36 -31
  240. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  241. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +5 -5
  242. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
  243. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +71 -67
  244. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  245. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +71 -67
  246. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  247. package/dist/astro/routes/api/schema/block-types/index.mjs +71 -67
  248. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  249. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +73 -69
  250. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  251. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +71 -67
  252. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  253. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +71 -67
  254. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  255. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +71 -67
  256. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  257. package/dist/astro/routes/api/schema/collections/index.mjs +71 -67
  258. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  259. package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -67
  260. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  261. package/dist/astro/routes/api/schema/index.mjs +16 -16
  262. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +71 -67
  263. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  264. package/dist/astro/routes/api/schema/orphans/index.mjs +71 -67
  265. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  266. package/dist/astro/routes/api/search/enable.mjs +19 -19
  267. package/dist/astro/routes/api/search/index.mjs +18 -18
  268. package/dist/astro/routes/api/search/rebuild.mjs +19 -19
  269. package/dist/astro/routes/api/search/stats.mjs +9 -9
  270. package/dist/astro/routes/api/search/suggest.mjs +18 -18
  271. package/dist/astro/routes/api/sections/_slug_.mjs +18 -18
  272. package/dist/astro/routes/api/sections/index.mjs +18 -18
  273. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  274. package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
  275. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  276. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  277. package/dist/astro/routes/api/settings/email.mjs +6 -6
  278. package/dist/astro/routes/api/settings.mjs +21 -21
  279. package/dist/astro/routes/api/setup/admin-verify.mjs +19 -19
  280. package/dist/astro/routes/api/setup/admin.mjs +18 -18
  281. package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -39
  282. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  283. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  284. package/dist/astro/routes/api/setup/index.d.mts.map +1 -1
  285. package/dist/astro/routes/api/setup/index.mjs +80 -49
  286. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  287. package/dist/astro/routes/api/setup/status.mjs +6 -6
  288. package/dist/astro/routes/api/snapshot.mjs +9 -9
  289. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  290. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -23
  291. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -23
  292. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -23
  293. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -23
  294. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -22
  295. package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -23
  296. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +36 -35
  297. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
  298. package/dist/astro/routes/api/taxonomies/index.mjs +23 -23
  299. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  300. package/dist/astro/routes/api/typegen.mjs +8 -8
  301. package/dist/astro/routes/api/visual-editing/action-token.mjs +6 -6
  302. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +19 -19
  303. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +4 -4
  304. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  305. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  306. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  307. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +16 -16
  308. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +19 -19
  309. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +19 -19
  310. package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -9
  311. package/dist/astro/routes/api/widget-areas/index.mjs +19 -19
  312. package/dist/astro/routes/api/widget-components.mjs +5 -5
  313. package/dist/astro/routes/robots.txt.mjs +6 -6
  314. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  315. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  316. package/dist/astro/types.d.mts +28 -18
  317. package/dist/astro/types.d.mts.map +1 -1
  318. package/dist/audit-CrgmE9LE.mjs +127 -0
  319. package/dist/audit-CrgmE9LE.mjs.map +1 -0
  320. package/dist/auth/providers/github.d.mts +1 -1
  321. package/dist/auth/providers/google.d.mts +1 -1
  322. package/dist/authoritative-records-C2YzIdbu.mjs +5172 -0
  323. package/dist/authoritative-records-C2YzIdbu.mjs.map +1 -0
  324. package/dist/authorize-WgdKF8QY.mjs +49 -0
  325. package/dist/authorize-WgdKF8QY.mjs.map +1 -0
  326. package/dist/backup-Ck8_lMO3.mjs +246 -0
  327. package/dist/backup-Ck8_lMO3.mjs.map +1 -0
  328. package/dist/block-types-BQ90asVI.mjs +132 -0
  329. package/dist/block-types-BQ90asVI.mjs.map +1 -0
  330. package/dist/block-values-ACFqgB1D.mjs +175 -0
  331. package/dist/block-values-ACFqgB1D.mjs.map +1 -0
  332. package/dist/bundle-Db1iNMv_.mjs +667 -0
  333. package/dist/bundle-Db1iNMv_.mjs.map +1 -0
  334. package/dist/byline-BayaYGoj.mjs +909 -0
  335. package/dist/byline-BayaYGoj.mjs.map +1 -0
  336. package/dist/byline-fields-B8HH-35f.mjs +254 -0
  337. package/dist/byline-fields-B8HH-35f.mjs.map +1 -0
  338. package/dist/byline-fields-hMPjf6Eu.mjs +123 -0
  339. package/dist/byline-fields-hMPjf6Eu.mjs.map +1 -0
  340. package/dist/byline-registry-B_EK_TQf.mjs +406 -0
  341. package/dist/byline-registry-B_EK_TQf.mjs.map +1 -0
  342. package/dist/bylines-DFAaFXWi.mjs +214 -0
  343. package/dist/bylines-DFAaFXWi.mjs.map +1 -0
  344. package/dist/bylines-DkIxUxmr.mjs +232 -0
  345. package/dist/bylines-DkIxUxmr.mjs.map +1 -0
  346. package/dist/cache-DkvhQ8XE.mjs +108 -0
  347. package/dist/cache-DkvhQ8XE.mjs.map +1 -0
  348. package/dist/canonical-CcSuuTlH.mjs +174 -0
  349. package/dist/canonical-CcSuuTlH.mjs.map +1 -0
  350. package/dist/capture-triggers-DJEoOTOq.mjs +362 -0
  351. package/dist/capture-triggers-DJEoOTOq.mjs.map +1 -0
  352. package/dist/challenge-store-CvBl81AQ.mjs +51 -0
  353. package/dist/challenge-store-CvBl81AQ.mjs.map +1 -0
  354. package/dist/checksum-CClweQzI.mjs +162 -0
  355. package/dist/checksum-CClweQzI.mjs.map +1 -0
  356. package/dist/chrome-tags-D5caJwwp.mjs +24 -0
  357. package/dist/chrome-tags-D5caJwwp.mjs.map +1 -0
  358. package/dist/chunks-DwBaj8aT.mjs +25 -0
  359. package/dist/chunks-DwBaj8aT.mjs.map +1 -0
  360. package/dist/cli/index.mjs +374 -761
  361. package/dist/cli/index.mjs.map +1 -1
  362. package/dist/client/cf-access.d.mts +1 -1
  363. package/dist/client/index.d.mts +18 -18
  364. package/dist/client/index.mjs +2 -2
  365. package/dist/collection-deletion-CLCdXsnV.mjs +436 -0
  366. package/dist/collection-deletion-CLCdXsnV.mjs.map +1 -0
  367. package/dist/collection-deletion-processor-hNw8x01F.mjs +217 -0
  368. package/dist/collection-deletion-processor-hNw8x01F.mjs.map +1 -0
  369. package/dist/collection-slugs-cache-CUuiduLq.mjs +85 -0
  370. package/dist/collection-slugs-cache-CUuiduLq.mjs.map +1 -0
  371. package/dist/comment-D2uvL63j.mjs +313 -0
  372. package/dist/comment-D2uvL63j.mjs.map +1 -0
  373. package/dist/comment-reaction-DevUuzg4.mjs +85 -0
  374. package/dist/comment-reaction-DevUuzg4.mjs.map +1 -0
  375. package/dist/comments-Cq0s7_hO.mjs +195 -0
  376. package/dist/comments-Cq0s7_hO.mjs.map +1 -0
  377. package/dist/comments-M4EDYAHw.mjs +99 -0
  378. package/dist/comments-M4EDYAHw.mjs.map +1 -0
  379. package/dist/components-CuIGwXMs.mjs +108 -0
  380. package/dist/components-CuIGwXMs.mjs.map +1 -0
  381. package/dist/config-52Ea5IWt.d.mts +39 -0
  382. package/dist/config-52Ea5IWt.d.mts.map +1 -0
  383. package/dist/config-CCz3xOLc.mjs +242 -0
  384. package/dist/config-CCz3xOLc.mjs.map +1 -0
  385. package/dist/config-D3d5Qudq.d.mts +6669 -0
  386. package/dist/config-D3d5Qudq.d.mts.map +1 -0
  387. package/dist/content-CbnufDsM.mjs +2018 -0
  388. package/dist/content-CbnufDsM.mjs.map +1 -0
  389. package/dist/content-list-query-D_7B1FE5.d.mts +26 -0
  390. package/dist/content-list-query-D_7B1FE5.d.mts.map +1 -0
  391. package/dist/content-policy-CYu6K1KB.mjs +46 -0
  392. package/dist/content-policy-CYu6K1KB.mjs.map +1 -0
  393. package/dist/content-repair-DlDUgFGp.mjs +442 -0
  394. package/dist/content-repair-DlDUgFGp.mjs.map +1 -0
  395. package/dist/context-CGQLA1-a.mjs +1922 -0
  396. package/dist/context-CGQLA1-a.mjs.map +1 -0
  397. package/dist/cron-c4D5C5Fx.mjs +284 -0
  398. package/dist/cron-c4D5C5Fx.mjs.map +1 -0
  399. package/dist/dashboard-CBq9kmOn.mjs +151 -0
  400. package/dist/dashboard-CBq9kmOn.mjs.map +1 -0
  401. package/dist/db/index.d.mts +3 -3
  402. package/dist/db/index.mjs +1 -1
  403. package/dist/db/libsql-migrations.d.mts +1 -1
  404. package/dist/db/libsql-migrations.mjs +4 -4
  405. package/dist/db/libsql.d.mts +1 -1
  406. package/dist/db/postgres-migrations.d.mts +1 -1
  407. package/dist/db/postgres-migrations.mjs +4 -4
  408. package/dist/db/postgres.d.mts +1 -1
  409. package/dist/db/sqlite-migrations.d.mts +1 -1
  410. package/dist/db/sqlite-migrations.mjs +4 -4
  411. package/dist/db/sqlite.d.mts +1 -1
  412. package/dist/db/sqlite.mjs +1 -1
  413. package/dist/default-DPsys51U.mjs +81 -0
  414. package/dist/default-DPsys51U.mjs.map +1 -0
  415. package/dist/deferred-tasks-CZ7rzBdo.d.mts +9 -0
  416. package/dist/deferred-tasks-CZ7rzBdo.d.mts.map +1 -0
  417. package/dist/dev-typegen-HRxwLRcT.mjs +29 -0
  418. package/dist/dev-typegen-HRxwLRcT.mjs.map +1 -0
  419. package/dist/device-flow-OcSqE9uY.mjs +521 -0
  420. package/dist/device-flow-OcSqE9uY.mjs.map +1 -0
  421. package/dist/digest-DVZ--cE9.mjs +194 -0
  422. package/dist/digest-DVZ--cE9.mjs.map +1 -0
  423. package/dist/direct-executor-DyjAqkpT.mjs +104 -0
  424. package/dist/direct-executor-DyjAqkpT.mjs.map +1 -0
  425. package/dist/dist-FPR93_xf.mjs +810 -0
  426. package/dist/dist-FPR93_xf.mjs.map +1 -0
  427. package/dist/email-console-DyQIgEnz.mjs +50 -0
  428. package/dist/email-console-DyQIgEnz.mjs.map +1 -0
  429. package/dist/email-locale-BYb16rVd.mjs +25 -0
  430. package/dist/email-locale-BYb16rVd.mjs.map +1 -0
  431. package/dist/emdash-runtime-CrzxJFmF.mjs +4214 -0
  432. package/dist/emdash-runtime-CrzxJFmF.mjs.map +1 -0
  433. package/dist/enrich-DBtCncE2.mjs +194 -0
  434. package/dist/enrich-DBtCncE2.mjs.map +1 -0
  435. package/dist/entry-lock-BN5y4YbO.d.mts +4481 -0
  436. package/dist/entry-lock-BN5y4YbO.d.mts.map +1 -0
  437. package/dist/entry-lock-BaRBHCsH.mjs +1173 -0
  438. package/dist/entry-lock-BaRBHCsH.mjs.map +1 -0
  439. package/dist/entry-lock-C6NcnZPV.mjs +163 -0
  440. package/dist/entry-lock-C6NcnZPV.mjs.map +1 -0
  441. package/dist/entry-locks-BTyQLdbC.mjs +167 -0
  442. package/dist/entry-locks-BTyQLdbC.mjs.map +1 -0
  443. package/dist/error-BfsNNrIE.mjs +90 -0
  444. package/dist/error-BfsNNrIE.mjs.map +1 -0
  445. package/dist/errors-BN1QAnEY.mjs +460 -0
  446. package/dist/errors-BN1QAnEY.mjs.map +1 -0
  447. package/dist/errors-Bt3goF8I.mjs +120 -0
  448. package/dist/errors-Bt3goF8I.mjs.map +1 -0
  449. package/dist/escape-BveidMa2.mjs +9 -0
  450. package/dist/escape-BveidMa2.mjs.map +1 -0
  451. package/dist/fence-Bb_IbCxI.mjs +162 -0
  452. package/dist/fence-Bb_IbCxI.mjs.map +1 -0
  453. package/dist/field-defs-cache-CsZctvbu.mjs +77 -0
  454. package/dist/field-defs-cache-CsZctvbu.mjs.map +1 -0
  455. package/dist/field-map-6m9rF49t.mjs +83 -0
  456. package/dist/field-map-6m9rF49t.mjs.map +1 -0
  457. package/dist/focal-point-CZ3d1wK5.mjs +23 -0
  458. package/dist/focal-point-CZ3d1wK5.mjs.map +1 -0
  459. package/dist/fts-manager-CCaZTp8y.mjs +443 -0
  460. package/dist/fts-manager-CCaZTp8y.mjs.map +1 -0
  461. package/dist/gc-xowRjczI.mjs +75 -0
  462. package/dist/gc-xowRjczI.mjs.map +1 -0
  463. package/dist/hash-COVK27Pc.mjs +37 -0
  464. package/dist/hash-COVK27Pc.mjs.map +1 -0
  465. package/dist/hook-result-CYSk0XFe.d.mts +31 -0
  466. package/dist/hook-result-CYSk0XFe.d.mts.map +1 -0
  467. package/dist/hreflang-CChPV7jx.mjs +105 -0
  468. package/dist/hreflang-CChPV7jx.mjs.map +1 -0
  469. package/dist/hreflang-DRslq3QI.d.mts +50 -0
  470. package/dist/hreflang-DRslq3QI.d.mts.map +1 -0
  471. package/dist/http-route-dispatch-CAdp2onn.mjs +339 -0
  472. package/dist/http-route-dispatch-CAdp2onn.mjs.map +1 -0
  473. package/dist/identity-NVTOOQyq.mjs +35 -0
  474. package/dist/identity-NVTOOQyq.mjs.map +1 -0
  475. package/dist/import-wpSO2N0x.mjs +2020 -0
  476. package/dist/import-wpSO2N0x.mjs.map +1 -0
  477. package/dist/index-CDs2wq4X.d.mts +623 -0
  478. package/dist/index-CDs2wq4X.d.mts.map +1 -0
  479. package/dist/index.d.mts +24 -24
  480. package/dist/index.mjs +103 -101
  481. package/dist/install-finalization-D9R9R-W8.mjs +58 -0
  482. package/dist/install-finalization-D9R9R-W8.mjs.map +1 -0
  483. package/dist/keys-Bck6LBfF.mjs +61 -0
  484. package/dist/keys-Bck6LBfF.mjs.map +1 -0
  485. package/dist/kinds-CYmRESWj.mjs +974 -0
  486. package/dist/kinds-CYmRESWj.mjs.map +1 -0
  487. package/dist/lifecycle-C815ZQfV.mjs +25 -0
  488. package/dist/lifecycle-C815ZQfV.mjs.map +1 -0
  489. package/dist/load-D99axixL.mjs +28 -0
  490. package/dist/load-D99axixL.mjs.map +1 -0
  491. package/dist/loader-CrRPfkHS.mjs +1197 -0
  492. package/dist/loader-CrRPfkHS.mjs.map +1 -0
  493. package/dist/loops-DMKlygqX.mjs +203 -0
  494. package/dist/loops-DMKlygqX.mjs.map +1 -0
  495. package/dist/manifest-builder-BQzCHNgB.mjs +189 -0
  496. package/dist/manifest-builder-BQzCHNgB.mjs.map +1 -0
  497. package/dist/manifest-schema-Ci2gmd0u.mjs +492 -0
  498. package/dist/manifest-schema-Ci2gmd0u.mjs.map +1 -0
  499. package/dist/media/image-endpoint.mjs +1 -1
  500. package/dist/media/index.d.mts +1 -1
  501. package/dist/media/index.mjs +4 -4
  502. package/dist/media/local-runtime.d.mts +14 -14
  503. package/dist/media/local-runtime.mjs +6 -6
  504. package/dist/media-BUQePMxP.mjs +373 -0
  505. package/dist/media-BUQePMxP.mjs.map +1 -0
  506. package/dist/media-DH8ibNlY.mjs +294 -0
  507. package/dist/media-DH8ibNlY.mjs.map +1 -0
  508. package/dist/media-OEIQ3bVc.mjs +408 -0
  509. package/dist/media-OEIQ3bVc.mjs.map +1 -0
  510. package/dist/media-allowlist-pYtaBA95.mjs +44 -0
  511. package/dist/media-allowlist-pYtaBA95.mjs.map +1 -0
  512. package/dist/media-folders-Bf8_s4de.mjs +210 -0
  513. package/dist/media-folders-Bf8_s4de.mjs.map +1 -0
  514. package/dist/media-url-C6klEuNd.mjs +43 -0
  515. package/dist/media-url-C6klEuNd.mjs.map +1 -0
  516. package/dist/media-usage-D7Y64m6v.mjs +1629 -0
  517. package/dist/media-usage-D7Y64m6v.mjs.map +1 -0
  518. package/dist/media-usage-activation-DrqbmgLA.mjs +78 -0
  519. package/dist/media-usage-activation-DrqbmgLA.mjs.map +1 -0
  520. package/dist/media-usage-work-DommYhYA.mjs +152 -0
  521. package/dist/media-usage-work-DommYhYA.mjs.map +1 -0
  522. package/dist/media-usage-work-HU63hNDu.mjs +586 -0
  523. package/dist/media-usage-work-HU63hNDu.mjs.map +1 -0
  524. package/dist/menus-BQfusWEC.mjs +3608 -0
  525. package/dist/menus-BQfusWEC.mjs.map +1 -0
  526. package/dist/menus-BtwjQt5s.mjs +753 -0
  527. package/dist/menus-BtwjQt5s.mjs.map +1 -0
  528. package/dist/menus-p_M1V7J_.mjs +139 -0
  529. package/dist/menus-p_M1V7J_.mjs.map +1 -0
  530. package/dist/migrations/index.d.mts +1 -1
  531. package/dist/migrations/index.mjs +3 -3
  532. package/dist/mime-C94qBG-P.mjs +36 -0
  533. package/dist/mime-C94qBG-P.mjs.map +1 -0
  534. package/dist/mode-DpYW3w6U.mjs +23 -0
  535. package/dist/mode-DpYW3w6U.mjs.map +1 -0
  536. package/dist/node-sqlite-compat-pWFw0lcc.mjs +46 -0
  537. package/dist/node-sqlite-compat-pWFw0lcc.mjs.map +1 -0
  538. package/dist/normalize-DduyxBjf.mjs +191 -0
  539. package/dist/normalize-DduyxBjf.mjs.map +1 -0
  540. package/dist/oauth-authorization-DAXsH1H9.mjs +274 -0
  541. package/dist/oauth-authorization-DAXsH1H9.mjs.map +1 -0
  542. package/dist/oauth-clients-DENiDQri.mjs +266 -0
  543. package/dist/oauth-clients-DENiDQri.mjs.map +1 -0
  544. package/dist/oauth-state-store-y8mEYVq9.mjs +50 -0
  545. package/dist/oauth-state-store-y8mEYVq9.mjs.map +1 -0
  546. package/dist/oauth-user-lookup-CtTYAy-O.mjs +26 -0
  547. package/dist/oauth-user-lookup-CtTYAy-O.mjs.map +1 -0
  548. package/dist/object-cache/memory.d.mts +1 -1
  549. package/dist/options-BYa1FgIM.d.mts +81 -0
  550. package/dist/options-BYa1FgIM.d.mts.map +1 -0
  551. package/dist/page/index.d.mts +2 -2
  552. package/dist/page/index.mjs +5 -5
  553. package/dist/parse-CORGGhHf.mjs +81 -0
  554. package/dist/parse-CORGGhHf.mjs.map +1 -0
  555. package/dist/parse-avNM1xWV.d.mts +168 -0
  556. package/dist/parse-avNM1xWV.d.mts.map +1 -0
  557. package/dist/passkey-config-Dih5YeIS.mjs +46 -0
  558. package/dist/passkey-config-Dih5YeIS.mjs.map +1 -0
  559. package/dist/paths-d51RFm8M.mjs +77 -0
  560. package/dist/paths-d51RFm8M.mjs.map +1 -0
  561. package/dist/patterns-CoqlXUvk.mjs +145 -0
  562. package/dist/patterns-CoqlXUvk.mjs.map +1 -0
  563. package/dist/placeholder-D2aksPMF.d.mts +306 -0
  564. package/dist/placeholder-D2aksPMF.d.mts.map +1 -0
  565. package/dist/plan-DqeZKuaR.mjs +135 -0
  566. package/dist/plan-DqeZKuaR.mjs.map +1 -0
  567. package/dist/plugin-test-runtime.d.mts +14 -14
  568. package/dist/plugin-test-runtime.mjs +110 -107
  569. package/dist/plugin-types.d.mts +2 -2
  570. package/dist/plugin-utils.d.mts +12 -12
  571. package/dist/plugins/adapt-sandbox-entry.d.mts +12 -12
  572. package/dist/plugins/adapt-sandbox-entry.mjs +3 -3
  573. package/dist/plugins/host.d.mts +5 -5
  574. package/dist/plugins/host.mjs +42 -41
  575. package/dist/plugins-Bb7oqjQA.mjs +277 -0
  576. package/dist/plugins-Bb7oqjQA.mjs.map +1 -0
  577. package/dist/policy-BcEqut3n.mjs +45 -0
  578. package/dist/policy-BcEqut3n.mjs.map +1 -0
  579. package/dist/portable-text-DXE8ymtD.mjs +307 -0
  580. package/dist/portable-text-DXE8ymtD.mjs.map +1 -0
  581. package/dist/preview-DEDWbwA_.mjs +107 -0
  582. package/dist/preview-DEDWbwA_.mjs.map +1 -0
  583. package/dist/protocol-BJbTzvwl.d.mts +61 -0
  584. package/dist/protocol-BJbTzvwl.d.mts.map +1 -0
  585. package/dist/public-submission-D9c9S14m.mjs +250 -0
  586. package/dist/public-submission-D9c9S14m.mjs.map +1 -0
  587. package/dist/public-url-CIRe-2T6.mjs +101 -0
  588. package/dist/public-url-CIRe-2T6.mjs.map +1 -0
  589. package/dist/query-BzifXlPS.mjs +1156 -0
  590. package/dist/query-BzifXlPS.mjs.map +1 -0
  591. package/dist/query-OzMJ6vJP.mjs +41 -0
  592. package/dist/query-OzMJ6vJP.mjs.map +1 -0
  593. package/dist/rate-limit-Csp60Vik.mjs +120 -0
  594. package/dist/rate-limit-Csp60Vik.mjs.map +1 -0
  595. package/dist/receipt-B-aU4hpJ.mjs +43 -0
  596. package/dist/receipt-B-aU4hpJ.mjs.map +1 -0
  597. package/dist/redirect-CDSw1sU3.mjs +17 -0
  598. package/dist/redirect-CDSw1sU3.mjs.map +1 -0
  599. package/dist/redirect-D1ArbO85.mjs +411 -0
  600. package/dist/redirect-D1ArbO85.mjs.map +1 -0
  601. package/dist/redirects-BjTwDTsV.mjs +148 -0
  602. package/dist/redirects-BjTwDTsV.mjs.map +1 -0
  603. package/dist/redirects-Ck50kH3n.mjs +446 -0
  604. package/dist/redirects-Ck50kH3n.mjs.map +1 -0
  605. package/dist/registry/testing.mjs +3 -3
  606. package/dist/registry-CFcNCayZ.mjs +6754 -0
  607. package/dist/registry-CFcNCayZ.mjs.map +1 -0
  608. package/dist/relations-Cfaa1fDl.mjs +776 -0
  609. package/dist/relations-Cfaa1fDl.mjs.map +1 -0
  610. package/dist/request-cache-iHRlHx1d.mjs +104 -0
  611. package/dist/request-cache-iHRlHx1d.mjs.map +1 -0
  612. package/dist/request-context.d.mts +1 -1
  613. package/dist/request-meta-D47mqyev.mjs +141 -0
  614. package/dist/request-meta-D47mqyev.mjs.map +1 -0
  615. package/dist/resolve-BPE8sMvx.mjs +99 -0
  616. package/dist/resolve-BPE8sMvx.mjs.map +1 -0
  617. package/dist/resolve-C0s1E_fH.mjs +199 -0
  618. package/dist/resolve-C0s1E_fH.mjs.map +1 -0
  619. package/dist/revision-j1p4-bOj.mjs +302 -0
  620. package/dist/revision-j1p4-bOj.mjs.map +1 -0
  621. package/dist/route-wire-C9PJV9aL.mjs +197 -0
  622. package/dist/route-wire-C9PJV9aL.mjs.map +1 -0
  623. package/dist/routes-lyYw0mMf.mjs +272 -0
  624. package/dist/routes-lyYw0mMf.mjs.map +1 -0
  625. package/dist/runner-B3eyB9Gb.mjs +6121 -0
  626. package/dist/runner-B3eyB9Gb.mjs.map +1 -0
  627. package/dist/runner-DoYH2Jcu.d.mts +68 -0
  628. package/dist/runner-DoYH2Jcu.d.mts.map +1 -0
  629. package/dist/runtime.d.mts +13 -13
  630. package/dist/runtime.mjs +3 -3
  631. package/dist/schema-BAayK46S.mjs +13 -0
  632. package/dist/schema-BAayK46S.mjs.map +1 -0
  633. package/dist/schema-Gqcl-8G4.mjs +815 -0
  634. package/dist/schema-Gqcl-8G4.mjs.map +1 -0
  635. package/dist/scopes-BqPOKoKf.mjs +34 -0
  636. package/dist/scopes-BqPOKoKf.mjs.map +1 -0
  637. package/dist/search-YJKPIEV6.mjs +448 -0
  638. package/dist/search-YJKPIEV6.mjs.map +1 -0
  639. package/dist/sections-BR_e-wK5.mjs +346 -0
  640. package/dist/sections-BR_e-wK5.mjs.map +1 -0
  641. package/dist/seed/index.d.mts +2 -2
  642. package/dist/seed/index.mjs +37 -31
  643. package/dist/seo/index.d.mts +3 -3
  644. package/dist/seo/index.mjs +22 -21
  645. package/dist/seo/index.mjs.map +1 -1
  646. package/dist/seo-Dsj8hy3j.mjs +114 -0
  647. package/dist/seo-Dsj8hy3j.mjs.map +1 -0
  648. package/dist/seo-XvH4LNNp.mjs +133 -0
  649. package/dist/seo-XvH4LNNp.mjs.map +1 -0
  650. package/dist/service-BsVG05gS.mjs +150 -0
  651. package/dist/service-BsVG05gS.mjs.map +1 -0
  652. package/dist/session-user-DgKbYrlj.mjs +51 -0
  653. package/dist/session-user-DgKbYrlj.mjs.map +1 -0
  654. package/dist/settings-CNPUntkh.mjs +51 -0
  655. package/dist/settings-CNPUntkh.mjs.map +1 -0
  656. package/dist/settings-D5EHi0Tk.mjs +439 -0
  657. package/dist/settings-D5EHi0Tk.mjs.map +1 -0
  658. package/dist/settings-DSfE7wOa.mjs +61 -0
  659. package/dist/settings-DSfE7wOa.mjs.map +1 -0
  660. package/dist/setup-complete-B8W8sJ9v.mjs +26 -0
  661. package/dist/setup-complete-B8W8sJ9v.mjs.map +1 -0
  662. package/dist/setup-nonce-DnSBP260.mjs +25 -0
  663. package/dist/setup-nonce-DnSBP260.mjs.map +1 -0
  664. package/dist/site-settings-NGzdrt7O.mjs +50 -0
  665. package/dist/site-settings-NGzdrt7O.mjs.map +1 -0
  666. package/dist/site-url-D6JB7tLW.mjs +16 -0
  667. package/dist/site-url-D6JB7tLW.mjs.map +1 -0
  668. package/dist/snapshot-CdcwwWAf.mjs +414 -0
  669. package/dist/snapshot-CdcwwWAf.mjs.map +1 -0
  670. package/dist/ssrf-Dv0_tRpo.mjs +406 -0
  671. package/dist/ssrf-Dv0_tRpo.mjs.map +1 -0
  672. package/dist/stage-CUjhED3P.mjs +662 -0
  673. package/dist/stage-CUjhED3P.mjs.map +1 -0
  674. package/dist/staged-C36IWXff.mjs +659 -0
  675. package/dist/staged-C36IWXff.mjs.map +1 -0
  676. package/dist/state-CKouMCSY.mjs +153 -0
  677. package/dist/state-CKouMCSY.mjs.map +1 -0
  678. package/dist/status-lzyj4Uu7.mjs +30 -0
  679. package/dist/status-lzyj4Uu7.mjs.map +1 -0
  680. package/dist/storage/local.d.mts +1 -1
  681. package/dist/storage/local.mjs +1 -1
  682. package/dist/storage/s3.d.mts +1 -1
  683. package/dist/storage/s3.mjs +1 -1
  684. package/dist/storage-query-B-cWcTjJ.d.mts +1594 -0
  685. package/dist/storage-query-B-cWcTjJ.d.mts.map +1 -0
  686. package/dist/tar-DsTXX6ch.mjs +449 -0
  687. package/dist/tar-DsTXX6ch.mjs.map +1 -0
  688. package/dist/target-DLQCwp_Z.mjs +27 -0
  689. package/dist/target-DLQCwp_Z.mjs.map +1 -0
  690. package/dist/taxonomies-BlAjr4BL.mjs +697 -0
  691. package/dist/taxonomies-BlAjr4BL.mjs.map +1 -0
  692. package/dist/taxonomies-Byyo7LOZ.mjs +939 -0
  693. package/dist/taxonomies-Byyo7LOZ.mjs.map +1 -0
  694. package/dist/taxonomy-CKDwM61Y.mjs +525 -0
  695. package/dist/taxonomy-CKDwM61Y.mjs.map +1 -0
  696. package/dist/tokens-BojXlk49.mjs +171 -0
  697. package/dist/tokens-BojXlk49.mjs.map +1 -0
  698. package/dist/transaction-DLPQWik1.mjs +29 -0
  699. package/dist/transaction-DLPQWik1.mjs.map +1 -0
  700. package/dist/transfer-XSTh2BCr.mjs +8706 -0
  701. package/dist/transfer-XSTh2BCr.mjs.map +1 -0
  702. package/dist/transfer-download-DkoCDA9d.mjs +33 -0
  703. package/dist/transfer-download-DkoCDA9d.mjs.map +1 -0
  704. package/dist/transfer-iQ26J-RT.mjs +166 -0
  705. package/dist/transfer-iQ26J-RT.mjs.map +1 -0
  706. package/dist/transformations-C7RQabKQ.mjs +196 -0
  707. package/dist/transformations-C7RQabKQ.mjs.map +1 -0
  708. package/dist/transport-D3RulfD6.mjs +136 -0
  709. package/dist/transport-D3RulfD6.mjs.map +1 -0
  710. package/dist/transport-DhlZlf4D.d.mts +42 -0
  711. package/dist/transport-DhlZlf4D.d.mts.map +1 -0
  712. package/dist/trusted-proxy-B6ECOZJc.mjs +51 -0
  713. package/dist/trusted-proxy-B6ECOZJc.mjs.map +1 -0
  714. package/dist/turnstile-lqUiY7lP.mjs +53 -0
  715. package/dist/turnstile-lqUiY7lP.mjs.map +1 -0
  716. package/dist/types-4Dn9bZhu.mjs +77 -0
  717. package/dist/types-4Dn9bZhu.mjs.map +1 -0
  718. package/dist/types-5LSo7PPx.d.mts +85 -0
  719. package/dist/types-5LSo7PPx.d.mts.map +1 -0
  720. package/dist/types-BQ3hwYJT.d.mts +896 -0
  721. package/dist/types-BQ3hwYJT.d.mts.map +1 -0
  722. package/dist/types-BYEk7qo3.d.mts +198 -0
  723. package/dist/types-BYEk7qo3.d.mts.map +1 -0
  724. package/dist/types-CJKsWVFR.mjs +199 -0
  725. package/dist/types-CJKsWVFR.mjs.map +1 -0
  726. package/dist/types-Ca_w8mmY.d.mts +363 -0
  727. package/dist/types-Ca_w8mmY.d.mts.map +1 -0
  728. package/dist/types-CkE41ZAG.mjs +18 -0
  729. package/dist/types-CkE41ZAG.mjs.map +1 -0
  730. package/dist/types-D0aJW2uR.d.mts +1641 -0
  731. package/dist/types-D0aJW2uR.d.mts.map +1 -0
  732. package/dist/types-DbpN4Qto.d.mts +372 -0
  733. package/dist/types-DbpN4Qto.d.mts.map +1 -0
  734. package/dist/types-ILDI1sdY.mjs +16 -0
  735. package/dist/types-ILDI1sdY.mjs.map +1 -0
  736. package/dist/types-OC5c-edM.mjs +22 -0
  737. package/dist/types-OC5c-edM.mjs.map +1 -0
  738. package/dist/types-aOOxRSx6.mjs +103 -0
  739. package/dist/types-aOOxRSx6.mjs.map +1 -0
  740. package/dist/types-m1WbUffD.d.mts +198 -0
  741. package/dist/types-m1WbUffD.d.mts.map +1 -0
  742. package/dist/types-uxLoPBio.d.mts +124 -0
  743. package/dist/types-uxLoPBio.d.mts.map +1 -0
  744. package/dist/types-we5uR-tV.d.mts +287 -0
  745. package/dist/types-we5uR-tV.d.mts.map +1 -0
  746. package/dist/upload-attempts-DduMy6B0.mjs +32 -0
  747. package/dist/upload-attempts-DduMy6B0.mjs.map +1 -0
  748. package/dist/url-pattern-B3EwxAAk.mjs +33 -0
  749. package/dist/url-pattern-B3EwxAAk.mjs.map +1 -0
  750. package/dist/user-ElwQjTQT.mjs +171 -0
  751. package/dist/user-ElwQjTQT.mjs.map +1 -0
  752. package/dist/utils-BlAXmfOG.mjs +439 -0
  753. package/dist/utils-BlAXmfOG.mjs.map +1 -0
  754. package/dist/validate-CH0X5b2c.d.mts +468 -0
  755. package/dist/validate-CH0X5b2c.d.mts.map +1 -0
  756. package/dist/validate-CfgRpcjA.mjs +492 -0
  757. package/dist/validate-CfgRpcjA.mjs.map +1 -0
  758. package/dist/validation-DvYJtv4k.mjs +218 -0
  759. package/dist/validation-DvYJtv4k.mjs.map +1 -0
  760. package/dist/version-DgYjhTud.mjs +9 -0
  761. package/dist/version-DgYjhTud.mjs.map +1 -0
  762. package/dist/version-Dq71scUb.mjs +7 -0
  763. package/dist/version-Dq71scUb.mjs.map +1 -0
  764. package/dist/widgets-ChFIj0be.mjs +126 -0
  765. package/dist/widgets-ChFIj0be.mjs.map +1 -0
  766. package/dist/wxr-taxonomies-CBZMp2YX.mjs +372 -0
  767. package/dist/wxr-taxonomies-CBZMp2YX.mjs.map +1 -0
  768. package/dist/wxr-taxonomies-DlKDpWN1.d.mts +34 -0
  769. package/dist/wxr-taxonomies-DlKDpWN1.d.mts.map +1 -0
  770. package/dist/zod-generator-DmTKI-Ig.mjs +426 -0
  771. package/dist/zod-generator-DmTKI-Ig.mjs.map +1 -0
  772. package/package.json +7 -6
  773. package/src/api/handlers/content.ts +593 -16
  774. package/src/api/handlers/device-flow.ts +74 -21
  775. package/src/api/handlers/index.ts +1 -0
  776. package/src/api/handlers/manifest.ts +79 -5
  777. package/src/api/handlers/media-upload.ts +17 -71
  778. package/src/api/handlers/media.ts +97 -3
  779. package/src/api/handlers/relations.ts +638 -157
  780. package/src/api/handlers/revision.ts +30 -0
  781. package/src/api/handlers/schema.ts +403 -1
  782. package/src/api/handlers/snapshot.ts +257 -3
  783. package/src/api/handlers/staged-references.ts +142 -0
  784. package/src/api/handlers/validate-references.ts +146 -0
  785. package/src/api/schemas/content.ts +13 -0
  786. package/src/api/schemas/relations.ts +54 -44
  787. package/src/api/schemas/schema.ts +14 -0
  788. package/src/astro/integration/routes.ts +15 -19
  789. package/src/astro/integration/vite-config.ts +10 -4
  790. package/src/astro/middleware.ts +1 -0
  791. package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +11 -54
  792. package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
  793. package/src/astro/routes/api/oauth/device/authorize.ts +33 -4
  794. package/src/astro/routes/api/relations/index.ts +4 -4
  795. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +6 -2
  796. package/src/astro/routes/api/setup/index.ts +66 -23
  797. package/src/astro/routes/api/snapshot.ts +2 -1
  798. package/src/astro/types.ts +10 -0
  799. package/src/cleanup.ts +10 -0
  800. package/src/cli/commands/export-seed.ts +510 -89
  801. package/src/components/Columns.astro +3 -1
  802. package/src/components/Cover.astro +3 -1
  803. package/src/components/WidgetArea.astro +3 -2
  804. package/src/database/migrations/086_relations_structural.ts +197 -0
  805. package/src/database/migrations/087_reference_field_relations.ts +407 -0
  806. package/src/database/migrations/runner.ts +4 -0
  807. package/src/database/reference-backfill.ts +141 -0
  808. package/src/database/repositories/content.ts +43 -8
  809. package/src/database/repositories/media.ts +40 -1
  810. package/src/database/repositories/redirect.ts +17 -34
  811. package/src/database/repositories/relation.ts +620 -208
  812. package/src/database/repositories/revision.ts +16 -0
  813. package/src/database/repositories/types.ts +38 -0
  814. package/src/database/transaction.ts +12 -1
  815. package/src/database/types.ts +14 -5
  816. package/src/emdash-runtime.ts +114 -11
  817. package/src/index.ts +11 -0
  818. package/src/loader.ts +169 -22
  819. package/src/mcp/server.ts +13 -48
  820. package/src/query.ts +455 -25
  821. package/src/references/field-map.ts +115 -0
  822. package/src/references/resolve.ts +160 -0
  823. package/src/references/staged.ts +117 -0
  824. package/src/references/types.ts +16 -0
  825. package/src/registry/artifact-fetch.ts +45 -271
  826. package/src/schema/registry.ts +99 -24
  827. package/src/schema/types.ts +58 -0
  828. package/src/schema/zod-generator.ts +67 -1
  829. package/src/seed/apply.ts +841 -103
  830. package/src/seed/types.ts +36 -2
  831. package/src/seed/validate.ts +78 -2
  832. package/src/transfer/analyze/unique-keys.ts +3 -12
  833. package/src/transfer/analyze/validate.ts +65 -39
  834. package/src/transfer/analyze/values.ts +12 -1
  835. package/src/transfer/export/readers.ts +12 -8
  836. package/src/transfer/format/columns.ts +26 -6
  837. package/src/transfer/format/kinds.ts +21 -5
  838. package/src/transfer/import/context.ts +8 -1
  839. package/src/transfer/ops/package-index.ts +1 -1
  840. package/dist/action-token-DYwe4Pk0.mjs +0 -26
  841. package/dist/action-token-DYwe4Pk0.mjs.map +0 -1
  842. package/dist/activation-LOkDM5WT.mjs +0 -382
  843. package/dist/activation-LOkDM5WT.mjs.map +0 -1
  844. package/dist/adapters-B64LbYcB.d.mts +0 -171
  845. package/dist/adapters-B64LbYcB.d.mts.map +0 -1
  846. package/dist/allowed-origins-CHB8oZNM.mjs +0 -116
  847. package/dist/allowed-origins-CHB8oZNM.mjs.map +0 -1
  848. package/dist/api-cFFZpyS0.mjs +0 -4718
  849. package/dist/api-cFFZpyS0.mjs.map +0 -1
  850. package/dist/api-tokens-s4i4aUp_.mjs +0 -166
  851. package/dist/api-tokens-s4i4aUp_.mjs.map +0 -1
  852. package/dist/apply-CoT603H3.mjs +0 -1163
  853. package/dist/apply-CoT603H3.mjs.map +0 -1
  854. package/dist/approvals-CqMfNxak.mjs +0 -460
  855. package/dist/approvals-CqMfNxak.mjs.map +0 -1
  856. package/dist/artifact-fetch-DZMOGZ3-.mjs +0 -818
  857. package/dist/artifact-fetch-DZMOGZ3-.mjs.map +0 -1
  858. package/dist/astro/routes/api/relations/_id_/translations.d.mts +0 -8
  859. package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +0 -1
  860. package/dist/astro/routes/api/relations/_id_/translations.mjs +0 -47
  861. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +0 -1
  862. package/dist/audit-RfCugiSB.mjs +0 -127
  863. package/dist/audit-RfCugiSB.mjs.map +0 -1
  864. package/dist/authoritative-records-CoJvBXAD.mjs +0 -5172
  865. package/dist/authoritative-records-CoJvBXAD.mjs.map +0 -1
  866. package/dist/authorize-seCifOMJ.mjs +0 -49
  867. package/dist/authorize-seCifOMJ.mjs.map +0 -1
  868. package/dist/backup-CBu0LrXf.mjs +0 -246
  869. package/dist/backup-CBu0LrXf.mjs.map +0 -1
  870. package/dist/block-type-registry-DUI_3KxT.mjs +0 -6709
  871. package/dist/block-type-registry-DUI_3KxT.mjs.map +0 -1
  872. package/dist/block-types-BmZmLmAD.mjs +0 -132
  873. package/dist/block-types-BmZmLmAD.mjs.map +0 -1
  874. package/dist/block-values-C_VIPr5t.mjs +0 -175
  875. package/dist/block-values-C_VIPr5t.mjs.map +0 -1
  876. package/dist/byline-DYmkXqvo.mjs +0 -909
  877. package/dist/byline-DYmkXqvo.mjs.map +0 -1
  878. package/dist/byline-fields-D28AT-Fh.mjs +0 -123
  879. package/dist/byline-fields-D28AT-Fh.mjs.map +0 -1
  880. package/dist/byline-registry-gnKscbQX.mjs +0 -406
  881. package/dist/byline-registry-gnKscbQX.mjs.map +0 -1
  882. package/dist/bylines-BPwJqoYH.mjs +0 -232
  883. package/dist/bylines-BPwJqoYH.mjs.map +0 -1
  884. package/dist/bylines-ukLaYpVZ.mjs +0 -214
  885. package/dist/bylines-ukLaYpVZ.mjs.map +0 -1
  886. package/dist/cache-m7UEkRFV.mjs +0 -108
  887. package/dist/cache-m7UEkRFV.mjs.map +0 -1
  888. package/dist/canonical-YhEQezjg.mjs +0 -174
  889. package/dist/canonical-YhEQezjg.mjs.map +0 -1
  890. package/dist/capture-triggers-kJyl_yyM.mjs +0 -362
  891. package/dist/capture-triggers-kJyl_yyM.mjs.map +0 -1
  892. package/dist/challenge-store-ppU6Uv13.mjs +0 -51
  893. package/dist/challenge-store-ppU6Uv13.mjs.map +0 -1
  894. package/dist/checksum-B2IINIlN.mjs +0 -162
  895. package/dist/checksum-B2IINIlN.mjs.map +0 -1
  896. package/dist/chrome-tags-DApCQSIk.mjs +0 -24
  897. package/dist/chrome-tags-DApCQSIk.mjs.map +0 -1
  898. package/dist/chunks-Dms7Uxbt.mjs +0 -25
  899. package/dist/chunks-Dms7Uxbt.mjs.map +0 -1
  900. package/dist/collection-deletion-BIm28mo3.mjs +0 -436
  901. package/dist/collection-deletion-BIm28mo3.mjs.map +0 -1
  902. package/dist/collection-deletion-processor-Br6rxs3u.mjs +0 -217
  903. package/dist/collection-deletion-processor-Br6rxs3u.mjs.map +0 -1
  904. package/dist/collection-slugs-cache-CjGk__zp.mjs +0 -85
  905. package/dist/collection-slugs-cache-CjGk__zp.mjs.map +0 -1
  906. package/dist/comment-CrBl22OF.mjs +0 -313
  907. package/dist/comment-CrBl22OF.mjs.map +0 -1
  908. package/dist/comment-reaction-JEQ2Fpd8.mjs +0 -85
  909. package/dist/comment-reaction-JEQ2Fpd8.mjs.map +0 -1
  910. package/dist/comments-2ah9du9y.mjs +0 -195
  911. package/dist/comments-2ah9du9y.mjs.map +0 -1
  912. package/dist/comments-fHZ8ON9O.mjs +0 -99
  913. package/dist/comments-fHZ8ON9O.mjs.map +0 -1
  914. package/dist/components-CXbq7CSM.mjs +0 -108
  915. package/dist/components-CXbq7CSM.mjs.map +0 -1
  916. package/dist/config-5ii2haYu.d.mts +0 -6528
  917. package/dist/config-5ii2haYu.d.mts.map +0 -1
  918. package/dist/config-IhybvkIQ.mjs +0 -242
  919. package/dist/config-IhybvkIQ.mjs.map +0 -1
  920. package/dist/config-Py43JK9r.d.mts +0 -39
  921. package/dist/config-Py43JK9r.d.mts.map +0 -1
  922. package/dist/content-DFaIEDj9.mjs +0 -2281
  923. package/dist/content-DFaIEDj9.mjs.map +0 -1
  924. package/dist/content-list-query-Dra4Dalc.d.mts +0 -26
  925. package/dist/content-list-query-Dra4Dalc.d.mts.map +0 -1
  926. package/dist/content-policy-DFNw91-d.mjs +0 -46
  927. package/dist/content-policy-DFNw91-d.mjs.map +0 -1
  928. package/dist/content-repair-Q8IUrpLL.mjs +0 -442
  929. package/dist/content-repair-Q8IUrpLL.mjs.map +0 -1
  930. package/dist/context-BeGccdUX.mjs +0 -1921
  931. package/dist/context-BeGccdUX.mjs.map +0 -1
  932. package/dist/cron-7DCJwPXq.mjs +0 -284
  933. package/dist/cron-7DCJwPXq.mjs.map +0 -1
  934. package/dist/dashboard-DjrB-xxZ.mjs +0 -151
  935. package/dist/dashboard-DjrB-xxZ.mjs.map +0 -1
  936. package/dist/default-DQ6vsviu.mjs +0 -81
  937. package/dist/default-DQ6vsviu.mjs.map +0 -1
  938. package/dist/deferred-tasks-BPxXUB4x.d.mts +0 -9
  939. package/dist/deferred-tasks-BPxXUB4x.d.mts.map +0 -1
  940. package/dist/dev-typegen-CZaPLl3V.mjs +0 -29
  941. package/dist/dev-typegen-CZaPLl3V.mjs.map +0 -1
  942. package/dist/device-flow-CRd6DXmW.mjs +0 -466
  943. package/dist/device-flow-CRd6DXmW.mjs.map +0 -1
  944. package/dist/digest-BarSh-pN.mjs +0 -194
  945. package/dist/digest-BarSh-pN.mjs.map +0 -1
  946. package/dist/direct-executor-BmuFJJZV.mjs +0 -104
  947. package/dist/direct-executor-BmuFJJZV.mjs.map +0 -1
  948. package/dist/dist-BNwANFJR.mjs +0 -810
  949. package/dist/dist-BNwANFJR.mjs.map +0 -1
  950. package/dist/email-console-bJn3ctqA.mjs +0 -50
  951. package/dist/email-console-bJn3ctqA.mjs.map +0 -1
  952. package/dist/email-locale-CN6WAMx0.mjs +0 -25
  953. package/dist/email-locale-CN6WAMx0.mjs.map +0 -1
  954. package/dist/emdash-runtime-DAjghyEG.mjs +0 -4186
  955. package/dist/emdash-runtime-DAjghyEG.mjs.map +0 -1
  956. package/dist/enrich-Dl3kZ-lP.mjs +0 -194
  957. package/dist/enrich-Dl3kZ-lP.mjs.map +0 -1
  958. package/dist/entry-lock-BJYdBfXb.mjs +0 -1097
  959. package/dist/entry-lock-BJYdBfXb.mjs.map +0 -1
  960. package/dist/entry-lock-DHQOxN7R.mjs +0 -163
  961. package/dist/entry-lock-DHQOxN7R.mjs.map +0 -1
  962. package/dist/entry-lock-DVhCt49A.d.mts +0 -4368
  963. package/dist/entry-lock-DVhCt49A.d.mts.map +0 -1
  964. package/dist/entry-locks-D0foLdjQ.mjs +0 -167
  965. package/dist/entry-locks-D0foLdjQ.mjs.map +0 -1
  966. package/dist/error-CfvOHP0M.mjs +0 -90
  967. package/dist/error-CfvOHP0M.mjs.map +0 -1
  968. package/dist/errors-BF0_LFhW.mjs +0 -460
  969. package/dist/errors-BF0_LFhW.mjs.map +0 -1
  970. package/dist/errors-DgE1zJGG.mjs +0 -120
  971. package/dist/errors-DgE1zJGG.mjs.map +0 -1
  972. package/dist/escape-CuaZhZvL.mjs +0 -9
  973. package/dist/escape-CuaZhZvL.mjs.map +0 -1
  974. package/dist/fence-CMDXJYc_.mjs +0 -162
  975. package/dist/fence-CMDXJYc_.mjs.map +0 -1
  976. package/dist/field-defs-cache-HIgBbqZZ.mjs +0 -77
  977. package/dist/field-defs-cache-HIgBbqZZ.mjs.map +0 -1
  978. package/dist/focal-point-Gr34o-4o.mjs +0 -23
  979. package/dist/focal-point-Gr34o-4o.mjs.map +0 -1
  980. package/dist/fts-manager-S-K0laoS.mjs +0 -443
  981. package/dist/fts-manager-S-K0laoS.mjs.map +0 -1
  982. package/dist/gc-DjKY0Ay1.mjs +0 -75
  983. package/dist/gc-DjKY0Ay1.mjs.map +0 -1
  984. package/dist/hash-SDAW6zC-.mjs +0 -37
  985. package/dist/hash-SDAW6zC-.mjs.map +0 -1
  986. package/dist/hook-result-B5bXDgS2.d.mts +0 -31
  987. package/dist/hook-result-B5bXDgS2.d.mts.map +0 -1
  988. package/dist/hreflang-D5uNnsGJ.d.mts +0 -50
  989. package/dist/hreflang-D5uNnsGJ.d.mts.map +0 -1
  990. package/dist/hreflang-DMFBL2eb.mjs +0 -105
  991. package/dist/hreflang-DMFBL2eb.mjs.map +0 -1
  992. package/dist/http-route-dispatch-BitqzwMy.mjs +0 -339
  993. package/dist/http-route-dispatch-BitqzwMy.mjs.map +0 -1
  994. package/dist/identity-IyNWwXr6.mjs +0 -35
  995. package/dist/identity-IyNWwXr6.mjs.map +0 -1
  996. package/dist/import-C3JZplWq.mjs +0 -2020
  997. package/dist/import-C3JZplWq.mjs.map +0 -1
  998. package/dist/index-D-hdtLe8.d.mts +0 -623
  999. package/dist/index-D-hdtLe8.d.mts.map +0 -1
  1000. package/dist/install-finalization-DfM1fj5x.mjs +0 -58
  1001. package/dist/install-finalization-DfM1fj5x.mjs.map +0 -1
  1002. package/dist/keys-yxLm5l35.mjs +0 -61
  1003. package/dist/keys-yxLm5l35.mjs.map +0 -1
  1004. package/dist/kinds-CRu_T5T5.mjs +0 -961
  1005. package/dist/kinds-CRu_T5T5.mjs.map +0 -1
  1006. package/dist/lifecycle-BzeGPeQ-.mjs +0 -25
  1007. package/dist/lifecycle-BzeGPeQ-.mjs.map +0 -1
  1008. package/dist/load-XgJiE6_3.mjs +0 -28
  1009. package/dist/load-XgJiE6_3.mjs.map +0 -1
  1010. package/dist/loader-BzqeR1ZN.mjs +0 -1086
  1011. package/dist/loader-BzqeR1ZN.mjs.map +0 -1
  1012. package/dist/loops-BQSzv5Zn.mjs +0 -203
  1013. package/dist/loops-BQSzv5Zn.mjs.map +0 -1
  1014. package/dist/manifest-builder-B8zR-73J.mjs +0 -189
  1015. package/dist/manifest-builder-B8zR-73J.mjs.map +0 -1
  1016. package/dist/manifest-schema-CY3zng_M.mjs +0 -492
  1017. package/dist/manifest-schema-CY3zng_M.mjs.map +0 -1
  1018. package/dist/media-Pu1L6xir.mjs +0 -408
  1019. package/dist/media-Pu1L6xir.mjs.map +0 -1
  1020. package/dist/media-Qp5S3eH3.mjs +0 -355
  1021. package/dist/media-Qp5S3eH3.mjs.map +0 -1
  1022. package/dist/media-allowlist-BSoa9Vvm.mjs +0 -44
  1023. package/dist/media-allowlist-BSoa9Vvm.mjs.map +0 -1
  1024. package/dist/media-folders-BE0oo2eX.mjs +0 -210
  1025. package/dist/media-folders-BE0oo2eX.mjs.map +0 -1
  1026. package/dist/media-h7tOiDLj.mjs +0 -221
  1027. package/dist/media-h7tOiDLj.mjs.map +0 -1
  1028. package/dist/media-url-jArBpzIG.mjs +0 -43
  1029. package/dist/media-url-jArBpzIG.mjs.map +0 -1
  1030. package/dist/media-usage-My-Vi-ex.mjs +0 -1629
  1031. package/dist/media-usage-My-Vi-ex.mjs.map +0 -1
  1032. package/dist/media-usage-activation-HKp7zk7W.mjs +0 -78
  1033. package/dist/media-usage-activation-HKp7zk7W.mjs.map +0 -1
  1034. package/dist/media-usage-work-C2OZLCAd.mjs +0 -586
  1035. package/dist/media-usage-work-C2OZLCAd.mjs.map +0 -1
  1036. package/dist/media-usage-work-DwUNbgvS.mjs +0 -152
  1037. package/dist/media-usage-work-DwUNbgvS.mjs.map +0 -1
  1038. package/dist/menus-BM7BPLOb.mjs +0 -139
  1039. package/dist/menus-BM7BPLOb.mjs.map +0 -1
  1040. package/dist/menus-ITeAbcIF.mjs +0 -753
  1041. package/dist/menus-ITeAbcIF.mjs.map +0 -1
  1042. package/dist/menus-TsSGmSR4.mjs +0 -3608
  1043. package/dist/menus-TsSGmSR4.mjs.map +0 -1
  1044. package/dist/mime-ChLqYwDk.mjs +0 -36
  1045. package/dist/mime-ChLqYwDk.mjs.map +0 -1
  1046. package/dist/mode-CCuKXUci.mjs +0 -23
  1047. package/dist/mode-CCuKXUci.mjs.map +0 -1
  1048. package/dist/node-sqlite-compat-CONMsl-x.mjs +0 -46
  1049. package/dist/node-sqlite-compat-CONMsl-x.mjs.map +0 -1
  1050. package/dist/normalize-CO2P8-iE.mjs +0 -191
  1051. package/dist/normalize-CO2P8-iE.mjs.map +0 -1
  1052. package/dist/oauth-authorization-DlMIL5_h.mjs +0 -274
  1053. package/dist/oauth-authorization-DlMIL5_h.mjs.map +0 -1
  1054. package/dist/oauth-clients-Djq9r_KP.mjs +0 -266
  1055. package/dist/oauth-clients-Djq9r_KP.mjs.map +0 -1
  1056. package/dist/oauth-state-store-BbjnZXNC.mjs +0 -50
  1057. package/dist/oauth-state-store-BbjnZXNC.mjs.map +0 -1
  1058. package/dist/oauth-user-lookup-vue9a64A.mjs +0 -26
  1059. package/dist/oauth-user-lookup-vue9a64A.mjs.map +0 -1
  1060. package/dist/options-SQCHQCPH.d.mts +0 -81
  1061. package/dist/options-SQCHQCPH.d.mts.map +0 -1
  1062. package/dist/parse-CVgO-Qai.d.mts +0 -168
  1063. package/dist/parse-CVgO-Qai.d.mts.map +0 -1
  1064. package/dist/parse-DY6OD1j_.mjs +0 -81
  1065. package/dist/parse-DY6OD1j_.mjs.map +0 -1
  1066. package/dist/passkey-config-X_H8128a.mjs +0 -46
  1067. package/dist/passkey-config-X_H8128a.mjs.map +0 -1
  1068. package/dist/paths-JxokKIbr.mjs +0 -77
  1069. package/dist/paths-JxokKIbr.mjs.map +0 -1
  1070. package/dist/patterns-BhAvqO0S.mjs +0 -145
  1071. package/dist/patterns-BhAvqO0S.mjs.map +0 -1
  1072. package/dist/placeholder-MSEd8gty.d.mts +0 -306
  1073. package/dist/placeholder-MSEd8gty.d.mts.map +0 -1
  1074. package/dist/plan-xjcWrAah.mjs +0 -135
  1075. package/dist/plan-xjcWrAah.mjs.map +0 -1
  1076. package/dist/plugins-DUXUt8B9.mjs +0 -277
  1077. package/dist/plugins-DUXUt8B9.mjs.map +0 -1
  1078. package/dist/policy-CUvwAARc.mjs +0 -45
  1079. package/dist/policy-CUvwAARc.mjs.map +0 -1
  1080. package/dist/portable-text-5O_ZGUjB.mjs +0 -307
  1081. package/dist/portable-text-5O_ZGUjB.mjs.map +0 -1
  1082. package/dist/preview-CIUcPYr6.mjs +0 -107
  1083. package/dist/preview-CIUcPYr6.mjs.map +0 -1
  1084. package/dist/protocol-B97DZaFr.d.mts +0 -61
  1085. package/dist/protocol-B97DZaFr.d.mts.map +0 -1
  1086. package/dist/public-submission-BFBUrqst.mjs +0 -250
  1087. package/dist/public-submission-BFBUrqst.mjs.map +0 -1
  1088. package/dist/public-url-Bn7U0D7-.mjs +0 -101
  1089. package/dist/public-url-Bn7U0D7-.mjs.map +0 -1
  1090. package/dist/query-B48peoRT.mjs +0 -890
  1091. package/dist/query-B48peoRT.mjs.map +0 -1
  1092. package/dist/query-C4IH0uhR.mjs +0 -41
  1093. package/dist/query-C4IH0uhR.mjs.map +0 -1
  1094. package/dist/rate-limit-BZ6nybgc.mjs +0 -120
  1095. package/dist/rate-limit-BZ6nybgc.mjs.map +0 -1
  1096. package/dist/receipt-B4wJj5Jq.mjs +0 -43
  1097. package/dist/receipt-B4wJj5Jq.mjs.map +0 -1
  1098. package/dist/redirect-Cd1E7VUt.mjs +0 -17
  1099. package/dist/redirect-Cd1E7VUt.mjs.map +0 -1
  1100. package/dist/redirect-iJf5fltD.mjs +0 -415
  1101. package/dist/redirect-iJf5fltD.mjs.map +0 -1
  1102. package/dist/redirects-CYu1u1aK.mjs +0 -446
  1103. package/dist/redirects-CYu1u1aK.mjs.map +0 -1
  1104. package/dist/redirects-Cv9apQKj.mjs +0 -148
  1105. package/dist/redirects-Cv9apQKj.mjs.map +0 -1
  1106. package/dist/relation-M4NUCb0b.mjs +0 -334
  1107. package/dist/relation-M4NUCb0b.mjs.map +0 -1
  1108. package/dist/relations-CCif47Oq.mjs +0 -403
  1109. package/dist/relations-CCif47Oq.mjs.map +0 -1
  1110. package/dist/relations-CK9CYUyr.mjs +0 -310
  1111. package/dist/relations-CK9CYUyr.mjs.map +0 -1
  1112. package/dist/request-cache-DzLYKm_x.mjs +0 -104
  1113. package/dist/request-cache-DzLYKm_x.mjs.map +0 -1
  1114. package/dist/request-meta-sZXt3sRo.mjs +0 -141
  1115. package/dist/request-meta-sZXt3sRo.mjs.map +0 -1
  1116. package/dist/resolve-2WbQsCvT.mjs +0 -199
  1117. package/dist/resolve-2WbQsCvT.mjs.map +0 -1
  1118. package/dist/route-wire--1hLuACz.mjs +0 -197
  1119. package/dist/route-wire--1hLuACz.mjs.map +0 -1
  1120. package/dist/routes-CUsM40Cc.mjs +0 -272
  1121. package/dist/routes-CUsM40Cc.mjs.map +0 -1
  1122. package/dist/runner-1y4J9fJB.mjs +0 -5742
  1123. package/dist/runner-1y4J9fJB.mjs.map +0 -1
  1124. package/dist/runner-D5_LzKXI.d.mts +0 -68
  1125. package/dist/runner-D5_LzKXI.d.mts.map +0 -1
  1126. package/dist/schema-BABiRdsH.mjs +0 -13
  1127. package/dist/schema-BABiRdsH.mjs.map +0 -1
  1128. package/dist/schema-Du3MzCG0.mjs +0 -446
  1129. package/dist/schema-Du3MzCG0.mjs.map +0 -1
  1130. package/dist/scopes-Dbk-ElhT.mjs +0 -34
  1131. package/dist/scopes-Dbk-ElhT.mjs.map +0 -1
  1132. package/dist/search-Bt1PL1jf.mjs +0 -448
  1133. package/dist/search-Bt1PL1jf.mjs.map +0 -1
  1134. package/dist/sections-Ddptx_o9.mjs +0 -346
  1135. package/dist/sections-Ddptx_o9.mjs.map +0 -1
  1136. package/dist/seo-CZT2oLtT.mjs +0 -114
  1137. package/dist/seo-CZT2oLtT.mjs.map +0 -1
  1138. package/dist/seo-D5w3-Azy.mjs +0 -133
  1139. package/dist/seo-D5w3-Azy.mjs.map +0 -1
  1140. package/dist/service-DuykXPyW.mjs +0 -150
  1141. package/dist/service-DuykXPyW.mjs.map +0 -1
  1142. package/dist/session-user-BhaVp8w0.mjs +0 -51
  1143. package/dist/session-user-BhaVp8w0.mjs.map +0 -1
  1144. package/dist/settings-2xNYr90o.mjs +0 -51
  1145. package/dist/settings-2xNYr90o.mjs.map +0 -1
  1146. package/dist/settings-CgjRWGW9.mjs +0 -439
  1147. package/dist/settings-CgjRWGW9.mjs.map +0 -1
  1148. package/dist/settings-DYidIB26.mjs +0 -61
  1149. package/dist/settings-DYidIB26.mjs.map +0 -1
  1150. package/dist/setup-complete-bOogcHWG.mjs +0 -26
  1151. package/dist/setup-complete-bOogcHWG.mjs.map +0 -1
  1152. package/dist/setup-nonce-0EGuKM4s.mjs +0 -25
  1153. package/dist/setup-nonce-0EGuKM4s.mjs.map +0 -1
  1154. package/dist/site-settings-DOgRUoFX.mjs +0 -50
  1155. package/dist/site-settings-DOgRUoFX.mjs.map +0 -1
  1156. package/dist/site-url-BU_bbxwj.mjs +0 -16
  1157. package/dist/site-url-BU_bbxwj.mjs.map +0 -1
  1158. package/dist/snapshot-CugwUqKQ.mjs +0 -237
  1159. package/dist/snapshot-CugwUqKQ.mjs.map +0 -1
  1160. package/dist/ssrf-CJUnJymJ.mjs +0 -406
  1161. package/dist/ssrf-CJUnJymJ.mjs.map +0 -1
  1162. package/dist/stage-DgrBz_du.mjs +0 -662
  1163. package/dist/stage-DgrBz_du.mjs.map +0 -1
  1164. package/dist/state-DDiPySSG.mjs +0 -153
  1165. package/dist/state-DDiPySSG.mjs.map +0 -1
  1166. package/dist/status-DZKIG4a9.mjs +0 -30
  1167. package/dist/status-DZKIG4a9.mjs.map +0 -1
  1168. package/dist/storage-query-Bdv7A62k.d.mts +0 -1576
  1169. package/dist/storage-query-Bdv7A62k.d.mts.map +0 -1
  1170. package/dist/tar-_1AgTYFu.mjs +0 -449
  1171. package/dist/tar-_1AgTYFu.mjs.map +0 -1
  1172. package/dist/target-_7pn2Gbg.mjs +0 -27
  1173. package/dist/target-_7pn2Gbg.mjs.map +0 -1
  1174. package/dist/taxonomies-C1IwNe8Q.mjs +0 -697
  1175. package/dist/taxonomies-C1IwNe8Q.mjs.map +0 -1
  1176. package/dist/taxonomies-C_XMoRcX.mjs +0 -939
  1177. package/dist/taxonomies-C_XMoRcX.mjs.map +0 -1
  1178. package/dist/taxonomy-C3Fu1YeH.mjs +0 -525
  1179. package/dist/taxonomy-C3Fu1YeH.mjs.map +0 -1
  1180. package/dist/tokens-u78jETkX.mjs +0 -171
  1181. package/dist/tokens-u78jETkX.mjs.map +0 -1
  1182. package/dist/transaction-BcJO4Tmc.mjs +0 -29
  1183. package/dist/transaction-BcJO4Tmc.mjs.map +0 -1
  1184. package/dist/transfer-BhUCrgDc.mjs +0 -8675
  1185. package/dist/transfer-BhUCrgDc.mjs.map +0 -1
  1186. package/dist/transfer-DIGvR9Af.mjs +0 -166
  1187. package/dist/transfer-DIGvR9Af.mjs.map +0 -1
  1188. package/dist/transfer-download-Pml7RMio.mjs +0 -33
  1189. package/dist/transfer-download-Pml7RMio.mjs.map +0 -1
  1190. package/dist/transformations-9gfpwY65.mjs +0 -196
  1191. package/dist/transformations-9gfpwY65.mjs.map +0 -1
  1192. package/dist/transport-BIfH7_hx.d.mts +0 -42
  1193. package/dist/transport-BIfH7_hx.d.mts.map +0 -1
  1194. package/dist/transport-DKWIq53q.mjs +0 -136
  1195. package/dist/transport-DKWIq53q.mjs.map +0 -1
  1196. package/dist/trusted-proxy-tKiVtyTD.mjs +0 -51
  1197. package/dist/trusted-proxy-tKiVtyTD.mjs.map +0 -1
  1198. package/dist/turnstile-DpsoyOfg.mjs +0 -53
  1199. package/dist/turnstile-DpsoyOfg.mjs.map +0 -1
  1200. package/dist/types-B4sUC2p1.d.mts +0 -198
  1201. package/dist/types-B4sUC2p1.d.mts.map +0 -1
  1202. package/dist/types-B7Lmsh1E.d.mts +0 -887
  1203. package/dist/types-B7Lmsh1E.d.mts.map +0 -1
  1204. package/dist/types-BZakh7Ym.mjs +0 -22
  1205. package/dist/types-BZakh7Ym.mjs.map +0 -1
  1206. package/dist/types-B_CppEmv.d.mts +0 -264
  1207. package/dist/types-B_CppEmv.d.mts.map +0 -1
  1208. package/dist/types-BcrBrE6-.mjs +0 -159
  1209. package/dist/types-BcrBrE6-.mjs.map +0 -1
  1210. package/dist/types-BkUg2yHx.mjs +0 -92
  1211. package/dist/types-BkUg2yHx.mjs.map +0 -1
  1212. package/dist/types-CAZgq9fO.d.mts +0 -124
  1213. package/dist/types-CAZgq9fO.d.mts.map +0 -1
  1214. package/dist/types-Cd-O03VG.d.mts +0 -363
  1215. package/dist/types-Cd-O03VG.d.mts.map +0 -1
  1216. package/dist/types-Cr-Kg-3D.d.mts +0 -1641
  1217. package/dist/types-Cr-Kg-3D.d.mts.map +0 -1
  1218. package/dist/types-D2fvWd1i.d.mts +0 -359
  1219. package/dist/types-D2fvWd1i.d.mts.map +0 -1
  1220. package/dist/types-D7HUsguf.mjs +0 -77
  1221. package/dist/types-D7HUsguf.mjs.map +0 -1
  1222. package/dist/types-DA1Te3Oy.d.mts +0 -198
  1223. package/dist/types-DA1Te3Oy.d.mts.map +0 -1
  1224. package/dist/types-DhV6Q5bP.mjs +0 -18
  1225. package/dist/types-DhV6Q5bP.mjs.map +0 -1
  1226. package/dist/types-DnnVSl6Y.d.mts +0 -85
  1227. package/dist/types-DnnVSl6Y.d.mts.map +0 -1
  1228. package/dist/types-VT4-BugW.mjs +0 -16
  1229. package/dist/types-VT4-BugW.mjs.map +0 -1
  1230. package/dist/upload-attempts-B68ZGNu9.mjs +0 -32
  1231. package/dist/upload-attempts-B68ZGNu9.mjs.map +0 -1
  1232. package/dist/url-pattern-CCeZMGOh.mjs +0 -33
  1233. package/dist/url-pattern-CCeZMGOh.mjs.map +0 -1
  1234. package/dist/user-DDSL-sGw.mjs +0 -171
  1235. package/dist/user-DDSL-sGw.mjs.map +0 -1
  1236. package/dist/utils-DdhmO9w9.mjs +0 -439
  1237. package/dist/utils-DdhmO9w9.mjs.map +0 -1
  1238. package/dist/validate-CHosPEhs.mjs +0 -453
  1239. package/dist/validate-CHosPEhs.mjs.map +0 -1
  1240. package/dist/validate-CM79QXYE.d.mts +0 -432
  1241. package/dist/validate-CM79QXYE.d.mts.map +0 -1
  1242. package/dist/validation-BFecQczG.mjs +0 -218
  1243. package/dist/validation-BFecQczG.mjs.map +0 -1
  1244. package/dist/version-BRZXVifl.mjs +0 -9
  1245. package/dist/version-BRZXVifl.mjs.map +0 -1
  1246. package/dist/version-DUQDHgrf.mjs +0 -7
  1247. package/dist/version-DUQDHgrf.mjs.map +0 -1
  1248. package/dist/widgets-WdV72brA.mjs +0 -126
  1249. package/dist/widgets-WdV72brA.mjs.map +0 -1
  1250. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts +0 -34
  1251. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts.map +0 -1
  1252. package/dist/wxr-taxonomies-DP6ESgMN.mjs +0 -372
  1253. package/dist/wxr-taxonomies-DP6ESgMN.mjs.map +0 -1
  1254. package/dist/zod-generator-D6uE4WiS.mjs +0 -389
  1255. package/dist/zod-generator-D6uE4WiS.mjs.map +0 -1
  1256. package/src/astro/routes/api/relations/[id]/translations.ts +0 -33
  1257. /package/dist/{api-tokens-CE1ECIg0.mjs → api-tokens-FaG1zPsj.mjs} +0 -0
  1258. /package/dist/{ssrf-DpBH7aOt.mjs → ssrf-DZOt8Qof.mjs} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"context-BeGccdUX.mjs","names":[],"sources":["../src/plugins/storage-query.ts","../src/plugins/storage-update.ts","../src/database/repositories/plugin-storage.ts","../src/plugins/content-access.ts","../src/plugins/media.ts","../src/plugins/route-error.ts","../src/plugins/context.ts"],"sourcesContent":["/**\n * Plugin Storage Query Validation and Building\n *\n * Validates that queries only use indexed fields and builds SQL WHERE clauses.\n *\n * @see PLUGIN-SYSTEM.md § Plugin Storage > Query Validation\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { pluginDataExtractExpr, pluginDataOrderExpr } from \"../database/dialect-helpers.js\";\nimport type { WhereClause, WhereValue, RangeFilter, InFilter, StartsWithFilter } from \"./types.js\";\n\n/**\n * Error thrown when querying non-indexed fields\n */\nexport class StorageQueryError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic field?: string,\n\t\tpublic suggestion?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"StorageQueryError\";\n\t}\n}\n\n/**\n * Error thrown when a guarded `updateIf` loses a concurrent race by aborting\n * rather than resolving to `{ applied: false }`.\n *\n * `updateIf`'s `{ applied: false }` contract (row absent OR guard failed)\n * assumes READ COMMITTED — the default. There, a losing concurrent writer\n * re-evaluates the guard against the winner's freshly committed row and\n * cleanly resolves to `{ applied: false }`. Two aborts escape that contract:\n *\n * - `40001` (serialization_failure), only above READ COMMITTED, where the\n * loser cannot re-read against a newer snapshot.\n * - `40P01` (deadlock_detected), at any isolation level, when transactions\n * take row locks in opposite order.\n *\n * This error surfaces either abort so the caller can retry the write.\n *\n * The no-oversell SAFETY invariant holds either way: a losing writer NEVER\n * applies its update — it either sees `{ applied: false }` or throws here.\n */\nexport class StorageSerializationError extends Error {\n\treadonly code = \"STORAGE_SERIALIZATION_FAILURE\";\n\treadonly retryable = true;\n\t/** The Postgres SQLSTATE that triggered this error (`40001` / `40P01`). */\n\treadonly sqlState?: string;\n\n\tconstructor(message: string, options?: { cause?: unknown; sqlState?: string }) {\n\t\tsuper(message, { cause: options?.cause });\n\t\tthis.name = \"StorageSerializationError\";\n\t\tthis.sqlState = options?.sqlState;\n\t}\n}\n\n/**\n * Check if a value is a range filter\n */\nexport function isRangeFilter(value: WhereValue): value is RangeFilter {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn \"gt\" in value || \"gte\" in value || \"lt\" in value || \"lte\" in value;\n}\n\n/**\n * Check if a value is an IN filter\n */\nexport function isInFilter(value: WhereValue): value is InFilter {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn \"in\" in value && Array.isArray(value.in);\n}\n\n/**\n * Check if a value is a startsWith filter\n */\nexport function isStartsWithFilter(value: WhereValue): value is StartsWithFilter {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn \"startsWith\" in value && typeof value.startsWith === \"string\";\n}\n\n/**\n * Escape LIKE pattern metacharacters so a startsWith prefix matches\n * literally. Without this, `%` and `_` in the prefix act as wildcards\n * (e.g. `{ startsWith: \"50%\" }` would match \"50x off\").\n */\nexport function escapeLikePattern(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"%\", \"\\\\%\").replaceAll(\"_\", \"\\\\_\");\n}\n\n/**\n * Get the set of indexed fields from index declarations\n */\nexport function getIndexedFields(indexes: Array<string | string[]>): Set<string> {\n\tconst fields = new Set<string>();\n\tfor (const index of indexes) {\n\t\tif (Array.isArray(index)) {\n\t\t\tfor (const field of index) {\n\t\t\t\tfields.add(field);\n\t\t\t}\n\t\t} else {\n\t\t\tfields.add(index);\n\t\t}\n\t}\n\treturn fields;\n}\n\n/**\n * Validate that all fields in a where clause are indexed\n */\nexport function validateWhereClause(\n\twhere: WhereClause,\n\tindexedFields: Set<string>,\n\tpluginId: string,\n\tcollection: string,\n): void {\n\tfor (const field of Object.keys(where)) {\n\t\tif (!indexedFields.has(field)) {\n\t\t\tthrow new StorageQueryError(\n\t\t\t\t`Cannot query on non-indexed field '${field}'.`,\n\t\t\t\tfield,\n\t\t\t\t`Add '${field}' to storage.${collection}.indexes in plugin '${pluginId}' to enable this query.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validate orderBy fields are indexed\n */\nexport function validateOrderByClause(\n\torderBy: Record<string, \"asc\" | \"desc\">,\n\tindexedFields: Set<string>,\n\tpluginId: string,\n\tcollection: string,\n): void {\n\tfor (const field of Object.keys(orderBy)) {\n\t\tif (!indexedFields.has(field)) {\n\t\t\tthrow new StorageQueryError(\n\t\t\t\t`Cannot order by non-indexed field '${field}'.`,\n\t\t\t\tfield,\n\t\t\t\t`Add '${field}' to storage.${collection}.indexes in plugin '${pluginId}' to enable ordering by this field.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * SQL expression for extracting a queryable field from the `_plugin_storage.data`\n * column.\n *\n * Delegates to `pluginDataExtractExpr`, which validates the field name before\n * interpolation and applies the dialect-correct extraction: a `::jsonb` cast on\n * Postgres (the `data` column is `text`) plus an optional type-guarded\n * `::numeric` cast so numeric comparisons don't fall back to lexical text\n * ordering.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function jsonExtract(\n\tdb: Kysely<any>,\n\tfield: string,\n\toptions?: { numeric?: boolean },\n): string {\n\treturn pluginDataExtractExpr(db, field, options);\n}\n\n/**\n * SQL expression for ordering by a `_plugin_storage.data` field.\n *\n * Delegates to `pluginDataOrderExpr`, which orders over the jsonb-native value\n * on Postgres so numeric fields sort numerically (not lexically) while staying\n * total across heterogeneous data. SQLite keeps `json_extract` (already numeric).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function jsonOrderExtract(db: Kysely<any>, field: string): string {\n\treturn pluginDataOrderExpr(db, field);\n}\n\n/**\n * Build a WHERE clause condition for a single field\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function buildCondition(\n\tdb: Kysely<any>,\n\tfield: string,\n\tvalue: WhereValue,\n): { sql: string; params: unknown[] } {\n\t// Numeric-vs-text is decided per condition from the JS type of the bound\n\t// value. On Postgres a text extract compared to a bound number would sort\n\t// lexically (`'9' >= '10'` is TRUE); a type-guarded `::numeric` cast on the\n\t// extract fixes it. String/boolean operands keep text comparison. SQLite is\n\t// unaffected — `json_extract` already returns a typed value.\n\tconst extractFor = (numeric: boolean): string => jsonExtract(db, field, { numeric });\n\n\tif (value === null) {\n\t\treturn { sql: `${extractFor(false)} IS NULL`, params: [] };\n\t}\n\n\tif (typeof value === \"number\") {\n\t\treturn { sql: `${extractFor(true)} = ?`, params: [value] };\n\t}\n\n\tif (typeof value === \"string\") {\n\t\treturn { sql: `${extractFor(false)} = ?`, params: [value] };\n\t}\n\n\tif (typeof value === \"boolean\") {\n\t\t// JSON booleans are stored as true/false strings\n\t\treturn { sql: `${extractFor(false)} = ?`, params: [value] };\n\t}\n\n\tif (isInFilter(value)) {\n\t\tconst numeric = value.in.length > 0 && value.in.every((v) => typeof v === \"number\");\n\t\tconst placeholders = value.in.map(() => \"?\").join(\", \");\n\t\treturn {\n\t\t\tsql: `${extractFor(numeric)} IN (${placeholders})`,\n\t\t\tparams: value.in,\n\t\t};\n\t}\n\n\tif (isStartsWithFilter(value)) {\n\t\t// ESCAPE '\\' works on both SQLite and PostgreSQL. startsWith is a string\n\t\t// operation, so always compare as text.\n\t\treturn {\n\t\t\tsql: `${extractFor(false)} LIKE ? ESCAPE '\\\\'`,\n\t\t\tparams: [`${escapeLikePattern(value.startsWith)}%`],\n\t\t};\n\t}\n\n\tif (isRangeFilter(value)) {\n\t\tconst conditions: string[] = [];\n\t\tconst params: unknown[] = [];\n\n\t\t// Each bound is cast to numeric only when its own operand is a number, so\n\t\t// a mixed range (e.g. a string lower bound) stays correct per side.\n\t\tconst pushBound = (op: string, bound: string | number): void => {\n\t\t\tconditions.push(`${extractFor(typeof bound === \"number\")} ${op} ?`);\n\t\t\tparams.push(bound);\n\t\t};\n\n\t\tif (value.gt !== undefined) pushBound(\">\", value.gt);\n\t\tif (value.gte !== undefined) pushBound(\">=\", value.gte);\n\t\tif (value.lt !== undefined) pushBound(\"<\", value.lt);\n\t\tif (value.lte !== undefined) pushBound(\"<=\", value.lte);\n\n\t\t// A filter with no defined bound contributes no SQL. Returning it would\n\t\t// widen the caller's predicate to \"match everything\" — survivable in a\n\t\t// read, but it strips the guard off a conditional write.\n\t\tif (conditions.length === 0) {\n\t\t\tthrow new StorageQueryError(\n\t\t\t\t`Range filter for field '${field}' has no defined bound`,\n\t\t\t\tfield,\n\t\t\t\t\"Provide at least one of gt, gte, lt, or lte, or omit the field.\",\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tsql: conditions.join(\" AND \"),\n\t\t\tparams,\n\t\t};\n\t}\n\n\tthrow new StorageQueryError(`Unknown filter type for field '${field}'`);\n}\n\n/**\n * Build a complete WHERE clause from a WhereClause object\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function buildWhereClause(\n\tdb: Kysely<any>,\n\twhere: WhereClause,\n): {\n\tsql: string;\n\tparams: unknown[];\n} {\n\tconst conditions: string[] = [];\n\tconst params: unknown[] = [];\n\n\tfor (const [field, value] of Object.entries(where)) {\n\t\tconst condition = buildCondition(db, field, value);\n\t\t// An empty slot in the join would emit `<cond> AND ` and fail to parse.\n\t\tif (!condition.sql) continue;\n\t\tconditions.push(condition.sql);\n\t\tparams.push(...condition.params);\n\t}\n\n\tif (conditions.length === 0) {\n\t\treturn { sql: \"\", params: [] };\n\t}\n\n\treturn {\n\t\tsql: conditions.join(\" AND \"),\n\t\tparams,\n\t};\n}\n\n/**\n * Build ORDER BY clause\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function buildOrderByClause(\n\tdb: Kysely<any>,\n\torderBy: Record<string, \"asc\" | \"desc\">,\n): string {\n\tconst clauses: string[] = [];\n\n\tfor (const [field, direction] of Object.entries(orderBy)) {\n\t\tclauses.push(`${jsonOrderExtract(db, field)} ${direction.toUpperCase()}`);\n\t}\n\n\tif (clauses.length === 0) {\n\t\treturn \"\";\n\t}\n\n\treturn `ORDER BY ${clauses.join(\", \")}`;\n}\n","import { validateJsonFieldName } from \"../database/validate.js\";\nimport type { RangeFilter, WhereClause, WhereValue } from \"./types.js\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction requireRecord(value: unknown, label: string): Record<string, unknown> {\n\tif (!isRecord(value)) {\n\t\tthrow new TypeError(`${label} must be an object`);\n\t}\n\tconst prototype: unknown = Object.getPrototypeOf(value);\n\tif (prototype !== Object.prototype && prototype !== null) {\n\t\tthrow new TypeError(`${label} must be a plain object`);\n\t}\n\treturn value;\n}\n\nfunction operand(value: unknown): string | number {\n\tif (typeof value === \"string\" || (typeof value === \"number\" && Number.isFinite(value))) {\n\t\treturn value;\n\t}\n\tthrow new TypeError(\"Storage guard operands must be strings or finite numbers\");\n}\n\nfunction normalizeFilter(value: unknown): WhereValue {\n\tif (value === null || typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\" || typeof value === \"number\") return operand(value);\n\tconst filter = requireRecord(value, \"Storage guard filter\");\n\tconst values = filter.in;\n\tif (Array.isArray(values)) {\n\t\treturn { in: Array.from(values, operand) };\n\t}\n\tconst prefix = filter.startsWith;\n\tif (typeof prefix === \"string\") {\n\t\treturn { startsWith: prefix };\n\t}\n\tconst range: RangeFilter = {};\n\tfor (const key of [\"gt\", \"gte\", \"lt\", \"lte\"] as const) {\n\t\tif (key in filter) {\n\t\t\tconst bound = filter[key];\n\t\t\trange[key] = bound === undefined ? undefined : operand(bound);\n\t\t}\n\t}\n\treturn range;\n}\n\nexport function parseStorageUpdate(value: unknown): {\n\twhere: WhereClause;\n\tsetEntries: Array<[string, unknown]>;\n\tdeltaEntries: Array<[string, number]>;\n} {\n\tconst args = requireRecord(value, \"Storage update arguments\");\n\tif (Object.keys(args).some((key) => key !== \"where\" && key !== \"set\" && key !== \"delta\")) {\n\t\tthrow new TypeError(\"Unknown storage update argument\");\n\t}\n\tconst where: WhereClause = {};\n\tfor (const [field, filter] of Object.entries(requireRecord(args.where, \"Storage where guard\"))) {\n\t\tvalidateJsonFieldName(field);\n\t\twhere[field] = normalizeFilter(filter);\n\t}\n\tconst set = args.set === undefined ? {} : requireRecord(args.set, \"Storage set\");\n\tconst delta = args.delta === undefined ? {} : requireRecord(args.delta, \"Storage delta\");\n\tconst setEntries: Array<[string, unknown]> = [];\n\tfor (const [field, entry] of Object.entries(set)) {\n\t\tif (entry === undefined) continue;\n\t\tvalidateJsonFieldName(field);\n\t\tconst serialized = JSON.stringify(entry);\n\t\tif (serialized === undefined)\n\t\t\tthrow new TypeError(\"Storage set values must be JSON serializable\");\n\t\tconst normalized: unknown = JSON.parse(serialized);\n\t\tsetEntries.push([field, normalized]);\n\t}\n\tconst setFields = new Set(setEntries.map(([field]) => field));\n\tconst deltaEntries: Array<[string, number]> = [];\n\tfor (const [field, entry] of Object.entries(delta)) {\n\t\tif (entry === undefined) continue;\n\t\tvalidateJsonFieldName(field);\n\t\tif (setFields.has(field)) throw new TypeError(\"Storage field appears in both set and delta\");\n\t\tconst spec = requireRecord(entry, \"Storage numeric delta\");\n\t\tconst keys = Object.keys(spec);\n\t\tconst key = keys[0];\n\t\tif (keys.length !== 1 || (key !== \"inc\" && key !== \"dec\")) {\n\t\t\tthrow new TypeError(\"Storage delta must contain exactly one of inc or dec\");\n\t\t}\n\t\tconst amount = spec[key];\n\t\tif (typeof amount !== \"number\" || !Number.isSafeInteger(amount)) {\n\t\t\tthrow new TypeError(\"Storage delta must be a safe integer\");\n\t\t}\n\t\tdeltaEntries.push([field, key === \"dec\" ? -amount : amount]);\n\t}\n\tif (setEntries.length + deltaEntries.length === 0) {\n\t\tthrow new TypeError(\"Storage update requires at least one of set or delta\");\n\t}\n\treturn { where, setEntries, deltaEntries };\n}\n","/**\n * Plugin Storage Repository\n *\n * Provides a document store API for plugin data storage.\n * Uses a single _plugin_storage table with JSON documents and expression indexes.\n *\n * @see PLUGIN-SYSTEM.md § Plugin Storage > Full API Reference\n */\n\nimport type { Kysely, RawBuilder } from \"kysely\";\nimport { sql } from \"kysely\";\n\nimport {\n\tassertStorageKey,\n\tassertStorageRevision,\n\tserializeConditionalValue,\n} from \"../../plugins/conditional-storage.js\";\nimport {\n\tbuildWhereClause,\n\tvalidateWhereClause,\n\tvalidateOrderByClause,\n\tgetIndexedFields,\n\tjsonOrderExtract,\n\tStorageQueryError,\n\tisInFilter,\n\tStorageSerializationError,\n} from \"../../plugins/storage-query.js\";\nimport { parseStorageUpdate } from \"../../plugins/storage-update.js\";\nimport type {\n\tStorageCollection,\n\tQueryOptions,\n\tPaginatedResult,\n\tWhereClause,\n\tUpdateIfResult,\n\tVersionedValue,\n\tConditionalWriteResult,\n\tConditionalDeleteResult,\n} from \"../../plugins/types.js\";\nimport { pluginDataWriteExpr, pluginDataUpdateGuard } from \"../dialect-helpers.js\";\nimport { withTransaction } from \"../transaction.js\";\nimport type { Database } from \"../types.js\";\nimport { encodeCursor, decodeCursor } from \"./types.js\";\n\n/**\n * SQLSTATEs a losing concurrent `updateIf` writer can abort with.\n *\n * `40001` (serialization_failure) is raised only above READ COMMITTED, where\n * the loser cannot re-evaluate its guard against a newer snapshot. `40P01`\n * (deadlock_detected) is not tied to isolation level: it needs only two\n * transactions taking row locks in opposite order, which a caller reaches at\n * READ COMMITTED by wrapping several `updateIf` calls in one transaction.\n */\nconst SERIALIZATION_SQLSTATES = new Set([\"40001\", \"40P01\"]);\n\nfunction errSqlState(err: unknown): string | undefined {\n\tif (typeof err !== \"object\" || err === null) return undefined;\n\tconst code = (err as { code?: unknown }).code;\n\tif (typeof code === \"string\") return code;\n\tconst cause = (err as { cause?: unknown }).cause;\n\tif (typeof cause === \"object\" && cause !== null) {\n\t\tconst causeCode = (cause as { code?: unknown }).code;\n\t\tif (typeof causeCode === \"string\") return causeCode;\n\t}\n\treturn undefined;\n}\n\nexport function mapSerializationFailure(err: unknown): unknown {\n\tconst sqlState = errSqlState(err);\n\tif (sqlState !== undefined && SERIALIZATION_SQLSTATES.has(sqlState)) {\n\t\treturn new StorageSerializationError(\n\t\t\t\"Storage write must be retried. Restart the transaction before retrying when using an explicit transaction.\",\n\t\t\t{ cause: err, sqlState },\n\t\t);\n\t}\n\treturn err;\n}\n\n/**\n * Interleave a `?`-placeholder SQL string with its params into a single\n * boolean raw expression. Used as a WHERE predicate directly — wrapping it\n * in `(...) = 1` breaks on Postgres, which has a strict boolean type (#920).\n */\nfunction rawWhereExpr(sqlText: string, params: unknown[]): RawBuilder<boolean> {\n\tconst parts: ReturnType<typeof sql>[] = [];\n\tlet paramIndex = 0;\n\tconst sqlParts = sqlText.split(\"?\");\n\tfor (let i = 0; i < sqlParts.length; i++) {\n\t\tif (i > 0) {\n\t\t\tparts.push(sql`${params[paramIndex++]}`);\n\t\t}\n\t\tif (sqlParts[i]) {\n\t\t\tparts.push(sql.raw(sqlParts[i]));\n\t\t}\n\t}\n\treturn sql<boolean>`(${sql.join(parts, sql.raw(\"\"))})`;\n}\n\n/**\n * Plugin Storage Repository\n *\n * Implements the StorageCollection interface for a specific plugin and collection.\n */\n/**\n * Rank a sort expression so NULLs get a deterministic position.\n *\n * A missing key in a schemaless document extracts as NULL, which sorts\n * differently per dialect (SQLite first, Postgres last) and makes every\n * comparison against it UNKNOWN. Sorting on this rank ahead of the value puts\n * NULLs in the same place on both dialects and keeps the seek operands\n * non-NULL.\n */\nfunction nullRank(expr: RawBuilder<unknown>): RawBuilder<number> {\n\treturn sql`(case when ${expr} is null then 1 else 0 end)`;\n}\n\nexport class PluginStorageRepository<T = unknown> implements StorageCollection<T> {\n\tprivate indexedFields: Set<string>;\n\n\tconstructor(\n\t\tprivate db: Kysely<Database>,\n\t\tprivate pluginId: string,\n\t\tprivate collection: string,\n\t\tindexes: Array<string | string[]>,\n\t) {\n\t\tthis.indexedFields = getIndexedFields(indexes);\n\t}\n\n\t/**\n\t * Get a document by ID\n\t */\n\tasync get(id: string): Promise<T | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_plugin_storage\")\n\t\t\t.select(\"data\")\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!row) return null;\n\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T\n\t\treturn JSON.parse(row.data) as T;\n\t}\n\n\t/**\n\t * Store a document\n\t */\n\tasync put(id: string, data: T): Promise<void> {\n\t\tconst now = new Date().toISOString();\n\t\tconst jsonData = JSON.stringify(data);\n\t\tconst revision = crypto.randomUUID();\n\n\t\tawait this.db\n\t\t\t.insertInto(\"_plugin_storage\")\n\t\t\t.values({\n\t\t\t\tplugin_id: this.pluginId,\n\t\t\t\tcollection: this.collection,\n\t\t\t\tid,\n\t\t\t\tdata: jsonData,\n\t\t\t\trevision,\n\t\t\t\tcreated_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.onConflict((oc) =>\n\t\t\t\toc.columns([\"plugin_id\", \"collection\", \"id\"]).doUpdateSet({\n\t\t\t\t\tdata: jsonData,\n\t\t\t\t\trevision,\n\t\t\t\t\tupdated_at: now,\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.execute();\n\t}\n\n\tasync getVersioned(id: string): Promise<VersionedValue<T> | null> {\n\t\tassertStorageKey(id);\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_plugin_storage\")\n\t\t\t.select([\"data\", \"revision\"])\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\tif (!row) return null;\n\t\treturn { value: JSON.parse(row.data), revision: row.revision };\n\t}\n\n\tasync compareAndSet(\n\t\tid: string,\n\t\texpectedRevision: string | null,\n\t\tdata: T,\n\t): Promise<ConditionalWriteResult> {\n\t\tassertStorageKey(id);\n\t\tif (expectedRevision !== null) assertStorageRevision(expectedRevision);\n\t\tconst jsonData = serializeConditionalValue(data);\n\t\tconst revision = crypto.randomUUID();\n\t\tconst now = new Date().toISOString();\n\t\tconst row =\n\t\t\texpectedRevision === null\n\t\t\t\t? await this.db\n\t\t\t\t\t\t.insertInto(\"_plugin_storage\")\n\t\t\t\t\t\t.values({\n\t\t\t\t\t\t\tplugin_id: this.pluginId,\n\t\t\t\t\t\t\tcollection: this.collection,\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tdata: jsonData,\n\t\t\t\t\t\t\trevision,\n\t\t\t\t\t\t\tcreated_at: now,\n\t\t\t\t\t\t\tupdated_at: now,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.onConflict((oc) => oc.columns([\"plugin_id\", \"collection\", \"id\"]).doNothing())\n\t\t\t\t\t\t.returning(\"revision\")\n\t\t\t\t\t\t.executeTakeFirst()\n\t\t\t\t: await this.db\n\t\t\t\t\t\t.updateTable(\"_plugin_storage\")\n\t\t\t\t\t\t.set({ data: jsonData, revision, updated_at: now })\n\t\t\t\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t\t\t\t.where(\"id\", \"=\", id)\n\t\t\t\t\t\t.where(\"revision\", \"=\", expectedRevision)\n\t\t\t\t\t\t.returning(\"revision\")\n\t\t\t\t\t\t.executeTakeFirst();\n\t\treturn row ? { applied: true, revision: row.revision } : { applied: false };\n\t}\n\n\tasync compareAndDelete(id: string, expectedRevision: string): Promise<ConditionalDeleteResult> {\n\t\tassertStorageKey(id);\n\t\tassertStorageRevision(expectedRevision);\n\t\tconst row = await this.db\n\t\t\t.deleteFrom(\"_plugin_storage\")\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.where(\"revision\", \"=\", expectedRevision)\n\t\t\t.returning(\"id\")\n\t\t\t.executeTakeFirst();\n\t\treturn { applied: row !== undefined };\n\t}\n\n\t/**\n\t * Delete a document\n\t */\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_plugin_storage\")\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\n\t\treturn (result.numDeletedRows ?? 0) > 0;\n\t}\n\n\t/**\n\t * Check if a document exists\n\t */\n\tasync exists(id: string): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_plugin_storage\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\n\t\treturn !!row;\n\t}\n\n\t/**\n\t * Get multiple documents by ID\n\t */\n\tasync getMany(ids: string[]): Promise<Map<string, T>> {\n\t\tif (ids.length === 0) return new Map();\n\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_plugin_storage\")\n\t\t\t.select([\"id\", \"data\"])\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"in\", ids)\n\t\t\t.execute();\n\n\t\tconst result = new Map<string, T>();\n\t\tfor (const row of rows) {\n\t\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T\n\t\t\tresult.set(row.id, JSON.parse(row.data) as T);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Store multiple documents\n\t */\n\tasync putMany(items: Array<{ id: string; data: T }>): Promise<void> {\n\t\tif (items.length === 0) return;\n\n\t\tconst now = new Date().toISOString();\n\n\t\t// SQLite doesn't support batch upserts well, so we do them one at a time\n\t\t// In a transaction for atomicity\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tfor (const item of items) {\n\t\t\t\tconst jsonData = JSON.stringify(item.data);\n\t\t\t\tconst revision = crypto.randomUUID();\n\t\t\t\tawait trx\n\t\t\t\t\t.insertInto(\"_plugin_storage\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tplugin_id: this.pluginId,\n\t\t\t\t\t\tcollection: this.collection,\n\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\tdata: jsonData,\n\t\t\t\t\t\trevision,\n\t\t\t\t\t\tcreated_at: now,\n\t\t\t\t\t\tupdated_at: now,\n\t\t\t\t\t})\n\t\t\t\t\t.onConflict((oc) =>\n\t\t\t\t\t\toc.columns([\"plugin_id\", \"collection\", \"id\"]).doUpdateSet({\n\t\t\t\t\t\t\tdata: jsonData,\n\t\t\t\t\t\t\trevision,\n\t\t\t\t\t\t\tupdated_at: now,\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\t.execute();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Delete multiple documents\n\t */\n\tasync deleteMany(ids: string[]): Promise<number> {\n\t\tif (ids.length === 0) return 0;\n\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_plugin_storage\")\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"in\", ids)\n\t\t\t.executeTakeFirst();\n\n\t\treturn Number(result.numDeletedRows ?? 0);\n\t}\n\n\t/**\n\t * Query documents with filters\n\t */\n\tasync query(options: QueryOptions = {}): Promise<PaginatedResult<{ id: string; data: T }>> {\n\t\tconst { where = {}, orderBy = {}, cursor } = options;\n\t\tconst limit = Math.min(options.limit ?? 50, 100);\n\n\t\t// Validate that all queried fields are indexed\n\t\tvalidateWhereClause(where, this.indexedFields, this.pluginId, this.collection);\n\t\tif (Object.keys(orderBy).length > 0) {\n\t\t\tvalidateOrderByClause(orderBy, this.indexedFields, this.pluginId, this.collection);\n\t\t}\n\n\t\t// Build base query\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_plugin_storage\")\n\t\t\t.select([\"id\", \"data\", \"created_at\"])\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection);\n\n\t\t// Add JSON extraction WHERE conditions\n\t\tconst whereResult = buildWhereClause(this.db, where);\n\t\tif (whereResult.sql) {\n\t\t\tquery = query.where(rawWhereExpr(whereResult.sql, whereResult.params));\n\t\t}\n\n\t\tconst orderEntries = Object.entries(orderBy);\n\t\tconst orderDirections = new Set(orderEntries.map(([, direction]) => direction));\n\t\tconst descending = orderEntries.length > 0 && orderEntries[0][1] === \"desc\";\n\n\t\t// A missing key in a schemaless document extracts as NULL, and NULL sorts\n\t\t// differently per dialect (SQLite first, Postgres last) and makes any\n\t\t// comparison against it UNKNOWN. Rank nulls explicitly so both the sort and\n\t\t// the seek agree on where they sit, on either dialect, and so no comparison\n\t\t// operand is ever NULL.\n\t\tconst sortExpr = (field: string): RawBuilder<unknown> =>\n\t\t\tsql`${sql.raw(jsonOrderExtract(this.db, field))}`;\n\n\t\t// Handle cursor-based pagination — throws on invalid cursor.\n\t\tif (cursor) {\n\t\t\tconst decoded = decodeCursor(cursor);\n\t\t\tif (orderEntries.length === 0) {\n\t\t\t\tquery = query.where(({ eb }) =>\n\t\t\t\t\teb(sql`(created_at, id)`, \">\", sql`(${decoded.orderValue}, ${decoded.id})`),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tif (orderDirections.size > 1) {\n\t\t\t\t\tthrow new StorageQueryError(\n\t\t\t\t\t\t\"Cursor pagination requires every orderBy field to share one direction.\",\n\t\t\t\t\t\tObject.keys(orderBy).join(\", \"),\n\t\t\t\t\t\t\"Sort every field the same way, or page without a cursor.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst op = descending ? sql`<` : sql`>`;\n\t\t\t\t// The cursor row's sort values, recomputed with the same expression\n\t\t\t\t// rather than carried in the cursor, so nothing is bound as a literal\n\t\t\t\t// and neither dialect has to coerce a JSON value to compare it.\n\t\t\t\tconst cursorExpr = (field: string): RawBuilder<unknown> =>\n\t\t\t\t\tsql`(select ${sql.raw(jsonOrderExtract(this.db, field))} from _plugin_storage where plugin_id = ${this.pluginId} and collection = ${this.collection} and id = ${decoded.id})`;\n\n\t\t\t\tconst fields = orderEntries.map(([field]) => {\n\t\t\t\t\tconst own = sortExpr(field);\n\t\t\t\t\tconst theirs = cursorExpr(field);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tequal: sql`(${nullRank(own)} = ${nullRank(theirs)} and (${nullRank(own)} = 1 or ${own} = ${theirs}))`,\n\t\t\t\t\t\tafter: sql`(${nullRank(own)} ${op} ${nullRank(theirs)} or (${nullRank(own)} = ${nullRank(theirs)} and ${nullRank(own)} = 0 and ${own} ${op} ${theirs}))`,\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\t\t// Lexicographic seek: ties on every earlier field, then strictly after\n\t\t\t\t// on this one; finally all fields tied and strictly after on id.\n\t\t\t\tconst terms = fields.map(\n\t\t\t\t\t(_, k) =>\n\t\t\t\t\t\tsql`(${sql.join([...fields.slice(0, k).map((f) => f.equal), fields[k].after], sql` and `)})`,\n\t\t\t\t);\n\t\t\t\tterms.push(\n\t\t\t\t\tsql`(${sql.join([...fields.map((f) => f.equal), sql`id ${op} ${decoded.id}`], sql` and `)})`,\n\t\t\t\t);\n\t\t\t\tquery = query.where(sql<boolean>`(${sql.join(terms, sql` or `)})`);\n\t\t\t}\n\t\t}\n\n\t\t// Build ORDER BY using sql template\n\t\tif (orderEntries.length > 0) {\n\t\t\tfor (const [field, direction] of orderEntries) {\n\t\t\t\tconst dir = direction === \"desc\" ? sql`desc` : sql`asc`;\n\t\t\t\tconst expr = sortExpr(field);\n\t\t\t\t// Null rank first so NULL placement is identical on both dialects.\n\t\t\t\tquery = query.orderBy(sql`${nullRank(expr)} ${dir}`);\n\t\t\t\t// Order over the jsonb-native value on Postgres so numeric fields sort\n\t\t\t\t// numerically, not lexically. See pluginDataOrderExpr.\n\t\t\t\tquery = query.orderBy(sql`${expr} ${dir}`);\n\t\t\t}\n\t\t\t// Total order, so a page boundary can never fall inside a group of ties.\n\t\t\tquery = query.orderBy(\"id\", descending ? \"desc\" : \"asc\");\n\t\t} else {\n\t\t\t// Default ordering for consistent pagination\n\t\t\tquery = query.orderBy(\"created_at\", \"asc\").orderBy(\"id\", \"asc\");\n\t\t}\n\n\t\t// Apply limit (fetch one extra to detect if there's more)\n\t\tquery = query.limit(limit + 1);\n\n\t\tconst rows = await query.execute();\n\n\t\tconst hasMore = rows.length > limit;\n\t\tconst items = rows.slice(0, limit).map((row) => ({\n\t\t\tid: row.id,\n\t\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T\n\t\t\tdata: JSON.parse(row.data) as T,\n\t\t}));\n\n\t\t// Generate cursor for next page if there are more results\n\t\tlet nextCursor: string | undefined;\n\t\tif (hasMore) {\n\t\t\tconst lastItem = rows[limit - 1];\n\t\t\tif (lastItem) {\n\t\t\t\tnextCursor = encodeCursor(lastItem.created_at, lastItem.id);\n\t\t\t}\n\t\t}\n\n\t\treturn { items, cursor: nextCursor, hasMore };\n\t}\n\n\t/**\n\t * Count documents matching a filter\n\t */\n\tasync count(where?: WhereClause): Promise<number> {\n\t\tif (where && Object.keys(where).length > 0) {\n\t\t\tvalidateWhereClause(where, this.indexedFields, this.pluginId, this.collection);\n\t\t}\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_plugin_storage\")\n\t\t\t.select(sql<number>`COUNT(*)`.as(\"count\"))\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection);\n\n\t\t// Add JSON extraction WHERE conditions\n\t\tif (where && Object.keys(where).length > 0) {\n\t\t\tconst whereResult = buildWhereClause(this.db, where);\n\t\t\tif (whereResult.sql) {\n\t\t\t\tquery = query.where(rawWhereExpr(whereResult.sql, whereResult.params));\n\t\t\t}\n\t\t}\n\n\t\tconst result = await query.executeTakeFirst();\n\t\t// Number() because the pg driver returns COUNT(*) (bigint) as a string.\n\t\treturn Number(result?.count ?? 0);\n\t}\n\n\tasync updateIf(id: string, args: unknown): Promise<UpdateIfResult<T>> {\n\t\tif (typeof id !== \"string\") throw new TypeError(\"Storage ID must be a string\");\n\t\tconst { where, setEntries, deltaEntries } = parseStorageUpdate(args);\n\n\t\t// Defensive empty-`in` guard: an empty `in: []` matches nothing. The shared\n\t\t// where-translation would emit invalid `IN ()`; short-circuit to a no-op\n\t\t// (matches nothing → applied:false) BEFORE building any SQL.\n\t\tfor (const value of Object.values(where)) {\n\t\t\tif (isInFilter(value) && value.in.length === 0) {\n\t\t\t\treturn { applied: false };\n\t\t\t}\n\t\t}\n\n\t\tconst now = new Date().toISOString();\n\t\tconst dataExpr = pluginDataWriteExpr(this.db, setEntries, deltaEntries);\n\n\t\tlet query = this.db\n\t\t\t.updateTable(\"_plugin_storage\")\n\t\t\t.set({ data: dataExpr, updated_at: now })\n\t\t\t.where(\"plugin_id\", \"=\", this.pluginId)\n\t\t\t.where(\"collection\", \"=\", this.collection)\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.where(pluginDataUpdateGuard(this.db, deltaEntries));\n\n\t\tconst whereResult = buildWhereClause(this.db, where);\n\t\tif (whereResult.sql) {\n\t\t\tquery = query.where(rawWhereExpr(whereResult.sql, whereResult.params));\n\t\t}\n\n\t\tlet row: { data: string } | undefined;\n\t\ttry {\n\t\t\trow = await query.returning(\"data\").executeTakeFirst();\n\t\t} catch (err) {\n\t\t\tthrow mapSerializationFailure(err);\n\t\t}\n\t\tif (!row) return { applied: false };\n\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T\n\t\tconst data = JSON.parse(row.data) as T;\n\t\treturn { applied: true, data };\n\t}\n}\n\n/**\n * Create a scoped storage accessor for a plugin\n */\nexport function createPluginStorageAccessor(\n\tdb: Kysely<Database>,\n\tpluginId: string,\n\tstorageConfig: Record<\n\t\tstring,\n\t\t{ indexes: Array<string | string[]>; uniqueIndexes?: Array<string | string[]> }\n\t>,\n): Record<string, StorageCollection> {\n\tconst accessor: Record<string, StorageCollection> = {};\n\n\tfor (const [collectionName, config] of Object.entries(storageConfig)) {\n\t\tconst allIndexes = [...config.indexes, ...(config.uniqueIndexes ?? [])];\n\t\taccessor[collectionName] = new PluginStorageRepository(\n\t\t\tdb,\n\t\t\tpluginId,\n\t\t\tcollectionName,\n\t\t\tallIndexes,\n\t\t);\n\t}\n\n\treturn accessor;\n}\n\n/**\n * Delete all storage data for a plugin\n */\nexport async function deleteAllPluginStorage(\n\tdb: Kysely<Database>,\n\tpluginId: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.deleteFrom(\"_plugin_storage\")\n\t\t.where(\"plugin_id\", \"=\", pluginId)\n\t\t.executeTakeFirst();\n\n\treturn Number(result.numDeletedRows ?? 0);\n}\n\n/**\n * Delete all storage data for a plugin collection\n */\nexport async function deletePluginCollection(\n\tdb: Kysely<Database>,\n\tpluginId: string,\n\tcollection: string,\n): Promise<number> {\n\tconst result = await db\n\t\t.deleteFrom(\"_plugin_storage\")\n\t\t.where(\"plugin_id\", \"=\", pluginId)\n\t\t.where(\"collection\", \"=\", collection)\n\t\t.executeTakeFirst();\n\n\treturn Number(result.numDeletedRows ?? 0);\n}\n","import type { Kysely } from \"kysely\";\n\nimport { ContentRepository } from \"../database/repositories/content.js\";\nimport { normalizeRevisionLimit, RevisionRepository } from \"../database/repositories/revision.js\";\nimport { SeoRepository } from \"../database/repositories/seo.js\";\nimport type { Database } from \"../database/types.js\";\nimport { resolveLocalizedContentRoutePath } from \"../i18n/resolve.js\";\nimport { SchemaRegistry } from \"../schema/registry.js\";\nimport type {\n\tContentAccess,\n\tContentItem,\n\tContentListOptions,\n\tPaginatedResult,\n\tSiteInfo,\n} from \"./types.js\";\n\nexport function createContentAccess(\n\tdb: Kysely<Database>,\n\taccessOptions?: { site?: SiteInfo; revisions?: boolean },\n): ContentAccess {\n\tconst contentRepo = new ContentRepository(db);\n\tconst seoRepo = new SeoRepository(db);\n\n\treturn {\n\t\tasync get(collection: string, id: string): Promise<ContentItem | null> {\n\t\t\tconst item = await contentRepo.findById(collection, id);\n\t\t\tif (!item) return null;\n\n\t\t\tconst result: ContentItem = {\n\t\t\t\tid: item.id,\n\t\t\t\ttype: item.type,\n\t\t\t\tslug: item.slug,\n\t\t\t\tstatus: item.status,\n\t\t\t\tdata: item.data,\n\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\tlocale: item.locale,\n\t\t\t\tpublishedAt: item.publishedAt,\n\t\t\t\tscheduledAt: item.scheduledAt,\n\t\t\t\tauthorId: item.authorId,\n\t\t\t\ttranslationGroup: item.translationGroup,\n\t\t\t\tliveRevisionId: item.liveRevisionId,\n\t\t\t\tdraftRevisionId: item.draftRevisionId,\n\t\t\t\tversion: item.version,\n\t\t\t};\n\n\t\t\tif (await seoRepo.isEnabled(collection)) {\n\t\t\t\tresult.seo = await seoRepo.get(collection, item.id);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t},\n\n\t\tasync list(\n\t\t\tcollection: string,\n\t\t\toptions?: ContentListOptions,\n\t\t): Promise<PaginatedResult<ContentItem>> {\n\t\t\tlet orderBy: { field: string; direction: \"asc\" | \"desc\" } | undefined;\n\t\t\tif (options?.orderBy) {\n\t\t\t\tconst entries = Object.entries(options.orderBy);\n\t\t\t\tconst first = entries[0];\n\t\t\t\tif (first) orderBy = { field: first[0], direction: first[1] };\n\t\t\t}\n\n\t\t\tconst result = await contentRepo.findMany(collection, {\n\t\t\t\tlimit: options?.limit ?? 50,\n\t\t\t\tcursor: options?.cursor,\n\t\t\t\torderBy,\n\t\t\t\twhere: options?.where,\n\t\t\t});\n\n\t\t\tconst items: ContentItem[] = result.items.map((item) => ({\n\t\t\t\tid: item.id,\n\t\t\t\ttype: item.type,\n\t\t\t\tslug: item.slug,\n\t\t\t\tstatus: item.status,\n\t\t\t\tdata: item.data,\n\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\tlocale: item.locale,\n\t\t\t\tpublishedAt: item.publishedAt,\n\t\t\t\tscheduledAt: item.scheduledAt,\n\t\t\t\tauthorId: item.authorId,\n\t\t\t\ttranslationGroup: item.translationGroup,\n\t\t\t\tliveRevisionId: item.liveRevisionId,\n\t\t\t\tdraftRevisionId: item.draftRevisionId,\n\t\t\t\tversion: item.version,\n\t\t\t}));\n\n\t\t\tif (items.length > 0 && (await seoRepo.isEnabled(collection))) {\n\t\t\t\tconst seoMap = await seoRepo.getMany(\n\t\t\t\t\tcollection,\n\t\t\t\t\titems.map((item) => item.id),\n\t\t\t\t);\n\t\t\t\tfor (const item of items) {\n\t\t\t\t\tconst seo = seoMap.get(item.id);\n\t\t\t\t\tif (seo) item.seo = seo;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { items, cursor: result.nextCursor, hasMore: !!result.nextCursor };\n\t\t},\n\n\t\tasync getTranslations(collection, id) {\n\t\t\tconst item = await contentRepo.findById(collection, id);\n\t\t\tif (!item) throw new Error(`Content not found: ${collection}/${id}`);\n\t\t\tconst translationGroup = item.translationGroup || item.id;\n\t\t\tconst translations = item.translationGroup\n\t\t\t\t? await contentRepo.findTranslations(collection, item.translationGroup)\n\t\t\t\t: [item];\n\t\t\treturn {\n\t\t\t\ttranslationGroup,\n\t\t\t\ttranslations: translations.map((translation) => ({\n\t\t\t\t\tid: translation.id,\n\t\t\t\t\tlocale: translation.locale,\n\t\t\t\t\tslug: translation.slug,\n\t\t\t\t\tstatus: translation.status,\n\t\t\t\t\tupdatedAt: translation.updatedAt,\n\t\t\t\t})),\n\t\t\t};\n\t\t},\n\n\t\tasync getPublicUrl(collection, id) {\n\t\t\tconst site = accessOptions?.site;\n\t\t\tif (!site?.url) return null;\n\t\t\tconst [item, collectionInfo] = await Promise.all([\n\t\t\t\tcontentRepo.findById(collection, id),\n\t\t\t\tnew SchemaRegistry(db).getCollection(collection),\n\t\t\t]);\n\t\t\tif (!item || item.status !== \"published\" || !item.slug || !collectionInfo?.routable) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst path = await resolveLocalizedContentRoutePath({\n\t\t\t\tpattern: collectionInfo.urlPattern ?? null,\n\t\t\t\tcollection,\n\t\t\t\tslug: item.slug,\n\t\t\t\tid: item.id,\n\t\t\t\tdate: item.publishedAt,\n\t\t\t\tlocale: item.locale || site.locale,\n\t\t\t\ttrailingSlash: site.trailingSlash,\n\t\t\t});\n\t\t\treturn path === null ? null : `${site.url}${path}`;\n\t\t},\n\n\t\t...(accessOptions?.revisions\n\t\t\t? {\n\t\t\t\t\tasync listRevisions(\n\t\t\t\t\t\tcollection: string,\n\t\t\t\t\t\tid: string,\n\t\t\t\t\t\trevisionOptions?: { limit?: number },\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst revisions = await new RevisionRepository(db).findVisibleByEntry(collection, id, {\n\t\t\t\t\t\t\tlimit: normalizeRevisionLimit(revisionOptions?.limit),\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn revisions.map(({ authorId: _authorId, ...revision }) => revision);\n\t\t\t\t\t},\n\t\t\t\t\tasync getRevision(collection: string, id: string, revisionId: string) {\n\t\t\t\t\t\tconst revision = await new RevisionRepository(db).findVisibleById(\n\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\trevisionId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!revision) return null;\n\t\t\t\t\t\tconst { authorId: _authorId, ...safeRevision } = revision;\n\t\t\t\t\t\treturn safeRevision;\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n","import type { Kysely } from \"kysely\";\n\nimport {\n\tMediaRepository,\n\ttype MediaItem as RepositoryMediaItem,\n} from \"../database/repositories/media.js\";\nimport type { Database } from \"../database/types.js\";\nimport { isValidFocalPointUpdate } from \"../media/focal-point.js\";\nimport type { Storage } from \"../storage/types.js\";\nimport type { MediaBytes, MediaItem, MediaMetadataPatch } from \"./types.js\";\n\nexport const DEFAULT_PLUGIN_MEDIA_READ_BYTES = 10 * 1024 * 1024;\nexport const MAX_PLUGIN_MEDIA_READ_BYTES = 16 * 1024 * 1024;\n\nfunction mediaUrl(item: RepositoryMediaItem): string {\n\treturn `/_emdash/api/media/asset/${encodeURIComponent(item.id)}/${encodeURIComponent(item.filename)}`;\n}\n\nexport function toPluginMediaItem(item: RepositoryMediaItem): MediaItem {\n\treturn {\n\t\tid: item.id,\n\t\tfilename: item.filename,\n\t\tmimeType: item.mimeType,\n\t\tsize: item.size,\n\t\turl: mediaUrl(item),\n\t\tcreatedAt: item.createdAt,\n\t\twidth: item.width,\n\t\theight: item.height,\n\t\talt: item.alt,\n\t\tcaption: item.caption,\n\t\tfocalX: item.focalX,\n\t\tfocalY: item.focalY,\n\t\tblurhash: item.blurhash,\n\t\tdominantColor: item.dominantColor,\n\t\tfolderId: item.folderId ?? null,\n\t\tstatus: \"ready\",\n\t};\n}\n\nfunction resolveByteLimit(maxBytes: number | undefined): number {\n\tconst limit = maxBytes ?? DEFAULT_PLUGIN_MEDIA_READ_BYTES;\n\tif (!Number.isSafeInteger(limit) || limit <= 0 || limit > MAX_PLUGIN_MEDIA_READ_BYTES) {\n\t\tthrow new RangeError(\n\t\t\t`media.readBytes maxBytes must be a positive integer no greater than ${MAX_PLUGIN_MEDIA_READ_BYTES}`,\n\t\t);\n\t}\n\treturn limit;\n}\n\nasync function readStreamWithLimit(\n\tbody: ReadableStream<Uint8Array>,\n\tmaxBytes: number,\n): Promise<Uint8Array> {\n\tconst reader = body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet size = 0;\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tsize += value.byteLength;\n\t\t\tif (size > maxBytes) {\n\t\t\t\ttry {\n\t\t\t\t\tawait reader.cancel();\n\t\t\t\t} catch {}\n\t\t\t\tthrow new PluginMediaByteLimitError(`Media exceeds the requested ${maxBytes}-byte limit`);\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n\n\tconst bytes = new Uint8Array(size);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tbytes.set(chunk, offset);\n\t\toffset += chunk.byteLength;\n\t}\n\treturn bytes;\n}\n\nclass PluginMediaByteLimitError extends RangeError {}\n\nexport async function readPluginMediaBytes(\n\tdb: Kysely<Database>,\n\tstorage: Pick<Storage, \"download\"> | undefined,\n\tid: string,\n\toptions?: { maxBytes?: number },\n): Promise<MediaBytes> {\n\tif (!storage) throw new Error(\"Media storage is not configured\");\n\tconst limit = resolveByteLimit(options?.maxBytes);\n\tconst item = await new MediaRepository(db).findById(id);\n\tif (!item || item.status !== \"ready\") {\n\t\tthrow new Error(\"Media item is not ready or does not exist\");\n\t}\n\tlet bytes: Uint8Array;\n\ttry {\n\t\tconst download = await storage.download(item.storageKey);\n\t\tbytes = await readStreamWithLimit(download.body, limit);\n\t} catch (error) {\n\t\tif (error instanceof PluginMediaByteLimitError) throw error;\n\t\t// oxlint-disable-next-line preserve-caught-error -- adapter errors may contain private storage keys\n\t\tthrow new Error(\"Failed to read media bytes\");\n\t}\n\treturn {\n\t\tbytes,\n\t\tfilename: item.filename,\n\t\tmimeType: item.mimeType,\n\t\tsize: bytes.byteLength,\n\t\t...(item.contentHash ? { contentHash: item.contentHash } : {}),\n\t};\n}\n\nexport async function updatePluginMediaMetadata(\n\tdb: Kysely<Database>,\n\tid: string,\n\tpatch: MediaMetadataPatch,\n): Promise<MediaItem> {\n\tconst parsed = parsePluginMediaMetadataPatch(patch);\n\tconst item = await new MediaRepository(db).updateReadyMetadata(id, parsed);\n\tif (!item) throw new Error(\"Media item is not ready or does not exist\");\n\treturn toPluginMediaItem(item);\n}\n\nconst MEDIA_METADATA_KEYS = new Set([\"alt\", \"caption\", \"focalX\", \"focalY\"]);\n\nexport function parsePluginMediaMetadataPatch(value: unknown): MediaMetadataPatch {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new TypeError(\"media.updateMetadata patch must be an object\");\n\t}\n\tconst keys = Object.keys(value);\n\tif (keys.length === 0) {\n\t\tthrow new TypeError(\"media.updateMetadata must change at least one metadata field\");\n\t}\n\tfor (const key of keys) {\n\t\tif (!MEDIA_METADATA_KEYS.has(key)) {\n\t\t\tthrow new TypeError(`media.updateMetadata cannot change ${key}`);\n\t\t}\n\t}\n\tconst alt = Reflect.get(value, \"alt\");\n\tconst caption = Reflect.get(value, \"caption\");\n\tconst focalX = Reflect.get(value, \"focalX\");\n\tconst focalY = Reflect.get(value, \"focalY\");\n\tif (alt !== undefined && alt !== null && typeof alt !== \"string\") {\n\t\tthrow new TypeError(\"media.updateMetadata alt must be a string or null\");\n\t}\n\tif (caption !== undefined && caption !== null && typeof caption !== \"string\") {\n\t\tthrow new TypeError(\"media.updateMetadata caption must be a string or null\");\n\t}\n\tif (focalX !== undefined && focalX !== null && typeof focalX !== \"number\") {\n\t\tthrow new TypeError(\"media.updateMetadata focalX must be a number or null\");\n\t}\n\tif (focalY !== undefined && focalY !== null && typeof focalY !== \"number\") {\n\t\tthrow new TypeError(\"media.updateMetadata focalY must be a number or null\");\n\t}\n\tconst patch: MediaMetadataPatch = {};\n\tif (alt !== undefined) patch.alt = alt;\n\tif (caption !== undefined) patch.caption = caption;\n\tif (focalX !== undefined) patch.focalX = focalX;\n\tif (focalY !== undefined) patch.focalY = focalY;\n\tif (!isValidFocalPointUpdate(patch)) {\n\t\tthrow new TypeError(\"focalX and focalY must both be valid numbers or both be null\");\n\t}\n\treturn patch;\n}\n","/**\n * Error class for plugin routes\n * Allows plugins to return structured errors with specific HTTP status codes\n */\nexport class PluginRouteError extends Error {\n\tconstructor(\n\t\tpublic code: string,\n\t\tmessage: string,\n\t\tpublic status: number = 400,\n\t\tpublic details?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"PluginRouteError\";\n\t}\n\n\t/**\n\t * Create a bad request error (400)\n\t */\n\tstatic badRequest(message: string, details?: unknown): PluginRouteError {\n\t\treturn new PluginRouteError(\"BAD_REQUEST\", message, 400, details);\n\t}\n\n\t/**\n\t * Create an unauthorized error (401)\n\t */\n\tstatic unauthorized(message: string = \"Unauthorized\"): PluginRouteError {\n\t\treturn new PluginRouteError(\"UNAUTHORIZED\", message, 401);\n\t}\n\n\t/**\n\t * Create a forbidden error (403)\n\t */\n\tstatic forbidden(message: string = \"Forbidden\"): PluginRouteError {\n\t\treturn new PluginRouteError(\"FORBIDDEN\", message, 403);\n\t}\n\n\t/**\n\t * Create a not found error (404)\n\t */\n\tstatic notFound(message: string = \"Not found\"): PluginRouteError {\n\t\treturn new PluginRouteError(\"NOT_FOUND\", message, 404);\n\t}\n\n\t/**\n\t * Create a conflict error (409)\n\t */\n\tstatic conflict(message: string, details?: unknown): PluginRouteError {\n\t\treturn new PluginRouteError(\"CONFLICT\", message, 409, details);\n\t}\n\n\t/**\n\t * Create an internal error (500)\n\t */\n\tstatic internal(message: string = \"Internal error\"): PluginRouteError {\n\t\treturn new PluginRouteError(\"INTERNAL_ERROR\", message, 500);\n\t}\n}\n","/**\n * Plugin Context v2\n *\n * Creates the unified context object provided to plugins in all hooks and routes.\n *\n */\n\nimport type { Kysely } from \"kysely\";\nimport mime from \"mime/lite\";\nimport { ulid } from \"ulidx\";\n\nimport { GLOBAL_UPLOAD_ALLOWLIST } from \"../api/handlers/media-allowlist.js\";\nimport { handleMediaDelete } from \"../api/handlers/media.js\";\nimport {\n\thandleRedirectCreate,\n\thandleRedirectDelete,\n\thandleRedirectList,\n\thandleRedirectUpdate,\n} from \"../api/handlers/redirects.js\";\nimport { handleTermCreate } from \"../api/handlers/taxonomies.js\";\nimport { CONTENT_TYPE_RE } from \"../api/schemas/media.js\";\nimport { createRedirectBody, updateRedirectBody } from \"../api/schemas/redirects.js\";\nimport { CommentRepository, type Comment } from \"../database/repositories/comment.js\";\nimport { ContentRepository } from \"../database/repositories/content.js\";\nimport { EntryLockRepository } from \"../database/repositories/entry-locks.js\";\nimport { MediaRepository } from \"../database/repositories/media.js\";\nimport { OptionsRepository } from \"../database/repositories/options.js\";\nimport { PluginStorageRepository } from \"../database/repositories/plugin-storage.js\";\nimport {\n\tRedirectRepository,\n\ttype Redirect,\n\ttype VersionedRedirectRecord,\n} from \"../database/repositories/redirect.js\";\nimport { SeoRepository } from \"../database/repositories/seo.js\";\nimport {\n\tfindTaxonomyStructure,\n\tselectTaxonomyDefs,\n} from \"../database/repositories/taxonomy-def.js\";\nimport { TaxonomyRepository, type Taxonomy } from \"../database/repositories/taxonomy.js\";\nimport { UserRepository } from \"../database/repositories/user.js\";\nimport { withTransaction } from \"../database/transaction.js\";\nimport type { Database } from \"../database/types.js\";\nimport { getI18nConfig, resolveContentCreateLocale } from \"../i18n/config.js\";\nimport {\n\tresolveAndValidateExternalUrl,\n\tSsrfError,\n\tstripCredentialHeaders,\n} from \"../import/ssrf.js\";\nimport { enrichImageMetadata } from \"../media/enrich.js\";\nimport { matchesMimeAllowlist, normalizeMime } from \"../media/mime.js\";\nimport { markContentMediaUsageCollectionStaleSafely } from \"../media/usage/content-refresh.js\";\nimport { SchemaRegistry } from \"../schema/registry.js\";\nimport { invalidateSiteSettingsCache } from \"../settings/index.js\";\nimport type { Storage } from \"../storage/types.js\";\nimport { assertStorageKey } from \"./conditional-storage.js\";\nimport { createContentAccess } from \"./content-access.js\";\nimport { CronAccessImpl } from \"./cron.js\";\nimport type { EmailPipeline } from \"./email.js\";\nimport {\n\tbufferPluginHttpRequest,\n\tpluginHttpRedirectAction,\n\tpluginHttpResponseFromWire,\n\tpluginHttpResponseToWire,\n\trewritePluginHttpRedirect,\n} from \"./http-wire.js\";\nimport { readPluginMediaBytes, toPluginMediaItem, updatePluginMediaMetadata } from \"./media.js\";\nimport { PluginRouteError } from \"./route-error.js\";\nimport {\n\tcreatePluginSecretRedactor,\n\tcreateSettingsAccess,\n\ttype PluginSecretRedactor,\n} from \"./settings.js\";\nimport type {\n\tResolvedPlugin,\n\tPluginContext,\n\tPluginStorageConfig,\n\tStorageCollection,\n\tKVAccess,\n\tSettingsAccess,\n\tCronAccess,\n\tEmailAccess,\n\tContentAccess,\n\tContentAccessWithWrite,\n\tVersionedContentItem,\n\tMediaAccess,\n\tMediaAccessWithWrite,\n\tHttpAccess,\n\tLogAccess,\n\tSiteInfo,\n\tUserAccess,\n\tUserInfo,\n\tContentItem,\n\tContentCreateOptions,\n\tContentItemSeoInput,\n\tContentWriteInput,\n\tMediaItem,\n\tPaginatedResult,\n\tQueryOptions,\n\tMediaListOptions,\n\tTaxonomyAccess,\n\tTaxonomyAccessWithWrite,\n\tTaxonomyDefInfo,\n\tTaxonomyTermInfo,\n\tTaxonomyTermCreateInput,\n\tTaxonomyReadOptions,\n\tCommentAccess,\n\tCommentListOptions,\n\tPluginComment,\n\tPluginCommentStatus,\n\tRedirectAccess,\n\tRedirectAccessWithWrite,\n\tRedirectCreateInput,\n\tRedirectInfo,\n\tRedirectListOptions,\n\tRedirectStatus,\n\tRedirectUpdateInput,\n\tVersionedRedirect,\n\tSchemaAccess,\n\tCollectionSchemaInfo,\n\tPluginContentCreateCallback,\n} from \"./types.js\";\n\nexport { createContentAccess } from \"./content-access.js\";\n\n// =============================================================================\n// KV Access\n// =============================================================================\n\n/**\n * Create KV accessor for a plugin\n * All keys are automatically prefixed with the plugin ID\n */\nexport function createKVAccess(\n\toptionsRepo: OptionsRepository,\n\tpluginId: string,\n\tsettings: SettingsAccess = createSettingsAccess(optionsRepo, pluginId),\n): KVAccess {\n\tconst prefix = `plugin:${pluginId}:`;\n\n\treturn {\n\t\tasync get<T>(key: string): Promise<T | null> {\n\t\t\tif (key.startsWith(\"settings:\")) return settings.get<T>(key.slice(\"settings:\".length));\n\t\t\treturn optionsRepo.get<T>(`${prefix}${key}`);\n\t\t},\n\t\tasync getVersioned<T>(key: string) {\n\t\t\tassertStorageKey(key);\n\t\t\tif (key.startsWith(\"settings:\")) {\n\t\t\t\treturn settings.getVersioned<T>(key.slice(\"settings:\".length));\n\t\t\t}\n\t\t\treturn optionsRepo.getVersioned<T>(`${prefix}${key}`);\n\t\t},\n\t\tasync compareAndSet(key, expectedRevision, value) {\n\t\t\tassertStorageKey(key);\n\t\t\tif (key.startsWith(\"settings:\")) {\n\t\t\t\treturn settings.compareAndSet(key.slice(\"settings:\".length), expectedRevision, value);\n\t\t\t}\n\t\t\treturn optionsRepo.compareAndSet(`${prefix}${key}`, expectedRevision, value);\n\t\t},\n\t\tasync compareAndDelete(key, expectedRevision) {\n\t\t\tassertStorageKey(key);\n\t\t\tif (key.startsWith(\"settings:\")) {\n\t\t\t\treturn settings.compareAndDelete(key.slice(\"settings:\".length), expectedRevision);\n\t\t\t}\n\t\t\treturn optionsRepo.compareAndDelete(`${prefix}${key}`, expectedRevision);\n\t\t},\n\n\t\tasync set(key: string, value: unknown): Promise<void> {\n\t\t\tif (key.startsWith(\"settings:\")) {\n\t\t\t\tawait settings.set(key.slice(\"settings:\".length), value);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait optionsRepo.set(`${prefix}${key}`, value);\n\t\t},\n\n\t\tasync delete(key: string): Promise<boolean> {\n\t\t\tif (key.startsWith(\"settings:\")) return settings.delete(key.slice(\"settings:\".length));\n\t\t\treturn optionsRepo.delete(`${prefix}${key}`);\n\t\t},\n\n\t\tasync list(keyPrefix?: string): Promise<Array<{ key: string; value: unknown }>> {\n\t\t\tconst requestedPrefix = keyPrefix ?? \"\";\n\t\t\tconst includesSettings =\n\t\t\t\t\"settings:\".startsWith(requestedPrefix) || requestedPrefix.startsWith(\"settings:\");\n\t\t\tconst fullPrefix = `${prefix}${requestedPrefix}`;\n\t\t\tconst entriesMap = await optionsRepo.getByPrefix(fullPrefix);\n\t\t\tconst result: Array<{ key: string; value: unknown }> = [];\n\t\t\tfor (const [fullKey, value] of entriesMap) {\n\t\t\t\tif (includesSettings && fullKey.startsWith(`${prefix}settings:`)) continue;\n\t\t\t\tresult.push({\n\t\t\t\t\tkey: fullKey.slice(prefix.length),\n\t\t\t\t\tvalue,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (includesSettings) {\n\t\t\t\tconst settingPrefix = requestedPrefix.startsWith(\"settings:\")\n\t\t\t\t\t? requestedPrefix.slice(\"settings:\".length)\n\t\t\t\t\t: \"\";\n\t\t\t\tfor (const entry of await settings.list(settingPrefix)) {\n\t\t\t\t\tconst key = `settings:${entry.key}`;\n\t\t\t\t\tif (key.startsWith(requestedPrefix)) result.push({ key, value: entry.value });\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t};\n}\n\n// =============================================================================\n// Storage Access\n// =============================================================================\n\n/**\n * Create storage collection accessor for a plugin\n * Wraps PluginStorageRepository with the v2 interface (no async iterators)\n */\nfunction createStorageCollection<T>(\n\tdb: Kysely<Database>,\n\tpluginId: string,\n\tcollectionName: string,\n\tindexes: Array<string | string[]>,\n): StorageCollection<T> {\n\tconst repo = new PluginStorageRepository<T>(db, pluginId, collectionName, indexes);\n\n\treturn {\n\t\tget: (id) => repo.get(id),\n\t\tgetVersioned: (id) => repo.getVersioned(id),\n\t\tcompareAndSet: (id, expectedRevision, data) => repo.compareAndSet(id, expectedRevision, data),\n\t\tcompareAndDelete: (id, expectedRevision) => repo.compareAndDelete(id, expectedRevision),\n\t\tput: (id, data) => repo.put(id, data),\n\t\tdelete: (id) => repo.delete(id),\n\t\texists: (id) => repo.exists(id),\n\t\tgetMany: (ids) => repo.getMany(ids),\n\t\tputMany: (items) => repo.putMany(items),\n\t\tdeleteMany: (ids) => repo.deleteMany(ids),\n\t\tcount: (where) => repo.count(where),\n\t\tupdateIf: (id, updateArgs) => repo.updateIf(id, updateArgs),\n\n\t\t// Query returns PaginatedResult instead of the old format\n\t\tasync query(options?: QueryOptions): Promise<PaginatedResult<{ id: string; data: T }>> {\n\t\t\tconst result = await repo.query({\n\t\t\t\twhere: options?.where,\n\t\t\t\torderBy: options?.orderBy,\n\t\t\t\tlimit: options?.limit,\n\t\t\t\tcursor: options?.cursor,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\titems: result.items,\n\t\t\t\tcursor: result.cursor,\n\t\t\t\thasMore: result.hasMore,\n\t\t\t};\n\t\t},\n\t};\n}\n\n/**\n * Create storage accessor with all declared collections\n */\nexport function createStorageAccess<T extends PluginStorageConfig>(\n\tdb: Kysely<Database>,\n\tpluginId: string,\n\tstorageConfig: T,\n): Record<string, StorageCollection> {\n\tconst storage: Record<string, StorageCollection> = {};\n\n\tfor (const [collectionName, config] of Object.entries(storageConfig)) {\n\t\tconst allIndexes = [...config.indexes, ...(config.uniqueIndexes ?? [])];\n\t\tstorage[collectionName] = createStorageCollection(db, pluginId, collectionName, allIndexes);\n\t}\n\n\treturn storage;\n}\n\n// =============================================================================\n// Content Access\n// =============================================================================\n\n/**\n * Extract `seo` from a plugin-supplied content write input and return both\n * parts. Mutates nothing — returns a new field map without the `seo` key.\n */\nfunction splitSeoFromInput(input: ContentWriteInput): {\n\tfields: Record<string, unknown>;\n\tseo: ContentItemSeoInput | undefined;\n} {\n\tconst { seo, ...fields } = input;\n\t// Reject non-object seo values rather than silently dropping them.\n\tif (seo !== undefined && (seo === null || typeof seo !== \"object\" || Array.isArray(seo))) {\n\t\tthrow new Error(\"content.seo must be an object\");\n\t}\n\treturn { fields, seo };\n}\n\n/**\n * Reject writing SEO to a collection that does not have it enabled.\n * Matches the REST API behavior (VALIDATION_ERROR).\n */\nasync function assertSeoEnabled(\n\tseoRepo: SeoRepository,\n\tcollection: string,\n\tseo: ContentItemSeoInput | undefined,\n): Promise<boolean> {\n\tconst hasSeo = await seoRepo.isEnabled(collection);\n\tif (seo !== undefined && !hasSeo) {\n\t\tthrow new Error(\n\t\t\t`Collection \"${collection}\" does not have SEO enabled. ` +\n\t\t\t\t`Remove the seo field or enable SEO on this collection.`,\n\t\t);\n\t}\n\treturn hasSeo;\n}\n\n/**\n * Parse the `collections` JSON column into a string array (`[]` on anything\n * else). Mirrors the guards in the Cloudflare/workerd bridges so an\n * in-process plugin degrades on malformed data instead of crashing.\n */\nfunction parseCollectionsColumn(value: string | null): string[] {\n\tif (!value) return [];\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(value);\n\t\treturn Array.isArray(parsed)\n\t\t\t? parsed.filter((item): item is string => typeof item === \"string\")\n\t\t\t: [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/** Map a repository `Taxonomy` row to the plugin-facing term shape. */\nfunction taxonomyToTermInfo(term: Taxonomy): TaxonomyTermInfo {\n\treturn {\n\t\tid: term.id,\n\t\ttaxonomy: term.name,\n\t\tslug: term.slug,\n\t\tlabel: term.label,\n\t\tparentId: term.parentId,\n\t\tdata: term.data,\n\t\tlocale: term.locale,\n\t\ttranslationGroup: term.translationGroup,\n\t};\n}\n\nfunction collectionToSchemaInfo(\n\tcollection: Awaited<ReturnType<SchemaRegistry[\"getCollectionWithFields\"]>>,\n): CollectionSchemaInfo | null {\n\tif (!collection) return null;\n\treturn {\n\t\tslug: collection.slug,\n\t\tlabel: collection.label,\n\t\tlabelSingular: collection.labelSingular ?? null,\n\t\tdescription: collection.description ?? null,\n\t\tsupports: collection.supports,\n\t\thasSeo: collection.hasSeo,\n\t\ttitleField: collection.titleField ?? null,\n\t\tdateField: collection.dateField ?? null,\n\t\turlPattern: collection.urlPattern ?? null,\n\t\troutable: collection.routable !== false,\n\t\thidden: collection.hidden,\n\t\tfields: collection.fields.map((field) => ({\n\t\t\tslug: field.slug,\n\t\t\tlabel: field.label,\n\t\t\ttype: field.type,\n\t\t\trequired: field.required,\n\t\t\tunique: field.unique,\n\t\t\t...(field.defaultValue === undefined ? {} : { default: field.defaultValue }),\n\t\t\t...(field.validation === undefined ? {} : { validation: field.validation }),\n\t\t\t...(field.widget === undefined ? {} : { widget: field.widget }),\n\t\t\t...(field.options === undefined ? {} : { options: field.options }),\n\t\t\tsearchable: field.searchable,\n\t\t\tindexed: field.indexed,\n\t\t\ttranslatable: field.translatable,\n\t\t\tsortOrder: field.sortOrder,\n\t\t})),\n\t};\n}\n\nexport function createSchemaAccess(db: Kysely<Database>): SchemaAccess {\n\tconst registry = new SchemaRegistry(db);\n\treturn {\n\t\tasync listCollections() {\n\t\t\tconst collections: CollectionSchemaInfo[] = [];\n\t\t\tfor (const collection of await registry.listCollectionsWithFields()) {\n\t\t\t\tconst info = collectionToSchemaInfo(collection);\n\t\t\t\tif (info) collections.push(info);\n\t\t\t}\n\t\t\treturn collections;\n\t\t},\n\t\tasync getCollection(slug) {\n\t\t\treturn collectionToSchemaInfo(await registry.getCollectionWithFields(slug));\n\t\t},\n\t};\n}\n\n/**\n * Create read-only taxonomy access (gated on `taxonomies:read`).\n */\nexport function createTaxonomyAccess(db: Kysely<Database>): TaxonomyAccess {\n\tconst taxonomyRepo = new TaxonomyRepository(db);\n\n\treturn {\n\t\tasync getAll(options?: TaxonomyReadOptions): Promise<TaxonomyDefInfo[]> {\n\t\t\tlet query = selectTaxonomyDefs(db);\n\t\t\tif (options?.locale !== undefined) query = query.where(\"d.locale\", \"=\", options.locale);\n\t\t\tconst rows = await query.orderBy(\"d.name\", \"asc\").execute();\n\t\t\treturn rows.map((row) => ({\n\t\t\t\tname: row.name,\n\t\t\t\tlabel: row.label,\n\t\t\t\tlabelSingular: row.label_singular,\n\t\t\t\thierarchical: row.hierarchical === 1,\n\t\t\t\tcollections: parseCollectionsColumn(row.collections),\n\t\t\t\tlocale: row.locale,\n\t\t\t}));\n\t\t},\n\n\t\tasync getTerms(taxonomy: string, options?: TaxonomyReadOptions): Promise<TaxonomyTermInfo[]> {\n\t\t\tconst terms = await taxonomyRepo.findByName(taxonomy, { locale: options?.locale });\n\t\t\treturn terms.map(taxonomyToTermInfo);\n\t\t},\n\n\t\tasync getEntryTerms(\n\t\t\tcollection: string,\n\t\t\tentryId: string,\n\t\t\toptions?: TaxonomyReadOptions & { taxonomy?: string },\n\t\t): Promise<TaxonomyTermInfo[]> {\n\t\t\tconst terms = await taxonomyRepo.getTermsForEntry(\n\t\t\t\tcollection,\n\t\t\t\tentryId,\n\t\t\t\toptions?.taxonomy,\n\t\t\t\toptions?.locale,\n\t\t\t);\n\t\t\treturn terms.map(taxonomyToTermInfo);\n\t\t},\n\t};\n}\n\nfunction toPluginComment(comment: Comment): PluginComment {\n\tif (comment.status === \"trash\") throw new Error(\"Trashed comments are not plugin-readable\");\n\treturn {\n\t\tid: comment.id,\n\t\tcollection: comment.collection,\n\t\tcontentId: comment.contentId,\n\t\tparentId: comment.parentId,\n\t\tauthorName: comment.authorName,\n\t\tauthorEmail: comment.authorEmail,\n\t\tbody: comment.body,\n\t\tstatus: comment.status,\n\t\tipHash: comment.ipHash,\n\t\tuserAgent: comment.userAgent,\n\t\tmoderationMetadata: comment.moderationMetadata,\n\t\tcreatedAt: comment.createdAt,\n\t\tupdatedAt: comment.updatedAt,\n\t};\n}\n\nexport function createCommentAccess(\n\tdb: Kysely<Database>,\n\tmoderate?: (\n\t\tid: string,\n\t\tstatus: PluginCommentStatus,\n\t\texpectedStatus: PluginCommentStatus,\n\t) => Promise<PluginComment>,\n): CommentAccess {\n\tconst repo = new CommentRepository(db);\n\treturn {\n\t\tasync get(id) {\n\t\t\tconst comment = await repo.findById(id);\n\t\t\treturn !comment || comment.status === \"trash\" ? null : toPluginComment(comment);\n\t\t},\n\t\tasync list(options: CommentListOptions = {}) {\n\t\t\tconst result = await repo.findForPlugin(options);\n\t\t\treturn {\n\t\t\t\titems: result.items.map(toPluginComment),\n\t\t\t\tcursor: result.nextCursor,\n\t\t\t\thasMore: result.nextCursor !== undefined,\n\t\t\t};\n\t\t},\n\t\tcount: (options) => repo.countForPlugin(options),\n\t\t...(moderate\n\t\t\t? {\n\t\t\t\t\tsetStatus: (id, status, options) => moderate(id, status, options.expectedStatus),\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nexport class RedirectAccessError extends Error {\n\toverride readonly name = \"RedirectAccessError\";\n\n\tconstructor(\n\t\treadonly code: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\nconst REDIRECT_REVISION_PREFIX = \"r1.\";\nconst BASE64_PADDING_RE = /=+$/;\n\nfunction encodeRedirectRevision(id: string, revision: string): string {\n\tconst payload = `${id}\\0${revision}`;\n\treturn `${REDIRECT_REVISION_PREFIX}${btoa(payload)\n\t\t.replaceAll(\"+\", \"-\")\n\t\t.replaceAll(\"/\", \"_\")\n\t\t.replace(BASE64_PADDING_RE, \"\")}`;\n}\n\nfunction decodeRedirectRevision(id: string, revision: string): string {\n\tif (typeof revision !== \"string\" || !revision.startsWith(REDIRECT_REVISION_PREFIX)) {\n\t\tthrow new RedirectAccessError(\"INVALID_PRECONDITION\", \"Invalid redirect revision\");\n\t}\n\ttry {\n\t\tconst encoded = revision\n\t\t\t.slice(REDIRECT_REVISION_PREFIX.length)\n\t\t\t.replaceAll(\"-\", \"+\")\n\t\t\t.replaceAll(\"_\", \"/\");\n\t\tconst padded = encoded.padEnd(Math.ceil(encoded.length / 4) * 4, \"=\");\n\t\tconst [revisionId, updatedAt, extra] = atob(padded).split(\"\\0\");\n\t\tif (revisionId !== id || !updatedAt || extra !== undefined) throw new Error(\"invalid\");\n\t\treturn updatedAt;\n\t} catch (error) {\n\t\tif (error instanceof RedirectAccessError) throw error;\n\t\tthrow new RedirectAccessError(\"INVALID_PRECONDITION\", \"Invalid redirect revision\");\n\t}\n}\n\nfunction toRedirectInfo(redirect: Redirect): RedirectInfo {\n\treturn {\n\t\t...redirect,\n\t\ttype: redirect.type as RedirectStatus,\n\t};\n}\n\nfunction toVersionedRedirect(record: VersionedRedirectRecord): VersionedRedirect {\n\treturn {\n\t\tredirect: toRedirectInfo(record.redirect),\n\t\t_rev: encodeRedirectRevision(record.redirect.id, record.configRevision),\n\t};\n}\n\nasync function readVersionedRedirect(\n\trepo: RedirectRepository,\n\tid: string,\n): Promise<VersionedRedirect | null> {\n\tconst record = await repo.findVersionedById(id);\n\treturn record ? toVersionedRedirect(record) : null;\n}\n\nfunction throwRedirectResult(error: { code: string; message: string }): never {\n\tthrow new RedirectAccessError(error.code, error.message);\n}\n\nfunction assertNoAutomaticRedirectMarker(input: object): void {\n\tif (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n\t\tthrow new RedirectAccessError(\"VALIDATION_ERROR\", \"Redirect input must be an object\");\n\t}\n\tif (Object.hasOwn(input, \"auto\")) {\n\t\tthrow new RedirectAccessError(\n\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\"The automatic redirect marker is managed by EmDash\",\n\t\t);\n\t}\n}\n\nexport function createRedirectAccess(db: Kysely<Database>): RedirectAccess;\nexport function createRedirectAccess(db: Kysely<Database>, writable: true): RedirectAccessWithWrite;\nexport function createRedirectAccess(\n\tdb: Kysely<Database>,\n\twritable = false,\n): RedirectAccess | RedirectAccessWithWrite {\n\tconst repo = new RedirectRepository(db);\n\tconst readAccess: RedirectAccess = {\n\t\tasync list(options: RedirectListOptions = {}) {\n\t\t\tconst result = await handleRedirectList(db, options);\n\t\t\tif (!result.success) return throwRedirectResult(result.error);\n\t\t\treturn {\n\t\t\t\titems: result.data.items.map(toRedirectInfo),\n\t\t\t\tcursor: result.data.nextCursor,\n\t\t\t\thasMore: result.data.nextCursor !== undefined,\n\t\t\t};\n\t\t},\n\t\tget: (id: string) => readVersionedRedirect(repo, id),\n\t};\n\tif (!writable) return readAccess;\n\n\treturn {\n\t\t...readAccess,\n\t\tasync create(input: RedirectCreateInput) {\n\t\t\tassertNoAutomaticRedirectMarker(input);\n\t\t\tconst parsed = createRedirectBody.safeParse(input);\n\t\t\tif (!parsed.success) {\n\t\t\t\tthrow new RedirectAccessError(\n\t\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t\tparsed.error.issues[0]?.message ?? \"Invalid redirect\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst result = await handleRedirectCreate(db, parsed.data);\n\t\t\tif (!result.success) return throwRedirectResult(result.error);\n\t\t\tconst current = await readVersionedRedirect(repo, result.data.id);\n\t\t\tif (!current) throw new RedirectAccessError(\"NOT_FOUND\", \"Created redirect not found\");\n\t\t\treturn current;\n\t\t},\n\t\tasync update(id: string, input: RedirectUpdateInput & { _rev: string }) {\n\t\t\tassertNoAutomaticRedirectMarker(input);\n\t\t\tconst { _rev, ...patch } = input;\n\t\t\tconst expectedRevision = decodeRedirectRevision(id, _rev);\n\t\t\tconst parsed = updateRedirectBody.safeParse(patch);\n\t\t\tif (!parsed.success) {\n\t\t\t\tthrow new RedirectAccessError(\n\t\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t\tparsed.error.issues[0]?.message ?? \"Invalid redirect\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst result = await handleRedirectUpdate(db, id, parsed.data, { expectedRevision });\n\t\t\tif (!result.success) return throwRedirectResult(result.error);\n\t\t\tconst current = await readVersionedRedirect(repo, result.data.id);\n\t\t\tif (!current) throw new RedirectAccessError(\"NOT_FOUND\", \"Updated redirect not found\");\n\t\t\treturn current;\n\t\t},\n\t\tasync delete(id: string, options: { _rev: string }) {\n\t\t\tif (typeof options !== \"object\" || options === null) {\n\t\t\t\tthrow new RedirectAccessError(\"INVALID_PRECONDITION\", \"Invalid redirect revision\");\n\t\t\t}\n\t\t\tconst expectedRevision = decodeRedirectRevision(id, options._rev);\n\t\t\tconst result = await handleRedirectDelete(db, id, { expectedRevision });\n\t\t\tif (!result.success) return throwRedirectResult(result.error);\n\t\t\treturn result.data.deleted;\n\t\t},\n\t};\n}\n\nconst MAX_TAXONOMY_DELTA_TERMS = 64;\n\nfunction taxonomyAccessError(code: string, message: string): Error {\n\treturn Object.assign(new Error(message), { code });\n}\n\nasync function resolveTaxonomyDelta(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tentryId: string,\n\ttaxonomy: string,\n\ttermIds: string[],\n): Promise<{ repo: TaxonomyRepository; groups: string[]; locale: string }> {\n\tif (termIds.length > MAX_TAXONOMY_DELTA_TERMS) {\n\t\tthrow taxonomyAccessError(\n\t\t\t\"VALIDATION_ERROR\",\n\t\t\t`A taxonomy assignment delta can contain at most ${MAX_TAXONOMY_DELTA_TERMS} term IDs`,\n\t\t);\n\t}\n\tif (termIds.some((id) => typeof id !== \"string\" || id.length === 0)) {\n\t\tthrow taxonomyAccessError(\"VALIDATION_ERROR\", \"Taxonomy term IDs must be non-empty strings\");\n\t}\n\n\tconst structure = await findTaxonomyStructure(db, taxonomy);\n\tif (!structure) {\n\t\tthrow taxonomyAccessError(\"NOT_FOUND\", `Taxonomy '${taxonomy}' not found`);\n\t}\n\tconst attached = structure.collections.includes(collection);\n\tif (!attached) {\n\t\tthrow taxonomyAccessError(\n\t\t\t\"VALIDATION_ERROR\",\n\t\t\t`Taxonomy '${taxonomy}' is not attached to collection '${collection}'`,\n\t\t);\n\t}\n\n\tconst entry = await new ContentRepository(db).findById(collection, entryId);\n\tif (!entry) {\n\t\tthrow taxonomyAccessError(\n\t\t\t\"NOT_FOUND\",\n\t\t\t`Content entry '${entryId}' not found in '${collection}'`,\n\t\t);\n\t}\n\n\tconst repo = new TaxonomyRepository(db);\n\tconst groups: string[] = [];\n\tfor (const id of new Set(termIds)) {\n\t\tconst term = await repo.findByIdOrTranslationGroup(id);\n\t\tif (!term) throw taxonomyAccessError(\"NOT_FOUND\", `Taxonomy term '${id}' not found`);\n\t\tif (term.name !== taxonomy) {\n\t\t\tthrow taxonomyAccessError(\n\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t`Taxonomy term '${id}' belongs to '${term.name}', not '${taxonomy}'`,\n\t\t\t);\n\t\t}\n\t\tgroups.push(term.translationGroup ?? term.id);\n\t}\n\n\treturn { repo, groups, locale: entry.locale ?? getI18nConfig()?.defaultLocale ?? \"en\" };\n}\n\nasync function readResolvedEntryTerms(\n\trepo: TaxonomyRepository,\n\tcollection: string,\n\tentryId: string,\n\ttaxonomy: string,\n\tlocale: string,\n): Promise<TaxonomyTermInfo[]> {\n\tconst defaultLocale = getI18nConfig()?.defaultLocale ?? locale;\n\tconst assignments = await repo.getTermAssignmentsForEntry(\n\t\tcollection,\n\t\tentryId,\n\t\ttaxonomy,\n\t\tlocale,\n\t\tdefaultLocale,\n\t);\n\treturn assignments.flatMap(({ term }) => (term ? [taxonomyToTermInfo(term)] : []));\n}\n\nexport function createTaxonomyAccessWithWrite(db: Kysely<Database>): TaxonomyAccessWithWrite {\n\treturn {\n\t\t...createTaxonomyAccess(db),\n\t\tasync createTerm(taxonomy: string, input: TaxonomyTermCreateInput) {\n\t\t\tconst result = await handleTermCreate(db, taxonomy, input);\n\t\t\tif (!result.success) throw taxonomyAccessError(result.error.code, result.error.message);\n\t\t\tconst { term } = result.data;\n\t\t\treturn {\n\t\t\t\tid: term.id,\n\t\t\t\ttaxonomy: term.name,\n\t\t\t\tslug: term.slug,\n\t\t\t\tlabel: term.label,\n\t\t\t\tparentId: term.parentId,\n\t\t\t\tdata: term.description ? { description: term.description } : null,\n\t\t\t\tlocale: term.locale,\n\t\t\t\ttranslationGroup: term.translationGroup,\n\t\t\t};\n\t\t},\n\t\tasync addEntryTerms(collection, entryId, taxonomy, termIds) {\n\t\t\tconst { repo, groups, locale } = await resolveTaxonomyDelta(\n\t\t\t\tdb,\n\t\t\t\tcollection,\n\t\t\t\tentryId,\n\t\t\t\ttaxonomy,\n\t\t\t\ttermIds,\n\t\t\t);\n\t\t\tawait repo.attachGroupsToEntry(collection, entryId, groups);\n\t\t\treturn readResolvedEntryTerms(repo, collection, entryId, taxonomy, locale);\n\t\t},\n\t\tasync removeEntryTerms(collection, entryId, taxonomy, termIds) {\n\t\t\tconst { repo, groups, locale } = await resolveTaxonomyDelta(\n\t\t\t\tdb,\n\t\t\t\tcollection,\n\t\t\t\tentryId,\n\t\t\t\ttaxonomy,\n\t\t\t\ttermIds,\n\t\t\t);\n\t\t\tawait repo.detachGroupsFromEntry(collection, entryId, groups);\n\t\t\treturn readResolvedEntryTerms(repo, collection, entryId, taxonomy, locale);\n\t\t},\n\t};\n}\n\n/**\n * Called immediately before a plugin content write; it throws to refuse the\n * write. When it returns a function, that function is called once the write\n * has succeeded.\n */\nexport type ContentWriteGuard = () => Promise<void | (() => Promise<void>)>;\n\nasync function afterContentWrite(recordWrite: void | (() => Promise<void>)): Promise<void> {\n\tif (typeof recordWrite === \"function\") await recordWrite();\n}\n\n/**\n * Create full content access with write operations.\n *\n * `create` and `update` accept a reserved `seo` key in their `data`\n * argument. When present, it is routed to the core SEO panel\n * (`_emdash_seo`) via `SeoRepository.upsert`, in the same transaction as\n * the content write. The returned `ContentItem.seo` reflects the resulting\n * SEO state for SEO-enabled collections.\n */\nexport function createContentAccessWithWrite(\n\tdb: Kysely<Database>,\n\tbeforeContentWrite?: ContentWriteGuard,\n\taccessOptions?: { site?: SiteInfo; revisions?: boolean },\n\tcontentCreate?: (data: {\n\t\tcollection: string;\n\t\tinput: ContentWriteInput;\n\t\toptions?: ContentCreateOptions;\n\t}) => Promise<ContentItem>,\n): ContentAccessWithWrite {\n\tconst readAccess = createContentAccess(db, accessOptions);\n\n\treturn {\n\t\t...readAccess,\n\n\t\tasync create(\n\t\t\tcollection: string,\n\t\t\tdata: ContentWriteInput,\n\t\t\toptions?: ContentCreateOptions,\n\t\t): Promise<ContentItem> {\n\t\t\tconst locale = resolveContentCreateLocale(options?.locale);\n\t\t\tconst recordWrite = await beforeContentWrite?.();\n\t\t\tif (contentCreate) {\n\t\t\t\tconst created = await contentCreate({\n\t\t\t\t\tcollection,\n\t\t\t\t\tinput: data,\n\t\t\t\t\toptions: { ...options, locale },\n\t\t\t\t});\n\t\t\t\tawait afterContentWrite(recordWrite);\n\t\t\t\treturn created;\n\t\t\t}\n\t\t\tconst { fields, seo } = splitSeoFromInput(data);\n\t\t\tlet contentMutated = false;\n\n\t\t\ttry {\n\t\t\t\tconst created = await withTransaction(db, async (trx) => {\n\t\t\t\t\tconst trxContentRepo = new ContentRepository(trx);\n\t\t\t\t\tconst trxSeoRepo = new SeoRepository(trx);\n\n\t\t\t\t\tconst hasSeo = await assertSeoEnabled(trxSeoRepo, collection, seo);\n\n\t\t\t\t\tconst item = await trxContentRepo.create({\n\t\t\t\t\t\ttype: collection,\n\t\t\t\t\t\tdata: fields,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\ttranslationOf: options?.translationOf,\n\t\t\t\t\t});\n\t\t\t\t\tcontentMutated = true;\n\n\t\t\t\t\tconst result: ContentItem = {\n\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\ttype: item.type,\n\t\t\t\t\t\tslug: item.slug,\n\t\t\t\t\t\tstatus: item.status,\n\t\t\t\t\t\tdata: item.data,\n\t\t\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\t\t\tlocale: item.locale,\n\t\t\t\t\t\tpublishedAt: item.publishedAt,\n\t\t\t\t\t\tscheduledAt: item.scheduledAt,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (hasSeo) {\n\t\t\t\t\t\tresult.seo =\n\t\t\t\t\t\t\tseo !== undefined\n\t\t\t\t\t\t\t\t? await trxSeoRepo.upsert(collection, item.id, seo)\n\t\t\t\t\t\t\t\t: await trxSeoRepo.get(collection, item.id);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn result;\n\t\t\t\t});\n\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(db, collection, \"CONTENT_USAGE_STALE\");\n\t\t\t\tawait afterContentWrite(recordWrite);\n\t\t\t\treturn created;\n\t\t\t} catch (error) {\n\t\t\t\tif (contentMutated) {\n\t\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(db, collection, \"CONTENT_USAGE_STALE\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\n\t\tasync update(collection: string, id: string, data: ContentWriteInput): Promise<ContentItem> {\n\t\t\tconst recordWrite = await beforeContentWrite?.();\n\t\t\tconst { fields, seo } = splitSeoFromInput(data);\n\t\t\tconst hasFieldUpdates = Object.keys(fields).length > 0;\n\t\t\tlet contentMutated = false;\n\n\t\t\ttry {\n\t\t\t\tconst updated = await withTransaction(db, async (trx) => {\n\t\t\t\t\tconst trxContentRepo = new ContentRepository(trx);\n\t\t\t\t\tconst trxSeoRepo = new SeoRepository(trx);\n\n\t\t\t\t\tconst hasSeo = await assertSeoEnabled(trxSeoRepo, collection, seo);\n\n\t\t\t\t\t// Pass the `data` payload to ContentRepository.updateDraftAware only when\n\t\t\t\t\t// there are field updates — passing an empty object would still\n\t\t\t\t\t// bump updated_at/version, but we want a seo-only call to touch\n\t\t\t\t\t// only the SEO table. updateDraftAware delegates no-op writes to\n\t\t\t\t\t// ContentRepository.update.\n\t\t\t\t\tconst item = hasFieldUpdates\n\t\t\t\t\t\t? await trxContentRepo.updateDraftAware(collection, id, { data: fields })\n\t\t\t\t\t\t: await (async () => {\n\t\t\t\t\t\t\t\tconst existing = await trxContentRepo.findById(collection, id);\n\t\t\t\t\t\t\t\tif (!existing) throw new Error(\"Content not found\");\n\t\t\t\t\t\t\t\treturn existing;\n\t\t\t\t\t\t\t})();\n\t\t\t\t\tif (hasFieldUpdates) contentMutated = true;\n\n\t\t\t\t\tconst result: ContentItem = {\n\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\ttype: item.type,\n\t\t\t\t\t\tslug: item.slug,\n\t\t\t\t\t\tstatus: item.status,\n\t\t\t\t\t\tdata: item.data,\n\t\t\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\t\t\tlocale: item.locale,\n\t\t\t\t\t\tpublishedAt: item.publishedAt,\n\t\t\t\t\t\tscheduledAt: item.scheduledAt,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (hasSeo) {\n\t\t\t\t\t\tresult.seo =\n\t\t\t\t\t\t\tseo !== undefined\n\t\t\t\t\t\t\t\t? await trxSeoRepo.upsert(collection, item.id, seo)\n\t\t\t\t\t\t\t\t: await trxSeoRepo.get(collection, item.id);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn result;\n\t\t\t\t});\n\t\t\t\tif (hasFieldUpdates) {\n\t\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(db, collection, \"CONTENT_USAGE_STALE\");\n\t\t\t\t}\n\t\t\t\tawait afterContentWrite(recordWrite);\n\t\t\t\treturn updated;\n\t\t\t} catch (error) {\n\t\t\t\tif (contentMutated) {\n\t\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(db, collection, \"CONTENT_USAGE_STALE\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\n\t\tasync delete(collection: string, id: string): Promise<boolean> {\n\t\t\tconst recordWrite = await beforeContentWrite?.();\n\t\t\tconst contentRepo = new ContentRepository(db);\n\t\t\tconst deleted = await contentRepo.delete(collection, id);\n\t\t\tif (deleted) {\n\t\t\t\t// A trashed entry can no longer be opened, so its holder can never\n\t\t\t\t// release the lease itself. Mirrors handleContentDelete.\n\t\t\t\tawait new EntryLockRepository(db).releaseEntry(collection, id);\n\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(db, collection, \"CONTENT_USAGE_STALE\");\n\t\t\t\tawait afterContentWrite(recordWrite);\n\t\t\t}\n\t\t\treturn deleted;\n\t\t},\n\t};\n}\n\n// =============================================================================\n// Media Access\n// =============================================================================\n\n/**\n * Create read-only media access\n */\nexport function createMediaAccess(db: Kysely<Database>): MediaAccess {\n\tconst mediaRepo = new MediaRepository(db);\n\n\treturn {\n\t\tasync get(id: string): Promise<MediaItem | null> {\n\t\t\tconst item = await mediaRepo.findById(id);\n\t\t\treturn item?.status === \"ready\" ? toPluginMediaItem(item) : null;\n\t\t},\n\n\t\tasync list(options?: MediaListOptions): Promise<PaginatedResult<MediaItem>> {\n\t\t\tconst result = await mediaRepo.findMany({\n\t\t\t\tlimit: options?.limit ?? 50,\n\t\t\t\tcursor: options?.cursor,\n\t\t\t\tmimeType: options?.mimeType,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\titems: result.items.map(toPluginMediaItem),\n\t\t\t\tcursor: result.nextCursor,\n\t\t\t\thasMore: !!result.nextCursor,\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction mediaReadDenied(): never {\n\tthrow new Error(\"Missing capability: media:read\");\n}\n\nfunction createBlockedMediaReadAccess(): MediaAccess {\n\treturn {\n\t\tget: async () => mediaReadDenied(),\n\t\tlist: async () => mediaReadDenied(),\n\t};\n}\n\nfunction allowedUploadType(contentType: string): string {\n\tif (!CONTENT_TYPE_RE.test(contentType)) {\n\t\tthrow PluginRouteError.badRequest(\"Invalid content type\");\n\t}\n\tconst mimeType = normalizeMime(contentType);\n\tif (!matchesMimeAllowlist(mimeType, GLOBAL_UPLOAD_ALLOWLIST)) {\n\t\tthrow new PluginRouteError(\"UNSUPPORTED_MEDIA_TYPE\", \"File type not allowed\", 415);\n\t}\n\treturn mimeType;\n}\n\nfunction uploadStorageKey(\n\tfilename: string,\n\tmimeType: string,\n): { basename: string; storageKey: string } {\n\tconst keyPrefix = ulid();\n\tconst basename = filename.split(\"/\").pop() ?? filename;\n\tconst dotIdx = basename.lastIndexOf(\".\");\n\tconst nameExt = dotIdx > 0 ? basename.slice(dotIdx + 1).toLowerCase() : \"\";\n\t// Local storage serves files by their key's extension, so it must map to an allowed type.\n\tconst nameType = mime.getType(nameExt);\n\tconst nameExtAllowed =\n\t\tnameType !== null && matchesMimeAllowlist(nameType, GLOBAL_UPLOAD_ALLOWLIST);\n\tconst ext =\n\t\tnameType === mimeType\n\t\t\t? nameExt\n\t\t\t: (mime.getExtension(mimeType) ?? (nameExtAllowed ? nameExt : null));\n\treturn { basename, storageKey: ext ? `${keyPrefix}.${ext}` : keyPrefix };\n}\n\n/**\n * Create full media access with write operations.\n *\n * `getUploadUrlFn` is optional: when omitted, `getUploadUrl()` is derived from\n * `storage` (create a pending record + a signed PUT URL), mirroring the REST\n * `/_emdash/api/media/upload-url` endpoint. `upload()` only needs `storage`.\n * If storage is not provided, both throw at call time.\n */\nexport function createMediaAccessWithWrite(\n\tdb: Kysely<Database>,\n\tgetUploadUrlFn:\n\t\t| ((filename: string, contentType: string) => Promise<{ uploadUrl: string; mediaId: string }>)\n\t\t| undefined,\n\tstorage?: Storage,\n): MediaAccessWithWrite {\n\tconst mediaRepo = new MediaRepository(db);\n\tconst readAccess = createMediaAccess(db);\n\n\tconst getUploadUrl = getUploadUrlFn\n\t\t? async (filename: string, contentType: string) =>\n\t\t\t\tgetUploadUrlFn(filename, allowedUploadType(contentType))\n\t\t: async (filename: string, contentType: string) => {\n\t\t\t\tif (!storage) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Media getUploadUrl() requires a storage backend. Configure storage in PluginContextFactoryOptions.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst mimeType = allowedUploadType(contentType);\n\t\t\t\tconst { basename, storageKey } = uploadStorageKey(filename, mimeType);\n\n\t\t\t\tconst media = await mediaRepo.createPending({\n\t\t\t\t\tfilename: basename,\n\t\t\t\t\tmimeType,\n\t\t\t\t\tstorageKey,\n\t\t\t\t});\n\n\t\t\t\tconst signed = await storage.getSignedUploadUrl({\n\t\t\t\t\tkey: storageKey,\n\t\t\t\t\tcontentType: mimeType,\n\t\t\t\t\texpiresIn: 3600,\n\t\t\t\t});\n\n\t\t\t\treturn { uploadUrl: signed.url, mediaId: media.id };\n\t\t\t};\n\n\treturn {\n\t\t...readAccess,\n\n\t\tgetUploadUrl,\n\n\t\tasync upload(\n\t\t\tfilename: string,\n\t\t\tcontentType: string,\n\t\t\tbytes: ArrayBuffer,\n\t\t): Promise<{ mediaId: string; storageKey: string; url: string }> {\n\t\t\tif (!storage) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Media upload() requires a storage backend. Configure storage in PluginContextFactoryOptions.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst mimeType = allowedUploadType(contentType);\n\t\t\tconst { basename, storageKey } = uploadStorageKey(filename, mimeType);\n\n\t\t\t// Upload to storage first\n\t\t\tawait storage.upload({\n\t\t\t\tkey: storageKey,\n\t\t\t\tbody: new Uint8Array(bytes),\n\t\t\t\tcontentType: mimeType,\n\t\t\t});\n\n\t\t\t// Derive dimensions + LQIP placeholders (no-op for non-images).\n\t\t\tconst enriched = await enrichImageMetadata(new Uint8Array(bytes), mimeType);\n\n\t\t\t// Create DB record — clean up storage on failure\n\t\t\tlet media;\n\t\t\ttry {\n\t\t\t\tmedia = await mediaRepo.create({\n\t\t\t\t\tfilename: basename,\n\t\t\t\t\tmimeType,\n\t\t\t\t\tsize: bytes.byteLength,\n\t\t\t\t\tstorageKey,\n\t\t\t\t\tstatus: \"ready\",\n\t\t\t\t\twidth: enriched.width,\n\t\t\t\t\theight: enriched.height,\n\t\t\t\t\tblurhash: enriched.blurhash,\n\t\t\t\t\tdominantColor: enriched.dominantColor,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tawait storage.delete(storageKey);\n\t\t\t\t} catch {\n\t\t\t\t\t// Best-effort cleanup\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tmediaId: media.id,\n\t\t\t\tstorageKey,\n\t\t\t\turl: `/_emdash/api/media/file/${storageKey}`,\n\t\t\t};\n\t\t},\n\n\t\tasync delete(id: string): Promise<boolean> {\n\t\t\tconst result = await handleMediaDelete(db, id, storage);\n\t\t\tif (!result.success) {\n\t\t\t\tif (result.error.code === \"NOT_FOUND\") return false;\n\t\t\t\tthrow new Error(result.error.message);\n\t\t\t}\n\t\t\t// Plugins can delete media that's referenced by site settings\n\t\t\t// (`logo`, `favicon`, `seo.defaultOgImage`); the worker-scoped\n\t\t\t// resolved-URL cache must be dropped or it will keep serving\n\t\t\t// 404s. Matches the invalidation in\n\t\t\t// `EmDashRuntime.handleMediaDelete`.\n\t\t\tinvalidateSiteSettingsCache();\n\t\t\treturn true;\n\t\t},\n\t};\n}\n\n// =============================================================================\n// HTTP Access\n// =============================================================================\n\n/** Maximum number of redirects to follow in plugin HTTP access */\nconst MAX_PLUGIN_REDIRECTS = 5;\n\nfunction stripTrailingDots(value: string): string {\n\tlet end = value.length;\n\twhile (end > 0 && value.charCodeAt(end - 1) === 46) end--;\n\treturn end === value.length ? value : value.slice(0, end);\n}\n\n/**\n * Check if a hostname matches any pattern in the allowed list.\n * Patterns: \"*\" matches all, \"*.example.com\" matches subdomains AND bare \"example.com\",\n * \"api.example.com\" matches exactly.\n */\nfunction isHostAllowed(host: string, allowedHosts: string[]): boolean {\n\tconst normalizedHost = stripTrailingDots(host.toLowerCase());\n\treturn allowedHosts.some((pattern) => {\n\t\tconst normalizedPattern = stripTrailingDots(pattern.toLowerCase());\n\t\tif (normalizedPattern === \"*\") return true;\n\t\tif (normalizedPattern.startsWith(\"*.\")) {\n\t\t\tconst suffix = normalizedPattern.slice(1); // \".example.com\"\n\t\t\t// Match subdomains (foo.example.com) and bare domain (example.com)\n\t\t\treturn normalizedHost.endsWith(suffix) || normalizedHost === normalizedPattern.slice(2);\n\t\t}\n\t\treturn normalizedHost === normalizedPattern;\n\t});\n}\n\nfunction tryParsePluginHttpTarget(url: string): URL | null {\n\ttry {\n\t\treturn new URL(url);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function validatePluginHttpTarget(pluginId: string, url: string): Promise<URL> {\n\ttry {\n\t\treturn await resolveAndValidateExternalUrl(url);\n\t} catch (error) {\n\t\tconst message = error instanceof SsrfError ? error.message : \"SSRF validation failed\";\n\t\tconst target = tryParsePluginHttpTarget(url);\n\t\tthrow new Error(\n\t\t\t`Plugin \"${pluginId}\": blocked fetch to \"${target ? target.hostname : \"invalid URL\"}\": ${message}`,\n\t\t\t{ cause: error },\n\t\t);\n\t}\n}\n\n/**\n * Create HTTP access with host validation and SSRF protection.\n *\n * Uses redirect: \"manual\" to re-validate each redirect target before dispatch.\n */\nexport function createHttpAccess(\n\tpluginId: string,\n\tallowedHosts: string[],\n\tfetchImpl: typeof fetch = globalThis.fetch,\n): HttpAccess {\n\treturn {\n\t\tasync fetch(url: string, init?: RequestInit): Promise<Response> {\n\t\t\t// Deny by default — plugins must declare allowed hosts\n\t\t\tif (allowedHosts.length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Plugin \"${pluginId}\" has no allowed hosts configured. ` +\n\t\t\t\t\t\t`Add hosts to the plugin's allowedHosts array to enable HTTP requests.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet currentUrl = url;\n\t\t\tlet currentInit = init;\n\t\t\tlet requestBuffered = false;\n\t\t\tlet redirected = false;\n\n\t\t\tfor (let i = 0; i <= MAX_PLUGIN_REDIRECTS; i++) {\n\t\t\t\tconst target = tryParsePluginHttpTarget(currentUrl);\n\t\t\t\tif (target && !isHostAllowed(target.hostname, allowedHosts)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Plugin \"${pluginId}\" is not allowed to fetch from host \"${target.hostname}\". ` +\n\t\t\t\t\t\t\t`Allowed hosts: ${allowedHosts.join(\", \")}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait validatePluginHttpTarget(pluginId, currentUrl);\n\t\t\t\tif (!requestBuffered) {\n\t\t\t\t\tcurrentInit = await bufferPluginHttpRequest(currentInit);\n\t\t\t\t\trequestBuffered = true;\n\t\t\t\t}\n\n\t\t\t\tconst response = await fetchImpl(currentUrl, {\n\t\t\t\t\t...currentInit,\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t});\n\n\t\t\t\tconst location = response.headers.get(\"Location\");\n\t\t\t\tif (location === null) {\n\t\t\t\t\treturn pluginHttpResponseFromWire(\n\t\t\t\t\t\tawait pluginHttpResponseToWire(response, currentUrl, redirected),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst redirectAction = pluginHttpRedirectAction(response.status, true, currentInit);\n\t\t\t\tif (redirectAction === \"return\") {\n\t\t\t\t\treturn pluginHttpResponseFromWire(\n\t\t\t\t\t\tawait pluginHttpResponseToWire(response, currentUrl, redirected),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tif (redirectAction === \"error\") {\n\t\t\t\t\tthrow new Error(`Plugin \"${pluginId}\": redirect mode is \"error\"`);\n\t\t\t\t}\n\n\t\t\t\t// Resolve relative redirects; strip credentials on cross-origin hops\n\t\t\t\tconst previousOrigin = new URL(currentUrl).origin;\n\t\t\t\tcurrentUrl = new URL(location, currentUrl).href;\n\t\t\t\tredirected = true;\n\t\t\t\tconst nextOrigin = new URL(currentUrl).origin;\n\t\t\t\tcurrentInit = rewritePluginHttpRedirect(response.status, currentInit);\n\n\t\t\t\tif (previousOrigin !== nextOrigin && currentInit) {\n\t\t\t\t\tcurrentInit = stripCredentialHeaders(currentInit);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`Plugin \"${pluginId}\": too many redirects (max ${MAX_PLUGIN_REDIRECTS})`);\n\t\t},\n\t};\n}\n\n/**\n * Create unrestricted HTTP access (for plugins with network:request:unrestricted capability).\n * No host validation, but applies SSRF protection on redirect targets to\n * prevent plugins from being tricked into reaching internal services.\n */\nexport function createUnrestrictedHttpAccess(\n\tpluginId: string,\n\tfetchImpl: typeof fetch = globalThis.fetch,\n): HttpAccess {\n\treturn {\n\t\tasync fetch(url: string, init?: RequestInit): Promise<Response> {\n\t\t\tlet currentUrl = url;\n\t\t\tlet currentInit = init;\n\t\t\tlet requestBuffered = false;\n\t\t\tlet redirected = false;\n\n\t\t\tfor (let i = 0; i <= MAX_PLUGIN_REDIRECTS; i++) {\n\t\t\t\tawait validatePluginHttpTarget(pluginId, currentUrl);\n\t\t\t\tif (!requestBuffered) {\n\t\t\t\t\tcurrentInit = await bufferPluginHttpRequest(currentInit);\n\t\t\t\t\trequestBuffered = true;\n\t\t\t\t}\n\n\t\t\t\tconst response = await fetchImpl(currentUrl, {\n\t\t\t\t\t...currentInit,\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t});\n\n\t\t\t\tconst location = response.headers.get(\"Location\");\n\t\t\t\tif (location === null) {\n\t\t\t\t\treturn pluginHttpResponseFromWire(\n\t\t\t\t\t\tawait pluginHttpResponseToWire(response, currentUrl, redirected),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst redirectAction = pluginHttpRedirectAction(response.status, true, currentInit);\n\t\t\t\tif (redirectAction === \"return\") {\n\t\t\t\t\treturn pluginHttpResponseFromWire(\n\t\t\t\t\t\tawait pluginHttpResponseToWire(response, currentUrl, redirected),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tif (redirectAction === \"error\") {\n\t\t\t\t\tthrow new Error(`Plugin \"${pluginId}\": redirect mode is \"error\"`);\n\t\t\t\t}\n\n\t\t\t\t// Resolve relative redirects; strip credentials on cross-origin hops\n\t\t\t\tconst previousOrigin = new URL(currentUrl).origin;\n\t\t\t\tcurrentUrl = new URL(location, currentUrl).href;\n\t\t\t\tredirected = true;\n\t\t\t\tconst nextOrigin = new URL(currentUrl).origin;\n\t\t\t\tcurrentInit = rewritePluginHttpRedirect(response.status, currentInit);\n\n\t\t\t\tif (previousOrigin !== nextOrigin && currentInit) {\n\t\t\t\t\tcurrentInit = stripCredentialHeaders(currentInit);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`Plugin \"${pluginId}\": too many redirects (max ${MAX_PLUGIN_REDIRECTS})`);\n\t\t},\n\t};\n}\n\n/**\n * Create blocked HTTP access (for plugins without network:request capability)\n */\nexport function createBlockedHttpAccess(pluginId: string): HttpAccess {\n\treturn {\n\t\tasync fetch(): Promise<never> {\n\t\t\tthrow new Error(\n\t\t\t\t`Plugin \"${pluginId}\" does not have the \"network:request\" capability. ` +\n\t\t\t\t\t`Add \"network:request\" to the plugin's capabilities to enable HTTP requests.`,\n\t\t\t);\n\t\t},\n\t};\n}\n\n// =============================================================================\n// Log Access\n// =============================================================================\n\n/**\n * Create logger for a plugin\n */\nexport function createLogAccess(pluginId: string, redactor?: PluginSecretRedactor): LogAccess {\n\tconst prefix = `[plugin:${pluginId}]`;\n\tconst redact = <T>(value: T): T => redactor?.redact(value) ?? value;\n\n\treturn {\n\t\tdebug(message: string, data?: unknown): void {\n\t\t\tif (data !== undefined) {\n\t\t\t\tconsole.debug(prefix, redact(message), redact(data));\n\t\t\t} else {\n\t\t\t\tconsole.debug(prefix, redact(message));\n\t\t\t}\n\t\t},\n\n\t\tinfo(message: string, data?: unknown): void {\n\t\t\tif (data !== undefined) {\n\t\t\t\tconsole.info(prefix, redact(message), redact(data));\n\t\t\t} else {\n\t\t\t\tconsole.info(prefix, redact(message));\n\t\t\t}\n\t\t},\n\n\t\twarn(message: string, data?: unknown): void {\n\t\t\tif (data !== undefined) {\n\t\t\t\tconsole.warn(prefix, redact(message), redact(data));\n\t\t\t} else {\n\t\t\t\tconsole.warn(prefix, redact(message));\n\t\t\t}\n\t\t},\n\n\t\terror(message: string, data?: unknown): void {\n\t\t\tif (data !== undefined) {\n\t\t\t\tconsole.error(prefix, redact(message), redact(data));\n\t\t\t} else {\n\t\t\t\tconsole.error(prefix, redact(message));\n\t\t\t}\n\t\t},\n\t};\n}\n\n// =============================================================================\n// Site Info\n// =============================================================================\n\nconst TRAILING_SLASH_RE = /\\/$/;\n\n/**\n * Options for creating site info\n */\nexport interface SiteInfoOptions {\n\t/** Site name from options table */\n\tsiteName?: string;\n\t/** Site URL from options table or Astro config */\n\tsiteUrl?: string;\n\t/** Site locale from options table */\n\tlocale?: string;\n\t/** Astro's `trailingSlash` config (from `virtual:emdash/config`). */\n\ttrailingSlash?: \"always\" | \"never\" | \"ignore\";\n}\n\n/**\n * Create site info from config and settings.\n *\n * Resolution order for URL:\n * 1. options table (emdash:site_url)\n * 2. Astro `site` config\n * 3. fallback to empty string\n */\nexport function createSiteInfo(options: SiteInfoOptions): SiteInfo {\n\treturn {\n\t\tname: options.siteName ?? \"\",\n\t\turl: (options.siteUrl ?? \"\").replace(TRAILING_SLASH_RE, \"\"), // strip trailing slash\n\t\tlocale: options.locale ?? \"en\",\n\t\ttrailingSlash: options.trailingSlash ?? \"ignore\", // Astro's default\n\t};\n}\n\n/**\n * Create a URL helper that generates absolute URLs from relative paths.\n * Validates that path starts with \"/\" and rejects protocol-relative paths (\"//\").\n */\nexport function createUrlHelper(siteUrl: string): (path: string) => string {\n\tconst base = siteUrl.replace(TRAILING_SLASH_RE, \"\"); // strip trailing slash\n\n\treturn (path: string): string => {\n\t\tif (!path.startsWith(\"/\")) {\n\t\t\tthrow new Error(`URL path must start with \"/\", got: \"${path}\"`);\n\t\t}\n\t\tif (path.startsWith(\"//\")) {\n\t\t\tthrow new Error(`URL path must not be protocol-relative, got: \"${path}\"`);\n\t\t}\n\t\treturn `${base}${path}`;\n\t};\n}\n\n// =============================================================================\n// User Access\n// =============================================================================\n\n/**\n * Convert a UserRepository user to the plugin-facing UserInfo shape.\n * Strips sensitive fields (avatarUrl, emailVerified, data).\n */\nfunction toUserInfo(user: {\n\tid: string;\n\temail: string;\n\tname: string | null;\n\trole: number;\n\tcreatedAt: string;\n}): UserInfo {\n\treturn {\n\t\tid: user.id,\n\t\temail: user.email,\n\t\tname: user.name,\n\t\trole: user.role,\n\t\tcreatedAt: user.createdAt,\n\t};\n}\n\n/**\n * Create read-only user access for plugins.\n * Excludes sensitive fields (password hashes, sessions, passkeys, avatar URL, data).\n */\nexport function createUserAccess(db: Kysely<Database>): UserAccess {\n\tconst userRepo = new UserRepository(db);\n\n\treturn {\n\t\tasync get(id: string): Promise<UserInfo | null> {\n\t\t\tconst user = await userRepo.findById(id);\n\t\t\tif (!user) return null;\n\t\t\treturn toUserInfo(user);\n\t\t},\n\n\t\tasync getByEmail(email: string): Promise<UserInfo | null> {\n\t\t\tconst user = await userRepo.findByEmail(email);\n\t\t\tif (!user) return null;\n\t\t\treturn toUserInfo(user);\n\t\t},\n\n\t\tasync list(opts?: {\n\t\t\trole?: number;\n\t\t\tlimit?: number;\n\t\t\tcursor?: string;\n\t\t}): Promise<{ items: UserInfo[]; nextCursor?: string }> {\n\t\t\tconst result = await userRepo.findMany({\n\t\t\t\trole: opts?.role as 10 | 20 | 30 | 40 | 50 | undefined,\n\t\t\t\tcursor: opts?.cursor,\n\t\t\t\tlimit: opts?.limit,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\titems: result.items.map(toUserInfo),\n\t\t\t\tnextCursor: result.nextCursor,\n\t\t\t};\n\t\t},\n\t};\n}\n\n// =============================================================================\n// Plugin Context Factory\n// =============================================================================\n\nexport interface PluginContextFactoryOptions {\n\tdb: Kysely<Database>;\n\tbeforeContentWrite?: ContentWriteGuard;\n\tcontentCreate?: PluginContentCreateCallback;\n\tcontentActions?: ContentActionCallbacks;\n\t/**\n\t * Resolver for the database connection, preferred over `db` when present.\n\t * Called per `createContext()` so connection-backed adapters (e.g. Postgres\n\t * over Hyperdrive) get the current request/event-scoped connection from ALS\n\t * rather than a snapshot of the per-isolate singleton — reusing the\n\t * singleton's socket from a later event trips workerd's cross-request I/O\n\t * guard. When omitted, `db` is used directly (correct for stateless\n\t * adapters like D1 and Node SQLite). `db` remains required as the fallback.\n\t */\n\tgetDb?: () => Kysely<Database>;\n\t/**\n\t * Storage backend for direct media uploads.\n\t * If not provided, upload() will throw.\n\t */\n\tstorage?: Storage;\n\t/**\n\t * Explicit provider for `ctx.media.getUploadUrl()`. Optional: when omitted\n\t * but `storage` is configured, the factory derives a working `getUploadUrl()`\n\t * (and `upload()`) from storage. Only when neither `getUploadUrl` nor\n\t * `storage` is present do media write operations become unavailable.\n\t */\n\tgetUploadUrl?: (\n\t\tfilename: string,\n\t\tcontentType: string,\n\t) => Promise<{ uploadUrl: string; mediaId: string }>;\n\t/**\n\t * Site information for ctx.site and ctx.url().\n\t * If not provided, site info will have empty defaults.\n\t */\n\tsiteInfo?: SiteInfoOptions;\n\t/**\n\t * Callback to notify the cron scheduler that the next due time may have changed.\n\t * If not provided, ctx.cron will not be available.\n\t */\n\tcronReschedule?: () => void;\n\t/** Clock used to calculate the first run of recurring plugin tasks. */\n\tnow?: () => Date;\n\t/**\n\t * Email pipeline instance for ctx.email.\n\t * If not provided (or no provider configured), ctx.email will be undefined.\n\t */\n\temailPipeline?: EmailPipeline;\n\t/**\n\t * Pre-resolved list of trusted proxy header names (from the runtime\n\t * `EmDashConfig.trustedProxyHeaders` or the env var). Plugin route\n\t * handlers pass this to `extractRequestMeta` so plugins see the same\n\t * client IP the core auth path does.\n\t */\n\ttrustedProxyHeaders?: string[];\n\tcommentModerate?: (\n\t\tpluginId: string,\n\t\tid: string,\n\t\tstatus: PluginCommentStatus,\n\t\texpectedStatus: PluginCommentStatus,\n\t) => Promise<PluginComment>;\n}\n\nexport interface ContentActionCallbacks {\n\t/** Register a sandbox invocation before it can call a content action. */\n\tbegin?(\n\t\tpluginId: string,\n\t\tinvocationId: string,\n\t\tinvalidateContentCache?: (tags: string[]) => Promise<void>,\n\t): void;\n\t/** Release queued after-hooks; `final: false` keeps late actions self-scheduling after timeout. */\n\tflush(pluginId: string, invocationId?: string, final?: boolean): Promise<void>;\n\tgetVersioned(\n\t\tpluginId: string,\n\t\tcollection: string,\n\t\tid: string,\n\t): Promise<VersionedContentItem | null>;\n\tpublish(\n\t\tpluginId: string,\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions: { _rev: string },\n\t\tinvocationId?: string,\n\t\tinvalidateContentCache?: (tags: string[]) => Promise<void>,\n\t): Promise<VersionedContentItem>;\n\tunpublish(\n\t\tpluginId: string,\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions: { _rev: string },\n\t\tinvocationId?: string,\n\t\tinvalidateContentCache?: (tags: string[]) => Promise<void>,\n\t): Promise<VersionedContentItem>;\n\tschedule(\n\t\tpluginId: string,\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions: { scheduledAt: string; _rev: string },\n\t\tinvocationId?: string,\n\t\tinvalidateContentCache?: (tags: string[]) => Promise<void>,\n\t): Promise<VersionedContentItem>;\n\tunschedule(\n\t\tpluginId: string,\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions: { _rev: string },\n\t\tinvocationId?: string,\n\t\tinvalidateContentCache?: (tags: string[]) => Promise<void>,\n\t): Promise<VersionedContentItem>;\n\tgetTrashedVersioned(\n\t\tpluginId: string,\n\t\tcollection: string,\n\t\tid: string,\n\t): Promise<VersionedContentItem | null>;\n\trestore(\n\t\tpluginId: string,\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions: { _rev: string },\n\t\tinvocationId?: string,\n\t\tinvalidateContentCache?: (tags: string[]) => Promise<void>,\n\t): Promise<VersionedContentItem>;\n}\n\n/**\n * Factory for creating plugin contexts\n */\nexport class PluginContextFactory {\n\tprivate resolveDb: () => Kysely<Database>;\n\tprivate beforeContentWrite?: ContentWriteGuard;\n\tprivate contentCreate?: PluginContentCreateCallback;\n\tprivate contentActions?: ContentActionCallbacks;\n\tprivate storage?: Storage;\n\tprivate getUploadUrl?: (\n\t\tfilename: string,\n\t\tcontentType: string,\n\t) => Promise<{ uploadUrl: string; mediaId: string }>;\n\tprivate site: SiteInfo;\n\tprivate urlHelper: (path: string) => string;\n\tprivate cronReschedule?: () => void;\n\tprivate now: () => Date;\n\tprivate emailPipeline?: EmailPipeline;\n\tprivate commentModerate?: PluginContextFactoryOptions[\"commentModerate\"];\n\t/**\n\t * Plugin IDs already warned about a missing media-write backend, so the\n\t * warning fires once per factory instead of on every hook/route context\n\t * creation (which would spam logs for hook-participating plugins).\n\t */\n\tprivate warnedMissingMediaBackend = new Set<string>();\n\n\tconstructor(options: PluginContextFactoryOptions) {\n\t\tconst fixedDb = options.db;\n\t\tthis.resolveDb = options.getDb ?? (() => fixedDb);\n\t\tthis.beforeContentWrite = options.beforeContentWrite;\n\t\tthis.contentCreate = options.contentCreate;\n\t\tthis.contentActions = options.contentActions;\n\t\tthis.storage = options.storage;\n\t\tthis.getUploadUrl = options.getUploadUrl;\n\t\tthis.site = createSiteInfo(options.siteInfo ?? {});\n\t\tthis.urlHelper = createUrlHelper(this.site.url);\n\t\tthis.cronReschedule = options.cronReschedule;\n\t\tthis.now = options.now ?? (() => new Date());\n\t\tthis.emailPipeline = options.emailPipeline;\n\t\tthis.commentModerate = options.commentModerate;\n\t}\n\n\t/**\n\t * Create the unified plugin context\n\t */\n\tcreateContext(plugin: ResolvedPlugin): PluginContext {\n\t\tconst capabilities = new Set(plugin.capabilities);\n\n\t\t// Resolve the connection once per context. For stateless adapters this\n\t\t// is the singleton; for connection-backed adapters it's the current\n\t\t// request/event-scoped connection from ALS. All repos below are built\n\t\t// from this local `db` so a hook never queries a stale singleton socket.\n\t\tconst db = this.resolveDb();\n\t\tconst optionsRepo = new OptionsRepository(db);\n\n\t\t// Always available\n\t\tconst secretRedactor = createPluginSecretRedactor();\n\t\tconst settings = createSettingsAccess(\n\t\t\toptionsRepo,\n\t\t\tplugin.id,\n\t\t\tplugin.admin.settingsSchema ?? {},\n\t\t\tundefined,\n\t\t\tsecretRedactor.add,\n\t\t);\n\t\tconst kv = createKVAccess(optionsRepo, plugin.id, settings);\n\t\tconst log = createLogAccess(plugin.id, secretRedactor);\n\t\tconst storage = createStorageAccess(db, plugin.id, plugin.storage);\n\n\t\t// Capability-gated: content\n\t\t// Note: capabilities reach this point already normalized to the\n\t\t// canonical names by definePlugin / adaptSandboxEntry. Deprecated\n\t\t// names (\"read:content\", \"write:content\") never appear here.\n\t\tlet content: ContentAccess | ContentAccessWithWrite | undefined;\n\t\tif (capabilities.has(\"content:write\")) {\n\t\t\tcontent = createContentAccessWithWrite(\n\t\t\t\tdb,\n\t\t\t\tthis.beforeContentWrite,\n\t\t\t\t{\n\t\t\t\t\tsite: this.site,\n\t\t\t\t\trevisions: capabilities.has(\"content:revisions:read\"),\n\t\t\t\t},\n\t\t\t\tthis.contentCreate\n\t\t\t\t\t? (input) => this.contentCreate!(plugin.id, input.collection, input.input, input.options)\n\t\t\t\t\t: undefined,\n\t\t\t);\n\t\t} else if (capabilities.has(\"content:read\")) {\n\t\t\tcontent = createContentAccess(db, {\n\t\t\t\tsite: this.site,\n\t\t\t\trevisions: capabilities.has(\"content:revisions:read\"),\n\t\t\t});\n\t\t}\n\t\tif (capabilities.has(\"content:publish\") && this.contentActions) {\n\t\t\tcontent = Object.assign(content ?? createContentAccess(db), {\n\t\t\t\tgetVersioned: (collection: string, id: string) =>\n\t\t\t\t\tthis.contentActions!.getVersioned(plugin.id, collection, id),\n\t\t\t\tpublish: (collection: string, id: string, options: { _rev: string }) =>\n\t\t\t\t\tthis.contentActions!.publish(plugin.id, collection, id, options),\n\t\t\t\tunpublish: (collection: string, id: string, options: { _rev: string }) =>\n\t\t\t\t\tthis.contentActions!.unpublish(plugin.id, collection, id, options),\n\t\t\t\tschedule: (\n\t\t\t\t\tcollection: string,\n\t\t\t\t\tid: string,\n\t\t\t\t\toptions: { scheduledAt: string; _rev: string },\n\t\t\t\t) => this.contentActions!.schedule(plugin.id, collection, id, options),\n\t\t\t\tunschedule: (collection: string, id: string, options: { _rev: string }) =>\n\t\t\t\t\tthis.contentActions!.unschedule(plugin.id, collection, id, options),\n\t\t\t});\n\t\t}\n\t\tif (capabilities.has(\"content:restore\") && this.contentActions) {\n\t\t\tcontent = Object.assign(\n\t\t\t\tcontent ?? {\n\t\t\t\t\tget: async () => {\n\t\t\t\t\t\tthrow new Error(\"Missing capability: content:read\");\n\t\t\t\t\t},\n\t\t\t\t\tlist: async () => {\n\t\t\t\t\t\tthrow new Error(\"Missing capability: content:read\");\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tgetTrashedVersioned: (collection: string, id: string) =>\n\t\t\t\t\t\tthis.contentActions!.getTrashedVersioned(plugin.id, collection, id),\n\t\t\t\t\trestore: (collection: string, id: string, options: { _rev: string }) =>\n\t\t\t\t\t\tthis.contentActions!.restore(plugin.id, collection, id, options),\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\tconst schema = capabilities.has(\"schema:read\") ? createSchemaAccess(db) : undefined;\n\n\t\t// Capability-gated: taxonomies\n\t\tlet taxonomies: TaxonomyAccess | TaxonomyAccessWithWrite | undefined;\n\t\tif (capabilities.has(\"taxonomies:write\")) {\n\t\t\ttaxonomies = createTaxonomyAccessWithWrite(db);\n\t\t} else if (capabilities.has(\"taxonomies:read\")) {\n\t\t\ttaxonomies = createTaxonomyAccess(db);\n\t\t}\n\n\t\tlet redirects: RedirectAccess | RedirectAccessWithWrite | undefined;\n\t\tif (capabilities.has(\"redirects:write\")) {\n\t\t\tredirects = createRedirectAccess(db, true);\n\t\t} else if (capabilities.has(\"redirects:read\")) {\n\t\t\tredirects = createRedirectAccess(db);\n\t\t}\n\n\t\t// Capability-gated: media\n\t\t// `upload()` only needs `storage`; `getUploadUrl()` is derived from\n\t\t// storage when no explicit provider is wired. Granting write access on\n\t\t// either avoids silently degrading media:write to read-only — the bug\n\t\t// where the runtime threads `storage` but not `getUploadUrl`.\n\t\tlet media: MediaAccess | MediaAccessWithWrite | undefined;\n\t\tconst hasMediaAccess =\n\t\t\tcapabilities.has(\"media:read\") ||\n\t\t\tcapabilities.has(\"media:write\") ||\n\t\t\tcapabilities.has(\"media:bytes:read\") ||\n\t\t\tcapabilities.has(\"media:metadata:write\");\n\t\tif (hasMediaAccess) {\n\t\t\tmedia =\n\t\t\t\tcapabilities.has(\"media:read\") || capabilities.has(\"media:write\")\n\t\t\t\t\t? createMediaAccess(db)\n\t\t\t\t\t: createBlockedMediaReadAccess();\n\t\t}\n\t\tif (capabilities.has(\"media:write\")) {\n\t\t\tif (this.getUploadUrl || this.storage) {\n\t\t\t\tmedia = createMediaAccessWithWrite(db, this.getUploadUrl, this.storage);\n\t\t\t} else {\n\t\t\t\tif (!this.warnedMissingMediaBackend.has(plugin.id)) {\n\t\t\t\t\tthis.warnedMissingMediaBackend.add(plugin.id);\n\t\t\t\t\tlog.warn(\n\t\t\t\t\t\t\"declares the media:write capability but no storage backend is configured; upload() is unavailable.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tmedia ??= createMediaAccess(db);\n\t\t\t}\n\t\t}\n\t\tif (capabilities.has(\"media:bytes:read\") && media) {\n\t\t\tmedia.readBytes = (id, options) => readPluginMediaBytes(db, this.storage, id, options);\n\t\t}\n\t\tif (capabilities.has(\"media:metadata:write\") && media) {\n\t\t\tmedia.updateMetadata = (id, patch) => updatePluginMediaMetadata(db, id, patch);\n\t\t}\n\n\t\t// Capability-gated: http\n\t\tlet http: HttpAccess | undefined;\n\t\tif (capabilities.has(\"network:request:unrestricted\")) {\n\t\t\thttp = createUnrestrictedHttpAccess(plugin.id);\n\t\t} else if (capabilities.has(\"network:request\")) {\n\t\t\thttp = createHttpAccess(plugin.id, plugin.allowedHosts);\n\t\t}\n\n\t\t// Capability-gated: users\n\t\tlet users: UserAccess | undefined;\n\t\tif (capabilities.has(\"users:read\")) {\n\t\t\tusers = createUserAccess(db);\n\t\t}\n\n\t\tlet comments: CommentAccess | undefined;\n\t\tif (capabilities.has(\"comments:moderate\")) {\n\t\t\tcomments = createCommentAccess(db, (id, status, expectedStatus) => {\n\t\t\t\tif (!this.commentModerate) throw new Error(\"Comment moderation is unavailable\");\n\t\t\t\treturn this.commentModerate(plugin.id, id, status, expectedStatus);\n\t\t\t});\n\t\t} else if (capabilities.has(\"comments:read\")) {\n\t\t\tcomments = createCommentAccess(db);\n\t\t}\n\n\t\t// Cron access — always available (scoped to plugin), but only if\n\t\t// the runtime provided a reschedule callback (i.e. cron is wired up).\n\t\tlet cron: CronAccess | undefined;\n\t\tif (this.cronReschedule) {\n\t\t\tcron = new CronAccessImpl(db, plugin.id, this.cronReschedule, this.now);\n\t\t}\n\n\t\t// Email access — requires email:send capability AND a configured provider\n\t\tlet email: EmailAccess | undefined;\n\t\tif (capabilities.has(\"email:send\") && this.emailPipeline?.isAvailable()) {\n\t\t\tconst pipeline = this.emailPipeline;\n\t\t\tconst pluginId = plugin.id;\n\t\t\temail = {\n\t\t\t\tsend: (message) => pipeline.send(message, pluginId),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tplugin: {\n\t\t\t\tid: plugin.id,\n\t\t\t\tversion: plugin.version,\n\t\t\t},\n\t\t\tstorage,\n\t\t\tkv,\n\t\t\tsettings,\n\t\t\tcontent,\n\t\t\tschema,\n\t\t\ttaxonomies,\n\t\t\tredirects,\n\t\t\tmedia,\n\t\t\thttp,\n\t\t\tlog,\n\t\t\tsite: this.site,\n\t\t\turl: this.urlHelper,\n\t\t\tusers,\n\t\t\tcomments,\n\t\t\tcron,\n\t\t\temail,\n\t\t};\n\t}\n}\n\n/**\n * Create a plugin context for a resolved plugin\n */\nexport function createPluginContext(\n\toptions: PluginContextFactoryOptions,\n\tplugin: ResolvedPlugin,\n): PluginContext {\n\tconst factory = new PluginContextFactory(options);\n\treturn factory.createContext(plugin);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,IAAa,oBAAb,cAAuC,MAAM;CAC5C,YACC,SACA,AAAO,OACP,AAAO,YACN;AACD,QAAM,QAAQ;EAHP;EACA;AAGP,OAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;AAuBd,IAAa,4BAAb,cAA+C,MAAM;CACpD,AAAS,OAAO;CAChB,AAAS,YAAY;;CAErB,AAAS;CAET,YAAY,SAAiB,SAAkD;AAC9E,QAAM,SAAS,EAAE,OAAO,SAAS,OAAO,CAAC;AACzC,OAAK,OAAO;AACZ,OAAK,WAAW,SAAS;;;;;;AAO3B,SAAgB,cAAc,OAAyC;AACtE,KAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAO,QAAQ,SAAS,SAAS,SAAS,QAAQ,SAAS,SAAS;;;;;AAMrE,SAAgB,WAAW,OAAsC;AAChE,KAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAO,QAAQ,SAAS,MAAM,QAAQ,MAAM,GAAG;;;;;AAMhD,SAAgB,mBAAmB,OAA8C;AAChF,KAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAO,gBAAgB,SAAS,OAAO,MAAM,eAAe;;;;;;;AAQ7D,SAAgB,kBAAkB,OAAuB;AACxD,QAAO,MAAM,WAAW,MAAM,OAAO,CAAC,WAAW,KAAK,MAAM,CAAC,WAAW,KAAK,MAAM;;;;;AAMpF,SAAgB,iBAAiB,SAAgD;CAChF,MAAM,yBAAS,IAAI,KAAa;AAChC,MAAK,MAAM,SAAS,QACnB,KAAI,MAAM,QAAQ,MAAM,CACvB,MAAK,MAAM,SAAS,MACnB,QAAO,IAAI,MAAM;KAGlB,QAAO,IAAI,MAAM;AAGnB,QAAO;;;;;AAMR,SAAgB,oBACf,OACA,eACA,UACA,YACO;AACP,MAAK,MAAM,SAAS,OAAO,KAAK,MAAM,CACrC,KAAI,CAAC,cAAc,IAAI,MAAM,CAC5B,OAAM,IAAI,kBACT,sCAAsC,MAAM,KAC5C,OACA,QAAQ,MAAM,eAAe,WAAW,sBAAsB,SAAS,yBACvE;;;;;AAQJ,SAAgB,sBACf,SACA,eACA,UACA,YACO;AACP,MAAK,MAAM,SAAS,OAAO,KAAK,QAAQ,CACvC,KAAI,CAAC,cAAc,IAAI,MAAM,CAC5B,OAAM,IAAI,kBACT,sCAAsC,MAAM,KAC5C,OACA,QAAQ,MAAM,eAAe,WAAW,sBAAsB,SAAS,qCACvE;;;;;;;;;;;;AAgBJ,SAAgB,YACf,IACA,OACA,SACS;AACT,QAAO,sBAAsB,IAAI,OAAO,QAAQ;;;;;;;;;AAWjD,SAAgB,iBAAiB,IAAiB,OAAuB;AACxE,QAAO,oBAAoB,IAAI,MAAM;;;;;AAOtC,SAAgB,eACf,IACA,OACA,OACqC;CAMrC,MAAM,cAAc,YAA6B,YAAY,IAAI,OAAO,EAAE,SAAS,CAAC;AAEpF,KAAI,UAAU,KACb,QAAO;EAAE,KAAK,GAAG,WAAW,MAAM,CAAC;EAAW,QAAQ,EAAE;EAAE;AAG3D,KAAI,OAAO,UAAU,SACpB,QAAO;EAAE,KAAK,GAAG,WAAW,KAAK,CAAC;EAAO,QAAQ,CAAC,MAAM;EAAE;AAG3D,KAAI,OAAO,UAAU,SACpB,QAAO;EAAE,KAAK,GAAG,WAAW,MAAM,CAAC;EAAO,QAAQ,CAAC,MAAM;EAAE;AAG5D,KAAI,OAAO,UAAU,UAEpB,QAAO;EAAE,KAAK,GAAG,WAAW,MAAM,CAAC;EAAO,QAAQ,CAAC,MAAM;EAAE;AAG5D,KAAI,WAAW,MAAM,EAAE;EACtB,MAAM,UAAU,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,OAAO,MAAM,OAAO,MAAM,SAAS;EACnF,MAAM,eAAe,MAAM,GAAG,UAAU,IAAI,CAAC,KAAK,KAAK;AACvD,SAAO;GACN,KAAK,GAAG,WAAW,QAAQ,CAAC,OAAO,aAAa;GAChD,QAAQ,MAAM;GACd;;AAGF,KAAI,mBAAmB,MAAM,CAG5B,QAAO;EACN,KAAK,GAAG,WAAW,MAAM,CAAC;EAC1B,QAAQ,CAAC,GAAG,kBAAkB,MAAM,WAAW,CAAC,GAAG;EACnD;AAGF,KAAI,cAAc,MAAM,EAAE;EACzB,MAAM,aAAuB,EAAE;EAC/B,MAAM,SAAoB,EAAE;EAI5B,MAAM,aAAa,IAAY,UAAiC;AAC/D,cAAW,KAAK,GAAG,WAAW,OAAO,UAAU,SAAS,CAAC,GAAG,GAAG,IAAI;AACnE,UAAO,KAAK,MAAM;;AAGnB,MAAI,MAAM,OAAO,OAAW,WAAU,KAAK,MAAM,GAAG;AACpD,MAAI,MAAM,QAAQ,OAAW,WAAU,MAAM,MAAM,IAAI;AACvD,MAAI,MAAM,OAAO,OAAW,WAAU,KAAK,MAAM,GAAG;AACpD,MAAI,MAAM,QAAQ,OAAW,WAAU,MAAM,MAAM,IAAI;AAKvD,MAAI,WAAW,WAAW,EACzB,OAAM,IAAI,kBACT,2BAA2B,MAAM,yBACjC,OACA,kEACA;AAGF,SAAO;GACN,KAAK,WAAW,KAAK,QAAQ;GAC7B;GACA;;AAGF,OAAM,IAAI,kBAAkB,kCAAkC,MAAM,GAAG;;;;;AAOxE,SAAgB,iBACf,IACA,OAIC;CACD,MAAM,aAAuB,EAAE;CAC/B,MAAM,SAAoB,EAAE;AAE5B,MAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,MAAM,EAAE;EACnD,MAAM,YAAY,eAAe,IAAI,OAAO,MAAM;AAElD,MAAI,CAAC,UAAU,IAAK;AACpB,aAAW,KAAK,UAAU,IAAI;AAC9B,SAAO,KAAK,GAAG,UAAU,OAAO;;AAGjC,KAAI,WAAW,WAAW,EACzB,QAAO;EAAE,KAAK;EAAI,QAAQ,EAAE;EAAE;AAG/B,QAAO;EACN,KAAK,WAAW,KAAK,QAAQ;EAC7B;EACA;;;;;ACrSF,SAAS,SAAS,OAAkD;AACnE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,cAAc,OAAgB,OAAwC;AAC9E,KAAI,CAAC,SAAS,MAAM,CACnB,OAAM,IAAI,UAAU,GAAG,MAAM,oBAAoB;CAElD,MAAM,YAAqB,OAAO,eAAe,MAAM;AACvD,KAAI,cAAc,OAAO,aAAa,cAAc,KACnD,OAAM,IAAI,UAAU,GAAG,MAAM,yBAAyB;AAEvD,QAAO;;AAGR,SAAS,QAAQ,OAAiC;AACjD,KAAI,OAAO,UAAU,YAAa,OAAO,UAAU,YAAY,OAAO,SAAS,MAAM,CACpF,QAAO;AAER,OAAM,IAAI,UAAU,2DAA2D;;AAGhF,SAAS,gBAAgB,OAA4B;AACpD,KAAI,UAAU,QAAQ,OAAO,UAAU,UAAW,QAAO;AACzD,KAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO,QAAQ,MAAM;CACjF,MAAM,SAAS,cAAc,OAAO,uBAAuB;CAC3D,MAAM,SAAS,OAAO;AACtB,KAAI,MAAM,QAAQ,OAAO,CACxB,QAAO,EAAE,IAAI,MAAM,KAAK,QAAQ,QAAQ,EAAE;CAE3C,MAAM,SAAS,OAAO;AACtB,KAAI,OAAO,WAAW,SACrB,QAAO,EAAE,YAAY,QAAQ;CAE9B,MAAM,QAAqB,EAAE;AAC7B,MAAK,MAAM,OAAO;EAAC;EAAM;EAAO;EAAM;EAAM,CAC3C,KAAI,OAAO,QAAQ;EAClB,MAAM,QAAQ,OAAO;AACrB,QAAM,OAAO,UAAU,SAAY,SAAY,QAAQ,MAAM;;AAG/D,QAAO;;AAGR,SAAgB,mBAAmB,OAIjC;CACD,MAAM,OAAO,cAAc,OAAO,2BAA2B;AAC7D,KAAI,OAAO,KAAK,KAAK,CAAC,MAAM,QAAQ,QAAQ,WAAW,QAAQ,SAAS,QAAQ,QAAQ,CACvF,OAAM,IAAI,UAAU,kCAAkC;CAEvD,MAAM,QAAqB,EAAE;AAC7B,MAAK,MAAM,CAAC,OAAO,WAAW,OAAO,QAAQ,cAAc,KAAK,OAAO,sBAAsB,CAAC,EAAE;AAC/F,wBAAsB,MAAM;AAC5B,QAAM,SAAS,gBAAgB,OAAO;;CAEvC,MAAM,MAAM,KAAK,QAAQ,SAAY,EAAE,GAAG,cAAc,KAAK,KAAK,cAAc;CAChF,MAAM,QAAQ,KAAK,UAAU,SAAY,EAAE,GAAG,cAAc,KAAK,OAAO,gBAAgB;CACxF,MAAM,aAAuC,EAAE;AAC/C,MAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,IAAI,EAAE;AACjD,MAAI,UAAU,OAAW;AACzB,wBAAsB,MAAM;EAC5B,MAAM,aAAa,KAAK,UAAU,MAAM;AACxC,MAAI,eAAe,OAClB,OAAM,IAAI,UAAU,+CAA+C;EACpE,MAAM,aAAsB,KAAK,MAAM,WAAW;AAClD,aAAW,KAAK,CAAC,OAAO,WAAW,CAAC;;CAErC,MAAM,YAAY,IAAI,IAAI,WAAW,KAAK,CAAC,WAAW,MAAM,CAAC;CAC7D,MAAM,eAAwC,EAAE;AAChD,MAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,MAAM,EAAE;AACnD,MAAI,UAAU,OAAW;AACzB,wBAAsB,MAAM;AAC5B,MAAI,UAAU,IAAI,MAAM,CAAE,OAAM,IAAI,UAAU,8CAA8C;EAC5F,MAAM,OAAO,cAAc,OAAO,wBAAwB;EAC1D,MAAM,OAAO,OAAO,KAAK,KAAK;EAC9B,MAAM,MAAM,KAAK;AACjB,MAAI,KAAK,WAAW,KAAM,QAAQ,SAAS,QAAQ,MAClD,OAAM,IAAI,UAAU,uDAAuD;EAE5E,MAAM,SAAS,KAAK;AACpB,MAAI,OAAO,WAAW,YAAY,CAAC,OAAO,cAAc,OAAO,CAC9D,OAAM,IAAI,UAAU,uCAAuC;AAE5D,eAAa,KAAK,CAAC,OAAO,QAAQ,QAAQ,CAAC,SAAS,OAAO,CAAC;;AAE7D,KAAI,WAAW,SAAS,aAAa,WAAW,EAC/C,OAAM,IAAI,UAAU,uDAAuD;AAE5E,QAAO;EAAE;EAAO;EAAY;EAAc;;;;;;;;;;;;;;AC1C3C,MAAM,0BAA0B,IAAI,IAAI,CAAC,SAAS,QAAQ,CAAC;AAE3D,SAAS,YAAY,KAAkC;AACtD,KAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM,QAAO;CACpD,MAAM,OAAQ,IAA2B;AACzC,KAAI,OAAO,SAAS,SAAU,QAAO;CACrC,MAAM,QAAS,IAA4B;AAC3C,KAAI,OAAO,UAAU,YAAY,UAAU,MAAM;EAChD,MAAM,YAAa,MAA6B;AAChD,MAAI,OAAO,cAAc,SAAU,QAAO;;;AAK5C,SAAgB,wBAAwB,KAAuB;CAC9D,MAAM,WAAW,YAAY,IAAI;AACjC,KAAI,aAAa,UAAa,wBAAwB,IAAI,SAAS,CAClE,QAAO,IAAI,0BACV,8GACA;EAAE,OAAO;EAAK;EAAU,CACxB;AAEF,QAAO;;;;;;;AAQR,SAAS,aAAa,SAAiB,QAAwC;CAC9E,MAAM,QAAkC,EAAE;CAC1C,IAAI,aAAa;CACjB,MAAM,WAAW,QAAQ,MAAM,IAAI;AACnC,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACzC,MAAI,IAAI,EACP,OAAM,KAAK,GAAG,GAAG,OAAO,gBAAgB;AAEzC,MAAI,SAAS,GACZ,OAAM,KAAK,IAAI,IAAI,SAAS,GAAG,CAAC;;AAGlC,QAAO,GAAY,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,GAAG,CAAC,CAAC;;;;;;;;;;;;;;;;AAiBrD,SAAS,SAAS,MAA+C;AAChE,QAAO,GAAG,cAAc,KAAK;;AAG9B,IAAa,0BAAb,MAAkF;CACjF,AAAQ;CAER,YACC,AAAQ,IACR,AAAQ,UACR,AAAQ,YACR,SACC;EAJO;EACA;EACA;AAGR,OAAK,gBAAgB,iBAAiB,QAAQ;;;;;CAM/C,MAAM,IAAI,IAA+B;EACxC,MAAM,MAAM,MAAM,KAAK,GACrB,WAAW,kBAAkB,CAC7B,OAAO,OAAO,CACd,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,KAAK,GAAG,CACpB,kBAAkB;AAEpB,MAAI,CAAC,IAAK,QAAO;AAEjB,SAAO,KAAK,MAAM,IAAI,KAAK;;;;;CAM5B,MAAM,IAAI,IAAY,MAAwB;EAC7C,MAAM,uBAAM,IAAI,MAAM,EAAC,aAAa;EACpC,MAAM,WAAW,KAAK,UAAU,KAAK;EACrC,MAAM,WAAW,OAAO,YAAY;AAEpC,QAAM,KAAK,GACT,WAAW,kBAAkB,CAC7B,OAAO;GACP,WAAW,KAAK;GAChB,YAAY,KAAK;GACjB;GACA,MAAM;GACN;GACA,YAAY;GACZ,YAAY;GACZ,CAAC,CACD,YAAY,OACZ,GAAG,QAAQ;GAAC;GAAa;GAAc;GAAK,CAAC,CAAC,YAAY;GACzD,MAAM;GACN;GACA,YAAY;GACZ,CAAC,CACF,CACA,SAAS;;CAGZ,MAAM,aAAa,IAA+C;AACjE,mBAAiB,GAAG;EACpB,MAAM,MAAM,MAAM,KAAK,GACrB,WAAW,kBAAkB,CAC7B,OAAO,CAAC,QAAQ,WAAW,CAAC,CAC5B,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,KAAK,GAAG,CACpB,kBAAkB;AACpB,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO;GAAE,OAAO,KAAK,MAAM,IAAI,KAAK;GAAE,UAAU,IAAI;GAAU;;CAG/D,MAAM,cACL,IACA,kBACA,MACkC;AAClC,mBAAiB,GAAG;AACpB,MAAI,qBAAqB,KAAM,uBAAsB,iBAAiB;EACtE,MAAM,WAAW,0BAA0B,KAAK;EAChD,MAAM,WAAW,OAAO,YAAY;EACpC,MAAM,uBAAM,IAAI,MAAM,EAAC,aAAa;EACpC,MAAM,MACL,qBAAqB,OAClB,MAAM,KAAK,GACV,WAAW,kBAAkB,CAC7B,OAAO;GACP,WAAW,KAAK;GAChB,YAAY,KAAK;GACjB;GACA,MAAM;GACN;GACA,YAAY;GACZ,YAAY;GACZ,CAAC,CACD,YAAY,OAAO,GAAG,QAAQ;GAAC;GAAa;GAAc;GAAK,CAAC,CAAC,WAAW,CAAC,CAC7E,UAAU,WAAW,CACrB,kBAAkB,GACnB,MAAM,KAAK,GACV,YAAY,kBAAkB,CAC9B,IAAI;GAAE,MAAM;GAAU;GAAU,YAAY;GAAK,CAAC,CAClD,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,KAAK,GAAG,CACpB,MAAM,YAAY,KAAK,iBAAiB,CACxC,UAAU,WAAW,CACrB,kBAAkB;AACvB,SAAO,MAAM;GAAE,SAAS;GAAM,UAAU,IAAI;GAAU,GAAG,EAAE,SAAS,OAAO;;CAG5E,MAAM,iBAAiB,IAAY,kBAA4D;AAC9F,mBAAiB,GAAG;AACpB,wBAAsB,iBAAiB;AASvC,SAAO,EAAE,SARG,MAAM,KAAK,GACrB,WAAW,kBAAkB,CAC7B,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,KAAK,GAAG,CACpB,MAAM,YAAY,KAAK,iBAAiB,CACxC,UAAU,KAAK,CACf,kBAAkB,KACM,QAAW;;;;;CAMtC,MAAM,OAAO,IAA8B;AAQ1C,WAPe,MAAM,KAAK,GACxB,WAAW,kBAAkB,CAC7B,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,KAAK,GAAG,CACpB,kBAAkB,EAEL,kBAAkB,KAAK;;;;;CAMvC,MAAM,OAAO,IAA8B;AAS1C,SAAO,CAAC,CARI,MAAM,KAAK,GACrB,WAAW,kBAAkB,CAC7B,OAAO,KAAK,CACZ,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,KAAK,GAAG,CACpB,kBAAkB;;;;;CAQrB,MAAM,QAAQ,KAAwC;AACrD,MAAI,IAAI,WAAW,EAAG,wBAAO,IAAI,KAAK;EAEtC,MAAM,OAAO,MAAM,KAAK,GACtB,WAAW,kBAAkB,CAC7B,OAAO,CAAC,MAAM,OAAO,CAAC,CACtB,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,MAAM,IAAI,CACtB,SAAS;EAEX,MAAM,yBAAS,IAAI,KAAgB;AACnC,OAAK,MAAM,OAAO,KAEjB,QAAO,IAAI,IAAI,IAAI,KAAK,MAAM,IAAI,KAAK,CAAM;AAE9C,SAAO;;;;;CAMR,MAAM,QAAQ,OAAsD;AACnE,MAAI,MAAM,WAAW,EAAG;EAExB,MAAM,uBAAM,IAAI,MAAM,EAAC,aAAa;AAIpC,QAAM,gBAAgB,KAAK,IAAI,OAAO,QAAQ;AAC7C,QAAK,MAAM,QAAQ,OAAO;IACzB,MAAM,WAAW,KAAK,UAAU,KAAK,KAAK;IAC1C,MAAM,WAAW,OAAO,YAAY;AACpC,UAAM,IACJ,WAAW,kBAAkB,CAC7B,OAAO;KACP,WAAW,KAAK;KAChB,YAAY,KAAK;KACjB,IAAI,KAAK;KACT,MAAM;KACN;KACA,YAAY;KACZ,YAAY;KACZ,CAAC,CACD,YAAY,OACZ,GAAG,QAAQ;KAAC;KAAa;KAAc;KAAK,CAAC,CAAC,YAAY;KACzD,MAAM;KACN;KACA,YAAY;KACZ,CAAC,CACF,CACA,SAAS;;IAEX;;;;;CAMH,MAAM,WAAW,KAAgC;AAChD,MAAI,IAAI,WAAW,EAAG,QAAO;EAE7B,MAAM,SAAS,MAAM,KAAK,GACxB,WAAW,kBAAkB,CAC7B,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,MAAM,IAAI,CACtB,kBAAkB;AAEpB,SAAO,OAAO,OAAO,kBAAkB,EAAE;;;;;CAM1C,MAAM,MAAM,UAAwB,EAAE,EAAqD;EAC1F,MAAM,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,WAAW;EAC7C,MAAM,QAAQ,KAAK,IAAI,QAAQ,SAAS,IAAI,IAAI;AAGhD,sBAAoB,OAAO,KAAK,eAAe,KAAK,UAAU,KAAK,WAAW;AAC9E,MAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EACjC,uBAAsB,SAAS,KAAK,eAAe,KAAK,UAAU,KAAK,WAAW;EAInF,IAAI,QAAQ,KAAK,GACf,WAAW,kBAAkB,CAC7B,OAAO;GAAC;GAAM;GAAQ;GAAa,CAAC,CACpC,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW;EAG3C,MAAM,cAAc,iBAAiB,KAAK,IAAI,MAAM;AACpD,MAAI,YAAY,IACf,SAAQ,MAAM,MAAM,aAAa,YAAY,KAAK,YAAY,OAAO,CAAC;EAGvE,MAAM,eAAe,OAAO,QAAQ,QAAQ;EAC5C,MAAM,kBAAkB,IAAI,IAAI,aAAa,KAAK,GAAG,eAAe,UAAU,CAAC;EAC/E,MAAM,aAAa,aAAa,SAAS,KAAK,aAAa,GAAG,OAAO;EAOrE,MAAM,YAAY,UACjB,GAAG,GAAG,IAAI,IAAI,iBAAiB,KAAK,IAAI,MAAM,CAAC;AAGhD,MAAI,QAAQ;GACX,MAAM,UAAU,aAAa,OAAO;AACpC,OAAI,aAAa,WAAW,EAC3B,SAAQ,MAAM,OAAO,EAAE,SACtB,GAAG,GAAG,oBAAoB,KAAK,GAAG,IAAI,QAAQ,WAAW,IAAI,QAAQ,GAAG,GAAG,CAC3E;QACK;AACN,QAAI,gBAAgB,OAAO,EAC1B,OAAM,IAAI,kBACT,0EACA,OAAO,KAAK,QAAQ,CAAC,KAAK,KAAK,EAC/B,2DACA;IAEF,MAAM,KAAK,aAAa,GAAG,MAAM,GAAG;IAIpC,MAAM,cAAc,UACnB,GAAG,WAAW,IAAI,IAAI,iBAAiB,KAAK,IAAI,MAAM,CAAC,CAAC,0CAA0C,KAAK,SAAS,oBAAoB,KAAK,WAAW,YAAY,QAAQ,GAAG;IAE5K,MAAM,SAAS,aAAa,KAAK,CAAC,WAAW;KAC5C,MAAM,MAAM,SAAS,MAAM;KAC3B,MAAM,SAAS,WAAW,MAAM;AAChC,YAAO;MACN,OAAO,GAAG,IAAI,SAAS,IAAI,CAAC,KAAK,SAAS,OAAO,CAAC,QAAQ,SAAS,IAAI,CAAC,UAAU,IAAI,KAAK,OAAO;MAClG,OAAO,GAAG,IAAI,SAAS,IAAI,CAAC,GAAG,GAAG,GAAG,SAAS,OAAO,CAAC,OAAO,SAAS,IAAI,CAAC,KAAK,SAAS,OAAO,CAAC,OAAO,SAAS,IAAI,CAAC,WAAW,IAAI,GAAG,GAAG,GAAG,OAAO;MACrJ;MACA;IAIF,MAAM,QAAQ,OAAO,KACnB,GAAG,MACH,GAAG,IAAI,IAAI,KAAK,CAAC,GAAG,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,GAC3F;AACD,UAAM,KACL,GAAG,IAAI,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,GAAG,QAAQ,KAAK,EAAE,GAAG,QAAQ,CAAC,GAC1F;AACD,YAAQ,MAAM,MAAM,GAAY,IAAI,IAAI,KAAK,OAAO,GAAG,OAAO,CAAC,GAAG;;;AAKpE,MAAI,aAAa,SAAS,GAAG;AAC5B,QAAK,MAAM,CAAC,OAAO,cAAc,cAAc;IAC9C,MAAM,MAAM,cAAc,SAAS,GAAG,SAAS,GAAG;IAClD,MAAM,OAAO,SAAS,MAAM;AAE5B,YAAQ,MAAM,QAAQ,GAAG,GAAG,SAAS,KAAK,CAAC,GAAG,MAAM;AAGpD,YAAQ,MAAM,QAAQ,GAAG,GAAG,KAAK,GAAG,MAAM;;AAG3C,WAAQ,MAAM,QAAQ,MAAM,aAAa,SAAS,MAAM;QAGxD,SAAQ,MAAM,QAAQ,cAAc,MAAM,CAAC,QAAQ,MAAM,MAAM;AAIhE,UAAQ,MAAM,MAAM,QAAQ,EAAE;EAE9B,MAAM,OAAO,MAAM,MAAM,SAAS;EAElC,MAAM,UAAU,KAAK,SAAS;EAC9B,MAAM,QAAQ,KAAK,MAAM,GAAG,MAAM,CAAC,KAAK,SAAS;GAChD,IAAI,IAAI;GAER,MAAM,KAAK,MAAM,IAAI,KAAK;GAC1B,EAAE;EAGH,IAAI;AACJ,MAAI,SAAS;GACZ,MAAM,WAAW,KAAK,QAAQ;AAC9B,OAAI,SACH,cAAa,aAAa,SAAS,YAAY,SAAS,GAAG;;AAI7D,SAAO;GAAE;GAAO,QAAQ;GAAY;GAAS;;;;;CAM9C,MAAM,MAAM,OAAsC;AACjD,MAAI,SAAS,OAAO,KAAK,MAAM,CAAC,SAAS,EACxC,qBAAoB,OAAO,KAAK,eAAe,KAAK,UAAU,KAAK,WAAW;EAG/E,IAAI,QAAQ,KAAK,GACf,WAAW,kBAAkB,CAC7B,OAAO,GAAW,WAAW,GAAG,QAAQ,CAAC,CACzC,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW;AAG3C,MAAI,SAAS,OAAO,KAAK,MAAM,CAAC,SAAS,GAAG;GAC3C,MAAM,cAAc,iBAAiB,KAAK,IAAI,MAAM;AACpD,OAAI,YAAY,IACf,SAAQ,MAAM,MAAM,aAAa,YAAY,KAAK,YAAY,OAAO,CAAC;;EAIxE,MAAM,SAAS,MAAM,MAAM,kBAAkB;AAE7C,SAAO,OAAO,QAAQ,SAAS,EAAE;;CAGlC,MAAM,SAAS,IAAY,MAA2C;AACrE,MAAI,OAAO,OAAO,SAAU,OAAM,IAAI,UAAU,8BAA8B;EAC9E,MAAM,EAAE,OAAO,YAAY,iBAAiB,mBAAmB,KAAK;AAKpE,OAAK,MAAM,SAAS,OAAO,OAAO,MAAM,CACvC,KAAI,WAAW,MAAM,IAAI,MAAM,GAAG,WAAW,EAC5C,QAAO,EAAE,SAAS,OAAO;EAI3B,MAAM,uBAAM,IAAI,MAAM,EAAC,aAAa;EACpC,MAAM,WAAW,oBAAoB,KAAK,IAAI,YAAY,aAAa;EAEvE,IAAI,QAAQ,KAAK,GACf,YAAY,kBAAkB,CAC9B,IAAI;GAAE,MAAM;GAAU,YAAY;GAAK,CAAC,CACxC,MAAM,aAAa,KAAK,KAAK,SAAS,CACtC,MAAM,cAAc,KAAK,KAAK,WAAW,CACzC,MAAM,MAAM,KAAK,GAAG,CACpB,MAAM,sBAAsB,KAAK,IAAI,aAAa,CAAC;EAErD,MAAM,cAAc,iBAAiB,KAAK,IAAI,MAAM;AACpD,MAAI,YAAY,IACf,SAAQ,MAAM,MAAM,aAAa,YAAY,KAAK,YAAY,OAAO,CAAC;EAGvE,IAAI;AACJ,MAAI;AACH,SAAM,MAAM,MAAM,UAAU,OAAO,CAAC,kBAAkB;WAC9C,KAAK;AACb,SAAM,wBAAwB,IAAI;;AAEnC,MAAI,CAAC,IAAK,QAAO,EAAE,SAAS,OAAO;AAGnC,SAAO;GAAE,SAAS;GAAM,MADX,KAAK,MAAM,IAAI,KAAK;GACH;;;;;;ACngBhC,SAAgB,oBACf,IACA,eACgB;CAChB,MAAM,cAAc,IAAI,kBAAkB,GAAG;CAC7C,MAAM,UAAU,IAAI,cAAc,GAAG;AAErC,QAAO;EACN,MAAM,IAAI,YAAoB,IAAyC;GACtE,MAAM,OAAO,MAAM,YAAY,SAAS,YAAY,GAAG;AACvD,OAAI,CAAC,KAAM,QAAO;GAElB,MAAM,SAAsB;IAC3B,IAAI,KAAK;IACT,MAAM,KAAK;IACX,MAAM,KAAK;IACX,QAAQ,KAAK;IACb,MAAM,KAAK;IACX,WAAW,KAAK;IAChB,WAAW,KAAK;IAChB,QAAQ,KAAK;IACb,aAAa,KAAK;IAClB,aAAa,KAAK;IAClB,UAAU,KAAK;IACf,kBAAkB,KAAK;IACvB,gBAAgB,KAAK;IACrB,iBAAiB,KAAK;IACtB,SAAS,KAAK;IACd;AAED,OAAI,MAAM,QAAQ,UAAU,WAAW,CACtC,QAAO,MAAM,MAAM,QAAQ,IAAI,YAAY,KAAK,GAAG;AAGpD,UAAO;;EAGR,MAAM,KACL,YACA,SACwC;GACxC,IAAI;AACJ,OAAI,SAAS,SAAS;IAErB,MAAM,QADU,OAAO,QAAQ,QAAQ,QAAQ,CACzB;AACtB,QAAI,MAAO,WAAU;KAAE,OAAO,MAAM;KAAI,WAAW,MAAM;KAAI;;GAG9D,MAAM,SAAS,MAAM,YAAY,SAAS,YAAY;IACrD,OAAO,SAAS,SAAS;IACzB,QAAQ,SAAS;IACjB;IACA,OAAO,SAAS;IAChB,CAAC;GAEF,MAAM,QAAuB,OAAO,MAAM,KAAK,UAAU;IACxD,IAAI,KAAK;IACT,MAAM,KAAK;IACX,MAAM,KAAK;IACX,QAAQ,KAAK;IACb,MAAM,KAAK;IACX,WAAW,KAAK;IAChB,WAAW,KAAK;IAChB,QAAQ,KAAK;IACb,aAAa,KAAK;IAClB,aAAa,KAAK;IAClB,UAAU,KAAK;IACf,kBAAkB,KAAK;IACvB,gBAAgB,KAAK;IACrB,iBAAiB,KAAK;IACtB,SAAS,KAAK;IACd,EAAE;AAEH,OAAI,MAAM,SAAS,KAAM,MAAM,QAAQ,UAAU,WAAW,EAAG;IAC9D,MAAM,SAAS,MAAM,QAAQ,QAC5B,YACA,MAAM,KAAK,SAAS,KAAK,GAAG,CAC5B;AACD,SAAK,MAAM,QAAQ,OAAO;KACzB,MAAM,MAAM,OAAO,IAAI,KAAK,GAAG;AAC/B,SAAI,IAAK,MAAK,MAAM;;;AAItB,UAAO;IAAE;IAAO,QAAQ,OAAO;IAAY,SAAS,CAAC,CAAC,OAAO;IAAY;;EAG1E,MAAM,gBAAgB,YAAY,IAAI;GACrC,MAAM,OAAO,MAAM,YAAY,SAAS,YAAY,GAAG;AACvD,OAAI,CAAC,KAAM,OAAM,IAAI,MAAM,sBAAsB,WAAW,GAAG,KAAK;AAKpE,UAAO;IACN,kBALwB,KAAK,oBAAoB,KAAK;IAMtD,eALoB,KAAK,mBACvB,MAAM,YAAY,iBAAiB,YAAY,KAAK,iBAAiB,GACrE,CAAC,KAAK,EAGmB,KAAK,iBAAiB;KAChD,IAAI,YAAY;KAChB,QAAQ,YAAY;KACpB,MAAM,YAAY;KAClB,QAAQ,YAAY;KACpB,WAAW,YAAY;KACvB,EAAE;IACH;;EAGF,MAAM,aAAa,YAAY,IAAI;GAClC,MAAM,OAAO,eAAe;AAC5B,OAAI,CAAC,MAAM,IAAK,QAAO;GACvB,MAAM,CAAC,MAAM,kBAAkB,MAAM,QAAQ,IAAI,CAChD,YAAY,SAAS,YAAY,GAAG,EACpC,IAAI,eAAe,GAAG,CAAC,cAAc,WAAW,CAChD,CAAC;AACF,OAAI,CAAC,QAAQ,KAAK,WAAW,eAAe,CAAC,KAAK,QAAQ,CAAC,gBAAgB,SAC1E,QAAO;GAER,MAAM,OAAO,MAAM,iCAAiC;IACnD,SAAS,eAAe,cAAc;IACtC;IACA,MAAM,KAAK;IACX,IAAI,KAAK;IACT,MAAM,KAAK;IACX,QAAQ,KAAK,UAAU,KAAK;IAC5B,eAAe,KAAK;IACpB,CAAC;AACF,UAAO,SAAS,OAAO,OAAO,GAAG,KAAK,MAAM;;EAG7C,GAAI,eAAe,YAChB;GACA,MAAM,cACL,YACA,IACA,iBACC;AAID,YAHkB,MAAM,IAAI,mBAAmB,GAAG,CAAC,mBAAmB,YAAY,IAAI,EACrF,OAAO,uBAAuB,iBAAiB,MAAM,EACrD,CAAC,EACe,KAAK,EAAE,UAAU,WAAW,GAAG,eAAe,SAAS;;GAEzE,MAAM,YAAY,YAAoB,IAAY,YAAoB;IACrE,MAAM,WAAW,MAAM,IAAI,mBAAmB,GAAG,CAAC,gBACjD,YACA,IACA,WACA;AACD,QAAI,CAAC,SAAU,QAAO;IACtB,MAAM,EAAE,UAAU,WAAW,GAAG,iBAAiB;AACjD,WAAO;;GAER,GACA,EAAE;EACL;;;;;AC7JF,MAAa,kCAAkC,KAAK,OAAO;AAC3D,MAAa,8BAA8B,KAAK,OAAO;AAEvD,SAAS,SAAS,MAAmC;AACpD,QAAO,4BAA4B,mBAAmB,KAAK,GAAG,CAAC,GAAG,mBAAmB,KAAK,SAAS;;AAGpG,SAAgB,kBAAkB,MAAsC;AACvE,QAAO;EACN,IAAI,KAAK;EACT,UAAU,KAAK;EACf,UAAU,KAAK;EACf,MAAM,KAAK;EACX,KAAK,SAAS,KAAK;EACnB,WAAW,KAAK;EAChB,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,KAAK,KAAK;EACV,SAAS,KAAK;EACd,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb,UAAU,KAAK;EACf,eAAe,KAAK;EACpB,UAAU,KAAK,YAAY;EAC3B,QAAQ;EACR;;AAGF,SAAS,iBAAiB,UAAsC;CAC/D,MAAM,QAAQ,YAAY;AAC1B,KAAI,CAAC,OAAO,cAAc,MAAM,IAAI,SAAS,KAAK,QAAQ,4BACzD,OAAM,IAAI,WACT,uEAAuE,8BACvE;AAEF,QAAO;;AAGR,eAAe,oBACd,MACA,UACsB;CACtB,MAAM,SAAS,KAAK,WAAW;CAC/B,MAAM,SAAuB,EAAE;CAC/B,IAAI,OAAO;AACX,KAAI;AACH,SAAO,MAAM;GACZ,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,OAAI,KAAM;AACV,WAAQ,MAAM;AACd,OAAI,OAAO,UAAU;AACpB,QAAI;AACH,WAAM,OAAO,QAAQ;YACd;AACR,UAAM,IAAI,0BAA0B,+BAA+B,SAAS,aAAa;;AAE1F,UAAO,KAAK,MAAM;;WAEV;AACT,SAAO,aAAa;;CAGrB,MAAM,QAAQ,IAAI,WAAW,KAAK;CAClC,IAAI,SAAS;AACb,MAAK,MAAM,SAAS,QAAQ;AAC3B,QAAM,IAAI,OAAO,OAAO;AACxB,YAAU,MAAM;;AAEjB,QAAO;;AAGR,IAAM,4BAAN,cAAwC,WAAW;AAEnD,eAAsB,qBACrB,IACA,SACA,IACA,SACsB;AACtB,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,kCAAkC;CAChE,MAAM,QAAQ,iBAAiB,SAAS,SAAS;CACjD,MAAM,OAAO,MAAM,IAAI,gBAAgB,GAAG,CAAC,SAAS,GAAG;AACvD,KAAI,CAAC,QAAQ,KAAK,WAAW,QAC5B,OAAM,IAAI,MAAM,4CAA4C;CAE7D,IAAI;AACJ,KAAI;AAEH,UAAQ,MAAM,qBADG,MAAM,QAAQ,SAAS,KAAK,WAAW,EACb,MAAM,MAAM;UAC/C,OAAO;AACf,MAAI,iBAAiB,0BAA2B,OAAM;AAEtD,QAAM,IAAI,MAAM,6BAA6B;;AAE9C,QAAO;EACN;EACA,UAAU,KAAK;EACf,UAAU,KAAK;EACf,MAAM,MAAM;EACZ,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,aAAa,GAAG,EAAE;EAC7D;;AAGF,eAAsB,0BACrB,IACA,IACA,OACqB;CACrB,MAAM,SAAS,8BAA8B,MAAM;CACnD,MAAM,OAAO,MAAM,IAAI,gBAAgB,GAAG,CAAC,oBAAoB,IAAI,OAAO;AAC1E,KAAI,CAAC,KAAM,OAAM,IAAI,MAAM,4CAA4C;AACvE,QAAO,kBAAkB,KAAK;;AAG/B,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAO;CAAW;CAAU;CAAS,CAAC;AAE3E,SAAgB,8BAA8B,OAAoC;AACjF,KAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,MAAM,CAC9D,OAAM,IAAI,UAAU,+CAA+C;CAEpE,MAAM,OAAO,OAAO,KAAK,MAAM;AAC/B,KAAI,KAAK,WAAW,EACnB,OAAM,IAAI,UAAU,+DAA+D;AAEpF,MAAK,MAAM,OAAO,KACjB,KAAI,CAAC,oBAAoB,IAAI,IAAI,CAChC,OAAM,IAAI,UAAU,sCAAsC,MAAM;CAGlE,MAAM,MAAM,QAAQ,IAAI,OAAO,MAAM;CACrC,MAAM,UAAU,QAAQ,IAAI,OAAO,UAAU;CAC7C,MAAM,SAAS,QAAQ,IAAI,OAAO,SAAS;CAC3C,MAAM,SAAS,QAAQ,IAAI,OAAO,SAAS;AAC3C,KAAI,QAAQ,UAAa,QAAQ,QAAQ,OAAO,QAAQ,SACvD,OAAM,IAAI,UAAU,oDAAoD;AAEzE,KAAI,YAAY,UAAa,YAAY,QAAQ,OAAO,YAAY,SACnE,OAAM,IAAI,UAAU,wDAAwD;AAE7E,KAAI,WAAW,UAAa,WAAW,QAAQ,OAAO,WAAW,SAChE,OAAM,IAAI,UAAU,uDAAuD;AAE5E,KAAI,WAAW,UAAa,WAAW,QAAQ,OAAO,WAAW,SAChE,OAAM,IAAI,UAAU,uDAAuD;CAE5E,MAAM,QAA4B,EAAE;AACpC,KAAI,QAAQ,OAAW,OAAM,MAAM;AACnC,KAAI,YAAY,OAAW,OAAM,UAAU;AAC3C,KAAI,WAAW,OAAW,OAAM,SAAS;AACzC,KAAI,WAAW,OAAW,OAAM,SAAS;AACzC,KAAI,CAAC,wBAAwB,MAAM,CAClC,OAAM,IAAI,UAAU,+DAA+D;AAEpF,QAAO;;;;;;;;;AChKR,IAAa,mBAAb,MAAa,yBAAyB,MAAM;CAC3C,YACC,AAAO,MACP,SACA,AAAO,SAAiB,KACxB,AAAO,SACN;AACD,QAAM,QAAQ;EALP;EAEA;EACA;AAGP,OAAK,OAAO;;;;;CAMb,OAAO,WAAW,SAAiB,SAAqC;AACvE,SAAO,IAAI,iBAAiB,eAAe,SAAS,KAAK,QAAQ;;;;;CAMlE,OAAO,aAAa,UAAkB,gBAAkC;AACvE,SAAO,IAAI,iBAAiB,gBAAgB,SAAS,IAAI;;;;;CAM1D,OAAO,UAAU,UAAkB,aAA+B;AACjE,SAAO,IAAI,iBAAiB,aAAa,SAAS,IAAI;;;;;CAMvD,OAAO,SAAS,UAAkB,aAA+B;AAChE,SAAO,IAAI,iBAAiB,aAAa,SAAS,IAAI;;;;;CAMvD,OAAO,SAAS,SAAiB,SAAqC;AACrE,SAAO,IAAI,iBAAiB,YAAY,SAAS,KAAK,QAAQ;;;;;CAM/D,OAAO,SAAS,UAAkB,kBAAoC;AACrE,SAAO,IAAI,iBAAiB,kBAAkB,SAAS,IAAI;;;;;;;;;;AC8E7D,SAAgB,eACf,aACA,UACA,WAA2B,qBAAqB,aAAa,SAAS,EAC3D;CACX,MAAM,SAAS,UAAU,SAAS;AAElC,QAAO;EACN,MAAM,IAAO,KAAgC;AAC5C,OAAI,IAAI,WAAW,YAAY,CAAE,QAAO,SAAS,IAAO,IAAI,MAAM,EAAmB,CAAC;AACtF,UAAO,YAAY,IAAO,GAAG,SAAS,MAAM;;EAE7C,MAAM,aAAgB,KAAa;AAClC,oBAAiB,IAAI;AACrB,OAAI,IAAI,WAAW,YAAY,CAC9B,QAAO,SAAS,aAAgB,IAAI,MAAM,EAAmB,CAAC;AAE/D,UAAO,YAAY,aAAgB,GAAG,SAAS,MAAM;;EAEtD,MAAM,cAAc,KAAK,kBAAkB,OAAO;AACjD,oBAAiB,IAAI;AACrB,OAAI,IAAI,WAAW,YAAY,CAC9B,QAAO,SAAS,cAAc,IAAI,MAAM,EAAmB,EAAE,kBAAkB,MAAM;AAEtF,UAAO,YAAY,cAAc,GAAG,SAAS,OAAO,kBAAkB,MAAM;;EAE7E,MAAM,iBAAiB,KAAK,kBAAkB;AAC7C,oBAAiB,IAAI;AACrB,OAAI,IAAI,WAAW,YAAY,CAC9B,QAAO,SAAS,iBAAiB,IAAI,MAAM,EAAmB,EAAE,iBAAiB;AAElF,UAAO,YAAY,iBAAiB,GAAG,SAAS,OAAO,iBAAiB;;EAGzE,MAAM,IAAI,KAAa,OAA+B;AACrD,OAAI,IAAI,WAAW,YAAY,EAAE;AAChC,UAAM,SAAS,IAAI,IAAI,MAAM,EAAmB,EAAE,MAAM;AACxD;;AAED,SAAM,YAAY,IAAI,GAAG,SAAS,OAAO,MAAM;;EAGhD,MAAM,OAAO,KAA+B;AAC3C,OAAI,IAAI,WAAW,YAAY,CAAE,QAAO,SAAS,OAAO,IAAI,MAAM,EAAmB,CAAC;AACtF,UAAO,YAAY,OAAO,GAAG,SAAS,MAAM;;EAG7C,MAAM,KAAK,WAAqE;GAC/E,MAAM,kBAAkB,aAAa;GACrC,MAAM,mBACL,YAAY,WAAW,gBAAgB,IAAI,gBAAgB,WAAW,YAAY;GACnF,MAAM,aAAa,GAAG,SAAS;GAC/B,MAAM,aAAa,MAAM,YAAY,YAAY,WAAW;GAC5D,MAAM,SAAiD,EAAE;AACzD,QAAK,MAAM,CAAC,SAAS,UAAU,YAAY;AAC1C,QAAI,oBAAoB,QAAQ,WAAW,GAAG,OAAO,WAAW,CAAE;AAClE,WAAO,KAAK;KACX,KAAK,QAAQ,MAAM,OAAO,OAAO;KACjC;KACA,CAAC;;AAEH,OAAI,kBAAkB;IACrB,MAAM,gBAAgB,gBAAgB,WAAW,YAAY,GAC1D,gBAAgB,MAAM,EAAmB,GACzC;AACH,SAAK,MAAM,SAAS,MAAM,SAAS,KAAK,cAAc,EAAE;KACvD,MAAM,MAAM,YAAY,MAAM;AAC9B,SAAI,IAAI,WAAW,gBAAgB,CAAE,QAAO,KAAK;MAAE;MAAK,OAAO,MAAM;MAAO,CAAC;;;AAG/E,UAAO;;EAER;;;;;;AAWF,SAAS,wBACR,IACA,UACA,gBACA,SACuB;CACvB,MAAM,OAAO,IAAI,wBAA2B,IAAI,UAAU,gBAAgB,QAAQ;AAElF,QAAO;EACN,MAAM,OAAO,KAAK,IAAI,GAAG;EACzB,eAAe,OAAO,KAAK,aAAa,GAAG;EAC3C,gBAAgB,IAAI,kBAAkB,SAAS,KAAK,cAAc,IAAI,kBAAkB,KAAK;EAC7F,mBAAmB,IAAI,qBAAqB,KAAK,iBAAiB,IAAI,iBAAiB;EACvF,MAAM,IAAI,SAAS,KAAK,IAAI,IAAI,KAAK;EACrC,SAAS,OAAO,KAAK,OAAO,GAAG;EAC/B,SAAS,OAAO,KAAK,OAAO,GAAG;EAC/B,UAAU,QAAQ,KAAK,QAAQ,IAAI;EACnC,UAAU,UAAU,KAAK,QAAQ,MAAM;EACvC,aAAa,QAAQ,KAAK,WAAW,IAAI;EACzC,QAAQ,UAAU,KAAK,MAAM,MAAM;EACnC,WAAW,IAAI,eAAe,KAAK,SAAS,IAAI,WAAW;EAG3D,MAAM,MAAM,SAA2E;GACtF,MAAM,SAAS,MAAM,KAAK,MAAM;IAC/B,OAAO,SAAS;IAChB,SAAS,SAAS;IAClB,OAAO,SAAS;IAChB,QAAQ,SAAS;IACjB,CAAC;AAEF,UAAO;IACN,OAAO,OAAO;IACd,QAAQ,OAAO;IACf,SAAS,OAAO;IAChB;;EAEF;;;;;AAMF,SAAgB,oBACf,IACA,UACA,eACoC;CACpC,MAAM,UAA6C,EAAE;AAErD,MAAK,MAAM,CAAC,gBAAgB,WAAW,OAAO,QAAQ,cAAc,CAEnE,SAAQ,kBAAkB,wBAAwB,IAAI,UAAU,gBAD7C,CAAC,GAAG,OAAO,SAAS,GAAI,OAAO,iBAAiB,EAAE,CAAE,CACoB;AAG5F,QAAO;;;;;;AAWR,SAAS,kBAAkB,OAGzB;CACD,MAAM,EAAE,KAAK,GAAG,WAAW;AAE3B,KAAI,QAAQ,WAAc,QAAQ,QAAQ,OAAO,QAAQ,YAAY,MAAM,QAAQ,IAAI,EACtF,OAAM,IAAI,MAAM,gCAAgC;AAEjD,QAAO;EAAE;EAAQ;EAAK;;;;;;AAOvB,eAAe,iBACd,SACA,YACA,KACmB;CACnB,MAAM,SAAS,MAAM,QAAQ,UAAU,WAAW;AAClD,KAAI,QAAQ,UAAa,CAAC,OACzB,OAAM,IAAI,MACT,eAAe,WAAW,qFAE1B;AAEF,QAAO;;;;;;;AAQR,SAAS,uBAAuB,OAAgC;AAC/D,KAAI,CAAC,MAAO,QAAO,EAAE;AACrB,KAAI;EACH,MAAM,SAAkB,KAAK,MAAM,MAAM;AACzC,SAAO,MAAM,QAAQ,OAAO,GACzB,OAAO,QAAQ,SAAyB,OAAO,SAAS,SAAS,GACjE,EAAE;SACE;AACP,SAAO,EAAE;;;;AAKX,SAAS,mBAAmB,MAAkC;AAC7D,QAAO;EACN,IAAI,KAAK;EACT,UAAU,KAAK;EACf,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,UAAU,KAAK;EACf,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,kBAAkB,KAAK;EACvB;;AAGF,SAAS,uBACR,YAC8B;AAC9B,KAAI,CAAC,WAAY,QAAO;AACxB,QAAO;EACN,MAAM,WAAW;EACjB,OAAO,WAAW;EAClB,eAAe,WAAW,iBAAiB;EAC3C,aAAa,WAAW,eAAe;EACvC,UAAU,WAAW;EACrB,QAAQ,WAAW;EACnB,YAAY,WAAW,cAAc;EACrC,WAAW,WAAW,aAAa;EACnC,YAAY,WAAW,cAAc;EACrC,UAAU,WAAW,aAAa;EAClC,QAAQ,WAAW;EACnB,QAAQ,WAAW,OAAO,KAAK,WAAW;GACzC,MAAM,MAAM;GACZ,OAAO,MAAM;GACb,MAAM,MAAM;GACZ,UAAU,MAAM;GAChB,QAAQ,MAAM;GACd,GAAI,MAAM,iBAAiB,SAAY,EAAE,GAAG,EAAE,SAAS,MAAM,cAAc;GAC3E,GAAI,MAAM,eAAe,SAAY,EAAE,GAAG,EAAE,YAAY,MAAM,YAAY;GAC1E,GAAI,MAAM,WAAW,SAAY,EAAE,GAAG,EAAE,QAAQ,MAAM,QAAQ;GAC9D,GAAI,MAAM,YAAY,SAAY,EAAE,GAAG,EAAE,SAAS,MAAM,SAAS;GACjE,YAAY,MAAM;GAClB,SAAS,MAAM;GACf,cAAc,MAAM;GACpB,WAAW,MAAM;GACjB,EAAE;EACH;;AAGF,SAAgB,mBAAmB,IAAoC;CACtE,MAAM,WAAW,IAAI,eAAe,GAAG;AACvC,QAAO;EACN,MAAM,kBAAkB;GACvB,MAAM,cAAsC,EAAE;AAC9C,QAAK,MAAM,cAAc,MAAM,SAAS,2BAA2B,EAAE;IACpE,MAAM,OAAO,uBAAuB,WAAW;AAC/C,QAAI,KAAM,aAAY,KAAK,KAAK;;AAEjC,UAAO;;EAER,MAAM,cAAc,MAAM;AACzB,UAAO,uBAAuB,MAAM,SAAS,wBAAwB,KAAK,CAAC;;EAE5E;;;;;AAMF,SAAgB,qBAAqB,IAAsC;CAC1E,MAAM,eAAe,IAAI,mBAAmB,GAAG;AAE/C,QAAO;EACN,MAAM,OAAO,SAA2D;GACvE,IAAI,QAAQ,mBAAmB,GAAG;AAClC,OAAI,SAAS,WAAW,OAAW,SAAQ,MAAM,MAAM,YAAY,KAAK,QAAQ,OAAO;AAEvF,WADa,MAAM,MAAM,QAAQ,UAAU,MAAM,CAAC,SAAS,EAC/C,KAAK,SAAS;IACzB,MAAM,IAAI;IACV,OAAO,IAAI;IACX,eAAe,IAAI;IACnB,cAAc,IAAI,iBAAiB;IACnC,aAAa,uBAAuB,IAAI,YAAY;IACpD,QAAQ,IAAI;IACZ,EAAE;;EAGJ,MAAM,SAAS,UAAkB,SAA4D;AAE5F,WADc,MAAM,aAAa,WAAW,UAAU,EAAE,QAAQ,SAAS,QAAQ,CAAC,EACrE,IAAI,mBAAmB;;EAGrC,MAAM,cACL,YACA,SACA,SAC8B;AAO9B,WANc,MAAM,aAAa,iBAChC,YACA,SACA,SAAS,UACT,SAAS,OACT,EACY,IAAI,mBAAmB;;EAErC;;AAGF,SAAS,gBAAgB,SAAiC;AACzD,KAAI,QAAQ,WAAW,QAAS,OAAM,IAAI,MAAM,2CAA2C;AAC3F,QAAO;EACN,IAAI,QAAQ;EACZ,YAAY,QAAQ;EACpB,WAAW,QAAQ;EACnB,UAAU,QAAQ;EAClB,YAAY,QAAQ;EACpB,aAAa,QAAQ;EACrB,MAAM,QAAQ;EACd,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EAChB,WAAW,QAAQ;EACnB,oBAAoB,QAAQ;EAC5B,WAAW,QAAQ;EACnB,WAAW,QAAQ;EACnB;;AAGF,SAAgB,oBACf,IACA,UAKgB;CAChB,MAAM,OAAO,IAAI,kBAAkB,GAAG;AACtC,QAAO;EACN,MAAM,IAAI,IAAI;GACb,MAAM,UAAU,MAAM,KAAK,SAAS,GAAG;AACvC,UAAO,CAAC,WAAW,QAAQ,WAAW,UAAU,OAAO,gBAAgB,QAAQ;;EAEhF,MAAM,KAAK,UAA8B,EAAE,EAAE;GAC5C,MAAM,SAAS,MAAM,KAAK,cAAc,QAAQ;AAChD,UAAO;IACN,OAAO,OAAO,MAAM,IAAI,gBAAgB;IACxC,QAAQ,OAAO;IACf,SAAS,OAAO,eAAe;IAC/B;;EAEF,QAAQ,YAAY,KAAK,eAAe,QAAQ;EAChD,GAAI,WACD,EACA,YAAY,IAAI,QAAQ,YAAY,SAAS,IAAI,QAAQ,QAAQ,eAAe,EAChF,GACA,EAAE;EACL;;AAGF,IAAa,sBAAb,cAAyC,MAAM;CAC9C,AAAkB,OAAO;CAEzB,YACC,AAAS,MACT,SACC;AACD,QAAM,QAAQ;EAHL;;;AAOX,MAAM,2BAA2B;AACjC,MAAM,oBAAoB;AAE1B,SAAS,uBAAuB,IAAY,UAA0B;CACrE,MAAM,UAAU,GAAG,GAAG,IAAI;AAC1B,QAAO,GAAG,2BAA2B,KAAK,QAAQ,CAChD,WAAW,KAAK,IAAI,CACpB,WAAW,KAAK,IAAI,CACpB,QAAQ,mBAAmB,GAAG;;AAGjC,SAAS,uBAAuB,IAAY,UAA0B;AACrE,KAAI,OAAO,aAAa,YAAY,CAAC,SAAS,WAAW,yBAAyB,CACjF,OAAM,IAAI,oBAAoB,wBAAwB,4BAA4B;AAEnF,KAAI;EACH,MAAM,UAAU,SACd,MAAM,EAAgC,CACtC,WAAW,KAAK,IAAI,CACpB,WAAW,KAAK,IAAI;EACtB,MAAM,SAAS,QAAQ,OAAO,KAAK,KAAK,QAAQ,SAAS,EAAE,GAAG,GAAG,IAAI;EACrE,MAAM,CAAC,YAAY,WAAW,SAAS,KAAK,OAAO,CAAC,MAAM,KAAK;AAC/D,MAAI,eAAe,MAAM,CAAC,aAAa,UAAU,OAAW,OAAM,IAAI,MAAM,UAAU;AACtF,SAAO;UACC,OAAO;AACf,MAAI,iBAAiB,oBAAqB,OAAM;AAChD,QAAM,IAAI,oBAAoB,wBAAwB,4BAA4B;;;AAIpF,SAAS,eAAe,UAAkC;AACzD,QAAO;EACN,GAAG;EACH,MAAM,SAAS;EACf;;AAGF,SAAS,oBAAoB,QAAoD;AAChF,QAAO;EACN,UAAU,eAAe,OAAO,SAAS;EACzC,MAAM,uBAAuB,OAAO,SAAS,IAAI,OAAO,eAAe;EACvE;;AAGF,eAAe,sBACd,MACA,IACoC;CACpC,MAAM,SAAS,MAAM,KAAK,kBAAkB,GAAG;AAC/C,QAAO,SAAS,oBAAoB,OAAO,GAAG;;AAG/C,SAAS,oBAAoB,OAAiD;AAC7E,OAAM,IAAI,oBAAoB,MAAM,MAAM,MAAM,QAAQ;;AAGzD,SAAS,gCAAgC,OAAqB;AAC7D,KAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,MAAM,CACtE,OAAM,IAAI,oBAAoB,oBAAoB,mCAAmC;AAEtF,KAAI,OAAO,OAAO,OAAO,OAAO,CAC/B,OAAM,IAAI,oBACT,oBACA,qDACA;;AAMH,SAAgB,qBACf,IACA,WAAW,OACgC;CAC3C,MAAM,OAAO,IAAI,mBAAmB,GAAG;CACvC,MAAM,aAA6B;EAClC,MAAM,KAAK,UAA+B,EAAE,EAAE;GAC7C,MAAM,SAAS,MAAM,mBAAmB,IAAI,QAAQ;AACpD,OAAI,CAAC,OAAO,QAAS,QAAO,oBAAoB,OAAO,MAAM;AAC7D,UAAO;IACN,OAAO,OAAO,KAAK,MAAM,IAAI,eAAe;IAC5C,QAAQ,OAAO,KAAK;IACpB,SAAS,OAAO,KAAK,eAAe;IACpC;;EAEF,MAAM,OAAe,sBAAsB,MAAM,GAAG;EACpD;AACD,KAAI,CAAC,SAAU,QAAO;AAEtB,QAAO;EACN,GAAG;EACH,MAAM,OAAO,OAA4B;AACxC,mCAAgC,MAAM;GACtC,MAAM,SAAS,mBAAmB,UAAU,MAAM;AAClD,OAAI,CAAC,OAAO,QACX,OAAM,IAAI,oBACT,oBACA,OAAO,MAAM,OAAO,IAAI,WAAW,mBACnC;GAEF,MAAM,SAAS,MAAM,qBAAqB,IAAI,OAAO,KAAK;AAC1D,OAAI,CAAC,OAAO,QAAS,QAAO,oBAAoB,OAAO,MAAM;GAC7D,MAAM,UAAU,MAAM,sBAAsB,MAAM,OAAO,KAAK,GAAG;AACjE,OAAI,CAAC,QAAS,OAAM,IAAI,oBAAoB,aAAa,6BAA6B;AACtF,UAAO;;EAER,MAAM,OAAO,IAAY,OAA+C;AACvE,mCAAgC,MAAM;GACtC,MAAM,EAAE,MAAM,GAAG,UAAU;GAC3B,MAAM,mBAAmB,uBAAuB,IAAI,KAAK;GACzD,MAAM,SAAS,mBAAmB,UAAU,MAAM;AAClD,OAAI,CAAC,OAAO,QACX,OAAM,IAAI,oBACT,oBACA,OAAO,MAAM,OAAO,IAAI,WAAW,mBACnC;GAEF,MAAM,SAAS,MAAM,qBAAqB,IAAI,IAAI,OAAO,MAAM,EAAE,kBAAkB,CAAC;AACpF,OAAI,CAAC,OAAO,QAAS,QAAO,oBAAoB,OAAO,MAAM;GAC7D,MAAM,UAAU,MAAM,sBAAsB,MAAM,OAAO,KAAK,GAAG;AACjE,OAAI,CAAC,QAAS,OAAM,IAAI,oBAAoB,aAAa,6BAA6B;AACtF,UAAO;;EAER,MAAM,OAAO,IAAY,SAA2B;AACnD,OAAI,OAAO,YAAY,YAAY,YAAY,KAC9C,OAAM,IAAI,oBAAoB,wBAAwB,4BAA4B;GAGnF,MAAM,SAAS,MAAM,qBAAqB,IAAI,IAAI,EAAE,kBAD3B,uBAAuB,IAAI,QAAQ,KAAK,EACK,CAAC;AACvE,OAAI,CAAC,OAAO,QAAS,QAAO,oBAAoB,OAAO,MAAM;AAC7D,UAAO,OAAO,KAAK;;EAEpB;;AAGF,MAAM,2BAA2B;AAEjC,SAAS,oBAAoB,MAAc,SAAwB;AAClE,QAAO,OAAO,OAAO,IAAI,MAAM,QAAQ,EAAE,EAAE,MAAM,CAAC;;AAGnD,eAAe,qBACd,IACA,YACA,SACA,UACA,SAC0E;AAC1E,KAAI,QAAQ,SAAS,yBACpB,OAAM,oBACL,oBACA,mDAAmD,yBAAyB,WAC5E;AAEF,KAAI,QAAQ,MAAM,OAAO,OAAO,OAAO,YAAY,GAAG,WAAW,EAAE,CAClE,OAAM,oBAAoB,oBAAoB,8CAA8C;CAG7F,MAAM,YAAY,MAAM,sBAAsB,IAAI,SAAS;AAC3D,KAAI,CAAC,UACJ,OAAM,oBAAoB,aAAa,aAAa,SAAS,aAAa;AAG3E,KAAI,CADa,UAAU,YAAY,SAAS,WAAW,CAE1D,OAAM,oBACL,oBACA,aAAa,SAAS,mCAAmC,WAAW,GACpE;CAGF,MAAM,QAAQ,MAAM,IAAI,kBAAkB,GAAG,CAAC,SAAS,YAAY,QAAQ;AAC3E,KAAI,CAAC,MACJ,OAAM,oBACL,aACA,kBAAkB,QAAQ,kBAAkB,WAAW,GACvD;CAGF,MAAM,OAAO,IAAI,mBAAmB,GAAG;CACvC,MAAM,SAAmB,EAAE;AAC3B,MAAK,MAAM,MAAM,IAAI,IAAI,QAAQ,EAAE;EAClC,MAAM,OAAO,MAAM,KAAK,2BAA2B,GAAG;AACtD,MAAI,CAAC,KAAM,OAAM,oBAAoB,aAAa,kBAAkB,GAAG,aAAa;AACpF,MAAI,KAAK,SAAS,SACjB,OAAM,oBACL,oBACA,kBAAkB,GAAG,gBAAgB,KAAK,KAAK,UAAU,SAAS,GAClE;AAEF,SAAO,KAAK,KAAK,oBAAoB,KAAK,GAAG;;AAG9C,QAAO;EAAE;EAAM;EAAQ,QAAQ,MAAM,UAAU,eAAe,EAAE,iBAAiB;EAAM;;AAGxF,eAAe,uBACd,MACA,YACA,SACA,UACA,QAC8B;CAC9B,MAAM,gBAAgB,eAAe,EAAE,iBAAiB;AAQxD,SAPoB,MAAM,KAAK,2BAC9B,YACA,SACA,UACA,QACA,cACA,EACkB,SAAS,EAAE,WAAY,OAAO,CAAC,mBAAmB,KAAK,CAAC,GAAG,EAAE,CAAE;;AAGnF,SAAgB,8BAA8B,IAA+C;AAC5F,QAAO;EACN,GAAG,qBAAqB,GAAG;EAC3B,MAAM,WAAW,UAAkB,OAAgC;GAClE,MAAM,SAAS,MAAM,iBAAiB,IAAI,UAAU,MAAM;AAC1D,OAAI,CAAC,OAAO,QAAS,OAAM,oBAAoB,OAAO,MAAM,MAAM,OAAO,MAAM,QAAQ;GACvF,MAAM,EAAE,SAAS,OAAO;AACxB,UAAO;IACN,IAAI,KAAK;IACT,UAAU,KAAK;IACf,MAAM,KAAK;IACX,OAAO,KAAK;IACZ,UAAU,KAAK;IACf,MAAM,KAAK,cAAc,EAAE,aAAa,KAAK,aAAa,GAAG;IAC7D,QAAQ,KAAK;IACb,kBAAkB,KAAK;IACvB;;EAEF,MAAM,cAAc,YAAY,SAAS,UAAU,SAAS;GAC3D,MAAM,EAAE,MAAM,QAAQ,WAAW,MAAM,qBACtC,IACA,YACA,SACA,UACA,QACA;AACD,SAAM,KAAK,oBAAoB,YAAY,SAAS,OAAO;AAC3D,UAAO,uBAAuB,MAAM,YAAY,SAAS,UAAU,OAAO;;EAE3E,MAAM,iBAAiB,YAAY,SAAS,UAAU,SAAS;GAC9D,MAAM,EAAE,MAAM,QAAQ,WAAW,MAAM,qBACtC,IACA,YACA,SACA,UACA,QACA;AACD,SAAM,KAAK,sBAAsB,YAAY,SAAS,OAAO;AAC7D,UAAO,uBAAuB,MAAM,YAAY,SAAS,UAAU,OAAO;;EAE3E;;AAUF,eAAe,kBAAkB,aAA0D;AAC1F,KAAI,OAAO,gBAAgB,WAAY,OAAM,aAAa;;;;;;;;;;;AAY3D,SAAgB,6BACf,IACA,oBACA,eACA,eAKyB;AAGzB,QAAO;EACN,GAHkB,oBAAoB,IAAI,cAAc;EAKxD,MAAM,OACL,YACA,MACA,SACuB;GACvB,MAAM,SAAS,2BAA2B,SAAS,OAAO;GAC1D,MAAM,cAAc,MAAM,sBAAsB;AAChD,OAAI,eAAe;IAClB,MAAM,UAAU,MAAM,cAAc;KACnC;KACA,OAAO;KACP,SAAS;MAAE,GAAG;MAAS;MAAQ;KAC/B,CAAC;AACF,UAAM,kBAAkB,YAAY;AACpC,WAAO;;GAER,MAAM,EAAE,QAAQ,QAAQ,kBAAkB,KAAK;GAC/C,IAAI,iBAAiB;AAErB,OAAI;IACH,MAAM,UAAU,MAAM,gBAAgB,IAAI,OAAO,QAAQ;KACxD,MAAM,iBAAiB,IAAI,kBAAkB,IAAI;KACjD,MAAM,aAAa,IAAI,cAAc,IAAI;KAEzC,MAAM,SAAS,MAAM,iBAAiB,YAAY,YAAY,IAAI;KAElE,MAAM,OAAO,MAAM,eAAe,OAAO;MACxC,MAAM;MACN,MAAM;MACN;MACA,eAAe,SAAS;MACxB,CAAC;AACF,sBAAiB;KAEjB,MAAM,SAAsB;MAC3B,IAAI,KAAK;MACT,MAAM,KAAK;MACX,MAAM,KAAK;MACX,QAAQ,KAAK;MACb,MAAM,KAAK;MACX,WAAW,KAAK;MAChB,WAAW,KAAK;MAChB,QAAQ,KAAK;MACb,aAAa,KAAK;MAClB,aAAa,KAAK;MAClB;AAED,SAAI,OACH,QAAO,MACN,QAAQ,SACL,MAAM,WAAW,OAAO,YAAY,KAAK,IAAI,IAAI,GACjD,MAAM,WAAW,IAAI,YAAY,KAAK,GAAG;AAG9C,YAAO;MACN;AACF,UAAM,2CAA2C,IAAI,YAAY,sBAAsB;AACvF,UAAM,kBAAkB,YAAY;AACpC,WAAO;YACC,OAAO;AACf,QAAI,eACH,OAAM,2CAA2C,IAAI,YAAY,sBAAsB;AAExF,UAAM;;;EAIR,MAAM,OAAO,YAAoB,IAAY,MAA+C;GAC3F,MAAM,cAAc,MAAM,sBAAsB;GAChD,MAAM,EAAE,QAAQ,QAAQ,kBAAkB,KAAK;GAC/C,MAAM,kBAAkB,OAAO,KAAK,OAAO,CAAC,SAAS;GACrD,IAAI,iBAAiB;AAErB,OAAI;IACH,MAAM,UAAU,MAAM,gBAAgB,IAAI,OAAO,QAAQ;KACxD,MAAM,iBAAiB,IAAI,kBAAkB,IAAI;KACjD,MAAM,aAAa,IAAI,cAAc,IAAI;KAEzC,MAAM,SAAS,MAAM,iBAAiB,YAAY,YAAY,IAAI;KAOlE,MAAM,OAAO,kBACV,MAAM,eAAe,iBAAiB,YAAY,IAAI,EAAE,MAAM,QAAQ,CAAC,GACvE,OAAO,YAAY;MACnB,MAAM,WAAW,MAAM,eAAe,SAAS,YAAY,GAAG;AAC9D,UAAI,CAAC,SAAU,OAAM,IAAI,MAAM,oBAAoB;AACnD,aAAO;SACJ;AACN,SAAI,gBAAiB,kBAAiB;KAEtC,MAAM,SAAsB;MAC3B,IAAI,KAAK;MACT,MAAM,KAAK;MACX,MAAM,KAAK;MACX,QAAQ,KAAK;MACb,MAAM,KAAK;MACX,WAAW,KAAK;MAChB,WAAW,KAAK;MAChB,QAAQ,KAAK;MACb,aAAa,KAAK;MAClB,aAAa,KAAK;MAClB;AAED,SAAI,OACH,QAAO,MACN,QAAQ,SACL,MAAM,WAAW,OAAO,YAAY,KAAK,IAAI,IAAI,GACjD,MAAM,WAAW,IAAI,YAAY,KAAK,GAAG;AAG9C,YAAO;MACN;AACF,QAAI,gBACH,OAAM,2CAA2C,IAAI,YAAY,sBAAsB;AAExF,UAAM,kBAAkB,YAAY;AACpC,WAAO;YACC,OAAO;AACf,QAAI,eACH,OAAM,2CAA2C,IAAI,YAAY,sBAAsB;AAExF,UAAM;;;EAIR,MAAM,OAAO,YAAoB,IAA8B;GAC9D,MAAM,cAAc,MAAM,sBAAsB;GAEhD,MAAM,UAAU,MADI,IAAI,kBAAkB,GAAG,CACX,OAAO,YAAY,GAAG;AACxD,OAAI,SAAS;AAGZ,UAAM,IAAI,oBAAoB,GAAG,CAAC,aAAa,YAAY,GAAG;AAC9D,UAAM,2CAA2C,IAAI,YAAY,sBAAsB;AACvF,UAAM,kBAAkB,YAAY;;AAErC,UAAO;;EAER;;;;;AAUF,SAAgB,kBAAkB,IAAmC;CACpE,MAAM,YAAY,IAAI,gBAAgB,GAAG;AAEzC,QAAO;EACN,MAAM,IAAI,IAAuC;GAChD,MAAM,OAAO,MAAM,UAAU,SAAS,GAAG;AACzC,UAAO,MAAM,WAAW,UAAU,kBAAkB,KAAK,GAAG;;EAG7D,MAAM,KAAK,SAAiE;GAC3E,MAAM,SAAS,MAAM,UAAU,SAAS;IACvC,OAAO,SAAS,SAAS;IACzB,QAAQ,SAAS;IACjB,UAAU,SAAS;IACnB,CAAC;AAEF,UAAO;IACN,OAAO,OAAO,MAAM,IAAI,kBAAkB;IAC1C,QAAQ,OAAO;IACf,SAAS,CAAC,CAAC,OAAO;IAClB;;EAEF;;AAGF,SAAS,kBAAyB;AACjC,OAAM,IAAI,MAAM,iCAAiC;;AAGlD,SAAS,+BAA4C;AACpD,QAAO;EACN,KAAK,YAAY,iBAAiB;EAClC,MAAM,YAAY,iBAAiB;EACnC;;AAGF,SAAS,kBAAkB,aAA6B;AACvD,KAAI,CAAC,gBAAgB,KAAK,YAAY,CACrC,OAAM,iBAAiB,WAAW,uBAAuB;CAE1D,MAAM,WAAW,cAAc,YAAY;AAC3C,KAAI,CAAC,qBAAqB,UAAU,wBAAwB,CAC3D,OAAM,IAAI,iBAAiB,0BAA0B,yBAAyB,IAAI;AAEnF,QAAO;;AAGR,SAAS,iBACR,UACA,UAC2C;CAC3C,MAAM,YAAY,MAAM;CACxB,MAAM,WAAW,SAAS,MAAM,IAAI,CAAC,KAAK,IAAI;CAC9C,MAAM,SAAS,SAAS,YAAY,IAAI;CACxC,MAAM,UAAU,SAAS,IAAI,SAAS,MAAM,SAAS,EAAE,CAAC,aAAa,GAAG;CAExE,MAAM,WAAW,KAAK,QAAQ,QAAQ;CACtC,MAAM,iBACL,aAAa,QAAQ,qBAAqB,UAAU,wBAAwB;CAC7E,MAAM,MACL,aAAa,WACV,UACC,KAAK,aAAa,SAAS,KAAK,iBAAiB,UAAU;AAChE,QAAO;EAAE;EAAU,YAAY,MAAM,GAAG,UAAU,GAAG,QAAQ;EAAW;;;;;;;;;;AAWzE,SAAgB,2BACf,IACA,gBAGA,SACuB;CACvB,MAAM,YAAY,IAAI,gBAAgB,GAAG;CACzC,MAAM,aAAa,kBAAkB,GAAG;CAExC,MAAM,eAAe,iBAClB,OAAO,UAAkB,gBACzB,eAAe,UAAU,kBAAkB,YAAY,CAAC,GACxD,OAAO,UAAkB,gBAAwB;AACjD,MAAI,CAAC,QACJ,OAAM,IAAI,MACT,qGACA;EAGF,MAAM,WAAW,kBAAkB,YAAY;EAC/C,MAAM,EAAE,UAAU,eAAe,iBAAiB,UAAU,SAAS;EAErE,MAAM,QAAQ,MAAM,UAAU,cAAc;GAC3C,UAAU;GACV;GACA;GACA,CAAC;AAQF,SAAO;GAAE,YANM,MAAM,QAAQ,mBAAmB;IAC/C,KAAK;IACL,aAAa;IACb,WAAW;IACX,CAAC,EAEyB;GAAK,SAAS,MAAM;GAAI;;AAGtD,QAAO;EACN,GAAG;EAEH;EAEA,MAAM,OACL,UACA,aACA,OACgE;AAChE,OAAI,CAAC,QACJ,OAAM,IAAI,MACT,+FACA;GAGF,MAAM,WAAW,kBAAkB,YAAY;GAC/C,MAAM,EAAE,UAAU,eAAe,iBAAiB,UAAU,SAAS;AAGrE,SAAM,QAAQ,OAAO;IACpB,KAAK;IACL,MAAM,IAAI,WAAW,MAAM;IAC3B,aAAa;IACb,CAAC;GAGF,MAAM,WAAW,MAAM,oBAAoB,IAAI,WAAW,MAAM,EAAE,SAAS;GAG3E,IAAI;AACJ,OAAI;AACH,YAAQ,MAAM,UAAU,OAAO;KAC9B,UAAU;KACV;KACA,MAAM,MAAM;KACZ;KACA,QAAQ;KACR,OAAO,SAAS;KAChB,QAAQ,SAAS;KACjB,UAAU,SAAS;KACnB,eAAe,SAAS;KACxB,CAAC;YACM,OAAO;AACf,QAAI;AACH,WAAM,QAAQ,OAAO,WAAW;YACzB;AAGR,UAAM;;AAGP,UAAO;IACN,SAAS,MAAM;IACf;IACA,KAAK,2BAA2B;IAChC;;EAGF,MAAM,OAAO,IAA8B;GAC1C,MAAM,SAAS,MAAM,kBAAkB,IAAI,IAAI,QAAQ;AACvD,OAAI,CAAC,OAAO,SAAS;AACpB,QAAI,OAAO,MAAM,SAAS,YAAa,QAAO;AAC9C,UAAM,IAAI,MAAM,OAAO,MAAM,QAAQ;;AAOtC,gCAA6B;AAC7B,UAAO;;EAER;;;AAQF,MAAM,uBAAuB;AAE7B,SAAS,kBAAkB,OAAuB;CACjD,IAAI,MAAM,MAAM;AAChB,QAAO,MAAM,KAAK,MAAM,WAAW,MAAM,EAAE,KAAK,GAAI;AACpD,QAAO,QAAQ,MAAM,SAAS,QAAQ,MAAM,MAAM,GAAG,IAAI;;;;;;;AAQ1D,SAAS,cAAc,MAAc,cAAiC;CACrE,MAAM,iBAAiB,kBAAkB,KAAK,aAAa,CAAC;AAC5D,QAAO,aAAa,MAAM,YAAY;EACrC,MAAM,oBAAoB,kBAAkB,QAAQ,aAAa,CAAC;AAClE,MAAI,sBAAsB,IAAK,QAAO;AACtC,MAAI,kBAAkB,WAAW,KAAK,EAAE;GACvC,MAAM,SAAS,kBAAkB,MAAM,EAAE;AAEzC,UAAO,eAAe,SAAS,OAAO,IAAI,mBAAmB,kBAAkB,MAAM,EAAE;;AAExF,SAAO,mBAAmB;GACzB;;AAGH,SAAS,yBAAyB,KAAyB;AAC1D,KAAI;AACH,SAAO,IAAI,IAAI,IAAI;SACZ;AACP,SAAO;;;AAIT,eAAe,yBAAyB,UAAkB,KAA2B;AACpF,KAAI;AACH,SAAO,MAAM,8BAA8B,IAAI;UACvC,OAAO;EACf,MAAM,UAAU,iBAAiB,YAAY,MAAM,UAAU;EAC7D,MAAM,SAAS,yBAAyB,IAAI;AAC5C,QAAM,IAAI,MACT,WAAW,SAAS,uBAAuB,SAAS,OAAO,WAAW,cAAc,KAAK,WACzF,EAAE,OAAO,OAAO,CAChB;;;;;;;;AASH,SAAgB,iBACf,UACA,cACA,YAA0B,WAAW,OACxB;AACb,QAAO,EACN,MAAM,MAAM,KAAa,MAAuC;AAE/D,MAAI,aAAa,WAAW,EAC3B,OAAM,IAAI,MACT,WAAW,SAAS,0GAEpB;EAGF,IAAI,aAAa;EACjB,IAAI,cAAc;EAClB,IAAI,kBAAkB;EACtB,IAAI,aAAa;AAEjB,OAAK,IAAI,IAAI,GAAG,KAAK,sBAAsB,KAAK;GAC/C,MAAM,SAAS,yBAAyB,WAAW;AACnD,OAAI,UAAU,CAAC,cAAc,OAAO,UAAU,aAAa,CAC1D,OAAM,IAAI,MACT,WAAW,SAAS,uCAAuC,OAAO,SAAS,oBACxD,aAAa,KAAK,KAAK,GAC1C;AAEF,SAAM,yBAAyB,UAAU,WAAW;AACpD,OAAI,CAAC,iBAAiB;AACrB,kBAAc,MAAM,wBAAwB,YAAY;AACxD,sBAAkB;;GAGnB,MAAM,WAAW,MAAM,UAAU,YAAY;IAC5C,GAAG;IACH,UAAU;IACV,CAAC;GAEF,MAAM,WAAW,SAAS,QAAQ,IAAI,WAAW;AACjD,OAAI,aAAa,KAChB,QAAO,2BACN,MAAM,yBAAyB,UAAU,YAAY,WAAW,CAChE;GAEF,MAAM,iBAAiB,yBAAyB,SAAS,QAAQ,MAAM,YAAY;AACnF,OAAI,mBAAmB,SACtB,QAAO,2BACN,MAAM,yBAAyB,UAAU,YAAY,WAAW,CAChE;AAEF,SAAM,SAAS,MAAM,QAAQ;AAC7B,OAAI,mBAAmB,QACtB,OAAM,IAAI,MAAM,WAAW,SAAS,6BAA6B;GAIlE,MAAM,iBAAiB,IAAI,IAAI,WAAW,CAAC;AAC3C,gBAAa,IAAI,IAAI,UAAU,WAAW,CAAC;AAC3C,gBAAa;GACb,MAAM,aAAa,IAAI,IAAI,WAAW,CAAC;AACvC,iBAAc,0BAA0B,SAAS,QAAQ,YAAY;AAErE,OAAI,mBAAmB,cAAc,YACpC,eAAc,uBAAuB,YAAY;;AAInD,QAAM,IAAI,MAAM,WAAW,SAAS,6BAA6B,qBAAqB,GAAG;IAE1F;;;;;;;AAQF,SAAgB,6BACf,UACA,YAA0B,WAAW,OACxB;AACb,QAAO,EACN,MAAM,MAAM,KAAa,MAAuC;EAC/D,IAAI,aAAa;EACjB,IAAI,cAAc;EAClB,IAAI,kBAAkB;EACtB,IAAI,aAAa;AAEjB,OAAK,IAAI,IAAI,GAAG,KAAK,sBAAsB,KAAK;AAC/C,SAAM,yBAAyB,UAAU,WAAW;AACpD,OAAI,CAAC,iBAAiB;AACrB,kBAAc,MAAM,wBAAwB,YAAY;AACxD,sBAAkB;;GAGnB,MAAM,WAAW,MAAM,UAAU,YAAY;IAC5C,GAAG;IACH,UAAU;IACV,CAAC;GAEF,MAAM,WAAW,SAAS,QAAQ,IAAI,WAAW;AACjD,OAAI,aAAa,KAChB,QAAO,2BACN,MAAM,yBAAyB,UAAU,YAAY,WAAW,CAChE;GAEF,MAAM,iBAAiB,yBAAyB,SAAS,QAAQ,MAAM,YAAY;AACnF,OAAI,mBAAmB,SACtB,QAAO,2BACN,MAAM,yBAAyB,UAAU,YAAY,WAAW,CAChE;AAEF,SAAM,SAAS,MAAM,QAAQ;AAC7B,OAAI,mBAAmB,QACtB,OAAM,IAAI,MAAM,WAAW,SAAS,6BAA6B;GAIlE,MAAM,iBAAiB,IAAI,IAAI,WAAW,CAAC;AAC3C,gBAAa,IAAI,IAAI,UAAU,WAAW,CAAC;AAC3C,gBAAa;GACb,MAAM,aAAa,IAAI,IAAI,WAAW,CAAC;AACvC,iBAAc,0BAA0B,SAAS,QAAQ,YAAY;AAErE,OAAI,mBAAmB,cAAc,YACpC,eAAc,uBAAuB,YAAY;;AAInD,QAAM,IAAI,MAAM,WAAW,SAAS,6BAA6B,qBAAqB,GAAG;IAE1F;;;;;AAwBF,SAAgB,gBAAgB,UAAkB,UAA4C;CAC7F,MAAM,SAAS,WAAW,SAAS;CACnC,MAAM,UAAa,UAAgB,UAAU,OAAO,MAAM,IAAI;AAE9D,QAAO;EACN,MAAM,SAAiB,MAAsB;AAC5C,OAAI,SAAS,OACZ,SAAQ,MAAM,QAAQ,OAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;OAEpD,SAAQ,MAAM,QAAQ,OAAO,QAAQ,CAAC;;EAIxC,KAAK,SAAiB,MAAsB;AAC3C,OAAI,SAAS,OACZ,SAAQ,KAAK,QAAQ,OAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;OAEnD,SAAQ,KAAK,QAAQ,OAAO,QAAQ,CAAC;;EAIvC,KAAK,SAAiB,MAAsB;AAC3C,OAAI,SAAS,OACZ,SAAQ,KAAK,QAAQ,OAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;OAEnD,SAAQ,KAAK,QAAQ,OAAO,QAAQ,CAAC;;EAIvC,MAAM,SAAiB,MAAsB;AAC5C,OAAI,SAAS,OACZ,SAAQ,MAAM,QAAQ,OAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;OAEpD,SAAQ,MAAM,QAAQ,OAAO,QAAQ,CAAC;;EAGxC;;AAOF,MAAM,oBAAoB;;;;;;;;;AAwB1B,SAAgB,eAAe,SAAoC;AAClE,QAAO;EACN,MAAM,QAAQ,YAAY;EAC1B,MAAM,QAAQ,WAAW,IAAI,QAAQ,mBAAmB,GAAG;EAC3D,QAAQ,QAAQ,UAAU;EAC1B,eAAe,QAAQ,iBAAiB;EACxC;;;;;;AAOF,SAAgB,gBAAgB,SAA2C;CAC1E,MAAM,OAAO,QAAQ,QAAQ,mBAAmB,GAAG;AAEnD,SAAQ,SAAyB;AAChC,MAAI,CAAC,KAAK,WAAW,IAAI,CACxB,OAAM,IAAI,MAAM,uCAAuC,KAAK,GAAG;AAEhE,MAAI,KAAK,WAAW,KAAK,CACxB,OAAM,IAAI,MAAM,iDAAiD,KAAK,GAAG;AAE1E,SAAO,GAAG,OAAO;;;;;;;AAYnB,SAAS,WAAW,MAMP;AACZ,QAAO;EACN,IAAI,KAAK;EACT,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,MAAM,KAAK;EACX,WAAW,KAAK;EAChB;;;;;;AAOF,SAAgB,iBAAiB,IAAkC;CAClE,MAAM,WAAW,IAAI,eAAe,GAAG;AAEvC,QAAO;EACN,MAAM,IAAI,IAAsC;GAC/C,MAAM,OAAO,MAAM,SAAS,SAAS,GAAG;AACxC,OAAI,CAAC,KAAM,QAAO;AAClB,UAAO,WAAW,KAAK;;EAGxB,MAAM,WAAW,OAAyC;GACzD,MAAM,OAAO,MAAM,SAAS,YAAY,MAAM;AAC9C,OAAI,CAAC,KAAM,QAAO;AAClB,UAAO,WAAW,KAAK;;EAGxB,MAAM,KAAK,MAI6C;GACvD,MAAM,SAAS,MAAM,SAAS,SAAS;IACtC,MAAM,MAAM;IACZ,QAAQ,MAAM;IACd,OAAO,MAAM;IACb,CAAC;AAEF,UAAO;IACN,OAAO,OAAO,MAAM,IAAI,WAAW;IACnC,YAAY,OAAO;IACnB;;EAEF;;;;;AAqIF,IAAa,uBAAb,MAAkC;CACjC,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAIR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;;;;;;CAMR,AAAQ,4CAA4B,IAAI,KAAa;CAErD,YAAY,SAAsC;EACjD,MAAM,UAAU,QAAQ;AACxB,OAAK,YAAY,QAAQ,gBAAgB;AACzC,OAAK,qBAAqB,QAAQ;AAClC,OAAK,gBAAgB,QAAQ;AAC7B,OAAK,iBAAiB,QAAQ;AAC9B,OAAK,UAAU,QAAQ;AACvB,OAAK,eAAe,QAAQ;AAC5B,OAAK,OAAO,eAAe,QAAQ,YAAY,EAAE,CAAC;AAClD,OAAK,YAAY,gBAAgB,KAAK,KAAK,IAAI;AAC/C,OAAK,iBAAiB,QAAQ;AAC9B,OAAK,MAAM,QAAQ,8BAAc,IAAI,MAAM;AAC3C,OAAK,gBAAgB,QAAQ;AAC7B,OAAK,kBAAkB,QAAQ;;;;;CAMhC,cAAc,QAAuC;EACpD,MAAM,eAAe,IAAI,IAAI,OAAO,aAAa;EAMjD,MAAM,KAAK,KAAK,WAAW;EAC3B,MAAM,cAAc,IAAI,kBAAkB,GAAG;EAG7C,MAAM,iBAAiB,4BAA4B;EACnD,MAAM,WAAW,qBAChB,aACA,OAAO,IACP,OAAO,MAAM,kBAAkB,EAAE,EACjC,QACA,eAAe,IACf;EACD,MAAM,KAAK,eAAe,aAAa,OAAO,IAAI,SAAS;EAC3D,MAAM,MAAM,gBAAgB,OAAO,IAAI,eAAe;EACtD,MAAM,UAAU,oBAAoB,IAAI,OAAO,IAAI,OAAO,QAAQ;EAMlE,IAAI;AACJ,MAAI,aAAa,IAAI,gBAAgB,CACpC,WAAU,6BACT,IACA,KAAK,oBACL;GACC,MAAM,KAAK;GACX,WAAW,aAAa,IAAI,yBAAyB;GACrD,EACD,KAAK,iBACD,UAAU,KAAK,cAAe,OAAO,IAAI,MAAM,YAAY,MAAM,OAAO,MAAM,QAAQ,GACvF,OACH;WACS,aAAa,IAAI,eAAe,CAC1C,WAAU,oBAAoB,IAAI;GACjC,MAAM,KAAK;GACX,WAAW,aAAa,IAAI,yBAAyB;GACrD,CAAC;AAEH,MAAI,aAAa,IAAI,kBAAkB,IAAI,KAAK,eAC/C,WAAU,OAAO,OAAO,WAAW,oBAAoB,GAAG,EAAE;GAC3D,eAAe,YAAoB,OAClC,KAAK,eAAgB,aAAa,OAAO,IAAI,YAAY,GAAG;GAC7D,UAAU,YAAoB,IAAY,YACzC,KAAK,eAAgB,QAAQ,OAAO,IAAI,YAAY,IAAI,QAAQ;GACjE,YAAY,YAAoB,IAAY,YAC3C,KAAK,eAAgB,UAAU,OAAO,IAAI,YAAY,IAAI,QAAQ;GACnE,WACC,YACA,IACA,YACI,KAAK,eAAgB,SAAS,OAAO,IAAI,YAAY,IAAI,QAAQ;GACtE,aAAa,YAAoB,IAAY,YAC5C,KAAK,eAAgB,WAAW,OAAO,IAAI,YAAY,IAAI,QAAQ;GACpE,CAAC;AAEH,MAAI,aAAa,IAAI,kBAAkB,IAAI,KAAK,eAC/C,WAAU,OAAO,OAChB,WAAW;GACV,KAAK,YAAY;AAChB,UAAM,IAAI,MAAM,mCAAmC;;GAEpD,MAAM,YAAY;AACjB,UAAM,IAAI,MAAM,mCAAmC;;GAEpD,EACD;GACC,sBAAsB,YAAoB,OACzC,KAAK,eAAgB,oBAAoB,OAAO,IAAI,YAAY,GAAG;GACpE,UAAU,YAAoB,IAAY,YACzC,KAAK,eAAgB,QAAQ,OAAO,IAAI,YAAY,IAAI,QAAQ;GACjE,CACD;EAGF,MAAM,SAAS,aAAa,IAAI,cAAc,GAAG,mBAAmB,GAAG,GAAG;EAG1E,IAAI;AACJ,MAAI,aAAa,IAAI,mBAAmB,CACvC,cAAa,8BAA8B,GAAG;WACpC,aAAa,IAAI,kBAAkB,CAC7C,cAAa,qBAAqB,GAAG;EAGtC,IAAI;AACJ,MAAI,aAAa,IAAI,kBAAkB,CACtC,aAAY,qBAAqB,IAAI,KAAK;WAChC,aAAa,IAAI,iBAAiB,CAC5C,aAAY,qBAAqB,GAAG;EAQrC,IAAI;AAMJ,MAJC,aAAa,IAAI,aAAa,IAC9B,aAAa,IAAI,cAAc,IAC/B,aAAa,IAAI,mBAAmB,IACpC,aAAa,IAAI,uBAAuB,CAExC,SACC,aAAa,IAAI,aAAa,IAAI,aAAa,IAAI,cAAc,GAC9D,kBAAkB,GAAG,GACrB,8BAA8B;AAEnC,MAAI,aAAa,IAAI,cAAc,CAClC,KAAI,KAAK,gBAAgB,KAAK,QAC7B,SAAQ,2BAA2B,IAAI,KAAK,cAAc,KAAK,QAAQ;OACjE;AACN,OAAI,CAAC,KAAK,0BAA0B,IAAI,OAAO,GAAG,EAAE;AACnD,SAAK,0BAA0B,IAAI,OAAO,GAAG;AAC7C,QAAI,KACH,qGACA;;AAEF,aAAU,kBAAkB,GAAG;;AAGjC,MAAI,aAAa,IAAI,mBAAmB,IAAI,MAC3C,OAAM,aAAa,IAAI,YAAY,qBAAqB,IAAI,KAAK,SAAS,IAAI,QAAQ;AAEvF,MAAI,aAAa,IAAI,uBAAuB,IAAI,MAC/C,OAAM,kBAAkB,IAAI,UAAU,0BAA0B,IAAI,IAAI,MAAM;EAI/E,IAAI;AACJ,MAAI,aAAa,IAAI,+BAA+B,CACnD,QAAO,6BAA6B,OAAO,GAAG;WACpC,aAAa,IAAI,kBAAkB,CAC7C,QAAO,iBAAiB,OAAO,IAAI,OAAO,aAAa;EAIxD,IAAI;AACJ,MAAI,aAAa,IAAI,aAAa,CACjC,SAAQ,iBAAiB,GAAG;EAG7B,IAAI;AACJ,MAAI,aAAa,IAAI,oBAAoB,CACxC,YAAW,oBAAoB,KAAK,IAAI,QAAQ,mBAAmB;AAClE,OAAI,CAAC,KAAK,gBAAiB,OAAM,IAAI,MAAM,oCAAoC;AAC/E,UAAO,KAAK,gBAAgB,OAAO,IAAI,IAAI,QAAQ,eAAe;IACjE;WACQ,aAAa,IAAI,gBAAgB,CAC3C,YAAW,oBAAoB,GAAG;EAKnC,IAAI;AACJ,MAAI,KAAK,eACR,QAAO,IAAI,eAAe,IAAI,OAAO,IAAI,KAAK,gBAAgB,KAAK,IAAI;EAIxE,IAAI;AACJ,MAAI,aAAa,IAAI,aAAa,IAAI,KAAK,eAAe,aAAa,EAAE;GACxE,MAAM,WAAW,KAAK;GACtB,MAAM,WAAW,OAAO;AACxB,WAAQ,EACP,OAAO,YAAY,SAAS,KAAK,SAAS,SAAS,EACnD;;AAGF,SAAO;GACN,QAAQ;IACP,IAAI,OAAO;IACX,SAAS,OAAO;IAChB;GACD;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,MAAM,KAAK;GACX,KAAK,KAAK;GACV;GACA;GACA;GACA;GACA"}