emdash 0.35.0 → 0.36.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 (763) hide show
  1. package/dist/activation-K0kGBWuJ.mjs +382 -0
  2. package/dist/activation-K0kGBWuJ.mjs.map +1 -0
  3. package/dist/{adapters-Bb1vG41D.d.mts → adapters-CzL3H752.d.mts} +3 -3
  4. package/dist/{adapters-Bb1vG41D.d.mts.map → adapters-CzL3H752.d.mts.map} +1 -1
  5. package/dist/{allowed-origins-DW7sYyqg.mjs → allowed-origins-maylGaHv.mjs} +2 -2
  6. package/dist/{allowed-origins-DW7sYyqg.mjs.map → allowed-origins-maylGaHv.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +22 -20
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +2 -2
  11. package/dist/api/schemas/index.mjs +5 -5
  12. package/dist/api-B0w3uBiG.mjs +2269 -0
  13. package/dist/api-B0w3uBiG.mjs.map +1 -0
  14. package/dist/{api-tokens-KO24G1Fd.mjs → api-tokens-9YrrCoE6.mjs} +2 -2
  15. package/dist/{api-tokens-KO24G1Fd.mjs.map → api-tokens-9YrrCoE6.mjs.map} +1 -1
  16. package/dist/{apply-kUDt80-G.mjs → apply-B_VMpJ2P.mjs} +34 -35
  17. package/dist/{apply-kUDt80-G.mjs.map → apply-B_VMpJ2P.mjs.map} +1 -1
  18. package/dist/astro/index.d.mts +12 -12
  19. package/dist/astro/index.mjs +26 -15
  20. package/dist/astro/index.mjs.map +1 -1
  21. package/dist/astro/middleware/auth.d.mts +10 -10
  22. package/dist/astro/middleware/auth.d.mts.map +1 -1
  23. package/dist/astro/middleware/auth.mjs +10 -7
  24. package/dist/astro/middleware/auth.mjs.map +1 -1
  25. package/dist/astro/middleware/media-usage-write-fence.mjs +2 -2
  26. package/dist/astro/middleware/redirect.mjs +4 -4
  27. package/dist/astro/middleware/request-context.mjs +3 -3
  28. package/dist/astro/middleware/setup.mjs +1 -1
  29. package/dist/astro/middleware.d.mts +11 -12
  30. package/dist/astro/middleware.d.mts.map +1 -1
  31. package/dist/astro/middleware.mjs +168 -1305
  32. package/dist/astro/middleware.mjs.map +1 -1
  33. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
  34. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
  35. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
  36. package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
  37. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  38. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -9
  39. package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -9
  40. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -9
  41. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +15 -15
  42. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +15 -15
  43. package/dist/astro/routes/api/admin/bylines/index.mjs +15 -15
  44. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +12 -12
  45. package/dist/astro/routes/api/admin/comments/_id_.mjs +4 -4
  46. package/dist/astro/routes/api/admin/comments/bulk.mjs +9 -9
  47. package/dist/astro/routes/api/admin/comments/counts.mjs +4 -4
  48. package/dist/astro/routes/api/admin/comments/index.mjs +9 -9
  49. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  50. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  51. package/dist/astro/routes/api/admin/media-usage/activation.d.mts +9 -0
  52. package/dist/astro/routes/api/admin/media-usage/activation.d.mts.map +1 -0
  53. package/dist/astro/routes/api/admin/media-usage/activation.mjs +46 -0
  54. package/dist/astro/routes/api/admin/media-usage/activation.mjs.map +1 -0
  55. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +14 -13
  56. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +14 -13
  58. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/media-usage/progress.d.mts +9 -0
  60. package/dist/astro/routes/api/admin/media-usage/progress.d.mts.map +1 -0
  61. package/dist/astro/routes/api/admin/media-usage/progress.mjs +44 -0
  62. package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -0
  63. package/dist/astro/routes/api/admin/media-usage/repair.mjs +16 -11
  64. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  65. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +14 -13
  66. package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +14 -13
  68. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  70. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  71. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +54 -48
  72. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +54 -48
  74. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +52 -46
  76. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
  78. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +52 -46
  79. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +53 -47
  81. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +53 -47
  83. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/index.mjs +52 -46
  85. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  87. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +52 -46
  88. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +53 -47
  90. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +52 -46
  92. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +53 -47
  94. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +54 -48
  96. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  97. package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +172 -133
  99. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +54 -48
  101. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/plugins/updates.mjs +52 -46
  103. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  104. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +52 -46
  105. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  106. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  107. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +52 -46
  108. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  109. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  110. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  111. package/dist/astro/routes/api/admin/users/_id_/index.mjs +7 -7
  112. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  113. package/dist/astro/routes/api/admin/users/index.mjs +6 -6
  114. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  115. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  116. package/dist/astro/routes/api/auth/invite/complete.mjs +11 -11
  117. package/dist/astro/routes/api/auth/invite/index.mjs +8 -8
  118. package/dist/astro/routes/api/auth/invite/register-options.mjs +10 -10
  119. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  120. package/dist/astro/routes/api/auth/magic-link/send.mjs +10 -10
  121. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  122. package/dist/astro/routes/api/auth/me.d.mts.map +1 -1
  123. package/dist/astro/routes/api/auth/me.mjs +19 -9
  124. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  125. package/dist/astro/routes/api/auth/mode.mjs +2 -2
  126. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  127. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  128. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
  129. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  130. package/dist/astro/routes/api/auth/passkey/options.mjs +12 -12
  131. package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -10
  132. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -11
  133. package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -11
  134. package/dist/astro/routes/api/auth/signup/complete.mjs +11 -11
  135. package/dist/astro/routes/api/auth/signup/request.mjs +10 -10
  136. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  137. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +13 -13
  138. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +12 -12
  139. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  140. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  141. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  142. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
  143. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -11
  144. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
  145. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +16 -14
  146. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  147. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +16 -14
  148. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  149. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  150. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  151. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  152. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +13 -13
  153. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  154. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  155. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  156. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  157. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  158. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
  159. package/dist/astro/routes/api/dashboard.mjs +7 -7
  160. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  161. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  162. package/dist/astro/routes/api/import/probe.mjs +16 -16
  163. package/dist/astro/routes/api/import/wordpress/analyze.mjs +2 -2
  164. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  165. package/dist/astro/routes/api/import/wordpress/execute.mjs +12 -12
  166. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  167. package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
  168. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
  169. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  170. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +12 -10
  171. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  172. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  173. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +16 -16
  174. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  175. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +26 -26
  176. package/dist/astro/routes/api/manifest.mjs +4 -4
  177. package/dist/astro/routes/api/mcp.mjs +42 -42
  178. package/dist/astro/routes/api/media/_id_/confirm.mjs +11 -11
  179. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  180. package/dist/astro/routes/api/media/_id_/usage.mjs +18 -13
  181. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  182. package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
  183. package/dist/astro/routes/api/media/_id_.mjs +21 -13
  184. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  185. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  186. package/dist/astro/routes/api/media/folders/_id_.d.mts +10 -0
  187. package/dist/astro/routes/api/media/folders/_id_.d.mts.map +1 -0
  188. package/dist/astro/routes/api/media/folders/_id_.mjs +52 -0
  189. package/dist/astro/routes/api/media/folders/_id_.mjs.map +1 -0
  190. package/dist/astro/routes/api/media/folders/index.d.mts +9 -0
  191. package/dist/astro/routes/api/media/folders/index.d.mts.map +1 -0
  192. package/dist/astro/routes/api/media/folders/index.mjs +41 -0
  193. package/dist/astro/routes/api/media/folders/index.mjs.map +1 -0
  194. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  195. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  196. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  197. package/dist/astro/routes/api/media/upload-url.mjs +9 -9
  198. package/dist/astro/routes/api/media.d.mts.map +1 -1
  199. package/dist/astro/routes/api/media.mjs +28 -19
  200. package/dist/astro/routes/api/media.mjs.map +1 -1
  201. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +8 -8
  202. package/dist/astro/routes/api/menus/_name_/items.mjs +8 -8
  203. package/dist/astro/routes/api/menus/_name_/reorder.mjs +8 -8
  204. package/dist/astro/routes/api/menus/_name_/translations.mjs +8 -8
  205. package/dist/astro/routes/api/menus/_name_.mjs +8 -8
  206. package/dist/astro/routes/api/menus/index.mjs +8 -8
  207. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  208. package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
  209. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  210. package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
  211. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  212. package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
  213. package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
  214. package/dist/astro/routes/api/oauth/token.mjs +5 -5
  215. package/dist/astro/routes/api/openapi.json.mjs +153 -6
  216. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  217. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  218. package/dist/astro/routes/api/redirects/404s/index.mjs +10 -10
  219. package/dist/astro/routes/api/redirects/404s/summary.mjs +10 -10
  220. package/dist/astro/routes/api/redirects/_id_.mjs +11 -11
  221. package/dist/astro/routes/api/redirects/index.mjs +11 -11
  222. package/dist/astro/routes/api/relations/_id_/index.mjs +16 -14
  223. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  224. package/dist/astro/routes/api/relations/_id_/translations.mjs +11 -9
  225. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  226. package/dist/astro/routes/api/relations/index.mjs +16 -14
  227. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  228. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  229. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  230. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +52 -46
  231. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  232. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +52 -46
  233. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  234. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +52 -46
  235. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  236. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +52 -46
  237. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  238. package/dist/astro/routes/api/schema/collections/index.mjs +52 -46
  239. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/schema/collections/reorder.mjs +52 -46
  241. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  242. package/dist/astro/routes/api/schema/index.mjs +10 -8
  243. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  244. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +52 -46
  245. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  246. package/dist/astro/routes/api/schema/orphans/index.mjs +52 -46
  247. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  248. package/dist/astro/routes/api/search/enable.mjs +10 -10
  249. package/dist/astro/routes/api/search/index.mjs +9 -9
  250. package/dist/astro/routes/api/search/rebuild.mjs +10 -10
  251. package/dist/astro/routes/api/search/stats.mjs +5 -5
  252. package/dist/astro/routes/api/search/suggest.mjs +9 -9
  253. package/dist/astro/routes/api/sections/_slug_.mjs +9 -9
  254. package/dist/astro/routes/api/sections/index.mjs +9 -9
  255. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +6 -6
  256. package/dist/astro/routes/api/settings/backups/archives/index.mjs +5 -5
  257. package/dist/astro/routes/api/settings/backups/export.mjs +6 -6
  258. package/dist/astro/routes/api/settings/backups/index.mjs +7 -7
  259. package/dist/astro/routes/api/settings/email.mjs +4 -4
  260. package/dist/astro/routes/api/settings.mjs +13 -13
  261. package/dist/astro/routes/api/setup/admin-verify.mjs +12 -12
  262. package/dist/astro/routes/api/setup/admin.mjs +11 -11
  263. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  264. package/dist/astro/routes/api/setup/dev-bypass.mjs +34 -27
  265. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  266. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  267. package/dist/astro/routes/api/setup/index.mjs +31 -29
  268. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  269. package/dist/astro/routes/api/setup/status.mjs +3 -3
  270. package/dist/astro/routes/api/snapshot.mjs +7 -7
  271. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +13 -13
  272. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +13 -13
  273. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +13 -13
  274. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +13 -13
  275. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +13 -13
  276. package/dist/astro/routes/api/taxonomies/_name_.mjs +13 -13
  277. package/dist/astro/routes/api/taxonomies/index.mjs +13 -13
  278. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  279. package/dist/astro/routes/api/typegen.mjs +4 -4
  280. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  281. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  282. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  283. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +7 -7
  284. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +10 -10
  285. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +10 -10
  286. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  287. package/dist/astro/routes/api/widget-areas/index.mjs +10 -10
  288. package/dist/astro/routes/api/widget-components.mjs +2 -2
  289. package/dist/astro/routes/robots.txt.mjs +6 -6
  290. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  291. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  292. package/dist/astro/types.d.mts +19 -14
  293. package/dist/astro/types.d.mts.map +1 -1
  294. package/dist/auth/providers/github.d.mts +1 -1
  295. package/dist/auth/providers/google.d.mts +1 -1
  296. package/dist/{authorize-DUElxgOQ.mjs → authorize-ByYs-Uxs.mjs} +2 -2
  297. package/dist/{authorize-DUElxgOQ.mjs.map → authorize-ByYs-Uxs.mjs.map} +1 -1
  298. package/dist/{backup-DWYpJlLj.mjs → backup-ChyHfIoX.mjs} +5 -5
  299. package/dist/{backup-DWYpJlLj.mjs.map → backup-ChyHfIoX.mjs.map} +1 -1
  300. package/dist/{bundle-vn56sLos.mjs → bundle-DZFhFurR.mjs} +4 -4
  301. package/dist/{bundle-vn56sLos.mjs.map → bundle-DZFhFurR.mjs.map} +1 -1
  302. package/dist/{byline-yjvWq4ip.mjs → byline-Cpnwrje1.mjs} +6 -6
  303. package/dist/{byline-yjvWq4ip.mjs.map → byline-Cpnwrje1.mjs.map} +1 -1
  304. package/dist/{byline-fields-txaLGoME.mjs → byline-fields-CAyA_Umd.mjs} +2 -2
  305. package/dist/{byline-fields-txaLGoME.mjs.map → byline-fields-CAyA_Umd.mjs.map} +1 -1
  306. package/dist/{byline-registry-DDun8sxh.mjs → byline-registry-Bpu9-MVs.mjs} +2 -2
  307. package/dist/{byline-registry-DDun8sxh.mjs.map → byline-registry-Bpu9-MVs.mjs.map} +1 -1
  308. package/dist/{bylines-DjXS5p0P.mjs → bylines-BSo9B9RX.mjs} +7 -7
  309. package/dist/{bylines-DjXS5p0P.mjs.map → bylines-BSo9B9RX.mjs.map} +1 -1
  310. package/dist/{bylines-Bu7pchQ4.mjs → bylines-CHjvehVX.mjs} +3 -3
  311. package/dist/{bylines-Bu7pchQ4.mjs.map → bylines-CHjvehVX.mjs.map} +1 -1
  312. package/dist/{cache-C46-3Irl.mjs → cache-5VirJ2Cn.mjs} +4 -4
  313. package/dist/{cache-C46-3Irl.mjs.map → cache-5VirJ2Cn.mjs.map} +1 -1
  314. package/dist/capture-triggers-CNW1q3HK.mjs +362 -0
  315. package/dist/capture-triggers-CNW1q3HK.mjs.map +1 -0
  316. package/dist/{challenge-store-SIL5DsF2.mjs → challenge-store-D5pSY2S1.mjs} +1 -1
  317. package/dist/{challenge-store-SIL5DsF2.mjs.map → challenge-store-D5pSY2S1.mjs.map} +1 -1
  318. package/dist/{chunks-fiZ8G9RJ.mjs → chunks-bNiX6_DR.mjs} +2 -2
  319. package/dist/{chunks-fiZ8G9RJ.mjs.map → chunks-bNiX6_DR.mjs.map} +1 -1
  320. package/dist/cli/index.mjs +36 -52
  321. package/dist/cli/index.mjs.map +1 -1
  322. package/dist/client/cf-access.d.mts +1 -1
  323. package/dist/client/index.d.mts +74 -4
  324. package/dist/client/index.d.mts.map +1 -1
  325. package/dist/client/index.mjs +54 -2
  326. package/dist/client/index.mjs.map +1 -1
  327. package/dist/{collection-deletion-DQPvMD8R.mjs → collection-deletion-m_oi2c0N.mjs} +13 -356
  328. package/dist/collection-deletion-m_oi2c0N.mjs.map +1 -0
  329. package/dist/{comment-Dxlep6cE.mjs → comment-DhvLEdhQ.mjs} +1 -1
  330. package/dist/{comment-Dxlep6cE.mjs.map → comment-DhvLEdhQ.mjs.map} +1 -1
  331. package/dist/{comment-reaction-D-2J84UE.mjs → comment-reaction-CRuItEjt.mjs} +2 -2
  332. package/dist/{comment-reaction-D-2J84UE.mjs.map → comment-reaction-CRuItEjt.mjs.map} +1 -1
  333. package/dist/{comments-CTfZtLmM.mjs → comments-CLj4bi8I.mjs} +2 -2
  334. package/dist/{comments-CTfZtLmM.mjs.map → comments-CLj4bi8I.mjs.map} +1 -1
  335. package/dist/{components-CQy3lh9x.mjs → components-v4U4DT2y.mjs} +1 -1
  336. package/dist/{components-CQy3lh9x.mjs.map → components-v4U4DT2y.mjs.map} +1 -1
  337. package/dist/{config-COQzTe5Q.d.mts → config-DrfghTPe.d.mts} +1 -1
  338. package/dist/{config-COQzTe5Q.d.mts.map → config-DrfghTPe.d.mts.map} +1 -1
  339. package/dist/{content-ZHCc1ngN.mjs → content-CP-SeXNa.mjs} +5 -4
  340. package/dist/content-CP-SeXNa.mjs.map +1 -0
  341. package/dist/{content-list-query-wJ2WN8Vp.d.mts → content-list-query-BhejKVqb.d.mts} +1 -1
  342. package/dist/{content-list-query-wJ2WN8Vp.d.mts.map → content-list-query-BhejKVqb.d.mts.map} +1 -1
  343. package/dist/{content-refresh-B_8SJzuU.mjs → content-refresh-DLOfIhYc.mjs} +1094 -93
  344. package/dist/content-refresh-DLOfIhYc.mjs.map +1 -0
  345. package/dist/{media-usage-BZCydfvu.mjs → content-repair-BCxzy0r4.mjs} +5 -196
  346. package/dist/content-repair-BCxzy0r4.mjs.map +1 -0
  347. package/dist/{context-ZldbZcle.mjs → context-BR5hRWiK.mjs} +13 -13
  348. package/dist/{context-ZldbZcle.mjs.map → context-BR5hRWiK.mjs.map} +1 -1
  349. package/dist/{cron-Y9aLtgrA.mjs → cron-CWfWrWKG.mjs} +1 -1
  350. package/dist/{cron-Y9aLtgrA.mjs.map → cron-CWfWrWKG.mjs.map} +1 -1
  351. package/dist/{dashboard-DvHbk_cv.mjs → dashboard-CkIV2rnQ.mjs} +5 -5
  352. package/dist/{dashboard-DvHbk_cv.mjs.map → dashboard-CkIV2rnQ.mjs.map} +1 -1
  353. package/dist/db/index.d.mts +3 -3
  354. package/dist/db/index.mjs +3 -3
  355. package/dist/db/index.mjs.map +1 -1
  356. package/dist/db/libsql-migrations.d.mts +1 -1
  357. package/dist/db/libsql-migrations.mjs +4 -4
  358. package/dist/db/libsql.d.mts +1 -1
  359. package/dist/db/postgres-migrations.d.mts +1 -1
  360. package/dist/db/postgres-migrations.mjs +4 -4
  361. package/dist/db/postgres.d.mts +1 -1
  362. package/dist/db/sqlite-migrations.d.mts +1 -1
  363. package/dist/db/sqlite-migrations.mjs +4 -4
  364. package/dist/db/sqlite.d.mts +1 -1
  365. package/dist/db/sqlite.mjs +3 -3
  366. package/dist/db/sqlite.mjs.map +1 -1
  367. package/dist/{default-DdDl3fxv.mjs → default-YMEfcQUx.mjs} +1 -1
  368. package/dist/{default-DdDl3fxv.mjs.map → default-YMEfcQUx.mjs.map} +1 -1
  369. package/dist/{deferred-tasks-SDWxrgzJ.d.mts → deferred-tasks-DfqxH5Xf.d.mts} +1 -1
  370. package/dist/{deferred-tasks-SDWxrgzJ.d.mts.map → deferred-tasks-DfqxH5Xf.d.mts.map} +1 -1
  371. package/dist/{device-flow-C0GdD_z8.mjs → device-flow-CojjSBwb.mjs} +5 -5
  372. package/dist/{device-flow-C0GdD_z8.mjs.map → device-flow-CojjSBwb.mjs.map} +1 -1
  373. package/dist/{direct-executor-CDXeJCSs.mjs → direct-executor-BWeWiRYB.mjs} +3 -3
  374. package/dist/{direct-executor-CDXeJCSs.mjs.map → direct-executor-BWeWiRYB.mjs.map} +1 -1
  375. package/dist/{dist-D_6CKR8z.mjs → dist-89xCrGqi.mjs} +1 -1
  376. package/dist/{dist-D_6CKR8z.mjs.map → dist-89xCrGqi.mjs.map} +1 -1
  377. package/dist/{email-console-BHNjIwiB.mjs → email-console-CEJgR_LB.mjs} +1 -1
  378. package/dist/{email-console-BHNjIwiB.mjs.map → email-console-CEJgR_LB.mjs.map} +1 -1
  379. package/dist/{enrich-_ySMEvEE.mjs → enrich-BX0IDp4z.mjs} +3 -3
  380. package/dist/{enrich-_ySMEvEE.mjs.map → enrich-BX0IDp4z.mjs.map} +1 -1
  381. package/dist/{error-DupyJZE2.mjs → error-D9w94fjV.mjs} +2 -2
  382. package/dist/{error-DupyJZE2.mjs.map → error-D9w94fjV.mjs.map} +1 -1
  383. package/dist/{errors-CLUPm7aD.mjs → errors-n2j49uNf.mjs} +22 -2
  384. package/dist/errors-n2j49uNf.mjs.map +1 -0
  385. package/dist/{escape-DUY2r2Zs.mjs → escape-DN4Qmjsl.mjs} +1 -1
  386. package/dist/{escape-DUY2r2Zs.mjs.map → escape-DN4Qmjsl.mjs.map} +1 -1
  387. package/dist/{field-defs-cache-BzwBlJrR.mjs → field-defs-cache-Bh4q6oar.mjs} +5 -5
  388. package/dist/{field-defs-cache-BzwBlJrR.mjs.map → field-defs-cache-Bh4q6oar.mjs.map} +1 -1
  389. package/dist/focal-point-BeWFo6Xx.mjs +23 -0
  390. package/dist/focal-point-BeWFo6Xx.mjs.map +1 -0
  391. package/dist/{fts-manager-DyZEohZC.mjs → fts-manager-BhOdW0bi.mjs} +3 -3
  392. package/dist/{fts-manager-DyZEohZC.mjs.map → fts-manager-BhOdW0bi.mjs.map} +1 -1
  393. package/dist/{hash-Cg0TXJPV.mjs → hash-CTcngWvj.mjs} +1 -1
  394. package/dist/{hash-Cg0TXJPV.mjs.map → hash-CTcngWvj.mjs.map} +1 -1
  395. package/dist/{hreflang-DwT2E0Sa.d.mts → hreflang-7pTHsLZJ.d.mts} +2 -2
  396. package/dist/{hreflang-DwT2E0Sa.d.mts.map → hreflang-7pTHsLZJ.d.mts.map} +1 -1
  397. package/dist/{hreflang-BBe83kKa.mjs → hreflang-Huc6O5wa.mjs} +7 -7
  398. package/dist/{hreflang-BBe83kKa.mjs.map → hreflang-Huc6O5wa.mjs.map} +1 -1
  399. package/dist/{identity-Ys6Dlc9C.mjs → identity-DXmb4aVp.mjs} +3 -3
  400. package/dist/{identity-Ys6Dlc9C.mjs.map → identity-DXmb4aVp.mjs.map} +1 -1
  401. package/dist/{import-DPkLmeXO.mjs → import-C4_O3KXU.mjs} +5 -5
  402. package/dist/{import-DPkLmeXO.mjs.map → import-C4_O3KXU.mjs.map} +1 -1
  403. package/dist/{index-C9KuQyO-.d.mts → index-6bRee8zb.d.mts} +3 -3
  404. package/dist/{index-C9KuQyO-.d.mts.map → index-6bRee8zb.d.mts.map} +1 -1
  405. package/dist/{index-BVBZj4-7.d.mts → index-DWbJrsAg.d.mts} +128 -52
  406. package/dist/index-DWbJrsAg.d.mts.map +1 -0
  407. package/dist/index.d.mts +21 -21
  408. package/dist/index.mjs +78 -72
  409. package/dist/{init-lock-6b309ZrF.mjs → init-lock-DJkX6Hto.mjs} +1 -1
  410. package/dist/{init-lock-6b309ZrF.mjs.map → init-lock-DJkX6Hto.mjs.map} +1 -1
  411. package/dist/{load-YJ2xl3ra.mjs → load-Bo7fZAbg.mjs} +2 -2
  412. package/dist/{load-YJ2xl3ra.mjs.map → load-Bo7fZAbg.mjs.map} +1 -1
  413. package/dist/{loader-CdG_Ci3H.mjs → loader-ZsjE4paL.mjs} +2 -2
  414. package/dist/{loader-CdG_Ci3H.mjs.map → loader-ZsjE4paL.mjs.map} +1 -1
  415. package/dist/{manifest-builder-B252yQUf.mjs → manifest-builder-QXuqvVMP.mjs} +2 -2
  416. package/dist/{manifest-builder-B252yQUf.mjs.map → manifest-builder-QXuqvVMP.mjs.map} +1 -1
  417. package/dist/{manifest-schema-BXbUAHod.mjs → manifest-schema-CUYPfCEH.mjs} +1 -1
  418. package/dist/{manifest-schema-BXbUAHod.mjs.map → manifest-schema-CUYPfCEH.mjs.map} +1 -1
  419. package/dist/media/image-endpoint.mjs +1 -1
  420. package/dist/media/index.d.mts +1 -1
  421. package/dist/media/index.mjs +13 -3
  422. package/dist/media/index.mjs.map +1 -1
  423. package/dist/media/local-runtime.d.mts +14 -12
  424. package/dist/media/local-runtime.d.mts.map +1 -1
  425. package/dist/media/local-runtime.mjs +11 -5
  426. package/dist/media/local-runtime.mjs.map +1 -1
  427. package/dist/{media-BWWWb8kg.mjs → media-BjwNuLEu.mjs} +100 -6
  428. package/dist/media-BjwNuLEu.mjs.map +1 -0
  429. package/dist/{media-CzhAn2--.mjs → media-D6SeAfBl.mjs} +41 -12
  430. package/dist/media-D6SeAfBl.mjs.map +1 -0
  431. package/dist/{media-allowlist-D6x-Us02.mjs → media-allowlist-D35v7bmL.mjs} +3 -2
  432. package/dist/media-allowlist-D35v7bmL.mjs.map +1 -0
  433. package/dist/media-folders-D-0CmRZj.mjs +210 -0
  434. package/dist/media-folders-D-0CmRZj.mjs.map +1 -0
  435. package/dist/{media-upload-CHBVn6m-.mjs → media-upload-C7bLXGcI.mjs} +9 -9
  436. package/dist/{media-upload-CHBVn6m-.mjs.map → media-upload-C7bLXGcI.mjs.map} +1 -1
  437. package/dist/{media-url-BvoX88FA.mjs → media-url-DH7giMx_.mjs} +1 -1
  438. package/dist/{media-url-BvoX88FA.mjs.map → media-url-DH7giMx_.mjs.map} +1 -1
  439. package/dist/media-usage-BTRJvS6V.mjs +1833 -0
  440. package/dist/media-usage-BTRJvS6V.mjs.map +1 -0
  441. package/dist/media-usage-activation-Dx0kPV6b.mjs +78 -0
  442. package/dist/media-usage-activation-Dx0kPV6b.mjs.map +1 -0
  443. package/dist/{media-usage-work-DrCbqBcl.mjs → media-usage-work-C-fhM30c.mjs} +221 -59
  444. package/dist/media-usage-work-C-fhM30c.mjs.map +1 -0
  445. package/dist/{media-usage-work-CLo_6tct.mjs → media-usage-work-DWb2XPMI.mjs} +4 -4
  446. package/dist/{media-usage-work-CLo_6tct.mjs.map → media-usage-work-DWb2XPMI.mjs.map} +1 -1
  447. package/dist/{media-usage-write-fence-aHEgN1zB.mjs → media-usage-write-fence-BwoJVRDC.mjs} +2 -2
  448. package/dist/{media-usage-write-fence-aHEgN1zB.mjs.map → media-usage-write-fence-BwoJVRDC.mjs.map} +1 -1
  449. package/dist/{menus-TCNSd2vp.mjs → menus-CD7EFLwz.mjs} +3 -3
  450. package/dist/{menus-TCNSd2vp.mjs.map → menus-CD7EFLwz.mjs.map} +1 -1
  451. package/dist/{menus-DSo5QeW0.mjs → menus-CNg0QlDt.mjs} +42 -26
  452. package/dist/menus-CNg0QlDt.mjs.map +1 -0
  453. package/dist/migrations/index.d.mts +1 -1
  454. package/dist/migrations/index.mjs +3 -3
  455. package/dist/{mime-DfIVjNkr.mjs → mime-CUIG6x84.mjs} +1 -1
  456. package/dist/mime-CUIG6x84.mjs.map +1 -0
  457. package/dist/{mode-BDoH_WcF.mjs → mode-DaUM_MB2.mjs} +1 -1
  458. package/dist/{mode-BDoH_WcF.mjs.map → mode-DaUM_MB2.mjs.map} +1 -1
  459. package/dist/node-sqlite-compat-Udb4Y-rs.mjs +46 -0
  460. package/dist/node-sqlite-compat-Udb4Y-rs.mjs.map +1 -0
  461. package/dist/{normalize-Bc-s_r-a.mjs → normalize-CSxdKBVa.mjs} +22 -1
  462. package/dist/normalize-CSxdKBVa.mjs.map +1 -0
  463. package/dist/{oauth-authorization-iOikmrJd.mjs → oauth-authorization-Dpsb-fMJ.mjs} +5 -5
  464. package/dist/{oauth-authorization-iOikmrJd.mjs.map → oauth-authorization-Dpsb-fMJ.mjs.map} +1 -1
  465. package/dist/{oauth-clients-CvI0nHMJ.mjs → oauth-clients-Bxnoe_67.mjs} +1 -1
  466. package/dist/{oauth-clients-CvI0nHMJ.mjs.map → oauth-clients-Bxnoe_67.mjs.map} +1 -1
  467. package/dist/{oauth-state-store-Ba8KZlwW.mjs → oauth-state-store-0C4s0K6w.mjs} +1 -1
  468. package/dist/{oauth-state-store-Ba8KZlwW.mjs.map → oauth-state-store-0C4s0K6w.mjs.map} +1 -1
  469. package/dist/{oauth-user-lookup-C5SQwGYC.mjs → oauth-user-lookup-wlGYSeqX.mjs} +1 -1
  470. package/dist/{oauth-user-lookup-C5SQwGYC.mjs.map → oauth-user-lookup-wlGYSeqX.mjs.map} +1 -1
  471. package/dist/object-cache/memory.d.mts +1 -1
  472. package/dist/{options-CBXIHUoT.mjs → options-BHPeIbBd.mjs} +1 -1
  473. package/dist/{options-CBXIHUoT.mjs.map → options-BHPeIbBd.mjs.map} +1 -1
  474. package/dist/{options--hhz-jZ1.d.mts → options-BhZIeFY1.d.mts} +3 -3
  475. package/dist/{options--hhz-jZ1.d.mts.map → options-BhZIeFY1.d.mts.map} +1 -1
  476. package/dist/page/index.d.mts +2 -2
  477. package/dist/{parse-DFbuc-Fh.mjs → parse-BRJg1kz8.mjs} +2 -2
  478. package/dist/{parse-DFbuc-Fh.mjs.map → parse-BRJg1kz8.mjs.map} +1 -1
  479. package/dist/{passkey-config-DFAmUyuE.mjs → passkey-config-B3P0nHRR.mjs} +1 -1
  480. package/dist/{passkey-config-DFAmUyuE.mjs.map → passkey-config-B3P0nHRR.mjs.map} +1 -1
  481. package/dist/{patterns-CiyXeDgr.mjs → patterns-D9iDO3j8.mjs} +1 -1
  482. package/dist/{patterns-CiyXeDgr.mjs.map → patterns-D9iDO3j8.mjs.map} +1 -1
  483. package/dist/{placeholder-Dp0K3RkD.d.mts → placeholder-BR4ZhVJl.d.mts} +7 -1
  484. package/dist/placeholder-BR4ZhVJl.d.mts.map +1 -0
  485. package/dist/plugin-types.d.mts +1 -1
  486. package/dist/plugin-utils.d.mts +10 -10
  487. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  488. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  489. package/dist/{policy-TluUIxuu.mjs → policy-BVRganJQ.mjs} +2 -2
  490. package/dist/{policy-TluUIxuu.mjs.map → policy-BVRganJQ.mjs.map} +1 -1
  491. package/dist/{portable-text-imBW5cHK.mjs → portable-text-C8Tvp4_g.mjs} +1 -1
  492. package/dist/{portable-text-imBW5cHK.mjs.map → portable-text-C8Tvp4_g.mjs.map} +1 -1
  493. package/dist/{preview-PW-nOnq4.mjs → preview-dn2dUyM0.mjs} +2 -2
  494. package/dist/{preview-PW-nOnq4.mjs.map → preview-dn2dUyM0.mjs.map} +1 -1
  495. package/dist/{protocol-DjsJHTlK.d.mts → protocol-CuBEsqgE.d.mts} +2 -2
  496. package/dist/{protocol-DjsJHTlK.d.mts.map → protocol-CuBEsqgE.d.mts.map} +1 -1
  497. package/dist/{public-url-CWoFhQT8.mjs → public-url-DRz_AinV.mjs} +1 -1
  498. package/dist/{public-url-CWoFhQT8.mjs.map → public-url-DRz_AinV.mjs.map} +1 -1
  499. package/dist/{query-zTVAR1Sl.mjs → query-D18vTdha.mjs} +14 -14
  500. package/dist/{query-zTVAR1Sl.mjs.map → query-D18vTdha.mjs.map} +1 -1
  501. package/dist/{query-BWs7O5Il.mjs → query-tZDEdtCN.mjs} +4 -4
  502. package/dist/{query-BWs7O5Il.mjs.map → query-tZDEdtCN.mjs.map} +1 -1
  503. package/dist/{rate-limit-Bx4g9m3p.mjs → rate-limit-on7KPo-v.mjs} +2 -2
  504. package/dist/{rate-limit-Bx4g9m3p.mjs.map → rate-limit-on7KPo-v.mjs.map} +1 -1
  505. package/dist/{redirect-COsS6SWJ.mjs → redirect-CZkbozu9.mjs} +2 -2
  506. package/dist/{redirect-COsS6SWJ.mjs.map → redirect-CZkbozu9.mjs.map} +1 -1
  507. package/dist/{redirect-BgAOGHDq.mjs → redirect-DrbEmU9a.mjs} +1 -1
  508. package/dist/{redirect-BgAOGHDq.mjs.map → redirect-DrbEmU9a.mjs.map} +1 -1
  509. package/dist/{redirects-DyChwDkG.mjs → redirects-BahWiu8Z.mjs} +5 -5
  510. package/dist/{redirects-DyChwDkG.mjs.map → redirects-BahWiu8Z.mjs.map} +1 -1
  511. package/dist/{redirects-DTDHWH31.mjs → redirects-CRIM55KH.mjs} +6 -6
  512. package/dist/{redirects-DTDHWH31.mjs.map → redirects-CRIM55KH.mjs.map} +1 -1
  513. package/dist/{api-BeBglVxU.mjs → registry-BiO5WwPq.mjs} +483 -2462
  514. package/dist/registry-BiO5WwPq.mjs.map +1 -0
  515. package/dist/{registry-Cqa2I749.mjs → registry-Cx-jEJOS.mjs} +9 -123
  516. package/dist/registry-Cx-jEJOS.mjs.map +1 -0
  517. package/dist/{relation-BnHB0T4J.mjs → relation-A6wLF_DS.mjs} +2 -2
  518. package/dist/{relation-BnHB0T4J.mjs.map → relation-A6wLF_DS.mjs.map} +1 -1
  519. package/dist/{relations-BBApI4e2.mjs → relations-BTPM2saV.mjs} +2 -2
  520. package/dist/{relations-BBApI4e2.mjs.map → relations-BTPM2saV.mjs.map} +1 -1
  521. package/dist/{relations-BHo5A8Zf.d.mts → relations-C7B46bcU.d.mts} +192 -33
  522. package/dist/relations-C7B46bcU.d.mts.map +1 -0
  523. package/dist/{relations-D5sM5fW0.mjs → relations-Cj5hZ6Zg.mjs} +4 -4
  524. package/dist/{relations-D5sM5fW0.mjs.map → relations-Cj5hZ6Zg.mjs.map} +1 -1
  525. package/dist/{request-cache-BSUptuJR.mjs → request-cache-DH9zdCOD.mjs} +1 -1
  526. package/dist/{request-cache-BSUptuJR.mjs.map → request-cache-DH9zdCOD.mjs.map} +1 -1
  527. package/dist/request-context.d.mts +1 -1
  528. package/dist/{request-meta-DgZJh3zG.mjs → request-meta-DRp5ENd_.mjs} +2 -2
  529. package/dist/{request-meta-DgZJh3zG.mjs.map → request-meta-DRp5ENd_.mjs.map} +1 -1
  530. package/dist/{resolve-DOhVEvty.mjs → resolve-DxUpTMmE.mjs} +1 -1
  531. package/dist/{resolve-DOhVEvty.mjs.map → resolve-DxUpTMmE.mjs.map} +1 -1
  532. package/dist/{runner-C1T11CfC.mjs → runner-77GOZCnH.mjs} +410 -286
  533. package/dist/runner-77GOZCnH.mjs.map +1 -0
  534. package/dist/{runner-BYHZn3Jy.d.mts → runner-zgqA_CqP.d.mts} +2 -2
  535. package/dist/{runner-BYHZn3Jy.d.mts.map → runner-zgqA_CqP.d.mts.map} +1 -1
  536. package/dist/runtime.d.mts +11 -11
  537. package/dist/runtime.mjs +1 -1
  538. package/dist/{schema-DZ5YVVZj.mjs → schema-BY-oVntF.mjs} +3 -3
  539. package/dist/{schema-DZ5YVVZj.mjs.map → schema-BY-oVntF.mjs.map} +1 -1
  540. package/dist/{schema-2AOsSn2v.mjs → schema-Cw9kVK0I.mjs} +35 -5
  541. package/dist/{schema-2AOsSn2v.mjs.map → schema-Cw9kVK0I.mjs.map} +1 -1
  542. package/dist/{scopes-8ClPF2bC.mjs → scopes-vMR1uIbt.mjs} +3 -3
  543. package/dist/{scopes-8ClPF2bC.mjs.map → scopes-vMR1uIbt.mjs.map} +1 -1
  544. package/dist/{search-u1QYdOCG.mjs → search-CfT3KxO5.mjs} +4 -4
  545. package/dist/{search-u1QYdOCG.mjs.map → search-CfT3KxO5.mjs.map} +1 -1
  546. package/dist/{secrets-BEgsAQEU.mjs → secrets-BH2Qow1-.mjs} +3 -3
  547. package/dist/{secrets-BEgsAQEU.mjs.map → secrets-BH2Qow1-.mjs.map} +1 -1
  548. package/dist/{sections-DmHviGyM.mjs → sections-DTfjyf1z.mjs} +2 -2
  549. package/dist/{sections-DmHviGyM.mjs.map → sections-DTfjyf1z.mjs.map} +1 -1
  550. package/dist/seed/index.d.mts +2 -2
  551. package/dist/seed/index.mjs +24 -22
  552. package/dist/seo/index.d.mts +3 -3
  553. package/dist/seo/index.mjs +16 -14
  554. package/dist/seo/index.mjs.map +1 -1
  555. package/dist/{seo-AFpVvTqr.mjs → seo-BSiTIXzd.mjs} +1 -1
  556. package/dist/{seo-AFpVvTqr.mjs.map → seo-BSiTIXzd.mjs.map} +1 -1
  557. package/dist/{seo-Dq4G-RrO.mjs → seo-Cm-dtvgk.mjs} +2 -2
  558. package/dist/{seo-Dq4G-RrO.mjs.map → seo-Cm-dtvgk.mjs.map} +1 -1
  559. package/dist/{service-BpArayPr.mjs → service-DYsDHEKe.mjs} +3 -3
  560. package/dist/{service-BpArayPr.mjs.map → service-DYsDHEKe.mjs.map} +1 -1
  561. package/dist/{session-user-BEorKVT-.mjs → session-user-CNAfvsdw.mjs} +1 -1
  562. package/dist/{session-user-BEorKVT-.mjs.map → session-user-CNAfvsdw.mjs.map} +1 -1
  563. package/dist/{settings-xRdoUZr0.mjs → settings-BgN-0DT-.mjs} +6 -6
  564. package/dist/{settings-xRdoUZr0.mjs.map → settings-BgN-0DT-.mjs.map} +1 -1
  565. package/dist/{settings-DE9xtzqd.mjs → settings-DjtkUo__.mjs} +3 -3
  566. package/dist/{settings-DE9xtzqd.mjs.map → settings-DjtkUo__.mjs.map} +1 -1
  567. package/dist/{setup-complete-BnT8pq_C.mjs → setup-complete-CcpXaPU7.mjs} +2 -2
  568. package/dist/{setup-complete-BnT8pq_C.mjs.map → setup-complete-CcpXaPU7.mjs.map} +1 -1
  569. package/dist/{setup-nonce-CBitf_oQ.mjs → setup-nonce-Reyw30jg.mjs} +1 -1
  570. package/dist/{setup-nonce-CBitf_oQ.mjs.map → setup-nonce-Reyw30jg.mjs.map} +1 -1
  571. package/dist/{single-flight-cache-B0eLKS6K.mjs → single-flight-cache-BPuGPdcN.mjs} +2 -2
  572. package/dist/{single-flight-cache-B0eLKS6K.mjs.map → single-flight-cache-BPuGPdcN.mjs.map} +1 -1
  573. package/dist/{site-url-DjpIXMXJ.mjs → site-url-Cs_V9n3V.mjs} +3 -3
  574. package/dist/{site-url-DjpIXMXJ.mjs.map → site-url-Cs_V9n3V.mjs.map} +1 -1
  575. package/dist/{snapshot-BBlGkb2q.mjs → snapshot-DSB8P7Lm.mjs} +1 -1
  576. package/dist/{snapshot-BBlGkb2q.mjs.map → snapshot-DSB8P7Lm.mjs.map} +1 -1
  577. package/dist/{ssrf-Cpvg_n3A.mjs → ssrf-DqebVE34.mjs} +21 -5
  578. package/dist/{ssrf-Cpvg_n3A.mjs.map → ssrf-DqebVE34.mjs.map} +1 -1
  579. package/dist/{state-DYwPue40.mjs → state-BJfU9Uzw.mjs} +12 -4
  580. package/dist/state-BJfU9Uzw.mjs.map +1 -0
  581. package/dist/{status-CWVYpbD8.mjs → status-DDu8HIQl.mjs} +1 -1
  582. package/dist/{status-CWVYpbD8.mjs.map → status-DDu8HIQl.mjs.map} +1 -1
  583. package/dist/storage/local.d.mts +1 -1
  584. package/dist/storage/local.mjs +1 -1
  585. package/dist/storage/s3.d.mts +1 -1
  586. package/dist/storage/s3.mjs +1 -1
  587. package/dist/{target-DixqqV5i.mjs → target-D0o26Azo.mjs} +1 -1
  588. package/dist/{target-DixqqV5i.mjs.map → target-D0o26Azo.mjs.map} +1 -1
  589. package/dist/{taxonomies-OHUIiIpI.mjs → taxonomies-CPGxo-bn.mjs} +5 -5
  590. package/dist/{taxonomies-OHUIiIpI.mjs.map → taxonomies-CPGxo-bn.mjs.map} +1 -1
  591. package/dist/{taxonomies-BlrncHi9.mjs → taxonomies-kmyudNGP.mjs} +7 -7
  592. package/dist/{taxonomies-BlrncHi9.mjs.map → taxonomies-kmyudNGP.mjs.map} +1 -1
  593. package/dist/{taxonomy-BqCZ1TdU.mjs → taxonomy-8X09dLN5.mjs} +4 -4
  594. package/dist/{taxonomy-BqCZ1TdU.mjs.map → taxonomy-8X09dLN5.mjs.map} +1 -1
  595. package/dist/{tokens-C39klX8R.mjs → tokens-gTS-IVUp.mjs} +1 -1
  596. package/dist/{tokens-C39klX8R.mjs.map → tokens-gTS-IVUp.mjs.map} +1 -1
  597. package/dist/{transaction-NQj4VJ7Z.mjs → transaction-0KOpOyMu.mjs} +2 -1
  598. package/dist/{transaction-NQj4VJ7Z.mjs.map → transaction-0KOpOyMu.mjs.map} +1 -1
  599. package/dist/{transport-RQE36APG.d.mts → transport-_6R1ub7t.d.mts} +1 -1
  600. package/dist/{transport-RQE36APG.d.mts.map → transport-_6R1ub7t.d.mts.map} +1 -1
  601. package/dist/{transport-DBJwa-Si.mjs → transport-fX59xaJz.mjs} +4 -3
  602. package/dist/{transport-DBJwa-Si.mjs.map → transport-fX59xaJz.mjs.map} +1 -1
  603. package/dist/{trusted-proxy-CEVekpby.mjs → trusted-proxy-fe6nEgR4.mjs} +1 -1
  604. package/dist/{trusted-proxy-CEVekpby.mjs.map → trusted-proxy-fe6nEgR4.mjs.map} +1 -1
  605. package/dist/types-75KIqzL9.mjs.map +1 -1
  606. package/dist/{types-BW1syrlw.mjs → types-BXUmsINL.mjs} +1 -1
  607. package/dist/{types-BW1syrlw.mjs.map → types-BXUmsINL.mjs.map} +1 -1
  608. package/dist/{types-BntycPTF.d.mts → types-Blb-MRC3.d.mts} +1 -1
  609. package/dist/{types-BntycPTF.d.mts.map → types-Blb-MRC3.d.mts.map} +1 -1
  610. package/dist/{types-C2pMvO62.d.mts → types-Br-ERaxh.d.mts} +2 -1
  611. package/dist/types-Br-ERaxh.d.mts.map +1 -0
  612. package/dist/{types-DWRhk9xZ.d.mts → types-BzBd3PeX.d.mts} +1 -1
  613. package/dist/{types-DWRhk9xZ.d.mts.map → types-BzBd3PeX.d.mts.map} +1 -1
  614. package/dist/{types-CXnOzDe1.d.mts → types-CLqvnd05.d.mts} +1 -1
  615. package/dist/{types-CXnOzDe1.d.mts.map → types-CLqvnd05.d.mts.map} +1 -1
  616. package/dist/{types-Dfk8KI5R.d.mts → types-D5VVLr7J.d.mts} +1 -1
  617. package/dist/{types-Dfk8KI5R.d.mts.map → types-D5VVLr7J.d.mts.map} +1 -1
  618. package/dist/{types-DQIDRKF2.d.mts → types-DHxzBjbD.d.mts} +10 -1
  619. package/dist/types-DHxzBjbD.d.mts.map +1 -0
  620. package/dist/{types-DN64_zzZ.d.mts → types-DJQxln7q.d.mts} +3 -3
  621. package/dist/{types-DN64_zzZ.d.mts.map → types-DJQxln7q.d.mts.map} +1 -1
  622. package/dist/{types-CtzytVXn.mjs → types-DM3vioBY.mjs} +1 -1
  623. package/dist/{types-CtzytVXn.mjs.map → types-DM3vioBY.mjs.map} +1 -1
  624. package/dist/{types-BcqdcT-r.d.mts → types-D_DWe7k9.d.mts} +1 -1
  625. package/dist/{types-BcqdcT-r.d.mts.map → types-D_DWe7k9.d.mts.map} +1 -1
  626. package/dist/{types-DrJrVCT1.d.mts → types-Vg6f5i3s.d.mts} +3 -3
  627. package/dist/{types-DrJrVCT1.d.mts.map → types-Vg6f5i3s.d.mts.map} +1 -1
  628. package/dist/{upload-attempts-D4FS8LT6.mjs → upload-attempts-CNyGSepg.mjs} +1 -1
  629. package/dist/{upload-attempts-D4FS8LT6.mjs.map → upload-attempts-CNyGSepg.mjs.map} +1 -1
  630. package/dist/{url-pattern-BHS0V5Ng.mjs → url-pattern-K-KdXcSe.mjs} +1 -1
  631. package/dist/{url-pattern-BHS0V5Ng.mjs.map → url-pattern-K-KdXcSe.mjs.map} +1 -1
  632. package/dist/{user-DJZfUJVE.mjs → user-CtYY0tp2.mjs} +2 -2
  633. package/dist/{user-DJZfUJVE.mjs.map → user-CtYY0tp2.mjs.map} +1 -1
  634. package/dist/{utils-D4vD_Y98.mjs → utils-HztC73hq.mjs} +1 -1
  635. package/dist/{utils-D4vD_Y98.mjs.map → utils-HztC73hq.mjs.map} +1 -1
  636. package/dist/{validate-BMLBvxOC.mjs → validate-Dd-IUjnZ.mjs} +2 -2
  637. package/dist/{validate-BMLBvxOC.mjs.map → validate-Dd-IUjnZ.mjs.map} +1 -1
  638. package/dist/{validate-CTqt5nuE.d.mts → validate-DlqdOZXB.d.mts} +5 -5
  639. package/dist/{validate-CTqt5nuE.d.mts.map → validate-DlqdOZXB.d.mts.map} +1 -1
  640. package/dist/{validation-npvENUCB.mjs → validation-D83n7Npi.mjs} +10 -8
  641. package/dist/{validation-npvENUCB.mjs.map → validation-D83n7Npi.mjs.map} +1 -1
  642. package/dist/version-ri-sCyAp.mjs +7 -0
  643. package/dist/{version-DB_fqCSI.mjs.map → version-ri-sCyAp.mjs.map} +1 -1
  644. package/dist/{widgets-BD3ho7Rq.mjs → widgets-CpmZd9Q-.mjs} +4 -4
  645. package/dist/{widgets-BD3ho7Rq.mjs.map → widgets-CpmZd9Q-.mjs.map} +1 -1
  646. package/dist/{wxr-taxonomies-Ca68766D.d.mts → wxr-taxonomies-BFd0y72_.d.mts} +1 -1
  647. package/dist/{wxr-taxonomies-Ca68766D.d.mts.map → wxr-taxonomies-BFd0y72_.d.mts.map} +1 -1
  648. package/dist/{wxr-taxonomies-B1R3vBoD.mjs → wxr-taxonomies-Df4vxWcU.mjs} +4 -4
  649. package/dist/{wxr-taxonomies-B1R3vBoD.mjs.map → wxr-taxonomies-Df4vxWcU.mjs.map} +1 -1
  650. package/dist/{zod-generator-LC-on_Vb.mjs → zod-generator-DylzusHh.mjs} +24 -18
  651. package/dist/zod-generator-DylzusHh.mjs.map +1 -0
  652. package/package.json +16 -8
  653. package/src/api/errors.ts +20 -0
  654. package/src/api/handlers/index.ts +17 -0
  655. package/src/api/handlers/media-allowlist.ts +1 -0
  656. package/src/api/handlers/media-folders.ts +130 -0
  657. package/src/api/handlers/media-usage-activation.ts +102 -0
  658. package/src/api/handlers/media-usage.ts +108 -0
  659. package/src/api/handlers/media.ts +62 -2
  660. package/src/api/handlers/registry.ts +134 -316
  661. package/src/api/openapi/document.ts +192 -2
  662. package/src/api/schemas/media-usage.ts +77 -0
  663. package/src/api/schemas/media.ts +69 -0
  664. package/src/astro/integration/routes.ts +18 -0
  665. package/src/astro/integration/vite-config.ts +2 -7
  666. package/src/astro/middleware/auth.ts +4 -0
  667. package/src/astro/middleware.ts +0 -7
  668. package/src/astro/routes/api/admin/media-usage/activation.ts +42 -0
  669. package/src/astro/routes/api/admin/media-usage/progress.ts +37 -0
  670. package/src/astro/routes/api/admin/plugins/registry/artifact.ts +246 -96
  671. package/src/astro/routes/api/auth/me.ts +14 -2
  672. package/src/astro/routes/api/media/[id].ts +3 -0
  673. package/src/astro/routes/api/media/folders/[id].ts +55 -0
  674. package/src/astro/routes/api/media/folders/index.ts +37 -0
  675. package/src/astro/routes/api/media.ts +12 -2
  676. package/src/astro/routes/api/setup/dev-bypass.ts +12 -0
  677. package/src/astro/types.ts +11 -1
  678. package/src/client/index.ts +140 -2
  679. package/src/client/transport.ts +6 -2
  680. package/src/components/EmDashImage.astro +154 -50
  681. package/src/components/Gallery.astro +7 -0
  682. package/src/components/InlinePortableTextEditor.tsx +130 -1
  683. package/src/components/LiveSearch.astro +23 -0
  684. package/src/components/inline-code-block.tsx +180 -49
  685. package/src/content/converters/gallery.ts +2 -0
  686. package/src/content/converters/types.ts +2 -0
  687. package/src/database/connection.ts +2 -31
  688. package/src/database/index.ts +1 -1
  689. package/src/database/json-recordset.ts +16 -0
  690. package/src/database/migrations/019_i18n.ts +1 -1
  691. package/src/database/migrations/071_restore_content_bylines_table.ts +43 -0
  692. package/src/database/migrations/072_media_folders.ts +72 -0
  693. package/src/database/migrations/073_media_focal_point.ts +57 -0
  694. package/src/database/migrations/runner.ts +8 -2
  695. package/src/database/repositories/content.ts +5 -4
  696. package/src/database/repositories/media-folders.ts +115 -0
  697. package/src/database/repositories/media-usage-work.ts +395 -111
  698. package/src/database/repositories/media-usage.ts +1038 -10
  699. package/src/database/repositories/media.ts +97 -29
  700. package/src/database/transaction.ts +1 -0
  701. package/src/database/types.ts +13 -0
  702. package/src/db/adapters.ts +2 -2
  703. package/src/db/node-sqlite-compat.ts +78 -0
  704. package/src/db/sqlite.ts +3 -3
  705. package/src/emdash-runtime.ts +110 -105
  706. package/src/fields/image.ts +7 -1
  707. package/src/fields/types.ts +6 -2
  708. package/src/index.ts +5 -0
  709. package/src/media/focal-point.ts +37 -0
  710. package/src/media/local-runtime.ts +8 -0
  711. package/src/media/mime.ts +1 -0
  712. package/src/media/normalize.ts +10 -0
  713. package/src/media/types.ts +10 -0
  714. package/src/media/usage/activation.ts +162 -35
  715. package/src/media/usage/capture-triggers.ts +19 -3
  716. package/src/media/usage/collection-deletion-processor.ts +7 -3
  717. package/src/media/usage/collection-deletion.ts +10 -0
  718. package/src/media/usage/content-refresh.ts +258 -39
  719. package/src/media/usage/content-snapshots.ts +128 -31
  720. package/src/media/usage/extractor.ts +32 -13
  721. package/src/media/usage/maintenance-engine.ts +166 -0
  722. package/src/media/usage/reconciliation-processor.ts +106 -29
  723. package/src/media/usage/reconciliation.ts +90 -7
  724. package/src/media/usage/work-processor.ts +342 -101
  725. package/src/plugins/index.ts +1 -0
  726. package/src/plugins/save-rejection.ts +20 -0
  727. package/src/plugins/scheduler/node.ts +1 -13
  728. package/src/plugins/scheduler/types.ts +0 -2
  729. package/src/plugins/state.ts +13 -3
  730. package/src/registry/artifact-fetch.ts +530 -0
  731. package/src/registry/config.ts +24 -6
  732. package/src/registry/types.ts +12 -15
  733. package/src/schema/types.ts +1 -0
  734. package/src/schema/zod-generator.ts +12 -4
  735. package/src/security/ssrf.ts +21 -2
  736. package/src/seed/apply.ts +4 -4
  737. package/src/ui.ts +2 -0
  738. package/dist/api-BeBglVxU.mjs.map +0 -1
  739. package/dist/collection-deletion-DQPvMD8R.mjs.map +0 -1
  740. package/dist/content-ZHCc1ngN.mjs.map +0 -1
  741. package/dist/content-refresh-B_8SJzuU.mjs.map +0 -1
  742. package/dist/errors-CLUPm7aD.mjs.map +0 -1
  743. package/dist/index-BVBZj4-7.d.mts.map +0 -1
  744. package/dist/media-BWWWb8kg.mjs.map +0 -1
  745. package/dist/media-CzhAn2--.mjs.map +0 -1
  746. package/dist/media-allowlist-D6x-Us02.mjs.map +0 -1
  747. package/dist/media-usage-BZCydfvu.mjs.map +0 -1
  748. package/dist/media-usage-work-DrCbqBcl.mjs.map +0 -1
  749. package/dist/menus-DSo5QeW0.mjs.map +0 -1
  750. package/dist/mime-DfIVjNkr.mjs.map +0 -1
  751. package/dist/normalize-Bc-s_r-a.mjs.map +0 -1
  752. package/dist/placeholder-Dp0K3RkD.d.mts.map +0 -1
  753. package/dist/registry-Cqa2I749.mjs.map +0 -1
  754. package/dist/relations-BHo5A8Zf.d.mts.map +0 -1
  755. package/dist/runner-C1T11CfC.mjs.map +0 -1
  756. package/dist/state-DYwPue40.mjs.map +0 -1
  757. package/dist/types-C2pMvO62.d.mts.map +0 -1
  758. package/dist/types-DQIDRKF2.d.mts.map +0 -1
  759. package/dist/version-DB_fqCSI.mjs +0 -7
  760. package/dist/zod-generator-LC-on_Vb.mjs.map +0 -1
  761. /package/dist/{api-tokens-rIXC6LdE.mjs → api-tokens-B5NHLNUN.mjs} +0 -0
  762. /package/dist/{ssrf-DpXgKsna.mjs → ssrf-BPKzkm6O.mjs} +0 -0
  763. /package/dist/{types-CP1CflWf.mjs → types-D6OcIp2P.mjs} +0 -0
@@ -5,13 +5,13 @@ import { ulid } from "ulidx";
5
5
 
6
6
  //#region src/database/repositories/media-usage-work.ts
7
7
  const MAX_PORTABLE_DURATION_SECONDS = 365 * 24 * 60 * 60;
8
- const MAX_WORK_SELECTION_LIMIT = 100;
8
+ const MAX_WORK_SELECTION_LIMIT = 1e3;
9
9
  const NON_NEGATIVE_DECIMAL_PATTERN = /^(?:0|[1-9][0-9]*)$/;
10
10
  const POSITIVE_DECIMAL_PATTERN = /^[1-9][0-9]*$/;
11
11
  const STABLE_ERROR_CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,63}$/;
12
12
  const MEDIA_USAGE_WORK_OPERATOR_DEFAULT_LIMIT = 50;
13
13
  const MEDIA_USAGE_WORK_OPERATOR_MAX_LIMIT = 100;
14
- const MEDIA_USAGE_RECONCILIATION_PAGE_LIMIT = 50;
14
+ const MEDIA_USAGE_RECONCILIATION_PAGE_LIMIT = 1e3;
15
15
  const MEDIA_USAGE_WORK_STATES = [
16
16
  "pending",
17
17
  "retry",
@@ -26,11 +26,12 @@ var MediaUsageWorkRepository = class {
26
26
  if (!input.collectionId || !input.collectionSlug || !input.runToken || !input.leaseToken) throw new Error("Reconciliation enqueue requires exact collection and lease identity");
27
27
  assertNonNegativeDecimal(input.changeEpoch, "change epoch");
28
28
  const contentIds = [...new Set(input.contentIds)];
29
- if (contentIds.length < 1 || contentIds.length > MEDIA_USAGE_RECONCILIATION_PAGE_LIMIT) throw new Error("Reconciliation enqueue requires from 1 to 50 content IDs");
29
+ if (contentIds.length < 1 || contentIds.length > MEDIA_USAGE_RECONCILIATION_PAGE_LIMIT) throw new Error("Reconciliation enqueue requires from 1 to 1000 content IDs");
30
30
  if (contentIds.some((contentId) => !contentId)) throw new Error("Reconciliation enqueue content IDs must not be empty");
31
31
  const now = this.timestampOffset(0);
32
+ const contentIdsJson = JSON.stringify(contentIds);
32
33
  await sql`
33
- WITH page(content_id) AS (VALUES ${sql.join(contentIds.map((contentId) => sql`(${contentId})`), sql`, `)})
34
+ WITH page(content_id) AS (${isPostgres(this.db) ? sql`SELECT value::text AS content_id FROM jsonb_array_elements_text(${contentIdsJson}::jsonb) AS value` : sql`SELECT value AS content_id FROM json_each(${contentIdsJson})`})
34
35
  INSERT INTO _emdash_media_usage_work (
35
36
  collection_id, collection_slug, content_id, change_epoch, work_version,
36
37
  state, attempt_count, next_attempt_at, lease_token, lease_expires_at,
@@ -159,8 +160,9 @@ var MediaUsageWorkRepository = class {
159
160
  async invalidateCoverageForOperatorRetry(input) {
160
161
  let query = this.db.updateTable("_emdash_media_usage_index_status as status").set({
161
162
  change_epoch: sql`change_epoch + 1`,
162
- status: sql`CASE WHEN status = 'complete' THEN 'stale' ELSE status END`,
163
- completed_at: sql`CASE WHEN status = 'complete' THEN NULL ELSE completed_at END`,
163
+ status: sql`CASE WHEN status IN ('complete', 'partial', 'failed') THEN 'stale' ELSE status END`,
164
+ completed_at: sql`CASE WHEN status IN ('complete', 'partial', 'failed') THEN NULL ELSE completed_at END`,
165
+ last_error_code: null,
164
166
  updated_at: this.timestampOffset(0)
165
167
  }).where("status.adapter_id", "=", "content-media").where("status.scope_type", "=", "collection").where("status.scope_key", "=", input.collectionSlug).where("status.collection_id", "=", input.collectionId).where("status.capture_state", "=", "active").where((eb) => eb.exists(eb.selectFrom("_emdash_collections as collection").select("collection.id").whereRef("collection.id", "=", "status.collection_id").whereRef("collection.slug", "=", "status.scope_key")));
166
168
  const observed = input.observed;
@@ -241,21 +243,42 @@ var MediaUsageWorkRepository = class {
241
243
  async findLiveLeaseExpiry(collectionId, contentId) {
242
244
  return (await this.db.selectFrom("_emdash_media_usage_work").select("lease_expires_at").where("collection_id", "=", collectionId).where("content_id", "=", contentId).where("state", "=", "leased").where("lease_expires_at", "is not", null).where(this.leaseIsLive()).executeTakeFirst())?.lease_expires_at ?? null;
243
245
  }
244
- async findDueWork(limit) {
245
- if (!Number.isSafeInteger(limit) || limit < 1 || limit > MAX_WORK_SELECTION_LIMIT) throw new Error(`Media usage due-work limit must be a whole number from 1 to ${MAX_WORK_SELECTION_LIMIT}`);
246
- const pendingRows = await this.findDueRows("pending", "next_attempt_at", limit);
247
- const retryRows = await this.findDueRows("retry", "next_attempt_at", limit);
248
- const leasedRows = await this.findDueRows("leased", "lease_expires_at", limit);
249
- return [
250
- ...pendingRows,
251
- ...retryRows,
252
- ...leasedRows
253
- ].map(rowToWork).toSorted(compareDueWork).slice(0, limit);
246
+ async claimDueWorkBatch(input) {
247
+ if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > MAX_WORK_SELECTION_LIMIT) throw new Error(`Media usage due-work limit must be a whole number from 1 to ${MAX_WORK_SELECTION_LIMIT}`);
248
+ const leaseDurationSeconds = durationSeconds(input.leaseDurationSeconds, "lease duration", false);
249
+ const leaseToken = ulid();
250
+ const now = this.timestampOffset(0);
251
+ let candidates = this.db.selectFrom("_emdash_media_usage_work as due").select([
252
+ "due.collection_id",
253
+ "due.content_id",
254
+ "due.work_version"
255
+ ]).where((eb) => eb.or([eb.and([eb("due.state", "in", ["pending", "retry"]), this.timestampIsDue("due.next_attempt_at")]), eb.and([
256
+ eb("due.state", "=", "leased"),
257
+ eb("due.lease_expires_at", "is not", null),
258
+ this.timestampIsDue("due.lease_expires_at")
259
+ ])])).orderBy(sql`CASE
260
+ WHEN due.state = 'leased' THEN due.lease_expires_at
261
+ ELSE due.next_attempt_at
262
+ END`, "asc").orderBy("due.updated_at", "asc").orderBy("due.collection_id", "asc").orderBy("due.content_id", "asc").limit(input.limit);
263
+ if (isPostgres(this.db)) candidates = candidates.forUpdate().skipLocked();
264
+ return (await this.db.with("due_media_usage_work", () => candidates).updateTable("_emdash_media_usage_work").set({
265
+ state: "leased",
266
+ lease_token: leaseToken,
267
+ lease_expires_at: this.timestampOffset(leaseDurationSeconds),
268
+ last_attempted_at: now,
269
+ updated_at: now
270
+ }).where((eb) => eb.and([eb.exists(eb.selectFrom("due_media_usage_work as due").select("due.content_id").whereRef("due.collection_id", "=", "_emdash_media_usage_work.collection_id").whereRef("due.content_id", "=", "_emdash_media_usage_work.content_id").whereRef("due.work_version", "=", "_emdash_media_usage_work.work_version")), eb.or([eb.and([eb("state", "in", ["pending", "retry"]), this.timestampIsDue("next_attempt_at")]), eb.and([
271
+ eb("state", "=", "leased"),
272
+ eb("lease_expires_at", "is not", null),
273
+ this.timestampIsDue("lease_expires_at")
274
+ ])])])).returningAll().execute()).map(rowToWork);
254
275
  }
255
- async findDueRows(state, timestampColumn, limit) {
256
- let query = this.db.selectFrom("_emdash_media_usage_work").selectAll().where("state", "=", state).where(this.timestampIsDue(timestampColumn)).orderBy(timestampColumn, "asc");
257
- if (timestampColumn === "next_attempt_at") query = query.orderBy("updated_at", "asc");
258
- return query.orderBy("collection_id", "asc").orderBy("content_id", "asc").limit(limit).execute();
276
+ async hasNonterminalWork() {
277
+ return await this.db.selectFrom("_emdash_media_usage_work").select("content_id").where("state", "in", [
278
+ "pending",
279
+ "retry",
280
+ "leased"
281
+ ]).limit(1).executeTakeFirst() !== void 0;
259
282
  }
260
283
  async findWorkForContent(collectionSlug, contentId) {
261
284
  if (!collectionSlug || !contentId) throw new Error("Media usage work lookup requires collection and content identity");
@@ -280,10 +303,158 @@ var MediaUsageWorkRepository = class {
280
303
  ])])).returningAll().executeTakeFirst();
281
304
  return row ? rowToWork(row) : null;
282
305
  }
283
- async completeWork(input) {
284
- assertLease(input);
285
- const result = await this.db.deleteFrom("_emdash_media_usage_work").where("collection_id", "=", input.collectionId).where("content_id", "=", input.contentId).where("work_version", "=", input.workVersion).where("state", "=", "leased").where("lease_token", "=", input.leaseToken).where(this.leaseIsLive()).executeTakeFirst();
286
- return Number(result.numDeletedRows ?? 0) > 0;
306
+ async completeWorkBatch(inputs) {
307
+ const unique = [...new Map(inputs.map((input) => {
308
+ assertLease(input);
309
+ return [workIdentityKey(input), input];
310
+ })).values()];
311
+ const completed = /* @__PURE__ */ new Set();
312
+ if (unique.length === 0) return completed;
313
+ const payload = JSON.stringify(unique.map((input) => ({
314
+ collection_id: input.collectionId,
315
+ content_id: input.contentId,
316
+ work_version: String(input.workVersion),
317
+ lease_token: input.leaseToken
318
+ })));
319
+ const result = await sql`
320
+ WITH claimed AS (${this.claimedWorkBatchInput(payload)})
321
+ DELETE FROM _emdash_media_usage_work AS work
322
+ WHERE work.state = 'leased'
323
+ AND ${this.qualifiedLeaseIsLive("work.lease_expires_at")}
324
+ AND EXISTS (
325
+ SELECT 1
326
+ FROM claimed
327
+ WHERE claimed.collection_id = work.collection_id
328
+ AND claimed.content_id = work.content_id
329
+ AND claimed.work_version = work.work_version
330
+ AND claimed.lease_token = work.lease_token
331
+ )
332
+ RETURNING collection_id, content_id, work_version
333
+ `.execute(this.db);
334
+ for (const row of result.rows) completed.add(workIdentityKey({
335
+ collectionId: row.collection_id,
336
+ contentId: row.content_id,
337
+ workVersion: row.work_version
338
+ }));
339
+ return completed;
340
+ }
341
+ async lockClaimedWorkBatch(inputs) {
342
+ const unique = [...new Map(inputs.map((input) => {
343
+ assertLease(input);
344
+ return [workIdentityKey(input), input];
345
+ })).values()].toSorted((left, right) => workIdentityKey(left).localeCompare(workIdentityKey(right)));
346
+ if (!isPostgres(this.db)) return new Set(unique.map(workIdentityKey));
347
+ if (unique.length === 0) return /* @__PURE__ */ new Set();
348
+ const payload = JSON.stringify(unique.map((input) => ({
349
+ collection_id: input.collectionId,
350
+ content_id: input.contentId,
351
+ work_version: String(input.workVersion),
352
+ lease_token: input.leaseToken
353
+ })));
354
+ const result = await sql`
355
+ WITH claimed AS (${this.claimedWorkBatchInput(payload)})
356
+ SELECT work.collection_id, work.content_id, work.work_version
357
+ FROM _emdash_media_usage_work AS work
358
+ INNER JOIN claimed
359
+ ON claimed.collection_id = work.collection_id
360
+ AND claimed.content_id = work.content_id
361
+ AND claimed.work_version = work.work_version
362
+ AND claimed.lease_token = work.lease_token
363
+ WHERE work.state = 'leased'
364
+ AND ${this.qualifiedLeaseIsLive("work.lease_expires_at")}
365
+ ORDER BY work.collection_id, work.content_id
366
+ FOR UPDATE
367
+ `.execute(this.db);
368
+ return new Set(result.rows.map((row) => workIdentityKey({
369
+ collectionId: row.collection_id,
370
+ contentId: row.content_id,
371
+ workVersion: row.work_version
372
+ })));
373
+ }
374
+ async retryClaimedWorkBatch(input) {
375
+ assertErrorCode(input.errorCode);
376
+ const retryDelaySeconds = durationSeconds(input.retryDelaySeconds, "retry delay", true);
377
+ if (!Number.isSafeInteger(input.maxAttempts) || input.maxAttempts < 1) throw new Error("Media usage work max attempts must be a positive whole number");
378
+ const unique = [...new Map(input.work.map((work) => {
379
+ assertLease(work);
380
+ return [workIdentityKey(work), work];
381
+ })).values()];
382
+ const transitioned = /* @__PURE__ */ new Map();
383
+ if (unique.length === 0) return transitioned;
384
+ const payload = JSON.stringify(unique.map((work) => ({
385
+ collection_id: work.collectionId,
386
+ content_id: work.contentId,
387
+ work_version: String(work.workVersion),
388
+ lease_token: work.leaseToken
389
+ })));
390
+ const result = await sql`
391
+ WITH claimed AS (${this.claimedWorkBatchInput(payload)})
392
+ UPDATE _emdash_media_usage_work AS work
393
+ SET state = CASE WHEN work.attempt_count + 1 >= ${input.maxAttempts} THEN 'failed' ELSE 'retry' END,
394
+ attempt_count = work.attempt_count + 1,
395
+ next_attempt_at = ${this.timestampOffset(retryDelaySeconds)},
396
+ lease_token = NULL,
397
+ lease_expires_at = NULL,
398
+ last_error_code = ${input.errorCode},
399
+ updated_at = ${this.timestampOffset(0)}
400
+ WHERE work.state = 'leased'
401
+ AND ${this.qualifiedLeaseIsLive("work.lease_expires_at")}
402
+ AND EXISTS (
403
+ SELECT 1
404
+ FROM claimed
405
+ WHERE claimed.collection_id = work.collection_id
406
+ AND claimed.content_id = work.content_id
407
+ AND claimed.work_version = work.work_version
408
+ AND claimed.lease_token = work.lease_token
409
+ )
410
+ RETURNING collection_id, content_id, work_version, state
411
+ `.execute(this.db);
412
+ for (const row of result.rows) transitioned.set(workIdentityKey({
413
+ collectionId: row.collection_id,
414
+ contentId: row.content_id,
415
+ workVersion: row.work_version
416
+ }), row.state);
417
+ return transitioned;
418
+ }
419
+ async releaseClaimedWorkBatch(inputs) {
420
+ const unique = [...new Map(inputs.map((input) => {
421
+ assertLease(input);
422
+ return [workIdentityKey(input), input];
423
+ })).values()];
424
+ const released = /* @__PURE__ */ new Set();
425
+ if (unique.length === 0) return released;
426
+ const payload = JSON.stringify(unique.map((input) => ({
427
+ collection_id: input.collectionId,
428
+ content_id: input.contentId,
429
+ work_version: String(input.workVersion),
430
+ lease_token: input.leaseToken
431
+ })));
432
+ const result = await sql`
433
+ WITH claimed AS (${this.claimedWorkBatchInput(payload)})
434
+ UPDATE _emdash_media_usage_work AS work
435
+ SET state = 'pending',
436
+ next_attempt_at = ${this.timestampOffset(0)},
437
+ lease_token = NULL,
438
+ lease_expires_at = NULL,
439
+ updated_at = ${this.timestampOffset(0)}
440
+ WHERE work.state = 'leased'
441
+ AND ${this.qualifiedLeaseIsLive("work.lease_expires_at")}
442
+ AND EXISTS (
443
+ SELECT 1
444
+ FROM claimed
445
+ WHERE claimed.collection_id = work.collection_id
446
+ AND claimed.content_id = work.content_id
447
+ AND claimed.work_version = work.work_version
448
+ AND claimed.lease_token = work.lease_token
449
+ )
450
+ RETURNING collection_id, content_id, work_version
451
+ `.execute(this.db);
452
+ for (const row of result.rows) released.add(workIdentityKey({
453
+ collectionId: row.collection_id,
454
+ contentId: row.content_id,
455
+ workVersion: row.work_version
456
+ }));
457
+ return released;
287
458
  }
288
459
  async deleteWorkThroughEpoch(collectionId, maxChangeEpoch) {
289
460
  if (!collectionId) throw new Error("Media usage work cleanup requires a collection ID");
@@ -291,27 +462,10 @@ var MediaUsageWorkRepository = class {
291
462
  const result = await this.db.deleteFrom("_emdash_media_usage_work").where("collection_id", "=", collectionId).where("change_epoch", "<=", maxChangeEpoch).executeTakeFirst();
292
463
  return Number(result.numDeletedRows ?? 0);
293
464
  }
294
- async retryWork(input) {
295
- const retryDelaySeconds = durationSeconds(input.retryDelaySeconds, "retry delay", true);
296
- assertErrorCode(input.errorCode);
297
- return this.transitionFailure(input, "retry", { next_attempt_at: this.timestampOffset(retryDelaySeconds) });
298
- }
299
- async failWork(input) {
300
- assertErrorCode(input.errorCode);
301
- return this.transitionFailure(input, "failed");
302
- }
303
- async transitionFailure(input, state, extra = {}) {
304
- assertLease(input);
305
- const result = await this.db.updateTable("_emdash_media_usage_work").set({
306
- state,
307
- attempt_count: sql`attempt_count + 1`,
308
- lease_token: null,
309
- lease_expires_at: null,
310
- last_error_code: input.errorCode,
311
- updated_at: this.timestampOffset(0),
312
- ...extra
313
- }).where("collection_id", "=", input.collectionId).where("content_id", "=", input.contentId).where("work_version", "=", input.workVersion).where("state", "=", "leased").where("lease_token", "=", input.leaseToken).where(this.leaseIsLive()).executeTakeFirst();
314
- return Number(result.numUpdatedRows ?? 0) > 0;
465
+ async deleteObsoleteReconciliationWork(input) {
466
+ assertNonNegativeDecimal(input.targetEpoch, "target epoch");
467
+ const result = await this.db.deleteFrom("_emdash_media_usage_work as work").where("work.collection_id", "=", input.collectionId).where("work.change_epoch", "<", input.targetEpoch).where((eb) => eb.exists(eb.selectFrom("_emdash_media_usage_reconciliations as reconciliation").innerJoin("_emdash_media_usage_index_status as status", (join) => join.onRef("status.collection_id", "=", "reconciliation.collection_id").onRef("status.scope_key", "=", "reconciliation.collection_slug")).innerJoin("_emdash_collections as collection", (join) => join.onRef("collection.id", "=", "reconciliation.collection_id").onRef("collection.slug", "=", "reconciliation.collection_slug")).select("reconciliation.collection_id").where("reconciliation.collection_id", "=", input.collectionId).where("reconciliation.collection_slug", "=", input.collectionSlug).where("reconciliation.run_token", "=", input.runToken).where("reconciliation.target_epoch", "=", input.targetEpoch).where("reconciliation.state", "=", "leased").where("reconciliation.lease_token", "=", input.leaseToken).where(this.qualifiedLeaseIsLive("reconciliation.lease_expires_at")).where("status.capture_state", "=", "active").where("status.reconciliation_required", "=", 1).where("status.status", "=", "running").where("status.cursor", "=", input.runToken).where("status.change_epoch", "=", input.targetEpoch))).executeTakeFirst();
468
+ return Number(result.numDeletedRows ?? 0);
315
469
  }
316
470
  leaseIsLive() {
317
471
  return isPostgres(this.db) ? sql`lease_expires_at::timestamptz > clock_timestamp()` : sql`lease_expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;
@@ -337,7 +491,28 @@ var MediaUsageWorkRepository = class {
337
491
  ${`${offsetSeconds >= 0 ? "+" : ""}${offsetSeconds} seconds`}
338
492
  )`;
339
493
  }
494
+ claimedWorkBatchInput(payload) {
495
+ if (isPostgres(this.db)) return sql`
496
+ SELECT
497
+ entry.value ->> 'collection_id' AS collection_id,
498
+ entry.value ->> 'content_id' AS content_id,
499
+ CAST(entry.value ->> 'work_version' AS bigint) AS work_version,
500
+ entry.value ->> 'lease_token' AS lease_token
501
+ FROM jsonb_array_elements(${payload}::jsonb) AS entry(value)
502
+ `;
503
+ return sql`
504
+ SELECT
505
+ json_extract(entry.value, '$.collection_id') AS collection_id,
506
+ json_extract(entry.value, '$.content_id') AS content_id,
507
+ CAST(json_extract(entry.value, '$.work_version') AS integer) AS work_version,
508
+ json_extract(entry.value, '$.lease_token') AS lease_token
509
+ FROM json_each(${payload}) AS entry
510
+ `;
511
+ }
340
512
  };
513
+ function workIdentityKey(input) {
514
+ return `${input.collectionId}\u0000${input.contentId}\u0000${String(input.workVersion)}`;
515
+ }
341
516
  function operatorLimit(value) {
342
517
  if (value === void 0) return MEDIA_USAGE_WORK_OPERATOR_DEFAULT_LIMIT;
343
518
  if (!Number.isSafeInteger(value) || value < 1 || value > MEDIA_USAGE_WORK_OPERATOR_MAX_LIMIT) throw new Error(`Media usage operator limit must be a whole number from 1 to ${MEDIA_USAGE_WORK_OPERATOR_MAX_LIMIT}`);
@@ -401,24 +576,11 @@ function rowToOperatorWork(row) {
401
576
  function isMediaUsageWorkState(value) {
402
577
  return value === "pending" || value === "retry" || value === "leased" || value === "failed";
403
578
  }
404
- function compareDueWork(a, b) {
405
- const eligibility = dueTimestamp(a).localeCompare(dueTimestamp(b));
406
- if (eligibility !== 0) return eligibility;
407
- const updated = a.updatedAt.localeCompare(b.updatedAt);
408
- if (updated !== 0) return updated;
409
- const collection = a.collectionId.localeCompare(b.collectionId);
410
- return collection !== 0 ? collection : a.contentId.localeCompare(b.contentId);
411
- }
412
579
  function compareOperatorWork(a, b) {
413
580
  const updated = b.updatedAt.localeCompare(a.updatedAt);
414
581
  return updated !== 0 ? updated : b.contentId.localeCompare(a.contentId);
415
582
  }
416
- function dueTimestamp(work) {
417
- if (work.state !== "leased") return work.nextAttemptAt;
418
- if (!work.leaseExpiresAt) throw new Error("Due leased media usage work must have a lease expiry");
419
- return work.leaseExpiresAt;
420
- }
421
583
 
422
584
  //#endregion
423
585
  export { MediaUsageWorkRepository as t };
424
- //# sourceMappingURL=media-usage-work-DrCbqBcl.mjs.map
586
+ //# sourceMappingURL=media-usage-work-C-fhM30c.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-usage-work-C-fhM30c.mjs","names":[],"sources":["../src/database/repositories/media-usage-work.ts"],"sourcesContent":["import { sql, type Kysely, type RawBuilder, type Selectable } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { isPostgres } from \"../dialect-helpers.js\";\nimport type { Database, MediaUsageWorkTable } from \"../types.js\";\nimport { decodeCursor, encodeCursor, type FindManyResult } from \"./types.js\";\n\nexport type MediaUsageWorkState = \"pending\" | \"retry\" | \"leased\" | \"failed\";\nexport type MediaUsageWorkVersion = number | string;\nconst MAX_PORTABLE_DURATION_SECONDS = 365 * 24 * 60 * 60;\nconst MAX_WORK_SELECTION_LIMIT = 1_000;\nconst NON_NEGATIVE_DECIMAL_PATTERN = /^(?:0|[1-9][0-9]*)$/;\nconst POSITIVE_DECIMAL_PATTERN = /^[1-9][0-9]*$/;\nconst STABLE_ERROR_CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,63}$/;\n\nexport const MEDIA_USAGE_WORK_OPERATOR_DEFAULT_LIMIT = 50;\nexport const MEDIA_USAGE_WORK_OPERATOR_MAX_LIMIT = 100;\nexport const MEDIA_USAGE_RECONCILIATION_PAGE_LIMIT = 1_000;\nconst MEDIA_USAGE_WORK_STATES = [\"pending\", \"retry\", \"leased\", \"failed\"] as const;\n\nexport interface MediaUsageWorkIdentity {\n\tcollectionId: string;\n\tcontentId: string;\n\tworkVersion: MediaUsageWorkVersion;\n}\n\nexport interface MediaUsageWorkLease extends MediaUsageWorkIdentity {\n\tleaseToken: string;\n}\n\nexport interface MediaUsageWorkRecord extends MediaUsageWorkIdentity {\n\tcollectionSlug: string;\n\tchangeEpoch: number | string;\n\tstate: MediaUsageWorkState;\n\tattemptCount: number;\n\tnextAttemptAt: string;\n\tleaseToken: string | null;\n\tleaseExpiresAt: string | null;\n\tlastAttemptedAt: string | null;\n\tlastErrorCode: string | null;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface MediaUsageOperatorWorkItem {\n\tcollectionId: string;\n\tcollectionSlug: string;\n\tcontentId: string;\n\tstate: MediaUsageWorkState;\n\tattemptCount: number;\n\tnextAttemptAt: string;\n\tleaseExpiresAt: string | null;\n\tlastAttemptedAt: string | null;\n\tlastErrorCode: string | null;\n\tupdatedAt: string;\n}\n\nexport type MediaUsageOperatorRetryResult =\n\t| { outcome: \"pending\"; changed: boolean; work: MediaUsageOperatorWorkItem }\n\t| { outcome: \"lease_active\"; leaseExpiresAt: string }\n\t| { outcome: \"collection_not_found\" }\n\t| { outcome: \"conflict\" };\n\nexport class MediaUsageWorkRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\tasync enqueueReconciliationPage(input: {\n\t\tcollectionId: string;\n\t\tcollectionSlug: string;\n\t\trunToken: string;\n\t\tleaseToken: string;\n\t\tchangeEpoch: number | string;\n\t\tphase: \"scan\" | \"sources\";\n\t\tcontentIds: readonly string[];\n\t}): Promise<void> {\n\t\tif (!input.collectionId || !input.collectionSlug || !input.runToken || !input.leaseToken) {\n\t\t\tthrow new Error(\"Reconciliation enqueue requires exact collection and lease identity\");\n\t\t}\n\t\tassertNonNegativeDecimal(input.changeEpoch, \"change epoch\");\n\t\tconst contentIds = [...new Set(input.contentIds)];\n\t\tif (contentIds.length < 1 || contentIds.length > MEDIA_USAGE_RECONCILIATION_PAGE_LIMIT) {\n\t\t\tthrow new Error(\"Reconciliation enqueue requires from 1 to 1000 content IDs\");\n\t\t}\n\t\tif (contentIds.some((contentId) => !contentId)) {\n\t\t\tthrow new Error(\"Reconciliation enqueue content IDs must not be empty\");\n\t\t}\n\t\tconst now = this.timestampOffset(0);\n\t\tconst contentIdsJson = JSON.stringify(contentIds);\n\t\tconst page = isPostgres(this.db)\n\t\t\t? sql`SELECT value::text AS content_id FROM jsonb_array_elements_text(${contentIdsJson}::jsonb) AS value`\n\t\t\t: sql`SELECT value AS content_id FROM json_each(${contentIdsJson})`;\n\t\tawait sql`\n\t\t\tWITH page(content_id) AS (${page})\n\t\t\tINSERT INTO _emdash_media_usage_work (\n\t\t\t\tcollection_id, collection_slug, content_id, change_epoch, work_version,\n\t\t\t\tstate, attempt_count, next_attempt_at, lease_token, lease_expires_at,\n\t\t\t\tlast_attempted_at, last_error_code, created_at, updated_at\n\t\t\t)\n\t\t\tSELECT\n\t\t\t\t${input.collectionId}, ${input.collectionSlug}, page.content_id, ${input.changeEpoch}, 1,\n\t\t\t\t'pending', 0, ${now}, NULL, NULL, NULL, NULL, ${now}, ${now}\n\t\t\tFROM page\n\t\t\tWHERE EXISTS (\n\t\t\t\tSELECT 1\n\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\tINNER JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\tON status.collection_id = reconciliation.collection_id\n\t\t\t\t\tAND status.scope_key = reconciliation.collection_slug\n\t\t\t\tINNER JOIN _emdash_collections AS collection\n\t\t\t\t\tON collection.id = reconciliation.collection_id\n\t\t\t\t\tAND collection.slug = reconciliation.collection_slug\n\t\t\t\tWHERE reconciliation.collection_id = ${input.collectionId}\n\t\t\t\t\tAND reconciliation.collection_slug = ${input.collectionSlug}\n\t\t\t\t\tAND reconciliation.run_token = ${input.runToken}\n\t\t\t\t\tAND reconciliation.target_epoch = ${input.changeEpoch}\n\t\t\t\t\tAND reconciliation.state = 'leased'\n\t\t\t\t\tAND reconciliation.phase = ${input.phase}\n\t\t\t\t\tAND reconciliation.lease_token = ${input.leaseToken}\n\t\t\t\t\tAND ${this.qualifiedLeaseIsLive(\"reconciliation.lease_expires_at\")}\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 status.reconciliation_required = 1\n\t\t\t\t\tAND status.status = 'running'\n\t\t\t\t\tAND status.cursor = ${input.runToken}\n\t\t\t\t\tAND status.change_epoch = ${input.changeEpoch}\n\t\t\t\t\tAND EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_activation AS activation\n\t\t\t\t\t\tWHERE activation.task_key = 'incremental_capture'\n\t\t\t\t\t\t\tAND activation.state = 'active'\n\t\t\t\t\t)\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 = reconciliation.collection_id\n\t\t\t\t\t)\n\t\t\t)\n\t\t\tON CONFLICT (collection_id, content_id) DO UPDATE SET\n\t\t\t\tcollection_slug = excluded.collection_slug,\n\t\t\t\tchange_epoch = excluded.change_epoch,\n\t\t\t\twork_version = _emdash_media_usage_work.work_version + 1,\n\t\t\t\tstate = 'pending',\n\t\t\t\tattempt_count = 0,\n\t\t\t\tnext_attempt_at = excluded.next_attempt_at,\n\t\t\t\tlease_token = NULL,\n\t\t\t\tlease_expires_at = NULL,\n\t\t\t\tlast_attempted_at = NULL,\n\t\t\t\tlast_error_code = NULL,\n\t\t\t\tupdated_at = excluded.updated_at\n\t\t\tWHERE _emdash_media_usage_work.change_epoch < excluded.change_epoch\n\t\t`.execute(this.db);\n\t}\n\n\tasync findOperatorPage(options: {\n\t\tcollectionSlug: string;\n\t\tstate?: MediaUsageWorkState;\n\t\tlimit?: number;\n\t\tcursor?: string;\n\t}): Promise<FindManyResult<MediaUsageOperatorWorkItem> | null> {\n\t\tif (!options.collectionSlug) {\n\t\t\tthrow new Error(\"Media usage work listing requires a collection slug\");\n\t\t}\n\t\tif (options.state !== undefined && !isMediaUsageWorkState(options.state)) {\n\t\t\tthrow new Error(\"Media usage work listing requires a valid state\");\n\t\t}\n\t\tconst limit = operatorLimit(options.limit);\n\t\tconst cursor = options.cursor ? decodeCursor(options.cursor) : null;\n\t\tconst collection = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select([\"id\", \"slug\"])\n\t\t\t.where(\"slug\", \"=\", options.collectionSlug)\n\t\t\t.executeTakeFirst();\n\t\tif (!collection) return null;\n\n\t\tconst states = options.state ? [options.state] : MEDIA_USAGE_WORK_STATES;\n\t\tconst candidates: MediaUsageOperatorWorkItem[] = [];\n\t\tfor (const state of states) {\n\t\t\tconst rows = await this.findOperatorRows({\n\t\t\t\tcollectionId: collection.id,\n\t\t\t\tcollectionSlug: collection.slug,\n\t\t\t\tstate,\n\t\t\t\tlimit: limit + 1,\n\t\t\t\tcursor,\n\t\t\t});\n\t\t\tcandidates.push(...rows.map(rowToOperatorWork));\n\t\t}\n\n\t\tconst ordered = candidates.toSorted(compareOperatorWork);\n\t\tconst items = ordered.slice(0, limit);\n\t\tconst result: FindManyResult<MediaUsageOperatorWorkItem> = { items };\n\t\tif (ordered.length > limit && items.length > 0) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.updatedAt, last.contentId);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate async findOperatorRows(input: {\n\t\tcollectionId: string;\n\t\tcollectionSlug: string;\n\t\tstate: MediaUsageWorkState;\n\t\tlimit: number;\n\t\tcursor: { orderValue: string; id: string } | null;\n\t}): Promise<Selectable<MediaUsageWorkTable>[]> {\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_work as work\")\n\t\t\t.innerJoin(\"_emdash_collections as current_collection\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"current_collection.id\", \"=\", \"work.collection_id\")\n\t\t\t\t\t.onRef(\"current_collection.slug\", \"=\", \"work.collection_slug\"),\n\t\t\t)\n\t\t\t.selectAll(\"work\")\n\t\t\t.where(\"work.collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"work.collection_slug\", \"=\", input.collectionSlug)\n\t\t\t.where(\"work.state\", \"=\", input.state);\n\t\tif (input.cursor) {\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"work.updated_at\", \"<\", input.cursor!.orderValue),\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"work.updated_at\", \"=\", input.cursor!.orderValue),\n\t\t\t\t\t\teb(\"work.content_id\", \"<\", input.cursor!.id),\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\t\treturn query\n\t\t\t.orderBy(\"work.updated_at\", \"desc\")\n\t\t\t.orderBy(\"work.content_id\", \"desc\")\n\t\t\t.limit(input.limit)\n\t\t\t.execute();\n\t}\n\n\tasync retryOperatorWork(input: {\n\t\tcollectionId: string;\n\t\tcontentId: string;\n\t}): Promise<MediaUsageOperatorRetryResult> {\n\t\tif (!input.collectionId || !input.contentId) {\n\t\t\tthrow new Error(\"Media usage operator retry requires collection and content IDs\");\n\t\t}\n\t\tconst collection = await this.findActiveOperatorCollection(input.collectionId);\n\t\tif (!collection) return { outcome: \"collection_not_found\" };\n\n\t\tconst observed = await this.findWorkByIdentity(input.collectionId, input.contentId);\n\t\tif (observed?.state === \"pending\" && observed.collection_slug === collection.slug) {\n\t\t\treturn { outcome: \"pending\", changed: false, work: rowToOperatorWork(observed) };\n\t\t}\n\n\t\tconst invalidated = await this.invalidateCoverageForOperatorRetry({\n\t\t\t...input,\n\t\t\tcollectionSlug: collection.slug,\n\t\t\tobserved,\n\t\t});\n\t\tif (!invalidated) return this.operatorRetryLost(input);\n\n\t\tconst reopened = observed\n\t\t\t? await this.reopenObservedWork(observed, collection.slug, invalidated.change_epoch)\n\t\t\t: await this.createOperatorWork({\n\t\t\t\t\t...input,\n\t\t\t\t\tcollectionSlug: collection.slug,\n\t\t\t\t\tchangeEpoch: invalidated.change_epoch,\n\t\t\t\t});\n\t\tif (reopened) {\n\t\t\treturn { outcome: \"pending\", changed: true, work: rowToOperatorWork(reopened) };\n\t\t}\n\t\treturn this.operatorRetryLost(input);\n\t}\n\n\tprivate async findActiveOperatorCollection(\n\t\tcollectionId: string,\n\t): Promise<{ id: string; slug: string } | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_collections as collection\")\n\t\t\t.innerJoin(\"_emdash_media_usage_index_status as status\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"status.collection_id\", \"=\", \"collection.id\")\n\t\t\t\t\t.onRef(\"status.scope_key\", \"=\", \"collection.slug\"),\n\t\t\t)\n\t\t\t.select([\"collection.id\", \"collection.slug\"])\n\t\t\t.where(\"collection.id\", \"=\", collectionId)\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.capture_state\", \"=\", \"active\")\n\t\t\t.executeTakeFirst();\n\t\treturn row ?? null;\n\t}\n\n\tprivate async findWorkByIdentity(\n\t\tcollectionId: string,\n\t\tcontentId: string,\n\t): Promise<Selectable<MediaUsageWorkTable> | null> {\n\t\treturn (\n\t\t\t(await this.db\n\t\t\t\t.selectFrom(\"_emdash_media_usage_work\")\n\t\t\t\t.selectAll()\n\t\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t\t.where(\"content_id\", \"=\", contentId)\n\t\t\t\t.executeTakeFirst()) ?? null\n\t\t);\n\t}\n\n\tprivate async invalidateCoverageForOperatorRetry(input: {\n\t\tcollectionId: string;\n\t\tcollectionSlug: string;\n\t\tcontentId: string;\n\t\tobserved: Selectable<MediaUsageWorkTable> | null;\n\t}): Promise<{ change_epoch: number | string } | null> {\n\t\tlet query = 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: sql<string>`CASE WHEN status IN ('complete', 'partial', 'failed') THEN 'stale' ELSE status END`,\n\t\t\t\tcompleted_at: sql<\n\t\t\t\t\tstring | null\n\t\t\t\t>`CASE WHEN status IN ('complete', 'partial', 'failed') THEN NULL ELSE completed_at END`,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: this.timestampOffset(0),\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\", \"=\", input.collectionSlug)\n\t\t\t.where(\"status.collection_id\", \"=\", input.collectionId)\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\n\t\tconst observed = input.observed;\n\t\tif (observed) {\n\t\t\tquery = query.where((eb) => {\n\t\t\t\tlet work = eb\n\t\t\t\t\t.selectFrom(\"_emdash_media_usage_work as work\")\n\t\t\t\t\t.select(\"work.content_id\")\n\t\t\t\t\t.whereRef(\"work.collection_id\", \"=\", \"status.collection_id\")\n\t\t\t\t\t.where(\"work.content_id\", \"=\", input.contentId)\n\t\t\t\t\t.where(\"work.work_version\", \"=\", observed.work_version)\n\t\t\t\t\t.where(\"work.state\", \"=\", observed.state);\n\t\t\t\tif (observed.state === \"leased\") {\n\t\t\t\t\twork = work\n\t\t\t\t\t\t.where(\"work.lease_expires_at\", \"is not\", null)\n\t\t\t\t\t\t.where(this.timestampIsDue(\"work.lease_expires_at\"));\n\t\t\t\t}\n\t\t\t\treturn eb.exists(work);\n\t\t\t});\n\t\t} else {\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.not(\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_work as work\")\n\t\t\t\t\t\t\t.select(\"work.content_id\")\n\t\t\t\t\t\t\t.whereRef(\"work.collection_id\", \"=\", \"status.collection_id\")\n\t\t\t\t\t\t\t.where(\"work.content_id\", \"=\", input.contentId),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\treturn (await query.returning(\"change_epoch\").executeTakeFirst()) ?? null;\n\t}\n\n\tprivate async reopenObservedWork(\n\t\tobserved: Selectable<MediaUsageWorkTable>,\n\t\tcollectionSlug: string,\n\t\tchangeEpoch: number | string,\n\t): Promise<Selectable<MediaUsageWorkTable> | null> {\n\t\tlet query = this.db\n\t\t\t.updateTable(\"_emdash_media_usage_work\")\n\t\t\t.set({\n\t\t\t\tcollection_slug: collectionSlug,\n\t\t\t\tchange_epoch: changeEpoch,\n\t\t\t\twork_version: sql<number>`work_version + 1`,\n\t\t\t\tstate: \"pending\",\n\t\t\t\tattempt_count: 0,\n\t\t\t\tnext_attempt_at: this.timestampOffset(0),\n\t\t\t\tlease_token: null,\n\t\t\t\tlease_expires_at: null,\n\t\t\t\tlast_attempted_at: null,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: this.timestampOffset(0),\n\t\t\t})\n\t\t\t.where(\"collection_id\", \"=\", observed.collection_id)\n\t\t\t.where(\"content_id\", \"=\", observed.content_id)\n\t\t\t.where(\"work_version\", \"=\", observed.work_version)\n\t\t\t.where(\"state\", \"=\", observed.state)\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.innerJoin(\"_emdash_media_usage_index_status as status\", (join) =>\n\t\t\t\t\t\t\tjoin\n\t\t\t\t\t\t\t\t.onRef(\"status.collection_id\", \"=\", \"collection.id\")\n\t\t\t\t\t\t\t\t.onRef(\"status.scope_key\", \"=\", \"collection.slug\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.select(\"collection.id\")\n\t\t\t\t\t\t.where(\"collection.id\", \"=\", observed.collection_id)\n\t\t\t\t\t\t.where(\"collection.slug\", \"=\", collectionSlug)\n\t\t\t\t\t\t.where(\"status.adapter_id\", \"=\", \"content-media\")\n\t\t\t\t\t\t.where(\"status.scope_type\", \"=\", \"collection\")\n\t\t\t\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t\t\t\t.where(\"status.change_epoch\", \"=\", changeEpoch),\n\t\t\t\t),\n\t\t\t);\n\t\tif (observed.state === \"leased\") {\n\t\t\tquery = query\n\t\t\t\t.where(\"lease_expires_at\", \"is not\", null)\n\t\t\t\t.where(this.timestampIsDue(\"lease_expires_at\"));\n\t\t}\n\t\treturn (await query.returningAll().executeTakeFirst()) ?? null;\n\t}\n\n\tprivate async createOperatorWork(input: {\n\t\tcollectionId: string;\n\t\tcollectionSlug: string;\n\t\tcontentId: string;\n\t\tchangeEpoch: number | string;\n\t}): Promise<Selectable<MediaUsageWorkTable> | null> {\n\t\tconst now = this.timestampOffset(0);\n\t\treturn (\n\t\t\t(await this.db\n\t\t\t\t.insertInto(\"_emdash_media_usage_work\")\n\t\t\t\t.columns([\n\t\t\t\t\t\"collection_id\",\n\t\t\t\t\t\"collection_slug\",\n\t\t\t\t\t\"content_id\",\n\t\t\t\t\t\"change_epoch\",\n\t\t\t\t\t\"work_version\",\n\t\t\t\t\t\"state\",\n\t\t\t\t\t\"attempt_count\",\n\t\t\t\t\t\"next_attempt_at\",\n\t\t\t\t\t\"lease_token\",\n\t\t\t\t\t\"lease_expires_at\",\n\t\t\t\t\t\"last_attempted_at\",\n\t\t\t\t\t\"last_error_code\",\n\t\t\t\t\t\"created_at\",\n\t\t\t\t\t\"updated_at\",\n\t\t\t\t])\n\t\t\t\t.expression((insert) =>\n\t\t\t\t\tinsert\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_index_status as status\")\n\t\t\t\t\t\t.innerJoin(\"_emdash_collections as collection\", (join) =>\n\t\t\t\t\t\t\tjoin\n\t\t\t\t\t\t\t\t.onRef(\"collection.id\", \"=\", \"status.collection_id\")\n\t\t\t\t\t\t\t\t.onRef(\"collection.slug\", \"=\", \"status.scope_key\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.select((select) => [\n\t\t\t\t\t\t\tselect.val(input.collectionId).as(\"collection_id\"),\n\t\t\t\t\t\t\t\"collection.slug as collection_slug\",\n\t\t\t\t\t\t\tselect.val(input.contentId).as(\"content_id\"),\n\t\t\t\t\t\t\t\"status.change_epoch as change_epoch\",\n\t\t\t\t\t\t\tselect.val(1).as(\"work_version\"),\n\t\t\t\t\t\t\tselect.val(\"pending\").as(\"state\"),\n\t\t\t\t\t\t\tselect.val(0).as(\"attempt_count\"),\n\t\t\t\t\t\t\tnow.as(\"next_attempt_at\"),\n\t\t\t\t\t\t\tsql<null>`NULL`.as(\"lease_token\"),\n\t\t\t\t\t\t\tsql<null>`NULL`.as(\"lease_expires_at\"),\n\t\t\t\t\t\t\tsql<null>`NULL`.as(\"last_attempted_at\"),\n\t\t\t\t\t\t\tsql<null>`NULL`.as(\"last_error_code\"),\n\t\t\t\t\t\t\tnow.as(\"created_at\"),\n\t\t\t\t\t\t\tnow.as(\"updated_at\"),\n\t\t\t\t\t\t])\n\t\t\t\t\t\t.where(\"status.adapter_id\", \"=\", \"content-media\")\n\t\t\t\t\t\t.where(\"status.scope_type\", \"=\", \"collection\")\n\t\t\t\t\t\t.where(\"status.scope_key\", \"=\", input.collectionSlug)\n\t\t\t\t\t\t.where(\"status.collection_id\", \"=\", input.collectionId)\n\t\t\t\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t\t\t\t.where(\"status.change_epoch\", \"=\", input.changeEpoch),\n\t\t\t\t)\n\t\t\t\t.onConflict((conflict) => conflict.columns([\"collection_id\", \"content_id\"]).doNothing())\n\t\t\t\t.returningAll()\n\t\t\t\t.executeTakeFirst()) ?? null\n\t\t);\n\t}\n\n\tprivate async operatorRetryLost(input: {\n\t\tcollectionId: string;\n\t\tcontentId: string;\n\t}): Promise<MediaUsageOperatorRetryResult> {\n\t\tif (!(await this.findActiveOperatorCollection(input.collectionId))) {\n\t\t\treturn { outcome: \"collection_not_found\" };\n\t\t}\n\t\tconst current = await this.findWorkByIdentity(input.collectionId, input.contentId);\n\t\tif (current?.state === \"pending\") {\n\t\t\treturn { outcome: \"pending\", changed: false, work: rowToOperatorWork(current) };\n\t\t}\n\t\tconst liveLease = await this.findLiveLeaseExpiry(input.collectionId, input.contentId);\n\t\tif (liveLease) return { outcome: \"lease_active\", leaseExpiresAt: liveLease };\n\t\treturn { outcome: \"conflict\" };\n\t}\n\n\tprivate async findLiveLeaseExpiry(\n\t\tcollectionId: string,\n\t\tcontentId: string,\n\t): Promise<string | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_work\")\n\t\t\t.select(\"lease_expires_at\")\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.where(\"content_id\", \"=\", contentId)\n\t\t\t.where(\"state\", \"=\", \"leased\")\n\t\t\t.where(\"lease_expires_at\", \"is not\", null)\n\t\t\t.where(this.leaseIsLive())\n\t\t\t.executeTakeFirst();\n\t\treturn row?.lease_expires_at ?? null;\n\t}\n\n\tasync claimDueWorkBatch(input: {\n\t\tlimit: number;\n\t\tleaseDurationSeconds: number;\n\t}): Promise<MediaUsageWorkRecord[]> {\n\t\tif (\n\t\t\t!Number.isSafeInteger(input.limit) ||\n\t\t\tinput.limit < 1 ||\n\t\t\tinput.limit > MAX_WORK_SELECTION_LIMIT\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Media usage due-work limit must be a whole number from 1 to ${MAX_WORK_SELECTION_LIMIT}`,\n\t\t\t);\n\t\t}\n\t\tconst leaseDurationSeconds = durationSeconds(\n\t\t\tinput.leaseDurationSeconds,\n\t\t\t\"lease duration\",\n\t\t\tfalse,\n\t\t);\n\t\tconst leaseToken = ulid();\n\t\tconst now = this.timestampOffset(0);\n\t\tlet candidates = this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_work as due\")\n\t\t\t.select([\"due.collection_id\", \"due.content_id\", \"due.work_version\"])\n\t\t\t.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"due.state\", \"in\", [\"pending\", \"retry\"]),\n\t\t\t\t\t\tthis.timestampIsDue(\"due.next_attempt_at\"),\n\t\t\t\t\t]),\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"due.state\", \"=\", \"leased\"),\n\t\t\t\t\t\teb(\"due.lease_expires_at\", \"is not\", null),\n\t\t\t\t\t\tthis.timestampIsDue(\"due.lease_expires_at\"),\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t)\n\t\t\t.orderBy(\n\t\t\t\tsql<string>`CASE\n\t\t\t\t\tWHEN due.state = 'leased' THEN due.lease_expires_at\n\t\t\t\t\tELSE due.next_attempt_at\n\t\t\t\tEND`,\n\t\t\t\t\"asc\",\n\t\t\t)\n\t\t\t.orderBy(\"due.updated_at\", \"asc\")\n\t\t\t.orderBy(\"due.collection_id\", \"asc\")\n\t\t\t.orderBy(\"due.content_id\", \"asc\")\n\t\t\t.limit(input.limit);\n\t\tif (isPostgres(this.db)) candidates = candidates.forUpdate().skipLocked();\n\t\tconst rows = await this.db\n\t\t\t.with(\"due_media_usage_work\", () => candidates)\n\t\t\t.updateTable(\"_emdash_media_usage_work\")\n\t\t\t.set({\n\t\t\t\tstate: \"leased\",\n\t\t\t\tlease_token: leaseToken,\n\t\t\t\tlease_expires_at: this.timestampOffset(leaseDurationSeconds),\n\t\t\t\tlast_attempted_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where((eb) =>\n\t\t\t\teb.and([\n\t\t\t\t\teb.exists(\n\t\t\t\t\t\teb\n\t\t\t\t\t\t\t.selectFrom(\"due_media_usage_work as due\")\n\t\t\t\t\t\t\t.select(\"due.content_id\")\n\t\t\t\t\t\t\t.whereRef(\"due.collection_id\", \"=\", \"_emdash_media_usage_work.collection_id\")\n\t\t\t\t\t\t\t.whereRef(\"due.content_id\", \"=\", \"_emdash_media_usage_work.content_id\")\n\t\t\t\t\t\t\t.whereRef(\"due.work_version\", \"=\", \"_emdash_media_usage_work.work_version\"),\n\t\t\t\t\t),\n\t\t\t\t\teb.or([\n\t\t\t\t\t\teb.and([\n\t\t\t\t\t\t\teb(\"state\", \"in\", [\"pending\", \"retry\"]),\n\t\t\t\t\t\t\tthis.timestampIsDue(\"next_attempt_at\"),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\teb.and([\n\t\t\t\t\t\t\teb(\"state\", \"=\", \"leased\"),\n\t\t\t\t\t\t\teb(\"lease_expires_at\", \"is not\", null),\n\t\t\t\t\t\t\tthis.timestampIsDue(\"lease_expires_at\"),\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\t.returningAll()\n\t\t\t.execute();\n\n\t\treturn rows.map(rowToWork);\n\t}\n\n\tasync hasNonterminalWork(): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_work\")\n\t\t\t.select(\"content_id\")\n\t\t\t.where(\"state\", \"in\", [\"pending\", \"retry\", \"leased\"])\n\t\t\t.limit(1)\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n\n\tasync findWorkForContent(\n\t\tcollectionSlug: string,\n\t\tcontentId: string,\n\t): Promise<MediaUsageWorkRecord | null> {\n\t\tif (!collectionSlug || !contentId) {\n\t\t\tthrow new Error(\"Media usage work lookup requires collection and content identity\");\n\t\t}\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_work\")\n\t\t\t.innerJoin(\"_emdash_collections as current_collection\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"current_collection.id\", \"=\", \"_emdash_media_usage_work.collection_id\")\n\t\t\t\t\t.onRef(\"current_collection.slug\", \"=\", \"_emdash_media_usage_work.collection_slug\"),\n\t\t\t)\n\t\t\t.selectAll(\"_emdash_media_usage_work\")\n\t\t\t.where(\"_emdash_media_usage_work.collection_slug\", \"=\", collectionSlug)\n\t\t\t.where(\"_emdash_media_usage_work.content_id\", \"=\", contentId)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToWork(row) : null;\n\t}\n\n\tasync claimWork(\n\t\tinput: MediaUsageWorkIdentity & {\n\t\t\tleaseDurationSeconds: number;\n\t\t},\n\t): Promise<MediaUsageWorkRecord | null> {\n\t\tassertIdentity(input);\n\t\tconst leaseDurationSeconds = durationSeconds(\n\t\t\tinput.leaseDurationSeconds,\n\t\t\t\"lease duration\",\n\t\t\tfalse,\n\t\t);\n\t\tconst leaseToken = ulid();\n\t\tconst now = this.timestampOffset(0);\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_work\")\n\t\t\t.set({\n\t\t\t\tstate: \"leased\",\n\t\t\t\tlease_token: leaseToken,\n\t\t\t\tlease_expires_at: this.timestampOffset(leaseDurationSeconds),\n\t\t\t\tlast_attempted_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"content_id\", \"=\", input.contentId)\n\t\t\t.where(\"work_version\", \"=\", input.workVersion)\n\t\t\t.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb.and([eb(\"state\", \"in\", [\"pending\", \"retry\"]), this.timestampIsDue(\"next_attempt_at\")]),\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"state\", \"=\", \"leased\"),\n\t\t\t\t\t\teb(\"lease_expires_at\", \"is not\", null),\n\t\t\t\t\t\tthis.timestampIsDue(\"lease_expires_at\"),\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t)\n\t\t\t.returningAll()\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? rowToWork(row) : null;\n\t}\n\n\tasync completeWorkBatch(inputs: readonly MediaUsageWorkLease[]): Promise<Set<string>> {\n\t\tconst unique = [\n\t\t\t...new Map(\n\t\t\t\tinputs.map((input) => {\n\t\t\t\t\tassertLease(input);\n\t\t\t\t\treturn [workIdentityKey(input), input] as const;\n\t\t\t\t}),\n\t\t\t).values(),\n\t\t];\n\t\tconst completed = new Set<string>();\n\t\tif (unique.length === 0) return completed;\n\t\tconst payload = JSON.stringify(\n\t\t\tunique.map((input) => ({\n\t\t\t\tcollection_id: input.collectionId,\n\t\t\t\tcontent_id: input.contentId,\n\t\t\t\twork_version: String(input.workVersion),\n\t\t\t\tlease_token: input.leaseToken,\n\t\t\t})),\n\t\t);\n\t\tconst claimed = this.claimedWorkBatchInput(payload);\n\t\tconst result = await sql<{\n\t\t\tcollection_id: string;\n\t\t\tcontent_id: string;\n\t\t\twork_version: MediaUsageWorkVersion;\n\t\t}>`\n\t\t\tWITH claimed AS (${claimed})\n\t\t\tDELETE FROM _emdash_media_usage_work AS work\n\t\t\tWHERE work.state = 'leased'\n\t\t\t\tAND ${this.qualifiedLeaseIsLive(\"work.lease_expires_at\")}\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM claimed\n\t\t\t\t\tWHERE claimed.collection_id = work.collection_id\n\t\t\t\t\t\tAND claimed.content_id = work.content_id\n\t\t\t\t\t\tAND claimed.work_version = work.work_version\n\t\t\t\t\t\tAND claimed.lease_token = work.lease_token\n\t\t\t\t)\n\t\t\tRETURNING collection_id, content_id, work_version\n\t\t`.execute(this.db);\n\t\tfor (const row of result.rows) {\n\t\t\tcompleted.add(\n\t\t\t\tworkIdentityKey({\n\t\t\t\t\tcollectionId: row.collection_id,\n\t\t\t\t\tcontentId: row.content_id,\n\t\t\t\t\tworkVersion: row.work_version,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn completed;\n\t}\n\n\tasync lockClaimedWorkBatch(inputs: readonly MediaUsageWorkLease[]): Promise<Set<string>> {\n\t\tconst unique = [\n\t\t\t...new Map(\n\t\t\t\tinputs.map((input) => {\n\t\t\t\t\tassertLease(input);\n\t\t\t\t\treturn [workIdentityKey(input), input] as const;\n\t\t\t\t}),\n\t\t\t).values(),\n\t\t].toSorted((left, right) => workIdentityKey(left).localeCompare(workIdentityKey(right)));\n\t\tif (!isPostgres(this.db)) return new Set(unique.map(workIdentityKey));\n\t\tif (unique.length === 0) return new Set();\n\t\tconst payload = JSON.stringify(\n\t\t\tunique.map((input) => ({\n\t\t\t\tcollection_id: input.collectionId,\n\t\t\t\tcontent_id: input.contentId,\n\t\t\t\twork_version: String(input.workVersion),\n\t\t\t\tlease_token: input.leaseToken,\n\t\t\t})),\n\t\t);\n\t\tconst claimed = this.claimedWorkBatchInput(payload);\n\t\tconst result = await sql<{\n\t\t\tcollection_id: string;\n\t\t\tcontent_id: string;\n\t\t\twork_version: MediaUsageWorkVersion;\n\t\t}>`\n\t\t\tWITH claimed AS (${claimed})\n\t\t\tSELECT work.collection_id, work.content_id, work.work_version\n\t\t\tFROM _emdash_media_usage_work AS work\n\t\t\tINNER JOIN claimed\n\t\t\t\tON claimed.collection_id = work.collection_id\n\t\t\t\tAND claimed.content_id = work.content_id\n\t\t\t\tAND claimed.work_version = work.work_version\n\t\t\t\tAND claimed.lease_token = work.lease_token\n\t\t\tWHERE work.state = 'leased'\n\t\t\t\tAND ${this.qualifiedLeaseIsLive(\"work.lease_expires_at\")}\n\t\t\tORDER BY work.collection_id, work.content_id\n\t\t\tFOR UPDATE\n\t\t`.execute(this.db);\n\t\treturn new Set(\n\t\t\tresult.rows.map((row) =>\n\t\t\t\tworkIdentityKey({\n\t\t\t\t\tcollectionId: row.collection_id,\n\t\t\t\t\tcontentId: row.content_id,\n\t\t\t\t\tworkVersion: row.work_version,\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t}\n\n\tasync retryClaimedWorkBatch(input: {\n\t\twork: readonly MediaUsageWorkLease[];\n\t\terrorCode: string;\n\t\tretryDelaySeconds: number;\n\t\tmaxAttempts: number;\n\t}): Promise<Map<string, \"retry\" | \"failed\">> {\n\t\tassertErrorCode(input.errorCode);\n\t\tconst retryDelaySeconds = durationSeconds(input.retryDelaySeconds, \"retry delay\", true);\n\t\tif (!Number.isSafeInteger(input.maxAttempts) || input.maxAttempts < 1) {\n\t\t\tthrow new Error(\"Media usage work max attempts must be a positive whole number\");\n\t\t}\n\t\tconst unique = [\n\t\t\t...new Map(\n\t\t\t\tinput.work.map((work) => {\n\t\t\t\t\tassertLease(work);\n\t\t\t\t\treturn [workIdentityKey(work), work] as const;\n\t\t\t\t}),\n\t\t\t).values(),\n\t\t];\n\t\tconst transitioned = new Map<string, \"retry\" | \"failed\">();\n\t\tif (unique.length === 0) return transitioned;\n\t\tconst payload = JSON.stringify(\n\t\t\tunique.map((work) => ({\n\t\t\t\tcollection_id: work.collectionId,\n\t\t\t\tcontent_id: work.contentId,\n\t\t\t\twork_version: String(work.workVersion),\n\t\t\t\tlease_token: work.leaseToken,\n\t\t\t})),\n\t\t);\n\t\tconst claimed = this.claimedWorkBatchInput(payload);\n\t\tconst result = await sql<{\n\t\t\tcollection_id: string;\n\t\t\tcontent_id: string;\n\t\t\twork_version: MediaUsageWorkVersion;\n\t\t\tstate: \"retry\" | \"failed\";\n\t\t}>`\n\t\t\tWITH claimed AS (${claimed})\n\t\t\tUPDATE _emdash_media_usage_work AS work\n\t\t\tSET state = CASE WHEN work.attempt_count + 1 >= ${input.maxAttempts} THEN 'failed' ELSE 'retry' END,\n\t\t\t\tattempt_count = work.attempt_count + 1,\n\t\t\t\tnext_attempt_at = ${this.timestampOffset(retryDelaySeconds)},\n\t\t\t\tlease_token = NULL,\n\t\t\t\tlease_expires_at = NULL,\n\t\t\t\tlast_error_code = ${input.errorCode},\n\t\t\t\tupdated_at = ${this.timestampOffset(0)}\n\t\t\tWHERE work.state = 'leased'\n\t\t\t\tAND ${this.qualifiedLeaseIsLive(\"work.lease_expires_at\")}\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM claimed\n\t\t\t\t\tWHERE claimed.collection_id = work.collection_id\n\t\t\t\t\t\tAND claimed.content_id = work.content_id\n\t\t\t\t\t\tAND claimed.work_version = work.work_version\n\t\t\t\t\t\tAND claimed.lease_token = work.lease_token\n\t\t\t\t)\n\t\t\tRETURNING collection_id, content_id, work_version, state\n\t\t`.execute(this.db);\n\t\tfor (const row of result.rows) {\n\t\t\ttransitioned.set(\n\t\t\t\tworkIdentityKey({\n\t\t\t\t\tcollectionId: row.collection_id,\n\t\t\t\t\tcontentId: row.content_id,\n\t\t\t\t\tworkVersion: row.work_version,\n\t\t\t\t}),\n\t\t\t\trow.state,\n\t\t\t);\n\t\t}\n\t\treturn transitioned;\n\t}\n\n\tasync releaseClaimedWorkBatch(inputs: readonly MediaUsageWorkLease[]): Promise<Set<string>> {\n\t\tconst unique = [\n\t\t\t...new Map(\n\t\t\t\tinputs.map((input) => {\n\t\t\t\t\tassertLease(input);\n\t\t\t\t\treturn [workIdentityKey(input), input] as const;\n\t\t\t\t}),\n\t\t\t).values(),\n\t\t];\n\t\tconst released = new Set<string>();\n\t\tif (unique.length === 0) return released;\n\t\tconst payload = JSON.stringify(\n\t\t\tunique.map((input) => ({\n\t\t\t\tcollection_id: input.collectionId,\n\t\t\t\tcontent_id: input.contentId,\n\t\t\t\twork_version: String(input.workVersion),\n\t\t\t\tlease_token: input.leaseToken,\n\t\t\t})),\n\t\t);\n\t\tconst claimed = this.claimedWorkBatchInput(payload);\n\t\tconst result = await sql<{\n\t\t\tcollection_id: string;\n\t\t\tcontent_id: string;\n\t\t\twork_version: MediaUsageWorkVersion;\n\t\t}>`\n\t\t\tWITH claimed AS (${claimed})\n\t\t\tUPDATE _emdash_media_usage_work AS work\n\t\t\tSET state = 'pending',\n\t\t\t\tnext_attempt_at = ${this.timestampOffset(0)},\n\t\t\t\tlease_token = NULL,\n\t\t\t\tlease_expires_at = NULL,\n\t\t\t\tupdated_at = ${this.timestampOffset(0)}\n\t\t\tWHERE work.state = 'leased'\n\t\t\t\tAND ${this.qualifiedLeaseIsLive(\"work.lease_expires_at\")}\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM claimed\n\t\t\t\t\tWHERE claimed.collection_id = work.collection_id\n\t\t\t\t\t\tAND claimed.content_id = work.content_id\n\t\t\t\t\t\tAND claimed.work_version = work.work_version\n\t\t\t\t\t\tAND claimed.lease_token = work.lease_token\n\t\t\t\t)\n\t\t\tRETURNING collection_id, content_id, work_version\n\t\t`.execute(this.db);\n\t\tfor (const row of result.rows) {\n\t\t\treleased.add(\n\t\t\t\tworkIdentityKey({\n\t\t\t\t\tcollectionId: row.collection_id,\n\t\t\t\t\tcontentId: row.content_id,\n\t\t\t\t\tworkVersion: row.work_version,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn released;\n\t}\n\n\tasync deleteWorkThroughEpoch(\n\t\tcollectionId: string,\n\t\tmaxChangeEpoch: number | string,\n\t): Promise<number> {\n\t\tif (!collectionId) throw new Error(\"Media usage work cleanup requires a collection ID\");\n\t\tassertNonNegativeDecimal(maxChangeEpoch, \"change epoch\");\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_media_usage_work\")\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.where(\"change_epoch\", \"<=\", maxChangeEpoch)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows ?? 0);\n\t}\n\n\tasync deleteObsoleteReconciliationWork(input: {\n\t\tcollectionId: string;\n\t\tcollectionSlug: string;\n\t\trunToken: string;\n\t\tleaseToken: string;\n\t\ttargetEpoch: number | string;\n\t}): Promise<number> {\n\t\tassertNonNegativeDecimal(input.targetEpoch, \"target epoch\");\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_media_usage_work as work\")\n\t\t\t.where(\"work.collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"work.change_epoch\", \"<\", input.targetEpoch)\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_reconciliations as reconciliation\")\n\t\t\t\t\t\t.innerJoin(\"_emdash_media_usage_index_status as status\", (join) =>\n\t\t\t\t\t\t\tjoin\n\t\t\t\t\t\t\t\t.onRef(\"status.collection_id\", \"=\", \"reconciliation.collection_id\")\n\t\t\t\t\t\t\t\t.onRef(\"status.scope_key\", \"=\", \"reconciliation.collection_slug\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.innerJoin(\"_emdash_collections as collection\", (join) =>\n\t\t\t\t\t\t\tjoin\n\t\t\t\t\t\t\t\t.onRef(\"collection.id\", \"=\", \"reconciliation.collection_id\")\n\t\t\t\t\t\t\t\t.onRef(\"collection.slug\", \"=\", \"reconciliation.collection_slug\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.select(\"reconciliation.collection_id\")\n\t\t\t\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.collectionId)\n\t\t\t\t\t\t.where(\"reconciliation.collection_slug\", \"=\", input.collectionSlug)\n\t\t\t\t\t\t.where(\"reconciliation.run_token\", \"=\", input.runToken)\n\t\t\t\t\t\t.where(\"reconciliation.target_epoch\", \"=\", input.targetEpoch)\n\t\t\t\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t\t\t\t.where(\"reconciliation.lease_token\", \"=\", input.leaseToken)\n\t\t\t\t\t\t.where(this.qualifiedLeaseIsLive(\"reconciliation.lease_expires_at\"))\n\t\t\t\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t\t\t\t.where(\"status.reconciliation_required\", \"=\", 1)\n\t\t\t\t\t\t.where(\"status.status\", \"=\", \"running\")\n\t\t\t\t\t\t.where(\"status.cursor\", \"=\", input.runToken)\n\t\t\t\t\t\t.where(\"status.change_epoch\", \"=\", input.targetEpoch),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows ?? 0);\n\t}\n\n\tprivate leaseIsLive(): RawBuilder<boolean> {\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`lease_expires_at::timestamptz > clock_timestamp()`\n\t\t\t: sql<boolean>`lease_expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate qualifiedLeaseIsLive(column: string): RawBuilder<boolean> {\n\t\tconst expiry = sql.ref(column);\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`${expiry} > to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`\n\t\t\t: sql<boolean>`${expiry} > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate timestampIsDue(\n\t\tcolumn:\n\t\t\t| \"next_attempt_at\"\n\t\t\t| \"lease_expires_at\"\n\t\t\t| \"work.lease_expires_at\"\n\t\t\t| \"work.next_attempt_at\"\n\t\t\t| \"due.next_attempt_at\"\n\t\t\t| \"due.lease_expires_at\",\n\t): RawBuilder<boolean> {\n\t\treturn isPostgres(this.db)\n\t\t\t? sql<boolean>`${sql.ref(column)} <= to_char(\n\t\t\t\tstatement_timestamp() AT TIME ZONE 'UTC',\n\t\t\t\t'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'\n\t\t\t)`\n\t\t\t: sql<boolean>`${sql.ref(column)} <= strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\t}\n\n\tprivate timestampOffset(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 claimedWorkBatchInput(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 ->> 'collection_id' AS collection_id,\n\t\t\t\t\tentry.value ->> 'content_id' AS content_id,\n\t\t\t\t\tCAST(entry.value ->> 'work_version' AS bigint) AS work_version,\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, '$.collection_id') AS collection_id,\n\t\t\t\tjson_extract(entry.value, '$.content_id') AS content_id,\n\t\t\t\tCAST(json_extract(entry.value, '$.work_version') AS integer) AS work_version,\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\nfunction workIdentityKey(input: MediaUsageWorkIdentity): string {\n\treturn `${input.collectionId}\\u0000${input.contentId}\\u0000${String(input.workVersion)}`;\n}\n\nfunction operatorLimit(value: number | undefined): number {\n\tif (value === undefined) return MEDIA_USAGE_WORK_OPERATOR_DEFAULT_LIMIT;\n\tif (!Number.isSafeInteger(value) || value < 1 || value > MEDIA_USAGE_WORK_OPERATOR_MAX_LIMIT) {\n\t\tthrow new Error(\n\t\t\t`Media usage operator limit must be a whole number from 1 to ${MEDIA_USAGE_WORK_OPERATOR_MAX_LIMIT}`,\n\t\t);\n\t}\n\treturn value;\n}\n\nfunction durationSeconds(value: number, label: string, allowZero: boolean): number {\n\tif (\n\t\t!Number.isSafeInteger(value) ||\n\t\tvalue < (allowZero ? 0 : 1) ||\n\t\tvalue > MAX_PORTABLE_DURATION_SECONDS\n\t) {\n\t\tthrow new Error(\n\t\t\t`Media usage work ${label} must be ${allowZero ? \"a non-negative\" : \"a positive\"} whole number of seconds no greater than one year`,\n\t\t);\n\t}\n\treturn value;\n}\n\nfunction assertIdentity(input: MediaUsageWorkIdentity): void {\n\tif (!input.collectionId || !input.contentId) {\n\t\tthrow new Error(\"Media usage work identity must include collection and content IDs\");\n\t}\n\tconst validVersion =\n\t\t(typeof input.workVersion === \"number\" &&\n\t\t\tNumber.isSafeInteger(input.workVersion) &&\n\t\t\tinput.workVersion > 0) ||\n\t\t(typeof input.workVersion === \"string\" && POSITIVE_DECIMAL_PATTERN.test(input.workVersion));\n\tif (!validVersion) {\n\t\tthrow new Error(\"Media usage work identity must include a work version\");\n\t}\n}\n\nfunction assertNonNegativeDecimal(value: number | string, label: string): void {\n\tconst valid =\n\t\t(typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0) ||\n\t\t(typeof value === \"string\" && NON_NEGATIVE_DECIMAL_PATTERN.test(value));\n\tif (!valid) throw new Error(`Media usage work ${label} must be a non-negative whole number`);\n}\n\nfunction assertToken(value: string): void {\n\tif (!value) throw new Error(\"Media usage work lease token must not be empty\");\n}\n\nfunction assertLease(input: MediaUsageWorkLease): void {\n\tassertIdentity(input);\n\tassertToken(input.leaseToken);\n}\n\nfunction assertErrorCode(value: string): void {\n\tif (!STABLE_ERROR_CODE_PATTERN.test(value)) {\n\t\tthrow new Error(\"Media usage work error code must use a stable SCREAMING_SNAKE_CASE value\");\n\t}\n}\n\nfunction rowToWork(row: Selectable<MediaUsageWorkTable>): MediaUsageWorkRecord {\n\tif (!isMediaUsageWorkState(row.state)) {\n\t\tthrow new Error(`Invalid media usage work state: ${row.state}`);\n\t}\n\treturn {\n\t\tcollectionId: row.collection_id,\n\t\tcollectionSlug: row.collection_slug,\n\t\tcontentId: row.content_id,\n\t\tchangeEpoch: row.change_epoch,\n\t\tworkVersion: row.work_version,\n\t\tstate: row.state,\n\t\tattemptCount: row.attempt_count,\n\t\tnextAttemptAt: row.next_attempt_at,\n\t\tleaseToken: row.lease_token,\n\t\tleaseExpiresAt: row.lease_expires_at,\n\t\tlastAttemptedAt: row.last_attempted_at,\n\t\tlastErrorCode: row.last_error_code,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n\nfunction rowToOperatorWork(\n\trow: Selectable<MediaUsageWorkTable> | MediaUsageWorkRecord,\n): MediaUsageOperatorWorkItem {\n\tconst work = \"collection_id\" in row ? rowToWork(row) : row;\n\treturn {\n\t\tcollectionId: work.collectionId,\n\t\tcollectionSlug: work.collectionSlug,\n\t\tcontentId: work.contentId,\n\t\tstate: work.state,\n\t\tattemptCount: work.attemptCount,\n\t\tnextAttemptAt: work.nextAttemptAt,\n\t\tleaseExpiresAt: work.leaseExpiresAt,\n\t\tlastAttemptedAt: work.lastAttemptedAt,\n\t\tlastErrorCode: work.lastErrorCode,\n\t\tupdatedAt: work.updatedAt,\n\t};\n}\n\nfunction isMediaUsageWorkState(value: string): value is MediaUsageWorkState {\n\treturn value === \"pending\" || value === \"retry\" || value === \"leased\" || value === \"failed\";\n}\n\nfunction compareOperatorWork(a: MediaUsageOperatorWorkItem, b: MediaUsageOperatorWorkItem): number {\n\tconst updated = b.updatedAt.localeCompare(a.updatedAt);\n\treturn updated !== 0 ? updated : b.contentId.localeCompare(a.contentId);\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { i as InvalidCursorError } from "./types-CQPWhPxE.mjs";
2
- import { t as MediaUsageWorkRepository } from "./media-usage-work-DrCbqBcl.mjs";
3
- import { t as ErrorCode } from "./errors-CLUPm7aD.mjs";
4
- import { t as MediaUsageCollectionDeletionRepository } from "./collection-deletion-DQPvMD8R.mjs";
2
+ import { t as MediaUsageWorkRepository } from "./media-usage-work-C-fhM30c.mjs";
3
+ import { t as MediaUsageCollectionDeletionRepository } from "./collection-deletion-m_oi2c0N.mjs";
4
+ import { t as ErrorCode } from "./errors-n2j49uNf.mjs";
5
5
 
6
6
  //#region src/api/handlers/media-usage-work.ts
7
7
  async function handleMediaUsageWorkList(db, query) {
@@ -149,4 +149,4 @@ async function handleMediaUsageWorkRetry(db, input) {
149
149
 
150
150
  //#endregion
151
151
  export { handleMediaUsageWorkRetry as i, handleMediaUsageCollectionDeletionRetry as n, handleMediaUsageWorkList as r, handleMediaUsageCollectionDeletionList as t };
152
- //# sourceMappingURL=media-usage-work-CLo_6tct.mjs.map
152
+ //# sourceMappingURL=media-usage-work-DWb2XPMI.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"media-usage-work-CLo_6tct.mjs","names":[],"sources":["../src/api/handlers/media-usage-work.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport { MediaUsageWorkRepository } from \"../../database/repositories/media-usage-work.js\";\nimport { InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { MediaUsageCollectionDeletionRepository } from \"../../media/usage/collection-deletion.js\";\nimport { ErrorCode } from \"../errors.js\";\nimport type {\n\tMediaUsageWorkListQuery,\n\tMediaUsageWorkListResponse,\n\tMediaUsageWorkRetryRequest,\n\tMediaUsageWorkRetryResponse,\n\tMediaUsageCollectionDeletionListQuery,\n\tMediaUsageCollectionDeletionListResponse,\n\tMediaUsageCollectionDeletionRetryRequest,\n\tMediaUsageCollectionDeletionRetryResponse,\n} from \"../schemas/media-usage.js\";\nimport type { ApiResult } from \"../types.js\";\n\nexport type {\n\tMediaUsageWorkItem,\n\tMediaUsageWorkListQuery,\n\tMediaUsageWorkListResponse,\n\tMediaUsageWorkRetryRequest,\n\tMediaUsageWorkRetryResponse,\n} from \"../schemas/media-usage.js\";\n\nexport async function handleMediaUsageWorkList(\n\tdb: Kysely<Database>,\n\tquery: MediaUsageWorkListQuery,\n): Promise<ApiResult<MediaUsageWorkListResponse>> {\n\ttry {\n\t\tconst page = await new MediaUsageWorkRepository(db).findOperatorPage({\n\t\t\tcollectionSlug: query.collection,\n\t\t\tstate: query.state,\n\t\t\tcursor: query.cursor,\n\t\t\tlimit: query.limit,\n\t\t});\n\t\tif (!page) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.COLLECTION_NOT_FOUND,\n\t\t\t\t\tmessage: \"Collection not found\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: page };\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.INVALID_CURSOR,\n\t\t\t\t\tmessage: \"Invalid media usage work cursor\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage-work] list failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_WORK_LIST_ERROR,\n\t\t\t\tmessage: \"Failed to list media usage work\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageCollectionDeletionList(\n\tdb: Kysely<Database>,\n\tquery: MediaUsageCollectionDeletionListQuery,\n): Promise<ApiResult<MediaUsageCollectionDeletionListResponse>> {\n\ttry {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: await new MediaUsageCollectionDeletionRepository(db).findOperatorPage(query),\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: ErrorCode.INVALID_CURSOR, message: \"Invalid cursor\" },\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage:collection-deletion] list failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_COLLECTION_DELETION_LIST_ERROR,\n\t\t\t\tmessage: \"Failed to list collection deletions\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageCollectionDeletionRetry(\n\tdb: Kysely<Database>,\n\tinput: MediaUsageCollectionDeletionRetryRequest,\n): Promise<ApiResult<MediaUsageCollectionDeletionRetryResponse>> {\n\ttry {\n\t\tconst result = await new MediaUsageCollectionDeletionRepository(db).retryOperatorDeletion(\n\t\t\tinput,\n\t\t);\n\t\tif (result.outcome === \"pending\") {\n\t\t\treturn { success: true, data: { changed: result.changed, item: result.item } };\n\t\t}\n\t\tif (result.outcome === \"lease_active\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.WORK_LEASE_ACTIVE,\n\t\t\t\t\tmessage: \"Collection deletion is currently leased\",\n\t\t\t\t\tdetails: { leaseExpiresAt: result.leaseExpiresAt },\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: result.outcome === \"not_found\" ? ErrorCode.NOT_FOUND : ErrorCode.WORK_CHANGED,\n\t\t\t\tmessage:\n\t\t\t\t\tresult.outcome === \"not_found\"\n\t\t\t\t\t\t? \"Collection deletion not found\"\n\t\t\t\t\t\t: \"Collection deletion changed\",\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage:collection-deletion] retry failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_COLLECTION_DELETION_RETRY_ERROR,\n\t\t\t\tmessage: \"Failed to retry collection deletion\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageWorkRetry(\n\tdb: Kysely<Database>,\n\tinput: MediaUsageWorkRetryRequest,\n): Promise<ApiResult<MediaUsageWorkRetryResponse>> {\n\ttry {\n\t\tconst result = await new MediaUsageWorkRepository(db).retryOperatorWork(input);\n\t\tswitch (result.outcome) {\n\t\t\tcase \"pending\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: { changed: result.changed, item: result.work },\n\t\t\t\t};\n\t\t\tcase \"lease_active\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: ErrorCode.WORK_LEASE_ACTIVE,\n\t\t\t\t\t\tmessage: \"Media usage work is currently leased\",\n\t\t\t\t\t\tdetails: { leaseExpiresAt: result.leaseExpiresAt },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\tcase \"collection_not_found\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: ErrorCode.COLLECTION_NOT_FOUND,\n\t\t\t\t\t\tmessage: \"Collection not found\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\tcase \"conflict\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: ErrorCode.WORK_CHANGED,\n\t\t\t\t\t\tmessage: \"Media usage work changed; retry the request\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage-work] retry failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_WORK_RETRY_ERROR,\n\t\t\t\tmessage: \"Failed to retry media usage work\",\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":";;;;;;AA2BA,eAAsB,yBACrB,IACA,OACiD;AACjD,KAAI;EACH,MAAM,OAAO,MAAM,IAAI,yBAAyB,GAAG,CAAC,iBAAiB;GACpE,gBAAgB,MAAM;GACtB,OAAO,MAAM;GACb,QAAQ,MAAM;GACd,OAAO,MAAM;GACb,CAAC;AACF,MAAI,CAAC,KACJ,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,SAAO;GAAE,SAAS;GAAM,MAAM;GAAM;UAC5B,OAAO;AACf,MAAI,iBAAiB,mBACpB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,UAAQ,MAAM,mCAAmC,MAAM;AACvD,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,uCACrB,IACA,OAC+D;AAC/D,KAAI;AACH,SAAO;GACN,SAAS;GACT,MAAM,MAAM,IAAI,uCAAuC,GAAG,CAAC,iBAAiB,MAAM;GAClF;UACO,OAAO;AACf,MAAI,iBAAiB,mBACpB,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM,UAAU;IAAgB,SAAS;IAAkB;GACpE;AAEF,UAAQ,MAAM,kDAAkD,MAAM;AACtE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,wCACrB,IACA,OACgE;AAChE,KAAI;EACH,MAAM,SAAS,MAAM,IAAI,uCAAuC,GAAG,CAAC,sBACnE,MACA;AACD,MAAI,OAAO,YAAY,UACtB,QAAO;GAAE,SAAS;GAAM,MAAM;IAAE,SAAS,OAAO;IAAS,MAAM,OAAO;IAAM;GAAE;AAE/E,MAAI,OAAO,YAAY,eACtB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT,SAAS,EAAE,gBAAgB,OAAO,gBAAgB;IAClD;GACD;AAEF,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,OAAO,YAAY,cAAc,UAAU,YAAY,UAAU;IACvE,SACC,OAAO,YAAY,cAChB,kCACA;IACJ;GACD;UACO,OAAO;AACf,UAAQ,MAAM,mDAAmD,MAAM;AACvE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,0BACrB,IACA,OACkD;AAClD,KAAI;EACH,MAAM,SAAS,MAAM,IAAI,yBAAyB,GAAG,CAAC,kBAAkB,MAAM;AAC9E,UAAQ,OAAO,SAAf;GACC,KAAK,UACJ,QAAO;IACN,SAAS;IACT,MAAM;KAAE,SAAS,OAAO;KAAS,MAAM,OAAO;KAAM;IACpD;GACF,KAAK,eACJ,QAAO;IACN,SAAS;IACT,OAAO;KACN,MAAM,UAAU;KAChB,SAAS;KACT,SAAS,EAAE,gBAAgB,OAAO,gBAAgB;KAClD;IACD;GACF,KAAK,uBACJ,QAAO;IACN,SAAS;IACT,OAAO;KACN,MAAM,UAAU;KAChB,SAAS;KACT;IACD;GACF,KAAK,WACJ,QAAO;IACN,SAAS;IACT,OAAO;KACN,MAAM,UAAU;KAChB,SAAS;KACT;IACD;;UAEK,OAAO;AACf,UAAQ,MAAM,oCAAoC,MAAM;AACxD,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD"}
1
+ {"version":3,"file":"media-usage-work-DWb2XPMI.mjs","names":[],"sources":["../src/api/handlers/media-usage-work.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport { MediaUsageWorkRepository } from \"../../database/repositories/media-usage-work.js\";\nimport { InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { MediaUsageCollectionDeletionRepository } from \"../../media/usage/collection-deletion.js\";\nimport { ErrorCode } from \"../errors.js\";\nimport type {\n\tMediaUsageWorkListQuery,\n\tMediaUsageWorkListResponse,\n\tMediaUsageWorkRetryRequest,\n\tMediaUsageWorkRetryResponse,\n\tMediaUsageCollectionDeletionListQuery,\n\tMediaUsageCollectionDeletionListResponse,\n\tMediaUsageCollectionDeletionRetryRequest,\n\tMediaUsageCollectionDeletionRetryResponse,\n} from \"../schemas/media-usage.js\";\nimport type { ApiResult } from \"../types.js\";\n\nexport type {\n\tMediaUsageWorkItem,\n\tMediaUsageWorkListQuery,\n\tMediaUsageWorkListResponse,\n\tMediaUsageWorkRetryRequest,\n\tMediaUsageWorkRetryResponse,\n} from \"../schemas/media-usage.js\";\n\nexport async function handleMediaUsageWorkList(\n\tdb: Kysely<Database>,\n\tquery: MediaUsageWorkListQuery,\n): Promise<ApiResult<MediaUsageWorkListResponse>> {\n\ttry {\n\t\tconst page = await new MediaUsageWorkRepository(db).findOperatorPage({\n\t\t\tcollectionSlug: query.collection,\n\t\t\tstate: query.state,\n\t\t\tcursor: query.cursor,\n\t\t\tlimit: query.limit,\n\t\t});\n\t\tif (!page) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.COLLECTION_NOT_FOUND,\n\t\t\t\t\tmessage: \"Collection not found\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: page };\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.INVALID_CURSOR,\n\t\t\t\t\tmessage: \"Invalid media usage work cursor\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage-work] list failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_WORK_LIST_ERROR,\n\t\t\t\tmessage: \"Failed to list media usage work\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageCollectionDeletionList(\n\tdb: Kysely<Database>,\n\tquery: MediaUsageCollectionDeletionListQuery,\n): Promise<ApiResult<MediaUsageCollectionDeletionListResponse>> {\n\ttry {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: await new MediaUsageCollectionDeletionRepository(db).findOperatorPage(query),\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: ErrorCode.INVALID_CURSOR, message: \"Invalid cursor\" },\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage:collection-deletion] list failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_COLLECTION_DELETION_LIST_ERROR,\n\t\t\t\tmessage: \"Failed to list collection deletions\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageCollectionDeletionRetry(\n\tdb: Kysely<Database>,\n\tinput: MediaUsageCollectionDeletionRetryRequest,\n): Promise<ApiResult<MediaUsageCollectionDeletionRetryResponse>> {\n\ttry {\n\t\tconst result = await new MediaUsageCollectionDeletionRepository(db).retryOperatorDeletion(\n\t\t\tinput,\n\t\t);\n\t\tif (result.outcome === \"pending\") {\n\t\t\treturn { success: true, data: { changed: result.changed, item: result.item } };\n\t\t}\n\t\tif (result.outcome === \"lease_active\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.WORK_LEASE_ACTIVE,\n\t\t\t\t\tmessage: \"Collection deletion is currently leased\",\n\t\t\t\t\tdetails: { leaseExpiresAt: result.leaseExpiresAt },\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: result.outcome === \"not_found\" ? ErrorCode.NOT_FOUND : ErrorCode.WORK_CHANGED,\n\t\t\t\tmessage:\n\t\t\t\t\tresult.outcome === \"not_found\"\n\t\t\t\t\t\t? \"Collection deletion not found\"\n\t\t\t\t\t\t: \"Collection deletion changed\",\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage:collection-deletion] retry failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_COLLECTION_DELETION_RETRY_ERROR,\n\t\t\t\tmessage: \"Failed to retry collection deletion\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageWorkRetry(\n\tdb: Kysely<Database>,\n\tinput: MediaUsageWorkRetryRequest,\n): Promise<ApiResult<MediaUsageWorkRetryResponse>> {\n\ttry {\n\t\tconst result = await new MediaUsageWorkRepository(db).retryOperatorWork(input);\n\t\tswitch (result.outcome) {\n\t\t\tcase \"pending\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: { changed: result.changed, item: result.work },\n\t\t\t\t};\n\t\t\tcase \"lease_active\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: ErrorCode.WORK_LEASE_ACTIVE,\n\t\t\t\t\t\tmessage: \"Media usage work is currently leased\",\n\t\t\t\t\t\tdetails: { leaseExpiresAt: result.leaseExpiresAt },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\tcase \"collection_not_found\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: ErrorCode.COLLECTION_NOT_FOUND,\n\t\t\t\t\t\tmessage: \"Collection not found\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\tcase \"conflict\":\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: ErrorCode.WORK_CHANGED,\n\t\t\t\t\t\tmessage: \"Media usage work changed; retry the request\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage-work] retry failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_WORK_RETRY_ERROR,\n\t\t\t\tmessage: \"Failed to retry media usage work\",\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":";;;;;;AA2BA,eAAsB,yBACrB,IACA,OACiD;AACjD,KAAI;EACH,MAAM,OAAO,MAAM,IAAI,yBAAyB,GAAG,CAAC,iBAAiB;GACpE,gBAAgB,MAAM;GACtB,OAAO,MAAM;GACb,QAAQ,MAAM;GACd,OAAO,MAAM;GACb,CAAC;AACF,MAAI,CAAC,KACJ,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,SAAO;GAAE,SAAS;GAAM,MAAM;GAAM;UAC5B,OAAO;AACf,MAAI,iBAAiB,mBACpB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,UAAQ,MAAM,mCAAmC,MAAM;AACvD,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,uCACrB,IACA,OAC+D;AAC/D,KAAI;AACH,SAAO;GACN,SAAS;GACT,MAAM,MAAM,IAAI,uCAAuC,GAAG,CAAC,iBAAiB,MAAM;GAClF;UACO,OAAO;AACf,MAAI,iBAAiB,mBACpB,QAAO;GACN,SAAS;GACT,OAAO;IAAE,MAAM,UAAU;IAAgB,SAAS;IAAkB;GACpE;AAEF,UAAQ,MAAM,kDAAkD,MAAM;AACtE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,wCACrB,IACA,OACgE;AAChE,KAAI;EACH,MAAM,SAAS,MAAM,IAAI,uCAAuC,GAAG,CAAC,sBACnE,MACA;AACD,MAAI,OAAO,YAAY,UACtB,QAAO;GAAE,SAAS;GAAM,MAAM;IAAE,SAAS,OAAO;IAAS,MAAM,OAAO;IAAM;GAAE;AAE/E,MAAI,OAAO,YAAY,eACtB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT,SAAS,EAAE,gBAAgB,OAAO,gBAAgB;IAClD;GACD;AAEF,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,OAAO,YAAY,cAAc,UAAU,YAAY,UAAU;IACvE,SACC,OAAO,YAAY,cAChB,kCACA;IACJ;GACD;UACO,OAAO;AACf,UAAQ,MAAM,mDAAmD,MAAM;AACvE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,0BACrB,IACA,OACkD;AAClD,KAAI;EACH,MAAM,SAAS,MAAM,IAAI,yBAAyB,GAAG,CAAC,kBAAkB,MAAM;AAC9E,UAAQ,OAAO,SAAf;GACC,KAAK,UACJ,QAAO;IACN,SAAS;IACT,MAAM;KAAE,SAAS,OAAO;KAAS,MAAM,OAAO;KAAM;IACpD;GACF,KAAK,eACJ,QAAO;IACN,SAAS;IACT,OAAO;KACN,MAAM,UAAU;KAChB,SAAS;KACT,SAAS,EAAE,gBAAgB,OAAO,gBAAgB;KAClD;IACD;GACF,KAAK,uBACJ,QAAO;IACN,SAAS;IACT,OAAO;KACN,MAAM,UAAU;KAChB,SAAS;KACT;IACD;GACF,KAAK,WACJ,QAAO;IACN,SAAS;IACT,OAAO;KACN,MAAM,UAAU;KAChB,SAAS;KACT;IACD;;UAEK,OAAO;AACf,UAAQ,MAAM,oCAAoC,MAAM;AACxD,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD"}
@@ -1,5 +1,5 @@
1
1
  import { p as tableExists } from "./dialect-helpers-BSbfaO3F.mjs";
2
- import { t as apiError } from "./error-DupyJZE2.mjs";
2
+ import { t as apiError } from "./error-D9w94fjV.mjs";
3
3
 
4
4
  //#region src/api/media-usage-write-fence.ts
5
5
  var MediaUsageActivationWriteBlockedError = class extends Error {
@@ -39,4 +39,4 @@ async function findMediaUsageActivationWriteFenceError(db) {
39
39
 
40
40
  //#endregion
41
41
  export { assertMediaUsageActivationWriteAllowed as n, checkMediaUsageActivationWriteFence as r, MediaUsageActivationWriteBlockedError as t };
42
- //# sourceMappingURL=media-usage-write-fence-aHEgN1zB.mjs.map
42
+ //# sourceMappingURL=media-usage-write-fence-BwoJVRDC.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"media-usage-write-fence-aHEgN1zB.mjs","names":[],"sources":["../src/api/media-usage-write-fence.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport { tableExists } from \"../database/dialect-helpers.js\";\nimport type { Database } from \"../database/types.js\";\nimport { apiError } from \"./error.js\";\n\nexport interface MediaUsageActivationWriteFenceError {\n\tcode: \"MEDIA_USAGE_ACTIVATION_IN_PROGRESS\" | \"MEDIA_USAGE_ACTIVATION_CHECK_FAILED\";\n\tmessage: string;\n\tstatus: 503;\n}\n\nexport class MediaUsageActivationWriteBlockedError extends Error {\n\tconstructor(\n\t\treadonly code: MediaUsageActivationWriteFenceError[\"code\"],\n\t\tmessage: string,\n\t\treadonly status: 503,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = code;\n\t}\n}\n\nexport async function checkMediaUsageActivationWriteFence(\n\tdb: Kysely<Database>,\n): Promise<Response | null> {\n\tconst error = await findMediaUsageActivationWriteFenceError(db);\n\treturn error ? apiError(error.code, error.message, error.status) : null;\n}\n\nexport async function assertMediaUsageActivationWriteAllowed(db: Kysely<Database>): Promise<void> {\n\tconst error = await findMediaUsageActivationWriteFenceError(db);\n\tif (error) {\n\t\tthrow new MediaUsageActivationWriteBlockedError(error.code, error.message, error.status);\n\t}\n}\n\nexport async function findMediaUsageActivationWriteFenceError(\n\tdb: Kysely<Database>,\n): Promise<MediaUsageActivationWriteFenceError | null> {\n\tif (!(await tableExists(db, \"_emdash_media_usage_activation\"))) return null;\n\ttry {\n\t\tconst row = await db\n\t\t\t.selectFrom(\"_emdash_media_usage_activation\")\n\t\t\t.select(\"state\")\n\t\t\t.where(\"task_key\", \"=\", \"incremental_capture\")\n\t\t\t.executeTakeFirst();\n\t\tif (row?.state === \"activating\") {\n\t\t\treturn {\n\t\t\t\tcode: \"MEDIA_USAGE_ACTIVATION_IN_PROGRESS\",\n\t\t\t\tmessage: \"Media usage activation is in progress\",\n\t\t\t\tstatus: 503,\n\t\t\t};\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage] Failed to check the activation write fence:\", error);\n\t\treturn {\n\t\t\tcode: \"MEDIA_USAGE_ACTIVATION_CHECK_FAILED\",\n\t\t\tmessage: \"Unable to verify media usage activation state\",\n\t\t\tstatus: 503,\n\t\t};\n\t}\n\treturn null;\n}\n"],"mappings":";;;;AAYA,IAAa,wCAAb,cAA2D,MAAM;CAChE,YACC,AAAS,MACT,SACA,AAAS,QACR;AACD,QAAM,QAAQ;EAJL;EAEA;AAGT,OAAK,OAAO;;;AAId,eAAsB,oCACrB,IAC2B;CAC3B,MAAM,QAAQ,MAAM,wCAAwC,GAAG;AAC/D,QAAO,QAAQ,SAAS,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO,GAAG;;AAGpE,eAAsB,uCAAuC,IAAqC;CACjG,MAAM,QAAQ,MAAM,wCAAwC,GAAG;AAC/D,KAAI,MACH,OAAM,IAAI,sCAAsC,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO;;AAI1F,eAAsB,wCACrB,IACsD;AACtD,KAAI,CAAE,MAAM,YAAY,IAAI,iCAAiC,CAAG,QAAO;AACvE,KAAI;AAMH,OALY,MAAM,GAChB,WAAW,iCAAiC,CAC5C,OAAO,QAAQ,CACf,MAAM,YAAY,KAAK,sBAAsB,CAC7C,kBAAkB,GACX,UAAU,aAClB,QAAO;GACN,MAAM;GACN,SAAS;GACT,QAAQ;GACR;UAEM,OAAO;AACf,UAAQ,MAAM,6DAA6D,MAAM;AACjF,SAAO;GACN,MAAM;GACN,SAAS;GACT,QAAQ;GACR;;AAEF,QAAO"}
1
+ {"version":3,"file":"media-usage-write-fence-BwoJVRDC.mjs","names":[],"sources":["../src/api/media-usage-write-fence.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport { tableExists } from \"../database/dialect-helpers.js\";\nimport type { Database } from \"../database/types.js\";\nimport { apiError } from \"./error.js\";\n\nexport interface MediaUsageActivationWriteFenceError {\n\tcode: \"MEDIA_USAGE_ACTIVATION_IN_PROGRESS\" | \"MEDIA_USAGE_ACTIVATION_CHECK_FAILED\";\n\tmessage: string;\n\tstatus: 503;\n}\n\nexport class MediaUsageActivationWriteBlockedError extends Error {\n\tconstructor(\n\t\treadonly code: MediaUsageActivationWriteFenceError[\"code\"],\n\t\tmessage: string,\n\t\treadonly status: 503,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = code;\n\t}\n}\n\nexport async function checkMediaUsageActivationWriteFence(\n\tdb: Kysely<Database>,\n): Promise<Response | null> {\n\tconst error = await findMediaUsageActivationWriteFenceError(db);\n\treturn error ? apiError(error.code, error.message, error.status) : null;\n}\n\nexport async function assertMediaUsageActivationWriteAllowed(db: Kysely<Database>): Promise<void> {\n\tconst error = await findMediaUsageActivationWriteFenceError(db);\n\tif (error) {\n\t\tthrow new MediaUsageActivationWriteBlockedError(error.code, error.message, error.status);\n\t}\n}\n\nexport async function findMediaUsageActivationWriteFenceError(\n\tdb: Kysely<Database>,\n): Promise<MediaUsageActivationWriteFenceError | null> {\n\tif (!(await tableExists(db, \"_emdash_media_usage_activation\"))) return null;\n\ttry {\n\t\tconst row = await db\n\t\t\t.selectFrom(\"_emdash_media_usage_activation\")\n\t\t\t.select(\"state\")\n\t\t\t.where(\"task_key\", \"=\", \"incremental_capture\")\n\t\t\t.executeTakeFirst();\n\t\tif (row?.state === \"activating\") {\n\t\t\treturn {\n\t\t\t\tcode: \"MEDIA_USAGE_ACTIVATION_IN_PROGRESS\",\n\t\t\t\tmessage: \"Media usage activation is in progress\",\n\t\t\t\tstatus: 503,\n\t\t\t};\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage] Failed to check the activation write fence:\", error);\n\t\treturn {\n\t\t\tcode: \"MEDIA_USAGE_ACTIVATION_CHECK_FAILED\",\n\t\t\tmessage: \"Unable to verify media usage activation state\",\n\t\t\tstatus: 503,\n\t\t};\n\t}\n\treturn null;\n}\n"],"mappings":";;;;AAYA,IAAa,wCAAb,cAA2D,MAAM;CAChE,YACC,AAAS,MACT,SACA,AAAS,QACR;AACD,QAAM,QAAQ;EAJL;EAEA;AAGT,OAAK,OAAO;;;AAId,eAAsB,oCACrB,IAC2B;CAC3B,MAAM,QAAQ,MAAM,wCAAwC,GAAG;AAC/D,QAAO,QAAQ,SAAS,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO,GAAG;;AAGpE,eAAsB,uCAAuC,IAAqC;CACjG,MAAM,QAAQ,MAAM,wCAAwC,GAAG;AAC/D,KAAI,MACH,OAAM,IAAI,sCAAsC,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO;;AAI1F,eAAsB,wCACrB,IACsD;AACtD,KAAI,CAAE,MAAM,YAAY,IAAI,iCAAiC,CAAG,QAAO;AACvE,KAAI;AAMH,OALY,MAAM,GAChB,WAAW,iCAAiC,CAC5C,OAAO,QAAQ,CACf,MAAM,YAAY,KAAK,sBAAsB,CAC7C,kBAAkB,GACX,UAAU,aAClB,QAAO;GACN,MAAM;GACN,SAAS;GACT,QAAQ;GACR;UAEM,OAAO;AACf,UAAQ,MAAM,6DAA6D,MAAM;AACjF,SAAO;GACN,MAAM;GACN,SAAS;GACT,QAAQ;GACR;;AAEF,QAAO"}
@@ -1,7 +1,7 @@
1
- import { c as __exportAll } from "./runner-C1T11CfC.mjs";
1
+ import { c as __exportAll } from "./runner-77GOZCnH.mjs";
2
2
  import { a as resolveConfiguredLocale, r as getI18nConfig } from "./config-C3EBstHi.mjs";
3
3
  import { u as invalidateMenuObjectCache } from "./object-cache-71tPfV4A.mjs";
4
- import { t as withTransaction } from "./transaction-NQj4VJ7Z.mjs";
4
+ import { t as withTransaction } from "./transaction-0KOpOyMu.mjs";
5
5
  import { ulid } from "ulidx";
6
6
 
7
7
  //#region src/database/repositories/menu.ts
@@ -741,4 +741,4 @@ async function handleMenuItemReorder(db, menuName, items, options = {}) {
741
741
 
742
742
  //#endregion
743
743
  export { handleMenuItemDelete as a, handleMenuList as c, menus_exports as d, handleMenuItemCreate as i, handleMenuTranslations as l, handleMenuDelete as n, handleMenuItemReorder as o, handleMenuGet as r, handleMenuItemUpdate as s, handleMenuCreate as t, handleMenuUpdate as u };
744
- //# sourceMappingURL=menus-TCNSd2vp.mjs.map
744
+ //# sourceMappingURL=menus-CD7EFLwz.mjs.map