emdash 0.36.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-CzL3H752.d.mts → adapters-DCEgOBXi.d.mts} +4 -2
- package/dist/{adapters-CzL3H752.d.mts.map → adapters-DCEgOBXi.d.mts.map} +1 -1
- package/dist/{allowed-origins-maylGaHv.mjs → allowed-origins-GFUVavRj.mjs} +2 -2
- package/dist/{allowed-origins-maylGaHv.mjs.map → allowed-origins-GFUVavRj.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +25 -24
- 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-BvxJmnFY.mjs +10094 -0
- package/dist/api-BvxJmnFY.mjs.map +1 -0
- package/dist/{api-tokens-9YrrCoE6.mjs → api-tokens-xpGqMHrC.mjs} +2 -2
- package/dist/{api-tokens-9YrrCoE6.mjs.map → api-tokens-xpGqMHrC.mjs.map} +1 -1
- package/dist/{apply-B_VMpJ2P.mjs → apply-DLmM3R7f.mjs} +26 -22
- package/dist/apply-DLmM3R7f.mjs.map +1 -0
- package/dist/artifact-fetch-P2JXVwOq.mjs +972 -0
- package/dist/artifact-fetch-P2JXVwOq.mjs.map +1 -0
- package/dist/astro/image-endpoint.mjs +2 -2
- package/dist/astro/image-endpoint.mjs.map +1 -1
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +138 -39
- 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 +223 -232
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
- package/dist/astro/routes/api/admin/api-tokens/index.mjs.map +1 -1
- 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 +17 -17
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -17
- package/dist/astro/routes/api/admin/bylines/index.mjs +17 -17
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +13 -13
- package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +10 -10
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +10 -10
- 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 +14 -14
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +17 -17
- 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 +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +59 -56
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +59 -56
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +57 -54
- 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 +57 -54
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +58 -55
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +58 -55
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +57 -54
- 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 +57 -54
- 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 +58 -55
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +58 -55
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +64 -57
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +18 -16
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +65 -58
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts +8 -0
- package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +96 -0
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -0
- package/dist/astro/routes/api/admin/plugins/updates.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +57 -54
- 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 +57 -54
- 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 +14 -14
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +13 -13
- 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 +19 -5
- 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 +18 -10
- 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 +20 -18
- 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 +20 -18
- 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 +16 -15
- 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 +19 -5
- 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 +8 -8
- 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 +18 -18
- 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 +15 -14
- 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 +18 -18
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +29 -28
- 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/manifest.mjs.map +1 -1
- package/dist/astro/routes/api/mcp.mjs +213 -74
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +11 -11
- package/dist/astro/routes/api/media/_id_/replace.d.mts +8 -0
- package/dist/astro/routes/api/media/_id_/replace.d.mts.map +1 -0
- package/dist/astro/routes/api/media/_id_/replace.mjs +91 -0
- package/dist/astro/routes/api/media/_id_/replace.mjs.map +1 -0
- package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
- package/dist/astro/routes/api/media/_id_/usage.mjs +19 -19
- package/dist/astro/routes/api/media/_id_.mjs +18 -18
- package/dist/astro/routes/api/media/file/_...key_.d.mts.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +3 -2
- package/dist/astro/routes/api/media/file/_...key_.mjs.map +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 +16 -14
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.d.mts.map +1 -1
- package/dist/astro/routes/api/media.mjs +53 -30
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +20 -13
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +15 -11
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +15 -11
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +16 -12
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +21 -14
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +15 -11
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- 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 +184 -52
- 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 +20 -18
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +15 -13
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +20 -18
- 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 +57 -54
- 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 +57 -54
- 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 +57 -54
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.mjs +57 -54
- 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 +57 -54
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +57 -54
- 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 +5 -5
- package/dist/astro/routes/api/settings/email.mjs.map +1 -1
- package/dist/astro/routes/api/settings.d.mts.map +1 -1
- package/dist/astro/routes/api/settings.mjs +21 -17
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- 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 +35 -33
- 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 +35 -33
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +22 -17
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -18
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +27 -19
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +22 -17
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_.mjs +28 -20
- package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +22 -17
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +10 -8
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +18 -14
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +16 -13
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -7
- package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.mjs +16 -13
- package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +8 -8
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -12
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +9 -9
- package/dist/astro/types.d.mts +50 -20
- 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-ByYs-Uxs.mjs → authorize-C2QHlWSS.mjs} +2 -2
- package/dist/{authorize-ByYs-Uxs.mjs.map → authorize-C2QHlWSS.mjs.map} +1 -1
- package/dist/{backup-ChyHfIoX.mjs → backup-oS8ft5Cm.mjs} +5 -5
- package/dist/{backup-ChyHfIoX.mjs.map → backup-oS8ft5Cm.mjs.map} +1 -1
- package/dist/{bundle-DZFhFurR.mjs → bundle-CL0JjIPx.mjs} +4 -4
- package/dist/{bundle-DZFhFurR.mjs.map → bundle-CL0JjIPx.mjs.map} +1 -1
- package/dist/{byline-Cpnwrje1.mjs → byline-Vdi85CsZ.mjs} +27 -14
- package/dist/byline-Vdi85CsZ.mjs.map +1 -0
- package/dist/{byline-fields-CAyA_Umd.mjs → byline-fields-DPVRFMz2.mjs} +2 -2
- package/dist/{byline-fields-CAyA_Umd.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-BSo9B9RX.mjs → bylines-BX8QhcTk.mjs} +7 -7
- package/dist/{bylines-BSo9B9RX.mjs.map → bylines-BX8QhcTk.mjs.map} +1 -1
- package/dist/{bylines-CHjvehVX.mjs → bylines-w-E1IEQd.mjs} +3 -3
- package/dist/{bylines-CHjvehVX.mjs.map → bylines-w-E1IEQd.mjs.map} +1 -1
- package/dist/{cache-5VirJ2Cn.mjs → cache--7HKu5Xm.mjs} +4 -4
- package/dist/{cache-5VirJ2Cn.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-D5pSY2S1.mjs → challenge-store-BIOak-tp.mjs} +5 -3
- package/dist/challenge-store-BIOak-tp.mjs.map +1 -0
- package/dist/chrome-tags-DzDQBCjX.mjs +24 -0
- package/dist/chrome-tags-DzDQBCjX.mjs.map +1 -0
- package/dist/{chunks-bNiX6_DR.mjs → chunks-VG_tyqnP.mjs} +2 -2
- package/dist/{chunks-bNiX6_DR.mjs.map → chunks-VG_tyqnP.mjs.map} +1 -1
- package/dist/cli/index.mjs +68 -40
- 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-m_oi2c0N.mjs → collection-deletion-BCwaWTDw.mjs} +4 -4
- package/dist/{collection-deletion-m_oi2c0N.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-CRuItEjt.mjs → comment-reaction-CDyvPQRj.mjs} +2 -2
- package/dist/{comment-reaction-CRuItEjt.mjs.map → comment-reaction-CDyvPQRj.mjs.map} +1 -1
- package/dist/{comment-DhvLEdhQ.mjs → comment-vxOzWbZN.mjs} +2 -2
- package/dist/{comment-DhvLEdhQ.mjs.map → comment-vxOzWbZN.mjs.map} +1 -1
- package/dist/{comments-CLj4bi8I.mjs → comments-VzmVLyaC.mjs} +2 -2
- package/dist/{comments-CLj4bi8I.mjs.map → comments-VzmVLyaC.mjs.map} +1 -1
- package/dist/{components-v4U4DT2y.mjs → components-CL6Wkdk-.mjs} +1 -1
- package/dist/{components-v4U4DT2y.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-DWbJrsAg.d.mts → config-CGAhyOjP.d.mts} +276 -76
- package/dist/config-CGAhyOjP.d.mts.map +1 -0
- package/dist/{config-DrfghTPe.d.mts → config-ChFzshGd.d.mts} +1 -1
- package/dist/{config-DrfghTPe.d.mts.map → config-ChFzshGd.d.mts.map} +1 -1
- package/dist/{content-CP-SeXNa.mjs → content-CNfMWuhY.mjs} +202 -46
- package/dist/content-CNfMWuhY.mjs.map +1 -0
- package/dist/{content-list-query-BhejKVqb.d.mts → content-list-query-B8d4UQp9.d.mts} +1 -1
- package/dist/{content-list-query-BhejKVqb.d.mts.map → content-list-query-B8d4UQp9.d.mts.map} +1 -1
- package/dist/{content-refresh-DLOfIhYc.mjs → content-refresh-GTMyi2Xy.mjs} +53 -26
- package/dist/content-refresh-GTMyi2Xy.mjs.map +1 -0
- package/dist/{content-repair-BCxzy0r4.mjs → content-repair-CIMt5C0U.mjs} +4 -4
- package/dist/{content-repair-BCxzy0r4.mjs.map → content-repair-CIMt5C0U.mjs.map} +1 -1
- package/dist/{context-BR5hRWiK.mjs → context-C9PB8vGd.mjs} +308 -33
- package/dist/context-C9PB8vGd.mjs.map +1 -0
- package/dist/{cron-CWfWrWKG.mjs → cron-DHAy9oyq.mjs} +1 -1
- package/dist/{cron-CWfWrWKG.mjs.map → cron-DHAy9oyq.mjs.map} +1 -1
- package/dist/{dashboard-CkIV2rnQ.mjs → dashboard-BNSvAN8A.mjs} +5 -5
- package/dist/{dashboard-CkIV2rnQ.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/index.mjs.map +1 -1
- 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/postgres.d.mts.map +1 -1
- package/dist/db/postgres.mjs +19 -3
- package/dist/db/postgres.mjs.map +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-YMEfcQUx.mjs → default-ByZ0JqZo.mjs} +1 -1
- package/dist/{default-YMEfcQUx.mjs.map → default-ByZ0JqZo.mjs.map} +1 -1
- package/dist/{deferred-tasks-DfqxH5Xf.d.mts → deferred-tasks-Cu4NSJpa.d.mts} +1 -1
- package/dist/{deferred-tasks-DfqxH5Xf.d.mts.map → deferred-tasks-Cu4NSJpa.d.mts.map} +1 -1
- package/dist/dev-typegen-DHT7lcMU.mjs +29 -0
- package/dist/dev-typegen-DHT7lcMU.mjs.map +1 -0
- package/dist/{device-flow-CojjSBwb.mjs → device-flow-Cf6bhCCT.mjs} +4 -4
- package/dist/{device-flow-CojjSBwb.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-BWeWiRYB.mjs → direct-executor-yAyUGSqB.mjs} +3 -3
- package/dist/{direct-executor-BWeWiRYB.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-CEJgR_LB.mjs → email-console-DNup1Fku.mjs} +1 -1
- package/dist/{email-console-CEJgR_LB.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-C7B46bcU.d.mts → entry-lock-CGAtrwAR.d.mts} +265 -76
- package/dist/entry-lock-CGAtrwAR.d.mts.map +1 -0
- package/dist/{redirects-CRIM55KH.mjs → entry-lock-DIYHAaSw.mjs} +112 -34
- 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-D9w94fjV.mjs → error-BDcFyoRt.mjs} +2 -2
- package/dist/{error-D9w94fjV.mjs.map → error-BDcFyoRt.mjs.map} +1 -1
- package/dist/{errors-n2j49uNf.mjs → errors-DvMdNrgf.mjs} +10 -1
- package/dist/errors-DvMdNrgf.mjs.map +1 -0
- package/dist/{escape-DN4Qmjsl.mjs → escape-B3asJC6W.mjs} +1 -1
- package/dist/{escape-DN4Qmjsl.mjs.map → escape-B3asJC6W.mjs.map} +1 -1
- package/dist/{field-defs-cache-Bh4q6oar.mjs → field-defs-cache-Cf5FHK0M.mjs} +5 -5
- package/dist/{field-defs-cache-Bh4q6oar.mjs.map → field-defs-cache-Cf5FHK0M.mjs.map} +1 -1
- package/dist/{fts-manager-BhOdW0bi.mjs → fts-manager-iddym8cd.mjs} +4 -4
- package/dist/{fts-manager-BhOdW0bi.mjs.map → fts-manager-iddym8cd.mjs.map} +1 -1
- package/dist/{hash-CTcngWvj.mjs → hash-BRweX6jz.mjs} +1 -1
- package/dist/{hash-CTcngWvj.mjs.map → hash-BRweX6jz.mjs.map} +1 -1
- package/dist/hook-result-BrshYHLx.d.mts +31 -0
- package/dist/hook-result-BrshYHLx.d.mts.map +1 -0
- package/dist/{hreflang-7pTHsLZJ.d.mts → hreflang-CQpu5bMy.d.mts} +2 -2
- package/dist/{hreflang-7pTHsLZJ.d.mts.map → hreflang-CQpu5bMy.d.mts.map} +1 -1
- package/dist/{hreflang-Huc6O5wa.mjs → hreflang-DshnweTC.mjs} +9 -8
- package/dist/{hreflang-Huc6O5wa.mjs.map → hreflang-DshnweTC.mjs.map} +1 -1
- package/dist/{identity-DXmb4aVp.mjs → identity-CjGKDq8J.mjs} +3 -3
- package/dist/{identity-DXmb4aVp.mjs.map → identity-CjGKDq8J.mjs.map} +1 -1
- package/dist/{import-C4_O3KXU.mjs → import-D96g2otw.mjs} +6 -6
- package/dist/{import-C4_O3KXU.mjs.map → import-D96g2otw.mjs.map} +1 -1
- package/dist/{index-6bRee8zb.d.mts → index-1ECYpfiF.d.mts} +3 -3
- package/dist/{index-6bRee8zb.d.mts.map → index-1ECYpfiF.d.mts.map} +1 -1
- package/dist/index.d.mts +22 -21
- package/dist/index.mjs +84 -81
- 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-Bo7fZAbg.mjs → load-DPtY9cZo.mjs} +2 -2
- package/dist/{load-Bo7fZAbg.mjs.map → load-DPtY9cZo.mjs.map} +1 -1
- package/dist/{loader-ZsjE4paL.mjs → loader-WJi6GFRn.mjs} +90 -17
- package/dist/loader-WJi6GFRn.mjs.map +1 -0
- package/dist/{manifest-builder-QXuqvVMP.mjs → manifest-builder-BfNlGQIA.mjs} +2 -2
- package/dist/{manifest-builder-QXuqvVMP.mjs.map → manifest-builder-BfNlGQIA.mjs.map} +1 -1
- package/dist/{manifest-schema-CUYPfCEH.mjs → manifest-schema-CILooI5J.mjs} +5 -5
- package/dist/manifest-schema-CILooI5J.mjs.map +1 -0
- package/dist/media/image-endpoint.d.mts +4 -2
- package/dist/media/image-endpoint.d.mts.map +1 -1
- package/dist/media/image-endpoint.mjs +6 -4
- package/dist/media/image-endpoint.mjs.map +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 +7 -7
- package/dist/{media-D6SeAfBl.mjs → media-BBm8Wg3f.mjs} +30 -2
- package/dist/media-BBm8Wg3f.mjs.map +1 -0
- package/dist/{media-BjwNuLEu.mjs → media-C1EIZKh1.mjs} +35 -5
- package/dist/media-C1EIZKh1.mjs.map +1 -0
- package/dist/{media-allowlist-D35v7bmL.mjs → media-allowlist-elXJgb_K.mjs} +2 -2
- package/dist/{media-allowlist-D35v7bmL.mjs.map → media-allowlist-elXJgb_K.mjs.map} +1 -1
- package/dist/{media-folders-D-0CmRZj.mjs → media-folders-DASfX_DH.mjs} +1 -1
- package/dist/{media-folders-D-0CmRZj.mjs.map → media-folders-DASfX_DH.mjs.map} +1 -1
- package/dist/{media-upload-C7bLXGcI.mjs → media-upload-C7_AQJ5v.mjs} +9 -9
- package/dist/{media-upload-C7bLXGcI.mjs.map → media-upload-C7_AQJ5v.mjs.map} +1 -1
- package/dist/{media-url-DH7giMx_.mjs → media-url-8dVl1loq.mjs} +19 -2
- package/dist/media-url-8dVl1loq.mjs.map +1 -0
- package/dist/{media-usage-BTRJvS6V.mjs → media-usage-C1EswMTq.mjs} +10 -10
- package/dist/{media-usage-BTRJvS6V.mjs.map → media-usage-C1EswMTq.mjs.map} +1 -1
- package/dist/{media-usage-activation-Dx0kPV6b.mjs → media-usage-activation-CrHNltlL.mjs} +3 -3
- package/dist/{media-usage-activation-Dx0kPV6b.mjs.map → media-usage-activation-CrHNltlL.mjs.map} +1 -1
- package/dist/{media-usage-work-C-fhM30c.mjs → media-usage-work-C5B1zT1c.mjs} +2 -2
- package/dist/{media-usage-work-C-fhM30c.mjs.map → media-usage-work-C5B1zT1c.mjs.map} +1 -1
- package/dist/{media-usage-work-DWb2XPMI.mjs → media-usage-work-IkQx_Yz6.mjs} +4 -4
- package/dist/{media-usage-work-DWb2XPMI.mjs.map → media-usage-work-IkQx_Yz6.mjs.map} +1 -1
- package/dist/{media-usage-write-fence-BwoJVRDC.mjs → media-usage-write-fence-B9anjOSg.mjs} +3 -3
- package/dist/{media-usage-write-fence-BwoJVRDC.mjs.map → media-usage-write-fence-B9anjOSg.mjs.map} +1 -1
- package/dist/{menus-CNg0QlDt.mjs → menus-D8mC4eaN.mjs} +406 -175
- package/dist/menus-D8mC4eaN.mjs.map +1 -0
- package/dist/{menus-CD7EFLwz.mjs → menus-UdwjHZJC.mjs} +12 -4
- package/dist/{menus-CD7EFLwz.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-DaUM_MB2.mjs → mode-Dm4BHhRH.mjs} +1 -1
- package/dist/{mode-DaUM_MB2.mjs.map → mode-Dm4BHhRH.mjs.map} +1 -1
- package/dist/{node-sqlite-compat-Udb4Y-rs.mjs → node-sqlite-compat-2sezm-Zd.mjs} +1 -1
- package/dist/{node-sqlite-compat-Udb4Y-rs.mjs.map → node-sqlite-compat-2sezm-Zd.mjs.map} +1 -1
- package/dist/{normalize-CSxdKBVa.mjs → normalize-4nkKGsuW.mjs} +15 -5
- package/dist/normalize-4nkKGsuW.mjs.map +1 -0
- package/dist/{oauth-authorization-Dpsb-fMJ.mjs → oauth-authorization-BxE_lURD.mjs} +4 -4
- package/dist/{oauth-authorization-Dpsb-fMJ.mjs.map → oauth-authorization-BxE_lURD.mjs.map} +1 -1
- package/dist/{oauth-clients-Bxnoe_67.mjs → oauth-clients-DJIdOdq0.mjs} +1 -1
- package/dist/{oauth-clients-Bxnoe_67.mjs.map → oauth-clients-DJIdOdq0.mjs.map} +1 -1
- package/dist/{oauth-state-store-0C4s0K6w.mjs → oauth-state-store-CsdxP57n.mjs} +1 -1
- package/dist/{oauth-state-store-0C4s0K6w.mjs.map → oauth-state-store-CsdxP57n.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-wlGYSeqX.mjs → oauth-user-lookup-HzzW-dkF.mjs} +1 -1
- package/dist/{oauth-user-lookup-wlGYSeqX.mjs.map → oauth-user-lookup-HzzW-dkF.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-71tPfV4A.mjs → object-cache-DVKnyOfy.mjs} +19 -3
- package/dist/object-cache-DVKnyOfy.mjs.map +1 -0
- package/dist/{options-BHPeIbBd.mjs → options-D1FBiAv1.mjs} +60 -5
- package/dist/options-D1FBiAv1.mjs.map +1 -0
- package/dist/{options-BhZIeFY1.d.mts → options-D8Y0VHc7.d.mts} +30 -11
- 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-BRJg1kz8.mjs → parse-WRg5C3NX.mjs} +2 -2
- package/dist/{parse-BRJg1kz8.mjs.map → parse-WRg5C3NX.mjs.map} +1 -1
- package/dist/{passkey-config-B3P0nHRR.mjs → passkey-config-qIdO-wF6.mjs} +1 -1
- package/dist/{passkey-config-B3P0nHRR.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-BR4ZhVJl.d.mts → placeholder-COrvARyD.d.mts} +1 -1
- package/dist/{placeholder-BR4ZhVJl.d.mts.map → placeholder-COrvARyD.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +8 -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-BVRganJQ.mjs → policy-XCfb-IE9.mjs} +2 -2
- package/dist/{policy-BVRganJQ.mjs.map → policy-XCfb-IE9.mjs.map} +1 -1
- package/dist/{portable-text-C8Tvp4_g.mjs → portable-text-BS3d5n-0.mjs} +1 -1
- package/dist/{portable-text-C8Tvp4_g.mjs.map → portable-text-BS3d5n-0.mjs.map} +1 -1
- package/dist/{preview-dn2dUyM0.mjs → preview-BxwsGgGp.mjs} +2 -2
- package/dist/{preview-dn2dUyM0.mjs.map → preview-BxwsGgGp.mjs.map} +1 -1
- package/dist/{protocol-CuBEsqgE.d.mts → protocol-CLn58-nw.d.mts} +2 -2
- package/dist/{protocol-CuBEsqgE.d.mts.map → protocol-CLn58-nw.d.mts.map} +1 -1
- package/dist/{public-url-DRz_AinV.mjs → public-url-FWWAvnre.mjs} +1 -1
- package/dist/{public-url-DRz_AinV.mjs.map → public-url-FWWAvnre.mjs.map} +1 -1
- package/dist/{query-D18vTdha.mjs → query-DygOte9M.mjs} +26 -17
- package/dist/query-DygOte9M.mjs.map +1 -0
- package/dist/{query-tZDEdtCN.mjs → query-gtXT03Wc.mjs} +5 -5
- package/dist/{query-tZDEdtCN.mjs.map → query-gtXT03Wc.mjs.map} +1 -1
- package/dist/{rate-limit-on7KPo-v.mjs → rate-limit-CQUPm0dh.mjs} +2 -2
- package/dist/{rate-limit-on7KPo-v.mjs.map → rate-limit-CQUPm0dh.mjs.map} +1 -1
- package/dist/{redirect-DrbEmU9a.mjs → redirect-D1cWafi6.mjs} +1 -1
- package/dist/{redirect-DrbEmU9a.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-BahWiu8Z.mjs → redirects-DN-ZE33W.mjs} +5 -5
- package/dist/{redirects-BahWiu8Z.mjs.map → redirects-DN-ZE33W.mjs.map} +1 -1
- package/dist/{registry-Cx-jEJOS.mjs → registry-DTqaqxed.mjs} +46 -12
- package/dist/registry-DTqaqxed.mjs.map +1 -0
- package/dist/{relation-A6wLF_DS.mjs → relation-DxgCHOBw.mjs} +2 -2
- package/dist/{relation-A6wLF_DS.mjs.map → relation-DxgCHOBw.mjs.map} +1 -1
- package/dist/{relations-Cj5hZ6Zg.mjs → relations-KKDSLUwS.mjs} +4 -4
- package/dist/{relations-Cj5hZ6Zg.mjs.map → relations-KKDSLUwS.mjs.map} +1 -1
- package/dist/{relations-BTPM2saV.mjs → relations-rOmbndUJ.mjs} +8 -8
- package/dist/relations-rOmbndUJ.mjs.map +1 -0
- 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-DRp5ENd_.mjs → request-meta-BgjUQLQ-.mjs} +2 -2
- package/dist/{request-meta-DRp5ENd_.mjs.map → request-meta-BgjUQLQ-.mjs.map} +1 -1
- package/dist/{resolve-DxUpTMmE.mjs → resolve-Cy0aWSRj.mjs} +37 -4
- package/dist/resolve-Cy0aWSRj.mjs.map +1 -0
- package/dist/{runner-zgqA_CqP.d.mts → runner-CfwysRM0.d.mts} +3 -2
- package/dist/runner-CfwysRM0.d.mts.map +1 -0
- package/dist/{runner-77GOZCnH.mjs → runner-nEzvnogG.mjs} +476 -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-BY-oVntF.mjs → schema-CRu38Pr5.mjs} +3 -3
- package/dist/{schema-BY-oVntF.mjs.map → schema-CRu38Pr5.mjs.map} +1 -1
- package/dist/{schema-Cw9kVK0I.mjs → schema-DifxndJx.mjs} +5 -5
- package/dist/{schema-Cw9kVK0I.mjs.map → schema-DifxndJx.mjs.map} +1 -1
- package/dist/{scopes-vMR1uIbt.mjs → scopes-D5A1OZbq.mjs} +3 -3
- package/dist/{scopes-vMR1uIbt.mjs.map → scopes-D5A1OZbq.mjs.map} +1 -1
- package/dist/{search-CfT3KxO5.mjs → search-DEPFSBFq.mjs} +4 -4
- package/dist/{search-CfT3KxO5.mjs.map → search-DEPFSBFq.mjs.map} +1 -1
- package/dist/{secrets-BH2Qow1-.mjs → secrets-CdfzLdoO.mjs} +3 -3
- package/dist/{secrets-BH2Qow1-.mjs.map → secrets-CdfzLdoO.mjs.map} +1 -1
- package/dist/{sections-DTfjyf1z.mjs → sections-3X52kmIR.mjs} +2 -2
- package/dist/{sections-DTfjyf1z.mjs.map → sections-3X52kmIR.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +28 -26
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.d.mts.map +1 -1
- package/dist/seo/index.mjs +20 -21
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-Cm-dtvgk.mjs → seo-Bw68KxRc.mjs} +3 -3
- package/dist/{seo-Cm-dtvgk.mjs.map → seo-Bw68KxRc.mjs.map} +1 -1
- package/dist/{seo-BSiTIXzd.mjs → seo-C4AmbsMU.mjs} +3 -2
- package/dist/seo-C4AmbsMU.mjs.map +1 -0
- package/dist/{service-DYsDHEKe.mjs → service-J_-Vgo7R.mjs} +3 -3
- package/dist/{service-DYsDHEKe.mjs.map → service-J_-Vgo7R.mjs.map} +1 -1
- package/dist/{session-user-CNAfvsdw.mjs → session-user-CbnMMwk6.mjs} +1 -1
- package/dist/{session-user-CNAfvsdw.mjs.map → session-user-CbnMMwk6.mjs.map} +1 -1
- package/dist/{settings-DjtkUo__.mjs → settings-AnEFYICn.mjs} +3 -3
- package/dist/{settings-DjtkUo__.mjs.map → settings-AnEFYICn.mjs.map} +1 -1
- package/dist/{settings-BgN-0DT-.mjs → settings-DcMjREe5.mjs} +21 -8
- package/dist/settings-DcMjREe5.mjs.map +1 -0
- package/dist/{setup-complete-CcpXaPU7.mjs → setup-complete-BClXXTvr.mjs} +2 -2
- package/dist/{setup-complete-CcpXaPU7.mjs.map → setup-complete-BClXXTvr.mjs.map} +1 -1
- package/dist/{setup-nonce-Reyw30jg.mjs → setup-nonce-BheRa4RG.mjs} +1 -1
- package/dist/{setup-nonce-Reyw30jg.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-Cs_V9n3V.mjs → site-url-Bqf-ea3N.mjs} +3 -3
- package/dist/{site-url-Cs_V9n3V.mjs.map → site-url-Bqf-ea3N.mjs.map} +1 -1
- package/dist/{snapshot-DSB8P7Lm.mjs → snapshot-C4CtXntb.mjs} +51 -35
- package/dist/snapshot-C4CtXntb.mjs.map +1 -0
- package/dist/{ssrf-DqebVE34.mjs → ssrf-gl4gFNhw.mjs} +151 -93
- package/dist/ssrf-gl4gFNhw.mjs.map +1 -0
- package/dist/{state-BJfU9Uzw.mjs → state-1F6IOhdQ.mjs} +1 -1
- package/dist/{state-BJfU9Uzw.mjs.map → state-1F6IOhdQ.mjs.map} +1 -1
- package/dist/{status-DDu8HIQl.mjs → status-Cenfk_r5.mjs} +1 -1
- package/dist/{status-DDu8HIQl.mjs.map → status-Cenfk_r5.mjs.map} +1 -1
- package/dist/storage/local.d.mts +2 -1
- package/dist/storage/local.d.mts.map +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/local.mjs.map +1 -1
- package/dist/storage/s3.d.mts +2 -1
- package/dist/storage/s3.d.mts.map +1 -1
- package/dist/storage/s3.mjs +3 -2
- package/dist/storage/s3.mjs.map +1 -1
- package/dist/{target-D0o26Azo.mjs → target-CRzeTs8G.mjs} +1 -1
- package/dist/{target-D0o26Azo.mjs.map → target-CRzeTs8G.mjs.map} +1 -1
- package/dist/{taxonomies-CPGxo-bn.mjs → taxonomies-BOdxuZpV.mjs} +23 -13
- package/dist/taxonomies-BOdxuZpV.mjs.map +1 -0
- package/dist/{taxonomies-kmyudNGP.mjs → taxonomies-NcFDq5Gg.mjs} +58 -23
- package/dist/taxonomies-NcFDq5Gg.mjs.map +1 -0
- package/dist/{taxonomy-8X09dLN5.mjs → taxonomy-DP1vny4K.mjs} +12 -4
- package/dist/{taxonomy-8X09dLN5.mjs.map → taxonomy-DP1vny4K.mjs.map} +1 -1
- package/dist/{tokens-gTS-IVUp.mjs → tokens-CDk8ox9p.mjs} +1 -1
- package/dist/{tokens-gTS-IVUp.mjs.map → tokens-CDk8ox9p.mjs.map} +1 -1
- package/dist/{transport-_6R1ub7t.d.mts → transport-BVn4tVb9.d.mts} +1 -1
- package/dist/{transport-_6R1ub7t.d.mts.map → transport-BVn4tVb9.d.mts.map} +1 -1
- package/dist/{transport-fX59xaJz.mjs → transport-DP0JI-8i.mjs} +1 -1
- package/dist/{transport-fX59xaJz.mjs.map → transport-DP0JI-8i.mjs.map} +1 -1
- package/dist/{trusted-proxy-fe6nEgR4.mjs → trusted-proxy-BTM6UxqD.mjs} +1 -1
- package/dist/{trusted-proxy-fe6nEgR4.mjs.map → trusted-proxy-BTM6UxqD.mjs.map} +1 -1
- package/dist/{types-D_DWe7k9.d.mts → types-2n848aVW.d.mts} +3 -2
- package/dist/types-2n848aVW.d.mts.map +1 -0
- package/dist/types-A2cN6a4a.mjs +3 -0
- package/dist/{types-75KIqzL9.mjs → types-BMXnRIrX.mjs} +4 -2
- package/dist/types-BMXnRIrX.mjs.map +1 -0
- package/dist/{types-Vg6f5i3s.d.mts → types-BouXpOsa.d.mts} +121 -4
- package/dist/types-BouXpOsa.d.mts.map +1 -0
- package/dist/{types-BXUmsINL.mjs → types-ByG2coLw.mjs} +1 -1
- package/dist/{types-BXUmsINL.mjs.map → types-ByG2coLw.mjs.map} +1 -1
- package/dist/types-CQPWhPxE.mjs.map +1 -1
- package/dist/{types-Blb-MRC3.d.mts → types-DEfNJ__A.d.mts} +1 -1
- package/dist/{types-Blb-MRC3.d.mts.map → types-DEfNJ__A.d.mts.map} +1 -1
- package/dist/{types-Br-ERaxh.d.mts → types-DKcKSbtB.d.mts} +23 -7
- package/dist/types-DKcKSbtB.d.mts.map +1 -0
- package/dist/{types-BzBd3PeX.d.mts → types-DRYs7uTL.d.mts} +1 -1
- package/dist/{types-BzBd3PeX.d.mts.map → types-DRYs7uTL.d.mts.map} +1 -1
- package/dist/{types-CLqvnd05.d.mts → types-DaEg7KX2.d.mts} +1 -1
- package/dist/{types-CLqvnd05.d.mts.map → types-DaEg7KX2.d.mts.map} +1 -1
- package/dist/{types-DJQxln7q.d.mts → types-LU8utpP_.d.mts} +14 -10
- package/dist/types-LU8utpP_.d.mts.map +1 -0
- package/dist/{types-D5VVLr7J.d.mts → types-VpYfPUxN.d.mts} +1 -1
- package/dist/{types-D5VVLr7J.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-DHxzBjbD.d.mts → types-tJWDK__M.d.mts} +14 -1
- package/dist/types-tJWDK__M.d.mts.map +1 -0
- package/dist/{upload-attempts-CNyGSepg.mjs → upload-attempts-C6S2y-lp.mjs} +1 -1
- package/dist/{upload-attempts-CNyGSepg.mjs.map → upload-attempts-C6S2y-lp.mjs.map} +1 -1
- package/dist/{url-pattern-K-KdXcSe.mjs → url-pattern-UYtxVTuj.mjs} +1 -1
- package/dist/{url-pattern-K-KdXcSe.mjs.map → url-pattern-UYtxVTuj.mjs.map} +1 -1
- package/dist/{user-CtYY0tp2.mjs → user-DIsIXogT.mjs} +2 -2
- package/dist/{user-CtYY0tp2.mjs.map → user-DIsIXogT.mjs.map} +1 -1
- package/dist/{utils-HztC73hq.mjs → utils-BicP5Qbg.mjs} +2 -2
- package/dist/{utils-HztC73hq.mjs.map → utils-BicP5Qbg.mjs.map} +1 -1
- package/dist/{validate-Dd-IUjnZ.mjs → validate-D8VPn4Hv.mjs} +8 -3
- package/dist/validate-D8VPn4Hv.mjs.map +1 -0
- package/dist/{validate-DlqdOZXB.d.mts → validate-Df6Dvwbw.d.mts} +12 -7
- package/dist/validate-Df6Dvwbw.d.mts.map +1 -0
- package/dist/{validation-D83n7Npi.mjs → validation-CzMJn9Ku.mjs} +13 -11
- package/dist/{validation-D83n7Npi.mjs.map → validation-CzMJn9Ku.mjs.map} +1 -1
- package/dist/version-CK67_SXX.mjs +7 -0
- package/dist/{version-ri-sCyAp.mjs.map → version-CK67_SXX.mjs.map} +1 -1
- package/dist/{widgets-CpmZd9Q-.mjs → widgets-RFVAxQl3.mjs} +18 -5
- package/dist/widgets-RFVAxQl3.mjs.map +1 -0
- package/dist/{wxr-taxonomies-BFd0y72_.d.mts → wxr-taxonomies-BX4yQL9s.d.mts} +1 -1
- package/dist/{wxr-taxonomies-BFd0y72_.d.mts.map → wxr-taxonomies-BX4yQL9s.d.mts.map} +1 -1
- package/dist/{wxr-taxonomies-Df4vxWcU.mjs → wxr-taxonomies-Csdp7yde.mjs} +4 -4
- package/dist/{wxr-taxonomies-Df4vxWcU.mjs.map → wxr-taxonomies-Csdp7yde.mjs.map} +1 -1
- package/dist/{zod-generator-DylzusHh.mjs → zod-generator-CNRGdnBY.mjs} +11 -7
- package/dist/zod-generator-CNRGdnBY.mjs.map +1 -0
- package/package.json +16 -11
- package/src/api/errors.ts +9 -0
- package/src/api/handlers/content.ts +115 -90
- package/src/api/handlers/entry-lock.ts +206 -0
- package/src/api/handlers/index.ts +1 -0
- package/src/api/handlers/manifest.ts +162 -12
- package/src/api/handlers/marketplace.ts +28 -20
- package/src/api/handlers/media.ts +30 -0
- package/src/api/handlers/menus.ts +9 -0
- package/src/api/handlers/registry.ts +406 -297
- 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 +25 -9
- package/src/api/openapi/document.ts +196 -11
- package/src/api/parse.ts +1 -1
- package/src/api/schemas/auth.ts +4 -4
- package/src/api/schemas/bylines.ts +3 -3
- package/src/api/schemas/comments.ts +1 -1
- package/src/api/schemas/common.ts +3 -2
- package/src/api/schemas/content.ts +86 -22
- package/src/api/schemas/entry-lock.ts +48 -0
- package/src/api/schemas/index.ts +1 -0
- package/src/api/schemas/media.ts +52 -0
- package/src/api/schemas/redirects.ts +6 -1
- package/src/api/schemas/schema.ts +14 -1
- package/src/api/schemas/setup.ts +1 -1
- package/src/api/schemas/taxonomies.ts +2 -2
- package/src/api/schemas/users.ts +1 -1
- package/src/api/types.ts +25 -10
- package/src/astro/dev-typegen.ts +35 -0
- package/src/astro/image-endpoint.ts +2 -2
- package/src/astro/integration/dev-typegen.ts +91 -0
- package/src/astro/integration/index.ts +18 -50
- package/src/astro/integration/routes.ts +10 -0
- package/src/astro/integration/runtime.ts +13 -5
- package/src/astro/integration/vite-config.ts +51 -2
- package/src/astro/middleware.ts +21 -0
- package/src/astro/routes/api/admin/api-tokens/index.ts +4 -1
- package/src/astro/routes/api/admin/oauth-clients/[id].ts +1 -1
- package/src/astro/routes/api/admin/oauth-clients/index.ts +1 -1
- package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/artifact.ts +3 -7
- package/src/astro/routes/api/admin/plugins/registry/install.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/verify.ts +60 -0
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +18 -2
- package/src/astro/routes/api/content/[collection]/[id]/lock.ts +133 -0
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +12 -1
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +20 -0
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +16 -2
- 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/api/manifest.ts +1 -1
- package/src/astro/routes/api/media/[id]/replace.ts +114 -0
- package/src/astro/routes/api/media/file/[...key].ts +4 -1
- package/src/astro/routes/api/media/upload-url.ts +8 -4
- package/src/astro/routes/api/media.ts +54 -8
- package/src/astro/routes/api/menus/[name]/items/[id].ts +7 -2
- package/src/astro/routes/api/menus/[name]/items.ts +4 -1
- package/src/astro/routes/api/menus/[name]/reorder.ts +4 -1
- package/src/astro/routes/api/menus/[name]/translations.ts +4 -1
- package/src/astro/routes/api/menus/[name].ts +7 -2
- package/src/astro/routes/api/menus/index.ts +4 -1
- package/src/astro/routes/api/settings/email.ts +1 -1
- package/src/astro/routes/api/settings.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name]/reorder.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug]/translations.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +7 -2
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name].ts +7 -2
- package/src/astro/routes/api/taxonomies/index.ts +4 -1
- package/src/astro/routes/api/widget-areas/[name]/reorder.ts +3 -1
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +5 -2
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +3 -1
- package/src/astro/routes/api/widget-areas/[name].ts +3 -1
- package/src/astro/routes/api/widget-areas/index.ts +3 -1
- package/src/astro/routes/sitemap-[collection].xml.ts +4 -0
- package/src/astro/types.ts +36 -8
- package/src/auth/challenge-store.ts +3 -1
- package/src/aws-sdk.d.ts +1 -0
- package/src/cache/chrome-tags.ts +24 -0
- 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/EmDashImage.astro +2 -1
- package/src/components/EmDashMedia.astro +2 -1
- package/src/components/Gallery.astro +18 -4
- package/src/components/InlineEditor.astro +3 -1
- package/src/components/InlinePortableTextEditor.tsx +112 -12
- package/src/components/PortableText.astro +4 -0
- package/src/components/Table.astro +147 -62
- package/src/components/widgets/Archives.astro +2 -37
- package/src/config/errors.ts +13 -0
- package/src/content/converters/index.ts +2 -0
- package/src/content/converters/mark-safety.ts +1 -0
- package/src/content/converters/portable-text-identity.ts +139 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +226 -69
- package/src/content/converters/prosemirror-to-portable-text.ts +128 -28
- package/src/content/converters/types.ts +11 -0
- package/src/database/dialect-helpers.ts +125 -0
- package/src/database/migrations/017_authorization_codes.ts +14 -4
- package/src/database/migrations/074_content_deleted_scheduled_index.ts +55 -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 +9 -1
- package/src/database/repositories/byline.ts +32 -16
- package/src/database/repositories/content.ts +284 -48
- package/src/database/repositories/entry-locks.ts +257 -0
- package/src/database/repositories/media-usage.ts +66 -37
- package/src/database/repositories/media.ts +60 -1
- package/src/database/repositories/options.ts +69 -5
- package/src/database/repositories/plugin-storage.ts +233 -9
- package/src/database/repositories/redirect.ts +17 -6
- package/src/database/repositories/taxonomy.ts +8 -0
- package/src/database/repositories/types.ts +11 -7
- package/src/database/types.ts +15 -1
- package/src/db/adapters.ts +8 -1
- package/src/db/postgres.ts +23 -0
- package/src/emdash-runtime.ts +196 -199
- package/src/fields/boolean.ts +1 -1
- package/src/fields/datetime.ts +1 -1
- package/src/fields/file.ts +1 -1
- package/src/fields/integer.ts +1 -1
- package/src/fields/json.ts +1 -1
- package/src/fields/multiselect.ts +1 -1
- package/src/fields/number.ts +1 -1
- package/src/fields/portable-text.ts +1 -1
- package/src/fields/richtext.ts +1 -1
- package/src/fields/select.ts +1 -1
- package/src/fields/slug.ts +1 -1
- package/src/fields/text.ts +1 -1
- package/src/fields/textarea.ts +1 -1
- package/src/fields/types.ts +2 -2
- package/src/i18n/resolve.ts +44 -4
- package/src/index.ts +39 -3
- package/src/loader.ts +96 -12
- package/src/mcp/server.ts +251 -29
- package/src/media/image-endpoint.ts +5 -2
- package/src/media/normalize.ts +15 -4
- package/src/media/responsive.ts +23 -0
- package/src/media/usage/cleanup.ts +9 -8
- package/src/media/usage/content-refresh.ts +2 -1
- package/src/menus/index.ts +33 -21
- package/src/object-cache/index.ts +44 -2
- package/src/page/seo-contributions.ts +78 -1
- package/src/page/seo-panel.ts +47 -0
- package/src/plugin-types.ts +27 -1
- package/src/plugins/conditional-storage.ts +30 -0
- package/src/plugins/context.ts +49 -17
- package/src/plugins/hooks.ts +10 -1
- package/src/plugins/index.ts +15 -0
- package/src/plugins/manager.ts +6 -2
- package/src/plugins/manifest-schema.ts +1 -1
- package/src/plugins/routes.ts +3 -1
- package/src/plugins/sandbox/hook-result.ts +52 -0
- package/src/plugins/sandbox/index.ts +10 -0
- 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 +120 -0
- package/src/query.ts +29 -3
- package/src/registry/artifact-checksum.ts +15 -0
- package/src/registry/artifact-verification.ts +85 -0
- package/src/registry/authoritative-records.ts +180 -0
- package/src/registry/config.ts +130 -27
- package/src/registry/record-labels.ts +28 -0
- package/src/registry/types.ts +5 -6
- package/src/schema/collection-slugs-cache.ts +157 -0
- package/src/schema/registry.ts +45 -3
- package/src/schema/types.ts +25 -6
- package/src/schema/zod-generator.ts +16 -13
- package/src/security/ssrf.ts +172 -143
- 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/settings/index.ts +16 -0
- package/src/storage/local.ts +1 -0
- package/src/storage/s3.ts +2 -0
- package/src/storage/types.ts +2 -0
- package/src/taxonomies/index.ts +40 -20
- package/src/taxonomies/term-counts.ts +22 -5
- package/src/widgets/archives.ts +67 -0
- package/src/widgets/index.ts +16 -0
- package/dist/api-B0w3uBiG.mjs +0 -2269
- package/dist/api-B0w3uBiG.mjs.map +0 -1
- package/dist/apply-B_VMpJ2P.mjs.map +0 -1
- package/dist/byline-Cpnwrje1.mjs.map +0 -1
- package/dist/challenge-store-D5pSY2S1.mjs.map +0 -1
- package/dist/content-CP-SeXNa.mjs.map +0 -1
- package/dist/content-refresh-DLOfIhYc.mjs.map +0 -1
- package/dist/context-BR5hRWiK.mjs.map +0 -1
- package/dist/dialect-helpers-BSbfaO3F.mjs.map +0 -1
- package/dist/errors-n2j49uNf.mjs.map +0 -1
- package/dist/index-DWbJrsAg.d.mts.map +0 -1
- package/dist/loader-ZsjE4paL.mjs.map +0 -1
- package/dist/manifest-schema-CUYPfCEH.mjs.map +0 -1
- package/dist/media-BjwNuLEu.mjs.map +0 -1
- package/dist/media-D6SeAfBl.mjs.map +0 -1
- package/dist/media-url-DH7giMx_.mjs.map +0 -1
- package/dist/menus-CNg0QlDt.mjs.map +0 -1
- package/dist/normalize-CSxdKBVa.mjs.map +0 -1
- package/dist/object-cache-71tPfV4A.mjs.map +0 -1
- package/dist/options-BHPeIbBd.mjs.map +0 -1
- package/dist/options-BhZIeFY1.d.mts.map +0 -1
- package/dist/query-D18vTdha.mjs.map +0 -1
- package/dist/redirect-CZkbozu9.mjs.map +0 -1
- package/dist/redirects-CRIM55KH.mjs.map +0 -1
- package/dist/registry-BiO5WwPq.mjs +0 -2716
- package/dist/registry-BiO5WwPq.mjs.map +0 -1
- package/dist/registry-Cx-jEJOS.mjs.map +0 -1
- package/dist/relations-BTPM2saV.mjs.map +0 -1
- package/dist/relations-C7B46bcU.d.mts.map +0 -1
- package/dist/resolve-DxUpTMmE.mjs.map +0 -1
- package/dist/runner-77GOZCnH.mjs.map +0 -1
- package/dist/runner-zgqA_CqP.d.mts.map +0 -1
- package/dist/seo-BSiTIXzd.mjs.map +0 -1
- package/dist/settings-BgN-0DT-.mjs.map +0 -1
- package/dist/snapshot-DSB8P7Lm.mjs.map +0 -1
- package/dist/ssrf-DqebVE34.mjs.map +0 -1
- package/dist/taxonomies-CPGxo-bn.mjs.map +0 -1
- package/dist/taxonomies-kmyudNGP.mjs.map +0 -1
- package/dist/types-75KIqzL9.mjs.map +0 -1
- package/dist/types-Br-ERaxh.d.mts.map +0 -1
- package/dist/types-D6OcIp2P.mjs +0 -3
- package/dist/types-DHxzBjbD.d.mts.map +0 -1
- package/dist/types-DJQxln7q.d.mts.map +0 -1
- package/dist/types-D_DWe7k9.d.mts.map +0 -1
- package/dist/types-Vg6f5i3s.d.mts.map +0 -1
- package/dist/validate-Dd-IUjnZ.mjs.map +0 -1
- package/dist/validate-DlqdOZXB.d.mts.map +0 -1
- package/dist/version-ri-sCyAp.mjs +0 -7
- package/dist/widgets-CpmZd9Q-.mjs.map +0 -1
- package/dist/zod-generator-DylzusHh.mjs.map +0 -1
- /package/dist/{api-tokens-B5NHLNUN.mjs → api-tokens-B_lfpmH3.mjs} +0 -0
- /package/dist/{ssrf-BPKzkm6O.mjs → ssrf-TQhaljuI.mjs} +0 -0
package/src/security/ssrf.ts
CHANGED
|
@@ -1,69 +1,94 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SSRF protection for
|
|
2
|
+
* SSRF protection for outbound HTTP requests.
|
|
3
3
|
*
|
|
4
|
-
* Validates that URLs
|
|
5
|
-
* Applied before any fetch() call in the import pipeline.
|
|
4
|
+
* Validates that URLs do not target non-public network addresses.
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
|
-
const IPV4_MAPPED_IPV6_DOTTED_PATTERN = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i;
|
|
9
|
-
const IPV4_MAPPED_IPV6_HEX_PATTERN = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
10
|
-
const IPV4_TRANSLATED_HEX_PATTERN = /^::ffff:0:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
11
|
-
const IPV6_EXPANDED_MAPPED_PATTERN =
|
|
12
|
-
/^0{0,4}:0{0,4}:0{0,4}:0{0,4}:0{0,4}:ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* IPv4-compatible (deprecated) addresses: ::XXXX:XXXX
|
|
16
|
-
*
|
|
17
|
-
* The WHATWG URL parser normalizes [::127.0.0.1] to [::7f00:1] (no ffff prefix).
|
|
18
|
-
* These are deprecated but still parsed, and bypass the ffff-based checks.
|
|
19
|
-
*/
|
|
20
|
-
const IPV4_COMPATIBLE_HEX_PATTERN = /^::([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* NAT64 prefix (RFC 6052): 64:ff9b::XXXX:XXXX
|
|
24
|
-
*
|
|
25
|
-
* Used by NAT64 gateways to embed IPv4 addresses in IPv6.
|
|
26
|
-
* [64:ff9b::127.0.0.1] normalizes to [64:ff9b::7f00:1].
|
|
27
|
-
*/
|
|
28
|
-
const NAT64_HEX_PATTERN = /^64:ff9b::([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
29
|
-
|
|
30
7
|
const IPV6_BRACKET_PATTERN = /^\[|\]$/g;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const IPV6_ULA_FC_PATTERN = /^fc[0-9a-f]{2}:/;
|
|
34
|
-
const IPV6_ULA_FD_PATTERN = /^fd[0-9a-f]{2}:/;
|
|
8
|
+
const IPV4_PART_PATTERN = /^(?:0|[1-9]\d{0,2})$/;
|
|
9
|
+
const IPV6_PART_PATTERN = /^[0-9a-f]{1,4}$/i;
|
|
35
10
|
|
|
36
11
|
/** Strip trailing dots from an FQDN-form hostname ("localhost." -> "localhost"). */
|
|
37
12
|
const TRAILING_DOT_PATTERN = /\.+$/;
|
|
38
13
|
|
|
39
14
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* Includes:
|
|
43
|
-
* - Loopback (127.0.0.0/8)
|
|
44
|
-
* - Private (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
|
|
45
|
-
* - Link-local (169.254.0.0/16)
|
|
46
|
-
* - Cloud metadata (169.254.169.254 — AWS/GCP/Azure)
|
|
47
|
-
* - IPv6 loopback and link-local
|
|
15
|
+
* IPv4 ranges that are not globally reachable unicast destinations.
|
|
48
16
|
*/
|
|
49
17
|
const BLOCKED_PATTERNS: Array<{ start: number; end: number }> = [
|
|
50
|
-
//
|
|
51
|
-
{ start: ip4ToNum(
|
|
52
|
-
//
|
|
18
|
+
// Current network
|
|
19
|
+
{ start: ip4ToNum(0, 0, 0, 0), end: ip4ToNum(0, 255, 255, 255) },
|
|
20
|
+
// Private use
|
|
53
21
|
{ start: ip4ToNum(10, 0, 0, 0), end: ip4ToNum(10, 255, 255, 255) },
|
|
54
|
-
//
|
|
22
|
+
// Shared address space
|
|
23
|
+
{ start: ip4ToNum(100, 64, 0, 0), end: ip4ToNum(100, 127, 255, 255) },
|
|
24
|
+
// Loopback
|
|
25
|
+
{ start: ip4ToNum(127, 0, 0, 0), end: ip4ToNum(127, 255, 255, 255) },
|
|
26
|
+
// Link-local, including common cloud metadata endpoints
|
|
27
|
+
{ start: ip4ToNum(169, 254, 0, 0), end: ip4ToNum(169, 254, 255, 255) },
|
|
28
|
+
// Private use
|
|
55
29
|
{ start: ip4ToNum(172, 16, 0, 0), end: ip4ToNum(172, 31, 255, 255) },
|
|
56
|
-
//
|
|
30
|
+
// IETF protocol assignments. Globally reachable exceptions are handled below.
|
|
31
|
+
{ start: ip4ToNum(192, 0, 0, 0), end: ip4ToNum(192, 0, 0, 255) },
|
|
32
|
+
// Documentation
|
|
33
|
+
{ start: ip4ToNum(192, 0, 2, 0), end: ip4ToNum(192, 0, 2, 255) },
|
|
34
|
+
// Deprecated 6to4 relay anycast
|
|
35
|
+
{ start: ip4ToNum(192, 88, 99, 0), end: ip4ToNum(192, 88, 99, 255) },
|
|
36
|
+
// Private use
|
|
57
37
|
{ start: ip4ToNum(192, 168, 0, 0), end: ip4ToNum(192, 168, 255, 255) },
|
|
58
|
-
//
|
|
59
|
-
{ start: ip4ToNum(
|
|
60
|
-
//
|
|
61
|
-
{ start: ip4ToNum(
|
|
38
|
+
// Benchmarking
|
|
39
|
+
{ start: ip4ToNum(198, 18, 0, 0), end: ip4ToNum(198, 19, 255, 255) },
|
|
40
|
+
// Documentation
|
|
41
|
+
{ start: ip4ToNum(198, 51, 100, 0), end: ip4ToNum(198, 51, 100, 255) },
|
|
42
|
+
{ start: ip4ToNum(203, 0, 113, 0), end: ip4ToNum(203, 0, 113, 255) },
|
|
43
|
+
// Multicast, reserved, and limited broadcast
|
|
44
|
+
{ start: ip4ToNum(224, 0, 0, 0), end: ip4ToNum(255, 255, 255, 255) },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const ALLOWED_IPV4_EXCEPTIONS = new Set([ip4ToNum(192, 0, 0, 9), ip4ToNum(192, 0, 0, 10)]);
|
|
48
|
+
|
|
49
|
+
interface Ipv6Range {
|
|
50
|
+
address: number[];
|
|
51
|
+
prefixLength: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ipv6Range(address: string, prefixLength: number): Ipv6Range {
|
|
55
|
+
const parsed = parseIpv6(address);
|
|
56
|
+
if (parsed === null) throw new Error(`Invalid IPv6 range: ${address}/${prefixLength}`);
|
|
57
|
+
return { address: parsed, prefixLength };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const IPV6_GLOBAL_UNICAST_RANGE = ipv6Range("2000::", 3);
|
|
61
|
+
const IPV4_COMPATIBLE_IPV6_RANGE = ipv6Range("::", 96);
|
|
62
|
+
const IPV4_EMBEDDED_IPV6_RANGES: Ipv6Range[] = [
|
|
63
|
+
IPV4_COMPATIBLE_IPV6_RANGE,
|
|
64
|
+
ipv6Range("::ffff:0:0", 96),
|
|
65
|
+
ipv6Range("::ffff:0:0:0", 96),
|
|
66
|
+
ipv6Range("64:ff9b::", 96),
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
/** Globally reachable allocations inside the otherwise reserved 2001::/23 block. */
|
|
70
|
+
const ALLOWED_IPV6_SPECIAL_RANGES: Ipv6Range[] = [
|
|
71
|
+
ipv6Range("2001:1::1", 128),
|
|
72
|
+
ipv6Range("2001:1::2", 128),
|
|
73
|
+
ipv6Range("2001:1::3", 128),
|
|
74
|
+
ipv6Range("2001:3::", 32),
|
|
75
|
+
ipv6Range("2001:4:112::", 48),
|
|
76
|
+
ipv6Range("2001:20::", 28),
|
|
77
|
+
ipv6Range("2001:30::", 28),
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
/** Non-global allocations inside the ordinary IPv6 global-unicast range. */
|
|
81
|
+
const BLOCKED_IPV6_GLOBAL_UNICAST_RANGES: Ipv6Range[] = [
|
|
82
|
+
ipv6Range("2001::", 23),
|
|
83
|
+
ipv6Range("2001:db8::", 32),
|
|
84
|
+
ipv6Range("2002::", 16),
|
|
85
|
+
ipv6Range("3ffe::", 16),
|
|
86
|
+
ipv6Range("3fff::", 20),
|
|
62
87
|
];
|
|
63
88
|
|
|
64
89
|
// Bracket-stripped form is used for lookups (validateExternalUrl strips
|
|
65
90
|
// brackets from parsed.hostname before checking), so "::1" appears here
|
|
66
|
-
// without brackets. The "::1" case is already covered by
|
|
91
|
+
// without brackets. The "::1" case is already covered by isNonPublicIp, but
|
|
67
92
|
// keeping it here makes the intent explicit and gives a clearer error
|
|
68
93
|
// message for the common `http://[::1]/` form.
|
|
69
94
|
const BLOCKED_HOSTNAMES = new Set([
|
|
@@ -101,80 +126,78 @@ function parseIpv4(ip: string): number | null {
|
|
|
101
126
|
const parts = ip.split(".");
|
|
102
127
|
if (parts.length !== 4) return null;
|
|
103
128
|
|
|
104
|
-
const nums = parts.map(Number);
|
|
105
|
-
if (nums.some((n) =>
|
|
129
|
+
const nums = parts.map((part) => (IPV4_PART_PATTERN.test(part) ? Number(part) : Number.NaN));
|
|
130
|
+
if (nums.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) return null;
|
|
106
131
|
|
|
107
132
|
return ip4ToNum(nums[0], nums[1], nums[2], nums[3]);
|
|
108
133
|
}
|
|
109
134
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
*/
|
|
119
|
-
export function normalizeIPv6MappedToIPv4(ip: string): string | null {
|
|
120
|
-
// Match hex-form IPv4-mapped IPv6: ::ffff:XXXX:XXXX
|
|
121
|
-
let match = ip.match(IPV4_MAPPED_IPV6_HEX_PATTERN);
|
|
122
|
-
if (!match) {
|
|
123
|
-
// Match IPv4-translated (RFC 6052): ::ffff:0:XXXX:XXXX
|
|
124
|
-
match = ip.match(IPV4_TRANSLATED_HEX_PATTERN);
|
|
125
|
-
}
|
|
126
|
-
if (!match) {
|
|
127
|
-
// Match fully expanded form: 0000:0000:0000:0000:0000:ffff:XXXX:XXXX
|
|
128
|
-
match = ip.match(IPV6_EXPANDED_MAPPED_PATTERN);
|
|
129
|
-
}
|
|
130
|
-
if (!match) {
|
|
131
|
-
// Match IPv4-compatible (deprecated) form: ::XXXX:XXXX (no ffff prefix)
|
|
132
|
-
match = ip.match(IPV4_COMPATIBLE_HEX_PATTERN);
|
|
133
|
-
}
|
|
134
|
-
if (!match) {
|
|
135
|
-
// Match NAT64 prefix (RFC 6052): 64:ff9b::XXXX:XXXX
|
|
136
|
-
match = ip.match(NAT64_HEX_PATTERN);
|
|
135
|
+
function parseIpv6(ip: string): number[] | null {
|
|
136
|
+
let address = ip;
|
|
137
|
+
if (address.includes(".")) {
|
|
138
|
+
const separator = address.lastIndexOf(":");
|
|
139
|
+
if (separator === -1) return null;
|
|
140
|
+
const ipv4 = parseIpv4(address.slice(separator + 1));
|
|
141
|
+
if (ipv4 === null) return null;
|
|
142
|
+
address = `${address.slice(0, separator + 1)}${(ipv4 >>> 16).toString(16)}:${(ipv4 & 0xffff).toString(16)}`;
|
|
137
143
|
}
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
if (address.includes(":::") || address.split("::").length > 2) return null;
|
|
145
|
+
|
|
146
|
+
const [before = "", after = ""] = address.split("::");
|
|
147
|
+
const head = before === "" ? [] : before.split(":");
|
|
148
|
+
const tail = after === "" ? [] : after.split(":");
|
|
149
|
+
const parts = [...head, ...tail];
|
|
150
|
+
if (parts.some((part) => !IPV6_PART_PATTERN.test(part)) || parts.length > 8) return null;
|
|
151
|
+
if (address.includes("::") ? parts.length >= 8 : parts.length !== 8) return null;
|
|
152
|
+
|
|
153
|
+
const zeroCount = address.includes("::") ? 8 - parts.length : 0;
|
|
154
|
+
return [...head, ...Array.from<string>({ length: zeroCount }).fill("0"), ...tail].map((part) =>
|
|
155
|
+
Number.parseInt(part, 16),
|
|
156
|
+
);
|
|
144
157
|
}
|
|
145
158
|
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const normalized = ip.toLowerCase();
|
|
151
|
-
|
|
152
|
-
// Handle IPv6 loopback
|
|
153
|
-
if (normalized === "::1" || normalized === "::ffff:127.0.0.1") return true;
|
|
154
|
-
|
|
155
|
-
// Handle IPv4-mapped IPv6 in hex form (WHATWG URL parser normalizes to this)
|
|
156
|
-
// e.g. ::ffff:7f00:1 -> 127.0.0.1, ::ffff:a9fe:a9fe -> 169.254.169.254
|
|
157
|
-
const hexIpv4 = normalizeIPv6MappedToIPv4(normalized);
|
|
158
|
-
if (hexIpv4) return isPrivateIp(hexIpv4);
|
|
159
|
-
|
|
160
|
-
// Handle IPv4-mapped IPv6 in dotted-decimal form
|
|
161
|
-
const v4Match = normalized.match(IPV4_MAPPED_IPV6_DOTTED_PATTERN);
|
|
162
|
-
const ipv4 = v4Match ? v4Match[1] : normalized;
|
|
163
|
-
|
|
164
|
-
const num = parseIpv4(ipv4);
|
|
165
|
-
if (num === null) {
|
|
166
|
-
// If we can't parse it, block IPv6 addresses that look internal.
|
|
167
|
-
// fc00::/7 is Unique Local (first byte 0xfc or 0xfd), fe80::/10 is
|
|
168
|
-
// link-local. Only match when followed by hex digit + colon to avoid
|
|
169
|
-
// collisions with hypothetical non-address strings.
|
|
170
|
-
return (
|
|
171
|
-
normalized.startsWith("fe80:") ||
|
|
172
|
-
IPV6_ULA_FC_PATTERN.test(normalized) ||
|
|
173
|
-
IPV6_ULA_FD_PATTERN.test(normalized)
|
|
174
|
-
);
|
|
159
|
+
function isIpv6InRange(address: number[], range: Ipv6Range): boolean {
|
|
160
|
+
const completeParts = Math.floor(range.prefixLength / 16);
|
|
161
|
+
for (let i = 0; i < completeParts; i++) {
|
|
162
|
+
if (address[i] !== range.address[i]) return false;
|
|
175
163
|
}
|
|
176
164
|
|
|
177
|
-
|
|
165
|
+
const remainingBits = range.prefixLength % 16;
|
|
166
|
+
if (remainingBits === 0) return true;
|
|
167
|
+
const mask = (0xffff << (16 - remainingBits)) & 0xffff;
|
|
168
|
+
return (address[completeParts] & mask) === (range.address[completeParts] & mask);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function extractEmbeddedIpv4(address: number[]): number | null {
|
|
172
|
+
if (!IPV4_EMBEDDED_IPV6_RANGES.some((range) => isIpv6InRange(address, range))) return null;
|
|
173
|
+
const ipv4 = ((address[6] << 16) | address[7]) >>> 0;
|
|
174
|
+
// The unspecified and loopback addresses retain their native IPv6 meaning.
|
|
175
|
+
if (ipv4 <= 1 && isIpv6InRange(address, IPV4_COMPATIBLE_IPV6_RANGE)) return null;
|
|
176
|
+
return ipv4;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Convert a hex-form IPv6 address with an embedded IPv4 destination to dotted decimal. */
|
|
180
|
+
export function normalizeIPv6MappedToIPv4(ip: string): string | null {
|
|
181
|
+
if (ip.includes(".")) return null;
|
|
182
|
+
const address = parseIpv6(ip);
|
|
183
|
+
if (address === null) return null;
|
|
184
|
+
const ipv4 = extractEmbeddedIpv4(address);
|
|
185
|
+
if (ipv4 === null) return null;
|
|
186
|
+
return `${ipv4 >>> 24}.${(ipv4 >>> 16) & 0xff}.${(ipv4 >>> 8) & 0xff}.${ipv4 & 0xff}`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function isNonPublicIp(ip: string): boolean {
|
|
190
|
+
const parsedIpv4 = parseIpv4(ip);
|
|
191
|
+
const ipv6 = parsedIpv4 === null ? parseIpv6(ip) : null;
|
|
192
|
+
const ipv4 = ipv6 === null ? parsedIpv4 : extractEmbeddedIpv4(ipv6);
|
|
193
|
+
if (ipv4 !== null) {
|
|
194
|
+
if (ALLOWED_IPV4_EXCEPTIONS.has(ipv4)) return false;
|
|
195
|
+
return BLOCKED_PATTERNS.some((range) => ipv4 >= range.start && ipv4 <= range.end);
|
|
196
|
+
}
|
|
197
|
+
if (ipv6 === null) return true;
|
|
198
|
+
if (ALLOWED_IPV6_SPECIAL_RANGES.some((range) => isIpv6InRange(ipv6, range))) return false;
|
|
199
|
+
if (!isIpv6InRange(ipv6, IPV6_GLOBAL_UNICAST_RANGE)) return true;
|
|
200
|
+
return BLOCKED_IPV6_GLOBAL_UNICAST_RANGES.some((range) => isIpv6InRange(ipv6, range));
|
|
178
201
|
}
|
|
179
202
|
|
|
180
203
|
/**
|
|
@@ -190,17 +213,15 @@ export class SsrfError extends Error {
|
|
|
190
213
|
}
|
|
191
214
|
|
|
192
215
|
/**
|
|
193
|
-
* Validate
|
|
216
|
+
* Validate a URL's scheme, hostname, and literal address.
|
|
194
217
|
*
|
|
195
218
|
* Checks:
|
|
196
219
|
* 1. URL is well-formed with http/https scheme
|
|
197
220
|
* 2. Hostname is not a known internal name (localhost, metadata endpoints)
|
|
198
|
-
* 3. If hostname is an IP literal, it
|
|
221
|
+
* 3. If hostname is an IP literal, it is a public address
|
|
199
222
|
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* before connecting, which needs a custom fetch implementation. This covers
|
|
203
|
-
* the most common SSRF vectors.
|
|
223
|
+
* Hostnames also need DNS validation before dispatch. Resolving and checking
|
|
224
|
+
* addresses does not bind an ordinary fetch() connection to those addresses.
|
|
204
225
|
*
|
|
205
226
|
* @throws SsrfError if the URL targets an internal address
|
|
206
227
|
*/
|
|
@@ -241,11 +262,11 @@ export function validateExternalUrl(url: string): URL {
|
|
|
241
262
|
}
|
|
242
263
|
}
|
|
243
264
|
|
|
244
|
-
// Check if hostname is
|
|
265
|
+
// Check if hostname is a non-public IP address. Use the
|
|
245
266
|
// normalized form so "127.0.0.1.." and friends don't bypass parseIpv4
|
|
246
267
|
// (which rejects extra trailing dots).
|
|
247
|
-
if (
|
|
248
|
-
throw new SsrfError("URLs targeting
|
|
268
|
+
if (isIpLiteral(normalizedHost) && isNonPublicIp(normalizedHost)) {
|
|
269
|
+
throw new SsrfError("URLs targeting non-public IP addresses are not allowed");
|
|
249
270
|
}
|
|
250
271
|
|
|
251
272
|
return parsed;
|
|
@@ -283,6 +304,7 @@ const DOH_TIMEOUT_MS = 3000;
|
|
|
283
304
|
const DEFAULT_DOH_URL = "https://cloudflare-dns.com/dns-query";
|
|
284
305
|
|
|
285
306
|
interface DohAnswer {
|
|
307
|
+
type: number;
|
|
286
308
|
data: string;
|
|
287
309
|
}
|
|
288
310
|
|
|
@@ -307,8 +329,14 @@ function parseDohResponse(raw: unknown): DohResponse {
|
|
|
307
329
|
const answers: DohAnswer[] = [];
|
|
308
330
|
if (hasProperty(raw, "Answer") && Array.isArray(raw.Answer)) {
|
|
309
331
|
for (const entry of raw.Answer) {
|
|
310
|
-
if (
|
|
311
|
-
|
|
332
|
+
if (
|
|
333
|
+
hasProperty(entry, "type") &&
|
|
334
|
+
typeof entry.type === "number" &&
|
|
335
|
+
Number.isInteger(entry.type) &&
|
|
336
|
+
hasProperty(entry, "data") &&
|
|
337
|
+
typeof entry.data === "string"
|
|
338
|
+
) {
|
|
339
|
+
answers.push({ type: entry.type, data: entry.data });
|
|
312
340
|
}
|
|
313
341
|
}
|
|
314
342
|
}
|
|
@@ -324,6 +352,7 @@ function parseDohResponse(raw: unknown): DohResponse {
|
|
|
324
352
|
*/
|
|
325
353
|
export const cloudflareDohResolver: DnsResolver = async (hostname) => {
|
|
326
354
|
async function query(type: "A" | "AAAA"): Promise<string[]> {
|
|
355
|
+
const expectedAnswerType = type === "A" ? 1 : 28;
|
|
327
356
|
const params = new URLSearchParams({ name: hostname, type });
|
|
328
357
|
const controller = new AbortController();
|
|
329
358
|
const timeout = setTimeout(() => controller.abort(), DOH_TIMEOUT_MS);
|
|
@@ -347,8 +376,10 @@ export const cloudflareDohResolver: DnsResolver = async (hostname) => {
|
|
|
347
376
|
}
|
|
348
377
|
// DoH Answer arrays often include CNAME records alongside A/AAAA
|
|
349
378
|
// records. Their `data` is a hostname, not an IP. Filter to just
|
|
350
|
-
// IP literals
|
|
351
|
-
return body.Answer.
|
|
379
|
+
// IP literals of the requested record type.
|
|
380
|
+
return body.Answer.filter((answer) => answer.type === expectedAnswerType)
|
|
381
|
+
.map((answer) => answer.data)
|
|
382
|
+
.filter(isIpLiteral);
|
|
352
383
|
} finally {
|
|
353
384
|
clearTimeout(timeout);
|
|
354
385
|
}
|
|
@@ -359,14 +390,12 @@ export const cloudflareDohResolver: DnsResolver = async (hostname) => {
|
|
|
359
390
|
};
|
|
360
391
|
|
|
361
392
|
/**
|
|
362
|
-
* Validate a URL and
|
|
363
|
-
*
|
|
364
|
-
* attacker-controlled domains that publicly resolve to private addresses,
|
|
365
|
-
* and wildcard DNS services like nip.io used by exploit tooling.
|
|
393
|
+
* Validate a URL and reject hostnames that resolve to non-public addresses,
|
|
394
|
+
* including wildcard DNS services like nip.io used by exploit tooling.
|
|
366
395
|
*
|
|
367
396
|
* Runs `validateExternalUrl` first for cheap pre-flight checks (scheme,
|
|
368
397
|
* literal IP, known-bad hostnames). Then resolves the hostname and rejects
|
|
369
|
-
* if ANY returned address is
|
|
398
|
+
* if ANY returned address is non-public.
|
|
370
399
|
*
|
|
371
400
|
* Fails closed: if resolution fails or returns no records, throws SsrfError.
|
|
372
401
|
*
|
|
@@ -381,9 +410,9 @@ export const cloudflareDohResolver: DnsResolver = async (hostname) => {
|
|
|
381
410
|
* - Host-file overrides or split-horizon corporate DNS on self-hosted Node.
|
|
382
411
|
* - Attacker-controlled rebinding services the caller has allowlisted.
|
|
383
412
|
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
413
|
+
* Connections must use the addresses from resolveAndValidateExternalUrlTarget
|
|
414
|
+
* to avoid a second lookup. Callers using ordinary fetch() need network-level
|
|
415
|
+
* egress controls to prevent these attacks.
|
|
387
416
|
*/
|
|
388
417
|
export async function resolveAndValidateExternalUrl(
|
|
389
418
|
url: string,
|
|
@@ -411,7 +440,7 @@ export async function resolveAndValidateExternalUrlTarget(
|
|
|
411
440
|
const hostname = parsed.hostname.replace(IPV6_BRACKET_PATTERN, "");
|
|
412
441
|
|
|
413
442
|
// If the hostname is already an IP literal, validateExternalUrl has
|
|
414
|
-
// already checked it against the
|
|
443
|
+
// already checked it against the non-public ranges. Skip DNS.
|
|
415
444
|
if (isIpLiteral(hostname)) {
|
|
416
445
|
return { url: parsed, addresses: [hostname] };
|
|
417
446
|
}
|
|
@@ -435,20 +464,17 @@ export async function resolveAndValidateExternalUrlTarget(
|
|
|
435
464
|
if (!isIpLiteral(ip)) {
|
|
436
465
|
throw new SsrfError("Hostname resolver returned a non-IP address");
|
|
437
466
|
}
|
|
438
|
-
if (
|
|
439
|
-
throw new SsrfError("Hostname resolves to a
|
|
467
|
+
if (isNonPublicIp(ip)) {
|
|
468
|
+
throw new SsrfError("Hostname resolves to a non-public IP address");
|
|
440
469
|
}
|
|
441
470
|
}
|
|
442
471
|
|
|
443
472
|
return { url: parsed, addresses };
|
|
444
473
|
}
|
|
445
474
|
|
|
446
|
-
/** True when a string
|
|
475
|
+
/** True when a string is a valid IPv4 or IPv6 literal. */
|
|
447
476
|
function isIpLiteral(host: string): boolean {
|
|
448
|
-
|
|
449
|
-
// Very loose IPv6 heuristic — matches anything with a colon, which is
|
|
450
|
-
// never valid in DNS hostnames, so this is safe.
|
|
451
|
-
return host.includes(":");
|
|
477
|
+
return parseIpv4(host) !== null || parseIpv6(host) !== null;
|
|
452
478
|
}
|
|
453
479
|
|
|
454
480
|
/**
|
|
@@ -467,13 +493,16 @@ const CREDENTIAL_HEADERS = ["authorization", "cookie", "proxy-authorization"];
|
|
|
467
493
|
export async function ssrfSafeFetch(
|
|
468
494
|
url: string,
|
|
469
495
|
init?: RequestInit,
|
|
470
|
-
options?: { resolver?: DnsResolver },
|
|
496
|
+
options?: { resolver?: DnsResolver; httpsOnly?: boolean },
|
|
471
497
|
): Promise<Response> {
|
|
472
498
|
let currentUrl = url;
|
|
473
499
|
let currentInit = init;
|
|
474
500
|
|
|
475
501
|
for (let i = 0; i <= MAX_REDIRECTS; i++) {
|
|
476
|
-
await resolveAndValidateExternalUrl(currentUrl, options);
|
|
502
|
+
const validated = await resolveAndValidateExternalUrl(currentUrl, options);
|
|
503
|
+
if (options?.httpsOnly === true && validated.protocol !== "https:") {
|
|
504
|
+
throw new SsrfError("Only HTTPS URLs are allowed");
|
|
505
|
+
}
|
|
477
506
|
|
|
478
507
|
const response = await globalThis.fetch(currentUrl, {
|
|
479
508
|
...currentInit,
|
package/src/seed/apply.ts
CHANGED
|
@@ -199,7 +199,9 @@ export async function applySeed(
|
|
|
199
199
|
routable: collection.routable,
|
|
200
200
|
hidden: collection.hidden,
|
|
201
201
|
sortOrder: collection.sortOrder,
|
|
202
|
+
group: collection.group,
|
|
202
203
|
commentsEnabled: collection.commentsEnabled,
|
|
204
|
+
editLocking: collection.editLocking,
|
|
203
205
|
});
|
|
204
206
|
result.collections.updated++;
|
|
205
207
|
|
|
@@ -277,7 +279,9 @@ export async function applySeed(
|
|
|
277
279
|
routable: collection.routable,
|
|
278
280
|
hidden: collection.hidden,
|
|
279
281
|
sortOrder: collection.sortOrder,
|
|
282
|
+
group: collection.group,
|
|
280
283
|
commentsEnabled: collection.commentsEnabled,
|
|
284
|
+
editLocking: collection.editLocking,
|
|
281
285
|
},
|
|
282
286
|
fields,
|
|
283
287
|
);
|
package/src/seed/types.ts
CHANGED
|
@@ -78,8 +78,9 @@ export interface SeedCollection {
|
|
|
78
78
|
/** Require a slug before an entry can be published. Defaults to true. */
|
|
79
79
|
routable?: boolean;
|
|
80
80
|
/**
|
|
81
|
-
* Omit this collection from the admin sidebar
|
|
82
|
-
* the API, MCP, plugin hooks, and
|
|
81
|
+
* Omit this collection from the admin sidebar and the dashboard quick
|
|
82
|
+
* actions. It stays reachable through the API, MCP, plugin hooks, and
|
|
83
|
+
* direct `/content/:collection` URLs.
|
|
83
84
|
*/
|
|
84
85
|
hidden?: boolean;
|
|
85
86
|
/**
|
|
@@ -87,8 +88,12 @@ export interface SeedCollection {
|
|
|
87
88
|
* a `sortOrder` keep the alphabetical order and follow the ordered ones.
|
|
88
89
|
*/
|
|
89
90
|
sortOrder?: number;
|
|
91
|
+
/** Admin sidebar folder shared with other collections of the same group. */
|
|
92
|
+
group?: string;
|
|
90
93
|
/** Enable comments on this collection */
|
|
91
94
|
commentsEnabled?: boolean;
|
|
95
|
+
/** Take an edit lock when an entry is opened (defaults to true) */
|
|
96
|
+
editLocking?: boolean;
|
|
92
97
|
/** Field slug powering the admin list Title column (defaults to title display) */
|
|
93
98
|
titleField?: string;
|
|
94
99
|
/** Field slug (a datetime field) powering the admin list Date column (defaults to last-updated) */
|
package/src/seed/validate.ts
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { getI18nConfig, resolveConfiguredLocale } from "../i18n/config.js";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
FIELD_TYPES,
|
|
10
|
+
isIndexableFieldType,
|
|
11
|
+
MAX_COLLECTION_GROUP_LENGTH,
|
|
12
|
+
MAX_COLLECTION_LIST_COLUMNS,
|
|
13
|
+
} from "../schema/types.js";
|
|
9
14
|
import type { SeedFile, SeedMenuItem, ValidationResult } from "./types.js";
|
|
10
15
|
|
|
11
16
|
const COLLECTION_FIELD_SLUG_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
@@ -107,9 +112,21 @@ export function validateSeed(data: unknown): ValidationResult {
|
|
|
107
112
|
if (!collection.label) {
|
|
108
113
|
errors.push(`${prefix}: label is required`);
|
|
109
114
|
}
|
|
115
|
+
if (collection.editLocking !== undefined && typeof collection.editLocking !== "boolean") {
|
|
116
|
+
errors.push(`${prefix}.editLocking: must be a boolean`);
|
|
117
|
+
}
|
|
110
118
|
if (collection.routable !== undefined && typeof collection.routable !== "boolean") {
|
|
111
119
|
errors.push(`${prefix}.routable: must be a boolean`);
|
|
112
120
|
}
|
|
121
|
+
if (collection.group !== undefined) {
|
|
122
|
+
if (typeof collection.group !== "string") {
|
|
123
|
+
errors.push(`${prefix}.group: must be a string`);
|
|
124
|
+
} else if (collection.group.trim().length > MAX_COLLECTION_GROUP_LENGTH) {
|
|
125
|
+
errors.push(
|
|
126
|
+
`${prefix}.group: must be at most ${MAX_COLLECTION_GROUP_LENGTH} characters`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
113
130
|
|
|
114
131
|
const declaredFieldSlugs = new Set(
|
|
115
132
|
Array.isArray(collection.fields)
|
package/src/seo/hreflang.ts
CHANGED
|
@@ -167,6 +167,7 @@ export async function getHreflangAlternatesWithDb(
|
|
|
167
167
|
collection,
|
|
168
168
|
slug: variant.slug || variant.id,
|
|
169
169
|
id: variant.id,
|
|
170
|
+
date: variant.publishedAt,
|
|
170
171
|
});
|
|
171
172
|
const localized = await localizePath(path, locale);
|
|
172
173
|
if (localized === null) continue;
|
package/src/seo/index.ts
CHANGED
|
@@ -30,13 +30,12 @@
|
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
32
|
import type { ContentSeo } from "../database/repositories/types.js";
|
|
33
|
-
import { buildSeoImageUrl } from "./media-url.js";
|
|
33
|
+
import { buildSeoImageUrl, resolveSeoCanonicalUrl } from "./media-url.js";
|
|
34
34
|
|
|
35
35
|
export { getHreflangAlternates, getHreflangAlternatesWithDb } from "./hreflang.js";
|
|
36
36
|
export type { HreflangAlternate, HreflangOptions } from "./hreflang.js";
|
|
37
37
|
|
|
38
38
|
const TRAILING_SLASH_RE = /\/$/;
|
|
39
|
-
const ABSOLUTE_URL_RE = /^https?:\/\//i;
|
|
40
39
|
|
|
41
40
|
/**
|
|
42
41
|
* Content input for SEO functions.
|
|
@@ -138,16 +137,12 @@ export function getSeoMeta<T>(content: SeoContentInput<T>, options: SeoMetaOptio
|
|
|
138
137
|
// OG image: SEO image > default
|
|
139
138
|
const ogImage = seo.image ? buildSeoImageUrl(seo.image, siteUrl) : (defaultOgImage ?? null);
|
|
140
139
|
|
|
141
|
-
// Canonical: explicit > path-based > null
|
|
140
|
+
// Canonical: explicit > path-based > null. The explicit value goes
|
|
141
|
+
// through the same resolver as the <EmDashHead> overlay, so a panel
|
|
142
|
+
// canonical renders identically on both paths.
|
|
142
143
|
let canonical: string | null = null;
|
|
143
144
|
if (seo.canonical) {
|
|
144
|
-
|
|
145
|
-
// produce "https://example.composts/x" when joined with siteUrl
|
|
146
|
-
if (siteUrl && !seo.canonical.startsWith("/") && !ABSOLUTE_URL_RE.test(seo.canonical)) {
|
|
147
|
-
canonical = `${siteUrl.replace(TRAILING_SLASH_RE, "")}/${seo.canonical}`;
|
|
148
|
-
} else {
|
|
149
|
-
canonical = seo.canonical;
|
|
150
|
-
}
|
|
145
|
+
canonical = resolveSeoCanonicalUrl(seo.canonical, siteUrl);
|
|
151
146
|
} else if (siteUrl && path) {
|
|
152
147
|
const safePath = path.startsWith("/") ? path : `/${path}`;
|
|
153
148
|
canonical = `${siteUrl.replace(TRAILING_SLASH_RE, "")}${safePath}`;
|
package/src/seo/media-url.ts
CHANGED
|
@@ -20,6 +20,12 @@ export function buildSeoImageUrl(imageRef: string, siteUrl?: string): string {
|
|
|
20
20
|
return imageRef;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
// `//host/path` is protocol-relative — already qualified, not a path
|
|
24
|
+
// to prefix with the site URL.
|
|
25
|
+
if (imageRef.startsWith("//")) {
|
|
26
|
+
return imageRef;
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
// Root-relative path (already includes the media API prefix). Without
|
|
24
30
|
// this branch we'd re-prefix and produce a doubled path that 404s.
|
|
25
31
|
if (imageRef.startsWith("/")) {
|
|
@@ -30,3 +36,23 @@ export function buildSeoImageUrl(imageRef: string, siteUrl?: string): string {
|
|
|
30
36
|
const mediaPath = `/_emdash/api/media/file/${imageRef}`;
|
|
31
37
|
return siteUrl ? `${siteUrl.replace(TRAILING_SLASH_RE, "")}${mediaPath}` : mediaPath;
|
|
32
38
|
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a stored SEO canonical value to a URL.
|
|
42
|
+
*
|
|
43
|
+
* The SEO panel accepts absolute URLs, root-relative paths, and bare
|
|
44
|
+
* relative paths. Relative paths are joined with `siteUrl` (adding a
|
|
45
|
+
* leading slash when missing, so we never produce
|
|
46
|
+
* `https://example.composts/x`). Without a `siteUrl` the value is
|
|
47
|
+
* returned as-is. Absolute output matters here: the resolved value feeds
|
|
48
|
+
* `<link rel="canonical">` and `og:url`, both of which search engines and
|
|
49
|
+
* scrapers expect fully qualified.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveSeoCanonicalUrl(canonical: string, siteUrl?: string): string {
|
|
52
|
+
// `//host/path` is protocol-relative — already qualified, not a path.
|
|
53
|
+
if (!siteUrl || ABSOLUTE_URL_RE.test(canonical) || canonical.startsWith("//")) {
|
|
54
|
+
return canonical;
|
|
55
|
+
}
|
|
56
|
+
const path = canonical.startsWith("/") ? canonical : `/${canonical}`;
|
|
57
|
+
return `${siteUrl.replace(TRAILING_SLASH_RE, "")}${path}`;
|
|
58
|
+
}
|
package/src/settings/index.ts
CHANGED
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
import type { Kysely } from "kysely";
|
|
9
9
|
|
|
10
10
|
import { after } from "../after.js";
|
|
11
|
+
import { siteSettingsTag } from "../cache/chrome-tags.js";
|
|
11
12
|
import { MediaRepository } from "../database/repositories/media.js";
|
|
12
13
|
import { OptionsRepository } from "../database/repositories/options.js";
|
|
13
14
|
import type { Database } from "../database/types.js";
|
|
14
15
|
import { getDb } from "../loader.js";
|
|
15
16
|
import { cachedQuery, invalidateObjectCache } from "../object-cache/index.js";
|
|
17
|
+
import type { CacheHint } from "../query.js";
|
|
16
18
|
import { peekRequestCache, requestCached } from "../request-cache.js";
|
|
17
19
|
|
|
18
20
|
/** Object-cache namespace for site settings. */
|
|
@@ -236,6 +238,20 @@ export function getSiteSettings(): Promise<Partial<SiteSettings>> {
|
|
|
236
238
|
);
|
|
237
239
|
}
|
|
238
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Get all site settings with a Workers edge-cache hint.
|
|
243
|
+
*
|
|
244
|
+
* Use the returned `cacheHint` with `Astro.cache.set()` so pages that render
|
|
245
|
+
* settings can be purged automatically when site settings change.
|
|
246
|
+
*/
|
|
247
|
+
export async function getSiteSettingsWithCacheHint(): Promise<{
|
|
248
|
+
data: Partial<SiteSettings>;
|
|
249
|
+
cacheHint: CacheHint;
|
|
250
|
+
}> {
|
|
251
|
+
const data = await getSiteSettings();
|
|
252
|
+
return { data, cacheHint: { tags: [siteSettingsTag()] } };
|
|
253
|
+
}
|
|
254
|
+
|
|
239
255
|
/**
|
|
240
256
|
* Get all site settings (with explicit db)
|
|
241
257
|
*
|
package/src/storage/local.ts
CHANGED
|
@@ -70,6 +70,7 @@ export class LocalStorage implements Storage {
|
|
|
70
70
|
key: string;
|
|
71
71
|
body: Buffer | Uint8Array | ReadableStream<Uint8Array>;
|
|
72
72
|
contentType: string;
|
|
73
|
+
cacheControl?: string;
|
|
73
74
|
}): Promise<UploadResult> {
|
|
74
75
|
try {
|
|
75
76
|
const filePath = this.getFilePath(options.key);
|