emdash 0.40.1 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1240) hide show
  1. package/dist/action-token-CbKDcPJi.mjs +26 -0
  2. package/dist/action-token-CbKDcPJi.mjs.map +1 -0
  3. package/dist/activation-PtniBLt9.mjs +382 -0
  4. package/dist/activation-PtniBLt9.mjs.map +1 -0
  5. package/dist/adapters-C_Tf5x90.d.mts +171 -0
  6. package/dist/adapters-C_Tf5x90.d.mts.map +1 -0
  7. package/dist/allowed-origins-U1z4TdEZ.mjs +116 -0
  8. package/dist/allowed-origins-U1z4TdEZ.mjs.map +1 -0
  9. package/dist/api/route-utils.d.mts +4 -4
  10. package/dist/api/route-utils.mjs +46 -45
  11. package/dist/api/route-utils.mjs.map +1 -1
  12. package/dist/api/schemas/index.d.mts +2 -2
  13. package/dist/api/schemas/index.mjs +10 -10
  14. package/dist/api-CXwQkV_m.mjs +5122 -0
  15. package/dist/api-CXwQkV_m.mjs.map +1 -0
  16. package/dist/api-tokens-89WlohEN.mjs +166 -0
  17. package/dist/api-tokens-89WlohEN.mjs.map +1 -0
  18. package/dist/apply-Do3KNnUk.mjs +1659 -0
  19. package/dist/apply-Do3KNnUk.mjs.map +1 -0
  20. package/dist/approvals-CAX9Yw33.mjs +460 -0
  21. package/dist/approvals-CAX9Yw33.mjs.map +1 -0
  22. package/dist/artifact-fetch-B9W4CEST.mjs +659 -0
  23. package/dist/artifact-fetch-B9W4CEST.mjs.map +1 -0
  24. package/dist/astro/index.d.mts +14 -14
  25. package/dist/astro/index.mjs +20 -24
  26. package/dist/astro/index.mjs.map +1 -1
  27. package/dist/astro/middleware/auth.d.mts +12 -12
  28. package/dist/astro/middleware/auth.mjs +10 -10
  29. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  30. package/dist/astro/middleware/redirect.mjs +7 -7
  31. package/dist/astro/middleware/request-context.mjs +3 -3
  32. package/dist/astro/middleware/setup.mjs +1 -1
  33. package/dist/astro/middleware.d.mts +12 -12
  34. package/dist/astro/middleware.mjs +109 -106
  35. package/dist/astro/middleware.mjs.map +1 -1
  36. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +14 -14
  37. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +14 -14
  38. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
  39. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  40. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +7 -7
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +17 -17
  42. package/dist/astro/routes/api/admin/byline-fields/index.mjs +17 -17
  43. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +17 -17
  44. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +23 -23
  45. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +23 -23
  46. package/dist/astro/routes/api/admin/bylines/index.mjs +23 -23
  47. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -18
  48. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
  49. package/dist/astro/routes/api/admin/comments/bulk.mjs +17 -17
  50. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
  51. package/dist/astro/routes/api/admin/comments/index.mjs +17 -17
  52. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  53. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  54. package/dist/astro/routes/api/admin/media-usage/activation.mjs +20 -20
  55. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +22 -22
  56. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +22 -22
  57. package/dist/astro/routes/api/admin/media-usage/progress.mjs +25 -25
  58. package/dist/astro/routes/api/admin/media-usage/repair.mjs +31 -31
  59. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +22 -22
  60. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +22 -22
  61. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
  62. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
  63. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +8 -8
  64. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +8 -8
  65. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +72 -68
  66. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +7 -7
  68. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +71 -67
  69. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +72 -68
  71. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +82 -78
  73. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/plugins/index.mjs +72 -68
  75. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +5 -5
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +71 -67
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +81 -77
  80. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  81. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +71 -67
  82. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  83. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +72 -68
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +83 -79
  86. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +9 -9
  88. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +74 -70
  89. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +7 -7
  91. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +72 -68
  92. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/updates.mjs +71 -67
  94. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +6 -6
  96. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +71 -67
  97. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +5 -5
  99. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +71 -67
  100. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  101. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +4 -4
  102. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +40 -40
  103. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +40 -40
  104. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +42 -42
  105. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +42 -42
  106. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +42 -42
  107. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +43 -43
  108. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +43 -43
  109. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +42 -42
  110. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +43 -43
  111. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +44 -44
  112. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +42 -42
  113. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +42 -42
  114. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +44 -44
  115. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +42 -42
  116. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +44 -44
  117. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +42 -42
  118. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +42 -42
  119. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +44 -44
  120. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +42 -42
  121. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +42 -42
  122. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +44 -44
  123. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +5 -5
  124. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +4 -4
  125. package/dist/astro/routes/api/admin/users/_id_/index.mjs +15 -15
  126. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
  127. package/dist/astro/routes/api/admin/users/index.mjs +14 -14
  128. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  129. package/dist/astro/routes/api/auth/invite/accept.mjs +4 -4
  130. package/dist/astro/routes/api/auth/invite/complete.mjs +18 -18
  131. package/dist/astro/routes/api/auth/invite/index.mjs +16 -16
  132. package/dist/astro/routes/api/auth/invite/register-options.mjs +17 -17
  133. package/dist/astro/routes/api/auth/logout.mjs +5 -5
  134. package/dist/astro/routes/api/auth/magic-link/send.mjs +18 -18
  135. package/dist/astro/routes/api/auth/magic-link/verify.mjs +14 -14
  136. package/dist/astro/routes/api/auth/me.mjs +15 -15
  137. package/dist/astro/routes/api/auth/mode.mjs +5 -5
  138. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  139. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  140. package/dist/astro/routes/api/auth/passkey/_id_.mjs +14 -14
  141. package/dist/astro/routes/api/auth/passkey/index.mjs +4 -4
  142. package/dist/astro/routes/api/auth/passkey/options.mjs +19 -19
  143. package/dist/astro/routes/api/auth/passkey/register/options.mjs +17 -17
  144. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +18 -18
  145. package/dist/astro/routes/api/auth/passkey/verify.mjs +18 -18
  146. package/dist/astro/routes/api/auth/signup/complete.mjs +18 -18
  147. package/dist/astro/routes/api/auth/signup/request.mjs +17 -17
  148. package/dist/astro/routes/api/auth/signup/verify.mjs +4 -4
  149. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  150. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -18
  151. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +5 -5
  152. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -17
  153. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
  154. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +17 -17
  155. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +5 -5
  156. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +11 -11
  157. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +31 -31
  158. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +17 -17
  159. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +1 -2
  160. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -1
  161. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +42 -53
  162. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  163. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +34 -29
  164. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  165. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
  166. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +5 -5
  167. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +17 -17
  168. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +25 -24
  169. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  170. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +5 -5
  171. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +17 -17
  172. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  173. package/dist/astro/routes/api/content/_collection_/_id_.mjs +18 -18
  174. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  175. package/dist/astro/routes/api/content/_collection_/authors.mjs +5 -5
  176. package/dist/astro/routes/api/content/_collection_/index.mjs +15 -15
  177. package/dist/astro/routes/api/content/_collection_/trash.mjs +15 -15
  178. package/dist/astro/routes/api/dashboard.mjs +10 -9
  179. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  180. package/dist/astro/routes/api/dev/emails.mjs +5 -5
  181. package/dist/astro/routes/api/health.mjs +6 -6
  182. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  183. package/dist/astro/routes/api/import/probe.mjs +23 -23
  184. package/dist/astro/routes/api/import/wordpress/analyze.mjs +6 -6
  185. package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -13
  186. package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
  187. package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -12
  188. package/dist/astro/routes/api/import/wordpress/media.mjs +19 -19
  189. package/dist/astro/routes/api/import/wordpress/prepare.mjs +18 -18
  190. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -13
  191. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +28 -28
  192. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  193. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +23 -23
  194. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -13
  195. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +34 -34
  196. package/dist/astro/routes/api/manifest.mjs +6 -6
  197. package/dist/astro/routes/api/mcp.mjs +91 -91
  198. package/dist/astro/routes/api/media/_id_/confirm.mjs +19 -19
  199. package/dist/astro/routes/api/media/_id_/replace.mjs +16 -16
  200. package/dist/astro/routes/api/media/_id_/upload.mjs +9 -9
  201. package/dist/astro/routes/api/media/_id_/usage.mjs +33 -33
  202. package/dist/astro/routes/api/media/_id_.mjs +31 -31
  203. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +6 -6
  204. package/dist/astro/routes/api/media/file/_...key_.mjs +9 -9
  205. package/dist/astro/routes/api/media/folders/_id_.mjs +16 -16
  206. package/dist/astro/routes/api/media/folders/index.mjs +16 -16
  207. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +5 -5
  208. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +5 -5
  209. package/dist/astro/routes/api/media/providers/index.mjs +5 -5
  210. package/dist/astro/routes/api/media/upload-url.mjs +18 -18
  211. package/dist/astro/routes/api/media.mjs +35 -35
  212. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -17
  213. package/dist/astro/routes/api/menus/_name_/items.mjs +17 -17
  214. package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -17
  215. package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -17
  216. package/dist/astro/routes/api/menus/_name_.mjs +17 -17
  217. package/dist/astro/routes/api/menus/index.mjs +17 -17
  218. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  219. package/dist/astro/routes/api/oauth/device/authorize.d.mts +2 -1
  220. package/dist/astro/routes/api/oauth/device/authorize.d.mts.map +1 -1
  221. package/dist/astro/routes/api/oauth/device/authorize.mjs +23 -9
  222. package/dist/astro/routes/api/oauth/device/authorize.mjs.map +1 -1
  223. package/dist/astro/routes/api/oauth/device/code.mjs +11 -11
  224. package/dist/astro/routes/api/oauth/device/token.mjs +10 -10
  225. package/dist/astro/routes/api/oauth/register.mjs +5 -5
  226. package/dist/astro/routes/api/oauth/token/refresh.mjs +8 -8
  227. package/dist/astro/routes/api/oauth/token/revoke.mjs +8 -8
  228. package/dist/astro/routes/api/oauth/token.mjs +8 -8
  229. package/dist/astro/routes/api/openapi.json.mjs +20 -20
  230. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +11 -11
  231. package/dist/astro/routes/api/redirects/404s/index.mjs +19 -19
  232. package/dist/astro/routes/api/redirects/404s/summary.mjs +19 -19
  233. package/dist/astro/routes/api/redirects/_id_.mjs +19 -19
  234. package/dist/astro/routes/api/redirects/index.mjs +19 -19
  235. package/dist/astro/routes/api/relations/_id_/index.mjs +34 -29
  236. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  237. package/dist/astro/routes/api/relations/index.mjs +36 -31
  238. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  239. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +5 -5
  240. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
  241. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +71 -67
  242. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  243. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +71 -67
  244. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  245. package/dist/astro/routes/api/schema/block-types/index.mjs +71 -67
  246. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  247. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +73 -69
  248. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  249. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +71 -67
  250. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  251. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +71 -67
  252. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  253. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +71 -67
  254. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  255. package/dist/astro/routes/api/schema/collections/index.mjs +71 -67
  256. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  257. package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -67
  258. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  259. package/dist/astro/routes/api/schema/index.mjs +16 -16
  260. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +71 -67
  261. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  262. package/dist/astro/routes/api/schema/orphans/index.mjs +71 -67
  263. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  264. package/dist/astro/routes/api/search/enable.mjs +19 -19
  265. package/dist/astro/routes/api/search/index.mjs +18 -18
  266. package/dist/astro/routes/api/search/rebuild.mjs +19 -19
  267. package/dist/astro/routes/api/search/stats.mjs +9 -9
  268. package/dist/astro/routes/api/search/suggest.mjs +18 -18
  269. package/dist/astro/routes/api/sections/_slug_.mjs +18 -18
  270. package/dist/astro/routes/api/sections/index.mjs +18 -18
  271. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  272. package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
  273. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  274. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  275. package/dist/astro/routes/api/settings/email.mjs +6 -6
  276. package/dist/astro/routes/api/settings.mjs +21 -21
  277. package/dist/astro/routes/api/setup/admin-verify.mjs +19 -19
  278. package/dist/astro/routes/api/setup/admin.mjs +18 -18
  279. package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -39
  280. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  281. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  282. package/dist/astro/routes/api/setup/index.mjs +50 -44
  283. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  284. package/dist/astro/routes/api/setup/status.mjs +6 -6
  285. package/dist/astro/routes/api/snapshot.mjs +8 -8
  286. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -23
  287. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -23
  288. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -23
  289. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -23
  290. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -22
  291. package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -23
  292. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +36 -35
  293. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
  294. package/dist/astro/routes/api/taxonomies/index.mjs +23 -23
  295. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  296. package/dist/astro/routes/api/typegen.mjs +8 -8
  297. package/dist/astro/routes/api/visual-editing/action-token.mjs +6 -6
  298. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +19 -19
  299. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +4 -4
  300. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  301. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  302. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  303. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +16 -16
  304. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +19 -19
  305. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +19 -19
  306. package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -9
  307. package/dist/astro/routes/api/widget-areas/index.mjs +19 -19
  308. package/dist/astro/routes/api/widget-components.mjs +5 -5
  309. package/dist/astro/routes/robots.txt.mjs +6 -6
  310. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  311. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  312. package/dist/astro/types.d.mts +24 -18
  313. package/dist/astro/types.d.mts.map +1 -1
  314. package/dist/audit-CrgmE9LE.mjs +127 -0
  315. package/dist/audit-CrgmE9LE.mjs.map +1 -0
  316. package/dist/auth/providers/github.d.mts +1 -1
  317. package/dist/auth/providers/google.d.mts +1 -1
  318. package/dist/authoritative-records-C2YzIdbu.mjs +5172 -0
  319. package/dist/authoritative-records-C2YzIdbu.mjs.map +1 -0
  320. package/dist/authorize-WgdKF8QY.mjs +49 -0
  321. package/dist/authorize-WgdKF8QY.mjs.map +1 -0
  322. package/dist/backup-Ck8_lMO3.mjs +246 -0
  323. package/dist/backup-Ck8_lMO3.mjs.map +1 -0
  324. package/dist/block-types-BQ90asVI.mjs +132 -0
  325. package/dist/block-types-BQ90asVI.mjs.map +1 -0
  326. package/dist/block-values-ACFqgB1D.mjs +175 -0
  327. package/dist/block-values-ACFqgB1D.mjs.map +1 -0
  328. package/dist/bundle-Db1iNMv_.mjs +667 -0
  329. package/dist/bundle-Db1iNMv_.mjs.map +1 -0
  330. package/dist/byline-BayaYGoj.mjs +909 -0
  331. package/dist/byline-BayaYGoj.mjs.map +1 -0
  332. package/dist/byline-fields-B8HH-35f.mjs +254 -0
  333. package/dist/byline-fields-B8HH-35f.mjs.map +1 -0
  334. package/dist/byline-fields-hMPjf6Eu.mjs +123 -0
  335. package/dist/byline-fields-hMPjf6Eu.mjs.map +1 -0
  336. package/dist/byline-registry-B_EK_TQf.mjs +406 -0
  337. package/dist/byline-registry-B_EK_TQf.mjs.map +1 -0
  338. package/dist/bylines-DFAaFXWi.mjs +214 -0
  339. package/dist/bylines-DFAaFXWi.mjs.map +1 -0
  340. package/dist/bylines-DkIxUxmr.mjs +232 -0
  341. package/dist/bylines-DkIxUxmr.mjs.map +1 -0
  342. package/dist/cache-DkvhQ8XE.mjs +108 -0
  343. package/dist/cache-DkvhQ8XE.mjs.map +1 -0
  344. package/dist/canonical-CcSuuTlH.mjs +174 -0
  345. package/dist/canonical-CcSuuTlH.mjs.map +1 -0
  346. package/dist/capture-triggers-DJEoOTOq.mjs +362 -0
  347. package/dist/capture-triggers-DJEoOTOq.mjs.map +1 -0
  348. package/dist/challenge-store-CvBl81AQ.mjs +51 -0
  349. package/dist/challenge-store-CvBl81AQ.mjs.map +1 -0
  350. package/dist/checksum-CClweQzI.mjs +162 -0
  351. package/dist/checksum-CClweQzI.mjs.map +1 -0
  352. package/dist/chrome-tags-D5caJwwp.mjs +24 -0
  353. package/dist/chrome-tags-D5caJwwp.mjs.map +1 -0
  354. package/dist/chunks-DwBaj8aT.mjs +25 -0
  355. package/dist/chunks-DwBaj8aT.mjs.map +1 -0
  356. package/dist/cli/index.mjs +374 -761
  357. package/dist/cli/index.mjs.map +1 -1
  358. package/dist/client/cf-access.d.mts +1 -1
  359. package/dist/client/index.d.mts +32 -32
  360. package/dist/client/index.mjs +2 -2
  361. package/dist/collection-deletion-CLCdXsnV.mjs +436 -0
  362. package/dist/collection-deletion-CLCdXsnV.mjs.map +1 -0
  363. package/dist/collection-deletion-processor-hNw8x01F.mjs +217 -0
  364. package/dist/collection-deletion-processor-hNw8x01F.mjs.map +1 -0
  365. package/dist/collection-slugs-cache-CUuiduLq.mjs +85 -0
  366. package/dist/collection-slugs-cache-CUuiduLq.mjs.map +1 -0
  367. package/dist/comment-D2uvL63j.mjs +313 -0
  368. package/dist/comment-D2uvL63j.mjs.map +1 -0
  369. package/dist/comment-reaction-DevUuzg4.mjs +85 -0
  370. package/dist/comment-reaction-DevUuzg4.mjs.map +1 -0
  371. package/dist/comments-Cq0s7_hO.mjs +195 -0
  372. package/dist/comments-Cq0s7_hO.mjs.map +1 -0
  373. package/dist/comments-M4EDYAHw.mjs +99 -0
  374. package/dist/comments-M4EDYAHw.mjs.map +1 -0
  375. package/dist/components-CuIGwXMs.mjs +108 -0
  376. package/dist/components-CuIGwXMs.mjs.map +1 -0
  377. package/dist/config-52Ea5IWt.d.mts +39 -0
  378. package/dist/config-52Ea5IWt.d.mts.map +1 -0
  379. package/dist/config-CCz3xOLc.mjs +242 -0
  380. package/dist/config-CCz3xOLc.mjs.map +1 -0
  381. package/dist/config-D3d5Qudq.d.mts +6669 -0
  382. package/dist/config-D3d5Qudq.d.mts.map +1 -0
  383. package/dist/content-CbnufDsM.mjs +2018 -0
  384. package/dist/content-CbnufDsM.mjs.map +1 -0
  385. package/dist/content-list-query-D_7B1FE5.d.mts +26 -0
  386. package/dist/content-list-query-D_7B1FE5.d.mts.map +1 -0
  387. package/dist/content-policy-CYu6K1KB.mjs +46 -0
  388. package/dist/content-policy-CYu6K1KB.mjs.map +1 -0
  389. package/dist/content-repair-DlDUgFGp.mjs +442 -0
  390. package/dist/content-repair-DlDUgFGp.mjs.map +1 -0
  391. package/dist/context-CGQLA1-a.mjs +1922 -0
  392. package/dist/context-CGQLA1-a.mjs.map +1 -0
  393. package/dist/cron-c4D5C5Fx.mjs +284 -0
  394. package/dist/cron-c4D5C5Fx.mjs.map +1 -0
  395. package/dist/dashboard-CBq9kmOn.mjs +151 -0
  396. package/dist/dashboard-CBq9kmOn.mjs.map +1 -0
  397. package/dist/db/index.d.mts +3 -3
  398. package/dist/db/index.mjs +1 -1
  399. package/dist/db/libsql-migrations.d.mts +1 -1
  400. package/dist/db/libsql-migrations.mjs +4 -4
  401. package/dist/db/libsql.d.mts +1 -1
  402. package/dist/db/postgres-migrations.d.mts +1 -1
  403. package/dist/db/postgres-migrations.mjs +4 -4
  404. package/dist/db/postgres.d.mts +1 -1
  405. package/dist/db/sqlite-migrations.d.mts +1 -1
  406. package/dist/db/sqlite-migrations.mjs +4 -4
  407. package/dist/db/sqlite.d.mts +1 -1
  408. package/dist/db/sqlite.mjs +1 -1
  409. package/dist/default-DPsys51U.mjs +81 -0
  410. package/dist/default-DPsys51U.mjs.map +1 -0
  411. package/dist/deferred-tasks-CZ7rzBdo.d.mts +9 -0
  412. package/dist/deferred-tasks-CZ7rzBdo.d.mts.map +1 -0
  413. package/dist/dev-typegen-HRxwLRcT.mjs +29 -0
  414. package/dist/dev-typegen-HRxwLRcT.mjs.map +1 -0
  415. package/dist/device-flow-OcSqE9uY.mjs +521 -0
  416. package/dist/device-flow-OcSqE9uY.mjs.map +1 -0
  417. package/dist/digest-DVZ--cE9.mjs +194 -0
  418. package/dist/digest-DVZ--cE9.mjs.map +1 -0
  419. package/dist/direct-executor-DyjAqkpT.mjs +104 -0
  420. package/dist/direct-executor-DyjAqkpT.mjs.map +1 -0
  421. package/dist/dist-FPR93_xf.mjs +810 -0
  422. package/dist/dist-FPR93_xf.mjs.map +1 -0
  423. package/dist/email-console-DyQIgEnz.mjs +50 -0
  424. package/dist/email-console-DyQIgEnz.mjs.map +1 -0
  425. package/dist/email-locale-BYb16rVd.mjs +25 -0
  426. package/dist/email-locale-BYb16rVd.mjs.map +1 -0
  427. package/dist/emdash-runtime-CrzxJFmF.mjs +4214 -0
  428. package/dist/emdash-runtime-CrzxJFmF.mjs.map +1 -0
  429. package/dist/enrich-DBtCncE2.mjs +194 -0
  430. package/dist/enrich-DBtCncE2.mjs.map +1 -0
  431. package/dist/entry-lock-BN5y4YbO.d.mts +4481 -0
  432. package/dist/entry-lock-BN5y4YbO.d.mts.map +1 -0
  433. package/dist/entry-lock-BaRBHCsH.mjs +1173 -0
  434. package/dist/entry-lock-BaRBHCsH.mjs.map +1 -0
  435. package/dist/entry-lock-C6NcnZPV.mjs +163 -0
  436. package/dist/entry-lock-C6NcnZPV.mjs.map +1 -0
  437. package/dist/entry-locks-BTyQLdbC.mjs +167 -0
  438. package/dist/entry-locks-BTyQLdbC.mjs.map +1 -0
  439. package/dist/error-BfsNNrIE.mjs +90 -0
  440. package/dist/error-BfsNNrIE.mjs.map +1 -0
  441. package/dist/errors-BN1QAnEY.mjs +460 -0
  442. package/dist/errors-BN1QAnEY.mjs.map +1 -0
  443. package/dist/errors-Bt3goF8I.mjs +120 -0
  444. package/dist/errors-Bt3goF8I.mjs.map +1 -0
  445. package/dist/escape-BveidMa2.mjs +9 -0
  446. package/dist/escape-BveidMa2.mjs.map +1 -0
  447. package/dist/fence-Bb_IbCxI.mjs +162 -0
  448. package/dist/fence-Bb_IbCxI.mjs.map +1 -0
  449. package/dist/field-defs-cache-CsZctvbu.mjs +77 -0
  450. package/dist/field-defs-cache-CsZctvbu.mjs.map +1 -0
  451. package/dist/field-map-6m9rF49t.mjs +83 -0
  452. package/dist/field-map-6m9rF49t.mjs.map +1 -0
  453. package/dist/focal-point-CZ3d1wK5.mjs +23 -0
  454. package/dist/focal-point-CZ3d1wK5.mjs.map +1 -0
  455. package/dist/fts-manager-CCaZTp8y.mjs +443 -0
  456. package/dist/fts-manager-CCaZTp8y.mjs.map +1 -0
  457. package/dist/gc-xowRjczI.mjs +75 -0
  458. package/dist/gc-xowRjczI.mjs.map +1 -0
  459. package/dist/hash-COVK27Pc.mjs +37 -0
  460. package/dist/hash-COVK27Pc.mjs.map +1 -0
  461. package/dist/hook-result-CYSk0XFe.d.mts +31 -0
  462. package/dist/hook-result-CYSk0XFe.d.mts.map +1 -0
  463. package/dist/hreflang-CChPV7jx.mjs +105 -0
  464. package/dist/hreflang-CChPV7jx.mjs.map +1 -0
  465. package/dist/hreflang-DRslq3QI.d.mts +50 -0
  466. package/dist/hreflang-DRslq3QI.d.mts.map +1 -0
  467. package/dist/http-route-dispatch-CAdp2onn.mjs +339 -0
  468. package/dist/http-route-dispatch-CAdp2onn.mjs.map +1 -0
  469. package/dist/identity-NVTOOQyq.mjs +35 -0
  470. package/dist/identity-NVTOOQyq.mjs.map +1 -0
  471. package/dist/import-wpSO2N0x.mjs +2020 -0
  472. package/dist/import-wpSO2N0x.mjs.map +1 -0
  473. package/dist/index-CDs2wq4X.d.mts +623 -0
  474. package/dist/index-CDs2wq4X.d.mts.map +1 -0
  475. package/dist/index.d.mts +24 -24
  476. package/dist/index.mjs +103 -101
  477. package/dist/install-finalization-D9R9R-W8.mjs +58 -0
  478. package/dist/install-finalization-D9R9R-W8.mjs.map +1 -0
  479. package/dist/keys-Bck6LBfF.mjs +61 -0
  480. package/dist/keys-Bck6LBfF.mjs.map +1 -0
  481. package/dist/kinds-CYmRESWj.mjs +974 -0
  482. package/dist/kinds-CYmRESWj.mjs.map +1 -0
  483. package/dist/lifecycle-C815ZQfV.mjs +25 -0
  484. package/dist/lifecycle-C815ZQfV.mjs.map +1 -0
  485. package/dist/load-D99axixL.mjs +28 -0
  486. package/dist/load-D99axixL.mjs.map +1 -0
  487. package/dist/loader-CrRPfkHS.mjs +1197 -0
  488. package/dist/loader-CrRPfkHS.mjs.map +1 -0
  489. package/dist/loops-DMKlygqX.mjs +203 -0
  490. package/dist/loops-DMKlygqX.mjs.map +1 -0
  491. package/dist/manifest-builder-BQzCHNgB.mjs +189 -0
  492. package/dist/manifest-builder-BQzCHNgB.mjs.map +1 -0
  493. package/dist/manifest-schema-Ci2gmd0u.mjs +492 -0
  494. package/dist/manifest-schema-Ci2gmd0u.mjs.map +1 -0
  495. package/dist/media/image-endpoint.mjs +1 -1
  496. package/dist/media/index.d.mts +1 -1
  497. package/dist/media/index.mjs +4 -4
  498. package/dist/media/local-runtime.d.mts +14 -14
  499. package/dist/media/local-runtime.mjs +6 -6
  500. package/dist/media-BUQePMxP.mjs +373 -0
  501. package/dist/media-BUQePMxP.mjs.map +1 -0
  502. package/dist/media-DH8ibNlY.mjs +294 -0
  503. package/dist/media-DH8ibNlY.mjs.map +1 -0
  504. package/dist/media-OEIQ3bVc.mjs +408 -0
  505. package/dist/media-OEIQ3bVc.mjs.map +1 -0
  506. package/dist/media-allowlist-pYtaBA95.mjs +44 -0
  507. package/dist/media-allowlist-pYtaBA95.mjs.map +1 -0
  508. package/dist/media-folders-Bf8_s4de.mjs +210 -0
  509. package/dist/media-folders-Bf8_s4de.mjs.map +1 -0
  510. package/dist/media-url-C6klEuNd.mjs +43 -0
  511. package/dist/media-url-C6klEuNd.mjs.map +1 -0
  512. package/dist/media-usage-D7Y64m6v.mjs +1629 -0
  513. package/dist/media-usage-D7Y64m6v.mjs.map +1 -0
  514. package/dist/media-usage-activation-DrqbmgLA.mjs +78 -0
  515. package/dist/media-usage-activation-DrqbmgLA.mjs.map +1 -0
  516. package/dist/media-usage-work-DommYhYA.mjs +152 -0
  517. package/dist/media-usage-work-DommYhYA.mjs.map +1 -0
  518. package/dist/media-usage-work-HU63hNDu.mjs +586 -0
  519. package/dist/media-usage-work-HU63hNDu.mjs.map +1 -0
  520. package/dist/menus-BQfusWEC.mjs +3608 -0
  521. package/dist/menus-BQfusWEC.mjs.map +1 -0
  522. package/dist/menus-BtwjQt5s.mjs +753 -0
  523. package/dist/menus-BtwjQt5s.mjs.map +1 -0
  524. package/dist/menus-p_M1V7J_.mjs +139 -0
  525. package/dist/menus-p_M1V7J_.mjs.map +1 -0
  526. package/dist/migrations/index.d.mts +1 -1
  527. package/dist/migrations/index.mjs +3 -3
  528. package/dist/mime-C94qBG-P.mjs +36 -0
  529. package/dist/mime-C94qBG-P.mjs.map +1 -0
  530. package/dist/mode-DpYW3w6U.mjs +23 -0
  531. package/dist/mode-DpYW3w6U.mjs.map +1 -0
  532. package/dist/node-sqlite-compat-pWFw0lcc.mjs +46 -0
  533. package/dist/node-sqlite-compat-pWFw0lcc.mjs.map +1 -0
  534. package/dist/normalize-DduyxBjf.mjs +191 -0
  535. package/dist/normalize-DduyxBjf.mjs.map +1 -0
  536. package/dist/oauth-authorization-DAXsH1H9.mjs +274 -0
  537. package/dist/oauth-authorization-DAXsH1H9.mjs.map +1 -0
  538. package/dist/oauth-clients-DENiDQri.mjs +266 -0
  539. package/dist/oauth-clients-DENiDQri.mjs.map +1 -0
  540. package/dist/oauth-state-store-y8mEYVq9.mjs +50 -0
  541. package/dist/oauth-state-store-y8mEYVq9.mjs.map +1 -0
  542. package/dist/oauth-user-lookup-CtTYAy-O.mjs +26 -0
  543. package/dist/oauth-user-lookup-CtTYAy-O.mjs.map +1 -0
  544. package/dist/object-cache/memory.d.mts +1 -1
  545. package/dist/options-BYa1FgIM.d.mts +81 -0
  546. package/dist/options-BYa1FgIM.d.mts.map +1 -0
  547. package/dist/page/index.d.mts +2 -2
  548. package/dist/page/index.mjs +5 -5
  549. package/dist/parse-CORGGhHf.mjs +81 -0
  550. package/dist/parse-CORGGhHf.mjs.map +1 -0
  551. package/dist/parse-avNM1xWV.d.mts +168 -0
  552. package/dist/parse-avNM1xWV.d.mts.map +1 -0
  553. package/dist/passkey-config-Dih5YeIS.mjs +46 -0
  554. package/dist/passkey-config-Dih5YeIS.mjs.map +1 -0
  555. package/dist/paths-d51RFm8M.mjs +77 -0
  556. package/dist/paths-d51RFm8M.mjs.map +1 -0
  557. package/dist/patterns-CoqlXUvk.mjs +145 -0
  558. package/dist/patterns-CoqlXUvk.mjs.map +1 -0
  559. package/dist/placeholder-D2aksPMF.d.mts +306 -0
  560. package/dist/placeholder-D2aksPMF.d.mts.map +1 -0
  561. package/dist/plan-DqeZKuaR.mjs +135 -0
  562. package/dist/plan-DqeZKuaR.mjs.map +1 -0
  563. package/dist/plugin-test-runtime.d.mts +14 -14
  564. package/dist/plugin-test-runtime.mjs +110 -107
  565. package/dist/plugin-types.d.mts +2 -2
  566. package/dist/plugin-utils.d.mts +12 -12
  567. package/dist/plugins/adapt-sandbox-entry.d.mts +12 -12
  568. package/dist/plugins/adapt-sandbox-entry.mjs +3 -3
  569. package/dist/plugins/host.d.mts +5 -5
  570. package/dist/plugins/host.mjs +42 -41
  571. package/dist/plugins-Bb7oqjQA.mjs +277 -0
  572. package/dist/plugins-Bb7oqjQA.mjs.map +1 -0
  573. package/dist/policy-BcEqut3n.mjs +45 -0
  574. package/dist/policy-BcEqut3n.mjs.map +1 -0
  575. package/dist/portable-text-DXE8ymtD.mjs +307 -0
  576. package/dist/portable-text-DXE8ymtD.mjs.map +1 -0
  577. package/dist/preview-DEDWbwA_.mjs +107 -0
  578. package/dist/preview-DEDWbwA_.mjs.map +1 -0
  579. package/dist/protocol-BJbTzvwl.d.mts +61 -0
  580. package/dist/protocol-BJbTzvwl.d.mts.map +1 -0
  581. package/dist/public-submission-D9c9S14m.mjs +250 -0
  582. package/dist/public-submission-D9c9S14m.mjs.map +1 -0
  583. package/dist/public-url-CIRe-2T6.mjs +101 -0
  584. package/dist/public-url-CIRe-2T6.mjs.map +1 -0
  585. package/dist/query-BzifXlPS.mjs +1156 -0
  586. package/dist/query-BzifXlPS.mjs.map +1 -0
  587. package/dist/query-OzMJ6vJP.mjs +41 -0
  588. package/dist/query-OzMJ6vJP.mjs.map +1 -0
  589. package/dist/rate-limit-Csp60Vik.mjs +120 -0
  590. package/dist/rate-limit-Csp60Vik.mjs.map +1 -0
  591. package/dist/receipt-B-aU4hpJ.mjs +43 -0
  592. package/dist/receipt-B-aU4hpJ.mjs.map +1 -0
  593. package/dist/redirect-CDSw1sU3.mjs +17 -0
  594. package/dist/redirect-CDSw1sU3.mjs.map +1 -0
  595. package/dist/redirect-D1ArbO85.mjs +411 -0
  596. package/dist/redirect-D1ArbO85.mjs.map +1 -0
  597. package/dist/redirects-BjTwDTsV.mjs +148 -0
  598. package/dist/redirects-BjTwDTsV.mjs.map +1 -0
  599. package/dist/redirects-Ck50kH3n.mjs +446 -0
  600. package/dist/redirects-Ck50kH3n.mjs.map +1 -0
  601. package/dist/registry/testing.mjs +3 -3
  602. package/dist/registry-CFcNCayZ.mjs +6754 -0
  603. package/dist/registry-CFcNCayZ.mjs.map +1 -0
  604. package/dist/relations-Cfaa1fDl.mjs +776 -0
  605. package/dist/relations-Cfaa1fDl.mjs.map +1 -0
  606. package/dist/request-cache-iHRlHx1d.mjs +104 -0
  607. package/dist/request-cache-iHRlHx1d.mjs.map +1 -0
  608. package/dist/request-context.d.mts +1 -1
  609. package/dist/request-meta-D47mqyev.mjs +141 -0
  610. package/dist/request-meta-D47mqyev.mjs.map +1 -0
  611. package/dist/resolve-BPE8sMvx.mjs +99 -0
  612. package/dist/resolve-BPE8sMvx.mjs.map +1 -0
  613. package/dist/resolve-C0s1E_fH.mjs +199 -0
  614. package/dist/resolve-C0s1E_fH.mjs.map +1 -0
  615. package/dist/revision-j1p4-bOj.mjs +302 -0
  616. package/dist/revision-j1p4-bOj.mjs.map +1 -0
  617. package/dist/route-wire-C9PJV9aL.mjs +197 -0
  618. package/dist/route-wire-C9PJV9aL.mjs.map +1 -0
  619. package/dist/routes-lyYw0mMf.mjs +272 -0
  620. package/dist/routes-lyYw0mMf.mjs.map +1 -0
  621. package/dist/runner-B3eyB9Gb.mjs +6121 -0
  622. package/dist/runner-B3eyB9Gb.mjs.map +1 -0
  623. package/dist/runner-DoYH2Jcu.d.mts +68 -0
  624. package/dist/runner-DoYH2Jcu.d.mts.map +1 -0
  625. package/dist/runtime.d.mts +13 -13
  626. package/dist/runtime.mjs +3 -3
  627. package/dist/schema-BAayK46S.mjs +13 -0
  628. package/dist/schema-BAayK46S.mjs.map +1 -0
  629. package/dist/schema-Gqcl-8G4.mjs +815 -0
  630. package/dist/schema-Gqcl-8G4.mjs.map +1 -0
  631. package/dist/scopes-BqPOKoKf.mjs +34 -0
  632. package/dist/scopes-BqPOKoKf.mjs.map +1 -0
  633. package/dist/search-YJKPIEV6.mjs +448 -0
  634. package/dist/search-YJKPIEV6.mjs.map +1 -0
  635. package/dist/sections-BR_e-wK5.mjs +346 -0
  636. package/dist/sections-BR_e-wK5.mjs.map +1 -0
  637. package/dist/seed/index.d.mts +2 -2
  638. package/dist/seed/index.mjs +37 -31
  639. package/dist/seo/index.d.mts +3 -3
  640. package/dist/seo/index.mjs +22 -21
  641. package/dist/seo/index.mjs.map +1 -1
  642. package/dist/seo-Dsj8hy3j.mjs +114 -0
  643. package/dist/seo-Dsj8hy3j.mjs.map +1 -0
  644. package/dist/seo-XvH4LNNp.mjs +133 -0
  645. package/dist/seo-XvH4LNNp.mjs.map +1 -0
  646. package/dist/service-BsVG05gS.mjs +150 -0
  647. package/dist/service-BsVG05gS.mjs.map +1 -0
  648. package/dist/session-user-DgKbYrlj.mjs +51 -0
  649. package/dist/session-user-DgKbYrlj.mjs.map +1 -0
  650. package/dist/settings-CNPUntkh.mjs +51 -0
  651. package/dist/settings-CNPUntkh.mjs.map +1 -0
  652. package/dist/settings-D5EHi0Tk.mjs +439 -0
  653. package/dist/settings-D5EHi0Tk.mjs.map +1 -0
  654. package/dist/settings-DSfE7wOa.mjs +61 -0
  655. package/dist/settings-DSfE7wOa.mjs.map +1 -0
  656. package/dist/setup-complete-B8W8sJ9v.mjs +26 -0
  657. package/dist/setup-complete-B8W8sJ9v.mjs.map +1 -0
  658. package/dist/setup-nonce-DnSBP260.mjs +25 -0
  659. package/dist/setup-nonce-DnSBP260.mjs.map +1 -0
  660. package/dist/site-settings-NGzdrt7O.mjs +50 -0
  661. package/dist/site-settings-NGzdrt7O.mjs.map +1 -0
  662. package/dist/site-url-D6JB7tLW.mjs +16 -0
  663. package/dist/site-url-D6JB7tLW.mjs.map +1 -0
  664. package/dist/snapshot-CdcwwWAf.mjs +414 -0
  665. package/dist/snapshot-CdcwwWAf.mjs.map +1 -0
  666. package/dist/ssrf-Dv0_tRpo.mjs +406 -0
  667. package/dist/ssrf-Dv0_tRpo.mjs.map +1 -0
  668. package/dist/stage-CUjhED3P.mjs +662 -0
  669. package/dist/stage-CUjhED3P.mjs.map +1 -0
  670. package/dist/staged-C36IWXff.mjs +659 -0
  671. package/dist/staged-C36IWXff.mjs.map +1 -0
  672. package/dist/state-CKouMCSY.mjs +153 -0
  673. package/dist/state-CKouMCSY.mjs.map +1 -0
  674. package/dist/status-lzyj4Uu7.mjs +30 -0
  675. package/dist/status-lzyj4Uu7.mjs.map +1 -0
  676. package/dist/storage/local.d.mts +1 -1
  677. package/dist/storage/local.mjs +1 -1
  678. package/dist/storage/s3.d.mts +1 -1
  679. package/dist/storage/s3.mjs +1 -1
  680. package/dist/storage-query-B-cWcTjJ.d.mts +1594 -0
  681. package/dist/storage-query-B-cWcTjJ.d.mts.map +1 -0
  682. package/dist/tar-DsTXX6ch.mjs +449 -0
  683. package/dist/tar-DsTXX6ch.mjs.map +1 -0
  684. package/dist/target-DLQCwp_Z.mjs +27 -0
  685. package/dist/target-DLQCwp_Z.mjs.map +1 -0
  686. package/dist/taxonomies-BlAjr4BL.mjs +697 -0
  687. package/dist/taxonomies-BlAjr4BL.mjs.map +1 -0
  688. package/dist/taxonomies-Byyo7LOZ.mjs +939 -0
  689. package/dist/taxonomies-Byyo7LOZ.mjs.map +1 -0
  690. package/dist/taxonomy-CKDwM61Y.mjs +525 -0
  691. package/dist/taxonomy-CKDwM61Y.mjs.map +1 -0
  692. package/dist/tokens-BojXlk49.mjs +171 -0
  693. package/dist/tokens-BojXlk49.mjs.map +1 -0
  694. package/dist/transaction-DLPQWik1.mjs +29 -0
  695. package/dist/transaction-DLPQWik1.mjs.map +1 -0
  696. package/dist/transfer-XSTh2BCr.mjs +8706 -0
  697. package/dist/transfer-XSTh2BCr.mjs.map +1 -0
  698. package/dist/transfer-download-DkoCDA9d.mjs +33 -0
  699. package/dist/transfer-download-DkoCDA9d.mjs.map +1 -0
  700. package/dist/transfer-iQ26J-RT.mjs +166 -0
  701. package/dist/transfer-iQ26J-RT.mjs.map +1 -0
  702. package/dist/transformations-C7RQabKQ.mjs +196 -0
  703. package/dist/transformations-C7RQabKQ.mjs.map +1 -0
  704. package/dist/transport-D3RulfD6.mjs +136 -0
  705. package/dist/transport-D3RulfD6.mjs.map +1 -0
  706. package/dist/transport-DhlZlf4D.d.mts +42 -0
  707. package/dist/transport-DhlZlf4D.d.mts.map +1 -0
  708. package/dist/trusted-proxy-B6ECOZJc.mjs +51 -0
  709. package/dist/trusted-proxy-B6ECOZJc.mjs.map +1 -0
  710. package/dist/turnstile-lqUiY7lP.mjs +53 -0
  711. package/dist/turnstile-lqUiY7lP.mjs.map +1 -0
  712. package/dist/types-4Dn9bZhu.mjs +77 -0
  713. package/dist/types-4Dn9bZhu.mjs.map +1 -0
  714. package/dist/types-5LSo7PPx.d.mts +85 -0
  715. package/dist/types-5LSo7PPx.d.mts.map +1 -0
  716. package/dist/types-BQ3hwYJT.d.mts +896 -0
  717. package/dist/types-BQ3hwYJT.d.mts.map +1 -0
  718. package/dist/types-BYEk7qo3.d.mts +198 -0
  719. package/dist/types-BYEk7qo3.d.mts.map +1 -0
  720. package/dist/types-CJKsWVFR.mjs +199 -0
  721. package/dist/types-CJKsWVFR.mjs.map +1 -0
  722. package/dist/types-Ca_w8mmY.d.mts +363 -0
  723. package/dist/types-Ca_w8mmY.d.mts.map +1 -0
  724. package/dist/types-CkE41ZAG.mjs +18 -0
  725. package/dist/types-CkE41ZAG.mjs.map +1 -0
  726. package/dist/types-D0aJW2uR.d.mts +1641 -0
  727. package/dist/types-D0aJW2uR.d.mts.map +1 -0
  728. package/dist/types-DbpN4Qto.d.mts +372 -0
  729. package/dist/types-DbpN4Qto.d.mts.map +1 -0
  730. package/dist/types-ILDI1sdY.mjs +16 -0
  731. package/dist/types-ILDI1sdY.mjs.map +1 -0
  732. package/dist/types-OC5c-edM.mjs +22 -0
  733. package/dist/types-OC5c-edM.mjs.map +1 -0
  734. package/dist/types-aOOxRSx6.mjs +103 -0
  735. package/dist/types-aOOxRSx6.mjs.map +1 -0
  736. package/dist/types-m1WbUffD.d.mts +198 -0
  737. package/dist/types-m1WbUffD.d.mts.map +1 -0
  738. package/dist/types-uxLoPBio.d.mts +124 -0
  739. package/dist/types-uxLoPBio.d.mts.map +1 -0
  740. package/dist/types-we5uR-tV.d.mts +287 -0
  741. package/dist/types-we5uR-tV.d.mts.map +1 -0
  742. package/dist/upload-attempts-DduMy6B0.mjs +32 -0
  743. package/dist/upload-attempts-DduMy6B0.mjs.map +1 -0
  744. package/dist/url-pattern-B3EwxAAk.mjs +33 -0
  745. package/dist/url-pattern-B3EwxAAk.mjs.map +1 -0
  746. package/dist/user-ElwQjTQT.mjs +171 -0
  747. package/dist/user-ElwQjTQT.mjs.map +1 -0
  748. package/dist/utils-BlAXmfOG.mjs +439 -0
  749. package/dist/utils-BlAXmfOG.mjs.map +1 -0
  750. package/dist/validate-CH0X5b2c.d.mts +468 -0
  751. package/dist/validate-CH0X5b2c.d.mts.map +1 -0
  752. package/dist/validate-CfgRpcjA.mjs +492 -0
  753. package/dist/validate-CfgRpcjA.mjs.map +1 -0
  754. package/dist/validation-DvYJtv4k.mjs +218 -0
  755. package/dist/validation-DvYJtv4k.mjs.map +1 -0
  756. package/dist/version-DgYjhTud.mjs +9 -0
  757. package/dist/version-DgYjhTud.mjs.map +1 -0
  758. package/dist/version-Dq71scUb.mjs +7 -0
  759. package/dist/version-Dq71scUb.mjs.map +1 -0
  760. package/dist/widgets-ChFIj0be.mjs +126 -0
  761. package/dist/widgets-ChFIj0be.mjs.map +1 -0
  762. package/dist/wxr-taxonomies-CBZMp2YX.mjs +372 -0
  763. package/dist/wxr-taxonomies-CBZMp2YX.mjs.map +1 -0
  764. package/dist/wxr-taxonomies-DlKDpWN1.d.mts +34 -0
  765. package/dist/wxr-taxonomies-DlKDpWN1.d.mts.map +1 -0
  766. package/dist/zod-generator-DmTKI-Ig.mjs +426 -0
  767. package/dist/zod-generator-DmTKI-Ig.mjs.map +1 -0
  768. package/package.json +7 -6
  769. package/src/api/handlers/content.ts +593 -16
  770. package/src/api/handlers/device-flow.ts +74 -21
  771. package/src/api/handlers/manifest.ts +79 -5
  772. package/src/api/handlers/relations.ts +638 -157
  773. package/src/api/handlers/revision.ts +30 -0
  774. package/src/api/handlers/schema.ts +403 -1
  775. package/src/api/handlers/staged-references.ts +142 -0
  776. package/src/api/handlers/validate-references.ts +146 -0
  777. package/src/api/schemas/content.ts +13 -0
  778. package/src/api/schemas/relations.ts +54 -44
  779. package/src/api/schemas/schema.ts +14 -0
  780. package/src/astro/integration/routes.ts +15 -19
  781. package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +11 -54
  782. package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
  783. package/src/astro/routes/api/oauth/device/authorize.ts +33 -4
  784. package/src/astro/routes/api/relations/index.ts +4 -4
  785. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +6 -2
  786. package/src/astro/types.ts +5 -0
  787. package/src/cli/commands/export-seed.ts +510 -89
  788. package/src/components/WidgetArea.astro +3 -2
  789. package/src/database/migrations/086_relations_structural.ts +197 -0
  790. package/src/database/migrations/087_reference_field_relations.ts +407 -0
  791. package/src/database/migrations/runner.ts +4 -0
  792. package/src/database/reference-backfill.ts +141 -0
  793. package/src/database/repositories/content.ts +43 -8
  794. package/src/database/repositories/relation.ts +620 -208
  795. package/src/database/repositories/revision.ts +16 -0
  796. package/src/database/repositories/types.ts +38 -0
  797. package/src/database/transaction.ts +12 -1
  798. package/src/database/types.ts +14 -5
  799. package/src/emdash-runtime.ts +86 -11
  800. package/src/index.ts +10 -0
  801. package/src/loader.ts +169 -22
  802. package/src/query.ts +455 -25
  803. package/src/references/field-map.ts +115 -0
  804. package/src/references/resolve.ts +160 -0
  805. package/src/references/staged.ts +117 -0
  806. package/src/references/types.ts +16 -0
  807. package/src/registry/artifact-fetch.ts +45 -271
  808. package/src/schema/registry.ts +99 -24
  809. package/src/schema/types.ts +58 -0
  810. package/src/schema/zod-generator.ts +67 -1
  811. package/src/seed/apply.ts +519 -62
  812. package/src/seed/types.ts +36 -2
  813. package/src/seed/validate.ts +78 -2
  814. package/src/transfer/analyze/unique-keys.ts +3 -12
  815. package/src/transfer/analyze/validate.ts +65 -39
  816. package/src/transfer/analyze/values.ts +12 -1
  817. package/src/transfer/export/readers.ts +12 -8
  818. package/src/transfer/format/columns.ts +26 -6
  819. package/src/transfer/format/kinds.ts +21 -5
  820. package/src/transfer/import/context.ts +8 -1
  821. package/src/transfer/ops/package-index.ts +1 -1
  822. package/dist/action-token-DYwe4Pk0.mjs +0 -26
  823. package/dist/action-token-DYwe4Pk0.mjs.map +0 -1
  824. package/dist/activation-LOkDM5WT.mjs +0 -382
  825. package/dist/activation-LOkDM5WT.mjs.map +0 -1
  826. package/dist/adapters-B64LbYcB.d.mts +0 -171
  827. package/dist/adapters-B64LbYcB.d.mts.map +0 -1
  828. package/dist/allowed-origins-CHB8oZNM.mjs +0 -116
  829. package/dist/allowed-origins-CHB8oZNM.mjs.map +0 -1
  830. package/dist/api-CuyNEHZG.mjs +0 -4718
  831. package/dist/api-CuyNEHZG.mjs.map +0 -1
  832. package/dist/api-tokens-s4i4aUp_.mjs +0 -166
  833. package/dist/api-tokens-s4i4aUp_.mjs.map +0 -1
  834. package/dist/apply-npY1TAhG.mjs +0 -1366
  835. package/dist/apply-npY1TAhG.mjs.map +0 -1
  836. package/dist/approvals-CqMfNxak.mjs +0 -460
  837. package/dist/approvals-CqMfNxak.mjs.map +0 -1
  838. package/dist/artifact-fetch-DZMOGZ3-.mjs +0 -818
  839. package/dist/artifact-fetch-DZMOGZ3-.mjs.map +0 -1
  840. package/dist/astro/routes/api/relations/_id_/translations.d.mts +0 -8
  841. package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +0 -1
  842. package/dist/astro/routes/api/relations/_id_/translations.mjs +0 -47
  843. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +0 -1
  844. package/dist/audit-RfCugiSB.mjs +0 -127
  845. package/dist/audit-RfCugiSB.mjs.map +0 -1
  846. package/dist/authoritative-records-CoJvBXAD.mjs +0 -5172
  847. package/dist/authoritative-records-CoJvBXAD.mjs.map +0 -1
  848. package/dist/authorize-seCifOMJ.mjs +0 -49
  849. package/dist/authorize-seCifOMJ.mjs.map +0 -1
  850. package/dist/backup-BQRj3afm.mjs +0 -246
  851. package/dist/backup-BQRj3afm.mjs.map +0 -1
  852. package/dist/block-type-registry-DUI_3KxT.mjs +0 -6709
  853. package/dist/block-type-registry-DUI_3KxT.mjs.map +0 -1
  854. package/dist/block-types-BmZmLmAD.mjs +0 -132
  855. package/dist/block-types-BmZmLmAD.mjs.map +0 -1
  856. package/dist/block-values-C_VIPr5t.mjs +0 -175
  857. package/dist/block-values-C_VIPr5t.mjs.map +0 -1
  858. package/dist/byline-DYmkXqvo.mjs +0 -909
  859. package/dist/byline-DYmkXqvo.mjs.map +0 -1
  860. package/dist/byline-fields-D28AT-Fh.mjs +0 -123
  861. package/dist/byline-fields-D28AT-Fh.mjs.map +0 -1
  862. package/dist/byline-registry-gnKscbQX.mjs +0 -406
  863. package/dist/byline-registry-gnKscbQX.mjs.map +0 -1
  864. package/dist/bylines-BPwJqoYH.mjs +0 -232
  865. package/dist/bylines-BPwJqoYH.mjs.map +0 -1
  866. package/dist/bylines-ukLaYpVZ.mjs +0 -214
  867. package/dist/bylines-ukLaYpVZ.mjs.map +0 -1
  868. package/dist/cache-m7UEkRFV.mjs +0 -108
  869. package/dist/cache-m7UEkRFV.mjs.map +0 -1
  870. package/dist/canonical-YhEQezjg.mjs +0 -174
  871. package/dist/canonical-YhEQezjg.mjs.map +0 -1
  872. package/dist/capture-triggers-kJyl_yyM.mjs +0 -362
  873. package/dist/capture-triggers-kJyl_yyM.mjs.map +0 -1
  874. package/dist/challenge-store-ppU6Uv13.mjs +0 -51
  875. package/dist/challenge-store-ppU6Uv13.mjs.map +0 -1
  876. package/dist/checksum-B2IINIlN.mjs +0 -162
  877. package/dist/checksum-B2IINIlN.mjs.map +0 -1
  878. package/dist/chrome-tags-DApCQSIk.mjs +0 -24
  879. package/dist/chrome-tags-DApCQSIk.mjs.map +0 -1
  880. package/dist/chunks-Dms7Uxbt.mjs +0 -25
  881. package/dist/chunks-Dms7Uxbt.mjs.map +0 -1
  882. package/dist/collection-deletion-BIm28mo3.mjs +0 -436
  883. package/dist/collection-deletion-BIm28mo3.mjs.map +0 -1
  884. package/dist/collection-deletion-processor-Br6rxs3u.mjs +0 -217
  885. package/dist/collection-deletion-processor-Br6rxs3u.mjs.map +0 -1
  886. package/dist/collection-slugs-cache-CjGk__zp.mjs +0 -85
  887. package/dist/collection-slugs-cache-CjGk__zp.mjs.map +0 -1
  888. package/dist/comment-CrBl22OF.mjs +0 -313
  889. package/dist/comment-CrBl22OF.mjs.map +0 -1
  890. package/dist/comment-reaction-JEQ2Fpd8.mjs +0 -85
  891. package/dist/comment-reaction-JEQ2Fpd8.mjs.map +0 -1
  892. package/dist/comments-2ah9du9y.mjs +0 -195
  893. package/dist/comments-2ah9du9y.mjs.map +0 -1
  894. package/dist/comments-fHZ8ON9O.mjs +0 -99
  895. package/dist/comments-fHZ8ON9O.mjs.map +0 -1
  896. package/dist/components-CXbq7CSM.mjs +0 -108
  897. package/dist/components-CXbq7CSM.mjs.map +0 -1
  898. package/dist/config-BjEm_3xL.d.mts +0 -6537
  899. package/dist/config-BjEm_3xL.d.mts.map +0 -1
  900. package/dist/config-IhybvkIQ.mjs +0 -242
  901. package/dist/config-IhybvkIQ.mjs.map +0 -1
  902. package/dist/config-Py43JK9r.d.mts +0 -39
  903. package/dist/config-Py43JK9r.d.mts.map +0 -1
  904. package/dist/content-DFaIEDj9.mjs +0 -2281
  905. package/dist/content-DFaIEDj9.mjs.map +0 -1
  906. package/dist/content-list-query-Dra4Dalc.d.mts +0 -26
  907. package/dist/content-list-query-Dra4Dalc.d.mts.map +0 -1
  908. package/dist/content-policy-DFNw91-d.mjs +0 -46
  909. package/dist/content-policy-DFNw91-d.mjs.map +0 -1
  910. package/dist/content-repair-Q8IUrpLL.mjs +0 -442
  911. package/dist/content-repair-Q8IUrpLL.mjs.map +0 -1
  912. package/dist/context-BV_7t-Ua.mjs +0 -1921
  913. package/dist/context-BV_7t-Ua.mjs.map +0 -1
  914. package/dist/cron-7DCJwPXq.mjs +0 -284
  915. package/dist/cron-7DCJwPXq.mjs.map +0 -1
  916. package/dist/dashboard-BP-iJqpd.mjs +0 -151
  917. package/dist/dashboard-BP-iJqpd.mjs.map +0 -1
  918. package/dist/default-DQ6vsviu.mjs +0 -81
  919. package/dist/default-DQ6vsviu.mjs.map +0 -1
  920. package/dist/deferred-tasks-BPxXUB4x.d.mts +0 -9
  921. package/dist/deferred-tasks-BPxXUB4x.d.mts.map +0 -1
  922. package/dist/dev-typegen-CZaPLl3V.mjs +0 -29
  923. package/dist/dev-typegen-CZaPLl3V.mjs.map +0 -1
  924. package/dist/device-flow-CRd6DXmW.mjs +0 -466
  925. package/dist/device-flow-CRd6DXmW.mjs.map +0 -1
  926. package/dist/digest-BarSh-pN.mjs +0 -194
  927. package/dist/digest-BarSh-pN.mjs.map +0 -1
  928. package/dist/direct-executor-D2lNadwo.mjs +0 -104
  929. package/dist/direct-executor-D2lNadwo.mjs.map +0 -1
  930. package/dist/dist-BNwANFJR.mjs +0 -810
  931. package/dist/dist-BNwANFJR.mjs.map +0 -1
  932. package/dist/email-console-bJn3ctqA.mjs +0 -50
  933. package/dist/email-console-bJn3ctqA.mjs.map +0 -1
  934. package/dist/email-locale-CN6WAMx0.mjs +0 -25
  935. package/dist/email-locale-CN6WAMx0.mjs.map +0 -1
  936. package/dist/emdash-runtime-CtfnZmPi.mjs +0 -4186
  937. package/dist/emdash-runtime-CtfnZmPi.mjs.map +0 -1
  938. package/dist/enrich-Dl3kZ-lP.mjs +0 -194
  939. package/dist/enrich-Dl3kZ-lP.mjs.map +0 -1
  940. package/dist/entry-lock-BJYdBfXb.mjs +0 -1097
  941. package/dist/entry-lock-BJYdBfXb.mjs.map +0 -1
  942. package/dist/entry-lock-Cf5OoIgN.d.mts +0 -4368
  943. package/dist/entry-lock-Cf5OoIgN.d.mts.map +0 -1
  944. package/dist/entry-lock-DHQOxN7R.mjs +0 -163
  945. package/dist/entry-lock-DHQOxN7R.mjs.map +0 -1
  946. package/dist/entry-locks-D0foLdjQ.mjs +0 -167
  947. package/dist/entry-locks-D0foLdjQ.mjs.map +0 -1
  948. package/dist/error-CfvOHP0M.mjs +0 -90
  949. package/dist/error-CfvOHP0M.mjs.map +0 -1
  950. package/dist/errors-BF0_LFhW.mjs +0 -460
  951. package/dist/errors-BF0_LFhW.mjs.map +0 -1
  952. package/dist/errors-DgE1zJGG.mjs +0 -120
  953. package/dist/errors-DgE1zJGG.mjs.map +0 -1
  954. package/dist/escape-CuaZhZvL.mjs +0 -9
  955. package/dist/escape-CuaZhZvL.mjs.map +0 -1
  956. package/dist/fence-CMDXJYc_.mjs +0 -162
  957. package/dist/fence-CMDXJYc_.mjs.map +0 -1
  958. package/dist/field-defs-cache-HIgBbqZZ.mjs +0 -77
  959. package/dist/field-defs-cache-HIgBbqZZ.mjs.map +0 -1
  960. package/dist/focal-point-Gr34o-4o.mjs +0 -23
  961. package/dist/focal-point-Gr34o-4o.mjs.map +0 -1
  962. package/dist/fts-manager-S-K0laoS.mjs +0 -443
  963. package/dist/fts-manager-S-K0laoS.mjs.map +0 -1
  964. package/dist/gc-DjKY0Ay1.mjs +0 -75
  965. package/dist/gc-DjKY0Ay1.mjs.map +0 -1
  966. package/dist/hash-SDAW6zC-.mjs +0 -37
  967. package/dist/hash-SDAW6zC-.mjs.map +0 -1
  968. package/dist/hook-result-B5bXDgS2.d.mts +0 -31
  969. package/dist/hook-result-B5bXDgS2.d.mts.map +0 -1
  970. package/dist/hreflang-CbVI4paR.mjs +0 -105
  971. package/dist/hreflang-CbVI4paR.mjs.map +0 -1
  972. package/dist/hreflang-D5uNnsGJ.d.mts +0 -50
  973. package/dist/hreflang-D5uNnsGJ.d.mts.map +0 -1
  974. package/dist/http-route-dispatch-BitqzwMy.mjs +0 -339
  975. package/dist/http-route-dispatch-BitqzwMy.mjs.map +0 -1
  976. package/dist/identity-Be5kzutJ.mjs +0 -35
  977. package/dist/identity-Be5kzutJ.mjs.map +0 -1
  978. package/dist/import-YzfKCaco.mjs +0 -2020
  979. package/dist/import-YzfKCaco.mjs.map +0 -1
  980. package/dist/index-D-hdtLe8.d.mts +0 -623
  981. package/dist/index-D-hdtLe8.d.mts.map +0 -1
  982. package/dist/install-finalization-DfM1fj5x.mjs +0 -58
  983. package/dist/install-finalization-DfM1fj5x.mjs.map +0 -1
  984. package/dist/keys-yxLm5l35.mjs +0 -61
  985. package/dist/keys-yxLm5l35.mjs.map +0 -1
  986. package/dist/kinds-CRu_T5T5.mjs +0 -961
  987. package/dist/kinds-CRu_T5T5.mjs.map +0 -1
  988. package/dist/lifecycle-BzeGPeQ-.mjs +0 -25
  989. package/dist/lifecycle-BzeGPeQ-.mjs.map +0 -1
  990. package/dist/load-XgJiE6_3.mjs +0 -28
  991. package/dist/load-XgJiE6_3.mjs.map +0 -1
  992. package/dist/loader-BzqeR1ZN.mjs +0 -1086
  993. package/dist/loader-BzqeR1ZN.mjs.map +0 -1
  994. package/dist/loops-BQSzv5Zn.mjs +0 -203
  995. package/dist/loops-BQSzv5Zn.mjs.map +0 -1
  996. package/dist/manifest-builder-BmSAOOEF.mjs +0 -189
  997. package/dist/manifest-builder-BmSAOOEF.mjs.map +0 -1
  998. package/dist/manifest-schema-CY3zng_M.mjs +0 -492
  999. package/dist/manifest-schema-CY3zng_M.mjs.map +0 -1
  1000. package/dist/media-CPXTbb1R.mjs +0 -373
  1001. package/dist/media-CPXTbb1R.mjs.map +0 -1
  1002. package/dist/media-JXRWDhw3.mjs +0 -294
  1003. package/dist/media-JXRWDhw3.mjs.map +0 -1
  1004. package/dist/media-Pu1L6xir.mjs +0 -408
  1005. package/dist/media-Pu1L6xir.mjs.map +0 -1
  1006. package/dist/media-allowlist-BSoa9Vvm.mjs +0 -44
  1007. package/dist/media-allowlist-BSoa9Vvm.mjs.map +0 -1
  1008. package/dist/media-folders-BE0oo2eX.mjs +0 -210
  1009. package/dist/media-folders-BE0oo2eX.mjs.map +0 -1
  1010. package/dist/media-url-jArBpzIG.mjs +0 -43
  1011. package/dist/media-url-jArBpzIG.mjs.map +0 -1
  1012. package/dist/media-usage-De-zeR9E.mjs +0 -1629
  1013. package/dist/media-usage-De-zeR9E.mjs.map +0 -1
  1014. package/dist/media-usage-activation-HKp7zk7W.mjs +0 -78
  1015. package/dist/media-usage-activation-HKp7zk7W.mjs.map +0 -1
  1016. package/dist/media-usage-work-C2OZLCAd.mjs +0 -586
  1017. package/dist/media-usage-work-C2OZLCAd.mjs.map +0 -1
  1018. package/dist/media-usage-work-DwUNbgvS.mjs +0 -152
  1019. package/dist/media-usage-work-DwUNbgvS.mjs.map +0 -1
  1020. package/dist/menus-BM7BPLOb.mjs +0 -139
  1021. package/dist/menus-BM7BPLOb.mjs.map +0 -1
  1022. package/dist/menus-Cm68rsAq.mjs +0 -3608
  1023. package/dist/menus-Cm68rsAq.mjs.map +0 -1
  1024. package/dist/menus-ITeAbcIF.mjs +0 -753
  1025. package/dist/menus-ITeAbcIF.mjs.map +0 -1
  1026. package/dist/mime-ChLqYwDk.mjs +0 -36
  1027. package/dist/mime-ChLqYwDk.mjs.map +0 -1
  1028. package/dist/mode-CCuKXUci.mjs +0 -23
  1029. package/dist/mode-CCuKXUci.mjs.map +0 -1
  1030. package/dist/node-sqlite-compat-CONMsl-x.mjs +0 -46
  1031. package/dist/node-sqlite-compat-CONMsl-x.mjs.map +0 -1
  1032. package/dist/normalize-CO2P8-iE.mjs +0 -191
  1033. package/dist/normalize-CO2P8-iE.mjs.map +0 -1
  1034. package/dist/oauth-authorization-DlMIL5_h.mjs +0 -274
  1035. package/dist/oauth-authorization-DlMIL5_h.mjs.map +0 -1
  1036. package/dist/oauth-clients-Djq9r_KP.mjs +0 -266
  1037. package/dist/oauth-clients-Djq9r_KP.mjs.map +0 -1
  1038. package/dist/oauth-state-store-BbjnZXNC.mjs +0 -50
  1039. package/dist/oauth-state-store-BbjnZXNC.mjs.map +0 -1
  1040. package/dist/oauth-user-lookup-vue9a64A.mjs +0 -26
  1041. package/dist/oauth-user-lookup-vue9a64A.mjs.map +0 -1
  1042. package/dist/options-SQCHQCPH.d.mts +0 -81
  1043. package/dist/options-SQCHQCPH.d.mts.map +0 -1
  1044. package/dist/parse-CVgO-Qai.d.mts +0 -168
  1045. package/dist/parse-CVgO-Qai.d.mts.map +0 -1
  1046. package/dist/parse-DY6OD1j_.mjs +0 -81
  1047. package/dist/parse-DY6OD1j_.mjs.map +0 -1
  1048. package/dist/passkey-config-X_H8128a.mjs +0 -46
  1049. package/dist/passkey-config-X_H8128a.mjs.map +0 -1
  1050. package/dist/paths-JxokKIbr.mjs +0 -77
  1051. package/dist/paths-JxokKIbr.mjs.map +0 -1
  1052. package/dist/patterns-BhAvqO0S.mjs +0 -145
  1053. package/dist/patterns-BhAvqO0S.mjs.map +0 -1
  1054. package/dist/placeholder-MSEd8gty.d.mts +0 -306
  1055. package/dist/placeholder-MSEd8gty.d.mts.map +0 -1
  1056. package/dist/plan-xjcWrAah.mjs +0 -135
  1057. package/dist/plan-xjcWrAah.mjs.map +0 -1
  1058. package/dist/plugins-DUXUt8B9.mjs +0 -277
  1059. package/dist/plugins-DUXUt8B9.mjs.map +0 -1
  1060. package/dist/policy-CUvwAARc.mjs +0 -45
  1061. package/dist/policy-CUvwAARc.mjs.map +0 -1
  1062. package/dist/portable-text-5O_ZGUjB.mjs +0 -307
  1063. package/dist/portable-text-5O_ZGUjB.mjs.map +0 -1
  1064. package/dist/preview-CIUcPYr6.mjs +0 -107
  1065. package/dist/preview-CIUcPYr6.mjs.map +0 -1
  1066. package/dist/protocol-B97DZaFr.d.mts +0 -61
  1067. package/dist/protocol-B97DZaFr.d.mts.map +0 -1
  1068. package/dist/public-submission-BFBUrqst.mjs +0 -250
  1069. package/dist/public-submission-BFBUrqst.mjs.map +0 -1
  1070. package/dist/public-url-Bn7U0D7-.mjs +0 -101
  1071. package/dist/public-url-Bn7U0D7-.mjs.map +0 -1
  1072. package/dist/query-B48peoRT.mjs +0 -890
  1073. package/dist/query-B48peoRT.mjs.map +0 -1
  1074. package/dist/query-C4IH0uhR.mjs +0 -41
  1075. package/dist/query-C4IH0uhR.mjs.map +0 -1
  1076. package/dist/rate-limit-BZ6nybgc.mjs +0 -120
  1077. package/dist/rate-limit-BZ6nybgc.mjs.map +0 -1
  1078. package/dist/receipt-B4wJj5Jq.mjs +0 -43
  1079. package/dist/receipt-B4wJj5Jq.mjs.map +0 -1
  1080. package/dist/redirect-B29UjdUn.mjs +0 -411
  1081. package/dist/redirect-B29UjdUn.mjs.map +0 -1
  1082. package/dist/redirect-Cd1E7VUt.mjs +0 -17
  1083. package/dist/redirect-Cd1E7VUt.mjs.map +0 -1
  1084. package/dist/redirects-Ca2MPfEG.mjs +0 -446
  1085. package/dist/redirects-Ca2MPfEG.mjs.map +0 -1
  1086. package/dist/redirects-Cv9apQKj.mjs +0 -148
  1087. package/dist/redirects-Cv9apQKj.mjs.map +0 -1
  1088. package/dist/relation-M4NUCb0b.mjs +0 -334
  1089. package/dist/relation-M4NUCb0b.mjs.map +0 -1
  1090. package/dist/relations-CCif47Oq.mjs +0 -403
  1091. package/dist/relations-CCif47Oq.mjs.map +0 -1
  1092. package/dist/relations-CK9CYUyr.mjs +0 -310
  1093. package/dist/relations-CK9CYUyr.mjs.map +0 -1
  1094. package/dist/request-cache-DzLYKm_x.mjs +0 -104
  1095. package/dist/request-cache-DzLYKm_x.mjs.map +0 -1
  1096. package/dist/request-meta-sZXt3sRo.mjs +0 -141
  1097. package/dist/request-meta-sZXt3sRo.mjs.map +0 -1
  1098. package/dist/resolve-2WbQsCvT.mjs +0 -199
  1099. package/dist/resolve-2WbQsCvT.mjs.map +0 -1
  1100. package/dist/route-wire--1hLuACz.mjs +0 -197
  1101. package/dist/route-wire--1hLuACz.mjs.map +0 -1
  1102. package/dist/routes-vrR95WR6.mjs +0 -272
  1103. package/dist/routes-vrR95WR6.mjs.map +0 -1
  1104. package/dist/runner-1y4J9fJB.mjs +0 -5742
  1105. package/dist/runner-1y4J9fJB.mjs.map +0 -1
  1106. package/dist/runner-D5_LzKXI.d.mts +0 -68
  1107. package/dist/runner-D5_LzKXI.d.mts.map +0 -1
  1108. package/dist/schema-BABiRdsH.mjs +0 -13
  1109. package/dist/schema-BABiRdsH.mjs.map +0 -1
  1110. package/dist/schema-Du3MzCG0.mjs +0 -446
  1111. package/dist/schema-Du3MzCG0.mjs.map +0 -1
  1112. package/dist/scopes-Dbk-ElhT.mjs +0 -34
  1113. package/dist/scopes-Dbk-ElhT.mjs.map +0 -1
  1114. package/dist/search-Bt1PL1jf.mjs +0 -448
  1115. package/dist/search-Bt1PL1jf.mjs.map +0 -1
  1116. package/dist/sections-Ddptx_o9.mjs +0 -346
  1117. package/dist/sections-Ddptx_o9.mjs.map +0 -1
  1118. package/dist/seo-CZT2oLtT.mjs +0 -114
  1119. package/dist/seo-CZT2oLtT.mjs.map +0 -1
  1120. package/dist/seo-D5w3-Azy.mjs +0 -133
  1121. package/dist/seo-D5w3-Azy.mjs.map +0 -1
  1122. package/dist/service-DuykXPyW.mjs +0 -150
  1123. package/dist/service-DuykXPyW.mjs.map +0 -1
  1124. package/dist/session-user-BhaVp8w0.mjs +0 -51
  1125. package/dist/session-user-BhaVp8w0.mjs.map +0 -1
  1126. package/dist/settings-B4vDl1fK.mjs +0 -439
  1127. package/dist/settings-B4vDl1fK.mjs.map +0 -1
  1128. package/dist/settings-DYidIB26.mjs +0 -61
  1129. package/dist/settings-DYidIB26.mjs.map +0 -1
  1130. package/dist/settings-Dyj6v8C4.mjs +0 -51
  1131. package/dist/settings-Dyj6v8C4.mjs.map +0 -1
  1132. package/dist/setup-complete-bOogcHWG.mjs +0 -26
  1133. package/dist/setup-complete-bOogcHWG.mjs.map +0 -1
  1134. package/dist/setup-nonce-0EGuKM4s.mjs +0 -25
  1135. package/dist/setup-nonce-0EGuKM4s.mjs.map +0 -1
  1136. package/dist/site-settings-DOgRUoFX.mjs +0 -50
  1137. package/dist/site-settings-DOgRUoFX.mjs.map +0 -1
  1138. package/dist/site-url-BU_bbxwj.mjs +0 -16
  1139. package/dist/site-url-BU_bbxwj.mjs.map +0 -1
  1140. package/dist/snapshot-PawoX-WG.mjs +0 -414
  1141. package/dist/snapshot-PawoX-WG.mjs.map +0 -1
  1142. package/dist/ssrf-CJUnJymJ.mjs +0 -406
  1143. package/dist/ssrf-CJUnJymJ.mjs.map +0 -1
  1144. package/dist/stage-DgrBz_du.mjs +0 -662
  1145. package/dist/stage-DgrBz_du.mjs.map +0 -1
  1146. package/dist/state-DDiPySSG.mjs +0 -153
  1147. package/dist/state-DDiPySSG.mjs.map +0 -1
  1148. package/dist/status-DZKIG4a9.mjs +0 -30
  1149. package/dist/status-DZKIG4a9.mjs.map +0 -1
  1150. package/dist/storage-query-FXJH5pI8.d.mts +0 -1581
  1151. package/dist/storage-query-FXJH5pI8.d.mts.map +0 -1
  1152. package/dist/tar-_1AgTYFu.mjs +0 -449
  1153. package/dist/tar-_1AgTYFu.mjs.map +0 -1
  1154. package/dist/target-_7pn2Gbg.mjs +0 -27
  1155. package/dist/target-_7pn2Gbg.mjs.map +0 -1
  1156. package/dist/taxonomies-C1IwNe8Q.mjs +0 -697
  1157. package/dist/taxonomies-C1IwNe8Q.mjs.map +0 -1
  1158. package/dist/taxonomies-C_XMoRcX.mjs +0 -939
  1159. package/dist/taxonomies-C_XMoRcX.mjs.map +0 -1
  1160. package/dist/taxonomy-C3Fu1YeH.mjs +0 -525
  1161. package/dist/taxonomy-C3Fu1YeH.mjs.map +0 -1
  1162. package/dist/tokens-u78jETkX.mjs +0 -171
  1163. package/dist/tokens-u78jETkX.mjs.map +0 -1
  1164. package/dist/transaction-BcJO4Tmc.mjs +0 -29
  1165. package/dist/transaction-BcJO4Tmc.mjs.map +0 -1
  1166. package/dist/transfer-DIGvR9Af.mjs +0 -166
  1167. package/dist/transfer-DIGvR9Af.mjs.map +0 -1
  1168. package/dist/transfer-DgeCvHnj.mjs +0 -8675
  1169. package/dist/transfer-DgeCvHnj.mjs.map +0 -1
  1170. package/dist/transfer-download-Pml7RMio.mjs +0 -33
  1171. package/dist/transfer-download-Pml7RMio.mjs.map +0 -1
  1172. package/dist/transformations-9gfpwY65.mjs +0 -196
  1173. package/dist/transformations-9gfpwY65.mjs.map +0 -1
  1174. package/dist/transport-BIfH7_hx.d.mts +0 -42
  1175. package/dist/transport-BIfH7_hx.d.mts.map +0 -1
  1176. package/dist/transport-DKWIq53q.mjs +0 -136
  1177. package/dist/transport-DKWIq53q.mjs.map +0 -1
  1178. package/dist/trusted-proxy-tKiVtyTD.mjs +0 -51
  1179. package/dist/trusted-proxy-tKiVtyTD.mjs.map +0 -1
  1180. package/dist/turnstile-DpsoyOfg.mjs +0 -53
  1181. package/dist/turnstile-DpsoyOfg.mjs.map +0 -1
  1182. package/dist/types-B4sUC2p1.d.mts +0 -198
  1183. package/dist/types-B4sUC2p1.d.mts.map +0 -1
  1184. package/dist/types-B7Lmsh1E.d.mts +0 -887
  1185. package/dist/types-B7Lmsh1E.d.mts.map +0 -1
  1186. package/dist/types-BZakh7Ym.mjs +0 -22
  1187. package/dist/types-BZakh7Ym.mjs.map +0 -1
  1188. package/dist/types-B_CppEmv.d.mts +0 -264
  1189. package/dist/types-B_CppEmv.d.mts.map +0 -1
  1190. package/dist/types-BcrBrE6-.mjs +0 -159
  1191. package/dist/types-BcrBrE6-.mjs.map +0 -1
  1192. package/dist/types-BkUg2yHx.mjs +0 -92
  1193. package/dist/types-BkUg2yHx.mjs.map +0 -1
  1194. package/dist/types-CAZgq9fO.d.mts +0 -124
  1195. package/dist/types-CAZgq9fO.d.mts.map +0 -1
  1196. package/dist/types-Cd-O03VG.d.mts +0 -363
  1197. package/dist/types-Cd-O03VG.d.mts.map +0 -1
  1198. package/dist/types-Cr-Kg-3D.d.mts +0 -1641
  1199. package/dist/types-Cr-Kg-3D.d.mts.map +0 -1
  1200. package/dist/types-D2fvWd1i.d.mts +0 -359
  1201. package/dist/types-D2fvWd1i.d.mts.map +0 -1
  1202. package/dist/types-D7HUsguf.mjs +0 -77
  1203. package/dist/types-D7HUsguf.mjs.map +0 -1
  1204. package/dist/types-DA1Te3Oy.d.mts +0 -198
  1205. package/dist/types-DA1Te3Oy.d.mts.map +0 -1
  1206. package/dist/types-DhV6Q5bP.mjs +0 -18
  1207. package/dist/types-DhV6Q5bP.mjs.map +0 -1
  1208. package/dist/types-DnnVSl6Y.d.mts +0 -85
  1209. package/dist/types-DnnVSl6Y.d.mts.map +0 -1
  1210. package/dist/types-VT4-BugW.mjs +0 -16
  1211. package/dist/types-VT4-BugW.mjs.map +0 -1
  1212. package/dist/upload-attempts-B68ZGNu9.mjs +0 -32
  1213. package/dist/upload-attempts-B68ZGNu9.mjs.map +0 -1
  1214. package/dist/url-pattern-CCeZMGOh.mjs +0 -33
  1215. package/dist/url-pattern-CCeZMGOh.mjs.map +0 -1
  1216. package/dist/user-DDSL-sGw.mjs +0 -171
  1217. package/dist/user-DDSL-sGw.mjs.map +0 -1
  1218. package/dist/utils-DdhmO9w9.mjs +0 -439
  1219. package/dist/utils-DdhmO9w9.mjs.map +0 -1
  1220. package/dist/validate-CHosPEhs.mjs +0 -453
  1221. package/dist/validate-CHosPEhs.mjs.map +0 -1
  1222. package/dist/validate-CM79QXYE.d.mts +0 -432
  1223. package/dist/validate-CM79QXYE.d.mts.map +0 -1
  1224. package/dist/validation-BFecQczG.mjs +0 -218
  1225. package/dist/validation-BFecQczG.mjs.map +0 -1
  1226. package/dist/version-BRZXVifl.mjs +0 -9
  1227. package/dist/version-BRZXVifl.mjs.map +0 -1
  1228. package/dist/version-DXsxRrob.mjs +0 -7
  1229. package/dist/version-DXsxRrob.mjs.map +0 -1
  1230. package/dist/widgets-WdV72brA.mjs +0 -126
  1231. package/dist/widgets-WdV72brA.mjs.map +0 -1
  1232. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts +0 -34
  1233. package/dist/wxr-taxonomies-BHTdqkmZ.d.mts.map +0 -1
  1234. package/dist/wxr-taxonomies-DP6ESgMN.mjs +0 -372
  1235. package/dist/wxr-taxonomies-DP6ESgMN.mjs.map +0 -1
  1236. package/dist/zod-generator-D6uE4WiS.mjs +0 -389
  1237. package/dist/zod-generator-D6uE4WiS.mjs.map +0 -1
  1238. package/src/astro/routes/api/relations/[id]/translations.ts +0 -33
  1239. /package/dist/{api-tokens-CE1ECIg0.mjs → api-tokens-FaG1zPsj.mjs} +0 -0
  1240. /package/dist/{ssrf-DpBH7aOt.mjs → ssrf-DZOt8Qof.mjs} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-CFcNCayZ.mjs","names":["canonicalize","isRecord","SLUG_PATTERN","MAX_SLUG_LENGTH","MAX_LABEL_LENGTH","BLOCK_FIELD_TYPE_SET","assertLabel","REPEATER_SUB_FIELD_TYPE_SET","isRecord","isRecord","isRecord","readString","isRecord","canonicalJson"],"sources":["../src/media/usage/projection-fingerprint.ts","../src/media/usage/types.ts","../src/database/json-recordset.ts","../src/database/repositories/media-usage.ts","../src/media/usage/schema-invalidation.ts","../src/schema/block-types.ts","../src/schema/block-type-contract.ts","../src/schema/block-type-registry.ts","../src/media/usage/content-fields.ts","../src/media/usage/extractor.ts","../src/media/usage/source-key.ts","../src/media/usage/content-snapshots.ts","../src/media/usage/content-refresh.ts","../src/transfer/format/columns.ts","../src/transfer/format/column-codec.ts","../src/transfer/import/rows.ts","../src/transfer/import/sql.ts","../src/schema/registry.ts"],"sourcesContent":["import type {\n\tMediaUsageOccurrenceInput,\n\tMediaUsageSourceInput,\n} from \"../../database/repositories/media-usage.js\";\nimport type { MediaUsageExtractionField } from \"./types.js\";\n\nexport const MEDIA_USAGE_PROJECTION_FINGERPRINT_VERSION = 1;\nconst FINGERPRINT_PREFIX = `media-usage-projection:v${MEDIA_USAGE_PROJECTION_FINGERPRINT_VERSION}:sha256:`;\nconst FINGERPRINT_PATTERN = new RegExp(`^${FINGERPRINT_PREFIX}[a-f0-9]{64}$`);\n\nexport interface MediaUsageProjectionFingerprintInput {\n\tcollectionId: string;\n\tsource: MediaUsageSourceInput;\n\toccurrences: readonly MediaUsageOccurrenceInput[];\n\textractionFields: readonly MediaUsageExtractionField[];\n}\n\nexport interface MediaUsageProjectionFingerprint {\n\tfingerprint: string;\n\tbyteLength: number;\n}\n\nexport async function buildMediaUsageProjectionFingerprint(\n\tinput: MediaUsageProjectionFingerprintInput,\n): Promise<MediaUsageProjectionFingerprint> {\n\tif (!input.collectionId) {\n\t\tthrow new Error(\"Media usage projection fingerprints require a collection identity\");\n\t}\n\tconst canonicalOccurrences = input.occurrences\n\t\t.map((occurrence) => ({\n\t\t\tfieldSlug: occurrence.fieldSlug,\n\t\t\tfieldPath: occurrence.fieldPath,\n\t\t\toccurrenceIndex: occurrence.occurrenceIndex ?? 0,\n\t\t\treferenceType: occurrence.referenceType,\n\t\t\tmediaId: occurrence.mediaId,\n\t\t\tprovider: occurrence.provider,\n\t\t\tproviderAssetId: occurrence.providerAssetId,\n\t\t\tmediaKind: occurrence.mediaKind ?? null,\n\t\t\tmimeType: occurrence.mimeType ?? null,\n\t\t}))\n\t\t.map((occurrence) => ({ occurrence, key: canonicalJson(occurrence) }))\n\t\t.toSorted((a, b) => compareCanonicalStrings(a.key, b.key))\n\t\t.map(({ occurrence }) => occurrence);\n\treturn buildCanonicalSha256Fingerprint(FINGERPRINT_PREFIX, {\n\t\tfingerprintVersion: MEDIA_USAGE_PROJECTION_FINGERPRINT_VERSION,\n\t\tcollectionId: input.collectionId,\n\t\textractionSchema: normalizeExtractionFields(input.extractionFields),\n\t\tsource: {\n\t\t\tsourceKey: input.source.sourceKey,\n\t\t\tsourceType: input.source.sourceType,\n\t\t\tcollectionSlug: input.source.collectionSlug ?? null,\n\t\t\tcontentId: input.source.contentId ?? null,\n\t\t\tsourceVariant: input.source.sourceVariant,\n\t\t\tlocale: input.source.locale ?? null,\n\t\t\ttranslationGroup: input.source.translationGroup ?? null,\n\t\t\tcontentSlug: input.source.contentSlug ?? null,\n\t\t\tcontentTitle: input.source.contentTitle ?? null,\n\t\t\tcontentStatus: input.source.contentStatus ?? null,\n\t\t\tcontentScheduledAt: input.source.contentScheduledAt ?? null,\n\t\t\tcontentDeletedAt: input.source.contentDeletedAt ?? null,\n\t\t\trevisionId: input.source.revisionId ?? null,\n\t\t\tschemaVersion: input.source.schemaVersion ?? 1,\n\t\t\tsourceCompleteness: input.source.sourceCompleteness ?? \"complete\",\n\t\t},\n\t\toccurrences: canonicalOccurrences,\n\t});\n}\n\nexport async function buildCanonicalSha256Fingerprint(\n\tprefix: string,\n\tpayload: unknown,\n): Promise<MediaUsageProjectionFingerprint> {\n\tconst encodedPayload = new TextEncoder().encode(canonicalJson(payload));\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", encodedPayload);\n\tconst hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\n\t\t\"\",\n\t);\n\treturn {\n\t\tfingerprint: `${prefix}${hex}`,\n\t\tbyteLength: encodedPayload.byteLength,\n\t};\n}\n\nfunction normalizeExtractionFields(\n\tfields: readonly MediaUsageExtractionField[],\n): Record<string, unknown>[] {\n\treturn fields\n\t\t.map((field) => {\n\t\t\tif (field.type === \"blocks\") {\n\t\t\t\treturn {\n\t\t\t\t\tslug: field.slug,\n\t\t\t\t\ttype: field.type,\n\t\t\t\t\tblockTypes: (field.blockTypes ?? []).map((type) => ({\n\t\t\t\t\t\tslug: type.slug,\n\t\t\t\t\t\tcurrentVersion: type.currentVersion,\n\t\t\t\t\t\tversions: type.versions.map((version) => ({\n\t\t\t\t\t\t\tversion: version.version,\n\t\t\t\t\t\t\tfingerprint: version.fingerprint,\n\t\t\t\t\t\t})),\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (field.type !== \"repeater\") return { slug: field.slug, type: field.type };\n\t\t\treturn {\n\t\t\t\tslug: field.slug,\n\t\t\t\ttype: field.type,\n\t\t\t\tsubFields: (field.validation?.subFields ?? [])\n\t\t\t\t\t.map((subField) => ({ slug: subField.slug, type: subField.type }))\n\t\t\t\t\t.toSorted((a, b) => compareCanonicalStrings(a.slug, b.slug)),\n\t\t\t};\n\t\t})\n\t\t.toSorted((a, b) => compareCanonicalStrings(String(a.slug), String(b.slug)));\n}\n\nfunction compareCanonicalStrings(a: string, b: string): number {\n\treturn a < b ? -1 : a > b ? 1 : 0;\n}\n\nexport function isMediaUsageProjectionFingerprint(value: string | null | undefined): boolean {\n\treturn typeof value === \"string\" && FINGERPRINT_PATTERN.test(value);\n}\n\nfunction canonicalJson(value: unknown): string {\n\treturn JSON.stringify(canonicalize(value));\n}\n\nfunction canonicalize(value: unknown): unknown {\n\tif (value === undefined) return null;\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n\tif (Array.isArray(value)) return value.map((item) => canonicalize(item));\n\tif (!isRecord(value)) return value;\n\n\tconst canonical: Record<string, unknown> = {};\n\tfor (const key of Object.keys(value).toSorted()) {\n\t\tcanonical[key] = canonicalize(value[key]);\n\t}\n\treturn canonical;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { BlockType } from \"../../schema/block-types.js\";\nimport type { FieldType } from \"../../schema/types.js\";\n\nexport const CONTENT_SOURCE_SCHEMA_VERSION = 2;\n\nexport type MediaKind =\n\t| \"image\"\n\t| \"video\"\n\t| \"audio\"\n\t| \"document\"\n\t| \"archive\"\n\t| \"font\"\n\t| \"text\"\n\t| \"other\";\n\nexport type MediaUsageReferenceType = \"image_field\" | \"file_field\" | \"portable_text_image\";\n\nexport interface MediaUsageExtractionSubField {\n\tslug: string;\n\ttype: FieldType;\n\tlabel?: string;\n}\n\nexport interface MediaUsageExtractionValidation {\n\tsubFields?: readonly MediaUsageExtractionSubField[];\n}\n\nexport interface MediaUsageExtractionField {\n\tslug: string;\n\ttype: FieldType;\n\tvalidation?: MediaUsageExtractionValidation | null;\n\tblockTypes?: readonly BlockType[];\n}\n\nexport interface ExtractMediaUsageOccurrencesInput {\n\tfields: readonly MediaUsageExtractionField[];\n\tdata: Record<string, unknown>;\n}\n\nexport interface ExtractedMediaUsageOccurrence {\n\tfieldSlug: string;\n\tfieldPath: string;\n\toccurrenceIndex: number;\n\treferenceType: MediaUsageReferenceType;\n\tmediaId: string | null;\n\tprovider: string;\n\tproviderAssetId: string;\n\tmediaKind: MediaKind | null;\n\tmimeType: string | null;\n}\n","import { sql, type Kysely, type RawBuilder } from \"kysely\";\n\nimport { isPostgres } from \"./dialect-helpers.js\";\nimport type { Database } from \"./types.js\";\n\nexport function jsonTextValues(\n\tdb: Kysely<Database>,\n\tvalues: readonly string[],\n): RawBuilder<{ value: string }> {\n\tconst payload = JSON.stringify([...new Set(values)]);\n\treturn isPostgres(db)\n\t\t? sql<{\n\t\t\t\tvalue: string;\n\t\t\t}>`SELECT value::text AS value FROM jsonb_array_elements_text(${payload}::jsonb) AS value`\n\t\t: sql<{ value: string }>`SELECT value AS value FROM json_each(${payload})`;\n}\n","import {\n\tsql,\n\ttype ExpressionBuilder,\n\ttype Kysely,\n\ttype RawBuilder,\n\ttype Selectable,\n\ttype Transaction,\n\ttype Updateable,\n} from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport {\n\tMEDIA_USAGE_ACTIVATION_RUNTIME_GENERATION,\n\tMediaUsageActivationVersionMismatchError,\n} from \"../../media/usage/activation.js\";\nimport { isMediaUsageProjectionFingerprint } from \"../../media/usage/projection-fingerprint.js\";\nimport type { MediaUsageContentSourceVariant } from \"../../media/usage/source-key.js\";\nimport {\n\tCONTENT_SOURCE_SCHEMA_VERSION,\n\ttype MediaKind,\n\ttype MediaUsageReferenceType,\n} from \"../../media/usage/types.js\";\nimport { getRequestContext } from \"../../request-context.js\";\nimport { chunks, SQL_BATCH_SIZE } from \"../../utils/chunks.js\";\nimport { isPostgres } from \"../dialect-helpers.js\";\nimport { jsonTextValues } from \"../json-recordset.js\";\nimport { withTransaction } from \"../transaction.js\";\nimport type {\n\tDatabase,\n\tMediaUsageIndexStatusTable,\n\tMediaUsageSourceTable,\n\tMediaUsageTable,\n} from \"../types.js\";\nimport { validateIdentifier } from \"../validate.js\";\nimport { decodeCursor, encodeCursor, InvalidCursorError, type FindManyResult } from \"./types.js\";\n\ntype DatabaseExecutor = Kysely<Database> | Transaction<Database>;\ntype MediaUsageSourceNullableStringColumn =\n\t| \"collection_id\"\n\t| \"source_fingerprint\"\n\t| \"source_updated_at\"\n\t| \"revision_id\"\n\t| \"updated_at\"\n\t| \"last_attempted_at\"\n\t| \"last_error_code\";\ntype BatchSourceExpectedColumn =\n\t| \"source.collection_id\"\n\t| \"source.source_fingerprint\"\n\t| \"source.source_updated_at\"\n\t| \"source.source_version\"\n\t| \"source.identity_version\"\n\t| \"source.revision_id\"\n\t| \"source.last_attempted_at\"\n\t| \"source.last_error_code\";\ntype BatchInputExpectedColumn =\n\t| \"input.expected_collection_id\"\n\t| \"input.expected_source_fingerprint\"\n\t| \"input.expected_source_updated_at\"\n\t| \"input.expected_source_version\"\n\t| \"input.expected_identity_version\"\n\t| \"input.expected_revision_id\"\n\t| \"input.expected_last_attempted_at\"\n\t| \"input.expected_last_error_code\";\nconst OCCURRENCE_BIND_COLUMNS = 13;\nconst D1_MAX_BOUND_PARAMETERS = 100;\nexport const MEDIA_USAGE_GENERATION_WRITE_LEASE_MS = 60 * 60 * 1000;\nconst OCCURRENCE_INSERT_BATCH_SIZE = Math.max(\n\t1,\n\tMath.floor(D1_MAX_BOUND_PARAMETERS / OCCURRENCE_BIND_COLUMNS),\n);\n\nfunction cleanupDeleteBatchSize(cleanupLease: MediaUsageCleanupLease | undefined): number {\n\treturn cleanupLease ? SQL_BATCH_SIZE - 3 : SQL_BATCH_SIZE;\n}\n\nfunction canIssueCleanupStatement(canIssueStatement: (() => boolean) | undefined): boolean {\n\treturn canIssueStatement?.() ?? true;\n}\n\nfunction nullableRefMatch(\n\tleft: \"content.live_revision_id\" | \"content.draft_revision_id\",\n\tright: \"input.revision_id\",\n): RawBuilder<boolean> {\n\tconst leftRef = sql.ref(left);\n\tconst rightRef = sql.ref(right);\n\treturn sql<boolean>`(\n\t\t(${leftRef} IS NULL AND ${rightRef} IS NULL)\n\t\tOR ${leftRef} = ${rightRef}\n\t)`;\n}\n\nconst MAX_JSON_BIND_BYTES = 1_900_000;\nconst MEDIA_USAGE_EVENT_QUERY_CEILING = 900;\nconst MEDIA_USAGE_QUERY_RESERVE = 150;\n\nfunction chunkJsonRows<T>(rows: readonly T[]): T[][] {\n\tconst batches: T[][] = [];\n\tlet batch: T[] = [];\n\tlet batchBytes = 2;\n\tfor (const row of rows) {\n\t\tconst rowBytes =\n\t\t\tnew TextEncoder().encode(JSON.stringify(row)).byteLength + (batch.length > 0 ? 1 : 0);\n\t\tif (batch.length > 0 && batchBytes + rowBytes > MAX_JSON_BIND_BYTES) {\n\t\t\tbatches.push(batch);\n\t\t\tbatch = [];\n\t\t\tbatchBytes = 2;\n\t\t}\n\t\tbatch.push(row);\n\t\tbatchBytes += rowBytes;\n\t}\n\tif (batch.length > 0) batches.push(batch);\n\treturn batches;\n}\n\nfunction mediaUsageQueryBudgetAllows(queries: number): boolean {\n\tconst metrics = getRequestContext()?.metrics;\n\treturn (\n\t\t!metrics ||\n\t\tmetrics.dbCount + queries + MEDIA_USAGE_QUERY_RESERVE <= MEDIA_USAGE_EVENT_QUERY_CEILING\n\t);\n}\n\nfunction mergeInto<T>(target: Set<T>, source: ReadonlySet<T>): void {\n\tfor (const value of source) target.add(value);\n}\n\nfunction batchOccurrenceRows(\n\tprepared: readonly {\n\t\tprojection: { occurrences: readonly MediaUsageOccurrenceInput[] };\n\t\tgeneration: string;\n\t\tleaseToken: string;\n\t\trow: { source_key: string };\n\t}[],\n\tnow: string,\n) {\n\treturn prepared.flatMap((item) =>\n\t\titem.projection.occurrences.map((occurrence) => ({\n\t\t\tid: ulid(),\n\t\t\tsource_key: item.row.source_key,\n\t\t\tgeneration: item.generation,\n\t\t\tfield_slug: occurrence.fieldSlug,\n\t\t\tfield_path: occurrence.fieldPath,\n\t\t\toccurrence_index: occurrence.occurrenceIndex ?? 0,\n\t\t\treference_type: occurrence.referenceType,\n\t\t\tmedia_id: occurrence.mediaId,\n\t\t\tprovider: occurrence.provider,\n\t\t\tprovider_asset_id: occurrence.providerAssetId,\n\t\t\tmedia_kind: occurrence.mediaKind ?? null,\n\t\t\tmime_type: occurrence.mimeType ?? null,\n\t\t\tcreated_at: now,\n\t\t\tlease_token: item.leaseToken,\n\t\t})),\n\t);\n}\n\ntype BatchOccurrenceRow = ReturnType<typeof batchOccurrenceRows>[number];\n\nfunction cleanupDurationSeconds(value: number): number {\n\tif (!Number.isSafeInteger(value) || value < 0) {\n\t\tthrow new Error(\"Media usage cleanup duration must be a non-negative whole number of seconds\");\n\t}\n\treturn value;\n}\n\nconst CONTENT_SOURCE_ELIGIBILITY = sql<boolean>`(\n\ts.source_variant = 'draft_overlay'\n\tOR (\n\t\ts.source_variant = 'columns'\n\t\tAND (\n\t\t\ts.content_status = 'published'\n\t\t\tOR NOT EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_media_usage_sources AS overlay\n\t\t\t\tWHERE overlay.source_type = 'content'\n\t\t\t\t\tAND overlay.collection_slug = s.collection_slug\n\t\t\t\t\tAND overlay.content_id = s.content_id\n\t\t\t\t\tAND overlay.source_variant = 'draft_overlay'\n\t\t\t\t\tAND ${contentSourceMatchesActiveCollection(\"overlay\", \"s.collection_id\")}\n\t\t\t)\n\t\t)\n\t)\n)`;\n\ntype ContentSourceAlias = \"deleted_source\" | \"overlay\" | \"s\" | \"state\";\ntype CurrentCollectionIdReference = \"collection.id\" | \"page.collection_id\" | \"s.collection_id\";\n\nfunction contentSourceMatchesActiveCollection(\n\tsource: ContentSourceAlias,\n\tcurrentCollectionId: CurrentCollectionIdReference,\n): RawBuilder<boolean> {\n\treturn sql<boolean>`(\n\t\tNOT EXISTS (\n\t\t\tSELECT 1\n\t\t\tFROM _emdash_media_usage_activation AS activation\n\t\t\tWHERE activation.task_key = 'incremental_capture'\n\t\t\t\tAND activation.state = 'active'\n\t\t)\n\t\tOR (\n\t\t\t${sql.ref(`${source}.collection_id`)} = ${sql.ref(currentCollectionId)}\n\t\t\tAND ${sql.ref(`${source}.identity_version`)} = 1\n\t\t)\n\t)`;\n}\n\nexport interface MediaUsageSourceInput {\n\tsourceKey: string;\n\tsourceType: string;\n\tcollectionId?: string | null;\n\tcollectionSlug?: string | null;\n\tcontentId?: string | null;\n\tsourceVariant: MediaUsageContentSourceVariant;\n\tlocale?: string | null;\n\ttranslationGroup?: string | null;\n\tcontentSlug?: string | null;\n\tcontentTitle?: string | null;\n\tcontentStatus?: string | null;\n\tcontentScheduledAt?: string | null;\n\tcontentDeletedAt?: string | null;\n\trevisionId?: string | null;\n\tschemaVersion?: number;\n\tsourceUpdatedAt?: string | null;\n\tsourceVersion?: number | null;\n\tsourceFingerprint?: string | null;\n\tidentityVersion?: number | null;\n\tsourceCompleteness?: MediaUsageSourceCompleteness;\n\tlastAttemptedAt?: string | null;\n\tlastErrorCode?: string | null;\n}\n\nexport interface MediaUsageOccurrenceInput {\n\tfieldSlug: string;\n\tfieldPath: string;\n\toccurrenceIndex?: number;\n\treferenceType: MediaUsageReferenceType;\n\tmediaId: string | null;\n\tprovider: string;\n\tproviderAssetId: string;\n\tmediaKind?: MediaKind | null;\n\tmimeType?: string | null;\n}\n\nexport interface MediaUsageSource {\n\tsourceKey: string;\n\tsourceType: string;\n\tcollectionId: string | null;\n\tcollectionSlug: string | null;\n\tcontentId: string | null;\n\tsourceVariant: string;\n\tlocale: string | null;\n\ttranslationGroup: string | null;\n\tcontentSlug: string | null;\n\tcontentTitle: string | null;\n\tcontentStatus: string | null;\n\tcontentScheduledAt: string | null;\n\tcontentDeletedAt: string | null;\n\trevisionId: string | null;\n\tcurrentGeneration: string;\n\tschemaVersion: number;\n\tsourceUpdatedAt: string | null;\n\tsourceVersion: number | null;\n\tsourceFingerprint: string | null;\n\tidentityVersion: number | null;\n\tsourceCompleteness: string;\n\tlastAttemptedAt: string | null;\n\tlastErrorCode: string | null;\n\tindexedAt: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface MediaUsageGuardedReplaceResult {\n\treplaced: boolean;\n\tunchanged: boolean;\n\t/** Populated only when a guarded replacement did not win the current source row. */\n\tsource: MediaUsageSource | null;\n}\n\nexport interface MediaUsageNewSourceProjection {\n\tsource: MediaUsageSourceInput;\n\toccurrences: readonly MediaUsageOccurrenceInput[];\n}\n\nexport interface MediaUsageExistingSourceProjection extends MediaUsageNewSourceProjection {\n\texpectedSource: MediaUsageSource;\n}\n\nexport interface MediaUsageGuardedDeleteResult {\n\tdeleted: boolean;\n\tsource: MediaUsageSource | null;\n}\n\nexport interface MediaUsageGuardedAbsentDeleteResult extends MediaUsageGuardedDeleteResult {\n\tcontentPresent: boolean;\n}\n\nexport interface MediaUsageGuardedAttemptResult {\n\tattempted: boolean;\n\t/** Populated only when a guarded attempted mark did not win the current source row. */\n\tsource: MediaUsageSource | null;\n}\n\nexport interface MediaUsageSourceGenerationDeletionMeasurement {\n\toccurrenceCount: number;\n\toccurrenceBytes: number;\n\texceedsOccurrenceLimit: boolean;\n}\n\nexport interface MediaUsageCleanupCursor {\n\tcreatedAt: string;\n\tid: string;\n}\n\nexport interface MediaUsageCleanupClaim {\n\tleaseToken: string;\n\tcursor: MediaUsageCleanupCursor | null;\n\tclaimedAt: string;\n\tscanBeforeAt: string;\n\tconsecutiveFailures: number;\n}\n\nexport interface MediaUsageCleanupCandidate {\n\tid: string;\n\tsourceKey: string;\n\tgeneration: string;\n\tcreatedAt: string;\n\tcurrentGeneration: string | null;\n\tindexedAt: string | null;\n\twriteLeaseExpiresAt: string | null;\n}\n\nexport interface MediaUsageCleanupLease {\n\tleaseToken: string;\n}\n\nexport interface MediaUsageCleanupDeleteOptions {\n\tcandidateIds?: readonly string[];\n\tcleanupLease?: MediaUsageCleanupLease;\n\tcanIssueStatement?: () => boolean;\n}\n\nexport interface MediaUsageCleanupCompletion {\n\tleaseToken: string;\n\tnextCursor: MediaUsageCleanupCursor | null;\n\tsweepComplete: boolean;\n\tcandidateCount: number;\n\tdeletedOrphans: number;\n\tdeletedStale: number;\n\tdeletedAbandoned: number;\n\tdeletedWriteLeases: number;\n\tbacklogLowerBound: number;\n\tscanHasMore: boolean;\n\tdurationMs: number;\n}\n\nexport interface MediaUsageIndexStatusRepairInput extends MediaUsageIndexStatusIdentity {\n\trunToken: string;\n\tschemaVersion?: number;\n\tstartedAt: string;\n\tupdatedAt?: string;\n}\n\nexport interface MediaUsageIndexStatusFinalizeInput extends MediaUsageIndexStatusIdentity {\n\trunToken: string;\n\tstatus: Exclude<MediaUsageIndexStatusValue, \"never\" | \"running\" | \"stale\">;\n\tschemaVersion?: number;\n\tcompletedAt: string;\n\tindexedSourceCount?: number;\n\tfailedSourceCount?: number;\n\tlastErrorCode?: string | null;\n\tupdatedAt?: string;\n}\n\nexport interface MediaUsageIndexStatusEpochRepairInput extends MediaUsageIndexStatusIdentity {\n\tcollectionId: string;\n\trunToken: string;\n\tschemaVersion: number;\n}\n\nexport interface MediaUsageIndexStatusEpochRepairRun {\n\tchangeEpoch: number | string;\n\tstartedAt: string;\n}\n\nexport interface MediaUsageIndexStatusEpochFinalizeInput extends MediaUsageIndexStatusEpochRepairInput {\n\tstartingEpoch: number | string;\n\tstatus: Exclude<MediaUsageIndexStatusValue, \"never\" | \"running\" | \"stale\">;\n\tindexedSourceCount: number;\n\tfailedSourceCount: number;\n\tlastErrorCode: string | null;\n}\n\nexport interface MediaUsageIncrementalStatusIdentity {\n\tcollectionId: string;\n\tcollectionSlug: string;\n}\n\nexport interface MediaUsageGuardedIndexStatusResult {\n\tfinalized: boolean;\n\tstatus: MediaUsageIndexStatus | null;\n}\n\nexport type MediaUsageSourceCompleteness =\n\t| \"unknown\"\n\t| \"complete\"\n\t| \"partial\"\n\t| \"failed\"\n\t| \"unsupported\";\n\nexport type MediaUsageIndexStatusValue =\n\t| \"never\"\n\t| \"running\"\n\t| \"complete\"\n\t| \"partial\"\n\t| \"failed\"\n\t| \"stale\";\n\nexport interface MediaUsageIndexStatusIdentity {\n\tadapterId: string;\n\tscopeType: string;\n\tscopeKey: string;\n}\n\nexport interface MediaUsageIndexStatusInput extends MediaUsageIndexStatusIdentity {\n\tstatus: MediaUsageIndexStatusValue;\n\tschemaVersion?: number;\n\tstartedAt?: string | null;\n\tcompletedAt?: string | null;\n\tcursor?: string | null;\n\tindexedSourceCount?: number;\n\tfailedSourceCount?: number;\n\tlastErrorCode?: string | null;\n\tupdatedAt?: string;\n}\n\nexport interface MediaUsageIndexStatus extends MediaUsageIndexStatusIdentity {\n\tstatus: string;\n\tschemaVersion: number;\n\tstartedAt: string | null;\n\tcompletedAt: string | null;\n\tcursor: string | null;\n\tindexedSourceCount: number;\n\tfailedSourceCount: number;\n\tlastErrorCode: string | null;\n\tupdatedAt: string;\n}\n\nexport interface FindMediaUsageOptions {\n\tlimit?: number;\n\tcursor?: string;\n}\n\nexport interface MediaUsageCollectionIndexStatusScope {\n\tcollectionSlug: string;\n\tstatus: string | null;\n\tschemaVersion: number | null;\n\treconciliationRequired: boolean;\n}\n\nexport interface MediaUsageCoverageRead {\n\tscopes: MediaUsageCollectionIndexStatusScope[];\n\t/** Raw JSON option values by name; `null` when the option is not stored. */\n\toptions: Map<string, string | null>;\n}\n\nexport interface MediaUsageCollectionProgress {\n\tstatus: \"indexing\" | \"ready\" | \"needs_attention\";\n\treadyCollections: number;\n\ttotalCollections: number;\n}\n\nexport interface MediaUsageEntrySource {\n\tsource: MediaUsageSource;\n\toccurrences: MediaUsageOccurrence[];\n}\n\nexport interface MediaUsageEntryGroup {\n\tcollectionSlug: string;\n\tcontentId: string;\n\tcontentDeletedAt: string | null;\n\tsources: MediaUsageEntrySource[];\n}\n\ninterface MediaUsageSourceRow {\n\tsource_key: string;\n\tsource_type: string;\n\tcollection_id: string | null;\n\tcollection_slug: string | null;\n\tcontent_id: string | null;\n\tsource_variant: string;\n\tlocale: string | null;\n\ttranslation_group: string | null;\n\tcontent_slug: string | null;\n\tcontent_title: string | null;\n\tcontent_status: string | null;\n\tcontent_scheduled_at: string | null;\n\tcontent_deleted_at: string | null;\n\trevision_id: string | null;\n\tcurrent_generation: string;\n\tschema_version: number;\n\tsource_updated_at: string | null;\n\tsource_version: number | null;\n\tsource_fingerprint: string | null;\n\tidentity_version: number | null;\n\tsource_completeness: string;\n\tlast_attempted_at: string | null;\n\tlast_error_code: string | null;\n\tindexed_at: string;\n\tcreated_at: string;\n\tupdated_at: string;\n}\n\nexport interface MediaUsageOccurrence {\n\tid: string;\n\tsourceKey: string;\n\tgeneration: string;\n\tfieldSlug: string;\n\tfieldPath: string;\n\toccurrenceIndex: number;\n\treferenceType: string;\n\tmediaId: string | null;\n\tprovider: string;\n\tproviderAssetId: string;\n\tmediaKind: string | null;\n\tmimeType: string | null;\n\tcreatedAt: string;\n}\n\nexport interface MediaUsageRecord {\n\tsource: MediaUsageSource;\n\toccurrence: MediaUsageOccurrence;\n}\n\ninterface JoinedUsageRow {\n\tsource_key: string;\n\tsource_type: string;\n\tcollection_id: string | null;\n\tcollection_slug: string | null;\n\tcontent_id: string | null;\n\tsource_variant: string;\n\tlocale: string | null;\n\ttranslation_group: string | null;\n\tcontent_slug: string | null;\n\tcontent_title: string | null;\n\tcontent_status: string | null;\n\tcontent_scheduled_at: string | null;\n\tcontent_deleted_at: string | null;\n\trevision_id: string | null;\n\tcurrent_generation: string;\n\tschema_version: number;\n\tsource_updated_at: string | null;\n\tsource_version: number | null;\n\tsource_fingerprint: string | null;\n\tidentity_version: number | null;\n\tsource_completeness: string;\n\tlast_attempted_at: string | null;\n\tlast_error_code: string | null;\n\tindexed_at: string;\n\tsource_created_at: string;\n\tsource_row_updated_at: string;\n\toccurrence_id: string;\n\tgeneration: string;\n\tfield_slug: string;\n\tfield_path: string;\n\toccurrence_index: number;\n\treference_type: string;\n\tmedia_id: string | null;\n\tprovider: string;\n\tprovider_asset_id: string;\n\tmedia_kind: string | null;\n\tmime_type: string | null;\n\toccurrence_created_at: string;\n}\n\ninterface GroupedUsageRow extends JoinedUsageRow {\n\tentry_deleted_at: string | null;\n\thas_more: number;\n}\n\n/** Persistence-only repository for the internal media usage projection tables. */\nexport class MediaUsageRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\tasync replaceSource(\n\t\tsource: MediaUsageSourceInput,\n\t\toccurrences: readonly MediaUsageOccurrenceInput[],\n\t): Promise<MediaUsageSource> {\n\t\tconst generation = ulid();\n\n\t\tconst admitted = await this.withGenerationWriteLease(\n\t\t\tsource,\n\t\t\tgeneration,\n\t\t\tasync (leaseToken, now) => {\n\t\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\t\tif (!(await this.lockCanonicalSourceCollection(trx, source))) {\n\t\t\t\t\t\tthrow new Error(`Media usage collection is no longer current for ${source.sourceKey}`);\n\t\t\t\t\t}\n\t\t\t\t\tawait this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);\n\t\t\t\t\tconst promoted = await this.upsertSource(trx, source, generation, now, leaseToken);\n\t\t\t\t\tif (!promoted) {\n\t\t\t\t\t\tthrow new Error(`Media usage generation lease expired for ${source.sourceKey}`);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t\tif (!admitted) {\n\t\t\tthrow new Error(`Media usage collection is no longer current for ${source.sourceKey}`);\n\t\t}\n\n\t\tconst replaced = await this.findSource(source.sourceKey);\n\t\tif (!replaced) {\n\t\t\tthrow new Error(`Media usage source ${source.sourceKey} was not persisted`);\n\t\t}\n\t\treturn replaced;\n\t}\n\tasync replaceSourceIfCurrent(\n\t\tsource: MediaUsageSourceInput,\n\t\toccurrences: readonly MediaUsageOccurrenceInput[],\n\t\texpectedCurrentGeneration: string | null,\n\t): Promise<MediaUsageGuardedReplaceResult> {\n\t\tif (\n\t\t\texpectedCurrentGeneration !== null &&\n\t\t\t(await this.projectionMatchesCurrentGeneration(source, expectedCurrentGeneration))\n\t\t) {\n\t\t\treturn { replaced: false, unchanged: true, source: null };\n\t\t}\n\t\tconst generation = ulid();\n\t\tlet replaced = false;\n\n\t\tawait this.withGenerationWriteLease(source, generation, async (leaseToken, now) => {\n\t\t\tconst row = this.buildSourceRow(source, generation, now);\n\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\tif (!(await this.lockCanonicalSourceCollection(trx, source))) return;\n\t\t\t\tawait this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);\n\t\t\t\tif (expectedCurrentGeneration === null) {\n\t\t\t\t\treplaced = await this.insertSourceIfAbsent(trx, row, leaseToken);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treplaced = await this.updateSourceIfGeneration(\n\t\t\t\t\ttrx,\n\t\t\t\t\trow,\n\t\t\t\t\texpectedCurrentGeneration,\n\t\t\t\t\tleaseToken,\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\n\t\treturn {\n\t\t\treplaced,\n\t\t\tunchanged: false,\n\t\t\tsource: replaced ? null : await this.findSource(source.sourceKey),\n\t\t};\n\t}\n\n\tasync findSource(sourceKey: string): Promise<MediaUsageSource | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources\")\n\t\t\t.selectAll()\n\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? rowToSource(row) : null;\n\t}\n\n\tasync findSources(sourceKeys: readonly string[]): Promise<Map<string, MediaUsageSource>> {\n\t\tconst uniqueSourceKeys = [...new Set(sourceKeys)];\n\t\tconst sources = new Map<string, MediaUsageSource>();\n\t\tif (uniqueSourceKeys.length === 0) return sources;\n\t\tfor (const sourceKeyBatch of chunkJsonRows(uniqueSourceKeys)) {\n\t\t\tconst input = jsonTextValues(this.db, sourceKeyBatch);\n\t\t\tconst result = await sql<Selectable<MediaUsageSourceTable>>`\n\t\t\t\tWITH requested AS (${input})\n\t\t\t\tSELECT source.*\n\t\t\t\tFROM _emdash_media_usage_sources AS source\n\t\t\t\tINNER JOIN requested ON requested.value = source.source_key\n\t\t\t`.execute(this.db);\n\t\t\tfor (const row of result.rows) {\n\t\t\t\tconst source = rowToSource(row);\n\t\t\t\tsources.set(source.sourceKey, source);\n\t\t\t}\n\t\t}\n\n\t\treturn sources;\n\t}\n\n\tasync measureSourceGenerationDeletion(\n\t\tsourceKey: string,\n\t\tgeneration: string,\n\t\tmaxOccurrences: number,\n\t): Promise<MediaUsageSourceGenerationDeletionMeasurement> {\n\t\tif (!Number.isSafeInteger(maxOccurrences) || maxOccurrences < 0) {\n\t\t\tthrow new Error(\"Media usage deletion measurement requires a non-negative row limit\");\n\t\t}\n\t\tconst payload = sql<string>`\n\t\t\tCOALESCE(field_slug, '') || COALESCE(field_path, '') ||\n\t\t\tCOALESCE(reference_type, '') || COALESCE(media_id, '') ||\n\t\t\tCOALESCE(provider, '') || COALESCE(provider_asset_id, '') ||\n\t\t\tCOALESCE(media_kind, '') || COALESCE(mime_type, '')\n\t\t`;\n\t\tconst occurrenceBytes = isPostgres(this.db)\n\t\t\t? sql<number>`octet_length(${payload})`\n\t\t\t: sql<number>`length(CAST(${payload} AS BLOB))`;\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage\")\n\t\t\t.select(occurrenceBytes.as(\"occurrence_bytes\"))\n\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t.where(\"generation\", \"=\", generation)\n\t\t\t.limit(maxOccurrences + 1)\n\t\t\t.execute();\n\n\t\treturn {\n\t\t\toccurrenceCount: rows.length,\n\t\t\toccurrenceBytes: rows.reduce((total, row) => total + Number(row.occurrence_bytes), 0),\n\t\t\texceedsOccurrenceLimit: rows.length > maxOccurrences,\n\t\t};\n\t}\n\n\tasync replaceSourceIfMatching(\n\t\tsource: MediaUsageSourceInput,\n\t\toccurrences: readonly MediaUsageOccurrenceInput[],\n\t\texpectedSource: MediaUsageSource | null,\n\t): Promise<MediaUsageGuardedReplaceResult> {\n\t\tif (\n\t\t\texpectedSource !== null &&\n\t\t\t(await this.projectionMatchesExpectedSource(source, expectedSource))\n\t\t) {\n\t\t\treturn { replaced: false, unchanged: true, source: null };\n\t\t}\n\t\tconst generation = ulid();\n\t\tlet replaced = false;\n\n\t\tawait this.withGenerationWriteLease(source, generation, async (leaseToken, now) => {\n\t\t\tconst row = this.buildSourceRow(source, generation, now);\n\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\tif (!(await this.lockCanonicalSourceCollection(trx, source))) return;\n\t\t\t\tawait this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);\n\t\t\t\tif (expectedSource === null) {\n\t\t\t\t\treplaced = await this.insertSourceIfAbsent(trx, row, leaseToken);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treplaced = await this.updateSourceIfMatching(trx, row, expectedSource, leaseToken);\n\t\t\t});\n\t\t});\n\n\t\treturn {\n\t\t\treplaced,\n\t\t\tunchanged: false,\n\t\t\tsource: replaced ? null : await this.findSource(source.sourceKey),\n\t\t};\n\t}\n\n\tasync replaceNewSourcesBatch(\n\t\tprojections: readonly MediaUsageNewSourceProjection[],\n\t): Promise<Set<string>> {\n\t\tconst unique = [\n\t\t\t...new Map(\n\t\t\t\tprojections.map((projection) => [projection.source.sourceKey, projection]),\n\t\t\t).values(),\n\t\t];\n\t\tif (unique.length === 0) return new Set();\n\t\tconst collectionSlug = unique[0]?.source.collectionSlug;\n\t\tconst collectionId = unique[0]?.source.collectionId;\n\t\tif (!collectionSlug || !collectionId) {\n\t\t\tthrow new Error(\"Canonical media usage batch requires collection identity\");\n\t\t}\n\t\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\t\tif (\n\t\t\tunique.some(\n\t\t\t\t(projection) =>\n\t\t\t\t\tprojection.source.collectionSlug !== collectionSlug ||\n\t\t\t\t\tprojection.source.collectionId !== collectionId,\n\t\t\t)\n\t\t) {\n\t\t\tthrow new Error(\"Canonical media usage batch must contain one collection\");\n\t\t}\n\n\t\tconst now = new Date().toISOString();\n\t\tconst expiresAt = new Date(Date.now() + MEDIA_USAGE_GENERATION_WRITE_LEASE_MS).toISOString();\n\t\tconst prepared = unique.map((projection) => {\n\t\t\tconst generation = ulid();\n\t\t\treturn {\n\t\t\t\tprojection,\n\t\t\t\tgeneration,\n\t\t\t\tleaseToken: ulid(),\n\t\t\t\trow: this.buildSourceRow(projection.source, generation, now),\n\t\t\t};\n\t\t});\n\t\tconst sourceRows = prepared.map((item) => ({\n\t\t\t...item.row,\n\t\t\tlease_token: item.leaseToken,\n\t\t}));\n\t\tconst occurrenceRows = batchOccurrenceRows(prepared, now);\n\t\tconst estimatedQueries =\n\t\t\t2 + chunkJsonRows(occurrenceRows).length + chunkJsonRows(sourceRows).length;\n\t\tif (!mediaUsageQueryBudgetAllows(estimatedQueries)) {\n\t\t\tif (unique.length === 1) return new Set();\n\t\t\tconst midpoint = Math.ceil(unique.length / 2);\n\t\t\tconst inserted = new Set<string>();\n\t\t\tmergeInto(inserted, await this.replaceNewSourcesBatch(unique.slice(0, midpoint)));\n\t\t\tmergeInto(inserted, await this.replaceNewSourcesBatch(unique.slice(midpoint)));\n\t\t\treturn inserted;\n\t\t}\n\n\t\tconst leasesPayload = JSON.stringify(\n\t\t\tprepared.map((item) => ({\n\t\t\t\tsource_key: item.row.source_key,\n\t\t\t\tcollection_id: item.row.collection_id,\n\t\t\t\tcollection_slug: item.row.collection_slug,\n\t\t\t\tgeneration: item.generation,\n\t\t\t\tlease_token: item.leaseToken,\n\t\t\t\texpires_at: expiresAt,\n\t\t\t\tcreated_at: now,\n\t\t\t})),\n\t\t);\n\t\tconst leases = this.generationWriteBatchInput(leasesPayload);\n\t\tawait sql`\n\t\t\tWITH input AS (${leases})\n\t\t\tINSERT INTO _emdash_media_usage_generation_writes (\n\t\t\t\tsource_key, generation, lease_token, expires_at, created_at\n\t\t\t)\n\t\t\tSELECT source_key, generation, lease_token, expires_at, created_at\n\t\t\tFROM input\n\t\t\tWHERE EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\tINNER JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\tON status.collection_id = collection.id\n\t\t\t\t\tAND status.scope_key = collection.slug\n\t\t\t\tWHERE collection.id = input.collection_id\n\t\t\t\t\tAND collection.slug = input.collection_slug\n\t\t\t\t\tAND status.adapter_id = 'content-media'\n\t\t\t\t\tAND status.scope_type = 'collection'\n\t\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\t\tWHERE deletion.collection_id = input.collection_id\n\t\t\t\t\t)\n\t\t\t)\n\t\t`.execute(this.db);\n\n\t\ttry {\n\t\t\tawait this.insertBatchOccurrences(occurrenceRows);\n\t\t\tconst tableName = `ec_${collectionSlug}`;\n\t\t\tvalidateIdentifier(tableName, \"content table\");\n\t\t\tconst inserted = new Set<string>();\n\t\t\tfor (const sourceRowBatch of chunkJsonRows(sourceRows)) {\n\t\t\t\tconst input = this.sourceBatchInput(JSON.stringify(sourceRowBatch));\n\t\t\t\tconst result = await sql<{ source_key: string }>`\n\t\t\t\t\tWITH input AS (${input})\n\t\t\t\t\tINSERT INTO _emdash_media_usage_sources (\n\t\t\t\t\t\tsource_key, source_type, collection_id, collection_slug, content_id,\n\t\t\t\t\t\tsource_variant, locale, translation_group, content_slug, content_title,\n\t\t\t\t\t\tcontent_status, content_scheduled_at, content_deleted_at, revision_id,\n\t\t\t\t\t\tcurrent_generation, schema_version, source_updated_at, source_version,\n\t\t\t\t\t\tsource_fingerprint, identity_version, source_completeness,\n\t\t\t\t\t\tlast_attempted_at, last_error_code, indexed_at, updated_at\n\t\t\t\t\t)\n\t\t\t\t\tSELECT\n\t\t\t\t\t\tinput.source_key, input.source_type, input.collection_id, input.collection_slug,\n\t\t\t\t\t\tinput.content_id, input.source_variant, input.locale, input.translation_group,\n\t\t\t\t\t\tinput.content_slug, input.content_title, input.content_status,\n\t\t\t\t\t\tinput.content_scheduled_at, input.content_deleted_at, input.revision_id,\n\t\t\t\t\t\tinput.current_generation, input.schema_version, input.source_updated_at,\n\t\t\t\t\t\tinput.source_version, input.source_fingerprint, input.identity_version,\n\t\t\t\t\t\tinput.source_completeness, input.last_attempted_at, input.last_error_code,\n\t\t\t\t\t\tinput.indexed_at, input.updated_at\n\t\t\t\t\tFROM input\n\t\t\t\t\tWHERE EXISTS (\n\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\tFROM _emdash_media_usage_generation_writes AS writer\n\t\t\t\t\t\tWHERE writer.source_key = input.source_key\n\t\t\t\t\t\t\tAND writer.generation = input.current_generation\n\t\t\t\t\t\t\tAND writer.lease_token = input.lease_token\n\t\t\t\t\t\t\tAND ${this.generationWriteLeaseExpiryIsInFuture(\"writer.expires_at\")}\n\t\t\t\t\t)\n\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\t\tINNER JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\t\t\tON status.collection_id = collection.id\n\t\t\t\t\t\t\tAND status.scope_key = collection.slug\n\t\t\t\t\t\tWHERE collection.id = input.collection_id\n\t\t\t\t\t\t\tAND collection.slug = input.collection_slug\n\t\t\t\t\t\t\tAND status.adapter_id = 'content-media'\n\t\t\t\t\t\t\tAND status.scope_type = 'collection'\n\t\t\t\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\t\t\tFROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\t\t\t\tWHERE deletion.collection_id = input.collection_id\n\t\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\tFROM ${sql.ref(tableName)} AS content\n\t\t\t\t\t\tWHERE content.id = input.content_id\n\t\t\t\t\t\t\tAND content.version = input.source_version\n\t\t\t\t\t\t\tAND content.updated_at = input.source_updated_at\n\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\t(input.source_variant = 'columns' AND ${nullableRefMatch(\"content.live_revision_id\", \"input.revision_id\")})\n\t\t\t\t\t\t\t\tOR\n\t\t\t\t\t\t\t\t(input.source_variant = 'draft_overlay' AND ${nullableRefMatch(\"content.draft_revision_id\", \"input.revision_id\")})\n\t\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\tON CONFLICT (source_key) DO NOTHING\n\t\t\t\t\tRETURNING source_key\n\t\t\t\t`.execute(this.db);\n\t\t\t\tfor (const row of result.rows) inserted.add(row.source_key);\n\t\t\t}\n\t\t\treturn inserted;\n\t\t} finally {\n\t\t\tawait sql`\n\t\t\t\tWITH input AS (${leases})\n\t\t\t\tDELETE FROM _emdash_media_usage_generation_writes AS writer\n\t\t\t\tWHERE EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM input\n\t\t\t\t\tWHERE input.source_key = writer.source_key\n\t\t\t\t\t\tAND input.generation = writer.generation\n\t\t\t\t\t\tAND input.lease_token = writer.lease_token\n\t\t\t\t)\n\t\t\t`.execute(this.db);\n\t\t}\n\t}\n\n\tasync replaceExistingSourcesBatch(\n\t\tprojections: readonly MediaUsageExistingSourceProjection[],\n\t): Promise<Set<string>> {\n\t\tconst unique = [\n\t\t\t...new Map(\n\t\t\t\tprojections.map((projection) => [projection.source.sourceKey, projection]),\n\t\t\t).values(),\n\t\t];\n\t\tif (unique.length === 0) return new Set();\n\t\tconst collectionSlug = unique[0]?.source.collectionSlug;\n\t\tconst collectionId = unique[0]?.source.collectionId;\n\t\tif (!collectionSlug || !collectionId) {\n\t\t\tthrow new Error(\"Canonical media usage batch requires collection identity\");\n\t\t}\n\t\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\t\tif (\n\t\t\tunique.some(\n\t\t\t\t(projection) =>\n\t\t\t\t\tprojection.source.collectionSlug !== collectionSlug ||\n\t\t\t\t\tprojection.source.collectionId !== collectionId,\n\t\t\t)\n\t\t) {\n\t\t\tthrow new Error(\"Canonical media usage batch must contain one collection\");\n\t\t}\n\n\t\tconst now = new Date().toISOString();\n\t\tconst expiresAt = new Date(Date.now() + MEDIA_USAGE_GENERATION_WRITE_LEASE_MS).toISOString();\n\t\tconst prepared = unique.map((projection) => {\n\t\t\tconst generation = ulid();\n\t\t\treturn {\n\t\t\t\tprojection,\n\t\t\t\tgeneration,\n\t\t\t\tleaseToken: ulid(),\n\t\t\t\trow: this.buildSourceRow(projection.source, generation, now),\n\t\t\t};\n\t\t});\n\t\tconst sourceRows = prepared.map((item) => ({\n\t\t\t...item.row,\n\t\t\tlease_token: item.leaseToken,\n\t\t\texpected_generation: item.projection.expectedSource.currentGeneration,\n\t\t\texpected_collection_id: item.projection.expectedSource.collectionId,\n\t\t\texpected_updated_at: item.projection.expectedSource.updatedAt,\n\t\t\texpected_source_fingerprint: item.projection.expectedSource.sourceFingerprint,\n\t\t\texpected_source_updated_at: item.projection.expectedSource.sourceUpdatedAt,\n\t\t\texpected_source_version: item.projection.expectedSource.sourceVersion,\n\t\t\texpected_identity_version: item.projection.expectedSource.identityVersion,\n\t\t\texpected_revision_id: item.projection.expectedSource.revisionId,\n\t\t\texpected_source_completeness: item.projection.expectedSource.sourceCompleteness,\n\t\t\texpected_last_attempted_at: item.projection.expectedSource.lastAttemptedAt,\n\t\t\texpected_last_error_code: item.projection.expectedSource.lastErrorCode,\n\t\t}));\n\t\tconst occurrenceRows = batchOccurrenceRows(prepared, now);\n\t\tconst estimatedQueries =\n\t\t\t2 + chunkJsonRows(occurrenceRows).length + chunkJsonRows(sourceRows).length;\n\t\tif (!mediaUsageQueryBudgetAllows(estimatedQueries)) {\n\t\t\tif (unique.length === 1) return new Set();\n\t\t\tconst midpoint = Math.ceil(unique.length / 2);\n\t\t\tconst replaced = new Set<string>();\n\t\t\tmergeInto(replaced, await this.replaceExistingSourcesBatch(unique.slice(0, midpoint)));\n\t\t\tmergeInto(replaced, await this.replaceExistingSourcesBatch(unique.slice(midpoint)));\n\t\t\treturn replaced;\n\t\t}\n\t\tconst leasesPayload = JSON.stringify(\n\t\t\tprepared.map((item) => ({\n\t\t\t\tsource_key: item.row.source_key,\n\t\t\t\tcollection_id: item.row.collection_id,\n\t\t\t\tcollection_slug: item.row.collection_slug,\n\t\t\t\tgeneration: item.generation,\n\t\t\t\tlease_token: item.leaseToken,\n\t\t\t\texpires_at: expiresAt,\n\t\t\t\tcreated_at: now,\n\t\t\t})),\n\t\t);\n\t\tconst leases = this.generationWriteBatchInput(leasesPayload);\n\t\tawait sql`\n\t\t\tWITH input AS (${leases})\n\t\t\tINSERT INTO _emdash_media_usage_generation_writes (\n\t\t\t\tsource_key, generation, lease_token, expires_at, created_at\n\t\t\t)\n\t\t\tSELECT source_key, generation, lease_token, expires_at, created_at\n\t\t\tFROM input\n\t\t\tWHERE EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\tINNER JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\tON status.collection_id = collection.id\n\t\t\t\t\tAND status.scope_key = collection.slug\n\t\t\t\tWHERE collection.id = input.collection_id\n\t\t\t\t\tAND collection.slug = input.collection_slug\n\t\t\t\t\tAND status.adapter_id = 'content-media'\n\t\t\t\t\tAND status.scope_type = 'collection'\n\t\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\t\tWHERE deletion.collection_id = input.collection_id\n\t\t\t\t\t)\n\t\t\t)\n\t\t`.execute(this.db);\n\n\t\ttry {\n\t\t\tawait this.insertBatchOccurrences(occurrenceRows);\n\t\t\tconst tableName = `ec_${collectionSlug}`;\n\t\t\tvalidateIdentifier(tableName, \"content table\");\n\t\t\tconst replaced = new Set<string>();\n\t\t\tfor (const sourceRowBatch of chunkJsonRows(sourceRows)) {\n\t\t\t\tconst input = this.sourceBatchInput(JSON.stringify(sourceRowBatch));\n\t\t\t\tconst result = await sql<{ source_key: string }>`\n\t\t\t\t\tWITH input AS (${input})\n\t\t\t\t\tUPDATE _emdash_media_usage_sources AS source\n\t\t\t\t\tSET source_type = input.source_type,\n\t\t\t\t\t\tcollection_id = input.collection_id,\n\t\t\t\t\t\tcollection_slug = input.collection_slug,\n\t\t\t\t\t\tcontent_id = input.content_id,\n\t\t\t\t\t\tsource_variant = input.source_variant,\n\t\t\t\t\t\tlocale = input.locale,\n\t\t\t\t\t\ttranslation_group = input.translation_group,\n\t\t\t\t\t\tcontent_slug = input.content_slug,\n\t\t\t\t\t\tcontent_title = input.content_title,\n\t\t\t\t\t\tcontent_status = input.content_status,\n\t\t\t\t\t\tcontent_scheduled_at = input.content_scheduled_at,\n\t\t\t\t\t\tcontent_deleted_at = input.content_deleted_at,\n\t\t\t\t\t\trevision_id = input.revision_id,\n\t\t\t\t\t\tcurrent_generation = input.current_generation,\n\t\t\t\t\t\tschema_version = input.schema_version,\n\t\t\t\t\t\tsource_updated_at = input.source_updated_at,\n\t\t\t\t\t\tsource_version = input.source_version,\n\t\t\t\t\t\tsource_fingerprint = input.source_fingerprint,\n\t\t\t\t\t\tidentity_version = input.identity_version,\n\t\t\t\t\t\tsource_completeness = input.source_completeness,\n\t\t\t\t\t\tlast_attempted_at = input.last_attempted_at,\n\t\t\t\t\t\tlast_error_code = input.last_error_code,\n\t\t\t\t\t\tindexed_at = input.indexed_at,\n\t\t\t\t\t\tupdated_at = input.updated_at\n\t\t\t\t\tFROM input\n\t\t\t\t\tWHERE source.source_key = input.source_key\n\t\t\t\t\t\tAND source.current_generation = input.expected_generation\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.collection_id\", \"input.expected_collection_id\")}\n\t\t\t\t\t\tAND source.updated_at = input.expected_updated_at\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.source_fingerprint\", \"input.expected_source_fingerprint\")}\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.source_updated_at\", \"input.expected_source_updated_at\")}\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.source_version\", \"input.expected_source_version\")}\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.identity_version\", \"input.expected_identity_version\")}\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.revision_id\", \"input.expected_revision_id\")}\n\t\t\t\t\t\tAND source.source_completeness = input.expected_source_completeness\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.last_attempted_at\", \"input.expected_last_attempted_at\")}\n\t\t\t\t\t\tAND ${this.batchRefsMatch(\"source.last_error_code\", \"input.expected_last_error_code\")}\n\t\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\t\tFROM _emdash_media_usage_generation_writes AS writer\n\t\t\t\t\t\t\tWHERE writer.source_key = input.source_key\n\t\t\t\t\t\t\t\tAND writer.generation = input.current_generation\n\t\t\t\t\t\t\t\tAND writer.lease_token = input.lease_token\n\t\t\t\t\t\t\t\tAND ${this.generationWriteLeaseExpiryIsInFuture(\"writer.expires_at\")}\n\t\t\t\t\t\t)\n\t\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\t\t\tINNER JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\t\t\t\tON status.collection_id = collection.id\n\t\t\t\t\t\t\t\tAND status.scope_key = collection.slug\n\t\t\t\t\t\t\tWHERE collection.id = input.collection_id\n\t\t\t\t\t\t\t\tAND collection.slug = input.collection_slug\n\t\t\t\t\t\t\t\tAND status.adapter_id = 'content-media'\n\t\t\t\t\t\t\t\tAND status.scope_type = 'collection'\n\t\t\t\t\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\t\t\t\tFROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\t\t\t\t\tWHERE deletion.collection_id = input.collection_id\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\t\tFROM ${sql.ref(tableName)} AS content\n\t\t\t\t\t\t\tWHERE content.id = input.content_id\n\t\t\t\t\t\t\t\tAND content.version = input.source_version\n\t\t\t\t\t\t\t\tAND content.updated_at = input.source_updated_at\n\t\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\t\t(input.source_variant = 'columns' AND ${nullableRefMatch(\"content.live_revision_id\", \"input.revision_id\")})\n\t\t\t\t\t\t\t\t\tOR\n\t\t\t\t\t\t\t\t\t(input.source_variant = 'draft_overlay' AND ${nullableRefMatch(\"content.draft_revision_id\", \"input.revision_id\")})\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\tRETURNING ${isPostgres(this.db) ? sql`source.source_key` : sql`source_key`} AS source_key\n\t\t\t\t`.execute(this.db);\n\t\t\t\tfor (const row of result.rows) replaced.add(row.source_key);\n\t\t\t}\n\t\t\treturn replaced;\n\t\t} finally {\n\t\t\tawait sql`\n\t\t\t\tWITH input AS (${leases})\n\t\t\t\tDELETE FROM _emdash_media_usage_generation_writes AS writer\n\t\t\t\tWHERE EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM input\n\t\t\t\t\tWHERE input.source_key = writer.source_key\n\t\t\t\t\t\tAND input.generation = writer.generation\n\t\t\t\t\t\tAND input.lease_token = writer.lease_token\n\t\t\t\t)\n\t\t\t`.execute(this.db);\n\t\t}\n\t}\n\n\tasync matchingExistingSourcesBatch(\n\t\tprojections: readonly MediaUsageExistingSourceProjection[],\n\t): Promise<Set<string>> {\n\t\tif (projections.length === 0) return new Set();\n\t\tconst now = new Date().toISOString();\n\t\tconst rows = projections.map((projection) => ({\n\t\t\t...this.buildSourceRow(projection.source, projection.expectedSource.currentGeneration, now),\n\t\t\texpected_generation: projection.expectedSource.currentGeneration,\n\t\t\texpected_collection_id: projection.expectedSource.collectionId,\n\t\t\texpected_updated_at: projection.expectedSource.updatedAt,\n\t\t\texpected_source_fingerprint: projection.expectedSource.sourceFingerprint,\n\t\t\texpected_source_updated_at: projection.expectedSource.sourceUpdatedAt,\n\t\t\texpected_source_version: projection.expectedSource.sourceVersion,\n\t\t\texpected_identity_version: projection.expectedSource.identityVersion,\n\t\t\texpected_revision_id: projection.expectedSource.revisionId,\n\t\t\texpected_source_completeness: projection.expectedSource.sourceCompleteness,\n\t\t\texpected_last_attempted_at: projection.expectedSource.lastAttemptedAt,\n\t\t\texpected_last_error_code: projection.expectedSource.lastErrorCode,\n\t\t}));\n\t\tif (!mediaUsageQueryBudgetAllows(chunkJsonRows(rows).length)) {\n\t\t\tif (projections.length === 1) return new Set();\n\t\t\tconst midpoint = Math.ceil(projections.length / 2);\n\t\t\tconst matched = new Set<string>();\n\t\t\tmergeInto(matched, await this.matchingExistingSourcesBatch(projections.slice(0, midpoint)));\n\t\t\tmergeInto(matched, await this.matchingExistingSourcesBatch(projections.slice(midpoint)));\n\t\t\treturn matched;\n\t\t}\n\t\tconst matched = new Set<string>();\n\t\tfor (const batch of chunkJsonRows(rows)) {\n\t\t\tconst input = this.sourceBatchInput(JSON.stringify(batch));\n\t\t\tconst result = await sql<{ source_key: string }>`\n\t\t\t\tWITH input AS (${input})\n\t\t\t\tSELECT source.source_key\n\t\t\t\tFROM _emdash_media_usage_sources AS source\n\t\t\t\tINNER JOIN input ON input.source_key = source.source_key\n\t\t\t\tWHERE source.current_generation = input.expected_generation\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.collection_id\", \"input.expected_collection_id\")}\n\t\t\t\t\tAND source.updated_at = input.expected_updated_at\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.source_fingerprint\", \"input.expected_source_fingerprint\")}\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.source_updated_at\", \"input.expected_source_updated_at\")}\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.source_version\", \"input.expected_source_version\")}\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.identity_version\", \"input.expected_identity_version\")}\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.revision_id\", \"input.expected_revision_id\")}\n\t\t\t\t\tAND source.source_completeness = input.expected_source_completeness\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.last_attempted_at\", \"input.expected_last_attempted_at\")}\n\t\t\t\t\tAND ${this.batchRefsMatch(\"source.last_error_code\", \"input.expected_last_error_code\")}\n\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\t\tWHERE collection.id = source.collection_id\n\t\t\t\t\t\t\tAND collection.slug = source.collection_slug\n\t\t\t\t\t)\n\t\t\t`.execute(this.db);\n\t\t\tfor (const row of result.rows) matched.add(row.source_key);\n\t\t}\n\t\treturn matched;\n\t}\n\n\tasync markSourceAttempted(source: MediaUsageSourceInput): Promise<MediaUsageSource> {\n\t\tif (source.collectionId !== undefined && source.collectionId !== null) {\n\t\t\tconst expectedSource = await this.findSource(source.sourceKey);\n\t\t\tconst result = await this.markSourceAttemptedIfMatching(source, expectedSource);\n\t\t\tif (!result.attempted) {\n\t\t\t\tthrow new Error(`Canonical media usage source ${source.sourceKey} is no longer current`);\n\t\t\t}\n\t\t\tconst attempted = await this.findSource(source.sourceKey);\n\t\t\tif (!attempted) {\n\t\t\t\tthrow new Error(`Media usage source ${source.sourceKey} was not persisted`);\n\t\t\t}\n\t\t\treturn attempted;\n\t\t}\n\n\t\tconst generation = ulid();\n\t\tawait this.withGenerationWriteLease(source, generation, async (leaseToken, now) => {\n\t\t\tconst row = this.buildAttemptedSourceRow(source, generation, now);\n\t\t\tconst updates = this.attemptedSourceUpdateSet(source, row);\n\t\t\tconst result = await this.db\n\t\t\t\t.insertInto(\"_emdash_media_usage_sources\")\n\t\t\t\t.values(row)\n\t\t\t\t.onConflict((oc) => oc.column(\"source_key\").doUpdateSet(updates))\n\t\t\t\t.executeTakeFirst();\n\t\t\tif ((result.numInsertedOrUpdatedRows ?? 0n) <= 0n) {\n\t\t\t\tthrow new Error(`Media usage generation lease expired for ${source.sourceKey}`);\n\t\t\t}\n\t\t});\n\n\t\tconst attempted = await this.findSource(source.sourceKey);\n\t\tif (!attempted) {\n\t\t\tthrow new Error(`Media usage source ${source.sourceKey} was not persisted`);\n\t\t}\n\t\treturn attempted;\n\t}\n\n\tasync markSourceAttemptedIfMatching(\n\t\tsource: MediaUsageSourceInput,\n\t\texpectedSource: MediaUsageSource | null,\n\t): Promise<MediaUsageGuardedAttemptResult> {\n\t\tconst generation = ulid();\n\t\tlet attempted = false;\n\n\t\tif (expectedSource === null) {\n\t\t\tawait this.withGenerationWriteLease(source, generation, async (leaseToken, now) => {\n\t\t\t\tconst row = this.buildAttemptedSourceRow(source, generation, now);\n\t\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\t\tif (!(await this.lockCanonicalSourceCollection(trx, source))) return;\n\t\t\t\t\tattempted = await this.persistSourceIfWriteLease(\n\t\t\t\t\t\ttrx,\n\t\t\t\t\t\trow,\n\t\t\t\t\t\tleaseToken,\n\t\t\t\t\t\tsql`ON CONFLICT (source_key) DO NOTHING`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tconst row = this.buildAttemptedSourceRow(source, generation, new Date().toISOString());\n\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\tif (!(await this.lockCanonicalSourceCollection(trx, source))) return;\n\t\t\t\tattempted = await this.updateAttemptedSourceIfMatching(trx, source, row, expectedSource);\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tattempted,\n\t\t\tsource: attempted ? null : await this.findSource(source.sourceKey),\n\t\t};\n\t}\n\n\tasync findActiveEntryCountsByMediaIds(mediaIds: readonly string[]): Promise<Map<string, number>> {\n\t\tconst uniqueMediaIds = [...new Set(mediaIds)];\n\t\tconst counts = new Map(uniqueMediaIds.map((mediaId) => [mediaId, 0]));\n\n\t\tfor (const mediaIdBatch of chunks(uniqueMediaIds, SQL_BATCH_SIZE)) {\n\t\t\tconst visibleEntries = this.currentContentMediaUsageBaseQuery()\n\t\t\t\t.select([\n\t\t\t\t\t\"u.media_id as media_id\",\n\t\t\t\t\t\"s.collection_slug as collection_slug\",\n\t\t\t\t\t\"s.content_id as content_id\",\n\t\t\t\t])\n\t\t\t\t.where(\"u.media_id\", \"in\", mediaIdBatch)\n\t\t\t\t.where((eb) =>\n\t\t\t\t\teb.not(\n\t\t\t\t\t\teb.exists(\n\t\t\t\t\t\t\teb\n\t\t\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_sources as deleted_source\")\n\t\t\t\t\t\t\t\t.select(\"deleted_source.source_key\")\n\t\t\t\t\t\t\t\t.where(\"deleted_source.source_type\", \"=\", \"content\")\n\t\t\t\t\t\t\t\t.whereRef(\"deleted_source.collection_slug\", \"=\", \"s.collection_slug\")\n\t\t\t\t\t\t\t\t.whereRef(\"deleted_source.content_id\", \"=\", \"s.content_id\")\n\t\t\t\t\t\t\t\t.where(\"deleted_source.source_variant\", \"in\", [\"columns\", \"draft_overlay\"])\n\t\t\t\t\t\t\t\t.where(contentSourceMatchesActiveCollection(\"deleted_source\", \"collection.id\"))\n\t\t\t\t\t\t\t\t.where(\"deleted_source.content_deleted_at\", \"is not\", null),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.distinct()\n\t\t\t\t.as(\"visible_entries\");\n\n\t\t\tconst rows = await this.db\n\t\t\t\t.selectFrom(visibleEntries)\n\t\t\t\t.select(\"media_id\")\n\t\t\t\t.select((eb) => eb.fn.countAll<number>().as(\"usage_count\"))\n\t\t\t\t.groupBy(\"media_id\")\n\t\t\t\t.execute();\n\n\t\t\tfor (const row of rows) {\n\t\t\t\tif (row.media_id !== null) counts.set(row.media_id, Number(row.usage_count));\n\t\t\t}\n\t\t}\n\n\t\treturn counts;\n\t}\n\n\t/**\n\t * Read collection index status and the named options in one statement.\n\t * The one-row anchor keeps the option values readable on a site with no\n\t * collections.\n\t */\n\tasync findCoverageWithOptions(\n\t\tidentity: Pick<MediaUsageIndexStatusIdentity, \"adapterId\" | \"scopeType\">,\n\t\toptionNames: readonly string[],\n\t): Promise<MediaUsageCoverageRead> {\n\t\tlet query = this.db\n\t\t\t.selectFrom(this.db.selectNoFrom(sql<number>`1`.as(\"anchor\")).as(\"anchor\"))\n\t\t\t.leftJoin(\"_emdash_collections as collection\", (join) => join.on(sql<boolean>`1 = 1`))\n\t\t\t.leftJoin(\"_emdash_media_usage_index_status as status\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.on(\"status.adapter_id\", \"=\", identity.adapterId)\n\t\t\t\t\t.on(\"status.scope_type\", \"=\", identity.scopeType)\n\t\t\t\t\t.onRef(\"status.scope_key\", \"=\", \"collection.slug\"),\n\t\t\t)\n\t\t\t.select([\n\t\t\t\t\"collection.slug as collection_slug\",\n\t\t\t\t\"status.status as status\",\n\t\t\t\t\"status.schema_version as schema_version\",\n\t\t\t\t\"status.reconciliation_required as reconciliation_required\",\n\t\t\t])\n\t\t\t.orderBy(\"collection.slug\", \"asc\");\n\t\tconst optionAliases = optionNames.map((name, index) => [name, `option_${index}`] as const);\n\t\tfor (const [name, alias] of optionAliases) {\n\t\t\tquery = query.select((eb) =>\n\t\t\t\teb.selectFrom(\"options\").select(\"value\").where(\"name\", \"=\", name).as(alias),\n\t\t\t);\n\t\t}\n\t\tconst rows: Array<Record<string, unknown>> = await query.execute();\n\n\t\tconst scopes: MediaUsageCollectionIndexStatusScope[] = [];\n\t\tfor (const row of rows) {\n\t\t\tif (typeof row.collection_slug !== \"string\") continue;\n\t\t\tscopes.push({\n\t\t\t\tcollectionSlug: row.collection_slug,\n\t\t\t\tstatus: typeof row.status === \"string\" ? row.status : null,\n\t\t\t\tschemaVersion: row.schema_version == null ? null : Number(row.schema_version),\n\t\t\t\treconciliationRequired:\n\t\t\t\t\trow.reconciliation_required != null && Number(row.reconciliation_required) !== 0,\n\t\t\t});\n\t\t}\n\t\tconst firstRow = rows[0];\n\t\tconst options = new Map<string, string | null>();\n\t\tfor (const [name, alias] of optionAliases) {\n\t\t\tconst value = firstRow?.[alias];\n\t\t\toptions.set(name, typeof value === \"string\" ? value : null);\n\t\t}\n\t\treturn { scopes, options };\n\t}\n\n\tasync findCollectionProgress(): Promise<MediaUsageCollectionProgress | null> {\n\t\tconst result = await sql<{\n\t\t\tactivation_active: boolean | number;\n\t\t\tactivation_generation: number | string | null;\n\t\t\tneeds_attention: boolean | number;\n\t\t\tready_collections: number | string;\n\t\t\ttotal_collections: number | string;\n\t\t\tcleanup_pending: boolean | number;\n\t\t}>`\n\t\t\tWITH collection_progress AS (\n\t\t\t\tSELECT\n\t\t\t\t\tCASE WHEN status.status = 'complete'\n\t\t\t\t\t\tAND status.schema_version = ${CONTENT_SOURCE_SCHEMA_VERSION}\n\t\t\t\t\t\tAND status.reconciliation_required = 0\n\t\t\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_work AS work\n\t\t\t\t\t\t\tWHERE work.collection_id = collection.id\n\t\t\t\t\t\t\t\tAND work.collection_slug = collection.slug\n\t\t\t\t\t\t)\n\t\t\t\t\tTHEN 1 ELSE 0 END AS is_ready,\n\t\t\t\t\tCASE WHEN status.collection_id IS NULL\n\t\t\t\t\t\tOR COALESCE(status.capture_state, '') <> 'active'\n\t\t\t\t\t\tOR status.status NOT IN ('complete', 'never', 'running', 'partial', 'failed', 'stale')\n\t\t\t\t\t\tOR status.status = 'failed'\n\t\t\t\t\t\tOR (\n\t\t\t\t\t\t\tstatus.reconciliation_required = 0\n\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\tstatus.status <> 'complete'\n\t\t\t\t\t\t\t\tOR COALESCE(status.schema_version, -1) <> ${CONTENT_SOURCE_SCHEMA_VERSION}\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_work AS work\n\t\t\t\t\t\t\t\tWHERE work.collection_id = collection.id\n\t\t\t\t\t\t\t\t\tAND work.collection_slug = collection.slug\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t\tOR EXISTS (\n\t\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_work AS work\n\t\t\t\t\t\t\tWHERE work.collection_id = collection.id\n\t\t\t\t\t\t\t\tAND work.collection_slug = collection.slug\n\t\t\t\t\t\t\t\tAND work.state = 'failed'\n\t\t\t\t\t\t)\n\t\t\t\t\t\tOR EXISTS (\n\t\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\t\t\t\tWHERE reconciliation.collection_id = collection.id\n\t\t\t\t\t\t\t\tAND reconciliation.collection_slug = collection.slug\n\t\t\t\t\t\t\t\tAND reconciliation.state = 'failed'\n\t\t\t\t\t\t\t\tAND status.reconciliation_required = 1\n\t\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\t\treconciliation.target_epoch IS NULL\n\t\t\t\t\t\t\t\t\tOR reconciliation.target_epoch >= status.change_epoch\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\tTHEN 1 ELSE 0 END AS needs_attention\n\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\tLEFT JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\tON status.adapter_id = 'content-media'\n\t\t\t\t\tAND status.scope_type = 'collection'\n\t\t\t\t\tAND status.collection_id = collection.id\n\t\t\t\t\tAND status.scope_key = collection.slug\n\t\t\t\tWHERE NOT EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\tWHERE deletion.collection_id = collection.id\n\t\t\t\t\t\tAND deletion.collection_slug = collection.slug\n\t\t\t\t)\n\t\t\t)\n\t\t\tSELECT\n\t\t\t\t(\n\t\t\t\t\tSELECT activation.runtime_generation\n\t\t\t\t\tFROM _emdash_media_usage_activation AS activation\n\t\t\t\t\tWHERE activation.task_key = 'incremental_capture'\n\t\t\t\t) AS activation_generation,\n\t\t\t\tEXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_activation AS activation\n\t\t\t\t\tWHERE activation.task_key = 'incremental_capture'\n\t\t\t\t\t\tAND activation.state = 'active'\n\t\t\t\t) AS activation_active,\n\t\t\t\tCOUNT(*) AS total_collections,\n\t\t\t\tCOALESCE(SUM(is_ready), 0) AS ready_collections,\n\t\t\t\tEXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\tWHERE deletion.state IN ('pending', 'retry', 'leased')\n\t\t\t\t) AS cleanup_pending,\n\t\t\t\tCASE WHEN COALESCE(MAX(needs_attention), 0) = 1 OR EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\tWHERE deletion.state = 'failed'\n\t\t\t\t) THEN 1 ELSE 0 END AS needs_attention\n\t\t\tFROM collection_progress\n\t\t`.execute(this.db);\n\t\tconst row = result.rows[0];\n\t\tif (!row) throw new Error(\"Media usage progress query returned no result\");\n\t\tif (!row.activation_active) return null;\n\t\tif (Number(row.activation_generation) !== MEDIA_USAGE_ACTIVATION_RUNTIME_GENERATION) {\n\t\t\tthrow new MediaUsageActivationVersionMismatchError(\n\t\t\t\t\"Media usage activation runtime generation is incompatible\",\n\t\t\t);\n\t\t}\n\t\tconst readyCollections = Number(row.ready_collections);\n\t\tconst totalCollections = Number(row.total_collections);\n\t\tconst cleanupPending = Number(row.cleanup_pending);\n\t\tconst needsAttention = Number(row.needs_attention);\n\t\tif (\n\t\t\t!Number.isSafeInteger(readyCollections) ||\n\t\t\t!Number.isSafeInteger(totalCollections) ||\n\t\t\treadyCollections < 0 ||\n\t\t\ttotalCollections < readyCollections ||\n\t\t\t(cleanupPending !== 0 && cleanupPending !== 1) ||\n\t\t\t(needsAttention !== 0 && needsAttention !== 1)\n\t\t) {\n\t\t\tthrow new Error(\"Media usage progress query returned invalid counts\");\n\t\t}\n\t\treturn {\n\t\t\tstatus: needsAttention\n\t\t\t\t? \"needs_attention\"\n\t\t\t\t: readyCollections === totalCollections && cleanupPending === 0\n\t\t\t\t\t? \"ready\"\n\t\t\t\t\t: \"indexing\",\n\t\t\treadyCollections,\n\t\t\ttotalCollections,\n\t\t};\n\t}\n\n\tasync findCurrentEntryUsagePageByMediaId(\n\t\tmediaId: string,\n\t\toptions: FindMediaUsageOptions = {},\n\t): Promise<FindManyResult<MediaUsageEntryGroup>> {\n\t\tconst requestedLimit = Math.floor(options.limit ?? 50);\n\t\tconst limit = Number.isFinite(requestedLimit) ? Math.min(Math.max(1, requestedLimit), 100) : 50;\n\t\tconst cursor = options.cursor ? decodeCursor(options.cursor) : null;\n\t\tif (cursor && (cursor.orderValue.length === 0 || cursor.id.length === 0)) {\n\t\t\tthrow new InvalidCursorError(options.cursor ?? \"\");\n\t\t}\n\t\tlet matchedGroups = this.currentContentMediaUsageBaseQuery()\n\t\t\t.select([\n\t\t\t\t\"collection.id as collection_id\",\n\t\t\t\t\"s.collection_slug as collection_slug\",\n\t\t\t\t\"s.content_id as content_id\",\n\t\t\t])\n\t\t\t.where(\"u.media_id\", \"=\", mediaId)\n\t\t\t.distinct();\n\t\tif (cursor) {\n\t\t\tmatchedGroups = matchedGroups.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"s.collection_slug\", \">\", cursor.orderValue),\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"s.collection_slug\", \"=\", cursor.orderValue),\n\t\t\t\t\t\teb(\"s.content_id\", \">\", cursor.id),\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\t\tmatchedGroups = matchedGroups\n\t\t\t.orderBy(\"s.collection_slug\", \"asc\")\n\t\t\t.orderBy(\"s.content_id\", \"asc\")\n\t\t\t.limit(limit + 1);\n\n\t\tconst rows: GroupedUsageRow[] = await this.db\n\t\t\t.with(\"matched_groups\", () => matchedGroups)\n\t\t\t.with(\"page_groups\", (db) =>\n\t\t\t\tdb\n\t\t\t\t\t.selectFrom(\"matched_groups\")\n\t\t\t\t\t.selectAll()\n\t\t\t\t\t.orderBy(\"collection_slug\", \"asc\")\n\t\t\t\t\t.orderBy(\"content_id\", \"asc\")\n\t\t\t\t\t.limit(limit),\n\t\t\t)\n\t\t\t.with(\"entry_state\", (db) =>\n\t\t\t\tdb\n\t\t\t\t\t.selectFrom(\"page_groups as page\")\n\t\t\t\t\t.crossJoin(\"_emdash_media_usage_sources as state\")\n\t\t\t\t\t.select([\"page.collection_id\", \"page.collection_slug\", \"page.content_id\"])\n\t\t\t\t\t.select((eb) =>\n\t\t\t\t\t\teb.fn.max<string | null>(\"state.content_deleted_at\").as(\"entry_deleted_at\"),\n\t\t\t\t\t)\n\t\t\t\t\t.whereRef(\"page.collection_slug\", \"=\", \"state.collection_slug\")\n\t\t\t\t\t.whereRef(\"page.content_id\", \"=\", \"state.content_id\")\n\t\t\t\t\t.where(\"state.source_type\", \"=\", \"content\")\n\t\t\t\t\t.where(\"state.source_variant\", \"in\", [\"columns\", \"draft_overlay\"])\n\t\t\t\t\t.where(contentSourceMatchesActiveCollection(\"state\", \"page.collection_id\"))\n\t\t\t\t\t.groupBy([\"page.collection_id\", \"page.collection_slug\", \"page.content_id\"]),\n\t\t\t)\n\t\t\t.selectFrom(\"entry_state as page\")\n\t\t\t.crossJoin(\"_emdash_media_usage_sources as s\")\n\t\t\t.crossJoin(\"_emdash_media_usage as u\")\n\t\t\t.whereRef(\"page.collection_slug\", \"=\", \"s.collection_slug\")\n\t\t\t.whereRef(\"page.content_id\", \"=\", \"s.content_id\")\n\t\t\t.where(contentSourceMatchesActiveCollection(\"s\", \"page.collection_id\"))\n\t\t\t.whereRef(\"s.source_key\", \"=\", \"u.source_key\")\n\t\t\t.whereRef(\"s.current_generation\", \"=\", \"u.generation\")\n\t\t\t.select(currentUsageSelect)\n\t\t\t.select(\"page.entry_deleted_at\")\n\t\t\t.select(\n\t\t\t\tsql<number>`CASE\n\t\t\t\t\tWHEN (SELECT COUNT(*) FROM matched_groups) > ${limit} THEN 1\n\t\t\t\t\tELSE 0\n\t\t\t\tEND`.as(\"has_more\"),\n\t\t\t)\n\t\t\t.where(\"u.media_id\", \"=\", mediaId)\n\t\t\t.where(\"s.source_type\", \"=\", \"content\")\n\t\t\t.where(\"s.collection_slug\", \"is not\", null)\n\t\t\t.where(\"s.content_id\", \"is not\", null)\n\t\t\t.where(\"s.source_variant\", \"in\", [\"columns\", \"draft_overlay\"])\n\t\t\t.where(CONTENT_SOURCE_ELIGIBILITY)\n\t\t\t.orderBy(\"s.collection_slug\", \"asc\")\n\t\t\t.orderBy(\"s.content_id\", \"asc\")\n\t\t\t.orderBy(\"s.source_variant\", \"asc\")\n\t\t\t.orderBy(\"s.source_key\", \"asc\")\n\t\t\t.orderBy(\"u.field_path\", \"asc\")\n\t\t\t.orderBy(\"u.occurrence_index\", \"asc\")\n\t\t\t.orderBy(\"u.id\", \"asc\")\n\t\t\t.execute();\n\n\t\tconst items = groupUsageRows(rows);\n\t\tconst result: FindManyResult<MediaUsageEntryGroup> = { items };\n\t\tif (Number(rows[0]?.has_more ?? 0) === 1 && items.length > 0) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.collectionSlug, last.contentId);\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync findCurrentUsageByMediaId(mediaId: string): Promise<MediaUsageRecord[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources as s\")\n\t\t\t.innerJoin(\"_emdash_media_usage as u\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"u.source_key\", \"=\", \"s.source_key\")\n\t\t\t\t\t.onRef(\"u.generation\", \"=\", \"s.current_generation\"),\n\t\t\t)\n\t\t\t.select(currentUsageSelect)\n\t\t\t.where(\"u.media_id\", \"=\", mediaId)\n\t\t\t.orderBy(\"s.source_key\", \"asc\")\n\t\t\t.orderBy(\"u.field_path\", \"asc\")\n\t\t\t.orderBy(\"u.occurrence_index\", \"asc\")\n\t\t\t.execute();\n\n\t\treturn rows.map(rowToUsageRecord);\n\t}\n\n\tasync findCurrentUsageByProviderAsset(\n\t\tprovider: string,\n\t\tproviderAssetId: string,\n\t): Promise<MediaUsageRecord[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources as s\")\n\t\t\t.innerJoin(\"_emdash_media_usage as u\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"u.source_key\", \"=\", \"s.source_key\")\n\t\t\t\t\t.onRef(\"u.generation\", \"=\", \"s.current_generation\"),\n\t\t\t)\n\t\t\t.select(currentUsageSelect)\n\t\t\t.where(\"u.provider\", \"=\", provider)\n\t\t\t.where(\"u.provider_asset_id\", \"=\", providerAssetId)\n\t\t\t.orderBy(\"s.source_key\", \"asc\")\n\t\t\t.orderBy(\"u.field_path\", \"asc\")\n\t\t\t.orderBy(\"u.occurrence_index\", \"asc\")\n\t\t\t.execute();\n\n\t\treturn rows.map(rowToUsageRecord);\n\t}\n\n\tasync findCurrentUsagePageByMediaId(\n\t\tmediaId: string,\n\t\toptions: FindMediaUsageOptions = {},\n\t): Promise<FindManyResult<MediaUsageRecord>> {\n\t\treturn this.findCurrentUsagePage((query) => query.where(\"u.media_id\", \"=\", mediaId), options);\n\t}\n\n\tasync findCurrentUsagePageByProviderAsset(\n\t\tprovider: string,\n\t\tproviderAssetId: string,\n\t\toptions: FindMediaUsageOptions = {},\n\t): Promise<FindManyResult<MediaUsageRecord>> {\n\t\treturn this.findCurrentUsagePage(\n\t\t\t(query) =>\n\t\t\t\tquery.where(\"u.provider\", \"=\", provider).where(\"u.provider_asset_id\", \"=\", providerAssetId),\n\t\t\toptions,\n\t\t);\n\t}\n\n\tasync deleteSource(sourceKey: string): Promise<number> {\n\t\treturn this.deleteSources([sourceKey]);\n\t}\n\n\tasync deleteSourceIfCurrent(\n\t\tsourceKey: string,\n\t\texpectedCurrentGeneration: string,\n\t): Promise<MediaUsageGuardedDeleteResult> {\n\t\tlet deleted = false;\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tawait this.lockCleanupBeforeSourceDelete(trx);\n\t\t\tconst result = await trx\n\t\t\t\t.deleteFrom(\"_emdash_media_usage_sources\")\n\t\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t\t.where(\"current_generation\", \"=\", expectedCurrentGeneration)\n\t\t\t\t.executeTakeFirst();\n\t\t\tdeleted = Number(result.numDeletedRows ?? 0) > 0;\n\t\t\tif (!deleted) return;\n\t\t\tawait this.deleteSourceGenerationOccurrences(trx, sourceKey, expectedCurrentGeneration);\n\t\t});\n\n\t\treturn {\n\t\t\tdeleted,\n\t\t\tsource: await this.findSource(sourceKey),\n\t\t};\n\t}\n\n\tasync deleteSourceIfMatching(\n\t\tsourceKey: string,\n\t\texpectedSource: MediaUsageSource,\n\t): Promise<MediaUsageGuardedDeleteResult> {\n\t\tlet deleted = false;\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tawait this.lockCleanupBeforeSourceDelete(trx);\n\t\t\tconst result = await trx\n\t\t\t\t.deleteFrom(\"_emdash_media_usage_sources\")\n\t\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t\t.where(this.sourceMatchExpression(expectedSource))\n\t\t\t\t.where(\n\t\t\t\t\tthis.currentCollectionExists(expectedSource.collectionId, expectedSource.collectionSlug),\n\t\t\t\t)\n\t\t\t\t.executeTakeFirst();\n\t\t\tdeleted = Number(result.numDeletedRows ?? 0) > 0;\n\t\t\tif (!deleted) return;\n\t\t\tawait this.deleteSourceGenerationOccurrences(\n\t\t\t\ttrx,\n\t\t\t\tsourceKey,\n\t\t\t\texpectedSource.currentGeneration,\n\t\t\t);\n\t\t});\n\n\t\treturn {\n\t\t\tdeleted,\n\t\t\tsource: await this.findSource(sourceKey),\n\t\t};\n\t}\n\n\tasync deleteSourceIfMatchingContentAbsent(\n\t\tsourceKey: string,\n\t\texpectedSource: MediaUsageSource,\n\t\tcollectionSlug: string,\n\t\tcontentId: string,\n\t): Promise<MediaUsageGuardedAbsentDeleteResult> {\n\t\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\t\tconst tableName = `ec_${collectionSlug}`;\n\t\tlet deleted = false;\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tawait this.lockCleanupBeforeSourceDelete(trx);\n\t\t\tconst result = await trx\n\t\t\t\t.deleteFrom(\"_emdash_media_usage_sources\")\n\t\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t\t.where(this.sourceMatchExpression(expectedSource))\n\t\t\t\t.where(\n\t\t\t\t\tthis.currentCollectionExists(expectedSource.collectionId, expectedSource.collectionSlug),\n\t\t\t\t)\n\t\t\t\t.where(\n\t\t\t\t\tsql<boolean>`NOT EXISTS (SELECT 1 FROM ${sql.ref(tableName)} WHERE id = ${contentId})`,\n\t\t\t\t)\n\t\t\t\t.executeTakeFirst();\n\t\t\tdeleted = Number(result.numDeletedRows ?? 0) > 0;\n\t\t\tif (!deleted) return;\n\t\t\tawait this.deleteSourceGenerationOccurrences(\n\t\t\t\ttrx,\n\t\t\t\tsourceKey,\n\t\t\t\texpectedSource.currentGeneration,\n\t\t\t);\n\t\t});\n\t\tconst contentPresent = deleted ? false : await this.contentRowExists(tableName, contentId);\n\n\t\treturn {\n\t\t\tdeleted,\n\t\t\tcontentPresent,\n\t\t\tsource: deleted || contentPresent ? null : await this.findSource(sourceKey),\n\t\t};\n\t}\n\n\tasync deleteSources(sourceKeys: readonly string[]): Promise<number> {\n\t\treturn this.deleteSourceKeys(sourceKeys);\n\t}\n\n\tasync deleteContentSources(collectionSlug: string, contentId: string): Promise<number> {\n\t\tconst sourceRows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources\")\n\t\t\t.select(\"source_key\")\n\t\t\t.where(\"source_type\", \"=\", \"content\")\n\t\t\t.where(\"collection_slug\", \"=\", collectionSlug)\n\t\t\t.where(\"content_id\", \"=\", contentId)\n\t\t\t.execute();\n\t\tconst sourceKeys = sourceRows.map((row) => row.source_key);\n\t\treturn this.deleteSourceKeys(sourceKeys);\n\t}\n\n\tasync deleteCollectionSources(collectionSlug: string): Promise<number> {\n\t\tlet deleted = 0;\n\t\twhile (true) {\n\t\t\tconst sourceRows = await this.db\n\t\t\t\t.selectFrom(\"_emdash_media_usage_sources\")\n\t\t\t\t.select(\"source_key\")\n\t\t\t\t.where(\"source_type\", \"=\", \"content\")\n\t\t\t\t.where(\"collection_slug\", \"=\", collectionSlug)\n\t\t\t\t.orderBy(\"source_key\", \"asc\")\n\t\t\t\t.limit(SQL_BATCH_SIZE)\n\t\t\t\t.execute();\n\t\t\tif (sourceRows.length === 0) break;\n\n\t\t\tdeleted += await this.deleteSourceKeys(sourceRows.map((row) => row.source_key));\n\t\t}\n\t\treturn deleted;\n\t}\n\n\tasync findCollectionContentSources(\n\t\tcollectionSlug: string,\n\t\tcollectionId?: string,\n\t): Promise<MediaUsageSource[]> {\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources\")\n\t\t\t.selectAll()\n\t\t\t.where(\"source_type\", \"=\", \"content\")\n\t\t\t.where(\"collection_slug\", \"=\", collectionSlug)\n\t\t\t.orderBy(\"source_key\", \"asc\");\n\t\tif (collectionId !== undefined) query = query.where(\"collection_id\", \"=\", collectionId);\n\t\tconst rows = await query.execute();\n\t\treturn rows.map((row) => rowToSource(row));\n\t}\n\n\tasync claimMediaUsageCleanup(input: {\n\t\tleaseToken: string;\n\t\tleaseDurationSeconds: number;\n\t\tnextEligibleDelaySeconds: number;\n\t\tsweepSafetyWindowSeconds: number;\n\t}): Promise<MediaUsageCleanupClaim | null> {\n\t\tconst leaseDurationSeconds = cleanupDurationSeconds(input.leaseDurationSeconds);\n\t\tconst nextEligibleDelaySeconds = cleanupDurationSeconds(input.nextEligibleDelaySeconds);\n\t\tconst sweepSafetyWindowSeconds = cleanupDurationSeconds(input.sweepSafetyWindowSeconds);\n\t\tconst claimedAt = this.cleanupTimestampOffset(0);\n\t\tconst leaseExpiresAt = this.cleanupTimestampOffset(leaseDurationSeconds);\n\t\tconst nextEligibleAt = this.cleanupTimestampOffset(nextEligibleDelaySeconds);\n\t\tconst sweepBeforeAt = this.cleanupTimestampOffset(-sweepSafetyWindowSeconds);\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_cleanup\")\n\t\t\t.set({\n\t\t\t\tlease_token: input.leaseToken,\n\t\t\t\tlease_expires_at: leaseExpiresAt,\n\t\t\t\tnext_eligible_at: nextEligibleAt,\n\t\t\t\tlast_started_at: claimedAt,\n\t\t\t\tupdated_at: claimedAt,\n\t\t\t\tscan_before_at: sql<string>`CASE\n\t\t\t\t\tWHEN scan_before_at IS NULL THEN ${sweepBeforeAt}\n\t\t\t\t\tELSE scan_before_at\n\t\t\t\tEND`,\n\t\t\t})\n\t\t\t.where(\"task_key\", \"=\", \"projection_gc\")\n\t\t\t.where(this.cleanupTimestampIsDue(\"next_eligible_at\"))\n\t\t\t.where((eb) =>\n\t\t\t\teb.or([eb(\"lease_token\", \"is\", null), this.cleanupTimestampIsDue(\"lease_expires_at\")]),\n\t\t\t)\n\t\t\t.returning([\n\t\t\t\t\"cursor_created_at\",\n\t\t\t\t\"cursor_id\",\n\t\t\t\t\"last_started_at\",\n\t\t\t\t\"scan_before_at\",\n\t\t\t\t\"consecutive_failures\",\n\t\t\t])\n\t\t\t.executeTakeFirst();\n\t\tif (!row) return null;\n\t\tif (!row.last_started_at || !row.scan_before_at) {\n\t\t\tthrow new Error(\"Media usage cleanup claim did not persist its database timestamps\");\n\t\t}\n\t\treturn {\n\t\t\tleaseToken: input.leaseToken,\n\t\t\tcursor:\n\t\t\t\trow.cursor_created_at && row.cursor_id\n\t\t\t\t\t? { createdAt: row.cursor_created_at, id: row.cursor_id }\n\t\t\t\t\t: null,\n\t\t\tclaimedAt: row.last_started_at,\n\t\t\tscanBeforeAt: row.scan_before_at,\n\t\t\tconsecutiveFailures: row.consecutive_failures,\n\t\t};\n\t}\n\n\t/**\n\t * Scans for reclaimable occurrences, or resolves to `null` when the sweep was\n\t * never issued because the lease is gone or the tick is out of budget. An\n\t * empty array means the scan ran and found nothing, which lets the caller\n\t * retire the sweep window; `null` must leave the cursor where it was.\n\t */\n\tasync findMediaUsageCleanupCandidates(input: {\n\t\tcutoff: string;\n\t\tcursor: MediaUsageCleanupCursor | null;\n\t\tlimit: number;\n\t\tcleanupLease?: MediaUsageCleanupLease;\n\t\tcanIssueStatement?: () => boolean;\n\t}): Promise<MediaUsageCleanupCandidate[] | null> {\n\t\tif (!(await this.admitCleanupScan(input.cleanupLease, input.canIssueStatement))) return null;\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_media_usage as u\")\n\t\t\t.leftJoin(\"_emdash_media_usage_sources as s\", \"s.source_key\", \"u.source_key\")\n\t\t\t.leftJoin(\"_emdash_media_usage_generation_writes as writer\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"writer.source_key\", \"=\", \"u.source_key\")\n\t\t\t\t\t.onRef(\"writer.generation\", \"=\", \"u.generation\"),\n\t\t\t)\n\t\t\t.select([\n\t\t\t\t\"u.id as id\",\n\t\t\t\t\"u.source_key as source_key\",\n\t\t\t\t\"u.generation as generation\",\n\t\t\t\t\"u.created_at as created_at\",\n\t\t\t\t\"s.current_generation as current_generation\",\n\t\t\t\t\"s.indexed_at as indexed_at\",\n\t\t\t\t\"writer.expires_at as write_lease_expires_at\",\n\t\t\t])\n\t\t\t.where(\"u.created_at\", \"<\", input.cutoff)\n\t\t\t.orderBy(\"u.created_at\", \"asc\")\n\t\t\t.orderBy(\"u.id\", \"asc\")\n\t\t\t.limit(Math.max(0, Math.floor(input.limit)));\n\n\t\tif (input.cursor) {\n\t\t\tconst cursor = input.cursor;\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb(eb.refTuple(\"u.created_at\", \"u.id\"), \">\", eb.tuple(cursor.createdAt, cursor.id)),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\treturn rows.map((row) => ({\n\t\t\tid: row.id,\n\t\t\tsourceKey: row.source_key,\n\t\t\tgeneration: row.generation,\n\t\t\tcreatedAt: row.created_at,\n\t\t\tcurrentGeneration: row.current_generation,\n\t\t\tindexedAt: row.indexed_at,\n\t\t\twriteLeaseExpiresAt: row.write_lease_expires_at,\n\t\t}));\n\t}\n\n\tasync completeMediaUsageCleanup(input: MediaUsageCleanupCompletion): Promise<boolean> {\n\t\tconst updates = {\n\t\t\tlease_token: null,\n\t\t\tlease_expires_at: null,\n\t\t\tcursor_created_at: input.sweepComplete ? null : (input.nextCursor?.createdAt ?? null),\n\t\t\tcursor_id: input.sweepComplete ? null : (input.nextCursor?.id ?? null),\n\t\t\t...(input.sweepComplete ? { scan_before_at: null } : {}),\n\t\t\tconsecutive_failures: 0,\n\t\t\tlast_completed_at: this.cleanupTimestampOffset(0),\n\t\t\tlast_candidate_count: input.candidateCount,\n\t\t\tlast_deleted_orphans: input.deletedOrphans,\n\t\t\tlast_deleted_stale: input.deletedStale,\n\t\t\tlast_deleted_abandoned: input.deletedAbandoned,\n\t\t\tlast_deleted_write_leases: input.deletedWriteLeases,\n\t\t\tlast_backlog_lower_bound: input.backlogLowerBound,\n\t\t\tlast_scan_has_more: input.scanHasMore ? 1 : 0,\n\t\t\tlast_duration_ms: input.durationMs,\n\t\t\tlast_error_code: null,\n\t\t\tupdated_at: this.cleanupTimestampOffset(0),\n\t\t};\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_cleanup\")\n\t\t\t.set(updates)\n\t\t\t.where(\"task_key\", \"=\", \"projection_gc\")\n\t\t\t.where(\"lease_token\", \"=\", input.leaseToken)\n\t\t\t.where(this.cleanupLeaseExpiryIsInFuture(\"_emdash_media_usage_cleanup.lease_expires_at\"))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0;\n\t}\n\n\tasync failMediaUsageCleanup(input: {\n\t\tleaseToken: string;\n\t\tretryDelaySeconds: number;\n\t\tconsecutiveFailures: number;\n\t\tdurationMs: number;\n\t\terrorCode: string;\n\t}): Promise<boolean> {\n\t\tconst retryDelaySeconds = cleanupDurationSeconds(input.retryDelaySeconds);\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_cleanup\")\n\t\t\t.set({\n\t\t\t\tlease_token: null,\n\t\t\t\tlease_expires_at: null,\n\t\t\t\tnext_eligible_at: this.cleanupTimestampOffset(retryDelaySeconds),\n\t\t\t\tconsecutive_failures: input.consecutiveFailures,\n\t\t\t\tlast_completed_at: this.cleanupTimestampOffset(0),\n\t\t\t\tlast_duration_ms: input.durationMs,\n\t\t\t\tlast_error_code: input.errorCode,\n\t\t\t\tupdated_at: this.cleanupTimestampOffset(0),\n\t\t\t})\n\t\t\t.where(\"task_key\", \"=\", \"projection_gc\")\n\t\t\t.where(\"lease_token\", \"=\", input.leaseToken)\n\t\t\t.where(this.cleanupLeaseExpiryIsInFuture(\"_emdash_media_usage_cleanup.lease_expires_at\"))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0;\n\t}\n\n\tasync deleteOrphanOccurrencesOlderThan(\n\t\tcutoff: string,\n\t\tlimit: number,\n\t\toptions: MediaUsageCleanupDeleteOptions = {},\n\t): Promise<number> {\n\t\tconst batchLimit = Math.floor(limit);\n\t\tif (batchLimit <= 0) return 0;\n\t\tif (options.candidateIds) {\n\t\t\treturn this.deleteOrphanCandidateIds(\n\t\t\t\toptions.candidateIds.slice(0, batchLimit),\n\t\t\t\tcutoff,\n\t\t\t\toptions.cleanupLease,\n\t\t\t\toptions.canIssueStatement,\n\t\t\t);\n\t\t}\n\t\tif (!(await this.admitCleanupScan(options.cleanupLease, options.canIssueStatement))) return 0;\n\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage as u\")\n\t\t\t.leftJoin(\"_emdash_media_usage_sources as s\", (join) =>\n\t\t\t\tjoin.onRef(\"s.source_key\", \"=\", \"u.source_key\"),\n\t\t\t)\n\t\t\t.leftJoin(\"_emdash_media_usage_generation_writes as writer\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"writer.source_key\", \"=\", \"u.source_key\")\n\t\t\t\t\t.onRef(\"writer.generation\", \"=\", \"u.generation\"),\n\t\t\t)\n\t\t\t.select(\"u.id\")\n\t\t\t.where(\"s.source_key\", \"is\", null)\n\t\t\t.where(\"u.created_at\", \"<\", cutoff)\n\t\t\t.where(this.noActiveGenerationWriteExpression(\"u\"))\n\t\t\t.orderBy(\"u.created_at\", \"asc\")\n\t\t\t.orderBy(\"u.id\", \"asc\")\n\t\t\t.limit(batchLimit)\n\t\t\t.execute();\n\n\t\treturn this.deleteOrphanCandidateIds(\n\t\t\trows.map((row) => row.id),\n\t\t\tcutoff,\n\t\t\toptions.cleanupLease,\n\t\t\toptions.canIssueStatement,\n\t\t);\n\t}\n\n\tasync deleteStaleGenerationsOlderThan(\n\t\tcutoff: string,\n\t\tlimit: number,\n\t\toptions: MediaUsageCleanupDeleteOptions = {},\n\t): Promise<number> {\n\t\tconst batchLimit = Math.floor(limit);\n\t\tif (batchLimit <= 0) return 0;\n\t\tif (options.candidateIds) {\n\t\t\treturn this.deleteStaleCandidateIds(\n\t\t\t\toptions.candidateIds.slice(0, batchLimit),\n\t\t\t\tcutoff,\n\t\t\t\toptions.cleanupLease,\n\t\t\t\toptions.canIssueStatement,\n\t\t\t);\n\t\t}\n\t\tif (!(await this.admitCleanupScan(options.cleanupLease, options.canIssueStatement))) return 0;\n\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage as u\")\n\t\t\t.innerJoin(\"_emdash_media_usage_sources as s\", (join) =>\n\t\t\t\tjoin.onRef(\"s.source_key\", \"=\", \"u.source_key\"),\n\t\t\t)\n\t\t\t.leftJoin(\"_emdash_media_usage_generation_writes as writer\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"writer.source_key\", \"=\", \"u.source_key\")\n\t\t\t\t\t.onRef(\"writer.generation\", \"=\", \"u.generation\"),\n\t\t\t)\n\t\t\t.select(\"u.id\")\n\t\t\t.where(\"u.created_at\", \"<\", cutoff)\n\t\t\t.whereRef(\"u.generation\", \"!=\", \"s.current_generation\")\n\t\t\t.whereRef(\"u.created_at\", \"<\", \"s.indexed_at\")\n\t\t\t.where(this.noActiveGenerationWriteExpression(\"u\"))\n\t\t\t.orderBy(\"u.created_at\", \"asc\")\n\t\t\t.orderBy(\"u.id\", \"asc\")\n\t\t\t.limit(batchLimit)\n\t\t\t.execute();\n\n\t\treturn this.deleteStaleCandidateIds(\n\t\t\trows.map((row) => row.id),\n\t\t\tcutoff,\n\t\t\toptions.cleanupLease,\n\t\t\toptions.canIssueStatement,\n\t\t);\n\t}\n\n\tasync deleteAbandonedGenerationsOlderThan(\n\t\tcutoff: string,\n\t\tlimit: number,\n\t\toptions: MediaUsageCleanupDeleteOptions = {},\n\t): Promise<number> {\n\t\tconst batchLimit = Math.floor(limit);\n\t\tif (batchLimit <= 0) return 0;\n\t\tif (options.candidateIds) {\n\t\t\treturn this.deleteAbandonedCandidateIds(\n\t\t\t\toptions.candidateIds.slice(0, batchLimit),\n\t\t\t\tcutoff,\n\t\t\t\toptions.cleanupLease,\n\t\t\t\toptions.canIssueStatement,\n\t\t\t);\n\t\t}\n\t\tif (!(await this.admitCleanupScan(options.cleanupLease, options.canIssueStatement))) return 0;\n\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage as u\")\n\t\t\t.innerJoin(\"_emdash_media_usage_sources as s\", (join) =>\n\t\t\t\tjoin.onRef(\"s.source_key\", \"=\", \"u.source_key\"),\n\t\t\t)\n\t\t\t.leftJoin(\"_emdash_media_usage_generation_writes as writer\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"writer.source_key\", \"=\", \"u.source_key\")\n\t\t\t\t\t.onRef(\"writer.generation\", \"=\", \"u.generation\"),\n\t\t\t)\n\t\t\t.select(\"u.id\")\n\t\t\t.where(\"u.created_at\", \"<\", cutoff)\n\t\t\t.whereRef(\"u.generation\", \"!=\", \"s.current_generation\")\n\t\t\t.whereRef(\"u.created_at\", \">=\", \"s.indexed_at\")\n\t\t\t.where(this.noActiveGenerationWriteExpression(\"u\"))\n\t\t\t.orderBy(\"u.created_at\", \"asc\")\n\t\t\t.orderBy(\"u.id\", \"asc\")\n\t\t\t.limit(batchLimit)\n\t\t\t.execute();\n\n\t\treturn this.deleteAbandonedCandidateIds(\n\t\t\trows.map((row) => row.id),\n\t\t\tcutoff,\n\t\t\toptions.cleanupLease,\n\t\t\toptions.canIssueStatement,\n\t\t);\n\t}\n\n\tasync deleteExpiredGenerationWriteLeases(\n\t\tlimit: number,\n\t\tcleanupLease?: MediaUsageCleanupLease,\n\t\tcanIssueStatement?: () => boolean,\n\t): Promise<number> {\n\t\tconst batchLimit = Math.floor(limit);\n\t\tif (batchLimit <= 0) return 0;\n\t\tif (!(await this.admitCleanupScan(cleanupLease, canIssueStatement))) return 0;\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_generation_writes\")\n\t\t\t.select(\"lease_token\")\n\t\t\t.where(this.generationWriteLeaseHasExpired(\"expires_at\"))\n\t\t\t.orderBy(\"expires_at\", \"asc\")\n\t\t\t.orderBy(\"lease_token\", \"asc\")\n\t\t\t.limit(batchLimit)\n\t\t\t.execute();\n\t\tif (rows.length === 0 || !canIssueCleanupStatement(canIssueStatement)) return 0;\n\t\tlet deleteQuery = this.db\n\t\t\t.deleteFrom(\"_emdash_media_usage_generation_writes\")\n\t\t\t.where(\n\t\t\t\t\"lease_token\",\n\t\t\t\t\"in\",\n\t\t\t\trows.map((row) => row.lease_token),\n\t\t\t)\n\t\t\t.where(this.generationWriteLeaseHasExpired(\"expires_at\"));\n\t\tif (cleanupLease)\n\t\t\tdeleteQuery = deleteQuery.where(this.activeCleanupLeaseExpression(cleanupLease));\n\t\tconst result = await deleteQuery.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows ?? 0);\n\t}\n\n\tasync upsertIndexStatus(input: MediaUsageIndexStatusInput): Promise<MediaUsageIndexStatus> {\n\t\tconst now = input.updatedAt ?? new Date().toISOString();\n\t\tconst row = {\n\t\t\tadapter_id: input.adapterId,\n\t\t\tscope_type: input.scopeType,\n\t\t\tscope_key: input.scopeKey,\n\t\t\tstatus: input.status,\n\t\t\tschema_version: input.schemaVersion ?? 1,\n\t\t\tstarted_at: input.startedAt ?? null,\n\t\t\tcompleted_at: input.completedAt ?? null,\n\t\t\tcursor: input.cursor ?? null,\n\t\t\tindexed_source_count: input.indexedSourceCount ?? 0,\n\t\t\tfailed_source_count: input.failedSourceCount ?? 0,\n\t\t\tlast_error_code: input.lastErrorCode ?? null,\n\t\t\tupdated_at: now,\n\t\t};\n\n\t\tawait this.db\n\t\t\t.insertInto(\"_emdash_media_usage_index_status\")\n\t\t\t.values(row)\n\t\t\t.onConflict((oc) =>\n\t\t\t\toc.columns([\"adapter_id\", \"scope_type\", \"scope_key\"]).doUpdateSet({\n\t\t\t\t\tstatus: row.status,\n\t\t\t\t\tschema_version: row.schema_version,\n\t\t\t\t\tstarted_at: row.started_at,\n\t\t\t\t\tcompleted_at: row.completed_at,\n\t\t\t\t\tcursor: row.cursor,\n\t\t\t\t\tindexed_source_count: row.indexed_source_count,\n\t\t\t\t\tfailed_source_count: row.failed_source_count,\n\t\t\t\t\tlast_error_code: row.last_error_code,\n\t\t\t\t\tupdated_at: row.updated_at,\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.execute();\n\n\t\tconst status = await this.findIndexStatus(input);\n\t\tif (!status) {\n\t\t\tthrow new Error(\n\t\t\t\t`Media usage index status ${input.adapterId}:${input.scopeType}:${input.scopeKey} was not persisted`,\n\t\t\t);\n\t\t}\n\t\treturn status;\n\t}\n\n\tasync invalidateIndexStatusForSchemaChange(collectionSlug: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status as status\")\n\t\t\t.set({\n\t\t\t\tchange_epoch: sql<number>`change_epoch + 1`,\n\t\t\t\tstatus: \"stale\",\n\t\t\t\tcompleted_at: null,\n\t\t\t\tcursor: null,\n\t\t\t\tlast_error_code: \"CONTENT_USAGE_STALE\",\n\t\t\t\treconciliation_required: 1,\n\t\t\t\tupdated_at: this.sortableUtcTimestamp(),\n\t\t\t})\n\t\t\t.where(\"status.adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"status.scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"status.scope_key\", \"=\", collectionSlug)\n\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_collections as collection\")\n\t\t\t\t\t\t.select(\"collection.id\")\n\t\t\t\t\t\t.whereRef(\"collection.id\", \"=\", \"status.collection_id\")\n\t\t\t\t\t\t.whereRef(\"collection.slug\", \"=\", \"status.scope_key\"),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_activation AS activation\n\t\t\t\t\tWHERE activation.task_key = 'incremental_capture'\n\t\t\t\t\t\tAND activation.state = 'active'\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync beginIndexStatusRepair(\n\t\tinput: MediaUsageIndexStatusRepairInput,\n\t): Promise<MediaUsageIndexStatus> {\n\t\treturn this.upsertIndexStatus({\n\t\t\tadapterId: input.adapterId,\n\t\t\tscopeType: input.scopeType,\n\t\t\tscopeKey: input.scopeKey,\n\t\t\tstatus: \"running\",\n\t\t\tschemaVersion: input.schemaVersion,\n\t\t\tstartedAt: input.startedAt,\n\t\t\tcompletedAt: null,\n\t\t\tcursor: input.runToken,\n\t\t\tindexedSourceCount: 0,\n\t\t\tfailedSourceCount: 0,\n\t\t\tlastErrorCode: null,\n\t\t\tupdatedAt: input.updatedAt,\n\t\t});\n\t}\n\n\tasync finalizeIndexStatusRepairIfRunning(\n\t\tinput: MediaUsageIndexStatusFinalizeInput,\n\t): Promise<MediaUsageGuardedIndexStatusResult> {\n\t\tconst updates: Updateable<MediaUsageIndexStatusTable> = {\n\t\t\tstatus: input.status,\n\t\t\tcompleted_at: input.completedAt,\n\t\t\tcursor: null,\n\t\t\tindexed_source_count: input.indexedSourceCount ?? 0,\n\t\t\tfailed_source_count: input.failedSourceCount ?? 0,\n\t\t\tlast_error_code: input.lastErrorCode ?? null,\n\t\t\tupdated_at: input.updatedAt ?? new Date().toISOString(),\n\t\t};\n\t\tif (input.schemaVersion !== undefined) updates.schema_version = input.schemaVersion;\n\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status\")\n\t\t\t.set(updates)\n\t\t\t.where(\"adapter_id\", \"=\", input.adapterId)\n\t\t\t.where(\"scope_type\", \"=\", input.scopeType)\n\t\t\t.where(\"scope_key\", \"=\", input.scopeKey)\n\t\t\t.where(\"status\", \"=\", \"running\")\n\t\t\t.where(\"cursor\", \"=\", input.runToken)\n\t\t\t.executeTakeFirst();\n\t\tconst finalized = Number(result.numUpdatedRows ?? 0) > 0;\n\n\t\treturn {\n\t\t\tfinalized,\n\t\t\tstatus: await this.findIndexStatus(input),\n\t\t};\n\t}\n\n\tasync beginIndexStatusRepairAtCurrentEpoch(\n\t\tinput: MediaUsageIndexStatusEpochRepairInput,\n\t): Promise<MediaUsageIndexStatusEpochRepairRun | null> {\n\t\tconst now = this.sortableUtcTimestamp();\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status\")\n\t\t\t.set({\n\t\t\t\tstatus: \"running\",\n\t\t\t\tschema_version: input.schemaVersion,\n\t\t\t\tstarted_at: now,\n\t\t\t\tcompleted_at: null,\n\t\t\t\tcursor: input.runToken,\n\t\t\t\tindexed_source_count: 0,\n\t\t\t\tfailed_source_count: 0,\n\t\t\t\tlast_error_code: null,\n\t\t\t\treconciliation_required: 1,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"adapter_id\", \"=\", input.adapterId)\n\t\t\t.where(\"scope_type\", \"=\", input.scopeType)\n\t\t\t.where(\"scope_key\", \"=\", input.scopeKey)\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"capture_state\", \"=\", \"active\")\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = ${input.collectionId}\n\t\t\t\t\t\tAND collection.slug = ${input.scopeKey}\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_activation AS activation\n\t\t\t\t\tWHERE activation.task_key = 'incremental_capture'\n\t\t\t\t\t\tAND activation.state = 'active'\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.returning([\"change_epoch\", \"started_at\"])\n\t\t\t.executeTakeFirst();\n\t\tif (!row?.started_at) return null;\n\t\treturn { changeEpoch: row.change_epoch, startedAt: row.started_at };\n\t}\n\n\tasync finalizeIndexStatusRepairAtEpoch(\n\t\tinput: MediaUsageIndexStatusEpochFinalizeInput,\n\t): Promise<MediaUsageGuardedIndexStatusResult> {\n\t\tconst now = this.sortableUtcTimestamp();\n\t\tconst updates = {\n\t\t\tstatus: input.status,\n\t\t\tschema_version: input.schemaVersion,\n\t\t\tcompleted_at: now,\n\t\t\tcursor: null,\n\t\t\tindexed_source_count: input.indexedSourceCount,\n\t\t\tfailed_source_count: input.failedSourceCount,\n\t\t\tlast_error_code: input.lastErrorCode,\n\t\t\treconciliation_required: input.status === \"complete\" ? 0 : 1,\n\t\t\tupdated_at: now,\n\t\t};\n\n\t\tlet query = this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status\")\n\t\t\t.set(updates)\n\t\t\t.where(\"adapter_id\", \"=\", input.adapterId)\n\t\t\t.where(\"scope_type\", \"=\", input.scopeType)\n\t\t\t.where(\"scope_key\", \"=\", input.scopeKey)\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"status\", \"=\", \"running\")\n\t\t\t.where(\"cursor\", \"=\", input.runToken)\n\t\t\t.where(\"change_epoch\", \"=\", input.startingEpoch)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = ${input.collectionId}\n\t\t\t\t\t\tAND collection.slug = ${input.scopeKey}\n\t\t\t\t)`,\n\t\t\t);\n\t\tif (input.status === \"complete\") {\n\t\t\tquery = query.where(\n\t\t\t\tsql<boolean>`NOT EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_work AS work\n\t\t\t\t\tWHERE work.collection_id = ${input.collectionId}\n\t\t\t\t)`,\n\t\t\t);\n\t\t}\n\t\tconst result = await query.executeTakeFirst();\n\t\tconst finalized = Number(result.numUpdatedRows ?? 0) > 0;\n\n\t\tif (!finalized) {\n\t\t\tawait this.db\n\t\t\t\t.updateTable(\"_emdash_media_usage_index_status\")\n\t\t\t\t.set({\n\t\t\t\t\tstatus: \"stale\",\n\t\t\t\t\tcompleted_at: null,\n\t\t\t\t\tcursor: null,\n\t\t\t\t\tlast_error_code: \"CONTENT_USAGE_REPAIR_CONFLICT\",\n\t\t\t\t\treconciliation_required: 1,\n\t\t\t\t\tupdated_at: this.sortableUtcTimestamp(),\n\t\t\t\t})\n\t\t\t\t.where(\"adapter_id\", \"=\", input.adapterId)\n\t\t\t\t.where(\"scope_type\", \"=\", input.scopeType)\n\t\t\t\t.where(\"scope_key\", \"=\", input.scopeKey)\n\t\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t\t.where(\"status\", \"=\", \"running\")\n\t\t\t\t.where(\"cursor\", \"=\", input.runToken)\n\t\t\t\t.execute();\n\t\t}\n\n\t\treturn {\n\t\t\tfinalized,\n\t\t\tstatus: await this.findIndexStatusForCollection(input, input.collectionId),\n\t\t};\n\t}\n\n\tasync recordIncrementalSuccess(input: MediaUsageIncrementalStatusIdentity): Promise<boolean> {\n\t\tconst observed = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_index_status\")\n\t\t\t.select(\"change_epoch\")\n\t\t\t.where(\"adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"scope_key\", \"=\", input.collectionSlug)\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"capture_state\", \"=\", \"active\")\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = ${input.collectionId}\n\t\t\t\t\t\tAND collection.slug = ${input.collectionSlug}\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\tif (!observed) return false;\n\n\t\tconst canComplete = sql<boolean>`(\n\t\t\treconciliation_required = 0\n\t\t\tAND status IN ('complete', 'stale', 'partial')\n\t\t\tAND NOT EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_media_usage_work AS work\n\t\t\t\tWHERE work.collection_id = ${input.collectionId}\n\t\t\t)\n\t\t)`;\n\t\tconst now = this.sortableUtcTimestamp();\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status\")\n\t\t\t.set({\n\t\t\t\tstatus: sql<string>`CASE WHEN ${canComplete} THEN 'complete' ELSE status END`,\n\t\t\t\tcompleted_at: sql<\n\t\t\t\t\tstring | null\n\t\t\t\t>`CASE WHEN ${canComplete} THEN ${now} ELSE completed_at END`,\n\t\t\t\tlast_error_code: sql<\n\t\t\t\t\tstring | null\n\t\t\t\t>`CASE WHEN ${canComplete} THEN NULL ELSE last_error_code END`,\n\t\t\t\tcursor: sql<string | null>`CASE WHEN ${canComplete} THEN NULL ELSE cursor END`,\n\t\t\t\tlast_incremental_success_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"scope_key\", \"=\", input.collectionSlug)\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"change_epoch\", \"=\", observed.change_epoch)\n\t\t\t.where(\"capture_state\", \"=\", \"active\")\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = ${input.collectionId}\n\t\t\t\t\t\tAND collection.slug = ${input.collectionSlug}\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0;\n\t}\n\n\tasync prepareIncrementalFinalization(\n\t\tinput: MediaUsageIncrementalStatusIdentity,\n\t): Promise<\n\t\t{ outcome: \"marked\"; marker: string } | { outcome: \"not_required\" } | { outcome: \"lost\" }\n\t> {\n\t\tconst observed = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_index_status\")\n\t\t\t.select([\"change_epoch\", \"reconciliation_required\"])\n\t\t\t.where(\"adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"scope_key\", \"=\", input.collectionSlug)\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"capture_state\", \"=\", \"active\")\n\t\t\t.executeTakeFirst();\n\t\tif (!observed) return { outcome: \"lost\" };\n\t\tif (observed.reconciliation_required !== 0) return { outcome: \"not_required\" };\n\t\tconst marker = `incremental-finalize:${String(observed.change_epoch)}:${ulid()}`;\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status\")\n\t\t\t.set({ cursor: marker, updated_at: this.sortableUtcTimestamp() })\n\t\t\t.where(\"adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"scope_key\", \"=\", input.collectionSlug)\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"capture_state\", \"=\", \"active\")\n\t\t\t.where(\"reconciliation_required\", \"=\", 0)\n\t\t\t.where(\"change_epoch\", \"=\", observed.change_epoch)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = ${input.collectionId}\n\t\t\t\t\t\tAND collection.slug = ${input.collectionSlug}\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`NOT EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\tWHERE deletion.collection_id = ${input.collectionId}\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0\n\t\t\t? { outcome: \"marked\", marker }\n\t\t\t: { outcome: \"lost\" };\n\t}\n\n\tasync recoverIncrementalFinalizations(): Promise<number> {\n\t\tconst markerMatchesEpoch = isPostgres(this.db)\n\t\t\t? sql<boolean>`status.cursor LIKE ('incremental-finalize:' || status.change_epoch::text || ':%')`\n\t\t\t: sql<boolean>`status.cursor LIKE ('incremental-finalize:' || CAST(status.change_epoch AS text) || ':%')`;\n\t\tconst now = new Date().toISOString();\n\t\tconst result = await sql<{ collection_id: string }>`\n\t\t\tUPDATE _emdash_media_usage_index_status AS status\n\t\t\tSET status = 'complete',\n\t\t\t\tcompleted_at = ${now},\n\t\t\t\tcursor = NULL,\n\t\t\t\tlast_error_code = NULL,\n\t\t\t\tlast_incremental_success_at = ${now},\n\t\t\t\tupdated_at = ${now}\n\t\t\tWHERE status.adapter_id = 'content-media'\n\t\t\t\tAND status.scope_type = 'collection'\n\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\tAND status.reconciliation_required = 0\n\t\t\t\tAND status.cursor IS NOT NULL\n\t\t\t\tAND ${markerMatchesEpoch}\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = status.collection_id\n\t\t\t\t\t\tAND collection.slug = status.scope_key\n\t\t\t\t)\n\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\tWHERE deletion.collection_id = status.collection_id\n\t\t\t\t)\n\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_work AS work\n\t\t\t\t\tWHERE work.collection_id = status.collection_id\n\t\t\t\t)\n\t\t\tRETURNING collection_id\n\t\t`.execute(this.db);\n\t\treturn result.rows.length;\n\t}\n\n\tasync recordIncrementalFailure(\n\t\tinput: MediaUsageIncrementalStatusIdentity & {\n\t\t\tcontentId: string;\n\t\t\tworkVersion: number | string;\n\t\t\terrorCode: string;\n\t\t},\n\t): Promise<boolean> {\n\t\tconst now = this.sortableUtcTimestamp();\n\t\tconst automaticRunOwnsCoverage = sql<boolean>`EXISTS (\n\t\t\tSELECT 1\n\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\tWHERE reconciliation.collection_id = ${input.collectionId}\n\t\t\t\tAND reconciliation.run_token = cursor\n\t\t)`;\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status\")\n\t\t\t.set({\n\t\t\t\tstatus: sql<string>`CASE\n\t\t\t\t\tWHEN ${automaticRunOwnsCoverage} THEN status\n\t\t\t\t\tWHEN reconciliation_required = 0 THEN 'partial'\n\t\t\t\t\tWHEN status = 'running' THEN 'stale'\n\t\t\t\t\tELSE status\n\t\t\t\tEND`,\n\t\t\t\tcompleted_at: sql<string | null>`CASE\n\t\t\t\t\tWHEN ${automaticRunOwnsCoverage} THEN completed_at\n\t\t\t\t\tWHEN reconciliation_required = 0 OR status = 'running' THEN NULL\n\t\t\t\t\tELSE completed_at\n\t\t\t\tEND`,\n\t\t\t\tcursor: sql<string | null>`CASE\n\t\t\t\t\tWHEN ${automaticRunOwnsCoverage} THEN cursor\n\t\t\t\t\tWHEN status = 'running' THEN NULL\n\t\t\t\t\tELSE cursor\n\t\t\t\tEND`,\n\t\t\t\tlast_error_code: input.errorCode,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"scope_key\", \"=\", input.collectionSlug)\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_work AS work\n\t\t\t\t\tWHERE work.collection_id = ${input.collectionId}\n\t\t\t\t\t\tAND work.content_id = ${input.contentId}\n\t\t\t\t\t\tAND work.work_version = ${input.workVersion}\n\t\t\t\t\t\tAND work.state = 'failed'\n\t\t\t\t\t\tAND work.last_error_code = ${input.errorCode}\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = ${input.collectionId}\n\t\t\t\t\t\tAND collection.slug = ${input.collectionSlug}\n\t\t\t\t)`,\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0;\n\t}\n\n\tasync recordIncrementalFailuresByCollection(input: {\n\t\tcollectionIds: readonly string[];\n\t\terrorCode: string;\n\t}): Promise<Set<string>> {\n\t\tconst collectionIds = [...new Set(input.collectionIds)];\n\t\tif (collectionIds.length === 0) return new Set();\n\t\tconst collections = jsonTextValues(this.db, collectionIds);\n\t\tconst now = new Date().toISOString();\n\t\tconst result = await sql<{ collection_id: string }>`\n\t\t\tWITH failed_collections AS (${collections})\n\t\t\tUPDATE _emdash_media_usage_index_status AS status\n\t\t\tSET status = CASE\n\t\t\t\t\tWHEN EXISTS (\n\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\t\t\tWHERE reconciliation.collection_id = status.collection_id\n\t\t\t\t\t\t\tAND reconciliation.run_token = status.cursor\n\t\t\t\t\t) THEN status.status\n\t\t\t\t\tWHEN status.reconciliation_required = 0 THEN 'partial'\n\t\t\t\t\tWHEN status.status = 'running' THEN 'stale'\n\t\t\t\t\tELSE status.status\n\t\t\t\tEND,\n\t\t\t\tcompleted_at = CASE\n\t\t\t\t\tWHEN EXISTS (\n\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\t\t\tWHERE reconciliation.collection_id = status.collection_id\n\t\t\t\t\t\t\tAND reconciliation.run_token = status.cursor\n\t\t\t\t\t) THEN status.completed_at\n\t\t\t\t\tWHEN status.reconciliation_required = 0 OR status.status = 'running' THEN NULL\n\t\t\t\t\tELSE status.completed_at\n\t\t\t\tEND,\n\t\t\t\tcursor = CASE\n\t\t\t\t\tWHEN EXISTS (\n\t\t\t\t\t\tSELECT 1\n\t\t\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\t\t\tWHERE reconciliation.collection_id = status.collection_id\n\t\t\t\t\t\t\tAND reconciliation.run_token = status.cursor\n\t\t\t\t\t) THEN status.cursor\n\t\t\t\t\tWHEN status.status = 'running' THEN NULL\n\t\t\t\t\tELSE status.cursor\n\t\t\t\tEND,\n\t\t\t\tlast_error_code = ${input.errorCode},\n\t\t\t\tupdated_at = ${now}\n\t\t\tWHERE status.adapter_id = 'content-media'\n\t\t\t\tAND status.scope_type = 'collection'\n\t\t\t\tAND status.collection_id IN (SELECT value FROM failed_collections)\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_work AS work\n\t\t\t\t\tWHERE work.collection_id = status.collection_id\n\t\t\t\t\t\tAND work.state = 'failed'\n\t\t\t\t\t\tAND work.last_error_code = ${input.errorCode}\n\t\t\t\t)\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_collections AS collection\n\t\t\t\t\tWHERE collection.id = status.collection_id\n\t\t\t\t\t\tAND collection.slug = status.scope_key\n\t\t\t\t)\n\t\t\tRETURNING collection_id\n\t\t`.execute(this.db);\n\t\treturn new Set(result.rows.map((row) => row.collection_id));\n\t}\n\n\tasync findIndexStatus(\n\t\tidentity: MediaUsageIndexStatusIdentity,\n\t): Promise<MediaUsageIndexStatus | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_index_status\")\n\t\t\t.selectAll()\n\t\t\t.where(\"adapter_id\", \"=\", identity.adapterId)\n\t\t\t.where(\"scope_type\", \"=\", identity.scopeType)\n\t\t\t.where(\"scope_key\", \"=\", identity.scopeKey)\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? rowToIndexStatus(row) : null;\n\t}\n\n\tprivate async findIndexStatusForCollection(\n\t\tidentity: MediaUsageIndexStatusIdentity,\n\t\tcollectionId: string,\n\t): Promise<MediaUsageIndexStatus | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_index_status\")\n\t\t\t.selectAll()\n\t\t\t.where(\"adapter_id\", \"=\", identity.adapterId)\n\t\t\t.where(\"scope_type\", \"=\", identity.scopeType)\n\t\t\t.where(\"scope_key\", \"=\", identity.scopeKey)\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToIndexStatus(row) : null;\n\t}\n\n\tasync deleteIndexStatus(\n\t\tidentity: MediaUsageIndexStatusIdentity,\n\t\tcollectionId?: string,\n\t): Promise<number> {\n\t\tlet query = this.db\n\t\t\t.deleteFrom(\"_emdash_media_usage_index_status\")\n\t\t\t.where(\"adapter_id\", \"=\", identity.adapterId)\n\t\t\t.where(\"scope_type\", \"=\", identity.scopeType)\n\t\t\t.where(\"scope_key\", \"=\", identity.scopeKey);\n\t\tif (collectionId !== undefined) query = query.where(\"collection_id\", \"=\", collectionId);\n\t\tconst result = await query.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows ?? 0);\n\t}\n\n\tprivate sortableUtcTimestamp(): RawBuilder<string> {\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<string>`to_char(clock_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`\n\t\t\t: sql<string>`strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate async findCurrentUsagePage(\n\t\tapplyFilter: (\n\t\t\tquery: ReturnType<MediaUsageRepository[\"currentUsageBaseQuery\"]>,\n\t\t) => ReturnType<MediaUsageRepository[\"currentUsageBaseQuery\"]>,\n\t\toptions: FindMediaUsageOptions,\n\t): Promise<FindManyResult<MediaUsageRecord>> {\n\t\tconst limit = Math.min(Math.max(1, options.limit ?? 50), 100);\n\t\tlet query = applyFilter(this.currentUsageBaseQuery())\n\t\t\t.orderBy(\"u.id\", \"asc\")\n\t\t\t.limit(limit + 1);\n\n\t\tif (options.cursor) {\n\t\t\tconst { id } = decodeCursor(options.cursor);\n\t\t\tquery = query.where(\"u.id\", \">\", id);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst items = rows.slice(0, limit).map(rowToUsageRecord);\n\t\tconst result: FindManyResult<MediaUsageRecord> = { items };\n\n\t\tif (rows.length > limit && items.length > 0) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.occurrence.id, last.occurrence.id);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate currentUsageBaseQuery() {\n\t\treturn this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources as s\")\n\t\t\t.innerJoin(\"_emdash_media_usage as u\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"u.source_key\", \"=\", \"s.source_key\")\n\t\t\t\t\t.onRef(\"u.generation\", \"=\", \"s.current_generation\"),\n\t\t\t)\n\t\t\t.select(currentUsageSelect);\n\t}\n\n\tprivate currentContentMediaUsageBaseQuery() {\n\t\treturn this.db\n\t\t\t.selectFrom(\"_emdash_media_usage as u\")\n\t\t\t.crossJoin(\"_emdash_media_usage_sources as s\")\n\t\t\t.innerJoin(\"_emdash_collections as collection\", \"collection.slug\", \"s.collection_slug\")\n\t\t\t.whereRef(\"s.source_key\", \"=\", \"u.source_key\")\n\t\t\t.whereRef(\"s.current_generation\", \"=\", \"u.generation\")\n\t\t\t.where(\"s.source_type\", \"=\", \"content\")\n\t\t\t.where(\"s.collection_slug\", \"is not\", null)\n\t\t\t.where(\"s.content_id\", \"is not\", null)\n\t\t\t.where(\"s.source_variant\", \"in\", [\"columns\", \"draft_overlay\"])\n\t\t\t.where(contentSourceMatchesActiveCollection(\"s\", \"collection.id\"))\n\t\t\t.where(CONTENT_SOURCE_ELIGIBILITY);\n\t}\n\n\tprivate async deleteOrphanCandidateIds(\n\t\tids: readonly string[],\n\t\tcutoff: string,\n\t\tcleanupLease?: MediaUsageCleanupLease,\n\t\tcanIssueStatement?: () => boolean,\n\t): Promise<number> {\n\t\tlet deleted = 0;\n\t\tfor (const idBatch of chunks([...ids], cleanupDeleteBatchSize(cleanupLease))) {\n\t\t\tif (!canIssueCleanupStatement(canIssueStatement)) break;\n\t\t\tif (cleanupLease) {\n\t\t\t\tawait this.markOrphanCandidatesForCleanup(idBatch, cutoff, cleanupLease);\n\t\t\t\tif (!canIssueCleanupStatement(canIssueStatement)) break;\n\t\t\t}\n\t\t\tlet query = this.db\n\t\t\t\t.deleteFrom(\"_emdash_media_usage\")\n\t\t\t\t.where(\"id\", \"in\", idBatch)\n\t\t\t\t.where(\"created_at\", \"<\", cutoff)\n\t\t\t\t.where(\n\t\t\t\t\tsql<boolean>`NOT EXISTS (SELECT 1 FROM _emdash_media_usage_sources source WHERE source.source_key = _emdash_media_usage.source_key)`,\n\t\t\t\t)\n\t\t\t\t.where(this.noActiveGenerationWriteExpression());\n\t\t\tif (cleanupLease) {\n\t\t\t\tquery = query\n\t\t\t\t\t.where(\"cleanup_lease_token\", \"=\", cleanupLease.leaseToken)\n\t\t\t\t\t.where(this.activeCleanupLeaseExpression(cleanupLease));\n\t\t\t}\n\t\t\tconst result = await query.executeTakeFirst();\n\t\t\tdeleted += Number(result.numDeletedRows ?? 0);\n\t\t}\n\t\treturn deleted;\n\t}\n\n\tprivate async deleteStaleCandidateIds(\n\t\tids: readonly string[],\n\t\tcutoff: string,\n\t\tcleanupLease?: MediaUsageCleanupLease,\n\t\tcanIssueStatement?: () => boolean,\n\t): Promise<number> {\n\t\tlet deleted = 0;\n\t\tfor (const idBatch of chunks([...ids], cleanupDeleteBatchSize(cleanupLease))) {\n\t\t\tif (!canIssueCleanupStatement(canIssueStatement)) break;\n\t\t\tif (cleanupLease) {\n\t\t\t\tawait this.markStaleCandidatesForCleanup(idBatch, cutoff, cleanupLease);\n\t\t\t\tif (!canIssueCleanupStatement(canIssueStatement)) break;\n\t\t\t}\n\t\t\tlet query = this.db\n\t\t\t\t.deleteFrom(\"_emdash_media_usage\")\n\t\t\t\t.where(\"id\", \"in\", idBatch)\n\t\t\t\t.where(\"created_at\", \"<\", cutoff)\n\t\t\t\t.where((eb) =>\n\t\t\t\t\teb.exists(\n\t\t\t\t\t\teb\n\t\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_sources as source\")\n\t\t\t\t\t\t\t.select(\"source.source_key\")\n\t\t\t\t\t\t\t.whereRef(\"source.source_key\", \"=\", \"_emdash_media_usage.source_key\")\n\t\t\t\t\t\t\t.whereRef(\"source.current_generation\", \"!=\", \"_emdash_media_usage.generation\")\n\t\t\t\t\t\t\t.whereRef(\"_emdash_media_usage.created_at\", \"<\", \"source.indexed_at\"),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.where(this.noActiveGenerationWriteExpression());\n\t\t\tif (cleanupLease) {\n\t\t\t\tquery = query\n\t\t\t\t\t.where(\"cleanup_lease_token\", \"=\", cleanupLease.leaseToken)\n\t\t\t\t\t.where(this.activeCleanupLeaseExpression(cleanupLease));\n\t\t\t}\n\t\t\tconst result = await query.executeTakeFirst();\n\t\t\tdeleted += Number(result.numDeletedRows ?? 0);\n\t\t}\n\t\treturn deleted;\n\t}\n\n\tprivate async deleteAbandonedCandidateIds(\n\t\tids: readonly string[],\n\t\tcutoff: string,\n\t\tcleanupLease?: MediaUsageCleanupLease,\n\t\tcanIssueStatement?: () => boolean,\n\t): Promise<number> {\n\t\tlet deleted = 0;\n\t\tfor (const idBatch of chunks([...ids], cleanupDeleteBatchSize(cleanupLease))) {\n\t\t\tif (!canIssueCleanupStatement(canIssueStatement)) break;\n\t\t\tif (cleanupLease) {\n\t\t\t\tawait this.markAbandonedCandidatesForCleanup(idBatch, cutoff, cleanupLease);\n\t\t\t\tif (!canIssueCleanupStatement(canIssueStatement)) break;\n\t\t\t}\n\t\t\tlet query = this.db\n\t\t\t\t.deleteFrom(\"_emdash_media_usage\")\n\t\t\t\t.where(\"id\", \"in\", idBatch)\n\t\t\t\t.where(\"created_at\", \"<\", cutoff)\n\t\t\t\t.where((eb) =>\n\t\t\t\t\teb.exists(\n\t\t\t\t\t\teb\n\t\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_sources as source\")\n\t\t\t\t\t\t\t.select(\"source.source_key\")\n\t\t\t\t\t\t\t.whereRef(\"source.source_key\", \"=\", \"_emdash_media_usage.source_key\")\n\t\t\t\t\t\t\t.whereRef(\"source.current_generation\", \"!=\", \"_emdash_media_usage.generation\")\n\t\t\t\t\t\t\t.whereRef(\"_emdash_media_usage.created_at\", \">=\", \"source.indexed_at\"),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.where(this.noActiveGenerationWriteExpression());\n\t\t\tif (cleanupLease) {\n\t\t\t\tquery = query\n\t\t\t\t\t.where(\"cleanup_lease_token\", \"=\", cleanupLease.leaseToken)\n\t\t\t\t\t.where(this.activeCleanupLeaseExpression(cleanupLease));\n\t\t\t}\n\t\t\tconst result = await query.executeTakeFirst();\n\t\t\tdeleted += Number(result.numDeletedRows ?? 0);\n\t\t}\n\t\treturn deleted;\n\t}\n\n\tprivate async markOrphanCandidatesForCleanup(\n\t\tids: readonly string[],\n\t\tcutoff: string,\n\t\tcleanupLease: MediaUsageCleanupLease,\n\t): Promise<void> {\n\t\tawait this.db\n\t\t\t.updateTable(\"_emdash_media_usage\")\n\t\t\t.set({ cleanup_lease_token: cleanupLease.leaseToken })\n\t\t\t.where(\"id\", \"in\", ids)\n\t\t\t.where(\"created_at\", \"<\", cutoff)\n\t\t\t.where(\n\t\t\t\tsql<boolean>`NOT EXISTS (SELECT 1 FROM _emdash_media_usage_sources source WHERE source.source_key = _emdash_media_usage.source_key)`,\n\t\t\t)\n\t\t\t.where(this.noActiveGenerationWriteExpression())\n\t\t\t.where(this.activeCleanupLeaseExpression(cleanupLease))\n\t\t\t.execute();\n\t}\n\n\tprivate async markStaleCandidatesForCleanup(\n\t\tids: readonly string[],\n\t\tcutoff: string,\n\t\tcleanupLease: MediaUsageCleanupLease,\n\t): Promise<void> {\n\t\tawait this.db\n\t\t\t.updateTable(\"_emdash_media_usage\")\n\t\t\t.set({ cleanup_lease_token: cleanupLease.leaseToken })\n\t\t\t.where(\"id\", \"in\", ids)\n\t\t\t.where(\"created_at\", \"<\", cutoff)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_sources as source\")\n\t\t\t\t\t\t.select(\"source.source_key\")\n\t\t\t\t\t\t.whereRef(\"source.source_key\", \"=\", \"_emdash_media_usage.source_key\")\n\t\t\t\t\t\t.whereRef(\"source.current_generation\", \"!=\", \"_emdash_media_usage.generation\")\n\t\t\t\t\t\t.whereRef(\"_emdash_media_usage.created_at\", \"<\", \"source.indexed_at\"),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.where(this.noActiveGenerationWriteExpression())\n\t\t\t.where(this.activeCleanupLeaseExpression(cleanupLease))\n\t\t\t.execute();\n\t}\n\n\tprivate async markAbandonedCandidatesForCleanup(\n\t\tids: readonly string[],\n\t\tcutoff: string,\n\t\tcleanupLease: MediaUsageCleanupLease,\n\t): Promise<void> {\n\t\tawait this.db\n\t\t\t.updateTable(\"_emdash_media_usage\")\n\t\t\t.set({ cleanup_lease_token: cleanupLease.leaseToken })\n\t\t\t.where(\"id\", \"in\", ids)\n\t\t\t.where(\"created_at\", \"<\", cutoff)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_sources as source\")\n\t\t\t\t\t\t.select(\"source.source_key\")\n\t\t\t\t\t\t.whereRef(\"source.source_key\", \"=\", \"_emdash_media_usage.source_key\")\n\t\t\t\t\t\t.whereRef(\"source.current_generation\", \"!=\", \"_emdash_media_usage.generation\")\n\t\t\t\t\t\t.whereRef(\"_emdash_media_usage.created_at\", \">=\", \"source.indexed_at\"),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.where(this.noActiveGenerationWriteExpression())\n\t\t\t.where(this.activeCleanupLeaseExpression(cleanupLease))\n\t\t\t.execute();\n\t}\n\n\tprivate noActiveGenerationWriteExpression(usageTable = \"_emdash_media_usage\") {\n\t\tconst sourceKey = sql.ref(`${usageTable}.source_key`);\n\t\tconst generation = sql.ref(`${usageTable}.generation`);\n\t\treturn sql<boolean>`NOT EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_media_usage_generation_writes AS writer\n\t\t\t\tWHERE writer.source_key = ${sourceKey}\n\t\t\t\t\tAND writer.generation = ${generation}\n\t\t\t\t\tAND ${this.generationWriteLeaseExpiryIsInFuture(\"writer.expires_at\")}\n\t\t\t)`;\n\t}\n\n\t/**\n\t * Gates a bounded cleanup scan on the lease and the tick's statement budget.\n\t *\n\t * The budget is re-read after the lease row because that read is itself a\n\t * statement: an isolate suspended across it can resume with the budget spent.\n\t */\n\tprivate async admitCleanupScan(\n\t\tcleanupLease: MediaUsageCleanupLease | undefined,\n\t\tcanIssueStatement: (() => boolean) | undefined,\n\t): Promise<boolean> {\n\t\tif (!canIssueCleanupStatement(canIssueStatement)) return false;\n\t\tif (!cleanupLease) return true;\n\t\treturn (\n\t\t\t(await this.holdsCleanupLease(cleanupLease)) && canIssueCleanupStatement(canIssueStatement)\n\t\t);\n\t}\n\n\t/**\n\t * Reads the lease row on its own so a lost lease can short-circuit a sweep.\n\t *\n\t * As a row-level `EXISTS` inside a `LIMIT`ed scan this predicate is constant\n\t * across every candidate row: when it is false the limit is unreachable and\n\t * the scan reads the whole `created_at` range before returning nothing.\n\t * Mutating statements still carry {@link activeCleanupLeaseExpression},\n\t * which is what actually fences a displaced owner.\n\t */\n\tprivate async holdsCleanupLease(cleanupLease: MediaUsageCleanupLease): Promise<boolean> {\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_cleanup\")\n\t\t\t.select(\"task_key\")\n\t\t\t.where(\"task_key\", \"=\", \"projection_gc\")\n\t\t\t.where(\"lease_token\", \"=\", cleanupLease.leaseToken)\n\t\t\t.where(this.cleanupLeaseExpiryIsInFuture(\"_emdash_media_usage_cleanup.lease_expires_at\"));\n\t\tif (isPostgres(this.db)) query = query.forUpdate();\n\t\treturn (await query.executeTakeFirst()) !== undefined;\n\t}\n\n\tprivate activeCleanupLeaseExpression(cleanupLease: MediaUsageCleanupLease) {\n\t\tconst rowLock = isPostgres(this.db) ? sql` FOR UPDATE` : sql``;\n\t\treturn sql<boolean>`EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_media_usage_cleanup AS cleanup\n\t\t\t\tWHERE cleanup.task_key = 'projection_gc'\n\t\t\t\t\tAND cleanup.lease_token = ${cleanupLease.leaseToken}\n\t\t\t\t\tAND ${this.cleanupLeaseExpiryIsInFuture(\"cleanup.lease_expires_at\")}\n\t\t\t\t${rowLock}\n\t\t\t)`;\n\t}\n\n\tprivate cleanupLeaseExpiryIsInFuture(column: string) {\n\t\tconst leaseExpiresAt = sql.ref(column);\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`${leaseExpiresAt}::timestamptz > clock_timestamp()`\n\t\t\t: sql<boolean>`${leaseExpiresAt} > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate cleanupTimestampIsDue(column: string) {\n\t\tconst timestamp = sql.ref(column);\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`${timestamp}::timestamptz <= clock_timestamp()`\n\t\t\t: sql<boolean>`${timestamp} <= strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate cleanupTimestampOffset(offsetSeconds: number): RawBuilder<string> {\n\t\tif (isPostgres(this.db)) {\n\t\t\treturn sql<string>`to_char(\n\t\t\t\t(clock_timestamp() AT TIME ZONE 'UTC') + (${offsetSeconds} * INTERVAL '1 second'),\n\t\t\t\t'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'\n\t\t\t)`;\n\t\t}\n\t\treturn sql<string>`strftime(\n\t\t\t'%Y-%m-%dT%H:%M:%fZ',\n\t\t\t'now',\n\t\t\t${`${offsetSeconds >= 0 ? \"+\" : \"\"}${offsetSeconds} seconds`}\n\t\t)`;\n\t}\n\n\tprivate generationWriteLeaseHasExpired(column: string) {\n\t\tconst leaseExpiresAt = sql.ref(column);\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`${leaseExpiresAt}::timestamptz <= clock_timestamp()`\n\t\t\t: sql<boolean>`${leaseExpiresAt} <= strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate async deleteSourceKeys(sourceKeys: readonly string[]): Promise<number> {\n\t\tconst uniqueSourceKeys = [...new Set(sourceKeys)];\n\t\tif (uniqueSourceKeys.length === 0) return 0;\n\n\t\treturn withTransaction(this.db, async (trx) => {\n\t\t\tawait this.lockCleanupBeforeSourceDelete(trx);\n\t\t\tlet deleted = 0;\n\t\t\tfor (const sourceKeyBatch of chunks(uniqueSourceKeys, SQL_BATCH_SIZE)) {\n\t\t\t\tconst result = await trx\n\t\t\t\t\t.deleteFrom(\"_emdash_media_usage_sources\")\n\t\t\t\t\t.where(\"source_key\", \"in\", sourceKeyBatch)\n\t\t\t\t\t.executeTakeFirst();\n\t\t\t\tdeleted += Number(result.numDeletedRows ?? 0);\n\n\t\t\t\tawait trx\n\t\t\t\t\t.updateTable(\"_emdash_media_usage\")\n\t\t\t\t\t.set({ cleanup_lease_token: null })\n\t\t\t\t\t.where(\"source_key\", \"in\", sourceKeyBatch)\n\t\t\t\t\t.execute();\n\t\t\t\tawait trx\n\t\t\t\t\t.deleteFrom(\"_emdash_media_usage\")\n\t\t\t\t\t.where(\"source_key\", \"in\", sourceKeyBatch)\n\t\t\t\t\t.execute();\n\t\t\t}\n\t\t\treturn deleted;\n\t\t});\n\t}\n\n\tprivate async deleteSourceGenerationOccurrences(\n\t\tdb: DatabaseExecutor,\n\t\tsourceKey: string,\n\t\tgeneration: string,\n\t): Promise<void> {\n\t\tawait db\n\t\t\t.updateTable(\"_emdash_media_usage\")\n\t\t\t.set({ cleanup_lease_token: null })\n\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t.where(\"generation\", \"=\", generation)\n\t\t\t.execute();\n\t\tawait db\n\t\t\t.deleteFrom(\"_emdash_media_usage\")\n\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t.where(\"generation\", \"=\", generation)\n\t\t\t.execute();\n\t}\n\n\tprivate async lockCleanupBeforeSourceDelete(db: DatabaseExecutor): Promise<void> {\n\t\tif (!isPostgres(this.db)) return;\n\t\tawait sql`\n\t\t\tSELECT 1\n\t\t\tFROM _emdash_media_usage_cleanup\n\t\t\tWHERE task_key = 'projection_gc'\n\t\t\tFOR SHARE\n\t\t`.execute(db);\n\t}\n\n\tprivate async insertOccurrences(\n\t\tdb: DatabaseExecutor,\n\t\tsourceKey: string,\n\t\tgeneration: string,\n\t\toccurrences: readonly MediaUsageOccurrenceInput[],\n\t\tnow: string,\n\t): Promise<void> {\n\t\tif (occurrences.length === 0) return;\n\n\t\tconst rows = occurrences.map((occurrence) => ({\n\t\t\tid: ulid(),\n\t\t\tsource_key: sourceKey,\n\t\t\tgeneration,\n\t\t\tfield_slug: occurrence.fieldSlug,\n\t\t\tfield_path: occurrence.fieldPath,\n\t\t\toccurrence_index: occurrence.occurrenceIndex ?? 0,\n\t\t\treference_type: occurrence.referenceType,\n\t\t\tmedia_id: occurrence.mediaId,\n\t\t\tprovider: occurrence.provider,\n\t\t\tprovider_asset_id: occurrence.providerAssetId,\n\t\t\tmedia_kind: occurrence.mediaKind ?? null,\n\t\t\tmime_type: occurrence.mimeType ?? null,\n\t\t\tcreated_at: now,\n\t\t}));\n\n\t\tfor (const rowBatch of chunks(rows, OCCURRENCE_INSERT_BATCH_SIZE)) {\n\t\t\tawait db.insertInto(\"_emdash_media_usage\").values(rowBatch).execute();\n\t\t}\n\t}\n\n\tprivate async insertBatchOccurrences(rows: readonly BatchOccurrenceRow[]): Promise<void> {\n\t\tfor (const rowBatch of chunkJsonRows(rows)) {\n\t\t\tconst input = this.occurrenceBatchInput(JSON.stringify(rowBatch));\n\t\t\tawait sql`\n\t\t\t\tWITH input AS (${input})\n\t\t\t\tINSERT INTO _emdash_media_usage (\n\t\t\t\t\tid, source_key, generation, field_slug, field_path, occurrence_index,\n\t\t\t\t\treference_type, media_id, provider, provider_asset_id, media_kind,\n\t\t\t\t\tmime_type, created_at\n\t\t\t\t)\n\t\t\t\tSELECT\n\t\t\t\t\tid, source_key, generation, field_slug, field_path, occurrence_index,\n\t\t\t\t\treference_type, media_id, provider, provider_asset_id, media_kind,\n\t\t\t\t\tmime_type, created_at\n\t\t\t\tFROM input\n\t\t\t\tWHERE EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM _emdash_media_usage_generation_writes AS writer\n\t\t\t\t\tWHERE writer.source_key = input.source_key\n\t\t\t\t\t\tAND writer.generation = input.generation\n\t\t\t\t\t\tAND writer.lease_token = input.lease_token\n\t\t\t\t\t\tAND ${this.generationWriteLeaseExpiryIsInFuture(\"writer.expires_at\")}\n\t\t\t\t)\n\t\t\t`.execute(this.db);\n\t\t}\n\t}\n\n\tprivate occurrenceBatchInput(payload: string): RawBuilder<unknown> {\n\t\tif (isPostgres(this.db)) {\n\t\t\treturn sql`\n\t\t\t\tSELECT\n\t\t\t\t\tentry.value ->> 'id' AS id,\n\t\t\t\t\tentry.value ->> 'source_key' AS source_key,\n\t\t\t\t\tentry.value ->> 'generation' AS generation,\n\t\t\t\t\tentry.value ->> 'field_slug' AS field_slug,\n\t\t\t\t\tentry.value ->> 'field_path' AS field_path,\n\t\t\t\t\tCAST(entry.value ->> 'occurrence_index' AS integer) AS occurrence_index,\n\t\t\t\t\tentry.value ->> 'reference_type' AS reference_type,\n\t\t\t\t\tentry.value ->> 'media_id' AS media_id,\n\t\t\t\t\tentry.value ->> 'provider' AS provider,\n\t\t\t\t\tentry.value ->> 'provider_asset_id' AS provider_asset_id,\n\t\t\t\t\tentry.value ->> 'media_kind' AS media_kind,\n\t\t\t\t\tentry.value ->> 'mime_type' AS mime_type,\n\t\t\t\t\tentry.value ->> 'created_at' AS created_at,\n\t\t\t\t\tentry.value ->> 'lease_token' AS lease_token\n\t\t\t\tFROM jsonb_array_elements(${payload}::jsonb) AS entry(value)\n\t\t\t`;\n\t\t}\n\t\treturn sql`\n\t\t\tSELECT\n\t\t\t\tjson_extract(entry.value, '$.id') AS id,\n\t\t\t\tjson_extract(entry.value, '$.source_key') AS source_key,\n\t\t\t\tjson_extract(entry.value, '$.generation') AS generation,\n\t\t\t\tjson_extract(entry.value, '$.field_slug') AS field_slug,\n\t\t\t\tjson_extract(entry.value, '$.field_path') AS field_path,\n\t\t\t\tCAST(json_extract(entry.value, '$.occurrence_index') AS integer) AS occurrence_index,\n\t\t\t\tjson_extract(entry.value, '$.reference_type') AS reference_type,\n\t\t\t\tjson_extract(entry.value, '$.media_id') AS media_id,\n\t\t\t\tjson_extract(entry.value, '$.provider') AS provider,\n\t\t\t\tjson_extract(entry.value, '$.provider_asset_id') AS provider_asset_id,\n\t\t\t\tjson_extract(entry.value, '$.media_kind') AS media_kind,\n\t\t\t\tjson_extract(entry.value, '$.mime_type') AS mime_type,\n\t\t\t\tjson_extract(entry.value, '$.created_at') AS created_at,\n\t\t\t\tjson_extract(entry.value, '$.lease_token') AS lease_token\n\t\t\tFROM json_each(${payload}) AS entry\n\t\t`;\n\t}\n\n\tprivate sourceBatchInput(payload: string): RawBuilder<unknown> {\n\t\tif (isPostgres(this.db)) {\n\t\t\treturn sql`\n\t\t\t\tSELECT\n\t\t\t\t\tentry.value ->> 'source_key' AS source_key,\n\t\t\t\t\tentry.value ->> 'source_type' AS source_type,\n\t\t\t\t\tentry.value ->> 'collection_id' AS collection_id,\n\t\t\t\t\tentry.value ->> 'collection_slug' AS collection_slug,\n\t\t\t\t\tentry.value ->> 'content_id' AS content_id,\n\t\t\t\t\tentry.value ->> 'source_variant' AS source_variant,\n\t\t\t\t\tentry.value ->> 'locale' AS locale,\n\t\t\t\t\tentry.value ->> 'translation_group' AS translation_group,\n\t\t\t\t\tentry.value ->> 'content_slug' AS content_slug,\n\t\t\t\t\tentry.value ->> 'content_title' AS content_title,\n\t\t\t\t\tentry.value ->> 'content_status' AS content_status,\n\t\t\t\t\tentry.value ->> 'content_scheduled_at' AS content_scheduled_at,\n\t\t\t\t\tentry.value ->> 'content_deleted_at' AS content_deleted_at,\n\t\t\t\t\tentry.value ->> 'revision_id' AS revision_id,\n\t\t\t\t\tentry.value ->> 'current_generation' AS current_generation,\n\t\t\t\t\tCAST(entry.value ->> 'schema_version' AS integer) AS schema_version,\n\t\t\t\t\tentry.value ->> 'source_updated_at' AS source_updated_at,\n\t\t\t\t\tCAST(entry.value ->> 'source_version' AS bigint) AS source_version,\n\t\t\t\t\tentry.value ->> 'source_fingerprint' AS source_fingerprint,\n\t\t\t\t\tCAST(entry.value ->> 'identity_version' AS integer) AS identity_version,\n\t\t\t\t\tentry.value ->> 'source_completeness' AS source_completeness,\n\t\t\t\t\tentry.value ->> 'last_attempted_at' AS last_attempted_at,\n\t\t\t\t\tentry.value ->> 'last_error_code' AS last_error_code,\n\t\t\t\t\tentry.value ->> 'indexed_at' AS indexed_at,\n\t\t\t\t\tentry.value ->> 'updated_at' AS updated_at,\n\t\t\t\t\tentry.value ->> 'lease_token' AS lease_token,\n\t\t\t\t\tentry.value ->> 'expected_generation' AS expected_generation,\n\t\t\t\t\tentry.value ->> 'expected_collection_id' AS expected_collection_id,\n\t\t\t\t\tentry.value ->> 'expected_updated_at' AS expected_updated_at,\n\t\t\t\t\tentry.value ->> 'expected_source_fingerprint' AS expected_source_fingerprint,\n\t\t\t\t\tentry.value ->> 'expected_source_updated_at' AS expected_source_updated_at,\n\t\t\t\t\tCAST(entry.value ->> 'expected_source_version' AS bigint) AS expected_source_version,\n\t\t\t\t\tCAST(entry.value ->> 'expected_identity_version' AS integer) AS expected_identity_version,\n\t\t\t\t\tentry.value ->> 'expected_revision_id' AS expected_revision_id,\n\t\t\t\t\tentry.value ->> 'expected_source_completeness' AS expected_source_completeness,\n\t\t\t\t\tentry.value ->> 'expected_last_attempted_at' AS expected_last_attempted_at,\n\t\t\t\t\tentry.value ->> 'expected_last_error_code' AS expected_last_error_code\n\t\t\t\tFROM jsonb_array_elements(${payload}::jsonb) AS entry(value)\n\t\t\t`;\n\t\t}\n\t\treturn sql`\n\t\t\tSELECT\n\t\t\t\tjson_extract(entry.value, '$.source_key') AS source_key,\n\t\t\t\tjson_extract(entry.value, '$.source_type') AS source_type,\n\t\t\t\tjson_extract(entry.value, '$.collection_id') AS collection_id,\n\t\t\t\tjson_extract(entry.value, '$.collection_slug') AS collection_slug,\n\t\t\t\tjson_extract(entry.value, '$.content_id') AS content_id,\n\t\t\t\tjson_extract(entry.value, '$.source_variant') AS source_variant,\n\t\t\t\tjson_extract(entry.value, '$.locale') AS locale,\n\t\t\t\tjson_extract(entry.value, '$.translation_group') AS translation_group,\n\t\t\t\tjson_extract(entry.value, '$.content_slug') AS content_slug,\n\t\t\t\tjson_extract(entry.value, '$.content_title') AS content_title,\n\t\t\t\tjson_extract(entry.value, '$.content_status') AS content_status,\n\t\t\t\tjson_extract(entry.value, '$.content_scheduled_at') AS content_scheduled_at,\n\t\t\t\tjson_extract(entry.value, '$.content_deleted_at') AS content_deleted_at,\n\t\t\t\tjson_extract(entry.value, '$.revision_id') AS revision_id,\n\t\t\t\tjson_extract(entry.value, '$.current_generation') AS current_generation,\n\t\t\t\tCAST(json_extract(entry.value, '$.schema_version') AS integer) AS schema_version,\n\t\t\t\tjson_extract(entry.value, '$.source_updated_at') AS source_updated_at,\n\t\t\t\tCAST(json_extract(entry.value, '$.source_version') AS integer) AS source_version,\n\t\t\t\tjson_extract(entry.value, '$.source_fingerprint') AS source_fingerprint,\n\t\t\t\tCAST(json_extract(entry.value, '$.identity_version') AS integer) AS identity_version,\n\t\t\t\tjson_extract(entry.value, '$.source_completeness') AS source_completeness,\n\t\t\t\tjson_extract(entry.value, '$.last_attempted_at') AS last_attempted_at,\n\t\t\t\tjson_extract(entry.value, '$.last_error_code') AS last_error_code,\n\t\t\t\tjson_extract(entry.value, '$.indexed_at') AS indexed_at,\n\t\t\t\tjson_extract(entry.value, '$.updated_at') AS updated_at,\n\t\t\t\tjson_extract(entry.value, '$.lease_token') AS lease_token,\n\t\t\t\tjson_extract(entry.value, '$.expected_generation') AS expected_generation,\n\t\t\t\tjson_extract(entry.value, '$.expected_collection_id') AS expected_collection_id,\n\t\t\t\tjson_extract(entry.value, '$.expected_updated_at') AS expected_updated_at,\n\t\t\t\tjson_extract(entry.value, '$.expected_source_fingerprint') AS expected_source_fingerprint,\n\t\t\t\tjson_extract(entry.value, '$.expected_source_updated_at') AS expected_source_updated_at,\n\t\t\t\tCAST(json_extract(entry.value, '$.expected_source_version') AS integer) AS expected_source_version,\n\t\t\t\tCAST(json_extract(entry.value, '$.expected_identity_version') AS integer) AS expected_identity_version,\n\t\t\t\tjson_extract(entry.value, '$.expected_revision_id') AS expected_revision_id,\n\t\t\t\tjson_extract(entry.value, '$.expected_source_completeness') AS expected_source_completeness,\n\t\t\t\tjson_extract(entry.value, '$.expected_last_attempted_at') AS expected_last_attempted_at,\n\t\t\t\tjson_extract(entry.value, '$.expected_last_error_code') AS expected_last_error_code\n\t\t\tFROM json_each(${payload}) AS entry\n\t\t`;\n\t}\n\n\tprivate generationWriteBatchInput(payload: string): RawBuilder<unknown> {\n\t\tif (isPostgres(this.db)) {\n\t\t\treturn sql`\n\t\t\t\tSELECT\n\t\t\t\t\tentry.value ->> 'source_key' AS source_key,\n\t\t\t\t\tentry.value ->> 'collection_id' AS collection_id,\n\t\t\t\t\tentry.value ->> 'collection_slug' AS collection_slug,\n\t\t\t\t\tentry.value ->> 'generation' AS generation,\n\t\t\t\t\tentry.value ->> 'lease_token' AS lease_token,\n\t\t\t\t\tentry.value ->> 'expires_at' AS expires_at,\n\t\t\t\t\tentry.value ->> 'created_at' AS created_at\n\t\t\t\tFROM jsonb_array_elements(${payload}::jsonb) AS entry(value)\n\t\t\t`;\n\t\t}\n\t\treturn sql`\n\t\t\tSELECT\n\t\t\t\tjson_extract(entry.value, '$.source_key') AS source_key,\n\t\t\t\tjson_extract(entry.value, '$.collection_id') AS collection_id,\n\t\t\t\tjson_extract(entry.value, '$.collection_slug') AS collection_slug,\n\t\t\t\tjson_extract(entry.value, '$.generation') AS generation,\n\t\t\t\tjson_extract(entry.value, '$.lease_token') AS lease_token,\n\t\t\t\tjson_extract(entry.value, '$.expires_at') AS expires_at,\n\t\t\t\tjson_extract(entry.value, '$.created_at') AS created_at\n\t\t\tFROM json_each(${payload}) AS entry\n\t\t`;\n\t}\n\n\tprivate batchRefsMatch(\n\t\tleft: BatchSourceExpectedColumn,\n\t\tright: BatchInputExpectedColumn,\n\t): RawBuilder<boolean> {\n\t\tconst leftRef = sql.ref(left);\n\t\tconst rightRef = sql.ref(right);\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`${leftRef} IS NOT DISTINCT FROM ${rightRef}`\n\t\t\t: sql<boolean>`${leftRef} IS ${rightRef}`;\n\t}\n\n\tprivate async lockCanonicalSourceCollection(\n\t\tdb: DatabaseExecutor,\n\t\tsource: MediaUsageSourceInput,\n\t): Promise<boolean> {\n\t\tif (source.collectionId === undefined || source.collectionId === null) return true;\n\t\tif (!source.collectionSlug) return false;\n\t\tif (!isPostgres(this.db)) return true;\n\t\tconst collection = await db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"id\", \"=\", source.collectionId)\n\t\t\t.where(\"slug\", \"=\", source.collectionSlug)\n\t\t\t.forKeyShare()\n\t\t\t.executeTakeFirst();\n\t\treturn collection !== undefined;\n\t}\n\n\tprivate async upsertSource(\n\t\tdb: DatabaseExecutor,\n\t\tsource: MediaUsageSourceInput,\n\t\tgeneration: string,\n\t\tnow: string,\n\t\tleaseToken: string,\n\t): Promise<boolean> {\n\t\tconst row = this.buildSourceRow(source, generation, now);\n\t\treturn this.persistSourceIfWriteLease(\n\t\t\tdb,\n\t\t\trow,\n\t\t\tleaseToken,\n\t\t\tsql`\n\t\t\t\tON CONFLICT (source_key) DO UPDATE SET\n\t\t\t\t\tsource_type = excluded.source_type,\n\t\t\t\t\tcollection_id = excluded.collection_id,\n\t\t\t\t\tcollection_slug = excluded.collection_slug,\n\t\t\t\t\tcontent_id = excluded.content_id,\n\t\t\t\t\tsource_variant = excluded.source_variant,\n\t\t\t\t\tlocale = excluded.locale,\n\t\t\t\t\ttranslation_group = excluded.translation_group,\n\t\t\t\t\tcontent_slug = excluded.content_slug,\n\t\t\t\t\tcontent_title = excluded.content_title,\n\t\t\t\t\tcontent_status = excluded.content_status,\n\t\t\t\t\tcontent_scheduled_at = excluded.content_scheduled_at,\n\t\t\t\t\tcontent_deleted_at = excluded.content_deleted_at,\n\t\t\t\t\trevision_id = excluded.revision_id,\n\t\t\t\t\tcurrent_generation = excluded.current_generation,\n\t\t\t\t\tschema_version = excluded.schema_version,\n\t\t\t\t\tsource_updated_at = excluded.source_updated_at,\n\t\t\t\t\tsource_version = excluded.source_version,\n\t\t\t\t\tsource_fingerprint = excluded.source_fingerprint,\n\t\t\t\t\tidentity_version = excluded.identity_version,\n\t\t\t\t\tsource_completeness = excluded.source_completeness,\n\t\t\t\t\tlast_attempted_at = excluded.last_attempted_at,\n\t\t\t\t\tlast_error_code = excluded.last_error_code,\n\t\t\t\t\tindexed_at = excluded.indexed_at,\n\t\t\t\t\tupdated_at = excluded.updated_at\n\t\t\t`,\n\t\t);\n\t}\n\n\tprivate async insertSourceIfAbsent(\n\t\tdb: DatabaseExecutor,\n\t\trow: ReturnType<MediaUsageRepository[\"buildSourceRow\"]>,\n\t\tleaseToken: string,\n\t): Promise<boolean> {\n\t\treturn this.persistSourceIfWriteLease(\n\t\t\tdb,\n\t\t\trow,\n\t\t\tleaseToken,\n\t\t\tsql`ON CONFLICT (source_key) DO NOTHING`,\n\t\t);\n\t}\n\n\tprivate async persistSourceIfWriteLease(\n\t\tdb: DatabaseExecutor,\n\t\trow:\n\t\t\t| ReturnType<MediaUsageRepository[\"buildSourceRow\"]>\n\t\t\t| ReturnType<MediaUsageRepository[\"buildAttemptedSourceRow\"]>,\n\t\tleaseToken: string,\n\t\tconflict: RawBuilder<unknown>,\n\t): Promise<boolean> {\n\t\tconst result = await sql`\n\t\t\tINSERT INTO _emdash_media_usage_sources (\n\t\t\t\tsource_key,\n\t\t\t\tsource_type,\n\t\t\t\tcollection_id,\n\t\t\t\tcollection_slug,\n\t\t\t\tcontent_id,\n\t\t\t\tsource_variant,\n\t\t\t\tlocale,\n\t\t\t\ttranslation_group,\n\t\t\t\tcontent_slug,\n\t\t\t\tcontent_title,\n\t\t\t\tcontent_status,\n\t\t\t\tcontent_scheduled_at,\n\t\t\t\tcontent_deleted_at,\n\t\t\t\trevision_id,\n\t\t\t\tcurrent_generation,\n\t\t\t\tschema_version,\n\t\t\t\tsource_updated_at,\n\t\t\t\tsource_version,\n\t\t\t\tsource_fingerprint,\n\t\t\t\tidentity_version,\n\t\t\t\tsource_completeness,\n\t\t\t\tlast_attempted_at,\n\t\t\t\tlast_error_code,\n\t\t\t\tindexed_at,\n\t\t\t\tupdated_at\n\t\t\t)\n\t\t\tSELECT\n\t\t\t\t${row.source_key},\n\t\t\t\t${row.source_type},\n\t\t\t\t${row.collection_id},\n\t\t\t\t${row.collection_slug},\n\t\t\t\t${row.content_id},\n\t\t\t\t${row.source_variant},\n\t\t\t\t${row.locale},\n\t\t\t\t${row.translation_group},\n\t\t\t\t${row.content_slug},\n\t\t\t\t${row.content_title},\n\t\t\t\t${row.content_status},\n\t\t\t\t${row.content_scheduled_at},\n\t\t\t\t${row.content_deleted_at},\n\t\t\t\t${row.revision_id},\n\t\t\t\t${row.current_generation},\n\t\t\t\t${row.schema_version},\n\t\t\t\t${row.source_updated_at},\n\t\t\t\t${row.source_version},\n\t\t\t\t${row.source_fingerprint},\n\t\t\t\t${row.identity_version},\n\t\t\t\t${row.source_completeness},\n\t\t\t\t${row.last_attempted_at},\n\t\t\t\t${row.last_error_code},\n\t\t\t\t${row.indexed_at},\n\t\t\t\t${row.updated_at}\n\t\t\tWHERE EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_media_usage_generation_writes\n\t\t\t\tWHERE source_key = ${row.source_key}\n\t\t\t\t\tAND generation = ${row.current_generation}\n\t\t\t\t\tAND lease_token = ${leaseToken}\n\t\t\t\t\tAND ${this.generationWriteLeaseExpiryIsInFuture(\"expires_at\")}\n\t\t\t)\n\t\t\tAND ${this.currentCollectionExists(row.collection_id, row.collection_slug)}\n\t\t\tAND ${this.currentCanonicalContentExists(row)}\n\t\t\t${conflict}\n\t\t`.execute(db);\n\t\treturn Number(result.numAffectedRows ?? 0) > 0;\n\t}\n\n\tprivate generationWriteLeaseExpression(\n\t\trow: ReturnType<MediaUsageRepository[\"buildSourceRow\"]>,\n\t\tleaseToken: string,\n\t) {\n\t\treturn (eb: ExpressionBuilder<Database, \"_emdash_media_usage_sources\">) =>\n\t\t\teb.exists(\n\t\t\t\teb\n\t\t\t\t\t.selectFrom(\"_emdash_media_usage_generation_writes\")\n\t\t\t\t\t.select(\"source_key\")\n\t\t\t\t\t.where(\"source_key\", \"=\", row.source_key)\n\t\t\t\t\t.where(\"generation\", \"=\", row.current_generation)\n\t\t\t\t\t.where(\"lease_token\", \"=\", leaseToken)\n\t\t\t\t\t.where(\n\t\t\t\t\t\tthis.generationWriteLeaseExpiryIsInFuture(\n\t\t\t\t\t\t\t\"_emdash_media_usage_generation_writes.expires_at\",\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t);\n\t}\n\n\tprivate generationWriteLeaseExpiryIsInFuture(column: string) {\n\t\tconst leaseExpiresAt = sql.ref(column);\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`${leaseExpiresAt}::timestamptz > clock_timestamp()`\n\t\t\t: sql<boolean>`${leaseExpiresAt} > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate async withGenerationWriteLease(\n\t\tsource: Pick<MediaUsageSourceInput, \"sourceKey\" | \"collectionId\" | \"collectionSlug\">,\n\t\tgeneration: string,\n\t\twrite: (leaseToken: string, startedAt: string) => Promise<void>,\n\t): Promise<boolean> {\n\t\tconst leaseToken = ulid();\n\t\tconst lease = await sql<{ created_at: string }>`\n\t\t\tINSERT INTO _emdash_media_usage_generation_writes (\n\t\t\t\tsource_key, generation, lease_token, expires_at, created_at\n\t\t\t)\n\t\t\tSELECT\n\t\t\t\t${source.sourceKey},\n\t\t\t\t${generation},\n\t\t\t\t${leaseToken},\n\t\t\t\t${this.generationWriteLeaseTimestampOffset(MEDIA_USAGE_GENERATION_WRITE_LEASE_MS / 1000)},\n\t\t\t\t${this.generationWriteLeaseTimestampOffset(0)}\n\t\t\tWHERE ${this.currentCollectionExists(\n\t\t\t\tsource.collectionId ?? null,\n\t\t\t\tsource.collectionSlug ?? null,\n\t\t\t)}\n\t\t\tRETURNING created_at\n\t\t`.execute(this.db);\n\t\tconst owner = lease.rows[0];\n\t\tif (!owner) return false;\n\n\t\ttry {\n\t\t\tawait write(leaseToken, owner.created_at);\n\t\t\treturn true;\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tawait this.db\n\t\t\t\t\t.deleteFrom(\"_emdash_media_usage_generation_writes\")\n\t\t\t\t\t.where(\"source_key\", \"=\", source.sourceKey)\n\t\t\t\t\t.where(\"generation\", \"=\", generation)\n\t\t\t\t\t.where(\"lease_token\", \"=\", leaseToken)\n\t\t\t\t\t.execute();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[media-usage] Failed to release generation write lease:\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate generationWriteLeaseTimestampOffset(offsetSeconds: number): RawBuilder<string> {\n\t\tif (isPostgres(this.db)) {\n\t\t\treturn sql<string>`to_char(\n\t\t\t\t(clock_timestamp() AT TIME ZONE 'UTC') + (${offsetSeconds} * INTERVAL '1 second'),\n\t\t\t\t'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'\n\t\t\t)`;\n\t\t}\n\t\treturn sql<string>`strftime(\n\t\t\t'%Y-%m-%dT%H:%M:%fZ',\n\t\t\t'now',\n\t\t\t${`${offsetSeconds >= 0 ? \"+\" : \"\"}${offsetSeconds} seconds`}\n\t\t)`;\n\t}\n\n\tprivate async updateSourceIfGeneration(\n\t\tdb: DatabaseExecutor,\n\t\trow: ReturnType<MediaUsageRepository[\"buildSourceRow\"]>,\n\t\texpectedCurrentGeneration: string,\n\t\tleaseToken: string,\n\t): Promise<boolean> {\n\t\tconst result = await db\n\t\t\t.updateTable(\"_emdash_media_usage_sources\")\n\t\t\t.set(this.sourceUpdateSet(row))\n\t\t\t.where(\"source_key\", \"=\", row.source_key)\n\t\t\t.where(\"current_generation\", \"=\", expectedCurrentGeneration)\n\t\t\t.where(this.generationWriteLeaseExpression(row, leaseToken))\n\t\t\t.where(this.currentCollectionExists(row.collection_id, row.collection_slug))\n\t\t\t.where(this.currentCanonicalContentExists(row))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0;\n\t}\n\n\tprivate async updateSourceIfMatching(\n\t\tdb: DatabaseExecutor,\n\t\trow: ReturnType<MediaUsageRepository[\"buildSourceRow\"]>,\n\t\texpectedSource: MediaUsageSource,\n\t\tleaseToken: string,\n\t): Promise<boolean> {\n\t\tconst result = await db\n\t\t\t.updateTable(\"_emdash_media_usage_sources\")\n\t\t\t.set(this.sourceUpdateSet(row))\n\t\t\t.where(\"source_key\", \"=\", row.source_key)\n\t\t\t.where(this.sourceMatchExpression(expectedSource))\n\t\t\t.where(this.generationWriteLeaseExpression(row, leaseToken))\n\t\t\t.where(this.currentCollectionExists(row.collection_id, row.collection_slug))\n\t\t\t.where(this.currentCanonicalContentExists(row))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0;\n\t}\n\n\tprivate async updateAttemptedSourceIfMatching(\n\t\tdb: DatabaseExecutor,\n\t\tsource: MediaUsageSourceInput,\n\t\trow: ReturnType<MediaUsageRepository[\"buildAttemptedSourceRow\"]>,\n\t\texpectedSource: MediaUsageSource,\n\t): Promise<boolean> {\n\t\tconst result = await db\n\t\t\t.updateTable(\"_emdash_media_usage_sources\")\n\t\t\t.set(this.attemptedSourceUpdateSet(source, row))\n\t\t\t.where(\"source_key\", \"=\", row.source_key)\n\t\t\t.where(this.sourceMatchExpression(expectedSource))\n\t\t\t.where(this.currentCollectionExists(row.collection_id, row.collection_slug))\n\t\t\t.where(this.currentCanonicalContentExists(row))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) > 0;\n\t}\n\n\tprivate sourceMatchExpression(expectedSource: MediaUsageSource) {\n\t\treturn (eb: ExpressionBuilder<Database, \"_emdash_media_usage_sources\">) =>\n\t\t\teb.and([\n\t\t\t\teb(\"current_generation\", \"=\", expectedSource.currentGeneration),\n\t\t\t\teb(\"source_completeness\", \"=\", expectedSource.sourceCompleteness),\n\t\t\t\tthis.nullableStringExpression(eb, \"collection_id\", expectedSource.collectionId),\n\t\t\t\tthis.nullableStringExpression(eb, \"updated_at\", expectedSource.updatedAt),\n\t\t\t\tthis.nullableStringExpression(eb, \"source_fingerprint\", expectedSource.sourceFingerprint),\n\t\t\t\tthis.nullableStringExpression(eb, \"source_updated_at\", expectedSource.sourceUpdatedAt),\n\t\t\t\tthis.nullableNumberExpression(eb, \"source_version\", expectedSource.sourceVersion),\n\t\t\t\tthis.nullableNumberExpression(eb, \"identity_version\", expectedSource.identityVersion),\n\t\t\t\tthis.nullableStringExpression(eb, \"revision_id\", expectedSource.revisionId),\n\t\t\t\tthis.nullableStringExpression(eb, \"last_attempted_at\", expectedSource.lastAttemptedAt),\n\t\t\t\tthis.nullableStringExpression(eb, \"last_error_code\", expectedSource.lastErrorCode),\n\t\t\t]);\n\t}\n\n\tprivate async projectionMatchesCurrentGeneration(\n\t\tsource: MediaUsageSourceInput,\n\t\texpectedCurrentGeneration: string,\n\t): Promise<boolean> {\n\t\tconst fingerprint = source.sourceFingerprint;\n\t\tif (!isMediaUsageProjectionFingerprint(fingerprint)) return false;\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources\")\n\t\t\t.select(\"source_key\")\n\t\t\t.where(\"source_key\", \"=\", source.sourceKey)\n\t\t\t.where(\"current_generation\", \"=\", expectedCurrentGeneration)\n\t\t\t.where(\"source_fingerprint\", \"=\", fingerprint!)\n\t\t\t.where(\"source_completeness\", \"=\", source.sourceCompleteness ?? \"complete\")\n\t\t\t.where(\"last_error_code\", \"is\", null)\n\t\t\t.where(\n\t\t\t\tthis.currentCollectionExists(source.collectionId ?? null, source.collectionSlug ?? null),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n\n\tasync projectionMatchesExpectedSource(\n\t\tsource: MediaUsageSourceInput,\n\t\texpectedSource: MediaUsageSource,\n\t): Promise<boolean> {\n\t\tconst fingerprint = source.sourceFingerprint;\n\t\tif (\n\t\t\t!isMediaUsageProjectionFingerprint(fingerprint) ||\n\t\t\texpectedSource.sourceFingerprint !== fingerprint ||\n\t\t\texpectedSource.sourceCompleteness !== (source.sourceCompleteness ?? \"complete\") ||\n\t\t\texpectedSource.lastErrorCode !== null\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources\")\n\t\t\t.select(\"source_key\")\n\t\t\t.where(\"source_key\", \"=\", source.sourceKey)\n\t\t\t.where(this.sourceMatchExpression(expectedSource))\n\t\t\t.where(\n\t\t\t\tthis.currentCollectionExists(source.collectionId ?? null, source.collectionSlug ?? null),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n\n\tprivate nullableStringExpression(\n\t\teb: ExpressionBuilder<Database, \"_emdash_media_usage_sources\">,\n\t\tcolumn: MediaUsageSourceNullableStringColumn,\n\t\tvalue: string | null,\n\t) {\n\t\treturn value === null ? eb(column, \"is\", null) : eb(column, \"=\", value);\n\t}\n\n\tprivate currentCollectionExists(\n\t\tcollectionId: string | null,\n\t\tcollectionSlug: string | null,\n\t): RawBuilder<boolean> {\n\t\tif (collectionId === null) return sql<boolean>`1 = 1`;\n\t\treturn sql<boolean>`EXISTS (\n\t\t\tSELECT 1\n\t\t\tFROM _emdash_collections\n\t\t\tWHERE id = ${collectionId}\n\t\t\t\tAND slug = ${collectionSlug}\n\t\t)`;\n\t}\n\n\tprivate currentCanonicalContentExists(\n\t\trow:\n\t\t\t| ReturnType<MediaUsageRepository[\"buildSourceRow\"]>\n\t\t\t| ReturnType<MediaUsageRepository[\"buildAttemptedSourceRow\"]>,\n\t): RawBuilder<boolean> {\n\t\tif (row.collection_id === null || row.identity_version !== 1 || row.source_type !== \"content\") {\n\t\t\treturn sql<boolean>`1 = 1`;\n\t\t}\n\t\tif (\n\t\t\t!row.collection_slug ||\n\t\t\t!row.content_id ||\n\t\t\trow.source_version === null ||\n\t\t\trow.source_updated_at === null\n\t\t) {\n\t\t\treturn sql<boolean>`1 = 0`;\n\t\t}\n\t\tvalidateIdentifier(row.collection_slug, \"collection slug\");\n\t\tconst tableName = `ec_${row.collection_slug}`;\n\t\tvalidateIdentifier(tableName, \"content table\");\n\t\tconst revisionColumn =\n\t\t\trow.source_variant === \"columns\"\n\t\t\t\t? \"live_revision_id\"\n\t\t\t\t: row.source_variant === \"draft_overlay\"\n\t\t\t\t\t? \"draft_revision_id\"\n\t\t\t\t\t: null;\n\t\tif (!revisionColumn) return sql<boolean>`1 = 0`;\n\t\tconst revision = sql.ref(`content.${revisionColumn}`);\n\t\tconst revisionMatches =\n\t\t\trow.revision_id === null\n\t\t\t\t? sql<boolean>`${revision} IS NULL`\n\t\t\t\t: sql<boolean>`${revision} = ${row.revision_id}`;\n\t\treturn sql<boolean>`EXISTS (\n\t\t\tSELECT 1\n\t\t\tFROM ${sql.ref(tableName)} AS content\n\t\t\tWHERE content.id = ${row.content_id}\n\t\t\t\tAND content.version = ${row.source_version}\n\t\t\t\tAND content.updated_at = ${row.source_updated_at}\n\t\t\t\tAND ${revisionMatches}\n\t\t)`;\n\t}\n\n\tprivate nullableNumberExpression(\n\t\teb: ExpressionBuilder<Database, \"_emdash_media_usage_sources\">,\n\t\tcolumn: \"source_version\" | \"identity_version\",\n\t\tvalue: number | null,\n\t) {\n\t\treturn value === null ? eb(column, \"is\", null) : eb(column, \"=\", value);\n\t}\n\n\tprivate async contentRowExists(tableName: string, contentId: string): Promise<boolean> {\n\t\tconst result = await sql<{ id: string }>`\n\t\t\tSELECT id\n\t\t\tFROM ${sql.ref(tableName)}\n\t\t\tWHERE id = ${contentId}\n\t\t\tLIMIT 1\n\t\t`.execute(this.db);\n\t\treturn result.rows.length > 0;\n\t}\n\n\tprivate buildSourceRow(source: MediaUsageSourceInput, generation: string, now: string) {\n\t\treturn {\n\t\t\tsource_key: source.sourceKey,\n\t\t\tsource_type: source.sourceType,\n\t\t\tcollection_id: source.collectionId ?? null,\n\t\t\tcollection_slug: source.collectionSlug ?? null,\n\t\t\tcontent_id: source.contentId ?? null,\n\t\t\tsource_variant: source.sourceVariant,\n\t\t\tlocale: source.locale ?? null,\n\t\t\ttranslation_group: source.translationGroup ?? null,\n\t\t\tcontent_slug: source.contentSlug ?? null,\n\t\t\tcontent_title: source.contentTitle ?? null,\n\t\t\tcontent_status: source.contentStatus ?? null,\n\t\t\tcontent_scheduled_at: source.contentScheduledAt ?? null,\n\t\t\tcontent_deleted_at: source.contentDeletedAt ?? null,\n\t\t\trevision_id: source.revisionId ?? null,\n\t\t\tcurrent_generation: generation,\n\t\t\tschema_version: source.schemaVersion ?? 1,\n\t\t\tsource_updated_at: source.sourceUpdatedAt ?? null,\n\t\t\tsource_version: source.sourceVersion ?? null,\n\t\t\tsource_fingerprint: source.sourceFingerprint ?? null,\n\t\t\tidentity_version: source.identityVersion ?? null,\n\t\t\t// Complete means this source was fully refreshed for the extractor's current\n\t\t\t// schema/version coverage, not that every possible reference shape is known.\n\t\t\tsource_completeness: source.sourceCompleteness ?? \"complete\",\n\t\t\tlast_attempted_at: source.lastAttemptedAt ?? now,\n\t\t\tlast_error_code: null,\n\t\t\tindexed_at: now,\n\t\t\tupdated_at: now,\n\t\t};\n\t}\n\n\tprivate buildAttemptedSourceRow(source: MediaUsageSourceInput, generation: string, now: string) {\n\t\treturn {\n\t\t\tsource_key: source.sourceKey,\n\t\t\tsource_type: source.sourceType,\n\t\t\tcollection_id: source.collectionId ?? null,\n\t\t\tcollection_slug: source.collectionSlug ?? null,\n\t\t\tcontent_id: source.contentId ?? null,\n\t\t\tsource_variant: source.sourceVariant,\n\t\t\tlocale: source.locale ?? null,\n\t\t\ttranslation_group: source.translationGroup ?? null,\n\t\t\tcontent_slug: source.contentSlug ?? null,\n\t\t\tcontent_title: source.contentTitle ?? null,\n\t\t\tcontent_status: source.contentStatus ?? null,\n\t\t\tcontent_scheduled_at: source.contentScheduledAt ?? null,\n\t\t\tcontent_deleted_at: source.contentDeletedAt ?? null,\n\t\t\trevision_id: source.revisionId ?? null,\n\t\t\tcurrent_generation: generation,\n\t\t\tschema_version: source.schemaVersion ?? 1,\n\t\t\tsource_updated_at: source.sourceUpdatedAt ?? null,\n\t\t\tsource_version: source.sourceVersion ?? null,\n\t\t\tsource_fingerprint: source.sourceFingerprint ?? null,\n\t\t\tidentity_version: source.identityVersion ?? null,\n\t\t\tsource_completeness:\n\t\t\t\tsource.sourceCompleteness ?? (source.lastErrorCode ? \"failed\" : \"unknown\"),\n\t\t\tlast_attempted_at: source.lastAttemptedAt ?? now,\n\t\t\tlast_error_code: source.lastErrorCode ?? null,\n\t\t\tindexed_at: now,\n\t\t\tupdated_at: now,\n\t\t};\n\t}\n\n\tprivate attemptedSourceUpdateSet(\n\t\tsource: MediaUsageSourceInput,\n\t\trow: ReturnType<MediaUsageRepository[\"buildAttemptedSourceRow\"]>,\n\t): Updateable<MediaUsageSourceTable> {\n\t\tconst updates: Updateable<MediaUsageSourceTable> = {\n\t\t\tsource_type: row.source_type,\n\t\t\tsource_variant: row.source_variant,\n\t\t\tsource_completeness: row.source_completeness,\n\t\t\tlast_attempted_at: row.last_attempted_at,\n\t\t\tlast_error_code: row.last_error_code,\n\t\t\tupdated_at: row.updated_at,\n\t\t};\n\n\t\tif (source.collectionSlug !== undefined) updates.collection_slug = row.collection_slug;\n\t\tif (source.collectionId !== undefined) updates.collection_id = row.collection_id;\n\t\tif (source.contentId !== undefined) updates.content_id = row.content_id;\n\t\tif (source.locale !== undefined) updates.locale = row.locale;\n\t\tif (source.translationGroup !== undefined) updates.translation_group = row.translation_group;\n\t\tif (source.contentSlug !== undefined) updates.content_slug = row.content_slug;\n\t\tif (source.contentTitle !== undefined) updates.content_title = row.content_title;\n\t\tif (source.contentStatus !== undefined) updates.content_status = row.content_status;\n\t\tif (source.contentScheduledAt !== undefined) {\n\t\t\tupdates.content_scheduled_at = row.content_scheduled_at;\n\t\t}\n\t\tif (source.contentDeletedAt !== undefined) updates.content_deleted_at = row.content_deleted_at;\n\t\tif (source.revisionId !== undefined) updates.revision_id = row.revision_id;\n\t\tif (source.schemaVersion !== undefined) updates.schema_version = row.schema_version;\n\t\tif (source.sourceUpdatedAt !== undefined) updates.source_updated_at = row.source_updated_at;\n\t\tif (source.sourceVersion !== undefined) updates.source_version = row.source_version;\n\t\tif (source.sourceFingerprint !== undefined) {\n\t\t\tupdates.source_fingerprint = row.source_fingerprint;\n\t\t}\n\t\tif (source.identityVersion !== undefined) updates.identity_version = row.identity_version;\n\n\t\treturn updates;\n\t}\n\n\tprivate sourceUpdateSet(\n\t\trow: ReturnType<MediaUsageRepository[\"buildSourceRow\"]>,\n\t): Updateable<MediaUsageSourceTable> {\n\t\treturn {\n\t\t\tsource_type: row.source_type,\n\t\t\tcollection_id: row.collection_id,\n\t\t\tcollection_slug: row.collection_slug,\n\t\t\tcontent_id: row.content_id,\n\t\t\tsource_variant: row.source_variant,\n\t\t\tlocale: row.locale,\n\t\t\ttranslation_group: row.translation_group,\n\t\t\tcontent_slug: row.content_slug,\n\t\t\tcontent_title: row.content_title,\n\t\t\tcontent_status: row.content_status,\n\t\t\tcontent_scheduled_at: row.content_scheduled_at,\n\t\t\tcontent_deleted_at: row.content_deleted_at,\n\t\t\trevision_id: row.revision_id,\n\t\t\tcurrent_generation: row.current_generation,\n\t\t\tschema_version: row.schema_version,\n\t\t\tsource_updated_at: row.source_updated_at,\n\t\t\tsource_version: row.source_version,\n\t\t\tsource_fingerprint: row.source_fingerprint,\n\t\t\tidentity_version: row.identity_version,\n\t\t\tsource_completeness: row.source_completeness,\n\t\t\tlast_attempted_at: row.last_attempted_at,\n\t\t\tlast_error_code: row.last_error_code,\n\t\t\tindexed_at: row.indexed_at,\n\t\t\tupdated_at: row.updated_at,\n\t\t};\n\t}\n}\n\nconst currentUsageSelect = [\n\t\"s.source_key as source_key\",\n\t\"s.source_type as source_type\",\n\t\"s.collection_id as collection_id\",\n\t\"s.collection_slug as collection_slug\",\n\t\"s.content_id as content_id\",\n\t\"s.source_variant as source_variant\",\n\t\"s.locale as locale\",\n\t\"s.translation_group as translation_group\",\n\t\"s.content_slug as content_slug\",\n\t\"s.content_title as content_title\",\n\t\"s.content_status as content_status\",\n\t\"s.content_scheduled_at as content_scheduled_at\",\n\t\"s.content_deleted_at as content_deleted_at\",\n\t\"s.revision_id as revision_id\",\n\t\"s.current_generation as current_generation\",\n\t\"s.schema_version as schema_version\",\n\t\"s.source_updated_at as source_updated_at\",\n\t\"s.source_version as source_version\",\n\t\"s.source_fingerprint as source_fingerprint\",\n\t\"s.identity_version as identity_version\",\n\t\"s.source_completeness as source_completeness\",\n\t\"s.last_attempted_at as last_attempted_at\",\n\t\"s.last_error_code as last_error_code\",\n\t\"s.indexed_at as indexed_at\",\n\t\"s.created_at as source_created_at\",\n\t\"s.updated_at as source_row_updated_at\",\n\t\"u.id as occurrence_id\",\n\t\"u.generation as generation\",\n\t\"u.field_slug as field_slug\",\n\t\"u.field_path as field_path\",\n\t\"u.occurrence_index as occurrence_index\",\n\t\"u.reference_type as reference_type\",\n\t\"u.media_id as media_id\",\n\t\"u.provider as provider\",\n\t\"u.provider_asset_id as provider_asset_id\",\n\t\"u.media_kind as media_kind\",\n\t\"u.mime_type as mime_type\",\n\t\"u.created_at as occurrence_created_at\",\n] as const;\n\nfunction groupUsageRows(rows: readonly GroupedUsageRow[]): MediaUsageEntryGroup[] {\n\tconst groups: MediaUsageEntryGroup[] = [];\n\n\tfor (const row of rows) {\n\t\tif (row.collection_slug === null || row.content_id === null) continue;\n\t\tconst record = rowToUsageRecord(row);\n\t\tlet group = groups.at(-1);\n\t\tif (\n\t\t\t!group ||\n\t\t\tgroup.collectionSlug !== row.collection_slug ||\n\t\t\tgroup.contentId !== row.content_id\n\t\t) {\n\t\t\tgroup = {\n\t\t\t\tcollectionSlug: row.collection_slug,\n\t\t\t\tcontentId: row.content_id,\n\t\t\t\tcontentDeletedAt: row.entry_deleted_at,\n\t\t\t\tsources: [],\n\t\t\t};\n\t\t\tgroups.push(group);\n\t\t}\n\n\t\tlet source = group.sources.at(-1);\n\t\tif (!source || source.source.sourceKey !== record.source.sourceKey) {\n\t\t\tsource = { source: record.source, occurrences: [] };\n\t\t\tgroup.sources.push(source);\n\t\t}\n\t\tsource.occurrences.push(record.occurrence);\n\t}\n\n\treturn groups;\n}\n\nfunction rowToSource(row: MediaUsageSourceRow): MediaUsageSource {\n\treturn {\n\t\tsourceKey: row.source_key,\n\t\tsourceType: row.source_type,\n\t\tcollectionId: row.collection_id,\n\t\tcollectionSlug: row.collection_slug,\n\t\tcontentId: row.content_id,\n\t\tsourceVariant: row.source_variant,\n\t\tlocale: row.locale,\n\t\ttranslationGroup: row.translation_group,\n\t\tcontentSlug: row.content_slug,\n\t\tcontentTitle: row.content_title,\n\t\tcontentStatus: row.content_status,\n\t\tcontentScheduledAt: row.content_scheduled_at,\n\t\tcontentDeletedAt: row.content_deleted_at,\n\t\trevisionId: row.revision_id,\n\t\tcurrentGeneration: row.current_generation,\n\t\tschemaVersion: Number(row.schema_version),\n\t\tsourceUpdatedAt: row.source_updated_at,\n\t\tsourceVersion: row.source_version === null ? null : Number(row.source_version),\n\t\tsourceFingerprint: row.source_fingerprint,\n\t\tidentityVersion: row.identity_version === null ? null : Number(row.identity_version),\n\t\tsourceCompleteness: row.source_completeness,\n\t\tlastAttemptedAt: row.last_attempted_at,\n\t\tlastErrorCode: row.last_error_code,\n\t\tindexedAt: row.indexed_at,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n\nfunction rowToOccurrence(row: Selectable<MediaUsageTable>): MediaUsageOccurrence {\n\treturn {\n\t\tid: row.id,\n\t\tsourceKey: row.source_key,\n\t\tgeneration: row.generation,\n\t\tfieldSlug: row.field_slug,\n\t\tfieldPath: row.field_path,\n\t\toccurrenceIndex: Number(row.occurrence_index),\n\t\treferenceType: row.reference_type,\n\t\tmediaId: row.media_id,\n\t\tprovider: row.provider,\n\t\tproviderAssetId: row.provider_asset_id,\n\t\tmediaKind: row.media_kind,\n\t\tmimeType: row.mime_type,\n\t\tcreatedAt: row.created_at,\n\t};\n}\n\nfunction rowToUsageRecord(row: JoinedUsageRow): MediaUsageRecord {\n\treturn {\n\t\tsource: rowToSource({\n\t\t\tsource_key: row.source_key,\n\t\t\tsource_type: row.source_type,\n\t\t\tcollection_id: row.collection_id,\n\t\t\tcollection_slug: row.collection_slug,\n\t\t\tcontent_id: row.content_id,\n\t\t\tsource_variant: row.source_variant,\n\t\t\tlocale: row.locale,\n\t\t\ttranslation_group: row.translation_group,\n\t\t\tcontent_slug: row.content_slug,\n\t\t\tcontent_title: row.content_title,\n\t\t\tcontent_status: row.content_status,\n\t\t\tcontent_scheduled_at: row.content_scheduled_at,\n\t\t\tcontent_deleted_at: row.content_deleted_at,\n\t\t\trevision_id: row.revision_id,\n\t\t\tcurrent_generation: row.current_generation,\n\t\t\tschema_version: row.schema_version,\n\t\t\tsource_updated_at: row.source_updated_at,\n\t\t\tsource_version: row.source_version,\n\t\t\tsource_fingerprint: row.source_fingerprint,\n\t\t\tidentity_version: row.identity_version,\n\t\t\tsource_completeness: row.source_completeness,\n\t\t\tlast_attempted_at: row.last_attempted_at,\n\t\t\tlast_error_code: row.last_error_code,\n\t\t\tindexed_at: row.indexed_at,\n\t\t\tcreated_at: row.source_created_at,\n\t\t\tupdated_at: row.source_row_updated_at,\n\t\t}),\n\t\toccurrence: rowToOccurrence({\n\t\t\tid: row.occurrence_id,\n\t\t\tsource_key: row.source_key,\n\t\t\tgeneration: row.generation,\n\t\t\tfield_slug: row.field_slug,\n\t\t\tfield_path: row.field_path,\n\t\t\toccurrence_index: row.occurrence_index,\n\t\t\treference_type: row.reference_type,\n\t\t\tmedia_id: row.media_id,\n\t\t\tprovider: row.provider,\n\t\t\tprovider_asset_id: row.provider_asset_id,\n\t\t\tmedia_kind: row.media_kind,\n\t\t\tmime_type: row.mime_type,\n\t\t\tcreated_at: row.occurrence_created_at,\n\t\t\tcleanup_lease_token: null,\n\t\t}),\n\t};\n}\n\nfunction rowToIndexStatus(row: Selectable<MediaUsageIndexStatusTable>): MediaUsageIndexStatus {\n\treturn {\n\t\tadapterId: row.adapter_id,\n\t\tscopeType: row.scope_type,\n\t\tscopeKey: row.scope_key,\n\t\tstatus: row.status,\n\t\tschemaVersion: Number(row.schema_version),\n\t\tstartedAt: row.started_at,\n\t\tcompletedAt: row.completed_at,\n\t\tcursor: row.cursor,\n\t\tindexedSourceCount: Number(row.indexed_source_count),\n\t\tfailedSourceCount: Number(row.failed_source_count),\n\t\tlastErrorCode: row.last_error_code,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n","import type { Kysely } from \"kysely\";\n\nimport { tableExists } from \"../../database/dialect-helpers.js\";\nimport { MediaUsageRepository } from \"../../database/repositories/media-usage.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport { CONTENT_SOURCE_SCHEMA_VERSION } from \"./types.js\";\n\nexport const CONTENT_MEDIA_USAGE_ADAPTER_ID = \"content-media\";\nexport const CONTENT_MEDIA_USAGE_COLLECTION_SCOPE = \"collection\";\n\nexport async function markContentMediaUsageCollectionStale(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tlastErrorCode: string,\n): Promise<void> {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\tconst repo = new MediaUsageRepository(db);\n\tconst identity = {\n\t\tadapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,\n\t\tscopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,\n\t\tscopeKey: collectionSlug,\n\t};\n\tconst existing = await repo.findIndexStatus(identity);\n\tawait repo.upsertIndexStatus({\n\t\t...identity,\n\t\tstatus: \"stale\",\n\t\tschemaVersion: existing?.schemaVersion ?? CONTENT_SOURCE_SCHEMA_VERSION,\n\t\tstartedAt: existing?.startedAt ?? null,\n\t\tcompletedAt: existing?.completedAt ?? null,\n\t\tcursor: existing?.cursor ?? null,\n\t\tindexedSourceCount: existing?.indexedSourceCount ?? 0,\n\t\tfailedSourceCount: existing?.failedSourceCount ?? 0,\n\t\tlastErrorCode,\n\t});\n}\n\nexport async function invalidateContentMediaUsageSchemaChange(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n): Promise<boolean> {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\tif (!(await tableExists(db, \"_emdash_media_usage_activation\"))) return false;\n\tconst activation = await db\n\t\t.selectFrom(\"_emdash_media_usage_activation\")\n\t\t.select(\"state\")\n\t\t.where(\"task_key\", \"=\", \"incremental_capture\")\n\t\t.executeTakeFirst();\n\tif (activation?.state !== \"active\") return false;\n\n\tconst invalidated = await new MediaUsageRepository(db).invalidateIndexStatusForSchemaChange(\n\t\tcollectionSlug,\n\t);\n\tif (!invalidated) {\n\t\tthrow new Error(`Cannot invalidate media usage coverage for collection ${collectionSlug}`);\n\t}\n\treturn true;\n}\n\nexport async function markContentMediaUsageCollectionStaleSafely(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tlastErrorCode: string,\n): Promise<boolean> {\n\ttry {\n\t\tawait markContentMediaUsageCollectionStale(db, collectionSlug, lastErrorCode);\n\t\treturn true;\n\t} catch (error) {\n\t\tconsole.error(`[media-usage] Failed to mark ${collectionSlug} stale:`, error);\n\t\treturn false;\n\t}\n}\n","import type { FieldValidation, RepeaterSubField, UnsupportedFieldType } from \"./types.js\";\n\nexport const BLOCK_FIELD_TYPES = [\n\t\"string\",\n\t\"text\",\n\t\"url\",\n\t\"number\",\n\t\"integer\",\n\t\"boolean\",\n\t\"datetime\",\n\t\"select\",\n\t\"multiSelect\",\n\t\"portableText\",\n\t\"image\",\n\t\"file\",\n\t\"repeater\",\n] as const;\n\nexport type BlockFieldType = (typeof BLOCK_FIELD_TYPES)[number];\nexport type BlockTypeSource = \"user\" | \"seed\";\n\nexport interface BlockFieldOptions {\n\tdarkVariant?: boolean;\n}\n\nexport interface BlockFieldDefinition {\n\tslug: string;\n\tlabel: string;\n\ttype: BlockFieldType;\n\trequired?: boolean;\n\tdefaultValue?: unknown;\n\tvalidation?: Omit<FieldValidation, \"required\">;\n\toptions?: BlockFieldOptions;\n}\n\nexport interface BlockTypeVersion {\n\tid: string;\n\tblockTypeId: string;\n\tversion: number;\n\tfields: BlockFieldDefinition[];\n\tfingerprint: string;\n\tactive: boolean;\n\tunsupportedTypes?: UnsupportedFieldType[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface BlockType {\n\tid: string;\n\tslug: string;\n\tlabel: string;\n\tdescription?: string;\n\ticon?: string;\n\tcategory?: string;\n\tcurrentVersion: number;\n\tsource: BlockTypeSource;\n\tversions: BlockTypeVersion[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface CreateBlockTypeInput {\n\tslug: string;\n\tlabel: string;\n\tdescription?: string;\n\ticon?: string;\n\tcategory?: string;\n\tsource?: BlockTypeSource;\n\tfields: BlockFieldDefinition[];\n}\n\nexport interface UpdateBlockTypeInput {\n\texpectedFingerprint: string;\n\tlabel?: string;\n\tdescription?: string | null;\n\ticon?: string | null;\n\tcategory?: string | null;\n\tfields?: BlockFieldDefinition[];\n\tbreaking?: boolean;\n}\n\nexport interface SeedBlockTypeVersionInput {\n\tversion: number;\n\tfields: BlockFieldDefinition[];\n}\n\nexport interface ApplySeedBlockTypeInput {\n\tslug: string;\n\tlabel: string;\n\tdescription?: string;\n\ticon?: string;\n\tcategory?: string;\n\tcurrentVersion: number;\n\tversions: SeedBlockTypeVersionInput[];\n}\n\nexport type BlockTypeDifferenceCompatibility = \"compatible\" | \"breaking\";\n\nexport interface BlockTypeDifference {\n\tpath: string;\n\tchange: string;\n\tcompatibility: BlockTypeDifferenceCompatibility;\n}\n\nexport interface BlockTypeCompatibility {\n\tcompatible: boolean;\n\tdifferences: BlockTypeDifference[];\n}\n\nexport type BlockRepeaterSubField = RepeaterSubField;\n","import {\n\tBLOCK_FIELD_TYPES,\n\ttype BlockFieldDefinition,\n\ttype BlockFieldType,\n\ttype BlockTypeCompatibility,\n\ttype BlockTypeDifference,\n} from \"./block-types.js\";\nimport { SchemaError } from \"./registry.js\";\nimport { REPEATER_SUB_FIELD_TYPES, type RepeaterSubField } from \"./types.js\";\n\nconst SLUG_PATTERN = /^[a-z][a-z0-9_]*$/;\nconst MIME_PATTERN = /^[a-z0-9][a-z0-9!#$&^_+\\-.]*\\/[a-z0-9!#$&^_+\\-.]*$/i;\nconst MAX_SLUG_LENGTH = 63;\nconst MAX_LABEL_LENGTH = 200;\nconst RESERVED_VALUE_KEYS: ReadonlySet<string> = new Set([\"_type\", \"_version\", \"_key\"]);\nconst BLOCK_FIELD_TYPE_SET: ReadonlySet<string> = new Set(BLOCK_FIELD_TYPES);\nconst REPEATER_TYPE_SET: ReadonlySet<string> = new Set(REPEATER_SUB_FIELD_TYPES);\n\nconst VALIDATION_KEYS: Record<BlockFieldType, ReadonlySet<string>> = {\n\tstring: new Set([\"minLength\", \"maxLength\", \"pattern\"]),\n\ttext: new Set([\"minLength\", \"maxLength\", \"pattern\"]),\n\turl: new Set([\"minLength\", \"maxLength\", \"pattern\"]),\n\tnumber: new Set([\"min\", \"max\"]),\n\tinteger: new Set([\"min\", \"max\"]),\n\tboolean: new Set(),\n\tdatetime: new Set(),\n\tselect: new Set([\"options\"]),\n\tmultiSelect: new Set([\"options\"]),\n\tportableText: new Set(),\n\timage: new Set([\"allowedMimeTypes\"]),\n\tfile: new Set([\"allowedMimeTypes\"]),\n\trepeater: new Set([\"subFields\", \"minItems\", \"maxItems\"]),\n};\n\nfunction fail(path: string, message: string): never {\n\tthrow new SchemaError(`${path}: ${message}`, \"VALIDATION_ERROR\", { path });\n}\n\nfunction assertSlug(slug: unknown, path: string): asserts slug is string {\n\tif (\n\t\ttypeof slug !== \"string\" ||\n\t\tslug.length === 0 ||\n\t\tslug.length > MAX_SLUG_LENGTH ||\n\t\t!SLUG_PATTERN.test(slug)\n\t) {\n\t\tfail(\n\t\t\tpath,\n\t\t\t\"must start with a letter and contain only lowercase letters, numbers, and underscores\",\n\t\t);\n\t}\n}\n\nfunction assertLabel(label: unknown, path: string): asserts label is string {\n\tif (typeof label !== \"string\" || label.trim().length === 0 || label.length > MAX_LABEL_LENGTH) {\n\t\tfail(path, `must contain between 1 and ${MAX_LABEL_LENGTH} characters`);\n\t}\n}\n\nfunction isJsonValue(value: unknown, seen: Set<object> = new Set()): boolean {\n\tif (value === null || typeof value === \"string\" || typeof value === \"boolean\") return true;\n\tif (typeof value === \"number\") return Number.isFinite(value);\n\tif (typeof value !== \"object\") return false;\n\tif (seen.has(value)) return false;\n\tseen.add(value);\n\tif (Array.isArray(value)) {\n\t\tconst valid = value.every((entry) => isJsonValue(entry, seen));\n\t\tseen.delete(value);\n\t\treturn valid;\n\t}\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (prototype !== Object.prototype && prototype !== null) {\n\t\tseen.delete(value);\n\t\treturn false;\n\t}\n\tconst valid = Object.values(value).every((entry) => isJsonValue(entry, seen));\n\tseen.delete(value);\n\treturn valid;\n}\n\nfunction validateOptions(values: unknown, path: string): asserts values is string[] {\n\tif (!Array.isArray(values) || values.length === 0) fail(path, \"must be a non-empty array\");\n\tif (values.some((value) => typeof value !== \"string\" || value.length === 0)) {\n\t\tfail(path, \"must contain non-empty strings\");\n\t}\n\tif (new Set(values).size !== values.length) fail(path, \"must not contain duplicates\");\n}\n\nfunction validateRepeaterSubFields(\n\tvalue: unknown,\n\tpath: string,\n): asserts value is RepeaterSubField[] {\n\tif (!Array.isArray(value) || value.length === 0) fail(path, \"must be a non-empty array\");\n\tconst slugs = new Set<string>();\n\tfor (const [index, subField] of value.entries()) {\n\t\tconst fieldPath = `${path}[${index}]`;\n\t\tif (!subField || typeof subField !== \"object\" || Array.isArray(subField)) {\n\t\t\tfail(fieldPath, \"must be an object\");\n\t\t}\n\t\tconst slug = \"slug\" in subField ? subField.slug : undefined;\n\t\tassertSlug(slug, `${fieldPath}.slug`);\n\t\tif (RESERVED_VALUE_KEYS.has(slug)) fail(`${fieldPath}.slug`, `\"${slug}\" is reserved`);\n\t\tif (slugs.has(slug)) fail(`${fieldPath}.slug`, `duplicate slug \"${slug}\"`);\n\t\tslugs.add(slug);\n\t\tconst label = \"label\" in subField ? subField.label : undefined;\n\t\tassertLabel(label, `${fieldPath}.label`);\n\t\tconst type = \"type\" in subField ? subField.type : undefined;\n\t\tif (typeof type !== \"string\" || !REPEATER_TYPE_SET.has(type)) {\n\t\t\tfail(`${fieldPath}.type`, `unsupported repeater field type \"${String(type)}\"`);\n\t\t}\n\t\tconst options = \"options\" in subField ? subField.options : undefined;\n\t\tif (type === \"select\") validateOptions(options, `${fieldPath}.options`);\n\t\telse if (options !== undefined)\n\t\t\tfail(`${fieldPath}.options`, `is not supported for type \"${type}\"`);\n\t\tconst required = \"required\" in subField ? subField.required : undefined;\n\t\tif (required !== undefined && typeof required !== \"boolean\") {\n\t\t\tfail(`${fieldPath}.required`, \"must be a boolean\");\n\t\t}\n\t}\n}\n\nfunction validateValidation(field: BlockFieldDefinition, path: string): void {\n\tconst validation = field.validation;\n\tif (validation === undefined) {\n\t\tif (field.type === \"select\" || field.type === \"multiSelect\") {\n\t\t\tfail(`${path}.validation.options`, `is required for type \"${field.type}\"`);\n\t\t}\n\t\tif (field.type === \"repeater\") fail(`${path}.validation.subFields`, \"is required\");\n\t\treturn;\n\t}\n\tif (!validation || typeof validation !== \"object\" || Array.isArray(validation)) {\n\t\tfail(`${path}.validation`, \"must be an object\");\n\t}\n\tfor (const key of Object.keys(validation)) {\n\t\tif (!VALIDATION_KEYS[field.type].has(key)) {\n\t\t\tfail(`${path}.validation.${key}`, `is not supported for type \"${field.type}\"`);\n\t\t}\n\t}\n\n\tfor (const [minimum, maximum] of [\n\t\t[\"min\", \"max\"],\n\t\t[\"minLength\", \"maxLength\"],\n\t\t[\"minItems\", \"maxItems\"],\n\t] as const) {\n\t\tconst minimumValue = validation[minimum];\n\t\tconst maximumValue = validation[maximum];\n\t\tif (\n\t\t\tminimumValue !== undefined &&\n\t\t\t(typeof minimumValue !== \"number\" || !Number.isFinite(minimumValue))\n\t\t) {\n\t\t\tfail(`${path}.validation.${minimum}`, \"must be a finite number\");\n\t\t}\n\t\tif (\n\t\t\tmaximumValue !== undefined &&\n\t\t\t(typeof maximumValue !== \"number\" || !Number.isFinite(maximumValue))\n\t\t) {\n\t\t\tfail(`${path}.validation.${maximum}`, \"must be a finite number\");\n\t\t}\n\t\tif (\n\t\t\ttypeof minimumValue === \"number\" &&\n\t\t\ttypeof maximumValue === \"number\" &&\n\t\t\tminimumValue > maximumValue\n\t\t) {\n\t\t\tfail(`${path}.validation.${maximum}`, `must be greater than or equal to ${minimum}`);\n\t\t}\n\t}\n\tfor (const key of [\"minLength\", \"maxLength\", \"minItems\", \"maxItems\"] as const) {\n\t\tconst value = validation[key];\n\t\tif (value !== undefined && (!Number.isInteger(value) || value < 0)) {\n\t\t\tfail(`${path}.validation.${key}`, \"must be a non-negative integer\");\n\t\t}\n\t}\n\tif (validation.pattern !== undefined) {\n\t\tif (typeof validation.pattern !== \"string\")\n\t\t\tfail(`${path}.validation.pattern`, \"must be a string\");\n\t\ttry {\n\t\t\tRegExp(validation.pattern);\n\t\t} catch {\n\t\t\tfail(`${path}.validation.pattern`, \"must be a valid regular expression\");\n\t\t}\n\t}\n\tif (field.type === \"select\" || field.type === \"multiSelect\") {\n\t\tvalidateOptions(validation.options, `${path}.validation.options`);\n\t}\n\tif (field.type === \"repeater\") {\n\t\tvalidateRepeaterSubFields(validation.subFields, `${path}.validation.subFields`);\n\t}\n\tif (validation.allowedMimeTypes !== undefined) {\n\t\tvalidateOptions(validation.allowedMimeTypes, `${path}.validation.allowedMimeTypes`);\n\t\tfor (const mime of validation.allowedMimeTypes) {\n\t\t\tif (!MIME_PATTERN.test(mime))\n\t\t\t\tfail(`${path}.validation.allowedMimeTypes`, `invalid MIME type \"${mime}\"`);\n\t\t}\n\t}\n}\n\nexport function validateBlockFields(\n\tfields: readonly BlockFieldDefinition[],\n): BlockFieldDefinition[] {\n\tif (!Array.isArray(fields)) fail(\"fields\", \"must be an array\");\n\tconst slugs = new Set<string>();\n\treturn fields.map((field, index) => {\n\t\tconst path = `fields[${index}]`;\n\t\tif (!field || typeof field !== \"object\" || Array.isArray(field))\n\t\t\tfail(path, \"must be an object\");\n\t\tassertSlug(field.slug, `${path}.slug`);\n\t\tif (RESERVED_VALUE_KEYS.has(field.slug)) fail(`${path}.slug`, `\"${field.slug}\" is reserved`);\n\t\tif (slugs.has(field.slug)) fail(`${path}.slug`, `duplicate slug \"${field.slug}\"`);\n\t\tslugs.add(field.slug);\n\t\tassertLabel(field.label, `${path}.label`);\n\t\tif (typeof field.type !== \"string\" || !BLOCK_FIELD_TYPE_SET.has(field.type)) {\n\t\t\tfail(`${path}.type`, `unsupported block field type \"${String(field.type)}\"`);\n\t\t}\n\t\tif (field.required !== undefined && typeof field.required !== \"boolean\") {\n\t\t\tfail(`${path}.required`, \"must be a boolean\");\n\t\t}\n\t\tif (field.defaultValue !== undefined && !isJsonValue(field.defaultValue)) {\n\t\t\tfail(`${path}.defaultValue`, \"must be a JSON value\");\n\t\t}\n\t\tif (field.options !== undefined) {\n\t\t\tif (field.type !== \"image\")\n\t\t\t\tfail(`${path}.options`, `is not supported for type \"${field.type}\"`);\n\t\t\tfor (const key of Object.keys(field.options)) {\n\t\t\t\tif (key !== \"darkVariant\") fail(`${path}.options.${key}`, \"is not a supported option\");\n\t\t\t}\n\t\t\tif (\n\t\t\t\tfield.options.darkVariant !== undefined &&\n\t\t\t\ttypeof field.options.darkVariant !== \"boolean\"\n\t\t\t) {\n\t\t\t\tfail(`${path}.options.darkVariant`, \"must be a boolean\");\n\t\t\t}\n\t\t}\n\t\tvalidateValidation(field, path);\n\t\treturn field;\n\t});\n}\n\nfunction canonicalize(value: unknown): unknown {\n\tif (Array.isArray(value)) return value.map(canonicalize);\n\tif (!value || typeof value !== \"object\") return value;\n\tconst result: Record<string, unknown> = {};\n\tfor (const [key, entry] of Object.entries(value).toSorted(([left], [right]) =>\n\t\tleft.localeCompare(right),\n\t)) {\n\t\tif (entry !== undefined) result[key] = canonicalize(entry);\n\t}\n\treturn result;\n}\n\nfunction contractFields(fields: readonly BlockFieldDefinition[]): unknown[] {\n\treturn fields.map((field) => ({\n\t\tslug: field.slug,\n\t\ttype: field.type,\n\t\trequired: field.required ?? false,\n\t\t...(field.defaultValue !== undefined ? { defaultValue: field.defaultValue } : {}),\n\t\t...(field.validation !== undefined ? { validation: field.validation } : {}),\n\t\t...(field.options !== undefined ? { options: field.options } : {}),\n\t}));\n}\n\nexport function canonicalBlockFields(fields: readonly BlockFieldDefinition[]): string {\n\treturn JSON.stringify(canonicalize(contractFields(fields)));\n}\n\nexport async function fingerprintBlockFields(\n\tfields: readonly BlockFieldDefinition[],\n): Promise<string> {\n\tconst bytes = new TextEncoder().encode(canonicalBlockFields(fields));\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", bytes);\n\tconst hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\n\t\t\"\",\n\t);\n\treturn `block-type:v1:sha256:${hex}`;\n}\n\nfunction equal(a: unknown, b: unknown): boolean {\n\treturn JSON.stringify(canonicalize(a)) === JSON.stringify(canonicalize(b));\n}\n\nfunction difference(\n\tdifferences: BlockTypeDifference[],\n\tpath: string,\n\tchange: string,\n\tcompatibility: \"compatible\" | \"breaking\",\n): void {\n\tdifferences.push({ path, change, compatibility });\n}\n\nfunction compareLowerBound(\n\tdifferences: BlockTypeDifference[],\n\tpath: string,\n\tkey: \"min\" | \"minLength\" | \"minItems\",\n\tbefore: number | undefined,\n\tafter: number | undefined,\n): void {\n\tif (before === after) return;\n\tconst compatible = after === undefined || (before !== undefined && after <= before);\n\tdifference(\n\t\tdifferences,\n\t\t`${path}.validation.${key}`,\n\t\t\"changed\",\n\t\tcompatible ? \"compatible\" : \"breaking\",\n\t);\n}\n\nfunction compareUpperBound(\n\tdifferences: BlockTypeDifference[],\n\tpath: string,\n\tkey: \"max\" | \"maxLength\" | \"maxItems\",\n\tbefore: number | undefined,\n\tafter: number | undefined,\n): void {\n\tif (before === after) return;\n\tconst compatible = after === undefined || (before !== undefined && after >= before);\n\tdifference(\n\t\tdifferences,\n\t\t`${path}.validation.${key}`,\n\t\t\"changed\",\n\t\tcompatible ? \"compatible\" : \"breaking\",\n\t);\n}\n\nfunction compareSet(\n\tdifferences: BlockTypeDifference[],\n\tpath: string,\n\tbefore: readonly string[] | undefined,\n\tafter: readonly string[] | undefined,\n): void {\n\tif (equal(before, after)) return;\n\tif (after === undefined) {\n\t\tdifference(differences, path, \"constraint removed\", \"compatible\");\n\t\treturn;\n\t}\n\tif (before === undefined) {\n\t\tdifference(differences, path, \"constraint added\", \"breaking\");\n\t\treturn;\n\t}\n\tconst afterSet = new Set(after);\n\tconst removed = before.some((value) => !afterSet.has(value));\n\tdifference(differences, path, \"allowed values changed\", removed ? \"breaking\" : \"compatible\");\n}\n\nfunction repeaterFields(fields: readonly RepeaterSubField[] | undefined): BlockFieldDefinition[] {\n\treturn (fields ?? []).map((field) => ({\n\t\tslug: field.slug,\n\t\tlabel: field.label,\n\t\ttype: field.type,\n\t\trequired: field.required,\n\t\t...(field.options ? { validation: { options: field.options } } : {}),\n\t}));\n}\n\nfunction compareValidation(\n\tdifferences: BlockTypeDifference[],\n\tpath: string,\n\tbefore: BlockFieldDefinition,\n\tafter: BlockFieldDefinition,\n): void {\n\tconst beforeValidation = before.validation;\n\tconst afterValidation = after.validation;\n\tcompareLowerBound(differences, path, \"min\", beforeValidation?.min, afterValidation?.min);\n\tcompareUpperBound(differences, path, \"max\", beforeValidation?.max, afterValidation?.max);\n\tcompareLowerBound(\n\t\tdifferences,\n\t\tpath,\n\t\t\"minLength\",\n\t\tbeforeValidation?.minLength,\n\t\tafterValidation?.minLength,\n\t);\n\tcompareUpperBound(\n\t\tdifferences,\n\t\tpath,\n\t\t\"maxLength\",\n\t\tbeforeValidation?.maxLength,\n\t\tafterValidation?.maxLength,\n\t);\n\tcompareLowerBound(\n\t\tdifferences,\n\t\tpath,\n\t\t\"minItems\",\n\t\tbeforeValidation?.minItems,\n\t\tafterValidation?.minItems,\n\t);\n\tcompareUpperBound(\n\t\tdifferences,\n\t\tpath,\n\t\t\"maxItems\",\n\t\tbeforeValidation?.maxItems,\n\t\tafterValidation?.maxItems,\n\t);\n\tif (beforeValidation?.pattern !== afterValidation?.pattern) {\n\t\tconst compatible = afterValidation?.pattern === undefined;\n\t\tdifference(\n\t\t\tdifferences,\n\t\t\t`${path}.validation.pattern`,\n\t\t\t\"changed\",\n\t\t\tcompatible ? \"compatible\" : \"breaking\",\n\t\t);\n\t}\n\tcompareSet(\n\t\tdifferences,\n\t\t`${path}.validation.options`,\n\t\tbeforeValidation?.options,\n\t\tafterValidation?.options,\n\t);\n\tcompareSet(\n\t\tdifferences,\n\t\t`${path}.validation.allowedMimeTypes`,\n\t\tbeforeValidation?.allowedMimeTypes,\n\t\tafterValidation?.allowedMimeTypes,\n\t);\n\tif (before.type === \"repeater\" && after.type === \"repeater\") {\n\t\tcompareFields(\n\t\t\tdifferences,\n\t\t\t`${path}.validation.subFields`,\n\t\t\trepeaterFields(beforeValidation?.subFields),\n\t\t\trepeaterFields(afterValidation?.subFields),\n\t\t);\n\t}\n}\n\nfunction compareFields(\n\tdifferences: BlockTypeDifference[],\n\tpath: string,\n\tbefore: readonly BlockFieldDefinition[],\n\tafter: readonly BlockFieldDefinition[],\n): void {\n\tconst beforeBySlug = new Map(before.map((field) => [field.slug, field]));\n\tconst afterBySlug = new Map(after.map((field) => [field.slug, field]));\n\tfor (const field of before) {\n\t\tif (!afterBySlug.has(field.slug)) {\n\t\t\tdifference(differences, `${path}.${field.slug}`, \"field removed\", \"breaking\");\n\t\t}\n\t}\n\tfor (const field of after) {\n\t\tconst previous = beforeBySlug.get(field.slug);\n\t\tconst fieldPath = `${path}.${field.slug}`;\n\t\tif (!previous) {\n\t\t\tdifference(differences, fieldPath, \"field added\", field.required ? \"breaking\" : \"compatible\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (previous.type !== field.type) {\n\t\t\tdifference(differences, `${fieldPath}.type`, \"type changed\", \"breaking\");\n\t\t\tcontinue;\n\t\t}\n\t\tif ((previous.required ?? false) !== (field.required ?? false)) {\n\t\t\tdifference(\n\t\t\t\tdifferences,\n\t\t\t\t`${fieldPath}.required`,\n\t\t\t\t\"required changed\",\n\t\t\t\tfield.required ? \"breaking\" : \"compatible\",\n\t\t\t);\n\t\t}\n\t\tif (!equal(previous.defaultValue, field.defaultValue)) {\n\t\t\tdifference(differences, `${fieldPath}.defaultValue`, \"default changed\", \"compatible\");\n\t\t}\n\t\tcompareValidation(differences, fieldPath, previous, field);\n\t\tif ((previous.options?.darkVariant ?? false) !== (field.options?.darkVariant ?? false)) {\n\t\t\tdifference(\n\t\t\t\tdifferences,\n\t\t\t\t`${fieldPath}.options.darkVariant`,\n\t\t\t\t\"dark variant changed\",\n\t\t\t\tfield.options?.darkVariant ? \"compatible\" : \"breaking\",\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function compareBlockFields(\n\tbefore: readonly BlockFieldDefinition[],\n\tafter: readonly BlockFieldDefinition[],\n): BlockTypeCompatibility {\n\tconst differences: BlockTypeDifference[] = [];\n\tcompareFields(differences, \"fields\", before, after);\n\treturn {\n\t\tcompatible: differences.every((entry) => entry.compatibility === \"compatible\"),\n\t\tdifferences,\n\t};\n}\n","import { sql, type Kysely, type RawBuilder, type Selectable } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { refreshDevTypes } from \"../astro/dev-typegen.js\";\nimport {\n\tcurrentTimestampValue,\n\texecuteAtomicBatchIfSupported,\n} from \"../database/dialect-helpers.js\";\nimport { withTransaction } from \"../database/transaction.js\";\nimport type { BlockTypeTable, BlockTypeVersionTable, Database } from \"../database/types.js\";\nimport {\n\tinvalidateContentMediaUsageSchemaChange,\n\tmarkContentMediaUsageCollectionStaleSafely,\n} from \"../media/usage/schema-invalidation.js\";\nimport {\n\tcompareBlockFields,\n\tfingerprintBlockFields,\n\tvalidateBlockFields,\n} from \"./block-type-contract.js\";\nimport {\n\tBLOCK_FIELD_TYPES,\n\ttype BlockFieldDefinition,\n\ttype BlockFieldType,\n\ttype BlockType,\n\ttype BlockTypeSource,\n\ttype BlockTypeVersion,\n\ttype CreateBlockTypeInput,\n\ttype UpdateBlockTypeInput,\n\ttype ApplySeedBlockTypeInput,\n} from \"./block-types.js\";\nimport { SchemaError } from \"./registry.js\";\nimport { REPEATER_SUB_FIELD_TYPES, RESERVED_FIELD_SLUGS } from \"./types.js\";\nimport { invalidateSchemaCache } from \"./zod-generator.js\";\n\nconst SLUG_PATTERN = /^[a-z][a-z0-9_]*$/;\nconst MAX_SLUG_LENGTH = 63;\nconst MAX_LABEL_LENGTH = 200;\nconst UNIQUE_VIOLATION = /unique constraint failed|duplicate key value violates unique constraint/i;\nconst BLOCK_FIELD_TYPE_SET: ReadonlySet<string> = new Set(BLOCK_FIELD_TYPES);\nconst REPEATER_SUB_FIELD_TYPE_SET: ReadonlySet<string> = new Set(REPEATER_SUB_FIELD_TYPES);\nconst RESERVED_BLOCK_TYPE_SLUGS: ReadonlySet<string> = new Set(RESERVED_FIELD_SLUGS);\n\ninterface ParsedStoredFields {\n\tfields: BlockFieldDefinition[];\n\tunsupportedTypes: Array<{ type: string; path: string }>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nasync function executeAtomicStatements(\n\tdb: Kysely<Database>,\n\tstatements: readonly RawBuilder<{ id: string }>[],\n): Promise<number[]> {\n\tconst batched = await executeAtomicBatchIfSupported(db, statements);\n\tif (batched) return batched.map((result) => result.rows.length);\n\treturn withTransaction(db, async (trx) => {\n\t\tconst counts: number[] = [];\n\t\tfor (const statement of statements) {\n\t\t\t// oxlint-disable-next-line no-await-in-loop -- statement order is the mutation's atomic contract\n\t\t\tcounts.push((await statement.execute(trx)).rows.length);\n\t\t}\n\t\treturn counts;\n\t});\n}\n\nfunction assertBlockTypeSlug(slug: string): void {\n\tif (slug.length === 0 || slug.length > MAX_SLUG_LENGTH || !SLUG_PATTERN.test(slug)) {\n\t\tthrow new SchemaError(`Invalid block type slug \"${slug}\"`, \"INVALID_SLUG\", { slug });\n\t}\n\tif (RESERVED_BLOCK_TYPE_SLUGS.has(slug)) {\n\t\tthrow new SchemaError(`Block type slug \"${slug}\" is reserved`, \"RESERVED_SLUG\", { slug });\n\t}\n}\n\nfunction assertLabel(label: string): void {\n\tif (label.trim().length === 0 || label.length > MAX_LABEL_LENGTH) {\n\t\tthrow new SchemaError(\n\t\t\t`Block type label must contain between 1 and ${MAX_LABEL_LENGTH} characters`,\n\t\t\t\"VALIDATION_ERROR\",\n\t\t\t{ path: \"label\" },\n\t\t);\n\t}\n}\n\nfunction sourceValue(source: string): BlockTypeSource {\n\tif (source === \"user\" || source === \"seed\") return source;\n\tthrow new SchemaError(\n\t\t`Stored block type source \"${source}\" is unsupported`,\n\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t);\n}\n\nfunction parseStoredFields(raw: string): ParsedStoredFields {\n\tconst parsed: unknown = JSON.parse(raw);\n\tif (!Array.isArray(parsed)) {\n\t\tthrow new SchemaError(\n\t\t\t\"Stored block type fields are not an array\",\n\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t);\n\t}\n\tconst unsupportedTypes: Array<{ type: string; path: string }> = [];\n\tconst fields = parsed.map((entry, index) => {\n\t\tif (!isRecord(entry) || typeof entry.slug !== \"string\" || typeof entry.label !== \"string\") {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Stored block type field at index ${index} is invalid`,\n\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t);\n\t\t}\n\t\tconst rawType = entry.type;\n\t\tif (typeof rawType !== \"string\") {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Stored block type field at index ${index} has no valid type`,\n\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t);\n\t\t}\n\t\tconst type: BlockFieldType = BLOCK_FIELD_TYPE_SET.has(rawType)\n\t\t\t? // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- membership in the complete runtime type set narrows this database string\n\t\t\t\t(rawType as BlockFieldType)\n\t\t\t: \"string\";\n\t\tif (!BLOCK_FIELD_TYPE_SET.has(rawType)) {\n\t\t\tunsupportedTypes.push({ type: rawType, path: `fields[${index}].type` });\n\t\t}\n\t\tif (type === \"repeater\" && isRecord(entry.validation)) {\n\t\t\tconst subFields = entry.validation.subFields;\n\t\t\tif (Array.isArray(subFields)) {\n\t\t\t\tfor (const [subIndex, subField] of subFields.entries()) {\n\t\t\t\t\tif (!isRecord(subField) || typeof subField.type !== \"string\") continue;\n\t\t\t\t\tif (!REPEATER_SUB_FIELD_TYPE_SET.has(subField.type)) {\n\t\t\t\t\t\tunsupportedTypes.push({\n\t\t\t\t\t\t\ttype: subField.type,\n\t\t\t\t\t\t\tpath: `fields[${index}].validation.subFields[${subIndex}].type`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Stored definitions are written only after `validateBlockFields`. The\n\t\t// runtime checks type discriminants above before exposing this shape and\n\t\t// carries every unknown discriminant separately in `unsupportedTypes`.\n\t\t// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- validated database JSON with fail-closed discriminants\n\t\treturn { ...entry, type } as unknown as BlockFieldDefinition;\n\t});\n\treturn {\n\t\tfields: unsupportedTypes.length === 0 ? validateBlockFields(fields) : fields,\n\t\tunsupportedTypes,\n\t};\n}\n\nfunction mapVersion(\n\trow: Selectable<BlockTypeVersionTable>,\n\tcurrentVersion: number,\n): BlockTypeVersion {\n\tconst parsed = parseStoredFields(row.fields);\n\treturn {\n\t\tid: row.id,\n\t\tblockTypeId: row.block_type_id,\n\t\tversion: row.version,\n\t\tfields: parsed.fields,\n\t\tfingerprint: row.fingerprint,\n\t\tactive: row.version === currentVersion,\n\t\tunsupportedTypes: parsed.unsupportedTypes.length > 0 ? parsed.unsupportedTypes : undefined,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n\nfunction mapBlockType(\n\trow: Selectable<BlockTypeTable>,\n\tversions: readonly Selectable<BlockTypeVersionTable>[],\n): BlockType {\n\treturn {\n\t\tid: row.id,\n\t\tslug: row.slug,\n\t\tlabel: row.label,\n\t\tdescription: row.description ?? undefined,\n\t\ticon: row.icon ?? undefined,\n\t\tcategory: row.category ?? undefined,\n\t\tcurrentVersion: row.current_version,\n\t\tsource: sourceValue(row.source),\n\t\tversions: versions.map((version) => mapVersion(version, row.current_version)),\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n\nfunction activeVersion(blockType: BlockType): BlockTypeVersion {\n\tconst version = blockType.versions.find(\n\t\t(candidate) => candidate.version === blockType.currentVersion,\n\t);\n\tif (!version) {\n\t\tthrow new SchemaError(\n\t\t\t`Block type \"${blockType.slug}\" has no active version ${blockType.currentVersion}`,\n\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t{ slug: blockType.slug, version: blockType.currentVersion },\n\t\t);\n\t}\n\treturn version;\n}\n\nexport class BlockTypeRegistry {\n\tconstructor(private db: Kysely<Database>) {}\n\n\tasync listBlockTypes(): Promise<BlockType[]> {\n\t\tconst [types, versions] = await Promise.all([\n\t\t\tthis.db.selectFrom(\"_emdash_block_types\").selectAll().orderBy(\"slug\", \"asc\").execute(),\n\t\t\tthis.db\n\t\t\t\t.selectFrom(\"_emdash_block_type_versions\")\n\t\t\t\t.selectAll()\n\t\t\t\t.orderBy(\"block_type_id\", \"asc\")\n\t\t\t\t.orderBy(\"version\", \"asc\")\n\t\t\t\t.execute(),\n\t\t]);\n\t\tconst byType = new Map<string, Selectable<BlockTypeVersionTable>[]>();\n\t\tfor (const version of versions) {\n\t\t\tconst entries = byType.get(version.block_type_id) ?? [];\n\t\t\tentries.push(version);\n\t\t\tbyType.set(version.block_type_id, entries);\n\t\t}\n\t\treturn types.map((type) => mapBlockType(type, byType.get(type.id) ?? []));\n\t}\n\n\tasync getBlockType(slug: string): Promise<BlockType | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_block_types\")\n\t\t\t.selectAll()\n\t\t\t.where(\"slug\", \"=\", slug)\n\t\t\t.executeTakeFirst();\n\t\tif (!row) return null;\n\t\tconst versions = await this.db\n\t\t\t.selectFrom(\"_emdash_block_type_versions\")\n\t\t\t.selectAll()\n\t\t\t.where(\"block_type_id\", \"=\", row.id)\n\t\t\t.orderBy(\"version\", \"asc\")\n\t\t\t.execute();\n\t\treturn mapBlockType(row, versions);\n\t}\n\n\tasync listAffectedCollections(blockTypeSlug: string): Promise<string[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_fields as field\")\n\t\t\t.innerJoin(\"_emdash_collections as collection\", \"collection.id\", \"field.collection_id\")\n\t\t\t.select([\"collection.slug as collection\", \"field.validation\"])\n\t\t\t.where(\"field.type\", \"=\", \"blocks\")\n\t\t\t.execute();\n\t\tconst affected = new Set<string>();\n\t\tfor (const row of rows) {\n\t\t\tif (!row.validation) continue;\n\t\t\tconst validation: unknown = JSON.parse(row.validation);\n\t\t\tif (!isRecord(validation)) continue;\n\t\t\tconst allowed = Array.isArray(validation.allowedTypes) ? validation.allowedTypes : [];\n\t\t\tconst retired = Array.isArray(validation.retiredTypes) ? validation.retiredTypes : [];\n\t\t\tif ([...allowed, ...retired].includes(blockTypeSlug)) affected.add(row.collection);\n\t\t}\n\t\treturn [...affected].toSorted();\n\t}\n\n\tprivate async beginMediaSchemaMutation(slug: string): Promise<ReadonlySet<string>> {\n\t\tconst invalidated = new Set<string>();\n\t\tfor (const collection of await this.listAffectedCollections(slug)) {\n\t\t\tif (await invalidateContentMediaUsageSchemaChange(this.db, collection)) {\n\t\t\t\tinvalidated.add(collection);\n\t\t\t}\n\t\t}\n\t\treturn invalidated;\n\t}\n\n\tprivate async notifyMutation(\n\t\tslug: string,\n\t\tmediaInvalidated?: ReadonlySet<string>,\n\t): Promise<void> {\n\t\tconst collections = await this.listAffectedCollections(slug);\n\t\tfor (const collection of collections) {\n\t\t\tinvalidateSchemaCache(collection);\n\t\t\tif (!mediaInvalidated) continue;\n\t\t\tif (mediaInvalidated.has(collection)) {\n\t\t\t\tawait invalidateContentMediaUsageSchemaChange(this.db, collection);\n\t\t\t} else {\n\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\tthis.db,\n\t\t\t\t\tcollection,\n\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\trefreshDevTypes(this.db);\n\t}\n\n\tasync createBlockType(input: CreateBlockTypeInput): Promise<BlockType> {\n\t\tassertBlockTypeSlug(input.slug);\n\t\tassertLabel(input.label);\n\t\tif (input.source !== undefined && input.source !== \"user\" && input.source !== \"seed\") {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Invalid block type source \"${String(input.source)}\"`,\n\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t{\n\t\t\t\t\tpath: \"source\",\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tconst fields = validateBlockFields(input.fields);\n\t\tconst fingerprint = await fingerprintBlockFields(fields);\n\t\tconst typeId = ulid();\n\t\tconst versionId = ulid();\n\t\tconst mediaInvalidated = await this.beginMediaSchemaMutation(input.slug);\n\t\ttry {\n\t\t\tawait executeAtomicStatements(this.db, [\n\t\t\t\tsql<{ id: string }>`\n\t\t\t\t\tINSERT INTO _emdash_block_types (\n\t\t\t\t\t\tid, slug, label, description, icon, category, current_version, source\n\t\t\t\t\t) VALUES (\n\t\t\t\t\t\t${typeId}, ${input.slug}, ${input.label}, ${input.description ?? null},\n\t\t\t\t\t\t${input.icon ?? null}, ${input.category ?? null}, 1, ${input.source ?? \"user\"}\n\t\t\t\t\t)\n\t\t\t\t\tRETURNING id\n\t\t\t\t`,\n\t\t\t\tsql<{ id: string }>`\n\t\t\t\t\tINSERT INTO _emdash_block_type_versions (\n\t\t\t\t\t\tid, block_type_id, version, fields, fingerprint\n\t\t\t\t\t) VALUES (\n\t\t\t\t\t\t${versionId}, ${typeId}, 1, ${JSON.stringify(fields)}, ${fingerprint}\n\t\t\t\t\t)\n\t\t\t\t\tRETURNING id\n\t\t\t\t`,\n\t\t\t]);\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && UNIQUE_VIOLATION.test(error.message)) {\n\t\t\t\tthrow new SchemaError(`Block type \"${input.slug}\" already exists`, \"BLOCK_TYPE_EXISTS\", {\n\t\t\t\t\tslug: input.slug,\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tconst created = await this.getBlockType(input.slug);\n\t\tif (!created) {\n\t\t\tthrow new SchemaError(`Block type \"${input.slug}\" was not created`, \"BLOCK_TYPE_NOT_FOUND\");\n\t\t}\n\t\tawait this.notifyMutation(input.slug, mediaInvalidated);\n\t\treturn created;\n\t}\n\n\tasync updateBlockType(slug: string, input: UpdateBlockTypeInput): Promise<BlockType> {\n\t\tconst existing = await this.getBlockType(slug);\n\t\tif (!existing) {\n\t\t\tthrow new SchemaError(`Block type \"${slug}\" not found`, \"BLOCK_TYPE_NOT_FOUND\", { slug });\n\t\t}\n\t\tconst active = activeVersion(existing);\n\t\tif (active.unsupportedTypes?.length) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Block type \"${slug}\" contains unsupported field types`,\n\t\t\t\t\"UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t{ unsupportedTypes: active.unsupportedTypes },\n\t\t\t);\n\t\t}\n\t\tif (active.fingerprint !== input.expectedFingerprint) {\n\t\t\tthrow new SchemaError(`Block type \"${slug}\" changed since it was read`, \"CONFLICT\", {\n\t\t\t\texpectedFingerprint: input.expectedFingerprint,\n\t\t\t\tactualFingerprint: active.fingerprint,\n\t\t\t});\n\t\t}\n\t\tif (input.label !== undefined) assertLabel(input.label);\n\n\t\tconst fields = input.fields === undefined ? undefined : validateBlockFields(input.fields);\n\t\tconst compatibility = fields ? compareBlockFields(active.fields, fields) : undefined;\n\t\tif (compatibility && !compatibility.compatible && !input.breaking) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Block type \"${slug}\" update requires a new version`,\n\t\t\t\t\"BLOCK_TYPE_BREAKING_CHANGE\",\n\t\t\t\t{ differences: compatibility.differences },\n\t\t\t);\n\t\t}\n\n\t\tconst nextFingerprint = fields ? await fingerprintBlockFields(fields) : active.fingerprint;\n\t\tconst metadataAssignments: RawBuilder<unknown>[] = [\n\t\t\tsql`updated_at = ${currentTimestampValue(this.db)}`,\n\t\t];\n\t\tif (input.label !== undefined) metadataAssignments.push(sql`label = ${input.label}`);\n\t\tif (input.description !== undefined) {\n\t\t\tmetadataAssignments.push(sql`description = ${input.description}`);\n\t\t}\n\t\tif (input.icon !== undefined) metadataAssignments.push(sql`icon = ${input.icon}`);\n\t\tif (input.category !== undefined) metadataAssignments.push(sql`category = ${input.category}`);\n\t\tconst metadataUpdate = sql<{ id: string }>`\n\t\t\tUPDATE _emdash_block_types\n\t\t\tSET ${sql.join(metadataAssignments, sql`, `)}\n\t\t\tWHERE id = ${existing.id}\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_block_type_versions\n\t\t\t\t\tWHERE block_type_id = ${existing.id}\n\t\t\t\t\t\tAND version = _emdash_block_types.current_version\n\t\t\t\t\t\tAND fingerprint = ${input.expectedFingerprint}\n\t\t\t\t)\n\t\t\tRETURNING id\n\t\t`;\n\t\tconst mediaInvalidated =\n\t\t\tfields && nextFingerprint !== active.fingerprint\n\t\t\t\t? await this.beginMediaSchemaMutation(slug)\n\t\t\t\t: undefined;\n\n\t\tif (compatibility && !compatibility.compatible && fields) {\n\t\t\tconst existingRetry = existing.versions.find(\n\t\t\t\t(version) =>\n\t\t\t\t\tversion.version !== existing.currentVersion &&\n\t\t\t\t\tversion.fingerprint === nextFingerprint &&\n\t\t\t\t\tJSON.stringify(version.fields) === JSON.stringify(fields),\n\t\t\t);\n\t\t\tif (!existingRetry) {\n\t\t\t\tconst nextVersion = Math.max(...existing.versions.map((version) => version.version)) + 1;\n\t\t\t\ttry {\n\t\t\t\t\tconst counts = await executeAtomicStatements(this.db, [\n\t\t\t\t\t\tsql<{ id: string }>`\n\t\t\t\t\t\t\tINSERT INTO _emdash_block_type_versions (\n\t\t\t\t\t\t\t\tid, block_type_id, version, fields, fingerprint\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\t\t${ulid()}, ${existing.id}, ${nextVersion},\n\t\t\t\t\t\t\t\t${JSON.stringify(fields)}, ${nextFingerprint}\n\t\t\t\t\t\t\tWHERE EXISTS (\n\t\t\t\t\t\t\t\tSELECT 1 FROM _emdash_block_type_versions\n\t\t\t\t\t\t\t\tWHERE block_type_id = ${existing.id}\n\t\t\t\t\t\t\t\t\tAND version = ${existing.currentVersion}\n\t\t\t\t\t\t\t\t\tAND fingerprint = ${input.expectedFingerprint}\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tRETURNING id\n\t\t\t\t\t\t`,\n\t\t\t\t\t\tmetadataUpdate,\n\t\t\t\t\t]);\n\t\t\t\t\tif (counts[0] !== 1 || counts[1] !== 1) {\n\t\t\t\t\t\tthrow new SchemaError(`Block type \"${slug}\" changed since it was read`, \"CONFLICT\");\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof SchemaError) throw error;\n\t\t\t\t\tif (error instanceof Error && UNIQUE_VIOLATION.test(error.message)) {\n\t\t\t\t\t\tconst reread = await this.getBlockType(slug);\n\t\t\t\t\t\tconst raced = reread?.versions.find((version) => version.version === nextVersion);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\traced?.fingerprint !== nextFingerprint ||\n\t\t\t\t\t\t\tJSON.stringify(raced.fields) !== JSON.stringify(fields)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t\t`Block type \"${slug}\" version ${nextVersion} was created concurrently with a different contract`,\n\t\t\t\t\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t\t\t\t\t\t{ version: nextVersion },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst counts = await executeAtomicStatements(this.db, [metadataUpdate]);\n\t\t\t\tif (counts[0] !== 1) {\n\t\t\t\t\tthrow new SchemaError(`Block type \"${slug}\" changed since it was read`, \"CONFLICT\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (fields) {\n\t\t\tconst counts = await executeAtomicStatements(this.db, [\n\t\t\t\tmetadataUpdate,\n\t\t\t\tsql<{ id: string }>`\n\t\t\t\t\tUPDATE _emdash_block_type_versions\n\t\t\t\t\tSET fields = ${JSON.stringify(fields)},\n\t\t\t\t\t\tfingerprint = ${nextFingerprint},\n\t\t\t\t\t\tupdated_at = ${currentTimestampValue(this.db)}\n\t\t\t\t\tWHERE block_type_id = ${existing.id}\n\t\t\t\t\t\tAND version = ${active.version}\n\t\t\t\t\t\tAND fingerprint = ${input.expectedFingerprint}\n\t\t\t\t\tRETURNING id\n\t\t\t\t`,\n\t\t\t]);\n\t\t\tif (counts[0] !== 1 || counts[1] !== 1) {\n\t\t\t\tthrow new SchemaError(`Block type \"${slug}\" changed since it was read`, \"CONFLICT\");\n\t\t\t}\n\t\t} else {\n\t\t\tconst counts = await executeAtomicStatements(this.db, [metadataUpdate]);\n\t\t\tif (counts[0] !== 1) {\n\t\t\t\tthrow new SchemaError(`Block type \"${slug}\" changed since it was read`, \"CONFLICT\");\n\t\t\t}\n\t\t}\n\n\t\tconst updated = await this.getBlockType(slug);\n\t\tif (!updated) throw new SchemaError(`Block type \"${slug}\" not found`, \"BLOCK_TYPE_NOT_FOUND\");\n\t\tawait this.notifyMutation(slug, mediaInvalidated);\n\t\treturn updated;\n\t}\n\n\tasync applySeedBlockType(\n\t\tinput: ApplySeedBlockTypeInput,\n\t\tonConflict: \"skip\" | \"error\" | \"update\" = \"skip\",\n\t): Promise<BlockType> {\n\t\tassertBlockTypeSlug(input.slug);\n\t\tassertLabel(input.label);\n\t\tconst versions = await Promise.all(\n\t\t\tinput.versions\n\t\t\t\t.toSorted((left, right) => left.version - right.version)\n\t\t\t\t.map(async (version) => ({\n\t\t\t\t\tversion: version.version,\n\t\t\t\t\tfields: validateBlockFields(version.fields),\n\t\t\t\t\tfingerprint: await fingerprintBlockFields(version.fields),\n\t\t\t\t})),\n\t\t);\n\t\tif (\n\t\t\tversions.length === 0 ||\n\t\t\tversions[0]?.version !== 1 ||\n\t\t\tversions.some(\n\t\t\t\t(version, index) =>\n\t\t\t\t\t!Number.isInteger(version.version) ||\n\t\t\t\t\tversion.version < 1 ||\n\t\t\t\t\t(index > 0 && version.version !== versions[index - 1].version + 1),\n\t\t\t)\n\t\t) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Block type \"${input.slug}\" versions must be contiguous positive integers starting at 1`,\n\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t);\n\t\t}\n\t\tif (!versions.some((version) => version.version === input.currentVersion)) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Block type \"${input.slug}\" currentVersion ${input.currentVersion} is not declared`,\n\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t);\n\t\t}\n\n\t\tconst existing = await this.getBlockType(input.slug);\n\t\tif (existing && onConflict === \"error\") {\n\t\t\tthrow new SchemaError(`Block type \"${input.slug}\" already exists`, \"BLOCK_TYPE_EXISTS\");\n\t\t}\n\t\tif (existing && onConflict === \"skip\") return existing;\n\t\tconst mediaInvalidated = await this.beginMediaSchemaMutation(input.slug);\n\n\t\tif (!existing) {\n\t\t\tconst typeId = ulid();\n\t\t\tconst statements: RawBuilder<{ id: string }>[] = [\n\t\t\t\tsql<{ id: string }>`\n\t\t\t\t\tINSERT INTO _emdash_block_types (\n\t\t\t\t\t\tid, slug, label, description, icon, category, current_version, source\n\t\t\t\t\t) VALUES (\n\t\t\t\t\t\t${typeId}, ${input.slug}, ${input.label}, ${input.description ?? null},\n\t\t\t\t\t\t${input.icon ?? null}, ${input.category ?? null}, ${input.currentVersion}, 'seed'\n\t\t\t\t\t)\n\t\t\t\t\tRETURNING id\n\t\t\t\t`,\n\t\t\t];\n\t\t\tfor (const version of versions) {\n\t\t\t\tstatements.push(sql<{ id: string }>`\n\t\t\t\t\tINSERT INTO _emdash_block_type_versions (\n\t\t\t\t\t\tid, block_type_id, version, fields, fingerprint\n\t\t\t\t\t) VALUES (\n\t\t\t\t\t\t${ulid()}, ${typeId}, ${version.version},\n\t\t\t\t\t\t${JSON.stringify(version.fields)}, ${version.fingerprint}\n\t\t\t\t\t)\n\t\t\t\t\tRETURNING id\n\t\t\t\t`);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait executeAtomicStatements(this.db, statements);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error && UNIQUE_VIOLATION.test(error.message)) {\n\t\t\t\t\tthrow new SchemaError(`Block type \"${input.slug}\" already exists`, \"BLOCK_TYPE_EXISTS\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} else {\n\t\t\tconst statements: RawBuilder<{ id: string }>[] = [\n\t\t\t\tsql<{ id: string }>`\n\t\t\t\t\tUPDATE _emdash_block_types\n\t\t\t\t\tSET label = ${input.label}, description = ${input.description ?? null},\n\t\t\t\t\t\ticon = ${input.icon ?? null}, category = ${input.category ?? null},\n\t\t\t\t\t\tupdated_at = ${currentTimestampValue(this.db)}\n\t\t\t\t\tWHERE id = ${existing.id}\n\t\t\t\t\tRETURNING id\n\t\t\t\t`,\n\t\t\t];\n\t\t\tfor (const version of versions) {\n\t\t\t\tconst stored = existing.versions.find((candidate) => candidate.version === version.version);\n\t\t\t\tif (stored) {\n\t\t\t\t\tif (stored.unsupportedTypes?.length) {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`Block type \"${input.slug}\" version ${version.version} contains unsupported field types`,\n\t\t\t\t\t\t\t\"UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t\t\t\t{ unsupportedTypes: stored.unsupportedTypes },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tstored.fingerprint !== version.fingerprint &&\n\t\t\t\t\t\t!compareBlockFields(stored.fields, version.fields).compatible\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`Block type \"${input.slug}\" version ${version.version} has an incompatible stored contract`,\n\t\t\t\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t\t\t\t\t{ version: version.version },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tstatements.push(sql<{ id: string }>`\n\t\t\t\t\t\tUPDATE _emdash_block_type_versions\n\t\t\t\t\t\tSET fields = ${JSON.stringify(version.fields)},\n\t\t\t\t\t\t\tfingerprint = ${version.fingerprint},\n\t\t\t\t\t\t\tupdated_at = ${currentTimestampValue(this.db)}\n\t\t\t\t\t\tWHERE id = ${stored.id}\n\t\t\t\t\t\tRETURNING id\n\t\t\t\t\t`);\n\t\t\t\t} else {\n\t\t\t\t\tstatements.push(sql<{ id: string }>`\n\t\t\t\t\t\tINSERT INTO _emdash_block_type_versions (\n\t\t\t\t\t\t\tid, block_type_id, version, fields, fingerprint\n\t\t\t\t\t\t) VALUES (\n\t\t\t\t\t\t\t${ulid()}, ${existing.id}, ${version.version},\n\t\t\t\t\t\t\t${JSON.stringify(version.fields)}, ${version.fingerprint}\n\t\t\t\t\t\t)\n\t\t\t\t\t\tRETURNING id\n\t\t\t\t\t`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tstatements.push(sql<{ id: string }>`\n\t\t\t\tUPDATE _emdash_block_types\n\t\t\t\tSET current_version = ${input.currentVersion},\n\t\t\t\t\tupdated_at = ${currentTimestampValue(this.db)}\n\t\t\t\tWHERE id = ${existing.id}\n\t\t\t\tRETURNING id\n\t\t\t`);\n\t\t\tawait executeAtomicStatements(this.db, statements);\n\t\t}\n\n\t\tconst applied = await this.getBlockType(input.slug);\n\t\tif (!applied) {\n\t\t\tthrow new SchemaError(`Block type \"${input.slug}\" not found`, \"BLOCK_TYPE_NOT_FOUND\");\n\t\t}\n\t\tawait this.notifyMutation(input.slug, mediaInvalidated);\n\t\treturn applied;\n\t}\n\n\tasync activateVersion(\n\t\tslug: string,\n\t\tversion: number,\n\t\texpectedFingerprint: string,\n\t): Promise<BlockType> {\n\t\tconst existing = await this.getBlockType(slug);\n\t\tif (!existing) {\n\t\t\tthrow new SchemaError(`Block type \"${slug}\" not found`, \"BLOCK_TYPE_NOT_FOUND\", { slug });\n\t\t}\n\t\tconst active = activeVersion(existing);\n\t\tif (active.fingerprint !== expectedFingerprint) {\n\t\t\tthrow new SchemaError(`Block type \"${slug}\" changed since it was read`, \"CONFLICT\", {\n\t\t\t\texpectedFingerprint,\n\t\t\t\tactualFingerprint: active.fingerprint,\n\t\t\t});\n\t\t}\n\t\tconst target = existing.versions.find((candidate) => candidate.version === version);\n\t\tif (!target) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Block type \"${slug}\" has no version ${version}`,\n\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t\t{ slug, version },\n\t\t\t);\n\t\t}\n\t\tif (target.unsupportedTypes?.length) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Block type \"${slug}\" version ${version} contains unsupported field types`,\n\t\t\t\t\"UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t{ unsupportedTypes: target.unsupportedTypes },\n\t\t\t);\n\t\t}\n\t\tconst mediaInvalidated =\n\t\t\tversion !== existing.currentVersion ? await this.beginMediaSchemaMutation(slug) : undefined;\n\t\tif (version !== existing.currentVersion) {\n\t\t\tconst result = await sql<{ id: string }>`\n\t\t\t\tUPDATE _emdash_block_types\n\t\t\t\tSET current_version = ${version},\n\t\t\t\t\tupdated_at = ${currentTimestampValue(this.db)}\n\t\t\t\tWHERE id = ${existing.id}\n\t\t\t\t\tAND current_version = ${existing.currentVersion}\n\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM _emdash_block_type_versions\n\t\t\t\t\t\tWHERE block_type_id = ${existing.id}\n\t\t\t\t\t\t\tAND version = ${existing.currentVersion}\n\t\t\t\t\t\t\tAND fingerprint = ${expectedFingerprint}\n\t\t\t\t\t)\n\t\t\t\tRETURNING id\n\t\t\t`.execute(this.db);\n\t\t\tif (result.rows.length !== 1) {\n\t\t\t\tthrow new SchemaError(`Block type \"${slug}\" changed since it was read`, \"CONFLICT\");\n\t\t\t}\n\t\t}\n\t\tconst updated = await this.getBlockType(slug);\n\t\tif (!updated) throw new SchemaError(`Block type \"${slug}\" not found`, \"BLOCK_TYPE_NOT_FOUND\");\n\t\tawait this.notifyMutation(slug, mediaInvalidated);\n\t\treturn updated;\n\t}\n}\n","import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport { BlockTypeRegistry } from \"../../schema/block-type-registry.js\";\nimport type { BlockType } from \"../../schema/block-types.js\";\nimport { buildCanonicalSha256Fingerprint } from \"./projection-fingerprint.js\";\nimport type { MediaUsageExtractionField, MediaUsageExtractionSubField } from \"./types.js\";\nimport { CONTENT_SOURCE_SCHEMA_VERSION } from \"./types.js\";\n\nexport type ContentMediaUsageField = MediaUsageExtractionField;\n\nexport interface ContentMediaUsageFieldDiscovery {\n\textractionFields: ContentMediaUsageField[];\n\tdisplayFieldSlugs: string[];\n}\n\nexport async function buildContentMediaUsageFieldFingerprint(\n\tdiscovery: ContentMediaUsageFieldDiscovery,\n): Promise<string> {\n\tconst extractionFields = discovery.extractionFields\n\t\t.map((field) => ({\n\t\t\tslug: field.slug,\n\t\t\ttype: field.type,\n\t\t\t...(field.type === \"blocks\"\n\t\t\t\t? {\n\t\t\t\t\t\tblockTypes: (field.blockTypes ?? []).map((type) => ({\n\t\t\t\t\t\t\tslug: type.slug,\n\t\t\t\t\t\t\tcurrentVersion: type.currentVersion,\n\t\t\t\t\t\t\tversions: type.versions.map((version) => ({\n\t\t\t\t\t\t\t\tversion: version.version,\n\t\t\t\t\t\t\t\tfingerprint: version.fingerprint,\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t})),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(field.type === \"repeater\"\n\t\t\t\t? {\n\t\t\t\t\t\tsubFields: (field.validation?.subFields ?? [])\n\t\t\t\t\t\t\t.map((subField) => ({ slug: subField.slug, type: subField.type }))\n\t\t\t\t\t\t\t.toSorted(compareFieldIdentity),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t}))\n\t\t.toSorted(compareFieldIdentity);\n\tconst result = await buildCanonicalSha256Fingerprint(\"media-usage-fields:v1:sha256:\", {\n\t\tfingerprintVersion: 1,\n\t\tcontentSourceSchemaVersion: CONTENT_SOURCE_SCHEMA_VERSION,\n\t\textractionFields,\n\t\tdisplayFieldSlugs: discovery.displayFieldSlugs.toSorted(compareStrings),\n\t});\n\treturn result.fingerprint;\n}\n\nexport class MediaUsageFieldDiscoveryError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic code:\n\t\t\t| \"INVALID_REPEATER_VALIDATION\"\n\t\t\t| \"INVALID_BLOCK_VALIDATION\"\n\t\t\t| \"UNSUPPORTED_BLOCK_DEFINITION\",\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"MediaUsageFieldDiscoveryError\";\n\t}\n}\n\ninterface FieldDiscoveryRow {\n\tslug: string;\n\ttype: string;\n\tvalidation: string | null;\n}\n\nconst DISPLAY_FIELD_SLUGS = [\"title\", \"name\"] as const;\nconst SUPPORTED_TOP_LEVEL_TYPES = [\"file\", \"image\", \"portableText\"] as const;\n\ntype SupportedTopLevelType = (typeof SUPPORTED_TOP_LEVEL_TYPES)[number];\n\nexport async function loadContentMediaUsageFields(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcollectionId?: string,\n): Promise<ContentMediaUsageFieldDiscovery> {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\n\tlet query = db\n\t\t.selectFrom(\"_emdash_fields\")\n\t\t.innerJoin(\"_emdash_collections\", \"_emdash_collections.id\", \"_emdash_fields.collection_id\")\n\t\t.select([\"_emdash_fields.slug\", \"_emdash_fields.type\", \"_emdash_fields.validation\"])\n\t\t.where(\"_emdash_collections.slug\", \"=\", collectionSlug);\n\tif (collectionId !== undefined) query = query.where(\"_emdash_collections.id\", \"=\", collectionId);\n\tconst rows = await query.execute();\n\n\tconst extractionFields: ContentMediaUsageField[] = [];\n\tconst rowBySlug = new Map<string, FieldDiscoveryRow>();\n\tconst allBlockTypes = rows.some((row) => row.type === \"blocks\")\n\t\t? await new BlockTypeRegistry(db).listBlockTypes()\n\t\t: [];\n\n\tfor (const row of rows) {\n\t\trowBySlug.set(row.slug, row);\n\t\tif (isSupportedTopLevelType(row.type)) {\n\t\t\tvalidateIdentifier(row.slug, \"media usage field slug\");\n\t\t\textractionFields.push({ slug: row.slug, type: row.type });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (row.type === \"repeater\") {\n\t\t\tvalidateIdentifier(row.slug, \"media usage field slug\");\n\t\t\tconst subFields = normalizeRepeaterImageSubFields(row.validation);\n\t\t\tif (subFields.length > 0) {\n\t\t\t\textractionFields.push({\n\t\t\t\t\tslug: row.slug,\n\t\t\t\t\ttype: \"repeater\",\n\t\t\t\t\tvalidation: { subFields },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (row.type === \"blocks\") {\n\t\t\tvalidateIdentifier(row.slug, \"media usage field slug\");\n\t\t\tconst configured = parseBlockTypeSlugs(row.validation);\n\t\t\tconst blockTypes = resolveMediaBlockTypes(allBlockTypes, configured);\n\t\t\textractionFields.push({ slug: row.slug, type: \"blocks\", blockTypes });\n\t\t}\n\t}\n\n\textractionFields.sort((a, b) => a.slug.localeCompare(b.slug));\n\n\treturn {\n\t\textractionFields,\n\t\tdisplayFieldSlugs: DISPLAY_FIELD_SLUGS.filter((slug) => {\n\t\t\tif (!rowBySlug.has(slug)) return false;\n\t\t\tvalidateIdentifier(slug, \"media usage display field slug\");\n\t\t\treturn true;\n\t\t}),\n\t};\n}\n\nfunction parseBlockTypeSlugs(rawValidation: string | null): string[] {\n\tconst validation = parseValidation(rawValidation, \"block\");\n\tif (!isRecord(validation)) {\n\t\tthrow new MediaUsageFieldDiscoveryError(\n\t\t\t\"Blocks field validation must be an object before media usage can be discovered\",\n\t\t\t\"INVALID_BLOCK_VALIDATION\",\n\t\t);\n\t}\n\tconst allowed = Array.isArray(validation.allowedTypes) ? validation.allowedTypes : [];\n\tconst retired = Array.isArray(validation.retiredTypes) ? validation.retiredTypes : [];\n\tconst values = [...allowed, ...retired];\n\tif (values.some((value) => typeof value !== \"string\")) {\n\t\tthrow new MediaUsageFieldDiscoveryError(\n\t\t\t\"Blocks field type lists must contain strings before media usage can be discovered\",\n\t\t\t\"INVALID_BLOCK_VALIDATION\",\n\t\t);\n\t}\n\treturn [...new Set(values)];\n}\n\nfunction resolveMediaBlockTypes(\n\ttypes: readonly BlockType[],\n\tslugs: readonly string[],\n): BlockType[] {\n\tconst bySlug = new Map(types.map((type) => [type.slug, type]));\n\treturn slugs.map((slug) => {\n\t\tconst type = bySlug.get(slug);\n\t\tif (!type || type.versions.some((version) => version.unsupportedTypes?.length)) {\n\t\t\tthrow new MediaUsageFieldDiscoveryError(\n\t\t\t\t`Block type \"${slug}\" cannot be resolved for media usage`,\n\t\t\t\t\"UNSUPPORTED_BLOCK_DEFINITION\",\n\t\t\t);\n\t\t}\n\t\treturn type;\n\t});\n}\n\nfunction normalizeRepeaterImageSubFields(\n\trawValidation: string | null,\n): MediaUsageExtractionSubField[] {\n\tconst validation = parseValidation(rawValidation, \"repeater\");\n\tif (!isRecord(validation) || !Array.isArray(validation.subFields)) return [];\n\n\tconst subFields: MediaUsageExtractionSubField[] = [];\n\tfor (const subField of validation.subFields) {\n\t\tif (!isRecord(subField) || subField.type !== \"image\") continue;\n\t\tif (typeof subField.slug !== \"string\") continue;\n\t\tvalidateIdentifier(subField.slug, \"media usage repeater sub-field slug\");\n\t\tsubFields.push({ slug: subField.slug, type: \"image\" });\n\t}\n\n\treturn subFields.toSorted((a, b) => a.slug.localeCompare(b.slug));\n}\n\nfunction parseValidation(rawValidation: string | null, kind: \"block\" | \"repeater\"): unknown {\n\tif (!rawValidation) return null;\n\ttry {\n\t\treturn JSON.parse(rawValidation);\n\t} catch {\n\t\tthrow new MediaUsageFieldDiscoveryError(\n\t\t\t`${kind === \"block\" ? \"Blocks\" : \"Repeater\"} field validation must be valid JSON before media usage can be discovered`,\n\t\t\tkind === \"block\" ? \"INVALID_BLOCK_VALIDATION\" : \"INVALID_REPEATER_VALIDATION\",\n\t\t);\n\t}\n}\n\nfunction isSupportedTopLevelType(value: string): value is SupportedTopLevelType {\n\treturn (SUPPORTED_TOP_LEVEL_TYPES as readonly string[]).includes(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction compareFieldIdentity(a: { slug: string }, b: { slug: string }): number {\n\treturn compareStrings(a.slug, b.slug);\n}\n\nfunction compareStrings(a: string, b: string): number {\n\treturn a < b ? -1 : a > b ? 1 : 0;\n}\n","import { normalizeMime } from \"../mime.js\";\nimport { INTERNAL_MEDIA_PREFIX } from \"../normalize.js\";\nimport type {\n\tExtractedMediaUsageOccurrence,\n\tExtractMediaUsageOccurrencesInput,\n\tMediaKind,\n\tMediaUsageExtractionSubField,\n\tMediaUsageReferenceType,\n} from \"./types.js\";\n\nconst URL_LIKE_RE = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\ninterface MediaRef {\n\tmediaId: string | null;\n\tprovider: string;\n\tproviderAssetId: string;\n\tmediaKind: MediaKind | null;\n\tmimeType: string | null;\n}\n\ninterface AddOccurrenceInput {\n\tfieldSlug: string;\n\tfieldPath: string;\n\treferenceType: MediaUsageReferenceType;\n\tvalue: unknown;\n\tfallbackKind: MediaKind | null;\n}\n\nexport function extractMediaUsageOccurrences({\n\tfields,\n\tdata,\n}: ExtractMediaUsageOccurrencesInput): ExtractedMediaUsageOccurrence[] {\n\tconst occurrences: ExtractedMediaUsageOccurrence[] = [];\n\tconst seen = new Set<string>();\n\n\tfor (const field of fields) {\n\t\tconst value = data[field.slug];\n\n\t\tif (field.type === \"image\") {\n\t\t\taddImageOccurrences(occurrences, seen, field.slug, field.slug, value);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"file\") {\n\t\t\taddOccurrence(occurrences, seen, {\n\t\t\t\tfieldSlug: field.slug,\n\t\t\t\tfieldPath: field.slug,\n\t\t\t\treferenceType: \"file_field\",\n\t\t\t\tvalue,\n\t\t\t\tfallbackKind: null,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"repeater\") {\n\t\t\textractRepeaterOccurrences(occurrences, seen, field.slug, value, field.validation?.subFields);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"portableText\") {\n\t\t\textractPortableTextOccurrences(occurrences, seen, field.slug, value);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"blocks\") {\n\t\t\textractBlockOccurrences(occurrences, seen, field, value);\n\t\t}\n\t}\n\n\treturn occurrences;\n}\n\nfunction extractRepeaterOccurrences(\n\toccurrences: ExtractedMediaUsageOccurrence[],\n\tseen: Set<string>,\n\tfieldSlug: string,\n\tvalue: unknown,\n\tsubFields: readonly MediaUsageExtractionSubField[] | undefined,\n\tpathPrefix = fieldSlug,\n): void {\n\tif (!Array.isArray(value) || !Array.isArray(subFields)) return;\n\n\tfor (const [itemIndex, item] of value.entries()) {\n\t\tif (!isRecord(item)) continue;\n\n\t\tfor (const subField of subFields) {\n\t\t\tif (subField.type !== \"image\") continue;\n\n\t\t\taddImageOccurrences(\n\t\t\t\toccurrences,\n\t\t\t\tseen,\n\t\t\t\tfieldSlug,\n\t\t\t\t`${pathPrefix}[${itemIndex}].${subField.slug}`,\n\t\t\t\titem[subField.slug],\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction addImageOccurrences(\n\toccurrences: ExtractedMediaUsageOccurrence[],\n\tseen: Set<string>,\n\tfieldSlug: string,\n\tfieldPath: string,\n\tvalue: unknown,\n): void {\n\taddOccurrence(occurrences, seen, {\n\t\tfieldSlug,\n\t\tfieldPath,\n\t\treferenceType: \"image_field\",\n\t\tvalue,\n\t\tfallbackKind: \"image\",\n\t});\n\tif (isRecord(value) && value.darkVariant != null) {\n\t\taddOccurrence(occurrences, seen, {\n\t\t\tfieldSlug,\n\t\t\tfieldPath: `${fieldPath}.darkVariant`,\n\t\t\treferenceType: \"image_field\",\n\t\t\tvalue: value.darkVariant,\n\t\t\tfallbackKind: \"image\",\n\t\t});\n\t}\n}\n\nfunction extractPortableTextOccurrences(\n\toccurrences: ExtractedMediaUsageOccurrence[],\n\tseen: Set<string>,\n\tfieldSlug: string,\n\tvalue: unknown,\n\tpathPrefix = fieldSlug,\n): void {\n\tif (!Array.isArray(value)) return;\n\n\tfor (const [blockIndex, block] of value.entries()) {\n\t\tif (!isRecord(block)) continue;\n\n\t\tif (block._type === \"image\") {\n\t\t\taddPortableTextAssetOccurrence(\n\t\t\t\toccurrences,\n\t\t\t\tseen,\n\t\t\t\tfieldSlug,\n\t\t\t\t`${pathPrefix}[${blockIndex}]`,\n\t\t\t\tblock.asset,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// A gallery block holds its images in `images[]`, each with its own asset.\n\t\tif (block._type === \"gallery\" && Array.isArray(block.images)) {\n\t\t\tfor (const [imageIndex, image] of block.images.entries()) {\n\t\t\t\tif (!isRecord(image)) continue;\n\t\t\t\taddPortableTextAssetOccurrence(\n\t\t\t\t\toccurrences,\n\t\t\t\t\tseen,\n\t\t\t\t\tfieldSlug,\n\t\t\t\t\t`${pathPrefix}[${blockIndex}].images[${imageIndex}]`,\n\t\t\t\t\timage.asset,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class MediaUsageBlockResolutionError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"MediaUsageBlockResolutionError\";\n\t}\n}\n\nfunction extractBlockOccurrences(\n\toccurrences: ExtractedMediaUsageOccurrence[],\n\tseen: Set<string>,\n\tfield: ExtractMediaUsageOccurrencesInput[\"fields\"][number],\n\tvalue: unknown,\n): void {\n\tif (!Array.isArray(value)) return;\n\tconst types = new Map((field.blockTypes ?? []).map((type) => [type.slug, type]));\n\tfor (const [index, block] of value.entries()) {\n\t\tif (!isRecord(block)) continue;\n\t\tif (\n\t\t\ttypeof block._type !== \"string\" ||\n\t\t\ttypeof block._version !== \"number\" ||\n\t\t\ttypeof block._key !== \"string\" ||\n\t\t\tblock._key.length === 0\n\t\t) {\n\t\t\tthrow new MediaUsageBlockResolutionError(\n\t\t\t\t`Block at ${field.slug}[${index}] has invalid identity metadata`,\n\t\t\t);\n\t\t}\n\t\tconst type = types.get(block._type);\n\t\tconst version = type?.versions.find((candidate) => candidate.version === block._version);\n\t\tif (!type || !version || version.unsupportedTypes?.length) {\n\t\t\tthrow new MediaUsageBlockResolutionError(\n\t\t\t\t`Block at ${field.slug}[${index}] has no retained definition`,\n\t\t\t);\n\t\t}\n\t\tconst pathPrefix = `${field.slug}.${block._key}`;\n\t\tfor (const nestedField of version.fields) {\n\t\t\tconst nestedValue = block[nestedField.slug];\n\t\t\tconst nestedPath = `${pathPrefix}.${nestedField.slug}`;\n\t\t\tif (nestedField.type === \"image\") {\n\t\t\t\taddImageOccurrences(occurrences, seen, field.slug, nestedPath, nestedValue);\n\t\t\t} else if (nestedField.type === \"file\") {\n\t\t\t\taddOccurrence(occurrences, seen, {\n\t\t\t\t\tfieldSlug: field.slug,\n\t\t\t\t\tfieldPath: nestedPath,\n\t\t\t\t\treferenceType: \"file_field\",\n\t\t\t\t\tvalue: nestedValue,\n\t\t\t\t\tfallbackKind: null,\n\t\t\t\t});\n\t\t\t} else if (nestedField.type === \"portableText\") {\n\t\t\t\textractPortableTextOccurrences(occurrences, seen, field.slug, nestedValue, nestedPath);\n\t\t\t} else if (nestedField.type === \"repeater\") {\n\t\t\t\textractRepeaterOccurrences(\n\t\t\t\t\toccurrences,\n\t\t\t\t\tseen,\n\t\t\t\t\tfield.slug,\n\t\t\t\t\tnestedValue,\n\t\t\t\t\tnestedField.validation?.subFields,\n\t\t\t\t\tnestedPath,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction addPortableTextAssetOccurrence(\n\toccurrences: ExtractedMediaUsageOccurrence[],\n\tseen: Set<string>,\n\tfieldSlug: string,\n\tpathPrefix: string,\n\tasset: unknown,\n): void {\n\tif (!isRecord(asset)) return;\n\n\tconst provider = normalizeProvider(asset.provider);\n\tconst ref = readPortableTextAssetRef(asset, provider);\n\tif (!ref) return;\n\n\taddRefOccurrence(occurrences, seen, {\n\t\tfieldSlug,\n\t\tfieldPath: `${pathPrefix}.asset.${ref.key}`,\n\t\treferenceType: \"portable_text_image\",\n\t\tref: buildMediaRef({\n\t\t\tid: ref.id,\n\t\t\tprovider,\n\t\t\tmimeType: normalizeMimeValue(asset.mimeType),\n\t\t\tfallbackKind: \"image\",\n\t\t}),\n\t});\n}\n\nfunction addOccurrence(\n\toccurrences: ExtractedMediaUsageOccurrence[],\n\tseen: Set<string>,\n\tinput: AddOccurrenceInput,\n): void {\n\tconst ref = readMediaRef(input.value, input.fallbackKind);\n\tif (!ref) return;\n\n\taddRefOccurrence(occurrences, seen, {\n\t\tfieldSlug: input.fieldSlug,\n\t\tfieldPath: input.fieldPath,\n\t\treferenceType: input.referenceType,\n\t\tref,\n\t});\n}\n\nfunction addRefOccurrence(\n\toccurrences: ExtractedMediaUsageOccurrence[],\n\tseen: Set<string>,\n\tinput: {\n\t\tfieldSlug: string;\n\t\tfieldPath: string;\n\t\treferenceType: MediaUsageReferenceType;\n\t\tref: MediaRef | null;\n\t},\n): void {\n\tif (!input.ref) return;\n\n\tconst occurrence: ExtractedMediaUsageOccurrence = {\n\t\tfieldSlug: input.fieldSlug,\n\t\tfieldPath: input.fieldPath,\n\t\toccurrenceIndex: 0,\n\t\treferenceType: input.referenceType,\n\t\tmediaId: input.ref.mediaId,\n\t\tprovider: input.ref.provider,\n\t\tproviderAssetId: input.ref.providerAssetId,\n\t\tmediaKind: input.ref.mediaKind,\n\t\tmimeType: input.ref.mimeType,\n\t};\n\n\tconst key = [\n\t\toccurrence.fieldSlug,\n\t\toccurrence.fieldPath,\n\t\toccurrence.occurrenceIndex,\n\t\toccurrence.referenceType,\n\t\toccurrence.provider,\n\t\toccurrence.providerAssetId,\n\t\toccurrence.mediaId ?? \"\",\n\t].join(\"\\0\");\n\n\tif (seen.has(key)) return;\n\tseen.add(key);\n\toccurrences.push(occurrence);\n}\n\nfunction readMediaRef(value: unknown, fallbackKind: MediaKind | null): MediaRef | null {\n\tif (typeof value === \"string\") {\n\t\tconst id = normalizeLocalMediaId(value);\n\t\treturn id ? buildMediaRef({ id, provider: \"local\", mimeType: null, fallbackKind }) : null;\n\t}\n\n\tif (!isRecord(value)) return null;\n\n\tconst provider = normalizeProvider(value.provider);\n\tconst id = provider === \"local\" ? normalizeLocalMediaId(value.id) : normalizeStableId(value.id);\n\tif (!id) return null;\n\n\treturn buildMediaRef({\n\t\tid,\n\t\tprovider,\n\t\tmimeType: normalizeMimeValue(value.mimeType),\n\t\tfallbackKind,\n\t});\n}\n\nfunction buildMediaRef(input: {\n\tid: string;\n\tprovider: string;\n\tmimeType: string | null;\n\tfallbackKind: MediaKind | null;\n}): MediaRef | null {\n\tconst provider = normalizeProvider(input.provider);\n\tif (provider === \"external\") return null;\n\n\treturn {\n\t\tmediaId: provider === \"local\" ? input.id : null,\n\t\tprovider,\n\t\tproviderAssetId: input.id,\n\t\tmediaKind: mediaKindFromMime(input.mimeType) ?? input.fallbackKind,\n\t\tmimeType: input.mimeType,\n\t};\n}\n\nfunction readPortableTextAssetRef(\n\tasset: Record<string, unknown>,\n\tprovider: string,\n): { key: \"_ref\" | \"id\"; id: string } | null {\n\tconst normalizeId = provider === \"local\" ? normalizeLocalMediaId : normalizeStableId;\n\tconst ref = normalizeId(asset._ref);\n\tif (ref) return { key: \"_ref\", id: ref };\n\n\tconst id = normalizeId(asset.id);\n\tif (id) return { key: \"id\", id };\n\n\treturn null;\n}\n\nfunction normalizeProvider(value: unknown): string {\n\tconst provider = readString(value)?.trim();\n\treturn provider || \"local\";\n}\n\nfunction normalizeLocalMediaId(value: unknown): string | null {\n\tconst id = normalizeStableId(value);\n\tif (!id) return null;\n\treturn id.includes(\"/\") ? null : id;\n}\n\nfunction normalizeStableId(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst trimmed = value.trim();\n\tif (!trimmed) return null;\n\tif (URL_LIKE_RE.test(trimmed)) return null;\n\tif (trimmed.startsWith(INTERNAL_MEDIA_PREFIX)) return null;\n\treturn trimmed;\n}\n\nfunction normalizeMimeValue(value: unknown): string | null {\n\tif (typeof value !== \"string\") return null;\n\tconst normalized = normalizeMime(value);\n\treturn normalized.includes(\"/\") ? normalized : null;\n}\n\nfunction mediaKindFromMime(mimeType: string | null): MediaKind | null {\n\tif (!mimeType) return null;\n\tif (mimeType.startsWith(\"image/\")) return \"image\";\n\tif (mimeType.startsWith(\"video/\")) return \"video\";\n\tif (mimeType.startsWith(\"audio/\")) return \"audio\";\n\tif (mimeType.startsWith(\"font/\") || mimeType.startsWith(\"application/font-\")) return \"font\";\n\tif (mimeType.startsWith(\"text/\")) return \"text\";\n\tif (isDocumentMime(mimeType)) return \"document\";\n\tif (isArchiveMime(mimeType)) return \"archive\";\n\treturn \"other\";\n}\n\nfunction isDocumentMime(mimeType: string): boolean {\n\treturn (\n\t\tmimeType === \"application/pdf\" ||\n\t\tmimeType === \"application/msword\" ||\n\t\tmimeType === \"application/rtf\" ||\n\t\tmimeType === \"application/vnd.ms-excel\" ||\n\t\tmimeType === \"application/vnd.ms-powerpoint\" ||\n\t\tmimeType.startsWith(\"application/vnd.openxmlformats-officedocument.\")\n\t);\n}\n\nfunction isArchiveMime(mimeType: string): boolean {\n\treturn (\n\t\tmimeType === \"application/zip\" ||\n\t\tmimeType === \"application/gzip\" ||\n\t\tmimeType === \"application/x-tar\" ||\n\t\tmimeType === \"application/x-7z-compressed\" ||\n\t\tmimeType === \"application/x-rar-compressed\" ||\n\t\tmimeType === \"application/vnd.rar\"\n\t);\n}\n\nfunction readString(value: unknown): string | null {\n\treturn typeof value === \"string\" ? value : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","export const MEDIA_USAGE_CONTENT_SOURCE_VARIANTS = [\"columns\", \"draft_overlay\"] as const;\n\nexport type MediaUsageContentSourceVariant = (typeof MEDIA_USAGE_CONTENT_SOURCE_VARIANTS)[number];\n\nexport interface ContentMediaUsageSourceKeyInput {\n\tcollectionId?: string;\n\tcollectionSlug: string;\n\tcontentId: string;\n\tsourceVariant: MediaUsageContentSourceVariant;\n}\n\nexport function isMediaUsageContentSourceVariant(\n\tvalue: unknown,\n): value is MediaUsageContentSourceVariant {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\t(MEDIA_USAGE_CONTENT_SOURCE_VARIANTS as readonly string[]).includes(value)\n\t);\n}\n\nexport function buildContentMediaUsageSourceKey(input: ContentMediaUsageSourceKeyInput): string {\n\tif (input.collectionId) {\n\t\treturn `content:${input.collectionId}:${input.contentId}:${input.sourceVariant}`;\n\t}\n\treturn `content:${input.collectionSlug}:${input.contentId}:${input.sourceVariant}`;\n}\n","import { sql, type Kysely } from \"kysely\";\n\nimport { jsonTextValues } from \"../../database/json-recordset.js\";\nimport type {\n\tMediaUsageOccurrenceInput,\n\tMediaUsageSourceInput,\n} from \"../../database/repositories/media-usage.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport {\n\tloadContentMediaUsageFields,\n\ttype ContentMediaUsageField,\n\ttype ContentMediaUsageFieldDiscovery,\n} from \"./content-fields.js\";\nimport { extractMediaUsageOccurrences } from \"./extractor.js\";\nimport { buildMediaUsageProjectionFingerprint } from \"./projection-fingerprint.js\";\nimport {\n\tbuildContentMediaUsageSourceKey,\n\ttype MediaUsageContentSourceVariant,\n} from \"./source-key.js\";\nimport { CONTENT_SOURCE_SCHEMA_VERSION } from \"./types.js\";\n\nexport { CONTENT_SOURCE_SCHEMA_VERSION } from \"./types.js\";\nconst CONTENT_COLLECTION_ID_RESULT = \"__emdash_media_usage_collection_id\";\n\nconst CONTENT_SYSTEM_COLUMNS = [\n\t\"id\",\n\t\"slug\",\n\t\"status\",\n\t\"created_at\",\n\t\"updated_at\",\n\t\"published_at\",\n\t\"scheduled_at\",\n\t\"deleted_at\",\n\t\"version\",\n\t\"live_revision_id\",\n\t\"draft_revision_id\",\n\t\"locale\",\n\t\"translation_group\",\n] as const;\n\nexport type LoadContentMediaUsageSnapshotsResult =\n\t| { success: true; snapshots: ContentMediaUsageSnapshot[] }\n\t| {\n\t\t\tsuccess: false;\n\t\t\terror:\n\t\t\t\t| \"CONTENT_NOT_FOUND\"\n\t\t\t\t| \"DRAFT_REVISION_NOT_FOUND\"\n\t\t\t\t| \"DRAFT_REVISION_MISMATCH\"\n\t\t\t\t| \"DRAFT_REVISION_INVALID\";\n\t\t\tsource?: MediaUsageSourceInput;\n\t\t\tsnapshots?: ContentMediaUsageSnapshot[];\n\t };\n\nexport interface ContentMediaUsageSnapshot {\n\tsource: MediaUsageSourceInput;\n\toccurrences: MediaUsageOccurrenceInput[];\n\tfields: readonly ContentMediaUsageField[];\n\tprojectionByteLength: number;\n}\n\nexport interface LoadContentMediaUsageSnapshotsOptions {\n\tcollectionId?: string;\n\tidentityVersion?: number;\n}\n\nexport interface LoadContentMediaUsageSnapshotsBatchControl {\n\tshouldContinue?: () => boolean;\n\tmaxOccurrenceCount?: number;\n\tmaxProjectionBytes?: number;\n}\n\nexport async function loadContentMediaUsageSnapshots(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n\tfieldDiscovery?: ContentMediaUsageFieldDiscovery,\n\toptions: LoadContentMediaUsageSnapshotsOptions = {},\n): Promise<LoadContentMediaUsageSnapshotsResult> {\n\tconst results = await loadContentMediaUsageSnapshotsBatch(\n\t\tdb,\n\t\tcollectionSlug,\n\t\t[contentId],\n\t\tfieldDiscovery,\n\t\toptions,\n\t);\n\treturn results.get(contentId) ?? { success: false, error: \"CONTENT_NOT_FOUND\" };\n}\n\nexport async function loadContentMediaUsageSnapshotsBatch(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentIds: readonly string[],\n\tfieldDiscovery?: ContentMediaUsageFieldDiscovery,\n\toptions: LoadContentMediaUsageSnapshotsOptions = {},\n\tcontrol: LoadContentMediaUsageSnapshotsBatchControl = {},\n): Promise<Map<string, LoadContentMediaUsageSnapshotsResult>> {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\tif (options.identityVersion !== undefined && !options.collectionId) {\n\t\tthrow new Error(\"Canonical media usage snapshots require a collection identity\");\n\t}\n\tconst discovery = fieldDiscovery ?? (await loadContentMediaUsageFields(db, collectionSlug));\n\tconst rows = await loadContentRows(\n\t\tdb,\n\t\tcollectionSlug,\n\t\tcontentIds,\n\t\t[...discovery.extractionFields.map((field) => field.slug), ...discovery.displayFieldSlugs],\n\t\toptions.collectionId,\n\t);\n\tconst revisionIds = Array.from(rows.values(), (row) =>\n\t\treadNullableString(row.draft_revision_id),\n\t).filter((revisionId): revisionId is string => revisionId !== null);\n\tconst revisions = await loadRevisionRows(db, revisionIds);\n\tconst results = new Map<string, LoadContentMediaUsageSnapshotsResult>();\n\tlet occurrenceCount = 0;\n\tlet projectionBytes = 0;\n\tfor (const contentId of new Set(contentIds)) {\n\t\tif (control.shouldContinue && !control.shouldContinue()) break;\n\t\tconst row = rows.get(contentId);\n\t\tconst result: LoadContentMediaUsageSnapshotsResult = row\n\t\t\t? await buildContentMediaUsageSnapshots(row, collectionSlug, discovery, options, revisions)\n\t\t\t: { success: false, error: \"CONTENT_NOT_FOUND\" };\n\t\tconst snapshots = result.success ? result.snapshots : (result.snapshots ?? []);\n\t\tconst itemOccurrenceCount = snapshots.reduce(\n\t\t\t(total, snapshot) => total + snapshot.occurrences.length,\n\t\t\t0,\n\t\t);\n\t\tconst itemProjectionBytes = snapshots.reduce(\n\t\t\t(total, snapshot) => total + snapshot.projectionByteLength,\n\t\t\t0,\n\t\t);\n\t\tif (\n\t\t\tresults.size > 0 &&\n\t\t\t((control.maxOccurrenceCount !== undefined &&\n\t\t\t\toccurrenceCount + itemOccurrenceCount > control.maxOccurrenceCount) ||\n\t\t\t\t(control.maxProjectionBytes !== undefined &&\n\t\t\t\t\tprojectionBytes + itemProjectionBytes > control.maxProjectionBytes))\n\t\t) {\n\t\t\tbreak;\n\t\t}\n\t\tresults.set(contentId, result);\n\t\toccurrenceCount += itemOccurrenceCount;\n\t\tprojectionBytes += itemProjectionBytes;\n\t}\n\treturn results;\n}\n\nasync function buildContentMediaUsageSnapshots(\n\trow: Record<string, unknown>,\n\tcollectionSlug: string,\n\tdiscovery: ContentMediaUsageFieldDiscovery,\n\toptions: LoadContentMediaUsageSnapshotsOptions,\n\trevisions: ReadonlyMap<\n\t\tstring,\n\t\t{ success: true; revision: RevisionSnapshotRow } | { success: false }\n\t>,\n): Promise<LoadContentMediaUsageSnapshotsResult> {\n\tconst collectionId = readString(row[CONTENT_COLLECTION_ID_RESULT]);\n\tif (!collectionId) {\n\t\tthrow new Error(\"Media usage snapshot query did not return a collection identity\");\n\t}\n\n\tconst columnsData = projectData(\n\t\trow,\n\t\tdiscovery.extractionFields.map((field) => field.slug),\n\t);\n\tconst displayData = projectRawData(row, discovery.displayFieldSlugs);\n\tconst occurrences = extractMediaUsageOccurrences({\n\t\tfields: discovery.extractionFields,\n\t\tdata: columnsData,\n\t});\n\tconst columnsRevisionId = readNullableString(row.live_revision_id);\n\tconst columnsSource = buildContentSource({\n\t\tcollectionId: options.collectionId,\n\t\tcollectionSlug,\n\t\tidentityVersion: options.identityVersion,\n\t\trow,\n\t\tdisplayData,\n\t\tsourceVariant: \"columns\",\n\t\trevisionId: columnsRevisionId,\n\t});\n\tconst columnsProjection = await buildMediaUsageProjectionFingerprint({\n\t\tcollectionId,\n\t\tsource: columnsSource,\n\t\toccurrences,\n\t\textractionFields: discovery.extractionFields,\n\t});\n\tcolumnsSource.sourceFingerprint = columnsProjection.fingerprint;\n\tconst snapshots: ContentMediaUsageSnapshot[] = [\n\t\t{\n\t\t\tsource: columnsSource,\n\t\t\toccurrences,\n\t\t\tfields: discovery.extractionFields,\n\t\t\tprojectionByteLength: columnsProjection.byteLength,\n\t\t},\n\t];\n\n\tconst draftRevisionId = readNullableString(row.draft_revision_id);\n\tif (draftRevisionId) {\n\t\tconst attemptedDraftSource = buildContentSource({\n\t\t\tcollectionId: options.collectionId,\n\t\t\tcollectionSlug,\n\t\t\tidentityVersion: options.identityVersion,\n\t\t\trow,\n\t\t\tdisplayData,\n\t\t\tsourceVariant: \"draft_overlay\",\n\t\t\trevisionId: draftRevisionId,\n\t\t});\n\t\tconst revisionResult = revisions.get(draftRevisionId);\n\t\tif (!revisionResult) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"DRAFT_REVISION_NOT_FOUND\",\n\t\t\t\tsource: attemptedDraftSource,\n\t\t\t\tsnapshots,\n\t\t\t};\n\t\t}\n\t\tif (!revisionResult.success) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"DRAFT_REVISION_INVALID\",\n\t\t\t\tsource: attemptedDraftSource,\n\t\t\t\tsnapshots,\n\t\t\t};\n\t\t}\n\t\tconst revision = revisionResult.revision;\n\t\tif (revision.collection !== collectionSlug || revision.entryId !== row.id) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: \"DRAFT_REVISION_MISMATCH\",\n\t\t\t\tsource: attemptedDraftSource,\n\t\t\t\tsnapshots,\n\t\t\t};\n\t\t}\n\n\t\tconst revisionData = stripRevisionMetadata(revision.data);\n\t\tconst draftOverlayData = { ...columnsData, ...revisionData };\n\t\tconst draftDisplayData = {\n\t\t\t...displayData,\n\t\t\t...projectPresentData(revisionData, discovery.displayFieldSlugs),\n\t\t};\n\t\tconst draftContentSlug =\n\t\t\treadNullableString(revision.data._slug) ?? readNullableString(row.slug);\n\t\tconst draftOccurrences = extractMediaUsageOccurrences({\n\t\t\tfields: discovery.extractionFields,\n\t\t\tdata: draftOverlayData,\n\t\t});\n\t\tconst draftSource = buildContentSource({\n\t\t\tcollectionId: options.collectionId,\n\t\t\tcollectionSlug,\n\t\t\tidentityVersion: options.identityVersion,\n\t\t\trow,\n\t\t\tdisplayData: draftDisplayData,\n\t\t\tsourceVariant: \"draft_overlay\",\n\t\t\trevisionId: draftRevisionId,\n\t\t\tcontentSlug: draftContentSlug,\n\t\t});\n\t\tconst draftProjection = await buildMediaUsageProjectionFingerprint({\n\t\t\tcollectionId,\n\t\t\tsource: draftSource,\n\t\t\toccurrences: draftOccurrences,\n\t\t\textractionFields: discovery.extractionFields,\n\t\t});\n\t\tdraftSource.sourceFingerprint = draftProjection.fingerprint;\n\t\tsnapshots.push({\n\t\t\tsource: draftSource,\n\t\t\toccurrences: draftOccurrences,\n\t\t\tfields: discovery.extractionFields,\n\t\t\tprojectionByteLength: draftProjection.byteLength,\n\t\t});\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tsnapshots,\n\t};\n}\n\ninterface RevisionSnapshotRow {\n\tid: string;\n\tcollection: string;\n\tentryId: string;\n\tdata: Record<string, unknown>;\n}\n\nasync function loadContentRows(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentIds: readonly string[],\n\tfieldSlugs: readonly string[],\n\texpectedCollectionId?: string,\n): Promise<Map<string, Record<string, unknown>>> {\n\tconst tableName = getContentTableName(collectionSlug);\n\tconst columns = uniqueColumns([...CONTENT_SYSTEM_COLUMNS, ...fieldSlugs]);\n\tconst columnRefs = columns.map((column) => sql.ref(`content.${column}`));\n\tconst rows = new Map<string, Record<string, unknown>>();\n\tconst uniqueContentIds = [...new Set(contentIds)];\n\tif (uniqueContentIds.length === 0) return rows;\n\tconst contentIdInput = jsonTextValues(db, uniqueContentIds);\n\tconst result = await sql<Record<string, unknown>>`\n\t\tWITH requested AS (${contentIdInput})\n\t\tSELECT\n\t\t\t${sql.join(columnRefs, sql`, `)},\n\t\t\tcollection.id AS __emdash_media_usage_collection_id\n\t\tFROM ${sql.ref(tableName)} AS content\n\t\tINNER JOIN requested ON requested.value = content.id\n\t\tINNER JOIN _emdash_collections AS collection\n\t\t\tON collection.slug = ${collectionSlug}\n\t\t\t${expectedCollectionId ? sql`AND collection.id = ${expectedCollectionId}` : sql``}\n\t`.execute(db);\n\tfor (const row of result.rows) {\n\t\tconst contentId = readString(row.id);\n\t\tif (contentId) rows.set(contentId, row);\n\t}\n\treturn rows;\n}\n\nasync function loadRevisionRows(\n\tdb: Kysely<Database>,\n\trevisionIds: readonly string[],\n): Promise<Map<string, { success: true; revision: RevisionSnapshotRow } | { success: false }>> {\n\tconst revisions = new Map<\n\t\tstring,\n\t\t{ success: true; revision: RevisionSnapshotRow } | { success: false }\n\t>();\n\tconst uniqueRevisionIds = [...new Set(revisionIds)];\n\tif (uniqueRevisionIds.length === 0) return revisions;\n\tconst revisionIdInput = jsonTextValues(db, uniqueRevisionIds);\n\tconst rows = await sql<{\n\t\tid: string;\n\t\tcollection: string;\n\t\tentry_id: string;\n\t\tdata: unknown;\n\t}>`\n\t\tWITH requested AS (${revisionIdInput})\n\t\tSELECT revision.id, revision.collection, revision.entry_id, revision.data\n\t\tFROM revisions AS revision\n\t\tINNER JOIN requested ON requested.value = revision.id\n\t`.execute(db);\n\tfor (const row of rows.rows) {\n\t\tconst data = parseRevisionData(row.data);\n\t\trevisions.set(\n\t\t\trow.id,\n\t\t\tdata\n\t\t\t\t? {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\trevision: {\n\t\t\t\t\t\t\tid: row.id,\n\t\t\t\t\t\t\tcollection: row.collection,\n\t\t\t\t\t\t\tentryId: row.entry_id,\n\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: { success: false },\n\t\t);\n\t}\n\treturn revisions;\n}\n\nfunction buildContentSource(input: {\n\tcollectionId?: string;\n\tcollectionSlug: string;\n\tidentityVersion?: number;\n\trow: Record<string, unknown>;\n\tdisplayData: Record<string, unknown>;\n\tsourceVariant: MediaUsageContentSourceVariant;\n\trevisionId: string | null;\n\tcontentSlug?: string | null;\n}): MediaUsageSourceInput {\n\tconst {\n\t\tcollectionId,\n\t\tcollectionSlug,\n\t\tidentityVersion,\n\t\trow,\n\t\tdisplayData,\n\t\tsourceVariant,\n\t\trevisionId,\n\t} = input;\n\tconst contentId = readString(row.id) ?? \"\";\n\tconst contentSlug = input.contentSlug ?? readNullableString(row.slug);\n\tconst source: MediaUsageSourceInput = {\n\t\tsourceKey: buildContentMediaUsageSourceKey({\n\t\t\tcollectionId,\n\t\t\tcollectionSlug,\n\t\t\tcontentId,\n\t\t\tsourceVariant,\n\t\t}),\n\t\tsourceType: \"content\",\n\t\tcollectionId,\n\t\tcollectionSlug,\n\t\tcontentId,\n\t\tsourceVariant,\n\t\tlocale: readNullableString(row.locale),\n\t\ttranslationGroup: readNullableString(row.translation_group),\n\t\tcontentSlug,\n\t\tcontentTitle: deriveContentTitle(displayData, contentSlug, contentId),\n\t\tcontentStatus: readNullableString(row.status),\n\t\tcontentScheduledAt: readNullableString(row.scheduled_at),\n\t\tcontentDeletedAt: readNullableString(row.deleted_at),\n\t\trevisionId,\n\t\tschemaVersion: CONTENT_SOURCE_SCHEMA_VERSION,\n\t\tsourceUpdatedAt: readNullableString(row.updated_at),\n\t\tsourceVersion: readNumber(row.version),\n\t\tidentityVersion,\n\t};\n\treturn source;\n}\n\nfunction projectData(\n\trow: Record<string, unknown>,\n\tfieldSlugs: readonly string[],\n): Record<string, unknown> {\n\tconst data: Record<string, unknown> = {};\n\tfor (const fieldSlug of fieldSlugs) {\n\t\tdata[fieldSlug] = deserializeValue(row[fieldSlug] ?? null);\n\t}\n\treturn data;\n}\n\nfunction projectRawData(\n\trow: Record<string, unknown>,\n\tfieldSlugs: readonly string[],\n): Record<string, unknown> {\n\tconst data: Record<string, unknown> = {};\n\tfor (const fieldSlug of fieldSlugs) {\n\t\tdata[fieldSlug] = row[fieldSlug] ?? null;\n\t}\n\treturn data;\n}\n\nfunction projectPresentData(\n\trow: Record<string, unknown>,\n\tfieldSlugs: readonly string[],\n): Record<string, unknown> {\n\tconst data: Record<string, unknown> = {};\n\tfor (const fieldSlug of fieldSlugs) {\n\t\tif (Object.hasOwn(row, fieldSlug)) data[fieldSlug] = row[fieldSlug];\n\t}\n\treturn data;\n}\n\nfunction uniqueColumns(columns: readonly string[]): string[] {\n\tconst unique = [...new Set(columns)];\n\tfor (const column of unique) validateIdentifier(column, \"content media usage column\");\n\treturn unique;\n}\n\nfunction getContentTableName(collectionSlug: string): string {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\treturn `ec_${collectionSlug}`;\n}\n\nfunction deserializeValue(value: unknown): unknown {\n\tif (typeof value === \"string\" && (value.startsWith(\"{\") || value.startsWith(\"[\"))) {\n\t\ttry {\n\t\t\treturn JSON.parse(value);\n\t\t} catch {\n\t\t\treturn value;\n\t\t}\n\t}\n\treturn value;\n}\n\nfunction parseRevisionData(value: unknown): Record<string, unknown> | null {\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(value);\n\t\t\treturn isRecord(parsed) ? parsed : null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn isRecord(value) ? value : null;\n}\n\nfunction stripRevisionMetadata(data: Record<string, unknown>): Record<string, unknown> {\n\tconst stripped: Record<string, unknown> = {};\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (!key.startsWith(\"_\")) stripped[key] = value;\n\t}\n\treturn stripped;\n}\n\nfunction deriveContentTitle(\n\tdisplayData: Record<string, unknown>,\n\tcontentSlug: string | null,\n\tcontentId: string,\n): string | null {\n\tfor (const fieldSlug of [\"title\", \"name\"] as const) {\n\t\tconst value = displayData[fieldSlug];\n\t\tif (typeof value === \"string\" && value.trim()) return value;\n\t}\n\treturn contentSlug ?? contentId;\n}\n\nfunction readString(value: unknown): string | null {\n\treturn typeof value === \"string\" ? value : null;\n}\n\nfunction readNullableString(value: unknown): string | null {\n\treturn value === null || value === undefined ? null : readString(value);\n}\n\nfunction readNumber(value: unknown): number | null {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"bigint\") return Number(value);\n\tif (typeof value === \"string\" && value) {\n\t\tconst parsed = Number(value);\n\t\treturn Number.isFinite(parsed) ? parsed : null;\n\t}\n\treturn null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { sql, type Kysely } from \"kysely\";\n\nimport {\n\ttype MediaUsageExistingSourceProjection,\n\tMediaUsageRepository,\n\ttype MediaUsageNewSourceProjection,\n\ttype MediaUsageSource,\n} from \"../../database/repositories/media-usage.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport { isI18nEnabled } from \"../../i18n/config.js\";\nimport {\n\tloadContentMediaUsageFields,\n\ttype ContentMediaUsageFieldDiscovery,\n} from \"./content-fields.js\";\nimport {\n\tloadContentMediaUsageSnapshots,\n\tloadContentMediaUsageSnapshotsBatch,\n\ttype ContentMediaUsageSnapshot,\n\ttype LoadContentMediaUsageSnapshotsResult,\n} from \"./content-snapshots.js\";\nimport {\n\tCONTENT_MEDIA_USAGE_ADAPTER_ID,\n\tCONTENT_MEDIA_USAGE_COLLECTION_SCOPE,\n\tmarkContentMediaUsageCollectionStale,\n\tmarkContentMediaUsageCollectionStaleSafely,\n} from \"./schema-invalidation.js\";\nimport {\n\tbuildContentMediaUsageSourceKey,\n\tMEDIA_USAGE_CONTENT_SOURCE_VARIANTS,\n} from \"./source-key.js\";\n\nexport {\n\tCONTENT_MEDIA_USAGE_ADAPTER_ID,\n\tCONTENT_MEDIA_USAGE_COLLECTION_SCOPE,\n\tinvalidateContentMediaUsageSchemaChange,\n\tmarkContentMediaUsageCollectionStale,\n\tmarkContentMediaUsageCollectionStaleSafely,\n} from \"./schema-invalidation.js\";\n\nconst CONTENT_USAGE_LOCKS_KEY = Symbol.for(\"emdash.mediaUsage.contentLocks\");\nconst CONTENT_USAGE_COLLECTION_LOCKS_KEY = Symbol.for(\"emdash.mediaUsage.collectionLocks\");\nconst CONTENT_USAGE_REFRESH_MAX_ATTEMPTS = 2;\n\nexport const MEDIA_USAGE_PROJECTION_ADMISSION_LIMITS = Object.freeze({\n\tmaxOccurrenceMutationUnitsPerClaim: 500,\n\tmaxProjectionMutationBytesPerVariant: 2_000_000,\n\tmaxProjectionMutationBytesPerClaim: 4_000_000,\n\tmaxOccurrenceMutationUnitsPerBatch: 50_000,\n\tmaxProjectionMutationBytesPerBatch: 16_000_000,\n});\n\nexport interface ContentMediaUsageAdmissionBudget {\n\tremainingOccurrenceMutationUnits: number;\n\tremainingProjectionMutationBytes: number;\n\thasReservedMutation: boolean;\n}\n\nexport type ContentMediaUsageProjectionAdmissionResult =\n\t| {\n\t\t\toutcome: \"admitted\";\n\t\t\tnoOpSourceKeys: ReadonlySet<string>;\n\t\t\tabsentSources: MediaUsageSource[];\n\t\t\toccurrenceMutationUnits: number;\n\t\t\tprojectionMutationBytes: number;\n\t }\n\t| { outcome: \"intrinsic_resource_limit\" }\n\t| { outcome: \"claim_budget_deferred\" };\n\n// These maps only de-dupe usage work inside the current isolate/process. Cross-worker\n// correctness comes from expected-generation guards on repository writes.\n\nexport type ContentMediaUsageRefreshErrorCode =\n\t| \"CONTENT_NOT_FOUND\"\n\t| \"DRAFT_REVISION_NOT_FOUND\"\n\t| \"DRAFT_REVISION_MISMATCH\"\n\t| \"DRAFT_REVISION_INVALID\"\n\t| \"CONTENT_USAGE_REFRESH_ERROR\"\n\t| \"CONTENT_USAGE_DELETE_ERROR\"\n\t| \"CONTENT_USAGE_GENERATION_CONFLICT\"\n\t| \"CONTENT_USAGE_RESOURCE_LIMIT\"\n\t| \"CONTENT_USAGE_STALE\";\n\ninterface ContentMediaUsageRefreshOptions {\n\tcollectionId?: string;\n\tdurableWork?: boolean;\n\tadmissionBudget?: ContentMediaUsageAdmissionBudget;\n\tfieldDiscovery?: ContentMediaUsageFieldDiscovery;\n\tobservedSources?: ReadonlyMap<string, MediaUsageSource>;\n\tsnapshotsResult?: LoadContentMediaUsageSnapshotsResult;\n}\n\nexport interface ContentMediaUsageRefreshResult {\n\tsuccess: boolean;\n\trefreshedSourceCount: number;\n\tdeletedSourceCount: number;\n\tfailedSourceCount: number;\n\terrorCode?: ContentMediaUsageRefreshErrorCode;\n}\n\nconst ZERO_RESULT: ContentMediaUsageRefreshResult = {\n\tsuccess: true,\n\trefreshedSourceCount: 0,\n\tdeletedSourceCount: 0,\n\tfailedSourceCount: 0,\n};\n\nexport function createContentMediaUsageAdmissionBudget(\n\tlimits: {\n\t\tmaxOccurrenceMutationUnits?: number;\n\t\tmaxProjectionMutationBytes?: number;\n\t} = {},\n): ContentMediaUsageAdmissionBudget {\n\treturn {\n\t\tremainingOccurrenceMutationUnits:\n\t\t\tlimits.maxOccurrenceMutationUnits ??\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxOccurrenceMutationUnitsPerClaim,\n\t\tremainingProjectionMutationBytes:\n\t\t\tlimits.maxProjectionMutationBytes ??\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxProjectionMutationBytesPerClaim,\n\t\thasReservedMutation: false,\n\t};\n}\n\nexport async function planContentMediaUsageProjectionAdmission(\n\trepo: MediaUsageRepository,\n\tsnapshots: readonly ContentMediaUsageSnapshot[],\n\tobservedSources: ReadonlyMap<string, MediaUsageSource>,\n\tcanonicalSourceKeys: readonly string[],\n\tbudget: ContentMediaUsageAdmissionBudget,\n): Promise<ContentMediaUsageProjectionAdmissionResult> {\n\tconst snapshotSourceKeys = new Set(snapshots.map((snapshot) => snapshot.source.sourceKey));\n\tconst absentSources = canonicalSourceKeys\n\t\t.filter((sourceKey) => !snapshotSourceKeys.has(sourceKey))\n\t\t.map((sourceKey) => observedSources.get(sourceKey))\n\t\t.filter((source): source is MediaUsageSource => source !== undefined);\n\tlet deletionOccurrenceUnits = 0;\n\tlet deletionBytes = 0;\n\tlet largestDeletionBytes = 0;\n\tfor (const source of absentSources) {\n\t\tconst measurement = await repo.measureSourceGenerationDeletion(\n\t\t\tsource.sourceKey,\n\t\t\tsource.currentGeneration,\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxOccurrenceMutationUnitsPerClaim,\n\t\t);\n\t\tif (measurement.exceedsOccurrenceLimit) {\n\t\t\treturn budget.hasReservedMutation\n\t\t\t\t? { outcome: \"claim_budget_deferred\" }\n\t\t\t\t: { outcome: \"intrinsic_resource_limit\" };\n\t\t}\n\t\tdeletionOccurrenceUnits += measurement.occurrenceCount;\n\t\tconst sourceDeletionBytes =\n\t\t\tstoredMediaUsageSourceByteLength(source) + measurement.occurrenceBytes * 2;\n\t\tdeletionBytes += sourceDeletionBytes;\n\t\tlargestDeletionBytes = Math.max(largestDeletionBytes, sourceDeletionBytes);\n\t}\n\n\tconst noOpSourceKeys = new Set<string>();\n\tlet cost = projectionAdmissionCost(\n\t\tsnapshots,\n\t\tnoOpSourceKeys,\n\t\tdeletionOccurrenceUnits,\n\t\tdeletionBytes,\n\t\tlargestDeletionBytes,\n\t);\n\tif (exceedsProjectionAdmissionLimits(cost)) {\n\t\tfor (const snapshot of snapshots) {\n\t\t\tconst expectedSource = observedSources.get(snapshot.source.sourceKey);\n\t\t\tif (\n\t\t\t\texpectedSource &&\n\t\t\t\t(await repo.projectionMatchesExpectedSource(snapshot.source, expectedSource))\n\t\t\t) {\n\t\t\t\tnoOpSourceKeys.add(snapshot.source.sourceKey);\n\t\t\t}\n\t\t}\n\t\tcost = projectionAdmissionCost(\n\t\t\tsnapshots,\n\t\t\tnoOpSourceKeys,\n\t\t\tdeletionOccurrenceUnits,\n\t\t\tdeletionBytes,\n\t\t\tlargestDeletionBytes,\n\t\t);\n\t}\n\n\tif (exceedsProjectionAdmissionLimits(cost)) {\n\t\treturn budget.hasReservedMutation\n\t\t\t? { outcome: \"claim_budget_deferred\" }\n\t\t\t: { outcome: \"intrinsic_resource_limit\" };\n\t}\n\tif (\n\t\tcost.occurrenceMutationUnits > budget.remainingOccurrenceMutationUnits ||\n\t\tcost.projectionMutationBytes > budget.remainingProjectionMutationBytes\n\t) {\n\t\treturn { outcome: \"claim_budget_deferred\" };\n\t}\n\n\tbudget.remainingOccurrenceMutationUnits -= cost.occurrenceMutationUnits;\n\tbudget.remainingProjectionMutationBytes -= cost.projectionMutationBytes;\n\tif (cost.occurrenceMutationUnits > 0 || cost.projectionMutationBytes > 0) {\n\t\tbudget.hasReservedMutation = true;\n\t}\n\treturn {\n\t\toutcome: \"admitted\",\n\t\tnoOpSourceKeys,\n\t\tabsentSources,\n\t\t...cost,\n\t};\n}\n\ninterface ProjectionAdmissionCost {\n\toccurrenceMutationUnits: number;\n\tprojectionMutationBytes: number;\n\tlargestProjectionMutationBytes: number;\n}\n\nfunction projectionAdmissionCost(\n\tsnapshots: readonly ContentMediaUsageSnapshot[],\n\tnoOpSourceKeys: ReadonlySet<string>,\n\tdeletionOccurrenceUnits: number,\n\tdeletionBytes: number,\n\tlargestDeletionBytes: number,\n): ProjectionAdmissionCost {\n\treturn snapshots.reduce<ProjectionAdmissionCost>(\n\t\t(cost, snapshot) => {\n\t\t\tif (noOpSourceKeys.has(snapshot.source.sourceKey)) return cost;\n\t\t\tcost.occurrenceMutationUnits += snapshot.occurrences.length;\n\t\t\tcost.projectionMutationBytes += snapshot.projectionByteLength;\n\t\t\tcost.largestProjectionMutationBytes = Math.max(\n\t\t\t\tcost.largestProjectionMutationBytes,\n\t\t\t\tsnapshot.projectionByteLength,\n\t\t\t);\n\t\t\treturn cost;\n\t\t},\n\t\t{\n\t\t\toccurrenceMutationUnits: deletionOccurrenceUnits,\n\t\t\tprojectionMutationBytes: deletionBytes,\n\t\t\tlargestProjectionMutationBytes: largestDeletionBytes,\n\t\t},\n\t);\n}\n\nfunction exceedsProjectionAdmissionLimits(cost: ProjectionAdmissionCost): boolean {\n\treturn (\n\t\tcost.occurrenceMutationUnits >\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxOccurrenceMutationUnitsPerClaim ||\n\t\tcost.largestProjectionMutationBytes >\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxProjectionMutationBytesPerVariant ||\n\t\tcost.projectionMutationBytes >\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxProjectionMutationBytesPerClaim\n\t);\n}\n\nfunction storedMediaUsageSourceByteLength(source: MediaUsageSource): number {\n\treturn new TextEncoder().encode(JSON.stringify(source)).byteLength;\n}\n\nexport async function refreshContentMediaUsage(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n): Promise<ContentMediaUsageRefreshResult> {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\treturn withContentUsageCollectionLock(collectionSlug, () =>\n\t\twithContentUsageLock(collectionSlug, contentId, () =>\n\t\t\trefreshContentMediaUsageUnlocked(db, collectionSlug, contentId, {}),\n\t\t),\n\t);\n}\n\nexport interface ContentMediaUsageWorkRefreshInput {\n\tcollectionId: string;\n\tcollectionSlug: string;\n\tcontentId: string;\n}\n\nexport interface ContentMediaUsageWorkBatchOptions {\n\tshouldContinue?: () => boolean;\n}\n\nexport async function refreshContentMediaUsageForWorkBatch(\n\tdb: Kysely<Database>,\n\titems: readonly ContentMediaUsageWorkRefreshInput[],\n\toptions: ContentMediaUsageWorkBatchOptions = {},\n): Promise<Map<string, ContentMediaUsageRefreshResult>> {\n\tconst results = new Map<string, ContentMediaUsageRefreshResult>();\n\tconst batchBudget = createContentMediaUsageAdmissionBudget({\n\t\tmaxOccurrenceMutationUnits:\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxOccurrenceMutationUnitsPerBatch,\n\t\tmaxProjectionMutationBytes:\n\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxProjectionMutationBytesPerBatch,\n\t});\n\tconst collections = new Map<string, ContentMediaUsageWorkRefreshInput[]>();\n\tfor (const item of items) {\n\t\tconst key = `${item.collectionId}\\u0000${item.collectionSlug}`;\n\t\tconst collectionItems = collections.get(key) ?? [];\n\t\tcollectionItems.push(item);\n\t\tcollections.set(key, collectionItems);\n\t}\n\tfor (const collectionItems of collections.values()) {\n\t\tif (options.shouldContinue && !options.shouldContinue()) break;\n\t\tconst first = collectionItems[0];\n\t\tif (!first) continue;\n\t\tvalidateIdentifier(first.collectionSlug, \"collection slug\");\n\t\tif (!first.collectionId)\n\t\t\tthrow new Error(\"Durable media usage work requires a collection identity\");\n\t\tawait withContentUsageCollectionLock(first.collectionSlug, async () => {\n\t\t\tconst fieldDiscovery = await loadContentMediaUsageFields(\n\t\t\t\tdb,\n\t\t\t\tfirst.collectionSlug,\n\t\t\t\tfirst.collectionId,\n\t\t\t);\n\t\t\tconst sourceKeys = collectionItems.flatMap((item) =>\n\t\t\t\tcontentSourceKeys(item.collectionSlug, item.contentId, item.collectionId),\n\t\t\t);\n\t\t\tconst repo = new MediaUsageRepository(db);\n\t\t\tconst observedSources = await repo.findSources(sourceKeys);\n\t\t\tconst snapshots = await loadContentMediaUsageSnapshotsBatch(\n\t\t\t\tdb,\n\t\t\t\tfirst.collectionSlug,\n\t\t\t\tcollectionItems.map((item) => item.contentId),\n\t\t\t\tfieldDiscovery,\n\t\t\t\t{ collectionId: first.collectionId, identityVersion: 1 },\n\t\t\t\t{\n\t\t\t\t\tshouldContinue: options.shouldContinue,\n\t\t\t\t\tmaxOccurrenceCount:\n\t\t\t\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxOccurrenceMutationUnitsPerBatch,\n\t\t\t\t\tmaxProjectionBytes:\n\t\t\t\t\t\tMEDIA_USAGE_PROJECTION_ADMISSION_LIMITS.maxProjectionMutationBytesPerBatch,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst newSourceProjections: MediaUsageNewSourceProjection[] = [];\n\t\t\tconst newSourceKeys = new Map<string, string[]>();\n\t\t\tconst existingSourceProjections: MediaUsageExistingSourceProjection[] = [];\n\t\t\tconst unchangedSourceProjections: MediaUsageExistingSourceProjection[] = [];\n\t\t\tconst existingSourceKeys = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ allCount: number; changed: string[]; unchanged: string[] }\n\t\t\t>();\n\t\t\tfor (const item of collectionItems) {\n\t\t\t\tif (options.shouldContinue && !options.shouldContinue()) break;\n\t\t\t\tconst snapshotsResult = snapshots.get(item.contentId);\n\t\t\t\tconst itemSourceKeys = contentSourceKeys(\n\t\t\t\t\titem.collectionSlug,\n\t\t\t\t\titem.contentId,\n\t\t\t\t\titem.collectionId,\n\t\t\t\t);\n\t\t\t\tif (!snapshotsResult?.success) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst snapshotsByKey = new Map(\n\t\t\t\t\tsnapshotsResult.snapshots.map(\n\t\t\t\t\t\t(snapshot) => [snapshot.source.sourceKey, snapshot] as const,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst existing = itemSourceKeys\n\t\t\t\t\t.map((sourceKey) => observedSources.get(sourceKey))\n\t\t\t\t\t.filter((source): source is MediaUsageSource => source !== undefined);\n\t\t\t\tconst allNew = existing.length === 0;\n\t\t\t\tconst allExisting =\n\t\t\t\t\texisting.length === snapshotsResult.snapshots.length &&\n\t\t\t\t\texisting.every((source) => snapshotsByKey.has(source.sourceKey));\n\t\t\t\tif (!allNew && !allExisting) continue;\n\t\t\t\tconst admission = await planContentMediaUsageProjectionAdmission(\n\t\t\t\t\trepo,\n\t\t\t\t\tsnapshotsResult.snapshots,\n\t\t\t\t\tobservedSources,\n\t\t\t\t\titemSourceKeys,\n\t\t\t\t\tbatchBudget,\n\t\t\t\t);\n\t\t\t\tif (admission.outcome === \"claim_budget_deferred\") break;\n\t\t\t\tif (admission.outcome !== \"admitted\") {\n\t\t\t\t\tresults.set(\n\t\t\t\t\t\tcontentRefreshKey(item.collectionId, item.contentId),\n\t\t\t\t\t\tadmissionFailureResult(admission.outcome),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst key = contentRefreshKey(item.collectionId, item.contentId);\n\t\t\t\tif (allNew) {\n\t\t\t\t\tnewSourceProjections.push(\n\t\t\t\t\t\t...snapshotsResult.snapshots.map((snapshot) => ({\n\t\t\t\t\t\t\tsource: snapshot.source,\n\t\t\t\t\t\t\toccurrences: snapshot.occurrences,\n\t\t\t\t\t\t})),\n\t\t\t\t\t);\n\t\t\t\t\tnewSourceKeys.set(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tsnapshotsResult.snapshots.map((snapshot) => snapshot.source.sourceKey),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst changed: string[] = [];\n\t\t\t\tconst unchanged: string[] = [];\n\t\t\t\tfor (const snapshot of snapshotsResult.snapshots) {\n\t\t\t\t\tconst expectedSource = observedSources.get(snapshot.source.sourceKey);\n\t\t\t\t\tif (!expectedSource) continue;\n\t\t\t\t\tif (\n\t\t\t\t\t\texpectedSource.sourceFingerprint === snapshot.source.sourceFingerprint &&\n\t\t\t\t\t\texpectedSource.sourceCompleteness ===\n\t\t\t\t\t\t\t(snapshot.source.sourceCompleteness ?? \"complete\") &&\n\t\t\t\t\t\texpectedSource.lastErrorCode === null\n\t\t\t\t\t) {\n\t\t\t\t\t\tunchanged.push(snapshot.source.sourceKey);\n\t\t\t\t\t\tunchangedSourceProjections.push({\n\t\t\t\t\t\t\tsource: snapshot.source,\n\t\t\t\t\t\t\toccurrences: snapshot.occurrences,\n\t\t\t\t\t\t\texpectedSource,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tchanged.push(snapshot.source.sourceKey);\n\t\t\t\t\texistingSourceProjections.push({\n\t\t\t\t\t\tsource: snapshot.source,\n\t\t\t\t\t\toccurrences: snapshot.occurrences,\n\t\t\t\t\t\texpectedSource,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\texistingSourceKeys.set(key, {\n\t\t\t\t\tallCount: snapshotsResult.snapshots.length,\n\t\t\t\t\tchanged,\n\t\t\t\t\tunchanged,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst insertedSourceKeys = await repo.replaceNewSourcesBatch(newSourceProjections);\n\t\t\tconst replacedSourceKeys = await repo.replaceExistingSourcesBatch(existingSourceProjections);\n\t\t\tconst matchedSourceKeys = await repo.matchingExistingSourcesBatch(unchangedSourceProjections);\n\t\t\tfor (const [key, expectedSourceKeys] of newSourceKeys) {\n\t\t\t\tresults.set(\n\t\t\t\t\tkey,\n\t\t\t\t\texpectedSourceKeys.every((sourceKey) => insertedSourceKeys.has(sourceKey))\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\trefreshedSourceCount: expectedSourceKeys.length,\n\t\t\t\t\t\t\t\tdeletedSourceCount: 0,\n\t\t\t\t\t\t\t\tfailedSourceCount: 0,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: generationConflictResult({ refreshedSourceCount: 0, deletedSourceCount: 0 }),\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [key, expected] of existingSourceKeys) {\n\t\t\t\tresults.set(\n\t\t\t\t\tkey,\n\t\t\t\t\texpected.changed.every((sourceKey) => replacedSourceKeys.has(sourceKey)) &&\n\t\t\t\t\t\texpected.unchanged.every((sourceKey) => matchedSourceKeys.has(sourceKey))\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\trefreshedSourceCount: expected.allCount,\n\t\t\t\t\t\t\t\tdeletedSourceCount: 0,\n\t\t\t\t\t\t\t\tfailedSourceCount: 0,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: generationConflictResult({ refreshedSourceCount: 0, deletedSourceCount: 0 }),\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const item of collectionItems) {\n\t\t\t\tif (options.shouldContinue && !options.shouldContinue()) break;\n\t\t\t\tconst key = contentRefreshKey(item.collectionId, item.contentId);\n\t\t\t\tif (!snapshots.has(item.contentId)) continue;\n\t\t\t\tif (results.has(key)) continue;\n\t\t\t\tconst result = await withContentUsageLock(item.collectionSlug, item.contentId, () =>\n\t\t\t\t\trefreshContentMediaUsageUnlocked(db, item.collectionSlug, item.contentId, {\n\t\t\t\t\t\tcollectionId: item.collectionId,\n\t\t\t\t\t\tdurableWork: true,\n\t\t\t\t\t\tfieldDiscovery,\n\t\t\t\t\t\tobservedSources,\n\t\t\t\t\t\tsnapshotsResult: snapshots.get(item.contentId),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tresults.set(key, result);\n\t\t\t}\n\t\t});\n\t}\n\treturn results;\n}\n\nasync function refreshContentMediaUsageUnlocked(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n\toptions: ContentMediaUsageRefreshOptions,\n): Promise<ContentMediaUsageRefreshResult> {\n\ttry {\n\t\tlet conflictResult: ContentMediaUsageRefreshResult | null = null;\n\t\tif (options.durableWork) options.admissionBudget = createContentMediaUsageAdmissionBudget();\n\t\tfor (let attempt = 0; attempt < CONTENT_USAGE_REFRESH_MAX_ATTEMPTS; attempt++) {\n\t\t\tconst result = await refreshContentMediaUsageAttempt(db, collectionSlug, contentId, options);\n\t\t\tif (result.errorCode !== \"CONTENT_USAGE_GENERATION_CONFLICT\") return result;\n\t\t\tconflictResult = result;\n\t\t\tif (options.admissionBudget?.hasReservedMutation) break;\n\t\t}\n\n\t\tif (options.durableWork) {\n\t\t\treturn generationConflictResult({\n\t\t\t\trefreshedSourceCount: conflictResult?.refreshedSourceCount ?? 0,\n\t\t\t\tdeletedSourceCount: conflictResult?.deletedSourceCount ?? 0,\n\t\t\t});\n\t\t}\n\t\treturn markGenerationConflict(db, collectionSlug, {\n\t\t\trefreshedSourceCount: conflictResult?.refreshedSourceCount ?? 0,\n\t\t\tdeletedSourceCount: conflictResult?.deletedSourceCount ?? 0,\n\t\t});\n\t} catch (error) {\n\t\tconsole.error(`[media-usage] Failed to refresh ${collectionSlug}/${contentId}:`, error);\n\t\tif (!options.durableWork) {\n\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\tdb,\n\t\t\t\tcollectionSlug,\n\t\t\t\t\"CONTENT_USAGE_REFRESH_ERROR\",\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\trefreshedSourceCount: 0,\n\t\t\tdeletedSourceCount: 0,\n\t\t\tfailedSourceCount: 0,\n\t\t\terrorCode: \"CONTENT_USAGE_REFRESH_ERROR\",\n\t\t};\n\t}\n}\n\nasync function refreshContentMediaUsageAttempt(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n\toptions: ContentMediaUsageRefreshOptions,\n): Promise<ContentMediaUsageRefreshResult> {\n\tconst repo = new MediaUsageRepository(db);\n\tconst canonicalSourceKeys = contentSourceKeys(collectionSlug, contentId, options.collectionId);\n\tconst observedSources = options.observedSources ?? (await repo.findSources(canonicalSourceKeys));\n\tconst snapshotsResult =\n\t\toptions.snapshotsResult ??\n\t\t(await loadContentMediaUsageSnapshots(\n\t\t\tdb,\n\t\t\tcollectionSlug,\n\t\t\tcontentId,\n\t\t\toptions.fieldDiscovery,\n\t\t\toptions.collectionId ? { collectionId: options.collectionId, identityVersion: 1 } : undefined,\n\t\t));\n\tif (!snapshotsResult.success) {\n\t\tif (snapshotsResult.error === \"CONTENT_NOT_FOUND\" && options.collectionId) {\n\t\t\tif (!options.admissionBudget)\n\t\t\t\tthrow new Error(\"Durable media usage work requires an admission budget\");\n\t\t\tconst admission = await planContentMediaUsageProjectionAdmission(\n\t\t\t\trepo,\n\t\t\t\t[],\n\t\t\t\tobservedSources,\n\t\t\t\tcanonicalSourceKeys,\n\t\t\t\toptions.admissionBudget,\n\t\t\t);\n\t\t\tif (admission.outcome !== \"admitted\") return admissionFailureResult(admission.outcome);\n\t\t\treturn deleteCanonicalContentSourcesIfAbsent(\n\t\t\t\trepo,\n\t\t\t\tadmission.absentSources,\n\t\t\t\tcollectionSlug,\n\t\t\t\tcontentId,\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tsnapshotsResult.error === \"CONTENT_NOT_FOUND\" &&\n\t\t\t!(await contentCollectionExists(db, collectionSlug))\n\t\t) {\n\t\t\tconst deletedSourceCount = await repo.deleteContentSources(collectionSlug, contentId);\n\t\t\treturn { ...ZERO_RESULT, deletedSourceCount };\n\t\t}\n\t\treturn options.durableWork\n\t\t\t? snapshotFailureResult(snapshotsResult)\n\t\t\t: markSnapshotFailure(db, collectionSlug, snapshotsResult);\n\t}\n\n\tif (!options.collectionId && !(await contentCollectionExists(db, collectionSlug))) {\n\t\tconst deletedSourceCount = await repo.deleteContentSources(collectionSlug, contentId);\n\t\treturn { ...ZERO_RESULT, deletedSourceCount };\n\t}\n\tconst admission = options.admissionBudget\n\t\t? await planContentMediaUsageProjectionAdmission(\n\t\t\t\trepo,\n\t\t\t\tsnapshotsResult.snapshots,\n\t\t\t\tobservedSources,\n\t\t\t\tcanonicalSourceKeys,\n\t\t\t\toptions.admissionBudget,\n\t\t\t)\n\t\t: null;\n\tif (admission && admission.outcome !== \"admitted\") {\n\t\treturn admissionFailureResult(admission.outcome);\n\t}\n\tlet refreshedSourceCount = 0;\n\tfor (const snapshot of snapshotsResult.snapshots) {\n\t\tif (\n\t\t\tadmission?.outcome === \"admitted\" &&\n\t\t\tadmission.noOpSourceKeys.has(snapshot.source.sourceKey)\n\t\t) {\n\t\t\trefreshedSourceCount++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst result = await repo.replaceSourceIfMatching(\n\t\t\tsnapshot.source,\n\t\t\tsnapshot.occurrences,\n\t\t\tobservedSources.get(snapshot.source.sourceKey) ?? null,\n\t\t);\n\t\tif (result.unchanged) {\n\t\t\trefreshedSourceCount++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (!result.replaced) {\n\t\t\treturn generationConflictResult({\n\t\t\t\trefreshedSourceCount,\n\t\t\t\tdeletedSourceCount: 0,\n\t\t\t});\n\t\t}\n\t\trefreshedSourceCount++;\n\t}\n\tif (!options.collectionId && !(await contentCollectionExists(db, collectionSlug))) {\n\t\tconst deletedSourceCount = await repo.deleteContentSources(collectionSlug, contentId);\n\t\treturn { ...ZERO_RESULT, deletedSourceCount };\n\t}\n\n\tconst expectedSourceKeys = new Set(\n\t\tsnapshotsResult.snapshots.map((snapshot) => snapshot.source.sourceKey),\n\t);\n\tconst absentSources =\n\t\tadmission?.outcome === \"admitted\"\n\t\t\t? admission.absentSources\n\t\t\t: canonicalSourceKeys\n\t\t\t\t\t.filter((sourceKey) => !expectedSourceKeys.has(sourceKey))\n\t\t\t\t\t.map((sourceKey) => observedSources.get(sourceKey))\n\t\t\t\t\t.filter((source): source is MediaUsageSource => source !== undefined);\n\tlet deletedSourceCount = 0;\n\tfor (const expectedSource of absentSources) {\n\t\tconst result = await repo.deleteSourceIfMatching(expectedSource.sourceKey, expectedSource);\n\t\tif (result.deleted) {\n\t\t\tdeletedSourceCount++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (result.source) {\n\t\t\treturn generationConflictResult({\n\t\t\t\trefreshedSourceCount,\n\t\t\t\tdeletedSourceCount,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\trefreshedSourceCount,\n\t\tdeletedSourceCount,\n\t\tfailedSourceCount: 0,\n\t};\n}\n\nexport function contentRefreshKey(collectionId: string, contentId: string): string {\n\treturn `${collectionId}\\u0000${contentId}`;\n}\n\nfunction contentSourceKeys(\n\tcollectionSlug: string,\n\tcontentId: string,\n\tcollectionId?: string,\n): string[] {\n\treturn MEDIA_USAGE_CONTENT_SOURCE_VARIANTS.map((sourceVariant) =>\n\t\tbuildContentMediaUsageSourceKey({\n\t\t\tcollectionId,\n\t\t\tcollectionSlug,\n\t\t\tcontentId,\n\t\t\tsourceVariant,\n\t\t}),\n\t);\n}\n\nfunction admissionFailureResult(\n\toutcome: \"intrinsic_resource_limit\" | \"claim_budget_deferred\",\n): ContentMediaUsageRefreshResult {\n\treturn {\n\t\t...generationConflictResult({ refreshedSourceCount: 0, deletedSourceCount: 0 }),\n\t\terrorCode:\n\t\t\toutcome === \"intrinsic_resource_limit\"\n\t\t\t\t? \"CONTENT_USAGE_RESOURCE_LIMIT\"\n\t\t\t\t: \"CONTENT_USAGE_GENERATION_CONFLICT\",\n\t};\n}\n\nasync function markGenerationConflict(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcounts: Pick<ContentMediaUsageRefreshResult, \"refreshedSourceCount\" | \"deletedSourceCount\">,\n): Promise<ContentMediaUsageRefreshResult> {\n\tawait markContentMediaUsageCollectionStaleSafely(\n\t\tdb,\n\t\tcollectionSlug,\n\t\t\"CONTENT_USAGE_GENERATION_CONFLICT\",\n\t);\n\treturn {\n\t\tsuccess: false,\n\t\trefreshedSourceCount: counts.refreshedSourceCount,\n\t\tdeletedSourceCount: counts.deletedSourceCount,\n\t\tfailedSourceCount: 0,\n\t\terrorCode: \"CONTENT_USAGE_GENERATION_CONFLICT\",\n\t};\n}\n\nfunction generationConflictResult(\n\tcounts: Pick<ContentMediaUsageRefreshResult, \"refreshedSourceCount\" | \"deletedSourceCount\">,\n): ContentMediaUsageRefreshResult {\n\treturn {\n\t\tsuccess: false,\n\t\trefreshedSourceCount: counts.refreshedSourceCount,\n\t\tdeletedSourceCount: counts.deletedSourceCount,\n\t\tfailedSourceCount: 0,\n\t\terrorCode: \"CONTENT_USAGE_GENERATION_CONFLICT\",\n\t};\n}\n\nasync function contentCollectionExists(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcollectionId?: string,\n): Promise<boolean> {\n\tlet query = db.selectFrom(\"_emdash_collections\").select(\"id\").where(\"slug\", \"=\", collectionSlug);\n\tif (collectionId) query = query.where(\"id\", \"=\", collectionId);\n\tconst row = await query.executeTakeFirst();\n\treturn row !== undefined;\n}\n\nexport async function deleteContentMediaUsage(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n): Promise<ContentMediaUsageRefreshResult> {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\treturn withContentUsageCollectionLock(collectionSlug, () =>\n\t\twithContentUsageLock(collectionSlug, contentId, () =>\n\t\t\tdeleteContentMediaUsageUnlocked(db, collectionSlug, contentId),\n\t\t),\n\t);\n}\n\nasync function deleteContentMediaUsageUnlocked(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n): Promise<ContentMediaUsageRefreshResult> {\n\ttry {\n\t\tconst deletedSourceCount = await new MediaUsageRepository(db).deleteContentSources(\n\t\t\tcollectionSlug,\n\t\t\tcontentId,\n\t\t);\n\t\treturn { ...ZERO_RESULT, deletedSourceCount };\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\t`[media-usage] Failed to delete usage for ${collectionSlug}/${contentId}:`,\n\t\t\terror,\n\t\t);\n\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\tdb,\n\t\t\tcollectionSlug,\n\t\t\t\"CONTENT_USAGE_DELETE_ERROR\",\n\t\t);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\trefreshedSourceCount: 0,\n\t\t\tdeletedSourceCount: 0,\n\t\t\tfailedSourceCount: 0,\n\t\t\terrorCode: \"CONTENT_USAGE_DELETE_ERROR\",\n\t\t};\n\t}\n}\n\nexport async function deleteContentMediaUsageCollection(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n): Promise<ContentMediaUsageRefreshResult> {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\treturn withContentUsageCollectionLock(collectionSlug, () =>\n\t\tdeleteContentMediaUsageCollectionUnlocked(db, collectionSlug),\n\t);\n}\n\nasync function deleteContentMediaUsageCollectionUnlocked(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n): Promise<ContentMediaUsageRefreshResult> {\n\ttry {\n\t\tconst repo = new MediaUsageRepository(db);\n\t\tconst deletedSourceCount = await repo.deleteCollectionSources(collectionSlug);\n\t\tawait repo.deleteIndexStatus({\n\t\t\tadapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,\n\t\t\tscopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,\n\t\t\tscopeKey: collectionSlug,\n\t\t});\n\t\treturn { ...ZERO_RESULT, deletedSourceCount };\n\t} catch (error) {\n\t\tconsole.error(`[media-usage] Failed to delete usage for collection ${collectionSlug}:`, error);\n\t\ttry {\n\t\t\tawait new MediaUsageRepository(db).deleteIndexStatus({\n\t\t\t\tadapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,\n\t\t\t\tscopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,\n\t\t\t\tscopeKey: collectionSlug,\n\t\t\t});\n\t\t} catch (statusError) {\n\t\t\tconsole.error(\n\t\t\t\t`[media-usage] Failed to clear usage status for deleted collection ${collectionSlug}:`,\n\t\t\t\tstatusError,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\trefreshedSourceCount: 0,\n\t\t\tdeletedSourceCount: 0,\n\t\t\tfailedSourceCount: 0,\n\t\t\terrorCode: \"CONTENT_USAGE_DELETE_ERROR\",\n\t\t};\n\t}\n}\n\nexport async function refreshContentMediaUsageAfterWrite(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n): Promise<void> {\n\tconst result = await refreshContentMediaUsage(db, collectionSlug, contentId);\n\tif (!result.success) {\n\t\tconsole.error(\n\t\t\t`[media-usage] Usage refresh for ${collectionSlug}/${contentId} finished with ${result.errorCode}`,\n\t\t);\n\t}\n}\n\nexport async function findNonTranslatableSiblingContentIds(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tupdatedContentId: string,\n\ttranslationGroup: string | null | undefined,\n\tupdatedData: Record<string, unknown> | undefined,\n\toptions: { absentAsCleared?: boolean } = {},\n): Promise<string[]> {\n\tif (!isI18nEnabled() || !updatedData || !translationGroup) return [];\n\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\tconst collection = await db\n\t\t.selectFrom(\"_emdash_collections\")\n\t\t.select(\"id\")\n\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t.executeTakeFirst();\n\tif (!collection) return [];\n\n\tconst fields = await db\n\t\t.selectFrom(\"_emdash_fields\")\n\t\t.select(\"slug\")\n\t\t.where(\"collection_id\", \"=\", collection.id)\n\t\t.where(\"translatable\", \"=\", 0)\n\t\t.execute();\n\n\tconst touchedNonTranslatableSlugs = fields\n\t\t.filter((field) => options.absentAsCleared || field.slug in updatedData)\n\t\t.map((field) => field.slug);\n\tif (touchedNonTranslatableSlugs.length === 0) return [];\n\n\tconst usageFields = await loadContentMediaUsageFields(db, collectionSlug);\n\tconst usageRelevantSlugs = new Set([\n\t\t...usageFields.extractionFields.map((field) => field.slug),\n\t\t...usageFields.displayFieldSlugs,\n\t]);\n\tif (!touchedNonTranslatableSlugs.some((slug) => usageRelevantSlugs.has(slug))) return [];\n\n\tconst tableName = `ec_${collectionSlug}`;\n\tconst rows = await sql<{ id: string }>`\n\t\tSELECT id\n\t\tFROM ${sql.ref(tableName)}\n\t\tWHERE translation_group = ${translationGroup}\n\t\tAND id != ${updatedContentId}\n\t\tORDER BY id ASC\n\t`.execute(db);\n\n\treturn rows.rows.map((row) => row.id);\n}\n\nasync function markSnapshotFailure(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tresult: Exclude<Awaited<ReturnType<typeof loadContentMediaUsageSnapshots>>, { success: true }>,\n): Promise<ContentMediaUsageRefreshResult> {\n\tconst repo = new MediaUsageRepository(db);\n\tif (result.source) {\n\t\tawait repo.markSourceAttempted({\n\t\t\t...result.source,\n\t\t\tsourceCompleteness: \"failed\",\n\t\t\tlastErrorCode: result.error,\n\t\t});\n\t}\n\tawait markContentMediaUsageCollectionStale(db, collectionSlug, result.error);\n\treturn {\n\t\tsuccess: false,\n\t\trefreshedSourceCount: 0,\n\t\tdeletedSourceCount: 0,\n\t\tfailedSourceCount: result.source ? 1 : 0,\n\t\terrorCode: result.error,\n\t};\n}\n\nfunction snapshotFailureResult(\n\tresult: Exclude<Awaited<ReturnType<typeof loadContentMediaUsageSnapshots>>, { success: true }>,\n): ContentMediaUsageRefreshResult {\n\treturn {\n\t\tsuccess: false,\n\t\trefreshedSourceCount: 0,\n\t\tdeletedSourceCount: 0,\n\t\tfailedSourceCount: result.source ? 1 : 0,\n\t\terrorCode: result.error,\n\t};\n}\n\nasync function deleteCanonicalContentSourcesIfAbsent(\n\trepo: MediaUsageRepository,\n\tobservedSources: readonly MediaUsageSource[],\n\tcollectionSlug: string,\n\tcontentId: string,\n): Promise<ContentMediaUsageRefreshResult> {\n\tlet deletedSourceCount = 0;\n\tfor (const source of observedSources) {\n\t\tconst result = await repo.deleteSourceIfMatchingContentAbsent(\n\t\t\tsource.sourceKey,\n\t\t\tsource,\n\t\t\tcollectionSlug,\n\t\t\tcontentId,\n\t\t);\n\t\tif (result.deleted) {\n\t\t\tdeletedSourceCount++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (result.contentPresent || result.source) {\n\t\t\treturn generationConflictResult({ refreshedSourceCount: 0, deletedSourceCount });\n\t\t}\n\t}\n\treturn { ...ZERO_RESULT, deletedSourceCount };\n}\n\nasync function withContentUsageLock<T>(\n\tcollectionSlug: string,\n\tcontentId: string,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst locks = getContentUsageLocks();\n\tconst lockKey = `${collectionSlug}\\0${contentId}`;\n\tconst previous = locks.get(lockKey) ?? Promise.resolve();\n\tlet releaseCurrent!: () => void;\n\tconst current = new Promise<void>((resolve) => {\n\t\treleaseCurrent = resolve;\n\t});\n\tconst next = previous.catch(() => {}).then(() => current);\n\tlocks.set(lockKey, next);\n\n\ttry {\n\t\tawait previous.catch(() => {});\n\t\treturn await fn();\n\t} finally {\n\t\treleaseCurrent();\n\t\tif (locks.get(lockKey) === next) locks.delete(lockKey);\n\t}\n}\n\nexport async function withContentUsageCollectionLock<T>(\n\tcollectionSlug: string,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\t// Coarse by design: row refreshes and collection source deletes must not interleave.\n\tconst locks = getContentUsageCollectionLocks();\n\tconst previous = locks.get(collectionSlug) ?? Promise.resolve();\n\tlet releaseCurrent!: () => void;\n\tconst current = new Promise<void>((resolve) => {\n\t\treleaseCurrent = resolve;\n\t});\n\tconst next = previous.catch(() => {}).then(() => current);\n\tlocks.set(collectionSlug, next);\n\n\ttry {\n\t\tawait previous.catch(() => {});\n\t\treturn await fn();\n\t} finally {\n\t\treleaseCurrent();\n\t\tif (locks.get(collectionSlug) === next) locks.delete(collectionSlug);\n\t}\n}\n\nfunction getContentUsageLocks(): Map<string, Promise<void>> {\n\tconst global = globalThis as typeof globalThis & Record<symbol, unknown>;\n\tconst existing = global[CONTENT_USAGE_LOCKS_KEY];\n\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis symbol slot stores only this map\n\tif (existing instanceof Map) return existing as Map<string, Promise<void>>;\n\tconst locks = new Map<string, Promise<void>>();\n\tglobal[CONTENT_USAGE_LOCKS_KEY] = locks;\n\treturn locks;\n}\n\nfunction getContentUsageCollectionLocks(): Map<string, Promise<void>> {\n\tconst global = globalThis as typeof globalThis & Record<symbol, unknown>;\n\tconst existing = global[CONTENT_USAGE_COLLECTION_LOCKS_KEY];\n\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis symbol slot stores only this map\n\tif (existing instanceof Map) return existing as Map<string, Promise<void>>;\n\tconst locks = new Map<string, Promise<void>>();\n\tglobal[CONTENT_USAGE_COLLECTION_LOCKS_KEY] = locks;\n\treturn locks;\n}\n","/**\n * Column classification registry for every portable table.\n *\n * Every column of a portable table must appear here, and every table in the\n * database must be either portable or listed as non-portable. Exporter readers\n * and verification call {@link assertColumnCoverage} before reading a table,\n * so a migration that adds a column fails loudly until someone decides how\n * the column transfers.\n *\n * Classes:\n * - `field`: exported as the record property `property` using `codec`.\n * - `principal`: holds an origin user id; exported as `property` (a principal\n * reference) and mapped through the plan's principal mappings on import.\n * - `mediaRef`: exported as `property`; its value may carry storage-key\n * references, which the exporter rewrites to `emdash-media:` placeholders.\n * - `derived`: not exported; the importer computes it on the target.\n * - `excluded`: not exported; the target keeps the column default.\n * - `randomized`: not exported; the importer fills a fresh opaque value.\n * - `targetLocal`: not exported; the value belongs to the target installation.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { listTableColumns, type TableColumnInfo } from \"../../database/dialect-helpers.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport { isStoragelessFieldRow } from \"../../schema/types.js\";\nimport { TransferError } from \"../errors.js\";\nimport type { RecordKind } from \"./kinds.js\";\n\nexport type ColumnClass =\n\t| \"field\"\n\t| \"excluded\"\n\t| \"derived\"\n\t| \"principal\"\n\t| \"mediaRef\"\n\t| \"randomized\"\n\t| \"targetLocal\";\n\n/**\n * How a column value maps to a record property:\n * - `text`: string, verbatim\n * - `integer` / `real`: number\n * - `boolean`: 0/1 integer ↔ boolean\n * - `json`: JSON held in a TEXT column ↔ parsed JSON value\n * - `nativeJson`: a column declared `json` (`ec_*` JSON fields)\n *\n * Decode and encode only through `column-codec.ts`.\n */\nexport type ColumnCodec = \"text\" | \"integer\" | \"real\" | \"boolean\" | \"json\" | \"nativeJson\";\n\nexport type ColumnSpec =\n\t| { class: \"field\" | \"principal\" | \"mediaRef\"; property: string; codec: ColumnCodec }\n\t| { class: \"excluded\" | \"derived\" | \"randomized\" | \"targetLocal\" };\n\nexport interface PortableTableSpec {\n\ttable: string;\n\tkind: RecordKind;\n\tcolumns: Readonly<Record<string, ColumnSpec>>;\n}\n\nfunction f(property: string, codec: ColumnCodec = \"text\"): ColumnSpec {\n\treturn { class: \"field\", property, codec };\n}\n\nfunction principal(property: string): ColumnSpec {\n\treturn { class: \"principal\", property, codec: \"text\" };\n}\n\nconst EXCLUDED: ColumnSpec = { class: \"excluded\" };\nconst DERIVED: ColumnSpec = { class: \"derived\" };\nconst RANDOMIZED: ColumnSpec = { class: \"randomized\" };\nconst TARGET_LOCAL: ColumnSpec = { class: \"targetLocal\" };\n\nconst PORTABLE_TABLE_LIST: PortableTableSpec[] = [\n\t{\n\t\ttable: \"_emdash_block_types\",\n\t\tkind: \"block_type\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\tdescription: f(\"description\"),\n\t\t\ticon: f(\"icon\"),\n\t\t\tcategory: f(\"category\"),\n\t\t\tcurrent_version: f(\"currentVersion\", \"integer\"),\n\t\t\tsource: f(\"source\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_block_type_versions\",\n\t\tkind: \"block_type_version\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tblock_type_id: f(\"blockTypeId\"),\n\t\t\tversion: f(\"version\", \"integer\"),\n\t\t\tfields: f(\"fields\", \"json\"),\n\t\t\tfingerprint: DERIVED,\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_collections\",\n\t\tkind: \"collection\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\tlabel_singular: f(\"labelSingular\"),\n\t\t\tdescription: f(\"description\"),\n\t\t\ticon: f(\"icon\"),\n\t\t\tsupports: f(\"supports\", \"json\"),\n\t\t\tsource: f(\"source\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t\tsearch_config: f(\"searchConfig\", \"json\"),\n\t\t\thas_seo: f(\"hasSeo\", \"boolean\"),\n\t\t\turl_pattern: f(\"urlPattern\"),\n\t\t\tcomments_enabled: f(\"commentsEnabled\", \"boolean\"),\n\t\t\tcomments_moderation: f(\"commentsModeration\"),\n\t\t\tcomments_closed_after_days: f(\"commentsClosedAfterDays\", \"integer\"),\n\t\t\tcomments_auto_approve_users: f(\"commentsAutoApproveUsers\", \"boolean\"),\n\t\t\thidden: f(\"hidden\", \"boolean\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t\tadmin_config: f(\"adminConfig\", \"json\"),\n\t\t\ttitle_field: f(\"titleField\"),\n\t\t\tdate_field: f(\"dateField\"),\n\t\t\troutable: f(\"routable\", \"boolean\"),\n\t\t\tedit_locking: f(\"editLocking\", \"boolean\"),\n\t\t\tnav_group: f(\"navGroup\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_fields\",\n\t\tkind: \"field\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tcollection_id: f(\"collectionId\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\ttype: f(\"type\"),\n\t\t\tcolumn_type: f(\"columnType\"),\n\t\t\trequired: f(\"required\", \"boolean\"),\n\t\t\tunique: f(\"unique\", \"boolean\"),\n\t\t\tdefault_value: f(\"defaultValue\", \"json\"),\n\t\t\tvalidation: f(\"validation\", \"json\"),\n\t\t\twidget: f(\"widget\"),\n\t\t\toptions: f(\"options\", \"json\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tsearchable: f(\"searchable\", \"boolean\"),\n\t\t\ttranslatable: f(\"translatable\", \"boolean\"),\n\t\t\tindexed: f(\"indexed\", \"boolean\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_taxonomy_defs\",\n\t\tkind: \"taxonomy_def\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tname: f(\"name\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\tlabel_singular: f(\"labelSingular\"),\n\t\t\thierarchical: f(\"hierarchical\", \"boolean\"),\n\t\t\tcollections: f(\"collections\", \"json\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tlocale: f(\"locale\"),\n\t\t\ttranslation_group: f(\"translationGroup\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_relations\",\n\t\tkind: \"relation\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\tparent_collection: f(\"parentCollection\"),\n\t\t\tchild_collection: f(\"childCollection\"),\n\t\t\tparent_label: f(\"parentLabel\"),\n\t\t\tchild_label: f(\"childLabel\"),\n\t\t\tparent_label_singular: f(\"parentLabelSingular\"),\n\t\t\tchild_label_singular: f(\"childLabelSingular\"),\n\t\t\tmax_children_per_parent: f(\"maxChildrenPerParent\", \"integer\"),\n\t\t\tmax_parents_per_child: f(\"maxParentsPerChild\", \"integer\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_byline_fields\",\n\t\tkind: \"byline_field\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\ttype: f(\"type\"),\n\t\t\trequired: f(\"required\", \"boolean\"),\n\t\t\ttranslatable: f(\"translatable\", \"boolean\"),\n\t\t\tvalidation: f(\"validation\", \"json\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"media_folders\",\n\t\tkind: \"media_folder\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tname: f(\"name\"),\n\t\t\tname_key: f(\"nameKey\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"media\",\n\t\tkind: \"media\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tfilename: f(\"filename\"),\n\t\t\tmime_type: f(\"mimeType\"),\n\t\t\tsize: f(\"size\", \"integer\"),\n\t\t\twidth: f(\"width\", \"integer\"),\n\t\t\theight: f(\"height\", \"integer\"),\n\t\t\tfocal_x: f(\"focalX\", \"real\"),\n\t\t\tfocal_y: f(\"focalY\", \"real\"),\n\t\t\talt: f(\"alt\"),\n\t\t\tcaption: f(\"caption\"),\n\t\t\tstorage_key: TARGET_LOCAL,\n\t\t\tcontent_hash: DERIVED,\n\t\t\tstatus: DERIVED,\n\t\t\tblurhash: f(\"blurhash\"),\n\t\t\tdominant_color: f(\"dominantColor\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tauthor_id: principal(\"authorPrincipal\"),\n\t\t\tfolder_id: f(\"folderId\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"taxonomies\",\n\t\tkind: \"term\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tname: f(\"name\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\tparent_id: f(\"parentId\"),\n\t\t\tdata: f(\"data\", \"json\"),\n\t\t\tlocale: f(\"locale\"),\n\t\t\ttranslation_group: f(\"translationGroup\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_bylines\",\n\t\tkind: \"byline\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\tdisplay_name: f(\"displayName\"),\n\t\t\tbio: f(\"bio\"),\n\t\t\tavatar_media_id: f(\"avatarMediaId\"),\n\t\t\twebsite_url: f(\"websiteUrl\"),\n\t\t\tuser_id: principal(\"userPrincipal\"),\n\t\t\tis_guest: f(\"isGuest\", \"boolean\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t\tlocale: f(\"locale\"),\n\t\t\ttranslation_group: f(\"translationGroup\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_byline_field_values\",\n\t\tkind: \"byline_field_value\",\n\t\tcolumns: {\n\t\t\tbyline_id: f(\"bylineId\"),\n\t\t\tfield_id: f(\"fieldId\"),\n\t\t\tvalue: f(\"value\", \"json\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_byline_field_group_values\",\n\t\tkind: \"byline_field_group_value\",\n\t\tcolumns: {\n\t\t\ttranslation_group: f(\"bylineGroup\"),\n\t\t\tfield_id: f(\"fieldId\"),\n\t\t\tvalue: f(\"value\", \"json\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"revisions\",\n\t\tkind: \"revision\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tcollection: f(\"collection\"),\n\t\t\tentry_id: f(\"entryId\"),\n\t\t\tdata: f(\"data\", \"json\"),\n\t\t\tauthor_id: principal(\"authorPrincipal\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"content_taxonomies\",\n\t\tkind: \"content_term\",\n\t\tcolumns: {\n\t\t\tcollection: f(\"collection\"),\n\t\t\tentry_id: f(\"entryGroup\"),\n\t\t\ttaxonomy_id: f(\"termGroup\"),\n\t\t\tstatus: EXCLUDED,\n\t\t\tscheduled_at: EXCLUDED,\n\t\t\tdeleted_at: EXCLUDED,\n\t\t\tlocale: EXCLUDED,\n\t\t\tpublished_at: EXCLUDED,\n\t\t\tcreated_at: EXCLUDED,\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_content_bylines\",\n\t\tkind: \"content_byline\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tcollection_slug: f(\"collection\"),\n\t\t\tcontent_id: f(\"entryId\"),\n\t\t\tbyline_id: f(\"bylineGroup\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t\trole_label: f(\"roleLabel\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_content_references\",\n\t\tkind: \"content_reference\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\trelation_id: f(\"relationId\"),\n\t\t\tparent_group: f(\"parentGroup\"),\n\t\t\tchild_group: f(\"childGroup\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_seo\",\n\t\tkind: \"seo\",\n\t\tcolumns: {\n\t\t\tcollection: f(\"collection\"),\n\t\t\tcontent_id: f(\"entryId\"),\n\t\t\tseo_title: f(\"seoTitle\"),\n\t\t\tseo_description: f(\"seoDescription\"),\n\t\t\tseo_image: { class: \"mediaRef\", property: \"seoImage\", codec: \"text\" },\n\t\t\tseo_canonical: f(\"seoCanonical\"),\n\t\t\tseo_no_index: f(\"seoNoIndex\", \"boolean\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_menus\",\n\t\tkind: \"menu\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tname: f(\"name\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t\tlocale: f(\"locale\"),\n\t\t\ttranslation_group: f(\"translationGroup\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_menu_items\",\n\t\tkind: \"menu_item\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tmenu_id: f(\"menuId\"),\n\t\t\tparent_id: f(\"parentId\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t\ttype: f(\"type\"),\n\t\t\treference_collection: f(\"referenceCollection\"),\n\t\t\treference_id: f(\"referenceGroup\"),\n\t\t\tcustom_url: f(\"customUrl\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\ttitle_attr: f(\"titleAttr\"),\n\t\t\ttarget: f(\"target\"),\n\t\t\tcss_classes: f(\"cssClasses\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tlocale: f(\"locale\"),\n\t\t\ttranslation_group: f(\"translationGroup\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_widget_areas\",\n\t\tkind: \"widget_area\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tname: f(\"name\"),\n\t\t\tlabel: f(\"label\"),\n\t\t\tdescription: f(\"description\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_widgets\",\n\t\tkind: \"widget\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tarea_id: f(\"areaId\"),\n\t\t\tsort_order: f(\"sortOrder\", \"integer\"),\n\t\t\ttype: f(\"type\"),\n\t\t\ttitle: f(\"title\"),\n\t\t\tcontent: f(\"content\", \"json\"),\n\t\t\tmenu_name: f(\"menuName\"),\n\t\t\tcomponent_id: f(\"componentId\"),\n\t\t\tcomponent_props: f(\"componentProps\", \"json\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_sections\",\n\t\tkind: \"section\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tslug: f(\"slug\"),\n\t\t\ttitle: f(\"title\"),\n\t\t\tdescription: f(\"description\"),\n\t\t\tkeywords: f(\"keywords\", \"json\"),\n\t\t\tcontent: f(\"content\", \"json\"),\n\t\t\tpreview_media_id: f(\"previewMediaId\"),\n\t\t\tsource: f(\"source\"),\n\t\t\ttheme_id: f(\"themeId\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_redirects\",\n\t\tkind: \"redirect\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tsource: f(\"source\"),\n\t\t\tdestination: f(\"destination\"),\n\t\t\ttype: f(\"type\", \"integer\"),\n\t\t\tis_pattern: f(\"isPattern\", \"boolean\"),\n\t\t\tenabled: f(\"enabled\", \"boolean\"),\n\t\t\thits: EXCLUDED,\n\t\t\tlast_hit_at: EXCLUDED,\n\t\t\tgroup_name: f(\"groupName\"),\n\t\t\tauto: f(\"auto\", \"boolean\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t\tconfig_revision: DERIVED,\n\t\t\tsource_guard: DERIVED,\n\t\t\twrite_generation: DERIVED,\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_comments\",\n\t\tkind: \"comment\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tcollection: f(\"collection\"),\n\t\t\tcontent_id: f(\"entryId\"),\n\t\t\tparent_id: f(\"parentId\"),\n\t\t\tauthor_name: f(\"authorName\"),\n\t\t\tauthor_email: f(\"authorEmail\"),\n\t\t\tauthor_user_id: principal(\"authorPrincipal\"),\n\t\t\tbody: f(\"body\"),\n\t\t\tstatus: f(\"status\"),\n\t\t\tip_hash: EXCLUDED,\n\t\t\tuser_agent: EXCLUDED,\n\t\t\tmoderation_metadata: f(\"moderationMetadata\", \"json\"),\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t\tupdated_at: f(\"updatedAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"_emdash_comment_reactions\",\n\t\tkind: \"comment_reaction\",\n\t\tcolumns: {\n\t\t\tid: f(\"id\"),\n\t\t\tcomment_id: f(\"commentId\"),\n\t\t\treaction: f(\"reaction\"),\n\t\t\tvoter_hash: RANDOMIZED,\n\t\t\tcreated_at: f(\"createdAt\"),\n\t\t},\n\t},\n\t{\n\t\ttable: \"options\",\n\t\tkind: \"setting\",\n\t\tcolumns: {\n\t\t\tname: f(\"id\"),\n\t\t\tvalue: f(\"value\", \"json\"),\n\t\t\trevision: DERIVED,\n\t\t},\n\t},\n];\n\nexport const PORTABLE_TABLES: readonly PortableTableSpec[] = Object.freeze(PORTABLE_TABLE_LIST);\n\n/** Standard columns of every `ec_*` content table (kind `entry`). */\nexport const CONTENT_TABLE_COLUMNS: Readonly<Record<string, ColumnSpec>> = Object.freeze({\n\tid: f(\"id\"),\n\tslug: f(\"slug\"),\n\tstatus: f(\"status\"),\n\tauthor_id: principal(\"authorPrincipal\"),\n\tprimary_byline_id: f(\"primaryBylineGroup\"),\n\tcreated_at: f(\"createdAt\"),\n\tupdated_at: f(\"updatedAt\"),\n\tpublished_at: f(\"publishedAt\"),\n\tscheduled_at: f(\"scheduledAt\"),\n\tdeleted_at: f(\"deletedAt\"),\n\tversion: f(\"version\", \"integer\"),\n\tlive_revision_id: f(\"liveRevisionId\"),\n\tdraft_revision_id: f(\"draftRevisionId\"),\n\tlocale: f(\"locale\"),\n\ttranslation_group: f(\"translationGroup\"),\n});\n\nexport const CONTENT_TABLE_PREFIX = \"ec_\";\n\n/**\n * Tables that never transfer, with the reason. Every table a migration\n * creates must be portable or listed here (or match a non-portable prefix).\n */\nexport const NON_PORTABLE_TABLES: Readonly<Record<string, string>> = Object.freeze({\n\tusers: \"auth\",\n\tcredentials: \"auth\",\n\tauth_tokens: \"auth\",\n\toauth_accounts: \"auth\",\n\tallowed_domains: \"auth\",\n\tauth_challenges: \"auth\",\n\t_emdash_api_tokens: \"auth\",\n\t_emdash_oauth_tokens: \"auth\",\n\t_emdash_oauth_clients: \"auth\",\n\t_emdash_authorization_codes: \"auth\",\n\t_emdash_device_codes: \"auth\",\n\t_emdash_rate_limits: \"runtime\",\n\t_emdash_entry_locks: \"runtime\",\n\t_emdash_cron_tasks: \"runtime\",\n\t_emdash_redirect_write_lock: \"runtime\",\n\t_emdash_404_log: \"runtime\",\n\t_emdash_revision_prune_queue: \"runtime\",\n\t_emdash_media_upload_attempts: \"runtime\",\n\t_emdash_media_usage: \"derived\",\n\t_emdash_media_usage_sources: \"derived\",\n\t_emdash_media_usage_cleanup: \"runtime\",\n\t_emdash_media_usage_cleanup_fence: \"runtime\",\n\t_emdash_media_usage_generation_writes: \"runtime\",\n\t_emdash_media_usage_index_status: \"derived\",\n\t_emdash_media_usage_activation: \"runtime\",\n\t_emdash_media_usage_work: \"runtime\",\n\t_emdash_media_usage_collection_deletions: \"runtime\",\n\t_emdash_media_usage_reconciliations: \"runtime\",\n\t_emdash_taxonomy_def_groups: \"derived\",\n\taudit_logs: \"audit\",\n\t_emdash_migrations: \"migrations\",\n\t_emdash_migrations_lock: \"migrations\",\n\t_plugin_storage: \"plugin\",\n\t_plugin_state: \"plugin\",\n\t_plugin_indexes: \"plugin\",\n});\n\nexport const NON_PORTABLE_TABLE_PREFIXES: readonly string[] = Object.freeze([\n\t\"_emdash_fts_\",\n\t\"_emdash_transfer_\",\n\t\"_plugin_\",\n\t\"sqlite_\",\n]);\n\nconst PORTABLE_BY_TABLE: ReadonlyMap<string, PortableTableSpec> = new Map(\n\tPORTABLE_TABLES.map((spec) => [spec.table, spec]),\n);\n\nconst PORTABLE_BY_KIND: ReadonlyMap<RecordKind, PortableTableSpec> = new Map(\n\tPORTABLE_TABLES.map((spec) => [spec.kind, spec]),\n);\n\nexport function isContentTableName(table: string): boolean {\n\treturn table.startsWith(CONTENT_TABLE_PREFIX);\n}\n\nexport function getPortableTableSpec(table: string): PortableTableSpec | undefined {\n\treturn PORTABLE_BY_TABLE.get(table);\n}\n\n/** The table for a kind; `entry` lives in `ec_*` tables and `principal` in none. */\nexport function getPortableTableSpecForKind(kind: RecordKind): PortableTableSpec | undefined {\n\treturn PORTABLE_BY_KIND.get(kind);\n}\n\nexport type TableClass = \"portable\" | \"content\" | \"nonPortable\" | \"unclassified\";\n\nexport function classifyTable(table: string): TableClass {\n\tif (PORTABLE_BY_TABLE.has(table)) return \"portable\";\n\tif (isContentTableName(table)) return \"content\";\n\tif (Object.hasOwn(NON_PORTABLE_TABLES, table)) return \"nonPortable\";\n\tif (NON_PORTABLE_TABLE_PREFIXES.some((prefix) => table.startsWith(prefix))) return \"nonPortable\";\n\treturn \"unclassified\";\n}\n\n/**\n * Column classification for a table in `db`. For an `ec_*` table the\n * standard columns come from {@link CONTENT_TABLE_COLUMNS} and each column\n * named by a registered field of that collection is a generic `field`\n * (property = field slug, codec from the field's column type).\n */\nexport async function getColumnSpecs(\n\tdb: Kysely<Database>,\n\ttable: string,\n): Promise<Readonly<Record<string, ColumnSpec>>> {\n\tconst spec = PORTABLE_BY_TABLE.get(table);\n\tif (spec) return spec.columns;\n\tif (!isContentTableName(table)) {\n\t\tthrow new TransferError(\"TRANSFER_SCHEMA_UNCLASSIFIED\", \"Table is not portable\", {\n\t\t\tdetail: { table },\n\t\t});\n\t}\n\tconst slug = table.slice(CONTENT_TABLE_PREFIX.length);\n\tvalidateIdentifier(slug, \"collection slug\");\n\tconst fields = await db\n\t\t.selectFrom(\"_emdash_fields\")\n\t\t.innerJoin(\"_emdash_collections\", \"_emdash_collections.id\", \"_emdash_fields.collection_id\")\n\t\t.select([\n\t\t\t\"_emdash_fields.slug as slug\",\n\t\t\t\"_emdash_fields.column_type as column_type\",\n\t\t\t\"_emdash_fields.type as type\",\n\t\t\t\"_emdash_fields.validation as validation\",\n\t\t])\n\t\t.where(\"_emdash_collections.slug\", \"=\", slug)\n\t\t.execute();\n\treturn contentColumnSpecs(fields, await listTableColumns(db, table));\n}\n\n/**\n * Column classification of an `ec_*` table from its collection's registered\n * fields and the table's declared columns (see {@link getColumnSpecs}).\n *\n * A storage-less field's values are content references, not a column. A\n * column left under its slug from before the field was bound is excluded.\n */\nexport function contentColumnSpecs(\n\tfields: ReadonlyArray<{\n\t\tslug: string;\n\t\tcolumn_type: string;\n\t\ttype: string;\n\t\tvalidation: string | null;\n\t}>,\n\ttableColumns: readonly TableColumnInfo[],\n): Readonly<Record<string, ColumnSpec>> {\n\tconst declared = new Map(tableColumns.map((column) => [column.name, column.type.toLowerCase()]));\n\tconst columns: Record<string, ColumnSpec> = { ...CONTENT_TABLE_COLUMNS };\n\tfor (const field of fields) {\n\t\tif (Object.hasOwn(columns, field.slug)) continue;\n\t\tif (isStoragelessFieldRow(field)) {\n\t\t\tcolumns[field.slug] = EXCLUDED;\n\t\t\tcontinue;\n\t\t}\n\t\tlet codec = codecForColumnType(field.column_type);\n\t\tif (codec === \"nativeJson\" && !JSON_COLUMN_TYPES.has(declared.get(field.slug) ?? \"\")) {\n\t\t\tcodec = \"json\";\n\t\t}\n\t\tcolumns[field.slug] = f(field.slug, codec);\n\t}\n\treturn columns;\n}\n\nconst JSON_COLUMN_TYPES: ReadonlySet<string> = new Set([\"json\", \"jsonb\"]);\n\nexport function codecForColumnType(columnType: string): ColumnCodec {\n\tswitch (columnType) {\n\t\tcase \"INTEGER\":\n\t\t\treturn \"integer\";\n\t\tcase \"REAL\":\n\t\t\treturn \"real\";\n\t\tcase \"JSON\":\n\t\t\treturn \"nativeJson\";\n\t\tdefault:\n\t\t\treturn \"text\";\n\t}\n}\n\n/** Columns present in `table` that the registry does not classify. */\nexport async function listUnclassifiedColumns(\n\tdb: Kysely<Database>,\n\ttable: string,\n): Promise<string[]> {\n\tconst specs = await getColumnSpecs(db, table);\n\tconst columns = await listTableColumns(db, table);\n\treturn columns.map((column) => column.name).filter((name) => !Object.hasOwn(specs, name));\n}\n\n/**\n * Throw `TRANSFER_SCHEMA_UNCLASSIFIED` unless every column of `table` is\n * classified. Readers call this before reading a table so an unclassified\n * column is never silently dropped from (or leaked into) a package.\n */\nexport async function assertColumnCoverage(db: Kysely<Database>, table: string): Promise<void> {\n\tassertCoverage(table, await listUnclassifiedColumns(db, table));\n}\n\n/** {@link assertColumnCoverage} for a table whose columns and specs are already loaded. */\nexport function assertLoadedColumnCoverage(\n\ttable: string,\n\tspecs: Readonly<Record<string, ColumnSpec>>,\n\ttableColumns: readonly TableColumnInfo[],\n): void {\n\tassertCoverage(\n\t\ttable,\n\t\ttableColumns.map((column) => column.name).filter((name) => !Object.hasOwn(specs, name)),\n\t);\n}\n\nfunction assertCoverage(table: string, unclassified: readonly string[]): void {\n\tif (unclassified.length > 0) {\n\t\tthrow new TransferError(\n\t\t\t\"TRANSFER_SCHEMA_UNCLASSIFIED\",\n\t\t\t`Table ${table} has columns without a transfer classification`,\n\t\t\t{ detail: { table, columns: unclassified.join(\",\") } },\n\t\t);\n\t}\n}\n","/**\n * The single decoding and encoding path between database column values and\n * record property values. Exporter readers, verification, and importer\n * writers must all go through these functions so a value read on one dialect\n * and written on another round-trips to the same record value.\n *\n * Rules:\n * - SQL `NULL` decodes to `undefined` (the property is omitted) and\n * `undefined`/`null` encode to `NULL`.\n * - `boolean`: 0/1 integers ↔ booleans (any non-zero number decodes to true).\n * - `integer`: numbers, and Postgres `bigint` strings, decode to numbers when\n * they are safe integers. Any other value (non-numeric text a SQLite column\n * may hold) decodes to itself.\n * - `real`: numbers. On Postgres, `real` is float4 and node-pg renders it\n * with float4 precision (`0.1`), which differs from the float4 value itself\n * (`Math.fround(0.1)`). Select REAL columns with {@link selectColumn}, which\n * casts to float8 on Postgres, so the decoded number is exactly the stored\n * float4 value.\n * - `json` (JSON held in a TEXT column): the parsed value; text that is not\n * valid JSON decodes to the text itself. Encoding always writes\n * `JSON.stringify`, so raw text that is not JSON is stored as a JSON\n * string: EmDash parses these columns as JSON when it reads them.\n * - `nativeJson` (a column declared `json`: `ec_*` JSON fields): on\n * Postgres, node-pg returns the parsed value; on SQLite the column has\n * NUMERIC affinity, so numbers come back as numbers and everything else as\n * text decoded like `json`. Encoding on Postgres is always\n * `JSON.stringify`; on SQLite numbers are written as numbers and the rest\n * like `json`.\n * - `text`: strings verbatim.\n * - A JSON `null` decodes like SQL `NULL` (absent): node-pg cannot tell them\n * apart in a `json` column, so neither dialect does. A NOT NULL JSON\n * column can only hold JSON `null` for an absent value, so encoding for\n * one (`notNull`) writes JSON `null`.\n *\n * Invariant: for every value `v` produced by `decodeColumn`,\n * `decodeColumn(encodeColumn(v))` on either dialect yields `v`.\n */\n\nimport { sql, type AliasedRawBuilder, type Kysely } from \"kysely\";\n\nimport { detectDialect, type DatabaseDialectType } from \"../../database/dialect-helpers.js\";\nimport { TransferError } from \"../errors.js\";\nimport type { ColumnCodec, ColumnSpec } from \"./columns.js\";\nimport { CONTENT_TABLE_COLUMNS } from \"./columns.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\ntype DialectSource = DatabaseDialectType | Kysely<any>;\n\nconst SAFE_INTEGER_TEXT = /^-?\\d+$/;\n\nfunction dialectOf(source: DialectSource): DatabaseDialectType {\n\treturn typeof source === \"string\" ? source : detectDialect(source);\n}\n\nfunction tryParseJson(text: string): { ok: true; value: unknown } | { ok: false } {\n\ttry {\n\t\treturn { ok: true, value: JSON.parse(text) };\n\t} catch {\n\t\treturn { ok: false };\n\t}\n}\n\nfunction invalid(codec: ColumnCodec, reason: string): TransferError {\n\treturn new TransferError(\"TRANSFER_RECORD_INVALID\", \"Value cannot be stored in its column\", {\n\t\tdetail: { codec, reason },\n\t});\n}\n\n/** Decode one raw column value. Returns `undefined` for SQL `NULL`. */\nexport function decodeColumn(source: DialectSource, codec: ColumnCodec, raw: unknown): unknown {\n\tif (raw === null || raw === undefined) return undefined;\n\tconst dialect = dialectOf(source);\n\tswitch (codec) {\n\t\tcase \"text\":\n\t\t\treturn raw;\n\t\tcase \"boolean\":\n\t\t\tif (typeof raw === \"number\") return raw !== 0;\n\t\t\tif (typeof raw === \"bigint\") return raw !== 0n;\n\t\t\tif (typeof raw === \"string\" && SAFE_INTEGER_TEXT.test(raw)) return Number(raw) !== 0;\n\t\t\tif (typeof raw === \"boolean\") return raw;\n\t\t\treturn raw;\n\t\tcase \"integer\":\n\t\t\tif (typeof raw === \"bigint\")\n\t\t\t\treturn Number.isSafeInteger(Number(raw)) ? Number(raw) : String(raw);\n\t\t\tif (typeof raw === \"string\" && SAFE_INTEGER_TEXT.test(raw)) {\n\t\t\t\tconst value = Number(raw);\n\t\t\t\treturn Number.isSafeInteger(value) ? value : raw;\n\t\t\t}\n\t\t\treturn raw;\n\t\tcase \"real\":\n\t\t\tif (typeof raw === \"string\" && dialect === \"postgres\") return Number(raw);\n\t\t\treturn raw;\n\t\tcase \"json\":\n\t\t\tif (typeof raw !== \"string\") return raw;\n\t\t\treturn decodeJsonText(raw);\n\t\tcase \"nativeJson\":\n\t\t\tif (dialect === \"postgres\") return raw;\n\t\t\tif (typeof raw !== \"string\") return raw;\n\t\t\treturn decodeJsonText(raw);\n\t}\n}\n\nfunction decodeJsonText(text: string): unknown {\n\tconst parsed = tryParseJson(text);\n\tif (!parsed.ok) return text;\n\treturn parsed.value === null ? undefined : parsed.value;\n}\n\n/**\n * Encode one record value for a column. Returns `null` for an absent value,\n * or JSON `null` when `notNull` is set for a JSON column.\n */\nexport function encodeColumn(\n\tsource: DialectSource,\n\tcodec: ColumnCodec,\n\tvalue: unknown,\n\toptions: { notNull?: boolean } = {},\n): unknown {\n\tif (value === undefined || value === null) {\n\t\treturn options.notNull && (codec === \"json\" || codec === \"nativeJson\") ? \"null\" : null;\n\t}\n\tconst dialect = dialectOf(source);\n\tswitch (codec) {\n\t\tcase \"text\":\n\t\t\tif (typeof value !== \"string\") throw invalid(codec, \"expected a string\");\n\t\t\treturn value;\n\t\tcase \"boolean\":\n\t\t\tif (typeof value !== \"boolean\") throw invalid(codec, \"expected a boolean\");\n\t\t\treturn value ? 1 : 0;\n\t\tcase \"integer\":\n\t\t\tif (typeof value === \"number\") {\n\t\t\t\tif (!Number.isSafeInteger(value)) throw invalid(codec, \"expected an integer\");\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tif (typeof value === \"string\" && dialect === \"sqlite\") return value;\n\t\t\tthrow invalid(codec, \"expected an integer\");\n\t\tcase \"real\":\n\t\t\tif (typeof value === \"number\") {\n\t\t\t\tif (!Number.isFinite(value)) throw invalid(codec, \"expected a finite number\");\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tif (typeof value === \"string\" && dialect === \"sqlite\") return value;\n\t\t\tthrow invalid(codec, \"expected a number\");\n\t\tcase \"json\":\n\t\t\treturn encodeJsonText(value);\n\t\tcase \"nativeJson\":\n\t\t\tif (dialect === \"postgres\") return JSON.stringify(value);\n\t\t\tif (typeof value === \"number\") return value;\n\t\t\treturn encodeJsonText(value);\n\t}\n}\n\nfunction encodeJsonText(value: unknown): string {\n\tconst text = JSON.stringify(value);\n\tif (text === undefined) throw invalid(\"json\", \"value is not JSON\");\n\treturn text;\n}\n\n/**\n * Select expression for a column, aliased to the column name. REAL columns\n * are cast to float8 on Postgres (see the module comment).\n */\nexport function selectColumn(\n\tsource: DialectSource,\n\tcolumn: string,\n\tcodec: ColumnCodec,\n): AliasedRawBuilder<unknown, string> {\n\tif (codec === \"real\" && dialectOf(source) === \"postgres\") {\n\t\treturn sql`${sql.ref(column)}::float8`.as(column);\n\t}\n\treturn sql`${sql.ref(column)}`.as(column);\n}\n\nfunction propertyOf(spec: ColumnSpec): { property: string; codec: ColumnCodec } | null {\n\treturn \"property\" in spec ? { property: spec.property, codec: spec.codec } : null;\n}\n\n/**\n * Select expressions for every exported column of a table (columns whose\n * class has a property), in `specs` order.\n */\nexport function selectExportedColumns(\n\tsource: DialectSource,\n\tspecs: Readonly<Record<string, ColumnSpec>>,\n): AliasedRawBuilder<unknown, string>[] {\n\tconst expressions: AliasedRawBuilder<unknown, string>[] = [];\n\tfor (const [column, spec] of Object.entries(specs)) {\n\t\tconst mapped = propertyOf(spec);\n\t\tif (mapped) expressions.push(selectColumn(source, column, mapped.codec));\n\t}\n\treturn expressions;\n}\n\n/** Decode a row into record properties; NULL columns are omitted. */\nexport function decodeRow(\n\tsource: DialectSource,\n\tspecs: Readonly<Record<string, ColumnSpec>>,\n\trow: Readonly<Record<string, unknown>>,\n): Record<string, unknown> {\n\tconst dialect = dialectOf(source);\n\tconst properties: Record<string, unknown> = {};\n\tfor (const [column, spec] of Object.entries(specs)) {\n\t\tconst mapped = propertyOf(spec);\n\t\tif (!mapped || !Object.hasOwn(row, column)) continue;\n\t\tconst value = decodeColumn(dialect, mapped.codec, row[column]);\n\t\tif (value !== undefined) properties[mapped.property] = value;\n\t}\n\treturn properties;\n}\n\n/**\n * Encode record properties into column values for every exported column of\n * `specs`. Absent properties become `NULL`. Columns of other classes are not\n * included; writers fill those themselves.\n */\nexport function encodeRow(\n\tsource: DialectSource,\n\tspecs: Readonly<Record<string, ColumnSpec>>,\n\tproperties: Readonly<Record<string, unknown>>,\n): Record<string, unknown> {\n\tconst dialect = dialectOf(source);\n\tconst row: Record<string, unknown> = {};\n\tfor (const [column, spec] of Object.entries(specs)) {\n\t\tconst mapped = propertyOf(spec);\n\t\tif (!mapped) continue;\n\t\trow[column] = encodeColumn(\n\t\t\tdialect,\n\t\t\tmapped.codec,\n\t\t\tObject.hasOwn(properties, mapped.property) ? properties[mapped.property] : undefined,\n\t\t);\n\t}\n\treturn row;\n}\n\n/** Whether an `ec_*` column is a field column rather than a standard column. */\nexport function isContentFieldColumn(column: string): boolean {\n\treturn !Object.hasOwn(CONTENT_TABLE_COLUMNS, column);\n}\n\n/**\n * Decode an `ec_*` row into the standard entry properties and the `fields`\n * map (field slug → value). `specs` comes from `getColumnSpecs`.\n */\nexport function decodeContentRow(\n\tsource: DialectSource,\n\tspecs: Readonly<Record<string, ColumnSpec>>,\n\trow: Readonly<Record<string, unknown>>,\n): { properties: Record<string, unknown>; fields: Record<string, unknown> } {\n\tconst standard: Record<string, ColumnSpec> = {};\n\tconst fieldSpecs: Record<string, ColumnSpec> = {};\n\tfor (const [column, spec] of Object.entries(specs)) {\n\t\tif (isContentFieldColumn(column)) fieldSpecs[column] = spec;\n\t\telse standard[column] = spec;\n\t}\n\treturn {\n\t\tproperties: decodeRow(source, standard, row),\n\t\tfields: decodeRow(source, fieldSpecs, row),\n\t};\n}\n\n/** Inverse of {@link decodeContentRow}. */\nexport function encodeContentRow(\n\tsource: DialectSource,\n\tspecs: Readonly<Record<string, ColumnSpec>>,\n\tproperties: Readonly<Record<string, unknown>>,\n\tfields: Readonly<Record<string, unknown>>,\n): Record<string, unknown> {\n\tconst standard: Record<string, ColumnSpec> = {};\n\tconst fieldSpecs: Record<string, ColumnSpec> = {};\n\tfor (const [column, spec] of Object.entries(specs)) {\n\t\tif (isContentFieldColumn(column)) fieldSpecs[column] = spec;\n\t\telse standard[column] = spec;\n\t}\n\treturn { ...encodeRow(source, standard, properties), ...encodeRow(source, fieldSpecs, fields) };\n}\n","/**\n * Record ↔ row helpers for the importer over the shared column codec\n * (`format/column-codec.ts`).\n *\n * Stored rows are compared with the rows the importer meant to write after\n * decoding both sides with the same codec, so dialect differences (Postgres\n * `json` columns returning parsed values, `bigint` strings) do not register as\n * mismatches. Postgres stores REAL columns as float4, so REAL values are\n * compared after `Math.fround` there.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { isPostgres } from \"../../database/dialect-helpers.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { isTransferError, TransferError } from \"../errors.js\";\nimport { canonicalJson } from \"../format/canonical.js\";\nimport { decodeColumn, encodeColumn } from \"../format/column-codec.js\";\nimport type { ColumnCodec, ColumnSpec } from \"../format/columns.js\";\n\nexport type Row = Record<string, unknown>;\n\n/** Codec per column, for the columns a comparison covers. */\nexport type RowCodecs = Readonly<Record<string, ColumnCodec>>;\n\n/** Codecs of the columns a record carries (`field`, `principal`, `mediaRef`). */\nexport function recordCodecs(columns: Readonly<Record<string, ColumnSpec>>): RowCodecs {\n\tconst codecs: Record<string, ColumnCodec> = {};\n\tfor (const [column, spec] of Object.entries(columns)) {\n\t\tif (\"property\" in spec) codecs[column] = spec.codec;\n\t}\n\treturn codecs;\n}\n\n/**\n * The row for `record` over every column the record carries. `record` must\n * already be in target form: placeholders resolved and principals mapped.\n */\nexport function encodeRecord(\n\tdb: Kysely<Database>,\n\tcolumns: Readonly<Record<string, ColumnSpec>>,\n\trecord: Readonly<Record<string, unknown>>,\n\tlocation: { kind: string; id: string },\n): Row {\n\tconst row: Row = {};\n\tfor (const [column, spec] of Object.entries(columns)) {\n\t\tif (!(\"property\" in spec)) continue;\n\t\trow[column] = encodeValue(\n\t\t\tdb,\n\t\t\tspec.codec,\n\t\t\tObject.hasOwn(record, spec.property) ? record[spec.property] : undefined,\n\t\t\t{ ...location, column },\n\t\t);\n\t}\n\treturn row;\n}\n\n/** `encodeColumn`, with the record and column named in a failure. */\nexport function encodeValue(\n\tdb: Kysely<Database>,\n\tcodec: ColumnCodec,\n\tvalue: unknown,\n\tlocation: { kind: string; id: string; column: string },\n\toptions: { notNull?: boolean } = {},\n): unknown {\n\ttry {\n\t\treturn encodeColumn(db, codec, value, options);\n\t} catch (error) {\n\t\tif (!isTransferError(error)) throw error;\n\t\tthrow new TransferError(error.code, \"Record value does not fit its target column\", {\n\t\t\tdetail: { ...location, ...error.detail },\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n\nfunction comparable(\n\tdb: Kysely<Database>,\n\tcodec: ColumnCodec,\n\traw: unknown,\n\toptions: { float4: boolean; encoded: boolean },\n): string | undefined {\n\tconst stored =\n\t\toptions.encoded && codec === \"nativeJson\" && isPostgres(db) && typeof raw === \"string\"\n\t\t\t? JSON.parse(raw)\n\t\t\t: raw;\n\tconst value = decodeColumn(db, codec, stored);\n\tif (value === undefined) return undefined;\n\tif (options.float4 && codec === \"real\" && typeof value === \"number\") {\n\t\treturn canonicalJson(Math.fround(value));\n\t}\n\treturn canonicalJson(value);\n}\n\n/**\n * The first column (in `codecs` order) where the stored row differs from the\n * row the importer encoded, or null when they are equal over those columns.\n * Postgres returns `json` columns parsed, so an encoded `nativeJson` value is\n * parsed before it is compared.\n */\nexport function firstDifference(\n\tdb: Kysely<Database>,\n\tcodecs: RowCodecs,\n\tencoded: Row,\n\tstored: Row,\n\toptions: { float4: boolean },\n): string | null {\n\tfor (const [column, codec] of Object.entries(codecs)) {\n\t\tconst want = comparable(db, codec, encoded[column], { ...options, encoded: true });\n\t\tconst have = comparable(db, codec, stored[column], { ...options, encoded: false });\n\t\tif (want !== have) return column;\n\t}\n\treturn null;\n}\n","/**\n * Parameter-bounded multi-row statements over tables named at runtime.\n *\n * Table and column names come from the column registry or from validated\n * collection and field slugs; every value is a bound parameter. Each\n * statement binds at most `TRANSFER_LIMITS.d1BindParameters` values.\n */\n\nimport { sql, type Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\nimport { chunks } from \"../../utils/chunks.js\";\nimport { rowsPerInsert, TRANSFER_LIMITS } from \"../format/limits.js\";\nimport type { Row } from \"./rows.js\";\n\nconst TABLE_NAME = /^_?[a-z][a-z0-9_]*$/;\n\nfunction tableRef(table: string) {\n\tif (!TABLE_NAME.test(table)) throw new Error(`Invalid table name ${table}`);\n\treturn sql.ref(table);\n}\n\nfunction columnRef(column: string) {\n\tvalidateIdentifier(column, \"column\");\n\treturn sql.ref(column);\n}\n\nexport type ConflictAction =\n\t| { type: \"nothing\" }\n\t/** Upsert on `target`, updating `update` columns from the proposed row. */\n\t| { type: \"update\"; target: readonly string[]; update: readonly string[] };\n\n/**\n * Insert `rows` (all with exactly `columns`) in statements of at most\n * `rowsPerInsert(columns.length)` rows. Returns the number of rows the\n * statements inserted or updated.\n */\nexport async function insertRows(\n\tdb: Kysely<Database>,\n\ttable: string,\n\tcolumns: readonly string[],\n\trows: readonly Row[],\n\tconflict: ConflictAction = { type: \"nothing\" },\n): Promise<number> {\n\tconst perStatement = rowsPerInsert(columns.length);\n\tif (perStatement === 0) throw new Error(`Too many columns for one insert into ${table}`);\n\tconst columnList = sql.join(columns.map(columnRef));\n\tconst onConflict =\n\t\tconflict.type === \"nothing\"\n\t\t\t? sql`ON CONFLICT DO NOTHING`\n\t\t\t: sql`ON CONFLICT (${sql.join(conflict.target.map(columnRef))}) DO UPDATE SET ${sql.join(\n\t\t\t\t\tconflict.update.map(\n\t\t\t\t\t\t(column) => sql`${columnRef(column)} = excluded.${columnRef(column)}`,\n\t\t\t\t\t),\n\t\t\t\t)}`;\n\tlet written = 0;\n\tfor (const batch of chunks([...rows], perStatement)) {\n\t\tconst values = sql.join(\n\t\t\tbatch.map((row) => sql`(${sql.join(columns.map((column) => row[column] ?? null))})`),\n\t\t);\n\t\tconst result =\n\t\t\tawait sql`INSERT INTO ${tableRef(table)} (${columnList}) VALUES ${values} ${onConflict}`.execute(\n\t\t\t\tdb,\n\t\t\t);\n\t\twritten += Number(result.numAffectedRows ?? 0n);\n\t}\n\treturn written;\n}\n\n/** Rows of `table` whose `keyColumns` equal one of `keys`. */\nexport async function selectByKeys(\n\tdb: Kysely<Database>,\n\ttable: string,\n\tkeyColumns: readonly string[],\n\tkeys: readonly Row[],\n): Promise<Row[]> {\n\tconst perStatement = Math.max(\n\t\t1,\n\t\tMath.floor(TRANSFER_LIMITS.d1BindParameters / keyColumns.length),\n\t);\n\tconst result: Row[] = [];\n\tfor (const batch of chunks([...keys], perStatement)) {\n\t\tconst [only] = keyColumns;\n\t\tconst where =\n\t\t\tkeyColumns.length === 1 && only !== undefined\n\t\t\t\t? sql`${columnRef(only)} IN (${sql.join(batch.map((key) => key[only] ?? null))})`\n\t\t\t\t: sql.join(\n\t\t\t\t\t\tbatch.map(\n\t\t\t\t\t\t\t(key) =>\n\t\t\t\t\t\t\t\tsql`(${sql.join(\n\t\t\t\t\t\t\t\t\tkeyColumns.map((column) => sql`${columnRef(column)} = ${key[column] ?? null}`),\n\t\t\t\t\t\t\t\t\tsql` AND `,\n\t\t\t\t\t\t\t\t)})`,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tsql` OR `,\n\t\t\t\t\t);\n\t\tconst rows = await sql<Row>`SELECT * FROM ${tableRef(table)} WHERE ${where}`.execute(db);\n\t\tresult.push(...rows.rows);\n\t}\n\treturn result;\n}\n\n/**\n * Set `columns` of the row whose `keyColumn` equals `key`, in statements of\n * at most `d1BindParameters - 1` columns.\n */\nexport async function updateColumns(\n\tdb: Kysely<Database>,\n\ttable: string,\n\tkeyColumn: string,\n\tkey: string,\n\trow: Row,\n\tcolumns: readonly string[],\n): Promise<number> {\n\tlet statements = 0;\n\tfor (const batch of chunks([...columns], TRANSFER_LIMITS.d1BindParameters - 1)) {\n\t\tconst assignments = sql.join(\n\t\t\tbatch.map((column) => sql`${columnRef(column)} = ${row[column] ?? null}`),\n\t\t);\n\t\tawait sql`UPDATE ${tableRef(table)} SET ${assignments} WHERE ${columnRef(keyColumn)} = ${key}`.execute(\n\t\t\tdb,\n\t\t);\n\t\tstatements++;\n\t}\n\treturn statements;\n}\n\n/** Statements `insertRows` + `selectByKeys` need for `count` rows. */\nexport function estimateStatements(count: number, columns: number, keyColumns = 1): number {\n\tconst perInsert = Math.max(1, rowsPerInsert(columns));\n\tconst perSelect = Math.max(1, Math.floor(TRANSFER_LIMITS.d1BindParameters / keyColumns));\n\treturn Math.ceil(count / perInsert) + Math.ceil(count / perSelect);\n}\n","import type {\n\tColumnDataType,\n\tCreateTableBuilder,\n\tInsertable,\n\tKysely,\n\tSelectable,\n\tUpdateable,\n} from \"kysely\";\nimport { sql } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { refreshDevTypes } from \"../astro/dev-typegen.js\";\nimport {\n\tcolumnExists,\n\tcurrentTimestamp,\n\tisPostgres,\n\tlistTablesLike,\n\ttableExists,\n} from \"../database/dialect-helpers.js\";\nimport { withTransaction } from \"../database/transaction.js\";\nimport type { CollectionTable, Database, FieldTable } from \"../database/types.js\";\nimport { validateIdentifier } from \"../database/validate.js\";\nimport {\n\tcanResumeMediaUsageCollectionCapture,\n\tfinalizeMediaUsageCollectionCapture,\n\tinstallPreparedMediaUsageCollectionCapture,\n\tmarkMediaUsageCollectionCaptureReady,\n\tprepareMediaUsageCollectionCapture,\n} from \"../media/usage/activation.js\";\nimport {\n\tdeleteActivatedMediaUsageCollection,\n\tisMediaUsageCollectionSlugDeleting,\n} from \"../media/usage/collection-deletion.js\";\nimport {\n\tdeleteContentMediaUsageCollection,\n\tinvalidateContentMediaUsageSchemaChange,\n\tmarkContentMediaUsageCollectionStaleSafely,\n} from \"../media/usage/content-refresh.js\";\nimport { FTSManager } from \"../search/fts-manager.js\";\nimport { getPortableTableSpec } from \"../transfer/format/columns.js\";\nimport { canonicalDigest } from \"../transfer/format/digest.js\";\nimport type { CollectionRecord, FieldRecord } from \"../transfer/format/kinds.js\";\nimport { encodeRecord, firstDifference, recordCodecs } from \"../transfer/import/rows.js\";\nimport { insertRows } from \"../transfer/import/sql.js\";\nimport type {\n\tImportCollectionOptions,\n\tImportCollectionResult,\n} from \"../transfer/schema-importer.js\";\nimport { chunks, SQL_BATCH_SIZE } from \"../utils/chunks.js\";\nimport { resetRegisteredCollectionsCache } from \"./collection-slugs-cache.js\";\nimport {\n\ttype Collection,\n\ttype CollectionAdminConfig,\n\ttype CollectionSource,\n\ttype CollectionSupport,\n\ttype ColumnType,\n\ttype Field,\n\ttype FieldValidation,\n\ttype UnsupportedFieldType,\n\ttype CreateCollectionInput,\n\ttype UpdateCollectionInput,\n\ttype CreateFieldInput,\n\ttype UpdateFieldInput,\n\ttype CollectionWithFields,\n\ttype FieldType,\n\tFIELD_TYPE_TO_COLUMN,\n\tREPEATER_SUB_FIELD_TYPES,\n\tisIndexableFieldType,\n\tisStoragelessField,\n\tRESERVED_FIELD_SLUGS,\n\tRESERVED_COLLECTION_SLUGS,\n\tMAX_BLOCKS_ITEMS,\n} from \"./types.js\";\n\n// Regex patterns for schema registry\nconst SLUG_VALIDATION_PATTERN = /^[a-z][a-z0-9_]*$/;\nconst EC_PREFIX_PATTERN = /^ec_/;\nconst SINGLE_QUOTE_PATTERN = /'/g;\nconst UNDERSCORE_PATTERN = /_/g;\nconst WORD_BOUNDARY_PATTERN = /\\b\\w/g;\nconst FIELD_ID_PATTERN = /^[0-9A-Z]{26}$/;\n\n/** Valid column types for runtime validation */\nconst COLUMN_TYPES: ReadonlySet<string> = new Set([\"TEXT\", \"REAL\", \"INTEGER\", \"JSON\"]);\nconst COLUMN_TYPE_TO_DATA_TYPE = {\n\tTEXT: \"text\",\n\tREAL: \"real\",\n\tINTEGER: \"integer\",\n\tJSON: \"json\",\n} satisfies Record<ColumnType, ColumnDataType>;\nconst TEXT_ALIAS_FIELD_TYPES: ReadonlySet<FieldType> = new Set([\"string\", \"text\", \"slug\"]);\n\n/** Field types usable as a `titleField` — plain text that reads well as a title. */\nconst TITLE_FIELD_TYPES: ReadonlySet<string> = new Set([\"string\", \"text\", \"slug\"]);\n\n/** Valid collection source prefixes/values */\nconst VALID_SOURCES: ReadonlySet<string> = new Set([\"manual\", \"discovered\", \"seed\"]);\n\nfunction isCollectionSource(value: string): value is CollectionSource {\n\treturn VALID_SOURCES.has(value) || value.startsWith(\"template:\") || value.startsWith(\"import:\");\n}\n\nfunction isFieldType(value: string): value is FieldType {\n\treturn value in FIELD_TYPE_TO_COLUMN;\n}\n\nfunction isColumnType(value: string): value is ColumnType {\n\treturn COLUMN_TYPES.has(value);\n}\n\nconst REPEATER_SUB_FIELD_TYPE_SET: ReadonlySet<string> = new Set(REPEATER_SUB_FIELD_TYPES);\n\nfunction findUnsupportedRepeaterSubFieldType(\n\tvalidation: unknown,\n): UnsupportedFieldType | undefined {\n\tif (!validation || typeof validation !== \"object\") return undefined;\n\tconst subFields = \"subFields\" in validation ? validation.subFields : undefined;\n\tif (!Array.isArray(subFields)) return undefined;\n\n\tfor (const [index, subField] of subFields.entries()) {\n\t\tif (!subField || typeof subField !== \"object\") continue;\n\t\tconst type = \"type\" in subField ? subField.type : undefined;\n\t\tif (typeof type === \"string\" && !REPEATER_SUB_FIELD_TYPE_SET.has(type)) {\n\t\t\treturn { type, path: `validation.subFields[${index}].type` };\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nconst VALID_COLLECTION_SUPPORTS: ReadonlySet<string> = new Set<CollectionSupport>([\n\t\"drafts\",\n\t\"revisions\",\n\t\"preview\",\n\t\"scheduling\",\n\t\"search\",\n\t\"seo\",\n]);\n\n// Each _emdash_fields row uses 16 bound parameters. Six rows keep every\n// multi-row INSERT below D1's 100-parameter statement limit.\nconst SEED_FIELD_INSERT_BATCH_SIZE = 6;\n\n/**\n * Rank given to collections without an explicit `sort_order`. SQLite sorts\n * NULL first on ASC while Postgres sorts it last, so the fallback is\n * materialised with COALESCE rather than left to the dialect.\n */\nconst UNORDERED_COLLECTION_RANK = 2147483647;\n\n/**\n * Collection ordering shared by every list read: explicit `sort_order`\n * first (ascending), then alphabetically by slug.\n */\nconst collectionOrder = sql<number>`coalesce(sort_order, ${sql.lit(UNORDERED_COLLECTION_RANK)})`;\n\nfunction assertIndexableField(\n\tfield: { type: FieldType; validation?: FieldValidation | null },\n\tindexed: boolean | undefined,\n\tslug: string,\n): void {\n\tif (!indexed) return;\n\tif (!isIndexableFieldType(field.type)) {\n\t\tthrow new SchemaError(\n\t\t\t`Field \"${slug}\" cannot be indexed because type \"${field.type}\" is not a scalar query type`,\n\t\t\t\"FIELD_NOT_INDEXABLE\",\n\t\t);\n\t}\n\tif (isStoragelessField(field)) {\n\t\tthrow new SchemaError(\n\t\t\t`Field \"${slug}\" cannot be indexed because it stores no column to index`,\n\t\t\t\"FIELD_NOT_INDEXABLE\",\n\t\t);\n\t}\n}\n\n/** A field record's `validation`, which the package carries as any JSON value. */\nfunction importFieldValidation(value: unknown): FieldValidation | undefined {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\treturn value;\n}\n\nfunction isCollectionSupport(value: unknown): value is CollectionSupport {\n\treturn typeof value === \"string\" && VALID_COLLECTION_SUPPORTS.has(value);\n}\n\n/**\n * Parse a collection's `supports` column (stored as a JSON array of\n * CollectionSupport keys). Unknown/invalid entries are filtered out so the\n * runtime value matches the declared `CollectionSupport[]` type.\n *\n * Throws on malformed JSON so corruption surfaces loudly; returns an empty\n * array only for explicitly null/empty values or non-array JSON.\n */\nfunction parseSupports(raw: string | null | undefined): CollectionSupport[] {\n\tif (!raw) return [];\n\tconst parsed: unknown = JSON.parse(raw);\n\tif (!Array.isArray(parsed)) return [];\n\treturn parsed.filter(isCollectionSupport);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseCollectionAdmin(raw: string | null | undefined): CollectionAdminConfig | undefined {\n\tif (!raw) return undefined;\n\tconst parsed: unknown = JSON.parse(raw);\n\tif (!isRecord(parsed)) return undefined;\n\tconst listColumns = parsed.listColumns;\n\treturn {\n\t\tlistColumns: Array.isArray(listColumns)\n\t\t\t? listColumns.filter((value): value is string => typeof value === \"string\")\n\t\t\t: undefined,\n\t};\n}\n\nexport async function buildSeedCollectionCaptureFingerprint(\n\tinput: Omit<CreateCollectionInput, \"source\">,\n\tfields: readonly CreateFieldInput[],\n): Promise<string> {\n\tconst supports = input.supports ?? [\"drafts\", \"revisions\"];\n\tconst hasSeo = input.hasSeo ?? supports.includes(\"seo\") ?? false;\n\tlet maxSortOrder = -1;\n\tconst definitions = fields.map((field) => {\n\t\tconst sortOrder = field.sortOrder ?? maxSortOrder + 1;\n\t\tmaxSortOrder = Math.max(maxSortOrder, sortOrder);\n\t\treturn {\n\t\t\tslug: field.slug,\n\t\t\tlabel: field.label,\n\t\t\ttype: field.type,\n\t\t\trequired: field.required ?? false,\n\t\t\tunique: field.unique ?? false,\n\t\t\tdefaultValue: field.defaultValue === undefined ? null : JSON.stringify(field.defaultValue),\n\t\t\tvalidation: field.validation ? JSON.stringify(field.validation) : null,\n\t\t\twidget: field.widget ?? null,\n\t\t\toptions: field.options ? JSON.stringify(field.options) : null,\n\t\t\tsortOrder,\n\t\t\tsearchable: field.searchable ?? false,\n\t\t\ttranslatable: field.translatable ?? true,\n\t\t};\n\t});\n\tconst payload = JSON.stringify(\n\t\tcanonicalizeFingerprintValue({\n\t\t\tversion: 1,\n\t\t\tcollection: {\n\t\t\t\tslug: input.slug,\n\t\t\t\tlabel: input.label,\n\t\t\t\tlabelSingular: input.labelSingular ?? null,\n\t\t\t\tdescription: input.description ?? null,\n\t\t\t\ticon: input.icon ?? null,\n\t\t\t\tadmin: input.admin ?? null,\n\t\t\t\tsupports,\n\t\t\t\thasSeo,\n\t\t\t\thidden: input.hidden ?? false,\n\t\t\t\tsortOrder: input.sortOrder ?? null,\n\t\t\t\t...(input.group ? { group: input.group } : {}),\n\t\t\t\tcommentsEnabled: input.commentsEnabled ?? false,\n\t\t\t\t...(input.editLocking === false ? { editLocking: false } : {}),\n\t\t\t\turlPattern: input.urlPattern ?? null,\n\t\t\t\troutable: input.routable ?? true,\n\t\t\t},\n\t\t\tfields: definitions,\n\t\t}),\n\t);\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(payload));\n\tconst hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\n\t\t\"\",\n\t);\n\treturn `media-usage-seed:v1:sha256:${hex}`;\n}\n\nfunction canonicalizeFingerprintValue(value: unknown): unknown {\n\tif (value === undefined) return { __emdashUndefined: true };\n\tif (Array.isArray(value)) return value.map(canonicalizeFingerprintValue);\n\tif (typeof value !== \"object\" || value === null) return value;\n\n\tconst canonical: Record<string, unknown> = {};\n\tfor (const [key, entry] of Object.entries(value).toSorted(([a], [b]) => a.localeCompare(b))) {\n\t\tcanonical[key] = canonicalizeFingerprintValue(entry);\n\t}\n\treturn canonical;\n}\n\n/**\n * Media-usage capture fingerprint for an imported collection, so an\n * interrupted import resumes only the capture lifecycle it started.\n */\nasync function importCaptureFingerprint(\n\trecord: CollectionRecord,\n\tfields: readonly FieldRecord[],\n): Promise<string> {\n\treturn `media-usage-import:v1:${await canonicalDigest({ collection: record, fields })}`;\n}\n\n/** Search stays disabled until the import's rebuild stage builds the index. */\nfunction importSearchConfig(config: CollectionRecord[\"searchConfig\"]): string | null {\n\tif (config === undefined) return null;\n\tif (isRecord(config) && config.enabled === true) {\n\t\treturn JSON.stringify({ ...config, enabled: false });\n\t}\n\treturn JSON.stringify(config);\n}\n\n/**\n * Error thrown when a schema operation fails\n */\nexport class SchemaError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic code: string,\n\t\tpublic details?: Record<string, unknown>,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"SchemaError\";\n\t}\n}\n\n/**\n * Schema Registry\n *\n * Manages collection and field definitions stored in D1.\n * Handles runtime DDL operations (CREATE TABLE, ALTER TABLE).\n */\nexport class SchemaRegistry {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t/**\n\t * Notify the dev typegen hook that the schema has changed.\n\t */\n\tprivate notifyTypegen(): void {\n\t\trefreshDevTypes(this.db);\n\t}\n\n\t// ============================================\n\t// Collection Operations\n\t// ============================================\n\n\t/**\n\t * List all collections\n\t */\n\tasync listCollections(): Promise<Collection[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(collectionOrder, \"asc\")\n\t\t\t.orderBy(\"slug\", \"asc\")\n\t\t\t.execute();\n\n\t\treturn rows.map(this.mapCollectionRow);\n\t}\n\n\t/**\n\t * Get a collection by slug\n\t */\n\tasync getCollection(slug: string): Promise<Collection | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.where(\"slug\", \"=\", slug)\n\t\t\t.selectAll()\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? this.mapCollectionRow(row) : null;\n\t}\n\n\t/**\n\t * Get a collection with all its fields\n\t */\n\tasync getCollectionWithFields(slug: string): Promise<CollectionWithFields | null> {\n\t\tconst collection = await this.getCollection(slug);\n\t\tif (!collection) return null;\n\n\t\tconst fields = await this.listFields(collection.id);\n\n\t\treturn { ...collection, fields };\n\t}\n\n\t/**\n\t * List every collection together with its fields in O(1) query shapes\n\t * — one for collections, then one batched query for the fields of every\n\t * returned collection — instead of the N+1 pattern of `listCollections`\n\t * + per-collection `listFields`. The fields query is chunked at\n\t * `SQL_BATCH_SIZE` to stay under D1's bound-parameter limit, so on\n\t * sites with more than `SQL_BATCH_SIZE` collections the field fetch\n\t * becomes `ceil(collectionCount / SQL_BATCH_SIZE)` queries — still\n\t * a constant factor, not N+1. Typical sites have well under\n\t * `SQL_BATCH_SIZE` collections, so this is two queries in practice.\n\t *\n\t * Used by the manifest build, which previously paid N+1 round-trips on\n\t * every admin request. Each round-trip costs ~80–150ms against the D1\n\t * primary on a busy link, so a 10-collection site spent ~1 s rebuilding\n\t * a manifest that is now built fresh per admin request (no cache).\n\t */\n\tasync listCollectionsWithFields(): Promise<CollectionWithFields[]> {\n\t\tconst collectionRows = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(collectionOrder, \"asc\")\n\t\t\t.orderBy(\"slug\", \"asc\")\n\t\t\t.execute();\n\n\t\tif (collectionRows.length === 0) return [];\n\n\t\tconst fieldsByCollection = new Map<string, Field[]>();\n\t\t// Chunk to stay under D1's bound-parameter limit. Typical sites have\n\t\t// well under SQL_BATCH_SIZE collections, so this is a single query\n\t\t// in practice; on larger sites it becomes a small constant number\n\t\t// of queries, never N+1.\n\t\tfor (const idChunk of chunks(\n\t\t\tcollectionRows.map((c) => c.id),\n\t\t\tSQL_BATCH_SIZE,\n\t\t)) {\n\t\t\tconst fieldRows = await this.db\n\t\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t\t.where(\"collection_id\", \"in\", idChunk)\n\t\t\t\t.selectAll()\n\t\t\t\t.orderBy(\"collection_id\", \"asc\")\n\t\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t\t.orderBy(\"created_at\", \"asc\")\n\t\t\t\t.execute();\n\t\t\tfor (const row of fieldRows) {\n\t\t\t\tconst list = fieldsByCollection.get(row.collection_id) ?? [];\n\t\t\t\tlist.push(this.mapFieldRow(row));\n\t\t\t\tfieldsByCollection.set(row.collection_id, list);\n\t\t\t}\n\t\t}\n\n\t\treturn collectionRows.map((c) => ({\n\t\t\t...this.mapCollectionRow(c),\n\t\t\tfields: fieldsByCollection.get(c.id) ?? [],\n\t\t}));\n\t}\n\n\t/**\n\t * Validate `titleField`/`dateField` against the collection's fields:\n\t * `titleField` must be a text-like field; `dateField` must be a `datetime` field.\n\t * Only truthy values are checked (undefined = unchanged, null/\"\" = cleared).\n\t */\n\tprivate async validateTitleDateFields(\n\t\tcollectionId: string,\n\t\tcollectionSlug: string,\n\t\tinput: { titleField?: string | null; dateField?: string | null },\n\t\tdb: Kysely<Database> = this.db,\n\t): Promise<void> {\n\t\tconst slugs = [input.titleField, input.dateField].filter((slug): slug is string => !!slug);\n\t\tif (slugs.length === 0) return;\n\n\t\tconst rows = await db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.where(\"slug\", \"in\", slugs)\n\t\t\t.select([\"slug\", \"type\"])\n\t\t\t.execute();\n\t\tconst typeBySlug = new Map(rows.map((row) => [row.slug, row.type]));\n\n\t\tif (input.titleField) {\n\t\t\tconst type = typeBySlug.get(input.titleField);\n\t\t\tif (type === undefined) {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`titleField \"${input.titleField}\" is not a field on \"${collectionSlug}\"`,\n\t\t\t\t\t\"INVALID_TITLE_FIELD\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!TITLE_FIELD_TYPES.has(type)) {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`titleField \"${input.titleField}\" must be a text field (got \"${type}\")`,\n\t\t\t\t\t\"INVALID_TITLE_FIELD\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (input.dateField) {\n\t\t\tconst type = typeBySlug.get(input.dateField);\n\t\t\tif (type === undefined) {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`dateField \"${input.dateField}\" is not a field on \"${collectionSlug}\"`,\n\t\t\t\t\t\"INVALID_DATE_FIELD\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (type !== \"datetime\") {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`dateField \"${input.dateField}\" must be a datetime field (got \"${type}\")`,\n\t\t\t\t\t\"INVALID_DATE_FIELD\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Create a new collection\n\t */\n\tasync createCollection(input: CreateCollectionInput): Promise<Collection> {\n\t\t// Validate slug\n\t\tthis.validateSlug(input.slug, \"collection\");\n\t\tif (RESERVED_COLLECTION_SLUGS.includes(input.slug)) {\n\t\t\tthrow new SchemaError(`Collection slug \"${input.slug}\" is reserved`, \"RESERVED_SLUG\");\n\t\t}\n\t\tif (await isMediaUsageCollectionSlugDeleting(this.db, input.slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${input.slug}\" already exists`, \"COLLECTION_EXISTS\");\n\t\t}\n\n\t\t// Check if collection already exists\n\t\tconst existing = await this.getCollection(input.slug);\n\t\tif (await isMediaUsageCollectionSlugDeleting(this.db, input.slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${input.slug}\" already exists`, \"COLLECTION_EXISTS\");\n\t\t}\n\t\tif (\n\t\t\texisting &&\n\t\t\t!(await canResumeMediaUsageCollectionCapture(this.db, {\n\t\t\t\tcollectionId: existing.id,\n\t\t\t\tcollectionSlug: existing.slug,\n\t\t\t}))\n\t\t) {\n\t\t\tthrow new SchemaError(`Collection \"${input.slug}\" already exists`, \"COLLECTION_EXISTS\");\n\t\t}\n\n\t\tconst proposedId = existing?.id ?? ulid();\n\n\t\t// Default `supports` to drafts + revisions when the caller didn't\n\t\t// specify it. Explicit empty array (`[]`) is preserved as an opt-out\n\t\t// — only `undefined` triggers the default. This is the canonical\n\t\t// default for new collections; the MCP and admin UI layers used to\n\t\t// duplicate this default but now defer to the registry.\n\t\tconst supports = input.supports ?? [\"drafts\", \"revisions\"];\n\n\t\t// Insert collection record and create content table in a transaction\n\t\t// so a failure in table creation doesn't leave an orphaned row.\n\t\t// Uses withTransaction for D1 compatibility (no transaction support).\n\t\t// Derive hasSeo from supports array if not explicitly set\n\t\tconst hasSeo = input.hasSeo ?? supports.includes(\"seo\") ?? false;\n\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tconst capture = await prepareMediaUsageCollectionCapture(trx, {\n\t\t\t\tcollectionId: proposedId,\n\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\tregisteredCollectionId: existing?.id,\n\t\t\t});\n\t\t\tconst values: Insertable<CollectionTable> = {\n\t\t\t\tid: capture.collectionId,\n\t\t\t\tslug: input.slug,\n\t\t\t\tlabel: input.label,\n\t\t\t\tlabel_singular: input.labelSingular ?? null,\n\t\t\t\tdescription: input.description ?? null,\n\t\t\t\ticon: input.icon ?? null,\n\t\t\t\tadmin_config: input.admin ? JSON.stringify(input.admin) : null,\n\t\t\t\tsupports: JSON.stringify(supports),\n\t\t\t\tsource: input.source ?? \"manual\",\n\t\t\t\thas_seo: hasSeo ? 1 : 0,\n\t\t\t\troutable: input.routable === false ? 0 : 1,\n\t\t\t\thidden: input.hidden ? 1 : 0,\n\t\t\t\tsort_order: input.sortOrder ?? null,\n\t\t\t\tnav_group: input.group?.trim() || null,\n\t\t\t\tcomments_enabled: input.commentsEnabled ? 1 : 0,\n\t\t\t\tedit_locking: input.editLocking === false ? 0 : 1,\n\t\t\t\turl_pattern: input.urlPattern ?? null,\n\t\t\t};\n\n\t\t\tif (capture.captureRequired) {\n\t\t\t\tawait this.createContentTable(input.slug, trx, [], {\n\t\t\t\t\tifNotExists: capture.resuming,\n\t\t\t\t});\n\t\t\t\tawait installPreparedMediaUsageCollectionCapture(trx, {\n\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\t});\n\t\t\t\tawait markMediaUsageCollectionCaptureReady(trx, {\n\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\t});\n\t\t\t\tif (!capture.registrationExists) {\n\t\t\t\t\tawait trx.insertInto(\"_emdash_collections\").values(values).execute();\n\t\t\t\t}\n\t\t\t\tawait finalizeMediaUsageCollectionCapture(trx, {\n\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait trx.insertInto(\"_emdash_collections\").values(values).execute();\n\t\t\tawait this.createContentTable(input.slug, trx);\n\t\t});\n\n\t\tconst collection = await this.getCollection(input.slug);\n\t\tif (!collection) {\n\t\t\tthrow new SchemaError(\"Failed to create collection\", \"CREATE_FAILED\");\n\t\t}\n\n\t\tresetRegisteredCollectionsCache();\n\t\tthis.notifyTypegen();\n\t\treturn collection;\n\t}\n\n\t/**\n\t * Create a seed-owned collection and all of its fields in bulk.\n\t *\n\t * Fresh seeds can define dozens of fields. Creating them through\n\t * `createField` performs multiple reads, one ALTER TABLE, and one media\n\t * usage invalidation per field, which can exhaust D1's per-request query\n\t * budget. This path validates the full schema before mutating it, creates\n\t * the complete content table in one statement, and inserts field metadata\n\t * in parameter-safe batches.\n\t */\n\tasync createSeedCollection(\n\t\tinput: Omit<CreateCollectionInput, \"source\">,\n\t\tfields: readonly CreateFieldInput[],\n\t): Promise<void> {\n\t\tthis.validateSlug(input.slug, \"collection\");\n\t\tif (RESERVED_COLLECTION_SLUGS.includes(input.slug)) {\n\t\t\tthrow new SchemaError(`Collection slug \"${input.slug}\" is reserved`, \"RESERVED_SLUG\");\n\t\t}\n\t\tif (await isMediaUsageCollectionSlugDeleting(this.db, input.slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${input.slug}\" already exists`, \"COLLECTION_EXISTS\");\n\t\t}\n\n\t\tconst fieldSlugs = new Set<string>();\n\t\tconst normalizedFields: CreateFieldInput[] = [];\n\t\tfor (const field of fields) {\n\t\t\tthis.validateSlug(field.slug, \"field\");\n\t\t\tassertIndexableField(field, field.indexed, field.slug);\n\t\t\tif (RESERVED_FIELD_SLUGS.includes(field.slug)) {\n\t\t\t\tthrow new SchemaError(`Field slug \"${field.slug}\" is reserved`, \"RESERVED_SLUG\");\n\t\t\t}\n\t\t\tif (fieldSlugs.has(field.slug)) {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`Field \"${field.slug}\" already exists in collection \"${input.slug}\"`,\n\t\t\t\t\t\"FIELD_EXISTS\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tfieldSlugs.add(field.slug);\n\t\t\tnormalizedFields.push(\n\t\t\t\tfield.type === \"blocks\"\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...field,\n\t\t\t\t\t\t\t// oxlint-disable-next-line no-await-in-loop -- every block definition must resolve before seed mutation starts\n\t\t\t\t\t\t\tvalidation: await this.normalizeBlocksFieldValidation(\n\t\t\t\t\t\t\t\tinput.slug,\n\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tthis.db,\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: { ...field },\n\t\t\t);\n\t\t}\n\n\t\tconst supports = input.supports ?? [\"drafts\", \"revisions\"];\n\t\tconst hasSeo = input.hasSeo ?? supports.includes(\"seo\") ?? false;\n\t\tconst creationFingerprint = await buildSeedCollectionCaptureFingerprint(\n\t\t\tinput,\n\t\t\tnormalizedFields,\n\t\t);\n\t\tconst existing = await this.getCollection(input.slug);\n\t\tif (await isMediaUsageCollectionSlugDeleting(this.db, input.slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${input.slug}\" already exists`, \"COLLECTION_EXISTS\");\n\t\t}\n\t\tif (\n\t\t\texisting &&\n\t\t\t!(await canResumeMediaUsageCollectionCapture(this.db, {\n\t\t\t\tcollectionId: existing.id,\n\t\t\t\tcollectionSlug: existing.slug,\n\t\t\t\tcreationFingerprint,\n\t\t\t}))\n\t\t) {\n\t\t\tthrow new SchemaError(`Collection \"${input.slug}\" already exists`, \"COLLECTION_EXISTS\");\n\t\t}\n\n\t\tconst proposedCollectionId = existing?.id ?? ulid();\n\t\tlet maxSortOrder = -1;\n\t\tconst fieldRows: Insertable<FieldTable>[] = normalizedFields.map((field) => {\n\t\t\tconst sortOrder = field.sortOrder ?? maxSortOrder + 1;\n\t\t\tmaxSortOrder = Math.max(maxSortOrder, sortOrder);\n\n\t\t\treturn {\n\t\t\t\tid: ulid(),\n\t\t\t\tcollection_id: proposedCollectionId,\n\t\t\t\tslug: field.slug,\n\t\t\t\tlabel: field.label,\n\t\t\t\ttype: field.type,\n\t\t\t\tcolumn_type: FIELD_TYPE_TO_COLUMN[field.type],\n\t\t\t\trequired: field.required ? 1 : 0,\n\t\t\t\tunique: field.unique ? 1 : 0,\n\t\t\t\tdefault_value: field.defaultValue !== undefined ? JSON.stringify(field.defaultValue) : null,\n\t\t\t\tvalidation: field.validation ? JSON.stringify(field.validation) : null,\n\t\t\t\twidget: field.widget ?? null,\n\t\t\t\toptions: field.options ? JSON.stringify(field.options) : null,\n\t\t\t\tsort_order: sortOrder,\n\t\t\t\tsearchable: field.searchable ? 1 : 0,\n\t\t\t\tindexed: field.indexed ? 1 : 0,\n\t\t\t\ttranslatable: field.translatable === false ? 0 : 1,\n\t\t\t};\n\t\t});\n\n\t\tlet schemaMutated = false;\n\t\ttry {\n\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\tconst capture = await prepareMediaUsageCollectionCapture(trx, {\n\t\t\t\t\tcollectionId: proposedCollectionId,\n\t\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\t\tcreationFingerprint,\n\t\t\t\t\tregisteredCollectionId: existing?.id,\n\t\t\t\t});\n\t\t\t\tconst collectionValues: Insertable<CollectionTable> = {\n\t\t\t\t\tid: capture.collectionId,\n\t\t\t\t\tslug: input.slug,\n\t\t\t\t\tlabel: input.label,\n\t\t\t\t\tlabel_singular: input.labelSingular ?? null,\n\t\t\t\t\tdescription: input.description ?? null,\n\t\t\t\t\ticon: input.icon ?? null,\n\t\t\t\t\tadmin_config: input.admin ? JSON.stringify(input.admin) : null,\n\t\t\t\t\tsupports: JSON.stringify(supports),\n\t\t\t\t\tsource: \"seed\",\n\t\t\t\t\thas_seo: hasSeo ? 1 : 0,\n\t\t\t\t\troutable: input.routable === false ? 0 : 1,\n\t\t\t\t\thidden: input.hidden ? 1 : 0,\n\t\t\t\t\tsort_order: input.sortOrder ?? null,\n\t\t\t\t\tnav_group: input.group?.trim() || null,\n\t\t\t\t\tcomments_enabled: input.commentsEnabled ? 1 : 0,\n\t\t\t\t\tedit_locking: input.editLocking === false ? 0 : 1,\n\t\t\t\t\turl_pattern: input.urlPattern ?? null,\n\t\t\t\t};\n\t\t\t\tconst rows = fieldRows.map((row) => ({\n\t\t\t\t\t...row,\n\t\t\t\t\tcollection_id: capture.collectionId,\n\t\t\t\t}));\n\n\t\t\t\tif (capture.captureRequired) {\n\t\t\t\t\tawait this.createContentTable(input.slug, trx, normalizedFields, {\n\t\t\t\t\t\tifNotExists: capture.resuming,\n\t\t\t\t\t});\n\t\t\t\t\tawait installPreparedMediaUsageCollectionCapture(trx, {\n\t\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\t\t});\n\t\t\t\t\tawait markMediaUsageCollectionCaptureReady(trx, {\n\t\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\t\t});\n\t\t\t\t\tif (!capture.registrationExists) {\n\t\t\t\t\t\tawait trx.insertInto(\"_emdash_collections\").values(collectionValues).execute();\n\t\t\t\t\t\tschemaMutated = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tawait trx.insertInto(\"_emdash_collections\").values(collectionValues).execute();\n\t\t\t\t\tschemaMutated = true;\n\t\t\t\t\tawait this.createContentTable(input.slug, trx, normalizedFields);\n\t\t\t\t}\n\n\t\t\t\tfor (const fieldBatch of chunks(rows, SEED_FIELD_INSERT_BATCH_SIZE)) {\n\t\t\t\t\tlet insert = trx.insertInto(\"_emdash_fields\").values(fieldBatch);\n\t\t\t\t\tif (capture.resuming) {\n\t\t\t\t\t\tinsert = insert.onConflict((conflict) =>\n\t\t\t\t\t\t\tconflict.columns([\"collection_id\", \"slug\"]).doNothing(),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait insert.execute();\n\t\t\t\t}\n\t\t\t\tlet indexedRows: readonly { id: string; slug: string; indexed?: number }[] = rows;\n\t\t\t\tif (capture.resuming) {\n\t\t\t\t\tindexedRows = await this.assertSeedFieldDefinitions(\n\t\t\t\t\t\tcapture.collectionId,\n\t\t\t\t\t\tnormalizedFields,\n\t\t\t\t\t\ttrx,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tfor (const field of indexedRows) {\n\t\t\t\t\tif (field.indexed === 1) {\n\t\t\t\t\t\tawait this.createFieldIndex(input.slug, field.id, field.slug, trx);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (capture.captureRequired) {\n\t\t\t\t\tawait finalizeMediaUsageCollectionCapture(trx, {\n\t\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\t\tcollectionSlug: input.slug,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tawait markContentMediaUsageCollectionStaleSafely(this.db, input.slug, \"CONTENT_USAGE_STALE\");\n\t\t} catch (error) {\n\t\t\tif (schemaMutated) {\n\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\tthis.db,\n\t\t\t\t\tinput.slug,\n\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tif (schemaMutated) resetRegisteredCollectionsCache();\n\t\t}\n\t\tthis.notifyTypegen();\n\t}\n\n\t/**\n\t * Write a site-package collection and its fields with their exact ids and\n\t * every column (see `CollectionImporter` in `transfer/schema-importer.ts`).\n\t *\n\t * Every statement is idempotent and none runs in a transaction, so a call\n\t * interrupted after any statement (D1 has no transactions) can be repeated\n\t * until it completes. Rows are inserted with `ON CONFLICT DO NOTHING` and\n\t * then read back; a stored row that differs from the record throws\n\t * `IMPORT_MISMATCH`.\n\t */\n\tasync importCollection(\n\t\trecord: CollectionRecord,\n\t\tfieldRecords: readonly FieldRecord[],\n\t\t_options: ImportCollectionOptions,\n\t): Promise<ImportCollectionResult> {\n\t\tthis.validateSlug(record.slug, \"collection\");\n\t\tif (RESERVED_COLLECTION_SLUGS.includes(record.slug)) {\n\t\t\tthrow new SchemaError(`Collection slug \"${record.slug}\" is reserved`, \"RESERVED_SLUG\");\n\t\t}\n\t\tconst fields = this.importFieldInputs(record, fieldRecords);\n\n\t\tconst conflicting = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select([\"id\", \"slug\"])\n\t\t\t.where((eb) => eb.or([eb(\"id\", \"=\", record.id), eb(\"slug\", \"=\", record.slug)]))\n\t\t\t.execute();\n\t\tif (conflicting.some((row) => row.id !== record.id || row.slug !== record.slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${record.slug}\" already exists`, \"COLLECTION_EXISTS\");\n\t\t}\n\t\tconst registered = conflicting.length > 0;\n\t\tif (await isMediaUsageCollectionSlugDeleting(this.db, record.slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${record.slug}\" is being deleted`, \"COLLECTION_EXISTS\");\n\t\t}\n\n\t\tconst identity = { collectionId: record.id, collectionSlug: record.slug };\n\t\tconst lifecycle = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_index_status\")\n\t\t\t.select([\"collection_id\", \"capture_state\"])\n\t\t\t.where(\"adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"scope_key\", \"=\", record.slug)\n\t\t\t.executeTakeFirst();\n\t\tconst captureFinalized =\n\t\t\tlifecycle?.collection_id === record.id && lifecycle.capture_state === \"active\";\n\t\tlet captureRequired = captureFinalized;\n\t\tif (!captureFinalized) {\n\t\t\tconst capture = await prepareMediaUsageCollectionCapture(this.db, {\n\t\t\t\t...identity,\n\t\t\t\tcreationFingerprint: await importCaptureFingerprint(record, fieldRecords),\n\t\t\t\tregisteredCollectionId: registered ? record.id : undefined,\n\t\t\t});\n\t\t\tcaptureRequired = capture.captureRequired;\n\t\t}\n\n\t\tawait this.createContentTable(record.slug, this.db, fields, { ifNotExists: true });\n\t\tif (captureRequired && !captureFinalized) {\n\t\t\tawait installPreparedMediaUsageCollectionCapture(this.db, identity);\n\t\t\tawait markMediaUsageCollectionCaptureReady(this.db, identity);\n\t\t}\n\n\t\tconst collectionSpec = getPortableTableSpec(\"_emdash_collections\");\n\t\tconst fieldSpec = getPortableTableSpec(\"_emdash_fields\");\n\t\tif (!collectionSpec || !fieldSpec) {\n\t\t\tthrow new SchemaError(\"Missing transfer column registry\", \"IMPORT_MISMATCH\");\n\t\t}\n\t\tconst collectionRow = {\n\t\t\t...encodeRecord(this.db, collectionSpec.columns, record, {\n\t\t\t\tkind: \"collection\",\n\t\t\t\tid: record.id,\n\t\t\t}),\n\t\t\tsearch_config: importSearchConfig(record.searchConfig),\n\t\t};\n\t\tconst insertedCollection = { ...collectionRow, title_field: null, date_field: null };\n\t\tconst collectionCreated =\n\t\t\t(await insertRows(this.db, \"_emdash_collections\", Object.keys(insertedCollection), [\n\t\t\t\tinsertedCollection,\n\t\t\t])) > 0;\n\n\t\tconst fieldRows = fieldRecords.map((field) =>\n\t\t\tencodeRecord(this.db, fieldSpec.columns, field, { kind: \"field\", id: field.id }),\n\t\t);\n\t\tconst fieldsCreated = await insertRows(\n\t\t\tthis.db,\n\t\t\t\"_emdash_fields\",\n\t\t\tObject.keys(recordCodecs(fieldSpec.columns)),\n\t\t\tfieldRows,\n\t\t);\n\n\t\tconst float4 = isPostgres(this.db);\n\t\tconst storedFields = await this.db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.selectAll()\n\t\t\t.where(\"collection_id\", \"=\", record.id)\n\t\t\t.execute();\n\t\tconst fieldCodecs = recordCodecs(fieldSpec.columns);\n\t\tconst storedById = new Map(storedFields.map((row) => [row.id, row]));\n\t\tif (storedFields.length !== fieldRows.length) {\n\t\t\tthrow new SchemaError(`Imported fields of \"${record.slug}\" do not match`, \"IMPORT_MISMATCH\");\n\t\t}\n\t\tfieldRecords.forEach((field, index) => {\n\t\t\tconst row = fieldRows[index];\n\t\t\tconst stored = storedById.get(field.id);\n\t\t\tif (\n\t\t\t\t!row ||\n\t\t\t\t!stored ||\n\t\t\t\tfirstDifference(this.db, fieldCodecs, row, stored, { float4 }) !== null\n\t\t\t) {\n\t\t\t\tthrow new SchemaError(`Imported field \"${field.slug}\" does not match`, \"IMPORT_MISMATCH\", {\n\t\t\t\t\tfieldId: field.id,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tfor (const field of fieldRecords) {\n\t\t\tif (field.indexed) await this.createFieldIndex(record.slug, field.id, field.slug);\n\t\t}\n\t\tif (captureRequired && !captureFinalized) {\n\t\t\tawait finalizeMediaUsageCollectionCapture(this.db, identity);\n\t\t}\n\n\t\tawait this.db\n\t\t\t.updateTable(\"_emdash_collections\")\n\t\t\t.set({ title_field: record.titleField ?? null, date_field: record.dateField ?? null })\n\t\t\t.where(\"id\", \"=\", record.id)\n\t\t\t.execute();\n\t\tconst storedCollection = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", record.id)\n\t\t\t.executeTakeFirst();\n\t\tconst expectedCollection = {\n\t\t\t...collectionRow,\n\t\t\ttitle_field: record.titleField ?? null,\n\t\t\tdate_field: record.dateField ?? null,\n\t\t};\n\t\tif (\n\t\t\t!storedCollection ||\n\t\t\tfirstDifference(\n\t\t\t\tthis.db,\n\t\t\t\trecordCodecs(collectionSpec.columns),\n\t\t\t\texpectedCollection,\n\t\t\t\tstoredCollection,\n\t\t\t\t{\n\t\t\t\t\tfloat4,\n\t\t\t\t},\n\t\t\t) !== null\n\t\t) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Imported collection \"${record.slug}\" does not match`,\n\t\t\t\t\"IMPORT_MISMATCH\",\n\t\t\t);\n\t\t}\n\n\t\tresetRegisteredCollectionsCache();\n\t\tthis.notifyTypegen();\n\t\treturn { collectionCreated, fieldsCreated };\n\t}\n\n\tprivate importFieldInputs(\n\t\trecord: CollectionRecord,\n\t\tfieldRecords: readonly FieldRecord[],\n\t): CreateFieldInput[] {\n\t\tconst slugs = new Set<string>();\n\t\treturn fieldRecords.map((field) => {\n\t\t\tif (field.collectionId !== record.id) {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`Field \"${field.slug}\" does not belong to \"${record.slug}\"`,\n\t\t\t\t\t\"IMPORT_MISMATCH\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.validateSlug(field.slug, \"field\");\n\t\t\tif (RESERVED_FIELD_SLUGS.includes(field.slug)) {\n\t\t\t\tthrow new SchemaError(`Field slug \"${field.slug}\" is reserved`, \"RESERVED_SLUG\");\n\t\t\t}\n\t\t\tif (slugs.has(field.slug)) {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`Field \"${field.slug}\" already exists in collection \"${record.slug}\"`,\n\t\t\t\t\t\"FIELD_EXISTS\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tslugs.add(field.slug);\n\t\t\tif (!isFieldType(field.type) || FIELD_TYPE_TO_COLUMN[field.type] !== field.columnType) {\n\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t`Field \"${field.slug}\" has an unsupported type or column type`,\n\t\t\t\t\t\"INVALID_FIELD_TYPE\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst validation = importFieldValidation(field.validation);\n\t\t\tassertIndexableField({ type: field.type, validation }, field.indexed, field.slug);\n\t\t\tif (field.indexed) this.getFieldIndexName(field.id);\n\t\t\treturn {\n\t\t\t\tslug: field.slug,\n\t\t\t\tlabel: field.label,\n\t\t\t\ttype: field.type,\n\t\t\t\trequired: field.required,\n\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\tvalidation,\n\t\t\t};\n\t\t});\n\t}\n\n\tprivate async assertSeedFieldDefinitions(\n\t\tcollectionId: string,\n\t\tfields: readonly CreateFieldInput[],\n\t\tdb: Kysely<Database>,\n\t): Promise<Selectable<FieldTable>[]> {\n\t\tconst stored = await db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.selectAll()\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.execute();\n\t\tif (stored.length !== fields.length) {\n\t\t\tthrow new SchemaError(\"Interrupted seed collection fields do not match\", \"CREATE_FAILED\");\n\t\t}\n\n\t\tlet maxSortOrder = -1;\n\t\tfor (const field of fields) {\n\t\t\tconst sortOrder = field.sortOrder ?? maxSortOrder + 1;\n\t\t\tmaxSortOrder = Math.max(maxSortOrder, sortOrder);\n\t\t\tconst row = stored.find((candidate) => candidate.slug === field.slug);\n\t\t\tif (\n\t\t\t\t!row ||\n\t\t\t\trow.label !== field.label ||\n\t\t\t\trow.type !== field.type ||\n\t\t\t\trow.column_type !== FIELD_TYPE_TO_COLUMN[field.type] ||\n\t\t\t\trow.required !== (field.required ? 1 : 0) ||\n\t\t\t\trow.unique !== (field.unique ? 1 : 0) ||\n\t\t\t\trow.default_value !==\n\t\t\t\t\t(field.defaultValue !== undefined ? JSON.stringify(field.defaultValue) : null) ||\n\t\t\t\trow.validation !== (field.validation ? JSON.stringify(field.validation) : null) ||\n\t\t\t\trow.widget !== (field.widget ?? null) ||\n\t\t\t\trow.options !== (field.options ? JSON.stringify(field.options) : null) ||\n\t\t\t\trow.sort_order !== sortOrder ||\n\t\t\t\trow.searchable !== (field.searchable ? 1 : 0) ||\n\t\t\t\trow.indexed !== (field.indexed ? 1 : 0) ||\n\t\t\t\trow.translatable !== (field.translatable === false ? 0 : 1)\n\t\t\t) {\n\t\t\t\tthrow new SchemaError(\"Interrupted seed collection fields do not match\", \"CREATE_FAILED\");\n\t\t\t}\n\t\t}\n\t\treturn stored;\n\t}\n\n\t/**\n\t * Update a collection\n\t */\n\tasync updateCollection(slug: string, input: UpdateCollectionInput): Promise<Collection> {\n\t\tconst updated = await withTransaction(this.db, async (trx) => {\n\t\t\tconst existingRow = await trx\n\t\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t\t.where(\"slug\", \"=\", slug)\n\t\t\t\t.selectAll()\n\t\t\t\t.executeTakeFirst();\n\t\t\tif (!existingRow) {\n\t\t\t\tthrow new SchemaError(`Collection \"${slug}\" not found`, \"COLLECTION_NOT_FOUND\");\n\t\t\t}\n\t\t\tconst existing = this.mapCollectionRow(existingRow);\n\t\t\tawait this.validateTitleDateFields(\n\t\t\t\texisting.id,\n\t\t\t\tslug,\n\t\t\t\t{\n\t\t\t\t\ttitleField: input.titleField,\n\t\t\t\t\tdateField: input.dateField,\n\t\t\t\t},\n\t\t\t\ttrx,\n\t\t\t);\n\t\t\tconst updates: Updateable<CollectionTable> = {};\n\n\t\t\tif (input.label !== undefined) updates.label = input.label;\n\t\t\tif (input.labelSingular !== undefined) updates.label_singular = input.labelSingular;\n\t\t\tif (input.description !== undefined) updates.description = input.description;\n\t\t\tif (input.icon !== undefined) updates.icon = input.icon;\n\t\t\tif (input.admin !== undefined) updates.admin_config = JSON.stringify(input.admin);\n\t\t\tif (input.supports !== undefined) updates.supports = JSON.stringify(input.supports);\n\t\t\tif (input.urlPattern !== undefined) updates.url_pattern = input.urlPattern;\n\t\t\tif (input.routable !== undefined) updates.routable = input.routable ? 1 : 0;\n\t\t\tif (input.hasSeo !== undefined) {\n\t\t\t\tupdates.has_seo = input.hasSeo ? 1 : 0;\n\t\t\t} else if (input.supports !== undefined) {\n\t\t\t\tupdates.has_seo = input.supports.includes(\"seo\") ? 1 : 0;\n\t\t\t}\n\t\t\tif (input.hidden !== undefined) updates.hidden = input.hidden ? 1 : 0;\n\t\t\tif (input.sortOrder !== undefined) updates.sort_order = input.sortOrder;\n\t\t\tif (input.group !== undefined) updates.nav_group = input.group?.trim() || null;\n\t\t\tif (input.titleField !== undefined) updates.title_field = input.titleField || null;\n\t\t\tif (input.dateField !== undefined) updates.date_field = input.dateField || null;\n\t\t\tif (input.commentsEnabled !== undefined) {\n\t\t\t\tupdates.comments_enabled = input.commentsEnabled ? 1 : 0;\n\t\t\t}\n\t\t\tif (input.commentsModeration !== undefined) {\n\t\t\t\tupdates.comments_moderation = input.commentsModeration;\n\t\t\t}\n\t\t\tif (input.commentsClosedAfterDays !== undefined) {\n\t\t\t\tupdates.comments_closed_after_days = input.commentsClosedAfterDays;\n\t\t\t}\n\t\t\tif (input.commentsAutoApproveUsers !== undefined) {\n\t\t\t\tupdates.comments_auto_approve_users = input.commentsAutoApproveUsers ? 1 : 0;\n\t\t\t}\n\t\t\tif (input.editLocking !== undefined) updates.edit_locking = input.editLocking ? 1 : 0;\n\n\t\t\tupdates.updated_at = new Date().toISOString();\n\t\t\tawait trx\n\t\t\t\t.updateTable(\"_emdash_collections\")\n\t\t\t\t.set(updates)\n\t\t\t\t.where(\"id\", \"=\", existing.id)\n\t\t\t\t.execute();\n\n\t\t\tconst row = await trx\n\t\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t\t.where(\"slug\", \"=\", slug)\n\t\t\t\t.selectAll()\n\t\t\t\t.executeTakeFirst();\n\n\t\t\tif (!row) {\n\t\t\t\tthrow new SchemaError(\"Failed to update collection\", \"UPDATE_FAILED\");\n\t\t\t}\n\n\t\t\t// Sync FTS state when the supports array changes (e.g. search toggled on/off)\n\t\t\tif (input.supports !== undefined) {\n\t\t\t\tconst hadSearch = existing.supports.includes(\"search\");\n\t\t\t\tconst hasSearch = parseSupports(row.supports).includes(\"search\");\n\t\t\t\tif (hadSearch !== hasSearch) {\n\t\t\t\t\tawait this.syncSearchState(slug, trx);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this.mapCollectionRow(row);\n\t\t});\n\t\tthis.notifyTypegen();\n\t\treturn updated;\n\t}\n\n\t/**\n\t * The content guard {@link deleteCollection} refuses on, on its own.\n\t *\n\t * A caller that has to cascade before deleting — relations, whose edges point\n\t * at rows the drop is about to take — needs to know the delete is acceptable\n\t * before it changes anything, since the cascade cannot be rolled back on D1.\n\t */\n\tasync assertCollectionDeletable(slug: string, options?: { force?: boolean }): Promise<void> {\n\t\tif (options?.force) return;\n\t\tconst existing = await this.getCollection(slug);\n\t\tif (existing && (await this.collectionHasContent(slug))) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Collection \"${slug}\" has content. Use force: true to delete.`,\n\t\t\t\t\"COLLECTION_HAS_CONTENT\",\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Delete a collection\n\t */\n\tasync deleteCollection(slug: string, options?: { force?: boolean }): Promise<void> {\n\t\tawait this.assertCollectionDeletable(slug, options);\n\t\tconst existing = await this.getCollection(slug);\n\t\tconst activated = await deleteActivatedMediaUsageCollection(this.db, {\n\t\t\tcollectionId: existing?.id,\n\t\t\tcollectionSlug: slug,\n\t\t\tforceDelete: options?.force === true,\n\t\t});\n\t\tif (activated === \"has_content\") {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Collection \"${slug}\" has content. Use force: true to delete.`,\n\t\t\t\t\"COLLECTION_HAS_CONTENT\",\n\t\t\t);\n\t\t}\n\t\tif (activated === \"in_progress\") {\n\t\t\tthrow new SchemaError(`Collection \"${slug}\" deletion is already in progress`, \"CONFLICT\");\n\t\t}\n\t\tif (activated === \"deleted\") return;\n\t\tif (!existing) {\n\t\t\tthrow new SchemaError(`Collection \"${slug}\" not found`, \"COLLECTION_NOT_FOUND\");\n\t\t}\n\n\t\tlet contentTableDropped = false;\n\t\ttry {\n\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\t// Drop FTS table and triggers before dropping the content table\n\t\t\t\tconst ftsManager = new FTSManager(trx);\n\t\t\t\tawait ftsManager.dropFtsTable(slug);\n\n\t\t\t\t// Drop the content table\n\t\t\t\tconst tableName = this.getTableName(slug);\n\t\t\t\tawait sql`DROP TABLE IF EXISTS ${sql.ref(tableName)}`.execute(trx);\n\t\t\t\tcontentTableDropped = true;\n\n\t\t\t\t// Delete the collection record (fields will cascade)\n\t\t\t\tawait trx.deleteFrom(\"_emdash_collections\").where(\"id\", \"=\", existing.id).execute();\n\t\t\t});\n\t\t\tawait deleteContentMediaUsageCollection(this.db, slug);\n\t\t} catch (error) {\n\t\t\tif (contentTableDropped && !(await tableExists(this.db, this.getTableName(slug)))) {\n\t\t\t\tawait deleteContentMediaUsageCollection(this.db, slug);\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// Even a failed delete may have dropped the ec_* table (D1 has no\n\t\t\t// real transactions) — over-invalidation is harmless, a stale set\n\t\t\t// is not.\n\t\t\tif (contentTableDropped) resetRegisteredCollectionsCache();\n\t\t}\n\t\tthis.notifyTypegen();\n\t}\n\n\t// ============================================\n\t// Field Operations\n\t// ============================================\n\n\t/**\n\t * List fields for a collection\n\t */\n\tasync listFields(collectionId: string): Promise<Field[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t.orderBy(\"created_at\", \"asc\")\n\t\t\t.execute();\n\n\t\treturn rows.map(this.mapFieldRow);\n\t}\n\n\t/**\n\t * Get a field by slug within a collection\n\t */\n\tasync getField(collectionSlug: string, fieldSlug: string): Promise<Field | null> {\n\t\tconst collection = await this.getCollection(collectionSlug);\n\t\tif (!collection) return null;\n\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.where(\"collection_id\", \"=\", collection.id)\n\t\t\t.where(\"slug\", \"=\", fieldSlug)\n\t\t\t.selectAll()\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? this.mapFieldRow(row) : null;\n\t}\n\n\t/**\n\t * Create a new field\n\t */\n\tasync createField(collectionSlug: string, input: CreateFieldInput): Promise<Field> {\n\t\tconst collection = await this.getCollection(collectionSlug);\n\t\tif (!collection) {\n\t\t\tthrow new SchemaError(`Collection \"${collectionSlug}\" not found`, \"COLLECTION_NOT_FOUND\");\n\t\t}\n\n\t\t// Validate slug\n\t\tthis.validateSlug(input.slug, \"field\");\n\t\tif (RESERVED_FIELD_SLUGS.includes(input.slug)) {\n\t\t\tthrow new SchemaError(`Field slug \"${input.slug}\" is reserved`, \"RESERVED_SLUG\");\n\t\t}\n\n\t\t// Check if field already exists\n\t\tconst existing = await this.getField(collectionSlug, input.slug);\n\t\tif (existing) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Field \"${input.slug}\" already exists in collection \"${collectionSlug}\"`,\n\t\t\t\t\"FIELD_EXISTS\",\n\t\t\t);\n\t\t}\n\n\t\tconst id = ulid();\n\t\tconst validation =\n\t\t\tinput.type === \"blocks\"\n\t\t\t\t? await this.normalizeBlocksFieldValidation(collectionSlug, input, undefined, this.db)\n\t\t\t\t: input.validation;\n\t\tconst columnType = FIELD_TYPE_TO_COLUMN[input.type];\n\t\tassertIndexableField(input, input.indexed, input.slug);\n\n\t\t// Get max sort order\n\t\tconst maxSort = await this.db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.where(\"collection_id\", \"=\", collection.id)\n\t\t\t.select((eb) => eb.fn.max<number>(\"sort_order\").as(\"max\"))\n\t\t\t.executeTakeFirst();\n\n\t\tconst sortOrder = input.sortOrder ?? (maxSort?.max ?? -1) + 1;\n\t\tconst activeCoverageInvalidated = await invalidateContentMediaUsageSchemaChange(\n\t\t\tthis.db,\n\t\t\tcollectionSlug,\n\t\t);\n\n\t\tlet schemaMutated = false;\n\t\ttry {\n\t\t\tconst created = await withTransaction(this.db, async (trx) => {\n\t\t\t\t// Insert field record\n\t\t\t\tawait trx\n\t\t\t\t\t.insertInto(\"_emdash_fields\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tcollection_id: collection.id,\n\t\t\t\t\t\tslug: input.slug,\n\t\t\t\t\t\tlabel: input.label,\n\t\t\t\t\t\ttype: input.type,\n\t\t\t\t\t\tcolumn_type: columnType,\n\t\t\t\t\t\trequired: input.required ? 1 : 0,\n\t\t\t\t\t\tunique: input.unique ? 1 : 0,\n\t\t\t\t\t\tdefault_value:\n\t\t\t\t\t\t\tinput.defaultValue !== undefined ? JSON.stringify(input.defaultValue) : null,\n\t\t\t\t\t\tvalidation: validation ? JSON.stringify(validation) : null,\n\t\t\t\t\t\twidget: input.widget ?? null,\n\t\t\t\t\t\toptions: input.options ? JSON.stringify(input.options) : null,\n\t\t\t\t\t\tsort_order: sortOrder,\n\t\t\t\t\t\tsearchable: input.searchable ? 1 : 0,\n\t\t\t\t\t\tindexed: input.indexed ? 1 : 0,\n\t\t\t\t\t\ttranslatable: input.translatable === false ? 0 : 1,\n\t\t\t\t\t})\n\t\t\t\t\t.execute();\n\t\t\t\tschemaMutated = true;\n\n\t\t\t\t// Add column to content table — pass trx to stay on the same connection.\n\t\t\t\t// A storage-less field persists no column; its values live in a side\n\t\t\t\t// table (see `isStoragelessField`). Insert the field row only.\n\t\t\t\tif (!isStoragelessField(input)) {\n\t\t\t\t\tawait this.addColumn(\n\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\tinput.slug,\n\t\t\t\t\t\tinput.type,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trequired: input.required,\n\t\t\t\t\t\t\tdefaultValue: input.defaultValue,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttrx,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (input.indexed) {\n\t\t\t\t\tawait this.createFieldIndex(collectionSlug, id, input.slug, trx);\n\t\t\t\t}\n\n\t\t\t\t// Read the created field via trx (not this.db) to avoid connection mutex deadlock\n\t\t\t\tconst fieldRow = await trx\n\t\t\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t\t\t.where(\"collection_id\", \"=\", collection.id)\n\t\t\t\t\t.where(\"slug\", \"=\", input.slug)\n\t\t\t\t\t.selectAll()\n\t\t\t\t\t.executeTakeFirst();\n\n\t\t\t\tif (!fieldRow) {\n\t\t\t\t\tthrow new SchemaError(\"Failed to create field\", \"CREATE_FAILED\");\n\t\t\t\t}\n\n\t\t\t\tconst field = this.mapFieldRow(fieldRow);\n\n\t\t\t\t// Sync search state if this field is searchable; support checks are handled by syncSearchState()\n\t\t\t\tif (input.searchable) {\n\t\t\t\t\tawait this.syncSearchState(collectionSlug, trx);\n\t\t\t\t}\n\n\t\t\t\treturn field;\n\t\t\t});\n\t\t\tif (activeCoverageInvalidated) {\n\t\t\t\tawait invalidateContentMediaUsageSchemaChange(this.db, collectionSlug);\n\t\t\t} else {\n\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\tthis.db,\n\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.notifyTypegen();\n\t\t\treturn created;\n\t\t} catch (error) {\n\t\t\tif (schemaMutated) {\n\t\t\t\tif (activeCoverageInvalidated) {\n\t\t\t\t\tawait invalidateContentMediaUsageSchemaChange(this.db, collectionSlug);\n\t\t\t\t} else {\n\t\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\t\tthis.db,\n\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Update a field\n\t */\n\tasync updateField(\n\t\tcollectionSlug: string,\n\t\tfieldSlug: string,\n\t\tinput: UpdateFieldInput,\n\t): Promise<Field> {\n\t\tlet activeCoverageInvalidated = false;\n\t\tlet schemaMutated = false;\n\t\ttry {\n\t\t\tconst updatedField = await withTransaction(this.db, async (trx) => {\n\t\t\t\tconst collectionRow = await trx\n\t\t\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t\t\t\t.select([\"id\", \"title_field\", \"date_field\"])\n\t\t\t\t\t.executeTakeFirst();\n\t\t\t\tconst fieldRow = collectionRow\n\t\t\t\t\t? await trx\n\t\t\t\t\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t\t\t\t\t.where(\"collection_id\", \"=\", collectionRow.id)\n\t\t\t\t\t\t\t.where(\"slug\", \"=\", fieldSlug)\n\t\t\t\t\t\t\t.selectAll()\n\t\t\t\t\t\t\t.executeTakeFirst()\n\t\t\t\t\t: undefined;\n\t\t\t\tif (!fieldRow) {\n\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t`Field \"${fieldSlug}\" not found in collection \"${collectionSlug}\"`,\n\t\t\t\t\t\t\"FIELD_NOT_FOUND\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst field = this.mapFieldRow(fieldRow);\n\t\t\t\tif (field.unsupportedType) {\n\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t`Field \"${fieldSlug}\" in collection \"${collectionSlug}\" uses unsupported field type \"${field.unsupportedType.type}\" at \"${field.unsupportedType.path}\"`,\n\t\t\t\t\t\t\"UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst updates: Updateable<FieldTable> = {};\n\t\t\t\tlet nextType = field.type;\n\t\t\t\tconst nextValidation =\n\t\t\t\t\tfield.type === \"blocks\"\n\t\t\t\t\t\t? await this.normalizeBlocksFieldValidation(\n\t\t\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t...input,\n\t\t\t\t\t\t\t\t\tslug: field.slug,\n\t\t\t\t\t\t\t\t\tlabel: input.label ?? field.label,\n\t\t\t\t\t\t\t\t\ttype: field.type,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\ttrx,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: input.validation !== undefined\n\t\t\t\t\t\t\t? input.validation\n\t\t\t\t\t\t\t: field.validation;\n\n\t\t\t\tif (input.type !== undefined && input.type !== field.type) {\n\t\t\t\t\t// A change into or out of storage-less is never a no-op column change:\n\t\t\t\t\t// string -> reference both map to TEXT and would slip past the affinity\n\t\t\t\t\t// check below, yet one has a column and the other does not. An unwired\n\t\t\t\t\t// reference field is column-backed, so its refusal comes from the\n\t\t\t\t\t// text-alias check instead.\n\t\t\t\t\tconst storagelessBefore = isStoragelessField(field);\n\t\t\t\t\tconst storagelessAfter = isStoragelessField({\n\t\t\t\t\t\ttype: input.type,\n\t\t\t\t\t\tvalidation: nextValidation,\n\t\t\t\t\t});\n\t\t\t\t\tif (storagelessBefore !== storagelessAfter) {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`Cannot change field \"${fieldSlug}\" in collection \"${collectionSlug}\" between ` +\n\t\t\t\t\t\t\t\t`storage-less and column-backed types (\"${field.type}\" -> \"${input.type}\").`,\n\t\t\t\t\t\t\t\"FIELD_TYPE_COLUMN_CHANGE\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newColumnType = FIELD_TYPE_TO_COLUMN[input.type];\n\t\t\t\t\tif (newColumnType !== field.columnType) {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`Cannot change field \"${fieldSlug}\" in collection \"${collectionSlug}\" from type ` +\n\t\t\t\t\t\t\t\t`\"${field.type}\" to \"${input.type}\": the underlying column type would change from ` +\n\t\t\t\t\t\t\t\t`${field.columnType} to ${newColumnType}, which requires a manual content migration.`,\n\t\t\t\t\t\t\t\"FIELD_TYPE_COLUMN_CHANGE\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (!TEXT_ALIAS_FIELD_TYPES.has(field.type) || !TEXT_ALIAS_FIELD_TYPES.has(input.type)) {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`Cannot change field \"${fieldSlug}\" in collection \"${collectionSlug}\" from type ` +\n\t\t\t\t\t\t\t\t`\"${field.type}\" to \"${input.type}\" without a manual content migration.`,\n\t\t\t\t\t\t\t\"FIELD_TYPE_CHANGE_REQUIRES_MIGRATION\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (collectionRow?.title_field === fieldSlug && !TITLE_FIELD_TYPES.has(input.type)) {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`titleField \"${fieldSlug}\" must stay a text field, not \"${input.type}\"`,\n\t\t\t\t\t\t\t\"INVALID_TITLE_FIELD\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (collectionRow?.date_field === fieldSlug && input.type !== \"datetime\") {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`dateField \"${fieldSlug}\" must stay a datetime field, not \"${input.type}\"`,\n\t\t\t\t\t\t\t\"INVALID_DATE_FIELD\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tnextType = input.type;\n\t\t\t\t\tupdates.type = input.type;\n\t\t\t\t\tupdates.column_type = newColumnType;\n\t\t\t\t}\n\n\t\t\t\tif (input.required !== undefined && input.required !== field.required) {\n\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t`Changing required for field \"${fieldSlug}\" requires a manual content migration.`,\n\t\t\t\t\t\t\"FIELD_UPDATE_REQUIRES_MIGRATION\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (input.unique !== undefined && input.unique !== field.unique) {\n\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t`Changing unique for field \"${fieldSlug}\" requires a manual content migration.`,\n\t\t\t\t\t\t\"FIELD_UPDATE_REQUIRES_MIGRATION\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (input.translatable === false && field.translatable) {\n\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t`Changing field \"${fieldSlug}\" to non-translatable requires a manual content migration.`,\n\t\t\t\t\t\t\"FIELD_UPDATE_REQUIRES_MIGRATION\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (input.label !== undefined) updates.label = input.label;\n\t\t\t\tif (input.required !== undefined) updates.required = input.required ? 1 : 0;\n\t\t\t\tif (input.unique !== undefined) updates.unique = input.unique ? 1 : 0;\n\t\t\t\tif (input.searchable !== undefined) updates.searchable = input.searchable ? 1 : 0;\n\t\t\t\tconst indexedChanged = input.indexed !== undefined && input.indexed !== field.indexed;\n\t\t\t\tif (indexedChanged) updates.indexed = input.indexed ? 1 : 0;\n\t\t\t\tif (input.translatable !== undefined) {\n\t\t\t\t\tupdates.translatable = input.translatable ? 1 : 0;\n\t\t\t\t}\n\t\t\t\tif (input.defaultValue !== undefined) {\n\t\t\t\t\tupdates.default_value = JSON.stringify(input.defaultValue);\n\t\t\t\t}\n\t\t\t\tif (input.validation !== undefined || field.type === \"blocks\") {\n\t\t\t\t\tupdates.validation = nextValidation ? JSON.stringify(nextValidation) : null;\n\t\t\t\t}\n\t\t\t\tif (input.widget !== undefined) updates.widget = input.widget;\n\t\t\t\tif (input.options !== undefined) updates.options = JSON.stringify(input.options);\n\t\t\t\tif (input.sortOrder !== undefined) updates.sort_order = input.sortOrder;\n\n\t\t\t\tassertIndexableField(\n\t\t\t\t\t{ type: nextType, validation: nextValidation },\n\t\t\t\t\tinput.indexed ?? field.indexed,\n\t\t\t\t\tfieldSlug,\n\t\t\t\t);\n\t\t\t\tif (Object.keys(updates).length === 0) return field;\n\n\t\t\t\tactiveCoverageInvalidated = await invalidateContentMediaUsageSchemaChange(\n\t\t\t\t\ttrx,\n\t\t\t\t\tcollectionSlug,\n\t\t\t\t);\n\n\t\t\t\tif (Object.keys(updates).length > 0) {\n\t\t\t\t\tawait trx.updateTable(\"_emdash_fields\").set(updates).where(\"id\", \"=\", field.id).execute();\n\t\t\t\t\tschemaMutated = true;\n\t\t\t\t}\n\n\t\t\t\tif (indexedChanged) {\n\t\t\t\t\tif (input.indexed) {\n\t\t\t\t\t\tawait this.createFieldIndex(collectionSlug, field.id, fieldSlug, trx);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.dropFieldIndex(field.id, trx);\n\t\t\t\t\t}\n\t\t\t\t\tschemaMutated = true;\n\t\t\t\t}\n\n\t\t\t\t// Read the updated field via trx (not this.db) to avoid connection mutex deadlock\n\t\t\t\tconst updatedRow = await trx\n\t\t\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t\t\t.where(\"collection_id\", \"=\", field.collectionId)\n\t\t\t\t\t.where(\"slug\", \"=\", fieldSlug)\n\t\t\t\t\t.selectAll()\n\t\t\t\t\t.executeTakeFirst();\n\n\t\t\t\tif (!updatedRow) {\n\t\t\t\t\tthrow new SchemaError(\"Failed to update field\", \"UPDATE_FAILED\");\n\t\t\t\t}\n\n\t\t\t\tconst updated = this.mapFieldRow(updatedRow);\n\n\t\t\t\t// If searchable changed, sync FTS state for this collection\n\t\t\t\tconst searchableChanged =\n\t\t\t\t\tschemaMutated && input.searchable !== undefined && input.searchable !== field.searchable;\n\t\t\t\tif (searchableChanged) {\n\t\t\t\t\tawait this.syncSearchState(collectionSlug, trx);\n\t\t\t\t}\n\n\t\t\t\treturn updated;\n\t\t\t});\n\t\t\tif (schemaMutated) {\n\t\t\t\tif (activeCoverageInvalidated) {\n\t\t\t\t\tawait invalidateContentMediaUsageSchemaChange(this.db, collectionSlug);\n\t\t\t\t} else {\n\t\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\t\tthis.db,\n\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.notifyTypegen();\n\t\t\treturn updatedField;\n\t\t} catch (error) {\n\t\t\tif (schemaMutated) {\n\t\t\t\tif (activeCoverageInvalidated) {\n\t\t\t\t\tawait invalidateContentMediaUsageSchemaChange(this.db, collectionSlug);\n\t\t\t\t} else {\n\t\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\t\tthis.db,\n\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Synchronize an existing FTS index with the collection's current state.\n\t *\n\t * Only rebuilds or disables — never first-time enables. First-time FTS\n\t * enablement is handled by the seed's explicit enableSearch call (which\n\t * is try-caught) or the admin UI toggle.\n\t *\n\t * - FTS active + still has search support and searchable fields → rebuild\n\t * - FTS active + lost search support or no searchable fields → disable\n\t * - FTS not active → no-op\n\t *\n\t * Pass `db` when calling from within a transaction so FTS operations\n\t * participate in the same transaction and are rolled back on failure.\n\t */\n\tprivate async syncSearchState(collectionSlug: string, db?: Kysely<Database>): Promise<void> {\n\t\tconst conn = db ?? this.db;\n\t\tconst ftsManager = new FTSManager(conn);\n\n\t\t// Query via conn (not this.db) to avoid connection mutex deadlock when called inside a transaction\n\t\tconst row = await conn\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t\t.select(\"supports\")\n\t\t\t.executeTakeFirst();\n\t\tif (!row) return;\n\n\t\tconst wantsSearch = parseSupports(row.supports).includes(\"search\");\n\t\tconst searchableFields = await ftsManager.getSearchableFields(collectionSlug);\n\t\tconst config = await ftsManager.getSearchConfig(collectionSlug);\n\t\tconst ftsActive = config?.enabled === true;\n\n\t\tif (wantsSearch && searchableFields.length > 0 && ftsActive) {\n\t\t\tawait ftsManager.rebuildIndex(\n\t\t\t\tcollectionSlug,\n\t\t\t\tsearchableFields,\n\t\t\t\tconfig?.weights,\n\t\t\t\tconfig?.tokenize,\n\t\t\t);\n\t\t} else if (ftsActive && (!wantsSearch || searchableFields.length === 0)) {\n\t\t\tawait ftsManager.disableSearch(collectionSlug);\n\t\t}\n\t}\n\n\t/**\n\t * Delete a field\n\t */\n\tasync deleteField(collectionSlug: string, fieldSlug: string): Promise<void> {\n\t\tconst field = await this.getField(collectionSlug, fieldSlug);\n\t\tif (!field) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Field \"${fieldSlug}\" not found in collection \"${collectionSlug}\"`,\n\t\t\t\t\"FIELD_NOT_FOUND\",\n\t\t\t);\n\t\t}\n\t\tconst activeCoverageInvalidated = await invalidateContentMediaUsageSchemaChange(\n\t\t\tthis.db,\n\t\t\tcollectionSlug,\n\t\t);\n\n\t\t// If this field powers the collection's titleField/dateField,\n\t\t// clear that reference in the same transaction — otherwise the metadata\n\t\t// would point at a dropped column and later crash the content list sort.\n\t\tconst collection = await this.getCollection(collectionSlug);\n\t\tconst clearTitle = collection?.titleField === fieldSlug;\n\t\tconst clearDate = collection?.dateField === fieldSlug;\n\n\t\tlet schemaMutated = false;\n\t\ttry {\n\t\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t\t// Delete the field record first so syncSearchState sees the updated field list.\n\t\t\t\t// This ordering matters for searchable fields: SQLite prevents dropping a column\n\t\t\t\t// that is still referenced by a trigger. syncSearchState drops and recreates the\n\t\t\t\t// FTS triggers based on the remaining searchable fields, clearing the dependency\n\t\t\t\t// before we attempt the ALTER TABLE DROP COLUMN below.\n\t\t\t\tawait trx.deleteFrom(\"_emdash_fields\").where(\"id\", \"=\", field.id).execute();\n\t\t\t\tschemaMutated = true;\n\n\t\t\t\tif (clearTitle || clearDate) {\n\t\t\t\t\tawait trx\n\t\t\t\t\t\t.updateTable(\"_emdash_collections\")\n\t\t\t\t\t\t.set({\n\t\t\t\t\t\t\t...(clearTitle ? { title_field: null } : {}),\n\t\t\t\t\t\t\t...(clearDate ? { date_field: null } : {}),\n\t\t\t\t\t\t\tupdated_at: new Date().toISOString(),\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t\t\t\t\t.execute();\n\t\t\t\t}\n\n\t\t\t\t// If the deleted field was searchable, sync FTS state (removes old triggers)\n\t\t\t\tif (field.searchable) {\n\t\t\t\t\tawait this.syncSearchState(collectionSlug, trx);\n\t\t\t\t}\n\n\t\t\t\tif (field.indexed) {\n\t\t\t\t\tawait this.dropFieldIndex(field.id, trx);\n\t\t\t\t}\n\n\t\t\t\t// Drop column from content table — safe now because FTS triggers are gone.\n\t\t\t\t// Whether a field is storage-less is a property of the row rather than of\n\t\t\t\t// its type: reference fields created before they became storage-less\n\t\t\t\t// still carry a column, and skipping the DDL would strand it and block\n\t\t\t\t// the slug from ever being reused.\n\t\t\t\tconst hasColumn = await columnExists(\n\t\t\t\t\ttrx,\n\t\t\t\t\tthis.getTableName(collectionSlug),\n\t\t\t\t\tthis.getColumnName(fieldSlug),\n\t\t\t\t);\n\t\t\t\tif (hasColumn) {\n\t\t\t\t\tawait this.dropColumn(collectionSlug, fieldSlug, trx);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (activeCoverageInvalidated) {\n\t\t\t\tawait invalidateContentMediaUsageSchemaChange(this.db, collectionSlug);\n\t\t\t} else {\n\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\tthis.db,\n\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (schemaMutated) {\n\t\t\t\tif (activeCoverageInvalidated) {\n\t\t\t\t\tawait invalidateContentMediaUsageSchemaChange(this.db, collectionSlug);\n\t\t\t\t} else {\n\t\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(\n\t\t\t\t\t\tthis.db,\n\t\t\t\t\t\tcollectionSlug,\n\t\t\t\t\t\t\"CONTENT_USAGE_STALE\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tthis.notifyTypegen();\n\t}\n\n\t/**\n\t * Reorder collections in the admin sidebar.\n\t *\n\t * `slugs` is the full desired order: every listed collection gets its\n\t * index as `sort_order`, and any collection left out has its explicit\n\t * position cleared, dropping it back to the alphabetical tail. Unknown or\n\t * duplicate slugs throw before anything is written.\n\t */\n\tasync reorderCollections(slugs: string[]): Promise<void> {\n\t\tconst known = new Set((await this.listCollections()).map((collection) => collection.slug));\n\n\t\tconst unknown = slugs.filter((slug) => !known.has(slug));\n\t\tif (unknown.length > 0) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Unknown collection${unknown.length > 1 ? \"s\" : \"\"}: ${unknown.join(\", \")}`,\n\t\t\t\t\"COLLECTION_NOT_FOUND\",\n\t\t\t\t{ slugs: unknown },\n\t\t\t);\n\t\t}\n\n\t\tconst duplicates = slugs.filter((slug, index) => slugs.indexOf(slug) !== index);\n\t\tif (duplicates.length > 0) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`Duplicate collection${duplicates.length > 1 ? \"s\" : \"\"}: ${[...new Set(duplicates)].join(\", \")}`,\n\t\t\t\t\"DUPLICATE_SLUG\",\n\t\t\t\t{ slugs: [...new Set(duplicates)] },\n\t\t\t);\n\t\t}\n\n\t\tconst now = new Date().toISOString();\n\t\tconst ordered = new Set(slugs);\n\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tfor (const [index, slug] of slugs.entries()) {\n\t\t\t\tawait trx\n\t\t\t\t\t.updateTable(\"_emdash_collections\")\n\t\t\t\t\t.set({ sort_order: index, updated_at: now })\n\t\t\t\t\t.where(\"slug\", \"=\", slug)\n\t\t\t\t\t.execute();\n\t\t\t}\n\n\t\t\tconst cleared = [...known].filter((slug) => !ordered.has(slug));\n\t\t\t// Chunked to stay under D1's bound-parameter limit; typical sites\n\t\t\t// clear far fewer than one chunk.\n\t\t\tfor (const slugChunk of chunks(cleared, SQL_BATCH_SIZE)) {\n\t\t\t\tawait trx\n\t\t\t\t\t.updateTable(\"_emdash_collections\")\n\t\t\t\t\t.set({ sort_order: null, updated_at: now })\n\t\t\t\t\t.where(\"slug\", \"in\", slugChunk)\n\t\t\t\t\t.execute();\n\t\t\t}\n\t\t});\n\t\tthis.notifyTypegen();\n\t}\n\n\t/**\n\t * Reorder fields\n\t */\n\tasync reorderFields(collectionSlug: string, fieldSlugs: string[]): Promise<void> {\n\t\tconst collection = await this.getCollection(collectionSlug);\n\t\tif (!collection) {\n\t\t\tthrow new SchemaError(`Collection \"${collectionSlug}\" not found`, \"COLLECTION_NOT_FOUND\");\n\t\t}\n\n\t\t// Update sort_order for each field\n\t\tfor (let i = 0; i < fieldSlugs.length; i++) {\n\t\t\tawait this.db\n\t\t\t\t.updateTable(\"_emdash_fields\")\n\t\t\t\t.set({ sort_order: i })\n\t\t\t\t.where(\"collection_id\", \"=\", collection.id)\n\t\t\t\t.where(\"slug\", \"=\", fieldSlugs[i])\n\t\t\t\t.execute();\n\t\t}\n\t\tthis.notifyTypegen();\n\t}\n\n\t// ============================================\n\t// DDL Operations\n\t// ============================================\n\n\t/**\n\t * Create a content table for a collection\n\t */\n\tprivate async createContentTable(\n\t\tslug: string,\n\t\tdb?: Kysely<Database>,\n\t\tfields: readonly CreateFieldInput[] = [],\n\t\toptions: { ifNotExists?: boolean } = {},\n\t): Promise<void> {\n\t\tconst conn = db ?? this.db;\n\t\tconst tableName = this.getTableName(slug);\n\n\t\tlet table: CreateTableBuilder<string, string> = conn.schema\n\t\t\t.createTable(tableName)\n\t\t\t.addColumn(\"id\", \"text\", (col) => col.primaryKey())\n\t\t\t.addColumn(\"slug\", \"text\")\n\t\t\t.addColumn(\"status\", \"text\", (col) => col.defaultTo(\"draft\"))\n\t\t\t.addColumn(\"author_id\", \"text\")\n\t\t\t.addColumn(\"primary_byline_id\", \"text\")\n\t\t\t.addColumn(\"created_at\", \"text\", (col) => col.defaultTo(currentTimestamp(conn)))\n\t\t\t.addColumn(\"updated_at\", \"text\", (col) => col.defaultTo(currentTimestamp(conn)))\n\t\t\t.addColumn(\"published_at\", \"text\")\n\t\t\t.addColumn(\"scheduled_at\", \"text\")\n\t\t\t.addColumn(\"deleted_at\", \"text\")\n\t\t\t.addColumn(\"version\", \"integer\", (col) => col.defaultTo(1))\n\t\t\t.addColumn(\"live_revision_id\", \"text\", (col) => col.references(\"revisions.id\"))\n\t\t\t.addColumn(\"draft_revision_id\", \"text\", (col) => col.references(\"revisions.id\"))\n\t\t\t.addColumn(\"locale\", \"text\", (col) => col.notNull().defaultTo(\"en\"))\n\t\t\t.addColumn(\"translation_group\", \"text\");\n\t\tif (options.ifNotExists) table = table.ifNotExists();\n\n\t\tfor (const field of fields) {\n\t\t\tif (isStoragelessField(field)) continue;\n\n\t\t\tconst columnName = this.getColumnName(field.slug);\n\t\t\tconst columnType = COLUMN_TYPE_TO_DATA_TYPE[FIELD_TYPE_TO_COLUMN[field.type]];\n\t\t\ttable = table.addColumn(columnName, columnType, (column) => {\n\t\t\t\tif (field.type === \"blocks\") return column.notNull().defaultTo(\"[]\");\n\t\t\t\tif (!field.required) return column;\n\n\t\t\t\tconst defaultValue =\n\t\t\t\t\tfield.defaultValue !== undefined\n\t\t\t\t\t\t? this.formatDefaultValue(field.defaultValue, field.type)\n\t\t\t\t\t\t: this.getEmptyDefault(field.type);\n\t\t\t\treturn column.notNull().defaultTo(sql.raw(defaultValue));\n\t\t\t});\n\t\t}\n\n\t\tawait table\n\t\t\t.addUniqueConstraint(`${tableName}_slug_locale_unique`, [\"slug\", \"locale\"])\n\t\t\t.execute();\n\n\t\tconst createIndex = options.ifNotExists ? sql`CREATE INDEX IF NOT EXISTS` : sql`CREATE INDEX`;\n\t\tconst createUniqueIndex = options.ifNotExists\n\t\t\t? sql`CREATE UNIQUE INDEX IF NOT EXISTS`\n\t\t\t: sql`CREATE UNIQUE INDEX`;\n\n\t\t// Create standard indexes\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_slug`)}\n\t\t\tON ${sql.ref(tableName)} (slug)\n\t\t`.execute(conn);\n\n\t\t// Name must stay identical to migration 074. `deleted_at` leads so the\n\t\t// scheduled-publishing sweep can seek it and walk `scheduled_at` for both\n\t\t// its range and its ORDER BY; a `scheduled_at`-only index leaves a\n\t\t// stats-blind planner reading every live row.\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_del_sched`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, scheduled_at)\n\t\t\tWHERE scheduled_at IS NOT NULL\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_live_revision`)}\n\t\t\tON ${sql.ref(tableName)} (live_revision_id)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_draft_revision`)}\n\t\t\tON ${sql.ref(tableName)} (draft_revision_id)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_author`)}\n\t\t\tON ${sql.ref(tableName)} (author_id)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_primary_byline`)}\n\t\t\tON ${sql.ref(tableName)} (primary_byline_id)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_locale`)}\n\t\t\tON ${sql.ref(tableName)} (locale)\n\t\t`.execute(conn);\n\n\t\t// Names must stay identical to migration 055, which creates these indexes\n\t\t// on tables that already exist. Lookups that don't constrain `deleted_at`\n\t\t// (menu and reference resolution) need the first; reads that do need the\n\t\t// second.\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_tg_locale`)}\n\t\t\tON ${sql.ref(tableName)} (translation_group, locale)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_del_tg_locale`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, translation_group, locale)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createUniqueIndex} ${sql.ref(`uidx_${tableName}_active_tg_locale`)}\n\t\t\tON ${sql.ref(tableName)} (translation_group, lower(locale))\n\t\t\tWHERE deleted_at IS NULL AND translation_group IS NOT NULL\n\t\t`.execute(conn);\n\n\t\t// Composite indexes for optimized query performance (see migration 033)\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_deleted_updated_id`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, updated_at DESC, id DESC)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_deleted_status`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, status)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_deleted_created_id`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, created_at DESC, id DESC)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_deleted_published_id`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, published_at DESC, id DESC)\n\t\t`.execute(conn);\n\n\t\t// Locale-aware composite indexes for i18n content lists (see migration 041).\n\t\t// Short `loc_upd`/`loc_crt` suffix keeps the updated/created discriminator\n\t\t// inside Postgres's 63-byte identifier limit for long slugs; keep these\n\t\t// names identical to migration 041.\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_loc_upd`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, locale, updated_at DESC, id DESC)\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\t${createIndex} ${sql.ref(`idx_${tableName}_loc_crt`)}\n\t\t\tON ${sql.ref(tableName)} (deleted_at, locale, created_at DESC, id DESC)\n\t\t`.execute(conn);\n\t}\n\n\tprivate getFieldIndexName(fieldId: string): string {\n\t\tif (!FIELD_ID_PATTERN.test(fieldId)) {\n\t\t\tthrow new SchemaError(`Invalid field id \"${fieldId}\"`, \"INVALID_FIELD_ID\");\n\t\t}\n\t\treturn `idx_cf_${fieldId.toLowerCase()}`;\n\t}\n\n\tprivate getLocaleFieldIndexName(fieldId: string): string {\n\t\treturn `${this.getFieldIndexName(fieldId)}_loc`;\n\t}\n\n\tprivate async createFieldIndex(\n\t\tcollectionSlug: string,\n\t\tfieldId: string,\n\t\tfieldSlug: string,\n\t\tdb?: Kysely<Database>,\n\t): Promise<void> {\n\t\tconst conn = db ?? this.db;\n\t\tconst tableName = this.getTableName(collectionSlug);\n\t\tconst columnName = this.getColumnName(fieldSlug);\n\t\tconst indexName = this.getFieldIndexName(fieldId);\n\t\tconst localeIndexName = this.getLocaleFieldIndexName(fieldId);\n\n\t\tawait sql`\n\t\t\tCREATE INDEX IF NOT EXISTS ${sql.ref(indexName)}\n\t\t\tON ${sql.ref(tableName)} (\n\t\t\t\t(${sql.ref(columnName)} IS NOT NULL),\n\t\t\t\t${sql.ref(columnName)},\n\t\t\t\tid\n\t\t\t)\n\t\t\tWHERE deleted_at IS NULL\n\t\t`.execute(conn);\n\n\t\tawait sql`\n\t\t\tCREATE INDEX IF NOT EXISTS ${sql.ref(localeIndexName)}\n\t\t\tON ${sql.ref(tableName)} (\n\t\t\t\tlocale,\n\t\t\t\t(${sql.ref(columnName)} IS NOT NULL),\n\t\t\t\t${sql.ref(columnName)},\n\t\t\t\tid\n\t\t\t)\n\t\t\tWHERE deleted_at IS NULL\n\t\t`.execute(conn);\n\t}\n\n\tprivate async dropFieldIndex(fieldId: string, db?: Kysely<Database>): Promise<void> {\n\t\tconst conn = db ?? this.db;\n\t\tawait sql`DROP INDEX IF EXISTS ${sql.ref(this.getFieldIndexName(fieldId))}`.execute(conn);\n\t\tawait sql`DROP INDEX IF EXISTS ${sql.ref(this.getLocaleFieldIndexName(fieldId))}`.execute(conn);\n\t}\n\n\t/**\n\t * Add a column to a content table\n\t */\n\tprivate async addColumn(\n\t\tcollectionSlug: string,\n\t\tfieldSlug: string,\n\t\tfieldType: FieldType,\n\t\toptions?: { required?: boolean; defaultValue?: unknown },\n\t\tdb?: Kysely<Database>,\n\t): Promise<void> {\n\t\tconst conn = db ?? this.db;\n\t\tconst tableName = this.getTableName(collectionSlug);\n\t\tconst columnType = FIELD_TYPE_TO_COLUMN[fieldType];\n\t\tconst columnName = this.getColumnName(fieldSlug);\n\n\t\t// Build ALTER TABLE statement\n\t\t// Note: SQLite requires DEFAULT for NOT NULL columns in ALTER TABLE\n\t\tif (fieldType === \"blocks\") {\n\t\t\tawait sql`\n\t\t\t\tALTER TABLE ${sql.ref(tableName)}\n\t\t\t\tADD COLUMN ${sql.ref(columnName)} ${sql.raw(columnType)} NOT NULL DEFAULT '[]'\n\t\t\t`.execute(conn);\n\t\t} else if (options?.required && options?.defaultValue !== undefined) {\n\t\t\tconst defaultVal = this.formatDefaultValue(options.defaultValue, fieldType);\n\t\t\tawait sql`\n\t\t\t\tALTER TABLE ${sql.ref(tableName)}\n\t\t\t\tADD COLUMN ${sql.ref(columnName)} ${sql.raw(columnType)} NOT NULL DEFAULT ${sql.raw(defaultVal)}\n\t\t\t`.execute(conn);\n\t\t} else if (options?.required) {\n\t\t\t// For required fields without default, use empty string/0 as default\n\t\t\tconst defaultVal = this.getEmptyDefault(fieldType);\n\t\t\tawait sql`\n\t\t\t\tALTER TABLE ${sql.ref(tableName)}\n\t\t\t\tADD COLUMN ${sql.ref(columnName)} ${sql.raw(columnType)} NOT NULL DEFAULT ${sql.raw(defaultVal)}\n\t\t\t`.execute(conn);\n\t\t} else {\n\t\t\tawait sql`\n\t\t\t\tALTER TABLE ${sql.ref(tableName)}\n\t\t\t\tADD COLUMN ${sql.ref(columnName)} ${sql.raw(columnType)}\n\t\t\t`.execute(conn);\n\t\t}\n\t}\n\n\t/**\n\t * Drop a column from a content table\n\t */\n\tprivate async dropColumn(\n\t\tcollectionSlug: string,\n\t\tfieldSlug: string,\n\t\tdb?: Kysely<Database>,\n\t): Promise<void> {\n\t\tconst tableName = this.getTableName(collectionSlug);\n\t\tconst columnName = this.getColumnName(fieldSlug);\n\n\t\tawait sql`\n\t\t\tALTER TABLE ${sql.ref(tableName)}\n\t\t\tDROP COLUMN ${sql.ref(columnName)}\n\t\t`.execute(db ?? this.db);\n\t}\n\n\t// ============================================\n\t// Helpers\n\t// ============================================\n\n\t/**\n\t * Check if a collection has any content\n\t */\n\tprivate async collectionHasContent(\n\t\tslug: string,\n\t\tdb: Kysely<Database> = this.db,\n\t): Promise<boolean> {\n\t\tconst tableName = this.getTableName(slug);\n\t\ttry {\n\t\t\tconst result = await sql<{ count: number }>`\n\t\t\t\tSELECT COUNT(*) as count FROM ${sql.ref(tableName)}\n\t\t\t\tWHERE deleted_at IS NULL\n\t\t\t`.execute(db);\n\t\t\treturn (result.rows[0]?.count ?? 0) > 0;\n\t\t} catch {\n\t\t\t// Table might not exist\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate async normalizeBlocksFieldValidation(\n\t\tcollectionSlug: string,\n\t\tinput: CreateFieldInput,\n\t\texisting: Field | undefined,\n\t\tdb: Kysely<Database>,\n\t\tcheckContent = true,\n\t): Promise<FieldValidation> {\n\t\tif (input.required) {\n\t\t\tthrow new SchemaError(\"Blocks fields cannot be required\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"required\",\n\t\t\t});\n\t\t}\n\t\tif (input.unique) {\n\t\t\tthrow new SchemaError(\"Blocks fields cannot be unique\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"unique\",\n\t\t\t});\n\t\t}\n\t\tif (input.indexed) {\n\t\t\tthrow new SchemaError(\"Blocks fields cannot be indexed\", \"FIELD_NOT_INDEXABLE\", {\n\t\t\t\tpath: \"indexed\",\n\t\t\t});\n\t\t}\n\t\tif (input.searchable) {\n\t\t\tthrow new SchemaError(\"Blocks fields cannot be searchable\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"searchable\",\n\t\t\t});\n\t\t}\n\t\tif (input.widget !== undefined) {\n\t\t\tthrow new SchemaError(\"Blocks fields cannot use custom widgets\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"widget\",\n\t\t\t});\n\t\t}\n\t\tif (input.options !== undefined) {\n\t\t\tthrow new SchemaError(\"Blocks fields do not accept widget options\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"options\",\n\t\t\t});\n\t\t}\n\t\tif (\n\t\t\tinput.defaultValue !== undefined &&\n\t\t\t(!Array.isArray(input.defaultValue) || input.defaultValue.length > 0)\n\t\t) {\n\t\t\tthrow new SchemaError(\"Blocks field defaults must be an empty array\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"defaultValue\",\n\t\t\t});\n\t\t}\n\n\t\tconst requested = input.validation ?? existing?.validation ?? {};\n\t\tconst allowedTypes = requested.allowedTypes ?? [];\n\t\tif (!Array.isArray(allowedTypes) || allowedTypes.some((slug) => typeof slug !== \"string\")) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t\"allowedTypes must be an array of block type slugs\",\n\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t{\n\t\t\t\t\tpath: \"validation.allowedTypes\",\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tif (new Set(allowedTypes).size !== allowedTypes.length) {\n\t\t\tthrow new SchemaError(\"allowedTypes must not contain duplicates\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"validation.allowedTypes\",\n\t\t\t});\n\t\t}\n\n\t\tconst previousAllowed = existing?.validation?.allowedTypes ?? [];\n\t\tconst previousRetired = existing?.validation?.retiredTypes ?? [];\n\t\tconst requestedRetired = existing ? previousRetired : (requested.retiredTypes ?? []);\n\t\tif (\n\t\t\t!Array.isArray(requestedRetired) ||\n\t\t\trequestedRetired.some((slug) => typeof slug !== \"string\")\n\t\t) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t\"retiredTypes must be an array of block type slugs\",\n\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t{\n\t\t\t\t\tpath: \"validation.retiredTypes\",\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tconst retiredTypes = [\n\t\t\t...new Set([\n\t\t\t\t...requestedRetired,\n\t\t\t\t...previousAllowed.filter((slug) => !allowedTypes.includes(slug)),\n\t\t\t]),\n\t\t].filter((slug) => !allowedTypes.includes(slug));\n\n\t\tconst minItems = requested.minItems ?? 0;\n\t\tconst maxItems = requested.maxItems ?? MAX_BLOCKS_ITEMS;\n\t\tif (!Number.isInteger(minItems) || minItems < 0) {\n\t\t\tthrow new SchemaError(\"minItems must be a non-negative integer\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"validation.minItems\",\n\t\t\t});\n\t\t}\n\t\tif (!Number.isInteger(maxItems) || maxItems < 1 || maxItems > MAX_BLOCKS_ITEMS) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`maxItems must be an integer between 1 and ${MAX_BLOCKS_ITEMS}`,\n\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t{ path: \"validation.maxItems\" },\n\t\t\t);\n\t\t}\n\t\tif (minItems > maxItems) {\n\t\t\tthrow new SchemaError(\"minItems cannot exceed maxItems\", \"VALIDATION_ERROR\", {\n\t\t\t\tpath: \"validation.minItems\",\n\t\t\t});\n\t\t}\n\t\tconst previousMin = existing?.validation?.minItems ?? 0;\n\t\tif (\n\t\t\tcheckContent &&\n\t\t\tminItems > previousMin &&\n\t\t\tminItems > 0 &&\n\t\t\t(await this.collectionHasContent(collectionSlug, db))\n\t\t) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t\"Raising minItems on a populated collection requires a content migration\",\n\t\t\t\t\"FIELD_UPDATE_REQUIRES_MIGRATION\",\n\t\t\t\t{ path: \"validation.minItems\" },\n\t\t\t);\n\t\t}\n\n\t\tconst referenced = [...new Set([...allowedTypes, ...retiredTypes])];\n\t\tif (referenced.length > 0) {\n\t\t\tconst types = await db\n\t\t\t\t.selectFrom(\"_emdash_block_types\")\n\t\t\t\t.select([\"id\", \"slug\", \"current_version\"])\n\t\t\t\t.where(\"slug\", \"in\", referenced)\n\t\t\t\t.execute();\n\t\t\tconst bySlug = new Map(types.map((type) => [type.slug, type]));\n\t\t\tfor (const slug of referenced) {\n\t\t\t\tif (!bySlug.has(slug)) {\n\t\t\t\t\tthrow new SchemaError(`Block type \"${slug}\" not found`, \"BLOCK_TYPE_NOT_FOUND\", {\n\t\t\t\t\t\tslug,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst allowedRows = allowedTypes.map((slug) => bySlug.get(slug)!);\n\t\t\tif (allowedRows.length > 0) {\n\t\t\t\tconst activeVersions = await db\n\t\t\t\t\t.selectFrom(\"_emdash_block_type_versions\")\n\t\t\t\t\t.select([\"block_type_id\", \"version\"])\n\t\t\t\t\t.where(\n\t\t\t\t\t\t\"block_type_id\",\n\t\t\t\t\t\t\"in\",\n\t\t\t\t\t\tallowedRows.map((type) => type.id),\n\t\t\t\t\t)\n\t\t\t\t\t.execute();\n\t\t\t\tfor (const type of allowedRows) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!activeVersions.some(\n\t\t\t\t\t\t\t(version) =>\n\t\t\t\t\t\t\t\tversion.block_type_id === type.id && version.version === type.current_version,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new SchemaError(\n\t\t\t\t\t\t\t`Block type \"${type.slug}\" has no active version ${type.current_version}`,\n\t\t\t\t\t\t\t\"BLOCK_TYPE_VERSION_CONFLICT\",\n\t\t\t\t\t\t\t{ slug: type.slug, version: type.current_version },\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { allowedTypes, retiredTypes, minItems, maxItems };\n\t}\n\n\t/**\n\t * Get table name for a collection\n\t */\n\tprivate getTableName(slug: string): string {\n\t\tvalidateIdentifier(slug, \"collection slug\");\n\t\treturn `ec_${slug}`;\n\t}\n\n\t/**\n\t * Get column name for a field\n\t */\n\tprivate getColumnName(slug: string): string {\n\t\tvalidateIdentifier(slug, \"field slug\");\n\t\treturn slug;\n\t}\n\n\t/**\n\t * Validate a slug\n\t */\n\tprivate validateSlug(slug: string, type: \"collection\" | \"field\"): void {\n\t\tif (!slug || typeof slug !== \"string\") {\n\t\t\tthrow new SchemaError(`${type} slug is required`, \"INVALID_SLUG\");\n\t\t}\n\n\t\tif (!SLUG_VALIDATION_PATTERN.test(slug)) {\n\t\t\tthrow new SchemaError(\n\t\t\t\t`${type} slug must start with a letter and contain only lowercase letters, numbers, and underscores`,\n\t\t\t\t\"INVALID_SLUG\",\n\t\t\t);\n\t\t}\n\n\t\tif (slug.length > 63) {\n\t\t\tthrow new SchemaError(`${type} slug must be 63 characters or less`, \"INVALID_SLUG\");\n\t\t}\n\t}\n\n\t/**\n\t * Format a default value for SQL.\n\t *\n\t * SQLite `ALTER TABLE ADD COLUMN ... DEFAULT` requires a literal constant\n\t * expression — parameterized values cannot be used here. We manually escape\n\t * single quotes and coerce types to ensure the output is safe.\n\t *\n\t * INTEGER/REAL values are coerced through `Number()` which can only produce\n\t * digits, `.`, `-`, `e`, `Infinity`, or `NaN` — all safe in SQL.\n\t * TEXT/JSON values have single quotes escaped via SQL standard doubling (`''`).\n\t */\n\tprivate formatDefaultValue(value: unknown, fieldType: FieldType): string {\n\t\tif (value === null || value === undefined) {\n\t\t\treturn \"NULL\";\n\t\t}\n\n\t\tconst columnType = FIELD_TYPE_TO_COLUMN[fieldType];\n\n\t\tif (columnType === \"JSON\") {\n\t\t\t// JSON.stringify produces valid JSON; escape single quotes for SQL literal\n\t\t\tconst json = JSON.stringify(value);\n\t\t\treturn `'${json.replace(SINGLE_QUOTE_PATTERN, \"''\")}'`;\n\t\t}\n\n\t\tif (columnType === \"INTEGER\") {\n\t\t\tif (typeof value === \"boolean\") {\n\t\t\t\treturn value ? \"1\" : \"0\";\n\t\t\t}\n\t\t\tconst num = Number(value);\n\t\t\tif (!Number.isFinite(num)) {\n\t\t\t\treturn \"0\";\n\t\t\t}\n\t\t\treturn String(Math.trunc(num));\n\t\t}\n\n\t\tif (columnType === \"REAL\") {\n\t\t\tconst num = Number(value);\n\t\t\tif (!Number.isFinite(num)) {\n\t\t\t\treturn \"0\";\n\t\t\t}\n\t\t\treturn String(num);\n\t\t}\n\n\t\t// TEXT — escape single quotes via SQL standard doubling\n\t\tlet text: string;\n\t\tif (typeof value === \"string\") {\n\t\t\ttext = value;\n\t\t} else if (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\t\ttext = String(value);\n\t\t} else if (typeof value === \"object\" && value !== null) {\n\t\t\ttext = JSON.stringify(value);\n\t\t} else {\n\t\t\ttext = \"\";\n\t\t}\n\t\treturn `'${text.replace(SINGLE_QUOTE_PATTERN, \"''\")}'`;\n\t}\n\n\t/**\n\t * Get empty default for a field type\n\t */\n\tprivate getEmptyDefault(fieldType: FieldType): string {\n\t\tif (fieldType === \"blocks\") return \"'[]'\";\n\t\tconst columnType = FIELD_TYPE_TO_COLUMN[fieldType];\n\n\t\tswitch (columnType) {\n\t\t\tcase \"INTEGER\":\n\t\t\t\treturn \"0\";\n\t\t\tcase \"REAL\":\n\t\t\t\treturn \"0.0\";\n\t\t\tcase \"JSON\":\n\t\t\t\treturn \"'null'\";\n\t\t\tdefault:\n\t\t\t\treturn \"''\";\n\t\t}\n\t}\n\n\t/**\n\t * Map a collection row to a Collection object\n\t */\n\tprivate mapCollectionRow = (row: Selectable<CollectionTable>): Collection => {\n\t\tconst moderation = row.comments_moderation;\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tslug: row.slug,\n\t\t\tlabel: row.label,\n\t\t\tlabelSingular: row.label_singular ?? undefined,\n\t\t\tdescription: row.description ?? undefined,\n\t\t\ticon: row.icon ?? undefined,\n\t\t\tadmin: parseCollectionAdmin(row.admin_config),\n\t\t\tsupports: parseSupports(row.supports),\n\t\t\tsource: row.source && isCollectionSource(row.source) ? row.source : undefined,\n\t\t\thasSeo: row.has_seo === 1,\n\t\t\t// Raw value; undefined when unset. The admin list resolves the\n\t\t\t// default (title fallback chain / updatedAt) at the point of use.\n\t\t\ttitleField: row.title_field ?? undefined,\n\t\t\tdateField: row.date_field ?? undefined,\n\t\t\turlPattern: row.url_pattern ?? undefined,\n\t\t\troutable: row.routable !== 0,\n\t\t\thidden: row.hidden === 1,\n\t\t\tsortOrder: row.sort_order ?? undefined,\n\t\t\tgroup: row.nav_group ?? undefined,\n\t\t\tcommentsEnabled: row.comments_enabled === 1,\n\t\t\tcommentsModeration:\n\t\t\t\tmoderation === \"all\" || moderation === \"first_time\" || moderation === \"none\"\n\t\t\t\t\t? moderation\n\t\t\t\t\t: \"first_time\",\n\t\t\tcommentsClosedAfterDays: row.comments_closed_after_days ?? 90,\n\t\t\tcommentsAutoApproveUsers: row.comments_auto_approve_users === 1,\n\t\t\teditLocking: row.edit_locking !== 0,\n\t\t\tcreatedAt: row.created_at,\n\t\t\tupdatedAt: row.updated_at,\n\t\t};\n\t};\n\n\t/**\n\t * Map a field row to a Field object\n\t */\n\tprivate mapFieldRow = (row: Selectable<FieldTable>): Field => {\n\t\tconst validation = row.validation ? JSON.parse(row.validation) : undefined;\n\t\tconst unsupportedType = isFieldType(row.type)\n\t\t\t? row.type === \"repeater\"\n\t\t\t\t? findUnsupportedRepeaterSubFieldType(validation)\n\t\t\t\t: undefined\n\t\t\t: { type: row.type, path: \"type\" };\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tcollectionId: row.collection_id,\n\t\t\tslug: row.slug,\n\t\t\tlabel: row.label,\n\t\t\ttype: isFieldType(row.type) ? row.type : \"string\",\n\t\t\tunsupportedType,\n\t\t\tcolumnType: isColumnType(row.column_type) ? row.column_type : \"TEXT\",\n\t\t\trequired: row.required === 1,\n\t\t\tunique: row.unique === 1,\n\t\t\tdefaultValue: row.default_value ? JSON.parse(row.default_value) : undefined,\n\t\t\tvalidation,\n\t\t\twidget: row.widget ?? undefined,\n\t\t\toptions: row.options ? JSON.parse(row.options) : undefined,\n\t\t\tsortOrder: row.sort_order,\n\t\t\tsearchable: row.searchable === 1,\n\t\t\tindexed: row.indexed === 1,\n\t\t\ttranslatable: row.translatable !== 0,\n\t\t\tcreatedAt: row.created_at,\n\t\t};\n\t};\n\n\t// ============================================\n\t// Discovery\n\t// ============================================\n\n\t/**\n\t * Discover orphaned content tables\n\t *\n\t * Finds ec_* tables that exist in the database but don't have a\n\t * corresponding entry in _emdash_collections.\n\t */\n\tasync discoverOrphanedTables(): Promise<\n\t\tArray<{ slug: string; tableName: string; rowCount: number }>\n\t> {\n\t\t// Get all ec_* tables\n\t\t// Content tables are ec_* (e.g., ec_posts, ec_pages)\n\t\t// Internal tables are _emdash_* (e.g., _emdash_collections, _emdash_fts_posts)\n\t\tconst allTables = await listTablesLike(this.db, \"ec_%\");\n\n\t\t// Get registered collections\n\t\tconst registered = await this.listCollections();\n\t\tconst registeredSlugs = new Set(registered.map((c) => c.slug));\n\n\t\t// Find orphans\n\t\tconst orphans: Array<{\n\t\t\tslug: string;\n\t\t\ttableName: string;\n\t\t\trowCount: number;\n\t\t}> = [];\n\n\t\tfor (const tableName of allTables) {\n\t\t\tconst slug = tableName.replace(EC_PREFIX_PATTERN, \"\");\n\n\t\t\tif (!registeredSlugs.has(slug)) {\n\t\t\t\t// Count rows in the orphaned table\n\t\t\t\ttry {\n\t\t\t\t\tconst countResult = await sql<{ count: number }>`\n\t\t\t\t\t\tSELECT COUNT(*) as count FROM ${sql.ref(tableName)}\n\t\t\t\t\t\tWHERE deleted_at IS NULL\n\t\t\t\t\t`.execute(this.db);\n\n\t\t\t\t\torphans.push({\n\t\t\t\t\t\tslug,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\trowCount: countResult.rows[0]?.count ?? 0,\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\t// Table might have unexpected schema, still report it\n\t\t\t\t\torphans.push({\n\t\t\t\t\t\tslug,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\trowCount: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn orphans;\n\t}\n\n\t/**\n\t * Register an orphaned table as a collection\n\t *\n\t * Creates a _emdash_collections entry for an existing ec_* table.\n\t */\n\tasync registerOrphanedTable(\n\t\tslug: string,\n\t\toptions?: {\n\t\t\tlabel?: string;\n\t\t\tlabelSingular?: string;\n\t\t\tdescription?: string;\n\t\t},\n\t): Promise<Collection> {\n\t\t// Verify table exists\n\t\tconst tableName = this.getTableName(slug);\n\t\tif (await isMediaUsageCollectionSlugDeleting(this.db, slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${slug}\" is already registered`, \"COLLECTION_EXISTS\");\n\t\t}\n\t\tconst exists = await tableExists(this.db, tableName);\n\n\t\tif (!exists) {\n\t\t\tthrow new SchemaError(`Table \"${tableName}\" does not exist`, \"TABLE_NOT_FOUND\");\n\t\t}\n\n\t\t// Check if already registered\n\t\tconst existing = await this.getCollection(slug);\n\t\tif (await isMediaUsageCollectionSlugDeleting(this.db, slug)) {\n\t\t\tthrow new SchemaError(`Collection \"${slug}\" is already registered`, \"COLLECTION_EXISTS\");\n\t\t}\n\t\tif (\n\t\t\texisting &&\n\t\t\t!(await canResumeMediaUsageCollectionCapture(this.db, {\n\t\t\t\tcollectionId: existing.id,\n\t\t\t\tcollectionSlug: existing.slug,\n\t\t\t}))\n\t\t) {\n\t\t\tthrow new SchemaError(`Collection \"${slug}\" is already registered`, \"COLLECTION_EXISTS\");\n\t\t}\n\n\t\t// Create collection entry\n\t\tconst proposedId = existing?.id ?? ulid();\n\t\tconst label = options?.label || this.slugToLabel(slug);\n\n\t\tlet collectionRegistered = false;\n\t\ttry {\n\t\t\tconst capture = await prepareMediaUsageCollectionCapture(this.db, {\n\t\t\t\tcollectionId: proposedId,\n\t\t\t\tcollectionSlug: slug,\n\t\t\t\tregisteredCollectionId: existing?.id,\n\t\t\t});\n\t\t\tif (capture.captureRequired) {\n\t\t\t\tawait installPreparedMediaUsageCollectionCapture(this.db, {\n\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\tcollectionSlug: slug,\n\t\t\t\t});\n\t\t\t\tawait markMediaUsageCollectionCaptureReady(this.db, {\n\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\tcollectionSlug: slug,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!capture.registrationExists) {\n\t\t\t\tawait this.db\n\t\t\t\t\t.insertInto(\"_emdash_collections\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tid: capture.collectionId,\n\t\t\t\t\t\tslug,\n\t\t\t\t\t\tlabel,\n\t\t\t\t\t\tlabel_singular: options?.labelSingular ?? null,\n\t\t\t\t\t\tdescription: options?.description ?? null,\n\t\t\t\t\t\ticon: null,\n\t\t\t\t\t\tsupports: JSON.stringify([]),\n\t\t\t\t\t\tsource: \"discovered\",\n\t\t\t\t\t\thas_seo: 0,\n\t\t\t\t\t\turl_pattern: null,\n\t\t\t\t\t})\n\t\t\t\t\t.execute();\n\t\t\t\tcollectionRegistered = true;\n\t\t\t}\n\t\t\tif (capture.captureRequired) {\n\t\t\t\tawait finalizeMediaUsageCollectionCapture(this.db, {\n\t\t\t\t\tcollectionId: capture.collectionId,\n\t\t\t\t\tcollectionSlug: slug,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst collection = await this.getCollection(slug);\n\t\t\tif (!collection) {\n\t\t\t\tthrow new SchemaError(\"Failed to register orphaned table\", \"REGISTER_FAILED\");\n\t\t\t}\n\t\t\tawait markContentMediaUsageCollectionStaleSafely(this.db, slug, \"CONTENT_USAGE_STALE\");\n\t\t\tthis.notifyTypegen();\n\n\t\t\treturn collection;\n\t\t} catch (error) {\n\t\t\tif (collectionRegistered) {\n\t\t\t\tawait markContentMediaUsageCollectionStaleSafely(this.db, slug, \"CONTENT_USAGE_STALE\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Convert slug to human-readable label\n\t */\n\tprivate slugToLabel(slug: string): string {\n\t\treturn slug\n\t\t\t.replace(UNDERSCORE_PATTERN, \" \")\n\t\t\t.replace(WORD_BOUNDARY_PATTERN, (c) => c.toUpperCase());\n\t}\n}\n"],"mappings":"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"}