emdash 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/activation-K0kGBWuJ.mjs +382 -0
- package/dist/activation-K0kGBWuJ.mjs.map +1 -0
- package/dist/{adapters-Bb1vG41D.d.mts → adapters-CzL3H752.d.mts} +3 -3
- package/dist/{adapters-Bb1vG41D.d.mts.map → adapters-CzL3H752.d.mts.map} +1 -1
- package/dist/{allowed-origins-DW7sYyqg.mjs → allowed-origins-maylGaHv.mjs} +2 -2
- package/dist/{allowed-origins-DW7sYyqg.mjs.map → allowed-origins-maylGaHv.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +22 -20
- 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-B0w3uBiG.mjs +2269 -0
- package/dist/api-B0w3uBiG.mjs.map +1 -0
- package/dist/{api-tokens-KO24G1Fd.mjs → api-tokens-9YrrCoE6.mjs} +2 -2
- package/dist/{api-tokens-KO24G1Fd.mjs.map → api-tokens-9YrrCoE6.mjs.map} +1 -1
- package/dist/{apply-kUDt80-G.mjs → apply-B_VMpJ2P.mjs} +34 -35
- package/dist/{apply-kUDt80-G.mjs.map → apply-B_VMpJ2P.mjs.map} +1 -1
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.mjs +26 -15
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +10 -7
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/media-usage-write-fence.mjs +2 -2
- package/dist/astro/middleware/redirect.mjs +4 -4
- package/dist/astro/middleware/request-context.mjs +3 -3
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +11 -12
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +168 -1305
- 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 +15 -15
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +15 -15
- package/dist/astro/routes/api/admin/bylines/index.mjs +15 -15
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +12 -12
- package/dist/astro/routes/api/admin/comments/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/comments/bulk.mjs +9 -9
- package/dist/astro/routes/api/admin/comments/counts.mjs +4 -4
- package/dist/astro/routes/api/admin/comments/index.mjs +9 -9
- 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.d.mts +9 -0
- package/dist/astro/routes/api/admin/media-usage/activation.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/activation.mjs +46 -0
- package/dist/astro/routes/api/admin/media-usage/activation.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +14 -13
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +14 -13
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/progress.d.mts +9 -0
- package/dist/astro/routes/api/admin/media-usage/progress.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/progress.mjs +44 -0
- package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +16 -11
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +14 -13
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +14 -13
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -1
- 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 +54 -48
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +54 -48
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +52 -46
- 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 +52 -46
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +53 -47
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +53 -47
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +52 -46
- 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 +52 -46
- 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 +53 -47
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +53 -47
- 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 +54 -48
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +172 -133
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +54 -48
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +52 -46
- 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 +52 -46
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +7 -7
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/auth/me.mjs +19 -9
- package/dist/astro/routes/api/auth/me.mjs.map +1 -1
- 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 +13 -13
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +12 -12
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
- 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.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +16 -14
- 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 +16 -14
- 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.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +13 -13
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
- package/dist/astro/routes/api/dashboard.mjs +7 -7
- 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 +2 -2
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +12 -12
- 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 +9 -9
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +12 -10
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
- 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 +26 -26
- package/dist/astro/routes/api/manifest.mjs +4 -4
- package/dist/astro/routes/api/mcp.mjs +42 -42
- package/dist/astro/routes/api/media/_id_/confirm.mjs +11 -11
- package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
- package/dist/astro/routes/api/media/_id_/usage.mjs +18 -13
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +21 -13
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
- package/dist/astro/routes/api/media/folders/_id_.d.mts +10 -0
- package/dist/astro/routes/api/media/folders/_id_.d.mts.map +1 -0
- package/dist/astro/routes/api/media/folders/_id_.mjs +52 -0
- package/dist/astro/routes/api/media/folders/_id_.mjs.map +1 -0
- package/dist/astro/routes/api/media/folders/index.d.mts +9 -0
- package/dist/astro/routes/api/media/folders/index.d.mts.map +1 -0
- package/dist/astro/routes/api/media/folders/index.mjs +41 -0
- package/dist/astro/routes/api/media/folders/index.mjs.map +1 -0
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/media.mjs +28 -19
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/items.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/translations.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_.mjs +8 -8
- package/dist/astro/routes/api/menus/index.mjs +8 -8
- 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 +153 -6
- 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 +10 -10
- package/dist/astro/routes/api/redirects/404s/summary.mjs +10 -10
- package/dist/astro/routes/api/redirects/_id_.mjs +11 -11
- package/dist/astro/routes/api/redirects/index.mjs +11 -11
- package/dist/astro/routes/api/relations/_id_/index.mjs +16 -14
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +11 -9
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +16 -14
- 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 +52 -46
- 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 +52 -46
- 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 +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +10 -8
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +52 -46
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +52 -46
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +10 -10
- package/dist/astro/routes/api/search/index.mjs +9 -9
- package/dist/astro/routes/api/search/rebuild.mjs +10 -10
- package/dist/astro/routes/api/search/stats.mjs +5 -5
- package/dist/astro/routes/api/search/suggest.mjs +9 -9
- package/dist/astro/routes/api/sections/_slug_.mjs +9 -9
- package/dist/astro/routes/api/sections/index.mjs +9 -9
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +6 -6
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +5 -5
- package/dist/astro/routes/api/settings/backups/export.mjs +6 -6
- package/dist/astro/routes/api/settings/backups/index.mjs +7 -7
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +13 -13
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +34 -27
- 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 +31 -29
- 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 +7 -7
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/_name_.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/index.mjs +13 -13
- 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 +7 -7
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +10 -10
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +10 -10
- package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/index.mjs +10 -10
- 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 +9 -9
- package/dist/astro/routes/sitemap.xml.mjs +7 -7
- package/dist/astro/types.d.mts +19 -14
- 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-DUElxgOQ.mjs → authorize-ByYs-Uxs.mjs} +2 -2
- package/dist/{authorize-DUElxgOQ.mjs.map → authorize-ByYs-Uxs.mjs.map} +1 -1
- package/dist/{backup-DWYpJlLj.mjs → backup-ChyHfIoX.mjs} +5 -5
- package/dist/{backup-DWYpJlLj.mjs.map → backup-ChyHfIoX.mjs.map} +1 -1
- package/dist/{bundle-vn56sLos.mjs → bundle-DZFhFurR.mjs} +4 -4
- package/dist/{bundle-vn56sLos.mjs.map → bundle-DZFhFurR.mjs.map} +1 -1
- package/dist/{byline-yjvWq4ip.mjs → byline-Cpnwrje1.mjs} +6 -6
- package/dist/{byline-yjvWq4ip.mjs.map → byline-Cpnwrje1.mjs.map} +1 -1
- package/dist/{byline-fields-txaLGoME.mjs → byline-fields-CAyA_Umd.mjs} +2 -2
- package/dist/{byline-fields-txaLGoME.mjs.map → byline-fields-CAyA_Umd.mjs.map} +1 -1
- package/dist/{byline-registry-DDun8sxh.mjs → byline-registry-Bpu9-MVs.mjs} +2 -2
- package/dist/{byline-registry-DDun8sxh.mjs.map → byline-registry-Bpu9-MVs.mjs.map} +1 -1
- package/dist/{bylines-DjXS5p0P.mjs → bylines-BSo9B9RX.mjs} +7 -7
- package/dist/{bylines-DjXS5p0P.mjs.map → bylines-BSo9B9RX.mjs.map} +1 -1
- package/dist/{bylines-Bu7pchQ4.mjs → bylines-CHjvehVX.mjs} +3 -3
- package/dist/{bylines-Bu7pchQ4.mjs.map → bylines-CHjvehVX.mjs.map} +1 -1
- package/dist/{cache-C46-3Irl.mjs → cache-5VirJ2Cn.mjs} +4 -4
- package/dist/{cache-C46-3Irl.mjs.map → cache-5VirJ2Cn.mjs.map} +1 -1
- package/dist/capture-triggers-CNW1q3HK.mjs +362 -0
- package/dist/capture-triggers-CNW1q3HK.mjs.map +1 -0
- package/dist/{challenge-store-SIL5DsF2.mjs → challenge-store-D5pSY2S1.mjs} +1 -1
- package/dist/{challenge-store-SIL5DsF2.mjs.map → challenge-store-D5pSY2S1.mjs.map} +1 -1
- package/dist/{chunks-fiZ8G9RJ.mjs → chunks-bNiX6_DR.mjs} +2 -2
- package/dist/{chunks-fiZ8G9RJ.mjs.map → chunks-bNiX6_DR.mjs.map} +1 -1
- package/dist/cli/index.mjs +36 -52
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +74 -4
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +54 -2
- package/dist/client/index.mjs.map +1 -1
- package/dist/{collection-deletion-DQPvMD8R.mjs → collection-deletion-m_oi2c0N.mjs} +13 -356
- package/dist/collection-deletion-m_oi2c0N.mjs.map +1 -0
- package/dist/{comment-Dxlep6cE.mjs → comment-DhvLEdhQ.mjs} +1 -1
- package/dist/{comment-Dxlep6cE.mjs.map → comment-DhvLEdhQ.mjs.map} +1 -1
- package/dist/{comment-reaction-D-2J84UE.mjs → comment-reaction-CRuItEjt.mjs} +2 -2
- package/dist/{comment-reaction-D-2J84UE.mjs.map → comment-reaction-CRuItEjt.mjs.map} +1 -1
- package/dist/{comments-CTfZtLmM.mjs → comments-CLj4bi8I.mjs} +2 -2
- package/dist/{comments-CTfZtLmM.mjs.map → comments-CLj4bi8I.mjs.map} +1 -1
- package/dist/{components-CQy3lh9x.mjs → components-v4U4DT2y.mjs} +1 -1
- package/dist/{components-CQy3lh9x.mjs.map → components-v4U4DT2y.mjs.map} +1 -1
- package/dist/{config-COQzTe5Q.d.mts → config-DrfghTPe.d.mts} +1 -1
- package/dist/{config-COQzTe5Q.d.mts.map → config-DrfghTPe.d.mts.map} +1 -1
- package/dist/{content-ZHCc1ngN.mjs → content-CP-SeXNa.mjs} +5 -4
- package/dist/content-CP-SeXNa.mjs.map +1 -0
- package/dist/{content-list-query-wJ2WN8Vp.d.mts → content-list-query-BhejKVqb.d.mts} +1 -1
- package/dist/{content-list-query-wJ2WN8Vp.d.mts.map → content-list-query-BhejKVqb.d.mts.map} +1 -1
- package/dist/{content-refresh-B_8SJzuU.mjs → content-refresh-DLOfIhYc.mjs} +1094 -93
- package/dist/content-refresh-DLOfIhYc.mjs.map +1 -0
- package/dist/{media-usage-BZCydfvu.mjs → content-repair-BCxzy0r4.mjs} +5 -196
- package/dist/content-repair-BCxzy0r4.mjs.map +1 -0
- package/dist/{context-ZldbZcle.mjs → context-BR5hRWiK.mjs} +13 -13
- package/dist/{context-ZldbZcle.mjs.map → context-BR5hRWiK.mjs.map} +1 -1
- package/dist/{cron-Y9aLtgrA.mjs → cron-CWfWrWKG.mjs} +1 -1
- package/dist/{cron-Y9aLtgrA.mjs.map → cron-CWfWrWKG.mjs.map} +1 -1
- package/dist/{dashboard-DvHbk_cv.mjs → dashboard-CkIV2rnQ.mjs} +5 -5
- package/dist/{dashboard-DvHbk_cv.mjs.map → dashboard-CkIV2rnQ.mjs.map} +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +3 -3
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql-migrations.d.mts +1 -1
- package/dist/db/libsql-migrations.mjs +4 -4
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres-migrations.d.mts +1 -1
- package/dist/db/postgres-migrations.mjs +4 -4
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite-migrations.d.mts +1 -1
- package/dist/db/sqlite-migrations.mjs +4 -4
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.mjs +3 -3
- package/dist/db/sqlite.mjs.map +1 -1
- package/dist/{default-DdDl3fxv.mjs → default-YMEfcQUx.mjs} +1 -1
- package/dist/{default-DdDl3fxv.mjs.map → default-YMEfcQUx.mjs.map} +1 -1
- package/dist/{deferred-tasks-SDWxrgzJ.d.mts → deferred-tasks-DfqxH5Xf.d.mts} +1 -1
- package/dist/{deferred-tasks-SDWxrgzJ.d.mts.map → deferred-tasks-DfqxH5Xf.d.mts.map} +1 -1
- package/dist/{device-flow-C0GdD_z8.mjs → device-flow-CojjSBwb.mjs} +5 -5
- package/dist/{device-flow-C0GdD_z8.mjs.map → device-flow-CojjSBwb.mjs.map} +1 -1
- package/dist/{direct-executor-CDXeJCSs.mjs → direct-executor-BWeWiRYB.mjs} +3 -3
- package/dist/{direct-executor-CDXeJCSs.mjs.map → direct-executor-BWeWiRYB.mjs.map} +1 -1
- package/dist/{dist-D_6CKR8z.mjs → dist-89xCrGqi.mjs} +1 -1
- package/dist/{dist-D_6CKR8z.mjs.map → dist-89xCrGqi.mjs.map} +1 -1
- package/dist/{email-console-BHNjIwiB.mjs → email-console-CEJgR_LB.mjs} +1 -1
- package/dist/{email-console-BHNjIwiB.mjs.map → email-console-CEJgR_LB.mjs.map} +1 -1
- package/dist/{enrich-_ySMEvEE.mjs → enrich-BX0IDp4z.mjs} +3 -3
- package/dist/{enrich-_ySMEvEE.mjs.map → enrich-BX0IDp4z.mjs.map} +1 -1
- package/dist/{error-DupyJZE2.mjs → error-D9w94fjV.mjs} +2 -2
- package/dist/{error-DupyJZE2.mjs.map → error-D9w94fjV.mjs.map} +1 -1
- package/dist/{errors-CLUPm7aD.mjs → errors-n2j49uNf.mjs} +22 -2
- package/dist/errors-n2j49uNf.mjs.map +1 -0
- package/dist/{escape-DUY2r2Zs.mjs → escape-DN4Qmjsl.mjs} +1 -1
- package/dist/{escape-DUY2r2Zs.mjs.map → escape-DN4Qmjsl.mjs.map} +1 -1
- package/dist/{field-defs-cache-BzwBlJrR.mjs → field-defs-cache-Bh4q6oar.mjs} +5 -5
- package/dist/{field-defs-cache-BzwBlJrR.mjs.map → field-defs-cache-Bh4q6oar.mjs.map} +1 -1
- package/dist/focal-point-BeWFo6Xx.mjs +23 -0
- package/dist/focal-point-BeWFo6Xx.mjs.map +1 -0
- package/dist/{fts-manager-DyZEohZC.mjs → fts-manager-BhOdW0bi.mjs} +3 -3
- package/dist/{fts-manager-DyZEohZC.mjs.map → fts-manager-BhOdW0bi.mjs.map} +1 -1
- package/dist/{hash-Cg0TXJPV.mjs → hash-CTcngWvj.mjs} +1 -1
- package/dist/{hash-Cg0TXJPV.mjs.map → hash-CTcngWvj.mjs.map} +1 -1
- package/dist/{hreflang-DwT2E0Sa.d.mts → hreflang-7pTHsLZJ.d.mts} +2 -2
- package/dist/{hreflang-DwT2E0Sa.d.mts.map → hreflang-7pTHsLZJ.d.mts.map} +1 -1
- package/dist/{hreflang-BBe83kKa.mjs → hreflang-Huc6O5wa.mjs} +7 -7
- package/dist/{hreflang-BBe83kKa.mjs.map → hreflang-Huc6O5wa.mjs.map} +1 -1
- package/dist/{identity-Ys6Dlc9C.mjs → identity-DXmb4aVp.mjs} +3 -3
- package/dist/{identity-Ys6Dlc9C.mjs.map → identity-DXmb4aVp.mjs.map} +1 -1
- package/dist/{import-DPkLmeXO.mjs → import-C4_O3KXU.mjs} +5 -5
- package/dist/{import-DPkLmeXO.mjs.map → import-C4_O3KXU.mjs.map} +1 -1
- package/dist/{index-C9KuQyO-.d.mts → index-6bRee8zb.d.mts} +3 -3
- package/dist/{index-C9KuQyO-.d.mts.map → index-6bRee8zb.d.mts.map} +1 -1
- package/dist/{index-BVBZj4-7.d.mts → index-DWbJrsAg.d.mts} +128 -52
- package/dist/index-DWbJrsAg.d.mts.map +1 -0
- package/dist/index.d.mts +21 -21
- package/dist/index.mjs +78 -72
- package/dist/{init-lock-6b309ZrF.mjs → init-lock-DJkX6Hto.mjs} +1 -1
- package/dist/{init-lock-6b309ZrF.mjs.map → init-lock-DJkX6Hto.mjs.map} +1 -1
- package/dist/{load-YJ2xl3ra.mjs → load-Bo7fZAbg.mjs} +2 -2
- package/dist/{load-YJ2xl3ra.mjs.map → load-Bo7fZAbg.mjs.map} +1 -1
- package/dist/{loader-CdG_Ci3H.mjs → loader-ZsjE4paL.mjs} +2 -2
- package/dist/{loader-CdG_Ci3H.mjs.map → loader-ZsjE4paL.mjs.map} +1 -1
- package/dist/{manifest-builder-B252yQUf.mjs → manifest-builder-QXuqvVMP.mjs} +2 -2
- package/dist/{manifest-builder-B252yQUf.mjs.map → manifest-builder-QXuqvVMP.mjs.map} +1 -1
- package/dist/{manifest-schema-BXbUAHod.mjs → manifest-schema-CUYPfCEH.mjs} +1 -1
- package/dist/{manifest-schema-BXbUAHod.mjs.map → manifest-schema-CUYPfCEH.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 +13 -3
- package/dist/media/index.mjs.map +1 -1
- package/dist/media/local-runtime.d.mts +14 -12
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +11 -5
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/{media-BWWWb8kg.mjs → media-BjwNuLEu.mjs} +100 -6
- package/dist/media-BjwNuLEu.mjs.map +1 -0
- package/dist/{media-CzhAn2--.mjs → media-D6SeAfBl.mjs} +41 -12
- package/dist/media-D6SeAfBl.mjs.map +1 -0
- package/dist/{media-allowlist-D6x-Us02.mjs → media-allowlist-D35v7bmL.mjs} +3 -2
- package/dist/media-allowlist-D35v7bmL.mjs.map +1 -0
- package/dist/media-folders-D-0CmRZj.mjs +210 -0
- package/dist/media-folders-D-0CmRZj.mjs.map +1 -0
- package/dist/{media-upload-CHBVn6m-.mjs → media-upload-C7bLXGcI.mjs} +9 -9
- package/dist/{media-upload-CHBVn6m-.mjs.map → media-upload-C7bLXGcI.mjs.map} +1 -1
- package/dist/{media-url-BvoX88FA.mjs → media-url-DH7giMx_.mjs} +1 -1
- package/dist/{media-url-BvoX88FA.mjs.map → media-url-DH7giMx_.mjs.map} +1 -1
- package/dist/media-usage-BTRJvS6V.mjs +1833 -0
- package/dist/media-usage-BTRJvS6V.mjs.map +1 -0
- package/dist/media-usage-activation-Dx0kPV6b.mjs +78 -0
- package/dist/media-usage-activation-Dx0kPV6b.mjs.map +1 -0
- package/dist/{media-usage-work-DrCbqBcl.mjs → media-usage-work-C-fhM30c.mjs} +221 -59
- package/dist/media-usage-work-C-fhM30c.mjs.map +1 -0
- package/dist/{media-usage-work-CLo_6tct.mjs → media-usage-work-DWb2XPMI.mjs} +4 -4
- package/dist/{media-usage-work-CLo_6tct.mjs.map → media-usage-work-DWb2XPMI.mjs.map} +1 -1
- package/dist/{media-usage-write-fence-aHEgN1zB.mjs → media-usage-write-fence-BwoJVRDC.mjs} +2 -2
- package/dist/{media-usage-write-fence-aHEgN1zB.mjs.map → media-usage-write-fence-BwoJVRDC.mjs.map} +1 -1
- package/dist/{menus-TCNSd2vp.mjs → menus-CD7EFLwz.mjs} +3 -3
- package/dist/{menus-TCNSd2vp.mjs.map → menus-CD7EFLwz.mjs.map} +1 -1
- package/dist/{menus-DSo5QeW0.mjs → menus-CNg0QlDt.mjs} +42 -26
- package/dist/menus-CNg0QlDt.mjs.map +1 -0
- package/dist/migrations/index.d.mts +1 -1
- package/dist/migrations/index.mjs +3 -3
- package/dist/{mime-DfIVjNkr.mjs → mime-CUIG6x84.mjs} +1 -1
- package/dist/mime-CUIG6x84.mjs.map +1 -0
- package/dist/{mode-BDoH_WcF.mjs → mode-DaUM_MB2.mjs} +1 -1
- package/dist/{mode-BDoH_WcF.mjs.map → mode-DaUM_MB2.mjs.map} +1 -1
- package/dist/node-sqlite-compat-Udb4Y-rs.mjs +46 -0
- package/dist/node-sqlite-compat-Udb4Y-rs.mjs.map +1 -0
- package/dist/{normalize-Bc-s_r-a.mjs → normalize-CSxdKBVa.mjs} +22 -1
- package/dist/normalize-CSxdKBVa.mjs.map +1 -0
- package/dist/{oauth-authorization-iOikmrJd.mjs → oauth-authorization-Dpsb-fMJ.mjs} +5 -5
- package/dist/{oauth-authorization-iOikmrJd.mjs.map → oauth-authorization-Dpsb-fMJ.mjs.map} +1 -1
- package/dist/{oauth-clients-CvI0nHMJ.mjs → oauth-clients-Bxnoe_67.mjs} +1 -1
- package/dist/{oauth-clients-CvI0nHMJ.mjs.map → oauth-clients-Bxnoe_67.mjs.map} +1 -1
- package/dist/{oauth-state-store-Ba8KZlwW.mjs → oauth-state-store-0C4s0K6w.mjs} +1 -1
- package/dist/{oauth-state-store-Ba8KZlwW.mjs.map → oauth-state-store-0C4s0K6w.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-C5SQwGYC.mjs → oauth-user-lookup-wlGYSeqX.mjs} +1 -1
- package/dist/{oauth-user-lookup-C5SQwGYC.mjs.map → oauth-user-lookup-wlGYSeqX.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{options-CBXIHUoT.mjs → options-BHPeIbBd.mjs} +1 -1
- package/dist/{options-CBXIHUoT.mjs.map → options-BHPeIbBd.mjs.map} +1 -1
- package/dist/{options--hhz-jZ1.d.mts → options-BhZIeFY1.d.mts} +3 -3
- package/dist/{options--hhz-jZ1.d.mts.map → options-BhZIeFY1.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-DFbuc-Fh.mjs → parse-BRJg1kz8.mjs} +2 -2
- package/dist/{parse-DFbuc-Fh.mjs.map → parse-BRJg1kz8.mjs.map} +1 -1
- package/dist/{passkey-config-DFAmUyuE.mjs → passkey-config-B3P0nHRR.mjs} +1 -1
- package/dist/{passkey-config-DFAmUyuE.mjs.map → passkey-config-B3P0nHRR.mjs.map} +1 -1
- package/dist/{patterns-CiyXeDgr.mjs → patterns-D9iDO3j8.mjs} +1 -1
- package/dist/{patterns-CiyXeDgr.mjs.map → patterns-D9iDO3j8.mjs.map} +1 -1
- package/dist/{placeholder-Dp0K3RkD.d.mts → placeholder-BR4ZhVJl.d.mts} +7 -1
- package/dist/placeholder-BR4ZhVJl.d.mts.map +1 -0
- package/dist/plugin-types.d.mts +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-TluUIxuu.mjs → policy-BVRganJQ.mjs} +2 -2
- package/dist/{policy-TluUIxuu.mjs.map → policy-BVRganJQ.mjs.map} +1 -1
- package/dist/{portable-text-imBW5cHK.mjs → portable-text-C8Tvp4_g.mjs} +1 -1
- package/dist/{portable-text-imBW5cHK.mjs.map → portable-text-C8Tvp4_g.mjs.map} +1 -1
- package/dist/{preview-PW-nOnq4.mjs → preview-dn2dUyM0.mjs} +2 -2
- package/dist/{preview-PW-nOnq4.mjs.map → preview-dn2dUyM0.mjs.map} +1 -1
- package/dist/{protocol-DjsJHTlK.d.mts → protocol-CuBEsqgE.d.mts} +2 -2
- package/dist/{protocol-DjsJHTlK.d.mts.map → protocol-CuBEsqgE.d.mts.map} +1 -1
- package/dist/{public-url-CWoFhQT8.mjs → public-url-DRz_AinV.mjs} +1 -1
- package/dist/{public-url-CWoFhQT8.mjs.map → public-url-DRz_AinV.mjs.map} +1 -1
- package/dist/{query-zTVAR1Sl.mjs → query-D18vTdha.mjs} +14 -14
- package/dist/{query-zTVAR1Sl.mjs.map → query-D18vTdha.mjs.map} +1 -1
- package/dist/{query-BWs7O5Il.mjs → query-tZDEdtCN.mjs} +4 -4
- package/dist/{query-BWs7O5Il.mjs.map → query-tZDEdtCN.mjs.map} +1 -1
- package/dist/{rate-limit-Bx4g9m3p.mjs → rate-limit-on7KPo-v.mjs} +2 -2
- package/dist/{rate-limit-Bx4g9m3p.mjs.map → rate-limit-on7KPo-v.mjs.map} +1 -1
- package/dist/{redirect-COsS6SWJ.mjs → redirect-CZkbozu9.mjs} +2 -2
- package/dist/{redirect-COsS6SWJ.mjs.map → redirect-CZkbozu9.mjs.map} +1 -1
- package/dist/{redirect-BgAOGHDq.mjs → redirect-DrbEmU9a.mjs} +1 -1
- package/dist/{redirect-BgAOGHDq.mjs.map → redirect-DrbEmU9a.mjs.map} +1 -1
- package/dist/{redirects-DyChwDkG.mjs → redirects-BahWiu8Z.mjs} +5 -5
- package/dist/{redirects-DyChwDkG.mjs.map → redirects-BahWiu8Z.mjs.map} +1 -1
- package/dist/{redirects-DTDHWH31.mjs → redirects-CRIM55KH.mjs} +6 -6
- package/dist/{redirects-DTDHWH31.mjs.map → redirects-CRIM55KH.mjs.map} +1 -1
- package/dist/{api-BeBglVxU.mjs → registry-BiO5WwPq.mjs} +483 -2462
- package/dist/registry-BiO5WwPq.mjs.map +1 -0
- package/dist/{registry-Cqa2I749.mjs → registry-Cx-jEJOS.mjs} +9 -123
- package/dist/registry-Cx-jEJOS.mjs.map +1 -0
- package/dist/{relation-BnHB0T4J.mjs → relation-A6wLF_DS.mjs} +2 -2
- package/dist/{relation-BnHB0T4J.mjs.map → relation-A6wLF_DS.mjs.map} +1 -1
- package/dist/{relations-BBApI4e2.mjs → relations-BTPM2saV.mjs} +2 -2
- package/dist/{relations-BBApI4e2.mjs.map → relations-BTPM2saV.mjs.map} +1 -1
- package/dist/{relations-BHo5A8Zf.d.mts → relations-C7B46bcU.d.mts} +192 -33
- package/dist/relations-C7B46bcU.d.mts.map +1 -0
- package/dist/{relations-D5sM5fW0.mjs → relations-Cj5hZ6Zg.mjs} +4 -4
- package/dist/{relations-D5sM5fW0.mjs.map → relations-Cj5hZ6Zg.mjs.map} +1 -1
- package/dist/{request-cache-BSUptuJR.mjs → request-cache-DH9zdCOD.mjs} +1 -1
- package/dist/{request-cache-BSUptuJR.mjs.map → request-cache-DH9zdCOD.mjs.map} +1 -1
- package/dist/request-context.d.mts +1 -1
- package/dist/{request-meta-DgZJh3zG.mjs → request-meta-DRp5ENd_.mjs} +2 -2
- package/dist/{request-meta-DgZJh3zG.mjs.map → request-meta-DRp5ENd_.mjs.map} +1 -1
- package/dist/{resolve-DOhVEvty.mjs → resolve-DxUpTMmE.mjs} +1 -1
- package/dist/{resolve-DOhVEvty.mjs.map → resolve-DxUpTMmE.mjs.map} +1 -1
- package/dist/{runner-C1T11CfC.mjs → runner-77GOZCnH.mjs} +410 -286
- package/dist/runner-77GOZCnH.mjs.map +1 -0
- package/dist/{runner-BYHZn3Jy.d.mts → runner-zgqA_CqP.d.mts} +2 -2
- package/dist/{runner-BYHZn3Jy.d.mts.map → runner-zgqA_CqP.d.mts.map} +1 -1
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +1 -1
- package/dist/{schema-DZ5YVVZj.mjs → schema-BY-oVntF.mjs} +3 -3
- package/dist/{schema-DZ5YVVZj.mjs.map → schema-BY-oVntF.mjs.map} +1 -1
- package/dist/{schema-2AOsSn2v.mjs → schema-Cw9kVK0I.mjs} +35 -5
- package/dist/{schema-2AOsSn2v.mjs.map → schema-Cw9kVK0I.mjs.map} +1 -1
- package/dist/{scopes-8ClPF2bC.mjs → scopes-vMR1uIbt.mjs} +3 -3
- package/dist/{scopes-8ClPF2bC.mjs.map → scopes-vMR1uIbt.mjs.map} +1 -1
- package/dist/{search-u1QYdOCG.mjs → search-CfT3KxO5.mjs} +4 -4
- package/dist/{search-u1QYdOCG.mjs.map → search-CfT3KxO5.mjs.map} +1 -1
- package/dist/{secrets-BEgsAQEU.mjs → secrets-BH2Qow1-.mjs} +3 -3
- package/dist/{secrets-BEgsAQEU.mjs.map → secrets-BH2Qow1-.mjs.map} +1 -1
- package/dist/{sections-DmHviGyM.mjs → sections-DTfjyf1z.mjs} +2 -2
- package/dist/{sections-DmHviGyM.mjs.map → sections-DTfjyf1z.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +24 -22
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +16 -14
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-AFpVvTqr.mjs → seo-BSiTIXzd.mjs} +1 -1
- package/dist/{seo-AFpVvTqr.mjs.map → seo-BSiTIXzd.mjs.map} +1 -1
- package/dist/{seo-Dq4G-RrO.mjs → seo-Cm-dtvgk.mjs} +2 -2
- package/dist/{seo-Dq4G-RrO.mjs.map → seo-Cm-dtvgk.mjs.map} +1 -1
- package/dist/{service-BpArayPr.mjs → service-DYsDHEKe.mjs} +3 -3
- package/dist/{service-BpArayPr.mjs.map → service-DYsDHEKe.mjs.map} +1 -1
- package/dist/{session-user-BEorKVT-.mjs → session-user-CNAfvsdw.mjs} +1 -1
- package/dist/{session-user-BEorKVT-.mjs.map → session-user-CNAfvsdw.mjs.map} +1 -1
- package/dist/{settings-xRdoUZr0.mjs → settings-BgN-0DT-.mjs} +6 -6
- package/dist/{settings-xRdoUZr0.mjs.map → settings-BgN-0DT-.mjs.map} +1 -1
- package/dist/{settings-DE9xtzqd.mjs → settings-DjtkUo__.mjs} +3 -3
- package/dist/{settings-DE9xtzqd.mjs.map → settings-DjtkUo__.mjs.map} +1 -1
- package/dist/{setup-complete-BnT8pq_C.mjs → setup-complete-CcpXaPU7.mjs} +2 -2
- package/dist/{setup-complete-BnT8pq_C.mjs.map → setup-complete-CcpXaPU7.mjs.map} +1 -1
- package/dist/{setup-nonce-CBitf_oQ.mjs → setup-nonce-Reyw30jg.mjs} +1 -1
- package/dist/{setup-nonce-CBitf_oQ.mjs.map → setup-nonce-Reyw30jg.mjs.map} +1 -1
- package/dist/{single-flight-cache-B0eLKS6K.mjs → single-flight-cache-BPuGPdcN.mjs} +2 -2
- package/dist/{single-flight-cache-B0eLKS6K.mjs.map → single-flight-cache-BPuGPdcN.mjs.map} +1 -1
- package/dist/{site-url-DjpIXMXJ.mjs → site-url-Cs_V9n3V.mjs} +3 -3
- package/dist/{site-url-DjpIXMXJ.mjs.map → site-url-Cs_V9n3V.mjs.map} +1 -1
- package/dist/{snapshot-BBlGkb2q.mjs → snapshot-DSB8P7Lm.mjs} +1 -1
- package/dist/{snapshot-BBlGkb2q.mjs.map → snapshot-DSB8P7Lm.mjs.map} +1 -1
- package/dist/{ssrf-Cpvg_n3A.mjs → ssrf-DqebVE34.mjs} +21 -5
- package/dist/{ssrf-Cpvg_n3A.mjs.map → ssrf-DqebVE34.mjs.map} +1 -1
- package/dist/{state-DYwPue40.mjs → state-BJfU9Uzw.mjs} +12 -4
- package/dist/state-BJfU9Uzw.mjs.map +1 -0
- package/dist/{status-CWVYpbD8.mjs → status-DDu8HIQl.mjs} +1 -1
- package/dist/{status-CWVYpbD8.mjs.map → status-DDu8HIQl.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-DixqqV5i.mjs → target-D0o26Azo.mjs} +1 -1
- package/dist/{target-DixqqV5i.mjs.map → target-D0o26Azo.mjs.map} +1 -1
- package/dist/{taxonomies-OHUIiIpI.mjs → taxonomies-CPGxo-bn.mjs} +5 -5
- package/dist/{taxonomies-OHUIiIpI.mjs.map → taxonomies-CPGxo-bn.mjs.map} +1 -1
- package/dist/{taxonomies-BlrncHi9.mjs → taxonomies-kmyudNGP.mjs} +7 -7
- package/dist/{taxonomies-BlrncHi9.mjs.map → taxonomies-kmyudNGP.mjs.map} +1 -1
- package/dist/{taxonomy-BqCZ1TdU.mjs → taxonomy-8X09dLN5.mjs} +4 -4
- package/dist/{taxonomy-BqCZ1TdU.mjs.map → taxonomy-8X09dLN5.mjs.map} +1 -1
- package/dist/{tokens-C39klX8R.mjs → tokens-gTS-IVUp.mjs} +1 -1
- package/dist/{tokens-C39klX8R.mjs.map → tokens-gTS-IVUp.mjs.map} +1 -1
- package/dist/{transaction-NQj4VJ7Z.mjs → transaction-0KOpOyMu.mjs} +2 -1
- package/dist/{transaction-NQj4VJ7Z.mjs.map → transaction-0KOpOyMu.mjs.map} +1 -1
- package/dist/{transport-RQE36APG.d.mts → transport-_6R1ub7t.d.mts} +1 -1
- package/dist/{transport-RQE36APG.d.mts.map → transport-_6R1ub7t.d.mts.map} +1 -1
- package/dist/{transport-DBJwa-Si.mjs → transport-fX59xaJz.mjs} +4 -3
- package/dist/{transport-DBJwa-Si.mjs.map → transport-fX59xaJz.mjs.map} +1 -1
- package/dist/{trusted-proxy-CEVekpby.mjs → trusted-proxy-fe6nEgR4.mjs} +1 -1
- package/dist/{trusted-proxy-CEVekpby.mjs.map → trusted-proxy-fe6nEgR4.mjs.map} +1 -1
- package/dist/types-75KIqzL9.mjs.map +1 -1
- package/dist/{types-BW1syrlw.mjs → types-BXUmsINL.mjs} +1 -1
- package/dist/{types-BW1syrlw.mjs.map → types-BXUmsINL.mjs.map} +1 -1
- package/dist/{types-BntycPTF.d.mts → types-Blb-MRC3.d.mts} +1 -1
- package/dist/{types-BntycPTF.d.mts.map → types-Blb-MRC3.d.mts.map} +1 -1
- package/dist/{types-C2pMvO62.d.mts → types-Br-ERaxh.d.mts} +2 -1
- package/dist/types-Br-ERaxh.d.mts.map +1 -0
- package/dist/{types-DWRhk9xZ.d.mts → types-BzBd3PeX.d.mts} +1 -1
- package/dist/{types-DWRhk9xZ.d.mts.map → types-BzBd3PeX.d.mts.map} +1 -1
- package/dist/{types-CXnOzDe1.d.mts → types-CLqvnd05.d.mts} +1 -1
- package/dist/{types-CXnOzDe1.d.mts.map → types-CLqvnd05.d.mts.map} +1 -1
- package/dist/{types-Dfk8KI5R.d.mts → types-D5VVLr7J.d.mts} +1 -1
- package/dist/{types-Dfk8KI5R.d.mts.map → types-D5VVLr7J.d.mts.map} +1 -1
- package/dist/{types-DQIDRKF2.d.mts → types-DHxzBjbD.d.mts} +10 -1
- package/dist/types-DHxzBjbD.d.mts.map +1 -0
- package/dist/{types-DN64_zzZ.d.mts → types-DJQxln7q.d.mts} +3 -3
- package/dist/{types-DN64_zzZ.d.mts.map → types-DJQxln7q.d.mts.map} +1 -1
- package/dist/{types-CtzytVXn.mjs → types-DM3vioBY.mjs} +1 -1
- package/dist/{types-CtzytVXn.mjs.map → types-DM3vioBY.mjs.map} +1 -1
- package/dist/{types-BcqdcT-r.d.mts → types-D_DWe7k9.d.mts} +1 -1
- package/dist/{types-BcqdcT-r.d.mts.map → types-D_DWe7k9.d.mts.map} +1 -1
- package/dist/{types-DrJrVCT1.d.mts → types-Vg6f5i3s.d.mts} +3 -3
- package/dist/{types-DrJrVCT1.d.mts.map → types-Vg6f5i3s.d.mts.map} +1 -1
- package/dist/{upload-attempts-D4FS8LT6.mjs → upload-attempts-CNyGSepg.mjs} +1 -1
- package/dist/{upload-attempts-D4FS8LT6.mjs.map → upload-attempts-CNyGSepg.mjs.map} +1 -1
- package/dist/{url-pattern-BHS0V5Ng.mjs → url-pattern-K-KdXcSe.mjs} +1 -1
- package/dist/{url-pattern-BHS0V5Ng.mjs.map → url-pattern-K-KdXcSe.mjs.map} +1 -1
- package/dist/{user-DJZfUJVE.mjs → user-CtYY0tp2.mjs} +2 -2
- package/dist/{user-DJZfUJVE.mjs.map → user-CtYY0tp2.mjs.map} +1 -1
- package/dist/{utils-D4vD_Y98.mjs → utils-HztC73hq.mjs} +1 -1
- package/dist/{utils-D4vD_Y98.mjs.map → utils-HztC73hq.mjs.map} +1 -1
- package/dist/{validate-BMLBvxOC.mjs → validate-Dd-IUjnZ.mjs} +2 -2
- package/dist/{validate-BMLBvxOC.mjs.map → validate-Dd-IUjnZ.mjs.map} +1 -1
- package/dist/{validate-CTqt5nuE.d.mts → validate-DlqdOZXB.d.mts} +5 -5
- package/dist/{validate-CTqt5nuE.d.mts.map → validate-DlqdOZXB.d.mts.map} +1 -1
- package/dist/{validation-npvENUCB.mjs → validation-D83n7Npi.mjs} +10 -8
- package/dist/{validation-npvENUCB.mjs.map → validation-D83n7Npi.mjs.map} +1 -1
- package/dist/version-ri-sCyAp.mjs +7 -0
- package/dist/{version-DB_fqCSI.mjs.map → version-ri-sCyAp.mjs.map} +1 -1
- package/dist/{widgets-BD3ho7Rq.mjs → widgets-CpmZd9Q-.mjs} +4 -4
- package/dist/{widgets-BD3ho7Rq.mjs.map → widgets-CpmZd9Q-.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-Ca68766D.d.mts → wxr-taxonomies-BFd0y72_.d.mts} +1 -1
- package/dist/{wxr-taxonomies-Ca68766D.d.mts.map → wxr-taxonomies-BFd0y72_.d.mts.map} +1 -1
- package/dist/{wxr-taxonomies-B1R3vBoD.mjs → wxr-taxonomies-Df4vxWcU.mjs} +4 -4
- package/dist/{wxr-taxonomies-B1R3vBoD.mjs.map → wxr-taxonomies-Df4vxWcU.mjs.map} +1 -1
- package/dist/{zod-generator-LC-on_Vb.mjs → zod-generator-DylzusHh.mjs} +24 -18
- package/dist/zod-generator-DylzusHh.mjs.map +1 -0
- package/package.json +16 -8
- package/src/api/errors.ts +20 -0
- package/src/api/handlers/index.ts +17 -0
- package/src/api/handlers/media-allowlist.ts +1 -0
- package/src/api/handlers/media-folders.ts +130 -0
- package/src/api/handlers/media-usage-activation.ts +102 -0
- package/src/api/handlers/media-usage.ts +108 -0
- package/src/api/handlers/media.ts +62 -2
- package/src/api/handlers/registry.ts +134 -316
- package/src/api/openapi/document.ts +192 -2
- package/src/api/schemas/media-usage.ts +77 -0
- package/src/api/schemas/media.ts +69 -0
- package/src/astro/integration/routes.ts +18 -0
- package/src/astro/integration/vite-config.ts +2 -7
- package/src/astro/middleware/auth.ts +4 -0
- package/src/astro/middleware.ts +0 -7
- package/src/astro/routes/api/admin/media-usage/activation.ts +42 -0
- package/src/astro/routes/api/admin/media-usage/progress.ts +37 -0
- package/src/astro/routes/api/admin/plugins/registry/artifact.ts +246 -96
- package/src/astro/routes/api/auth/me.ts +14 -2
- package/src/astro/routes/api/media/[id].ts +3 -0
- package/src/astro/routes/api/media/folders/[id].ts +55 -0
- package/src/astro/routes/api/media/folders/index.ts +37 -0
- package/src/astro/routes/api/media.ts +12 -2
- package/src/astro/routes/api/setup/dev-bypass.ts +12 -0
- package/src/astro/types.ts +11 -1
- package/src/client/index.ts +140 -2
- package/src/client/transport.ts +6 -2
- package/src/components/EmDashImage.astro +154 -50
- package/src/components/Gallery.astro +7 -0
- package/src/components/InlinePortableTextEditor.tsx +130 -1
- package/src/components/LiveSearch.astro +23 -0
- package/src/components/inline-code-block.tsx +180 -49
- package/src/content/converters/gallery.ts +2 -0
- package/src/content/converters/types.ts +2 -0
- package/src/database/connection.ts +2 -31
- package/src/database/index.ts +1 -1
- package/src/database/json-recordset.ts +16 -0
- package/src/database/migrations/019_i18n.ts +1 -1
- package/src/database/migrations/071_restore_content_bylines_table.ts +43 -0
- package/src/database/migrations/072_media_folders.ts +72 -0
- package/src/database/migrations/073_media_focal_point.ts +57 -0
- package/src/database/migrations/runner.ts +8 -2
- package/src/database/repositories/content.ts +5 -4
- package/src/database/repositories/media-folders.ts +115 -0
- package/src/database/repositories/media-usage-work.ts +395 -111
- package/src/database/repositories/media-usage.ts +1038 -10
- package/src/database/repositories/media.ts +97 -29
- package/src/database/transaction.ts +1 -0
- package/src/database/types.ts +13 -0
- package/src/db/adapters.ts +2 -2
- package/src/db/node-sqlite-compat.ts +78 -0
- package/src/db/sqlite.ts +3 -3
- package/src/emdash-runtime.ts +110 -105
- package/src/fields/image.ts +7 -1
- package/src/fields/types.ts +6 -2
- package/src/index.ts +5 -0
- package/src/media/focal-point.ts +37 -0
- package/src/media/local-runtime.ts +8 -0
- package/src/media/mime.ts +1 -0
- package/src/media/normalize.ts +10 -0
- package/src/media/types.ts +10 -0
- package/src/media/usage/activation.ts +162 -35
- package/src/media/usage/capture-triggers.ts +19 -3
- package/src/media/usage/collection-deletion-processor.ts +7 -3
- package/src/media/usage/collection-deletion.ts +10 -0
- package/src/media/usage/content-refresh.ts +258 -39
- package/src/media/usage/content-snapshots.ts +128 -31
- package/src/media/usage/extractor.ts +32 -13
- package/src/media/usage/maintenance-engine.ts +166 -0
- package/src/media/usage/reconciliation-processor.ts +106 -29
- package/src/media/usage/reconciliation.ts +90 -7
- package/src/media/usage/work-processor.ts +342 -101
- package/src/plugins/index.ts +1 -0
- package/src/plugins/save-rejection.ts +20 -0
- package/src/plugins/scheduler/node.ts +1 -13
- package/src/plugins/scheduler/types.ts +0 -2
- package/src/plugins/state.ts +13 -3
- package/src/registry/artifact-fetch.ts +530 -0
- package/src/registry/config.ts +24 -6
- package/src/registry/types.ts +12 -15
- package/src/schema/types.ts +1 -0
- package/src/schema/zod-generator.ts +12 -4
- package/src/security/ssrf.ts +21 -2
- package/src/seed/apply.ts +4 -4
- package/src/ui.ts +2 -0
- package/dist/api-BeBglVxU.mjs.map +0 -1
- package/dist/collection-deletion-DQPvMD8R.mjs.map +0 -1
- package/dist/content-ZHCc1ngN.mjs.map +0 -1
- package/dist/content-refresh-B_8SJzuU.mjs.map +0 -1
- package/dist/errors-CLUPm7aD.mjs.map +0 -1
- package/dist/index-BVBZj4-7.d.mts.map +0 -1
- package/dist/media-BWWWb8kg.mjs.map +0 -1
- package/dist/media-CzhAn2--.mjs.map +0 -1
- package/dist/media-allowlist-D6x-Us02.mjs.map +0 -1
- package/dist/media-usage-BZCydfvu.mjs.map +0 -1
- package/dist/media-usage-work-DrCbqBcl.mjs.map +0 -1
- package/dist/menus-DSo5QeW0.mjs.map +0 -1
- package/dist/mime-DfIVjNkr.mjs.map +0 -1
- package/dist/normalize-Bc-s_r-a.mjs.map +0 -1
- package/dist/placeholder-Dp0K3RkD.d.mts.map +0 -1
- package/dist/registry-Cqa2I749.mjs.map +0 -1
- package/dist/relations-BHo5A8Zf.d.mts.map +0 -1
- package/dist/runner-C1T11CfC.mjs.map +0 -1
- package/dist/state-DYwPue40.mjs.map +0 -1
- package/dist/types-C2pMvO62.d.mts.map +0 -1
- package/dist/types-DQIDRKF2.d.mts.map +0 -1
- package/dist/version-DB_fqCSI.mjs +0 -7
- package/dist/zod-generator-LC-on_Vb.mjs.map +0 -1
- /package/dist/{api-tokens-rIXC6LdE.mjs → api-tokens-B5NHLNUN.mjs} +0 -0
- /package/dist/{ssrf-DpXgKsna.mjs → ssrf-BPKzkm6O.mjs} +0 -0
- /package/dist/{types-CP1CflWf.mjs → types-D6OcIp2P.mjs} +0 -0
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
* Trust model (CRITICAL): the proxy never accepts an artifact URL from the
|
|
11
11
|
* client. The caller addresses an artifact by its coordinates
|
|
12
12
|
* `(did, slug, version, kind, index)`; the server resolves the *declared*
|
|
13
|
-
*
|
|
14
|
-
* aggregator.
|
|
15
|
-
*
|
|
13
|
+
* artifact source from the validated release record fetched from the
|
|
14
|
+
* configured aggregator. Blob-backed images resolve to the record-scoped
|
|
15
|
+
* Cumulus deployment; URL artifacts retain the external fallback.
|
|
16
16
|
*
|
|
17
17
|
* The publisher-declared URL is still untrusted (an attacker who controls a
|
|
18
18
|
* publisher record, or the aggregator, can point it anywhere), so the
|
|
@@ -22,13 +22,24 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import type { Did } from "@atcute/lexicons";
|
|
25
|
+
import { evaluateRegistryReleaseWithdrawal } from "@emdash-cms/registry-client/withdrawal";
|
|
26
|
+
import { NSID, RECORD_SCOPED_BLOB_CACHE_TYPE } from "@emdash-cms/registry-lexicons";
|
|
27
|
+
import {
|
|
28
|
+
recordScopedImageCacheUrl,
|
|
29
|
+
resolvePublisherPdsEndpoint,
|
|
30
|
+
type ReleaseArtifactReference,
|
|
31
|
+
} from "@emdash-cms/registry-verification/artifact";
|
|
32
|
+
import { multihashFromBlobCid } from "@emdash-cms/registry-verification/checksum";
|
|
33
|
+
import { fetchVerifiedResource } from "@emdash-cms/registry-verification/fetch";
|
|
25
34
|
import type { APIRoute } from "astro";
|
|
26
35
|
|
|
27
36
|
import { requirePerm } from "#api/authorize.js";
|
|
28
37
|
import { apiError } from "#api/error.js";
|
|
29
|
-
import {
|
|
38
|
+
import { verifyChecksum } from "#api/handlers/registry.js";
|
|
30
39
|
|
|
40
|
+
import { fetchRegistryArtifactUrl } from "../../../../../../registry/artifact-fetch.js";
|
|
31
41
|
import { coerceRegistryConfig, validateAggregatorUrl } from "../../../../../../registry/config.js";
|
|
42
|
+
import { resolveAndValidateExternalUrlTarget } from "../../../../../../security/ssrf.js";
|
|
32
43
|
|
|
33
44
|
export const prerender = false;
|
|
34
45
|
|
|
@@ -39,15 +50,9 @@ export const prerender = false;
|
|
|
39
50
|
* executes when navigated to as a top-level document), and the publisher
|
|
40
51
|
* supplies the bytes. Rather than serve it behind mitigations, we refuse it
|
|
41
52
|
* end-to-end — the publish CLI rejects SVG artifacts too, so a conforming
|
|
42
|
-
* release never references one.
|
|
53
|
+
* release never references one.
|
|
43
54
|
*/
|
|
44
|
-
const ALLOWED_IMAGE_TYPES = new Set([
|
|
45
|
-
"image/png",
|
|
46
|
-
"image/jpeg",
|
|
47
|
-
"image/webp",
|
|
48
|
-
"image/gif",
|
|
49
|
-
"image/avif",
|
|
50
|
-
]);
|
|
55
|
+
const ALLOWED_IMAGE_TYPES = new Set(["image/png", "image/jpeg", "image/webp"]);
|
|
51
56
|
|
|
52
57
|
/** Artifact kinds the proxy can resolve. `screenshot` additionally needs `index`. */
|
|
53
58
|
const ALLOWED_KINDS = new Set(["icon", "banner", "screenshot"]);
|
|
@@ -56,11 +61,12 @@ const ALLOWED_KINDS = new Set(["icon", "banner", "screenshot"]);
|
|
|
56
61
|
const DID_PATTERN = /^did:[a-z]+:.+/;
|
|
57
62
|
/** Slug grammar: ASCII letter then letters / digits / `-` / `_`. Mirrors the install route. */
|
|
58
63
|
const SLUG_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
|
|
64
|
+
const CID_PATTERN = /^b[a-z2-7]+$/;
|
|
59
65
|
/** Non-negative integer, for the screenshot index param. */
|
|
60
66
|
const INDEX_PATTERN = /^\d+$/;
|
|
61
67
|
|
|
62
68
|
/** Cap proxied images so a hostile host can't stream an unbounded body. */
|
|
63
|
-
const MAX_IMAGE_BYTES =
|
|
69
|
+
const MAX_IMAGE_BYTES = 1024 * 1024;
|
|
64
70
|
|
|
65
71
|
/** Redirect hops to follow, re-validating each target against SSRF rules. */
|
|
66
72
|
const MAX_REDIRECTS = 5;
|
|
@@ -98,40 +104,89 @@ function timedFetch(totalDeadline: number): typeof fetch {
|
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
/**
|
|
101
|
-
* Narrow one entry of a release's `artifacts` map to a usable image
|
|
107
|
+
* Narrow one entry of a release's `artifacts` map to a usable image source.
|
|
102
108
|
*
|
|
103
109
|
* The embedded `release` record is lexicon-validated at the DiscoveryClient
|
|
104
110
|
* boundary, but `artifacts` is an aggregator pass-through typed `unknown`, so
|
|
105
|
-
* the entry's shape is not guaranteed.
|
|
106
|
-
* value is an object carrying a non-empty string `url`; everything else
|
|
107
|
-
* (missing key, wrong type, no `url`) yields `null`.
|
|
111
|
+
* the entry's shape is not guaranteed.
|
|
108
112
|
*/
|
|
109
|
-
|
|
113
|
+
type DeclaredArtifact = ReleaseArtifactReference & { requiresAuth: boolean };
|
|
114
|
+
|
|
115
|
+
interface ResolvedArtifact {
|
|
116
|
+
artifact: DeclaredArtifact;
|
|
117
|
+
record: {
|
|
118
|
+
did: string;
|
|
119
|
+
collection: string;
|
|
120
|
+
rkey: string;
|
|
121
|
+
cid: string;
|
|
122
|
+
};
|
|
123
|
+
imageCacheUrl?: URL;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function declaredArtifact(value: unknown): DeclaredArtifact | null {
|
|
110
127
|
if (!value || typeof value !== "object") return null;
|
|
111
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above;
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; fields checked below
|
|
112
129
|
const entry = value as Record<string, unknown>;
|
|
113
130
|
const url = entry.url;
|
|
114
|
-
|
|
115
|
-
|
|
131
|
+
const blob = entry.blob;
|
|
132
|
+
const checksum = entry.checksum;
|
|
133
|
+
const ref = objectProperty(blob, "ref");
|
|
134
|
+
const blobCid = objectProperty(ref, "$link");
|
|
135
|
+
const blobMimeType = objectProperty(blob, "mimeType");
|
|
136
|
+
const blobSize = objectProperty(blob, "size");
|
|
137
|
+
const hasUrl = typeof url === "string" && url.length > 0;
|
|
138
|
+
const hasBlob =
|
|
139
|
+
typeof blobCid === "string" &&
|
|
140
|
+
blobCid.length > 0 &&
|
|
141
|
+
typeof blobMimeType === "string" &&
|
|
142
|
+
Number.isSafeInteger(blobSize) &&
|
|
143
|
+
Number(blobSize) >= 0;
|
|
144
|
+
if ((!hasUrl && !hasBlob) || typeof checksum !== "string" || checksum.length === 0) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
...(hasUrl ? { url } : {}),
|
|
149
|
+
...(hasBlob
|
|
150
|
+
? {
|
|
151
|
+
blob: {
|
|
152
|
+
$type: "blob" as const,
|
|
153
|
+
ref: { $link: blobCid },
|
|
154
|
+
mimeType: blobMimeType,
|
|
155
|
+
size: Number(blobSize),
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
: {}),
|
|
159
|
+
checksum,
|
|
160
|
+
requiresAuth: entry.requiresAuth === true,
|
|
161
|
+
};
|
|
116
162
|
}
|
|
117
163
|
|
|
118
164
|
/**
|
|
119
|
-
* Resolve the declared artifact
|
|
165
|
+
* Resolve the declared artifact source for `(kind, index)` from a release's
|
|
120
166
|
* `artifacts` map. Returns `null` when the requested artifact isn't present
|
|
121
167
|
* or doesn't carry a usable URL.
|
|
122
168
|
*/
|
|
123
|
-
function
|
|
169
|
+
function resolveDeclaredArtifact(
|
|
170
|
+
artifacts: unknown,
|
|
171
|
+
kind: string,
|
|
172
|
+
index: number,
|
|
173
|
+
): DeclaredArtifact | null {
|
|
124
174
|
if (!artifacts || typeof artifacts !== "object") return null;
|
|
125
175
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; each entry shape-narrowed by declaredArtifactUrl
|
|
126
176
|
const map = artifacts as Record<string, unknown>;
|
|
127
177
|
|
|
128
|
-
if (kind === "icon") return
|
|
129
|
-
if (kind === "banner") return
|
|
178
|
+
if (kind === "icon") return declaredArtifact(map.icon);
|
|
179
|
+
if (kind === "banner") return declaredArtifact(map.banner);
|
|
130
180
|
// kind === "screenshot"
|
|
131
181
|
const screenshots = map.screenshots;
|
|
132
182
|
if (!Array.isArray(screenshots)) return null;
|
|
133
183
|
if (index < 0 || index >= screenshots.length) return null;
|
|
134
|
-
return
|
|
184
|
+
return declaredArtifact(screenshots[index]);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function objectProperty(value: unknown, key: string): unknown {
|
|
188
|
+
if (!value || typeof value !== "object") return undefined;
|
|
189
|
+
return Object.getOwnPropertyDescriptor(value, key)?.value;
|
|
135
190
|
}
|
|
136
191
|
|
|
137
192
|
export const GET: APIRoute = async ({ url, locals }) => {
|
|
@@ -146,12 +201,13 @@ export const GET: APIRoute = async ({ url, locals }) => {
|
|
|
146
201
|
|
|
147
202
|
const did = url.searchParams.get("did");
|
|
148
203
|
const slug = url.searchParams.get("slug");
|
|
204
|
+
const cid = url.searchParams.get("cid");
|
|
149
205
|
const kind = url.searchParams.get("kind");
|
|
150
206
|
const versionParam = url.searchParams.get("version");
|
|
151
207
|
const indexParam = url.searchParams.get("index");
|
|
152
208
|
|
|
153
|
-
if (!did || !slug || !kind) {
|
|
154
|
-
return apiError("INVALID_REQUEST", "Missing did, slug, or kind", 400);
|
|
209
|
+
if (!did || !slug || !cid || !kind) {
|
|
210
|
+
return apiError("INVALID_REQUEST", "Missing did, slug, cid, or kind", 400);
|
|
155
211
|
}
|
|
156
212
|
if (did.length > 256 || !DID_PATTERN.test(did)) {
|
|
157
213
|
return apiError("INVALID_REQUEST", "Invalid did", 400);
|
|
@@ -159,6 +215,9 @@ export const GET: APIRoute = async ({ url, locals }) => {
|
|
|
159
215
|
if (slug.length > 64 || !SLUG_PATTERN.test(slug)) {
|
|
160
216
|
return apiError("INVALID_REQUEST", "Invalid slug", 400);
|
|
161
217
|
}
|
|
218
|
+
if (cid.length > 256 || !CID_PATTERN.test(cid)) {
|
|
219
|
+
return apiError("INVALID_REQUEST", "Invalid release CID", 400);
|
|
220
|
+
}
|
|
162
221
|
if (!ALLOWED_KINDS.has(kind)) {
|
|
163
222
|
return apiError("INVALID_REQUEST", "Invalid kind", 400);
|
|
164
223
|
}
|
|
@@ -196,73 +255,56 @@ export const GET: APIRoute = async ({ url, locals }) => {
|
|
|
196
255
|
}
|
|
197
256
|
|
|
198
257
|
// Resolve the publisher-declared artifact URL from the release record.
|
|
199
|
-
let
|
|
258
|
+
let resolvedArtifact: ResolvedArtifact;
|
|
200
259
|
try {
|
|
201
|
-
const resolved = await
|
|
260
|
+
const resolved = await resolveArtifact(registryConfig, did, slug, version, cid, kind, index);
|
|
202
261
|
if (resolved === null) {
|
|
203
262
|
return apiError("ARTIFACT_NOT_FOUND", "Artifact not found", 404);
|
|
204
263
|
}
|
|
205
|
-
|
|
264
|
+
resolvedArtifact = resolved;
|
|
206
265
|
} catch {
|
|
207
266
|
return apiError("ARTIFACT_RESOLVE_FAILED", "Failed to resolve artifact", 502);
|
|
208
267
|
}
|
|
209
|
-
|
|
210
268
|
const controller = new AbortController();
|
|
211
269
|
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
212
270
|
try {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
let response: Response;
|
|
225
|
-
for (let hop = 0; ; hop++) {
|
|
226
|
-
response = await fetch(current.href, { redirect: "manual", signal: controller.signal });
|
|
227
|
-
if (response.status < 300 || response.status >= 400) break;
|
|
228
|
-
const location = response.headers.get("location");
|
|
229
|
-
if (!location) break;
|
|
230
|
-
if (hop === MAX_REDIRECTS) {
|
|
231
|
-
return apiError("ARTIFACT_URL_REJECTED", "Too many redirects", 502);
|
|
271
|
+
const fetchOptions = proxyFetchOptions(controller.signal);
|
|
272
|
+
let bytes: Uint8Array | undefined;
|
|
273
|
+
let headers: Headers | undefined;
|
|
274
|
+
let checksumValid: boolean | undefined;
|
|
275
|
+
if (resolvedArtifact.imageCacheUrl) {
|
|
276
|
+
const transformed = await fetchVerifiedResource(resolvedArtifact.imageCacheUrl, fetchOptions);
|
|
277
|
+
if (transformed.success) {
|
|
278
|
+
bytes = transformed.value.bytes;
|
|
279
|
+
headers = transformed.value.headers;
|
|
232
280
|
}
|
|
233
|
-
let next: URL;
|
|
234
|
-
try {
|
|
235
|
-
next = await assertSafeArtifactUrl(new URL(location, current).href);
|
|
236
|
-
} catch {
|
|
237
|
-
return apiError("ARTIFACT_URL_REJECTED", "Redirect target is not allowed", 400);
|
|
238
|
-
}
|
|
239
|
-
current = next;
|
|
240
281
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
282
|
+
if (!bytes || !headers) {
|
|
283
|
+
const raw = await fetchRawArtifact(resolvedArtifact, fetchOptions);
|
|
284
|
+
if (!raw.success) return artifactFetchError(raw.code);
|
|
285
|
+
bytes = raw.bytes;
|
|
286
|
+
headers = raw.headers;
|
|
287
|
+
checksumValid = raw.checksumValid;
|
|
244
288
|
}
|
|
245
289
|
|
|
246
290
|
// Content-Type allowlist: only image types are proxied. A non-image
|
|
247
291
|
// (HTML error page, JSON, octet-stream) is rejected so the admin
|
|
248
292
|
// never renders publisher-controlled markup from the EmDash origin.
|
|
249
|
-
const rawType =
|
|
293
|
+
const rawType = headers.get("content-type") ?? "";
|
|
250
294
|
const contentType = rawType.split(";", 1)[0]!.trim().toLowerCase();
|
|
251
295
|
if (!ALLOWED_IMAGE_TYPES.has(contentType)) {
|
|
252
296
|
return apiError("ARTIFACT_NOT_IMAGE", "Artifact is not an allowed image type", 415);
|
|
253
297
|
}
|
|
254
298
|
|
|
255
|
-
const declaredLength =
|
|
299
|
+
const declaredLength = headers.get("content-length");
|
|
256
300
|
if (declaredLength) {
|
|
257
301
|
const declared = Number(declaredLength);
|
|
258
302
|
if (Number.isFinite(declared) && declared > MAX_IMAGE_BYTES) {
|
|
259
303
|
return apiError("ARTIFACT_TOO_LARGE", "Artifact exceeds size limit", 413);
|
|
260
304
|
}
|
|
261
305
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (bytes === null) {
|
|
265
|
-
return apiError("ARTIFACT_TOO_LARGE", "Artifact exceeds size limit", 413);
|
|
306
|
+
if (checksumValid === false) {
|
|
307
|
+
return artifactFetchError("CHECKSUM_MISMATCH");
|
|
266
308
|
}
|
|
267
309
|
|
|
268
310
|
// Only the allowlisted Content-Type is forwarded — never copy other
|
|
@@ -299,22 +341,25 @@ export const GET: APIRoute = async ({ url, locals }) => {
|
|
|
299
341
|
* left untouched, so a small amount of resolution-pattern duplication is
|
|
300
342
|
* accepted here.
|
|
301
343
|
*/
|
|
302
|
-
async function
|
|
344
|
+
async function resolveArtifact(
|
|
303
345
|
registryConfig: { aggregatorUrl: string; acceptLabelers?: string },
|
|
304
346
|
did: string,
|
|
305
347
|
slug: string,
|
|
306
348
|
version: string | undefined,
|
|
349
|
+
cid: string,
|
|
307
350
|
kind: string,
|
|
308
351
|
index: number,
|
|
309
|
-
): Promise<
|
|
352
|
+
): Promise<ResolvedArtifact | null> {
|
|
310
353
|
// Lazy-load the discovery client so the `@atcute/client` dependency only
|
|
311
354
|
// loads when the registry path is exercised.
|
|
312
|
-
const { DiscoveryClient } =
|
|
355
|
+
const { DiscoveryClient, registryLabelerPolicy } =
|
|
356
|
+
await import("@emdash-cms/registry-client/discovery");
|
|
313
357
|
|
|
314
358
|
const aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;
|
|
315
359
|
const discovery = new DiscoveryClient({
|
|
316
360
|
aggregatorUrl: registryConfig.aggregatorUrl,
|
|
317
361
|
acceptLabelers: registryConfig.acceptLabelers,
|
|
362
|
+
labelerPolicy: registryLabelerPolicy(registryConfig.acceptLabelers),
|
|
318
363
|
fetch: timedFetch(aggregatorDeadline),
|
|
319
364
|
});
|
|
320
365
|
|
|
@@ -347,9 +392,65 @@ async function resolveArtifactUrl(
|
|
|
347
392
|
return undefined;
|
|
348
393
|
})();
|
|
349
394
|
|
|
350
|
-
if (
|
|
395
|
+
if (
|
|
396
|
+
!releaseView?.release ||
|
|
397
|
+
releaseView.cid !== cid ||
|
|
398
|
+
releaseView.did !== publisherDid ||
|
|
399
|
+
releaseView.package !== slug ||
|
|
400
|
+
(version !== undefined && releaseView.version !== version) ||
|
|
401
|
+
releaseView.release.package !== slug ||
|
|
402
|
+
releaseView.release.version !== releaseView.version
|
|
403
|
+
) {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
if (evaluateRegistryReleaseWithdrawal(releaseView, discovery.labelerPolicy).withdrawn) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const descriptor = resolveDeclaredArtifact(releaseView.release.artifacts, kind, index);
|
|
411
|
+
if (!descriptor || descriptor.requiresAuth || releaseView.release.auth !== undefined) return null;
|
|
412
|
+
const blobCid = descriptor.blob?.ref.$link;
|
|
413
|
+
let imageCacheUrl: URL | undefined;
|
|
414
|
+
if (blobCid) {
|
|
415
|
+
const expected = multihashFromBlobCid(blobCid);
|
|
416
|
+
if (!expected.success || expected.value !== descriptor.checksum) return null;
|
|
417
|
+
const rkey = `${slug}:${releaseView.version}`;
|
|
418
|
+
const serviceEndpoint = releaseView.artifactCaches
|
|
419
|
+
.map(recordScopedCacheEndpoint)
|
|
420
|
+
.find((value) => value !== null);
|
|
421
|
+
if (serviceEndpoint) {
|
|
422
|
+
const preset = kind === "icon" ? "avatar" : kind === "banner" ? "banner" : "feed_thumbnail";
|
|
423
|
+
const cacheUrl = recordScopedImageCacheUrl(
|
|
424
|
+
serviceEndpoint,
|
|
425
|
+
preset,
|
|
426
|
+
{
|
|
427
|
+
did,
|
|
428
|
+
collection: NSID.packageRelease,
|
|
429
|
+
rkey,
|
|
430
|
+
cid: releaseView.cid,
|
|
431
|
+
},
|
|
432
|
+
blobCid,
|
|
433
|
+
);
|
|
434
|
+
if (!cacheUrl.success) return null;
|
|
435
|
+
imageCacheUrl = cacheUrl.value;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
artifact: descriptor,
|
|
440
|
+
record: {
|
|
441
|
+
did,
|
|
442
|
+
collection: NSID.packageRelease,
|
|
443
|
+
rkey: `${slug}:${releaseView.version}`,
|
|
444
|
+
cid: releaseView.cid,
|
|
445
|
+
},
|
|
446
|
+
...(imageCacheUrl ? { imageCacheUrl } : {}),
|
|
447
|
+
};
|
|
448
|
+
}
|
|
351
449
|
|
|
352
|
-
|
|
450
|
+
function recordScopedCacheEndpoint(value: unknown): string | null {
|
|
451
|
+
if (objectProperty(value, "$type") !== RECORD_SCOPED_BLOB_CACHE_TYPE) return null;
|
|
452
|
+
const endpoint = objectProperty(value, "serviceEndpoint");
|
|
453
|
+
return typeof endpoint === "string" ? endpoint : null;
|
|
353
454
|
}
|
|
354
455
|
|
|
355
456
|
/**
|
|
@@ -357,32 +458,81 @@ async function resolveArtifactUrl(
|
|
|
357
458
|
* `null` when the cap is breached (the streamed body lied about / omitted
|
|
358
459
|
* Content-Length). The cap is the real defence against an unbounded body.
|
|
359
460
|
*/
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
461
|
+
function proxyFetchOptions(signal: AbortSignal) {
|
|
462
|
+
return {
|
|
463
|
+
fetch: async (url: URL, init: RequestInit) =>
|
|
464
|
+
fetchRegistryArtifactUrl(url.href, {
|
|
465
|
+
signal: init.signal instanceof AbortSignal ? init.signal : signal,
|
|
466
|
+
maxResponseBytes: MAX_IMAGE_BYTES,
|
|
467
|
+
}),
|
|
468
|
+
resolveHostname: async (hostname: string) =>
|
|
469
|
+
(await resolveAndValidateExternalUrlTarget(`https://${hostname}/`)).addresses,
|
|
470
|
+
allowHttpLocalhost: import.meta.env.DEV,
|
|
471
|
+
maxBytes: MAX_IMAGE_BYTES,
|
|
472
|
+
maxRedirects: MAX_REDIRECTS,
|
|
473
|
+
totalTimeoutMs: FETCH_TIMEOUT_MS,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async function fetchRawArtifact(
|
|
478
|
+
resolved: ResolvedArtifact,
|
|
479
|
+
options: ReturnType<typeof proxyFetchOptions>,
|
|
480
|
+
): Promise<
|
|
481
|
+
| { success: true; bytes: Uint8Array; headers: Headers; checksumValid: boolean }
|
|
482
|
+
| { success: false; code: string }
|
|
483
|
+
> {
|
|
484
|
+
const urls: URL[] = [];
|
|
485
|
+
const blobCid = resolved.artifact.blob?.ref.$link;
|
|
486
|
+
let lastCode = "FETCH_FAILED";
|
|
487
|
+
let checksumMismatch: { bytes: Uint8Array; headers: Headers } | undefined;
|
|
488
|
+
if (blobCid) {
|
|
489
|
+
const pds = await resolvePublisherPdsEndpoint(resolved.record.did, options);
|
|
490
|
+
if (pds.success) {
|
|
491
|
+
const url = new URL("/xrpc/com.atproto.sync.getBlob", pds.value);
|
|
492
|
+
url.searchParams.set("did", resolved.record.did);
|
|
493
|
+
url.searchParams.set("cid", blobCid);
|
|
494
|
+
urls.push(url);
|
|
495
|
+
} else {
|
|
496
|
+
lastCode = pds.error.code;
|
|
497
|
+
}
|
|
365
498
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
chunks.push(value);
|
|
499
|
+
if (resolved.artifact.url) urls.push(new URL(resolved.artifact.url));
|
|
500
|
+
|
|
501
|
+
for (const url of urls) {
|
|
502
|
+
const fetched = await fetchVerifiedResource(url, options);
|
|
503
|
+
if (!fetched.success) {
|
|
504
|
+
lastCode = fetched.error.code;
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
if (!(await verifyChecksum(fetched.value.bytes, resolved.artifact.checksum))) {
|
|
508
|
+
lastCode = "CHECKSUM_MISMATCH";
|
|
509
|
+
checksumMismatch = { bytes: fetched.value.bytes, headers: fetched.value.headers };
|
|
510
|
+
continue;
|
|
379
511
|
}
|
|
512
|
+
return {
|
|
513
|
+
success: true,
|
|
514
|
+
bytes: fetched.value.bytes,
|
|
515
|
+
headers: fetched.value.headers,
|
|
516
|
+
checksumValid: true,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
if (checksumMismatch) return { success: true, ...checksumMismatch, checksumValid: false };
|
|
520
|
+
return { success: false, code: lastCode };
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function artifactFetchError(code: string): Response {
|
|
524
|
+
if (code === "CHECKSUM_MISMATCH") {
|
|
525
|
+
return apiError(
|
|
526
|
+
"ARTIFACT_CHECKSUM_MISMATCH",
|
|
527
|
+
"Artifact bytes do not match the approved release record",
|
|
528
|
+
502,
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
if (code === "RESOURCE_SIZE_EXCEEDED") {
|
|
532
|
+
return apiError("ARTIFACT_TOO_LARGE", "Artifact exceeds size limit", 413);
|
|
380
533
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
for (const chunk of chunks) {
|
|
384
|
-
combined.set(chunk, offset);
|
|
385
|
-
offset += chunk.length;
|
|
534
|
+
if (code === "HOST_REJECTED" || code === "INVALID_URL") {
|
|
535
|
+
return apiError("ARTIFACT_URL_REJECTED", "Artifact URL is not allowed", 400);
|
|
386
536
|
}
|
|
387
|
-
return
|
|
537
|
+
return apiError("ARTIFACT_FETCH_FAILED", "Failed to fetch artifact", 502);
|
|
388
538
|
}
|
|
@@ -15,16 +15,28 @@ import { authMeActionBody } from "#api/schemas.js";
|
|
|
15
15
|
import { UserRepository } from "#db/repositories/user.js";
|
|
16
16
|
|
|
17
17
|
export const GET: APIRoute = async ({ locals }) => {
|
|
18
|
-
const { user } = locals;
|
|
18
|
+
const { user, emdash } = locals;
|
|
19
19
|
|
|
20
20
|
if (!user) {
|
|
21
21
|
return apiError("NOT_AUTHENTICATED", "Not authenticated", 401);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
let userData = user.data;
|
|
25
|
+
if (locals.__playgroundDb) {
|
|
26
|
+
if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const persistedUser = await new UserRepository(emdash.db).findById(user.id);
|
|
30
|
+
if (persistedUser) userData = persistedUser.data;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return handleError(error, "Failed to fetch current user", "CURRENT_USER_ERROR");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
24
36
|
// Check if this is the user's first login (for welcome modal).
|
|
25
37
|
// The flag is persisted in the user's `data` JSON column so it survives
|
|
26
38
|
// session expiry / rotation.
|
|
27
|
-
const isFirstLogin = !
|
|
39
|
+
const isFirstLogin = !userData?.welcomeDismissed;
|
|
28
40
|
|
|
29
41
|
// Return safe user info (no sensitive data)
|
|
30
42
|
return apiSuccess({
|
|
@@ -92,6 +92,9 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
|
|
|
92
92
|
caption: body.caption,
|
|
93
93
|
width: body.width,
|
|
94
94
|
height: body.height,
|
|
95
|
+
folderId: body.folderId,
|
|
96
|
+
focalX: body.focalX,
|
|
97
|
+
focalY: body.focalY,
|
|
95
98
|
});
|
|
96
99
|
|
|
97
100
|
return unwrapResult(result);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { APIRoute } from "astro";
|
|
2
|
+
|
|
3
|
+
import { requirePerm } from "#api/authorize.js";
|
|
4
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
5
|
+
import {
|
|
6
|
+
handleMediaFolderDelete,
|
|
7
|
+
handleMediaFolderGet,
|
|
8
|
+
handleMediaFolderUpdate,
|
|
9
|
+
} from "#api/handlers/media-folders.js";
|
|
10
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
11
|
+
import { mediaFolderBody, mediaFolderIdSchema } from "#api/schemas.js";
|
|
12
|
+
|
|
13
|
+
export const prerender = false;
|
|
14
|
+
|
|
15
|
+
function parseFolderId(id: string | undefined): string | Response {
|
|
16
|
+
const result = mediaFolderIdSchema.safeParse(id);
|
|
17
|
+
return result.success
|
|
18
|
+
? result.data
|
|
19
|
+
: apiError("VALIDATION_ERROR", "Invalid media folder ID", 400);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const GET: APIRoute = async ({ params, locals }) => {
|
|
23
|
+
const { emdash, user } = locals;
|
|
24
|
+
const denied = requirePerm(user, "media:read");
|
|
25
|
+
if (denied) return denied;
|
|
26
|
+
if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
27
|
+
|
|
28
|
+
const id = parseFolderId(params.id);
|
|
29
|
+
if (id instanceof Response) return id;
|
|
30
|
+
return unwrapResult(await handleMediaFolderGet(emdash.db, id));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const PUT: APIRoute = async ({ params, request, locals }) => {
|
|
34
|
+
const { emdash, user } = locals;
|
|
35
|
+
const denied = requirePerm(user, "media:edit_any");
|
|
36
|
+
if (denied) return denied;
|
|
37
|
+
if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
38
|
+
|
|
39
|
+
const id = parseFolderId(params.id);
|
|
40
|
+
if (id instanceof Response) return id;
|
|
41
|
+
const body = await parseBody(request, mediaFolderBody);
|
|
42
|
+
if (isParseError(body)) return body;
|
|
43
|
+
return unwrapResult(await handleMediaFolderUpdate(emdash.db, id, body));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const DELETE: APIRoute = async ({ params, locals }) => {
|
|
47
|
+
const { emdash, user } = locals;
|
|
48
|
+
const denied = requirePerm(user, "media:edit_any");
|
|
49
|
+
if (denied) return denied;
|
|
50
|
+
if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
51
|
+
|
|
52
|
+
const id = parseFolderId(params.id);
|
|
53
|
+
if (id instanceof Response) return id;
|
|
54
|
+
return unwrapResult(await handleMediaFolderDelete(emdash.db, id));
|
|
55
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { APIRoute } from "astro";
|
|
2
|
+
|
|
3
|
+
import { requirePerm } from "#api/authorize.js";
|
|
4
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
5
|
+
import { handleMediaFolderCreate, handleMediaFolderList } from "#api/handlers/media-folders.js";
|
|
6
|
+
import { isParseError, parseBody, parseQuery } from "#api/parse.js";
|
|
7
|
+
import { mediaFolderBody, mediaFolderListQuery } from "#api/schemas.js";
|
|
8
|
+
|
|
9
|
+
export const prerender = false;
|
|
10
|
+
|
|
11
|
+
export const GET: APIRoute = async ({ request, locals }) => {
|
|
12
|
+
const { emdash, user } = locals;
|
|
13
|
+
const denied = requirePerm(user, "media:read");
|
|
14
|
+
if (denied) return denied;
|
|
15
|
+
if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
16
|
+
|
|
17
|
+
const query = parseQuery(new URL(request.url), mediaFolderListQuery);
|
|
18
|
+
if (isParseError(query)) return query;
|
|
19
|
+
return unwrapResult(
|
|
20
|
+
await handleMediaFolderList(emdash.db, {
|
|
21
|
+
limit: query.limit,
|
|
22
|
+
cursor: query.cursor,
|
|
23
|
+
q: query.q,
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
29
|
+
const { emdash, user } = locals;
|
|
30
|
+
const denied = requirePerm(user, "media:edit_any");
|
|
31
|
+
if (denied) return denied;
|
|
32
|
+
if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
33
|
+
|
|
34
|
+
const body = await parseBody(request, mediaFolderBody);
|
|
35
|
+
if (isParseError(body)) return body;
|
|
36
|
+
return unwrapResult(await handleMediaFolderCreate(emdash.db, body), 201);
|
|
37
|
+
};
|
|
@@ -55,9 +55,11 @@ export const GET: APIRoute = async ({ request, locals }) => {
|
|
|
55
55
|
|
|
56
56
|
const result = await emdash.handleMediaList({
|
|
57
57
|
cursor: query.cursor,
|
|
58
|
+
page: query.page,
|
|
58
59
|
limit: query.limit,
|
|
59
60
|
mimeType: query.mimeType,
|
|
60
61
|
q: query.q,
|
|
62
|
+
folderId: query.folderId === "unfiled" ? null : query.folderId,
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
if (!result.success) {
|
|
@@ -67,7 +69,11 @@ export const GET: APIRoute = async ({ request, locals }) => {
|
|
|
67
69
|
// Add URL to each media item (relative URLs for portability)
|
|
68
70
|
const itemsWithUrl = result.data.items.map((item) => addUrlToMedia(item));
|
|
69
71
|
if (query.includeUsage !== "1") {
|
|
70
|
-
return apiSuccess({
|
|
72
|
+
return apiSuccess({
|
|
73
|
+
items: itemsWithUrl,
|
|
74
|
+
nextCursor: result.data.nextCursor,
|
|
75
|
+
totalCount: result.data.totalCount,
|
|
76
|
+
});
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
const includeCount = canReadMediaUsageCount(user, locals.tokenScopes);
|
|
@@ -85,7 +91,11 @@ export const GET: APIRoute = async ({ request, locals }) => {
|
|
|
85
91
|
itemsWithUsage.push({ ...item, usage });
|
|
86
92
|
}
|
|
87
93
|
|
|
88
|
-
return apiSuccess({
|
|
94
|
+
return apiSuccess({
|
|
95
|
+
items: itemsWithUsage,
|
|
96
|
+
nextCursor: result.data.nextCursor,
|
|
97
|
+
totalCount: result.data.totalCount,
|
|
98
|
+
});
|
|
89
99
|
};
|
|
90
100
|
|
|
91
101
|
/**
|