emdash 0.40.1 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1240) hide show
  1. package/dist/action-token-CbKDcPJi.mjs +26 -0
  2. package/dist/action-token-CbKDcPJi.mjs.map +1 -0
  3. package/dist/activation-PtniBLt9.mjs +382 -0
  4. package/dist/activation-PtniBLt9.mjs.map +1 -0
  5. package/dist/adapters-C_Tf5x90.d.mts +171 -0
  6. package/dist/adapters-C_Tf5x90.d.mts.map +1 -0
  7. package/dist/allowed-origins-U1z4TdEZ.mjs +116 -0
  8. package/dist/allowed-origins-U1z4TdEZ.mjs.map +1 -0
  9. package/dist/api/route-utils.d.mts +4 -4
  10. package/dist/api/route-utils.mjs +46 -45
  11. package/dist/api/route-utils.mjs.map +1 -1
  12. package/dist/api/schemas/index.d.mts +2 -2
  13. package/dist/api/schemas/index.mjs +10 -10
  14. package/dist/api-CXwQkV_m.mjs +5122 -0
  15. package/dist/api-CXwQkV_m.mjs.map +1 -0
  16. package/dist/api-tokens-89WlohEN.mjs +166 -0
  17. package/dist/api-tokens-89WlohEN.mjs.map +1 -0
  18. package/dist/apply-Do3KNnUk.mjs +1659 -0
  19. package/dist/apply-Do3KNnUk.mjs.map +1 -0
  20. package/dist/approvals-CAX9Yw33.mjs +460 -0
  21. package/dist/approvals-CAX9Yw33.mjs.map +1 -0
  22. package/dist/artifact-fetch-B9W4CEST.mjs +659 -0
  23. package/dist/artifact-fetch-B9W4CEST.mjs.map +1 -0
  24. package/dist/astro/index.d.mts +14 -14
  25. package/dist/astro/index.mjs +20 -24
  26. package/dist/astro/index.mjs.map +1 -1
  27. package/dist/astro/middleware/auth.d.mts +12 -12
  28. package/dist/astro/middleware/auth.mjs +10 -10
  29. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  30. package/dist/astro/middleware/redirect.mjs +7 -7
  31. package/dist/astro/middleware/request-context.mjs +3 -3
  32. package/dist/astro/middleware/setup.mjs +1 -1
  33. package/dist/astro/middleware.d.mts +12 -12
  34. package/dist/astro/middleware.mjs +109 -106
  35. package/dist/astro/middleware.mjs.map +1 -1
  36. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +14 -14
  37. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +14 -14
  38. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
  39. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  40. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +7 -7
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +17 -17
  42. package/dist/astro/routes/api/admin/byline-fields/index.mjs +17 -17
  43. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +17 -17
  44. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +23 -23
  45. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +23 -23
  46. package/dist/astro/routes/api/admin/bylines/index.mjs +23 -23
  47. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -18
  48. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
  49. package/dist/astro/routes/api/admin/comments/bulk.mjs +17 -17
  50. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
  51. package/dist/astro/routes/api/admin/comments/index.mjs +17 -17
  52. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  53. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  54. package/dist/astro/routes/api/admin/media-usage/activation.mjs +20 -20
  55. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +22 -22
  56. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +22 -22
  57. package/dist/astro/routes/api/admin/media-usage/progress.mjs +25 -25
  58. package/dist/astro/routes/api/admin/media-usage/repair.mjs +31 -31
  59. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +22 -22
  60. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +22 -22
  61. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
  62. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
  63. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +8 -8
  64. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +8 -8
  65. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +72 -68
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +7 -7
  68. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +71 -67
  69. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +72 -68
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +82 -78
  73. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/plugins/index.mjs +72 -68
  75. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +5 -5
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +71 -67
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +81 -77
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  81. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +71 -67
  82. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  83. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +72 -68
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +83 -79
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +9 -9
  88. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +74 -70
  89. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +7 -7
  91. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +72 -68
  92. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/updates.mjs +71 -67
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +6 -6
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +71 -67
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +5 -5
  99. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +71 -67
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +4 -4
  102. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +40 -40
  103. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +40 -40
  104. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +42 -42
  105. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +42 -42
  106. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +42 -42
  107. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +43 -43
  108. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +43 -43
  109. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +42 -42
  110. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +43 -43
  111. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +44 -44
  112. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +42 -42
  113. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +42 -42
  114. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +44 -44
  115. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +42 -42
  116. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +44 -44
  117. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +42 -42
  118. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +42 -42
  119. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +44 -44
  120. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +42 -42
  121. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +42 -42
  122. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +44 -44
  123. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +5 -5
  124. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +4 -4
  125. package/dist/astro/routes/api/admin/users/_id_/index.mjs +15 -15
  126. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
  127. package/dist/astro/routes/api/admin/users/index.mjs +14 -14
  128. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  129. package/dist/astro/routes/api/auth/invite/accept.mjs +4 -4
  130. package/dist/astro/routes/api/auth/invite/complete.mjs +18 -18
  131. package/dist/astro/routes/api/auth/invite/index.mjs +16 -16
  132. package/dist/astro/routes/api/auth/invite/register-options.mjs +17 -17
  133. package/dist/astro/routes/api/auth/logout.mjs +5 -5
  134. package/dist/astro/routes/api/auth/magic-link/send.mjs +18 -18
  135. package/dist/astro/routes/api/auth/magic-link/verify.mjs +14 -14
  136. package/dist/astro/routes/api/auth/me.mjs +15 -15
  137. package/dist/astro/routes/api/auth/mode.mjs +5 -5
  138. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  139. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  140. package/dist/astro/routes/api/auth/passkey/_id_.mjs +14 -14
  141. package/dist/astro/routes/api/auth/passkey/index.mjs +4 -4
  142. package/dist/astro/routes/api/auth/passkey/options.mjs +19 -19
  143. package/dist/astro/routes/api/auth/passkey/register/options.mjs +17 -17
  144. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +18 -18
  145. package/dist/astro/routes/api/auth/passkey/verify.mjs +18 -18
  146. package/dist/astro/routes/api/auth/signup/complete.mjs +18 -18
  147. package/dist/astro/routes/api/auth/signup/request.mjs +17 -17
  148. package/dist/astro/routes/api/auth/signup/verify.mjs +4 -4
  149. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  150. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -18
  151. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +5 -5
  152. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -17
  153. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
  154. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +17 -17
  155. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +5 -5
  156. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +11 -11
  157. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +31 -31
  158. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +17 -17
  159. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +1 -2
  160. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -1
  161. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +42 -53
  162. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  163. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +34 -29
  164. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  165. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
  166. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +5 -5
  167. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +17 -17
  168. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +25 -24
  169. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  170. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +5 -5
  171. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +17 -17
  172. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  173. package/dist/astro/routes/api/content/_collection_/_id_.mjs +18 -18
  174. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  175. package/dist/astro/routes/api/content/_collection_/authors.mjs +5 -5
  176. package/dist/astro/routes/api/content/_collection_/index.mjs +15 -15
  177. package/dist/astro/routes/api/content/_collection_/trash.mjs +15 -15
  178. package/dist/astro/routes/api/dashboard.mjs +10 -9
  179. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  180. package/dist/astro/routes/api/dev/emails.mjs +5 -5
  181. package/dist/astro/routes/api/health.mjs +6 -6
  182. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  183. package/dist/astro/routes/api/import/probe.mjs +23 -23
  184. package/dist/astro/routes/api/import/wordpress/analyze.mjs +6 -6
  185. package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -13
  186. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
  187. package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -12
  188. package/dist/astro/routes/api/import/wordpress/media.mjs +19 -19
  189. package/dist/astro/routes/api/import/wordpress/prepare.mjs +18 -18
  190. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -13
  191. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +28 -28
  192. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  193. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +23 -23
  194. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -13
  195. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +34 -34
  196. package/dist/astro/routes/api/manifest.mjs +6 -6
  197. package/dist/astro/routes/api/mcp.mjs +91 -91
  198. package/dist/astro/routes/api/media/_id_/confirm.mjs +19 -19
  199. package/dist/astro/routes/api/media/_id_/replace.mjs +16 -16
  200. package/dist/astro/routes/api/media/_id_/upload.mjs +9 -9
  201. package/dist/astro/routes/api/media/_id_/usage.mjs +33 -33
  202. package/dist/astro/routes/api/media/_id_.mjs +31 -31
  203. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +6 -6
  204. package/dist/astro/routes/api/media/file/_...key_.mjs +9 -9
  205. package/dist/astro/routes/api/media/folders/_id_.mjs +16 -16
  206. package/dist/astro/routes/api/media/folders/index.mjs +16 -16
  207. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +5 -5
  208. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +5 -5
  209. package/dist/astro/routes/api/media/providers/index.mjs +5 -5
  210. package/dist/astro/routes/api/media/upload-url.mjs +18 -18
  211. package/dist/astro/routes/api/media.mjs +35 -35
  212. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -17
  213. package/dist/astro/routes/api/menus/_name_/items.mjs +17 -17
  214. package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -17
  215. package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -17
  216. package/dist/astro/routes/api/menus/_name_.mjs +17 -17
  217. package/dist/astro/routes/api/menus/index.mjs +17 -17
  218. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  219. package/dist/astro/routes/api/oauth/device/authorize.d.mts +2 -1
  220. package/dist/astro/routes/api/oauth/device/authorize.d.mts.map +1 -1
  221. package/dist/astro/routes/api/oauth/device/authorize.mjs +23 -9
  222. package/dist/astro/routes/api/oauth/device/authorize.mjs.map +1 -1
  223. package/dist/astro/routes/api/oauth/device/code.mjs +11 -11
  224. package/dist/astro/routes/api/oauth/device/token.mjs +10 -10
  225. package/dist/astro/routes/api/oauth/register.mjs +5 -5
  226. package/dist/astro/routes/api/oauth/token/refresh.mjs +8 -8
  227. package/dist/astro/routes/api/oauth/token/revoke.mjs +8 -8
  228. package/dist/astro/routes/api/oauth/token.mjs +8 -8
  229. package/dist/astro/routes/api/openapi.json.mjs +20 -20
  230. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +11 -11
  231. package/dist/astro/routes/api/redirects/404s/index.mjs +19 -19
  232. package/dist/astro/routes/api/redirects/404s/summary.mjs +19 -19
  233. package/dist/astro/routes/api/redirects/_id_.mjs +19 -19
  234. package/dist/astro/routes/api/redirects/index.mjs +19 -19
  235. package/dist/astro/routes/api/relations/_id_/index.mjs +34 -29
  236. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  237. package/dist/astro/routes/api/relations/index.mjs +36 -31
  238. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  239. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +5 -5
  240. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
  241. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +71 -67
  242. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  243. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +71 -67
  244. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  245. package/dist/astro/routes/api/schema/block-types/index.mjs +71 -67
  246. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  247. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +73 -69
  248. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  249. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +71 -67
  250. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  251. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +71 -67
  252. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  253. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +71 -67
  254. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  255. package/dist/astro/routes/api/schema/collections/index.mjs +71 -67
  256. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  257. package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -67
  258. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  259. package/dist/astro/routes/api/schema/index.mjs +16 -16
  260. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +71 -67
  261. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  262. package/dist/astro/routes/api/schema/orphans/index.mjs +71 -67
  263. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  264. package/dist/astro/routes/api/search/enable.mjs +19 -19
  265. package/dist/astro/routes/api/search/index.mjs +18 -18
  266. package/dist/astro/routes/api/search/rebuild.mjs +19 -19
  267. package/dist/astro/routes/api/search/stats.mjs +9 -9
  268. package/dist/astro/routes/api/search/suggest.mjs +18 -18
  269. package/dist/astro/routes/api/sections/_slug_.mjs +18 -18
  270. package/dist/astro/routes/api/sections/index.mjs +18 -18
  271. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  272. package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
  273. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  274. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  275. package/dist/astro/routes/api/settings/email.mjs +6 -6
  276. package/dist/astro/routes/api/settings.mjs +21 -21
  277. package/dist/astro/routes/api/setup/admin-verify.mjs +19 -19
  278. package/dist/astro/routes/api/setup/admin.mjs +18 -18
  279. package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -39
  280. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  281. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  282. package/dist/astro/routes/api/setup/index.mjs +50 -44
  283. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  284. package/dist/astro/routes/api/setup/status.mjs +6 -6
  285. package/dist/astro/routes/api/snapshot.mjs +8 -8
  286. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -23
  287. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -23
  288. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -23
  289. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -23
  290. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -22
  291. package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -23
  292. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +36 -35
  293. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
  294. package/dist/astro/routes/api/taxonomies/index.mjs +23 -23
  295. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  296. package/dist/astro/routes/api/typegen.mjs +8 -8
  297. package/dist/astro/routes/api/visual-editing/action-token.mjs +6 -6
  298. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +19 -19
  299. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +4 -4
  300. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  301. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  302. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  303. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +16 -16
  304. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +19 -19
  305. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +19 -19
  306. package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -9
  307. package/dist/astro/routes/api/widget-areas/index.mjs +19 -19
  308. package/dist/astro/routes/api/widget-components.mjs +5 -5
  309. package/dist/astro/routes/robots.txt.mjs +6 -6
  310. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  311. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  312. package/dist/astro/types.d.mts +24 -18
  313. package/dist/astro/types.d.mts.map +1 -1
  314. package/dist/audit-CrgmE9LE.mjs +127 -0
  315. package/dist/audit-CrgmE9LE.mjs.map +1 -0
  316. package/dist/auth/providers/github.d.mts +1 -1
  317. package/dist/auth/providers/google.d.mts +1 -1
  318. package/dist/authoritative-records-C2YzIdbu.mjs +5172 -0
  319. package/dist/authoritative-records-C2YzIdbu.mjs.map +1 -0
  320. package/dist/authorize-WgdKF8QY.mjs +49 -0
  321. package/dist/authorize-WgdKF8QY.mjs.map +1 -0
  322. package/dist/backup-Ck8_lMO3.mjs +246 -0
  323. package/dist/backup-Ck8_lMO3.mjs.map +1 -0
  324. package/dist/block-types-BQ90asVI.mjs +132 -0
  325. package/dist/block-types-BQ90asVI.mjs.map +1 -0
  326. package/dist/block-values-ACFqgB1D.mjs +175 -0
  327. package/dist/block-values-ACFqgB1D.mjs.map +1 -0
  328. package/dist/bundle-Db1iNMv_.mjs +667 -0
  329. package/dist/bundle-Db1iNMv_.mjs.map +1 -0
  330. package/dist/byline-BayaYGoj.mjs +909 -0
  331. package/dist/byline-BayaYGoj.mjs.map +1 -0
  332. package/dist/byline-fields-B8HH-35f.mjs +254 -0
  333. package/dist/byline-fields-B8HH-35f.mjs.map +1 -0
  334. package/dist/byline-fields-hMPjf6Eu.mjs +123 -0
  335. package/dist/byline-fields-hMPjf6Eu.mjs.map +1 -0
  336. package/dist/byline-registry-B_EK_TQf.mjs +406 -0
  337. package/dist/byline-registry-B_EK_TQf.mjs.map +1 -0
  338. package/dist/bylines-DFAaFXWi.mjs +214 -0
  339. package/dist/bylines-DFAaFXWi.mjs.map +1 -0
  340. package/dist/bylines-DkIxUxmr.mjs +232 -0
  341. package/dist/bylines-DkIxUxmr.mjs.map +1 -0
  342. package/dist/cache-DkvhQ8XE.mjs +108 -0
  343. package/dist/cache-DkvhQ8XE.mjs.map +1 -0
  344. package/dist/canonical-CcSuuTlH.mjs +174 -0
  345. package/dist/canonical-CcSuuTlH.mjs.map +1 -0
  346. package/dist/capture-triggers-DJEoOTOq.mjs +362 -0
  347. package/dist/capture-triggers-DJEoOTOq.mjs.map +1 -0
  348. package/dist/challenge-store-CvBl81AQ.mjs +51 -0
  349. package/dist/challenge-store-CvBl81AQ.mjs.map +1 -0
  350. package/dist/checksum-CClweQzI.mjs +162 -0
  351. package/dist/checksum-CClweQzI.mjs.map +1 -0
  352. package/dist/chrome-tags-D5caJwwp.mjs +24 -0
  353. package/dist/chrome-tags-D5caJwwp.mjs.map +1 -0
  354. package/dist/chunks-DwBaj8aT.mjs +25 -0
  355. package/dist/chunks-DwBaj8aT.mjs.map +1 -0
  356. package/dist/cli/index.mjs +374 -761
  357. package/dist/cli/index.mjs.map +1 -1
  358. package/dist/client/cf-access.d.mts +1 -1
  359. package/dist/client/index.d.mts +32 -32
  360. package/dist/client/index.mjs +2 -2
  361. package/dist/collection-deletion-CLCdXsnV.mjs +436 -0
  362. package/dist/collection-deletion-CLCdXsnV.mjs.map +1 -0
  363. package/dist/collection-deletion-processor-hNw8x01F.mjs +217 -0
  364. package/dist/collection-deletion-processor-hNw8x01F.mjs.map +1 -0
  365. package/dist/collection-slugs-cache-CUuiduLq.mjs +85 -0
  366. package/dist/collection-slugs-cache-CUuiduLq.mjs.map +1 -0
  367. package/dist/comment-D2uvL63j.mjs +313 -0
  368. package/dist/comment-D2uvL63j.mjs.map +1 -0
  369. package/dist/comment-reaction-DevUuzg4.mjs +85 -0
  370. package/dist/comment-reaction-DevUuzg4.mjs.map +1 -0
  371. package/dist/comments-Cq0s7_hO.mjs +195 -0
  372. package/dist/comments-Cq0s7_hO.mjs.map +1 -0
  373. package/dist/comments-M4EDYAHw.mjs +99 -0
  374. package/dist/comments-M4EDYAHw.mjs.map +1 -0
  375. package/dist/components-CuIGwXMs.mjs +108 -0
  376. package/dist/components-CuIGwXMs.mjs.map +1 -0
  377. package/dist/config-52Ea5IWt.d.mts +39 -0
  378. package/dist/config-52Ea5IWt.d.mts.map +1 -0
  379. package/dist/config-CCz3xOLc.mjs +242 -0
  380. package/dist/config-CCz3xOLc.mjs.map +1 -0
  381. package/dist/config-D3d5Qudq.d.mts +6669 -0
  382. package/dist/config-D3d5Qudq.d.mts.map +1 -0
  383. package/dist/content-CbnufDsM.mjs +2018 -0
  384. package/dist/content-CbnufDsM.mjs.map +1 -0
  385. package/dist/content-list-query-D_7B1FE5.d.mts +26 -0
  386. package/dist/content-list-query-D_7B1FE5.d.mts.map +1 -0
  387. package/dist/content-policy-CYu6K1KB.mjs +46 -0
  388. package/dist/content-policy-CYu6K1KB.mjs.map +1 -0
  389. package/dist/content-repair-DlDUgFGp.mjs +442 -0
  390. package/dist/content-repair-DlDUgFGp.mjs.map +1 -0
  391. package/dist/context-CGQLA1-a.mjs +1922 -0
  392. package/dist/context-CGQLA1-a.mjs.map +1 -0
  393. package/dist/cron-c4D5C5Fx.mjs +284 -0
  394. package/dist/cron-c4D5C5Fx.mjs.map +1 -0
  395. package/dist/dashboard-CBq9kmOn.mjs +151 -0
  396. package/dist/dashboard-CBq9kmOn.mjs.map +1 -0
  397. package/dist/db/index.d.mts +3 -3
  398. package/dist/db/index.mjs +1 -1
  399. package/dist/db/libsql-migrations.d.mts +1 -1
  400. package/dist/db/libsql-migrations.mjs +4 -4
  401. package/dist/db/libsql.d.mts +1 -1
  402. package/dist/db/postgres-migrations.d.mts +1 -1
  403. package/dist/db/postgres-migrations.mjs +4 -4
  404. package/dist/db/postgres.d.mts +1 -1
  405. package/dist/db/sqlite-migrations.d.mts +1 -1
  406. package/dist/db/sqlite-migrations.mjs +4 -4
  407. package/dist/db/sqlite.d.mts +1 -1
  408. package/dist/db/sqlite.mjs +1 -1
  409. package/dist/default-DPsys51U.mjs +81 -0
  410. package/dist/default-DPsys51U.mjs.map +1 -0
  411. package/dist/deferred-tasks-CZ7rzBdo.d.mts +9 -0
  412. package/dist/deferred-tasks-CZ7rzBdo.d.mts.map +1 -0
  413. package/dist/dev-typegen-HRxwLRcT.mjs +29 -0
  414. package/dist/dev-typegen-HRxwLRcT.mjs.map +1 -0
  415. package/dist/device-flow-OcSqE9uY.mjs +521 -0
  416. package/dist/device-flow-OcSqE9uY.mjs.map +1 -0
  417. package/dist/digest-DVZ--cE9.mjs +194 -0
  418. package/dist/digest-DVZ--cE9.mjs.map +1 -0
  419. package/dist/direct-executor-DyjAqkpT.mjs +104 -0
  420. package/dist/direct-executor-DyjAqkpT.mjs.map +1 -0
  421. package/dist/dist-FPR93_xf.mjs +810 -0
  422. package/dist/dist-FPR93_xf.mjs.map +1 -0
  423. package/dist/email-console-DyQIgEnz.mjs +50 -0
  424. package/dist/email-console-DyQIgEnz.mjs.map +1 -0
  425. package/dist/email-locale-BYb16rVd.mjs +25 -0
  426. package/dist/email-locale-BYb16rVd.mjs.map +1 -0
  427. package/dist/emdash-runtime-CrzxJFmF.mjs +4214 -0
  428. package/dist/emdash-runtime-CrzxJFmF.mjs.map +1 -0
  429. package/dist/enrich-DBtCncE2.mjs +194 -0
  430. package/dist/enrich-DBtCncE2.mjs.map +1 -0
  431. package/dist/entry-lock-BN5y4YbO.d.mts +4481 -0
  432. package/dist/entry-lock-BN5y4YbO.d.mts.map +1 -0
  433. package/dist/entry-lock-BaRBHCsH.mjs +1173 -0
  434. package/dist/entry-lock-BaRBHCsH.mjs.map +1 -0
  435. package/dist/entry-lock-C6NcnZPV.mjs +163 -0
  436. package/dist/entry-lock-C6NcnZPV.mjs.map +1 -0
  437. package/dist/entry-locks-BTyQLdbC.mjs +167 -0
  438. package/dist/entry-locks-BTyQLdbC.mjs.map +1 -0
  439. package/dist/error-BfsNNrIE.mjs +90 -0
  440. package/dist/error-BfsNNrIE.mjs.map +1 -0
  441. package/dist/errors-BN1QAnEY.mjs +460 -0
  442. package/dist/errors-BN1QAnEY.mjs.map +1 -0
  443. package/dist/errors-Bt3goF8I.mjs +120 -0
  444. package/dist/errors-Bt3goF8I.mjs.map +1 -0
  445. package/dist/escape-BveidMa2.mjs +9 -0
  446. package/dist/escape-BveidMa2.mjs.map +1 -0
  447. package/dist/fence-Bb_IbCxI.mjs +162 -0
  448. package/dist/fence-Bb_IbCxI.mjs.map +1 -0
  449. package/dist/field-defs-cache-CsZctvbu.mjs +77 -0
  450. package/dist/field-defs-cache-CsZctvbu.mjs.map +1 -0
  451. package/dist/field-map-6m9rF49t.mjs +83 -0
  452. package/dist/field-map-6m9rF49t.mjs.map +1 -0
  453. package/dist/focal-point-CZ3d1wK5.mjs +23 -0
  454. package/dist/focal-point-CZ3d1wK5.mjs.map +1 -0
  455. package/dist/fts-manager-CCaZTp8y.mjs +443 -0
  456. package/dist/fts-manager-CCaZTp8y.mjs.map +1 -0
  457. package/dist/gc-xowRjczI.mjs +75 -0
  458. package/dist/gc-xowRjczI.mjs.map +1 -0
  459. package/dist/hash-COVK27Pc.mjs +37 -0
  460. package/dist/hash-COVK27Pc.mjs.map +1 -0
  461. package/dist/hook-result-CYSk0XFe.d.mts +31 -0
  462. package/dist/hook-result-CYSk0XFe.d.mts.map +1 -0
  463. package/dist/hreflang-CChPV7jx.mjs +105 -0
  464. package/dist/hreflang-CChPV7jx.mjs.map +1 -0
  465. package/dist/hreflang-DRslq3QI.d.mts +50 -0
  466. package/dist/hreflang-DRslq3QI.d.mts.map +1 -0
  467. package/dist/http-route-dispatch-CAdp2onn.mjs +339 -0
  468. package/dist/http-route-dispatch-CAdp2onn.mjs.map +1 -0
  469. package/dist/identity-NVTOOQyq.mjs +35 -0
  470. package/dist/identity-NVTOOQyq.mjs.map +1 -0
  471. package/dist/import-wpSO2N0x.mjs +2020 -0
  472. package/dist/import-wpSO2N0x.mjs.map +1 -0
  473. package/dist/index-CDs2wq4X.d.mts +623 -0
  474. package/dist/index-CDs2wq4X.d.mts.map +1 -0
  475. package/dist/index.d.mts +24 -24
  476. package/dist/index.mjs +103 -101
  477. package/dist/install-finalization-D9R9R-W8.mjs +58 -0
  478. package/dist/install-finalization-D9R9R-W8.mjs.map +1 -0
  479. package/dist/keys-Bck6LBfF.mjs +61 -0
  480. package/dist/keys-Bck6LBfF.mjs.map +1 -0
  481. package/dist/kinds-CYmRESWj.mjs +974 -0
  482. package/dist/kinds-CYmRESWj.mjs.map +1 -0
  483. package/dist/lifecycle-C815ZQfV.mjs +25 -0
  484. package/dist/lifecycle-C815ZQfV.mjs.map +1 -0
  485. package/dist/load-D99axixL.mjs +28 -0
  486. package/dist/load-D99axixL.mjs.map +1 -0
  487. package/dist/loader-CrRPfkHS.mjs +1197 -0
  488. package/dist/loader-CrRPfkHS.mjs.map +1 -0
  489. package/dist/loops-DMKlygqX.mjs +203 -0
  490. package/dist/loops-DMKlygqX.mjs.map +1 -0
  491. package/dist/manifest-builder-BQzCHNgB.mjs +189 -0
  492. package/dist/manifest-builder-BQzCHNgB.mjs.map +1 -0
  493. package/dist/manifest-schema-Ci2gmd0u.mjs +492 -0
  494. package/dist/manifest-schema-Ci2gmd0u.mjs.map +1 -0
  495. package/dist/media/image-endpoint.mjs +1 -1
  496. package/dist/media/index.d.mts +1 -1
  497. package/dist/media/index.mjs +4 -4
  498. package/dist/media/local-runtime.d.mts +14 -14
  499. package/dist/media/local-runtime.mjs +6 -6
  500. package/dist/media-BUQePMxP.mjs +373 -0
  501. package/dist/media-BUQePMxP.mjs.map +1 -0
  502. package/dist/media-DH8ibNlY.mjs +294 -0
  503. package/dist/media-DH8ibNlY.mjs.map +1 -0
  504. package/dist/media-OEIQ3bVc.mjs +408 -0
  505. package/dist/media-OEIQ3bVc.mjs.map +1 -0
  506. package/dist/media-allowlist-pYtaBA95.mjs +44 -0
  507. package/dist/media-allowlist-pYtaBA95.mjs.map +1 -0
  508. package/dist/media-folders-Bf8_s4de.mjs +210 -0
  509. package/dist/media-folders-Bf8_s4de.mjs.map +1 -0
  510. package/dist/media-url-C6klEuNd.mjs +43 -0
  511. package/dist/media-url-C6klEuNd.mjs.map +1 -0
  512. package/dist/media-usage-D7Y64m6v.mjs +1629 -0
  513. package/dist/media-usage-D7Y64m6v.mjs.map +1 -0
  514. package/dist/media-usage-activation-DrqbmgLA.mjs +78 -0
  515. package/dist/media-usage-activation-DrqbmgLA.mjs.map +1 -0
  516. package/dist/media-usage-work-DommYhYA.mjs +152 -0
  517. package/dist/media-usage-work-DommYhYA.mjs.map +1 -0
  518. package/dist/media-usage-work-HU63hNDu.mjs +586 -0
  519. package/dist/media-usage-work-HU63hNDu.mjs.map +1 -0
  520. package/dist/menus-BQfusWEC.mjs +3608 -0
  521. package/dist/menus-BQfusWEC.mjs.map +1 -0
  522. package/dist/menus-BtwjQt5s.mjs +753 -0
  523. package/dist/menus-BtwjQt5s.mjs.map +1 -0
  524. package/dist/menus-p_M1V7J_.mjs +139 -0
  525. package/dist/menus-p_M1V7J_.mjs.map +1 -0
  526. package/dist/migrations/index.d.mts +1 -1
  527. package/dist/migrations/index.mjs +3 -3
  528. package/dist/mime-C94qBG-P.mjs +36 -0
  529. package/dist/mime-C94qBG-P.mjs.map +1 -0
  530. package/dist/mode-DpYW3w6U.mjs +23 -0
  531. package/dist/mode-DpYW3w6U.mjs.map +1 -0
  532. package/dist/node-sqlite-compat-pWFw0lcc.mjs +46 -0
  533. package/dist/node-sqlite-compat-pWFw0lcc.mjs.map +1 -0
  534. package/dist/normalize-DduyxBjf.mjs +191 -0
  535. package/dist/normalize-DduyxBjf.mjs.map +1 -0
  536. package/dist/oauth-authorization-DAXsH1H9.mjs +274 -0
  537. package/dist/oauth-authorization-DAXsH1H9.mjs.map +1 -0
  538. package/dist/oauth-clients-DENiDQri.mjs +266 -0
  539. package/dist/oauth-clients-DENiDQri.mjs.map +1 -0
  540. package/dist/oauth-state-store-y8mEYVq9.mjs +50 -0
  541. package/dist/oauth-state-store-y8mEYVq9.mjs.map +1 -0
  542. package/dist/oauth-user-lookup-CtTYAy-O.mjs +26 -0
  543. package/dist/oauth-user-lookup-CtTYAy-O.mjs.map +1 -0
  544. package/dist/object-cache/memory.d.mts +1 -1
  545. package/dist/options-BYa1FgIM.d.mts +81 -0
  546. package/dist/options-BYa1FgIM.d.mts.map +1 -0
  547. package/dist/page/index.d.mts +2 -2
  548. package/dist/page/index.mjs +5 -5
  549. package/dist/parse-CORGGhHf.mjs +81 -0
  550. package/dist/parse-CORGGhHf.mjs.map +1 -0
  551. package/dist/parse-avNM1xWV.d.mts +168 -0
  552. package/dist/parse-avNM1xWV.d.mts.map +1 -0
  553. package/dist/passkey-config-Dih5YeIS.mjs +46 -0
  554. package/dist/passkey-config-Dih5YeIS.mjs.map +1 -0
  555. package/dist/paths-d51RFm8M.mjs +77 -0
  556. package/dist/paths-d51RFm8M.mjs.map +1 -0
  557. package/dist/patterns-CoqlXUvk.mjs +145 -0
  558. package/dist/patterns-CoqlXUvk.mjs.map +1 -0
  559. package/dist/placeholder-D2aksPMF.d.mts +306 -0
  560. package/dist/placeholder-D2aksPMF.d.mts.map +1 -0
  561. package/dist/plan-DqeZKuaR.mjs +135 -0
  562. package/dist/plan-DqeZKuaR.mjs.map +1 -0
  563. package/dist/plugin-test-runtime.d.mts +14 -14
  564. package/dist/plugin-test-runtime.mjs +110 -107
  565. package/dist/plugin-types.d.mts +2 -2
  566. package/dist/plugin-utils.d.mts +12 -12
  567. package/dist/plugins/adapt-sandbox-entry.d.mts +12 -12
  568. package/dist/plugins/adapt-sandbox-entry.mjs +3 -3
  569. package/dist/plugins/host.d.mts +5 -5
  570. package/dist/plugins/host.mjs +42 -41
  571. package/dist/plugins-Bb7oqjQA.mjs +277 -0
  572. package/dist/plugins-Bb7oqjQA.mjs.map +1 -0
  573. package/dist/policy-BcEqut3n.mjs +45 -0
  574. package/dist/policy-BcEqut3n.mjs.map +1 -0
  575. package/dist/portable-text-DXE8ymtD.mjs +307 -0
  576. package/dist/portable-text-DXE8ymtD.mjs.map +1 -0
  577. package/dist/preview-DEDWbwA_.mjs +107 -0
  578. package/dist/preview-DEDWbwA_.mjs.map +1 -0
  579. package/dist/protocol-BJbTzvwl.d.mts +61 -0
  580. package/dist/protocol-BJbTzvwl.d.mts.map +1 -0
  581. package/dist/public-submission-D9c9S14m.mjs +250 -0
  582. package/dist/public-submission-D9c9S14m.mjs.map +1 -0
  583. package/dist/public-url-CIRe-2T6.mjs +101 -0
  584. package/dist/public-url-CIRe-2T6.mjs.map +1 -0
  585. package/dist/query-BzifXlPS.mjs +1156 -0
  586. package/dist/query-BzifXlPS.mjs.map +1 -0
  587. package/dist/query-OzMJ6vJP.mjs +41 -0
  588. package/dist/query-OzMJ6vJP.mjs.map +1 -0
  589. package/dist/rate-limit-Csp60Vik.mjs +120 -0
  590. package/dist/rate-limit-Csp60Vik.mjs.map +1 -0
  591. package/dist/receipt-B-aU4hpJ.mjs +43 -0
  592. package/dist/receipt-B-aU4hpJ.mjs.map +1 -0
  593. package/dist/redirect-CDSw1sU3.mjs +17 -0
  594. package/dist/redirect-CDSw1sU3.mjs.map +1 -0
  595. package/dist/redirect-D1ArbO85.mjs +411 -0
  596. package/dist/redirect-D1ArbO85.mjs.map +1 -0
  597. package/dist/redirects-BjTwDTsV.mjs +148 -0
  598. package/dist/redirects-BjTwDTsV.mjs.map +1 -0
  599. package/dist/redirects-Ck50kH3n.mjs +446 -0
  600. package/dist/redirects-Ck50kH3n.mjs.map +1 -0
  601. package/dist/registry/testing.mjs +3 -3
  602. package/dist/registry-CFcNCayZ.mjs +6754 -0
  603. package/dist/registry-CFcNCayZ.mjs.map +1 -0
  604. package/dist/relations-Cfaa1fDl.mjs +776 -0
  605. package/dist/relations-Cfaa1fDl.mjs.map +1 -0
  606. package/dist/request-cache-iHRlHx1d.mjs +104 -0
  607. package/dist/request-cache-iHRlHx1d.mjs.map +1 -0
  608. package/dist/request-context.d.mts +1 -1
  609. package/dist/request-meta-D47mqyev.mjs +141 -0
  610. package/dist/request-meta-D47mqyev.mjs.map +1 -0
  611. package/dist/resolve-BPE8sMvx.mjs +99 -0
  612. package/dist/resolve-BPE8sMvx.mjs.map +1 -0
  613. package/dist/resolve-C0s1E_fH.mjs +199 -0
  614. package/dist/resolve-C0s1E_fH.mjs.map +1 -0
  615. package/dist/revision-j1p4-bOj.mjs +302 -0
  616. package/dist/revision-j1p4-bOj.mjs.map +1 -0
  617. package/dist/route-wire-C9PJV9aL.mjs +197 -0
  618. package/dist/route-wire-C9PJV9aL.mjs.map +1 -0
  619. package/dist/routes-lyYw0mMf.mjs +272 -0
  620. package/dist/routes-lyYw0mMf.mjs.map +1 -0
  621. package/dist/runner-B3eyB9Gb.mjs +6121 -0
  622. package/dist/runner-B3eyB9Gb.mjs.map +1 -0
  623. package/dist/runner-DoYH2Jcu.d.mts +68 -0
  624. package/dist/runner-DoYH2Jcu.d.mts.map +1 -0
  625. package/dist/runtime.d.mts +13 -13
  626. package/dist/runtime.mjs +3 -3
  627. package/dist/schema-BAayK46S.mjs +13 -0
  628. package/dist/schema-BAayK46S.mjs.map +1 -0
  629. package/dist/schema-Gqcl-8G4.mjs +815 -0
  630. package/dist/schema-Gqcl-8G4.mjs.map +1 -0
  631. package/dist/scopes-BqPOKoKf.mjs +34 -0
  632. package/dist/scopes-BqPOKoKf.mjs.map +1 -0
  633. package/dist/search-YJKPIEV6.mjs +448 -0
  634. package/dist/search-YJKPIEV6.mjs.map +1 -0
  635. package/dist/sections-BR_e-wK5.mjs +346 -0
  636. package/dist/sections-BR_e-wK5.mjs.map +1 -0
  637. package/dist/seed/index.d.mts +2 -2
  638. package/dist/seed/index.mjs +37 -31
  639. package/dist/seo/index.d.mts +3 -3
  640. package/dist/seo/index.mjs +22 -21
  641. package/dist/seo/index.mjs.map +1 -1
  642. package/dist/seo-Dsj8hy3j.mjs +114 -0
  643. package/dist/seo-Dsj8hy3j.mjs.map +1 -0
  644. package/dist/seo-XvH4LNNp.mjs +133 -0
  645. package/dist/seo-XvH4LNNp.mjs.map +1 -0
  646. package/dist/service-BsVG05gS.mjs +150 -0
  647. package/dist/service-BsVG05gS.mjs.map +1 -0
  648. package/dist/session-user-DgKbYrlj.mjs +51 -0
  649. package/dist/session-user-DgKbYrlj.mjs.map +1 -0
  650. package/dist/settings-CNPUntkh.mjs +51 -0
  651. package/dist/settings-CNPUntkh.mjs.map +1 -0
  652. package/dist/settings-D5EHi0Tk.mjs +439 -0
  653. package/dist/settings-D5EHi0Tk.mjs.map +1 -0
  654. package/dist/settings-DSfE7wOa.mjs +61 -0
  655. package/dist/settings-DSfE7wOa.mjs.map +1 -0
  656. package/dist/setup-complete-B8W8sJ9v.mjs +26 -0
  657. package/dist/setup-complete-B8W8sJ9v.mjs.map +1 -0
  658. package/dist/setup-nonce-DnSBP260.mjs +25 -0
  659. package/dist/setup-nonce-DnSBP260.mjs.map +1 -0
  660. package/dist/site-settings-NGzdrt7O.mjs +50 -0
  661. package/dist/site-settings-NGzdrt7O.mjs.map +1 -0
  662. package/dist/site-url-D6JB7tLW.mjs +16 -0
  663. package/dist/site-url-D6JB7tLW.mjs.map +1 -0
  664. package/dist/snapshot-CdcwwWAf.mjs +414 -0
  665. package/dist/snapshot-CdcwwWAf.mjs.map +1 -0
  666. package/dist/ssrf-Dv0_tRpo.mjs +406 -0
  667. package/dist/ssrf-Dv0_tRpo.mjs.map +1 -0
  668. package/dist/stage-CUjhED3P.mjs +662 -0
  669. package/dist/stage-CUjhED3P.mjs.map +1 -0
  670. package/dist/staged-C36IWXff.mjs +659 -0
  671. package/dist/staged-C36IWXff.mjs.map +1 -0
  672. package/dist/state-CKouMCSY.mjs +153 -0
  673. package/dist/state-CKouMCSY.mjs.map +1 -0
  674. package/dist/status-lzyj4Uu7.mjs +30 -0
  675. package/dist/status-lzyj4Uu7.mjs.map +1 -0
  676. package/dist/storage/local.d.mts +1 -1
  677. package/dist/storage/local.mjs +1 -1
  678. package/dist/storage/s3.d.mts +1 -1
  679. package/dist/storage/s3.mjs +1 -1
  680. package/dist/storage-query-B-cWcTjJ.d.mts +1594 -0
  681. package/dist/storage-query-B-cWcTjJ.d.mts.map +1 -0
  682. package/dist/tar-DsTXX6ch.mjs +449 -0
  683. package/dist/tar-DsTXX6ch.mjs.map +1 -0
  684. package/dist/target-DLQCwp_Z.mjs +27 -0
  685. package/dist/target-DLQCwp_Z.mjs.map +1 -0
  686. package/dist/taxonomies-BlAjr4BL.mjs +697 -0
  687. package/dist/taxonomies-BlAjr4BL.mjs.map +1 -0
  688. package/dist/taxonomies-Byyo7LOZ.mjs +939 -0
  689. package/dist/taxonomies-Byyo7LOZ.mjs.map +1 -0
  690. package/dist/taxonomy-CKDwM61Y.mjs +525 -0
  691. package/dist/taxonomy-CKDwM61Y.mjs.map +1 -0
  692. package/dist/tokens-BojXlk49.mjs +171 -0
  693. package/dist/tokens-BojXlk49.mjs.map +1 -0
  694. package/dist/transaction-DLPQWik1.mjs +29 -0
  695. package/dist/transaction-DLPQWik1.mjs.map +1 -0
  696. package/dist/transfer-XSTh2BCr.mjs +8706 -0
  697. package/dist/transfer-XSTh2BCr.mjs.map +1 -0
  698. package/dist/transfer-download-DkoCDA9d.mjs +33 -0
  699. package/dist/transfer-download-DkoCDA9d.mjs.map +1 -0
  700. package/dist/transfer-iQ26J-RT.mjs +166 -0
  701. package/dist/transfer-iQ26J-RT.mjs.map +1 -0
  702. package/dist/transformations-C7RQabKQ.mjs +196 -0
  703. package/dist/transformations-C7RQabKQ.mjs.map +1 -0
  704. package/dist/transport-D3RulfD6.mjs +136 -0
  705. package/dist/transport-D3RulfD6.mjs.map +1 -0
  706. package/dist/transport-DhlZlf4D.d.mts +42 -0
  707. package/dist/transport-DhlZlf4D.d.mts.map +1 -0
  708. package/dist/trusted-proxy-B6ECOZJc.mjs +51 -0
  709. package/dist/trusted-proxy-B6ECOZJc.mjs.map +1 -0
  710. package/dist/turnstile-lqUiY7lP.mjs +53 -0
  711. package/dist/turnstile-lqUiY7lP.mjs.map +1 -0
  712. package/dist/types-4Dn9bZhu.mjs +77 -0
  713. package/dist/types-4Dn9bZhu.mjs.map +1 -0
  714. package/dist/types-5LSo7PPx.d.mts +85 -0
  715. package/dist/types-5LSo7PPx.d.mts.map +1 -0
  716. package/dist/types-BQ3hwYJT.d.mts +896 -0
  717. package/dist/types-BQ3hwYJT.d.mts.map +1 -0
  718. package/dist/types-BYEk7qo3.d.mts +198 -0
  719. package/dist/types-BYEk7qo3.d.mts.map +1 -0
  720. package/dist/types-CJKsWVFR.mjs +199 -0
  721. package/dist/types-CJKsWVFR.mjs.map +1 -0
  722. package/dist/types-Ca_w8mmY.d.mts +363 -0
  723. package/dist/types-Ca_w8mmY.d.mts.map +1 -0
  724. package/dist/types-CkE41ZAG.mjs +18 -0
  725. package/dist/types-CkE41ZAG.mjs.map +1 -0
  726. package/dist/types-D0aJW2uR.d.mts +1641 -0
  727. package/dist/types-D0aJW2uR.d.mts.map +1 -0
  728. package/dist/types-DbpN4Qto.d.mts +372 -0
  729. package/dist/types-DbpN4Qto.d.mts.map +1 -0
  730. package/dist/types-ILDI1sdY.mjs +16 -0
  731. package/dist/types-ILDI1sdY.mjs.map +1 -0
  732. package/dist/types-OC5c-edM.mjs +22 -0
  733. package/dist/types-OC5c-edM.mjs.map +1 -0
  734. package/dist/types-aOOxRSx6.mjs +103 -0
  735. package/dist/types-aOOxRSx6.mjs.map +1 -0
  736. package/dist/types-m1WbUffD.d.mts +198 -0
  737. package/dist/types-m1WbUffD.d.mts.map +1 -0
  738. package/dist/types-uxLoPBio.d.mts +124 -0
  739. package/dist/types-uxLoPBio.d.mts.map +1 -0
  740. package/dist/types-we5uR-tV.d.mts +287 -0
  741. package/dist/types-we5uR-tV.d.mts.map +1 -0
  742. package/dist/upload-attempts-DduMy6B0.mjs +32 -0
  743. package/dist/upload-attempts-DduMy6B0.mjs.map +1 -0
  744. package/dist/url-pattern-B3EwxAAk.mjs +33 -0
  745. package/dist/url-pattern-B3EwxAAk.mjs.map +1 -0
  746. package/dist/user-ElwQjTQT.mjs +171 -0
  747. package/dist/user-ElwQjTQT.mjs.map +1 -0
  748. package/dist/utils-BlAXmfOG.mjs +439 -0
  749. package/dist/utils-BlAXmfOG.mjs.map +1 -0
  750. package/dist/validate-CH0X5b2c.d.mts +468 -0
  751. package/dist/validate-CH0X5b2c.d.mts.map +1 -0
  752. package/dist/validate-CfgRpcjA.mjs +492 -0
  753. package/dist/validate-CfgRpcjA.mjs.map +1 -0
  754. package/dist/validation-DvYJtv4k.mjs +218 -0
  755. package/dist/validation-DvYJtv4k.mjs.map +1 -0
  756. package/dist/version-DgYjhTud.mjs +9 -0
  757. package/dist/version-DgYjhTud.mjs.map +1 -0
  758. package/dist/version-Dq71scUb.mjs +7 -0
  759. package/dist/version-Dq71scUb.mjs.map +1 -0
  760. package/dist/widgets-ChFIj0be.mjs +126 -0
  761. package/dist/widgets-ChFIj0be.mjs.map +1 -0
  762. package/dist/wxr-taxonomies-CBZMp2YX.mjs +372 -0
  763. package/dist/wxr-taxonomies-CBZMp2YX.mjs.map +1 -0
  764. package/dist/wxr-taxonomies-DlKDpWN1.d.mts +34 -0
  765. package/dist/wxr-taxonomies-DlKDpWN1.d.mts.map +1 -0
  766. package/dist/zod-generator-DmTKI-Ig.mjs +426 -0
  767. package/dist/zod-generator-DmTKI-Ig.mjs.map +1 -0
  768. package/package.json +7 -6
  769. package/src/api/handlers/content.ts +593 -16
  770. package/src/api/handlers/device-flow.ts +74 -21
  771. package/src/api/handlers/manifest.ts +79 -5
  772. package/src/api/handlers/relations.ts +638 -157
  773. package/src/api/handlers/revision.ts +30 -0
  774. package/src/api/handlers/schema.ts +403 -1
  775. package/src/api/handlers/staged-references.ts +142 -0
  776. package/src/api/handlers/validate-references.ts +146 -0
  777. package/src/api/schemas/content.ts +13 -0
  778. package/src/api/schemas/relations.ts +54 -44
  779. package/src/api/schemas/schema.ts +14 -0
  780. package/src/astro/integration/routes.ts +15 -19
  781. package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +11 -54
  782. package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
  783. package/src/astro/routes/api/oauth/device/authorize.ts +33 -4
  784. package/src/astro/routes/api/relations/index.ts +4 -4
  785. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +6 -2
  786. package/src/astro/types.ts +5 -0
  787. package/src/cli/commands/export-seed.ts +510 -89
  788. package/src/components/WidgetArea.astro +3 -2
  789. package/src/database/migrations/086_relations_structural.ts +197 -0
  790. package/src/database/migrations/087_reference_field_relations.ts +407 -0
  791. package/src/database/migrations/runner.ts +4 -0
  792. package/src/database/reference-backfill.ts +141 -0
  793. package/src/database/repositories/content.ts +43 -8
  794. package/src/database/repositories/relation.ts +620 -208
  795. package/src/database/repositories/revision.ts +16 -0
  796. package/src/database/repositories/types.ts +38 -0
  797. package/src/database/transaction.ts +12 -1
  798. package/src/database/types.ts +14 -5
  799. package/src/emdash-runtime.ts +86 -11
  800. package/src/index.ts +10 -0
  801. package/src/loader.ts +169 -22
  802. package/src/query.ts +455 -25
  803. package/src/references/field-map.ts +115 -0
  804. package/src/references/resolve.ts +160 -0
  805. package/src/references/staged.ts +117 -0
  806. package/src/references/types.ts +16 -0
  807. package/src/registry/artifact-fetch.ts +45 -271
  808. package/src/schema/registry.ts +99 -24
  809. package/src/schema/types.ts +58 -0
  810. package/src/schema/zod-generator.ts +67 -1
  811. package/src/seed/apply.ts +519 -62
  812. package/src/seed/types.ts +36 -2
  813. package/src/seed/validate.ts +78 -2
  814. package/src/transfer/analyze/unique-keys.ts +3 -12
  815. package/src/transfer/analyze/validate.ts +65 -39
  816. package/src/transfer/analyze/values.ts +12 -1
  817. package/src/transfer/export/readers.ts +12 -8
  818. package/src/transfer/format/columns.ts +26 -6
  819. package/src/transfer/format/kinds.ts +21 -5
  820. package/src/transfer/import/context.ts +8 -1
  821. package/src/transfer/ops/package-index.ts +1 -1
  822. package/dist/action-token-DYwe4Pk0.mjs +0 -26
  823. package/dist/action-token-DYwe4Pk0.mjs.map +0 -1
  824. package/dist/activation-LOkDM5WT.mjs +0 -382
  825. package/dist/activation-LOkDM5WT.mjs.map +0 -1
  826. package/dist/adapters-B64LbYcB.d.mts +0 -171
  827. package/dist/adapters-B64LbYcB.d.mts.map +0 -1
  828. package/dist/allowed-origins-CHB8oZNM.mjs +0 -116
  829. package/dist/allowed-origins-CHB8oZNM.mjs.map +0 -1
  830. package/dist/api-CuyNEHZG.mjs +0 -4718
  831. package/dist/api-CuyNEHZG.mjs.map +0 -1
  832. package/dist/api-tokens-s4i4aUp_.mjs +0 -166
  833. package/dist/api-tokens-s4i4aUp_.mjs.map +0 -1
  834. package/dist/apply-npY1TAhG.mjs +0 -1366
  835. package/dist/apply-npY1TAhG.mjs.map +0 -1
  836. package/dist/approvals-CqMfNxak.mjs +0 -460
  837. package/dist/approvals-CqMfNxak.mjs.map +0 -1
  838. package/dist/artifact-fetch-DZMOGZ3-.mjs +0 -818
  839. package/dist/artifact-fetch-DZMOGZ3-.mjs.map +0 -1
  840. package/dist/astro/routes/api/relations/_id_/translations.d.mts +0 -8
  841. package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +0 -1
  842. package/dist/astro/routes/api/relations/_id_/translations.mjs +0 -47
  843. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +0 -1
  844. package/dist/audit-RfCugiSB.mjs +0 -127
  845. package/dist/audit-RfCugiSB.mjs.map +0 -1
  846. package/dist/authoritative-records-CoJvBXAD.mjs +0 -5172
  847. package/dist/authoritative-records-CoJvBXAD.mjs.map +0 -1
  848. package/dist/authorize-seCifOMJ.mjs +0 -49
  849. package/dist/authorize-seCifOMJ.mjs.map +0 -1
  850. package/dist/backup-BQRj3afm.mjs +0 -246
  851. package/dist/backup-BQRj3afm.mjs.map +0 -1
  852. package/dist/block-type-registry-DUI_3KxT.mjs +0 -6709
  853. package/dist/block-type-registry-DUI_3KxT.mjs.map +0 -1
  854. package/dist/block-types-BmZmLmAD.mjs +0 -132
  855. package/dist/block-types-BmZmLmAD.mjs.map +0 -1
  856. package/dist/block-values-C_VIPr5t.mjs +0 -175
  857. package/dist/block-values-C_VIPr5t.mjs.map +0 -1
  858. package/dist/byline-DYmkXqvo.mjs +0 -909
  859. package/dist/byline-DYmkXqvo.mjs.map +0 -1
  860. package/dist/byline-fields-D28AT-Fh.mjs +0 -123
  861. package/dist/byline-fields-D28AT-Fh.mjs.map +0 -1
  862. package/dist/byline-registry-gnKscbQX.mjs +0 -406
  863. package/dist/byline-registry-gnKscbQX.mjs.map +0 -1
  864. package/dist/bylines-BPwJqoYH.mjs +0 -232
  865. package/dist/bylines-BPwJqoYH.mjs.map +0 -1
  866. package/dist/bylines-ukLaYpVZ.mjs +0 -214
  867. package/dist/bylines-ukLaYpVZ.mjs.map +0 -1
  868. package/dist/cache-m7UEkRFV.mjs +0 -108
  869. package/dist/cache-m7UEkRFV.mjs.map +0 -1
  870. package/dist/canonical-YhEQezjg.mjs +0 -174
  871. package/dist/canonical-YhEQezjg.mjs.map +0 -1
  872. package/dist/capture-triggers-kJyl_yyM.mjs +0 -362
  873. package/dist/capture-triggers-kJyl_yyM.mjs.map +0 -1
  874. package/dist/challenge-store-ppU6Uv13.mjs +0 -51
  875. package/dist/challenge-store-ppU6Uv13.mjs.map +0 -1
  876. package/dist/checksum-B2IINIlN.mjs +0 -162
  877. package/dist/checksum-B2IINIlN.mjs.map +0 -1
  878. package/dist/chrome-tags-DApCQSIk.mjs +0 -24
  879. package/dist/chrome-tags-DApCQSIk.mjs.map +0 -1
  880. package/dist/chunks-Dms7Uxbt.mjs +0 -25
  881. package/dist/chunks-Dms7Uxbt.mjs.map +0 -1
  882. package/dist/collection-deletion-BIm28mo3.mjs +0 -436
  883. package/dist/collection-deletion-BIm28mo3.mjs.map +0 -1
  884. package/dist/collection-deletion-processor-Br6rxs3u.mjs +0 -217
  885. package/dist/collection-deletion-processor-Br6rxs3u.mjs.map +0 -1
  886. package/dist/collection-slugs-cache-CjGk__zp.mjs +0 -85
  887. package/dist/collection-slugs-cache-CjGk__zp.mjs.map +0 -1
  888. package/dist/comment-CrBl22OF.mjs +0 -313
  889. package/dist/comment-CrBl22OF.mjs.map +0 -1
  890. package/dist/comment-reaction-JEQ2Fpd8.mjs +0 -85
  891. package/dist/comment-reaction-JEQ2Fpd8.mjs.map +0 -1
  892. package/dist/comments-2ah9du9y.mjs +0 -195
  893. package/dist/comments-2ah9du9y.mjs.map +0 -1
  894. package/dist/comments-fHZ8ON9O.mjs +0 -99
  895. package/dist/comments-fHZ8ON9O.mjs.map +0 -1
  896. package/dist/components-CXbq7CSM.mjs +0 -108
  897. package/dist/components-CXbq7CSM.mjs.map +0 -1
  898. package/dist/config-BjEm_3xL.d.mts +0 -6537
  899. package/dist/config-BjEm_3xL.d.mts.map +0 -1
  900. package/dist/config-IhybvkIQ.mjs +0 -242
  901. package/dist/config-IhybvkIQ.mjs.map +0 -1
  902. package/dist/config-Py43JK9r.d.mts +0 -39
  903. package/dist/config-Py43JK9r.d.mts.map +0 -1
  904. package/dist/content-DFaIEDj9.mjs +0 -2281
  905. package/dist/content-DFaIEDj9.mjs.map +0 -1
  906. package/dist/content-list-query-Dra4Dalc.d.mts +0 -26
  907. package/dist/content-list-query-Dra4Dalc.d.mts.map +0 -1
  908. package/dist/content-policy-DFNw91-d.mjs +0 -46
  909. package/dist/content-policy-DFNw91-d.mjs.map +0 -1
  910. package/dist/content-repair-Q8IUrpLL.mjs +0 -442
  911. package/dist/content-repair-Q8IUrpLL.mjs.map +0 -1
  912. package/dist/context-BV_7t-Ua.mjs +0 -1921
  913. package/dist/context-BV_7t-Ua.mjs.map +0 -1
  914. package/dist/cron-7DCJwPXq.mjs +0 -284
  915. package/dist/cron-7DCJwPXq.mjs.map +0 -1
  916. package/dist/dashboard-BP-iJqpd.mjs +0 -151
  917. package/dist/dashboard-BP-iJqpd.mjs.map +0 -1
  918. package/dist/default-DQ6vsviu.mjs +0 -81
  919. package/dist/default-DQ6vsviu.mjs.map +0 -1
  920. package/dist/deferred-tasks-BPxXUB4x.d.mts +0 -9
  921. package/dist/deferred-tasks-BPxXUB4x.d.mts.map +0 -1
  922. package/dist/dev-typegen-CZaPLl3V.mjs +0 -29
  923. package/dist/dev-typegen-CZaPLl3V.mjs.map +0 -1
  924. package/dist/device-flow-CRd6DXmW.mjs +0 -466
  925. package/dist/device-flow-CRd6DXmW.mjs.map +0 -1
  926. package/dist/digest-BarSh-pN.mjs +0 -194
  927. package/dist/digest-BarSh-pN.mjs.map +0 -1
  928. package/dist/direct-executor-D2lNadwo.mjs +0 -104
  929. package/dist/direct-executor-D2lNadwo.mjs.map +0 -1
  930. package/dist/dist-BNwANFJR.mjs +0 -810
  931. package/dist/dist-BNwANFJR.mjs.map +0 -1
  932. package/dist/email-console-bJn3ctqA.mjs +0 -50
  933. package/dist/email-console-bJn3ctqA.mjs.map +0 -1
  934. package/dist/email-locale-CN6WAMx0.mjs +0 -25
  935. package/dist/email-locale-CN6WAMx0.mjs.map +0 -1
  936. package/dist/emdash-runtime-CtfnZmPi.mjs +0 -4186
  937. package/dist/emdash-runtime-CtfnZmPi.mjs.map +0 -1
  938. package/dist/enrich-Dl3kZ-lP.mjs +0 -194
  939. package/dist/enrich-Dl3kZ-lP.mjs.map +0 -1
  940. package/dist/entry-lock-BJYdBfXb.mjs +0 -1097
  941. package/dist/entry-lock-BJYdBfXb.mjs.map +0 -1
  942. package/dist/entry-lock-Cf5OoIgN.d.mts +0 -4368
  943. package/dist/entry-lock-Cf5OoIgN.d.mts.map +0 -1
  944. package/dist/entry-lock-DHQOxN7R.mjs +0 -163
  945. package/dist/entry-lock-DHQOxN7R.mjs.map +0 -1
  946. package/dist/entry-locks-D0foLdjQ.mjs +0 -167
  947. package/dist/entry-locks-D0foLdjQ.mjs.map +0 -1
  948. package/dist/error-CfvOHP0M.mjs +0 -90
  949. package/dist/error-CfvOHP0M.mjs.map +0 -1
  950. package/dist/errors-BF0_LFhW.mjs +0 -460
  951. package/dist/errors-BF0_LFhW.mjs.map +0 -1
  952. package/dist/errors-DgE1zJGG.mjs +0 -120
  953. package/dist/errors-DgE1zJGG.mjs.map +0 -1
  954. package/dist/escape-CuaZhZvL.mjs +0 -9
  955. package/dist/escape-CuaZhZvL.mjs.map +0 -1
  956. package/dist/fence-CMDXJYc_.mjs +0 -162
  957. package/dist/fence-CMDXJYc_.mjs.map +0 -1
  958. package/dist/field-defs-cache-HIgBbqZZ.mjs +0 -77
  959. package/dist/field-defs-cache-HIgBbqZZ.mjs.map +0 -1
  960. package/dist/focal-point-Gr34o-4o.mjs +0 -23
  961. package/dist/focal-point-Gr34o-4o.mjs.map +0 -1
  962. package/dist/fts-manager-S-K0laoS.mjs +0 -443
  963. package/dist/fts-manager-S-K0laoS.mjs.map +0 -1
  964. package/dist/gc-DjKY0Ay1.mjs +0 -75
  965. package/dist/gc-DjKY0Ay1.mjs.map +0 -1
  966. package/dist/hash-SDAW6zC-.mjs +0 -37
  967. package/dist/hash-SDAW6zC-.mjs.map +0 -1
  968. package/dist/hook-result-B5bXDgS2.d.mts +0 -31
  969. package/dist/hook-result-B5bXDgS2.d.mts.map +0 -1
  970. package/dist/hreflang-CbVI4paR.mjs +0 -105
  971. package/dist/hreflang-CbVI4paR.mjs.map +0 -1
  972. package/dist/hreflang-D5uNnsGJ.d.mts +0 -50
  973. package/dist/hreflang-D5uNnsGJ.d.mts.map +0 -1
  974. package/dist/http-route-dispatch-BitqzwMy.mjs +0 -339
  975. package/dist/http-route-dispatch-BitqzwMy.mjs.map +0 -1
  976. package/dist/identity-Be5kzutJ.mjs +0 -35
  977. package/dist/identity-Be5kzutJ.mjs.map +0 -1
  978. package/dist/import-YzfKCaco.mjs +0 -2020
  979. package/dist/import-YzfKCaco.mjs.map +0 -1
  980. package/dist/index-D-hdtLe8.d.mts +0 -623
  981. package/dist/index-D-hdtLe8.d.mts.map +0 -1
  982. package/dist/install-finalization-DfM1fj5x.mjs +0 -58
  983. package/dist/install-finalization-DfM1fj5x.mjs.map +0 -1
  984. package/dist/keys-yxLm5l35.mjs +0 -61
  985. package/dist/keys-yxLm5l35.mjs.map +0 -1
  986. package/dist/kinds-CRu_T5T5.mjs +0 -961
  987. package/dist/kinds-CRu_T5T5.mjs.map +0 -1
  988. package/dist/lifecycle-BzeGPeQ-.mjs +0 -25
  989. package/dist/lifecycle-BzeGPeQ-.mjs.map +0 -1
  990. package/dist/load-XgJiE6_3.mjs +0 -28
  991. package/dist/load-XgJiE6_3.mjs.map +0 -1
  992. package/dist/loader-BzqeR1ZN.mjs +0 -1086
  993. package/dist/loader-BzqeR1ZN.mjs.map +0 -1
  994. package/dist/loops-BQSzv5Zn.mjs +0 -203
  995. package/dist/loops-BQSzv5Zn.mjs.map +0 -1
  996. package/dist/manifest-builder-BmSAOOEF.mjs +0 -189
  997. package/dist/manifest-builder-BmSAOOEF.mjs.map +0 -1
  998. package/dist/manifest-schema-CY3zng_M.mjs +0 -492
  999. package/dist/manifest-schema-CY3zng_M.mjs.map +0 -1
  1000. package/dist/media-CPXTbb1R.mjs +0 -373
  1001. package/dist/media-CPXTbb1R.mjs.map +0 -1
  1002. package/dist/media-JXRWDhw3.mjs +0 -294
  1003. package/dist/media-JXRWDhw3.mjs.map +0 -1
  1004. package/dist/media-Pu1L6xir.mjs +0 -408
  1005. package/dist/media-Pu1L6xir.mjs.map +0 -1
  1006. package/dist/media-allowlist-BSoa9Vvm.mjs +0 -44
  1007. package/dist/media-allowlist-BSoa9Vvm.mjs.map +0 -1
  1008. package/dist/media-folders-BE0oo2eX.mjs +0 -210
  1009. package/dist/media-folders-BE0oo2eX.mjs.map +0 -1
  1010. package/dist/media-url-jArBpzIG.mjs +0 -43
  1011. package/dist/media-url-jArBpzIG.mjs.map +0 -1
  1012. package/dist/media-usage-De-zeR9E.mjs +0 -1629
  1013. package/dist/media-usage-De-zeR9E.mjs.map +0 -1
  1014. package/dist/media-usage-activation-HKp7zk7W.mjs +0 -78
  1015. package/dist/media-usage-activation-HKp7zk7W.mjs.map +0 -1
  1016. package/dist/media-usage-work-C2OZLCAd.mjs +0 -586
  1017. package/dist/media-usage-work-C2OZLCAd.mjs.map +0 -1
  1018. package/dist/media-usage-work-DwUNbgvS.mjs +0 -152
  1019. package/dist/media-usage-work-DwUNbgvS.mjs.map +0 -1
  1020. package/dist/menus-BM7BPLOb.mjs +0 -139
  1021. package/dist/menus-BM7BPLOb.mjs.map +0 -1
  1022. package/dist/menus-Cm68rsAq.mjs +0 -3608
  1023. package/dist/menus-Cm68rsAq.mjs.map +0 -1
  1024. package/dist/menus-ITeAbcIF.mjs +0 -753
  1025. package/dist/menus-ITeAbcIF.mjs.map +0 -1
  1026. package/dist/mime-ChLqYwDk.mjs +0 -36
  1027. package/dist/mime-ChLqYwDk.mjs.map +0 -1
  1028. package/dist/mode-CCuKXUci.mjs +0 -23
  1029. package/dist/mode-CCuKXUci.mjs.map +0 -1
  1030. package/dist/node-sqlite-compat-CONMsl-x.mjs +0 -46
  1031. package/dist/node-sqlite-compat-CONMsl-x.mjs.map +0 -1
  1032. package/dist/normalize-CO2P8-iE.mjs +0 -191
  1033. package/dist/normalize-CO2P8-iE.mjs.map +0 -1
  1034. package/dist/oauth-authorization-DlMIL5_h.mjs +0 -274
  1035. package/dist/oauth-authorization-DlMIL5_h.mjs.map +0 -1
  1036. package/dist/oauth-clients-Djq9r_KP.mjs +0 -266
  1037. package/dist/oauth-clients-Djq9r_KP.mjs.map +0 -1
  1038. package/dist/oauth-state-store-BbjnZXNC.mjs +0 -50
  1039. package/dist/oauth-state-store-BbjnZXNC.mjs.map +0 -1
  1040. package/dist/oauth-user-lookup-vue9a64A.mjs +0 -26
  1041. package/dist/oauth-user-lookup-vue9a64A.mjs.map +0 -1
  1042. package/dist/options-SQCHQCPH.d.mts +0 -81
  1043. package/dist/options-SQCHQCPH.d.mts.map +0 -1
  1044. package/dist/parse-CVgO-Qai.d.mts +0 -168
  1045. package/dist/parse-CVgO-Qai.d.mts.map +0 -1
  1046. package/dist/parse-DY6OD1j_.mjs +0 -81
  1047. package/dist/parse-DY6OD1j_.mjs.map +0 -1
  1048. package/dist/passkey-config-X_H8128a.mjs +0 -46
  1049. package/dist/passkey-config-X_H8128a.mjs.map +0 -1
  1050. package/dist/paths-JxokKIbr.mjs +0 -77
  1051. package/dist/paths-JxokKIbr.mjs.map +0 -1
  1052. package/dist/patterns-BhAvqO0S.mjs +0 -145
  1053. package/dist/patterns-BhAvqO0S.mjs.map +0 -1
  1054. package/dist/placeholder-MSEd8gty.d.mts +0 -306
  1055. package/dist/placeholder-MSEd8gty.d.mts.map +0 -1
  1056. package/dist/plan-xjcWrAah.mjs +0 -135
  1057. package/dist/plan-xjcWrAah.mjs.map +0 -1
  1058. package/dist/plugins-DUXUt8B9.mjs +0 -277
  1059. package/dist/plugins-DUXUt8B9.mjs.map +0 -1
  1060. package/dist/policy-CUvwAARc.mjs +0 -45
  1061. package/dist/policy-CUvwAARc.mjs.map +0 -1
  1062. package/dist/portable-text-5O_ZGUjB.mjs +0 -307
  1063. package/dist/portable-text-5O_ZGUjB.mjs.map +0 -1
  1064. package/dist/preview-CIUcPYr6.mjs +0 -107
  1065. package/dist/preview-CIUcPYr6.mjs.map +0 -1
  1066. package/dist/protocol-B97DZaFr.d.mts +0 -61
  1067. package/dist/protocol-B97DZaFr.d.mts.map +0 -1
  1068. package/dist/public-submission-BFBUrqst.mjs +0 -250
  1069. package/dist/public-submission-BFBUrqst.mjs.map +0 -1
  1070. package/dist/public-url-Bn7U0D7-.mjs +0 -101
  1071. package/dist/public-url-Bn7U0D7-.mjs.map +0 -1
  1072. package/dist/query-B48peoRT.mjs +0 -890
  1073. package/dist/query-B48peoRT.mjs.map +0 -1
  1074. package/dist/query-C4IH0uhR.mjs +0 -41
  1075. package/dist/query-C4IH0uhR.mjs.map +0 -1
  1076. package/dist/rate-limit-BZ6nybgc.mjs +0 -120
  1077. package/dist/rate-limit-BZ6nybgc.mjs.map +0 -1
  1078. package/dist/receipt-B4wJj5Jq.mjs +0 -43
  1079. package/dist/receipt-B4wJj5Jq.mjs.map +0 -1
  1080. package/dist/redirect-B29UjdUn.mjs +0 -411
  1081. package/dist/redirect-B29UjdUn.mjs.map +0 -1
  1082. package/dist/redirect-Cd1E7VUt.mjs +0 -17
  1083. package/dist/redirect-Cd1E7VUt.mjs.map +0 -1
  1084. package/dist/redirects-Ca2MPfEG.mjs +0 -446
  1085. package/dist/redirects-Ca2MPfEG.mjs.map +0 -1
  1086. package/dist/redirects-Cv9apQKj.mjs +0 -148
  1087. package/dist/redirects-Cv9apQKj.mjs.map +0 -1
  1088. package/dist/relation-M4NUCb0b.mjs +0 -334
  1089. package/dist/relation-M4NUCb0b.mjs.map +0 -1
  1090. package/dist/relations-CCif47Oq.mjs +0 -403
  1091. package/dist/relations-CCif47Oq.mjs.map +0 -1
  1092. package/dist/relations-CK9CYUyr.mjs +0 -310
  1093. package/dist/relations-CK9CYUyr.mjs.map +0 -1
  1094. package/dist/request-cache-DzLYKm_x.mjs +0 -104
  1095. package/dist/request-cache-DzLYKm_x.mjs.map +0 -1
  1096. package/dist/request-meta-sZXt3sRo.mjs +0 -141
  1097. package/dist/request-meta-sZXt3sRo.mjs.map +0 -1
  1098. package/dist/resolve-2WbQsCvT.mjs +0 -199
  1099. package/dist/resolve-2WbQsCvT.mjs.map +0 -1
  1100. package/dist/route-wire--1hLuACz.mjs +0 -197
  1101. package/dist/route-wire--1hLuACz.mjs.map +0 -1
  1102. package/dist/routes-vrR95WR6.mjs +0 -272
  1103. package/dist/routes-vrR95WR6.mjs.map +0 -1
  1104. package/dist/runner-1y4J9fJB.mjs +0 -5742
  1105. package/dist/runner-1y4J9fJB.mjs.map +0 -1
  1106. package/dist/runner-D5_LzKXI.d.mts +0 -68
  1107. package/dist/runner-D5_LzKXI.d.mts.map +0 -1
  1108. package/dist/schema-BABiRdsH.mjs +0 -13
  1109. package/dist/schema-BABiRdsH.mjs.map +0 -1
  1110. package/dist/schema-Du3MzCG0.mjs +0 -446
  1111. package/dist/schema-Du3MzCG0.mjs.map +0 -1
  1112. package/dist/scopes-Dbk-ElhT.mjs +0 -34
  1113. package/dist/scopes-Dbk-ElhT.mjs.map +0 -1
  1114. package/dist/search-Bt1PL1jf.mjs +0 -448
  1115. package/dist/search-Bt1PL1jf.mjs.map +0 -1
  1116. package/dist/sections-Ddptx_o9.mjs +0 -346
  1117. package/dist/sections-Ddptx_o9.mjs.map +0 -1
  1118. package/dist/seo-CZT2oLtT.mjs +0 -114
  1119. package/dist/seo-CZT2oLtT.mjs.map +0 -1
  1120. package/dist/seo-D5w3-Azy.mjs +0 -133
  1121. package/dist/seo-D5w3-Azy.mjs.map +0 -1
  1122. package/dist/service-DuykXPyW.mjs +0 -150
  1123. package/dist/service-DuykXPyW.mjs.map +0 -1
  1124. package/dist/session-user-BhaVp8w0.mjs +0 -51
  1125. package/dist/session-user-BhaVp8w0.mjs.map +0 -1
  1126. package/dist/settings-B4vDl1fK.mjs +0 -439
  1127. package/dist/settings-B4vDl1fK.mjs.map +0 -1
  1128. package/dist/settings-DYidIB26.mjs +0 -61
  1129. package/dist/settings-DYidIB26.mjs.map +0 -1
  1130. package/dist/settings-Dyj6v8C4.mjs +0 -51
  1131. package/dist/settings-Dyj6v8C4.mjs.map +0 -1
  1132. package/dist/setup-complete-bOogcHWG.mjs +0 -26
  1133. package/dist/setup-complete-bOogcHWG.mjs.map +0 -1
  1134. package/dist/setup-nonce-0EGuKM4s.mjs +0 -25
  1135. package/dist/setup-nonce-0EGuKM4s.mjs.map +0 -1
  1136. package/dist/site-settings-DOgRUoFX.mjs +0 -50
  1137. package/dist/site-settings-DOgRUoFX.mjs.map +0 -1
  1138. package/dist/site-url-BU_bbxwj.mjs +0 -16
  1139. package/dist/site-url-BU_bbxwj.mjs.map +0 -1
  1140. package/dist/snapshot-PawoX-WG.mjs +0 -414
  1141. package/dist/snapshot-PawoX-WG.mjs.map +0 -1
  1142. package/dist/ssrf-CJUnJymJ.mjs +0 -406
  1143. package/dist/ssrf-CJUnJymJ.mjs.map +0 -1
  1144. package/dist/stage-DgrBz_du.mjs +0 -662
  1145. package/dist/stage-DgrBz_du.mjs.map +0 -1
  1146. package/dist/state-DDiPySSG.mjs +0 -153
  1147. package/dist/state-DDiPySSG.mjs.map +0 -1
  1148. package/dist/status-DZKIG4a9.mjs +0 -30
  1149. package/dist/status-DZKIG4a9.mjs.map +0 -1
  1150. package/dist/storage-query-FXJH5pI8.d.mts +0 -1581
  1151. package/dist/storage-query-FXJH5pI8.d.mts.map +0 -1
  1152. package/dist/tar-_1AgTYFu.mjs +0 -449
  1153. package/dist/tar-_1AgTYFu.mjs.map +0 -1
  1154. package/dist/target-_7pn2Gbg.mjs +0 -27
  1155. package/dist/target-_7pn2Gbg.mjs.map +0 -1
  1156. package/dist/taxonomies-C1IwNe8Q.mjs +0 -697
  1157. package/dist/taxonomies-C1IwNe8Q.mjs.map +0 -1
  1158. package/dist/taxonomies-C_XMoRcX.mjs +0 -939
  1159. package/dist/taxonomies-C_XMoRcX.mjs.map +0 -1
  1160. package/dist/taxonomy-C3Fu1YeH.mjs +0 -525
  1161. package/dist/taxonomy-C3Fu1YeH.mjs.map +0 -1
  1162. package/dist/tokens-u78jETkX.mjs +0 -171
  1163. package/dist/tokens-u78jETkX.mjs.map +0 -1
  1164. package/dist/transaction-BcJO4Tmc.mjs +0 -29
  1165. package/dist/transaction-BcJO4Tmc.mjs.map +0 -1
  1166. package/dist/transfer-DIGvR9Af.mjs +0 -166
  1167. package/dist/transfer-DIGvR9Af.mjs.map +0 -1
  1168. package/dist/transfer-DgeCvHnj.mjs +0 -8675
  1169. package/dist/transfer-DgeCvHnj.mjs.map +0 -1
  1170. package/dist/transfer-download-Pml7RMio.mjs +0 -33
  1171. package/dist/transfer-download-Pml7RMio.mjs.map +0 -1
  1172. package/dist/transformations-9gfpwY65.mjs +0 -196
  1173. package/dist/transformations-9gfpwY65.mjs.map +0 -1
  1174. package/dist/transport-BIfH7_hx.d.mts +0 -42
  1175. package/dist/transport-BIfH7_hx.d.mts.map +0 -1
  1176. package/dist/transport-DKWIq53q.mjs +0 -136
  1177. package/dist/transport-DKWIq53q.mjs.map +0 -1
  1178. package/dist/trusted-proxy-tKiVtyTD.mjs +0 -51
  1179. package/dist/trusted-proxy-tKiVtyTD.mjs.map +0 -1
  1180. package/dist/turnstile-DpsoyOfg.mjs +0 -53
  1181. package/dist/turnstile-DpsoyOfg.mjs.map +0 -1
  1182. package/dist/types-B4sUC2p1.d.mts +0 -198
  1183. package/dist/types-B4sUC2p1.d.mts.map +0 -1
  1184. package/dist/types-B7Lmsh1E.d.mts +0 -887
  1185. package/dist/types-B7Lmsh1E.d.mts.map +0 -1
  1186. package/dist/types-BZakh7Ym.mjs +0 -22
  1187. package/dist/types-BZakh7Ym.mjs.map +0 -1
  1188. package/dist/types-B_CppEmv.d.mts +0 -264
  1189. package/dist/types-B_CppEmv.d.mts.map +0 -1
  1190. package/dist/types-BcrBrE6-.mjs +0 -159
  1191. package/dist/types-BcrBrE6-.mjs.map +0 -1
  1192. package/dist/types-BkUg2yHx.mjs +0 -92
  1193. package/dist/types-BkUg2yHx.mjs.map +0 -1
  1194. package/dist/types-CAZgq9fO.d.mts +0 -124
  1195. package/dist/types-CAZgq9fO.d.mts.map +0 -1
  1196. package/dist/types-Cd-O03VG.d.mts +0 -363
  1197. package/dist/types-Cd-O03VG.d.mts.map +0 -1
  1198. package/dist/types-Cr-Kg-3D.d.mts +0 -1641
  1199. package/dist/types-Cr-Kg-3D.d.mts.map +0 -1
  1200. package/dist/types-D2fvWd1i.d.mts +0 -359
  1201. package/dist/types-D2fvWd1i.d.mts.map +0 -1
  1202. package/dist/types-D7HUsguf.mjs +0 -77
  1203. package/dist/types-D7HUsguf.mjs.map +0 -1
  1204. package/dist/types-DA1Te3Oy.d.mts +0 -198
  1205. package/dist/types-DA1Te3Oy.d.mts.map +0 -1
  1206. package/dist/types-DhV6Q5bP.mjs +0 -18
  1207. package/dist/types-DhV6Q5bP.mjs.map +0 -1
  1208. package/dist/types-DnnVSl6Y.d.mts +0 -85
  1209. package/dist/types-DnnVSl6Y.d.mts.map +0 -1
  1210. package/dist/types-VT4-BugW.mjs +0 -16
  1211. package/dist/types-VT4-BugW.mjs.map +0 -1
  1212. package/dist/upload-attempts-B68ZGNu9.mjs +0 -32
  1213. package/dist/upload-attempts-B68ZGNu9.mjs.map +0 -1
  1214. package/dist/url-pattern-CCeZMGOh.mjs +0 -33
  1215. package/dist/url-pattern-CCeZMGOh.mjs.map +0 -1
  1216. package/dist/user-DDSL-sGw.mjs +0 -171
  1217. package/dist/user-DDSL-sGw.mjs.map +0 -1
  1218. package/dist/utils-DdhmO9w9.mjs +0 -439
  1219. package/dist/utils-DdhmO9w9.mjs.map +0 -1
  1220. package/dist/validate-CHosPEhs.mjs +0 -453
  1221. package/dist/validate-CHosPEhs.mjs.map +0 -1
  1222. package/dist/validate-CM79QXYE.d.mts +0 -432
  1223. package/dist/validate-CM79QXYE.d.mts.map +0 -1
  1224. package/dist/validation-BFecQczG.mjs +0 -218
  1225. package/dist/validation-BFecQczG.mjs.map +0 -1
  1226. package/dist/version-BRZXVifl.mjs +0 -9
  1227. package/dist/version-BRZXVifl.mjs.map +0 -1
  1228. package/dist/version-DXsxRrob.mjs +0 -7
  1229. package/dist/version-DXsxRrob.mjs.map +0 -1
  1230. package/dist/widgets-WdV72brA.mjs +0 -126
  1231. package/dist/widgets-WdV72brA.mjs.map +0 -1
  1232. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts +0 -34
  1233. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts.map +0 -1
  1234. package/dist/wxr-taxonomies-DP6ESgMN.mjs +0 -372
  1235. package/dist/wxr-taxonomies-DP6ESgMN.mjs.map +0 -1
  1236. package/dist/zod-generator-D6uE4WiS.mjs +0 -389
  1237. package/dist/zod-generator-D6uE4WiS.mjs.map +0 -1
  1238. package/src/astro/routes/api/relations/[id]/translations.ts +0 -33
  1239. /package/dist/{api-tokens-CE1ECIg0.mjs → api-tokens-FaG1zPsj.mjs} +0 -0
  1240. /package/dist/{ssrf-DpBH7aOt.mjs → ssrf-DZOt8Qof.mjs} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations-Cfaa1fDl.mjs","names":["isRecord"],"sources":["../src/api/handlers/validate-references.ts","../src/api/handlers/relations.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { requestCached } from \"../../request-cache.js\";\nimport type { ApiResult } from \"../types.js\";\n\nexport interface ReferenceFieldConstraints {\n\t/** Field slug — how the entry API addresses the selection. */\n\tslug: string;\n\t/** Relation slug the field binds to. */\n\trelation: string;\n\t/** Relation id, for the reads that address the link table directly. */\n\trelationId: string | null;\n\t/** Which end of the relation the field's own collection sits on. */\n\trelationSide: \"parent\" | \"child\";\n\t/** How many entries this side of the relation may hold. `null` is unlimited. */\n\tmaxSelected: number | null;\n\t/** How many this field's selection may hand each entry it selects. */\n\tmaxOpposite: number | null;\n\trequired: boolean;\n}\n\nfunction validationError(message: string): ApiResult<never> {\n\treturn { success: false, error: { code: \"VALIDATION_ERROR\", message } };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\n/**\n * Every reference field on a collection that is bound to a relation, by field\n * slug — the key the entry API takes a selection under.\n */\nexport function referenceFieldConstraints(\n\tdb: Kysely<Database>,\n\tcollection: string,\n): Promise<Map<string, ReferenceFieldConstraints>> {\n\treturn requestCached(`reference-field-constraints:${collection}`, async () => {\n\t\tconst fields = await db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.innerJoin(\"_emdash_collections\", \"_emdash_collections.id\", \"_emdash_fields.collection_id\")\n\t\t\t.select([\"_emdash_fields.slug\", \"_emdash_fields.required\", \"_emdash_fields.validation\"])\n\t\t\t.where(\"_emdash_collections.slug\", \"=\", collection)\n\t\t\t.where(\"_emdash_fields.type\", \"=\", \"reference\")\n\t\t\t.execute();\n\n\t\t// Cardinality lives on the relation, not the field: with both ends of a\n\t\t// relation bindable, two fields carrying their own limits could disagree\n\t\t// about one edge set. The field contributes only which end it views.\n\t\tconst relations = await db\n\t\t\t.selectFrom(\"_emdash_relations\")\n\t\t\t.select([\"id\", \"slug\", \"max_children_per_parent\", \"max_parents_per_child\"])\n\t\t\t.execute();\n\t\tconst limits = new Map(relations.map((r) => [r.slug, r]));\n\n\t\tconst constraints = new Map<string, ReferenceFieldConstraints>();\n\t\tfor (const field of fields) {\n\t\t\tif (!field.validation) continue;\n\n\t\t\tlet parsed: unknown;\n\t\t\ttry {\n\t\t\t\tparsed = JSON.parse(field.validation);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!isRecord(parsed) || typeof parsed.relation !== \"string\") continue;\n\n\t\t\tconst relation = limits.get(parsed.relation);\n\t\t\tconst relationSide = parsed.relationSide === \"child\" ? \"child\" : \"parent\";\n\t\t\tconst onChildSide = relationSide === \"child\";\n\n\t\t\tconstraints.set(field.slug, {\n\t\t\t\tslug: field.slug,\n\t\t\t\trelation: parsed.relation,\n\t\t\t\trelationId: relation?.id ?? null,\n\t\t\t\trelationSide,\n\t\t\t\tmaxSelected: onChildSide\n\t\t\t\t\t? (relation?.max_parents_per_child ?? null)\n\t\t\t\t\t: (relation?.max_children_per_parent ?? null),\n\t\t\t\tmaxOpposite: onChildSide\n\t\t\t\t\t? (relation?.max_children_per_parent ?? null)\n\t\t\t\t\t: (relation?.max_parents_per_child ?? null),\n\t\t\t\trequired: field.required === 1,\n\t\t\t});\n\t\t}\n\t\treturn constraints;\n\t});\n}\n\n/**\n * The field viewing one end of a relation, for the relation-scoped routes, which\n * address a relation rather than a field. At most one field binds each\n * (relation, side), so this is unambiguous.\n */\nexport function constraintsForRelationSide(\n\tconstraints: Map<string, ReferenceFieldConstraints>,\n\trelation: string,\n\tside: \"parent\" | \"child\",\n): ReferenceFieldConstraints | undefined {\n\tfor (const field of constraints.values()) {\n\t\tif (field.relation === relation && field.relationSide === side) return field;\n\t}\n\treturn undefined;\n}\n\nexport function validateReferenceSelection(\n\tconstraints: ReferenceFieldConstraints,\n\tchildIds: string[],\n): ApiResult<true> {\n\tconst max = constraints.maxSelected;\n\tif (max !== null && childIds.length > max) {\n\t\treturn validationError(\n\t\t\tmax === 1\n\t\t\t\t? `Field '${constraints.slug}' accepts a single reference, received ${childIds.length}.`\n\t\t\t\t: `Field '${constraints.slug}' accepts at most ${max} references, received ${childIds.length}.`,\n\t\t);\n\t}\n\tif (constraints.required && childIds.length === 0) {\n\t\treturn validationError(\n\t\t\t`Field '${constraints.slug}' is required and must reference at least one entry.`,\n\t\t);\n\t}\n\treturn { success: true, data: true };\n}\n\nexport async function validateRequiredReferencesPresent(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\treferences: Record<string, string[]> | undefined,\n\ttranslationOf: string | undefined,\n): Promise<ApiResult<true>> {\n\t// References belong to a translation group, so a new locale row inherits\n\t// the source group's existing edges when its payload omits them.\n\tif (translationOf) return { success: true, data: true };\n\n\tconst constraints = await referenceFieldConstraints(db, collection);\n\tfor (const field of constraints.values()) {\n\t\tif (!field.required) continue;\n\t\tif (references && Object.hasOwn(references, field.slug)) continue;\n\t\treturn validationError(\n\t\t\t`Field '${field.slug}' is required and must reference at least one entry.`,\n\t\t);\n\t}\n\treturn { success: true, data: true };\n}\n","import type { Kysely } from \"kysely\";\n\nimport { ContentRepository } from \"../../database/repositories/content.js\";\nimport {\n\tRelationRepository,\n\ttype ContentReference,\n\ttype CreateRelationInput,\n\ttype Relation,\n\ttype UpdateRelationInput,\n} from \"../../database/repositories/relation.js\";\nimport { RevisionRepository } from \"../../database/repositories/revision.js\";\nimport { InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { ContentItem } from \"../../database/repositories/types.js\";\nimport { withTransaction } from \"../../database/transaction.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { invalidateCollectionCache } from \"../../object-cache/index.js\";\nimport {\n\tpageStagedGroups,\n\treadStagedReferences,\n\ttype PageOfGroups,\n} from \"../../references/staged.js\";\nimport { requestCached } from \"../../request-cache.js\";\nimport { invalidateSchemaCache } from \"../../schema/index.js\";\nimport { SchemaRegistry } from \"../../schema/registry.js\";\nimport type { ApiResult } from \"../types.js\";\nimport {\n\tconstraintsForRelationSide,\n\treferenceFieldConstraints,\n\tvalidateReferenceSelection,\n\ttype ReferenceFieldConstraints,\n} from \"./validate-references.js\";\n\n/** Map an edge-read failure: a bad pagination cursor is a 400 client error,\n * everything else is the generic 500-shaped reference-read error. */\nfunction referencesGetError(error: unknown): ApiResult<never> {\n\tif (error instanceof InvalidCursorError) {\n\t\treturn { success: false, error: { code: \"INVALID_CURSOR\", message: error.message } };\n\t}\n\treturn {\n\t\tsuccess: false,\n\t\terror: { code: \"REFERENCES_GET_ERROR\", message: \"Failed to get references\" },\n\t};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\n/** True for SQLite UNIQUE / Postgres unique_violation messages (matches the\n * fingerprint used in the content handlers). Narrow enough not to catch NOT\n * NULL / CHECK violations whose messages also say \"constraint\". */\nfunction isUniqueViolation(error: unknown): boolean {\n\tconst message = error instanceof Error ? error.message.toLowerCase() : \"\";\n\treturn message.includes(\"unique constraint failed\") || message.includes(\"duplicate key\");\n}\n\nexport async function handleRelationCreate(\n\tdb: Kysely<Database>,\n\tinput: CreateRelationInput,\n): Promise<ApiResult<{ relation: Relation }>> {\n\ttry {\n\t\tconst repo = new RelationRepository(db);\n\n\t\t// Invariant: a relation must point at collections that exist. There is no\n\t\t// SQL FK (the edge endpoints are content translation_groups, which\n\t\t// precludes one), so a ghost collection would yield a\n\t\t// structurally-valid-but-permanently-useless relation.\n\t\tconst registry = new SchemaRegistry(db);\n\t\tfor (const collection of [input.parentCollection, input.childCollection]) {\n\t\t\tif (!(await registry.getCollection(collection))) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"COLLECTION_NOT_FOUND\",\n\t\t\t\t\t\tmessage: `Collection '${collection}' not found`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tconst relation = await repo.create(input);\n\t\treturn { success: true, data: { relation } };\n\t} catch (error) {\n\t\tif (isUniqueViolation(error)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"CONFLICT\",\n\t\t\t\t\tmessage: \"A relation with this slug already exists\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"RELATION_CREATE_ERROR\", message: \"Failed to create relation\" },\n\t\t};\n\t}\n}\n\n/**\n * A relation plus what deleting it would take with it: the reference fields\n * that view it, and how many links it holds. Both delete dialogs enumerate\n * these before the user confirms.\n */\nexport interface RelationWithUsage extends Relation {\n\tboundFields: BoundField[];\n\tlinkCount: number;\n}\n\nexport async function handleRelationGet(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ relation: RelationWithUsage }>> {\n\ttry {\n\t\tconst repo = new RelationRepository(db);\n\t\tconst relation = await repo.findById(id);\n\t\tif (!relation) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Relation not found\" } };\n\t\t}\n\t\tconst [boundFields, edgeCounts] = await Promise.all([\n\t\t\tfieldsBoundToRelation(db, relation.slug),\n\t\t\trepo.countEdgesByRelation(),\n\t\t]);\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { relation: { ...relation, boundFields, linkCount: edgeCounts.get(relation.id) ?? 0 } },\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"RELATION_GET_ERROR\", message: \"Failed to get relation\" },\n\t\t};\n\t}\n}\n\n/**\n * List relations, optionally only those `collection` takes part in.\n *\n * The admin's relation picker filters this way: a reference field can only bind\n * to a relation with its own collection on one end.\n */\nexport async function handleRelationList(\n\tdb: Kysely<Database>,\n\topts: { collection?: string } = {},\n): Promise<ApiResult<{ relations: RelationWithUsage[] }>> {\n\ttry {\n\t\tconst repo = new RelationRepository(db);\n\t\tconst [relations, boundByRelation, edgeCounts] = await Promise.all([\n\t\t\topts.collection ? repo.findForCollection(opts.collection) : repo.list(),\n\t\t\tfieldsBoundByRelation(db),\n\t\t\trepo.countEdgesByRelation(),\n\t\t]);\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\trelations: relations.map((relation) => ({\n\t\t\t\t\t...relation,\n\t\t\t\t\tboundFields: boundByRelation.get(relation.slug) ?? [],\n\t\t\t\t\tlinkCount: edgeCounts.get(relation.id) ?? 0,\n\t\t\t\t})),\n\t\t\t},\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"RELATION_LIST_ERROR\", message: \"Failed to list relations\" },\n\t\t};\n\t}\n}\n\nexport async function handleRelationUpdate(\n\tdb: Kysely<Database>,\n\tid: string,\n\tinput: UpdateRelationInput,\n): Promise<ApiResult<{ relation: Relation }>> {\n\ttry {\n\t\tconst repo = new RelationRepository(db);\n\t\tconst relation = await repo.update(id, input);\n\t\tif (!relation) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Relation not found\" } };\n\t\t}\n\t\treturn { success: true, data: { relation } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"RELATION_UPDATE_ERROR\", message: \"Failed to update relation\" },\n\t\t};\n\t}\n}\n\n/** A reference field that views a relation, and which end it views it from. */\nexport interface BoundField {\n\tcollectionSlug: string;\n\tfieldSlug: string;\n\tside: \"parent\" | \"child\";\n}\n\n/**\n * Every reference field on the site, grouped by the slug of the relation it\n * binds.\n *\n * Filtered in JS rather than through `json_extract`: `_emdash_fields` holds one\n * row per field on the whole site, and the reference-typed subset of that is\n * small enough that a scan beats a dialect-specific JSON path. Grouping the\n * whole set in one pass also keeps the relations list to a single scan instead\n * of one per row.\n */\nexport async function fieldsBoundByRelation(\n\tdb: Kysely<Database>,\n): Promise<Map<string, BoundField[]>> {\n\tconst rows = await db\n\t\t.selectFrom(\"_emdash_fields\")\n\t\t.innerJoin(\"_emdash_collections\", \"_emdash_collections.id\", \"_emdash_fields.collection_id\")\n\t\t.select([\n\t\t\t\"_emdash_fields.slug as fieldSlug\",\n\t\t\t\"_emdash_collections.slug as collectionSlug\",\n\t\t\t\"_emdash_fields.validation as validation\",\n\t\t])\n\t\t.where(\"_emdash_fields.type\", \"=\", \"reference\")\n\t\t.execute();\n\n\tconst byRelation = new Map<string, BoundField[]>();\n\tfor (const row of rows) {\n\t\tif (!row.validation) continue;\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(row.validation);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!isRecord(parsed) || typeof parsed.relation !== \"string\") continue;\n\t\tconst bound: BoundField = {\n\t\t\tcollectionSlug: row.collectionSlug,\n\t\t\tfieldSlug: row.fieldSlug,\n\t\t\tside: parsed.relationSide === \"child\" ? \"child\" : \"parent\",\n\t\t};\n\t\tconst list = byRelation.get(parsed.relation);\n\t\tif (list) list.push(bound);\n\t\telse byRelation.set(parsed.relation, [bound]);\n\t}\n\treturn byRelation;\n}\n\n/** Every reference field bound to one relation, across both of its ends. */\nexport async function fieldsBoundToRelation(\n\tdb: Kysely<Database>,\n\trelationSlug: string,\n): Promise<BoundField[]> {\n\treturn (await fieldsBoundByRelation(db)).get(relationSlug) ?? [];\n}\n\n/**\n * Delete a relation, the reference fields bound to it, and its edges.\n *\n * A relation is only ever deleted deliberately — from the relations admin page,\n * or by the checkbox on a field delete — and it cannot leave a field pointing at\n * nothing, so the fields go with it either way. Callers show the count first;\n * `deletedFields` reports what actually went.\n *\n * Order matters: fields first, then the relation row and its edges. On D1\n * `withTransaction` degrades to sequential statements, so an interrupted run\n * leaves a relation with fewer bound fields — visible on the relations page and\n * finishable — rather than fields pointing at a relation that no longer exists.\n */\nexport async function handleRelationDelete(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ deleted: true; deletedFields: string[] }>> {\n\ttry {\n\t\tconst repo = new RelationRepository(db);\n\t\tconst relation = await repo.findById(id);\n\t\tif (!relation) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Relation not found\" } };\n\t\t}\n\n\t\tconst bound = await fieldsBoundToRelation(db, relation.slug);\n\n\t\tconst deleted = await withTransaction(db, async (trx) => {\n\t\t\tconst registry = new SchemaRegistry(trx);\n\t\t\tfor (const field of bound) {\n\t\t\t\tawait registry.deleteField(field.collectionSlug, field.fieldSlug);\n\t\t\t}\n\t\t\treturn new RelationRepository(trx).delete(id);\n\t\t});\n\n\t\tif (!deleted) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Relation not found\" } };\n\t\t}\n\n\t\tfor (const collection of new Set(bound.map((f) => f.collectionSlug))) {\n\t\t\tinvalidateCollectionCache(collection);\n\t\t\tinvalidateSchemaCache(collection);\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tdeleted: true,\n\t\t\t\tdeletedFields: bound.map((f) => `${f.collectionSlug}.${f.fieldSlug}`),\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\"Relation delete error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"RELATION_DELETE_ERROR\", message: \"Failed to delete relation\" },\n\t\t};\n\t}\n}\n\nexport type EntryRef = {\n\tid: string;\n\tslug: string | null;\n\tcollection: string;\n\t/**\n\t * Display label sourced from the collection's configured `titleField`, then\n\t * `title`, then `name` — `null` when none is set, leaving the client to fall\n\t * back to slug/id. Mirrors the admin's `getEntryTitle`.\n\t */\n\ttitle: string | null;\n\t/** The actual locale of the resolved variant — see `pickVariant`. */\n\tlocale: string | null;\n\t/**\n\t * The edge's target: the translation group `id` was resolved from. Stable\n\t * across locales, unlike `id`, so callers comparing a ref against a content\n\t * row (the admin's picker) match the entry rather than one of its variants.\n\t */\n\ttranslationGroup: string | null;\n\tsortOrder?: number;\n};\n\n/**\n * Display title for a resolved entry: the collection's configured `titleField`,\n * then `title`, then `name`, else null.\n */\nfunction entryTitle(data: Record<string, unknown>, titleField?: string): string | null {\n\tif (titleField) {\n\t\tconst configured = data[titleField];\n\t\tif (typeof configured === \"string\" && configured.length > 0) return configured;\n\t}\n\tif (typeof data.title === \"string\" && data.title.length > 0) return data.title;\n\tif (typeof data.name === \"string\" && data.name.length > 0) return data.name;\n\treturn null;\n}\n\n/**\n * The collection's configured `titleField`, memoized for the request: a single\n * content read hydrates every reference field, and several of them commonly\n * target the same collection.\n */\nexport async function getReferenceTitleField(\n\tdb: Kysely<Database>,\n\tcollection: string,\n): Promise<string | undefined> {\n\treturn requestCached(`reference-title-field:${collection}`, async () => {\n\t\tconst row = await db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select(\"title_field\")\n\t\t\t.where(\"slug\", \"=\", collection)\n\t\t\t.executeTakeFirst();\n\t\treturn row?.title_field ?? undefined;\n\t});\n}\n\n/** Resolve a relation from an id OR its slug. */\nasync function resolveRelation(\n\trepo: RelationRepository,\n\tidOrSlug: string,\n): Promise<Relation | null> {\n\treturn (await repo.findById(idOrSlug)) ?? (await repo.findBySlug(idOrSlug));\n}\n\n/**\n * Pick the locale variant matching `locale`, falling back to the first entry\n * (lowest locale code). The fallback is intentional — an edge is keyed by\n * `translation_group`, so a referenced entry that exists only in another locale\n * is still a real reference — but the returned ref carries the variant's actual\n * `locale` so callers never mistake a fallback for the requested locale.\n */\nfunction pickVariant(items: ContentItem[], locale: string | null): ContentItem | undefined {\n\treturn items.find((i) => i.locale === locale) ?? items[0];\n}\n\n/**\n * Resolve edge groups to loadable entries in `collection` at `locale`.\n * Dangling groups (no surviving entry) are skipped — cleanup is a later slice.\n *\n * All groups are loaded in one batched query (chunked at `SQL_BATCH_SIZE`)\n * rather than a `findTranslations` per edge, so a parent with N children costs\n * a constant number of queries, not N+1. Edge order (the caller's `sort_order`)\n * is preserved by iterating `edges`.\n *\n * `includeDrafts` is false for callers without `content:read_drafts`: the load\n * is restricted to published entries so a draft/scheduled entry referenced by an\n * edge is skipped exactly like a dangling one, never leaking its id/slug/locale.\n */\nexport function resolveEntries(\n\tcontent: ContentRepository,\n\tcollection: string,\n\tedges: ContentReference[],\n\tpick: (e: ContentReference) => string,\n\tlocale: string | null,\n\tincludeDrafts: boolean,\n\ttitleField?: string,\n): Promise<EntryRef[]> {\n\treturn resolveGroupSelection(\n\t\tcontent,\n\t\tcollection,\n\t\tedges.map((edge) => ({ group: pick(edge), sortOrder: edge.sortOrder })),\n\t\tlocale,\n\t\tincludeDrafts,\n\t\ttitleField,\n\t);\n}\n\n/**\n * `resolveEntries` for a selection that has no links behind it yet — a pending\n * one staged in a draft revision, which is already a list of translation groups\n * in the order the editor chose. Position stands in for the `sort_order` the\n * links will carry once it is published.\n */\nexport function resolveEntryGroups(\n\tcontent: ContentRepository,\n\tcollection: string,\n\tgroups: string[],\n\tlocale: string | null,\n\tincludeDrafts: boolean,\n\ttitleField?: string,\n): Promise<EntryRef[]> {\n\treturn resolveGroupSelection(\n\t\tcontent,\n\t\tcollection,\n\t\tgroups.map((group, index) => ({ group, sortOrder: index })),\n\t\tlocale,\n\t\tincludeDrafts,\n\t\ttitleField,\n\t);\n}\n\nasync function resolveGroupSelection(\n\tcontent: ContentRepository,\n\tcollection: string,\n\tselection: Array<{ group: string; sortOrder: number }>,\n\tlocale: string | null,\n\tincludeDrafts: boolean,\n\ttitleField?: string,\n): Promise<EntryRef[]> {\n\tconst all = await content.findTranslationsForGroups(\n\t\tcollection,\n\t\tselection.map((entry) => entry.group),\n\t\t{ publishedOnly: !includeDrafts },\n\t);\n\n\t// Group the flat variant list by translation_group so each selected entry can\n\t// pick its own locale variant.\n\tconst variantsByGroup = new Map<string, ContentItem[]>();\n\tfor (const item of all) {\n\t\tif (item.translationGroup == null) continue;\n\t\tconst list = variantsByGroup.get(item.translationGroup);\n\t\tif (list) list.push(item);\n\t\telse variantsByGroup.set(item.translationGroup, [item]);\n\t}\n\n\tconst refs: EntryRef[] = [];\n\tfor (const selected of selection) {\n\t\tconst variants = variantsByGroup.get(selected.group);\n\t\tif (!variants) continue;\n\t\tconst entry = pickVariant(variants, locale);\n\t\tif (!entry) continue;\n\t\trefs.push({\n\t\t\tid: entry.id,\n\t\t\tslug: entry.slug,\n\t\t\tcollection,\n\t\t\ttitle: entryTitle(entry.data, titleField),\n\t\t\tlocale: entry.locale,\n\t\t\ttranslationGroup: entry.translationGroup,\n\t\t\tsortOrder: selected.sortOrder,\n\t\t});\n\t}\n\treturn refs;\n}\n\n/** Pagination inputs for the edge read endpoints. */\nexport type PageOptions = { limit?: number; cursor?: string };\n\n/**\n * The page of a pending selection this end stages, when there is one.\n *\n * These routes address a relation and a side; a staged selection is keyed by the\n * field slug the entry API takes it under, so the field viewing this end is what\n * connects them. Returns undefined when the caller may not see drafts, the entry\n * has no draft, or the draft stages nothing for this field — all of which mean\n * the published links are the answer.\n */\nasync function stagedPageFor(\n\tdb: Kysely<Database>,\n\toptions: {\n\t\tcollection: string;\n\t\trelationSlug: string;\n\t\tside: \"parent\" | \"child\";\n\t\tdraftRevisionId: string | null | undefined;\n\t\tincludeDrafts: boolean;\n\t\tpage: PageOptions;\n\t},\n): Promise<PageOfGroups | undefined> {\n\tif (!options.includeDrafts || !options.draftRevisionId) return undefined;\n\n\tconst field = constraintsForRelationSide(\n\t\tawait referenceFieldConstraints(db, options.collection),\n\t\toptions.relationSlug,\n\t\toptions.side,\n\t);\n\tif (!field) return undefined;\n\n\tconst revision = await new RevisionRepository(db).findById(options.draftRevisionId);\n\tconst groups = readStagedReferences(revision?.data)?.[field.slug];\n\tif (!groups) return undefined;\n\n\treturn pageStagedGroups(groups, options.page);\n}\n\nexport async function handleReferenceChildrenGet(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tentryId: string,\n\trelation: string,\n\tpage: PageOptions = {},\n\tincludeDrafts = false,\n): Promise<ApiResult<{ children: EntryRef[]; nextCursor?: string }>> {\n\ttry {\n\t\tconst repo = new RelationRepository(db);\n\t\tconst content = new ContentRepository(db);\n\n\t\tconst rel = await resolveRelation(repo, relation);\n\t\tif (!rel)\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Relation not found\" } };\n\t\tif (collection !== rel.parentCollection) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\t\tmessage: \"Entry is not the parent side of this relation\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst entry = await content.findByIdOrSlug(collection, entryId);\n\t\t// A caller without draft access must not anchor on a non-published entry —\n\t\t// return NOT_FOUND (not 403) so they can't probe draft ids by status code,\n\t\t// mirroring the single-item content read.\n\t\tif (!entry?.translationGroup || (!includeDrafts && entry.status !== \"published\")) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Content entry not found\" } };\n\t\t}\n\n\t\tconst titleField = await getReferenceTitleField(db, rel.childCollection);\n\n\t\t// A pending selection replaces the published one for a caller that may see\n\t\t// it, page for page — the entry read answers the same way, and a walk that\n\t\t// started on one of them must not continue on the other.\n\t\tconst staged = await stagedPageFor(db, {\n\t\t\tcollection,\n\t\t\trelationSlug: rel.slug,\n\t\t\tside: \"parent\",\n\t\t\tdraftRevisionId: entry.draftRevisionId,\n\t\t\tincludeDrafts,\n\t\t\tpage,\n\t\t});\n\t\tif (staged) {\n\t\t\tconst children = await resolveEntryGroups(\n\t\t\t\tcontent,\n\t\t\t\trel.childCollection,\n\t\t\t\tstaged.groups,\n\t\t\t\tentry.locale,\n\t\t\t\tincludeDrafts,\n\t\t\t\ttitleField,\n\t\t\t);\n\t\t\treturn { success: true, data: { children, nextCursor: staged.nextCursor } };\n\t\t}\n\n\t\tconst edges = await repo.getChildrenPage(rel.id, entry.translationGroup, page);\n\t\tconst children = await resolveEntries(\n\t\t\tcontent,\n\t\t\trel.childCollection,\n\t\t\tedges.items,\n\t\t\t(e) => e.childGroup,\n\t\t\tentry.locale,\n\t\t\tincludeDrafts,\n\t\t\ttitleField,\n\t\t);\n\t\treturn { success: true, data: { children, nextCursor: edges.nextCursor } };\n\t} catch (error) {\n\t\treturn referencesGetError(error);\n\t}\n}\n\n/**\n * A selection expressed in the identifiers the link table actually stores:\n * `translation_group` on both ends, because an edge names a thing rather than\n * one locale's row of it.\n */\nexport interface ReferenceSelectionWrite extends ResolvedReferenceTargets {\n\t/** The selecting entry's own translation group. */\n\tentryGroup: string;\n}\n\n/**\n * The same selection, resolved before the entry it belongs to is known — which\n * is what a create has to do, since its row does not exist until it is written\n * and, on D1, writing it cannot be taken back.\n */\nexport interface ResolvedReferenceTargets {\n\t/** The relation, by id or slug — `setChildren` / `setParents` take either. */\n\trelation: string;\n\t/** The end of the relation the selecting entry sits on. */\n\tside: \"parent\" | \"child\";\n\t/** The selected entries' translation groups, in the caller's order. */\n\tgroups: string[];\n}\n\n/**\n * Resolve a bound field's selection to what the link table stores, without\n * writing anything and without needing the selecting entry to exist.\n *\n * The field decides the relation and the end it views: a field on the `parent`\n * end selects children, one on the `child` end selects the parents pointing at\n * it. `entryGroup` is the selecting entry's own translation group when it has\n * one — the far-side count discounts links it already holds, since replacing a\n * selection with itself adds nothing. A new entry passes `null`: it holds no\n * links yet.\n */\nasync function resolveReferenceTargets(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tconstraints: ReferenceFieldConstraints,\n\tselectedIds: string[],\n\tentryGroup: string | null,\n): Promise<ApiResult<ResolvedReferenceTargets>> {\n\tconst repo = new RelationRepository(db);\n\tconst content = new ContentRepository(db);\n\tconst side = constraints.relationSide;\n\n\tconst rel = await resolveRelation(repo, constraints.relation);\n\tif (!rel) return { success: false, error: { code: \"NOT_FOUND\", message: \"Relation not found\" } };\n\n\tconst ownCollection = side === \"parent\" ? rel.parentCollection : rel.childCollection;\n\tconst otherCollection = side === \"parent\" ? rel.childCollection : rel.parentCollection;\n\tif (collection !== ownCollection) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\tmessage: `Entry is not the ${side} side of this relation`,\n\t\t\t},\n\t\t};\n\t}\n\n\tconst selection = validateReferenceSelection(constraints, selectedIds);\n\tif (!selection.success) return selection;\n\n\t// Resolve every selected entry within the relation's other collection in one\n\t// batch (constant queries, not an N+1 of point lookups for a set up to 1000).\n\t// An id that does not resolve there fails collection-agreement (invariant 3);\n\t// order is preserved by iterating the caller's ids.\n\tconst resolved = await content.findManyByIdOrSlug(otherCollection, selectedIds);\n\tconst groups: string[] = [];\n\tfor (const selectedId of selectedIds) {\n\t\tconst other = resolved.get(selectedId);\n\t\tif (!other?.translationGroup) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\t\tmessage: `${side === \"parent\" ? \"Child\" : \"Parent\"} entry '${selectedId}' not found in ${otherCollection}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tgroups.push(other.translationGroup);\n\t}\n\n\tconst far = await validateOppositeSideLimit(db, {\n\t\trelationId: rel.id,\n\t\tfarLimit: side === \"parent\" ? rel.maxParentsPerChild : rel.maxChildrenPerParent,\n\t\tside,\n\t\tentryGroup,\n\t\tgroups,\n\t\tlabels: selectedIds,\n\t});\n\tif (!far.success) return far;\n\n\treturn { success: true, data: { relation: rel.id, side, groups } };\n}\n\n/**\n * Check what a selection does to the *other* end's cardinality.\n *\n * Cardinality binds both ends, but only one end ever selects: a field on the\n * parent side that hands a child its second parent breaks `maxParentsPerChild`\n * even though the parent's own limit is untouched. Links the selecting entry\n * already holds are discounted — replacing a selection with itself adds nothing.\n *\n * `labels` names each group the way the caller addressed it, so the message\n * quotes the id someone typed. Publication has only the groups, which it stages;\n * it quotes those.\n */\nexport async function validateOppositeSideLimit(\n\tdb: Kysely<Database>,\n\toptions: {\n\t\trelationId: string;\n\t\t/** The opposite end's limit. `null` is unlimited — nothing to check. */\n\t\tfarLimit: number | null;\n\t\t/** The end the selecting entry sits on. */\n\t\tside: \"parent\" | \"child\";\n\t\tentryGroup: string | null;\n\t\tgroups: string[];\n\t\tlabels?: string[];\n\t},\n): Promise<ApiResult<true>> {\n\tconst { farLimit, side, groups } = options;\n\tif (farLimit === null || groups.length === 0) return { success: true, data: true };\n\n\tconst counts = await new RelationRepository(db).countEdgesByGroup(\n\t\toptions.relationId,\n\t\tside === \"parent\" ? \"child\" : \"parent\",\n\t\tgroups,\n\t\toptions.entryGroup,\n\t);\n\tfor (const [index, group] of groups.entries()) {\n\t\tif ((counts.get(group) ?? 0) + 1 <= farLimit) continue;\n\t\tconst farSide = side === \"parent\" ? \"parent\" : \"child\";\n\t\tconst label = options.labels?.[index] ?? group;\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\tmessage:\n\t\t\t\t\tfarLimit === 1\n\t\t\t\t\t\t? `Entry '${label}' already has a ${farSide} on this relation, which allows one.`\n\t\t\t\t\t\t: `Entry '${label}' already has the maximum of ${farLimit} ${farSide} entries on this relation.`,\n\t\t\t},\n\t\t};\n\t}\n\treturn { success: true, data: true };\n}\n\n/**\n * {@link resolveReferenceTargets} for an entry that already exists, anchoring the\n * selection on that entry's translation group.\n */\nasync function resolveReferenceSide(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tentryId: string,\n\tconstraints: ReferenceFieldConstraints,\n\tselectedIds: string[],\n): Promise<ApiResult<ReferenceSelectionWrite>> {\n\tconst entry = await new ContentRepository(db).findByIdOrSlug(collection, entryId);\n\tif (!entry?.translationGroup) {\n\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Content entry not found\" } };\n\t}\n\n\tconst resolved = await resolveReferenceTargets(\n\t\tdb,\n\t\tcollection,\n\t\tconstraints,\n\t\tselectedIds,\n\t\tentry.translationGroup,\n\t);\n\tif (!resolved.success) return resolved;\n\treturn { success: true, data: { ...resolved.data, entryGroup: entry.translationGroup } };\n}\n\n/**\n * Replace one end's links from an already-resolved selection.\n *\n * Resolution has already proved the relation, the entry and every selected entry\n * exist, so nothing here fails on the caller's input. What it can still hit is\n * the far end's limit closing between resolving and writing — a slot another\n * request took in that window. The write refuses the edge rather than exceeding\n * the limit, and throws so the save reports it; the throw carries an `apiError`\n * the content handlers map to a response.\n */\nexport async function writeReferenceSelection(\n\tdb: Kysely<Database>,\n\tselection: ReferenceSelectionWrite,\n): Promise<void> {\n\tconst repo = new RelationRepository(db);\n\tconst rel = await resolveRelation(repo, selection.relation);\n\tif (!rel) return;\n\n\tconst rejected =\n\t\tselection.side === \"parent\"\n\t\t\t? await repo.setChildren(rel.id, selection.entryGroup, selection.groups)\n\t\t\t: await repo.setParents(rel.id, selection.entryGroup, selection.groups);\n\tif (rejected.length > 0) {\n\t\tconst farSide = selection.side === \"parent\" ? \"parent\" : \"child\";\n\t\tthrow Object.assign(\n\t\t\tnew Error(\n\t\t\t\t`Entry '${rejected[0]}' already has the maximum number of ${farSide} entries on this relation.`,\n\t\t\t),\n\t\t\t{ apiError: { code: \"VALIDATION_ERROR\" } },\n\t\t);\n\t}\n\n\t// A link is part of what a cached entry renders on both ends — a parent's\n\t// selection and a child's backlinks — while no row of either collection has\n\t// changed. Nothing else here would tell those snapshots they are stale.\n\tinvalidateCollectionCache(rel.parentCollection);\n\tif (rel.childCollection !== rel.parentCollection) {\n\t\tinvalidateCollectionCache(rel.childCollection);\n\t}\n}\n\n/**\n * Replace a reference field's selection on one entry, addressed by field slug.\n *\n * The field decides which relation and which end: a field bound to the parent\n * end replaces that entry's children, one bound to the child end replaces the\n * parents pointing at it. This is what the entry create/update body writes\n * through, so a site addresses a selection the way it addresses any other field.\n */\nexport async function setReferenceSelection(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tentryId: string,\n\tfieldSlug: string,\n\tselectedIds: string[],\n): Promise<ApiResult<{ relationId: string; entryGroup: string }>> {\n\tconst resolved = await resolveReferenceSelection(db, collection, entryId, fieldSlug, selectedIds);\n\tif (!resolved.success) return resolved;\n\tawait writeReferenceSelection(db, resolved.data);\n\treturn {\n\t\tsuccess: true,\n\t\tdata: { relationId: resolved.data.relation, entryGroup: resolved.data.entryGroup },\n\t};\n}\n\n/**\n * `setReferenceSelection` up to but not including the write.\n *\n * A collection that keeps drafts stages the result in its draft revision instead\n * of writing links, so a save reports a bad id or an over-long selection exactly\n * as a direct write would, and publication has nothing left to resolve.\n */\nexport async function resolveReferenceSelection(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tentryId: string,\n\tfieldSlug: string,\n\tselectedIds: string[],\n): Promise<ApiResult<ReferenceSelectionWrite>> {\n\tconst constraints = (await referenceFieldConstraints(db, collection)).get(fieldSlug);\n\tif (!constraints) return notAReferenceField(fieldSlug, collection);\n\treturn resolveReferenceSide(db, collection, entryId, constraints, selectedIds);\n}\n\n/**\n * `resolveReferenceSelection` for an entry that does not exist yet.\n *\n * A create resolves its whole payload before it writes its row, because on D1\n * that row is committed the moment it is written: a selection that cannot be\n * resolved has to be refused while there is still nothing to take back.\n *\n * `entryGroup` is the group the new row will join — a new translation inherits\n * the source's — or null when the row starts a group of its own and so holds no\n * links yet.\n */\nexport async function resolveReferenceSelectionTargets(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tfieldSlug: string,\n\tselectedIds: string[],\n\tentryGroup: string | null,\n): Promise<ApiResult<ResolvedReferenceTargets>> {\n\tconst constraints = (await referenceFieldConstraints(db, collection)).get(fieldSlug);\n\tif (!constraints) return notAReferenceField(fieldSlug, collection);\n\treturn resolveReferenceTargets(db, collection, constraints, selectedIds, entryGroup);\n}\n\nfunction notAReferenceField(fieldSlug: string, collection: string): ApiResult<never> {\n\treturn {\n\t\tsuccess: false,\n\t\terror: {\n\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\tmessage: `Field '${fieldSlug}' is not a reference field on ${collection}`,\n\t\t},\n\t};\n}\n\nexport async function handleReferenceParentsGet(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tentryId: string,\n\trelation: string,\n\tpage: PageOptions = {},\n\tincludeDrafts = false,\n): Promise<ApiResult<{ parents: EntryRef[]; nextCursor?: string }>> {\n\ttry {\n\t\tconst repo = new RelationRepository(db);\n\t\tconst content = new ContentRepository(db);\n\n\t\tconst rel = await resolveRelation(repo, relation);\n\t\tif (!rel)\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Relation not found\" } };\n\t\tif (collection !== rel.childCollection) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\t\tmessage: \"Entry is not the child side of this relation\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst entry = await content.findByIdOrSlug(collection, entryId);\n\t\t// Same draft-anchor guard as the children read: a non-draft-reader anchoring\n\t\t// on an unpublished entry gets NOT_FOUND, not its backlinks.\n\t\tif (!entry?.translationGroup || (!includeDrafts && entry.status !== \"published\")) {\n\t\t\treturn { success: false, error: { code: \"NOT_FOUND\", message: \"Content entry not found\" } };\n\t\t}\n\n\t\tconst titleField = await getReferenceTitleField(db, rel.parentCollection);\n\n\t\t// As on the children read: a field bound to this end stages its pending\n\t\t// selection in the entry's draft, and that is what a drafts-aware caller\n\t\t// pages through.\n\t\tconst staged = await stagedPageFor(db, {\n\t\t\tcollection,\n\t\t\trelationSlug: rel.slug,\n\t\t\tside: \"child\",\n\t\t\tdraftRevisionId: entry.draftRevisionId,\n\t\t\tincludeDrafts,\n\t\t\tpage,\n\t\t});\n\t\tif (staged) {\n\t\t\tconst parents = await resolveEntryGroups(\n\t\t\t\tcontent,\n\t\t\t\trel.parentCollection,\n\t\t\t\tstaged.groups,\n\t\t\t\tentry.locale,\n\t\t\t\tincludeDrafts,\n\t\t\t\ttitleField,\n\t\t\t);\n\t\t\treturn { success: true, data: { parents, nextCursor: staged.nextCursor } };\n\t\t}\n\n\t\tconst edges = await repo.getParentsPage(rel.id, entry.translationGroup, page);\n\t\tconst parents = await resolveEntries(\n\t\t\tcontent,\n\t\t\trel.parentCollection,\n\t\t\tedges.items,\n\t\t\t(e) => e.parentGroup,\n\t\t\tentry.locale,\n\t\t\tincludeDrafts,\n\t\t\ttitleField,\n\t\t);\n\t\treturn { success: true, data: { parents, nextCursor: edges.nextCursor } };\n\t} catch (error) {\n\t\treturn referencesGetError(error);\n\t}\n}\n"],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ import { getRequestContext } from "./request-context.mjs";
2
+
3
+ //#region src/request-cache.ts
4
+ const STORE_KEY = Symbol.for("emdash:request-cache");
5
+ const g = globalThis;
6
+ const store = g[STORE_KEY] ?? (() => {
7
+ const wm = /* @__PURE__ */ new WeakMap();
8
+ g[STORE_KEY] = wm;
9
+ return wm;
10
+ })();
11
+ /**
12
+ * Return a cached result for `key` if one exists in the current
13
+ * request scope, otherwise call `fn`, cache its promise, and return it.
14
+ *
15
+ * Caches the *promise*, not the resolved value, so concurrent calls
16
+ * with the same key share a single in-flight query.
17
+ */
18
+ function requestCached(key, fn) {
19
+ const ctx = getRequestContext();
20
+ if (!ctx) return fn();
21
+ let cache = store.get(ctx);
22
+ if (!cache) {
23
+ cache = /* @__PURE__ */ new Map();
24
+ store.set(ctx, cache);
25
+ }
26
+ const existing = cache.get(key);
27
+ if (existing) {
28
+ if (ctx.metrics) ctx.metrics.cacheHits += 1;
29
+ return existing;
30
+ }
31
+ if (ctx.metrics) ctx.metrics.cacheMisses += 1;
32
+ const promise = Promise.resolve().then(fn).catch((error) => {
33
+ cache.delete(key);
34
+ throw error;
35
+ });
36
+ cache.set(key, promise);
37
+ return promise;
38
+ }
39
+ /**
40
+ * Look up an entry in the request-scoped cache without inserting one.
41
+ *
42
+ * Returns the in-flight or resolved promise if the key exists in the
43
+ * current request, otherwise `undefined`. Callers can use this to
44
+ * opportunistically satisfy a narrower query (e.g. `getSiteSetting("seo")`)
45
+ * from a broader one (`getSiteSettings()`) that's already been loaded
46
+ * by a parent template — avoiding a redundant round-trip.
47
+ *
48
+ * No-ops outside a request context.
49
+ */
50
+ function peekRequestCache(key) {
51
+ const ctx = getRequestContext();
52
+ if (!ctx) return void 0;
53
+ return store.get(ctx)?.get(key);
54
+ }
55
+ /**
56
+ * Pre-populate the request-scoped cache with a resolved value.
57
+ *
58
+ * Internal helper shared between hydration paths (taxonomy terms,
59
+ * bylines, etc.) that already have the data in hand and want downstream
60
+ * callers using `requestCached(key, ...)` to skip the database entirely.
61
+ * Not exported from the package entrypoint — keep it internal until we
62
+ * have a documented plugin/extension surface for hydration.
63
+ *
64
+ * No-ops outside a request context (local dev without ALS).
65
+ *
66
+ * Does not overwrite an existing entry — if a query for this key is already
67
+ * in flight, its promise wins.
68
+ */
69
+ function setRequestCacheEntry(key, value) {
70
+ const ctx = getRequestContext();
71
+ if (!ctx) return;
72
+ let cache = store.get(ctx);
73
+ if (!cache) {
74
+ cache = /* @__PURE__ */ new Map();
75
+ store.set(ctx, cache);
76
+ }
77
+ if (cache.has(key)) return;
78
+ cache.set(key, Promise.resolve(value));
79
+ }
80
+ /**
81
+ * Remove a key from the request-scoped cache.
82
+ *
83
+ * Used by write paths that need to invalidate a downstream read cache —
84
+ * `setRequestCacheEntry` deliberately doesn't overwrite, and `requestCached`
85
+ * returns the cached promise even after the underlying data has changed.
86
+ * Without an explicit clear, a `read → write → read` sequence in a single
87
+ * request can return stale data on the second read.
88
+ *
89
+ * Concrete case: `BylineRepository.update` invalidates
90
+ * `byline-field-group-values:${translation_group}` after writing a
91
+ * non-translatable custom-field value, so the post-update `findById`
92
+ * (and any later reads in the same request) see the fresh value.
93
+ *
94
+ * No-ops outside a request context.
95
+ */
96
+ function clearRequestCacheEntry(key) {
97
+ const ctx = getRequestContext();
98
+ if (!ctx) return;
99
+ store.get(ctx)?.delete(key);
100
+ }
101
+
102
+ //#endregion
103
+ export { setRequestCacheEntry as i, peekRequestCache as n, requestCached as r, clearRequestCacheEntry as t };
104
+ //# sourceMappingURL=request-cache-iHRlHx1d.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-cache-iHRlHx1d.mjs","names":[],"sources":["../src/request-cache.ts"],"sourcesContent":["/**\n * Per-request query cache\n *\n * Deduplicates identical database queries within a single page render.\n * Uses the ALS request context as a WeakMap key so the cache is\n * automatically GC'd when the request completes.\n *\n * When no request context is available (e.g. local dev without D1\n * replicas), queries bypass the cache — local SQLite is fast enough\n * that deduplication doesn't matter.\n *\n * The WeakMap is stored on globalThis with a Symbol key to guarantee\n * a singleton even when bundlers duplicate this module across chunks\n * (same pattern as request-context.ts).\n */\n\nimport type { EmDashRequestContext } from \"./request-context.js\";\nimport { getRequestContext } from \"./request-context.js\";\n\ntype CacheStore = WeakMap<EmDashRequestContext, Map<string, Promise<unknown>>>;\n\nconst STORE_KEY = Symbol.for(\"emdash:request-cache\");\nconst g = globalThis as Record<symbol, unknown>;\nconst store: CacheStore =\n\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see request-context.ts)\n\t(g[STORE_KEY] as CacheStore | undefined) ??\n\t(() => {\n\t\tconst wm: CacheStore = new WeakMap();\n\t\tg[STORE_KEY] = wm;\n\t\treturn wm;\n\t})();\n\n/**\n * Return a cached result for `key` if one exists in the current\n * request scope, otherwise call `fn`, cache its promise, and return it.\n *\n * Caches the *promise*, not the resolved value, so concurrent calls\n * with the same key share a single in-flight query.\n */\nexport function requestCached<T>(key: string, fn: () => Promise<T>): Promise<T> {\n\tconst ctx = getRequestContext();\n\tif (!ctx) return fn();\n\n\tlet cache = store.get(ctx);\n\tif (!cache) {\n\t\tcache = new Map();\n\t\tstore.set(ctx, cache);\n\t}\n\n\tconst existing = cache.get(key);\n\tif (existing) {\n\t\tif (ctx.metrics) ctx.metrics.cacheHits += 1;\n\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- heterogeneous cache; key namespacing guarantees the stored promise resolves to T\n\t\treturn existing as Promise<T>;\n\t}\n\tif (ctx.metrics) ctx.metrics.cacheMisses += 1;\n\n\tconst promise = Promise.resolve()\n\t\t.then(fn)\n\t\t.catch((error) => {\n\t\t\tcache.delete(key);\n\t\t\tthrow error;\n\t\t});\n\tcache.set(key, promise);\n\treturn promise;\n}\n\n/**\n * Look up an entry in the request-scoped cache without inserting one.\n *\n * Returns the in-flight or resolved promise if the key exists in the\n * current request, otherwise `undefined`. Callers can use this to\n * opportunistically satisfy a narrower query (e.g. `getSiteSetting(\"seo\")`)\n * from a broader one (`getSiteSettings()`) that's already been loaded\n * by a parent template — avoiding a redundant round-trip.\n *\n * No-ops outside a request context.\n */\nexport function peekRequestCache<T>(key: string): Promise<T> | undefined {\n\tconst ctx = getRequestContext();\n\tif (!ctx) return undefined;\n\tconst cache = store.get(ctx);\n\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- heterogeneous cache; caller is responsible for using a T-compatible key\n\treturn cache?.get(key) as Promise<T> | undefined;\n}\n\n/**\n * Pre-populate the request-scoped cache with a resolved value.\n *\n * Internal helper shared between hydration paths (taxonomy terms,\n * bylines, etc.) that already have the data in hand and want downstream\n * callers using `requestCached(key, ...)` to skip the database entirely.\n * Not exported from the package entrypoint — keep it internal until we\n * have a documented plugin/extension surface for hydration.\n *\n * No-ops outside a request context (local dev without ALS).\n *\n * Does not overwrite an existing entry — if a query for this key is already\n * in flight, its promise wins.\n */\nexport function setRequestCacheEntry<T>(key: string, value: T): void {\n\tconst ctx = getRequestContext();\n\tif (!ctx) return;\n\n\tlet cache = store.get(ctx);\n\tif (!cache) {\n\t\tcache = new Map();\n\t\tstore.set(ctx, cache);\n\t}\n\n\tif (cache.has(key)) return;\n\tcache.set(key, Promise.resolve(value));\n}\n\n/**\n * Remove a key from the request-scoped cache.\n *\n * Used by write paths that need to invalidate a downstream read cache —\n * `setRequestCacheEntry` deliberately doesn't overwrite, and `requestCached`\n * returns the cached promise even after the underlying data has changed.\n * Without an explicit clear, a `read → write → read` sequence in a single\n * request can return stale data on the second read.\n *\n * Concrete case: `BylineRepository.update` invalidates\n * `byline-field-group-values:${translation_group}` after writing a\n * non-translatable custom-field value, so the post-update `findById`\n * (and any later reads in the same request) see the fresh value.\n *\n * No-ops outside a request context.\n */\nexport function clearRequestCacheEntry(key: string): void {\n\tconst ctx = getRequestContext();\n\tif (!ctx) return;\n\tconst cache = store.get(ctx);\n\tcache?.delete(key);\n}\n"],"mappings":";;;AAqBA,MAAM,YAAY,OAAO,IAAI,uBAAuB;AACpD,MAAM,IAAI;AACV,MAAM,QAEJ,EAAE,qBACI;CACN,MAAM,qBAAiB,IAAI,SAAS;AACpC,GAAE,aAAa;AACf,QAAO;IACJ;;;;;;;;AASL,SAAgB,cAAiB,KAAa,IAAkC;CAC/E,MAAM,MAAM,mBAAmB;AAC/B,KAAI,CAAC,IAAK,QAAO,IAAI;CAErB,IAAI,QAAQ,MAAM,IAAI,IAAI;AAC1B,KAAI,CAAC,OAAO;AACX,0BAAQ,IAAI,KAAK;AACjB,QAAM,IAAI,KAAK,MAAM;;CAGtB,MAAM,WAAW,MAAM,IAAI,IAAI;AAC/B,KAAI,UAAU;AACb,MAAI,IAAI,QAAS,KAAI,QAAQ,aAAa;AAE1C,SAAO;;AAER,KAAI,IAAI,QAAS,KAAI,QAAQ,eAAe;CAE5C,MAAM,UAAU,QAAQ,SAAS,CAC/B,KAAK,GAAG,CACR,OAAO,UAAU;AACjB,QAAM,OAAO,IAAI;AACjB,QAAM;GACL;AACH,OAAM,IAAI,KAAK,QAAQ;AACvB,QAAO;;;;;;;;;;;;;AAcR,SAAgB,iBAAoB,KAAqC;CACxE,MAAM,MAAM,mBAAmB;AAC/B,KAAI,CAAC,IAAK,QAAO;AAGjB,QAFc,MAAM,IAAI,IAAI,EAEd,IAAI,IAAI;;;;;;;;;;;;;;;;AAiBvB,SAAgB,qBAAwB,KAAa,OAAgB;CACpE,MAAM,MAAM,mBAAmB;AAC/B,KAAI,CAAC,IAAK;CAEV,IAAI,QAAQ,MAAM,IAAI,IAAI;AAC1B,KAAI,CAAC,OAAO;AACX,0BAAQ,IAAI,KAAK;AACjB,QAAM,IAAI,KAAK,MAAM;;AAGtB,KAAI,MAAM,IAAI,IAAI,CAAE;AACpB,OAAM,IAAI,KAAK,QAAQ,QAAQ,MAAM,CAAC;;;;;;;;;;;;;;;;;;AAmBvC,SAAgB,uBAAuB,KAAmB;CACzD,MAAM,MAAM,mBAAmB;AAC/B,KAAI,CAAC,IAAK;AAEV,CADc,MAAM,IAAI,IAAI,EACrB,OAAO,IAAI"}
@@ -1,5 +1,5 @@
1
1
  import { QueryRecorder } from "./database/instrumentation.mjs";
2
- import { t as DeferredTaskTracker } from "./deferred-tasks-BPxXUB4x.mjs";
2
+ import { t as DeferredTaskTracker } from "./deferred-tasks-CZ7rzBdo.mjs";
3
3
 
4
4
  //#region src/request-context.d.ts
5
5
  /**
@@ -0,0 +1,141 @@
1
+ import { n as normalizeTrustedHeaders, t as getTrustedProxyHeaders } from "./trusted-proxy-B6ECOZJc.mjs";
2
+
3
+ //#region src/plugins/request-meta.ts
4
+ /**
5
+ * Loose validation for IPv4 and IPv6 addresses.
6
+ * Accepts digits, hex chars, dots, and colons — rejects anything else
7
+ * (e.g. HTML tags, scripts, or other non-IP garbage in spoofed headers).
8
+ */
9
+ const IP_PATTERN = /^[\da-fA-F.:]+$/;
10
+ /**
11
+ * Extract the first IP from an X-Forwarded-For header value.
12
+ * The header may contain a comma-separated list of IPs; the first
13
+ * entry is the original client IP.
14
+ *
15
+ * Returns null if the extracted value doesn't look like an IP address.
16
+ */
17
+ function parseFirstForwardedIp(header) {
18
+ const trimmed = header.split(",")[0]?.trim();
19
+ if (!trimmed) return null;
20
+ return IP_PATTERN.test(trimmed) ? trimmed : null;
21
+ }
22
+ /**
23
+ * Read an IP from an operator-declared trusted header. XFF-style headers
24
+ * (any name ending in `forwarded-for`) are parsed as comma-separated lists
25
+ * and the first entry is used; everything else is treated as a single
26
+ * trimmed value.
27
+ */
28
+ function readIpFromHeader(headers, name) {
29
+ const value = headers.get(name);
30
+ if (!value) return null;
31
+ if (name.endsWith("forwarded-for")) return parseFirstForwardedIp(value);
32
+ const trimmed = value.trim();
33
+ if (!trimmed) return null;
34
+ return IP_PATTERN.test(trimmed) ? trimmed : null;
35
+ }
36
+ /**
37
+ * Get the Cloudflare `cf` object from the request, if present.
38
+ * Returns undefined when not running on Cloudflare Workers.
39
+ */
40
+ function getCfObject(request) {
41
+ return request.cf;
42
+ }
43
+ /**
44
+ * Extract geographic information from the Cloudflare `cf` object
45
+ * attached to the request. Returns null when not running on CF Workers.
46
+ */
47
+ function extractGeo(cf) {
48
+ if (!cf) return null;
49
+ const country = cf.country ?? null;
50
+ const region = cf.region ?? null;
51
+ const city = cf.city ?? null;
52
+ if (country === null && region === null && city === null) return null;
53
+ return {
54
+ country,
55
+ region,
56
+ city
57
+ };
58
+ }
59
+ /**
60
+ * Extract normalized request metadata from a Request object.
61
+ *
62
+ * IP resolution order:
63
+ * 1. `CF-Connecting-IP` — trusted only when a `cf` object is present on the
64
+ * request. CF edge overwrites any client-supplied value, so this is the
65
+ * cryptographically trustworthy path on Workers. Operator-declared
66
+ * trusted headers cannot override it.
67
+ * 2. `X-Forwarded-For` first entry — trusted only with a `cf` object.
68
+ * 3. Operator-declared trusted proxy headers (from `config.trustedProxyHeaders`
69
+ * or the `EMDASH_TRUSTED_PROXY_HEADERS` env var), tried in order. Used as
70
+ * the primary source off-CF and as a fill-in on CF.
71
+ * 4. `null`
72
+ *
73
+ * The second argument accepts either the EmDash config or a pre-resolved
74
+ * list of trusted headers, so callers that already have the list don't have
75
+ * to round-trip through the config every request.
76
+ */
77
+ function extractRequestMeta(request, configOrTrustedHeaders) {
78
+ const headers = request.headers;
79
+ const cf = getCfObject(request);
80
+ const trusted = resolveTrustedHeaders(configOrTrustedHeaders);
81
+ let ip = null;
82
+ if (cf) {
83
+ const cfIp = headers.get("cf-connecting-ip")?.trim();
84
+ if (cfIp && IP_PATTERN.test(cfIp)) ip = cfIp;
85
+ if (!ip) {
86
+ const xff = headers.get("x-forwarded-for");
87
+ ip = xff ? parseFirstForwardedIp(xff) : null;
88
+ }
89
+ }
90
+ if (!ip) for (const name of trusted) {
91
+ const value = readIpFromHeader(headers, name);
92
+ if (value) {
93
+ ip = value;
94
+ break;
95
+ }
96
+ }
97
+ const userAgent = headers.get("user-agent")?.trim() || null;
98
+ const referer = headers.get("referer")?.trim() || null;
99
+ const geo = extractGeo(cf);
100
+ return {
101
+ ip,
102
+ userAgent,
103
+ referer,
104
+ geo
105
+ };
106
+ }
107
+ function resolveTrustedHeaders(value) {
108
+ if (Array.isArray(value)) return normalizeTrustedHeaders(value);
109
+ return getTrustedProxyHeaders(value);
110
+ }
111
+ /**
112
+ * Headers that must never cross the RPC boundary to sandboxed plugins.
113
+ * Session tokens, auth credentials, and infrastructure headers are stripped
114
+ * to prevent malicious plugins from exfiltrating sensitive data.
115
+ */
116
+ const SANDBOX_STRIPPED_HEADERS = new Set([
117
+ "cookie",
118
+ "set-cookie",
119
+ "authorization",
120
+ "proxy-authorization",
121
+ "cf-access-jwt-assertion",
122
+ "cf-access-client-id",
123
+ "cf-access-client-secret",
124
+ "x-emdash-request"
125
+ ]);
126
+ /**
127
+ * Copy request headers into a plain object, stripping sensitive headers
128
+ * that must not be exposed to sandboxed plugin code.
129
+ */
130
+ function sanitizeHeadersForSandbox(headers, allowedHeaders) {
131
+ const safe = {};
132
+ const allowed = allowedHeaders ? new Set(allowedHeaders.map((header) => header.toLowerCase())) : null;
133
+ headers.forEach((value, key) => {
134
+ if (!SANDBOX_STRIPPED_HEADERS.has(key) && !key.startsWith("cf-access-") && (allowed === null || allowed.has(key))) safe[key] = value;
135
+ });
136
+ return safe;
137
+ }
138
+
139
+ //#endregion
140
+ export { sanitizeHeadersForSandbox as n, extractRequestMeta as t };
141
+ //# sourceMappingURL=request-meta-D47mqyev.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-meta-D47mqyev.mjs","names":[],"sources":["../src/plugins/request-meta.ts"],"sourcesContent":["/**\n * Request Metadata Extraction\n *\n * Extracts normalized metadata (IP, user agent, referer, geo) from\n * incoming requests. Used by plugin route handlers to access request\n * context without touching raw headers.\n *\n */\n\nimport type { EmDashConfig } from \"../astro/integration/runtime.js\";\nimport { getTrustedProxyHeaders, normalizeTrustedHeaders } from \"../auth/trusted-proxy.js\";\nimport type { GeoInfo, RequestMeta } from \"./types.js\";\n\n/**\n * Cloudflare Workers `cf` object shape (subset we use).\n * Present on requests when running on Cloudflare Workers.\n */\ninterface CfProperties {\n\tcountry?: string;\n\tregion?: string;\n\tcity?: string;\n}\n\n/**\n * Loose validation for IPv4 and IPv6 addresses.\n * Accepts digits, hex chars, dots, and colons — rejects anything else\n * (e.g. HTML tags, scripts, or other non-IP garbage in spoofed headers).\n */\nconst IP_PATTERN = /^[\\da-fA-F.:]+$/;\n\n/**\n * Extract the first IP from an X-Forwarded-For header value.\n * The header may contain a comma-separated list of IPs; the first\n * entry is the original client IP.\n *\n * Returns null if the extracted value doesn't look like an IP address.\n */\nfunction parseFirstForwardedIp(header: string): string | null {\n\tconst first = header.split(\",\")[0];\n\tconst trimmed = first?.trim();\n\tif (!trimmed) return null;\n\treturn IP_PATTERN.test(trimmed) ? trimmed : null;\n}\n\n/**\n * Read an IP from an operator-declared trusted header. XFF-style headers\n * (any name ending in `forwarded-for`) are parsed as comma-separated lists\n * and the first entry is used; everything else is treated as a single\n * trimmed value.\n */\nfunction readIpFromHeader(headers: Headers, name: string): string | null {\n\tconst value = headers.get(name);\n\tif (!value) return null;\n\tif (name.endsWith(\"forwarded-for\")) {\n\t\treturn parseFirstForwardedIp(value);\n\t}\n\tconst trimmed = value.trim();\n\tif (!trimmed) return null;\n\treturn IP_PATTERN.test(trimmed) ? trimmed : null;\n}\n\n/**\n * Get the Cloudflare `cf` object from the request, if present.\n * Returns undefined when not running on Cloudflare Workers.\n */\nfunction getCfObject(request: Request): CfProperties | undefined {\n\treturn (request as unknown as { cf?: CfProperties }).cf;\n}\n\n/**\n * Extract geographic information from the Cloudflare `cf` object\n * attached to the request. Returns null when not running on CF Workers.\n */\nfunction extractGeo(cf: CfProperties | undefined): GeoInfo | null {\n\tif (!cf) return null;\n\n\tconst country = cf.country ?? null;\n\tconst region = cf.region ?? null;\n\tconst city = cf.city ?? null;\n\n\t// Only return geo if at least one field is populated\n\tif (country === null && region === null && city === null) return null;\n\n\treturn { country, region, city };\n}\n\n/**\n * Extract normalized request metadata from a Request object.\n *\n * IP resolution order:\n * 1. `CF-Connecting-IP` — trusted only when a `cf` object is present on the\n * request. CF edge overwrites any client-supplied value, so this is the\n * cryptographically trustworthy path on Workers. Operator-declared\n * trusted headers cannot override it.\n * 2. `X-Forwarded-For` first entry — trusted only with a `cf` object.\n * 3. Operator-declared trusted proxy headers (from `config.trustedProxyHeaders`\n * or the `EMDASH_TRUSTED_PROXY_HEADERS` env var), tried in order. Used as\n * the primary source off-CF and as a fill-in on CF.\n * 4. `null`\n *\n * The second argument accepts either the EmDash config or a pre-resolved\n * list of trusted headers, so callers that already have the list don't have\n * to round-trip through the config every request.\n */\nexport function extractRequestMeta(\n\trequest: Request,\n\tconfigOrTrustedHeaders?: EmDashConfig | null | { trustedProxyHeaders?: string[] } | string[],\n): RequestMeta {\n\tconst headers = request.headers;\n\tconst cf = getCfObject(request);\n\tconst trusted = resolveTrustedHeaders(configOrTrustedHeaders);\n\n\tlet ip: string | null = null;\n\n\t// On Cloudflare, prefer the cryptographically trustworthy headers first.\n\tif (cf) {\n\t\tconst cfIp = headers.get(\"cf-connecting-ip\")?.trim();\n\t\tif (cfIp && IP_PATTERN.test(cfIp)) {\n\t\t\tip = cfIp;\n\t\t}\n\t\tif (!ip) {\n\t\t\tconst xff = headers.get(\"x-forwarded-for\");\n\t\t\tip = xff ? parseFirstForwardedIp(xff) : null;\n\t\t}\n\t}\n\n\t// Fall through to operator-declared trusted headers. On CF this fills\n\t// in when the CF headers are absent; off-CF it's the primary source.\n\tif (!ip) {\n\t\tfor (const name of trusted) {\n\t\t\tconst value = readIpFromHeader(headers, name);\n\t\t\tif (value) {\n\t\t\t\tip = value;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst userAgent = headers.get(\"user-agent\")?.trim() || null;\n\tconst referer = headers.get(\"referer\")?.trim() || null;\n\tconst geo = extractGeo(cf);\n\n\treturn { ip, userAgent, referer, geo };\n}\n\nfunction resolveTrustedHeaders(\n\tvalue: EmDashConfig | null | { trustedProxyHeaders?: string[] } | string[] | undefined,\n): string[] {\n\tif (Array.isArray(value)) {\n\t\t// Apply the same RFC 7230 validation the config/env path does so a\n\t\t// caller passing a pre-resolved list with bad entries can't crash\n\t\t// `Headers.get()` downstream.\n\t\treturn normalizeTrustedHeaders(value);\n\t}\n\treturn getTrustedProxyHeaders(value);\n}\n\n// =============================================================================\n// Header Sanitization for Sandbox\n// =============================================================================\n\n/**\n * Headers that must never cross the RPC boundary to sandboxed plugins.\n * Session tokens, auth credentials, and infrastructure headers are stripped\n * to prevent malicious plugins from exfiltrating sensitive data.\n */\nconst SANDBOX_STRIPPED_HEADERS = new Set([\n\t\"cookie\",\n\t\"set-cookie\",\n\t\"authorization\",\n\t\"proxy-authorization\",\n\t\"cf-access-jwt-assertion\",\n\t\"cf-access-client-id\",\n\t\"cf-access-client-secret\",\n\t\"x-emdash-request\",\n]);\n\n/**\n * Copy request headers into a plain object, stripping sensitive headers\n * that must not be exposed to sandboxed plugin code.\n */\nexport function sanitizeHeadersForSandbox(\n\theaders: Headers,\n\tallowedHeaders?: readonly string[],\n): Record<string, string> {\n\tconst safe: Record<string, string> = {};\n\tconst allowed = allowedHeaders\n\t\t? new Set(allowedHeaders.map((header) => header.toLowerCase()))\n\t\t: null;\n\theaders.forEach((value, key) => {\n\t\tif (\n\t\t\t!SANDBOX_STRIPPED_HEADERS.has(key) &&\n\t\t\t!key.startsWith(\"cf-access-\") &&\n\t\t\t(allowed === null || allowed.has(key))\n\t\t) {\n\t\t\tsafe[key] = value;\n\t\t}\n\t});\n\treturn safe;\n}\n"],"mappings":";;;;;;;;AA4BA,MAAM,aAAa;;;;;;;;AASnB,SAAS,sBAAsB,QAA+B;CAE7D,MAAM,UADQ,OAAO,MAAM,IAAI,CAAC,IACT,MAAM;AAC7B,KAAI,CAAC,QAAS,QAAO;AACrB,QAAO,WAAW,KAAK,QAAQ,GAAG,UAAU;;;;;;;;AAS7C,SAAS,iBAAiB,SAAkB,MAA6B;CACxE,MAAM,QAAQ,QAAQ,IAAI,KAAK;AAC/B,KAAI,CAAC,MAAO,QAAO;AACnB,KAAI,KAAK,SAAS,gBAAgB,CACjC,QAAO,sBAAsB,MAAM;CAEpC,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,CAAC,QAAS,QAAO;AACrB,QAAO,WAAW,KAAK,QAAQ,GAAG,UAAU;;;;;;AAO7C,SAAS,YAAY,SAA4C;AAChE,QAAQ,QAA6C;;;;;;AAOtD,SAAS,WAAW,IAA8C;AACjE,KAAI,CAAC,GAAI,QAAO;CAEhB,MAAM,UAAU,GAAG,WAAW;CAC9B,MAAM,SAAS,GAAG,UAAU;CAC5B,MAAM,OAAO,GAAG,QAAQ;AAGxB,KAAI,YAAY,QAAQ,WAAW,QAAQ,SAAS,KAAM,QAAO;AAEjE,QAAO;EAAE;EAAS;EAAQ;EAAM;;;;;;;;;;;;;;;;;;;;AAqBjC,SAAgB,mBACf,SACA,wBACc;CACd,MAAM,UAAU,QAAQ;CACxB,MAAM,KAAK,YAAY,QAAQ;CAC/B,MAAM,UAAU,sBAAsB,uBAAuB;CAE7D,IAAI,KAAoB;AAGxB,KAAI,IAAI;EACP,MAAM,OAAO,QAAQ,IAAI,mBAAmB,EAAE,MAAM;AACpD,MAAI,QAAQ,WAAW,KAAK,KAAK,CAChC,MAAK;AAEN,MAAI,CAAC,IAAI;GACR,MAAM,MAAM,QAAQ,IAAI,kBAAkB;AAC1C,QAAK,MAAM,sBAAsB,IAAI,GAAG;;;AAM1C,KAAI,CAAC,GACJ,MAAK,MAAM,QAAQ,SAAS;EAC3B,MAAM,QAAQ,iBAAiB,SAAS,KAAK;AAC7C,MAAI,OAAO;AACV,QAAK;AACL;;;CAKH,MAAM,YAAY,QAAQ,IAAI,aAAa,EAAE,MAAM,IAAI;CACvD,MAAM,UAAU,QAAQ,IAAI,UAAU,EAAE,MAAM,IAAI;CAClD,MAAM,MAAM,WAAW,GAAG;AAE1B,QAAO;EAAE;EAAI;EAAW;EAAS;EAAK;;AAGvC,SAAS,sBACR,OACW;AACX,KAAI,MAAM,QAAQ,MAAM,CAIvB,QAAO,wBAAwB,MAAM;AAEtC,QAAO,uBAAuB,MAAM;;;;;;;AAYrC,MAAM,2BAA2B,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;;;;;AAMF,SAAgB,0BACf,SACA,gBACyB;CACzB,MAAM,OAA+B,EAAE;CACvC,MAAM,UAAU,iBACb,IAAI,IAAI,eAAe,KAAK,WAAW,OAAO,aAAa,CAAC,CAAC,GAC7D;AACH,SAAQ,SAAS,OAAO,QAAQ;AAC/B,MACC,CAAC,yBAAyB,IAAI,IAAI,IAClC,CAAC,IAAI,WAAW,aAAa,KAC5B,YAAY,QAAQ,QAAQ,IAAI,IAAI,EAErC,MAAK,OAAO;GAEZ;AACF,QAAO"}
@@ -0,0 +1,99 @@
1
+ import "./dialect-helpers-7_IqPdh9.mjs";
2
+ import { i as isI18nEnabled, n as getFallbackChain } from "./config-CvmjJcVw.mjs";
3
+ import "./datetime-normalization-PeiEdcRY.mjs";
4
+ import "./after-PcEvMY_6.mjs";
5
+ import "./base64-DvnNgP7e.mjs";
6
+ import "./object-cache-CqWNY5uP.mjs";
7
+ import "./types-aOOxRSx6.mjs";
8
+ import { t as RevisionRepository } from "./revision-j1p4-bOj.mjs";
9
+ import "./request-cache-iHRlHx1d.mjs";
10
+ import { a as pageStagedGroups, c as RelationRepository, n as REFERENCE_PAGE_MAX_LIMIT, o as readStagedReferences, t as REFERENCE_PAGE_LIMIT } from "./staged-C36IWXff.mjs";
11
+ import { c as loadEntriesByGroups, s as getDb } from "./loader-CrRPfkHS.mjs";
12
+ import { n as getReferenceFieldMap } from "./field-map-6m9rF49t.mjs";
13
+
14
+ //#region src/references/resolve.ts
15
+ /**
16
+ * Resolve an entry's reference selections to loadable entries, for the public
17
+ * query path.
18
+ *
19
+ * The cost is bounded and predictable: one link read per selected field, then
20
+ * one entry read per *distinct* target collection — never one per link. A
21
+ * caller that selects no fields issues nothing at all, which is what keeps
22
+ * references off the logged-out hot path of every render that does not ask for
23
+ * them.
24
+ */
25
+ function pageOptions(query) {
26
+ if (query === true) return { limit: REFERENCE_PAGE_LIMIT };
27
+ const requested = query.limit ?? REFERENCE_PAGE_LIMIT;
28
+ return {
29
+ limit: Math.min(Math.max(requested, 1), REFERENCE_PAGE_MAX_LIMIT),
30
+ cursor: query.cursor
31
+ };
32
+ }
33
+ function localeChainFor(locale) {
34
+ if (locale === null) return [];
35
+ return isI18nEnabled() ? getFallbackChain(locale) : [locale];
36
+ }
37
+ async function resolveReferencePages(options) {
38
+ const fieldMap = await getReferenceFieldMap(options.collection);
39
+ const requested = Object.entries(options.selection).filter((entry) => entry[1] !== void 0 && fieldMap.has(entry[0]));
40
+ if (requested.length === 0) return {};
41
+ const db = await getDb();
42
+ const relations = new RelationRepository(db);
43
+ const staged = options.serveDrafts && options.draftRevisionId ? readStagedReferences((await new RevisionRepository(db).findById(options.draftRevisionId))?.data) : void 0;
44
+ const pages = new Map(await Promise.all(requested.map(async ([slug, query]) => {
45
+ const binding = fieldMap.get(slug);
46
+ const page = pageOptions(query);
47
+ const stagedGroups = staged?.[slug];
48
+ if (stagedGroups) return [slug, pageStagedGroups(stagedGroups, page)];
49
+ const links = binding.side === "child" ? await relations.getParentsPageById(binding.relationId, options.entryGroup, page) : await relations.getChildrenPageById(binding.relationId, options.entryGroup, page);
50
+ return [slug, {
51
+ groups: links.items.map((link) => binding.side === "child" ? link.parentGroup : link.childGroup),
52
+ nextCursor: links.nextCursor
53
+ }];
54
+ })));
55
+ const groupsByCollection = /* @__PURE__ */ new Map();
56
+ for (const [slug, page] of pages) {
57
+ const target = fieldMap.get(slug).targetCollection;
58
+ const groups = groupsByCollection.get(target) ?? /* @__PURE__ */ new Set();
59
+ for (const group of page.groups) groups.add(group);
60
+ groupsByCollection.set(target, groups);
61
+ }
62
+ const localeChain = localeChainFor(options.locale);
63
+ const variantsByCollection = /* @__PURE__ */ new Map();
64
+ await Promise.all(Array.from(groupsByCollection, async ([collection, groups]) => {
65
+ const loaded = await loadEntriesByGroups(collection, [...groups], {
66
+ publishedOnly: !options.serveDrafts,
67
+ localeChain
68
+ });
69
+ const byGroup = /* @__PURE__ */ new Map();
70
+ for (const entry of loaded) {
71
+ const group = entry.data.translationGroup;
72
+ if (typeof group === "string") byGroup.set(group, entry);
73
+ }
74
+ variantsByCollection.set(collection, byGroup);
75
+ }));
76
+ const resolved = {};
77
+ for (const [slug, page] of pages) {
78
+ const collection = fieldMap.get(slug).targetCollection;
79
+ const byGroup = variantsByCollection.get(collection);
80
+ const entries = [];
81
+ for (const group of page.groups) {
82
+ const variant = byGroup?.get(group);
83
+ if (variant) entries.push(variant);
84
+ }
85
+ resolved[slug] = page.nextCursor ? {
86
+ collection,
87
+ entries,
88
+ nextCursor: page.nextCursor
89
+ } : {
90
+ collection,
91
+ entries
92
+ };
93
+ }
94
+ return resolved;
95
+ }
96
+
97
+ //#endregion
98
+ export { resolveReferencePages };
99
+ //# sourceMappingURL=resolve-BPE8sMvx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-BPE8sMvx.mjs","names":[],"sources":["../src/references/resolve.ts"],"sourcesContent":["/**\n * Resolve an entry's reference selections to loadable entries, for the public\n * query path.\n *\n * The cost is bounded and predictable: one link read per selected field, then\n * one entry read per *distinct* target collection — never one per link. A\n * caller that selects no fields issues nothing at all, which is what keeps\n * references off the logged-out hot path of every render that does not ask for\n * them.\n */\n\nimport { RelationRepository } from \"../database/repositories/relation.js\";\nimport { RevisionRepository } from \"../database/repositories/revision.js\";\nimport { getFallbackChain, isI18nEnabled } from \"../i18n/config.js\";\nimport { getDb, loadEntriesByGroups, type LoadedEntry } from \"../loader.js\";\nimport { getReferenceFieldMap } from \"./field-map.js\";\nimport {\n\tpageStagedGroups,\n\treadStagedReferences,\n\tREFERENCE_PAGE_LIMIT,\n\tREFERENCE_PAGE_MAX_LIMIT,\n\ttype PageOfGroups,\n} from \"./staged.js\";\nimport type { ReferenceQuery, ReferenceSelection } from \"./types.js\";\n\n/** One reference field's resolved page, before the query layer wraps the entries. */\nexport interface ResolvedReferencePage {\n\t/** The collection the entries belong to — what the `edit` proxy is scoped to. */\n\tcollection: string;\n\tentries: LoadedEntry[];\n\tnextCursor?: string;\n}\n\nexport interface ResolveReferencesOptions {\n\t/** The collection the selecting entry belongs to. */\n\tcollection: string;\n\t/** The selecting entry's own translation group. */\n\tentryGroup: string;\n\t/** The locale the parent resolved to, used to pick each target's variant. */\n\tlocale: string | null;\n\t/** The selecting entry's draft revision, when it has one. */\n\tdraftRevisionId?: string;\n\t/**\n\t * Whether this render may see unpublished content. It decides both halves of\n\t * draft visibility: whether a pending selection staged in the draft revision\n\t * replaces the published one, and whether an unpublished target resolves at\n\t * all.\n\t */\n\tserveDrafts: boolean;\n\t/** The fields to resolve, by field slug. */\n\tselection: ReferenceSelection;\n}\n\nfunction pageOptions(query: ReferenceQuery): { limit: number; cursor?: string } {\n\tif (query === true) return { limit: REFERENCE_PAGE_LIMIT };\n\tconst requested = query.limit ?? REFERENCE_PAGE_LIMIT;\n\treturn {\n\t\tlimit: Math.min(Math.max(requested, 1), REFERENCE_PAGE_MAX_LIMIT),\n\t\tcursor: query.cursor,\n\t};\n}\n\nfunction localeChainFor(locale: string | null): string[] {\n\tif (locale === null) return [];\n\treturn isI18nEnabled() ? getFallbackChain(locale) : [locale];\n}\n\nexport async function resolveReferencePages(\n\toptions: ResolveReferencesOptions,\n): Promise<Record<string, ResolvedReferencePage>> {\n\tconst fieldMap = await getReferenceFieldMap(options.collection);\n\tconst requested = Object.entries(options.selection).filter(\n\t\t(entry): entry is [string, ReferenceQuery] => entry[1] !== undefined && fieldMap.has(entry[0]),\n\t);\n\tif (requested.length === 0) return {};\n\n\tconst db = await getDb();\n\tconst relations = new RelationRepository(db);\n\n\tconst staged =\n\t\toptions.serveDrafts && options.draftRevisionId\n\t\t\t? readStagedReferences(\n\t\t\t\t\t(await new RevisionRepository(db).findById(options.draftRevisionId))?.data,\n\t\t\t\t)\n\t\t\t: undefined;\n\n\t// Phase one: each field's page of translation groups, in selection order.\n\t// Concurrent, like phase two — the fields are independent, and awaiting them\n\t// in turn would make N fields N sequential round trips.\n\tconst pages = new Map(\n\t\tawait Promise.all(\n\t\t\trequested.map(async ([slug, query]): Promise<[string, PageOfGroups]> => {\n\t\t\t\tconst binding = fieldMap.get(slug)!;\n\t\t\t\tconst page = pageOptions(query);\n\n\t\t\t\tconst stagedGroups = staged?.[slug];\n\t\t\t\tif (stagedGroups) return [slug, pageStagedGroups(stagedGroups, page)];\n\n\t\t\t\tconst links =\n\t\t\t\t\tbinding.side === \"child\"\n\t\t\t\t\t\t? await relations.getParentsPageById(binding.relationId, options.entryGroup, page)\n\t\t\t\t\t\t: await relations.getChildrenPageById(binding.relationId, options.entryGroup, page);\n\t\t\t\treturn [\n\t\t\t\t\tslug,\n\t\t\t\t\t{\n\t\t\t\t\t\tgroups: links.items.map((link) =>\n\t\t\t\t\t\t\tbinding.side === \"child\" ? link.parentGroup : link.childGroup,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnextCursor: links.nextCursor,\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}),\n\t\t),\n\t);\n\n\t// Phase two: one entry read per distinct target collection, however many\n\t// fields point at it.\n\tconst groupsByCollection = new Map<string, Set<string>>();\n\tfor (const [slug, page] of pages) {\n\t\tconst target = fieldMap.get(slug)!.targetCollection;\n\t\tconst groups = groupsByCollection.get(target) ?? new Set<string>();\n\t\tfor (const group of page.groups) groups.add(group);\n\t\tgroupsByCollection.set(target, groups);\n\t}\n\n\tconst localeChain = localeChainFor(options.locale);\n\tconst variantsByCollection = new Map<string, Map<string, LoadedEntry>>();\n\tawait Promise.all(\n\t\tArray.from(groupsByCollection, async ([collection, groups]) => {\n\t\t\tconst loaded = await loadEntriesByGroups(collection, [...groups], {\n\t\t\t\tpublishedOnly: !options.serveDrafts,\n\t\t\t\tlocaleChain,\n\t\t\t});\n\t\t\tconst byGroup = new Map<string, LoadedEntry>();\n\t\t\tfor (const entry of loaded) {\n\t\t\t\tconst group = entry.data.translationGroup;\n\t\t\t\tif (typeof group === \"string\") byGroup.set(group, entry);\n\t\t\t}\n\t\t\tvariantsByCollection.set(collection, byGroup);\n\t\t}),\n\t);\n\n\t// Phase three: rebuild each field in link order. A group with no surviving\n\t// variant — deleted, or unpublished for a render that may not see drafts —\n\t// drops out, exactly as a dangling link does.\n\tconst resolved: Record<string, ResolvedReferencePage> = {};\n\tfor (const [slug, page] of pages) {\n\t\tconst collection = fieldMap.get(slug)!.targetCollection;\n\t\tconst byGroup = variantsByCollection.get(collection);\n\t\tconst entries: LoadedEntry[] = [];\n\t\tfor (const group of page.groups) {\n\t\t\tconst variant = byGroup?.get(group);\n\t\t\tif (variant) entries.push(variant);\n\t\t}\n\t\tresolved[slug] = page.nextCursor\n\t\t\t? { collection, entries, nextCursor: page.nextCursor }\n\t\t\t: { collection, entries };\n\t}\n\treturn resolved;\n}\n"],"mappings":"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"}