emdash 1.3.0 → 1.4.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 (970) hide show
  1. package/dist/{activation-Dim4YMM7.mjs → activation-CGlyigmg.mjs} +3 -3
  2. package/dist/{activation-Dim4YMM7.mjs.map → activation-CGlyigmg.mjs.map} +1 -1
  3. package/dist/{adapters-F_xorvWv.d.mts → adapters-D9a1PfqH.d.mts} +1 -1
  4. package/dist/{adapters-F_xorvWv.d.mts.map → adapters-D9a1PfqH.d.mts.map} +1 -1
  5. package/dist/{after-PcEvMY_6.mjs → after-32yNRvd2.mjs} +5 -2
  6. package/dist/{after-PcEvMY_6.mjs.map → after-32yNRvd2.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +4 -4
  8. package/dist/api/route-utils.mjs +50 -49
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +1 -1
  11. package/dist/api/schemas/index.mjs +7 -7
  12. package/dist/{api-D-7BNHoz.mjs → api--PYoyeTo.mjs} +121 -48
  13. package/dist/api--PYoyeTo.mjs.map +1 -0
  14. package/dist/api-tokens-DqSlkDVI.mjs +9 -0
  15. package/dist/api-tokens-DqSlkDVI.mjs.map +1 -0
  16. package/dist/{api-tokens-Bx38ZCQp.mjs → api-tokens-GNCsIegW.mjs} +3 -3
  17. package/dist/{api-tokens-Bx38ZCQp.mjs.map → api-tokens-GNCsIegW.mjs.map} +1 -1
  18. package/dist/{apply-T7ATgzCh.mjs → apply-DVnupNeS.mjs} +149 -91
  19. package/dist/apply-DVnupNeS.mjs.map +1 -0
  20. package/dist/{approvals-D-m6wvGl.mjs → approvals-DTtYSB27.mjs} +2 -2
  21. package/dist/{approvals-D-m6wvGl.mjs.map → approvals-DTtYSB27.mjs.map} +1 -1
  22. package/dist/{artifacts-htGyfCSt.mjs → artifacts-Dvdp2KK-.mjs} +29 -13
  23. package/dist/artifacts-Dvdp2KK-.mjs.map +1 -0
  24. package/dist/astro/image-endpoint.mjs +12 -2
  25. package/dist/astro/image-endpoint.mjs.map +1 -1
  26. package/dist/astro/index.d.mts +15 -14
  27. package/dist/astro/index.d.mts.map +1 -1
  28. package/dist/astro/index.mjs +59 -8
  29. package/dist/astro/index.mjs.map +1 -1
  30. package/dist/astro/middleware/auth.d.mts +13 -12
  31. package/dist/astro/middleware/auth.d.mts.map +1 -1
  32. package/dist/astro/middleware/auth.mjs +10 -8
  33. package/dist/astro/middleware/auth.mjs.map +1 -1
  34. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  35. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  36. package/dist/astro/middleware/redirect.mjs +129 -49
  37. package/dist/astro/middleware/redirect.mjs.map +1 -1
  38. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  39. package/dist/astro/middleware/request-context.mjs +18 -9
  40. package/dist/astro/middleware/request-context.mjs.map +1 -1
  41. package/dist/astro/middleware.d.mts +13 -12
  42. package/dist/astro/middleware.d.mts.map +1 -1
  43. package/dist/astro/middleware.mjs +111 -101
  44. package/dist/astro/middleware.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +11 -11
  46. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +11 -11
  47. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
  48. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  49. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  50. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +14 -14
  51. package/dist/astro/routes/api/admin/byline-fields/index.mjs +14 -14
  52. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +14 -14
  53. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +25 -25
  54. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +25 -25
  55. package/dist/astro/routes/api/admin/bylines/index.mjs +25 -25
  56. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +17 -17
  57. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
  58. package/dist/astro/routes/api/admin/comments/bulk.mjs +16 -16
  59. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
  60. package/dist/astro/routes/api/admin/comments/index.mjs +16 -16
  61. package/dist/astro/routes/api/admin/core-update.mjs +6 -6
  62. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
  63. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
  64. package/dist/astro/routes/api/admin/media-usage/activation.mjs +18 -18
  65. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +19 -19
  66. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +19 -19
  67. package/dist/astro/routes/api/admin/media-usage/progress.mjs +22 -21
  68. package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/media-usage/repair.mjs +26 -25
  70. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +19 -19
  72. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +19 -19
  73. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  74. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  75. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +7 -7
  76. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +7 -7
  77. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +66 -65
  78. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +5 -5
  80. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +66 -65
  81. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +66 -65
  83. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +73 -72
  85. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/index.mjs +66 -65
  87. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  89. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +66 -65
  90. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +73 -72
  92. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +66 -65
  94. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +66 -65
  96. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  97. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +74 -73
  98. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  99. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +4 -4
  100. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +68 -67
  101. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +4 -4
  103. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +67 -66
  104. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  105. package/dist/astro/routes/api/admin/plugins/updates.mjs +66 -65
  106. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  107. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +5 -5
  108. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +66 -65
  109. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  110. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  111. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +66 -65
  112. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  113. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +3 -3
  114. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +33 -32
  115. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs.map +1 -1
  116. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +33 -32
  117. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs.map +1 -1
  118. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +35 -34
  119. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs.map +1 -1
  120. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +35 -34
  121. package/dist/astro/routes/api/admin/transfer/capabilities.mjs.map +1 -1
  122. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +35 -34
  123. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs.map +1 -1
  124. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +36 -35
  125. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs.map +1 -1
  126. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +36 -35
  127. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs.map +1 -1
  128. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +35 -34
  129. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs.map +1 -1
  130. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +36 -35
  131. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs.map +1 -1
  132. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +37 -36
  133. package/dist/astro/routes/api/admin/transfer/exports/index.mjs.map +1 -1
  134. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +35 -34
  135. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs.map +1 -1
  136. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +35 -34
  137. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs.map +1 -1
  138. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +37 -36
  139. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs.map +1 -1
  140. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +35 -34
  141. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs.map +1 -1
  142. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +37 -36
  143. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs.map +1 -1
  144. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +35 -34
  145. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs.map +1 -1
  146. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +35 -34
  147. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs.map +1 -1
  148. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +37 -36
  149. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs.map +1 -1
  150. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +35 -34
  151. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs.map +1 -1
  152. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +35 -34
  153. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs.map +1 -1
  154. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +37 -36
  155. package/dist/astro/routes/api/admin/transfer/imports/index.mjs.map +1 -1
  156. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  157. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  158. package/dist/astro/routes/api/admin/users/_id_/index.mjs +12 -12
  159. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
  160. package/dist/astro/routes/api/admin/users/index.mjs +11 -11
  161. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  162. package/dist/astro/routes/api/auth/handover.mjs +5 -5
  163. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  164. package/dist/astro/routes/api/auth/invite/complete.mjs +15 -15
  165. package/dist/astro/routes/api/auth/invite/index.mjs +12 -12
  166. package/dist/astro/routes/api/auth/invite/register-options.mjs +13 -13
  167. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  168. package/dist/astro/routes/api/auth/magic-link/send.mjs +14 -14
  169. package/dist/astro/routes/api/auth/magic-link/verify.mjs +13 -13
  170. package/dist/astro/routes/api/auth/me.mjs +12 -12
  171. package/dist/astro/routes/api/auth/mode.mjs +3 -3
  172. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +8 -8
  173. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +1 -1
  174. package/dist/astro/routes/api/auth/passkey/_id_.mjs +11 -11
  175. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  176. package/dist/astro/routes/api/auth/passkey/options.mjs +15 -15
  177. package/dist/astro/routes/api/auth/passkey/register/options.mjs +13 -13
  178. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +13 -13
  179. package/dist/astro/routes/api/auth/passkey/verify.mjs +15 -15
  180. package/dist/astro/routes/api/auth/signup/complete.mjs +15 -15
  181. package/dist/astro/routes/api/auth/signup/request.mjs +13 -13
  182. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  183. package/dist/astro/routes/api/calendar.mjs +12 -12
  184. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  185. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +17 -17
  186. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  187. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +15 -15
  188. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  189. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +15 -15
  190. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  191. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +9 -9
  192. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +29 -28
  193. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
  194. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +15 -15
  195. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +34 -33
  196. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  197. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +34 -33
  198. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  199. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  200. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  201. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +15 -15
  202. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
  203. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +35 -27
  204. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  205. package/dist/astro/routes/api/content/_collection_/_id_/translations.d.mts.map +1 -1
  206. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +8 -4
  207. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs.map +1 -1
  208. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +15 -15
  209. package/dist/astro/routes/api/content/_collection_/_id_.mjs +15 -15
  210. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  211. package/dist/astro/routes/api/content/_collection_/index.mjs +12 -12
  212. package/dist/astro/routes/api/content/_collection_/trash.mjs +12 -12
  213. package/dist/astro/routes/api/dashboard.mjs +22 -16
  214. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  215. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  216. package/dist/astro/routes/api/dev/scheduled-tasks.mjs +97 -95
  217. package/dist/astro/routes/api/dev/scheduled-tasks.mjs.map +1 -1
  218. package/dist/astro/routes/api/health.mjs +4 -4
  219. package/dist/astro/routes/api/import/probe.d.mts +4 -3
  220. package/dist/astro/routes/api/import/probe.d.mts.map +1 -1
  221. package/dist/astro/routes/api/import/probe.mjs +27 -25
  222. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  223. package/dist/astro/routes/api/import/wordpress/analyze.d.mts +4 -3
  224. package/dist/astro/routes/api/import/wordpress/analyze.d.mts.map +1 -1
  225. package/dist/astro/routes/api/import/wordpress/analyze.mjs +7 -29
  226. package/dist/astro/routes/api/import/wordpress/analyze.mjs.map +1 -1
  227. package/dist/astro/routes/api/import/wordpress/execute.d.mts +14 -13
  228. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  229. package/dist/astro/routes/api/import/wordpress/execute.mjs +29 -29
  230. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  231. package/dist/astro/routes/api/import/wordpress/media.d.mts +13 -12
  232. package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
  233. package/dist/astro/routes/api/import/wordpress/media.mjs +14 -14
  234. package/dist/astro/routes/api/import/wordpress/prepare.mjs +19 -19
  235. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  236. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +14 -13
  237. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
  238. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +25 -24
  239. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  240. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  241. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +27 -25
  242. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  243. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +14 -13
  244. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
  245. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +39 -38
  246. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  247. package/dist/astro/routes/api/manifest.mjs +4 -4
  248. package/dist/astro/routes/api/mcp.mjs +99 -83
  249. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  250. package/dist/astro/routes/api/media/_id_/confirm.mjs +16 -16
  251. package/dist/astro/routes/api/media/_id_/replace.mjs +12 -12
  252. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  253. package/dist/astro/routes/api/media/_id_/usage.mjs +28 -27
  254. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  255. package/dist/astro/routes/api/media/_id_.mjs +26 -25
  256. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  257. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +5 -5
  258. package/dist/astro/routes/api/media/file/_...key_.d.mts.map +1 -1
  259. package/dist/astro/routes/api/media/file/_...key_.mjs +62 -8
  260. package/dist/astro/routes/api/media/file/_...key_.mjs.map +1 -1
  261. package/dist/astro/routes/api/media/folders/_id_.mjs +13 -13
  262. package/dist/astro/routes/api/media/folders/index.mjs +13 -13
  263. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  264. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  265. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  266. package/dist/astro/routes/api/media/upload-url.mjs +15 -15
  267. package/dist/astro/routes/api/media.mjs +30 -29
  268. package/dist/astro/routes/api/media.mjs.map +1 -1
  269. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -15
  270. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  271. package/dist/astro/routes/api/menus/_name_/items.mjs +17 -15
  272. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  273. package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -15
  274. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  275. package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -15
  276. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  277. package/dist/astro/routes/api/menus/_name_.mjs +17 -15
  278. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  279. package/dist/astro/routes/api/menus/index.mjs +17 -15
  280. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  281. package/dist/astro/routes/api/oauth/authorize.mjs +2 -2
  282. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  283. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  284. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  285. package/dist/astro/routes/api/oauth/register.mjs +5 -5
  286. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  287. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  288. package/dist/astro/routes/api/oauth/token.d.mts.map +1 -1
  289. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  290. package/dist/astro/routes/api/oauth/token.mjs.map +1 -1
  291. package/dist/astro/routes/api/openapi.json.mjs +12 -12
  292. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +9 -9
  293. package/dist/astro/routes/api/redirects/404s/index.mjs +20 -19
  294. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  295. package/dist/astro/routes/api/redirects/404s/summary.mjs +20 -19
  296. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  297. package/dist/astro/routes/api/redirects/_id_.mjs +21 -20
  298. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  299. package/dist/astro/routes/api/redirects/index.mjs +21 -20
  300. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  301. package/dist/astro/routes/api/relations/_id_/index.mjs +34 -33
  302. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  303. package/dist/astro/routes/api/relations/index.mjs +34 -33
  304. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  305. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  306. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +15 -15
  307. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +66 -65
  308. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  309. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +66 -65
  310. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  311. package/dist/astro/routes/api/schema/block-types/index.mjs +66 -65
  312. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  313. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +66 -65
  314. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  315. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +66 -65
  316. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  317. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +66 -65
  318. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  319. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +66 -65
  320. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  321. package/dist/astro/routes/api/schema/collections/index.mjs +66 -65
  322. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  323. package/dist/astro/routes/api/schema/collections/reorder.mjs +66 -65
  324. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  325. package/dist/astro/routes/api/schema/index.mjs +17 -16
  326. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  327. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +66 -65
  328. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  329. package/dist/astro/routes/api/schema/orphans/index.mjs +66 -65
  330. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  331. package/dist/astro/routes/api/search/enable.mjs +20 -18
  332. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  333. package/dist/astro/routes/api/search/index.mjs +19 -17
  334. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  335. package/dist/astro/routes/api/search/rebuild.mjs +20 -18
  336. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  337. package/dist/astro/routes/api/search/stats.mjs +13 -11
  338. package/dist/astro/routes/api/search/stats.mjs.map +1 -1
  339. package/dist/astro/routes/api/search/suggest.mjs +19 -17
  340. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  341. package/dist/astro/routes/api/sections/_slug_.mjs +19 -17
  342. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  343. package/dist/astro/routes/api/sections/index.mjs +19 -17
  344. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  345. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  346. package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
  347. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  348. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  349. package/dist/astro/routes/api/settings/domain-notify.mjs +7 -7
  350. package/dist/astro/routes/api/settings/domain.mjs +19 -17
  351. package/dist/astro/routes/api/settings/domain.mjs.map +1 -1
  352. package/dist/astro/routes/api/settings/email.mjs +5 -5
  353. package/dist/astro/routes/api/settings.mjs +25 -23
  354. package/dist/astro/routes/api/settings.mjs.map +1 -1
  355. package/dist/astro/routes/api/setup/admin-verify.mjs +18 -18
  356. package/dist/astro/routes/api/setup/admin.mjs +14 -14
  357. package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -44
  358. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  359. package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
  360. package/dist/astro/routes/api/setup/index.mjs +48 -47
  361. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  362. package/dist/astro/routes/api/setup/status.mjs +4 -4
  363. package/dist/astro/routes/api/site/domain-proof.mjs +17 -15
  364. package/dist/astro/routes/api/site/domain-proof.mjs.map +1 -1
  365. package/dist/astro/routes/api/snapshot.mjs +9 -9
  366. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +25 -24
  367. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  368. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +25 -24
  369. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  370. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +25 -24
  371. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  372. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +25 -24
  373. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  374. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +25 -24
  375. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
  376. package/dist/astro/routes/api/taxonomies/_name_.mjs +25 -24
  377. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
  378. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +35 -34
  379. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
  380. package/dist/astro/routes/api/taxonomies/index.mjs +25 -24
  381. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  382. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  383. package/dist/astro/routes/api/typegen.mjs +5 -5
  384. package/dist/astro/routes/api/visual-editing/action-token.mjs +5 -5
  385. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +17 -17
  386. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +3 -3
  387. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +1 -1
  388. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +1 -1
  389. package/dist/astro/routes/api/widget-areas/_name_/reorder.d.mts.map +1 -1
  390. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +24 -13
  391. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  392. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts.map +1 -1
  393. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +22 -17
  394. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  395. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +21 -17
  396. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  397. package/dist/astro/routes/api/widget-areas/_name_.mjs +14 -10
  398. package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
  399. package/dist/astro/routes/api/widget-areas/index.mjs +21 -17
  400. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  401. package/dist/astro/routes/api/widget-components.mjs +3 -3
  402. package/dist/astro/routes/robots.txt.mjs +16 -14
  403. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  404. package/dist/astro/routes/sitemap-_collection_.xml.mjs +18 -16
  405. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  406. package/dist/astro/routes/sitemap.xml.mjs +16 -14
  407. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  408. package/dist/astro/types.d.mts +22 -20
  409. package/dist/astro/types.d.mts.map +1 -1
  410. package/dist/{audit-_gieLVGU.mjs → audit-B8XE-0UV.mjs} +2 -2
  411. package/dist/{audit-_gieLVGU.mjs.map → audit-B8XE-0UV.mjs.map} +1 -1
  412. package/dist/auth/providers/github.d.mts +1 -1
  413. package/dist/auth/providers/google.d.mts +1 -1
  414. package/dist/auth/providers/microsoft.d.mts +1 -1
  415. package/dist/{authorize-DPFBGbE6.mjs → authorize-NJgp8kLI.mjs} +2 -2
  416. package/dist/{authorize-DPFBGbE6.mjs.map → authorize-NJgp8kLI.mjs.map} +1 -1
  417. package/dist/{backup-3FgVxiDJ.mjs → backup-8rPSJ28a.mjs} +4 -4
  418. package/dist/{backup-3FgVxiDJ.mjs.map → backup-8rPSJ28a.mjs.map} +1 -1
  419. package/dist/{block-types-CYcG56JB.mjs → block-types-BbOrfnWs.mjs} +5 -5
  420. package/dist/{block-types-CYcG56JB.mjs.map → block-types-BbOrfnWs.mjs.map} +1 -1
  421. package/dist/{block-values-gCX4HBSl.mjs → block-values-Dg0-8PPS.mjs} +4 -4
  422. package/dist/{block-values-gCX4HBSl.mjs.map → block-values-Dg0-8PPS.mjs.map} +1 -1
  423. package/dist/{byline-BR1qhyiw.mjs → byline-DHJS-GGb.mjs} +123 -38
  424. package/dist/byline-DHJS-GGb.mjs.map +1 -0
  425. package/dist/{byline-fields-BLXZnX7N.mjs → byline-fields-CiR8FvvF.mjs} +3 -3
  426. package/dist/{byline-fields-BLXZnX7N.mjs.map → byline-fields-CiR8FvvF.mjs.map} +1 -1
  427. package/dist/{byline-fields-4ClDC88c.mjs → byline-fields-D6KYsEa7.mjs} +2 -2
  428. package/dist/{byline-fields-4ClDC88c.mjs.map → byline-fields-D6KYsEa7.mjs.map} +1 -1
  429. package/dist/{byline-registry-dvt4N3xV.mjs → byline-registry-BhzpO41z.mjs} +3 -3
  430. package/dist/{byline-registry-dvt4N3xV.mjs.map → byline-registry-BhzpO41z.mjs.map} +1 -1
  431. package/dist/{bylines-CVOvRUL7.mjs → bylines-Bsg5cH4S.mjs} +7 -7
  432. package/dist/bylines-Bsg5cH4S.mjs.map +1 -0
  433. package/dist/{bylines-DxOs9B7z.mjs → bylines-f_ZEc6Sn.mjs} +8 -8
  434. package/dist/{bylines-DxOs9B7z.mjs.map → bylines-f_ZEc6Sn.mjs.map} +1 -1
  435. package/dist/{cache-CEU9wo_h.mjs → cache-5DHbpEWu.mjs} +4 -4
  436. package/dist/{cache-CEU9wo_h.mjs.map → cache-5DHbpEWu.mjs.map} +1 -1
  437. package/dist/{capture-triggers-CT6dK9zd.mjs → capture-triggers-BezAvWcB.mjs} +2 -2
  438. package/dist/{capture-triggers-CT6dK9zd.mjs.map → capture-triggers-BezAvWcB.mjs.map} +1 -1
  439. package/dist/{challenge-store-C17BYx2-.mjs → challenge-store-B1C0V4b3.mjs} +1 -1
  440. package/dist/{challenge-store-C17BYx2-.mjs.map → challenge-store-B1C0V4b3.mjs.map} +1 -1
  441. package/dist/{chunks-xC4UD5-S.mjs → chunks-DiW8VMwz.mjs} +2 -2
  442. package/dist/{chunks-xC4UD5-S.mjs.map → chunks-DiW8VMwz.mjs.map} +1 -1
  443. package/dist/cli/index.mjs +53 -52
  444. package/dist/cli/index.mjs.map +1 -1
  445. package/dist/client/cf-access.d.mts +1 -1
  446. package/dist/client/index.d.mts +61 -61
  447. package/dist/client/index.d.mts.map +1 -1
  448. package/dist/client/index.mjs +3 -2
  449. package/dist/client/index.mjs.map +1 -1
  450. package/dist/{collection-slugs-cache-e09QeJQt.mjs → collection-slugs-cache-DIrLjqH-.mjs} +20 -14
  451. package/dist/collection-slugs-cache-DIrLjqH-.mjs.map +1 -0
  452. package/dist/{comment-UvIWDKcW.mjs → comment-DB74Zpa4.mjs} +18 -8
  453. package/dist/comment-DB74Zpa4.mjs.map +1 -0
  454. package/dist/{comment-reaction-dGp6_FRo.mjs → comment-reaction-BScxIWUn.mjs} +2 -2
  455. package/dist/{comment-reaction-dGp6_FRo.mjs.map → comment-reaction-BScxIWUn.mjs.map} +1 -1
  456. package/dist/{comments-pej-_BUO.mjs → comments-Cor_zKml.mjs} +3 -3
  457. package/dist/{comments-pej-_BUO.mjs.map → comments-Cor_zKml.mjs.map} +1 -1
  458. package/dist/config-Cs_AwWXI.mjs +106 -0
  459. package/dist/config-Cs_AwWXI.mjs.map +1 -0
  460. package/dist/{config-CFMojMFK.d.mts → config-D44_8G9J.d.mts} +3 -1
  461. package/dist/config-D44_8G9J.d.mts.map +1 -0
  462. package/dist/{config-Bsm_u_oE.d.mts → config-sDhZvkLR.d.mts} +56 -20
  463. package/dist/config-sDhZvkLR.d.mts.map +1 -0
  464. package/dist/{content-DQSRZTVw.mjs → content-BKHUVsE5.mjs} +67 -30
  465. package/dist/content-BKHUVsE5.mjs.map +1 -0
  466. package/dist/{content-list-query-CYKcY6Vi.d.mts → content-list-query-ByP4jRpZ.d.mts} +1 -1
  467. package/dist/{content-list-query-CYKcY6Vi.d.mts.map → content-list-query-ByP4jRpZ.d.mts.map} +1 -1
  468. package/dist/{content-policy-Dm32n9C6.mjs → content-policy-BmE0MPZY.mjs} +1 -1
  469. package/dist/{content-policy-Dm32n9C6.mjs.map → content-policy-BmE0MPZY.mjs.map} +1 -1
  470. package/dist/{content-repair-DNh5--x5.mjs → content-repair-Ukdxoq-R.mjs} +4 -4
  471. package/dist/{content-repair-DNh5--x5.mjs.map → content-repair-Ukdxoq-R.mjs.map} +1 -1
  472. package/dist/{context-BYptmCN0.mjs → context-CzjejcsE.mjs} +32 -33
  473. package/dist/context-CzjejcsE.mjs.map +1 -0
  474. package/dist/{credits-B9iORdWB.mjs → credits-BKREepht.mjs} +3 -3
  475. package/dist/{credits-B9iORdWB.mjs.map → credits-BKREepht.mjs.map} +1 -1
  476. package/dist/{dashboard-D0jcgBD7.mjs → dashboard-ynr1qJWM.mjs} +10 -9
  477. package/dist/dashboard-ynr1qJWM.mjs.map +1 -0
  478. package/dist/database/migration-lock.mjs +1 -1
  479. package/dist/db/index.d.mts +3 -3
  480. package/dist/db/index.mjs +3 -3
  481. package/dist/db/libsql-migrations.d.mts +1 -1
  482. package/dist/db/libsql-migrations.mjs +5 -5
  483. package/dist/db/libsql.d.mts +1 -1
  484. package/dist/db/postgres-migrations.d.mts +1 -1
  485. package/dist/db/postgres-migrations.mjs +5 -5
  486. package/dist/db/postgres.d.mts +1 -1
  487. package/dist/db/sqlite-migrations.d.mts +1 -1
  488. package/dist/db/sqlite-migrations.mjs +5 -5
  489. package/dist/db/sqlite.d.mts +1 -1
  490. package/dist/{db-errors-CBD5yMro.mjs → db-errors-unnO6yiZ.mjs} +12 -2
  491. package/dist/db-errors-unnO6yiZ.mjs.map +1 -0
  492. package/dist/deferred-tasks-wlMFJL95.d.mts +10 -0
  493. package/dist/deferred-tasks-wlMFJL95.d.mts.map +1 -0
  494. package/dist/{destination-r2zIAZ2S.mjs → destination-DR3IHjmy.mjs} +1 -1
  495. package/dist/{destination-r2zIAZ2S.mjs.map → destination-DR3IHjmy.mjs.map} +1 -1
  496. package/dist/{device-flow-BkFKBoAn.mjs → device-flow-D1U392GC.mjs} +3 -5
  497. package/dist/device-flow-D1U392GC.mjs.map +1 -0
  498. package/dist/{dialect-helpers-7_IqPdh9.mjs → dialect-helpers-B1XN2HGB.mjs} +10 -3
  499. package/dist/dialect-helpers-B1XN2HGB.mjs.map +1 -0
  500. package/dist/{direct-executor-Cbxzg4qe.mjs → direct-executor-Bs2g0ake.mjs} +4 -4
  501. package/dist/{direct-executor-Cbxzg4qe.mjs.map → direct-executor-Bs2g0ake.mjs.map} +1 -1
  502. package/dist/{dist-Cfu8mMBs.mjs → dist-BUmWMTbN.mjs} +1 -1
  503. package/dist/{dist-Cfu8mMBs.mjs.map → dist-BUmWMTbN.mjs.map} +1 -1
  504. package/dist/{email-locale-BJ8DjTzZ.mjs → email-locale-Bs3HFdnq.mjs} +1 -1
  505. package/dist/{email-locale-BJ8DjTzZ.mjs.map → email-locale-Bs3HFdnq.mjs.map} +1 -1
  506. package/dist/{emdash-runtime-DVi7vtXC.mjs → emdash-runtime-C8T-pZpS.mjs} +108 -62
  507. package/dist/emdash-runtime-C8T-pZpS.mjs.map +1 -0
  508. package/dist/{enrich-Duu4sV3a.mjs → enrich-DFlfnd3u.mjs} +3 -3
  509. package/dist/{enrich-Duu4sV3a.mjs.map → enrich-DFlfnd3u.mjs.map} +1 -1
  510. package/dist/{entry-lock-C7VX0NGK.d.mts → entry-lock-BulbgPBX.d.mts} +23 -23
  511. package/dist/{entry-lock-C7VX0NGK.d.mts.map → entry-lock-BulbgPBX.d.mts.map} +1 -1
  512. package/dist/{entry-lock-Df6-XhIu.mjs → entry-lock-CRVmruM0.mjs} +4 -4
  513. package/dist/{entry-lock-Df6-XhIu.mjs.map → entry-lock-CRVmruM0.mjs.map} +1 -1
  514. package/dist/{entry-lock-DLxCffFW.mjs → entry-lock-D-zJQ4q6.mjs} +3 -3
  515. package/dist/{entry-lock-DLxCffFW.mjs.map → entry-lock-D-zJQ4q6.mjs.map} +1 -1
  516. package/dist/{entry-locks-DJAqVweV.mjs → entry-locks-CJ9uhqg1.mjs} +2 -2
  517. package/dist/{entry-locks-DJAqVweV.mjs.map → entry-locks-CJ9uhqg1.mjs.map} +1 -1
  518. package/dist/{env-types-C3FCVBWe.mjs → env-types-BE3bCvfP.mjs} +5 -5
  519. package/dist/{env-types-C3FCVBWe.mjs.map → env-types-BE3bCvfP.mjs.map} +1 -1
  520. package/dist/{error-CVWeIOku.mjs → error-BCMgPxdn.mjs} +3 -3
  521. package/dist/{error-CVWeIOku.mjs.map → error-BCMgPxdn.mjs.map} +1 -1
  522. package/dist/{errors-BOYNdIo3.mjs → errors-8gJqv-XV.mjs} +15 -2
  523. package/dist/{errors-BOYNdIo3.mjs.map → errors-8gJqv-XV.mjs.map} +1 -1
  524. package/dist/{fence-C3MUitUN.mjs → fence-Dagicj14.mjs} +4 -4
  525. package/dist/{fence-C3MUitUN.mjs.map → fence-Dagicj14.mjs.map} +1 -1
  526. package/dist/{field-map-Bft9LKak.mjs → field-map-BSXdNGt5.mjs} +11 -10
  527. package/dist/field-map-BSXdNGt5.mjs.map +1 -0
  528. package/dist/{focal-point-JX8kcOTQ.mjs → focal-point-CgCcr1Ca.mjs} +1 -1
  529. package/dist/{focal-point-JX8kcOTQ.mjs.map → focal-point-CgCcr1Ca.mjs.map} +1 -1
  530. package/dist/{fts-manager-Beg3e4bI.mjs → fts-manager-6861qcwk.mjs} +68 -22
  531. package/dist/fts-manager-6861qcwk.mjs.map +1 -0
  532. package/dist/{gc-ByyAYiYE.mjs → gc-CNkXB3mE.mjs} +8 -8
  533. package/dist/{gc-ByyAYiYE.mjs.map → gc-CNkXB3mE.mjs.map} +1 -1
  534. package/dist/{hook-result-BrdLyOdI.d.mts → hook-result-f8t7hIuu.d.mts} +1 -1
  535. package/dist/{hook-result-BrdLyOdI.d.mts.map → hook-result-f8t7hIuu.d.mts.map} +1 -1
  536. package/dist/{hreflang-CY_F5OjF.d.mts → hreflang-8dUOJAPJ.d.mts} +2 -2
  537. package/dist/{hreflang-CY_F5OjF.d.mts.map → hreflang-8dUOJAPJ.d.mts.map} +1 -1
  538. package/dist/{hreflang-C8Jb-hrf.mjs → hreflang-BW5A4FLK.mjs} +8 -8
  539. package/dist/{hreflang-C8Jb-hrf.mjs.map → hreflang-BW5A4FLK.mjs.map} +1 -1
  540. package/dist/{http-route-dispatch-CyeW6iPv.mjs → http-route-dispatch-rXKvTNm9.mjs} +5 -5
  541. package/dist/{http-route-dispatch-CyeW6iPv.mjs.map → http-route-dispatch-rXKvTNm9.mjs.map} +1 -1
  542. package/dist/{identity-Cael5uTT.mjs → identity-CPRRSovU.mjs} +3 -3
  543. package/dist/{identity-Cael5uTT.mjs.map → identity-CPRRSovU.mjs.map} +1 -1
  544. package/dist/{import-BUXjdZUn.mjs → import-yVbfPyfd.mjs} +5 -5
  545. package/dist/{import-BUXjdZUn.mjs.map → import-yVbfPyfd.mjs.map} +1 -1
  546. package/dist/index-VM7Fzxwe.d.mts +260 -0
  547. package/dist/index-VM7Fzxwe.d.mts.map +1 -0
  548. package/dist/index.d.mts +25 -24
  549. package/dist/index.mjs +89 -88
  550. package/dist/{install-finalization-3JX5qQEA.mjs → install-finalization-RU6VrHOX.mjs} +1 -1
  551. package/dist/{install-finalization-3JX5qQEA.mjs.map → install-finalization-RU6VrHOX.mjs.map} +1 -1
  552. package/dist/{json-recordset-BUjxhr77.mjs → json-recordset-D0WhN2UA.mjs} +2 -2
  553. package/dist/{json-recordset-BUjxhr77.mjs.map → json-recordset-D0WhN2UA.mjs.map} +1 -1
  554. package/dist/{lifecycle-7vUJeFRe.mjs → lifecycle-B8d7Rdqx.mjs} +1 -1
  555. package/dist/{lifecycle-7vUJeFRe.mjs.map → lifecycle-B8d7Rdqx.mjs.map} +1 -1
  556. package/dist/{load-CdAG9wz-.mjs → load-D4xtzm6h.mjs} +2 -2
  557. package/dist/{load-CdAG9wz-.mjs.map → load-D4xtzm6h.mjs.map} +1 -1
  558. package/dist/{loader-CswroUbe.mjs → loader-DhnedqY4.mjs} +199 -101
  559. package/dist/loader-DhnedqY4.mjs.map +1 -0
  560. package/dist/{loops-uA4iTOzd.mjs → loops-B2YS-Zzr.mjs} +2 -2
  561. package/dist/{loops-uA4iTOzd.mjs.map → loops-B2YS-Zzr.mjs.map} +1 -1
  562. package/dist/{manifest-builder-B8zjuH3f.mjs → manifest-builder-g1FLviel.mjs} +10 -3
  563. package/dist/manifest-builder-g1FLviel.mjs.map +1 -0
  564. package/dist/media/image-endpoint.d.mts +3 -2
  565. package/dist/media/image-endpoint.d.mts.map +1 -1
  566. package/dist/media/image-endpoint.mjs +17 -8
  567. package/dist/media/image-endpoint.mjs.map +1 -1
  568. package/dist/media/index.d.mts +1 -1
  569. package/dist/media/index.mjs +7 -6
  570. package/dist/media/index.mjs.map +1 -1
  571. package/dist/media/local-runtime.d.mts +15 -14
  572. package/dist/media/local-runtime.d.mts.map +1 -1
  573. package/dist/media/local-runtime.mjs +20 -15
  574. package/dist/media/local-runtime.mjs.map +1 -1
  575. package/dist/{media-1WC65OCB.mjs → media-BR4_t-Wd.mjs} +3 -3
  576. package/dist/{media-1WC65OCB.mjs.map → media-BR4_t-Wd.mjs.map} +1 -1
  577. package/dist/{media--dJRU6i2.mjs → media-CikS-q6E.mjs} +4 -4
  578. package/dist/{media--dJRU6i2.mjs.map → media-CikS-q6E.mjs.map} +1 -1
  579. package/dist/{media-Bws9f18T.mjs → media-DepNLhPq.mjs} +14 -4
  580. package/dist/media-DepNLhPq.mjs.map +1 -0
  581. package/dist/{media-allowlist-BJB7MFx6.mjs → media-allowlist-BMBLqyWh.mjs} +2 -2
  582. package/dist/{media-allowlist-BJB7MFx6.mjs.map → media-allowlist-BMBLqyWh.mjs.map} +1 -1
  583. package/dist/{media-folders-Dn3C16B8.mjs → media-folders-CI0Wydfo.mjs} +2 -2
  584. package/dist/{media-folders-Dn3C16B8.mjs.map → media-folders-CI0Wydfo.mjs.map} +1 -1
  585. package/dist/{media-usage-CF0WVcLO.mjs → media-usage-X1_20MY-.mjs} +8 -8
  586. package/dist/{media-usage-CF0WVcLO.mjs.map → media-usage-X1_20MY-.mjs.map} +1 -1
  587. package/dist/{media-usage-activation-C9HwVw5w.mjs → media-usage-activation-bWusy3M2.mjs} +3 -3
  588. package/dist/{media-usage-activation-C9HwVw5w.mjs.map → media-usage-activation-bWusy3M2.mjs.map} +1 -1
  589. package/dist/{media-usage-work-m3AWTmmC.mjs → media-usage-work-B2RaoJIa.mjs} +4 -4
  590. package/dist/{media-usage-work-m3AWTmmC.mjs.map → media-usage-work-B2RaoJIa.mjs.map} +1 -1
  591. package/dist/{media-usage-work-CkLa5-nc.mjs → media-usage-work-BCK2J-v_.mjs} +7 -7
  592. package/dist/{media-usage-work-CkLa5-nc.mjs.map → media-usage-work-BCK2J-v_.mjs.map} +1 -1
  593. package/dist/{menus-BCVSSp1z.mjs → menus-B0Qqv_cS.mjs} +176 -92
  594. package/dist/menus-B0Qqv_cS.mjs.map +1 -0
  595. package/dist/{menus-Cl4kwdt7.mjs → menus-oypxT1pI.mjs} +134 -53
  596. package/dist/menus-oypxT1pI.mjs.map +1 -0
  597. package/dist/{menus-BSzwObhV.mjs → menus-uEAxWAm1.mjs} +3 -3
  598. package/dist/{menus-BSzwObhV.mjs.map → menus-uEAxWAm1.mjs.map} +1 -1
  599. package/dist/migrations/index.d.mts +1 -1
  600. package/dist/migrations/index.mjs +5 -5
  601. package/dist/{mime-B5M9R53H.mjs → mime-D1We9jUx.mjs} +1 -1
  602. package/dist/{mime-B5M9R53H.mjs.map → mime-D1We9jUx.mjs.map} +1 -1
  603. package/dist/{normalize-BuWa0lvd.mjs → normalize-Cx-bNwhP.mjs} +41 -12
  604. package/dist/normalize-Cx-bNwhP.mjs.map +1 -0
  605. package/dist/{oauth-authorization-TpEJrYB7.mjs → oauth-authorization-CPLgBrdo.mjs} +19 -6
  606. package/dist/oauth-authorization-CPLgBrdo.mjs.map +1 -0
  607. package/dist/{oauth-state-store-CHMn_mwc.mjs → oauth-state-store-BndCfRum.mjs} +1 -1
  608. package/dist/{oauth-state-store-CHMn_mwc.mjs.map → oauth-state-store-BndCfRum.mjs.map} +1 -1
  609. package/dist/object-cache/memory.d.mts +1 -1
  610. package/dist/{object-cache-Bo6DGaC9.mjs → object-cache-DmKr09La.mjs} +21 -4
  611. package/dist/{object-cache-Bo6DGaC9.mjs.map → object-cache-DmKr09La.mjs.map} +1 -1
  612. package/dist/{options-DJWaq3Ie.d.mts → options-BUUgroHg.d.mts} +3 -3
  613. package/dist/{options-DJWaq3Ie.d.mts.map → options-BUUgroHg.d.mts.map} +1 -1
  614. package/dist/page/index.d.mts +2 -2
  615. package/dist/page/index.mjs +16 -14
  616. package/dist/page/index.mjs.map +1 -1
  617. package/dist/{parse-DgQ2NABT.mjs → parse-B_b6gZxG.mjs} +2 -2
  618. package/dist/{parse-DgQ2NABT.mjs.map → parse-B_b6gZxG.mjs.map} +1 -1
  619. package/dist/{parse-CWHOFc6z.d.mts → parse-Dndx1QmN.d.mts} +3 -3
  620. package/dist/{parse-CWHOFc6z.d.mts.map → parse-Dndx1QmN.d.mts.map} +1 -1
  621. package/dist/{passkey-config-D0kdzEao.mjs → passkey-config-D2Lua5__.mjs} +1 -1
  622. package/dist/{passkey-config-D0kdzEao.mjs.map → passkey-config-D2Lua5__.mjs.map} +1 -1
  623. package/dist/{patterns-CMNnYCgf.mjs → patterns-CryGz_EV.mjs} +1 -1
  624. package/dist/{patterns-CMNnYCgf.mjs.map → patterns-CryGz_EV.mjs.map} +1 -1
  625. package/dist/{placeholder-D41vk11_.d.mts → placeholder-CSKu5OkD.d.mts} +9 -1
  626. package/dist/placeholder-CSKu5OkD.d.mts.map +1 -0
  627. package/dist/plugin-test-runtime.d.mts +17 -15
  628. package/dist/plugin-test-runtime.d.mts.map +1 -1
  629. package/dist/plugin-test-runtime.mjs +99 -98
  630. package/dist/plugin-types.d.mts +2 -2
  631. package/dist/plugin-utils.d.mts +13 -12
  632. package/dist/plugin-utils.d.mts.map +1 -1
  633. package/dist/plugins/adapt-sandbox-entry.d.mts +13 -12
  634. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  635. package/dist/plugins/host.d.mts +5 -5
  636. package/dist/plugins/host.mjs +48 -47
  637. package/dist/{policy-DLQ--Hnm.mjs → policy-BPugqmeV.mjs} +13 -5
  638. package/dist/policy-BPugqmeV.mjs.map +1 -0
  639. package/dist/{protocol-79kUO7jP.d.mts → protocol-PoAfD_9W.d.mts} +2 -2
  640. package/dist/{protocol-79kUO7jP.d.mts.map → protocol-PoAfD_9W.d.mts.map} +1 -1
  641. package/dist/{public-plugin-api-routes-BuAMJ8nN.mjs → public-plugin-api-routes-CMljrTby.mjs} +9 -9
  642. package/dist/{public-plugin-api-routes-BuAMJ8nN.mjs.map → public-plugin-api-routes-CMljrTby.mjs.map} +1 -1
  643. package/dist/{public-submission-Di3TsgzX.mjs → public-submission-ayqoyee4.mjs} +10 -10
  644. package/dist/{public-submission-Di3TsgzX.mjs.map → public-submission-ayqoyee4.mjs.map} +1 -1
  645. package/dist/query-BFHjCzSh.mjs +37 -0
  646. package/dist/query-BFHjCzSh.mjs.map +1 -0
  647. package/dist/{query-CpnRlBh8.mjs → query-D62NntCZ.mjs} +55 -65
  648. package/dist/query-D62NntCZ.mjs.map +1 -0
  649. package/dist/{query-haKvLAWl.mjs → query-LmPY2y0C.mjs} +5 -5
  650. package/dist/{query-haKvLAWl.mjs.map → query-LmPY2y0C.mjs.map} +1 -1
  651. package/dist/{rate-limit-Xp4d0NBY.mjs → rate-limit-C04Llsoc.mjs} +3 -3
  652. package/dist/{rate-limit-Xp4d0NBY.mjs.map → rate-limit-C04Llsoc.mjs.map} +1 -1
  653. package/dist/{redirect-DiS_3mA4.mjs → redirect-DjLdw427.mjs} +6 -6
  654. package/dist/{redirect-DiS_3mA4.mjs.map → redirect-DjLdw427.mjs.map} +1 -1
  655. package/dist/{redirect-paths-CNYq7w80.mjs → redirect-paths-DOaVBp6E.mjs} +1 -1
  656. package/dist/{redirect-paths-CNYq7w80.mjs.map → redirect-paths-DOaVBp6E.mjs.map} +1 -1
  657. package/dist/{redirects-BHpy-VsZ.mjs → redirects-Cpq1catN.mjs} +6 -6
  658. package/dist/{redirects-BHpy-VsZ.mjs.map → redirects-Cpq1catN.mjs.map} +1 -1
  659. package/dist/{redirects-BEVSRMa2.mjs → redirects-CyvvZrCJ.mjs} +2 -2
  660. package/dist/{redirects-BEVSRMa2.mjs.map → redirects-CyvvZrCJ.mjs.map} +1 -1
  661. package/dist/{registry-TUVaid9Z.mjs → registry-B0-O575m.mjs} +25 -20
  662. package/dist/registry-B0-O575m.mjs.map +1 -0
  663. package/dist/{relations-CA_QuMTU.mjs → relations-WIOojTL4.mjs} +24 -11
  664. package/dist/relations-WIOojTL4.mjs.map +1 -0
  665. package/dist/{request-cache-C4CIo5ad.mjs → request-cache-5z2WzWmh.mjs} +1 -1
  666. package/dist/{request-cache-C4CIo5ad.mjs.map → request-cache-5z2WzWmh.mjs.map} +1 -1
  667. package/dist/request-context.d.mts +12 -1
  668. package/dist/request-context.d.mts.map +1 -1
  669. package/dist/request-context.mjs.map +1 -1
  670. package/dist/{resolve-DwNM-CXl.mjs → resolve-BNnm8EkB.mjs} +14 -13
  671. package/dist/{resolve-DwNM-CXl.mjs.map → resolve-BNnm8EkB.mjs.map} +1 -1
  672. package/dist/{resolve-D-kqyKns.mjs → resolve-DdNXBJSr.mjs} +4 -4
  673. package/dist/resolve-DdNXBJSr.mjs.map +1 -0
  674. package/dist/{revision-BVp8S0e_.mjs → revision-Dx7Uth1X.mjs} +5 -5
  675. package/dist/{revision-BVp8S0e_.mjs.map → revision-Dx7Uth1X.mjs.map} +1 -1
  676. package/dist/{routes-BerZFrvV.mjs → routes-avqgc-8r.mjs} +3 -3
  677. package/dist/{routes-BerZFrvV.mjs.map → routes-avqgc-8r.mjs.map} +1 -1
  678. package/dist/{runner-C5NeAkBQ.mjs → runner-Bkkfk4O8.mjs} +78 -4
  679. package/dist/runner-Bkkfk4O8.mjs.map +1 -0
  680. package/dist/{runner-BObHz5FC.d.mts → runner-Dfgp6-S_.d.mts} +7 -2
  681. package/dist/runner-Dfgp6-S_.d.mts.map +1 -0
  682. package/dist/runtime.d.mts +14 -13
  683. package/dist/runtime.d.mts.map +1 -1
  684. package/dist/runtime.mjs +8 -6
  685. package/dist/runtime.mjs.map +1 -1
  686. package/dist/schema/project-env-types.mjs +43 -42
  687. package/dist/schema/project-env-types.mjs.map +1 -1
  688. package/dist/{schema-DJRfvM_o.mjs → schema-B-3rntlX.mjs} +11 -11
  689. package/dist/{schema-DJRfvM_o.mjs.map → schema-B-3rntlX.mjs.map} +1 -1
  690. package/dist/{schema-C4OBuv6Z.mjs → schema-BqBlUZtb.mjs} +4 -4
  691. package/dist/{schema-C4OBuv6Z.mjs.map → schema-BqBlUZtb.mjs.map} +1 -1
  692. package/dist/{scopes-BU03K7Uo.mjs → scopes-DNaY7Ey0.mjs} +3 -3
  693. package/dist/{scopes-BU03K7Uo.mjs.map → scopes-DNaY7Ey0.mjs.map} +1 -1
  694. package/dist/{search-DfVzks89.mjs → search-BPWTnpnD.mjs} +32 -32
  695. package/dist/search-BPWTnpnD.mjs.map +1 -0
  696. package/dist/{secrets-Cc_O3Kp-.mjs → secrets-Dswzrz3k.mjs} +2 -2
  697. package/dist/{secrets-Cc_O3Kp-.mjs.map → secrets-Dswzrz3k.mjs.map} +1 -1
  698. package/dist/{sections-BMy4JVUz.mjs → sections-rSao6rBG.mjs} +3 -3
  699. package/dist/{sections-BMy4JVUz.mjs.map → sections-rSao6rBG.mjs.map} +1 -1
  700. package/dist/seed/index.d.mts +2 -2
  701. package/dist/seed/index.mjs +42 -41
  702. package/dist/seo/index.d.mts +3 -3
  703. package/dist/seo/index.mjs +30 -28
  704. package/dist/seo/index.mjs.map +1 -1
  705. package/dist/{seo-VZYOEy8f.mjs → seo-B_H_pqOd.mjs} +3 -3
  706. package/dist/{seo-VZYOEy8f.mjs.map → seo-B_H_pqOd.mjs.map} +1 -1
  707. package/dist/{service-Bo_usgSk.mjs → service-DpiUQVpp.mjs} +2 -2
  708. package/dist/{service-Bo_usgSk.mjs.map → service-DpiUQVpp.mjs.map} +1 -1
  709. package/dist/{session-user-DlpPdf8L.mjs → session-user-DiE4JKPP.mjs} +4 -4
  710. package/dist/{session-user-DlpPdf8L.mjs.map → session-user-DiE4JKPP.mjs.map} +1 -1
  711. package/dist/{settings-DS914jjE.mjs → settings--XlUdUaI.mjs} +3 -3
  712. package/dist/{settings-DS914jjE.mjs.map → settings--XlUdUaI.mjs.map} +1 -1
  713. package/dist/{settings-CWb84sDm.mjs → settings-D932YP2-.mjs} +111 -44
  714. package/dist/settings-D932YP2-.mjs.map +1 -0
  715. package/dist/{setup-complete-BuNxAUiN.mjs → setup-complete-qsJYWutC.mjs} +2 -2
  716. package/dist/{setup-complete-BuNxAUiN.mjs.map → setup-complete-qsJYWutC.mjs.map} +1 -1
  717. package/dist/{setup-nonce-BnEAX0iy.mjs → setup-nonce-CBFgUFXw.mjs} +1 -1
  718. package/dist/{setup-nonce-BnEAX0iy.mjs.map → setup-nonce-CBFgUFXw.mjs.map} +1 -1
  719. package/dist/{site-domain-Bq5j5bVg.mjs → site-domain-oRGS_JfA.mjs} +2 -2
  720. package/dist/{site-domain-Bq5j5bVg.mjs.map → site-domain-oRGS_JfA.mjs.map} +1 -1
  721. package/dist/{sitemap-name-BTg2NJJv.mjs → sitemap-name-B8QP8wud.mjs} +1 -1
  722. package/dist/{sitemap-name-BTg2NJJv.mjs.map → sitemap-name-B8QP8wud.mjs.map} +1 -1
  723. package/dist/{slugify-bu2-jKia.mjs → slugify-BDEG9pLk.mjs} +1 -1
  724. package/dist/{slugify-bu2-jKia.mjs.map → slugify-BDEG9pLk.mjs.map} +1 -1
  725. package/dist/{snapshot-DYsG4uOq.mjs → snapshot-BjaXDZQ5.mjs} +2 -2
  726. package/dist/{snapshot-DYsG4uOq.mjs.map → snapshot-BjaXDZQ5.mjs.map} +1 -1
  727. package/dist/{stage-D8DWgPcO.mjs → stage-CZQnXM_G.mjs} +3 -3
  728. package/dist/{stage-D8DWgPcO.mjs.map → stage-CZQnXM_G.mjs.map} +1 -1
  729. package/dist/{staged-CD_imitH.mjs → staged-ByBmPFtX.mjs} +3 -3
  730. package/dist/{staged-CD_imitH.mjs.map → staged-ByBmPFtX.mjs.map} +1 -1
  731. package/dist/storage/local.d.mts +1 -1
  732. package/dist/storage/s3.d.mts +1 -1
  733. package/dist/{storage-query-DRyu3bSU.d.mts → storage-query-BFp06Y0s.d.mts} +22 -10
  734. package/dist/storage-query-BFp06Y0s.d.mts.map +1 -0
  735. package/dist/{taxonomies-Dd9JJv_a.mjs → taxonomies-5SR76j11.mjs} +15 -17
  736. package/dist/taxonomies-5SR76j11.mjs.map +1 -0
  737. package/dist/{taxonomies-ChnU7Mc8.mjs → taxonomies-B__VmCKQ.mjs} +64 -58
  738. package/dist/taxonomies-B__VmCKQ.mjs.map +1 -0
  739. package/dist/{taxonomy-C_C_LBAU.mjs → taxonomy-CMI5fczd.mjs} +30 -17
  740. package/dist/taxonomy-CMI5fczd.mjs.map +1 -0
  741. package/dist/{transaction-BVYIo_yu.mjs → transaction-CkoQ5wqQ.mjs} +1 -1
  742. package/dist/{transaction-BVYIo_yu.mjs.map → transaction-CkoQ5wqQ.mjs.map} +1 -1
  743. package/dist/{transfer-WmWiR3xf.mjs → transfer-BbKfufJ4.mjs} +2 -2
  744. package/dist/{transfer-WmWiR3xf.mjs.map → transfer-BbKfufJ4.mjs.map} +1 -1
  745. package/dist/{transfer-ClH6w6BV.mjs → transfer-DTGblAj2.mjs} +71 -34
  746. package/dist/{transfer-ClH6w6BV.mjs.map → transfer-DTGblAj2.mjs.map} +1 -1
  747. package/dist/{transfer-download--ofRj9Cw.mjs → transfer-download-D9LQEDX0.mjs} +1 -1
  748. package/dist/{transfer-download--ofRj9Cw.mjs.map → transfer-download-D9LQEDX0.mjs.map} +1 -1
  749. package/dist/{transport-DxiXnbXk.d.mts → transport-Dm5QzpT_.d.mts} +1 -1
  750. package/dist/{transport-DxiXnbXk.d.mts.map → transport-Dm5QzpT_.d.mts.map} +1 -1
  751. package/dist/{transport-BjbqNiPI.mjs → transport-Dzpn5b3i.mjs} +4 -3
  752. package/dist/transport-Dzpn5b3i.mjs.map +1 -0
  753. package/dist/{turnstile-CJwvsOqw.mjs → turnstile-Cs2wfkJG.mjs} +1 -1
  754. package/dist/{turnstile-CJwvsOqw.mjs.map → turnstile-Cs2wfkJG.mjs.map} +1 -1
  755. package/dist/{types-BA3ey2QH.d.mts → types-BAsCk5KU.d.mts} +1 -1
  756. package/dist/{types-BA3ey2QH.d.mts.map → types-BAsCk5KU.d.mts.map} +1 -1
  757. package/dist/{types-RLgeIpnF.d.mts → types-BuvSwT9Y.d.mts} +8 -7
  758. package/dist/{types-RLgeIpnF.d.mts.map → types-BuvSwT9Y.d.mts.map} +1 -1
  759. package/dist/{types-CNB-dj6F.d.mts → types-C4KT3Md2.d.mts} +10 -6
  760. package/dist/types-C4KT3Md2.d.mts.map +1 -0
  761. package/dist/{types-DvqVxZXa.d.mts → types-CVXHwIBB.d.mts} +1 -1
  762. package/dist/{types-DvqVxZXa.d.mts.map → types-CVXHwIBB.d.mts.map} +1 -1
  763. package/dist/{types-BGmQ0uXs.mjs → types-C_asjp1J.mjs} +1 -1
  764. package/dist/types-C_asjp1J.mjs.map +1 -0
  765. package/dist/{types-DHO7Pd25.d.mts → types-CadaL_k8.d.mts} +1 -1
  766. package/dist/{types-DHO7Pd25.d.mts.map → types-CadaL_k8.d.mts.map} +1 -1
  767. package/dist/{types-QoPHm-2w.d.mts → types-CjftrmZR.d.mts} +3 -3
  768. package/dist/{types-QoPHm-2w.d.mts.map → types-CjftrmZR.d.mts.map} +1 -1
  769. package/dist/{types-DCFavOii.d.mts → types-DKwRUA-x.d.mts} +1 -1
  770. package/dist/{types-DCFavOii.d.mts.map → types-DKwRUA-x.d.mts.map} +1 -1
  771. package/dist/{types-D2NEXtgB.mjs → types-DwhEvIVb.mjs} +8 -2
  772. package/dist/types-DwhEvIVb.mjs.map +1 -0
  773. package/dist/{types-Bwpzb5o6.d.mts → types-GwAyS5SH.d.mts} +1 -1
  774. package/dist/{types-Bwpzb5o6.d.mts.map → types-GwAyS5SH.d.mts.map} +1 -1
  775. package/dist/{types-slSqujQL.d.mts → types-uU2YNYSt.d.mts} +6 -1
  776. package/dist/types-uU2YNYSt.d.mts.map +1 -0
  777. package/dist/{update-check-BxNg9T6N.mjs → update-check-ABBJgg6M.mjs} +4 -4
  778. package/dist/{update-check-BxNg9T6N.mjs.map → update-check-ABBJgg6M.mjs.map} +1 -1
  779. package/dist/{url-Dn3IStq8.mjs → url-DTfGDJhI.mjs} +1 -1
  780. package/dist/{url-Dn3IStq8.mjs.map → url-DTfGDJhI.mjs.map} +1 -1
  781. package/dist/{user-BlCTKVAm.mjs → user-By8SzQxS.mjs} +3 -3
  782. package/dist/{user-BlCTKVAm.mjs.map → user-By8SzQxS.mjs.map} +1 -1
  783. package/dist/{utils-TPt7w2cS.mjs → utils-D5uOi6WS.mjs} +13 -5
  784. package/dist/utils-D5uOi6WS.mjs.map +1 -0
  785. package/dist/{index-BB9sVisO.d.mts → utils-Szp4iBQB.d.mts} +9 -256
  786. package/dist/utils-Szp4iBQB.d.mts.map +1 -0
  787. package/dist/{validate-emKxGC5F.d.mts → validate-DDvxy6qG.d.mts} +8 -8
  788. package/dist/{validate-emKxGC5F.d.mts.map → validate-DDvxy6qG.d.mts.map} +1 -1
  789. package/dist/{validate-DxYhJQA-.mjs → validate-Dz-TIOFB.mjs} +7 -7
  790. package/dist/{validate-DxYhJQA-.mjs.map → validate-Dz-TIOFB.mjs.map} +1 -1
  791. package/dist/{validation-Ckq4vsVg.mjs → validation-Fc9ZSUS_.mjs} +17 -16
  792. package/dist/{validation-Ckq4vsVg.mjs.map → validation-Fc9ZSUS_.mjs.map} +1 -1
  793. package/dist/version-Bu6Nlbb5.mjs +7 -0
  794. package/dist/{version-DHmGpcch.mjs.map → version-Bu6Nlbb5.mjs.map} +1 -1
  795. package/dist/version-DqB7LIO7.mjs +49 -0
  796. package/dist/version-DqB7LIO7.mjs.map +1 -0
  797. package/dist/{widgets-DA5XmvVC.mjs → widgets-BUx_Mf2q.mjs} +18 -5
  798. package/dist/widgets-BUx_Mf2q.mjs.map +1 -0
  799. package/dist/{wxr-taxonomies-RgRG0d5e.mjs → wxr-taxonomies-DbJtWrWM.mjs} +7 -6
  800. package/dist/wxr-taxonomies-DbJtWrWM.mjs.map +1 -0
  801. package/dist/{wxr-taxonomies-CrMonejI.d.mts → wxr-taxonomies-Dy2i2ON3.d.mts} +1 -1
  802. package/dist/wxr-taxonomies-Dy2i2ON3.d.mts.map +1 -0
  803. package/dist/{zod-generator-D0JKy94C.mjs → zod-generator--nlM0930.mjs} +5 -4
  804. package/dist/zod-generator--nlM0930.mjs.map +1 -0
  805. package/package.json +5 -5
  806. package/src/api/handlers/bulk-tag.ts +11 -3
  807. package/src/api/handlers/bylines.ts +6 -2
  808. package/src/api/handlers/content.ts +154 -23
  809. package/src/api/handlers/dashboard.ts +13 -6
  810. package/src/api/handlers/device-flow.ts +1 -3
  811. package/src/api/handlers/menus.ts +27 -13
  812. package/src/api/handlers/oauth-authorization.ts +1 -3
  813. package/src/api/handlers/relations.ts +15 -1
  814. package/src/api/handlers/taxonomies.ts +27 -17
  815. package/src/astro/image-endpoint.ts +23 -2
  816. package/src/astro/integration/admin-nav.ts +52 -0
  817. package/src/astro/integration/index.ts +7 -0
  818. package/src/astro/integration/runtime.ts +14 -0
  819. package/src/astro/integration/shims/use-sync-external-store-with-selector.js +2 -0
  820. package/src/astro/integration/shims/use-sync-external-store.js +4 -1
  821. package/src/astro/integration/vite-config.ts +16 -8
  822. package/src/astro/middleware/auth.ts +9 -2
  823. package/src/astro/middleware/redirect.ts +158 -63
  824. package/src/astro/middleware/request-context.ts +1 -0
  825. package/src/astro/middleware.ts +17 -4
  826. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +4 -1
  827. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +14 -1
  828. package/src/astro/routes/api/dashboard.ts +2 -0
  829. package/src/astro/routes/api/import/wordpress/analyze.ts +5 -29
  830. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -3
  831. package/src/astro/routes/api/media/file/[...key].ts +31 -7
  832. package/src/astro/routes/api/oauth/token.ts +5 -1
  833. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +7 -1
  834. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +3 -1
  835. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +2 -1
  836. package/src/astro/routes/api/widget-areas/[name].ts +2 -1
  837. package/src/astro/routes/api/widget-areas/index.ts +2 -1
  838. package/src/astro/types.ts +4 -3
  839. package/src/auth/api-tokens.ts +3 -0
  840. package/src/auth/types.ts +6 -0
  841. package/src/cleanup.ts +44 -0
  842. package/src/cli/commands/export-seed.ts +6 -4
  843. package/src/cli/commands/login.ts +2 -4
  844. package/src/client/index.ts +1 -0
  845. package/src/client/transport.ts +11 -7
  846. package/src/components/EmDashImage.astro +14 -2
  847. package/src/components/InlinePortableTextEditor.tsx +4 -1
  848. package/src/components/inline-bubble-menu.tsx +109 -95
  849. package/src/components/inline-image.tsx +54 -48
  850. package/src/database/dialect-helpers.ts +10 -3
  851. package/src/database/migrations/content-sized.ts +82 -0
  852. package/src/database/migrations/policy.ts +28 -2
  853. package/src/database/migrations/runner.ts +48 -0
  854. package/src/database/repositories/byline.ts +95 -31
  855. package/src/database/repositories/comment.ts +17 -7
  856. package/src/database/repositories/content.ts +96 -23
  857. package/src/database/repositories/media.ts +17 -0
  858. package/src/database/repositories/menu.ts +236 -139
  859. package/src/database/repositories/taxonomy-def.ts +9 -2
  860. package/src/database/repositories/taxonomy.ts +47 -14
  861. package/src/database/repositories/types.ts +14 -3
  862. package/src/database/types.ts +1 -1
  863. package/src/emdash-runtime.ts +60 -17
  864. package/src/fields/image.ts +1 -0
  865. package/src/i18n/config.ts +58 -10
  866. package/src/i18n/normalize.ts +16 -2
  867. package/src/i18n/query.ts +47 -0
  868. package/src/i18n/resolve.ts +8 -3
  869. package/src/import/utils.ts +15 -2
  870. package/src/import/wxr-taxonomies.ts +3 -2
  871. package/src/index.ts +1 -0
  872. package/src/loader.ts +183 -114
  873. package/src/mcp/server.ts +28 -1
  874. package/src/media/caption.ts +30 -0
  875. package/src/media/content-disposition.ts +56 -0
  876. package/src/media/image-endpoint.ts +13 -6
  877. package/src/media/local-runtime.ts +3 -0
  878. package/src/media/normalize.ts +17 -8
  879. package/src/media/responsive.ts +12 -2
  880. package/src/media/types.ts +16 -3
  881. package/src/media/usage/content-fields.ts +2 -1
  882. package/src/menus/index.ts +158 -36
  883. package/src/migrations/manifest.ts +1 -0
  884. package/src/object-cache/index.ts +22 -0
  885. package/src/plugin-test-runtime.ts +1 -0
  886. package/src/plugins/byline-access.ts +3 -1
  887. package/src/plugins/context.ts +1 -2
  888. package/src/plugins/storage-indexes.ts +7 -3
  889. package/src/query.ts +67 -53
  890. package/src/redirects/artifacts.ts +39 -5
  891. package/src/references/field-map.ts +6 -4
  892. package/src/request-context.ts +8 -0
  893. package/src/schema/collection-slugs-cache.ts +31 -17
  894. package/src/schema/registry.ts +9 -0
  895. package/src/schema/types.ts +7 -6
  896. package/src/schema/zod-generator.ts +2 -1
  897. package/src/search/fts-manager.ts +103 -31
  898. package/src/search/query.ts +31 -64
  899. package/src/seed/apply.ts +221 -109
  900. package/src/seed/types.ts +6 -4
  901. package/src/settings/index.ts +135 -35
  902. package/src/settings/version.ts +54 -0
  903. package/src/taxonomies/index.ts +99 -85
  904. package/src/taxonomies/term-counts.ts +2 -1
  905. package/src/transfer/import/advance.ts +12 -1
  906. package/src/transfer/import/scaffold.ts +7 -1
  907. package/src/transfer/import/stages.ts +53 -2
  908. package/src/utils/db-errors.ts +15 -0
  909. package/src/utils/revalidating-cache.ts +85 -0
  910. package/src/virtual-modules.d.ts +1 -0
  911. package/src/visual-editing/toolbar.ts +7 -2
  912. package/src/widgets/index.ts +27 -13
  913. package/dist/api-D-7BNHoz.mjs.map +0 -1
  914. package/dist/api-tokens-CdP49zVF.mjs +0 -3
  915. package/dist/apply-T7ATgzCh.mjs.map +0 -1
  916. package/dist/artifacts-htGyfCSt.mjs.map +0 -1
  917. package/dist/byline-BR1qhyiw.mjs.map +0 -1
  918. package/dist/bylines-CVOvRUL7.mjs.map +0 -1
  919. package/dist/collection-slugs-cache-e09QeJQt.mjs.map +0 -1
  920. package/dist/comment-UvIWDKcW.mjs.map +0 -1
  921. package/dist/config-Bsm_u_oE.d.mts.map +0 -1
  922. package/dist/config-CFMojMFK.d.mts.map +0 -1
  923. package/dist/config-CvmjJcVw.mjs +0 -73
  924. package/dist/config-CvmjJcVw.mjs.map +0 -1
  925. package/dist/content-DQSRZTVw.mjs.map +0 -1
  926. package/dist/context-BYptmCN0.mjs.map +0 -1
  927. package/dist/dashboard-D0jcgBD7.mjs.map +0 -1
  928. package/dist/db-errors-CBD5yMro.mjs.map +0 -1
  929. package/dist/deferred-tasks-ZvUECSzI.d.mts +0 -9
  930. package/dist/deferred-tasks-ZvUECSzI.d.mts.map +0 -1
  931. package/dist/device-flow-BkFKBoAn.mjs.map +0 -1
  932. package/dist/dialect-helpers-7_IqPdh9.mjs.map +0 -1
  933. package/dist/emdash-runtime-DVi7vtXC.mjs.map +0 -1
  934. package/dist/field-defs-cache-Dez5iWJJ.mjs +0 -77
  935. package/dist/field-defs-cache-Dez5iWJJ.mjs.map +0 -1
  936. package/dist/field-map-Bft9LKak.mjs.map +0 -1
  937. package/dist/fts-manager-Beg3e4bI.mjs.map +0 -1
  938. package/dist/index-BB9sVisO.d.mts.map +0 -1
  939. package/dist/loader-CswroUbe.mjs.map +0 -1
  940. package/dist/manifest-builder-B8zjuH3f.mjs.map +0 -1
  941. package/dist/media-Bws9f18T.mjs.map +0 -1
  942. package/dist/menus-BCVSSp1z.mjs.map +0 -1
  943. package/dist/menus-Cl4kwdt7.mjs.map +0 -1
  944. package/dist/normalize-BuWa0lvd.mjs.map +0 -1
  945. package/dist/oauth-authorization-TpEJrYB7.mjs.map +0 -1
  946. package/dist/placeholder-D41vk11_.d.mts.map +0 -1
  947. package/dist/policy-DLQ--Hnm.mjs.map +0 -1
  948. package/dist/query-CpnRlBh8.mjs.map +0 -1
  949. package/dist/registry-TUVaid9Z.mjs.map +0 -1
  950. package/dist/relations-CA_QuMTU.mjs.map +0 -1
  951. package/dist/resolve-D-kqyKns.mjs.map +0 -1
  952. package/dist/runner-BObHz5FC.d.mts.map +0 -1
  953. package/dist/runner-C5NeAkBQ.mjs.map +0 -1
  954. package/dist/search-DfVzks89.mjs.map +0 -1
  955. package/dist/settings-CWb84sDm.mjs.map +0 -1
  956. package/dist/storage-query-DRyu3bSU.d.mts.map +0 -1
  957. package/dist/taxonomies-ChnU7Mc8.mjs.map +0 -1
  958. package/dist/taxonomies-Dd9JJv_a.mjs.map +0 -1
  959. package/dist/taxonomy-C_C_LBAU.mjs.map +0 -1
  960. package/dist/transport-BjbqNiPI.mjs.map +0 -1
  961. package/dist/types-BGmQ0uXs.mjs.map +0 -1
  962. package/dist/types-CNB-dj6F.d.mts.map +0 -1
  963. package/dist/types-D2NEXtgB.mjs.map +0 -1
  964. package/dist/types-slSqujQL.d.mts.map +0 -1
  965. package/dist/utils-TPt7w2cS.mjs.map +0 -1
  966. package/dist/version-DHmGpcch.mjs +0 -7
  967. package/dist/widgets-DA5XmvVC.mjs.map +0 -1
  968. package/dist/wxr-taxonomies-CrMonejI.d.mts.map +0 -1
  969. package/dist/wxr-taxonomies-RgRG0d5e.mjs.map +0 -1
  970. package/dist/zod-generator-D0JKy94C.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"validate-DxYhJQA-.mjs","names":[],"sources":["../src/seed/validate.ts"],"sourcesContent":["/**\n * Seed file validation\n *\n * Validates a seed file structure before applying it.\n */\n\nimport { getI18nConfig, resolveConfiguredLocale } from \"../i18n/config.js\";\nimport { isSiteRelativeDestination } from \"../redirects/destination.js\";\nimport { isPattern, validateDestinationParams, validatePattern } from \"../redirects/patterns.js\";\nimport { validateBlockFields } from \"../schema/block-type-contract.js\";\nimport {\n\tFIELD_TYPES,\n\tisIndexableFieldType,\n\tMAX_COLLECTION_GROUP_LENGTH,\n\tMAX_COLLECTION_ICON_LENGTH,\n\tMAX_COLLECTION_LIST_COLUMNS,\n\tRESERVED_COLLECTION_SLUGS,\n\tRESERVED_FIELD_SLUGS,\n} from \"../schema/types.js\";\nimport { compileUrlPattern } from \"../schema/url-pattern.js\";\nimport type { SeedFile, SeedMenuItem, SeedTaxonomy, ValidationResult } from \"./types.js\";\n\nconst COLLECTION_FIELD_SLUG_PATTERN = /^[a-z][a-z0-9_]*$/;\n/** Matches `SchemaRegistry.validateSlug`, which collection and field slugs go through. */\nconst MAX_SLUG_LENGTH = 63;\nconst SLUG_PATTERN = /^[a-z0-9-]+$/;\nconst REDIRECT_TYPES = new Set([301, 302, 307, 308]);\nconst CRLF_PATTERN = /[\\r\\n]/;\n\n/** Type guard for Record<string, unknown> */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isValidRedirectPath(path: string): boolean {\n\tif (!path.startsWith(\"/\") || path.startsWith(\"//\") || CRLF_PATTERN.test(path)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\treturn !decodeURIComponent(path).split(\"/\").includes(\"..\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * The entry that declares `taxonomy`'s `hierarchical` and `collections`: the last\n * entry of its `translationOf` chain within the taxonomy's name, or undefined when\n * the chain loops.\n */\nexport function findTaxonomyStructureSource<T extends Pick<SeedTaxonomy, \"name\" | \"translationOf\">>(\n\ttaxonomy: T,\n\ttaxonomiesById: ReadonlyMap<string, T>,\n): T | undefined {\n\tconst visited = new Set<T>();\n\tlet current = taxonomy;\n\twhile (!visited.has(current)) {\n\t\tvisited.add(current);\n\t\tconst source = current.translationOf ? taxonomiesById.get(current.translationOf) : undefined;\n\t\tif (!source || source.name !== current.name) return current;\n\t\tcurrent = source;\n\t}\n\treturn undefined;\n}\n\n/** Whether `a` and `b` disagree on `hierarchical` or `collections`, comparing only fields both declare. */\nfunction declaresDifferentStructure(a: SeedTaxonomy, b: SeedTaxonomy): boolean {\n\tif (\n\t\ta.hierarchical !== undefined &&\n\t\tb.hierarchical !== undefined &&\n\t\ta.hierarchical !== b.hierarchical\n\t) {\n\t\treturn true;\n\t}\n\tif (!Array.isArray(a.collections) || !Array.isArray(b.collections)) return false;\n\tconst own = new Set(a.collections);\n\tconst other = new Set(b.collections);\n\treturn own.size !== other.size || [...own].some((collection) => !other.has(collection));\n}\n\n/**\n * Validate a seed file\n *\n * @param data - Unknown data to validate as a seed file\n * @returns Validation result with errors and warnings\n */\nexport function validateSeed(data: unknown): ValidationResult {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\n\t// Basic type check\n\tif (!data || typeof data !== \"object\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terrors: [\"Seed must be an object\"],\n\t\t\twarnings: [],\n\t\t};\n\t}\n\n\tconst seed = data as Partial<SeedFile>;\n\tconst defaultLocale =\n\t\tgetI18nConfig()?.defaultLocale ??\n\t\t(typeof seed.defaultLocale === \"string\" ? seed.defaultLocale : \"en\");\n\n\t// Required fields\n\tif (!seed.version) {\n\t\terrors.push(\"Seed must have a version field\");\n\t} else if (seed.version !== \"1\") {\n\t\terrors.push(`Unsupported seed version: ${String(seed.version)}`);\n\t}\n\n\t// defaultLocale backfills the locale of rows that omit one, so a blank or\n\t// whitespace-padded value would silently write empty/invalid locales to the DB.\n\t// Exported seeds never hit this, but it's part of the public schema now.\n\tif (seed.defaultLocale !== undefined) {\n\t\tif (\n\t\t\ttypeof seed.defaultLocale !== \"string\" ||\n\t\t\tseed.defaultLocale.length === 0 ||\n\t\t\tseed.defaultLocale !== seed.defaultLocale.trim()\n\t\t) {\n\t\t\terrors.push(\n\t\t\t\t\"defaultLocale: must be a non-empty string with no leading or trailing whitespace\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (seed.blockTypes !== undefined) {\n\t\tif (!Array.isArray(seed.blockTypes)) {\n\t\t\terrors.push(\"blockTypes must be an array\");\n\t\t} else {\n\t\t\tconst slugs = new Set<string>();\n\t\t\tfor (const [index, blockType] of seed.blockTypes.entries()) {\n\t\t\t\tconst prefix = `blockTypes[${index}]`;\n\t\t\t\tif (!blockType.slug || !COLLECTION_FIELD_SLUG_PATTERN.test(blockType.slug)) {\n\t\t\t\t\terrors.push(`${prefix}.slug: must be a valid block type slug`);\n\t\t\t\t} else if (slugs.has(blockType.slug)) {\n\t\t\t\t\terrors.push(`${prefix}.slug: duplicate block type slug \"${blockType.slug}\"`);\n\t\t\t\t} else {\n\t\t\t\t\tslugs.add(blockType.slug);\n\t\t\t\t}\n\t\t\t\tif (!blockType.label) errors.push(`${prefix}.label: is required`);\n\t\t\t\tif (!Array.isArray(blockType.versions) || blockType.versions.length === 0) {\n\t\t\t\t\terrors.push(`${prefix}.versions: must be a non-empty array`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst numbers = blockType.versions.map((version) => version.version);\n\t\t\t\tconst sorted = [...numbers].toSorted((left, right) => left - right);\n\t\t\t\tif (\n\t\t\t\t\tsorted[0] !== 1 ||\n\t\t\t\t\tsorted.some((version, versionIndex) => version !== versionIndex + 1)\n\t\t\t\t) {\n\t\t\t\t\terrors.push(`${prefix}.versions: numbers must be contiguous and start at 1`);\n\t\t\t\t}\n\t\t\t\tif (!numbers.includes(blockType.currentVersion)) {\n\t\t\t\t\terrors.push(`${prefix}.currentVersion: must name a declared version`);\n\t\t\t\t}\n\t\t\t\tfor (const [versionIndex, version] of blockType.versions.entries()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvalidateBlockFields(version.fields);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.versions[${versionIndex}].${error instanceof Error ? error.message : \"invalid fields\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate collections\n\tif (seed.collections) {\n\t\tif (!Array.isArray(seed.collections)) {\n\t\t\terrors.push(\"collections must be an array\");\n\t\t} else {\n\t\t\tconst collectionSlugs = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.collections.length; i++) {\n\t\t\t\tconst collection = seed.collections[i];\n\t\t\t\tconst prefix = `collections[${i}]`;\n\n\t\t\t\tif (!collection.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Check for valid slug format\n\t\t\t\t\tif (!COLLECTION_FIELD_SLUG_PATTERN.test(collection.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must start with a letter and contain only lowercase letters, numbers, and underscores`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Reserved slugs pass the format check but are rejected by the schema registry on apply\n\t\t\t\t\tif (RESERVED_COLLECTION_SLUGS.includes(collection.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: collection slug \"${collection.slug}\" is reserved`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for duplicate slugs\n\t\t\t\t\tif (collectionSlugs.has(collection.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate collection slug \"${collection.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tcollectionSlugs.add(collection.slug);\n\t\t\t\t}\n\n\t\t\t\tif (!collection.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\t\t\t\tif (collection.editLocking !== undefined && typeof collection.editLocking !== \"boolean\") {\n\t\t\t\t\terrors.push(`${prefix}.editLocking: must be a boolean`);\n\t\t\t\t}\n\t\t\t\tif (collection.routable !== undefined && typeof collection.routable !== \"boolean\") {\n\t\t\t\t\terrors.push(`${prefix}.routable: must be a boolean`);\n\t\t\t\t}\n\t\t\t\tif (collection.urlPattern !== undefined) {\n\t\t\t\t\tif (typeof collection.urlPattern !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.urlPattern: must be a string`);\n\t\t\t\t\t} else if (collection.urlPattern) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcompileUrlPattern(collection.urlPattern);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${prefix}.urlPattern: ${error instanceof Error ? error.message : \"invalid URL pattern\"}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (collection.group !== undefined) {\n\t\t\t\t\tif (typeof collection.group !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.group: must be a string`);\n\t\t\t\t\t} else if (collection.group.trim().length > MAX_COLLECTION_GROUP_LENGTH) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.group: must be at most ${MAX_COLLECTION_GROUP_LENGTH} characters`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (collection.icon !== undefined) {\n\t\t\t\t\tif (typeof collection.icon !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.icon: must be a string`);\n\t\t\t\t\t} else if (collection.icon.trim().length > MAX_COLLECTION_ICON_LENGTH) {\n\t\t\t\t\t\terrors.push(`${prefix}.icon: must be at most ${MAX_COLLECTION_ICON_LENGTH} characters`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst declaredFieldSlugs = new Set(\n\t\t\t\t\tArray.isArray(collection.fields)\n\t\t\t\t\t\t? collection.fields.flatMap((field) =>\n\t\t\t\t\t\t\t\tisRecord(field) && typeof field.slug === \"string\" ? [field.slug] : [],\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: [],\n\t\t\t\t);\n\n\t\t\t\tif (collection.admin !== undefined) {\n\t\t\t\t\tif (!isRecord(collection.admin)) {\n\t\t\t\t\t\terrors.push(`${prefix}.admin: must be an object`);\n\t\t\t\t\t} else if (collection.admin.listColumns !== undefined) {\n\t\t\t\t\t\tif (!Array.isArray(collection.admin.listColumns)) {\n\t\t\t\t\t\t\terrors.push(`${prefix}.admin.listColumns: must be an array`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (collection.admin.listColumns.length > MAX_COLLECTION_LIST_COLUMNS) {\n\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t`${prefix}.admin.listColumns: must contain at most ${MAX_COLLECTION_LIST_COLUMNS} items`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (let j = 0; j < collection.admin.listColumns.length; j++) {\n\t\t\t\t\t\t\t\tconst slug = collection.admin.listColumns[j];\n\t\t\t\t\t\t\t\tif (typeof slug !== \"string\" || !COLLECTION_FIELD_SLUG_PATTERN.test(slug)) {\n\t\t\t\t\t\t\t\t\terrors.push(`${prefix}.admin.listColumns[${j}]: must be a valid field slug`);\n\t\t\t\t\t\t\t\t} else if (!declaredFieldSlugs.has(slug)) {\n\t\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t\t`${prefix}.admin.listColumns[${j}]: references unknown field \"${slug}\"`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tisRecord(collection.admin) &&\n\t\t\t\t\t\tcollection.admin.quickCreate !== undefined &&\n\t\t\t\t\t\ttypeof collection.admin.quickCreate !== \"boolean\"\n\t\t\t\t\t) {\n\t\t\t\t\t\terrors.push(`${prefix}.admin.quickCreate: must be a boolean`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Validate fields\n\t\t\t\tif (!Array.isArray(collection.fields)) {\n\t\t\t\t\terrors.push(`${prefix}.fields: must be an array`);\n\t\t\t\t} else {\n\t\t\t\t\tconst fieldSlugs = new Set<string>();\n\n\t\t\t\t\tfor (let j = 0; j < collection.fields.length; j++) {\n\t\t\t\t\t\tconst field = collection.fields[j];\n\t\t\t\t\t\tconst fieldPrefix = `${prefix}.fields[${j}]`;\n\n\t\t\t\t\t\tif (!field.slug) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}: slug is required`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Check for valid slug format\n\t\t\t\t\t\t\tif (!COLLECTION_FIELD_SLUG_PATTERN.test(field.slug)) {\n\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.slug: must start with a letter and contain only lowercase letters, numbers, and underscores`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Reserved slugs pass the format check but are rejected by the schema registry on apply\n\t\t\t\t\t\t\tif (RESERVED_FIELD_SLUGS.includes(field.slug)) {\n\t\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.slug: field slug \"${field.slug}\" is reserved`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Check for duplicate field slugs\n\t\t\t\t\t\t\tif (fieldSlugs.has(field.slug)) {\n\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.slug: duplicate field slug \"${field.slug}\" in collection \"${collection.slug}\"`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfieldSlugs.add(field.slug);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!field.label) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}: label is required`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (field.indexed !== undefined && typeof field.indexed !== \"boolean\") {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.indexed: must be a boolean`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (field.translatable !== undefined && typeof field.translatable !== \"boolean\") {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.translatable: must be a boolean`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!field.type) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}: type is required`);\n\t\t\t\t\t\t} else if (!(FIELD_TYPES as readonly string[]).includes(field.type)) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.type: unsupported field type \"${field.type}\"`);\n\t\t\t\t\t\t} else if (field.indexed === true && !isIndexableFieldType(field.type)) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.indexed: type \"${field.type}\" cannot be indexed`);\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tfield.indexed === true &&\n\t\t\t\t\t\t\tfield.type === \"reference\" &&\n\t\t\t\t\t\t\ttypeof field.validation?.targetCollection === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// A targetCollection makes this field storage-less on apply: its\n\t\t\t\t\t\t\t// selection becomes relation edges, leaving no column to index.\n\t\t\t\t\t\t\t// Without one it stays a plain entry-id column, which can be.\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${fieldPrefix}.indexed: a reference field with a targetCollection stores no column to index`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (field.type === \"repeater\") {\n\t\t\t\t\t\t\tconst subFields = field.validation?.subFields;\n\t\t\t\t\t\t\tif (\"fields\" in field) {\n\t\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.fields: repeater sub-fields must be defined in validation.subFields; these fields are ignored`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else if (!Array.isArray(subFields) || subFields.length === 0) {\n\t\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.validation.subFields: repeater needs a non-empty array of sub-fields, so its rows have nothing to edit`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate relations\n\tif (seed.relations) {\n\t\tif (!Array.isArray(seed.relations)) {\n\t\t\terrors.push(\"relations must be an array\");\n\t\t} else {\n\t\t\tconst relationSlugs = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.relations.length; i++) {\n\t\t\t\tconst relation = seed.relations[i];\n\t\t\t\tconst prefix = `relations[${i}]`;\n\t\t\t\tif (!relation) continue;\n\n\t\t\t\tif (!relation.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!COLLECTION_FIELD_SLUG_PATTERN.test(relation.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must start with a letter and contain only lowercase letters, numbers, and underscores`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (relation.slug.length > MAX_SLUG_LENGTH) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: must be ${MAX_SLUG_LENGTH} characters or fewer`);\n\t\t\t\t\t}\n\t\t\t\t\tif (relationSlugs.has(relation.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate relation slug \"${relation.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\trelationSlugs.add(relation.slug);\n\t\t\t\t}\n\n\t\t\t\tfor (const end of [\"parentCollection\", \"childCollection\"] as const) {\n\t\t\t\t\tconst value = relation[end];\n\t\t\t\t\tif (!value) {\n\t\t\t\t\t\terrors.push(`${prefix}: ${end} is required`);\n\t\t\t\t\t} else if (!COLLECTION_FIELD_SLUG_PATTERN.test(value)) {\n\t\t\t\t\t\terrors.push(`${prefix}.${end}: \"${value}\" is not a valid collection slug`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const label of [\"parentLabel\", \"childLabel\"] as const) {\n\t\t\t\t\tif (!relation[label]) errors.push(`${prefix}: ${label} is required`);\n\t\t\t\t}\n\t\t\t\tfor (const label of [\"parentLabelSingular\", \"childLabelSingular\"] as const) {\n\t\t\t\t\tconst value = relation[label];\n\t\t\t\t\tif (value !== undefined && typeof value !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.${label}: must be a string`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const limit of [\"maxChildrenPerParent\", \"maxParentsPerChild\"] as const) {\n\t\t\t\t\tconst value = relation[limit];\n\t\t\t\t\tif (value === undefined || value === null) continue;\n\t\t\t\t\tif (!Number.isInteger(value) || value < 1) {\n\t\t\t\t\t\terrors.push(`${prefix}.${limit}: must be a positive integer, or null for unlimited`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate taxonomies\n\tif (seed.taxonomies) {\n\t\tif (!Array.isArray(seed.taxonomies)) {\n\t\t\terrors.push(\"taxonomies must be an array\");\n\t\t} else {\n\t\t\tconst taxonomyNames = new Set<string>();\n\t\t\tconst taxonomiesById = new Map<string, SeedTaxonomy>();\n\t\t\tfor (const taxonomy of seed.taxonomies) {\n\t\t\t\tif (taxonomy.id) taxonomiesById.set(taxonomy.id, taxonomy);\n\t\t\t}\n\t\t\tconst structureDeclarations = new Map<string, SeedTaxonomy>();\n\n\t\t\tfor (let i = 0; i < seed.taxonomies.length; i++) {\n\t\t\t\tconst taxonomy = seed.taxonomies[i];\n\t\t\t\tconst prefix = `taxonomies[${i}]`;\n\n\t\t\t\tif (!taxonomy.name) {\n\t\t\t\t\terrors.push(`${prefix}: name is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Uniqueness is per (name, locale).\n\t\t\t\t\tconst locale = resolveConfiguredLocale(taxonomy.locale ?? defaultLocale);\n\t\t\t\t\tconst key = `${taxonomy.name}::${locale}`;\n\t\t\t\t\tif (taxonomyNames.has(key)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\ttaxonomy.locale\n\t\t\t\t\t\t\t\t? `${prefix}.name: duplicate taxonomy \"${taxonomy.name}\" in locale \"${taxonomy.locale}\"`\n\t\t\t\t\t\t\t\t: `${prefix}.name: duplicate taxonomy name \"${taxonomy.name}\"`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttaxonomyNames.add(key);\n\t\t\t\t}\n\n\t\t\t\tif (!taxonomy.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\n\t\t\t\tconst structureSource = findTaxonomyStructureSource(taxonomy, taxonomiesById);\n\n\t\t\t\t// A translation takes its taxonomy's structure, so it may omit both, but only\n\t\t\t\t// from an entry of the same taxonomy.\n\t\t\t\tif (\n\t\t\t\t\ttaxonomy.translationOf &&\n\t\t\t\t\t(taxonomy.hierarchical === undefined || taxonomy.collections === undefined)\n\t\t\t\t) {\n\t\t\t\t\tif (!structureSource) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.translationOf: the translationOf chain from \"${taxonomy.translationOf}\" loops, so hierarchical and collections are required`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (structureSource === taxonomy) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.translationOf: \"${taxonomy.translationOf}\" is not an entry of taxonomy \"${taxonomy.name}\", so hierarchical and collections are required`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (taxonomy.hierarchical === undefined && !taxonomy.translationOf) {\n\t\t\t\t\terrors.push(`${prefix}: hierarchical is required`);\n\t\t\t\t}\n\n\t\t\t\tif (taxonomy.collections === undefined) {\n\t\t\t\t\tif (!taxonomy.translationOf) errors.push(`${prefix}.collections: must be an array`);\n\t\t\t\t} else if (!Array.isArray(taxonomy.collections)) {\n\t\t\t\t\terrors.push(`${prefix}.collections: must be an array`);\n\t\t\t\t} else if (taxonomy.collections.length === 0 && !taxonomy.translationOf) {\n\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t`${prefix}.collections: taxonomy \"${taxonomy.name}\" is not assigned to any collections`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (structureSource && structureSource !== taxonomy) {\n\t\t\t\t\tif (declaresDifferentStructure(taxonomy, structureSource)) {\n\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t`${prefix}: hierarchical and collections come from taxonomies[${seed.taxonomies.indexOf(structureSource)}], so the values declared here are ignored`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if (structureSource && taxonomy.name) {\n\t\t\t\t\tconst declaring = structureDeclarations.get(taxonomy.name);\n\t\t\t\t\tif (!declaring) {\n\t\t\t\t\t\tstructureDeclarations.set(taxonomy.name, taxonomy);\n\t\t\t\t\t} else if (declaresDifferentStructure(taxonomy, declaring)) {\n\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t`${prefix}: hierarchical and collections differ from taxonomies[${seed.taxonomies.indexOf(declaring)}]; every locale of taxonomy \"${taxonomy.name}\" shares them, so only one entry's values apply`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst hierarchical = (structureSource ?? taxonomy).hierarchical;\n\n\t\t\t\t// Validate terms if present\n\t\t\t\tif (taxonomy.terms) {\n\t\t\t\t\tif (!Array.isArray(taxonomy.terms)) {\n\t\t\t\t\t\terrors.push(`${prefix}.terms: must be an array`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst termSlugs = new Set<string>();\n\n\t\t\t\t\t\tfor (let j = 0; j < taxonomy.terms.length; j++) {\n\t\t\t\t\t\t\tconst term = taxonomy.terms[j];\n\t\t\t\t\t\t\tconst termPrefix = `${prefix}.terms[${j}]`;\n\n\t\t\t\t\t\t\tif (!term.slug) {\n\t\t\t\t\t\t\t\terrors.push(`${termPrefix}: slug is required`);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Uniqueness is per (slug, locale) so the same slug can repeat\n\t\t\t\t\t\t\t\t// across locale variants of the def.\n\t\t\t\t\t\t\t\tconst locale = resolveConfiguredLocale(\n\t\t\t\t\t\t\t\t\tterm.locale ?? taxonomy.locale ?? defaultLocale,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst key = `${term.slug}::${locale}`;\n\t\t\t\t\t\t\t\tif (termSlugs.has(key)) {\n\t\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t\t`${termPrefix}.slug: duplicate term slug \"${term.slug}\" in taxonomy \"${taxonomy.name}\"`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttermSlugs.add(key);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!term.label) {\n\t\t\t\t\t\t\t\terrors.push(`${termPrefix}: label is required`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Check parent reference validity (for hierarchical taxonomies)\n\t\t\t\t\t\t\tif (term.parent && hierarchical) {\n\t\t\t\t\t\t\t\t// Parent will be validated in a second pass\n\t\t\t\t\t\t\t} else if (term.parent && !hierarchical) {\n\t\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t\t`${termPrefix}.parent: taxonomy \"${taxonomy.name}\" is not hierarchical, parent will be ignored`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Second pass: validate parent references (within the same locale).\n\t\t\t\t\t\tif (hierarchical && taxonomy.terms) {\n\t\t\t\t\t\t\tfor (let j = 0; j < taxonomy.terms.length; j++) {\n\t\t\t\t\t\t\t\tconst term = taxonomy.terms[j];\n\t\t\t\t\t\t\t\tconst termLocale = resolveConfiguredLocale(\n\t\t\t\t\t\t\t\t\tterm.locale ?? taxonomy.locale ?? defaultLocale,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (term.parent && !termSlugs.has(`${term.parent}::${termLocale}`)) {\n\t\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t\t`${prefix}.terms[${j}].parent: parent term \"${term.parent}\" not found in taxonomy`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Check for circular references\n\t\t\t\t\t\t\t\tif (term.parent === term.slug) {\n\t\t\t\t\t\t\t\t\terrors.push(`${prefix}.terms[${j}].parent: term cannot be its own parent`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate menus\n\tif (seed.menus) {\n\t\tif (!Array.isArray(seed.menus)) {\n\t\t\terrors.push(\"menus must be an array\");\n\t\t} else {\n\t\t\tconst menuNames = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.menus.length; i++) {\n\t\t\t\tconst menu = seed.menus[i];\n\t\t\t\tconst prefix = `menus[${i}]`;\n\n\t\t\t\tif (!menu.name) {\n\t\t\t\t\terrors.push(`${prefix}: name is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Uniqueness is per (name, locale) — siblings of a translation\n\t\t\t\t\t// group share name but differ in locale.\n\t\t\t\t\tconst locale = resolveConfiguredLocale(menu.locale ?? defaultLocale);\n\t\t\t\t\tconst key = `${menu.name}::${locale}`;\n\t\t\t\t\tif (menuNames.has(key)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\tmenu.locale\n\t\t\t\t\t\t\t\t? `${prefix}.name: duplicate menu \"${menu.name}\" in locale \"${menu.locale}\"`\n\t\t\t\t\t\t\t\t: `${prefix}.name: duplicate menu name \"${menu.name}\"`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tmenuNames.add(key);\n\t\t\t\t}\n\n\t\t\t\tif (!menu.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\n\t\t\t\tif (!Array.isArray(menu.items)) {\n\t\t\t\t\terrors.push(`${prefix}.items: must be an array`);\n\t\t\t\t} else {\n\t\t\t\t\tvalidateMenuItems(menu.items, prefix, errors, warnings);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate redirects\n\tif (seed.redirects) {\n\t\tif (!Array.isArray(seed.redirects)) {\n\t\t\terrors.push(\"redirects must be an array\");\n\t\t} else {\n\t\t\tconst redirectSources = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.redirects.length; i++) {\n\t\t\t\tconst redirect = seed.redirects[i];\n\t\t\t\tconst prefix = `redirects[${i}]`;\n\n\t\t\t\tif (!isRecord(redirect)) {\n\t\t\t\t\terrors.push(`${prefix}: must be an object`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst source = typeof redirect.source === \"string\" ? redirect.source : undefined;\n\t\t\t\tconst destination =\n\t\t\t\t\ttypeof redirect.destination === \"string\" ? redirect.destination : undefined;\n\n\t\t\t\tif (!source) {\n\t\t\t\t\terrors.push(`${prefix}: source is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!isValidRedirectPath(source)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.source: must be a path starting with / (no protocol-relative URLs, path traversal, or newlines)`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (redirectSources.has(source)) {\n\t\t\t\t\t\terrors.push(`${prefix}.source: duplicate redirect source \"${source}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tredirectSources.add(source);\n\t\t\t\t}\n\n\t\t\t\tif (!destination) {\n\t\t\t\t\terrors.push(`${prefix}: destination is required`);\n\t\t\t\t} else if (!isValidRedirectPath(destination) || !isSiteRelativeDestination(destination)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`${prefix}.destination: must be a path starting with / (no protocol-relative URLs, backslash prefixes, path traversal, or control characters)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (source && isPattern(source)) {\n\t\t\t\t\tconst patternError = validatePattern(source);\n\t\t\t\t\tif (patternError) {\n\t\t\t\t\t\terrors.push(`${prefix}.source: invalid pattern: ${patternError}`);\n\t\t\t\t\t} else if (destination) {\n\t\t\t\t\t\tconst destinationError = validateDestinationParams(source, destination);\n\t\t\t\t\t\tif (destinationError) {\n\t\t\t\t\t\t\terrors.push(`${prefix}.destination: ${destinationError}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (redirect.type !== undefined) {\n\t\t\t\t\tif (typeof redirect.type !== \"number\" || !REDIRECT_TYPES.has(redirect.type)) {\n\t\t\t\t\t\terrors.push(`${prefix}.type: must be 301, 302, 307, or 308`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (redirect.enabled !== undefined && typeof redirect.enabled !== \"boolean\") {\n\t\t\t\t\terrors.push(`${prefix}.enabled: must be a boolean`);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tredirect.groupName !== undefined &&\n\t\t\t\t\ttypeof redirect.groupName !== \"string\" &&\n\t\t\t\t\tredirect.groupName !== null\n\t\t\t\t) {\n\t\t\t\t\terrors.push(`${prefix}.groupName: must be a string or null`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate widget areas\n\tif (seed.widgetAreas) {\n\t\tif (!Array.isArray(seed.widgetAreas)) {\n\t\t\terrors.push(\"widgetAreas must be an array\");\n\t\t} else {\n\t\t\tconst areaNames = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.widgetAreas.length; i++) {\n\t\t\t\tconst area = seed.widgetAreas[i];\n\t\t\t\tconst prefix = `widgetAreas[${i}]`;\n\n\t\t\t\tif (!area.name) {\n\t\t\t\t\terrors.push(`${prefix}: name is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Check for duplicate area names\n\t\t\t\t\tif (areaNames.has(area.name)) {\n\t\t\t\t\t\terrors.push(`${prefix}.name: duplicate widget area name \"${area.name}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tareaNames.add(area.name);\n\t\t\t\t}\n\n\t\t\t\tif (!area.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\n\t\t\t\tif (!Array.isArray(area.widgets)) {\n\t\t\t\t\terrors.push(`${prefix}.widgets: must be an array`);\n\t\t\t\t} else {\n\t\t\t\t\tfor (let j = 0; j < area.widgets.length; j++) {\n\t\t\t\t\t\tconst widget = area.widgets[j];\n\t\t\t\t\t\tconst widgetPrefix = `${prefix}.widgets[${j}]`;\n\n\t\t\t\t\t\tif (!widget.type) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}: type is required`);\n\t\t\t\t\t\t} else if (![\"content\", \"menu\", \"component\"].includes(widget.type)) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}.type: must be \"content\", \"menu\", or \"component\"`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Type-specific validation\n\t\t\t\t\t\tif (widget.type === \"menu\" && !widget.menuName) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}: menuName is required for menu widgets`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (widget.type === \"component\" && !widget.componentId) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}: componentId is required for component widgets`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (\"settings\" in widget) {\n\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t`${widgetPrefix}.settings: not applied; widget options belong in \"props\"`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate sections\n\tif (seed.sections) {\n\t\tif (!Array.isArray(seed.sections)) {\n\t\t\terrors.push(\"sections must be an array\");\n\t\t} else {\n\t\t\tconst sectionSlugs = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.sections.length; i++) {\n\t\t\t\tconst section = seed.sections[i];\n\t\t\t\tconst prefix = `sections[${i}]`;\n\n\t\t\t\tif (!section.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!SLUG_PATTERN.test(section.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must contain only lowercase letters, numbers, and hyphens`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (sectionSlugs.has(section.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate section slug \"${section.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tsectionSlugs.add(section.slug);\n\t\t\t\t}\n\n\t\t\t\tif (!section.title) {\n\t\t\t\t\terrors.push(`${prefix}: title is required`);\n\t\t\t\t}\n\n\t\t\t\tif (!Array.isArray(section.content)) {\n\t\t\t\t\terrors.push(`${prefix}.content: must be an array`);\n\t\t\t\t}\n\n\t\t\t\t// Validate source\n\t\t\t\tif (section.source && ![\"theme\", \"user\", \"import\"].includes(section.source)) {\n\t\t\t\t\terrors.push(`${prefix}.source: must be \"theme\", \"user\", or \"import\"`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate bylines\n\tif (seed.bylines) {\n\t\tif (!Array.isArray(seed.bylines)) {\n\t\t\terrors.push(\"bylines must be an array\");\n\t\t} else {\n\t\t\tconst bylineIds = new Set<string>();\n\t\t\tconst bylineSlugs = new Set<string>();\n\t\t\tfor (let i = 0; i < seed.bylines.length; i++) {\n\t\t\t\tconst byline = seed.bylines[i];\n\t\t\t\tconst prefix = `bylines[${i}]`;\n\n\t\t\t\tif (!byline.id) {\n\t\t\t\t\terrors.push(`${prefix}: id is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (bylineIds.has(byline.id)) {\n\t\t\t\t\t\terrors.push(`${prefix}.id: duplicate byline id \"${byline.id}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tbylineIds.add(byline.id);\n\t\t\t\t}\n\n\t\t\t\tif (!byline.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!SLUG_PATTERN.test(byline.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must contain only lowercase letters, numbers, and hyphens`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (bylineSlugs.has(byline.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate byline slug \"${byline.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tbylineSlugs.add(byline.slug);\n\t\t\t\t}\n\n\t\t\t\tif (!byline.displayName) {\n\t\t\t\t\terrors.push(`${prefix}: displayName is required`);\n\t\t\t\t}\n\n\t\t\t\tif (byline.avatar !== undefined) {\n\t\t\t\t\tconst avatar: unknown = byline.avatar;\n\t\t\t\t\tif (!isRecord(avatar)) {\n\t\t\t\t\t\terrors.push(`${prefix}.avatar: must be an object`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// storageKey is used verbatim in a `where storage_key = ?` lookup,\n\t\t\t\t\t\t// so surrounding whitespace would silently never match a real key.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof avatar.storageKey !== \"string\" ||\n\t\t\t\t\t\t\tavatar.storageKey.length === 0 ||\n\t\t\t\t\t\t\tavatar.storageKey !== avatar.storageKey.trim()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${prefix}.avatar.storageKey: must be a non-empty string with no leading or trailing whitespace`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (const key of [\"alt\", \"filename\", \"mimeType\"] as const) {\n\t\t\t\t\t\t\tif (avatar[key] !== undefined && typeof avatar[key] !== \"string\") {\n\t\t\t\t\t\t\t\terrors.push(`${prefix}.avatar.${key}: must be a string`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// filename/mimeType are used verbatim, so reject blank or\n\t\t\t\t\t\t// whitespace-padded values (an empty filename would create a\n\t\t\t\t\t\t// media row with no basename; a padded mime type is invalid).\n\t\t\t\t\t\tfor (const key of [\"filename\", \"mimeType\"] as const) {\n\t\t\t\t\t\t\tconst v = avatar[key];\n\t\t\t\t\t\t\tif (typeof v === \"string\" && (v.length === 0 || v !== v.trim())) {\n\t\t\t\t\t\t\t\terrors.push(`${prefix}.avatar.${key}: must not be empty or whitespace-padded`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (const key of [\"width\", \"height\"] as const) {\n\t\t\t\t\t\t\tconst v = avatar[key];\n\t\t\t\t\t\t\tif (v !== undefined && (typeof v !== \"number\" || !Number.isFinite(v) || v < 0)) {\n\t\t\t\t\t\t\t\terrors.push(`${prefix}.avatar.${key}: must be a non-negative number`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate content\n\tif (seed.content) {\n\t\tif (typeof seed.content !== \"object\" || Array.isArray(seed.content)) {\n\t\t\terrors.push(\"content must be an object (collection -> entries)\");\n\t\t} else {\n\t\t\tfor (const [collectionSlug, entries] of Object.entries(seed.content)) {\n\t\t\t\tif (!Array.isArray(entries)) {\n\t\t\t\t\terrors.push(`content.${collectionSlug}: must be an array`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst collectionRoutable =\n\t\t\t\t\tseed.collections?.find((collection) => collection.slug === collectionSlug)?.routable !==\n\t\t\t\t\tfalse;\n\n\t\t\t\tconst entryIds = new Set<string>();\n\n\t\t\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\t\t\tconst entry = entries[i];\n\t\t\t\t\tconst prefix = `content.${collectionSlug}[${i}]`;\n\n\t\t\t\t\tif (!entry.id) {\n\t\t\t\t\t\terrors.push(`${prefix}: id is required`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Check for duplicate entry IDs\n\t\t\t\t\t\tif (entryIds.has(entry.id)) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${prefix}.id: duplicate entry id \"${entry.id}\" in collection \"${collectionSlug}\"`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tentryIds.add(entry.id);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst hasSlug = typeof entry.slug === \"string\" && entry.slug.trim().length > 0;\n\t\t\t\t\tif (entry.slug !== undefined && entry.slug !== null && typeof entry.slug !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: must be a string`);\n\t\t\t\t\t}\n\t\t\t\t\tif (collectionRoutable && !hasSlug) {\n\t\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!entry.data || typeof entry.data !== \"object\") {\n\t\t\t\t\t\terrors.push(`${prefix}: data must be an object`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Validate i18n fields\n\t\t\t\t\tif (entry.translationOf) {\n\t\t\t\t\t\tif (!entry.locale) {\n\t\t\t\t\t\t\terrors.push(`${prefix}: locale is required when translationOf is set`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Second pass: validate translationOf references within this collection\n\t\t\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\t\t\tconst entry = entries[i];\n\t\t\t\t\tif (entry.translationOf && !entryIds.has(entry.translationOf)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`content.${collectionSlug}[${i}].translationOf: references \"${entry.translationOf}\" which is not in this collection`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate cross-references (content refs in menus)\n\tif (seed.menus && seed.content) {\n\t\tconst allContentIds = new Set<string>();\n\t\tfor (const entries of Object.values(seed.content)) {\n\t\t\tif (Array.isArray(entries)) {\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tif (entry.id) {\n\t\t\t\t\t\tallContentIds.add(entry.id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check menu item refs\n\t\tfor (const menu of seed.menus) {\n\t\t\tif (Array.isArray(menu.items)) {\n\t\t\t\tvalidateMenuItemRefs(menu.items, allContentIds, warnings);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate byline refs in content\n\tif (seed.content) {\n\t\tconst seedBylineIds = new Set<string>((seed.bylines ?? []).map((byline) => byline.id));\n\t\tfor (const [collectionSlug, entries] of Object.entries(seed.content)) {\n\t\t\tif (!Array.isArray(entries)) continue;\n\t\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\t\tconst entry = entries[i];\n\t\t\t\tif (!entry.bylines) continue;\n\t\t\t\tif (!Array.isArray(entry.bylines)) {\n\t\t\t\t\terrors.push(`content.${collectionSlug}[${i}].bylines: must be an array`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (let j = 0; j < entry.bylines.length; j++) {\n\t\t\t\t\tconst credit = entry.bylines[j];\n\t\t\t\t\tconst prefix = `content.${collectionSlug}[${i}].bylines[${j}]`;\n\t\t\t\t\tif (!credit.byline) {\n\t\t\t\t\t\terrors.push(`${prefix}.byline: is required`);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!seedBylineIds.has(credit.byline)) {\n\t\t\t\t\t\terrors.push(`${prefix}.byline: references unknown byline \"${credit.byline}\"`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n/**\n * Validate menu items recursively\n */\nfunction validateMenuItems(\n\titems: unknown[],\n\tprefix: string,\n\terrors: string[],\n\twarnings: string[],\n): void {\n\tfor (let i = 0; i < items.length; i++) {\n\t\tconst raw = items[i];\n\t\tconst itemPrefix = `${prefix}.items[${i}]`;\n\n\t\tif (!isRecord(raw)) {\n\t\t\terrors.push(`${itemPrefix}: must be an object`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst item = raw;\n\n\t\tconst itemType = typeof item.type === \"string\" ? item.type : undefined;\n\n\t\tif (!itemType) {\n\t\t\terrors.push(`${itemPrefix}: type is required`);\n\t\t} else if (![\"custom\", \"page\", \"post\", \"taxonomy\", \"collection\"].includes(itemType)) {\n\t\t\terrors.push(\n\t\t\t\t`${itemPrefix}.type: must be \"custom\", \"page\", \"post\", \"taxonomy\", or \"collection\"`,\n\t\t\t);\n\t\t}\n\n\t\t// Type-specific validation\n\t\tif (itemType === \"custom\" && !item.url) {\n\t\t\terrors.push(`${itemPrefix}: url is required for custom menu items`);\n\t\t}\n\n\t\tif ((itemType === \"page\" || itemType === \"post\") && !item.ref) {\n\t\t\terrors.push(`${itemPrefix}: ref is required for page/post menu items`);\n\t\t}\n\n\t\t// Validate children recursively\n\t\tif (Array.isArray(item.children)) {\n\t\t\tvalidateMenuItems(item.children, itemPrefix, errors, warnings);\n\t\t}\n\t}\n}\n\n/**\n * Validate menu item references exist in content\n */\nfunction validateMenuItemRefs(\n\titems: SeedMenuItem[],\n\tcontentIds: Set<string>,\n\twarnings: string[],\n): void {\n\tfor (const item of items) {\n\t\tif ((item.type === \"page\" || item.type === \"post\") && item.ref) {\n\t\t\tif (!contentIds.has(item.ref)) {\n\t\t\t\twarnings.push(`Menu item references content \"${item.ref}\" which is not in the seed file`);\n\t\t\t}\n\t\t}\n\n\t\tif (item.children) {\n\t\t\tvalidateMenuItemRefs(item.children, contentIds, warnings);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBA,MAAM,gCAAgC;;AAEtC,MAAM,kBAAkB;AACxB,MAAM,eAAe;AACrB,MAAM,iBAAiB,IAAI,IAAI;CAAC;CAAK;CAAK;CAAK;CAAI,CAAC;AACpD,MAAM,eAAe;;AAGrB,SAAS,SAAS,OAAkD;AACnE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG5E,SAAS,oBAAoB,MAAuB;AACnD,KAAI,CAAC,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,KAAK,IAAI,aAAa,KAAK,KAAK,CAC5E,QAAO;AAGR,KAAI;AACH,SAAO,CAAC,mBAAmB,KAAK,CAAC,MAAM,IAAI,CAAC,SAAS,KAAK;SACnD;AACP,SAAO;;;;;;;;AAST,SAAgB,4BACf,UACA,gBACgB;CAChB,MAAM,0BAAU,IAAI,KAAQ;CAC5B,IAAI,UAAU;AACd,QAAO,CAAC,QAAQ,IAAI,QAAQ,EAAE;AAC7B,UAAQ,IAAI,QAAQ;EACpB,MAAM,SAAS,QAAQ,gBAAgB,eAAe,IAAI,QAAQ,cAAc,GAAG;AACnF,MAAI,CAAC,UAAU,OAAO,SAAS,QAAQ,KAAM,QAAO;AACpD,YAAU;;;;AAMZ,SAAS,2BAA2B,GAAiB,GAA0B;AAC9E,KACC,EAAE,iBAAiB,UACnB,EAAE,iBAAiB,UACnB,EAAE,iBAAiB,EAAE,aAErB,QAAO;AAER,KAAI,CAAC,MAAM,QAAQ,EAAE,YAAY,IAAI,CAAC,MAAM,QAAQ,EAAE,YAAY,CAAE,QAAO;CAC3E,MAAM,MAAM,IAAI,IAAI,EAAE,YAAY;CAClC,MAAM,QAAQ,IAAI,IAAI,EAAE,YAAY;AACpC,QAAO,IAAI,SAAS,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,eAAe,CAAC,MAAM,IAAI,WAAW,CAAC;;;;;;;;AASxF,SAAgB,aAAa,MAAiC;CAC7D,MAAM,SAAmB,EAAE;CAC3B,MAAM,WAAqB,EAAE;AAG7B,KAAI,CAAC,QAAQ,OAAO,SAAS,SAC5B,QAAO;EACN,OAAO;EACP,QAAQ,CAAC,yBAAyB;EAClC,UAAU,EAAE;EACZ;CAGF,MAAM,OAAO;CACb,MAAM,gBACL,eAAe,EAAE,kBAChB,OAAO,KAAK,kBAAkB,WAAW,KAAK,gBAAgB;AAGhE,KAAI,CAAC,KAAK,QACT,QAAO,KAAK,iCAAiC;UACnC,KAAK,YAAY,IAC3B,QAAO,KAAK,6BAA6B,OAAO,KAAK,QAAQ,GAAG;AAMjE,KAAI,KAAK,kBAAkB,QAC1B;MACC,OAAO,KAAK,kBAAkB,YAC9B,KAAK,cAAc,WAAW,KAC9B,KAAK,kBAAkB,KAAK,cAAc,MAAM,CAEhD,QAAO,KACN,mFACA;;AAIH,KAAI,KAAK,eAAe,OACvB,KAAI,CAAC,MAAM,QAAQ,KAAK,WAAW,CAClC,QAAO,KAAK,8BAA8B;MACpC;EACN,MAAM,wBAAQ,IAAI,KAAa;AAC/B,OAAK,MAAM,CAAC,OAAO,cAAc,KAAK,WAAW,SAAS,EAAE;GAC3D,MAAM,SAAS,cAAc,MAAM;AACnC,OAAI,CAAC,UAAU,QAAQ,CAAC,8BAA8B,KAAK,UAAU,KAAK,CACzE,QAAO,KAAK,GAAG,OAAO,wCAAwC;YACpD,MAAM,IAAI,UAAU,KAAK,CACnC,QAAO,KAAK,GAAG,OAAO,oCAAoC,UAAU,KAAK,GAAG;OAE5E,OAAM,IAAI,UAAU,KAAK;AAE1B,OAAI,CAAC,UAAU,MAAO,QAAO,KAAK,GAAG,OAAO,qBAAqB;AACjE,OAAI,CAAC,MAAM,QAAQ,UAAU,SAAS,IAAI,UAAU,SAAS,WAAW,GAAG;AAC1E,WAAO,KAAK,GAAG,OAAO,sCAAsC;AAC5D;;GAED,MAAM,UAAU,UAAU,SAAS,KAAK,YAAY,QAAQ,QAAQ;GACpE,MAAM,SAAS,CAAC,GAAG,QAAQ,CAAC,UAAU,MAAM,UAAU,OAAO,MAAM;AACnE,OACC,OAAO,OAAO,KACd,OAAO,MAAM,SAAS,iBAAiB,YAAY,eAAe,EAAE,CAEpE,QAAO,KAAK,GAAG,OAAO,sDAAsD;AAE7E,OAAI,CAAC,QAAQ,SAAS,UAAU,eAAe,CAC9C,QAAO,KAAK,GAAG,OAAO,+CAA+C;AAEtE,QAAK,MAAM,CAAC,cAAc,YAAY,UAAU,SAAS,SAAS,CACjE,KAAI;AACH,wBAAoB,QAAQ,OAAO;YAC3B,OAAO;AACf,WAAO,KACN,GAAG,OAAO,YAAY,aAAa,IAAI,iBAAiB,QAAQ,MAAM,UAAU,mBAChF;;;;AAQN,KAAI,KAAK,YACR,KAAI,CAAC,MAAM,QAAQ,KAAK,YAAY,CACnC,QAAO,KAAK,+BAA+B;MACrC;EACN,MAAM,kCAAkB,IAAI,KAAa;AAEzC,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;GACjD,MAAM,aAAa,KAAK,YAAY;GACpC,MAAM,SAAS,eAAe,EAAE;AAEhC,OAAI,CAAC,WAAW,KACf,QAAO,KAAK,GAAG,OAAO,oBAAoB;QACpC;AAEN,QAAI,CAAC,8BAA8B,KAAK,WAAW,KAAK,CACvD,QAAO,KACN,GAAG,OAAO,8FACV;AAIF,QAAI,0BAA0B,SAAS,WAAW,KAAK,CACtD,QAAO,KAAK,GAAG,OAAO,0BAA0B,WAAW,KAAK,eAAe;AAIhF,QAAI,gBAAgB,IAAI,WAAW,KAAK,CACvC,QAAO,KAAK,GAAG,OAAO,oCAAoC,WAAW,KAAK,GAAG;AAE9E,oBAAgB,IAAI,WAAW,KAAK;;AAGrC,OAAI,CAAC,WAAW,MACf,QAAO,KAAK,GAAG,OAAO,qBAAqB;AAE5C,OAAI,WAAW,gBAAgB,UAAa,OAAO,WAAW,gBAAgB,UAC7E,QAAO,KAAK,GAAG,OAAO,iCAAiC;AAExD,OAAI,WAAW,aAAa,UAAa,OAAO,WAAW,aAAa,UACvE,QAAO,KAAK,GAAG,OAAO,8BAA8B;AAErD,OAAI,WAAW,eAAe,QAC7B;QAAI,OAAO,WAAW,eAAe,SACpC,QAAO,KAAK,GAAG,OAAO,+BAA+B;aAC3C,WAAW,WACrB,KAAI;AACH,uBAAkB,WAAW,WAAW;aAChC,OAAO;AACf,YAAO,KACN,GAAG,OAAO,eAAe,iBAAiB,QAAQ,MAAM,UAAU,wBAClE;;;AAIJ,OAAI,WAAW,UAAU,QACxB;QAAI,OAAO,WAAW,UAAU,SAC/B,QAAO,KAAK,GAAG,OAAO,0BAA0B;aACtC,WAAW,MAAM,MAAM,CAAC,SAAS,4BAC3C,QAAO,KACN,GAAG,OAAO,0BAA0B,4BAA4B,aAChE;;AAGH,OAAI,WAAW,SAAS,QACvB;QAAI,OAAO,WAAW,SAAS,SAC9B,QAAO,KAAK,GAAG,OAAO,yBAAyB;aACrC,WAAW,KAAK,MAAM,CAAC,SAAS,2BAC1C,QAAO,KAAK,GAAG,OAAO,yBAAyB,2BAA2B,aAAa;;GAIzF,MAAM,qBAAqB,IAAI,IAC9B,MAAM,QAAQ,WAAW,OAAO,GAC7B,WAAW,OAAO,SAAS,UAC3B,SAAS,MAAM,IAAI,OAAO,MAAM,SAAS,WAAW,CAAC,MAAM,KAAK,GAAG,EAAE,CACrE,GACA,EAAE,CACL;AAED,OAAI,WAAW,UAAU,QAAW;AACnC,QAAI,CAAC,SAAS,WAAW,MAAM,CAC9B,QAAO,KAAK,GAAG,OAAO,2BAA2B;aACvC,WAAW,MAAM,gBAAgB,OAC3C,KAAI,CAAC,MAAM,QAAQ,WAAW,MAAM,YAAY,CAC/C,QAAO,KAAK,GAAG,OAAO,sCAAsC;SACtD;AACN,SAAI,WAAW,MAAM,YAAY,SAAS,4BACzC,QAAO,KACN,GAAG,OAAO,2CAA2C,4BAA4B,QACjF;AAEF,UAAK,IAAI,IAAI,GAAG,IAAI,WAAW,MAAM,YAAY,QAAQ,KAAK;MAC7D,MAAM,OAAO,WAAW,MAAM,YAAY;AAC1C,UAAI,OAAO,SAAS,YAAY,CAAC,8BAA8B,KAAK,KAAK,CACxE,QAAO,KAAK,GAAG,OAAO,qBAAqB,EAAE,+BAA+B;eAClE,CAAC,mBAAmB,IAAI,KAAK,CACvC,QAAO,KACN,GAAG,OAAO,qBAAqB,EAAE,+BAA+B,KAAK,GACrE;;;AAKL,QACC,SAAS,WAAW,MAAM,IAC1B,WAAW,MAAM,gBAAgB,UACjC,OAAO,WAAW,MAAM,gBAAgB,UAExC,QAAO,KAAK,GAAG,OAAO,uCAAuC;;AAK/D,OAAI,CAAC,MAAM,QAAQ,WAAW,OAAO,CACpC,QAAO,KAAK,GAAG,OAAO,2BAA2B;QAC3C;IACN,MAAM,6BAAa,IAAI,KAAa;AAEpC,SAAK,IAAI,IAAI,GAAG,IAAI,WAAW,OAAO,QAAQ,KAAK;KAClD,MAAM,QAAQ,WAAW,OAAO;KAChC,MAAM,cAAc,GAAG,OAAO,UAAU,EAAE;AAE1C,SAAI,CAAC,MAAM,KACV,QAAO,KAAK,GAAG,YAAY,oBAAoB;UACzC;AAEN,UAAI,CAAC,8BAA8B,KAAK,MAAM,KAAK,CAClD,QAAO,KACN,GAAG,YAAY,8FACf;AAIF,UAAI,qBAAqB,SAAS,MAAM,KAAK,CAC5C,QAAO,KAAK,GAAG,YAAY,qBAAqB,MAAM,KAAK,eAAe;AAI3E,UAAI,WAAW,IAAI,MAAM,KAAK,CAC7B,QAAO,KACN,GAAG,YAAY,+BAA+B,MAAM,KAAK,mBAAmB,WAAW,KAAK,GAC5F;AAEF,iBAAW,IAAI,MAAM,KAAK;;AAG3B,SAAI,CAAC,MAAM,MACV,QAAO,KAAK,GAAG,YAAY,qBAAqB;AAGjD,SAAI,MAAM,YAAY,UAAa,OAAO,MAAM,YAAY,UAC3D,QAAO,KAAK,GAAG,YAAY,6BAA6B;AAGzD,SAAI,MAAM,iBAAiB,UAAa,OAAO,MAAM,iBAAiB,UACrE,QAAO,KAAK,GAAG,YAAY,kCAAkC;AAG9D,SAAI,CAAC,MAAM,KACV,QAAO,KAAK,GAAG,YAAY,oBAAoB;cACrC,CAAE,YAAkC,SAAS,MAAM,KAAK,CAClE,QAAO,KAAK,GAAG,YAAY,iCAAiC,MAAM,KAAK,GAAG;cAChE,MAAM,YAAY,QAAQ,CAAC,qBAAqB,MAAM,KAAK,CACrE,QAAO,KAAK,GAAG,YAAY,kBAAkB,MAAM,KAAK,qBAAqB;cAE7E,MAAM,YAAY,QAClB,MAAM,SAAS,eACf,OAAO,MAAM,YAAY,qBAAqB,SAK9C,QAAO,KACN,GAAG,YAAY,+EACf;AAGF,SAAI,MAAM,SAAS,YAAY;MAC9B,MAAM,YAAY,MAAM,YAAY;AACpC,UAAI,YAAY,MACf,UAAS,KACR,GAAG,YAAY,gGACf;eACS,CAAC,MAAM,QAAQ,UAAU,IAAI,UAAU,WAAW,EAC5D,UAAS,KACR,GAAG,YAAY,yGACf;;;;;;AAUR,KAAI,KAAK,UACR,KAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,CACjC,QAAO,KAAK,6BAA6B;MACnC;EACN,MAAM,gCAAgB,IAAI,KAAa;AAEvC,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,UAAU,QAAQ,KAAK;GAC/C,MAAM,WAAW,KAAK,UAAU;GAChC,MAAM,SAAS,aAAa,EAAE;AAC9B,OAAI,CAAC,SAAU;AAEf,OAAI,CAAC,SAAS,KACb,QAAO,KAAK,GAAG,OAAO,oBAAoB;QACpC;AACN,QAAI,CAAC,8BAA8B,KAAK,SAAS,KAAK,CACrD,QAAO,KACN,GAAG,OAAO,8FACV;AAEF,QAAI,SAAS,KAAK,SAAS,gBAC1B,QAAO,KAAK,GAAG,OAAO,iBAAiB,gBAAgB,sBAAsB;AAE9E,QAAI,cAAc,IAAI,SAAS,KAAK,CACnC,QAAO,KAAK,GAAG,OAAO,kCAAkC,SAAS,KAAK,GAAG;AAE1E,kBAAc,IAAI,SAAS,KAAK;;AAGjC,QAAK,MAAM,OAAO,CAAC,oBAAoB,kBAAkB,EAAW;IACnE,MAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,MACJ,QAAO,KAAK,GAAG,OAAO,IAAI,IAAI,cAAc;aAClC,CAAC,8BAA8B,KAAK,MAAM,CACpD,QAAO,KAAK,GAAG,OAAO,GAAG,IAAI,KAAK,MAAM,kCAAkC;;AAI5E,QAAK,MAAM,SAAS,CAAC,eAAe,aAAa,CAChD,KAAI,CAAC,SAAS,OAAQ,QAAO,KAAK,GAAG,OAAO,IAAI,MAAM,cAAc;AAErE,QAAK,MAAM,SAAS,CAAC,uBAAuB,qBAAqB,EAAW;IAC3E,MAAM,QAAQ,SAAS;AACvB,QAAI,UAAU,UAAa,OAAO,UAAU,SAC3C,QAAO,KAAK,GAAG,OAAO,GAAG,MAAM,oBAAoB;;AAIrD,QAAK,MAAM,SAAS,CAAC,wBAAwB,qBAAqB,EAAW;IAC5E,MAAM,QAAQ,SAAS;AACvB,QAAI,UAAU,UAAa,UAAU,KAAM;AAC3C,QAAI,CAAC,OAAO,UAAU,MAAM,IAAI,QAAQ,EACvC,QAAO,KAAK,GAAG,OAAO,GAAG,MAAM,qDAAqD;;;;AAQzF,KAAI,KAAK,WACR,KAAI,CAAC,MAAM,QAAQ,KAAK,WAAW,CAClC,QAAO,KAAK,8BAA8B;MACpC;EACN,MAAM,gCAAgB,IAAI,KAAa;EACvC,MAAM,iCAAiB,IAAI,KAA2B;AACtD,OAAK,MAAM,YAAY,KAAK,WAC3B,KAAI,SAAS,GAAI,gBAAe,IAAI,SAAS,IAAI,SAAS;EAE3D,MAAM,wCAAwB,IAAI,KAA2B;AAE7D,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;GAChD,MAAM,WAAW,KAAK,WAAW;GACjC,MAAM,SAAS,cAAc,EAAE;AAE/B,OAAI,CAAC,SAAS,KACb,QAAO,KAAK,GAAG,OAAO,oBAAoB;QACpC;IAEN,MAAM,SAAS,wBAAwB,SAAS,UAAU,cAAc;IACxE,MAAM,MAAM,GAAG,SAAS,KAAK,IAAI;AACjC,QAAI,cAAc,IAAI,IAAI,CACzB,QAAO,KACN,SAAS,SACN,GAAG,OAAO,6BAA6B,SAAS,KAAK,eAAe,SAAS,OAAO,KACpF,GAAG,OAAO,kCAAkC,SAAS,KAAK,GAC7D;AAEF,kBAAc,IAAI,IAAI;;AAGvB,OAAI,CAAC,SAAS,MACb,QAAO,KAAK,GAAG,OAAO,qBAAqB;GAG5C,MAAM,kBAAkB,4BAA4B,UAAU,eAAe;AAI7E,OACC,SAAS,kBACR,SAAS,iBAAiB,UAAa,SAAS,gBAAgB,SAEjE;QAAI,CAAC,gBACJ,QAAO,KACN,GAAG,OAAO,gDAAgD,SAAS,cAAc,uDACjF;aACS,oBAAoB,SAC9B,QAAO,KACN,GAAG,OAAO,mBAAmB,SAAS,cAAc,iCAAiC,SAAS,KAAK,iDACnG;;AAIH,OAAI,SAAS,iBAAiB,UAAa,CAAC,SAAS,cACpD,QAAO,KAAK,GAAG,OAAO,4BAA4B;AAGnD,OAAI,SAAS,gBAAgB,QAC5B;QAAI,CAAC,SAAS,cAAe,QAAO,KAAK,GAAG,OAAO,gCAAgC;cACzE,CAAC,MAAM,QAAQ,SAAS,YAAY,CAC9C,QAAO,KAAK,GAAG,OAAO,gCAAgC;YAC5C,SAAS,YAAY,WAAW,KAAK,CAAC,SAAS,cACzD,UAAS,KACR,GAAG,OAAO,0BAA0B,SAAS,KAAK,sCAClD;AAGF,OAAI,mBAAmB,oBAAoB,UAC1C;QAAI,2BAA2B,UAAU,gBAAgB,CACxD,UAAS,KACR,GAAG,OAAO,sDAAsD,KAAK,WAAW,QAAQ,gBAAgB,CAAC,4CACzG;cAEQ,mBAAmB,SAAS,MAAM;IAC5C,MAAM,YAAY,sBAAsB,IAAI,SAAS,KAAK;AAC1D,QAAI,CAAC,UACJ,uBAAsB,IAAI,SAAS,MAAM,SAAS;aACxC,2BAA2B,UAAU,UAAU,CACzD,UAAS,KACR,GAAG,OAAO,wDAAwD,KAAK,WAAW,QAAQ,UAAU,CAAC,+BAA+B,SAAS,KAAK,iDAClJ;;GAIH,MAAM,gBAAgB,mBAAmB,UAAU;AAGnD,OAAI,SAAS,MACZ,KAAI,CAAC,MAAM,QAAQ,SAAS,MAAM,CACjC,QAAO,KAAK,GAAG,OAAO,0BAA0B;QAC1C;IACN,MAAM,4BAAY,IAAI,KAAa;AAEnC,SAAK,IAAI,IAAI,GAAG,IAAI,SAAS,MAAM,QAAQ,KAAK;KAC/C,MAAM,OAAO,SAAS,MAAM;KAC5B,MAAM,aAAa,GAAG,OAAO,SAAS,EAAE;AAExC,SAAI,CAAC,KAAK,KACT,QAAO,KAAK,GAAG,WAAW,oBAAoB;UACxC;MAGN,MAAM,SAAS,wBACd,KAAK,UAAU,SAAS,UAAU,cAClC;MACD,MAAM,MAAM,GAAG,KAAK,KAAK,IAAI;AAC7B,UAAI,UAAU,IAAI,IAAI,CACrB,QAAO,KACN,GAAG,WAAW,8BAA8B,KAAK,KAAK,iBAAiB,SAAS,KAAK,GACrF;AAEF,gBAAU,IAAI,IAAI;;AAGnB,SAAI,CAAC,KAAK,MACT,QAAO,KAAK,GAAG,WAAW,qBAAqB;AAIhD,SAAI,KAAK,UAAU,cAAc,YAEtB,KAAK,UAAU,CAAC,aAC1B,UAAS,KACR,GAAG,WAAW,qBAAqB,SAAS,KAAK,+CACjD;;AAKH,QAAI,gBAAgB,SAAS,MAC5B,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,MAAM,QAAQ,KAAK;KAC/C,MAAM,OAAO,SAAS,MAAM;KAC5B,MAAM,aAAa,wBAClB,KAAK,UAAU,SAAS,UAAU,cAClC;AACD,SAAI,KAAK,UAAU,CAAC,UAAU,IAAI,GAAG,KAAK,OAAO,IAAI,aAAa,CACjE,QAAO,KACN,GAAG,OAAO,SAAS,EAAE,yBAAyB,KAAK,OAAO,yBAC1D;AAIF,SAAI,KAAK,WAAW,KAAK,KACxB,QAAO,KAAK,GAAG,OAAO,SAAS,EAAE,yCAAyC;;;;;AAWlF,KAAI,KAAK,MACR,KAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,CAC7B,QAAO,KAAK,yBAAyB;MAC/B;EACN,MAAM,4BAAY,IAAI,KAAa;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;GAC3C,MAAM,OAAO,KAAK,MAAM;GACxB,MAAM,SAAS,SAAS,EAAE;AAE1B,OAAI,CAAC,KAAK,KACT,QAAO,KAAK,GAAG,OAAO,oBAAoB;QACpC;IAGN,MAAM,SAAS,wBAAwB,KAAK,UAAU,cAAc;IACpE,MAAM,MAAM,GAAG,KAAK,KAAK,IAAI;AAC7B,QAAI,UAAU,IAAI,IAAI,CACrB,QAAO,KACN,KAAK,SACF,GAAG,OAAO,yBAAyB,KAAK,KAAK,eAAe,KAAK,OAAO,KACxE,GAAG,OAAO,8BAA8B,KAAK,KAAK,GACrD;AAEF,cAAU,IAAI,IAAI;;AAGnB,OAAI,CAAC,KAAK,MACT,QAAO,KAAK,GAAG,OAAO,qBAAqB;AAG5C,OAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,CAC7B,QAAO,KAAK,GAAG,OAAO,0BAA0B;OAEhD,mBAAkB,KAAK,OAAO,QAAQ,QAAQ,SAAS;;;AAO3D,KAAI,KAAK,UACR,KAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,CACjC,QAAO,KAAK,6BAA6B;MACnC;EACN,MAAM,kCAAkB,IAAI,KAAa;AAEzC,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,UAAU,QAAQ,KAAK;GAC/C,MAAM,WAAW,KAAK,UAAU;GAChC,MAAM,SAAS,aAAa,EAAE;AAE9B,OAAI,CAAC,SAAS,SAAS,EAAE;AACxB,WAAO,KAAK,GAAG,OAAO,qBAAqB;AAC3C;;GAGD,MAAM,SAAS,OAAO,SAAS,WAAW,WAAW,SAAS,SAAS;GACvE,MAAM,cACL,OAAO,SAAS,gBAAgB,WAAW,SAAS,cAAc;AAEnE,OAAI,CAAC,OACJ,QAAO,KAAK,GAAG,OAAO,sBAAsB;QACtC;AACN,QAAI,CAAC,oBAAoB,OAAO,CAC/B,QAAO,KACN,GAAG,OAAO,kGACV;AAGF,QAAI,gBAAgB,IAAI,OAAO,CAC9B,QAAO,KAAK,GAAG,OAAO,sCAAsC,OAAO,GAAG;AAEvE,oBAAgB,IAAI,OAAO;;AAG5B,OAAI,CAAC,YACJ,QAAO,KAAK,GAAG,OAAO,2BAA2B;YACvC,CAAC,oBAAoB,YAAY,IAAI,CAAC,0BAA0B,YAAY,CACtF,QAAO,KACN,GAAG,OAAO,qIACV;AAGF,OAAI,UAAU,UAAU,OAAO,EAAE;IAChC,MAAM,eAAe,gBAAgB,OAAO;AAC5C,QAAI,aACH,QAAO,KAAK,GAAG,OAAO,4BAA4B,eAAe;aACvD,aAAa;KACvB,MAAM,mBAAmB,0BAA0B,QAAQ,YAAY;AACvE,SAAI,iBACH,QAAO,KAAK,GAAG,OAAO,gBAAgB,mBAAmB;;;AAK5D,OAAI,SAAS,SAAS,QACrB;QAAI,OAAO,SAAS,SAAS,YAAY,CAAC,eAAe,IAAI,SAAS,KAAK,CAC1E,QAAO,KAAK,GAAG,OAAO,sCAAsC;;AAI9D,OAAI,SAAS,YAAY,UAAa,OAAO,SAAS,YAAY,UACjE,QAAO,KAAK,GAAG,OAAO,6BAA6B;AAGpD,OACC,SAAS,cAAc,UACvB,OAAO,SAAS,cAAc,YAC9B,SAAS,cAAc,KAEvB,QAAO,KAAK,GAAG,OAAO,sCAAsC;;;AAOhE,KAAI,KAAK,YACR,KAAI,CAAC,MAAM,QAAQ,KAAK,YAAY,CACnC,QAAO,KAAK,+BAA+B;MACrC;EACN,MAAM,4BAAY,IAAI,KAAa;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;GACjD,MAAM,OAAO,KAAK,YAAY;GAC9B,MAAM,SAAS,eAAe,EAAE;AAEhC,OAAI,CAAC,KAAK,KACT,QAAO,KAAK,GAAG,OAAO,oBAAoB;QACpC;AAEN,QAAI,UAAU,IAAI,KAAK,KAAK,CAC3B,QAAO,KAAK,GAAG,OAAO,qCAAqC,KAAK,KAAK,GAAG;AAEzE,cAAU,IAAI,KAAK,KAAK;;AAGzB,OAAI,CAAC,KAAK,MACT,QAAO,KAAK,GAAG,OAAO,qBAAqB;AAG5C,OAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,CAC/B,QAAO,KAAK,GAAG,OAAO,4BAA4B;OAElD,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;IAC7C,MAAM,SAAS,KAAK,QAAQ;IAC5B,MAAM,eAAe,GAAG,OAAO,WAAW,EAAE;AAE5C,QAAI,CAAC,OAAO,KACX,QAAO,KAAK,GAAG,aAAa,oBAAoB;aACtC,CAAC;KAAC;KAAW;KAAQ;KAAY,CAAC,SAAS,OAAO,KAAK,CACjE,QAAO,KAAK,GAAG,aAAa,kDAAkD;AAI/E,QAAI,OAAO,SAAS,UAAU,CAAC,OAAO,SACrC,QAAO,KAAK,GAAG,aAAa,yCAAyC;AAGtE,QAAI,OAAO,SAAS,eAAe,CAAC,OAAO,YAC1C,QAAO,KAAK,GAAG,aAAa,iDAAiD;AAG9E,QAAI,cAAc,OACjB,UAAS,KACR,GAAG,aAAa,0DAChB;;;;AASP,KAAI,KAAK,SACR,KAAI,CAAC,MAAM,QAAQ,KAAK,SAAS,CAChC,QAAO,KAAK,4BAA4B;MAClC;EACN,MAAM,+BAAe,IAAI,KAAa;AAEtC,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;GAC9C,MAAM,UAAU,KAAK,SAAS;GAC9B,MAAM,SAAS,YAAY,EAAE;AAE7B,OAAI,CAAC,QAAQ,KACZ,QAAO,KAAK,GAAG,OAAO,oBAAoB;QACpC;AACN,QAAI,CAAC,aAAa,KAAK,QAAQ,KAAK,CACnC,QAAO,KACN,GAAG,OAAO,kEACV;AAEF,QAAI,aAAa,IAAI,QAAQ,KAAK,CACjC,QAAO,KAAK,GAAG,OAAO,iCAAiC,QAAQ,KAAK,GAAG;AAExE,iBAAa,IAAI,QAAQ,KAAK;;AAG/B,OAAI,CAAC,QAAQ,MACZ,QAAO,KAAK,GAAG,OAAO,qBAAqB;AAG5C,OAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,CAClC,QAAO,KAAK,GAAG,OAAO,4BAA4B;AAInD,OAAI,QAAQ,UAAU,CAAC;IAAC;IAAS;IAAQ;IAAS,CAAC,SAAS,QAAQ,OAAO,CAC1E,QAAO,KAAK,GAAG,OAAO,+CAA+C;;;AAOzE,KAAI,KAAK,QACR,KAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,CAC/B,QAAO,KAAK,2BAA2B;MACjC;EACN,MAAM,4BAAY,IAAI,KAAa;EACnC,MAAM,8BAAc,IAAI,KAAa;AACrC,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;GAC7C,MAAM,SAAS,KAAK,QAAQ;GAC5B,MAAM,SAAS,WAAW,EAAE;AAE5B,OAAI,CAAC,OAAO,GACX,QAAO,KAAK,GAAG,OAAO,kBAAkB;QAClC;AACN,QAAI,UAAU,IAAI,OAAO,GAAG,CAC3B,QAAO,KAAK,GAAG,OAAO,4BAA4B,OAAO,GAAG,GAAG;AAEhE,cAAU,IAAI,OAAO,GAAG;;AAGzB,OAAI,CAAC,OAAO,KACX,QAAO,KAAK,GAAG,OAAO,oBAAoB;QACpC;AACN,QAAI,CAAC,aAAa,KAAK,OAAO,KAAK,CAClC,QAAO,KACN,GAAG,OAAO,kEACV;AAEF,QAAI,YAAY,IAAI,OAAO,KAAK,CAC/B,QAAO,KAAK,GAAG,OAAO,gCAAgC,OAAO,KAAK,GAAG;AAEtE,gBAAY,IAAI,OAAO,KAAK;;AAG7B,OAAI,CAAC,OAAO,YACX,QAAO,KAAK,GAAG,OAAO,2BAA2B;AAGlD,OAAI,OAAO,WAAW,QAAW;IAChC,MAAM,SAAkB,OAAO;AAC/B,QAAI,CAAC,SAAS,OAAO,CACpB,QAAO,KAAK,GAAG,OAAO,4BAA4B;SAC5C;AAGN,SACC,OAAO,OAAO,eAAe,YAC7B,OAAO,WAAW,WAAW,KAC7B,OAAO,eAAe,OAAO,WAAW,MAAM,CAE9C,QAAO,KACN,GAAG,OAAO,uFACV;AAEF,UAAK,MAAM,OAAO;MAAC;MAAO;MAAY;MAAW,CAChD,KAAI,OAAO,SAAS,UAAa,OAAO,OAAO,SAAS,SACvD,QAAO,KAAK,GAAG,OAAO,UAAU,IAAI,oBAAoB;AAM1D,UAAK,MAAM,OAAO,CAAC,YAAY,WAAW,EAAW;MACpD,MAAM,IAAI,OAAO;AACjB,UAAI,OAAO,MAAM,aAAa,EAAE,WAAW,KAAK,MAAM,EAAE,MAAM,EAC7D,QAAO,KAAK,GAAG,OAAO,UAAU,IAAI,0CAA0C;;AAGhF,UAAK,MAAM,OAAO,CAAC,SAAS,SAAS,EAAW;MAC/C,MAAM,IAAI,OAAO;AACjB,UAAI,MAAM,WAAc,OAAO,MAAM,YAAY,CAAC,OAAO,SAAS,EAAE,IAAI,IAAI,GAC3E,QAAO,KAAK,GAAG,OAAO,UAAU,IAAI,iCAAiC;;;;;;AAU5E,KAAI,KAAK,QACR,KAAI,OAAO,KAAK,YAAY,YAAY,MAAM,QAAQ,KAAK,QAAQ,CAClE,QAAO,KAAK,oDAAoD;KAEhE,MAAK,MAAM,CAAC,gBAAgB,YAAY,OAAO,QAAQ,KAAK,QAAQ,EAAE;AACrE,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAE;AAC5B,UAAO,KAAK,WAAW,eAAe,oBAAoB;AAC1D;;EAED,MAAM,qBACL,KAAK,aAAa,MAAM,eAAe,WAAW,SAAS,eAAe,EAAE,aAC5E;EAED,MAAM,2BAAW,IAAI,KAAa;AAElC,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;GACxC,MAAM,QAAQ,QAAQ;GACtB,MAAM,SAAS,WAAW,eAAe,GAAG,EAAE;AAE9C,OAAI,CAAC,MAAM,GACV,QAAO,KAAK,GAAG,OAAO,kBAAkB;QAClC;AAEN,QAAI,SAAS,IAAI,MAAM,GAAG,CACzB,QAAO,KACN,GAAG,OAAO,2BAA2B,MAAM,GAAG,mBAAmB,eAAe,GAChF;AAEF,aAAS,IAAI,MAAM,GAAG;;GAGvB,MAAM,UAAU,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,MAAM,CAAC,SAAS;AAC7E,OAAI,MAAM,SAAS,UAAa,MAAM,SAAS,QAAQ,OAAO,MAAM,SAAS,SAC5E,QAAO,KAAK,GAAG,OAAO,yBAAyB;AAEhD,OAAI,sBAAsB,CAAC,QAC1B,QAAO,KAAK,GAAG,OAAO,oBAAoB;AAG3C,OAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,SAAS,SACxC,QAAO,KAAK,GAAG,OAAO,0BAA0B;AAIjD,OAAI,MAAM,eACT;QAAI,CAAC,MAAM,OACV,QAAO,KAAK,GAAG,OAAO,gDAAgD;;;AAMzE,OAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;GACxC,MAAM,QAAQ,QAAQ;AACtB,OAAI,MAAM,iBAAiB,CAAC,SAAS,IAAI,MAAM,cAAc,CAC5D,QAAO,KACN,WAAW,eAAe,GAAG,EAAE,+BAA+B,MAAM,cAAc,mCAClF;;;AAQN,KAAI,KAAK,SAAS,KAAK,SAAS;EAC/B,MAAM,gCAAgB,IAAI,KAAa;AACvC,OAAK,MAAM,WAAW,OAAO,OAAO,KAAK,QAAQ,CAChD,KAAI,MAAM,QAAQ,QAAQ,EACzB;QAAK,MAAM,SAAS,QACnB,KAAI,MAAM,GACT,eAAc,IAAI,MAAM,GAAG;;AAO/B,OAAK,MAAM,QAAQ,KAAK,MACvB,KAAI,MAAM,QAAQ,KAAK,MAAM,CAC5B,sBAAqB,KAAK,OAAO,eAAe,SAAS;;AAM5D,KAAI,KAAK,SAAS;EACjB,MAAM,gBAAgB,IAAI,KAAa,KAAK,WAAW,EAAE,EAAE,KAAK,WAAW,OAAO,GAAG,CAAC;AACtF,OAAK,MAAM,CAAC,gBAAgB,YAAY,OAAO,QAAQ,KAAK,QAAQ,EAAE;AACrE,OAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE;AAC7B,QAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;IACxC,MAAM,QAAQ,QAAQ;AACtB,QAAI,CAAC,MAAM,QAAS;AACpB,QAAI,CAAC,MAAM,QAAQ,MAAM,QAAQ,EAAE;AAClC,YAAO,KAAK,WAAW,eAAe,GAAG,EAAE,6BAA6B;AACxE;;AAED,SAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,QAAQ,KAAK;KAC9C,MAAM,SAAS,MAAM,QAAQ;KAC7B,MAAM,SAAS,WAAW,eAAe,GAAG,EAAE,YAAY,EAAE;AAC5D,SAAI,CAAC,OAAO,QAAQ;AACnB,aAAO,KAAK,GAAG,OAAO,sBAAsB;AAC5C;;AAED,SAAI,CAAC,cAAc,IAAI,OAAO,OAAO,CACpC,QAAO,KAAK,GAAG,OAAO,sCAAsC,OAAO,OAAO,GAAG;;;;;AAOlF,QAAO;EACN,OAAO,OAAO,WAAW;EACzB;EACA;EACA;;;;;AAMF,SAAS,kBACR,OACA,QACA,QACA,UACO;AACP,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACtC,MAAM,MAAM,MAAM;EAClB,MAAM,aAAa,GAAG,OAAO,SAAS,EAAE;AAExC,MAAI,CAAC,SAAS,IAAI,EAAE;AACnB,UAAO,KAAK,GAAG,WAAW,qBAAqB;AAC/C;;EAGD,MAAM,OAAO;EAEb,MAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AAE7D,MAAI,CAAC,SACJ,QAAO,KAAK,GAAG,WAAW,oBAAoB;WACpC,CAAC;GAAC;GAAU;GAAQ;GAAQ;GAAY;GAAa,CAAC,SAAS,SAAS,CAClF,QAAO,KACN,GAAG,WAAW,sEACd;AAIF,MAAI,aAAa,YAAY,CAAC,KAAK,IAClC,QAAO,KAAK,GAAG,WAAW,yCAAyC;AAGpE,OAAK,aAAa,UAAU,aAAa,WAAW,CAAC,KAAK,IACzD,QAAO,KAAK,GAAG,WAAW,4CAA4C;AAIvE,MAAI,MAAM,QAAQ,KAAK,SAAS,CAC/B,mBAAkB,KAAK,UAAU,YAAY,QAAQ,SAAS;;;;;;AAQjE,SAAS,qBACR,OACA,YACA,UACO;AACP,MAAK,MAAM,QAAQ,OAAO;AACzB,OAAK,KAAK,SAAS,UAAU,KAAK,SAAS,WAAW,KAAK,KAC1D;OAAI,CAAC,WAAW,IAAI,KAAK,IAAI,CAC5B,UAAS,KAAK,iCAAiC,KAAK,IAAI,iCAAiC;;AAI3F,MAAI,KAAK,SACR,sBAAqB,KAAK,UAAU,YAAY,SAAS"}
1
+ {"version":3,"file":"validate-Dz-TIOFB.mjs","names":[],"sources":["../src/seed/validate.ts"],"sourcesContent":["/**\n * Seed file validation\n *\n * Validates a seed file structure before applying it.\n */\n\nimport { getI18nConfig, resolveConfiguredLocale } from \"../i18n/config.js\";\nimport { isSiteRelativeDestination } from \"../redirects/destination.js\";\nimport { isPattern, validateDestinationParams, validatePattern } from \"../redirects/patterns.js\";\nimport { validateBlockFields } from \"../schema/block-type-contract.js\";\nimport {\n\tFIELD_TYPES,\n\tisIndexableFieldType,\n\tMAX_COLLECTION_GROUP_LENGTH,\n\tMAX_COLLECTION_ICON_LENGTH,\n\tMAX_COLLECTION_LIST_COLUMNS,\n\tRESERVED_COLLECTION_SLUGS,\n\tRESERVED_FIELD_SLUGS,\n} from \"../schema/types.js\";\nimport { compileUrlPattern } from \"../schema/url-pattern.js\";\nimport type { SeedFile, SeedMenuItem, SeedTaxonomy, ValidationResult } from \"./types.js\";\n\nconst COLLECTION_FIELD_SLUG_PATTERN = /^[a-z][a-z0-9_]*$/;\n/** Matches `SchemaRegistry.validateSlug`, which collection and field slugs go through. */\nconst MAX_SLUG_LENGTH = 63;\nconst SLUG_PATTERN = /^[a-z0-9-]+$/;\nconst REDIRECT_TYPES = new Set([301, 302, 307, 308]);\nconst CRLF_PATTERN = /[\\r\\n]/;\n\n/** Type guard for Record<string, unknown> */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isValidRedirectPath(path: string): boolean {\n\tif (!path.startsWith(\"/\") || path.startsWith(\"//\") || CRLF_PATTERN.test(path)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\treturn !decodeURIComponent(path).split(\"/\").includes(\"..\");\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * The entry that declares `taxonomy`'s `hierarchical` and `collections`: the last\n * entry of its `translationOf` chain within the taxonomy's name, or undefined when\n * the chain loops.\n */\nexport function findTaxonomyStructureSource<T extends Pick<SeedTaxonomy, \"name\" | \"translationOf\">>(\n\ttaxonomy: T,\n\ttaxonomiesById: ReadonlyMap<string, T>,\n): T | undefined {\n\tconst visited = new Set<T>();\n\tlet current = taxonomy;\n\twhile (!visited.has(current)) {\n\t\tvisited.add(current);\n\t\tconst source = current.translationOf ? taxonomiesById.get(current.translationOf) : undefined;\n\t\tif (!source || source.name !== current.name) return current;\n\t\tcurrent = source;\n\t}\n\treturn undefined;\n}\n\n/** Whether `a` and `b` disagree on `hierarchical` or `collections`, comparing only fields both declare. */\nfunction declaresDifferentStructure(a: SeedTaxonomy, b: SeedTaxonomy): boolean {\n\tif (\n\t\ta.hierarchical !== undefined &&\n\t\tb.hierarchical !== undefined &&\n\t\ta.hierarchical !== b.hierarchical\n\t) {\n\t\treturn true;\n\t}\n\tif (!Array.isArray(a.collections) || !Array.isArray(b.collections)) return false;\n\tconst own = new Set(a.collections);\n\tconst other = new Set(b.collections);\n\treturn own.size !== other.size || [...own].some((collection) => !other.has(collection));\n}\n\n/**\n * Validate a seed file\n *\n * @param data - Unknown data to validate as a seed file\n * @returns Validation result with errors and warnings\n */\nexport function validateSeed(data: unknown): ValidationResult {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\n\t// Basic type check\n\tif (!data || typeof data !== \"object\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terrors: [\"Seed must be an object\"],\n\t\t\twarnings: [],\n\t\t};\n\t}\n\n\tconst seed = data as Partial<SeedFile>;\n\tconst defaultLocale =\n\t\tgetI18nConfig()?.defaultLocale ??\n\t\t(typeof seed.defaultLocale === \"string\" ? seed.defaultLocale : \"en\");\n\n\t// Required fields\n\tif (!seed.version) {\n\t\terrors.push(\"Seed must have a version field\");\n\t} else if (seed.version !== \"1\") {\n\t\terrors.push(`Unsupported seed version: ${String(seed.version)}`);\n\t}\n\n\t// defaultLocale backfills the locale of rows that omit one, so a blank or\n\t// whitespace-padded value would silently write empty/invalid locales to the DB.\n\t// Exported seeds never hit this, but it's part of the public schema now.\n\tif (seed.defaultLocale !== undefined) {\n\t\tif (\n\t\t\ttypeof seed.defaultLocale !== \"string\" ||\n\t\t\tseed.defaultLocale.length === 0 ||\n\t\t\tseed.defaultLocale !== seed.defaultLocale.trim()\n\t\t) {\n\t\t\terrors.push(\n\t\t\t\t\"defaultLocale: must be a non-empty string with no leading or trailing whitespace\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (seed.blockTypes !== undefined) {\n\t\tif (!Array.isArray(seed.blockTypes)) {\n\t\t\terrors.push(\"blockTypes must be an array\");\n\t\t} else {\n\t\t\tconst slugs = new Set<string>();\n\t\t\tfor (const [index, blockType] of seed.blockTypes.entries()) {\n\t\t\t\tconst prefix = `blockTypes[${index}]`;\n\t\t\t\tif (!blockType.slug || !COLLECTION_FIELD_SLUG_PATTERN.test(blockType.slug)) {\n\t\t\t\t\terrors.push(`${prefix}.slug: must be a valid block type slug`);\n\t\t\t\t} else if (slugs.has(blockType.slug)) {\n\t\t\t\t\terrors.push(`${prefix}.slug: duplicate block type slug \"${blockType.slug}\"`);\n\t\t\t\t} else {\n\t\t\t\t\tslugs.add(blockType.slug);\n\t\t\t\t}\n\t\t\t\tif (!blockType.label) errors.push(`${prefix}.label: is required`);\n\t\t\t\tif (!Array.isArray(blockType.versions) || blockType.versions.length === 0) {\n\t\t\t\t\terrors.push(`${prefix}.versions: must be a non-empty array`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst numbers = blockType.versions.map((version) => version.version);\n\t\t\t\tconst sorted = [...numbers].toSorted((left, right) => left - right);\n\t\t\t\tif (\n\t\t\t\t\tsorted[0] !== 1 ||\n\t\t\t\t\tsorted.some((version, versionIndex) => version !== versionIndex + 1)\n\t\t\t\t) {\n\t\t\t\t\terrors.push(`${prefix}.versions: numbers must be contiguous and start at 1`);\n\t\t\t\t}\n\t\t\t\tif (!numbers.includes(blockType.currentVersion)) {\n\t\t\t\t\terrors.push(`${prefix}.currentVersion: must name a declared version`);\n\t\t\t\t}\n\t\t\t\tfor (const [versionIndex, version] of blockType.versions.entries()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvalidateBlockFields(version.fields);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.versions[${versionIndex}].${error instanceof Error ? error.message : \"invalid fields\"}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate collections\n\tif (seed.collections) {\n\t\tif (!Array.isArray(seed.collections)) {\n\t\t\terrors.push(\"collections must be an array\");\n\t\t} else {\n\t\t\tconst collectionSlugs = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.collections.length; i++) {\n\t\t\t\tconst collection = seed.collections[i];\n\t\t\t\tconst prefix = `collections[${i}]`;\n\n\t\t\t\tif (!collection.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Check for valid slug format\n\t\t\t\t\tif (!COLLECTION_FIELD_SLUG_PATTERN.test(collection.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must start with a letter and contain only lowercase letters, numbers, and underscores`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Reserved slugs pass the format check but are rejected by the schema registry on apply\n\t\t\t\t\tif (RESERVED_COLLECTION_SLUGS.includes(collection.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: collection slug \"${collection.slug}\" is reserved`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for duplicate slugs\n\t\t\t\t\tif (collectionSlugs.has(collection.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate collection slug \"${collection.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tcollectionSlugs.add(collection.slug);\n\t\t\t\t}\n\n\t\t\t\tif (!collection.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\t\t\t\tif (collection.editLocking !== undefined && typeof collection.editLocking !== \"boolean\") {\n\t\t\t\t\terrors.push(`${prefix}.editLocking: must be a boolean`);\n\t\t\t\t}\n\t\t\t\tif (collection.routable !== undefined && typeof collection.routable !== \"boolean\") {\n\t\t\t\t\terrors.push(`${prefix}.routable: must be a boolean`);\n\t\t\t\t}\n\t\t\t\tif (collection.urlPattern !== undefined) {\n\t\t\t\t\tif (typeof collection.urlPattern !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.urlPattern: must be a string`);\n\t\t\t\t\t} else if (collection.urlPattern) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcompileUrlPattern(collection.urlPattern);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${prefix}.urlPattern: ${error instanceof Error ? error.message : \"invalid URL pattern\"}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (collection.group !== undefined) {\n\t\t\t\t\tif (typeof collection.group !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.group: must be a string`);\n\t\t\t\t\t} else if (collection.group.trim().length > MAX_COLLECTION_GROUP_LENGTH) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.group: must be at most ${MAX_COLLECTION_GROUP_LENGTH} characters`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (collection.icon !== undefined) {\n\t\t\t\t\tif (typeof collection.icon !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.icon: must be a string`);\n\t\t\t\t\t} else if (collection.icon.trim().length > MAX_COLLECTION_ICON_LENGTH) {\n\t\t\t\t\t\terrors.push(`${prefix}.icon: must be at most ${MAX_COLLECTION_ICON_LENGTH} characters`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst declaredFieldSlugs = new Set(\n\t\t\t\t\tArray.isArray(collection.fields)\n\t\t\t\t\t\t? collection.fields.flatMap((field) =>\n\t\t\t\t\t\t\t\tisRecord(field) && typeof field.slug === \"string\" ? [field.slug] : [],\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: [],\n\t\t\t\t);\n\n\t\t\t\tif (collection.admin !== undefined) {\n\t\t\t\t\tif (!isRecord(collection.admin)) {\n\t\t\t\t\t\terrors.push(`${prefix}.admin: must be an object`);\n\t\t\t\t\t} else if (collection.admin.listColumns !== undefined) {\n\t\t\t\t\t\tif (!Array.isArray(collection.admin.listColumns)) {\n\t\t\t\t\t\t\terrors.push(`${prefix}.admin.listColumns: must be an array`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (collection.admin.listColumns.length > MAX_COLLECTION_LIST_COLUMNS) {\n\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t`${prefix}.admin.listColumns: must contain at most ${MAX_COLLECTION_LIST_COLUMNS} items`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (let j = 0; j < collection.admin.listColumns.length; j++) {\n\t\t\t\t\t\t\t\tconst slug = collection.admin.listColumns[j];\n\t\t\t\t\t\t\t\tif (typeof slug !== \"string\" || !COLLECTION_FIELD_SLUG_PATTERN.test(slug)) {\n\t\t\t\t\t\t\t\t\terrors.push(`${prefix}.admin.listColumns[${j}]: must be a valid field slug`);\n\t\t\t\t\t\t\t\t} else if (!declaredFieldSlugs.has(slug)) {\n\t\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t\t`${prefix}.admin.listColumns[${j}]: references unknown field \"${slug}\"`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tisRecord(collection.admin) &&\n\t\t\t\t\t\tcollection.admin.quickCreate !== undefined &&\n\t\t\t\t\t\ttypeof collection.admin.quickCreate !== \"boolean\"\n\t\t\t\t\t) {\n\t\t\t\t\t\terrors.push(`${prefix}.admin.quickCreate: must be a boolean`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Validate fields\n\t\t\t\tif (!Array.isArray(collection.fields)) {\n\t\t\t\t\terrors.push(`${prefix}.fields: must be an array`);\n\t\t\t\t} else {\n\t\t\t\t\tconst fieldSlugs = new Set<string>();\n\n\t\t\t\t\tfor (let j = 0; j < collection.fields.length; j++) {\n\t\t\t\t\t\tconst field = collection.fields[j];\n\t\t\t\t\t\tconst fieldPrefix = `${prefix}.fields[${j}]`;\n\n\t\t\t\t\t\tif (!field.slug) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}: slug is required`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Check for valid slug format\n\t\t\t\t\t\t\tif (!COLLECTION_FIELD_SLUG_PATTERN.test(field.slug)) {\n\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.slug: must start with a letter and contain only lowercase letters, numbers, and underscores`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Reserved slugs pass the format check but are rejected by the schema registry on apply\n\t\t\t\t\t\t\tif (RESERVED_FIELD_SLUGS.includes(field.slug)) {\n\t\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.slug: field slug \"${field.slug}\" is reserved`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Check for duplicate field slugs\n\t\t\t\t\t\t\tif (fieldSlugs.has(field.slug)) {\n\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.slug: duplicate field slug \"${field.slug}\" in collection \"${collection.slug}\"`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfieldSlugs.add(field.slug);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!field.label) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}: label is required`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (field.indexed !== undefined && typeof field.indexed !== \"boolean\") {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.indexed: must be a boolean`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (field.translatable !== undefined && typeof field.translatable !== \"boolean\") {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.translatable: must be a boolean`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!field.type) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}: type is required`);\n\t\t\t\t\t\t} else if (!(FIELD_TYPES as readonly string[]).includes(field.type)) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.type: unsupported field type \"${field.type}\"`);\n\t\t\t\t\t\t} else if (field.indexed === true && !isIndexableFieldType(field.type)) {\n\t\t\t\t\t\t\terrors.push(`${fieldPrefix}.indexed: type \"${field.type}\" cannot be indexed`);\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tfield.indexed === true &&\n\t\t\t\t\t\t\tfield.type === \"reference\" &&\n\t\t\t\t\t\t\ttypeof field.validation?.targetCollection === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// A targetCollection makes this field storage-less on apply: its\n\t\t\t\t\t\t\t// selection becomes relation edges, leaving no column to index.\n\t\t\t\t\t\t\t// Without one it stays a plain entry-id column, which can be.\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${fieldPrefix}.indexed: a reference field with a targetCollection stores no column to index`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (field.type === \"repeater\") {\n\t\t\t\t\t\t\tconst subFields = field.validation?.subFields;\n\t\t\t\t\t\t\tif (\"fields\" in field) {\n\t\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.fields: repeater sub-fields must be defined in validation.subFields; these fields are ignored`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else if (!Array.isArray(subFields) || subFields.length === 0) {\n\t\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t\t`${fieldPrefix}.validation.subFields: repeater needs a non-empty array of sub-fields, so its rows have nothing to edit`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate relations\n\tif (seed.relations) {\n\t\tif (!Array.isArray(seed.relations)) {\n\t\t\terrors.push(\"relations must be an array\");\n\t\t} else {\n\t\t\tconst relationSlugs = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.relations.length; i++) {\n\t\t\t\tconst relation = seed.relations[i];\n\t\t\t\tconst prefix = `relations[${i}]`;\n\t\t\t\tif (!relation) continue;\n\n\t\t\t\tif (!relation.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!COLLECTION_FIELD_SLUG_PATTERN.test(relation.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must start with a letter and contain only lowercase letters, numbers, and underscores`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (relation.slug.length > MAX_SLUG_LENGTH) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: must be ${MAX_SLUG_LENGTH} characters or fewer`);\n\t\t\t\t\t}\n\t\t\t\t\tif (relationSlugs.has(relation.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate relation slug \"${relation.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\trelationSlugs.add(relation.slug);\n\t\t\t\t}\n\n\t\t\t\tfor (const end of [\"parentCollection\", \"childCollection\"] as const) {\n\t\t\t\t\tconst value = relation[end];\n\t\t\t\t\tif (!value) {\n\t\t\t\t\t\terrors.push(`${prefix}: ${end} is required`);\n\t\t\t\t\t} else if (!COLLECTION_FIELD_SLUG_PATTERN.test(value)) {\n\t\t\t\t\t\terrors.push(`${prefix}.${end}: \"${value}\" is not a valid collection slug`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const label of [\"parentLabel\", \"childLabel\"] as const) {\n\t\t\t\t\tif (!relation[label]) errors.push(`${prefix}: ${label} is required`);\n\t\t\t\t}\n\t\t\t\tfor (const label of [\"parentLabelSingular\", \"childLabelSingular\"] as const) {\n\t\t\t\t\tconst value = relation[label];\n\t\t\t\t\tif (value !== undefined && typeof value !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.${label}: must be a string`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const limit of [\"maxChildrenPerParent\", \"maxParentsPerChild\"] as const) {\n\t\t\t\t\tconst value = relation[limit];\n\t\t\t\t\tif (value === undefined || value === null) continue;\n\t\t\t\t\tif (!Number.isInteger(value) || value < 1) {\n\t\t\t\t\t\terrors.push(`${prefix}.${limit}: must be a positive integer, or null for unlimited`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate taxonomies\n\tif (seed.taxonomies) {\n\t\tif (!Array.isArray(seed.taxonomies)) {\n\t\t\terrors.push(\"taxonomies must be an array\");\n\t\t} else {\n\t\t\tconst taxonomyNames = new Set<string>();\n\t\t\tconst taxonomiesById = new Map<string, SeedTaxonomy>();\n\t\t\tfor (const taxonomy of seed.taxonomies) {\n\t\t\t\tif (taxonomy.id) taxonomiesById.set(taxonomy.id, taxonomy);\n\t\t\t}\n\t\t\tconst structureDeclarations = new Map<string, SeedTaxonomy>();\n\n\t\t\tfor (let i = 0; i < seed.taxonomies.length; i++) {\n\t\t\t\tconst taxonomy = seed.taxonomies[i];\n\t\t\t\tconst prefix = `taxonomies[${i}]`;\n\n\t\t\t\tif (!taxonomy.name) {\n\t\t\t\t\terrors.push(`${prefix}: name is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Uniqueness is per (name, locale).\n\t\t\t\t\tconst locale = resolveConfiguredLocale(taxonomy.locale ?? defaultLocale);\n\t\t\t\t\tconst key = `${taxonomy.name}::${locale}`;\n\t\t\t\t\tif (taxonomyNames.has(key)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\ttaxonomy.locale\n\t\t\t\t\t\t\t\t? `${prefix}.name: duplicate taxonomy \"${taxonomy.name}\" in locale \"${taxonomy.locale}\"`\n\t\t\t\t\t\t\t\t: `${prefix}.name: duplicate taxonomy name \"${taxonomy.name}\"`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttaxonomyNames.add(key);\n\t\t\t\t}\n\n\t\t\t\tif (!taxonomy.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\n\t\t\t\tconst structureSource = findTaxonomyStructureSource(taxonomy, taxonomiesById);\n\n\t\t\t\t// A translation takes its taxonomy's structure, so it may omit both, but only\n\t\t\t\t// from an entry of the same taxonomy.\n\t\t\t\tif (\n\t\t\t\t\ttaxonomy.translationOf &&\n\t\t\t\t\t(taxonomy.hierarchical === undefined || taxonomy.collections === undefined)\n\t\t\t\t) {\n\t\t\t\t\tif (!structureSource) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.translationOf: the translationOf chain from \"${taxonomy.translationOf}\" loops, so hierarchical and collections are required`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (structureSource === taxonomy) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.translationOf: \"${taxonomy.translationOf}\" is not an entry of taxonomy \"${taxonomy.name}\", so hierarchical and collections are required`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (taxonomy.hierarchical === undefined && !taxonomy.translationOf) {\n\t\t\t\t\terrors.push(`${prefix}: hierarchical is required`);\n\t\t\t\t}\n\n\t\t\t\tif (taxonomy.collections === undefined) {\n\t\t\t\t\tif (!taxonomy.translationOf) errors.push(`${prefix}.collections: must be an array`);\n\t\t\t\t} else if (!Array.isArray(taxonomy.collections)) {\n\t\t\t\t\terrors.push(`${prefix}.collections: must be an array`);\n\t\t\t\t} else if (taxonomy.collections.length === 0 && !taxonomy.translationOf) {\n\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t`${prefix}.collections: taxonomy \"${taxonomy.name}\" is not assigned to any collections`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (structureSource && structureSource !== taxonomy) {\n\t\t\t\t\tif (declaresDifferentStructure(taxonomy, structureSource)) {\n\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t`${prefix}: hierarchical and collections come from taxonomies[${seed.taxonomies.indexOf(structureSource)}], so the values declared here are ignored`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if (structureSource && taxonomy.name) {\n\t\t\t\t\tconst declaring = structureDeclarations.get(taxonomy.name);\n\t\t\t\t\tif (!declaring) {\n\t\t\t\t\t\tstructureDeclarations.set(taxonomy.name, taxonomy);\n\t\t\t\t\t} else if (declaresDifferentStructure(taxonomy, declaring)) {\n\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t`${prefix}: hierarchical and collections differ from taxonomies[${seed.taxonomies.indexOf(declaring)}]; every locale of taxonomy \"${taxonomy.name}\" shares them, so only one entry's values apply`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst hierarchical = (structureSource ?? taxonomy).hierarchical;\n\n\t\t\t\t// Validate terms if present\n\t\t\t\tif (taxonomy.terms) {\n\t\t\t\t\tif (!Array.isArray(taxonomy.terms)) {\n\t\t\t\t\t\terrors.push(`${prefix}.terms: must be an array`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst termSlugs = new Set<string>();\n\n\t\t\t\t\t\tfor (let j = 0; j < taxonomy.terms.length; j++) {\n\t\t\t\t\t\t\tconst term = taxonomy.terms[j];\n\t\t\t\t\t\t\tconst termPrefix = `${prefix}.terms[${j}]`;\n\n\t\t\t\t\t\t\tif (!term.slug) {\n\t\t\t\t\t\t\t\terrors.push(`${termPrefix}: slug is required`);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Uniqueness is per (slug, locale) so the same slug can repeat\n\t\t\t\t\t\t\t\t// across locale variants of the def.\n\t\t\t\t\t\t\t\tconst locale = resolveConfiguredLocale(\n\t\t\t\t\t\t\t\t\tterm.locale ?? taxonomy.locale ?? defaultLocale,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst key = `${term.slug}::${locale}`;\n\t\t\t\t\t\t\t\tif (termSlugs.has(key)) {\n\t\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t\t`${termPrefix}.slug: duplicate term slug \"${term.slug}\" in taxonomy \"${taxonomy.name}\"`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttermSlugs.add(key);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!term.label) {\n\t\t\t\t\t\t\t\terrors.push(`${termPrefix}: label is required`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Check parent reference validity (for hierarchical taxonomies)\n\t\t\t\t\t\t\tif (term.parent && hierarchical) {\n\t\t\t\t\t\t\t\t// Parent will be validated in a second pass\n\t\t\t\t\t\t\t} else if (term.parent && !hierarchical) {\n\t\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t\t`${termPrefix}.parent: taxonomy \"${taxonomy.name}\" is not hierarchical, parent will be ignored`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Second pass: validate parent references (within the same locale).\n\t\t\t\t\t\tif (hierarchical && taxonomy.terms) {\n\t\t\t\t\t\t\tfor (let j = 0; j < taxonomy.terms.length; j++) {\n\t\t\t\t\t\t\t\tconst term = taxonomy.terms[j];\n\t\t\t\t\t\t\t\tconst termLocale = resolveConfiguredLocale(\n\t\t\t\t\t\t\t\t\tterm.locale ?? taxonomy.locale ?? defaultLocale,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (term.parent && !termSlugs.has(`${term.parent}::${termLocale}`)) {\n\t\t\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t\t\t`${prefix}.terms[${j}].parent: parent term \"${term.parent}\" not found in taxonomy`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Check for circular references\n\t\t\t\t\t\t\t\tif (term.parent === term.slug) {\n\t\t\t\t\t\t\t\t\terrors.push(`${prefix}.terms[${j}].parent: term cannot be its own parent`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate menus\n\tif (seed.menus) {\n\t\tif (!Array.isArray(seed.menus)) {\n\t\t\terrors.push(\"menus must be an array\");\n\t\t} else {\n\t\t\tconst menuNames = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.menus.length; i++) {\n\t\t\t\tconst menu = seed.menus[i];\n\t\t\t\tconst prefix = `menus[${i}]`;\n\n\t\t\t\tif (!menu.name) {\n\t\t\t\t\terrors.push(`${prefix}: name is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Uniqueness is per (name, locale) — siblings of a translation\n\t\t\t\t\t// group share name but differ in locale.\n\t\t\t\t\tconst locale = resolveConfiguredLocale(menu.locale ?? defaultLocale);\n\t\t\t\t\tconst key = `${menu.name}::${locale}`;\n\t\t\t\t\tif (menuNames.has(key)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\tmenu.locale\n\t\t\t\t\t\t\t\t? `${prefix}.name: duplicate menu \"${menu.name}\" in locale \"${menu.locale}\"`\n\t\t\t\t\t\t\t\t: `${prefix}.name: duplicate menu name \"${menu.name}\"`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tmenuNames.add(key);\n\t\t\t\t}\n\n\t\t\t\tif (!menu.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\n\t\t\t\tif (!Array.isArray(menu.items)) {\n\t\t\t\t\terrors.push(`${prefix}.items: must be an array`);\n\t\t\t\t} else {\n\t\t\t\t\tvalidateMenuItems(menu.items, prefix, errors, warnings);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate redirects\n\tif (seed.redirects) {\n\t\tif (!Array.isArray(seed.redirects)) {\n\t\t\terrors.push(\"redirects must be an array\");\n\t\t} else {\n\t\t\tconst redirectSources = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.redirects.length; i++) {\n\t\t\t\tconst redirect = seed.redirects[i];\n\t\t\t\tconst prefix = `redirects[${i}]`;\n\n\t\t\t\tif (!isRecord(redirect)) {\n\t\t\t\t\terrors.push(`${prefix}: must be an object`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst source = typeof redirect.source === \"string\" ? redirect.source : undefined;\n\t\t\t\tconst destination =\n\t\t\t\t\ttypeof redirect.destination === \"string\" ? redirect.destination : undefined;\n\n\t\t\t\tif (!source) {\n\t\t\t\t\terrors.push(`${prefix}: source is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!isValidRedirectPath(source)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.source: must be a path starting with / (no protocol-relative URLs, path traversal, or newlines)`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (redirectSources.has(source)) {\n\t\t\t\t\t\terrors.push(`${prefix}.source: duplicate redirect source \"${source}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tredirectSources.add(source);\n\t\t\t\t}\n\n\t\t\t\tif (!destination) {\n\t\t\t\t\terrors.push(`${prefix}: destination is required`);\n\t\t\t\t} else if (!isValidRedirectPath(destination) || !isSiteRelativeDestination(destination)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`${prefix}.destination: must be a path starting with / (no protocol-relative URLs, backslash prefixes, path traversal, or control characters)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (source && isPattern(source)) {\n\t\t\t\t\tconst patternError = validatePattern(source);\n\t\t\t\t\tif (patternError) {\n\t\t\t\t\t\terrors.push(`${prefix}.source: invalid pattern: ${patternError}`);\n\t\t\t\t\t} else if (destination) {\n\t\t\t\t\t\tconst destinationError = validateDestinationParams(source, destination);\n\t\t\t\t\t\tif (destinationError) {\n\t\t\t\t\t\t\terrors.push(`${prefix}.destination: ${destinationError}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (redirect.type !== undefined) {\n\t\t\t\t\tif (typeof redirect.type !== \"number\" || !REDIRECT_TYPES.has(redirect.type)) {\n\t\t\t\t\t\terrors.push(`${prefix}.type: must be 301, 302, 307, or 308`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (redirect.enabled !== undefined && typeof redirect.enabled !== \"boolean\") {\n\t\t\t\t\terrors.push(`${prefix}.enabled: must be a boolean`);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tredirect.groupName !== undefined &&\n\t\t\t\t\ttypeof redirect.groupName !== \"string\" &&\n\t\t\t\t\tredirect.groupName !== null\n\t\t\t\t) {\n\t\t\t\t\terrors.push(`${prefix}.groupName: must be a string or null`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate widget areas\n\tif (seed.widgetAreas) {\n\t\tif (!Array.isArray(seed.widgetAreas)) {\n\t\t\terrors.push(\"widgetAreas must be an array\");\n\t\t} else {\n\t\t\tconst areaNames = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.widgetAreas.length; i++) {\n\t\t\t\tconst area = seed.widgetAreas[i];\n\t\t\t\tconst prefix = `widgetAreas[${i}]`;\n\n\t\t\t\tif (!area.name) {\n\t\t\t\t\terrors.push(`${prefix}: name is required`);\n\t\t\t\t} else {\n\t\t\t\t\t// Check for duplicate area names\n\t\t\t\t\tif (areaNames.has(area.name)) {\n\t\t\t\t\t\terrors.push(`${prefix}.name: duplicate widget area name \"${area.name}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tareaNames.add(area.name);\n\t\t\t\t}\n\n\t\t\t\tif (!area.label) {\n\t\t\t\t\terrors.push(`${prefix}: label is required`);\n\t\t\t\t}\n\n\t\t\t\tif (!Array.isArray(area.widgets)) {\n\t\t\t\t\terrors.push(`${prefix}.widgets: must be an array`);\n\t\t\t\t} else {\n\t\t\t\t\tfor (let j = 0; j < area.widgets.length; j++) {\n\t\t\t\t\t\tconst widget = area.widgets[j];\n\t\t\t\t\t\tconst widgetPrefix = `${prefix}.widgets[${j}]`;\n\n\t\t\t\t\t\tif (!widget.type) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}: type is required`);\n\t\t\t\t\t\t} else if (![\"content\", \"menu\", \"component\"].includes(widget.type)) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}.type: must be \"content\", \"menu\", or \"component\"`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Type-specific validation\n\t\t\t\t\t\tif (widget.type === \"menu\" && !widget.menuName) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}: menuName is required for menu widgets`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (widget.type === \"component\" && !widget.componentId) {\n\t\t\t\t\t\t\terrors.push(`${widgetPrefix}: componentId is required for component widgets`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (\"settings\" in widget) {\n\t\t\t\t\t\t\twarnings.push(\n\t\t\t\t\t\t\t\t`${widgetPrefix}.settings: not applied; widget options belong in \"props\"`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate sections\n\tif (seed.sections) {\n\t\tif (!Array.isArray(seed.sections)) {\n\t\t\terrors.push(\"sections must be an array\");\n\t\t} else {\n\t\t\tconst sectionSlugs = new Set<string>();\n\n\t\t\tfor (let i = 0; i < seed.sections.length; i++) {\n\t\t\t\tconst section = seed.sections[i];\n\t\t\t\tconst prefix = `sections[${i}]`;\n\n\t\t\t\tif (!section.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!SLUG_PATTERN.test(section.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must contain only lowercase letters, numbers, and hyphens`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (sectionSlugs.has(section.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate section slug \"${section.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tsectionSlugs.add(section.slug);\n\t\t\t\t}\n\n\t\t\t\tif (!section.title) {\n\t\t\t\t\terrors.push(`${prefix}: title is required`);\n\t\t\t\t}\n\n\t\t\t\tif (!Array.isArray(section.content)) {\n\t\t\t\t\terrors.push(`${prefix}.content: must be an array`);\n\t\t\t\t}\n\n\t\t\t\t// Validate source\n\t\t\t\tif (section.source && ![\"theme\", \"user\", \"import\"].includes(section.source)) {\n\t\t\t\t\terrors.push(`${prefix}.source: must be \"theme\", \"user\", or \"import\"`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate bylines\n\tif (seed.bylines) {\n\t\tif (!Array.isArray(seed.bylines)) {\n\t\t\terrors.push(\"bylines must be an array\");\n\t\t} else {\n\t\t\tconst bylineIds = new Set<string>();\n\t\t\tconst bylineSlugs = new Set<string>();\n\t\t\tfor (let i = 0; i < seed.bylines.length; i++) {\n\t\t\t\tconst byline = seed.bylines[i];\n\t\t\t\tconst prefix = `bylines[${i}]`;\n\n\t\t\t\tif (!byline.id) {\n\t\t\t\t\terrors.push(`${prefix}: id is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (bylineIds.has(byline.id)) {\n\t\t\t\t\t\terrors.push(`${prefix}.id: duplicate byline id \"${byline.id}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tbylineIds.add(byline.id);\n\t\t\t\t}\n\n\t\t\t\tif (!byline.slug) {\n\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t} else {\n\t\t\t\t\tif (!SLUG_PATTERN.test(byline.slug)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`${prefix}.slug: must contain only lowercase letters, numbers, and hyphens`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (bylineSlugs.has(byline.slug)) {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: duplicate byline slug \"${byline.slug}\"`);\n\t\t\t\t\t}\n\t\t\t\t\tbylineSlugs.add(byline.slug);\n\t\t\t\t}\n\n\t\t\t\tif (!byline.displayName) {\n\t\t\t\t\terrors.push(`${prefix}: displayName is required`);\n\t\t\t\t}\n\n\t\t\t\tif (byline.avatar !== undefined) {\n\t\t\t\t\tconst avatar: unknown = byline.avatar;\n\t\t\t\t\tif (!isRecord(avatar)) {\n\t\t\t\t\t\terrors.push(`${prefix}.avatar: must be an object`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// storageKey is used verbatim in a `where storage_key = ?` lookup,\n\t\t\t\t\t\t// so surrounding whitespace would silently never match a real key.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof avatar.storageKey !== \"string\" ||\n\t\t\t\t\t\t\tavatar.storageKey.length === 0 ||\n\t\t\t\t\t\t\tavatar.storageKey !== avatar.storageKey.trim()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${prefix}.avatar.storageKey: must be a non-empty string with no leading or trailing whitespace`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (const key of [\"alt\", \"filename\", \"mimeType\"] as const) {\n\t\t\t\t\t\t\tif (avatar[key] !== undefined && typeof avatar[key] !== \"string\") {\n\t\t\t\t\t\t\t\terrors.push(`${prefix}.avatar.${key}: must be a string`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// filename/mimeType are used verbatim, so reject blank or\n\t\t\t\t\t\t// whitespace-padded values (an empty filename would create a\n\t\t\t\t\t\t// media row with no basename; a padded mime type is invalid).\n\t\t\t\t\t\tfor (const key of [\"filename\", \"mimeType\"] as const) {\n\t\t\t\t\t\t\tconst v = avatar[key];\n\t\t\t\t\t\t\tif (typeof v === \"string\" && (v.length === 0 || v !== v.trim())) {\n\t\t\t\t\t\t\t\terrors.push(`${prefix}.avatar.${key}: must not be empty or whitespace-padded`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (const key of [\"width\", \"height\"] as const) {\n\t\t\t\t\t\t\tconst v = avatar[key];\n\t\t\t\t\t\t\tif (v !== undefined && (typeof v !== \"number\" || !Number.isFinite(v) || v < 0)) {\n\t\t\t\t\t\t\t\terrors.push(`${prefix}.avatar.${key}: must be a non-negative number`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate content\n\tif (seed.content) {\n\t\tif (typeof seed.content !== \"object\" || Array.isArray(seed.content)) {\n\t\t\terrors.push(\"content must be an object (collection -> entries)\");\n\t\t} else {\n\t\t\tfor (const [collectionSlug, entries] of Object.entries(seed.content)) {\n\t\t\t\tif (!Array.isArray(entries)) {\n\t\t\t\t\terrors.push(`content.${collectionSlug}: must be an array`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst collectionRoutable =\n\t\t\t\t\tseed.collections?.find((collection) => collection.slug === collectionSlug)?.routable !==\n\t\t\t\t\tfalse;\n\n\t\t\t\tconst entryIds = new Set<string>();\n\n\t\t\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\t\t\tconst entry = entries[i];\n\t\t\t\t\tconst prefix = `content.${collectionSlug}[${i}]`;\n\n\t\t\t\t\tif (!entry.id) {\n\t\t\t\t\t\terrors.push(`${prefix}: id is required`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Check for duplicate entry IDs\n\t\t\t\t\t\tif (entryIds.has(entry.id)) {\n\t\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t\t`${prefix}.id: duplicate entry id \"${entry.id}\" in collection \"${collectionSlug}\"`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tentryIds.add(entry.id);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst hasSlug = typeof entry.slug === \"string\" && entry.slug.trim().length > 0;\n\t\t\t\t\tif (entry.slug !== undefined && entry.slug !== null && typeof entry.slug !== \"string\") {\n\t\t\t\t\t\terrors.push(`${prefix}.slug: must be a string`);\n\t\t\t\t\t}\n\t\t\t\t\tif (collectionRoutable && !hasSlug) {\n\t\t\t\t\t\terrors.push(`${prefix}: slug is required`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!entry.data || typeof entry.data !== \"object\") {\n\t\t\t\t\t\terrors.push(`${prefix}: data must be an object`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Validate i18n fields\n\t\t\t\t\tif (entry.translationOf) {\n\t\t\t\t\t\tif (!entry.locale) {\n\t\t\t\t\t\t\terrors.push(`${prefix}: locale is required when translationOf is set`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Second pass: validate translationOf references within this collection\n\t\t\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\t\t\tconst entry = entries[i];\n\t\t\t\t\tif (entry.translationOf && !entryIds.has(entry.translationOf)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`content.${collectionSlug}[${i}].translationOf: references \"${entry.translationOf}\" which is not in this collection`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate cross-references (content refs in menus)\n\tif (seed.menus && seed.content) {\n\t\tconst allContentIds = new Set<string>();\n\t\tfor (const entries of Object.values(seed.content)) {\n\t\t\tif (Array.isArray(entries)) {\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tif (entry.id) {\n\t\t\t\t\t\tallContentIds.add(entry.id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check menu item refs\n\t\tfor (const menu of seed.menus) {\n\t\t\tif (Array.isArray(menu.items)) {\n\t\t\t\tvalidateMenuItemRefs(menu.items, allContentIds, warnings);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate byline refs in content\n\tif (seed.content) {\n\t\tconst seedBylineIds = new Set<string>((seed.bylines ?? []).map((byline) => byline.id));\n\t\tfor (const [collectionSlug, entries] of Object.entries(seed.content)) {\n\t\t\tif (!Array.isArray(entries)) continue;\n\t\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\t\tconst entry = entries[i];\n\t\t\t\tif (!entry.bylines) continue;\n\t\t\t\tif (!Array.isArray(entry.bylines)) {\n\t\t\t\t\terrors.push(`content.${collectionSlug}[${i}].bylines: must be an array`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (let j = 0; j < entry.bylines.length; j++) {\n\t\t\t\t\tconst credit = entry.bylines[j];\n\t\t\t\t\tconst prefix = `content.${collectionSlug}[${i}].bylines[${j}]`;\n\t\t\t\t\tif (!credit.byline) {\n\t\t\t\t\t\terrors.push(`${prefix}.byline: is required`);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!seedBylineIds.has(credit.byline)) {\n\t\t\t\t\t\terrors.push(`${prefix}.byline: references unknown byline \"${credit.byline}\"`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n/**\n * Validate menu items recursively\n */\nfunction validateMenuItems(\n\titems: unknown[],\n\tprefix: string,\n\terrors: string[],\n\twarnings: string[],\n): void {\n\tfor (let i = 0; i < items.length; i++) {\n\t\tconst raw = items[i];\n\t\tconst itemPrefix = `${prefix}.items[${i}]`;\n\n\t\tif (!isRecord(raw)) {\n\t\t\terrors.push(`${itemPrefix}: must be an object`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst item = raw;\n\n\t\tconst itemType = typeof item.type === \"string\" ? item.type : undefined;\n\n\t\tif (!itemType) {\n\t\t\terrors.push(`${itemPrefix}: type is required`);\n\t\t} else if (![\"custom\", \"page\", \"post\", \"taxonomy\", \"collection\"].includes(itemType)) {\n\t\t\terrors.push(\n\t\t\t\t`${itemPrefix}.type: must be \"custom\", \"page\", \"post\", \"taxonomy\", or \"collection\"`,\n\t\t\t);\n\t\t}\n\n\t\t// Type-specific validation\n\t\tif (itemType === \"custom\" && !item.url) {\n\t\t\terrors.push(`${itemPrefix}: url is required for custom menu items`);\n\t\t}\n\n\t\tif ((itemType === \"page\" || itemType === \"post\") && !item.ref) {\n\t\t\terrors.push(`${itemPrefix}: ref is required for page/post menu items`);\n\t\t}\n\n\t\t// Validate children recursively\n\t\tif (Array.isArray(item.children)) {\n\t\t\tvalidateMenuItems(item.children, itemPrefix, errors, warnings);\n\t\t}\n\t}\n}\n\n/**\n * Validate menu item references exist in content\n */\nfunction validateMenuItemRefs(\n\titems: SeedMenuItem[],\n\tcontentIds: Set<string>,\n\twarnings: string[],\n): void {\n\tfor (const item of items) {\n\t\tif ((item.type === \"page\" || item.type === \"post\") && item.ref) {\n\t\t\tif (!contentIds.has(item.ref)) {\n\t\t\t\twarnings.push(`Menu item references content \"${item.ref}\" which is not in the seed file`);\n\t\t\t}\n\t\t}\n\n\t\tif (item.children) {\n\t\t\tvalidateMenuItemRefs(item.children, contentIds, warnings);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -1,21 +1,22 @@
1
- import { n as isMissingTableError } from "./db-errors-CBD5yMro.mjs";
1
+ import { r as isMissingTableError } from "./db-errors-unnO6yiZ.mjs";
2
2
  import { t as validateIdentifier } from "./validate-DANX1-Qi.mjs";
3
- import "./dialect-helpers-7_IqPdh9.mjs";
4
- import "./config-CvmjJcVw.mjs";
3
+ import "./dialect-helpers-B1XN2HGB.mjs";
4
+ import "./config-Cs_AwWXI.mjs";
5
+ import "./after-32yNRvd2.mjs";
5
6
  import "./base64-BQBZwXCx.mjs";
6
- import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-xC4UD5-S.mjs";
7
- import "./request-cache-C4CIo5ad.mjs";
8
- import "./url-Dn3IStq8.mjs";
9
- import "./types-D2NEXtgB.mjs";
10
- import "./fts-manager-Beg3e4bI.mjs";
11
- import "./json-recordset-BUjxhr77.mjs";
12
- import "./collection-slugs-cache-e09QeJQt.mjs";
13
- import "./media-usage-work-CkLa5-nc.mjs";
14
- import "./capture-triggers-CT6dK9zd.mjs";
15
- import "./activation-Dim4YMM7.mjs";
16
- import { n as SchemaRegistry } from "./registry-TUVaid9Z.mjs";
7
+ import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-DiW8VMwz.mjs";
8
+ import "./request-cache-5z2WzWmh.mjs";
9
+ import "./url-DTfGDJhI.mjs";
10
+ import "./types-DwhEvIVb.mjs";
11
+ import "./fts-manager-6861qcwk.mjs";
12
+ import "./json-recordset-D0WhN2UA.mjs";
13
+ import "./collection-slugs-cache-DIrLjqH-.mjs";
14
+ import "./media-usage-work-BCK2J-v_.mjs";
15
+ import "./capture-triggers-BezAvWcB.mjs";
16
+ import "./activation-CGlyigmg.mjs";
17
+ import { n as SchemaRegistry } from "./registry-B0-O575m.mjs";
17
18
  import "./hash-BJaeek87.mjs";
18
- import { o as generateZodSchema } from "./zod-generator-D0JKy94C.mjs";
19
+ import { o as generateZodSchema } from "./zod-generator--nlM0930.mjs";
19
20
  import "./errors-B4f4It-2.mjs";
20
21
  import "./canonical-BudtH-Fx.mjs";
21
22
  import "./digest-DJ1tHCgy.mjs";
@@ -217,4 +218,4 @@ async function validateContentData(db, collection, data, options = {}) {
217
218
 
218
219
  //#endregion
219
220
  export { validateContentData };
220
- //# sourceMappingURL=validation-Ckq4vsVg.mjs.map
221
+ //# sourceMappingURL=validation-Fc9ZSUS_.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation-Ckq4vsVg.mjs","names":[],"sources":["../src/api/handlers/validation.ts"],"sourcesContent":["/**\n * Field-level validation for content create / update.\n *\n * Wires the existing `generateZodSchema()` pipeline (`schema/zod-generator.ts`)\n * into the handler boundary so REST and MCP both get the same enforcement:\n *\n * - required fields must be present and non-empty\n * - select / multiSelect values must match the configured options\n * - reference fields must resolve to a real, non-trashed target\n *\n * Errors surface as `{ code: \"VALIDATION_ERROR\", message, details: { issues } }`.\n * The message lists every offending field so callers can fix everything in a\n * single round trip; `issues` carries the same failures one by one, with a\n * code and any bound that failed, so the admin can word them for editors.\n */\n\nimport { sql, type Kysely } from \"kysely\";\nimport type { z } from \"zod\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport { SchemaRegistry } from \"../../schema/registry.js\";\nimport type { Field } from \"../../schema/types.js\";\nimport { generateZodSchema } from \"../../schema/zod-generator.js\";\nimport { chunks, SQL_BATCH_SIZE } from \"../../utils/chunks.js\";\nimport { isMissingTableError } from \"../../utils/db-errors.js\";\n\n/**\n * One rejected value. `code` is `required`, `unknown_field`,\n * `reference_not_found` or `invalid_reference_target`, or else the Zod issue\n * code. Length, range and item-count failures carry `origin` and the bound,\n * format failures carry `format`.\n */\nexport interface ContentValidationIssue {\n\tpath: string;\n\tcode: string;\n\tmessage: string;\n\torigin?: string;\n\tminimum?: number;\n\tmaximum?: number;\n\tformat?: string;\n}\n\ntype ValidationResult =\n\t| { ok: true }\n\t| {\n\t\t\tok: false;\n\t\t\terror: {\n\t\t\t\tcode: \"VALIDATION_ERROR\" | \"COLLECTION_NOT_FOUND\" | \"UNSUPPORTED_FIELD_TYPE\";\n\t\t\t\tmessage: string;\n\t\t\t\tdetails?: { issues: ContentValidationIssue[] };\n\t\t\t};\n\t };\n\n/** Treat `undefined`, `null`, and `\"\"` as \"not set\". */\nfunction isMissing(value: unknown): boolean {\n\treturn value === undefined || value === null || value === \"\";\n}\n\n/**\n * Resolve the target collection slug for a reference field.\n *\n * Schema-defined reference fields (the static `reference()` factory in\n * `fields/reference.ts`) put the target in `options.collection`. The MCP\n * `schema_create_field` tool also puts it there. Tests and some admin paths\n * stash it inside `validation.collection` directly; we accept both.\n */\nfunction getReferenceTargetCollection(field: Field): string | undefined {\n\tconst fromOptions = field.options?.collection;\n\tif (typeof fromOptions === \"string\" && fromOptions.length > 0) return fromOptions;\n\tconst validation = field.validation;\n\tif (validation && \"collection\" in validation) {\n\t\tconst fromValidation: unknown = (validation as { collection?: unknown }).collection;\n\t\tif (typeof fromValidation === \"string\" && fromValidation.length > 0) return fromValidation;\n\t}\n\treturn undefined;\n}\n\n/**\n * Format a Zod issue path into a human-readable field reference, e.g.\n * `tags`, `tags.1`, `image.alt`.\n */\nfunction formatIssuePath(path: ReadonlyArray<PropertyKey>): string {\n\tif (path.length === 0) return \"(root)\";\n\treturn path.map((seg) => String(seg)).join(\".\");\n}\n\nfunction isSubFieldPath(\n\tpath: ReadonlyArray<PropertyKey>,\n\tfieldTypes: ReadonlyMap<string, string>,\n): boolean {\n\treturn path.length === 3 && fieldTypes.get(String(path[0])) === \"repeater\";\n}\n\nfunction isFieldOrSubFieldPath(\n\tpath: ReadonlyArray<PropertyKey>,\n\tfieldTypes: ReadonlyMap<string, string>,\n): boolean {\n\treturn path.length === 1 || isSubFieldPath(path, fieldTypes);\n}\n\nfunction fromZodIssue(\n\tissue: z.core.$ZodIssue,\n\tfieldTypes: ReadonlyMap<string, string>,\n): ContentValidationIssue {\n\tconst result: ContentValidationIssue = {\n\t\tpath: formatIssuePath(issue.path),\n\t\tcode: issue.code,\n\t\tmessage: issue.message,\n\t};\n\tswitch (issue.code) {\n\t\tcase \"invalid_type\":\n\t\tcase \"invalid_union\":\n\t\tcase \"invalid_value\":\n\t\t\t// Zod reports a missing or null value as a type, union or option\n\t\t\t// mismatch. A key missing inside a value, such as a Portable Text\n\t\t\t// block's `_type`, leaves the value malformed rather than the field empty.\n\t\t\tif (issue.input == null && isFieldOrSubFieldPath(issue.path, fieldTypes)) {\n\t\t\t\tresult.code = \"required\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"too_small\":\n\t\t\tresult.origin = issue.origin;\n\t\t\tif (typeof issue.minimum === \"number\") result.minimum = issue.minimum;\n\t\t\t// A required repeater sub-field rejects \"\" as a one-character minimum.\n\t\t\tif (issue.input === \"\" && isSubFieldPath(issue.path, fieldTypes)) {\n\t\t\t\tresult.code = \"required\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"too_big\":\n\t\t\tresult.origin = issue.origin;\n\t\t\tif (typeof issue.maximum === \"number\") result.maximum = issue.maximum;\n\t\t\tbreak;\n\t\tcase \"invalid_format\":\n\t\t\tresult.format = issue.format;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\n/**\n * Validate `data` against the collection's field definitions.\n *\n * `partial: true` switches Zod into partial mode so updates can include\n * only the fields being changed without tripping required-field errors on\n * fields the caller didn't touch. Required fields that ARE present in\n * partial-mode data still get the empty-string check below.\n */\nexport async function validateContentData(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tdata: Record<string, unknown>,\n\toptions: { partial?: boolean } = {},\n): Promise<ValidationResult> {\n\tconst registry = new SchemaRegistry(db);\n\tconst collectionWithFields = await registry.getCollectionWithFields(collection);\n\tif (!collectionWithFields) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COLLECTION_NOT_FOUND\",\n\t\t\t\tmessage: `Collection '${collection}' not found`,\n\t\t\t},\n\t\t};\n\t}\n\n\tconst issues: ContentValidationIssue[] = [];\n\tconst unsupportedField = collectionWithFields.fields.find((field) => field.unsupportedType);\n\tif (unsupportedField?.unsupportedType) {\n\t\tconst { type, path } = unsupportedField.unsupportedType;\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\tmessage: `Collection '${collection}' field '${unsupportedField.slug}' uses unsupported field type '${type}' at '${path}'`,\n\t\t\t},\n\t\t};\n\t}\n\n\t// Detect unknown keys explicitly so callers get a useful error rather\n\t// than silently dropped data. Leading-underscore keys (e.g. `_slug`,\n\t// `_rev`) are reserved for internal handler/runtime use and aren't real\n\t// fields; skip them.\n\tconst knownFields = new Set(collectionWithFields.fields.map((f) => f.slug));\n\tfor (const key of Object.keys(data)) {\n\t\tif (key.startsWith(\"_\")) continue;\n\t\tif (!knownFields.has(key)) {\n\t\t\tissues.push({\n\t\t\t\tpath: key,\n\t\t\t\tcode: \"unknown_field\",\n\t\t\t\tmessage: `unknown field on collection '${collection}'`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Zod handles type, enum, length and missing-required (in non-partial\n\t// mode) checks. Empty-string handling for required string fields is\n\t// done as a separate pass below since Zod's `z.string()` accepts \"\".\n\tconst baseSchema = generateZodSchema(collectionWithFields);\n\tconst schema = options.partial ? baseSchema.partial() : baseSchema;\n\tconst parsed = schema.safeParse(data, { reportInput: true });\n\tif (!parsed.success) {\n\t\tconst fieldTypes = new Map(collectionWithFields.fields.map((f) => [f.slug, f.type]));\n\t\tfor (const issue of parsed.error.issues) {\n\t\t\tissues.push(fromZodIssue(issue, fieldTypes));\n\t\t}\n\t}\n\n\t// Empty-string-on-required check. In create mode (partial=false) Zod\n\t// already catches missing/null for required fields, but `z.string()`\n\t// happily accepts \"\". In update mode (partial=true) the field is only\n\t// checked if it's present in `data`.\n\tfor (const field of collectionWithFields.fields) {\n\t\tif (!field.required) continue;\n\t\tconst present = Object.hasOwn(data, field.slug);\n\t\tif (options.partial && !present) continue;\n\t\tif (data[field.slug] === \"\") {\n\t\t\tissues.push({\n\t\t\t\tpath: field.slug,\n\t\t\t\tcode: \"required\",\n\t\t\t\tmessage: \"required (empty value not allowed)\",\n\t\t\t});\n\t\t}\n\t}\n\n\t// Reference target existence. Only check fields that:\n\t// - have a value (non-missing) in `data`\n\t// - have a resolvable target collection\n\t// - in partial mode: are present in `data`\n\t// Batch one IN-query per target collection to keep round-trips low.\n\tconst refsByTarget = new Map<string, { field: string; id: string }[]>();\n\tfor (const field of collectionWithFields.fields) {\n\t\tif (field.type !== \"reference\") continue;\n\t\tif (options.partial && !Object.hasOwn(data, field.slug)) continue;\n\t\tconst value = data[field.slug];\n\t\tif (isMissing(value)) continue;\n\t\tif (typeof value !== \"string\") continue; // Zod will have flagged this already\n\t\tconst target = getReferenceTargetCollection(field);\n\t\tif (!target) continue;\n\t\tconst list = refsByTarget.get(target) ?? [];\n\t\tlist.push({ field: field.slug, id: value });\n\t\trefsByTarget.set(target, list);\n\t}\n\n\tfor (const [target, refs] of refsByTarget) {\n\t\t// Validate the target collection slug before interpolating into raw\n\t\t// SQL — defense-in-depth even though slugs are already validated at\n\t\t// schema-create time.\n\t\ttry {\n\t\t\tvalidateIdentifier(target, \"reference target collection\");\n\t\t} catch {\n\t\t\tfor (const ref of refs) {\n\t\t\t\tissues.push({\n\t\t\t\t\tpath: ref.field,\n\t\t\t\t\tcode: \"invalid_reference_target\",\n\t\t\t\t\tmessage: `invalid reference target collection '${target}'`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ids = [...new Set(refs.map((r) => r.id))];\n\t\tconst tableName = `ec_${target}`;\n\n\t\t// Chunk the IN clause to stay below D1's bind-parameter limit. One\n\t\t// reference per request is the common case today; chunking makes the\n\t\t// helper safe if a future multiSelect-of-references is added.\n\t\tconst found = new Set<string>();\n\t\tlet targetTableMissing = false;\n\t\tfor (const idChunk of chunks(ids, SQL_BATCH_SIZE)) {\n\t\t\ttry {\n\t\t\t\tconst rows = await sql<{ id: string }>`\n\t\t\t\t\tSELECT id FROM ${sql.ref(tableName)}\n\t\t\t\t\tWHERE id IN (${sql.join(idChunk)})\n\t\t\t\t\tAND deleted_at IS NULL\n\t\t\t\t`.execute(db);\n\t\t\t\tfor (const row of rows.rows) {\n\t\t\t\t\tfound.add(row.id);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Missing table = the target collection table doesn't exist\n\t\t\t\t// (orphan reference). Treat all those references as missing.\n\t\t\t\t// Any other DB error (permissions, connection, syntax) must\n\t\t\t\t// propagate — silently dropping data integrity errors as\n\t\t\t\t// \"not found\" is exactly the bug F5 fixes.\n\t\t\t\tif (isMissingTableError(error)) {\n\t\t\t\t\ttargetTableMissing = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tfor (const ref of refs) {\n\t\t\tif (targetTableMissing || !found.has(ref.id)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tpath: ref.field,\n\t\t\t\t\tcode: \"reference_not_found\",\n\t\t\t\t\tmessage: `target '${ref.id}' not found in collection '${target}'`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tif (issues.length === 0) return { ok: true };\n\treturn {\n\t\tok: false,\n\t\terror: {\n\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\tmessage: issues.map((issue) => `${issue.path}: ${issue.message}`).join(\"; \"),\n\t\t\tdetails: { issues },\n\t\t},\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"validation-Fc9ZSUS_.mjs","names":[],"sources":["../src/api/handlers/validation.ts"],"sourcesContent":["/**\n * Field-level validation for content create / update.\n *\n * Wires the existing `generateZodSchema()` pipeline (`schema/zod-generator.ts`)\n * into the handler boundary so REST and MCP both get the same enforcement:\n *\n * - required fields must be present and non-empty\n * - select / multiSelect values must match the configured options\n * - reference fields must resolve to a real, non-trashed target\n *\n * Errors surface as `{ code: \"VALIDATION_ERROR\", message, details: { issues } }`.\n * The message lists every offending field so callers can fix everything in a\n * single round trip; `issues` carries the same failures one by one, with a\n * code and any bound that failed, so the admin can word them for editors.\n */\n\nimport { sql, type Kysely } from \"kysely\";\nimport type { z } from \"zod\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport { SchemaRegistry } from \"../../schema/registry.js\";\nimport type { Field } from \"../../schema/types.js\";\nimport { generateZodSchema } from \"../../schema/zod-generator.js\";\nimport { chunks, SQL_BATCH_SIZE } from \"../../utils/chunks.js\";\nimport { isMissingTableError } from \"../../utils/db-errors.js\";\n\n/**\n * One rejected value. `code` is `required`, `unknown_field`,\n * `reference_not_found` or `invalid_reference_target`, or else the Zod issue\n * code. Length, range and item-count failures carry `origin` and the bound,\n * format failures carry `format`.\n */\nexport interface ContentValidationIssue {\n\tpath: string;\n\tcode: string;\n\tmessage: string;\n\torigin?: string;\n\tminimum?: number;\n\tmaximum?: number;\n\tformat?: string;\n}\n\ntype ValidationResult =\n\t| { ok: true }\n\t| {\n\t\t\tok: false;\n\t\t\terror: {\n\t\t\t\tcode: \"VALIDATION_ERROR\" | \"COLLECTION_NOT_FOUND\" | \"UNSUPPORTED_FIELD_TYPE\";\n\t\t\t\tmessage: string;\n\t\t\t\tdetails?: { issues: ContentValidationIssue[] };\n\t\t\t};\n\t };\n\n/** Treat `undefined`, `null`, and `\"\"` as \"not set\". */\nfunction isMissing(value: unknown): boolean {\n\treturn value === undefined || value === null || value === \"\";\n}\n\n/**\n * Resolve the target collection slug for a reference field.\n *\n * Schema-defined reference fields (the static `reference()` factory in\n * `fields/reference.ts`) put the target in `options.collection`. The MCP\n * `schema_create_field` tool also puts it there. Tests and some admin paths\n * stash it inside `validation.collection` directly; we accept both.\n */\nfunction getReferenceTargetCollection(field: Field): string | undefined {\n\tconst fromOptions = field.options?.collection;\n\tif (typeof fromOptions === \"string\" && fromOptions.length > 0) return fromOptions;\n\tconst validation = field.validation;\n\tif (validation && \"collection\" in validation) {\n\t\tconst fromValidation: unknown = (validation as { collection?: unknown }).collection;\n\t\tif (typeof fromValidation === \"string\" && fromValidation.length > 0) return fromValidation;\n\t}\n\treturn undefined;\n}\n\n/**\n * Format a Zod issue path into a human-readable field reference, e.g.\n * `tags`, `tags.1`, `image.alt`.\n */\nfunction formatIssuePath(path: ReadonlyArray<PropertyKey>): string {\n\tif (path.length === 0) return \"(root)\";\n\treturn path.map((seg) => String(seg)).join(\".\");\n}\n\nfunction isSubFieldPath(\n\tpath: ReadonlyArray<PropertyKey>,\n\tfieldTypes: ReadonlyMap<string, string>,\n): boolean {\n\treturn path.length === 3 && fieldTypes.get(String(path[0])) === \"repeater\";\n}\n\nfunction isFieldOrSubFieldPath(\n\tpath: ReadonlyArray<PropertyKey>,\n\tfieldTypes: ReadonlyMap<string, string>,\n): boolean {\n\treturn path.length === 1 || isSubFieldPath(path, fieldTypes);\n}\n\nfunction fromZodIssue(\n\tissue: z.core.$ZodIssue,\n\tfieldTypes: ReadonlyMap<string, string>,\n): ContentValidationIssue {\n\tconst result: ContentValidationIssue = {\n\t\tpath: formatIssuePath(issue.path),\n\t\tcode: issue.code,\n\t\tmessage: issue.message,\n\t};\n\tswitch (issue.code) {\n\t\tcase \"invalid_type\":\n\t\tcase \"invalid_union\":\n\t\tcase \"invalid_value\":\n\t\t\t// Zod reports a missing or null value as a type, union or option\n\t\t\t// mismatch. A key missing inside a value, such as a Portable Text\n\t\t\t// block's `_type`, leaves the value malformed rather than the field empty.\n\t\t\tif (issue.input == null && isFieldOrSubFieldPath(issue.path, fieldTypes)) {\n\t\t\t\tresult.code = \"required\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"too_small\":\n\t\t\tresult.origin = issue.origin;\n\t\t\tif (typeof issue.minimum === \"number\") result.minimum = issue.minimum;\n\t\t\t// A required repeater sub-field rejects \"\" as a one-character minimum.\n\t\t\tif (issue.input === \"\" && isSubFieldPath(issue.path, fieldTypes)) {\n\t\t\t\tresult.code = \"required\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"too_big\":\n\t\t\tresult.origin = issue.origin;\n\t\t\tif (typeof issue.maximum === \"number\") result.maximum = issue.maximum;\n\t\t\tbreak;\n\t\tcase \"invalid_format\":\n\t\t\tresult.format = issue.format;\n\t\t\tbreak;\n\t}\n\treturn result;\n}\n\n/**\n * Validate `data` against the collection's field definitions.\n *\n * `partial: true` switches Zod into partial mode so updates can include\n * only the fields being changed without tripping required-field errors on\n * fields the caller didn't touch. Required fields that ARE present in\n * partial-mode data still get the empty-string check below.\n */\nexport async function validateContentData(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tdata: Record<string, unknown>,\n\toptions: { partial?: boolean } = {},\n): Promise<ValidationResult> {\n\tconst registry = new SchemaRegistry(db);\n\tconst collectionWithFields = await registry.getCollectionWithFields(collection);\n\tif (!collectionWithFields) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COLLECTION_NOT_FOUND\",\n\t\t\t\tmessage: `Collection '${collection}' not found`,\n\t\t\t},\n\t\t};\n\t}\n\n\tconst issues: ContentValidationIssue[] = [];\n\tconst unsupportedField = collectionWithFields.fields.find((field) => field.unsupportedType);\n\tif (unsupportedField?.unsupportedType) {\n\t\tconst { type, path } = unsupportedField.unsupportedType;\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\tmessage: `Collection '${collection}' field '${unsupportedField.slug}' uses unsupported field type '${type}' at '${path}'`,\n\t\t\t},\n\t\t};\n\t}\n\n\t// Detect unknown keys explicitly so callers get a useful error rather\n\t// than silently dropped data. Leading-underscore keys (e.g. `_slug`,\n\t// `_rev`) are reserved for internal handler/runtime use and aren't real\n\t// fields; skip them.\n\tconst knownFields = new Set(collectionWithFields.fields.map((f) => f.slug));\n\tfor (const key of Object.keys(data)) {\n\t\tif (key.startsWith(\"_\")) continue;\n\t\tif (!knownFields.has(key)) {\n\t\t\tissues.push({\n\t\t\t\tpath: key,\n\t\t\t\tcode: \"unknown_field\",\n\t\t\t\tmessage: `unknown field on collection '${collection}'`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Zod handles type, enum, length and missing-required (in non-partial\n\t// mode) checks. Empty-string handling for required string fields is\n\t// done as a separate pass below since Zod's `z.string()` accepts \"\".\n\tconst baseSchema = generateZodSchema(collectionWithFields);\n\tconst schema = options.partial ? baseSchema.partial() : baseSchema;\n\tconst parsed = schema.safeParse(data, { reportInput: true });\n\tif (!parsed.success) {\n\t\tconst fieldTypes = new Map(collectionWithFields.fields.map((f) => [f.slug, f.type]));\n\t\tfor (const issue of parsed.error.issues) {\n\t\t\tissues.push(fromZodIssue(issue, fieldTypes));\n\t\t}\n\t}\n\n\t// Empty-string-on-required check. In create mode (partial=false) Zod\n\t// already catches missing/null for required fields, but `z.string()`\n\t// happily accepts \"\". In update mode (partial=true) the field is only\n\t// checked if it's present in `data`.\n\tfor (const field of collectionWithFields.fields) {\n\t\tif (!field.required) continue;\n\t\tconst present = Object.hasOwn(data, field.slug);\n\t\tif (options.partial && !present) continue;\n\t\tif (data[field.slug] === \"\") {\n\t\t\tissues.push({\n\t\t\t\tpath: field.slug,\n\t\t\t\tcode: \"required\",\n\t\t\t\tmessage: \"required (empty value not allowed)\",\n\t\t\t});\n\t\t}\n\t}\n\n\t// Reference target existence. Only check fields that:\n\t// - have a value (non-missing) in `data`\n\t// - have a resolvable target collection\n\t// - in partial mode: are present in `data`\n\t// Batch one IN-query per target collection to keep round-trips low.\n\tconst refsByTarget = new Map<string, { field: string; id: string }[]>();\n\tfor (const field of collectionWithFields.fields) {\n\t\tif (field.type !== \"reference\") continue;\n\t\tif (options.partial && !Object.hasOwn(data, field.slug)) continue;\n\t\tconst value = data[field.slug];\n\t\tif (isMissing(value)) continue;\n\t\tif (typeof value !== \"string\") continue; // Zod will have flagged this already\n\t\tconst target = getReferenceTargetCollection(field);\n\t\tif (!target) continue;\n\t\tconst list = refsByTarget.get(target) ?? [];\n\t\tlist.push({ field: field.slug, id: value });\n\t\trefsByTarget.set(target, list);\n\t}\n\n\tfor (const [target, refs] of refsByTarget) {\n\t\t// Validate the target collection slug before interpolating into raw\n\t\t// SQL — defense-in-depth even though slugs are already validated at\n\t\t// schema-create time.\n\t\ttry {\n\t\t\tvalidateIdentifier(target, \"reference target collection\");\n\t\t} catch {\n\t\t\tfor (const ref of refs) {\n\t\t\t\tissues.push({\n\t\t\t\t\tpath: ref.field,\n\t\t\t\t\tcode: \"invalid_reference_target\",\n\t\t\t\t\tmessage: `invalid reference target collection '${target}'`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ids = [...new Set(refs.map((r) => r.id))];\n\t\tconst tableName = `ec_${target}`;\n\n\t\t// Chunk the IN clause to stay below D1's bind-parameter limit. One\n\t\t// reference per request is the common case today; chunking makes the\n\t\t// helper safe if a future multiSelect-of-references is added.\n\t\tconst found = new Set<string>();\n\t\tlet targetTableMissing = false;\n\t\tfor (const idChunk of chunks(ids, SQL_BATCH_SIZE)) {\n\t\t\ttry {\n\t\t\t\tconst rows = await sql<{ id: string }>`\n\t\t\t\t\tSELECT id FROM ${sql.ref(tableName)}\n\t\t\t\t\tWHERE id IN (${sql.join(idChunk)})\n\t\t\t\t\tAND deleted_at IS NULL\n\t\t\t\t`.execute(db);\n\t\t\t\tfor (const row of rows.rows) {\n\t\t\t\t\tfound.add(row.id);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Missing table = the target collection table doesn't exist\n\t\t\t\t// (orphan reference). Treat all those references as missing.\n\t\t\t\t// Any other DB error (permissions, connection, syntax) must\n\t\t\t\t// propagate — silently dropping data integrity errors as\n\t\t\t\t// \"not found\" is exactly the bug F5 fixes.\n\t\t\t\tif (isMissingTableError(error)) {\n\t\t\t\t\ttargetTableMissing = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tfor (const ref of refs) {\n\t\t\tif (targetTableMissing || !found.has(ref.id)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tpath: ref.field,\n\t\t\t\t\tcode: \"reference_not_found\",\n\t\t\t\t\tmessage: `target '${ref.id}' not found in collection '${target}'`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tif (issues.length === 0) return { ok: true };\n\treturn {\n\t\tok: false,\n\t\terror: {\n\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\tmessage: issues.map((issue) => `${issue.path}: ${issue.message}`).join(\"; \"),\n\t\t\tdetails: { issues },\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ //#region src/version.ts
2
+ const VERSION = "1.4.0";
3
+ const COMMIT = "10beb8c5a";
4
+
5
+ //#endregion
6
+ export { VERSION as n, COMMIT as t };
7
+ //# sourceMappingURL=version-Bu6Nlbb5.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-DHmGpcch.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["/**\n * Build-time version constants, replaced by tsdown/Vite `define`.\n * Falls back to \"dev\" when running uncompiled (tests, dev).\n */\n\ndeclare const __EMDASH_VERSION__: string;\ndeclare const __EMDASH_COMMIT__: string;\n\nexport const VERSION: string =\n\ttypeof __EMDASH_VERSION__ !== \"undefined\" ? __EMDASH_VERSION__ : \"dev\";\n\nexport const COMMIT: string = typeof __EMDASH_COMMIT__ !== \"undefined\" ? __EMDASH_COMMIT__ : \"dev\";\n"],"mappings":";AAQA,MAAa;AAGb,MAAa"}
1
+ {"version":3,"file":"version-Bu6Nlbb5.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["/**\n * Build-time version constants, replaced by tsdown/Vite `define`.\n * Falls back to \"dev\" when running uncompiled (tests, dev).\n */\n\ndeclare const __EMDASH_VERSION__: string;\ndeclare const __EMDASH_COMMIT__: string;\n\nexport const VERSION: string =\n\ttypeof __EMDASH_VERSION__ !== \"undefined\" ? __EMDASH_VERSION__ : \"dev\";\n\nexport const COMMIT: string = typeof __EMDASH_COMMIT__ !== \"undefined\" ? __EMDASH_COMMIT__ : \"dev\";\n"],"mappings":";AAQA,MAAa;AAGb,MAAa"}
@@ -0,0 +1,49 @@
1
+ import { u as isPostgres } from "./dialect-helpers-B1XN2HGB.mjs";
2
+ import { sql } from "kysely";
3
+
4
+ //#region src/settings/version.ts
5
+ const SITE_OPTION_PREFIX = "site:%";
6
+ /** Returns the canonical JSON representation of a site-settings revision fingerprint. */
7
+ function normalizeSiteSettingsVersion(input) {
8
+ const decoded = JSON.parse(input);
9
+ if (!Array.isArray(decoded)) throw new Error("Invalid site settings version");
10
+ const entries = [];
11
+ for (const entry of decoded) {
12
+ if (!Array.isArray(entry)) throw new Error("Invalid site settings version entry");
13
+ const name = entry[0];
14
+ const revision = entry[1];
15
+ if (typeof name !== "string" || typeof revision !== "string") throw new Error("Invalid site settings version entry");
16
+ entries.push([name, revision]);
17
+ }
18
+ return JSON.stringify(entries.toSorted(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
19
+ }
20
+ /**
21
+ * Builds the scalar query used to observe site-setting revisions alongside an
22
+ * existing read. It deliberately does not read option values.
23
+ */
24
+ function siteSettingsVersionQuery(db) {
25
+ if (isPostgres(db)) return sql`(
26
+ select coalesce(
27
+ json_agg(json_build_array(name, revision) order by name)::text,
28
+ '[]'
29
+ )
30
+ from options
31
+ where name like ${SITE_OPTION_PREFIX}
32
+ )`;
33
+ return sql`(
34
+ select coalesce(
35
+ json_group_array(json_array(name, revision)),
36
+ '[]'
37
+ )
38
+ from (
39
+ select name, revision
40
+ from options
41
+ where name glob ${"site:*"}
42
+ order by name
43
+ )
44
+ )`;
45
+ }
46
+
47
+ //#endregion
48
+ export { siteSettingsVersionQuery as n, normalizeSiteSettingsVersion as t };
49
+ //# sourceMappingURL=version-DqB7LIO7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-DqB7LIO7.mjs","names":[],"sources":["../src/settings/version.ts"],"sourcesContent":["import type { Kysely, RawBuilder } from \"kysely\";\nimport { sql } from \"kysely\";\n\nimport { isPostgres } from \"../database/dialect-helpers.js\";\nimport type { Database } from \"../database/types.js\";\n\nconst SITE_OPTION_PREFIX = \"site:%\";\n\n/** Returns the canonical JSON representation of a site-settings revision fingerprint. */\nexport function normalizeSiteSettingsVersion(input: string): string {\n\tconst decoded: unknown = JSON.parse(input);\n\tif (!Array.isArray(decoded)) throw new Error(\"Invalid site settings version\");\n\tconst entries: [string, string][] = [];\n\tfor (const entry of decoded) {\n\t\tif (!Array.isArray(entry)) throw new Error(\"Invalid site settings version entry\");\n\t\tconst name: unknown = entry[0];\n\t\tconst revision: unknown = entry[1];\n\t\tif (typeof name !== \"string\" || typeof revision !== \"string\") {\n\t\t\tthrow new Error(\"Invalid site settings version entry\");\n\t\t}\n\t\tentries.push([name, revision]);\n\t}\n\treturn JSON.stringify(entries.toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));\n}\n\n/**\n * Builds the scalar query used to observe site-setting revisions alongside an\n * existing read. It deliberately does not read option values.\n */\nexport function siteSettingsVersionQuery(db: Kysely<Database>): RawBuilder<string> {\n\tif (isPostgres(db)) {\n\t\treturn sql<string>`(\n\t\t\tselect coalesce(\n\t\t\t\tjson_agg(json_build_array(name, revision) order by name)::text,\n\t\t\t\t'[]'\n\t\t\t)\n\t\t\tfrom options\n\t\t\twhere name like ${SITE_OPTION_PREFIX}\n\t\t)`;\n\t}\n\n\treturn sql<string>`(\n\t\tselect coalesce(\n\t\t\tjson_group_array(json_array(name, revision)),\n\t\t\t'[]'\n\t\t)\n\t\tfrom (\n\t\t\tselect name, revision\n\t\t\tfrom options\n\t\t\twhere name glob ${\"site:*\"}\n\t\t\torder by name\n\t\t)\n\t)`;\n}\n"],"mappings":";;;;AAMA,MAAM,qBAAqB;;AAG3B,SAAgB,6BAA6B,OAAuB;CACnE,MAAM,UAAmB,KAAK,MAAM,MAAM;AAC1C,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,OAAM,IAAI,MAAM,gCAAgC;CAC7E,MAAM,UAA8B,EAAE;AACtC,MAAK,MAAM,SAAS,SAAS;AAC5B,MAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,OAAM,IAAI,MAAM,sCAAsC;EACjF,MAAM,OAAgB,MAAM;EAC5B,MAAM,WAAoB,MAAM;AAChC,MAAI,OAAO,SAAS,YAAY,OAAO,aAAa,SACnD,OAAM,IAAI,MAAM,sCAAsC;AAEvD,UAAQ,KAAK,CAAC,MAAM,SAAS,CAAC;;AAE/B,QAAO,KAAK,UAAU,QAAQ,UAAU,CAAC,IAAI,CAAC,OAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,EAAG,CAAC;;;;;;AAOpF,SAAgB,yBAAyB,IAA0C;AAClF,KAAI,WAAW,GAAG,CACjB,QAAO,GAAW;;;;;;qBAMC,mBAAmB;;AAIvC,QAAO,GAAW;;;;;;;;qBAQE,SAAS"}
@@ -1,6 +1,7 @@
1
- import { n as peekRequestCache, r as requestCached } from "./request-cache-C4CIo5ad.mjs";
1
+ import { n as cachedQuery, t as CacheNamespace } from "./object-cache-DmKr09La.mjs";
2
+ import { n as peekRequestCache, r as requestCached } from "./request-cache-5z2WzWmh.mjs";
2
3
  import { i as widgetAreaTag } from "./chrome-tags-BIKBMZYO.mjs";
3
- import { c as getDb } from "./loader-CswroUbe.mjs";
4
+ import { u as getDb } from "./loader-DhnedqY4.mjs";
4
5
  import { t as getWidgetComponents$1 } from "./components-Brp__9xo.mjs";
5
6
 
6
7
  //#region src/widgets/index.ts
@@ -13,7 +14,13 @@ async function getWidgetArea(name) {
13
14
  if (prefetched) try {
14
15
  return (await prefetched).find((area) => area.name === name) ?? null;
15
16
  } catch {}
16
- return groupAreaRows(await selectAreasWithWidgets(await getDb()).where("a.name", "=", name).orderBy("w.sort_order", "asc").execute())[0] ?? null;
17
+ return cachedQuery({
18
+ namespace: CacheNamespace.WIDGETS,
19
+ key: `area:${name}`,
20
+ load: async () => {
21
+ return groupAreaRows(await selectAreasWithWidgets(await getDb()).where("a.name", "=", name).orderBy("w.sort_order", "asc").execute())[0] ?? null;
22
+ }
23
+ });
17
24
  });
18
25
  }
19
26
  /**
@@ -86,7 +93,13 @@ async function getWidgetAreaWithCacheHint(name) {
86
93
  * Get all widget areas with their widgets
87
94
  */
88
95
  async function getWidgetAreas() {
89
- return groupAreaRows(await selectAreasWithWidgets(await getDb()).orderBy("a.created_at", "asc").orderBy("a.id", "asc").orderBy("w.sort_order", "asc").execute());
96
+ return cachedQuery({
97
+ namespace: CacheNamespace.WIDGETS,
98
+ key: "areas",
99
+ load: async () => {
100
+ return groupAreaRows(await selectAreasWithWidgets(await getDb()).orderBy("a.created_at", "asc").orderBy("a.id", "asc").orderBy("w.sort_order", "asc").execute());
101
+ }
102
+ });
90
103
  }
91
104
  /**
92
105
  * Get available widget components (for admin UI)
@@ -118,4 +131,4 @@ function rowToWidget(row) {
118
131
 
119
132
  //#endregion
120
133
  export { rowToWidget as a, getWidgetComponents as i, getWidgetAreaWithCacheHint as n, getWidgetAreas as r, getWidgetArea as t };
121
- //# sourceMappingURL=widgets-DA5XmvVC.mjs.map
134
+ //# sourceMappingURL=widgets-BUx_Mf2q.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widgets-BUx_Mf2q.mjs","names":["getComponentRegistry"],"sources":["../src/widgets/index.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport { widgetAreaTag } from \"../cache/chrome-tags.js\";\nimport type { Database } from \"../database/types.js\";\nimport { getDb } from \"../loader.js\";\nimport { cachedQuery, CacheNamespace } from \"../object-cache/index.js\";\nimport type { CacheHint } from \"../query.js\";\nimport { peekRequestCache, requestCached } from \"../request-cache.js\";\nimport { getWidgetComponents as getComponentRegistry } from \"./components.js\";\nimport type { Widget, WidgetArea, WidgetRow, WidgetComponentDef } from \"./types.js\";\n\nexport type {\n\tWidget,\n\tWidgetArea,\n\tWidgetType,\n\tWidgetComponentDef,\n\tPropDef,\n\tCreateWidgetAreaInput,\n\tCreateWidgetInput,\n\tUpdateWidgetInput,\n\tReorderWidgetsInput,\n} from \"./types.js\";\nexport { invalidateWidgetObjectCache } from \"../object-cache/index.js\";\n\n/**\n * Get a widget area by name, with all its widgets.\n */\nexport async function getWidgetArea(name: string): Promise<WidgetArea | null> {\n\treturn requestCached(`widget-area:${name}`, async () => {\n\t\tconst prefetched = peekRequestCache<WidgetArea[]>(\"widget-areas\");\n\t\tif (prefetched) {\n\t\t\ttry {\n\t\t\t\tconst areas = await prefetched;\n\t\t\t\treturn areas.find((area) => area.name === name) ?? null;\n\t\t\t} catch {\n\t\t\t\t// Optional prefetch failure must still allow the scoped read.\n\t\t\t}\n\t\t}\n\n\t\treturn cachedQuery({\n\t\t\tnamespace: CacheNamespace.WIDGETS,\n\t\t\tkey: `area:${name}`,\n\t\t\tload: async () => {\n\t\t\t\tconst db = await getDb();\n\t\t\t\tconst rows = await selectAreasWithWidgets(db)\n\t\t\t\t\t.where(\"a.name\", \"=\", name)\n\t\t\t\t\t.orderBy(\"w.sort_order\", \"asc\")\n\t\t\t\t\t.execute();\n\t\t\t\treturn groupAreaRows(rows)[0] ?? null;\n\t\t\t},\n\t\t});\n\t});\n}\n\n/**\n * Areas left-joined with their widgets, so areas and widgets load in one\n * round trip. An area with no widgets yields one row with null widget columns.\n */\nfunction selectAreasWithWidgets(db: Kysely<Database>) {\n\treturn db\n\t\t.selectFrom(\"_emdash_widget_areas as a\")\n\t\t.leftJoin(\"_emdash_widgets as w\", \"w.area_id\", \"a.id\")\n\t\t.select([\n\t\t\t\"a.id as a_id\",\n\t\t\t\"a.name as a_name\",\n\t\t\t\"a.label as a_label\",\n\t\t\t\"a.description as a_description\",\n\t\t\t\"w.id as w_id\",\n\t\t\t\"w.type as w_type\",\n\t\t\t\"w.title as w_title\",\n\t\t\t\"w.content as w_content\",\n\t\t\t\"w.menu_name as w_menu_name\",\n\t\t\t\"w.component_id as w_component_id\",\n\t\t\t\"w.component_props as w_component_props\",\n\t\t\t\"w.area_id as w_area_id\",\n\t\t\t\"w.sort_order as w_sort_order\",\n\t\t\t\"w.created_at as w_created_at\",\n\t\t]);\n}\n\ntype AreaWidgetRow = Awaited<\n\tReturnType<ReturnType<typeof selectAreasWithWidgets>[\"execute\"]>\n>[number];\n\n/** Group joined rows into areas, keeping row order for areas and widgets. */\nfunction groupAreaRows(rows: AreaWidgetRow[]): WidgetArea[] {\n\tconst areas = new Map<string, WidgetArea>();\n\tfor (const row of rows) {\n\t\tlet area = areas.get(row.a_id);\n\t\tif (!area) {\n\t\t\tarea = {\n\t\t\t\tid: row.a_id,\n\t\t\t\tname: row.a_name,\n\t\t\t\tlabel: row.a_label,\n\t\t\t\tdescription: row.a_description ?? undefined,\n\t\t\t\twidgets: [],\n\t\t\t};\n\t\t\tareas.set(row.a_id, area);\n\t\t}\n\t\tif (row.w_id === null) continue;\n\t\t// Every w_* column is non-null whenever w_id is set.\n\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- left-join row is non-null when w_id is set; see above\n\t\tconst widgetRow = {\n\t\t\tid: row.w_id,\n\t\t\ttype: row.w_type,\n\t\t\ttitle: row.w_title,\n\t\t\tcontent: row.w_content,\n\t\t\tmenu_name: row.w_menu_name,\n\t\t\tcomponent_id: row.w_component_id,\n\t\t\tcomponent_props: row.w_component_props,\n\t\t\tarea_id: row.w_area_id,\n\t\t\tsort_order: row.w_sort_order,\n\t\t\tcreated_at: row.w_created_at,\n\t\t} as WidgetRow;\n\t\tarea.widgets.push(rowToWidget(widgetRow));\n\t}\n\treturn [...areas.values()];\n}\n\n/**\n * Get a widget area by name with a Workers edge-cache hint.\n *\n * Use the returned `cacheHint` with `Astro.cache.set()` so pages that render\n * this widget area can be purged automatically when its widgets change.\n */\nexport async function getWidgetAreaWithCacheHint(name: string): Promise<{\n\tdata: WidgetArea | null;\n\tcacheHint: CacheHint;\n}> {\n\tconst data = await getWidgetArea(name);\n\treturn { data, cacheHint: { tags: [widgetAreaTag(name)] } };\n}\n\n/**\n * Get all widget areas with their widgets\n */\nexport async function getWidgetAreas(): Promise<WidgetArea[]> {\n\treturn cachedQuery({\n\t\tnamespace: CacheNamespace.WIDGETS,\n\t\tkey: \"areas\",\n\t\tload: async () => {\n\t\t\tconst db = await getDb();\n\t\t\tconst rows = await selectAreasWithWidgets(db)\n\t\t\t\t.orderBy(\"a.created_at\", \"asc\")\n\t\t\t\t.orderBy(\"a.id\", \"asc\")\n\t\t\t\t.orderBy(\"w.sort_order\", \"asc\")\n\t\t\t\t.execute();\n\t\t\treturn groupAreaRows(rows);\n\t\t},\n\t});\n}\n\n/**\n * Get available widget components (for admin UI)\n */\nexport function getWidgetComponents(): WidgetComponentDef[] {\n\treturn getComponentRegistry();\n}\n\n/**\n * Convert a widget row to the API type\n */\nexport function rowToWidget(row: WidgetRow): Widget {\n\tconst widget: Widget = {\n\t\tid: row.id,\n\t\ttype: row.type,\n\t\ttitle: row.title ?? undefined,\n\t};\n\n\t// Type-specific fields\n\tif (row.type === \"content\" && row.content) {\n\t\ttry {\n\t\t\twidget.content = JSON.parse(row.content);\n\t\t} catch {\n\t\t\t// Invalid JSON, ignore\n\t\t}\n\t}\n\n\tif (row.type === \"menu\" && row.menu_name) {\n\t\twidget.menuName = row.menu_name;\n\t}\n\n\tif (row.type === \"component\" && row.component_id) {\n\t\twidget.componentId = row.component_id;\n\t\tif (row.component_props) {\n\t\t\ttry {\n\t\t\t\twidget.componentProps = JSON.parse(row.component_props);\n\t\t\t} catch {\n\t\t\t\t// Invalid JSON, ignore\n\t\t\t}\n\t\t}\n\t}\n\n\treturn widget;\n}\n"],"mappings":";;;;;;;;;;AA2BA,eAAsB,cAAc,MAA0C;AAC7E,QAAO,cAAc,eAAe,QAAQ,YAAY;EACvD,MAAM,aAAa,iBAA+B,eAAe;AACjE,MAAI,WACH,KAAI;AAEH,WADc,MAAM,YACP,MAAM,SAAS,KAAK,SAAS,KAAK,IAAI;UAC5C;AAKT,SAAO,YAAY;GAClB,WAAW,eAAe;GAC1B,KAAK,QAAQ;GACb,MAAM,YAAY;AAMjB,WAAO,cAJM,MAAM,uBADR,MAAM,OAAO,CACqB,CAC3C,MAAM,UAAU,KAAK,KAAK,CAC1B,QAAQ,gBAAgB,MAAM,CAC9B,SAAS,CACe,CAAC,MAAM;;GAElC,CAAC;GACD;;;;;;AAOH,SAAS,uBAAuB,IAAsB;AACrD,QAAO,GACL,WAAW,4BAA4B,CACvC,SAAS,wBAAwB,aAAa,OAAO,CACrD,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;;;AAQJ,SAAS,cAAc,MAAqC;CAC3D,MAAM,wBAAQ,IAAI,KAAyB;AAC3C,MAAK,MAAM,OAAO,MAAM;EACvB,IAAI,OAAO,MAAM,IAAI,IAAI,KAAK;AAC9B,MAAI,CAAC,MAAM;AACV,UAAO;IACN,IAAI,IAAI;IACR,MAAM,IAAI;IACV,OAAO,IAAI;IACX,aAAa,IAAI,iBAAiB;IAClC,SAAS,EAAE;IACX;AACD,SAAM,IAAI,IAAI,MAAM,KAAK;;AAE1B,MAAI,IAAI,SAAS,KAAM;EAGvB,MAAM,YAAY;GACjB,IAAI,IAAI;GACR,MAAM,IAAI;GACV,OAAO,IAAI;GACX,SAAS,IAAI;GACb,WAAW,IAAI;GACf,cAAc,IAAI;GAClB,iBAAiB,IAAI;GACrB,SAAS,IAAI;GACb,YAAY,IAAI;GAChB,YAAY,IAAI;GAChB;AACD,OAAK,QAAQ,KAAK,YAAY,UAAU,CAAC;;AAE1C,QAAO,CAAC,GAAG,MAAM,QAAQ,CAAC;;;;;;;;AAS3B,eAAsB,2BAA2B,MAG9C;AAEF,QAAO;EAAE,MADI,MAAM,cAAc,KAAK;EACvB,WAAW,EAAE,MAAM,CAAC,cAAc,KAAK,CAAC,EAAE;EAAE;;;;;AAM5D,eAAsB,iBAAwC;AAC7D,QAAO,YAAY;EAClB,WAAW,eAAe;EAC1B,KAAK;EACL,MAAM,YAAY;AAOjB,UAAO,cALM,MAAM,uBADR,MAAM,OAAO,CACqB,CAC3C,QAAQ,gBAAgB,MAAM,CAC9B,QAAQ,QAAQ,MAAM,CACtB,QAAQ,gBAAgB,MAAM,CAC9B,SAAS,CACe;;EAE3B,CAAC;;;;;AAMH,SAAgB,sBAA4C;AAC3D,QAAOA,uBAAsB;;;;;AAM9B,SAAgB,YAAY,KAAwB;CACnD,MAAM,SAAiB;EACtB,IAAI,IAAI;EACR,MAAM,IAAI;EACV,OAAO,IAAI,SAAS;EACpB;AAGD,KAAI,IAAI,SAAS,aAAa,IAAI,QACjC,KAAI;AACH,SAAO,UAAU,KAAK,MAAM,IAAI,QAAQ;SACjC;AAKT,KAAI,IAAI,SAAS,UAAU,IAAI,UAC9B,QAAO,WAAW,IAAI;AAGvB,KAAI,IAAI,SAAS,eAAe,IAAI,cAAc;AACjD,SAAO,cAAc,IAAI;AACzB,MAAI,IAAI,gBACP,KAAI;AACH,UAAO,iBAAiB,KAAK,MAAM,IAAI,gBAAgB;UAChD;;AAMV,QAAO"}
@@ -1,6 +1,7 @@
1
- import { t as TaxonomyRepository } from "./taxonomy-C_C_LBAU.mjs";
2
- import { g as selectTaxonomyDefs, p as findTaxonomyStructure } from "./loader-CswroUbe.mjs";
3
- import { d as invalidateTermCache } from "./taxonomies-ChnU7Mc8.mjs";
1
+ import { n as localeMatches, r as localeOrder } from "./query-BFHjCzSh.mjs";
2
+ import { t as TaxonomyRepository } from "./taxonomy-CMI5fczd.mjs";
3
+ import { v as findTaxonomyStructure, x as selectTaxonomyDefs } from "./loader-DhnedqY4.mjs";
4
+ import { d as invalidateTermCache } from "./taxonomies-B__VmCKQ.mjs";
4
5
 
5
6
  //#region src/import/wxr-taxonomies.ts
6
7
  /**
@@ -151,7 +152,7 @@ async function ensureTermsBatch(db, state, descriptors, locale) {
151
152
  * argument).
152
153
  */
153
154
  async function findExistingTerms(db, descriptors, locale) {
154
- const { chunks, SQL_BATCH_SIZE } = await import("./chunks-xC4UD5-S.mjs").then((n) => n.r);
155
+ const { chunks, SQL_BATCH_SIZE } = await import("./chunks-DiW8VMwz.mjs").then((n) => n.r);
155
156
  const rows = [];
156
157
  const seenKeys = /* @__PURE__ */ new Set();
157
158
  for (const batch of chunks(descriptors, Math.floor(SQL_BATCH_SIZE / 2))) {
@@ -159,7 +160,7 @@ async function findExistingTerms(db, descriptors, locale) {
159
160
  "id",
160
161
  "name",
161
162
  "slug"
162
- ]).where((eb) => eb.or(batch.map((d) => eb.and([eb("name", "=", d.taxonomyName), eb("slug", "=", d.slug)])))).$if(locale !== void 0, (qb) => qb.where("locale", "=", locale)).orderBy("locale", "asc").execute();
163
+ ]).where((eb) => eb.or(batch.map((d) => eb.and([eb("name", "=", d.taxonomyName), eb("slug", "=", d.slug)])))).$if(locale !== void 0, (qb) => qb.where(localeMatches("locale", locale))).orderBy(locale !== void 0 ? localeOrder("locale", locale) : "locale", "asc").execute();
163
164
  for (const row of batchRows) {
164
165
  const key = termKey(row.name, row.slug);
165
166
  if (seenKeys.has(key)) continue;
@@ -450,4 +451,4 @@ async function mirrorTermsToLocales(db, plan, postLocales, canonicalLocale) {
450
451
 
451
452
  //#endregion
452
453
  export { preImportWxrTaxonomies as a, mirrorTermsToLocales as i, isWxrTaxonomyConflictError as n, setPostTermAssignmentsReplacing as o, loadTaxonomyPlanFromDb as r, attachPostTaxonomies as t };
453
- //# sourceMappingURL=wxr-taxonomies-RgRG0d5e.mjs.map
454
+ //# sourceMappingURL=wxr-taxonomies-DbJtWrWM.mjs.map