emdash 0.40.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1258) hide show
  1. package/dist/action-token-CbKDcPJi.mjs +26 -0
  2. package/dist/action-token-CbKDcPJi.mjs.map +1 -0
  3. package/dist/activation-PtniBLt9.mjs +382 -0
  4. package/dist/activation-PtniBLt9.mjs.map +1 -0
  5. package/dist/adapters-C_Tf5x90.d.mts +171 -0
  6. package/dist/adapters-C_Tf5x90.d.mts.map +1 -0
  7. package/dist/allowed-origins-U1z4TdEZ.mjs +116 -0
  8. package/dist/allowed-origins-U1z4TdEZ.mjs.map +1 -0
  9. package/dist/api/route-utils.d.mts +4 -4
  10. package/dist/api/route-utils.mjs +46 -45
  11. package/dist/api/route-utils.mjs.map +1 -1
  12. package/dist/api/schemas/index.d.mts +2 -2
  13. package/dist/api/schemas/index.mjs +10 -10
  14. package/dist/api-CXwQkV_m.mjs +5122 -0
  15. package/dist/api-CXwQkV_m.mjs.map +1 -0
  16. package/dist/api-tokens-89WlohEN.mjs +166 -0
  17. package/dist/api-tokens-89WlohEN.mjs.map +1 -0
  18. package/dist/apply-Do3KNnUk.mjs +1659 -0
  19. package/dist/apply-Do3KNnUk.mjs.map +1 -0
  20. package/dist/approvals-CAX9Yw33.mjs +460 -0
  21. package/dist/approvals-CAX9Yw33.mjs.map +1 -0
  22. package/dist/artifact-fetch-B9W4CEST.mjs +659 -0
  23. package/dist/artifact-fetch-B9W4CEST.mjs.map +1 -0
  24. package/dist/astro/index.d.mts +14 -14
  25. package/dist/astro/index.mjs +26 -30
  26. package/dist/astro/index.mjs.map +1 -1
  27. package/dist/astro/middleware/auth.d.mts +12 -12
  28. package/dist/astro/middleware/auth.mjs +10 -10
  29. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  30. package/dist/astro/middleware/redirect.mjs +7 -7
  31. package/dist/astro/middleware/request-context.mjs +3 -3
  32. package/dist/astro/middleware/setup.mjs +1 -1
  33. package/dist/astro/middleware.d.mts +12 -12
  34. package/dist/astro/middleware.d.mts.map +1 -1
  35. package/dist/astro/middleware.mjs +110 -106
  36. package/dist/astro/middleware.mjs.map +1 -1
  37. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +14 -14
  38. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +14 -14
  39. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
  40. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +7 -7
  42. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +17 -17
  43. package/dist/astro/routes/api/admin/byline-fields/index.mjs +17 -17
  44. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +17 -17
  45. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +23 -23
  46. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +23 -23
  47. package/dist/astro/routes/api/admin/bylines/index.mjs +23 -23
  48. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -18
  49. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
  50. package/dist/astro/routes/api/admin/comments/bulk.mjs +17 -17
  51. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
  52. package/dist/astro/routes/api/admin/comments/index.mjs +17 -17
  53. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  54. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  55. package/dist/astro/routes/api/admin/media-usage/activation.mjs +20 -20
  56. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +22 -22
  57. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +22 -22
  58. package/dist/astro/routes/api/admin/media-usage/progress.mjs +25 -25
  59. package/dist/astro/routes/api/admin/media-usage/repair.mjs +31 -31
  60. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +22 -22
  61. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +22 -22
  62. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
  63. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
  64. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +8 -8
  65. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +8 -8
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +72 -68
  67. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +7 -7
  69. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +71 -67
  70. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +72 -68
  72. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +82 -78
  74. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/index.mjs +72 -68
  76. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +5 -5
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +71 -67
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +81 -77
  81. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +71 -67
  83. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +72 -68
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +83 -79
  87. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +9 -9
  89. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +74 -70
  90. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +7 -7
  92. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +72 -68
  93. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs +71 -67
  95. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +6 -6
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +71 -67
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  99. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +5 -5
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +71 -67
  101. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +4 -4
  103. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +40 -40
  104. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +40 -40
  105. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +42 -42
  106. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +42 -42
  107. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +42 -42
  108. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +43 -43
  109. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +43 -43
  110. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +42 -42
  111. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +43 -43
  112. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +44 -44
  113. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +42 -42
  114. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +42 -42
  115. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +44 -44
  116. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +42 -42
  117. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +44 -44
  118. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +42 -42
  119. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +42 -42
  120. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +44 -44
  121. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +42 -42
  122. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +42 -42
  123. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +44 -44
  124. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +5 -5
  125. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +4 -4
  126. package/dist/astro/routes/api/admin/users/_id_/index.mjs +15 -15
  127. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
  128. package/dist/astro/routes/api/admin/users/index.mjs +14 -14
  129. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  130. package/dist/astro/routes/api/auth/invite/accept.mjs +4 -4
  131. package/dist/astro/routes/api/auth/invite/complete.mjs +18 -18
  132. package/dist/astro/routes/api/auth/invite/index.mjs +16 -16
  133. package/dist/astro/routes/api/auth/invite/register-options.mjs +17 -17
  134. package/dist/astro/routes/api/auth/logout.mjs +5 -5
  135. package/dist/astro/routes/api/auth/magic-link/send.mjs +18 -18
  136. package/dist/astro/routes/api/auth/magic-link/verify.mjs +14 -14
  137. package/dist/astro/routes/api/auth/me.mjs +15 -15
  138. package/dist/astro/routes/api/auth/mode.mjs +5 -5
  139. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  140. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  141. package/dist/astro/routes/api/auth/passkey/_id_.mjs +14 -14
  142. package/dist/astro/routes/api/auth/passkey/index.mjs +4 -4
  143. package/dist/astro/routes/api/auth/passkey/options.mjs +19 -19
  144. package/dist/astro/routes/api/auth/passkey/register/options.mjs +17 -17
  145. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +18 -18
  146. package/dist/astro/routes/api/auth/passkey/verify.mjs +18 -18
  147. package/dist/astro/routes/api/auth/signup/complete.mjs +18 -18
  148. package/dist/astro/routes/api/auth/signup/request.mjs +17 -17
  149. package/dist/astro/routes/api/auth/signup/verify.mjs +4 -4
  150. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  151. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -18
  152. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +5 -5
  153. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -17
  154. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
  155. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +17 -17
  156. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +5 -5
  157. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +11 -11
  158. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +31 -31
  159. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +17 -17
  160. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +1 -2
  161. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -1
  162. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +42 -53
  163. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  164. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +34 -29
  165. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  166. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
  167. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +5 -5
  168. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +17 -17
  169. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +25 -24
  170. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  171. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +5 -5
  172. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +17 -17
  173. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  174. package/dist/astro/routes/api/content/_collection_/_id_.mjs +18 -18
  175. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  176. package/dist/astro/routes/api/content/_collection_/authors.mjs +5 -5
  177. package/dist/astro/routes/api/content/_collection_/index.mjs +15 -15
  178. package/dist/astro/routes/api/content/_collection_/trash.mjs +15 -15
  179. package/dist/astro/routes/api/dashboard.mjs +10 -9
  180. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  181. package/dist/astro/routes/api/dev/emails.mjs +5 -5
  182. package/dist/astro/routes/api/health.mjs +6 -6
  183. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  184. package/dist/astro/routes/api/import/probe.mjs +23 -23
  185. package/dist/astro/routes/api/import/wordpress/analyze.mjs +6 -6
  186. package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -13
  187. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
  188. package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -12
  189. package/dist/astro/routes/api/import/wordpress/media.mjs +19 -19
  190. package/dist/astro/routes/api/import/wordpress/prepare.mjs +18 -18
  191. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -13
  192. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +28 -28
  193. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  194. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +23 -23
  195. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -13
  196. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +34 -34
  197. package/dist/astro/routes/api/manifest.mjs +6 -6
  198. package/dist/astro/routes/api/mcp.mjs +98 -118
  199. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  200. package/dist/astro/routes/api/media/_id_/confirm.mjs +19 -19
  201. package/dist/astro/routes/api/media/_id_/replace.mjs +16 -16
  202. package/dist/astro/routes/api/media/_id_/upload.mjs +9 -9
  203. package/dist/astro/routes/api/media/_id_/usage.mjs +33 -33
  204. package/dist/astro/routes/api/media/_id_.mjs +31 -31
  205. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +6 -6
  206. package/dist/astro/routes/api/media/file/_...key_.mjs +9 -9
  207. package/dist/astro/routes/api/media/folders/_id_.mjs +16 -16
  208. package/dist/astro/routes/api/media/folders/index.mjs +16 -16
  209. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +5 -5
  210. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +5 -5
  211. package/dist/astro/routes/api/media/providers/index.mjs +5 -5
  212. package/dist/astro/routes/api/media/upload-url.mjs +18 -18
  213. package/dist/astro/routes/api/media.mjs +35 -35
  214. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -17
  215. package/dist/astro/routes/api/menus/_name_/items.mjs +17 -17
  216. package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -17
  217. package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -17
  218. package/dist/astro/routes/api/menus/_name_.mjs +17 -17
  219. package/dist/astro/routes/api/menus/index.mjs +17 -17
  220. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  221. package/dist/astro/routes/api/oauth/device/authorize.d.mts +2 -1
  222. package/dist/astro/routes/api/oauth/device/authorize.d.mts.map +1 -1
  223. package/dist/astro/routes/api/oauth/device/authorize.mjs +23 -9
  224. package/dist/astro/routes/api/oauth/device/authorize.mjs.map +1 -1
  225. package/dist/astro/routes/api/oauth/device/code.mjs +11 -11
  226. package/dist/astro/routes/api/oauth/device/token.mjs +10 -10
  227. package/dist/astro/routes/api/oauth/register.mjs +5 -5
  228. package/dist/astro/routes/api/oauth/token/refresh.mjs +8 -8
  229. package/dist/astro/routes/api/oauth/token/revoke.mjs +8 -8
  230. package/dist/astro/routes/api/oauth/token.mjs +8 -8
  231. package/dist/astro/routes/api/openapi.json.mjs +20 -20
  232. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +11 -11
  233. package/dist/astro/routes/api/redirects/404s/index.mjs +19 -19
  234. package/dist/astro/routes/api/redirects/404s/summary.mjs +19 -19
  235. package/dist/astro/routes/api/redirects/_id_.mjs +19 -19
  236. package/dist/astro/routes/api/redirects/index.mjs +19 -19
  237. package/dist/astro/routes/api/relations/_id_/index.mjs +34 -29
  238. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  239. package/dist/astro/routes/api/relations/index.mjs +36 -31
  240. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  241. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +5 -5
  242. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
  243. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +71 -67
  244. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  245. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +71 -67
  246. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  247. package/dist/astro/routes/api/schema/block-types/index.mjs +71 -67
  248. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  249. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +73 -69
  250. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  251. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +71 -67
  252. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  253. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +71 -67
  254. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  255. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +71 -67
  256. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  257. package/dist/astro/routes/api/schema/collections/index.mjs +71 -67
  258. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  259. package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -67
  260. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  261. package/dist/astro/routes/api/schema/index.mjs +16 -16
  262. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +71 -67
  263. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  264. package/dist/astro/routes/api/schema/orphans/index.mjs +71 -67
  265. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  266. package/dist/astro/routes/api/search/enable.mjs +19 -19
  267. package/dist/astro/routes/api/search/index.mjs +18 -18
  268. package/dist/astro/routes/api/search/rebuild.mjs +19 -19
  269. package/dist/astro/routes/api/search/stats.mjs +9 -9
  270. package/dist/astro/routes/api/search/suggest.mjs +18 -18
  271. package/dist/astro/routes/api/sections/_slug_.mjs +18 -18
  272. package/dist/astro/routes/api/sections/index.mjs +18 -18
  273. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  274. package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
  275. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  276. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  277. package/dist/astro/routes/api/settings/email.mjs +6 -6
  278. package/dist/astro/routes/api/settings.mjs +21 -21
  279. package/dist/astro/routes/api/setup/admin-verify.mjs +19 -19
  280. package/dist/astro/routes/api/setup/admin.mjs +18 -18
  281. package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -39
  282. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  283. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  284. package/dist/astro/routes/api/setup/index.d.mts.map +1 -1
  285. package/dist/astro/routes/api/setup/index.mjs +80 -49
  286. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  287. package/dist/astro/routes/api/setup/status.mjs +6 -6
  288. package/dist/astro/routes/api/snapshot.mjs +9 -9
  289. package/dist/astro/routes/api/snapshot.mjs.map +1 -1
  290. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -23
  291. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -23
  292. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -23
  293. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -23
  294. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -22
  295. package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -23
  296. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +36 -35
  297. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
  298. package/dist/astro/routes/api/taxonomies/index.mjs +23 -23
  299. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  300. package/dist/astro/routes/api/typegen.mjs +8 -8
  301. package/dist/astro/routes/api/visual-editing/action-token.mjs +6 -6
  302. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +19 -19
  303. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +4 -4
  304. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  305. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  306. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  307. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +16 -16
  308. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +19 -19
  309. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +19 -19
  310. package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -9
  311. package/dist/astro/routes/api/widget-areas/index.mjs +19 -19
  312. package/dist/astro/routes/api/widget-components.mjs +5 -5
  313. package/dist/astro/routes/robots.txt.mjs +6 -6
  314. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  315. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  316. package/dist/astro/types.d.mts +28 -18
  317. package/dist/astro/types.d.mts.map +1 -1
  318. package/dist/audit-CrgmE9LE.mjs +127 -0
  319. package/dist/audit-CrgmE9LE.mjs.map +1 -0
  320. package/dist/auth/providers/github.d.mts +1 -1
  321. package/dist/auth/providers/google.d.mts +1 -1
  322. package/dist/authoritative-records-C2YzIdbu.mjs +5172 -0
  323. package/dist/authoritative-records-C2YzIdbu.mjs.map +1 -0
  324. package/dist/authorize-WgdKF8QY.mjs +49 -0
  325. package/dist/authorize-WgdKF8QY.mjs.map +1 -0
  326. package/dist/backup-Ck8_lMO3.mjs +246 -0
  327. package/dist/backup-Ck8_lMO3.mjs.map +1 -0
  328. package/dist/block-types-BQ90asVI.mjs +132 -0
  329. package/dist/block-types-BQ90asVI.mjs.map +1 -0
  330. package/dist/block-values-ACFqgB1D.mjs +175 -0
  331. package/dist/block-values-ACFqgB1D.mjs.map +1 -0
  332. package/dist/bundle-Db1iNMv_.mjs +667 -0
  333. package/dist/bundle-Db1iNMv_.mjs.map +1 -0
  334. package/dist/byline-BayaYGoj.mjs +909 -0
  335. package/dist/byline-BayaYGoj.mjs.map +1 -0
  336. package/dist/byline-fields-B8HH-35f.mjs +254 -0
  337. package/dist/byline-fields-B8HH-35f.mjs.map +1 -0
  338. package/dist/byline-fields-hMPjf6Eu.mjs +123 -0
  339. package/dist/byline-fields-hMPjf6Eu.mjs.map +1 -0
  340. package/dist/byline-registry-B_EK_TQf.mjs +406 -0
  341. package/dist/byline-registry-B_EK_TQf.mjs.map +1 -0
  342. package/dist/bylines-DFAaFXWi.mjs +214 -0
  343. package/dist/bylines-DFAaFXWi.mjs.map +1 -0
  344. package/dist/bylines-DkIxUxmr.mjs +232 -0
  345. package/dist/bylines-DkIxUxmr.mjs.map +1 -0
  346. package/dist/cache-DkvhQ8XE.mjs +108 -0
  347. package/dist/cache-DkvhQ8XE.mjs.map +1 -0
  348. package/dist/canonical-CcSuuTlH.mjs +174 -0
  349. package/dist/canonical-CcSuuTlH.mjs.map +1 -0
  350. package/dist/capture-triggers-DJEoOTOq.mjs +362 -0
  351. package/dist/capture-triggers-DJEoOTOq.mjs.map +1 -0
  352. package/dist/challenge-store-CvBl81AQ.mjs +51 -0
  353. package/dist/challenge-store-CvBl81AQ.mjs.map +1 -0
  354. package/dist/checksum-CClweQzI.mjs +162 -0
  355. package/dist/checksum-CClweQzI.mjs.map +1 -0
  356. package/dist/chrome-tags-D5caJwwp.mjs +24 -0
  357. package/dist/chrome-tags-D5caJwwp.mjs.map +1 -0
  358. package/dist/chunks-DwBaj8aT.mjs +25 -0
  359. package/dist/chunks-DwBaj8aT.mjs.map +1 -0
  360. package/dist/cli/index.mjs +374 -761
  361. package/dist/cli/index.mjs.map +1 -1
  362. package/dist/client/cf-access.d.mts +1 -1
  363. package/dist/client/index.d.mts +18 -18
  364. package/dist/client/index.mjs +2 -2
  365. package/dist/collection-deletion-CLCdXsnV.mjs +436 -0
  366. package/dist/collection-deletion-CLCdXsnV.mjs.map +1 -0
  367. package/dist/collection-deletion-processor-hNw8x01F.mjs +217 -0
  368. package/dist/collection-deletion-processor-hNw8x01F.mjs.map +1 -0
  369. package/dist/collection-slugs-cache-CUuiduLq.mjs +85 -0
  370. package/dist/collection-slugs-cache-CUuiduLq.mjs.map +1 -0
  371. package/dist/comment-D2uvL63j.mjs +313 -0
  372. package/dist/comment-D2uvL63j.mjs.map +1 -0
  373. package/dist/comment-reaction-DevUuzg4.mjs +85 -0
  374. package/dist/comment-reaction-DevUuzg4.mjs.map +1 -0
  375. package/dist/comments-Cq0s7_hO.mjs +195 -0
  376. package/dist/comments-Cq0s7_hO.mjs.map +1 -0
  377. package/dist/comments-M4EDYAHw.mjs +99 -0
  378. package/dist/comments-M4EDYAHw.mjs.map +1 -0
  379. package/dist/components-CuIGwXMs.mjs +108 -0
  380. package/dist/components-CuIGwXMs.mjs.map +1 -0
  381. package/dist/config-52Ea5IWt.d.mts +39 -0
  382. package/dist/config-52Ea5IWt.d.mts.map +1 -0
  383. package/dist/config-CCz3xOLc.mjs +242 -0
  384. package/dist/config-CCz3xOLc.mjs.map +1 -0
  385. package/dist/config-D3d5Qudq.d.mts +6669 -0
  386. package/dist/config-D3d5Qudq.d.mts.map +1 -0
  387. package/dist/content-CbnufDsM.mjs +2018 -0
  388. package/dist/content-CbnufDsM.mjs.map +1 -0
  389. package/dist/content-list-query-D_7B1FE5.d.mts +26 -0
  390. package/dist/content-list-query-D_7B1FE5.d.mts.map +1 -0
  391. package/dist/content-policy-CYu6K1KB.mjs +46 -0
  392. package/dist/content-policy-CYu6K1KB.mjs.map +1 -0
  393. package/dist/content-repair-DlDUgFGp.mjs +442 -0
  394. package/dist/content-repair-DlDUgFGp.mjs.map +1 -0
  395. package/dist/context-CGQLA1-a.mjs +1922 -0
  396. package/dist/context-CGQLA1-a.mjs.map +1 -0
  397. package/dist/cron-c4D5C5Fx.mjs +284 -0
  398. package/dist/cron-c4D5C5Fx.mjs.map +1 -0
  399. package/dist/dashboard-CBq9kmOn.mjs +151 -0
  400. package/dist/dashboard-CBq9kmOn.mjs.map +1 -0
  401. package/dist/db/index.d.mts +3 -3
  402. package/dist/db/index.mjs +1 -1
  403. package/dist/db/libsql-migrations.d.mts +1 -1
  404. package/dist/db/libsql-migrations.mjs +4 -4
  405. package/dist/db/libsql.d.mts +1 -1
  406. package/dist/db/postgres-migrations.d.mts +1 -1
  407. package/dist/db/postgres-migrations.mjs +4 -4
  408. package/dist/db/postgres.d.mts +1 -1
  409. package/dist/db/sqlite-migrations.d.mts +1 -1
  410. package/dist/db/sqlite-migrations.mjs +4 -4
  411. package/dist/db/sqlite.d.mts +1 -1
  412. package/dist/db/sqlite.mjs +1 -1
  413. package/dist/default-DPsys51U.mjs +81 -0
  414. package/dist/default-DPsys51U.mjs.map +1 -0
  415. package/dist/deferred-tasks-CZ7rzBdo.d.mts +9 -0
  416. package/dist/deferred-tasks-CZ7rzBdo.d.mts.map +1 -0
  417. package/dist/dev-typegen-HRxwLRcT.mjs +29 -0
  418. package/dist/dev-typegen-HRxwLRcT.mjs.map +1 -0
  419. package/dist/device-flow-OcSqE9uY.mjs +521 -0
  420. package/dist/device-flow-OcSqE9uY.mjs.map +1 -0
  421. package/dist/digest-DVZ--cE9.mjs +194 -0
  422. package/dist/digest-DVZ--cE9.mjs.map +1 -0
  423. package/dist/direct-executor-DyjAqkpT.mjs +104 -0
  424. package/dist/direct-executor-DyjAqkpT.mjs.map +1 -0
  425. package/dist/dist-FPR93_xf.mjs +810 -0
  426. package/dist/dist-FPR93_xf.mjs.map +1 -0
  427. package/dist/email-console-DyQIgEnz.mjs +50 -0
  428. package/dist/email-console-DyQIgEnz.mjs.map +1 -0
  429. package/dist/email-locale-BYb16rVd.mjs +25 -0
  430. package/dist/email-locale-BYb16rVd.mjs.map +1 -0
  431. package/dist/emdash-runtime-CrzxJFmF.mjs +4214 -0
  432. package/dist/emdash-runtime-CrzxJFmF.mjs.map +1 -0
  433. package/dist/enrich-DBtCncE2.mjs +194 -0
  434. package/dist/enrich-DBtCncE2.mjs.map +1 -0
  435. package/dist/entry-lock-BN5y4YbO.d.mts +4481 -0
  436. package/dist/entry-lock-BN5y4YbO.d.mts.map +1 -0
  437. package/dist/entry-lock-BaRBHCsH.mjs +1173 -0
  438. package/dist/entry-lock-BaRBHCsH.mjs.map +1 -0
  439. package/dist/entry-lock-C6NcnZPV.mjs +163 -0
  440. package/dist/entry-lock-C6NcnZPV.mjs.map +1 -0
  441. package/dist/entry-locks-BTyQLdbC.mjs +167 -0
  442. package/dist/entry-locks-BTyQLdbC.mjs.map +1 -0
  443. package/dist/error-BfsNNrIE.mjs +90 -0
  444. package/dist/error-BfsNNrIE.mjs.map +1 -0
  445. package/dist/errors-BN1QAnEY.mjs +460 -0
  446. package/dist/errors-BN1QAnEY.mjs.map +1 -0
  447. package/dist/errors-Bt3goF8I.mjs +120 -0
  448. package/dist/errors-Bt3goF8I.mjs.map +1 -0
  449. package/dist/escape-BveidMa2.mjs +9 -0
  450. package/dist/escape-BveidMa2.mjs.map +1 -0
  451. package/dist/fence-Bb_IbCxI.mjs +162 -0
  452. package/dist/fence-Bb_IbCxI.mjs.map +1 -0
  453. package/dist/field-defs-cache-CsZctvbu.mjs +77 -0
  454. package/dist/field-defs-cache-CsZctvbu.mjs.map +1 -0
  455. package/dist/field-map-6m9rF49t.mjs +83 -0
  456. package/dist/field-map-6m9rF49t.mjs.map +1 -0
  457. package/dist/focal-point-CZ3d1wK5.mjs +23 -0
  458. package/dist/focal-point-CZ3d1wK5.mjs.map +1 -0
  459. package/dist/fts-manager-CCaZTp8y.mjs +443 -0
  460. package/dist/fts-manager-CCaZTp8y.mjs.map +1 -0
  461. package/dist/gc-xowRjczI.mjs +75 -0
  462. package/dist/gc-xowRjczI.mjs.map +1 -0
  463. package/dist/hash-COVK27Pc.mjs +37 -0
  464. package/dist/hash-COVK27Pc.mjs.map +1 -0
  465. package/dist/hook-result-CYSk0XFe.d.mts +31 -0
  466. package/dist/hook-result-CYSk0XFe.d.mts.map +1 -0
  467. package/dist/hreflang-CChPV7jx.mjs +105 -0
  468. package/dist/hreflang-CChPV7jx.mjs.map +1 -0
  469. package/dist/hreflang-DRslq3QI.d.mts +50 -0
  470. package/dist/hreflang-DRslq3QI.d.mts.map +1 -0
  471. package/dist/http-route-dispatch-CAdp2onn.mjs +339 -0
  472. package/dist/http-route-dispatch-CAdp2onn.mjs.map +1 -0
  473. package/dist/identity-NVTOOQyq.mjs +35 -0
  474. package/dist/identity-NVTOOQyq.mjs.map +1 -0
  475. package/dist/import-wpSO2N0x.mjs +2020 -0
  476. package/dist/import-wpSO2N0x.mjs.map +1 -0
  477. package/dist/index-CDs2wq4X.d.mts +623 -0
  478. package/dist/index-CDs2wq4X.d.mts.map +1 -0
  479. package/dist/index.d.mts +24 -24
  480. package/dist/index.mjs +103 -101
  481. package/dist/install-finalization-D9R9R-W8.mjs +58 -0
  482. package/dist/install-finalization-D9R9R-W8.mjs.map +1 -0
  483. package/dist/keys-Bck6LBfF.mjs +61 -0
  484. package/dist/keys-Bck6LBfF.mjs.map +1 -0
  485. package/dist/kinds-CYmRESWj.mjs +974 -0
  486. package/dist/kinds-CYmRESWj.mjs.map +1 -0
  487. package/dist/lifecycle-C815ZQfV.mjs +25 -0
  488. package/dist/lifecycle-C815ZQfV.mjs.map +1 -0
  489. package/dist/load-D99axixL.mjs +28 -0
  490. package/dist/load-D99axixL.mjs.map +1 -0
  491. package/dist/loader-CrRPfkHS.mjs +1197 -0
  492. package/dist/loader-CrRPfkHS.mjs.map +1 -0
  493. package/dist/loops-DMKlygqX.mjs +203 -0
  494. package/dist/loops-DMKlygqX.mjs.map +1 -0
  495. package/dist/manifest-builder-BQzCHNgB.mjs +189 -0
  496. package/dist/manifest-builder-BQzCHNgB.mjs.map +1 -0
  497. package/dist/manifest-schema-Ci2gmd0u.mjs +492 -0
  498. package/dist/manifest-schema-Ci2gmd0u.mjs.map +1 -0
  499. package/dist/media/image-endpoint.mjs +1 -1
  500. package/dist/media/index.d.mts +1 -1
  501. package/dist/media/index.mjs +4 -4
  502. package/dist/media/local-runtime.d.mts +14 -14
  503. package/dist/media/local-runtime.mjs +6 -6
  504. package/dist/media-BUQePMxP.mjs +373 -0
  505. package/dist/media-BUQePMxP.mjs.map +1 -0
  506. package/dist/media-DH8ibNlY.mjs +294 -0
  507. package/dist/media-DH8ibNlY.mjs.map +1 -0
  508. package/dist/media-OEIQ3bVc.mjs +408 -0
  509. package/dist/media-OEIQ3bVc.mjs.map +1 -0
  510. package/dist/media-allowlist-pYtaBA95.mjs +44 -0
  511. package/dist/media-allowlist-pYtaBA95.mjs.map +1 -0
  512. package/dist/media-folders-Bf8_s4de.mjs +210 -0
  513. package/dist/media-folders-Bf8_s4de.mjs.map +1 -0
  514. package/dist/media-url-C6klEuNd.mjs +43 -0
  515. package/dist/media-url-C6klEuNd.mjs.map +1 -0
  516. package/dist/media-usage-D7Y64m6v.mjs +1629 -0
  517. package/dist/media-usage-D7Y64m6v.mjs.map +1 -0
  518. package/dist/media-usage-activation-DrqbmgLA.mjs +78 -0
  519. package/dist/media-usage-activation-DrqbmgLA.mjs.map +1 -0
  520. package/dist/media-usage-work-DommYhYA.mjs +152 -0
  521. package/dist/media-usage-work-DommYhYA.mjs.map +1 -0
  522. package/dist/media-usage-work-HU63hNDu.mjs +586 -0
  523. package/dist/media-usage-work-HU63hNDu.mjs.map +1 -0
  524. package/dist/menus-BQfusWEC.mjs +3608 -0
  525. package/dist/menus-BQfusWEC.mjs.map +1 -0
  526. package/dist/menus-BtwjQt5s.mjs +753 -0
  527. package/dist/menus-BtwjQt5s.mjs.map +1 -0
  528. package/dist/menus-p_M1V7J_.mjs +139 -0
  529. package/dist/menus-p_M1V7J_.mjs.map +1 -0
  530. package/dist/migrations/index.d.mts +1 -1
  531. package/dist/migrations/index.mjs +3 -3
  532. package/dist/mime-C94qBG-P.mjs +36 -0
  533. package/dist/mime-C94qBG-P.mjs.map +1 -0
  534. package/dist/mode-DpYW3w6U.mjs +23 -0
  535. package/dist/mode-DpYW3w6U.mjs.map +1 -0
  536. package/dist/node-sqlite-compat-pWFw0lcc.mjs +46 -0
  537. package/dist/node-sqlite-compat-pWFw0lcc.mjs.map +1 -0
  538. package/dist/normalize-DduyxBjf.mjs +191 -0
  539. package/dist/normalize-DduyxBjf.mjs.map +1 -0
  540. package/dist/oauth-authorization-DAXsH1H9.mjs +274 -0
  541. package/dist/oauth-authorization-DAXsH1H9.mjs.map +1 -0
  542. package/dist/oauth-clients-DENiDQri.mjs +266 -0
  543. package/dist/oauth-clients-DENiDQri.mjs.map +1 -0
  544. package/dist/oauth-state-store-y8mEYVq9.mjs +50 -0
  545. package/dist/oauth-state-store-y8mEYVq9.mjs.map +1 -0
  546. package/dist/oauth-user-lookup-CtTYAy-O.mjs +26 -0
  547. package/dist/oauth-user-lookup-CtTYAy-O.mjs.map +1 -0
  548. package/dist/object-cache/memory.d.mts +1 -1
  549. package/dist/options-BYa1FgIM.d.mts +81 -0
  550. package/dist/options-BYa1FgIM.d.mts.map +1 -0
  551. package/dist/page/index.d.mts +2 -2
  552. package/dist/page/index.mjs +5 -5
  553. package/dist/parse-CORGGhHf.mjs +81 -0
  554. package/dist/parse-CORGGhHf.mjs.map +1 -0
  555. package/dist/parse-avNM1xWV.d.mts +168 -0
  556. package/dist/parse-avNM1xWV.d.mts.map +1 -0
  557. package/dist/passkey-config-Dih5YeIS.mjs +46 -0
  558. package/dist/passkey-config-Dih5YeIS.mjs.map +1 -0
  559. package/dist/paths-d51RFm8M.mjs +77 -0
  560. package/dist/paths-d51RFm8M.mjs.map +1 -0
  561. package/dist/patterns-CoqlXUvk.mjs +145 -0
  562. package/dist/patterns-CoqlXUvk.mjs.map +1 -0
  563. package/dist/placeholder-D2aksPMF.d.mts +306 -0
  564. package/dist/placeholder-D2aksPMF.d.mts.map +1 -0
  565. package/dist/plan-DqeZKuaR.mjs +135 -0
  566. package/dist/plan-DqeZKuaR.mjs.map +1 -0
  567. package/dist/plugin-test-runtime.d.mts +14 -14
  568. package/dist/plugin-test-runtime.mjs +110 -107
  569. package/dist/plugin-types.d.mts +2 -2
  570. package/dist/plugin-utils.d.mts +12 -12
  571. package/dist/plugins/adapt-sandbox-entry.d.mts +12 -12
  572. package/dist/plugins/adapt-sandbox-entry.mjs +3 -3
  573. package/dist/plugins/host.d.mts +5 -5
  574. package/dist/plugins/host.mjs +42 -41
  575. package/dist/plugins-Bb7oqjQA.mjs +277 -0
  576. package/dist/plugins-Bb7oqjQA.mjs.map +1 -0
  577. package/dist/policy-BcEqut3n.mjs +45 -0
  578. package/dist/policy-BcEqut3n.mjs.map +1 -0
  579. package/dist/portable-text-DXE8ymtD.mjs +307 -0
  580. package/dist/portable-text-DXE8ymtD.mjs.map +1 -0
  581. package/dist/preview-DEDWbwA_.mjs +107 -0
  582. package/dist/preview-DEDWbwA_.mjs.map +1 -0
  583. package/dist/protocol-BJbTzvwl.d.mts +61 -0
  584. package/dist/protocol-BJbTzvwl.d.mts.map +1 -0
  585. package/dist/public-submission-D9c9S14m.mjs +250 -0
  586. package/dist/public-submission-D9c9S14m.mjs.map +1 -0
  587. package/dist/public-url-CIRe-2T6.mjs +101 -0
  588. package/dist/public-url-CIRe-2T6.mjs.map +1 -0
  589. package/dist/query-BzifXlPS.mjs +1156 -0
  590. package/dist/query-BzifXlPS.mjs.map +1 -0
  591. package/dist/query-OzMJ6vJP.mjs +41 -0
  592. package/dist/query-OzMJ6vJP.mjs.map +1 -0
  593. package/dist/rate-limit-Csp60Vik.mjs +120 -0
  594. package/dist/rate-limit-Csp60Vik.mjs.map +1 -0
  595. package/dist/receipt-B-aU4hpJ.mjs +43 -0
  596. package/dist/receipt-B-aU4hpJ.mjs.map +1 -0
  597. package/dist/redirect-CDSw1sU3.mjs +17 -0
  598. package/dist/redirect-CDSw1sU3.mjs.map +1 -0
  599. package/dist/redirect-D1ArbO85.mjs +411 -0
  600. package/dist/redirect-D1ArbO85.mjs.map +1 -0
  601. package/dist/redirects-BjTwDTsV.mjs +148 -0
  602. package/dist/redirects-BjTwDTsV.mjs.map +1 -0
  603. package/dist/redirects-Ck50kH3n.mjs +446 -0
  604. package/dist/redirects-Ck50kH3n.mjs.map +1 -0
  605. package/dist/registry/testing.mjs +3 -3
  606. package/dist/registry-CFcNCayZ.mjs +6754 -0
  607. package/dist/registry-CFcNCayZ.mjs.map +1 -0
  608. package/dist/relations-Cfaa1fDl.mjs +776 -0
  609. package/dist/relations-Cfaa1fDl.mjs.map +1 -0
  610. package/dist/request-cache-iHRlHx1d.mjs +104 -0
  611. package/dist/request-cache-iHRlHx1d.mjs.map +1 -0
  612. package/dist/request-context.d.mts +1 -1
  613. package/dist/request-meta-D47mqyev.mjs +141 -0
  614. package/dist/request-meta-D47mqyev.mjs.map +1 -0
  615. package/dist/resolve-BPE8sMvx.mjs +99 -0
  616. package/dist/resolve-BPE8sMvx.mjs.map +1 -0
  617. package/dist/resolve-C0s1E_fH.mjs +199 -0
  618. package/dist/resolve-C0s1E_fH.mjs.map +1 -0
  619. package/dist/revision-j1p4-bOj.mjs +302 -0
  620. package/dist/revision-j1p4-bOj.mjs.map +1 -0
  621. package/dist/route-wire-C9PJV9aL.mjs +197 -0
  622. package/dist/route-wire-C9PJV9aL.mjs.map +1 -0
  623. package/dist/routes-lyYw0mMf.mjs +272 -0
  624. package/dist/routes-lyYw0mMf.mjs.map +1 -0
  625. package/dist/runner-B3eyB9Gb.mjs +6121 -0
  626. package/dist/runner-B3eyB9Gb.mjs.map +1 -0
  627. package/dist/runner-DoYH2Jcu.d.mts +68 -0
  628. package/dist/runner-DoYH2Jcu.d.mts.map +1 -0
  629. package/dist/runtime.d.mts +13 -13
  630. package/dist/runtime.mjs +3 -3
  631. package/dist/schema-BAayK46S.mjs +13 -0
  632. package/dist/schema-BAayK46S.mjs.map +1 -0
  633. package/dist/schema-Gqcl-8G4.mjs +815 -0
  634. package/dist/schema-Gqcl-8G4.mjs.map +1 -0
  635. package/dist/scopes-BqPOKoKf.mjs +34 -0
  636. package/dist/scopes-BqPOKoKf.mjs.map +1 -0
  637. package/dist/search-YJKPIEV6.mjs +448 -0
  638. package/dist/search-YJKPIEV6.mjs.map +1 -0
  639. package/dist/sections-BR_e-wK5.mjs +346 -0
  640. package/dist/sections-BR_e-wK5.mjs.map +1 -0
  641. package/dist/seed/index.d.mts +2 -2
  642. package/dist/seed/index.mjs +37 -31
  643. package/dist/seo/index.d.mts +3 -3
  644. package/dist/seo/index.mjs +22 -21
  645. package/dist/seo/index.mjs.map +1 -1
  646. package/dist/seo-Dsj8hy3j.mjs +114 -0
  647. package/dist/seo-Dsj8hy3j.mjs.map +1 -0
  648. package/dist/seo-XvH4LNNp.mjs +133 -0
  649. package/dist/seo-XvH4LNNp.mjs.map +1 -0
  650. package/dist/service-BsVG05gS.mjs +150 -0
  651. package/dist/service-BsVG05gS.mjs.map +1 -0
  652. package/dist/session-user-DgKbYrlj.mjs +51 -0
  653. package/dist/session-user-DgKbYrlj.mjs.map +1 -0
  654. package/dist/settings-CNPUntkh.mjs +51 -0
  655. package/dist/settings-CNPUntkh.mjs.map +1 -0
  656. package/dist/settings-D5EHi0Tk.mjs +439 -0
  657. package/dist/settings-D5EHi0Tk.mjs.map +1 -0
  658. package/dist/settings-DSfE7wOa.mjs +61 -0
  659. package/dist/settings-DSfE7wOa.mjs.map +1 -0
  660. package/dist/setup-complete-B8W8sJ9v.mjs +26 -0
  661. package/dist/setup-complete-B8W8sJ9v.mjs.map +1 -0
  662. package/dist/setup-nonce-DnSBP260.mjs +25 -0
  663. package/dist/setup-nonce-DnSBP260.mjs.map +1 -0
  664. package/dist/site-settings-NGzdrt7O.mjs +50 -0
  665. package/dist/site-settings-NGzdrt7O.mjs.map +1 -0
  666. package/dist/site-url-D6JB7tLW.mjs +16 -0
  667. package/dist/site-url-D6JB7tLW.mjs.map +1 -0
  668. package/dist/snapshot-CdcwwWAf.mjs +414 -0
  669. package/dist/snapshot-CdcwwWAf.mjs.map +1 -0
  670. package/dist/ssrf-Dv0_tRpo.mjs +406 -0
  671. package/dist/ssrf-Dv0_tRpo.mjs.map +1 -0
  672. package/dist/stage-CUjhED3P.mjs +662 -0
  673. package/dist/stage-CUjhED3P.mjs.map +1 -0
  674. package/dist/staged-C36IWXff.mjs +659 -0
  675. package/dist/staged-C36IWXff.mjs.map +1 -0
  676. package/dist/state-CKouMCSY.mjs +153 -0
  677. package/dist/state-CKouMCSY.mjs.map +1 -0
  678. package/dist/status-lzyj4Uu7.mjs +30 -0
  679. package/dist/status-lzyj4Uu7.mjs.map +1 -0
  680. package/dist/storage/local.d.mts +1 -1
  681. package/dist/storage/local.mjs +1 -1
  682. package/dist/storage/s3.d.mts +1 -1
  683. package/dist/storage/s3.mjs +1 -1
  684. package/dist/storage-query-B-cWcTjJ.d.mts +1594 -0
  685. package/dist/storage-query-B-cWcTjJ.d.mts.map +1 -0
  686. package/dist/tar-DsTXX6ch.mjs +449 -0
  687. package/dist/tar-DsTXX6ch.mjs.map +1 -0
  688. package/dist/target-DLQCwp_Z.mjs +27 -0
  689. package/dist/target-DLQCwp_Z.mjs.map +1 -0
  690. package/dist/taxonomies-BlAjr4BL.mjs +697 -0
  691. package/dist/taxonomies-BlAjr4BL.mjs.map +1 -0
  692. package/dist/taxonomies-Byyo7LOZ.mjs +939 -0
  693. package/dist/taxonomies-Byyo7LOZ.mjs.map +1 -0
  694. package/dist/taxonomy-CKDwM61Y.mjs +525 -0
  695. package/dist/taxonomy-CKDwM61Y.mjs.map +1 -0
  696. package/dist/tokens-BojXlk49.mjs +171 -0
  697. package/dist/tokens-BojXlk49.mjs.map +1 -0
  698. package/dist/transaction-DLPQWik1.mjs +29 -0
  699. package/dist/transaction-DLPQWik1.mjs.map +1 -0
  700. package/dist/transfer-XSTh2BCr.mjs +8706 -0
  701. package/dist/transfer-XSTh2BCr.mjs.map +1 -0
  702. package/dist/transfer-download-DkoCDA9d.mjs +33 -0
  703. package/dist/transfer-download-DkoCDA9d.mjs.map +1 -0
  704. package/dist/transfer-iQ26J-RT.mjs +166 -0
  705. package/dist/transfer-iQ26J-RT.mjs.map +1 -0
  706. package/dist/transformations-C7RQabKQ.mjs +196 -0
  707. package/dist/transformations-C7RQabKQ.mjs.map +1 -0
  708. package/dist/transport-D3RulfD6.mjs +136 -0
  709. package/dist/transport-D3RulfD6.mjs.map +1 -0
  710. package/dist/transport-DhlZlf4D.d.mts +42 -0
  711. package/dist/transport-DhlZlf4D.d.mts.map +1 -0
  712. package/dist/trusted-proxy-B6ECOZJc.mjs +51 -0
  713. package/dist/trusted-proxy-B6ECOZJc.mjs.map +1 -0
  714. package/dist/turnstile-lqUiY7lP.mjs +53 -0
  715. package/dist/turnstile-lqUiY7lP.mjs.map +1 -0
  716. package/dist/types-4Dn9bZhu.mjs +77 -0
  717. package/dist/types-4Dn9bZhu.mjs.map +1 -0
  718. package/dist/types-5LSo7PPx.d.mts +85 -0
  719. package/dist/types-5LSo7PPx.d.mts.map +1 -0
  720. package/dist/types-BQ3hwYJT.d.mts +896 -0
  721. package/dist/types-BQ3hwYJT.d.mts.map +1 -0
  722. package/dist/types-BYEk7qo3.d.mts +198 -0
  723. package/dist/types-BYEk7qo3.d.mts.map +1 -0
  724. package/dist/types-CJKsWVFR.mjs +199 -0
  725. package/dist/types-CJKsWVFR.mjs.map +1 -0
  726. package/dist/types-Ca_w8mmY.d.mts +363 -0
  727. package/dist/types-Ca_w8mmY.d.mts.map +1 -0
  728. package/dist/types-CkE41ZAG.mjs +18 -0
  729. package/dist/types-CkE41ZAG.mjs.map +1 -0
  730. package/dist/types-D0aJW2uR.d.mts +1641 -0
  731. package/dist/types-D0aJW2uR.d.mts.map +1 -0
  732. package/dist/types-DbpN4Qto.d.mts +372 -0
  733. package/dist/types-DbpN4Qto.d.mts.map +1 -0
  734. package/dist/types-ILDI1sdY.mjs +16 -0
  735. package/dist/types-ILDI1sdY.mjs.map +1 -0
  736. package/dist/types-OC5c-edM.mjs +22 -0
  737. package/dist/types-OC5c-edM.mjs.map +1 -0
  738. package/dist/types-aOOxRSx6.mjs +103 -0
  739. package/dist/types-aOOxRSx6.mjs.map +1 -0
  740. package/dist/types-m1WbUffD.d.mts +198 -0
  741. package/dist/types-m1WbUffD.d.mts.map +1 -0
  742. package/dist/types-uxLoPBio.d.mts +124 -0
  743. package/dist/types-uxLoPBio.d.mts.map +1 -0
  744. package/dist/types-we5uR-tV.d.mts +287 -0
  745. package/dist/types-we5uR-tV.d.mts.map +1 -0
  746. package/dist/upload-attempts-DduMy6B0.mjs +32 -0
  747. package/dist/upload-attempts-DduMy6B0.mjs.map +1 -0
  748. package/dist/url-pattern-B3EwxAAk.mjs +33 -0
  749. package/dist/url-pattern-B3EwxAAk.mjs.map +1 -0
  750. package/dist/user-ElwQjTQT.mjs +171 -0
  751. package/dist/user-ElwQjTQT.mjs.map +1 -0
  752. package/dist/utils-BlAXmfOG.mjs +439 -0
  753. package/dist/utils-BlAXmfOG.mjs.map +1 -0
  754. package/dist/validate-CH0X5b2c.d.mts +468 -0
  755. package/dist/validate-CH0X5b2c.d.mts.map +1 -0
  756. package/dist/validate-CfgRpcjA.mjs +492 -0
  757. package/dist/validate-CfgRpcjA.mjs.map +1 -0
  758. package/dist/validation-DvYJtv4k.mjs +218 -0
  759. package/dist/validation-DvYJtv4k.mjs.map +1 -0
  760. package/dist/version-DgYjhTud.mjs +9 -0
  761. package/dist/version-DgYjhTud.mjs.map +1 -0
  762. package/dist/version-Dq71scUb.mjs +7 -0
  763. package/dist/version-Dq71scUb.mjs.map +1 -0
  764. package/dist/widgets-ChFIj0be.mjs +126 -0
  765. package/dist/widgets-ChFIj0be.mjs.map +1 -0
  766. package/dist/wxr-taxonomies-CBZMp2YX.mjs +372 -0
  767. package/dist/wxr-taxonomies-CBZMp2YX.mjs.map +1 -0
  768. package/dist/wxr-taxonomies-DlKDpWN1.d.mts +34 -0
  769. package/dist/wxr-taxonomies-DlKDpWN1.d.mts.map +1 -0
  770. package/dist/zod-generator-DmTKI-Ig.mjs +426 -0
  771. package/dist/zod-generator-DmTKI-Ig.mjs.map +1 -0
  772. package/package.json +7 -6
  773. package/src/api/handlers/content.ts +593 -16
  774. package/src/api/handlers/device-flow.ts +74 -21
  775. package/src/api/handlers/index.ts +1 -0
  776. package/src/api/handlers/manifest.ts +79 -5
  777. package/src/api/handlers/media-upload.ts +17 -71
  778. package/src/api/handlers/media.ts +97 -3
  779. package/src/api/handlers/relations.ts +638 -157
  780. package/src/api/handlers/revision.ts +30 -0
  781. package/src/api/handlers/schema.ts +403 -1
  782. package/src/api/handlers/snapshot.ts +257 -3
  783. package/src/api/handlers/staged-references.ts +142 -0
  784. package/src/api/handlers/validate-references.ts +146 -0
  785. package/src/api/schemas/content.ts +13 -0
  786. package/src/api/schemas/relations.ts +54 -44
  787. package/src/api/schemas/schema.ts +14 -0
  788. package/src/astro/integration/routes.ts +15 -19
  789. package/src/astro/integration/vite-config.ts +10 -4
  790. package/src/astro/middleware.ts +1 -0
  791. package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +11 -54
  792. package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
  793. package/src/astro/routes/api/oauth/device/authorize.ts +33 -4
  794. package/src/astro/routes/api/relations/index.ts +4 -4
  795. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +6 -2
  796. package/src/astro/routes/api/setup/index.ts +66 -23
  797. package/src/astro/routes/api/snapshot.ts +2 -1
  798. package/src/astro/types.ts +10 -0
  799. package/src/cleanup.ts +10 -0
  800. package/src/cli/commands/export-seed.ts +510 -89
  801. package/src/components/Columns.astro +3 -1
  802. package/src/components/Cover.astro +3 -1
  803. package/src/components/WidgetArea.astro +3 -2
  804. package/src/database/migrations/086_relations_structural.ts +197 -0
  805. package/src/database/migrations/087_reference_field_relations.ts +407 -0
  806. package/src/database/migrations/runner.ts +4 -0
  807. package/src/database/reference-backfill.ts +141 -0
  808. package/src/database/repositories/content.ts +43 -8
  809. package/src/database/repositories/media.ts +40 -1
  810. package/src/database/repositories/redirect.ts +17 -34
  811. package/src/database/repositories/relation.ts +620 -208
  812. package/src/database/repositories/revision.ts +16 -0
  813. package/src/database/repositories/types.ts +38 -0
  814. package/src/database/transaction.ts +12 -1
  815. package/src/database/types.ts +14 -5
  816. package/src/emdash-runtime.ts +114 -11
  817. package/src/index.ts +11 -0
  818. package/src/loader.ts +169 -22
  819. package/src/mcp/server.ts +13 -48
  820. package/src/query.ts +455 -25
  821. package/src/references/field-map.ts +115 -0
  822. package/src/references/resolve.ts +160 -0
  823. package/src/references/staged.ts +117 -0
  824. package/src/references/types.ts +16 -0
  825. package/src/registry/artifact-fetch.ts +45 -271
  826. package/src/schema/registry.ts +99 -24
  827. package/src/schema/types.ts +58 -0
  828. package/src/schema/zod-generator.ts +67 -1
  829. package/src/seed/apply.ts +841 -103
  830. package/src/seed/types.ts +36 -2
  831. package/src/seed/validate.ts +78 -2
  832. package/src/transfer/analyze/unique-keys.ts +3 -12
  833. package/src/transfer/analyze/validate.ts +65 -39
  834. package/src/transfer/analyze/values.ts +12 -1
  835. package/src/transfer/export/readers.ts +12 -8
  836. package/src/transfer/format/columns.ts +26 -6
  837. package/src/transfer/format/kinds.ts +21 -5
  838. package/src/transfer/import/context.ts +8 -1
  839. package/src/transfer/ops/package-index.ts +1 -1
  840. package/dist/action-token-DYwe4Pk0.mjs +0 -26
  841. package/dist/action-token-DYwe4Pk0.mjs.map +0 -1
  842. package/dist/activation-LOkDM5WT.mjs +0 -382
  843. package/dist/activation-LOkDM5WT.mjs.map +0 -1
  844. package/dist/adapters-B64LbYcB.d.mts +0 -171
  845. package/dist/adapters-B64LbYcB.d.mts.map +0 -1
  846. package/dist/allowed-origins-CHB8oZNM.mjs +0 -116
  847. package/dist/allowed-origins-CHB8oZNM.mjs.map +0 -1
  848. package/dist/api-cFFZpyS0.mjs +0 -4718
  849. package/dist/api-cFFZpyS0.mjs.map +0 -1
  850. package/dist/api-tokens-s4i4aUp_.mjs +0 -166
  851. package/dist/api-tokens-s4i4aUp_.mjs.map +0 -1
  852. package/dist/apply-CoT603H3.mjs +0 -1163
  853. package/dist/apply-CoT603H3.mjs.map +0 -1
  854. package/dist/approvals-CqMfNxak.mjs +0 -460
  855. package/dist/approvals-CqMfNxak.mjs.map +0 -1
  856. package/dist/artifact-fetch-DZMOGZ3-.mjs +0 -818
  857. package/dist/artifact-fetch-DZMOGZ3-.mjs.map +0 -1
  858. package/dist/astro/routes/api/relations/_id_/translations.d.mts +0 -8
  859. package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +0 -1
  860. package/dist/astro/routes/api/relations/_id_/translations.mjs +0 -47
  861. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +0 -1
  862. package/dist/audit-RfCugiSB.mjs +0 -127
  863. package/dist/audit-RfCugiSB.mjs.map +0 -1
  864. package/dist/authoritative-records-CoJvBXAD.mjs +0 -5172
  865. package/dist/authoritative-records-CoJvBXAD.mjs.map +0 -1
  866. package/dist/authorize-seCifOMJ.mjs +0 -49
  867. package/dist/authorize-seCifOMJ.mjs.map +0 -1
  868. package/dist/backup-CBu0LrXf.mjs +0 -246
  869. package/dist/backup-CBu0LrXf.mjs.map +0 -1
  870. package/dist/block-type-registry-DUI_3KxT.mjs +0 -6709
  871. package/dist/block-type-registry-DUI_3KxT.mjs.map +0 -1
  872. package/dist/block-types-BmZmLmAD.mjs +0 -132
  873. package/dist/block-types-BmZmLmAD.mjs.map +0 -1
  874. package/dist/block-values-C_VIPr5t.mjs +0 -175
  875. package/dist/block-values-C_VIPr5t.mjs.map +0 -1
  876. package/dist/byline-DYmkXqvo.mjs +0 -909
  877. package/dist/byline-DYmkXqvo.mjs.map +0 -1
  878. package/dist/byline-fields-D28AT-Fh.mjs +0 -123
  879. package/dist/byline-fields-D28AT-Fh.mjs.map +0 -1
  880. package/dist/byline-registry-gnKscbQX.mjs +0 -406
  881. package/dist/byline-registry-gnKscbQX.mjs.map +0 -1
  882. package/dist/bylines-BPwJqoYH.mjs +0 -232
  883. package/dist/bylines-BPwJqoYH.mjs.map +0 -1
  884. package/dist/bylines-ukLaYpVZ.mjs +0 -214
  885. package/dist/bylines-ukLaYpVZ.mjs.map +0 -1
  886. package/dist/cache-m7UEkRFV.mjs +0 -108
  887. package/dist/cache-m7UEkRFV.mjs.map +0 -1
  888. package/dist/canonical-YhEQezjg.mjs +0 -174
  889. package/dist/canonical-YhEQezjg.mjs.map +0 -1
  890. package/dist/capture-triggers-kJyl_yyM.mjs +0 -362
  891. package/dist/capture-triggers-kJyl_yyM.mjs.map +0 -1
  892. package/dist/challenge-store-ppU6Uv13.mjs +0 -51
  893. package/dist/challenge-store-ppU6Uv13.mjs.map +0 -1
  894. package/dist/checksum-B2IINIlN.mjs +0 -162
  895. package/dist/checksum-B2IINIlN.mjs.map +0 -1
  896. package/dist/chrome-tags-DApCQSIk.mjs +0 -24
  897. package/dist/chrome-tags-DApCQSIk.mjs.map +0 -1
  898. package/dist/chunks-Dms7Uxbt.mjs +0 -25
  899. package/dist/chunks-Dms7Uxbt.mjs.map +0 -1
  900. package/dist/collection-deletion-BIm28mo3.mjs +0 -436
  901. package/dist/collection-deletion-BIm28mo3.mjs.map +0 -1
  902. package/dist/collection-deletion-processor-Br6rxs3u.mjs +0 -217
  903. package/dist/collection-deletion-processor-Br6rxs3u.mjs.map +0 -1
  904. package/dist/collection-slugs-cache-CjGk__zp.mjs +0 -85
  905. package/dist/collection-slugs-cache-CjGk__zp.mjs.map +0 -1
  906. package/dist/comment-CrBl22OF.mjs +0 -313
  907. package/dist/comment-CrBl22OF.mjs.map +0 -1
  908. package/dist/comment-reaction-JEQ2Fpd8.mjs +0 -85
  909. package/dist/comment-reaction-JEQ2Fpd8.mjs.map +0 -1
  910. package/dist/comments-2ah9du9y.mjs +0 -195
  911. package/dist/comments-2ah9du9y.mjs.map +0 -1
  912. package/dist/comments-fHZ8ON9O.mjs +0 -99
  913. package/dist/comments-fHZ8ON9O.mjs.map +0 -1
  914. package/dist/components-CXbq7CSM.mjs +0 -108
  915. package/dist/components-CXbq7CSM.mjs.map +0 -1
  916. package/dist/config-5ii2haYu.d.mts +0 -6528
  917. package/dist/config-5ii2haYu.d.mts.map +0 -1
  918. package/dist/config-IhybvkIQ.mjs +0 -242
  919. package/dist/config-IhybvkIQ.mjs.map +0 -1
  920. package/dist/config-Py43JK9r.d.mts +0 -39
  921. package/dist/config-Py43JK9r.d.mts.map +0 -1
  922. package/dist/content-DFaIEDj9.mjs +0 -2281
  923. package/dist/content-DFaIEDj9.mjs.map +0 -1
  924. package/dist/content-list-query-Dra4Dalc.d.mts +0 -26
  925. package/dist/content-list-query-Dra4Dalc.d.mts.map +0 -1
  926. package/dist/content-policy-DFNw91-d.mjs +0 -46
  927. package/dist/content-policy-DFNw91-d.mjs.map +0 -1
  928. package/dist/content-repair-Q8IUrpLL.mjs +0 -442
  929. package/dist/content-repair-Q8IUrpLL.mjs.map +0 -1
  930. package/dist/context-BeGccdUX.mjs +0 -1921
  931. package/dist/context-BeGccdUX.mjs.map +0 -1
  932. package/dist/cron-7DCJwPXq.mjs +0 -284
  933. package/dist/cron-7DCJwPXq.mjs.map +0 -1
  934. package/dist/dashboard-DjrB-xxZ.mjs +0 -151
  935. package/dist/dashboard-DjrB-xxZ.mjs.map +0 -1
  936. package/dist/default-DQ6vsviu.mjs +0 -81
  937. package/dist/default-DQ6vsviu.mjs.map +0 -1
  938. package/dist/deferred-tasks-BPxXUB4x.d.mts +0 -9
  939. package/dist/deferred-tasks-BPxXUB4x.d.mts.map +0 -1
  940. package/dist/dev-typegen-CZaPLl3V.mjs +0 -29
  941. package/dist/dev-typegen-CZaPLl3V.mjs.map +0 -1
  942. package/dist/device-flow-CRd6DXmW.mjs +0 -466
  943. package/dist/device-flow-CRd6DXmW.mjs.map +0 -1
  944. package/dist/digest-BarSh-pN.mjs +0 -194
  945. package/dist/digest-BarSh-pN.mjs.map +0 -1
  946. package/dist/direct-executor-BmuFJJZV.mjs +0 -104
  947. package/dist/direct-executor-BmuFJJZV.mjs.map +0 -1
  948. package/dist/dist-BNwANFJR.mjs +0 -810
  949. package/dist/dist-BNwANFJR.mjs.map +0 -1
  950. package/dist/email-console-bJn3ctqA.mjs +0 -50
  951. package/dist/email-console-bJn3ctqA.mjs.map +0 -1
  952. package/dist/email-locale-CN6WAMx0.mjs +0 -25
  953. package/dist/email-locale-CN6WAMx0.mjs.map +0 -1
  954. package/dist/emdash-runtime-DAjghyEG.mjs +0 -4186
  955. package/dist/emdash-runtime-DAjghyEG.mjs.map +0 -1
  956. package/dist/enrich-Dl3kZ-lP.mjs +0 -194
  957. package/dist/enrich-Dl3kZ-lP.mjs.map +0 -1
  958. package/dist/entry-lock-BJYdBfXb.mjs +0 -1097
  959. package/dist/entry-lock-BJYdBfXb.mjs.map +0 -1
  960. package/dist/entry-lock-DHQOxN7R.mjs +0 -163
  961. package/dist/entry-lock-DHQOxN7R.mjs.map +0 -1
  962. package/dist/entry-lock-DVhCt49A.d.mts +0 -4368
  963. package/dist/entry-lock-DVhCt49A.d.mts.map +0 -1
  964. package/dist/entry-locks-D0foLdjQ.mjs +0 -167
  965. package/dist/entry-locks-D0foLdjQ.mjs.map +0 -1
  966. package/dist/error-CfvOHP0M.mjs +0 -90
  967. package/dist/error-CfvOHP0M.mjs.map +0 -1
  968. package/dist/errors-BF0_LFhW.mjs +0 -460
  969. package/dist/errors-BF0_LFhW.mjs.map +0 -1
  970. package/dist/errors-DgE1zJGG.mjs +0 -120
  971. package/dist/errors-DgE1zJGG.mjs.map +0 -1
  972. package/dist/escape-CuaZhZvL.mjs +0 -9
  973. package/dist/escape-CuaZhZvL.mjs.map +0 -1
  974. package/dist/fence-CMDXJYc_.mjs +0 -162
  975. package/dist/fence-CMDXJYc_.mjs.map +0 -1
  976. package/dist/field-defs-cache-HIgBbqZZ.mjs +0 -77
  977. package/dist/field-defs-cache-HIgBbqZZ.mjs.map +0 -1
  978. package/dist/focal-point-Gr34o-4o.mjs +0 -23
  979. package/dist/focal-point-Gr34o-4o.mjs.map +0 -1
  980. package/dist/fts-manager-S-K0laoS.mjs +0 -443
  981. package/dist/fts-manager-S-K0laoS.mjs.map +0 -1
  982. package/dist/gc-DjKY0Ay1.mjs +0 -75
  983. package/dist/gc-DjKY0Ay1.mjs.map +0 -1
  984. package/dist/hash-SDAW6zC-.mjs +0 -37
  985. package/dist/hash-SDAW6zC-.mjs.map +0 -1
  986. package/dist/hook-result-B5bXDgS2.d.mts +0 -31
  987. package/dist/hook-result-B5bXDgS2.d.mts.map +0 -1
  988. package/dist/hreflang-D5uNnsGJ.d.mts +0 -50
  989. package/dist/hreflang-D5uNnsGJ.d.mts.map +0 -1
  990. package/dist/hreflang-DMFBL2eb.mjs +0 -105
  991. package/dist/hreflang-DMFBL2eb.mjs.map +0 -1
  992. package/dist/http-route-dispatch-BitqzwMy.mjs +0 -339
  993. package/dist/http-route-dispatch-BitqzwMy.mjs.map +0 -1
  994. package/dist/identity-IyNWwXr6.mjs +0 -35
  995. package/dist/identity-IyNWwXr6.mjs.map +0 -1
  996. package/dist/import-C3JZplWq.mjs +0 -2020
  997. package/dist/import-C3JZplWq.mjs.map +0 -1
  998. package/dist/index-D-hdtLe8.d.mts +0 -623
  999. package/dist/index-D-hdtLe8.d.mts.map +0 -1
  1000. package/dist/install-finalization-DfM1fj5x.mjs +0 -58
  1001. package/dist/install-finalization-DfM1fj5x.mjs.map +0 -1
  1002. package/dist/keys-yxLm5l35.mjs +0 -61
  1003. package/dist/keys-yxLm5l35.mjs.map +0 -1
  1004. package/dist/kinds-CRu_T5T5.mjs +0 -961
  1005. package/dist/kinds-CRu_T5T5.mjs.map +0 -1
  1006. package/dist/lifecycle-BzeGPeQ-.mjs +0 -25
  1007. package/dist/lifecycle-BzeGPeQ-.mjs.map +0 -1
  1008. package/dist/load-XgJiE6_3.mjs +0 -28
  1009. package/dist/load-XgJiE6_3.mjs.map +0 -1
  1010. package/dist/loader-BzqeR1ZN.mjs +0 -1086
  1011. package/dist/loader-BzqeR1ZN.mjs.map +0 -1
  1012. package/dist/loops-BQSzv5Zn.mjs +0 -203
  1013. package/dist/loops-BQSzv5Zn.mjs.map +0 -1
  1014. package/dist/manifest-builder-B8zR-73J.mjs +0 -189
  1015. package/dist/manifest-builder-B8zR-73J.mjs.map +0 -1
  1016. package/dist/manifest-schema-CY3zng_M.mjs +0 -492
  1017. package/dist/manifest-schema-CY3zng_M.mjs.map +0 -1
  1018. package/dist/media-Pu1L6xir.mjs +0 -408
  1019. package/dist/media-Pu1L6xir.mjs.map +0 -1
  1020. package/dist/media-Qp5S3eH3.mjs +0 -355
  1021. package/dist/media-Qp5S3eH3.mjs.map +0 -1
  1022. package/dist/media-allowlist-BSoa9Vvm.mjs +0 -44
  1023. package/dist/media-allowlist-BSoa9Vvm.mjs.map +0 -1
  1024. package/dist/media-folders-BE0oo2eX.mjs +0 -210
  1025. package/dist/media-folders-BE0oo2eX.mjs.map +0 -1
  1026. package/dist/media-h7tOiDLj.mjs +0 -221
  1027. package/dist/media-h7tOiDLj.mjs.map +0 -1
  1028. package/dist/media-url-jArBpzIG.mjs +0 -43
  1029. package/dist/media-url-jArBpzIG.mjs.map +0 -1
  1030. package/dist/media-usage-My-Vi-ex.mjs +0 -1629
  1031. package/dist/media-usage-My-Vi-ex.mjs.map +0 -1
  1032. package/dist/media-usage-activation-HKp7zk7W.mjs +0 -78
  1033. package/dist/media-usage-activation-HKp7zk7W.mjs.map +0 -1
  1034. package/dist/media-usage-work-C2OZLCAd.mjs +0 -586
  1035. package/dist/media-usage-work-C2OZLCAd.mjs.map +0 -1
  1036. package/dist/media-usage-work-DwUNbgvS.mjs +0 -152
  1037. package/dist/media-usage-work-DwUNbgvS.mjs.map +0 -1
  1038. package/dist/menus-BM7BPLOb.mjs +0 -139
  1039. package/dist/menus-BM7BPLOb.mjs.map +0 -1
  1040. package/dist/menus-ITeAbcIF.mjs +0 -753
  1041. package/dist/menus-ITeAbcIF.mjs.map +0 -1
  1042. package/dist/menus-TsSGmSR4.mjs +0 -3608
  1043. package/dist/menus-TsSGmSR4.mjs.map +0 -1
  1044. package/dist/mime-ChLqYwDk.mjs +0 -36
  1045. package/dist/mime-ChLqYwDk.mjs.map +0 -1
  1046. package/dist/mode-CCuKXUci.mjs +0 -23
  1047. package/dist/mode-CCuKXUci.mjs.map +0 -1
  1048. package/dist/node-sqlite-compat-CONMsl-x.mjs +0 -46
  1049. package/dist/node-sqlite-compat-CONMsl-x.mjs.map +0 -1
  1050. package/dist/normalize-CO2P8-iE.mjs +0 -191
  1051. package/dist/normalize-CO2P8-iE.mjs.map +0 -1
  1052. package/dist/oauth-authorization-DlMIL5_h.mjs +0 -274
  1053. package/dist/oauth-authorization-DlMIL5_h.mjs.map +0 -1
  1054. package/dist/oauth-clients-Djq9r_KP.mjs +0 -266
  1055. package/dist/oauth-clients-Djq9r_KP.mjs.map +0 -1
  1056. package/dist/oauth-state-store-BbjnZXNC.mjs +0 -50
  1057. package/dist/oauth-state-store-BbjnZXNC.mjs.map +0 -1
  1058. package/dist/oauth-user-lookup-vue9a64A.mjs +0 -26
  1059. package/dist/oauth-user-lookup-vue9a64A.mjs.map +0 -1
  1060. package/dist/options-SQCHQCPH.d.mts +0 -81
  1061. package/dist/options-SQCHQCPH.d.mts.map +0 -1
  1062. package/dist/parse-CVgO-Qai.d.mts +0 -168
  1063. package/dist/parse-CVgO-Qai.d.mts.map +0 -1
  1064. package/dist/parse-DY6OD1j_.mjs +0 -81
  1065. package/dist/parse-DY6OD1j_.mjs.map +0 -1
  1066. package/dist/passkey-config-X_H8128a.mjs +0 -46
  1067. package/dist/passkey-config-X_H8128a.mjs.map +0 -1
  1068. package/dist/paths-JxokKIbr.mjs +0 -77
  1069. package/dist/paths-JxokKIbr.mjs.map +0 -1
  1070. package/dist/patterns-BhAvqO0S.mjs +0 -145
  1071. package/dist/patterns-BhAvqO0S.mjs.map +0 -1
  1072. package/dist/placeholder-MSEd8gty.d.mts +0 -306
  1073. package/dist/placeholder-MSEd8gty.d.mts.map +0 -1
  1074. package/dist/plan-xjcWrAah.mjs +0 -135
  1075. package/dist/plan-xjcWrAah.mjs.map +0 -1
  1076. package/dist/plugins-DUXUt8B9.mjs +0 -277
  1077. package/dist/plugins-DUXUt8B9.mjs.map +0 -1
  1078. package/dist/policy-CUvwAARc.mjs +0 -45
  1079. package/dist/policy-CUvwAARc.mjs.map +0 -1
  1080. package/dist/portable-text-5O_ZGUjB.mjs +0 -307
  1081. package/dist/portable-text-5O_ZGUjB.mjs.map +0 -1
  1082. package/dist/preview-CIUcPYr6.mjs +0 -107
  1083. package/dist/preview-CIUcPYr6.mjs.map +0 -1
  1084. package/dist/protocol-B97DZaFr.d.mts +0 -61
  1085. package/dist/protocol-B97DZaFr.d.mts.map +0 -1
  1086. package/dist/public-submission-BFBUrqst.mjs +0 -250
  1087. package/dist/public-submission-BFBUrqst.mjs.map +0 -1
  1088. package/dist/public-url-Bn7U0D7-.mjs +0 -101
  1089. package/dist/public-url-Bn7U0D7-.mjs.map +0 -1
  1090. package/dist/query-B48peoRT.mjs +0 -890
  1091. package/dist/query-B48peoRT.mjs.map +0 -1
  1092. package/dist/query-C4IH0uhR.mjs +0 -41
  1093. package/dist/query-C4IH0uhR.mjs.map +0 -1
  1094. package/dist/rate-limit-BZ6nybgc.mjs +0 -120
  1095. package/dist/rate-limit-BZ6nybgc.mjs.map +0 -1
  1096. package/dist/receipt-B4wJj5Jq.mjs +0 -43
  1097. package/dist/receipt-B4wJj5Jq.mjs.map +0 -1
  1098. package/dist/redirect-Cd1E7VUt.mjs +0 -17
  1099. package/dist/redirect-Cd1E7VUt.mjs.map +0 -1
  1100. package/dist/redirect-iJf5fltD.mjs +0 -415
  1101. package/dist/redirect-iJf5fltD.mjs.map +0 -1
  1102. package/dist/redirects-CYu1u1aK.mjs +0 -446
  1103. package/dist/redirects-CYu1u1aK.mjs.map +0 -1
  1104. package/dist/redirects-Cv9apQKj.mjs +0 -148
  1105. package/dist/redirects-Cv9apQKj.mjs.map +0 -1
  1106. package/dist/relation-M4NUCb0b.mjs +0 -334
  1107. package/dist/relation-M4NUCb0b.mjs.map +0 -1
  1108. package/dist/relations-CCif47Oq.mjs +0 -403
  1109. package/dist/relations-CCif47Oq.mjs.map +0 -1
  1110. package/dist/relations-CK9CYUyr.mjs +0 -310
  1111. package/dist/relations-CK9CYUyr.mjs.map +0 -1
  1112. package/dist/request-cache-DzLYKm_x.mjs +0 -104
  1113. package/dist/request-cache-DzLYKm_x.mjs.map +0 -1
  1114. package/dist/request-meta-sZXt3sRo.mjs +0 -141
  1115. package/dist/request-meta-sZXt3sRo.mjs.map +0 -1
  1116. package/dist/resolve-2WbQsCvT.mjs +0 -199
  1117. package/dist/resolve-2WbQsCvT.mjs.map +0 -1
  1118. package/dist/route-wire--1hLuACz.mjs +0 -197
  1119. package/dist/route-wire--1hLuACz.mjs.map +0 -1
  1120. package/dist/routes-CUsM40Cc.mjs +0 -272
  1121. package/dist/routes-CUsM40Cc.mjs.map +0 -1
  1122. package/dist/runner-1y4J9fJB.mjs +0 -5742
  1123. package/dist/runner-1y4J9fJB.mjs.map +0 -1
  1124. package/dist/runner-D5_LzKXI.d.mts +0 -68
  1125. package/dist/runner-D5_LzKXI.d.mts.map +0 -1
  1126. package/dist/schema-BABiRdsH.mjs +0 -13
  1127. package/dist/schema-BABiRdsH.mjs.map +0 -1
  1128. package/dist/schema-Du3MzCG0.mjs +0 -446
  1129. package/dist/schema-Du3MzCG0.mjs.map +0 -1
  1130. package/dist/scopes-Dbk-ElhT.mjs +0 -34
  1131. package/dist/scopes-Dbk-ElhT.mjs.map +0 -1
  1132. package/dist/search-Bt1PL1jf.mjs +0 -448
  1133. package/dist/search-Bt1PL1jf.mjs.map +0 -1
  1134. package/dist/sections-Ddptx_o9.mjs +0 -346
  1135. package/dist/sections-Ddptx_o9.mjs.map +0 -1
  1136. package/dist/seo-CZT2oLtT.mjs +0 -114
  1137. package/dist/seo-CZT2oLtT.mjs.map +0 -1
  1138. package/dist/seo-D5w3-Azy.mjs +0 -133
  1139. package/dist/seo-D5w3-Azy.mjs.map +0 -1
  1140. package/dist/service-DuykXPyW.mjs +0 -150
  1141. package/dist/service-DuykXPyW.mjs.map +0 -1
  1142. package/dist/session-user-BhaVp8w0.mjs +0 -51
  1143. package/dist/session-user-BhaVp8w0.mjs.map +0 -1
  1144. package/dist/settings-2xNYr90o.mjs +0 -51
  1145. package/dist/settings-2xNYr90o.mjs.map +0 -1
  1146. package/dist/settings-CgjRWGW9.mjs +0 -439
  1147. package/dist/settings-CgjRWGW9.mjs.map +0 -1
  1148. package/dist/settings-DYidIB26.mjs +0 -61
  1149. package/dist/settings-DYidIB26.mjs.map +0 -1
  1150. package/dist/setup-complete-bOogcHWG.mjs +0 -26
  1151. package/dist/setup-complete-bOogcHWG.mjs.map +0 -1
  1152. package/dist/setup-nonce-0EGuKM4s.mjs +0 -25
  1153. package/dist/setup-nonce-0EGuKM4s.mjs.map +0 -1
  1154. package/dist/site-settings-DOgRUoFX.mjs +0 -50
  1155. package/dist/site-settings-DOgRUoFX.mjs.map +0 -1
  1156. package/dist/site-url-BU_bbxwj.mjs +0 -16
  1157. package/dist/site-url-BU_bbxwj.mjs.map +0 -1
  1158. package/dist/snapshot-CugwUqKQ.mjs +0 -237
  1159. package/dist/snapshot-CugwUqKQ.mjs.map +0 -1
  1160. package/dist/ssrf-CJUnJymJ.mjs +0 -406
  1161. package/dist/ssrf-CJUnJymJ.mjs.map +0 -1
  1162. package/dist/stage-DgrBz_du.mjs +0 -662
  1163. package/dist/stage-DgrBz_du.mjs.map +0 -1
  1164. package/dist/state-DDiPySSG.mjs +0 -153
  1165. package/dist/state-DDiPySSG.mjs.map +0 -1
  1166. package/dist/status-DZKIG4a9.mjs +0 -30
  1167. package/dist/status-DZKIG4a9.mjs.map +0 -1
  1168. package/dist/storage-query-Bdv7A62k.d.mts +0 -1576
  1169. package/dist/storage-query-Bdv7A62k.d.mts.map +0 -1
  1170. package/dist/tar-_1AgTYFu.mjs +0 -449
  1171. package/dist/tar-_1AgTYFu.mjs.map +0 -1
  1172. package/dist/target-_7pn2Gbg.mjs +0 -27
  1173. package/dist/target-_7pn2Gbg.mjs.map +0 -1
  1174. package/dist/taxonomies-C1IwNe8Q.mjs +0 -697
  1175. package/dist/taxonomies-C1IwNe8Q.mjs.map +0 -1
  1176. package/dist/taxonomies-C_XMoRcX.mjs +0 -939
  1177. package/dist/taxonomies-C_XMoRcX.mjs.map +0 -1
  1178. package/dist/taxonomy-C3Fu1YeH.mjs +0 -525
  1179. package/dist/taxonomy-C3Fu1YeH.mjs.map +0 -1
  1180. package/dist/tokens-u78jETkX.mjs +0 -171
  1181. package/dist/tokens-u78jETkX.mjs.map +0 -1
  1182. package/dist/transaction-BcJO4Tmc.mjs +0 -29
  1183. package/dist/transaction-BcJO4Tmc.mjs.map +0 -1
  1184. package/dist/transfer-BhUCrgDc.mjs +0 -8675
  1185. package/dist/transfer-BhUCrgDc.mjs.map +0 -1
  1186. package/dist/transfer-DIGvR9Af.mjs +0 -166
  1187. package/dist/transfer-DIGvR9Af.mjs.map +0 -1
  1188. package/dist/transfer-download-Pml7RMio.mjs +0 -33
  1189. package/dist/transfer-download-Pml7RMio.mjs.map +0 -1
  1190. package/dist/transformations-9gfpwY65.mjs +0 -196
  1191. package/dist/transformations-9gfpwY65.mjs.map +0 -1
  1192. package/dist/transport-BIfH7_hx.d.mts +0 -42
  1193. package/dist/transport-BIfH7_hx.d.mts.map +0 -1
  1194. package/dist/transport-DKWIq53q.mjs +0 -136
  1195. package/dist/transport-DKWIq53q.mjs.map +0 -1
  1196. package/dist/trusted-proxy-tKiVtyTD.mjs +0 -51
  1197. package/dist/trusted-proxy-tKiVtyTD.mjs.map +0 -1
  1198. package/dist/turnstile-DpsoyOfg.mjs +0 -53
  1199. package/dist/turnstile-DpsoyOfg.mjs.map +0 -1
  1200. package/dist/types-B4sUC2p1.d.mts +0 -198
  1201. package/dist/types-B4sUC2p1.d.mts.map +0 -1
  1202. package/dist/types-B7Lmsh1E.d.mts +0 -887
  1203. package/dist/types-B7Lmsh1E.d.mts.map +0 -1
  1204. package/dist/types-BZakh7Ym.mjs +0 -22
  1205. package/dist/types-BZakh7Ym.mjs.map +0 -1
  1206. package/dist/types-B_CppEmv.d.mts +0 -264
  1207. package/dist/types-B_CppEmv.d.mts.map +0 -1
  1208. package/dist/types-BcrBrE6-.mjs +0 -159
  1209. package/dist/types-BcrBrE6-.mjs.map +0 -1
  1210. package/dist/types-BkUg2yHx.mjs +0 -92
  1211. package/dist/types-BkUg2yHx.mjs.map +0 -1
  1212. package/dist/types-CAZgq9fO.d.mts +0 -124
  1213. package/dist/types-CAZgq9fO.d.mts.map +0 -1
  1214. package/dist/types-Cd-O03VG.d.mts +0 -363
  1215. package/dist/types-Cd-O03VG.d.mts.map +0 -1
  1216. package/dist/types-Cr-Kg-3D.d.mts +0 -1641
  1217. package/dist/types-Cr-Kg-3D.d.mts.map +0 -1
  1218. package/dist/types-D2fvWd1i.d.mts +0 -359
  1219. package/dist/types-D2fvWd1i.d.mts.map +0 -1
  1220. package/dist/types-D7HUsguf.mjs +0 -77
  1221. package/dist/types-D7HUsguf.mjs.map +0 -1
  1222. package/dist/types-DA1Te3Oy.d.mts +0 -198
  1223. package/dist/types-DA1Te3Oy.d.mts.map +0 -1
  1224. package/dist/types-DhV6Q5bP.mjs +0 -18
  1225. package/dist/types-DhV6Q5bP.mjs.map +0 -1
  1226. package/dist/types-DnnVSl6Y.d.mts +0 -85
  1227. package/dist/types-DnnVSl6Y.d.mts.map +0 -1
  1228. package/dist/types-VT4-BugW.mjs +0 -16
  1229. package/dist/types-VT4-BugW.mjs.map +0 -1
  1230. package/dist/upload-attempts-B68ZGNu9.mjs +0 -32
  1231. package/dist/upload-attempts-B68ZGNu9.mjs.map +0 -1
  1232. package/dist/url-pattern-CCeZMGOh.mjs +0 -33
  1233. package/dist/url-pattern-CCeZMGOh.mjs.map +0 -1
  1234. package/dist/user-DDSL-sGw.mjs +0 -171
  1235. package/dist/user-DDSL-sGw.mjs.map +0 -1
  1236. package/dist/utils-DdhmO9w9.mjs +0 -439
  1237. package/dist/utils-DdhmO9w9.mjs.map +0 -1
  1238. package/dist/validate-CHosPEhs.mjs +0 -453
  1239. package/dist/validate-CHosPEhs.mjs.map +0 -1
  1240. package/dist/validate-CM79QXYE.d.mts +0 -432
  1241. package/dist/validate-CM79QXYE.d.mts.map +0 -1
  1242. package/dist/validation-BFecQczG.mjs +0 -218
  1243. package/dist/validation-BFecQczG.mjs.map +0 -1
  1244. package/dist/version-BRZXVifl.mjs +0 -9
  1245. package/dist/version-BRZXVifl.mjs.map +0 -1
  1246. package/dist/version-DUQDHgrf.mjs +0 -7
  1247. package/dist/version-DUQDHgrf.mjs.map +0 -1
  1248. package/dist/widgets-WdV72brA.mjs +0 -126
  1249. package/dist/widgets-WdV72brA.mjs.map +0 -1
  1250. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts +0 -34
  1251. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts.map +0 -1
  1252. package/dist/wxr-taxonomies-DP6ESgMN.mjs +0 -372
  1253. package/dist/wxr-taxonomies-DP6ESgMN.mjs.map +0 -1
  1254. package/dist/zod-generator-D6uE4WiS.mjs +0 -389
  1255. package/dist/zod-generator-D6uE4WiS.mjs.map +0 -1
  1256. package/src/astro/routes/api/relations/[id]/translations.ts +0 -33
  1257. /package/dist/{api-tokens-CE1ECIg0.mjs → api-tokens-FaG1zPsj.mjs} +0 -0
  1258. /package/dist/{ssrf-DpBH7aOt.mjs → ssrf-DZOt8Qof.mjs} +0 -0
@@ -1,50 +1,106 @@
1
- import type { Kysely, Selectable } from "kysely";
1
+ import { sql, type Kysely, type Selectable } from "kysely";
2
2
  import { ulid } from "ulidx";
3
3
 
4
4
  import { chunks, SQL_BATCH_SIZE } from "../../utils/chunks.js";
5
5
  import type { Database, RelationTable, ContentReferenceTable } from "../types.js";
6
- import { decodeCursor, encodeCursor, InvalidCursorError, type FindManyResult } from "./types.js";
6
+ import {
7
+ decodeCursor,
8
+ encodeCursor,
9
+ InvalidCursorError,
10
+ STAGED_CURSOR_MARKER,
11
+ type FindManyResult,
12
+ } from "./types.js";
13
+
14
+ // Each reference-edge row binds six values. Derive the row count so every
15
+ // INSERT stays within D1's 100-parameter statement ceiling.
16
+ const REFERENCE_INSERT_BIND_COLUMNS = 6;
17
+ const D1_MAX_BOUND_PARAMETERS = 100;
18
+ export const REFERENCE_INSERT_BATCH_SIZE = Math.floor(
19
+ D1_MAX_BOUND_PARAMETERS / REFERENCE_INSERT_BIND_COLUMNS,
20
+ );
21
+
22
+ // Repositioning binds an edge id twice — once to match the CASE branch, once in
23
+ // the row filter. The new position is a literal and binds nothing.
24
+ const REFERENCE_REPOSITION_BIND_COLUMNS = 2;
25
+ const REFERENCE_REPOSITION_BATCH_SIZE = Math.floor(
26
+ D1_MAX_BOUND_PARAMETERS / REFERENCE_REPOSITION_BIND_COLUMNS,
27
+ );
28
+
29
+ /** A reference edge as it is written. */
30
+ interface EdgeInsert {
31
+ id: string;
32
+ relation_id: string;
33
+ parent_group: string;
34
+ child_group: string;
35
+ sort_order: number;
36
+ created_at: string;
37
+ }
38
+
39
+ /** Where an existing edge should sit in its parent's list. */
40
+ interface EdgePosition {
41
+ id: string;
42
+ sortOrder: number;
43
+ }
44
+
45
+ /**
46
+ * Narrow a computed position to a non-negative integer before it is written as
47
+ * a SQL literal. Every caller passes an array index; this is what keeps that
48
+ * true at the one place the value stops being a bound parameter.
49
+ */
50
+ function asPosition(sortOrder: number): number {
51
+ if (!Number.isInteger(sortOrder) || sortOrder < 0) {
52
+ throw new TypeError(`Invalid reference sort order: ${sortOrder}`);
53
+ }
54
+ return sortOrder;
55
+ }
7
56
 
57
+ /**
58
+ * A relation definition. Not localized: a relation joins the same two
59
+ * collections whatever language you read it in, and its role labels are
60
+ * single-valued like a collection's or a field's. That is what lets `slug` be
61
+ * unique outright (migration 086) and resolve without a locale.
62
+ */
8
63
  export interface Relation {
9
64
  id: string;
10
- name: string;
65
+ slug: string;
11
66
  parentCollection: string;
12
67
  childCollection: string;
13
68
  parentLabel: string;
14
69
  childLabel: string;
15
- locale: string;
16
- translationGroup: string;
70
+ parentLabelSingular: string | null;
71
+ childLabelSingular: string | null;
72
+ /** How many children one parent may hold. `null` means unlimited. */
73
+ maxChildrenPerParent: number | null;
74
+ /** How many parents one child may hold. `null` means unlimited. */
75
+ maxParentsPerChild: number | null;
17
76
  }
18
77
 
19
78
  export interface CreateRelationInput {
20
- name: string;
21
- /** Required for a base relation; ignored (inherited from the source) when
22
- * `translationOf` is set. */
23
- parentCollection?: string;
24
- /** Required for a base relation; ignored (inherited from the source) when
25
- * `translationOf` is set. */
26
- childCollection?: string;
79
+ slug: string;
80
+ parentCollection: string;
81
+ childCollection: string;
27
82
  parentLabel: string;
28
83
  childLabel: string;
29
- /** Omit to let the DB default (current value: 'en') apply. Higher layers
30
- * resolve locale from request context / i18n config. */
31
- locale?: string;
32
- /** When set, joins the source relation's translation_group AND inherits its
33
- * structural fields (name, parentCollection, childCollection). Only locale +
34
- * labels may differ on a translation. */
35
- translationOf?: string;
84
+ parentLabelSingular?: string | null;
85
+ childLabelSingular?: string | null;
86
+ maxChildrenPerParent?: number | null;
87
+ maxParentsPerChild?: number | null;
36
88
  }
37
89
 
38
90
  export interface UpdateRelationInput {
39
- /** Only localized fields are mutable per row. Changing structural fields
40
- * (name/collections) is a cross-group operation deferred to a later slice. */
91
+ /** Structural fields are immutable: a reference field stores the slug, and
92
+ * the edges are keyed by the id. */
41
93
  parentLabel?: string;
42
94
  childLabel?: string;
95
+ parentLabelSingular?: string | null;
96
+ childLabelSingular?: string | null;
97
+ maxChildrenPerParent?: number | null;
98
+ maxParentsPerChild?: number | null;
43
99
  }
44
100
 
45
101
  export interface ContentReference {
46
102
  id: string;
47
- relationGroup: string;
103
+ relationId: string;
48
104
  parentGroup: string;
49
105
  childGroup: string;
50
106
  sortOrder: number;
@@ -53,74 +109,47 @@ export interface ContentReference {
53
109
  /**
54
110
  * Content-references repository.
55
111
  *
56
- * Owns relation *definitions* (`_emdash_relations`, row-per-locale, mirroring
57
- * `_emdash_taxonomy_defs`) and the *edge* junction (`_emdash_content_references`,
58
- * keyed by `translation_group` so edges are locale-agnostic, mirroring
112
+ * Owns relation *definitions* (`_emdash_relations`) and the *edge* junction
113
+ * (`_emdash_content_references`, whose endpoints are content
114
+ * `translation_group`s so edges are locale-agnostic, mirroring
59
115
  * `content_taxonomies`).
60
116
  *
117
+ * A relation is schema, so it is not localized — it sits with
118
+ * `_emdash_collections` and `_emdash_fields`, not with the row-per-locale
119
+ * tables. See migration 086.
120
+ *
61
121
  * Like `TaxonomyRepository`, this is not the validation boundary: it trusts its
62
122
  * typed inputs. The API slice supplies Zod schemas at the route and enforces
63
- * collection-agreement / relation-existence invariants in the handler. The repo
64
- * does not resolve locale fallbacks — callers pass the locale they want.
123
+ * collection-agreement / relation-existence invariants in the handler.
65
124
  */
66
125
  export class RelationRepository {
67
126
  constructor(private db: Kysely<Database>) {}
68
127
 
69
128
  /**
70
- * Create a relation. Without `translationOf`, mints a fresh group
71
- * (`translation_group = id`, matching the migration backfill pattern). With
72
- * `translationOf`, the structural fields (name, parentCollection,
73
- * childCollection) and the translation_group are inherited from the source;
74
- * locale and the two labels are taken from `input`.
129
+ * Create a relation.
130
+ *
131
+ * `slug` is unique across all relations, so a duplicate raises the DB's
132
+ * unique violation for the handler to translate into a conflict.
75
133
  */
76
134
  async create(input: CreateRelationInput): Promise<Relation> {
77
135
  const id = ulid();
78
136
  const now = new Date().toISOString();
79
137
 
80
- let translationGroup = id;
81
- let name: string;
82
- let parentCollection: string;
83
- let childCollection: string;
84
-
85
- if (input.translationOf) {
86
- const source = await this.findById(input.translationOf);
87
- // translation_group is NOT NULL here, so we cannot fall back to a
88
- // fresh group like TaxonomyRepository does — a bad translationOf must
89
- // fail loudly rather than silently mint an unlinked relation.
90
- if (!source) throw new Error("Source relation for translation not found");
91
- translationGroup = source.translationGroup;
92
- name = source.name;
93
- parentCollection = source.parentCollection;
94
- childCollection = source.childCollection;
95
- } else {
96
- // A base relation carries its own structural fields. The API layer's Zod
97
- // schema enforces this; guard here too since the repo trusts its inputs
98
- // and the columns are NOT NULL.
99
- if (input.parentCollection === undefined || input.childCollection === undefined) {
100
- throw new Error(
101
- "parentCollection and childCollection are required unless translationOf is set",
102
- );
103
- }
104
- name = input.name;
105
- parentCollection = input.parentCollection;
106
- childCollection = input.childCollection;
107
- }
108
-
109
138
  await this.db
110
139
  .insertInto("_emdash_relations")
111
140
  .values({
112
141
  id,
113
- name,
114
- parent_collection: parentCollection,
115
- child_collection: childCollection,
142
+ slug: input.slug,
143
+ parent_collection: input.parentCollection,
144
+ child_collection: input.childCollection,
116
145
  parent_label: input.parentLabel,
117
146
  child_label: input.childLabel,
147
+ parent_label_singular: input.parentLabelSingular ?? null,
148
+ child_label_singular: input.childLabelSingular ?? null,
149
+ max_children_per_parent: input.maxChildrenPerParent ?? null,
150
+ max_parents_per_child: input.maxParentsPerChild ?? null,
118
151
  created_at: now,
119
152
  updated_at: now,
120
- // Omit `locale` so the DB DEFAULT (configured defaultLocale)
121
- // applies — matches TaxonomyRepository.create.
122
- ...(input.locale !== undefined ? { locale: input.locale } : {}),
123
- translation_group: translationGroup,
124
153
  })
125
154
  .execute();
126
155
 
@@ -139,62 +168,46 @@ export class RelationRepository {
139
168
  }
140
169
 
141
170
  /**
142
- * Find a relation by name. With `locale`, filter by it; without, return the
143
- * lowest-locale-code match deterministically. Mirrors
144
- * `TaxonomyRepository.findBySlug` — note this returns a single row, unlike
145
- * `TaxonomyRepository.findByName` which returns every term in a taxonomy.
171
+ * Find a relation by its slug. No locale: a slug identifies a relation
172
+ * outright (`UNIQUE(slug)`, migration 086), which is what lets an entry in
173
+ * any locale address it.
146
174
  */
147
- async findByName(name: string, locale?: string): Promise<Relation | null> {
148
- let query = this.db.selectFrom("_emdash_relations").selectAll().where("name", "=", name);
149
- if (locale !== undefined) query = query.where("locale", "=", locale);
150
- const row = await query.orderBy("locale", "asc").executeTakeFirst();
175
+ async findBySlug(slug: string): Promise<Relation | null> {
176
+ const row = await this.db
177
+ .selectFrom("_emdash_relations")
178
+ .selectAll()
179
+ .where("slug", "=", slug)
180
+ .executeTakeFirst();
151
181
  return row ? this.rowToRelation(row) : null;
152
182
  }
153
183
 
154
- /** Every translation sibling (including itself) sharing a translation_group. */
155
- async findTranslations(translationGroup: string): Promise<Relation[]> {
184
+ /** All relations, ordered by slug. */
185
+ async list(): Promise<Relation[]> {
156
186
  const rows = await this.db
157
187
  .selectFrom("_emdash_relations")
158
188
  .selectAll()
159
- .where("translation_group", "=", translationGroup)
160
- .orderBy("locale", "asc")
189
+ .orderBy("slug", "asc")
161
190
  .execute();
162
191
  return rows.map((row) => this.rowToRelation(row));
163
192
  }
164
193
 
165
- /**
166
- * All relations, ordered by name then id (id is a stable tiebreak for
167
- * relations sharing a name across locales). Optionally filtered by locale.
168
- */
169
- async list(locale?: string): Promise<Relation[]> {
170
- let query = this.db
171
- .selectFrom("_emdash_relations")
172
- .selectAll()
173
- .orderBy("name", "asc")
174
- .orderBy("id", "asc");
175
- if (locale !== undefined) query = query.where("locale", "=", locale);
176
- const rows = await query.execute();
177
- return rows.map((row) => this.rowToRelation(row));
178
- }
179
-
180
194
  /** Relations where `collection` is the parent OR the child side. */
181
- async findForCollection(collection: string, locale?: string): Promise<Relation[]> {
182
- let query = this.db
195
+ async findForCollection(collection: string): Promise<Relation[]> {
196
+ const rows = await this.db
183
197
  .selectFrom("_emdash_relations")
184
198
  .selectAll()
185
199
  .where((eb) =>
186
200
  eb.or([eb("parent_collection", "=", collection), eb("child_collection", "=", collection)]),
187
201
  )
188
- .orderBy("name", "asc")
189
- .orderBy("id", "asc");
190
- if (locale !== undefined) query = query.where("locale", "=", locale);
191
- const rows = await query.execute();
202
+ .orderBy("slug", "asc")
203
+ .execute();
192
204
  return rows.map((row) => this.rowToRelation(row));
193
205
  }
194
206
 
195
207
  /**
196
- * Update the localized labels of one relation row. Structural fields are
197
- * immutable here (a cross-group concern). No-ops when nothing is supplied.
208
+ * Update a relation's role labels and cardinality. Structural fields are
209
+ * immutable — a reference field stores the slug, and the edges are keyed by
210
+ * the id. No-ops when nothing is supplied.
198
211
  */
199
212
  async update(id: string, input: UpdateRelationInput): Promise<Relation | null> {
200
213
  const existing = await this.findById(id);
@@ -203,6 +216,18 @@ export class RelationRepository {
203
216
  const updates: Record<string, unknown> = {};
204
217
  if (input.parentLabel !== undefined) updates.parent_label = input.parentLabel;
205
218
  if (input.childLabel !== undefined) updates.child_label = input.childLabel;
219
+ if (input.parentLabelSingular !== undefined) {
220
+ updates.parent_label_singular = input.parentLabelSingular;
221
+ }
222
+ if (input.childLabelSingular !== undefined) {
223
+ updates.child_label_singular = input.childLabelSingular;
224
+ }
225
+ if (input.maxChildrenPerParent !== undefined) {
226
+ updates.max_children_per_parent = input.maxChildrenPerParent;
227
+ }
228
+ if (input.maxParentsPerChild !== undefined) {
229
+ updates.max_parents_per_child = input.maxParentsPerChild;
230
+ }
206
231
 
207
232
  if (Object.keys(updates).length > 0) {
208
233
  updates.updated_at = new Date().toISOString();
@@ -213,26 +238,14 @@ export class RelationRepository {
213
238
  }
214
239
 
215
240
  /**
216
- * Delete one relation row. When it is the *last* translation of its group,
217
- * purge edges referencing that group (application-layer cascade — group
218
- * linking precludes a SQL FK). Mirrors `TaxonomyRepository.delete`.
241
+ * Delete a relation and its edges (application-layer cascade — the edge
242
+ * table has no FK).
219
243
  */
220
244
  async delete(id: string): Promise<boolean> {
221
245
  const relation = await this.findById(id);
222
246
  if (!relation) return false;
223
247
 
224
- const siblings = await this.db
225
- .selectFrom("_emdash_relations")
226
- .select("id")
227
- .where("translation_group", "=", relation.translationGroup)
228
- .where("id", "!=", id)
229
- .execute();
230
- if (siblings.length === 0) {
231
- await this.db
232
- .deleteFrom("_emdash_content_references")
233
- .where("relation_group", "=", relation.translationGroup)
234
- .execute();
235
- }
248
+ await this.db.deleteFrom("_emdash_content_references").where("relation_id", "=", id).execute();
236
249
 
237
250
  const result = await this.db
238
251
  .deleteFrom("_emdash_relations")
@@ -241,22 +254,148 @@ export class RelationRepository {
241
254
  return (result.numDeletedRows ?? 0n) > 0n;
242
255
  }
243
256
 
244
- /** Normalize a relation id OR group to its translation_group. Returns null
245
- * for an unknown relation (edge methods then no-op, matching
257
+ /**
258
+ * Insert one edge only while the end it lands on is still under its limit,
259
+ * deciding and writing in a single statement.
260
+ *
261
+ * A count read before the insert answers for a moment that has passed by the
262
+ * time the row goes in: two requests can both read a free slot and both fill
263
+ * it, and the unique edge constraint does not catch it because they are
264
+ * different pairs. Folding the count into the insert's `WHERE` makes the
265
+ * decision and the write one thing, on D1 as much as anywhere. Returns false
266
+ * when the limit refused the row.
267
+ */
268
+ private async insertEdgeWithinLimit(
269
+ row: EdgeInsert,
270
+ limitedSide: "parent" | "child",
271
+ limit: number,
272
+ ): Promise<boolean> {
273
+ const column = limitedSide === "parent" ? "parent_group" : "child_group";
274
+ const group = limitedSide === "parent" ? row.parent_group : row.child_group;
275
+ const result = await sql`
276
+ INSERT INTO ${sql.ref("_emdash_content_references")}
277
+ (id, relation_id, parent_group, child_group, sort_order, created_at)
278
+ SELECT ${row.id}, ${row.relation_id}, ${row.parent_group}, ${row.child_group},
279
+ ${row.sort_order}, ${row.created_at}
280
+ WHERE (
281
+ SELECT COUNT(*) FROM ${sql.ref("_emdash_content_references")}
282
+ WHERE relation_id = ${row.relation_id} AND ${sql.ref(column)} = ${group}
283
+ ) < ${limit}
284
+ `.execute(this.db);
285
+ return (result.numAffectedRows ?? 0n) > 0n;
286
+ }
287
+
288
+ /**
289
+ * Write new edges, taking back the ones already written if the limited end
290
+ * refuses a later one.
291
+ *
292
+ * Returns the refused group in a one-element array, or an empty array when
293
+ * every row went in. The rollback is what lets a replacement add before it
294
+ * removes: on D1 nothing else can take a partial write back.
295
+ *
296
+ * An unlimited end cannot refuse anything, so its rows go in as batches; a
297
+ * limited one takes a statement per edge, because a limit enforced only by a
298
+ * count before the write is one two requests can both walk past.
299
+ */
300
+ private async insertEdges(
301
+ rows: EdgeInsert[],
302
+ limitedSide: "parent" | "child",
303
+ limit: number | null,
304
+ ): Promise<string[]> {
305
+ if (rows.length === 0) return [];
306
+
307
+ if (limit === null) {
308
+ for (const rowBatch of chunks(rows, REFERENCE_INSERT_BATCH_SIZE)) {
309
+ // oxlint-disable-next-line no-await-in-loop -- one statement per D1-safe batch
310
+ await this.db
311
+ .insertInto("_emdash_content_references")
312
+ .values(rowBatch)
313
+ .onConflict((oc) => oc.doNothing())
314
+ .execute();
315
+ }
316
+ return [];
317
+ }
318
+
319
+ const written: string[] = [];
320
+ for (const row of rows) {
321
+ // oxlint-disable-next-line no-await-in-loop -- one statement per edge is what makes the limit hold
322
+ const inserted = await this.insertEdgeWithinLimit(row, limitedSide, limit);
323
+ if (inserted) {
324
+ written.push(row.id);
325
+ continue;
326
+ }
327
+ await this.deleteEdgesById(written);
328
+ return [limitedSide === "parent" ? row.parent_group : row.child_group];
329
+ }
330
+ return [];
331
+ }
332
+
333
+ /** Remove edges by id, in D1-safe batches. */
334
+ private async deleteEdgesById(ids: string[]): Promise<void> {
335
+ for (const idBatch of chunks(ids, SQL_BATCH_SIZE)) {
336
+ // oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
337
+ await this.db.deleteFrom("_emdash_content_references").where("id", "in", idBatch).execute();
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Move kept edges to their new positions, a statement per batch rather than
343
+ * one per edge: dragging one entry up a long list moves every entry below it,
344
+ * and that is a single editor action.
345
+ */
346
+ private async repositionEdges(moves: EdgePosition[]): Promise<void> {
347
+ for (const moveBatch of chunks(moves, REFERENCE_REPOSITION_BATCH_SIZE)) {
348
+ // The position is a literal, not a bind: it is an index this method
349
+ // computed, and every branch of a CASE binding one would leave Postgres
350
+ // inferring the result type from parameters alone.
351
+ const branches = moveBatch.map(
352
+ (move) => sql`WHEN ${move.id} THEN ${sql.lit(asPosition(move.sortOrder))}`,
353
+ );
354
+ // oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
355
+ await this.db
356
+ .updateTable("_emdash_content_references")
357
+ .set({
358
+ sort_order: sql<number>`CASE ${sql.ref("id")} ${sql.join(branches, sql` `)} END`,
359
+ })
360
+ .where(
361
+ "id",
362
+ "in",
363
+ moveBatch.map((move) => move.id),
364
+ )
365
+ .execute();
366
+ }
367
+ }
368
+
369
+ /** Normalize a relation id OR slug to its id. Returns null for an unknown
370
+ * relation (edge methods then no-op, matching
246
371
  * `TaxonomyRepository.attachToEntry`). */
247
- private async resolveRelationGroup(idOrGroup: string): Promise<string | null> {
372
+ private async resolveRelationId(idOrSlug: string): Promise<string | null> {
373
+ return (await this.resolveRelationLimits(idOrSlug))?.id ?? null;
374
+ }
375
+
376
+ /** The same lookup, carrying the limits an edge write has to hold to. */
377
+ private async resolveRelationLimits(idOrSlug: string): Promise<{
378
+ id: string;
379
+ maxChildrenPerParent: number | null;
380
+ maxParentsPerChild: number | null;
381
+ } | null> {
248
382
  const row = await this.db
249
383
  .selectFrom("_emdash_relations")
250
- .select(["translation_group"])
251
- .where((eb) => eb.or([eb("id", "=", idOrGroup), eb("translation_group", "=", idOrGroup)]))
384
+ .select(["id", "max_children_per_parent", "max_parents_per_child"])
385
+ .where((eb) => eb.or([eb("id", "=", idOrSlug), eb("slug", "=", idOrSlug)]))
252
386
  .executeTakeFirst();
253
- return row?.translation_group ?? null;
387
+ if (!row) return null;
388
+ return {
389
+ id: row.id,
390
+ maxChildrenPerParent: row.max_children_per_parent,
391
+ maxParentsPerChild: row.max_parents_per_child,
392
+ };
254
393
  }
255
394
 
256
395
  private rowToReference(row: Selectable<ContentReferenceTable>): ContentReference {
257
396
  return {
258
397
  id: row.id,
259
- relationGroup: row.relation_group,
398
+ relationId: row.relation_id,
260
399
  parentGroup: row.parent_group,
261
400
  childGroup: row.child_group,
262
401
  sortOrder: row.sort_order,
@@ -279,15 +418,15 @@ export class RelationRepository {
279
418
  childGroup: string,
280
419
  sortOrder?: number,
281
420
  ): Promise<void> {
282
- const relationGroup = await this.resolveRelationGroup(relation);
283
- if (!relationGroup) return;
421
+ const relationId = await this.resolveRelationId(relation);
422
+ if (!relationId) return;
284
423
 
285
424
  let order = sortOrder;
286
425
  if (order === undefined) {
287
426
  const max = await this.db
288
427
  .selectFrom("_emdash_content_references")
289
428
  .select((eb) => eb.fn.max("sort_order").as("max"))
290
- .where("relation_group", "=", relationGroup)
429
+ .where("relation_id", "=", relationId)
291
430
  .where("parent_group", "=", parentGroup)
292
431
  .executeTakeFirst();
293
432
  order = max?.max === null || max?.max === undefined ? 0 : Number(max.max) + 1;
@@ -297,7 +436,7 @@ export class RelationRepository {
297
436
  .insertInto("_emdash_content_references")
298
437
  .values({
299
438
  id: ulid(),
300
- relation_group: relationGroup,
439
+ relation_id: relationId,
301
440
  parent_group: parentGroup,
302
441
  child_group: childGroup,
303
442
  sort_order: order,
@@ -309,12 +448,12 @@ export class RelationRepository {
309
448
 
310
449
  /** Remove one `parentGroup → childGroup` edge under a relation. */
311
450
  async removeReference(relation: string, parentGroup: string, childGroup: string): Promise<void> {
312
- const relationGroup = await this.resolveRelationGroup(relation);
313
- if (!relationGroup) return;
451
+ const relationId = await this.resolveRelationId(relation);
452
+ if (!relationId) return;
314
453
 
315
454
  await this.db
316
455
  .deleteFrom("_emdash_content_references")
317
- .where("relation_group", "=", relationGroup)
456
+ .where("relation_id", "=", relationId)
318
457
  .where("parent_group", "=", parentGroup)
319
458
  .where("child_group", "=", childGroup)
320
459
  .execute();
@@ -322,13 +461,13 @@ export class RelationRepository {
322
461
 
323
462
  /** Forward traversal: a parent's children for a relation, ordered. */
324
463
  async getChildren(relation: string, parentGroup: string): Promise<ContentReference[]> {
325
- const relationGroup = await this.resolveRelationGroup(relation);
326
- if (!relationGroup) return [];
464
+ const relationId = await this.resolveRelationId(relation);
465
+ if (!relationId) return [];
327
466
 
328
467
  const rows = await this.db
329
468
  .selectFrom("_emdash_content_references")
330
469
  .selectAll()
331
- .where("relation_group", "=", relationGroup)
470
+ .where("relation_id", "=", relationId)
332
471
  .where("parent_group", "=", parentGroup)
333
472
  .orderBy("sort_order", "asc")
334
473
  .orderBy("id", "asc")
@@ -348,31 +487,63 @@ export class RelationRepository {
348
487
  parentGroup: string,
349
488
  options: { limit?: number; cursor?: string } = {},
350
489
  ): Promise<FindManyResult<ContentReference>> {
351
- const relationGroup = await this.resolveRelationGroup(relation);
352
- if (!relationGroup) return { items: [] };
490
+ const relationId = await this.resolveRelationId(relation);
491
+ if (!relationId) return { items: [] };
492
+ return this.getChildrenPageById(relationId, parentGroup, options);
493
+ }
353
494
 
495
+ /** `getChildrenPage` for a caller that already holds the relation's id. */
496
+ async getChildrenPageById(
497
+ relationId: string,
498
+ parentGroup: string,
499
+ options: { limit?: number; cursor?: string } = {},
500
+ ): Promise<FindManyResult<ContentReference>> {
354
501
  const limit = Math.min(options.limit || 50, 100);
355
502
 
356
503
  let query = this.db
357
504
  .selectFrom("_emdash_content_references")
358
505
  .selectAll()
359
- .where("relation_group", "=", relationGroup)
506
+ .where("relation_id", "=", relationId)
360
507
  .where("parent_group", "=", parentGroup);
361
508
 
362
509
  if (options.cursor) {
363
510
  const decoded = decodeCursor(options.cursor);
364
- const sortOrder = Number(decoded.orderValue);
365
- // `decodeCursor` only guarantees `orderValue` is a string; a hand-crafted
366
- // cursor with a non-numeric order value would coerce to NaN and blow up at
367
- // the driver bind as a 500. A bad cursor is a client error — surface it as
368
- // INVALID_CURSOR (400). Server-issued cursors are always numeric here.
369
- if (!Number.isFinite(sortOrder)) throw new InvalidCursorError(options.cursor);
370
- query = query.where((eb) =>
371
- eb.or([
372
- eb("sort_order", ">", sortOrder),
373
- eb.and([eb("sort_order", "=", sortOrder), eb("id", ">", decoded.id)]),
374
- ]),
375
- );
511
+ if (decoded.orderValue === STAGED_CURSOR_MARKER) {
512
+ // A cursor issued over a draft's pending selection anchors on a
513
+ // translation group rather than a row here, which is what a render
514
+ // sees when the draft publishes mid-pagination. Resume after that
515
+ // group's edge so the walk continues; if the group is no longer
516
+ // selected there is nothing to resume from, so the page restarts.
517
+ query = query.where((eb) => {
518
+ const anchor = () =>
519
+ eb
520
+ .selectFrom("_emdash_content_references as anchor")
521
+ .where("anchor.relation_id", "=", relationId)
522
+ .where("anchor.parent_group", "=", parentGroup)
523
+ .where("anchor.child_group", "=", decoded.id);
524
+ return eb.or([
525
+ eb.not(eb.exists(anchor().select("anchor.id"))),
526
+ eb("sort_order", ">", anchor().select("anchor.sort_order")),
527
+ eb.and([
528
+ eb("sort_order", "=", anchor().select("anchor.sort_order")),
529
+ eb("id", ">", anchor().select("anchor.id")),
530
+ ]),
531
+ ]);
532
+ });
533
+ } else {
534
+ const sortOrder = Number(decoded.orderValue);
535
+ // `decodeCursor` only guarantees `orderValue` is a string; a hand-crafted
536
+ // cursor with a non-numeric order value would coerce to NaN and blow up at
537
+ // the driver bind as a 500. A bad cursor is a client error — surface it as
538
+ // INVALID_CURSOR (400). Server-issued cursors are always numeric here.
539
+ if (!Number.isFinite(sortOrder)) throw new InvalidCursorError(options.cursor);
540
+ query = query.where((eb) =>
541
+ eb.or([
542
+ eb("sort_order", ">", sortOrder),
543
+ eb.and([eb("sort_order", "=", sortOrder), eb("id", ">", decoded.id)]),
544
+ ]),
545
+ );
546
+ }
376
547
  }
377
548
 
378
549
  const rows = await query
@@ -393,13 +564,13 @@ export class RelationRepository {
393
564
 
394
565
  /** Backlink traversal: the parents that reference a child for a relation. */
395
566
  async getParents(relation: string, childGroup: string): Promise<ContentReference[]> {
396
- const relationGroup = await this.resolveRelationGroup(relation);
397
- if (!relationGroup) return [];
567
+ const relationId = await this.resolveRelationId(relation);
568
+ if (!relationId) return [];
398
569
 
399
570
  const rows = await this.db
400
571
  .selectFrom("_emdash_content_references")
401
572
  .selectAll()
402
- .where("relation_group", "=", relationGroup)
573
+ .where("relation_id", "=", relationId)
403
574
  .where("child_group", "=", childGroup)
404
575
  .orderBy("id", "asc")
405
576
  .execute();
@@ -408,58 +579,254 @@ export class RelationRepository {
408
579
 
409
580
  /**
410
581
  * Replace all children of `parentGroup` under a relation with `childGroups`,
411
- * assigning positional sort_order (index in the deduped array). Deletes the
412
- * old set for this (relation, parent) and re-inserts — simple and correct;
413
- * the set is small (one parent's children). Mirrors the intent of
414
- * `TaxonomyRepository.setTermsForEntry`.
582
+ * assigning positional sort_order (index in the deduped array).
583
+ * Mirrors the intent of `TaxonomyRepository.setTermsForEntry`.
415
584
  *
416
585
  * A parent references a given child at most once (the unique edge), so
417
586
  * duplicate `childGroups` are collapsed first-occurrence-wins rather than
418
- * relying on the insert's onConflict to silently drop them. Not wrapped in a
419
- * transaction: a crash between the delete and insert leaves the parent with
420
- * no children — acceptable for a replace-all, since a retry restores state.
587
+ * relying on the insert's onConflict to silently drop them.
588
+ *
589
+ * Written as a diff, in the order add → remove → reposition, rather than as a
590
+ * delete of the whole end followed by a re-insert. There is no transaction on
591
+ * D1: a replacement that removed first would leave the parent holding nothing
592
+ * the moment the far side refused one of the additions, and report a failed
593
+ * save over an emptied field. Additions already written come back out when a
594
+ * later one is refused, so a refused call leaves the selection as it found it.
595
+ * The diff also keeps an edge the caller is merely re-stating out of the far
596
+ * side's count, which a delete-and-reinsert survives only because its delete
597
+ * frees the slot a moment before it asks for it back.
421
598
  *
422
599
  * Concurrency: two simultaneous replace-all calls for the same (relation,
423
- * parent) can interleave their deletes and inserts and merge into the union of
424
- * both sets (a lost update — neither "replace" wins). This is non-corrupting —
425
- * keyset pagination stays totally ordered via the `(sort_order, id)` tiebreak
426
- * even with duplicate sort_orders — and a single client editing one parent's
427
- * children serially never hits it. A D1-portable fix isn't available (no
428
- * multi-statement transactions), so concurrent replace-all on one parent is
429
- * unsupported by design rather than guarded here.
600
+ * parent) can interleave and merge into the union of both sets (a lost update
601
+ * — neither "replace" wins). This is non-corrupting — keyset pagination stays
602
+ * totally ordered via the `(sort_order, id)` tiebreak even with duplicate
603
+ * sort_orders — and a single client editing one parent's children serially
604
+ * never hits it. A D1-portable fix isn't available (no multi-statement
605
+ * transactions), so concurrent replace-all on one parent is unsupported by
606
+ * design rather than guarded here.
607
+ *
608
+ * Returns the child group `maxParentsPerChild` refused, in a one-element
609
+ * array — empty unless the relation limits that end and something else has
610
+ * taken the slot since the caller resolved its selection.
430
611
  */
431
- async setChildren(relation: string, parentGroup: string, childGroups: string[]): Promise<void> {
432
- const relationGroup = await this.resolveRelationGroup(relation);
433
- if (!relationGroup) return;
612
+ async setChildren(
613
+ relation: string,
614
+ parentGroup: string,
615
+ childGroups: string[],
616
+ ): Promise<string[]> {
617
+ const rel = await this.resolveRelationLimits(relation);
618
+ if (!rel) return [];
434
619
 
435
- await this.db
436
- .deleteFrom("_emdash_content_references")
437
- .where("relation_group", "=", relationGroup)
620
+ const existing = await this.db
621
+ .selectFrom("_emdash_content_references")
622
+ .select(["id", "child_group", "sort_order"])
623
+ .where("relation_id", "=", rel.id)
438
624
  .where("parent_group", "=", parentGroup)
439
625
  .execute();
626
+ const existingChildren = new Set(existing.map((row) => row.child_group));
440
627
 
441
628
  // Collapse duplicates so positional sort_order has no gaps.
442
629
  const uniqueChildGroups = [...new Set(childGroups)];
443
- if (uniqueChildGroups.length === 0) return;
630
+ const positions = new Map(uniqueChildGroups.map((childGroup, index) => [childGroup, index]));
444
631
 
445
632
  const now = new Date().toISOString();
446
- await this.db
447
- .insertInto("_emdash_content_references")
448
- .values(
449
- uniqueChildGroups.map((childGroup, index) => ({
450
- id: ulid(),
451
- relation_group: relationGroup,
452
- parent_group: parentGroup,
453
- child_group: childGroup,
454
- sort_order: index,
455
- created_at: now,
456
- })),
457
- )
458
- // Belt-and-suspenders: the DELETE above already cleared this
459
- // (relation, parent), so no conflict is possible within one call.
460
- // This is NOT a concurrency guarantee — delete-then-insert is not atomic.
461
- .onConflict((oc) => oc.doNothing())
633
+ const additions = uniqueChildGroups
634
+ .map((childGroup, index) => ({ childGroup, index }))
635
+ .filter(({ childGroup }) => !existingChildren.has(childGroup))
636
+ .map(({ childGroup, index }) => ({
637
+ id: ulid(),
638
+ relation_id: rel.id,
639
+ parent_group: parentGroup,
640
+ child_group: childGroup,
641
+ sort_order: index,
642
+ created_at: now,
643
+ }));
644
+
645
+ const rejected = await this.insertEdges(additions, "child", rel.maxParentsPerChild);
646
+ if (rejected.length > 0) return rejected;
647
+
648
+ const removals: string[] = [];
649
+ const repositions: EdgePosition[] = [];
650
+ for (const row of existing) {
651
+ const position = positions.get(row.child_group);
652
+ if (position === undefined) removals.push(row.id);
653
+ else if (position !== row.sort_order) repositions.push({ id: row.id, sortOrder: position });
654
+ }
655
+ await this.deleteEdgesById(removals);
656
+ await this.repositionEdges(repositions);
657
+ return [];
658
+ }
659
+
660
+ /**
661
+ * Replace all parents of `childGroup` under a relation with `parentGroups`:
662
+ * the mirror of `setChildren`, for a field bound to the child side.
663
+ *
664
+ * Duplicates collapse first-occurrence-wins, and the same diff ordering and
665
+ * non-transactional caveats apply — see `setChildren`, including that two
666
+ * concurrent replace-all calls for one (relation, child) can merge.
667
+ *
668
+ * `sort_order` orders children within a parent and has no counterpart on this
669
+ * side, so a *new* edge takes the next position among that parent's existing
670
+ * children rather than a position in this child's list. A parent the caller
671
+ * re-states keeps the position it already holds: that position is the other
672
+ * side's list order, and saving a backlink field must not rewrite it. A
673
+ * child-side field therefore has no order of its own; `getParents` reads by
674
+ * `id`.
675
+ *
676
+ * Returns the parent group `maxChildrenPerParent` refused, the mirror of what
677
+ * `setChildren` returns.
678
+ */
679
+ async setParents(
680
+ relation: string,
681
+ childGroup: string,
682
+ parentGroups: string[],
683
+ ): Promise<string[]> {
684
+ const rel = await this.resolveRelationLimits(relation);
685
+ if (!rel) return [];
686
+ const relationId = rel.id;
687
+
688
+ const existing = await this.db
689
+ .selectFrom("_emdash_content_references")
690
+ .select(["id", "parent_group"])
691
+ .where("relation_id", "=", relationId)
692
+ .where("child_group", "=", childGroup)
462
693
  .execute();
694
+ const existingParents = new Set(existing.map((row) => row.parent_group));
695
+
696
+ const uniqueParentGroups = [...new Set(parentGroups)];
697
+ const selected = new Set(uniqueParentGroups);
698
+ const newParents = uniqueParentGroups.filter(
699
+ (parentGroup) => !existingParents.has(parentGroup),
700
+ );
701
+
702
+ // One query for every new parent's highest position, so appending stays a
703
+ // fixed number of round trips rather than one per parent.
704
+ const nextSortOrder = new Map<string, number>();
705
+ for (const groupBatch of chunks(newParents, REFERENCE_INSERT_BATCH_SIZE)) {
706
+ // oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
707
+ const maxima = await this.db
708
+ .selectFrom("_emdash_content_references")
709
+ .select((eb) => ["parent_group", eb.fn.max("sort_order").as("max")])
710
+ .where("relation_id", "=", relationId)
711
+ .where("parent_group", "in", groupBatch)
712
+ .groupBy("parent_group")
713
+ .execute();
714
+ for (const row of maxima) {
715
+ nextSortOrder.set(row.parent_group, row.max === null ? 0 : Number(row.max) + 1);
716
+ }
717
+ }
718
+
719
+ const now = new Date().toISOString();
720
+ const additions = newParents.map((parentGroup) => ({
721
+ id: ulid(),
722
+ relation_id: relationId,
723
+ parent_group: parentGroup,
724
+ child_group: childGroup,
725
+ sort_order: nextSortOrder.get(parentGroup) ?? 0,
726
+ created_at: now,
727
+ }));
728
+
729
+ const rejected = await this.insertEdges(additions, "parent", rel.maxChildrenPerParent);
730
+ if (rejected.length > 0) return rejected;
731
+
732
+ await this.deleteEdgesById(
733
+ existing.filter((row) => !selected.has(row.parent_group)).map((row) => row.id),
734
+ );
735
+ return [];
736
+ }
737
+
738
+ /**
739
+ * Copy every outgoing edge of `fromParentGroup` onto `toParentGroup`,
740
+ * preserving relation, child, and sort order. Used when duplicating a content
741
+ * entry so the copy carries the same reference selections (edges are
742
+ * storage-less, keyed by translation_group, so they don't ride along in the
743
+ * row's `data`). Only the parent side is copied; backlinks pointing at the
744
+ * original stay on the original. Idempotent per edge via onConflict.
745
+ *
746
+ * A copy is still a new edge, so it holds to `maxParentsPerChild` like any
747
+ * other: a child already at its limit cannot also belong to the copy. Returns
748
+ * the child group that refused, in a one-element array, having taken back
749
+ * every edge this call had already written — the caller decides what a
750
+ * duplicate that cannot carry its selection should do.
751
+ */
752
+ async copyParentEdges(fromParentGroup: string, toParentGroup: string): Promise<string[]> {
753
+ const rows = await this.db
754
+ .selectFrom("_emdash_content_references")
755
+ .selectAll()
756
+ .where("parent_group", "=", fromParentGroup)
757
+ .execute();
758
+ if (rows.length === 0) return [];
759
+
760
+ const now = new Date().toISOString();
761
+ // Each relation carries its own limit, so the copies are written a relation
762
+ // at a time rather than as one undifferentiated batch.
763
+ const byRelation = new Map<string, EdgeInsert[]>();
764
+ for (const row of rows) {
765
+ const copies = byRelation.get(row.relation_id) ?? [];
766
+ copies.push({
767
+ id: ulid(),
768
+ relation_id: row.relation_id,
769
+ parent_group: toParentGroup,
770
+ child_group: row.child_group,
771
+ sort_order: row.sort_order,
772
+ created_at: now,
773
+ });
774
+ byRelation.set(row.relation_id, copies);
775
+ }
776
+
777
+ const written: string[] = [];
778
+ for (const [relationId, copies] of byRelation) {
779
+ // oxlint-disable-next-line no-await-in-loop -- each relation's limit gates its own copies
780
+ const rel = await this.resolveRelationLimits(relationId);
781
+ // oxlint-disable-next-line no-await-in-loop -- sequential so a refusal stops the rest
782
+ const rejected = await this.insertEdges(copies, "child", rel?.maxParentsPerChild ?? null);
783
+ if (rejected.length > 0) {
784
+ // `insertEdges` took back its own partial write; the relations already
785
+ // copied are this call's to undo.
786
+ await this.deleteEdgesById(written);
787
+ return rejected;
788
+ }
789
+ written.push(...copies.map((copy) => copy.id));
790
+ }
791
+ return [];
792
+ }
793
+
794
+ /**
795
+ * How many edges each of `groups` already holds at one end of a relation,
796
+ * ignoring edges whose opposite end is `excludeOppositeGroup`.
797
+ *
798
+ * The exclusion is what lets a re-save of an unchanged selection pass: the
799
+ * selecting entry's own edges are not counted against the limit it is about
800
+ * to re-establish. Groups with no edges are absent from the map.
801
+ */
802
+ async countEdgesByGroup(
803
+ relationId: string,
804
+ side: "parent" | "child",
805
+ groups: string[],
806
+ excludeOppositeGroup: string | null,
807
+ ): Promise<Map<string, number>> {
808
+ const column = side === "parent" ? "parent_group" : "child_group";
809
+ const opposite = side === "parent" ? "child_group" : "parent_group";
810
+
811
+ const counts = new Map<string, number>();
812
+ for (const groupBatch of chunks([...new Set(groups)], SQL_BATCH_SIZE)) {
813
+ let query = this.db
814
+ .selectFrom("_emdash_content_references")
815
+ .select((eb) => [column, eb.fn.countAll().as("count")])
816
+ .where("relation_id", "=", relationId)
817
+ .where(column, "in", groupBatch);
818
+ // An entry with no group of its own yet holds no links to discount, and
819
+ // `!= NULL` is never true — it would silently count nothing at all.
820
+ if (excludeOppositeGroup !== null) {
821
+ query = query.where(opposite, "!=", excludeOppositeGroup);
822
+ }
823
+ // oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
824
+ const rows = await query.groupBy(column).execute();
825
+ for (const row of rows) {
826
+ counts.set(row[column], Number(row.count));
827
+ }
828
+ }
829
+ return counts;
463
830
  }
464
831
 
465
832
  /**
@@ -475,20 +842,46 @@ export class RelationRepository {
475
842
  childGroup: string,
476
843
  options: { limit?: number; cursor?: string } = {},
477
844
  ): Promise<FindManyResult<ContentReference>> {
478
- const relationGroup = await this.resolveRelationGroup(relation);
479
- if (!relationGroup) return { items: [] };
845
+ const relationId = await this.resolveRelationId(relation);
846
+ if (!relationId) return { items: [] };
847
+ return this.getParentsPageById(relationId, childGroup, options);
848
+ }
480
849
 
850
+ /** `getParentsPage` for a caller that already holds the relation's id. */
851
+ async getParentsPageById(
852
+ relationId: string,
853
+ childGroup: string,
854
+ options: { limit?: number; cursor?: string } = {},
855
+ ): Promise<FindManyResult<ContentReference>> {
481
856
  const limit = Math.min(options.limit || 50, 100);
482
857
 
483
858
  let query = this.db
484
859
  .selectFrom("_emdash_content_references")
485
860
  .selectAll()
486
- .where("relation_group", "=", relationGroup)
861
+ .where("relation_id", "=", relationId)
487
862
  .where("child_group", "=", childGroup);
488
863
 
489
864
  if (options.cursor) {
490
865
  const decoded = decodeCursor(options.cursor);
491
- query = query.where("id", ">", decoded.id);
866
+ if (decoded.orderValue === STAGED_CURSOR_MARKER) {
867
+ // The mirror of `getChildrenPageById`: a staged cursor anchors on a
868
+ // translation group, which compared against `id` would page from an
869
+ // arbitrary point. Resume after that group's edge, or restart when the
870
+ // group is no longer selected.
871
+ query = query.where((eb) => {
872
+ const anchor = eb
873
+ .selectFrom("_emdash_content_references as anchor")
874
+ .where("anchor.relation_id", "=", relationId)
875
+ .where("anchor.child_group", "=", childGroup)
876
+ .where("anchor.parent_group", "=", decoded.id);
877
+ return eb.or([
878
+ eb.not(eb.exists(anchor.select("anchor.id"))),
879
+ eb("id", ">", anchor.select("anchor.id")),
880
+ ]);
881
+ });
882
+ } else {
883
+ query = query.where("id", ">", decoded.id);
884
+ }
492
885
  }
493
886
 
494
887
  const rows = await query
@@ -510,8 +903,8 @@ export class RelationRepository {
510
903
  * Remove every edge where `group` is the parent OR the child — i.e. ensure no
511
904
  * orphaned reference edges survive when a content entry is deleted. The
512
905
  * application-layer cascade that group-linking precludes at the SQL level.
513
- * Wiring this into the content-delete path is a later (handler) slice.
514
- * Returns the number of edges removed.
906
+ * Callers must be sure the whole group is gone: edges outlive any single
907
+ * locale row. Returns the number of edges removed.
515
908
  */
516
909
  async clearReferencesForGroup(group: string): Promise<number> {
517
910
  const result = await this.db
@@ -523,12 +916,12 @@ export class RelationRepository {
523
916
 
524
917
  /** Count a parent's children under a relation. */
525
918
  async countChildren(relation: string, parentGroup: string): Promise<number> {
526
- const relationGroup = await this.resolveRelationGroup(relation);
527
- if (!relationGroup) return 0;
919
+ const relationId = await this.resolveRelationId(relation);
920
+ if (!relationId) return 0;
528
921
  const result = await this.db
529
922
  .selectFrom("_emdash_content_references")
530
923
  .select((eb) => eb.fn.count("id").as("count"))
531
- .where("relation_group", "=", relationGroup)
924
+ .where("relation_id", "=", relationId)
532
925
  .where("parent_group", "=", parentGroup)
533
926
  .executeTakeFirst();
534
927
  return Number(result?.count ?? 0);
@@ -536,17 +929,34 @@ export class RelationRepository {
536
929
 
537
930
  /** Count a child's parents (backlinks) under a relation. */
538
931
  async countParents(relation: string, childGroup: string): Promise<number> {
539
- const relationGroup = await this.resolveRelationGroup(relation);
540
- if (!relationGroup) return 0;
932
+ const relationId = await this.resolveRelationId(relation);
933
+ if (!relationId) return 0;
541
934
  const result = await this.db
542
935
  .selectFrom("_emdash_content_references")
543
936
  .select((eb) => eb.fn.count("id").as("count"))
544
- .where("relation_group", "=", relationGroup)
937
+ .where("relation_id", "=", relationId)
545
938
  .where("child_group", "=", childGroup)
546
939
  .executeTakeFirst();
547
940
  return Number(result?.count ?? 0);
548
941
  }
549
942
 
943
+ /**
944
+ * Total edges per relation, for every relation at once. Relations with no
945
+ * edges are absent from the map.
946
+ *
947
+ * One grouped scan rather than a count per relation: the delete dialogs name
948
+ * how many links go with a relation, and the relations list shows the same
949
+ * number on every row.
950
+ */
951
+ async countEdgesByRelation(): Promise<Map<string, number>> {
952
+ const rows = await this.db
953
+ .selectFrom("_emdash_content_references")
954
+ .select(["relation_id", (eb) => eb.fn.count("id").as("count")])
955
+ .groupBy("relation_id")
956
+ .execute();
957
+ return new Map(rows.map((row) => [row.relation_id, Number(row.count ?? 0)]));
958
+ }
959
+
550
960
  /**
551
961
  * Batch child-counts for many parents under a relation. Chunks at
552
962
  * SQL_BATCH_SIZE for D1's bind-parameter limit. Returns parent_group → count
@@ -559,14 +969,14 @@ export class RelationRepository {
559
969
  ): Promise<Map<string, number>> {
560
970
  const counts = new Map<string, number>();
561
971
  if (parentGroups.length === 0) return counts;
562
- const relationGroup = await this.resolveRelationGroup(relation);
563
- if (!relationGroup) return counts;
972
+ const relationId = await this.resolveRelationId(relation);
973
+ if (!relationId) return counts;
564
974
 
565
975
  for (const chunk of chunks(parentGroups, SQL_BATCH_SIZE)) {
566
976
  const rows = await this.db
567
977
  .selectFrom("_emdash_content_references")
568
978
  .select(["parent_group", (eb) => eb.fn.count("id").as("count")])
569
- .where("relation_group", "=", relationGroup)
979
+ .where("relation_id", "=", relationId)
570
980
  .where("parent_group", "in", chunk)
571
981
  .groupBy("parent_group")
572
982
  .execute();
@@ -580,13 +990,15 @@ export class RelationRepository {
580
990
  private rowToRelation(row: Selectable<RelationTable>): Relation {
581
991
  return {
582
992
  id: row.id,
583
- name: row.name,
993
+ slug: row.slug,
584
994
  parentCollection: row.parent_collection,
585
995
  childCollection: row.child_collection,
586
996
  parentLabel: row.parent_label,
587
997
  childLabel: row.child_label,
588
- locale: row.locale,
589
- translationGroup: row.translation_group,
998
+ parentLabelSingular: row.parent_label_singular,
999
+ childLabelSingular: row.child_label_singular,
1000
+ maxChildrenPerParent: row.max_children_per_parent,
1001
+ maxParentsPerChild: row.max_parents_per_child,
590
1002
  };
591
1003
  }
592
1004
  }