emdash 0.37.0 → 0.38.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.
- package/dist/{activation-K0kGBWuJ.mjs → activation-DyNTe_Tl.mjs} +3 -3
- package/dist/{activation-K0kGBWuJ.mjs.map → activation-DyNTe_Tl.mjs.map} +1 -1
- package/dist/{adapters-BDQwg236.d.mts → adapters-DCEgOBXi.d.mts} +1 -1
- package/dist/{adapters-BDQwg236.d.mts.map → adapters-DCEgOBXi.d.mts.map} +1 -1
- package/dist/{allowed-origins-BGglilcs.mjs → allowed-origins-GFUVavRj.mjs} +2 -2
- package/dist/{allowed-origins-BGglilcs.mjs.map → allowed-origins-GFUVavRj.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +23 -22
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +5 -5
- package/dist/{api-Dz6rgoa3.mjs → api-BvxJmnFY.mjs} +141 -87
- package/dist/api-BvxJmnFY.mjs.map +1 -0
- package/dist/{api-tokens-BSsQACNe.mjs → api-tokens-xpGqMHrC.mjs} +2 -2
- package/dist/{api-tokens-BSsQACNe.mjs.map → api-tokens-xpGqMHrC.mjs.map} +1 -1
- package/dist/{apply-B4SIOxR1.mjs → apply-DLmM3R7f.mjs} +25 -21
- package/dist/apply-DLmM3R7f.mjs.map +1 -0
- package/dist/{config-it29yDLA.mjs → artifact-fetch-P2JXVwOq.mjs} +8 -199
- package/dist/artifact-fetch-P2JXVwOq.mjs.map +1 -0
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +37 -11
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +6 -6
- package/dist/astro/middleware/media-usage-write-fence.mjs +3 -3
- package/dist/astro/middleware/redirect.mjs +7 -5
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.mjs +3 -3
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +10 -10
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +154 -125
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -9
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -9
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -9
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +16 -16
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +16 -16
- package/dist/astro/routes/api/admin/bylines/index.mjs +16 -16
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +11 -11
- package/dist/astro/routes/api/admin/comments/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/counts.mjs +3 -3
- package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/media-usage/activation.mjs +13 -13
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +15 -15
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +15 -15
- package/dist/astro/routes/api/admin/media-usage/progress.mjs +13 -13
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +16 -16
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +15 -15
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +15 -15
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +56 -53
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +56 -53
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +54 -51
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +54 -51
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +55 -52
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +55 -52
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +54 -51
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +54 -51
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +55 -52
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +54 -51
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +55 -52
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +56 -53
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +5 -4
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +56 -53
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +55 -52
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +54 -51
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +54 -51
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +54 -51
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
- package/dist/astro/routes/api/admin/users/index.mjs +6 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
- package/dist/astro/routes/api/auth/invite/complete.mjs +11 -11
- package/dist/astro/routes/api/auth/invite/index.mjs +8 -8
- package/dist/astro/routes/api/auth/invite/register-options.mjs +10 -10
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +10 -10
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/me.mjs +7 -7
- package/dist/astro/routes/api/auth/mode.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/options.mjs +12 -12
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -10
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -11
- package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -11
- package/dist/astro/routes/api/auth/signup/complete.mjs +11 -11
- package/dist/astro/routes/api/auth/signup/request.mjs +10 -10
- package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +11 -11
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +13 -8
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts +10 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +66 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -11
- package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +14 -9
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +19 -17
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +19 -17
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +15 -8
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +15 -14
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +13 -8
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +23 -11
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/index.mjs +14 -9
- package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
- package/dist/astro/routes/api/dashboard.mjs +6 -6
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +16 -16
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +14 -13
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +10 -10
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +13 -13
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +16 -16
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +27 -26
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +4 -4
- package/dist/astro/routes/api/mcp.mjs +71 -55
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +10 -10
- package/dist/astro/routes/api/media/_id_/replace.mjs +8 -8
- package/dist/astro/routes/api/media/_id_/upload.mjs +5 -5
- package/dist/astro/routes/api/media/_id_/usage.mjs +18 -18
- package/dist/astro/routes/api/media/_id_.mjs +17 -17
- package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
- package/dist/astro/routes/api/media/folders/_id_.mjs +8 -8
- package/dist/astro/routes/api/media/folders/index.mjs +8 -8
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
- package/dist/astro/routes/api/media/providers/index.mjs +2 -2
- package/dist/astro/routes/api/media/upload-url.mjs +9 -9
- package/dist/astro/routes/api/media.mjs +21 -21
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_/items.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_.mjs +9 -9
- package/dist/astro/routes/api/menus/index.mjs +9 -9
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
- package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
- package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
- package/dist/astro/routes/api/oauth/register.mjs +2 -2
- package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
- package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
- package/dist/astro/routes/api/oauth/token.mjs +5 -5
- package/dist/astro/routes/api/openapi.json.mjs +84 -18
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
- package/dist/astro/routes/api/redirects/404s/index.mjs +12 -11
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -11
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +13 -12
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +13 -12
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.mjs +19 -17
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +14 -12
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +19 -17
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +54 -51
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +54 -51
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +54 -51
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +54 -51
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +54 -51
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.mjs +54 -51
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +13 -11
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +54 -51
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +54 -51
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +12 -11
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +11 -10
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +12 -11
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +7 -6
- package/dist/astro/routes/api/search/stats.mjs.map +1 -1
- package/dist/astro/routes/api/search/suggest.mjs +11 -10
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +11 -10
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +11 -10
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -6
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -5
- package/dist/astro/routes/api/settings/backups/archives/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/export.mjs +7 -6
- package/dist/astro/routes/api/settings/backups/export.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/index.mjs +8 -7
- package/dist/astro/routes/api/settings/backups/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +14 -14
- package/dist/astro/routes/api/setup/admin-verify.mjs +12 -12
- package/dist/astro/routes/api/setup/admin.mjs +11 -11
- package/dist/astro/routes/api/setup/dev-bypass.mjs +33 -31
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +33 -31
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +3 -3
- package/dist/astro/routes/api/snapshot.mjs +8 -7
- package/dist/astro/routes/api/snapshot.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +15 -14
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +5 -5
- package/dist/astro/routes/api/typegen.mjs +4 -4
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +12 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +12 -12
- package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
- package/dist/astro/routes/api/widget-areas/index.mjs +12 -12
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +6 -6
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +11 -10
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +7 -7
- package/dist/astro/types.d.mts +32 -17
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{authorize-Bkf_UHhD.mjs → authorize-C2QHlWSS.mjs} +2 -2
- package/dist/{authorize-Bkf_UHhD.mjs.map → authorize-C2QHlWSS.mjs.map} +1 -1
- package/dist/{backup-rwVAl9NI.mjs → backup-oS8ft5Cm.mjs} +5 -5
- package/dist/{backup-rwVAl9NI.mjs.map → backup-oS8ft5Cm.mjs.map} +1 -1
- package/dist/{bundle-C8S2Zl6U.mjs → bundle-CL0JjIPx.mjs} +4 -4
- package/dist/{bundle-C8S2Zl6U.mjs.map → bundle-CL0JjIPx.mjs.map} +1 -1
- package/dist/{byline-DuhF7NWl.mjs → byline-Vdi85CsZ.mjs} +6 -6
- package/dist/{byline-DuhF7NWl.mjs.map → byline-Vdi85CsZ.mjs.map} +1 -1
- package/dist/{byline-fields-BovY4KYM.mjs → byline-fields-DPVRFMz2.mjs} +2 -2
- package/dist/{byline-fields-BovY4KYM.mjs.map → byline-fields-DPVRFMz2.mjs.map} +1 -1
- package/dist/{byline-registry-Bpu9-MVs.mjs → byline-registry-BxDGIO0I.mjs} +2 -2
- package/dist/{byline-registry-Bpu9-MVs.mjs.map → byline-registry-BxDGIO0I.mjs.map} +1 -1
- package/dist/{bylines-CJ5nd6Lw.mjs → bylines-BX8QhcTk.mjs} +7 -7
- package/dist/{bylines-CJ5nd6Lw.mjs.map → bylines-BX8QhcTk.mjs.map} +1 -1
- package/dist/{bylines-RwBAeOF1.mjs → bylines-w-E1IEQd.mjs} +3 -3
- package/dist/{bylines-RwBAeOF1.mjs.map → bylines-w-E1IEQd.mjs.map} +1 -1
- package/dist/{cache-BF5Kvn59.mjs → cache--7HKu5Xm.mjs} +4 -4
- package/dist/{cache-BF5Kvn59.mjs.map → cache--7HKu5Xm.mjs.map} +1 -1
- package/dist/{capture-triggers-CNW1q3HK.mjs → capture-triggers-CeAsC76Z.mjs} +2 -2
- package/dist/{capture-triggers-CNW1q3HK.mjs.map → capture-triggers-CeAsC76Z.mjs.map} +1 -1
- package/dist/{challenge-store-DQN_Yrck.mjs → challenge-store-BIOak-tp.mjs} +1 -1
- package/dist/{challenge-store-DQN_Yrck.mjs.map → challenge-store-BIOak-tp.mjs.map} +1 -1
- package/dist/{chrome-tags-D8fiZG94.mjs → chrome-tags-DzDQBCjX.mjs} +1 -1
- package/dist/{chrome-tags-D8fiZG94.mjs.map → chrome-tags-DzDQBCjX.mjs.map} +1 -1
- package/dist/{chunks-C4szrD8o.mjs → chunks-VG_tyqnP.mjs} +2 -2
- package/dist/{chunks-C4szrD8o.mjs.map → chunks-VG_tyqnP.mjs.map} +1 -1
- package/dist/cli/index.mjs +66 -38
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +17 -7
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +17 -12
- package/dist/client/index.mjs.map +1 -1
- package/dist/{collection-deletion-Bj07NHbj.mjs → collection-deletion-BCwaWTDw.mjs} +4 -4
- package/dist/{collection-deletion-Bj07NHbj.mjs.map → collection-deletion-BCwaWTDw.mjs.map} +1 -1
- package/dist/collection-slugs-cache-7lTmNzeA.mjs +85 -0
- package/dist/collection-slugs-cache-7lTmNzeA.mjs.map +1 -0
- package/dist/{comment-reaction-BhrvSHml.mjs → comment-reaction-CDyvPQRj.mjs} +2 -2
- package/dist/{comment-reaction-BhrvSHml.mjs.map → comment-reaction-CDyvPQRj.mjs.map} +1 -1
- package/dist/{comments-Ct4ensnf.mjs → comments-VzmVLyaC.mjs} +1 -1
- package/dist/{comments-Ct4ensnf.mjs.map → comments-VzmVLyaC.mjs.map} +1 -1
- package/dist/{components-DJbo1z0S.mjs → components-CL6Wkdk-.mjs} +1 -1
- package/dist/{components-DJbo1z0S.mjs.map → components-CL6Wkdk-.mjs.map} +1 -1
- package/dist/config--eWjQJE5.mjs +217 -0
- package/dist/config--eWjQJE5.mjs.map +1 -0
- package/dist/{index-BJNMCWmu.d.mts → config-CGAhyOjP.d.mts} +138 -47
- package/dist/config-CGAhyOjP.d.mts.map +1 -0
- package/dist/{config-B9eZ340f.d.mts → config-ChFzshGd.d.mts} +1 -1
- package/dist/{config-B9eZ340f.d.mts.map → config-ChFzshGd.d.mts.map} +1 -1
- package/dist/{content-DjvM0T92.mjs → content-CNfMWuhY.mjs} +121 -5
- package/dist/content-CNfMWuhY.mjs.map +1 -0
- package/dist/{content-list-query-Btqd4uV2.d.mts → content-list-query-B8d4UQp9.d.mts} +1 -1
- package/dist/{content-list-query-Btqd4uV2.d.mts.map → content-list-query-B8d4UQp9.d.mts.map} +1 -1
- package/dist/{content-refresh-Bwp-8yGy.mjs → content-refresh-GTMyi2Xy.mjs} +8 -8
- package/dist/{content-refresh-Bwp-8yGy.mjs.map → content-refresh-GTMyi2Xy.mjs.map} +1 -1
- package/dist/{content-repair-Czdp7jz5.mjs → content-repair-CIMt5C0U.mjs} +4 -4
- package/dist/{content-repair-Czdp7jz5.mjs.map → content-repair-CIMt5C0U.mjs.map} +1 -1
- package/dist/{context-CX6gxOLW.mjs → context-C9PB8vGd.mjs} +265 -25
- package/dist/context-C9PB8vGd.mjs.map +1 -0
- package/dist/{cron-C6o7VppJ.mjs → cron-DHAy9oyq.mjs} +1 -1
- package/dist/{cron-C6o7VppJ.mjs.map → cron-DHAy9oyq.mjs.map} +1 -1
- package/dist/{dashboard-C2kTeeRI.mjs → dashboard-BNSvAN8A.mjs} +4 -4
- package/dist/{dashboard-C2kTeeRI.mjs.map → dashboard-BNSvAN8A.mjs.map} +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/libsql-migrations.d.mts +1 -1
- package/dist/db/libsql-migrations.mjs +5 -5
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres-migrations.d.mts +1 -1
- package/dist/db/postgres-migrations.mjs +5 -5
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite-migrations.d.mts +1 -1
- package/dist/db/sqlite-migrations.mjs +5 -5
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.mjs +1 -1
- package/dist/{default-Clra32mw.mjs → default-ByZ0JqZo.mjs} +1 -1
- package/dist/{default-Clra32mw.mjs.map → default-ByZ0JqZo.mjs.map} +1 -1
- package/dist/{deferred-tasks-CvDETTJO.d.mts → deferred-tasks-Cu4NSJpa.d.mts} +1 -1
- package/dist/{deferred-tasks-CvDETTJO.d.mts.map → deferred-tasks-Cu4NSJpa.d.mts.map} +1 -1
- package/dist/{dev-typegen-DzOPfsNj.mjs → dev-typegen-DHT7lcMU.mjs} +1 -1
- package/dist/{dev-typegen-DzOPfsNj.mjs.map → dev-typegen-DHT7lcMU.mjs.map} +1 -1
- package/dist/{device-flow-D2oCWvLJ.mjs → device-flow-Cf6bhCCT.mjs} +4 -4
- package/dist/{device-flow-D2oCWvLJ.mjs.map → device-flow-Cf6bhCCT.mjs.map} +1 -1
- package/dist/{dialect-helpers-BSbfaO3F.mjs → dialect-helpers-BcQvkHgn.mjs} +83 -2
- package/dist/dialect-helpers-BcQvkHgn.mjs.map +1 -0
- package/dist/{direct-executor-Bfa5_ToE.mjs → direct-executor-yAyUGSqB.mjs} +3 -3
- package/dist/{direct-executor-Bfa5_ToE.mjs.map → direct-executor-yAyUGSqB.mjs.map} +1 -1
- package/dist/{dist-89xCrGqi.mjs → dist-BAsh8dbf.mjs} +1 -1
- package/dist/{dist-89xCrGqi.mjs.map → dist-BAsh8dbf.mjs.map} +1 -1
- package/dist/{email-console-Dzb6uGYa.mjs → email-console-DNup1Fku.mjs} +1 -1
- package/dist/{email-console-Dzb6uGYa.mjs.map → email-console-DNup1Fku.mjs.map} +1 -1
- package/dist/{enrich-BX0IDp4z.mjs → enrich-t2Xvjdqa.mjs} +3 -3
- package/dist/{enrich-BX0IDp4z.mjs.map → enrich-t2Xvjdqa.mjs.map} +1 -1
- package/dist/entry-lock-BEr8gDkG.mjs +163 -0
- package/dist/entry-lock-BEr8gDkG.mjs.map +1 -0
- package/dist/{relations-DnRK4YIT.d.mts → entry-lock-CGAtrwAR.d.mts} +92 -37
- package/dist/entry-lock-CGAtrwAR.d.mts.map +1 -0
- package/dist/{redirects-BLNOWQTn.mjs → entry-lock-DIYHAaSw.mjs} +57 -14
- package/dist/entry-lock-DIYHAaSw.mjs.map +1 -0
- package/dist/entry-locks-BEcX7ET0.mjs +167 -0
- package/dist/entry-locks-BEcX7ET0.mjs.map +1 -0
- package/dist/{error-DFrQjppn.mjs → error-BDcFyoRt.mjs} +2 -2
- package/dist/{error-DFrQjppn.mjs.map → error-BDcFyoRt.mjs.map} +1 -1
- package/dist/{errors-DsVoDUjJ.mjs → errors-DvMdNrgf.mjs} +8 -1
- package/dist/errors-DvMdNrgf.mjs.map +1 -0
- package/dist/{escape-HmHTC1Is.mjs → escape-B3asJC6W.mjs} +1 -1
- package/dist/{escape-HmHTC1Is.mjs.map → escape-B3asJC6W.mjs.map} +1 -1
- package/dist/{field-defs-cache-BM4SIRqH.mjs → field-defs-cache-Cf5FHK0M.mjs} +5 -5
- package/dist/{field-defs-cache-BM4SIRqH.mjs.map → field-defs-cache-Cf5FHK0M.mjs.map} +1 -1
- package/dist/{fts-manager-Do1BlW2r.mjs → fts-manager-iddym8cd.mjs} +4 -4
- package/dist/{fts-manager-Do1BlW2r.mjs.map → fts-manager-iddym8cd.mjs.map} +1 -1
- package/dist/{hash-3JJPlHF2.mjs → hash-BRweX6jz.mjs} +1 -1
- package/dist/{hash-3JJPlHF2.mjs.map → hash-BRweX6jz.mjs.map} +1 -1
- package/dist/{hook-result-DCh2WUpe.d.mts → hook-result-BrshYHLx.d.mts} +1 -1
- package/dist/{hook-result-DCh2WUpe.d.mts.map → hook-result-BrshYHLx.d.mts.map} +1 -1
- package/dist/{hreflang-B6hbAuuO.d.mts → hreflang-CQpu5bMy.d.mts} +2 -2
- package/dist/{hreflang-B6hbAuuO.d.mts.map → hreflang-CQpu5bMy.d.mts.map} +1 -1
- package/dist/{hreflang-DQbPZliA.mjs → hreflang-DshnweTC.mjs} +9 -8
- package/dist/{hreflang-DQbPZliA.mjs.map → hreflang-DshnweTC.mjs.map} +1 -1
- package/dist/{identity-DksvEazf.mjs → identity-CjGKDq8J.mjs} +3 -3
- package/dist/{identity-DksvEazf.mjs.map → identity-CjGKDq8J.mjs.map} +1 -1
- package/dist/{import-CJpaBBBT.mjs → import-D96g2otw.mjs} +5 -5
- package/dist/{import-CJpaBBBT.mjs.map → import-D96g2otw.mjs.map} +1 -1
- package/dist/{index-Du8K7bWa.d.mts → index-1ECYpfiF.d.mts} +3 -3
- package/dist/{index-Du8K7bWa.d.mts.map → index-1ECYpfiF.d.mts.map} +1 -1
- package/dist/index.d.mts +22 -22
- package/dist/index.mjs +81 -78
- package/dist/{init-lock-DJkX6Hto.mjs → init-lock-CFNBe_iH.mjs} +1 -1
- package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-CFNBe_iH.mjs.map} +1 -1
- package/dist/{load-CawHjTOH.mjs → load-DPtY9cZo.mjs} +2 -2
- package/dist/{load-CawHjTOH.mjs.map → load-DPtY9cZo.mjs.map} +1 -1
- package/dist/{loader-Z8vl7zTq.mjs → loader-WJi6GFRn.mjs} +46 -8
- package/dist/loader-WJi6GFRn.mjs.map +1 -0
- package/dist/{manifest-builder-COtzuca2.mjs → manifest-builder-BfNlGQIA.mjs} +2 -2
- package/dist/{manifest-builder-COtzuca2.mjs.map → manifest-builder-BfNlGQIA.mjs.map} +1 -1
- package/dist/{manifest-schema-BNWwR8Vd.mjs → manifest-schema-CILooI5J.mjs} +1 -1
- package/dist/{manifest-schema-BNWwR8Vd.mjs.map → manifest-schema-CILooI5J.mjs.map} +1 -1
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +3 -3
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +5 -5
- package/dist/{media-BHjus86Y.mjs → media-C1EIZKh1.mjs} +1 -1
- package/dist/{media-BHjus86Y.mjs.map → media-C1EIZKh1.mjs.map} +1 -1
- package/dist/{media-allowlist-CoTBWoDp.mjs → media-allowlist-elXJgb_K.mjs} +2 -2
- package/dist/{media-allowlist-CoTBWoDp.mjs.map → media-allowlist-elXJgb_K.mjs.map} +1 -1
- package/dist/{media-folders-BGkATs8n.mjs → media-folders-DASfX_DH.mjs} +1 -1
- package/dist/{media-folders-BGkATs8n.mjs.map → media-folders-DASfX_DH.mjs.map} +1 -1
- package/dist/{media-upload-BCidR-EY.mjs → media-upload-C7_AQJ5v.mjs} +8 -8
- package/dist/{media-upload-BCidR-EY.mjs.map → media-upload-C7_AQJ5v.mjs.map} +1 -1
- package/dist/{media-url-DHoPr0hq.mjs → media-url-8dVl1loq.mjs} +19 -2
- package/dist/media-url-8dVl1loq.mjs.map +1 -0
- package/dist/{media-usage-CdY5jhSR.mjs → media-usage-C1EswMTq.mjs} +9 -9
- package/dist/{media-usage-CdY5jhSR.mjs.map → media-usage-C1EswMTq.mjs.map} +1 -1
- package/dist/{media-usage-activation-BgeMtK5C.mjs → media-usage-activation-CrHNltlL.mjs} +3 -3
- package/dist/{media-usage-activation-BgeMtK5C.mjs.map → media-usage-activation-CrHNltlL.mjs.map} +1 -1
- package/dist/{media-usage-work-D6D9sMCA.mjs → media-usage-work-C5B1zT1c.mjs} +2 -2
- package/dist/{media-usage-work-D6D9sMCA.mjs.map → media-usage-work-C5B1zT1c.mjs.map} +1 -1
- package/dist/{media-usage-work-CnGCdHxx.mjs → media-usage-work-IkQx_Yz6.mjs} +4 -4
- package/dist/{media-usage-work-CnGCdHxx.mjs.map → media-usage-work-IkQx_Yz6.mjs.map} +1 -1
- package/dist/{media-usage-write-fence-hjeD4u7s.mjs → media-usage-write-fence-B9anjOSg.mjs} +3 -3
- package/dist/{media-usage-write-fence-hjeD4u7s.mjs.map → media-usage-write-fence-B9anjOSg.mjs.map} +1 -1
- package/dist/{menus-6qSwTNxG.mjs → menus-D8mC4eaN.mjs} +115 -136
- package/dist/menus-D8mC4eaN.mjs.map +1 -0
- package/dist/{menus-uvPLXMZf.mjs → menus-UdwjHZJC.mjs} +11 -3
- package/dist/{menus-uvPLXMZf.mjs.map → menus-UdwjHZJC.mjs.map} +1 -1
- package/dist/migrations/index.d.mts +1 -1
- package/dist/migrations/index.mjs +4 -4
- package/dist/{mime-CUIG6x84.mjs → mime-DYpsOAny.mjs} +1 -1
- package/dist/{mime-CUIG6x84.mjs.map → mime-DYpsOAny.mjs.map} +1 -1
- package/dist/{mode-DN_WneRx.mjs → mode-Dm4BHhRH.mjs} +1 -1
- package/dist/{mode-DN_WneRx.mjs.map → mode-Dm4BHhRH.mjs.map} +1 -1
- package/dist/{node-sqlite-compat-BuJXIeMz.mjs → node-sqlite-compat-2sezm-Zd.mjs} +1 -1
- package/dist/{node-sqlite-compat-BuJXIeMz.mjs.map → node-sqlite-compat-2sezm-Zd.mjs.map} +1 -1
- package/dist/{normalize-C2xNjTSG.mjs → normalize-4nkKGsuW.mjs} +1 -1
- package/dist/{normalize-C2xNjTSG.mjs.map → normalize-4nkKGsuW.mjs.map} +1 -1
- package/dist/{oauth-authorization-Dj6Kwc21.mjs → oauth-authorization-BxE_lURD.mjs} +4 -4
- package/dist/{oauth-authorization-Dj6Kwc21.mjs.map → oauth-authorization-BxE_lURD.mjs.map} +1 -1
- package/dist/{oauth-clients-FD7I0J8m.mjs → oauth-clients-DJIdOdq0.mjs} +1 -1
- package/dist/{oauth-clients-FD7I0J8m.mjs.map → oauth-clients-DJIdOdq0.mjs.map} +1 -1
- package/dist/{oauth-state-store-DkmDOmHs.mjs → oauth-state-store-CsdxP57n.mjs} +1 -1
- package/dist/{oauth-state-store-DkmDOmHs.mjs.map → oauth-state-store-CsdxP57n.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-CvIwGpYd.mjs → oauth-user-lookup-HzzW-dkF.mjs} +1 -1
- package/dist/{oauth-user-lookup-CvIwGpYd.mjs.map → oauth-user-lookup-HzzW-dkF.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{options-BHPeIbBd.mjs → options-D1FBiAv1.mjs} +60 -5
- package/dist/options-D1FBiAv1.mjs.map +1 -0
- package/dist/{options-CYb4y7hM.d.mts → options-D8Y0VHc7.d.mts} +9 -3
- package/dist/options-D8Y0VHc7.d.mts.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/page/index.d.mts.map +1 -1
- package/dist/page/index.mjs +12 -0
- package/dist/page/index.mjs.map +1 -1
- package/dist/{parse-Ckpg-Qfp.mjs → parse-WRg5C3NX.mjs} +2 -2
- package/dist/{parse-Ckpg-Qfp.mjs.map → parse-WRg5C3NX.mjs.map} +1 -1
- package/dist/{passkey-config-O_lj3y0k.mjs → passkey-config-qIdO-wF6.mjs} +1 -1
- package/dist/{passkey-config-O_lj3y0k.mjs.map → passkey-config-qIdO-wF6.mjs.map} +1 -1
- package/dist/{patterns-D9iDO3j8.mjs → patterns-DC8CLptu.mjs} +1 -1
- package/dist/{patterns-D9iDO3j8.mjs.map → patterns-DC8CLptu.mjs.map} +1 -1
- package/dist/{placeholder-4X9BrRrp.d.mts → placeholder-COrvARyD.d.mts} +1 -1
- package/dist/{placeholder-4X9BrRrp.d.mts.map → placeholder-COrvARyD.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +3 -3
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-utils.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
- package/dist/{policy-Dhtwntrt.mjs → policy-XCfb-IE9.mjs} +2 -2
- package/dist/{policy-Dhtwntrt.mjs.map → policy-XCfb-IE9.mjs.map} +1 -1
- package/dist/{portable-text-U85hOafW.mjs → portable-text-BS3d5n-0.mjs} +1 -1
- package/dist/{portable-text-U85hOafW.mjs.map → portable-text-BS3d5n-0.mjs.map} +1 -1
- package/dist/{preview-B_vJLvf8.mjs → preview-BxwsGgGp.mjs} +2 -2
- package/dist/{preview-B_vJLvf8.mjs.map → preview-BxwsGgGp.mjs.map} +1 -1
- package/dist/{protocol-JdD2YhY9.d.mts → protocol-CLn58-nw.d.mts} +2 -2
- package/dist/{protocol-JdD2YhY9.d.mts.map → protocol-CLn58-nw.d.mts.map} +1 -1
- package/dist/{public-url-CarhZJgf.mjs → public-url-FWWAvnre.mjs} +1 -1
- package/dist/{public-url-CarhZJgf.mjs.map → public-url-FWWAvnre.mjs.map} +1 -1
- package/dist/{query-BZKZcG5b.mjs → query-DygOte9M.mjs} +25 -16
- package/dist/query-DygOte9M.mjs.map +1 -0
- package/dist/{query-BndaFxxp.mjs → query-gtXT03Wc.mjs} +4 -4
- package/dist/{query-BndaFxxp.mjs.map → query-gtXT03Wc.mjs.map} +1 -1
- package/dist/{rate-limit-BZmATC6W.mjs → rate-limit-CQUPm0dh.mjs} +2 -2
- package/dist/{rate-limit-BZmATC6W.mjs.map → rate-limit-CQUPm0dh.mjs.map} +1 -1
- package/dist/{redirect-CzqnLxK-.mjs → redirect-D1cWafi6.mjs} +1 -1
- package/dist/{redirect-CzqnLxK-.mjs.map → redirect-D1cWafi6.mjs.map} +1 -1
- package/dist/{redirect-CZkbozu9.mjs → redirect-DId44BS1.mjs} +19 -6
- package/dist/redirect-DId44BS1.mjs.map +1 -0
- package/dist/{redirects-CqzNM0KM.mjs → redirects-DN-ZE33W.mjs} +5 -5
- package/dist/{redirects-CqzNM0KM.mjs.map → redirects-DN-ZE33W.mjs.map} +1 -1
- package/dist/{registry-AZAsRsor.mjs → registry-DTqaqxed.mjs} +26 -10
- package/dist/registry-DTqaqxed.mjs.map +1 -0
- package/dist/{relation-04DfKRTO.mjs → relation-DxgCHOBw.mjs} +2 -2
- package/dist/{relation-04DfKRTO.mjs.map → relation-DxgCHOBw.mjs.map} +1 -1
- package/dist/{relations-CcFwDJdJ.mjs → relations-KKDSLUwS.mjs} +4 -4
- package/dist/{relations-CcFwDJdJ.mjs.map → relations-KKDSLUwS.mjs.map} +1 -1
- package/dist/{relations-C4htk5sb.mjs → relations-rOmbndUJ.mjs} +3 -3
- package/dist/{relations-C4htk5sb.mjs.map → relations-rOmbndUJ.mjs.map} +1 -1
- package/dist/{request-cache-DH9zdCOD.mjs → request-cache-DAZZmesc.mjs} +1 -1
- package/dist/{request-cache-DH9zdCOD.mjs.map → request-cache-DAZZmesc.mjs.map} +1 -1
- package/dist/request-context.d.mts +1 -1
- package/dist/{request-meta-DYxLlnmz.mjs → request-meta-BgjUQLQ-.mjs} +2 -2
- package/dist/{request-meta-DYxLlnmz.mjs.map → request-meta-BgjUQLQ-.mjs.map} +1 -1
- package/dist/{resolve-prZ3mP7l.mjs → resolve-Cy0aWSRj.mjs} +37 -4
- package/dist/resolve-Cy0aWSRj.mjs.map +1 -0
- package/dist/{runner-YKfIMnaF.d.mts → runner-CfwysRM0.d.mts} +2 -2
- package/dist/{runner-YKfIMnaF.d.mts.map → runner-CfwysRM0.d.mts.map} +1 -1
- package/dist/{runner-BLIDKpmA.mjs → runner-nEzvnogG.mjs} +419 -295
- package/dist/runner-nEzvnogG.mjs.map +1 -0
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +3 -2
- package/dist/runtime.mjs.map +1 -1
- package/dist/{schema-CGnBeLiW.mjs → schema-CRu38Pr5.mjs} +3 -3
- package/dist/{schema-CGnBeLiW.mjs.map → schema-CRu38Pr5.mjs.map} +1 -1
- package/dist/{schema-DYr-Vd-L.mjs → schema-DifxndJx.mjs} +4 -4
- package/dist/{schema-DYr-Vd-L.mjs.map → schema-DifxndJx.mjs.map} +1 -1
- package/dist/{scopes-BhWvBavj.mjs → scopes-D5A1OZbq.mjs} +3 -3
- package/dist/{scopes-BhWvBavj.mjs.map → scopes-D5A1OZbq.mjs.map} +1 -1
- package/dist/{search-C-qDk4kx.mjs → search-DEPFSBFq.mjs} +4 -4
- package/dist/{search-C-qDk4kx.mjs.map → search-DEPFSBFq.mjs.map} +1 -1
- package/dist/{secrets-rEtHt-6z.mjs → secrets-CdfzLdoO.mjs} +3 -3
- package/dist/{secrets-rEtHt-6z.mjs.map → secrets-CdfzLdoO.mjs.map} +1 -1
- package/dist/{sections-B_nYvlwn.mjs → sections-3X52kmIR.mjs} +2 -2
- package/dist/{sections-B_nYvlwn.mjs.map → sections-3X52kmIR.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +26 -24
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.d.mts.map +1 -1
- package/dist/seo/index.mjs +18 -19
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-926NRIgt.mjs → seo-Bw68KxRc.mjs} +2 -2
- package/dist/{seo-926NRIgt.mjs.map → seo-Bw68KxRc.mjs.map} +1 -1
- package/dist/{seo-CVWkdv6x.mjs → seo-C4AmbsMU.mjs} +3 -2
- package/dist/seo-C4AmbsMU.mjs.map +1 -0
- package/dist/{service-CJl3ZAYs.mjs → service-J_-Vgo7R.mjs} +2 -2
- package/dist/{service-CJl3ZAYs.mjs.map → service-J_-Vgo7R.mjs.map} +1 -1
- package/dist/{session-user-BlMgqCHS.mjs → session-user-CbnMMwk6.mjs} +1 -1
- package/dist/{session-user-BlMgqCHS.mjs.map → session-user-CbnMMwk6.mjs.map} +1 -1
- package/dist/{settings-Cwm6o2jY.mjs → settings-AnEFYICn.mjs} +3 -3
- package/dist/{settings-Cwm6o2jY.mjs.map → settings-AnEFYICn.mjs.map} +1 -1
- package/dist/{settings--wobrkkC.mjs → settings-DcMjREe5.mjs} +6 -6
- package/dist/{settings--wobrkkC.mjs.map → settings-DcMjREe5.mjs.map} +1 -1
- package/dist/{setup-complete-DQbClIN2.mjs → setup-complete-BClXXTvr.mjs} +2 -2
- package/dist/{setup-complete-DQbClIN2.mjs.map → setup-complete-BClXXTvr.mjs.map} +1 -1
- package/dist/{setup-nonce-DZCFS2sn.mjs → setup-nonce-BheRa4RG.mjs} +1 -1
- package/dist/{setup-nonce-DZCFS2sn.mjs.map → setup-nonce-BheRa4RG.mjs.map} +1 -1
- package/dist/{single-flight-cache-BPuGPdcN.mjs → single-flight-cache-jaswDzmQ.mjs} +2 -2
- package/dist/{single-flight-cache-BPuGPdcN.mjs.map → single-flight-cache-jaswDzmQ.mjs.map} +1 -1
- package/dist/{site-url-BrxA_E9H.mjs → site-url-Bqf-ea3N.mjs} +3 -3
- package/dist/{site-url-BrxA_E9H.mjs.map → site-url-Bqf-ea3N.mjs.map} +1 -1
- package/dist/{snapshot--OCDTqdb.mjs → snapshot-C4CtXntb.mjs} +51 -35
- package/dist/snapshot-C4CtXntb.mjs.map +1 -0
- package/dist/{ssrf-5sIM5jzl.mjs → ssrf-gl4gFNhw.mjs} +148 -91
- package/dist/ssrf-gl4gFNhw.mjs.map +1 -0
- package/dist/{state-BpFVsJZB.mjs → state-1F6IOhdQ.mjs} +1 -1
- package/dist/{state-BpFVsJZB.mjs.map → state-1F6IOhdQ.mjs.map} +1 -1
- package/dist/{status-B777-dXz.mjs → status-Cenfk_r5.mjs} +1 -1
- package/dist/{status-B777-dXz.mjs.map → status-Cenfk_r5.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/{target-BmR0iTwz.mjs → target-CRzeTs8G.mjs} +1 -1
- package/dist/{target-BmR0iTwz.mjs.map → target-CRzeTs8G.mjs.map} +1 -1
- package/dist/{taxonomies-DkAkMupr.mjs → taxonomies-BOdxuZpV.mjs} +11 -4
- package/dist/taxonomies-BOdxuZpV.mjs.map +1 -0
- package/dist/{taxonomies-Wfy_Lg12.mjs → taxonomies-NcFDq5Gg.mjs} +23 -14
- package/dist/taxonomies-NcFDq5Gg.mjs.map +1 -0
- package/dist/{taxonomy-tJepplLL.mjs → taxonomy-DP1vny4K.mjs} +11 -3
- package/dist/{taxonomy-tJepplLL.mjs.map → taxonomy-DP1vny4K.mjs.map} +1 -1
- package/dist/{tokens-BCO1oruF.mjs → tokens-CDk8ox9p.mjs} +1 -1
- package/dist/{tokens-BCO1oruF.mjs.map → tokens-CDk8ox9p.mjs.map} +1 -1
- package/dist/{transport-xh6YKW2G.d.mts → transport-BVn4tVb9.d.mts} +1 -1
- package/dist/{transport-xh6YKW2G.d.mts.map → transport-BVn4tVb9.d.mts.map} +1 -1
- package/dist/{transport-Dr3qtwXC.mjs → transport-DP0JI-8i.mjs} +1 -1
- package/dist/{transport-Dr3qtwXC.mjs.map → transport-DP0JI-8i.mjs.map} +1 -1
- package/dist/{trusted-proxy-BR5F1Otp.mjs → trusted-proxy-BTM6UxqD.mjs} +1 -1
- package/dist/{trusted-proxy-BR5F1Otp.mjs.map → trusted-proxy-BTM6UxqD.mjs.map} +1 -1
- package/dist/{types-CXFkwEGC.d.mts → types-2n848aVW.d.mts} +1 -1
- package/dist/{types-CXFkwEGC.d.mts.map → types-2n848aVW.d.mts.map} +1 -1
- package/dist/{types-75KIqzL9.mjs → types-BMXnRIrX.mjs} +4 -2
- package/dist/types-BMXnRIrX.mjs.map +1 -0
- package/dist/{types-B6GrPic4.d.mts → types-BouXpOsa.d.mts} +115 -4
- package/dist/types-BouXpOsa.d.mts.map +1 -0
- package/dist/{types-3qNFPlci.mjs → types-ByG2coLw.mjs} +1 -1
- package/dist/{types-3qNFPlci.mjs.map → types-ByG2coLw.mjs.map} +1 -1
- package/dist/types-CQPWhPxE.mjs.map +1 -1
- package/dist/{types-CDtkNSFQ.d.mts → types-DEfNJ__A.d.mts} +1 -1
- package/dist/{types-CDtkNSFQ.d.mts.map → types-DEfNJ__A.d.mts.map} +1 -1
- package/dist/{types-xDMtUFnO.d.mts → types-DKcKSbtB.d.mts} +23 -7
- package/dist/types-DKcKSbtB.d.mts.map +1 -0
- package/dist/{types-C00oyCZp.d.mts → types-DRYs7uTL.d.mts} +1 -1
- package/dist/{types-C00oyCZp.d.mts.map → types-DRYs7uTL.d.mts.map} +1 -1
- package/dist/{types-DczELMop.d.mts → types-DaEg7KX2.d.mts} +1 -1
- package/dist/{types-DczELMop.d.mts.map → types-DaEg7KX2.d.mts.map} +1 -1
- package/dist/{types-BuHW4xDE.d.mts → types-LU8utpP_.d.mts} +6 -3
- package/dist/types-LU8utpP_.d.mts.map +1 -0
- package/dist/{types-CPeXo1wF.d.mts → types-VpYfPUxN.d.mts} +1 -1
- package/dist/{types-CPeXo1wF.d.mts.map → types-VpYfPUxN.d.mts.map} +1 -1
- package/dist/{types-DM3vioBY.mjs → types-c9GP7Dj5.mjs} +1 -1
- package/dist/{types-DM3vioBY.mjs.map → types-c9GP7Dj5.mjs.map} +1 -1
- package/dist/{types-FV23hEoW.d.mts → types-tJWDK__M.d.mts} +14 -1
- package/dist/types-tJWDK__M.d.mts.map +1 -0
- package/dist/{upload-attempts-BsqoQ1fn.mjs → upload-attempts-C6S2y-lp.mjs} +1 -1
- package/dist/{upload-attempts-BsqoQ1fn.mjs.map → upload-attempts-C6S2y-lp.mjs.map} +1 -1
- package/dist/{url-pattern-D4c2czpJ.mjs → url-pattern-UYtxVTuj.mjs} +1 -1
- package/dist/{url-pattern-D4c2czpJ.mjs.map → url-pattern-UYtxVTuj.mjs.map} +1 -1
- package/dist/{user-BTZ40aq6.mjs → user-DIsIXogT.mjs} +2 -2
- package/dist/{user-BTZ40aq6.mjs.map → user-DIsIXogT.mjs.map} +1 -1
- package/dist/{utils-BKvNjjhY.mjs → utils-BicP5Qbg.mjs} +2 -2
- package/dist/{utils-BKvNjjhY.mjs.map → utils-BicP5Qbg.mjs.map} +1 -1
- package/dist/{validate-DE_LRwo9.mjs → validate-D8VPn4Hv.mjs} +8 -3
- package/dist/validate-D8VPn4Hv.mjs.map +1 -0
- package/dist/{validate-DUP27OYD.d.mts → validate-Df6Dvwbw.d.mts} +12 -7
- package/dist/validate-Df6Dvwbw.d.mts.map +1 -0
- package/dist/{validation-BMImFJ11.mjs → validation-CzMJn9Ku.mjs} +13 -11
- package/dist/{validation-BMImFJ11.mjs.map → validation-CzMJn9Ku.mjs.map} +1 -1
- package/dist/version-CK67_SXX.mjs +7 -0
- package/dist/{version-Bii3suaO.mjs.map → version-CK67_SXX.mjs.map} +1 -1
- package/dist/{widgets-D3gJ10xU.mjs → widgets-RFVAxQl3.mjs} +5 -5
- package/dist/{widgets-D3gJ10xU.mjs.map → widgets-RFVAxQl3.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-B2Og_6rU.d.mts → wxr-taxonomies-BX4yQL9s.d.mts} +1 -1
- package/dist/{wxr-taxonomies-B2Og_6rU.d.mts.map → wxr-taxonomies-BX4yQL9s.d.mts.map} +1 -1
- package/dist/{wxr-taxonomies-Cxngsjwo.mjs → wxr-taxonomies-Csdp7yde.mjs} +4 -4
- package/dist/{wxr-taxonomies-Cxngsjwo.mjs.map → wxr-taxonomies-Csdp7yde.mjs.map} +1 -1
- package/dist/{zod-generator-BuYSQJB7.mjs → zod-generator-CNRGdnBY.mjs} +3 -3
- package/dist/{zod-generator-BuYSQJB7.mjs.map → zod-generator-CNRGdnBY.mjs.map} +1 -1
- package/package.json +12 -10
- package/src/api/errors.ts +7 -0
- package/src/api/handlers/content.ts +66 -79
- package/src/api/handlers/entry-lock.ts +206 -0
- package/src/api/handlers/manifest.ts +1 -0
- package/src/api/handlers/marketplace.ts +28 -20
- package/src/api/handlers/menus.ts +9 -0
- package/src/api/handlers/registry.ts +13 -8
- package/src/api/handlers/revision.ts +2 -1
- package/src/api/handlers/seo.ts +10 -1
- package/src/api/handlers/snapshot.ts +84 -72
- package/src/api/handlers/taxonomies.ts +9 -0
- package/src/api/openapi/document.ts +111 -6
- package/src/api/schemas/content.ts +8 -0
- package/src/api/schemas/entry-lock.ts +48 -0
- package/src/api/schemas/index.ts +1 -0
- package/src/api/schemas/schema.ts +10 -1
- package/src/api/types.ts +2 -0
- package/src/astro/integration/index.ts +9 -6
- package/src/astro/integration/routes.ts +5 -0
- package/src/astro/integration/runtime.ts +13 -5
- package/src/astro/integration/vite-config.ts +30 -0
- package/src/astro/middleware.ts +16 -0
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +10 -0
- package/src/astro/routes/api/content/[collection]/[id]/lock.ts +133 -0
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +11 -1
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +20 -0
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +10 -0
- package/src/astro/routes/api/content/[collection]/[id].ts +27 -2
- package/src/astro/routes/api/content/[collection]/index.ts +3 -0
- package/src/astro/routes/sitemap-[collection].xml.ts +4 -0
- package/src/astro/types.ts +13 -3
- package/src/cli/commands/content.ts +31 -5
- package/src/cli/commands/export-seed.ts +2 -0
- package/src/client/index.ts +34 -7
- package/src/components/EmDashBodyEnd.astro +4 -1
- package/src/components/EmDashBodyStart.astro +4 -1
- package/src/components/EmDashHead.astro +35 -16
- package/src/components/Gallery.astro +18 -4
- package/src/components/InlineEditor.astro +3 -1
- package/src/components/InlinePortableTextEditor.tsx +106 -11
- package/src/components/PortableText.astro +4 -0
- package/src/components/Table.astro +147 -62
- package/src/config/errors.ts +13 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +26 -2
- package/src/content/converters/prosemirror-to-portable-text.ts +35 -6
- package/src/content/converters/types.ts +10 -0
- package/src/database/dialect-helpers.ts +125 -0
- package/src/database/migrations/075_entry_edit_locks.ts +44 -0
- package/src/database/migrations/076_collection_nav_group.ts +22 -0
- package/src/database/migrations/077_plugin_storage_revisions.ts +89 -0
- package/src/database/migrations/runner.ts +6 -0
- package/src/database/repositories/content.ts +170 -1
- package/src/database/repositories/entry-locks.ts +257 -0
- package/src/database/repositories/options.ts +69 -5
- package/src/database/repositories/plugin-storage.ts +159 -0
- package/src/database/repositories/redirect.ts +17 -6
- package/src/database/repositories/taxonomy.ts +8 -0
- package/src/database/repositories/types.ts +3 -0
- package/src/database/types.ts +15 -1
- package/src/emdash-runtime.ts +117 -50
- package/src/i18n/resolve.ts +44 -4
- package/src/index.ts +14 -0
- package/src/loader.ts +35 -4
- package/src/mcp/server.ts +23 -5
- package/src/media/responsive.ts +23 -0
- package/src/media/usage/content-refresh.ts +2 -1
- package/src/menus/index.ts +17 -21
- package/src/page/seo-contributions.ts +78 -1
- package/src/page/seo-panel.ts +47 -0
- package/src/plugin-types.ts +9 -0
- package/src/plugins/conditional-storage.ts +30 -0
- package/src/plugins/context.ts +49 -17
- package/src/plugins/hooks.ts +7 -1
- package/src/plugins/index.ts +9 -0
- package/src/plugins/manager.ts +5 -2
- package/src/plugins/sandbox/types.ts +16 -2
- package/src/plugins/storage-query.ts +45 -0
- package/src/plugins/storage-update.ts +96 -0
- package/src/plugins/types.ts +114 -0
- package/src/query.ts +29 -3
- package/src/registry/config.ts +130 -27
- package/src/registry/types.ts +5 -6
- package/src/schema/collection-slugs-cache.ts +157 -0
- package/src/schema/registry.ts +19 -0
- package/src/schema/types.ts +25 -6
- package/src/security/ssrf.ts +167 -141
- package/src/seed/apply.ts +4 -0
- package/src/seed/types.ts +7 -2
- package/src/seed/validate.ts +18 -1
- package/src/seo/hreflang.ts +1 -0
- package/src/seo/index.ts +5 -10
- package/src/seo/media-url.ts +26 -0
- package/src/taxonomies/term-counts.ts +22 -5
- package/dist/api-Dz6rgoa3.mjs.map +0 -1
- package/dist/apply-B4SIOxR1.mjs.map +0 -1
- package/dist/config-it29yDLA.mjs.map +0 -1
- package/dist/content-DjvM0T92.mjs.map +0 -1
- package/dist/context-CX6gxOLW.mjs.map +0 -1
- package/dist/dialect-helpers-BSbfaO3F.mjs.map +0 -1
- package/dist/errors-DsVoDUjJ.mjs.map +0 -1
- package/dist/index-BJNMCWmu.d.mts.map +0 -1
- package/dist/loader-Z8vl7zTq.mjs.map +0 -1
- package/dist/media-url-DHoPr0hq.mjs.map +0 -1
- package/dist/menus-6qSwTNxG.mjs.map +0 -1
- package/dist/options-BHPeIbBd.mjs.map +0 -1
- package/dist/options-CYb4y7hM.d.mts.map +0 -1
- package/dist/query-BZKZcG5b.mjs.map +0 -1
- package/dist/redirect-CZkbozu9.mjs.map +0 -1
- package/dist/redirects-BLNOWQTn.mjs.map +0 -1
- package/dist/registry-AZAsRsor.mjs.map +0 -1
- package/dist/relations-DnRK4YIT.d.mts.map +0 -1
- package/dist/resolve-prZ3mP7l.mjs.map +0 -1
- package/dist/runner-BLIDKpmA.mjs.map +0 -1
- package/dist/seo-CVWkdv6x.mjs.map +0 -1
- package/dist/snapshot--OCDTqdb.mjs.map +0 -1
- package/dist/ssrf-5sIM5jzl.mjs.map +0 -1
- package/dist/taxonomies-DkAkMupr.mjs.map +0 -1
- package/dist/taxonomies-Wfy_Lg12.mjs.map +0 -1
- package/dist/types-75KIqzL9.mjs.map +0 -1
- package/dist/types-B6GrPic4.d.mts.map +0 -1
- package/dist/types-BuHW4xDE.d.mts.map +0 -1
- package/dist/types-FV23hEoW.d.mts.map +0 -1
- package/dist/types-xDMtUFnO.d.mts.map +0 -1
- package/dist/validate-DE_LRwo9.mjs.map +0 -1
- package/dist/validate-DUP27OYD.d.mts.map +0 -1
- package/dist/version-Bii3suaO.mjs +0 -7
- /package/dist/{api-tokens-BfYts-sq.mjs → api-tokens-B_lfpmH3.mjs} +0 -0
- /package/dist/{ssrf-Dg3cIT-b.mjs → ssrf-TQhaljuI.mjs} +0 -0
- /package/dist/{types-DfuTR6dL.mjs → types-A2cN6a4a.mjs} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as MediaUsageActivationVersionMismatchError, r as activateMediaUsageCapture, s as getMediaUsageActivationStatus } from "./activation-
|
|
2
|
-
import { t as ErrorCode } from "./errors-
|
|
1
|
+
import { n as MediaUsageActivationVersionMismatchError, r as activateMediaUsageCapture, s as getMediaUsageActivationStatus } from "./activation-DyNTe_Tl.mjs";
|
|
2
|
+
import { t as ErrorCode } from "./errors-DvMdNrgf.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/api/handlers/media-usage-activation.ts
|
|
5
5
|
async function handleMediaUsageActivationStatus(db) {
|
|
@@ -75,4 +75,4 @@ async function handleMediaUsageActivationAdvance(db, input) {
|
|
|
75
75
|
|
|
76
76
|
//#endregion
|
|
77
77
|
export { handleMediaUsageActivationStatus as n, handleMediaUsageActivationAdvance as t };
|
|
78
|
-
//# sourceMappingURL=media-usage-activation-
|
|
78
|
+
//# sourceMappingURL=media-usage-activation-CrHNltlL.mjs.map
|
package/dist/{media-usage-activation-BgeMtK5C.mjs.map → media-usage-activation-CrHNltlL.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-usage-activation-
|
|
1
|
+
{"version":3,"file":"media-usage-activation-CrHNltlL.mjs","names":[],"sources":["../src/api/handlers/media-usage-activation.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport {\n\tactivateMediaUsageCapture,\n\tgetMediaUsageActivationStatus,\n\tMediaUsageActivationVersionMismatchError,\n} from \"../../media/usage/activation.js\";\nimport { ErrorCode } from \"../errors.js\";\nimport type {\n\tMediaUsageActivationAdvanceRequest,\n\tMediaUsageActivationAdvanceResponse,\n\tMediaUsageActivationStatus,\n} from \"../schemas/media-usage.js\";\nimport type { ApiResult } from \"../types.js\";\n\nexport async function handleMediaUsageActivationStatus(\n\tdb: Kysely<Database>,\n): Promise<ApiResult<MediaUsageActivationStatus>> {\n\ttry {\n\t\treturn { success: true, data: await getMediaUsageActivationStatus(db) };\n\t} catch (error) {\n\t\tif (error instanceof MediaUsageActivationVersionMismatchError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,\n\t\t\t\t\tmessage: \"Media usage activation version is incompatible with this runtime\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage:activation] status read failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_READ_ERROR,\n\t\t\t\tmessage: \"Failed to read media usage activation status\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageActivationAdvance(\n\tdb: Kysely<Database>,\n\tinput: MediaUsageActivationAdvanceRequest,\n): Promise<ApiResult<MediaUsageActivationAdvanceResponse>> {\n\ttry {\n\t\tconst result = await activateMediaUsageCapture(db, {\n\t\t\twritersDrained: input.writersDrained,\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.MEDIA_USAGE_ACTIVATION_BUSY,\n\t\t\t\t\tmessage: \"Media usage activation is already in progress\",\n\t\t\t\t\tdetails: { leaseExpiresAt: result.leaseExpiresAt },\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (result.outcome === \"conflict\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_CONFLICT,\n\t\t\t\t\tmessage: \"Media usage activation ownership changed\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst activation = await getMediaUsageActivationStatus(db);\n\t\tif (activation.state === \"expanded\") {\n\t\t\tthrow new Error(\"Media usage activation did not advance\");\n\t\t}\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\toutcome: activation.state,\n\t\t\t\tprocessedCollections: result.processedCollections,\n\t\t\t\tactivation,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof MediaUsageActivationVersionMismatchError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,\n\t\t\t\t\tmessage: \"Media usage activation version is incompatible with this runtime\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage:activation] advance failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_ADVANCE_ERROR,\n\t\t\t\tmessage: \"Failed to advance media usage activation\",\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":";;;;AAgBA,eAAsB,iCACrB,IACiD;AACjD,KAAI;AACH,SAAO;GAAE,SAAS;GAAM,MAAM,MAAM,8BAA8B,GAAG;GAAE;UAC/D,OAAO;AACf,MAAI,iBAAiB,yCACpB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,UAAQ,MAAM,gDAAgD,MAAM;AACpE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,kCACrB,IACA,OAC0D;AAC1D,KAAI;EACH,MAAM,SAAS,MAAM,0BAA0B,IAAI,EAClD,gBAAgB,MAAM,gBACtB,CAAC;AACF,MAAI,OAAO,YAAY,eACtB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT,SAAS,EAAE,gBAAgB,OAAO,gBAAgB;IAClD;GACD;AAEF,MAAI,OAAO,YAAY,WACtB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;EAGF,MAAM,aAAa,MAAM,8BAA8B,GAAG;AAC1D,MAAI,WAAW,UAAU,WACxB,OAAM,IAAI,MAAM,yCAAyC;AAE1D,SAAO;GACN,SAAS;GACT,MAAM;IACL,SAAS,WAAW;IACpB,sBAAsB,OAAO;IAC7B;IACA;GACD;UACO,OAAO;AACf,MAAI,iBAAiB,yCACpB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,UAAQ,MAAM,4CAA4C,MAAM;AAChE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as isPostgres } from "./dialect-helpers-
|
|
1
|
+
import { s as isPostgres } from "./dialect-helpers-BcQvkHgn.mjs";
|
|
2
2
|
import { o as decodeCursor, s as encodeCursor } from "./types-CQPWhPxE.mjs";
|
|
3
3
|
import { sql } from "kysely";
|
|
4
4
|
import { ulid } from "ulidx";
|
|
@@ -583,4 +583,4 @@ function compareOperatorWork(a, b) {
|
|
|
583
583
|
|
|
584
584
|
//#endregion
|
|
585
585
|
export { MediaUsageWorkRepository as t };
|
|
586
|
-
//# sourceMappingURL=media-usage-work-
|
|
586
|
+
//# sourceMappingURL=media-usage-work-C5B1zT1c.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-usage-work-D6D9sMCA.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
|
+
{"version":3,"file":"media-usage-work-C5B1zT1c.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":";;;;;;AASA,MAAM,gCAAgC,MAAM,KAAK,KAAK;AACtD,MAAM,2BAA2B;AACjC,MAAM,+BAA+B;AACrC,MAAM,2BAA2B;AACjC,MAAM,4BAA4B;AAElC,MAAa,0CAA0C;AACvD,MAAa,sCAAsC;AACnD,MAAa,wCAAwC;AACrD,MAAM,0BAA0B;CAAC;CAAW;CAAS;CAAU;CAAS;AA6CxE,IAAa,2BAAb,MAAsC;CACrC,YAAY,AAAQ,IAAsB;EAAtB;;CAEpB,MAAM,0BAA0B,OAQd;AACjB,MAAI,CAAC,MAAM,gBAAgB,CAAC,MAAM,kBAAkB,CAAC,MAAM,YAAY,CAAC,MAAM,WAC7E,OAAM,IAAI,MAAM,sEAAsE;AAEvF,2BAAyB,MAAM,aAAa,eAAe;EAC3D,MAAM,aAAa,CAAC,GAAG,IAAI,IAAI,MAAM,WAAW,CAAC;AACjD,MAAI,WAAW,SAAS,KAAK,WAAW,SAAS,sCAChD,OAAM,IAAI,MAAM,6DAA6D;AAE9E,MAAI,WAAW,MAAM,cAAc,CAAC,UAAU,CAC7C,OAAM,IAAI,MAAM,uDAAuD;EAExE,MAAM,MAAM,KAAK,gBAAgB,EAAE;EACnC,MAAM,iBAAiB,KAAK,UAAU,WAAW;AAIjD,QAAM,GAAG;+BAHI,WAAW,KAAK,GAAG,GAC7B,GAAG,mEAAmE,eAAe,qBACrF,GAAG,6CAA6C,eAAe,GAEhC;;;;;;;MAO9B,MAAM,aAAa,IAAI,MAAM,eAAe,qBAAqB,MAAM,YAAY;oBACrE,IAAI,4BAA4B,IAAI,IAAI,IAAI;;;;;;;;;;;2CAWrB,MAAM,aAAa;4CAClB,MAAM,eAAe;sCAC3B,MAAM,SAAS;yCACZ,MAAM,YAAY;;kCAEzB,MAAM,MAAM;wCACN,MAAM,WAAW;WAC9C,KAAK,qBAAqB,kCAAkC,CAAC;;;;;;2BAM7C,MAAM,SAAS;iCACT,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;IAwB/C,QAAQ,KAAK,GAAG;;CAGnB,MAAM,iBAAiB,SAKwC;AAC9D,MAAI,CAAC,QAAQ,eACZ,OAAM,IAAI,MAAM,sDAAsD;AAEvE,MAAI,QAAQ,UAAU,UAAa,CAAC,sBAAsB,QAAQ,MAAM,CACvE,OAAM,IAAI,MAAM,kDAAkD;EAEnE,MAAM,QAAQ,cAAc,QAAQ,MAAM;EAC1C,MAAM,SAAS,QAAQ,SAAS,aAAa,QAAQ,OAAO,GAAG;EAC/D,MAAM,aAAa,MAAM,KAAK,GAC5B,WAAW,sBAAsB,CACjC,OAAO,CAAC,MAAM,OAAO,CAAC,CACtB,MAAM,QAAQ,KAAK,QAAQ,eAAe,CAC1C,kBAAkB;AACpB,MAAI,CAAC,WAAY,QAAO;EAExB,MAAM,SAAS,QAAQ,QAAQ,CAAC,QAAQ,MAAM,GAAG;EACjD,MAAM,aAA2C,EAAE;AACnD,OAAK,MAAM,SAAS,QAAQ;GAC3B,MAAM,OAAO,MAAM,KAAK,iBAAiB;IACxC,cAAc,WAAW;IACzB,gBAAgB,WAAW;IAC3B;IACA,OAAO,QAAQ;IACf;IACA,CAAC;AACF,cAAW,KAAK,GAAG,KAAK,IAAI,kBAAkB,CAAC;;EAGhD,MAAM,UAAU,WAAW,SAAS,oBAAoB;EACxD,MAAM,QAAQ,QAAQ,MAAM,GAAG,MAAM;EACrC,MAAM,SAAqD,EAAE,OAAO;AACpE,MAAI,QAAQ,SAAS,SAAS,MAAM,SAAS,GAAG;GAC/C,MAAM,OAAO,MAAM,GAAG,GAAG;AACzB,UAAO,aAAa,aAAa,KAAK,WAAW,KAAK,UAAU;;AAEjE,SAAO;;CAGR,MAAc,iBAAiB,OAMgB;EAC9C,IAAI,QAAQ,KAAK,GACf,WAAW,mCAAmC,CAC9C,UAAU,8CAA8C,SACxD,KACE,MAAM,yBAAyB,KAAK,qBAAqB,CACzD,MAAM,2BAA2B,KAAK,uBAAuB,CAC/D,CACA,UAAU,OAAO,CACjB,MAAM,sBAAsB,KAAK,MAAM,aAAa,CACpD,MAAM,wBAAwB,KAAK,MAAM,eAAe,CACxD,MAAM,cAAc,KAAK,MAAM,MAAM;AACvC,MAAI,MAAM,OACT,SAAQ,MAAM,OAAO,OACpB,GAAG,GAAG,CACL,GAAG,mBAAmB,KAAK,MAAM,OAAQ,WAAW,EACpD,GAAG,IAAI,CACN,GAAG,mBAAmB,KAAK,MAAM,OAAQ,WAAW,EACpD,GAAG,mBAAmB,KAAK,MAAM,OAAQ,GAAG,CAC5C,CAAC,CACF,CAAC,CACF;AAEF,SAAO,MACL,QAAQ,mBAAmB,OAAO,CAClC,QAAQ,mBAAmB,OAAO,CAClC,MAAM,MAAM,MAAM,CAClB,SAAS;;CAGZ,MAAM,kBAAkB,OAGmB;AAC1C,MAAI,CAAC,MAAM,gBAAgB,CAAC,MAAM,UACjC,OAAM,IAAI,MAAM,iEAAiE;EAElF,MAAM,aAAa,MAAM,KAAK,6BAA6B,MAAM,aAAa;AAC9E,MAAI,CAAC,WAAY,QAAO,EAAE,SAAS,wBAAwB;EAE3D,MAAM,WAAW,MAAM,KAAK,mBAAmB,MAAM,cAAc,MAAM,UAAU;AACnF,MAAI,UAAU,UAAU,aAAa,SAAS,oBAAoB,WAAW,KAC5E,QAAO;GAAE,SAAS;GAAW,SAAS;GAAO,MAAM,kBAAkB,SAAS;GAAE;EAGjF,MAAM,cAAc,MAAM,KAAK,mCAAmC;GACjE,GAAG;GACH,gBAAgB,WAAW;GAC3B;GACA,CAAC;AACF,MAAI,CAAC,YAAa,QAAO,KAAK,kBAAkB,MAAM;EAEtD,MAAM,WAAW,WACd,MAAM,KAAK,mBAAmB,UAAU,WAAW,MAAM,YAAY,aAAa,GAClF,MAAM,KAAK,mBAAmB;GAC9B,GAAG;GACH,gBAAgB,WAAW;GAC3B,aAAa,YAAY;GACzB,CAAC;AACJ,MAAI,SACH,QAAO;GAAE,SAAS;GAAW,SAAS;GAAM,MAAM,kBAAkB,SAAS;GAAE;AAEhF,SAAO,KAAK,kBAAkB,MAAM;;CAGrC,MAAc,6BACb,cAC+C;AAc/C,SAbY,MAAM,KAAK,GACrB,WAAW,oCAAoC,CAC/C,UAAU,+CAA+C,SACzD,KACE,MAAM,wBAAwB,KAAK,gBAAgB,CACnD,MAAM,oBAAoB,KAAK,kBAAkB,CACnD,CACA,OAAO,CAAC,iBAAiB,kBAAkB,CAAC,CAC5C,MAAM,iBAAiB,KAAK,aAAa,CACzC,MAAM,qBAAqB,KAAK,gBAAgB,CAChD,MAAM,qBAAqB,KAAK,aAAa,CAC7C,MAAM,wBAAwB,KAAK,SAAS,CAC5C,kBAAkB,IACN;;CAGf,MAAc,mBACb,cACA,WACkD;AAClD,SACE,MAAM,KAAK,GACV,WAAW,2BAA2B,CACtC,WAAW,CACX,MAAM,iBAAiB,KAAK,aAAa,CACzC,MAAM,cAAc,KAAK,UAAU,CACnC,kBAAkB,IAAK;;CAI3B,MAAc,mCAAmC,OAKK;EACrD,IAAI,QAAQ,KAAK,GACf,YAAY,6CAA6C,CACzD,IAAI;GACJ,cAAc,GAAW;GACzB,QAAQ,GAAW;GACnB,cAAc,GAEb;GACD,iBAAiB;GACjB,YAAY,KAAK,gBAAgB,EAAE;GACnC,CAAC,CACD,MAAM,qBAAqB,KAAK,gBAAgB,CAChD,MAAM,qBAAqB,KAAK,aAAa,CAC7C,MAAM,oBAAoB,KAAK,MAAM,eAAe,CACpD,MAAM,wBAAwB,KAAK,MAAM,aAAa,CACtD,MAAM,wBAAwB,KAAK,SAAS,CAC5C,OAAO,OACP,GAAG,OACF,GACE,WAAW,oCAAoC,CAC/C,OAAO,gBAAgB,CACvB,SAAS,iBAAiB,KAAK,uBAAuB,CACtD,SAAS,mBAAmB,KAAK,mBAAmB,CACtD,CACD;EAEF,MAAM,WAAW,MAAM;AACvB,MAAI,SACH,SAAQ,MAAM,OAAO,OAAO;GAC3B,IAAI,OAAO,GACT,WAAW,mCAAmC,CAC9C,OAAO,kBAAkB,CACzB,SAAS,sBAAsB,KAAK,uBAAuB,CAC3D,MAAM,mBAAmB,KAAK,MAAM,UAAU,CAC9C,MAAM,qBAAqB,KAAK,SAAS,aAAa,CACtD,MAAM,cAAc,KAAK,SAAS,MAAM;AAC1C,OAAI,SAAS,UAAU,SACtB,QAAO,KACL,MAAM,yBAAyB,UAAU,KAAK,CAC9C,MAAM,KAAK,eAAe,wBAAwB,CAAC;AAEtD,UAAO,GAAG,OAAO,KAAK;IACrB;MAEF,SAAQ,MAAM,OAAO,OACpB,GAAG,IACF,GAAG,OACF,GACE,WAAW,mCAAmC,CAC9C,OAAO,kBAAkB,CACzB,SAAS,sBAAsB,KAAK,uBAAuB,CAC3D,MAAM,mBAAmB,KAAK,MAAM,UAAU,CAChD,CACD,CACD;AAGF,SAAQ,MAAM,MAAM,UAAU,eAAe,CAAC,kBAAkB,IAAK;;CAGtE,MAAc,mBACb,UACA,gBACA,aACkD;EAClD,IAAI,QAAQ,KAAK,GACf,YAAY,2BAA2B,CACvC,IAAI;GACJ,iBAAiB;GACjB,cAAc;GACd,cAAc,GAAW;GACzB,OAAO;GACP,eAAe;GACf,iBAAiB,KAAK,gBAAgB,EAAE;GACxC,aAAa;GACb,kBAAkB;GAClB,mBAAmB;GACnB,iBAAiB;GACjB,YAAY,KAAK,gBAAgB,EAAE;GACnC,CAAC,CACD,MAAM,iBAAiB,KAAK,SAAS,cAAc,CACnD,MAAM,cAAc,KAAK,SAAS,WAAW,CAC7C,MAAM,gBAAgB,KAAK,SAAS,aAAa,CACjD,MAAM,SAAS,KAAK,SAAS,MAAM,CACnC,OAAO,OACP,GAAG,OACF,GACE,WAAW,oCAAoC,CAC/C,UAAU,+CAA+C,SACzD,KACE,MAAM,wBAAwB,KAAK,gBAAgB,CACnD,MAAM,oBAAoB,KAAK,kBAAkB,CACnD,CACA,OAAO,gBAAgB,CACvB,MAAM,iBAAiB,KAAK,SAAS,cAAc,CACnD,MAAM,mBAAmB,KAAK,eAAe,CAC7C,MAAM,qBAAqB,KAAK,gBAAgB,CAChD,MAAM,qBAAqB,KAAK,aAAa,CAC7C,MAAM,wBAAwB,KAAK,SAAS,CAC5C,MAAM,uBAAuB,KAAK,YAAY,CAChD,CACD;AACF,MAAI,SAAS,UAAU,SACtB,SAAQ,MACN,MAAM,oBAAoB,UAAU,KAAK,CACzC,MAAM,KAAK,eAAe,mBAAmB,CAAC;AAEjD,SAAQ,MAAM,MAAM,cAAc,CAAC,kBAAkB,IAAK;;CAG3D,MAAc,mBAAmB,OAKmB;EACnD,MAAM,MAAM,KAAK,gBAAgB,EAAE;AACnC,SACE,MAAM,KAAK,GACV,WAAW,2BAA2B,CACtC,QAAQ;GACR;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,CAAC,CACD,YAAY,WACZ,OACE,WAAW,6CAA6C,CACxD,UAAU,sCAAsC,SAChD,KACE,MAAM,iBAAiB,KAAK,uBAAuB,CACnD,MAAM,mBAAmB,KAAK,mBAAmB,CACnD,CACA,QAAQ,WAAW;GACnB,OAAO,IAAI,MAAM,aAAa,CAAC,GAAG,gBAAgB;GAClD;GACA,OAAO,IAAI,MAAM,UAAU,CAAC,GAAG,aAAa;GAC5C;GACA,OAAO,IAAI,EAAE,CAAC,GAAG,eAAe;GAChC,OAAO,IAAI,UAAU,CAAC,GAAG,QAAQ;GACjC,OAAO,IAAI,EAAE,CAAC,GAAG,gBAAgB;GACjC,IAAI,GAAG,kBAAkB;GACzB,GAAS,OAAO,GAAG,cAAc;GACjC,GAAS,OAAO,GAAG,mBAAmB;GACtC,GAAS,OAAO,GAAG,oBAAoB;GACvC,GAAS,OAAO,GAAG,kBAAkB;GACrC,IAAI,GAAG,aAAa;GACpB,IAAI,GAAG,aAAa;GACpB,CAAC,CACD,MAAM,qBAAqB,KAAK,gBAAgB,CAChD,MAAM,qBAAqB,KAAK,aAAa,CAC7C,MAAM,oBAAoB,KAAK,MAAM,eAAe,CACpD,MAAM,wBAAwB,KAAK,MAAM,aAAa,CACtD,MAAM,wBAAwB,KAAK,SAAS,CAC5C,MAAM,uBAAuB,KAAK,MAAM,YAAY,CACtD,CACA,YAAY,aAAa,SAAS,QAAQ,CAAC,iBAAiB,aAAa,CAAC,CAAC,WAAW,CAAC,CACvF,cAAc,CACd,kBAAkB,IAAK;;CAI3B,MAAc,kBAAkB,OAGW;AAC1C,MAAI,CAAE,MAAM,KAAK,6BAA6B,MAAM,aAAa,CAChE,QAAO,EAAE,SAAS,wBAAwB;EAE3C,MAAM,UAAU,MAAM,KAAK,mBAAmB,MAAM,cAAc,MAAM,UAAU;AAClF,MAAI,SAAS,UAAU,UACtB,QAAO;GAAE,SAAS;GAAW,SAAS;GAAO,MAAM,kBAAkB,QAAQ;GAAE;EAEhF,MAAM,YAAY,MAAM,KAAK,oBAAoB,MAAM,cAAc,MAAM,UAAU;AACrF,MAAI,UAAW,QAAO;GAAE,SAAS;GAAgB,gBAAgB;GAAW;AAC5E,SAAO,EAAE,SAAS,YAAY;;CAG/B,MAAc,oBACb,cACA,WACyB;AAUzB,UATY,MAAM,KAAK,GACrB,WAAW,2BAA2B,CACtC,OAAO,mBAAmB,CAC1B,MAAM,iBAAiB,KAAK,aAAa,CACzC,MAAM,cAAc,KAAK,UAAU,CACnC,MAAM,SAAS,KAAK,SAAS,CAC7B,MAAM,oBAAoB,UAAU,KAAK,CACzC,MAAM,KAAK,aAAa,CAAC,CACzB,kBAAkB,GACR,oBAAoB;;CAGjC,MAAM,kBAAkB,OAGY;AACnC,MACC,CAAC,OAAO,cAAc,MAAM,MAAM,IAClC,MAAM,QAAQ,KACd,MAAM,QAAQ,yBAEd,OAAM,IAAI,MACT,+DAA+D,2BAC/D;EAEF,MAAM,uBAAuB,gBAC5B,MAAM,sBACN,kBACA,MACA;EACD,MAAM,aAAa,MAAM;EACzB,MAAM,MAAM,KAAK,gBAAgB,EAAE;EACnC,IAAI,aAAa,KAAK,GACpB,WAAW,kCAAkC,CAC7C,OAAO;GAAC;GAAqB;GAAkB;GAAmB,CAAC,CACnE,OAAO,OACP,GAAG,GAAG,CACL,GAAG,IAAI,CACN,GAAG,aAAa,MAAM,CAAC,WAAW,QAAQ,CAAC,EAC3C,KAAK,eAAe,sBAAsB,CAC1C,CAAC,EACF,GAAG,IAAI;GACN,GAAG,aAAa,KAAK,SAAS;GAC9B,GAAG,wBAAwB,UAAU,KAAK;GAC1C,KAAK,eAAe,uBAAuB;GAC3C,CAAC,CACF,CAAC,CACF,CACA,QACA,GAAW;;;UAIX,MACA,CACA,QAAQ,kBAAkB,MAAM,CAChC,QAAQ,qBAAqB,MAAM,CACnC,QAAQ,kBAAkB,MAAM,CAChC,MAAM,MAAM,MAAM;AACpB,MAAI,WAAW,KAAK,GAAG,CAAE,cAAa,WAAW,WAAW,CAAC,YAAY;AAqCzE,UApCa,MAAM,KAAK,GACtB,KAAK,8BAA8B,WAAW,CAC9C,YAAY,2BAA2B,CACvC,IAAI;GACJ,OAAO;GACP,aAAa;GACb,kBAAkB,KAAK,gBAAgB,qBAAqB;GAC5D,mBAAmB;GACnB,YAAY;GACZ,CAAC,CACD,OAAO,OACP,GAAG,IAAI,CACN,GAAG,OACF,GACE,WAAW,8BAA8B,CACzC,OAAO,iBAAiB,CACxB,SAAS,qBAAqB,KAAK,yCAAyC,CAC5E,SAAS,kBAAkB,KAAK,sCAAsC,CACtE,SAAS,oBAAoB,KAAK,wCAAwC,CAC5E,EACD,GAAG,GAAG,CACL,GAAG,IAAI,CACN,GAAG,SAAS,MAAM,CAAC,WAAW,QAAQ,CAAC,EACvC,KAAK,eAAe,kBAAkB,CACtC,CAAC,EACF,GAAG,IAAI;GACN,GAAG,SAAS,KAAK,SAAS;GAC1B,GAAG,oBAAoB,UAAU,KAAK;GACtC,KAAK,eAAe,mBAAmB;GACvC,CAAC,CACF,CAAC,CACF,CAAC,CACF,CACA,cAAc,CACd,SAAS,EAEC,IAAI,UAAU;;CAG3B,MAAM,qBAAuC;AAO5C,SANY,MAAM,KAAK,GACrB,WAAW,2BAA2B,CACtC,OAAO,aAAa,CACpB,MAAM,SAAS,MAAM;GAAC;GAAW;GAAS;GAAS,CAAC,CACpD,MAAM,EAAE,CACR,kBAAkB,KACL;;CAGhB,MAAM,mBACL,gBACA,WACuC;AACvC,MAAI,CAAC,kBAAkB,CAAC,UACvB,OAAM,IAAI,MAAM,mEAAmE;EAEpF,MAAM,MAAM,MAAM,KAAK,GACrB,WAAW,2BAA2B,CACtC,UAAU,8CAA8C,SACxD,KACE,MAAM,yBAAyB,KAAK,yCAAyC,CAC7E,MAAM,2BAA2B,KAAK,2CAA2C,CACnF,CACA,UAAU,2BAA2B,CACrC,MAAM,4CAA4C,KAAK,eAAe,CACtE,MAAM,uCAAuC,KAAK,UAAU,CAC5D,kBAAkB;AACpB,SAAO,MAAM,UAAU,IAAI,GAAG;;CAG/B,MAAM,UACL,OAGuC;AACvC,iBAAe,MAAM;EACrB,MAAM,uBAAuB,gBAC5B,MAAM,sBACN,kBACA,MACA;EACD,MAAM,aAAa,MAAM;EACzB,MAAM,MAAM,KAAK,gBAAgB,EAAE;EACnC,MAAM,MAAM,MAAM,KAAK,GACrB,YAAY,2BAA2B,CACvC,IAAI;GACJ,OAAO;GACP,aAAa;GACb,kBAAkB,KAAK,gBAAgB,qBAAqB;GAC5D,mBAAmB;GACnB,YAAY;GACZ,CAAC,CACD,MAAM,iBAAiB,KAAK,MAAM,aAAa,CAC/C,MAAM,cAAc,KAAK,MAAM,UAAU,CACzC,MAAM,gBAAgB,KAAK,MAAM,YAAY,CAC7C,OAAO,OACP,GAAG,GAAG,CACL,GAAG,IAAI,CAAC,GAAG,SAAS,MAAM,CAAC,WAAW,QAAQ,CAAC,EAAE,KAAK,eAAe,kBAAkB,CAAC,CAAC,EACzF,GAAG,IAAI;GACN,GAAG,SAAS,KAAK,SAAS;GAC1B,GAAG,oBAAoB,UAAU,KAAK;GACtC,KAAK,eAAe,mBAAmB;GACvC,CAAC,CACF,CAAC,CACF,CACA,cAAc,CACd,kBAAkB;AAEpB,SAAO,MAAM,UAAU,IAAI,GAAG;;CAG/B,MAAM,kBAAkB,QAA8D;EACrF,MAAM,SAAS,CACd,GAAG,IAAI,IACN,OAAO,KAAK,UAAU;AACrB,eAAY,MAAM;AAClB,UAAO,CAAC,gBAAgB,MAAM,EAAE,MAAM;IACrC,CACF,CAAC,QAAQ,CACV;EACD,MAAM,4BAAY,IAAI,KAAa;AACnC,MAAI,OAAO,WAAW,EAAG,QAAO;EAChC,MAAM,UAAU,KAAK,UACpB,OAAO,KAAK,WAAW;GACtB,eAAe,MAAM;GACrB,YAAY,MAAM;GAClB,cAAc,OAAO,MAAM,YAAY;GACvC,aAAa,MAAM;GACnB,EAAE,CACH;EAED,MAAM,SAAS,MAAM,GAInB;sBALc,KAAK,sBAAsB,QAAQ,CAMvB;;;UAGpB,KAAK,qBAAqB,wBAAwB,CAAC;;;;;;;;;;IAUzD,QAAQ,KAAK,GAAG;AAClB,OAAK,MAAM,OAAO,OAAO,KACxB,WAAU,IACT,gBAAgB;GACf,cAAc,IAAI;GAClB,WAAW,IAAI;GACf,aAAa,IAAI;GACjB,CAAC,CACF;AAEF,SAAO;;CAGR,MAAM,qBAAqB,QAA8D;EACxF,MAAM,SAAS,CACd,GAAG,IAAI,IACN,OAAO,KAAK,UAAU;AACrB,eAAY,MAAM;AAClB,UAAO,CAAC,gBAAgB,MAAM,EAAE,MAAM;IACrC,CACF,CAAC,QAAQ,CACV,CAAC,UAAU,MAAM,UAAU,gBAAgB,KAAK,CAAC,cAAc,gBAAgB,MAAM,CAAC,CAAC;AACxF,MAAI,CAAC,WAAW,KAAK,GAAG,CAAE,QAAO,IAAI,IAAI,OAAO,IAAI,gBAAgB,CAAC;AACrE,MAAI,OAAO,WAAW,EAAG,wBAAO,IAAI,KAAK;EACzC,MAAM,UAAU,KAAK,UACpB,OAAO,KAAK,WAAW;GACtB,eAAe,MAAM;GACrB,YAAY,MAAM;GAClB,cAAc,OAAO,MAAM,YAAY;GACvC,aAAa,MAAM;GACnB,EAAE,CACH;EAED,MAAM,SAAS,MAAM,GAInB;sBALc,KAAK,sBAAsB,QAAQ,CAMvB;;;;;;;;;UASpB,KAAK,qBAAqB,wBAAwB,CAAC;;;IAGzD,QAAQ,KAAK,GAAG;AAClB,SAAO,IAAI,IACV,OAAO,KAAK,KAAK,QAChB,gBAAgB;GACf,cAAc,IAAI;GAClB,WAAW,IAAI;GACf,aAAa,IAAI;GACjB,CAAC,CACF,CACD;;CAGF,MAAM,sBAAsB,OAKiB;AAC5C,kBAAgB,MAAM,UAAU;EAChC,MAAM,oBAAoB,gBAAgB,MAAM,mBAAmB,eAAe,KAAK;AACvF,MAAI,CAAC,OAAO,cAAc,MAAM,YAAY,IAAI,MAAM,cAAc,EACnE,OAAM,IAAI,MAAM,gEAAgE;EAEjF,MAAM,SAAS,CACd,GAAG,IAAI,IACN,MAAM,KAAK,KAAK,SAAS;AACxB,eAAY,KAAK;AACjB,UAAO,CAAC,gBAAgB,KAAK,EAAE,KAAK;IACnC,CACF,CAAC,QAAQ,CACV;EACD,MAAM,+BAAe,IAAI,KAAiC;AAC1D,MAAI,OAAO,WAAW,EAAG,QAAO;EAChC,MAAM,UAAU,KAAK,UACpB,OAAO,KAAK,UAAU;GACrB,eAAe,KAAK;GACpB,YAAY,KAAK;GACjB,cAAc,OAAO,KAAK,YAAY;GACtC,aAAa,KAAK;GAClB,EAAE,CACH;EAED,MAAM,SAAS,MAAM,GAKnB;sBANc,KAAK,sBAAsB,QAAQ,CAOvB;;qDAEuB,MAAM,YAAY;;wBAE/C,KAAK,gBAAgB,kBAAkB,CAAC;;;wBAGxC,MAAM,UAAU;mBACrB,KAAK,gBAAgB,EAAE,CAAC;;UAEjC,KAAK,qBAAqB,wBAAwB,CAAC;;;;;;;;;;IAUzD,QAAQ,KAAK,GAAG;AAClB,OAAK,MAAM,OAAO,OAAO,KACxB,cAAa,IACZ,gBAAgB;GACf,cAAc,IAAI;GAClB,WAAW,IAAI;GACf,aAAa,IAAI;GACjB,CAAC,EACF,IAAI,MACJ;AAEF,SAAO;;CAGR,MAAM,wBAAwB,QAA8D;EAC3F,MAAM,SAAS,CACd,GAAG,IAAI,IACN,OAAO,KAAK,UAAU;AACrB,eAAY,MAAM;AAClB,UAAO,CAAC,gBAAgB,MAAM,EAAE,MAAM;IACrC,CACF,CAAC,QAAQ,CACV;EACD,MAAM,2BAAW,IAAI,KAAa;AAClC,MAAI,OAAO,WAAW,EAAG,QAAO;EAChC,MAAM,UAAU,KAAK,UACpB,OAAO,KAAK,WAAW;GACtB,eAAe,MAAM;GACrB,YAAY,MAAM;GAClB,cAAc,OAAO,MAAM,YAAY;GACvC,aAAa,MAAM;GACnB,EAAE,CACH;EAED,MAAM,SAAS,MAAM,GAInB;sBALc,KAAK,sBAAsB,QAAQ,CAMvB;;;wBAGN,KAAK,gBAAgB,EAAE,CAAC;;;mBAG7B,KAAK,gBAAgB,EAAE,CAAC;;UAEjC,KAAK,qBAAqB,wBAAwB,CAAC;;;;;;;;;;IAUzD,QAAQ,KAAK,GAAG;AAClB,OAAK,MAAM,OAAO,OAAO,KACxB,UAAS,IACR,gBAAgB;GACf,cAAc,IAAI;GAClB,WAAW,IAAI;GACf,aAAa,IAAI;GACjB,CAAC,CACF;AAEF,SAAO;;CAGR,MAAM,uBACL,cACA,gBACkB;AAClB,MAAI,CAAC,aAAc,OAAM,IAAI,MAAM,oDAAoD;AACvF,2BAAyB,gBAAgB,eAAe;EACxD,MAAM,SAAS,MAAM,KAAK,GACxB,WAAW,2BAA2B,CACtC,MAAM,iBAAiB,KAAK,aAAa,CACzC,MAAM,gBAAgB,MAAM,eAAe,CAC3C,kBAAkB;AACpB,SAAO,OAAO,OAAO,kBAAkB,EAAE;;CAG1C,MAAM,iCAAiC,OAMnB;AACnB,2BAAyB,MAAM,aAAa,eAAe;EAC3D,MAAM,SAAS,MAAM,KAAK,GACxB,WAAW,mCAAmC,CAC9C,MAAM,sBAAsB,KAAK,MAAM,aAAa,CACpD,MAAM,qBAAqB,KAAK,MAAM,YAAY,CAClD,OAAO,OACP,GAAG,OACF,GACE,WAAW,wDAAwD,CACnE,UAAU,+CAA+C,SACzD,KACE,MAAM,wBAAwB,KAAK,+BAA+B,CAClE,MAAM,oBAAoB,KAAK,iCAAiC,CAClE,CACA,UAAU,sCAAsC,SAChD,KACE,MAAM,iBAAiB,KAAK,+BAA+B,CAC3D,MAAM,mBAAmB,KAAK,iCAAiC,CACjE,CACA,OAAO,+BAA+B,CACtC,MAAM,gCAAgC,KAAK,MAAM,aAAa,CAC9D,MAAM,kCAAkC,KAAK,MAAM,eAAe,CAClE,MAAM,4BAA4B,KAAK,MAAM,SAAS,CACtD,MAAM,+BAA+B,KAAK,MAAM,YAAY,CAC5D,MAAM,wBAAwB,KAAK,SAAS,CAC5C,MAAM,8BAA8B,KAAK,MAAM,WAAW,CAC1D,MAAM,KAAK,qBAAqB,kCAAkC,CAAC,CACnE,MAAM,wBAAwB,KAAK,SAAS,CAC5C,MAAM,kCAAkC,KAAK,EAAE,CAC/C,MAAM,iBAAiB,KAAK,UAAU,CACtC,MAAM,iBAAiB,KAAK,MAAM,SAAS,CAC3C,MAAM,uBAAuB,KAAK,MAAM,YAAY,CACtD,CACD,CACA,kBAAkB;AACpB,SAAO,OAAO,OAAO,kBAAkB,EAAE;;CAG1C,AAAQ,cAAmC;AAC1C,SAAO,WAAW,KAAK,GAAG,GACvB,GAAY,sDACZ,GAAY;;CAGhB,AAAQ,qBAAqB,QAAqC;EACjE,MAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,SAAO,WAAW,KAAK,GAAG,GACvB,GAAY,GAAG,OAAO,yFACtB,GAAY,GAAG,OAAO;;CAG1B,AAAQ,eACP,QAOsB;AACtB,SAAO,WAAW,KAAK,GAAG,GACvB,GAAY,GAAG,IAAI,IAAI,OAAO,CAAC;;;QAI/B,GAAY,GAAG,IAAI,IAAI,OAAO,CAAC;;CAGnC,AAAQ,gBAAgB,eAA2C;AAClE,MAAI,WAAW,KAAK,GAAG,CACtB,QAAO,GAAW;gDAC2B,cAAc;;;AAI5D,SAAO,GAAW;;;KAGf,GAAG,iBAAiB,IAAI,MAAM,KAAK,cAAc,UAAU;;;CAI/D,AAAQ,sBAAsB,SAAsC;AACnE,MAAI,WAAW,KAAK,GAAG,CACtB,QAAO,GAAG;;;;;;gCAMmB,QAAQ;;AAGtC,SAAO,GAAG;;;;;;oBAMQ,QAAQ;;;;AAK5B,SAAS,gBAAgB,OAAuC;AAC/D,QAAO,GAAG,MAAM,aAAa,QAAQ,MAAM,UAAU,QAAQ,OAAO,MAAM,YAAY;;AAGvF,SAAS,cAAc,OAAmC;AACzD,KAAI,UAAU,OAAW,QAAO;AAChC,KAAI,CAAC,OAAO,cAAc,MAAM,IAAI,QAAQ,KAAK,QAAQ,oCACxD,OAAM,IAAI,MACT,+DAA+D,sCAC/D;AAEF,QAAO;;AAGR,SAAS,gBAAgB,OAAe,OAAe,WAA4B;AAClF,KACC,CAAC,OAAO,cAAc,MAAM,IAC5B,SAAS,YAAY,IAAI,MACzB,QAAQ,8BAER,OAAM,IAAI,MACT,oBAAoB,MAAM,WAAW,YAAY,mBAAmB,aAAa,mDACjF;AAEF,QAAO;;AAGR,SAAS,eAAe,OAAqC;AAC5D,KAAI,CAAC,MAAM,gBAAgB,CAAC,MAAM,UACjC,OAAM,IAAI,MAAM,oEAAoE;AAOrF,KAAI,EAJF,OAAO,MAAM,gBAAgB,YAC7B,OAAO,cAAc,MAAM,YAAY,IACvC,MAAM,cAAc,KACpB,OAAO,MAAM,gBAAgB,YAAY,yBAAyB,KAAK,MAAM,YAAY,EAE1F,OAAM,IAAI,MAAM,wDAAwD;;AAI1E,SAAS,yBAAyB,OAAwB,OAAqB;AAI9E,KAAI,EAFF,OAAO,UAAU,YAAY,OAAO,cAAc,MAAM,IAAI,SAAS,KACrE,OAAO,UAAU,YAAY,6BAA6B,KAAK,MAAM,EAC3D,OAAM,IAAI,MAAM,oBAAoB,MAAM,sCAAsC;;AAG7F,SAAS,YAAY,OAAqB;AACzC,KAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iDAAiD;;AAG9E,SAAS,YAAY,OAAkC;AACtD,gBAAe,MAAM;AACrB,aAAY,MAAM,WAAW;;AAG9B,SAAS,gBAAgB,OAAqB;AAC7C,KAAI,CAAC,0BAA0B,KAAK,MAAM,CACzC,OAAM,IAAI,MAAM,2EAA2E;;AAI7F,SAAS,UAAU,KAA4D;AAC9E,KAAI,CAAC,sBAAsB,IAAI,MAAM,CACpC,OAAM,IAAI,MAAM,mCAAmC,IAAI,QAAQ;AAEhE,QAAO;EACN,cAAc,IAAI;EAClB,gBAAgB,IAAI;EACpB,WAAW,IAAI;EACf,aAAa,IAAI;EACjB,aAAa,IAAI;EACjB,OAAO,IAAI;EACX,cAAc,IAAI;EAClB,eAAe,IAAI;EACnB,YAAY,IAAI;EAChB,gBAAgB,IAAI;EACpB,iBAAiB,IAAI;EACrB,eAAe,IAAI;EACnB,WAAW,IAAI;EACf,WAAW,IAAI;EACf;;AAGF,SAAS,kBACR,KAC6B;CAC7B,MAAM,OAAO,mBAAmB,MAAM,UAAU,IAAI,GAAG;AACvD,QAAO;EACN,cAAc,KAAK;EACnB,gBAAgB,KAAK;EACrB,WAAW,KAAK;EAChB,OAAO,KAAK;EACZ,cAAc,KAAK;EACnB,eAAe,KAAK;EACpB,gBAAgB,KAAK;EACrB,iBAAiB,KAAK;EACtB,eAAe,KAAK;EACpB,WAAW,KAAK;EAChB;;AAGF,SAAS,sBAAsB,OAA6C;AAC3E,QAAO,UAAU,aAAa,UAAU,WAAW,UAAU,YAAY,UAAU;;AAGpF,SAAS,oBAAoB,GAA+B,GAAuC;CAClG,MAAM,UAAU,EAAE,UAAU,cAAc,EAAE,UAAU;AACtD,QAAO,YAAY,IAAI,UAAU,EAAE,UAAU,cAAc,EAAE,UAAU"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as InvalidCursorError } from "./types-CQPWhPxE.mjs";
|
|
2
|
-
import { t as MediaUsageCollectionDeletionRepository } from "./collection-deletion-
|
|
3
|
-
import { t as MediaUsageWorkRepository } from "./media-usage-work-
|
|
4
|
-
import { t as ErrorCode } from "./errors-
|
|
2
|
+
import { t as MediaUsageCollectionDeletionRepository } from "./collection-deletion-BCwaWTDw.mjs";
|
|
3
|
+
import { t as MediaUsageWorkRepository } from "./media-usage-work-C5B1zT1c.mjs";
|
|
4
|
+
import { t as ErrorCode } from "./errors-DvMdNrgf.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-
|
|
152
|
+
//# sourceMappingURL=media-usage-work-IkQx_Yz6.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-usage-work-
|
|
1
|
+
{"version":3,"file":"media-usage-work-IkQx_Yz6.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
|
-
import {
|
|
2
|
-
import { t as apiError } from "./error-
|
|
1
|
+
import { g as tableExists } from "./dialect-helpers-BcQvkHgn.mjs";
|
|
2
|
+
import { t as apiError } from "./error-BDcFyoRt.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-
|
|
42
|
+
//# sourceMappingURL=media-usage-write-fence-B9anjOSg.mjs.map
|
package/dist/{media-usage-write-fence-hjeD4u7s.mjs.map → media-usage-write-fence-B9anjOSg.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-usage-write-fence-
|
|
1
|
+
{"version":3,"file":"media-usage-write-fence-B9anjOSg.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"}
|