emdash 0.28.1 → 0.29.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/{adapters-hUy8vOB-.d.mts → adapters-DPAkL6QF.d.mts} +1 -1
- package/dist/{adapters-hUy8vOB-.d.mts.map → adapters-DPAkL6QF.d.mts.map} +1 -1
- package/dist/{allowed-origins-CRsJ6BPM.mjs → allowed-origins-FXB-FplB.mjs} +2 -2
- package/dist/{allowed-origins-CRsJ6BPM.mjs.map → allowed-origins-FXB-FplB.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +22 -21
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +4 -4
- package/dist/{api-DxFSorgk.mjs → api-DVbHNApo.mjs} +75 -23
- package/dist/api-DVbHNApo.mjs.map +1 -0
- package/dist/{api-tokens-DvqeZmVq.mjs → api-tokens-UYBkl17d.mjs} +2 -2
- package/dist/{api-tokens-DvqeZmVq.mjs.map → api-tokens-UYBkl17d.mjs.map} +1 -1
- package/dist/{apply-CDJqIjPU.mjs → apply-D23iUV4q.mjs} +20 -20
- package/dist/{apply-CDJqIjPU.mjs.map → apply-D23iUV4q.mjs.map} +1 -1
- package/dist/astro/index.d.mts +13 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +10 -5
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +11 -10
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +8 -8
- package/dist/astro/middleware/redirect.mjs +7 -7
- package/dist/astro/middleware/request-context.d.mts +3 -0
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +257 -30
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +2 -2
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +125 -79
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +13 -13
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/bulk.mjs +10 -10
- package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/index.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/comments/index.mjs +10 -10
- package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
- package/dist/astro/routes/api/admin/media-usage/repair.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/repair.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +28 -0
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -0
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +43 -41
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +43 -41
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +42 -40
- 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 +42 -40
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +43 -41
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +43 -41
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +42 -40
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +42 -40
- 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 +4 -4
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +42 -40
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
- package/dist/astro/routes/api/admin/users/index.mjs +7 -7
- package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -7
- package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
- package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
- package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
- package/dist/astro/routes/api/auth/logout.mjs +4 -4
- package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -11
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
- package/dist/astro/routes/api/auth/me.mjs +8 -8
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs.map +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
- package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
- package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
- package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
- package/dist/astro/routes/api/auth/signup/request.mjs +11 -11
- package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +69 -14
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +13 -13
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +12 -12
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +9 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +71 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.d.mts +8 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +50 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
- package/dist/astro/routes/api/dashboard.mjs +8 -8
- package/dist/astro/routes/api/dev/emails.mjs +4 -4
- 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 +5 -5
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +12 -11
- package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
- package/dist/astro/routes/api/import/wordpress/media.d.mts +11 -10
- package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +12 -16
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +11 -11
- 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/callback.mjs +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +12 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +28 -28
- package/dist/astro/routes/api/manifest.mjs +6 -6
- package/dist/astro/routes/api/mcp.mjs +56 -47
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +9 -9
- package/dist/astro/routes/api/media/_id_.mjs +8 -8
- package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
- package/dist/astro/routes/api/media/providers/index.mjs +4 -4
- package/dist/astro/routes/api/media/upload-url.mjs +10 -10
- package/dist/astro/routes/api/media.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_/items.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_.mjs +9 -9
- package/dist/astro/routes/api/menus/index.mjs +9 -9
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
- package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
- package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
- package/dist/astro/routes/api/oauth/register.mjs +4 -4
- package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
- package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
- package/dist/astro/routes/api/oauth/token.mjs +7 -7
- package/dist/astro/routes/api/openapi.json.mjs +24 -5
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
- package/dist/astro/routes/api/redirects/404s/index.mjs +12 -12
- package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -12
- package/dist/astro/routes/api/redirects/_id_.mjs +13 -13
- package/dist/astro/routes/api/redirects/index.mjs +13 -13
- package/dist/astro/routes/api/relations/_id_/index.d.mts +10 -0
- package/dist/astro/routes/api/relations/_id_/index.d.mts.map +1 -0
- package/dist/astro/routes/api/relations/_id_/index.mjs +69 -0
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -0
- package/dist/astro/routes/api/relations/_id_/translations.d.mts +8 -0
- package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +1 -0
- package/dist/astro/routes/api/relations/_id_/translations.mjs +34 -0
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -0
- package/dist/astro/routes/api/relations/index.d.mts +9 -0
- package/dist/astro/routes/api/relations/index.d.mts.map +1 -0
- package/dist/astro/routes/api/relations/index.mjs +53 -0
- package/dist/astro/routes/api/relations/index.mjs.map +1 -0
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.d.mts.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +42 -40
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.d.mts.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +42 -40
- 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 +42 -40
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +42 -40
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +42 -40
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +9 -9
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +42 -40
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +42 -40
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +12 -12
- package/dist/astro/routes/api/search/index.mjs +13 -12
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +12 -12
- package/dist/astro/routes/api/search/stats.mjs +8 -8
- package/dist/astro/routes/api/search/suggest.mjs +11 -11
- package/dist/astro/routes/api/sections/_slug_.mjs +11 -11
- package/dist/astro/routes/api/sections/index.mjs +11 -11
- package/dist/astro/routes/api/settings/email.mjs +6 -6
- package/dist/astro/routes/api/settings.mjs +15 -15
- package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
- package/dist/astro/routes/api/setup/admin.mjs +12 -12
- package/dist/astro/routes/api/setup/dev-bypass.mjs +29 -29
- package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
- package/dist/astro/routes/api/setup/index.mjs +30 -30
- package/dist/astro/routes/api/setup/status.mjs +5 -5
- package/dist/astro/routes/api/snapshot.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +15 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +15 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +15 -15
- package/dist/astro/routes/api/taxonomies/index.mjs +15 -15
- package/dist/astro/routes/api/themes/preview.mjs +7 -7
- package/dist/astro/routes/api/typegen.mjs +6 -6
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +12 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +12 -12
- package/dist/astro/routes/api/widget-areas/_name_.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/index.mjs +12 -12
- package/dist/astro/routes/api/widget-components.mjs +4 -4
- package/dist/astro/routes/robots.txt.mjs +9 -9
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +12 -12
- package/dist/astro/routes/sitemap.xml.mjs +10 -10
- package/dist/astro/types.d.mts +16 -13
- 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-Dz88F_Fw.mjs → authorize-BmCwQCib.mjs} +2 -2
- package/dist/{authorize-Dz88F_Fw.mjs.map → authorize-BmCwQCib.mjs.map} +1 -1
- package/dist/{base64-CmWvODNW.mjs → base64-C74Msx8h.mjs} +1 -1
- package/dist/{base64-CmWvODNW.mjs.map → base64-C74Msx8h.mjs.map} +1 -1
- package/dist/{byline-Bm8ZgUP9.mjs → byline-BWb5H-65.mjs} +8 -8
- package/dist/{byline-Bm8ZgUP9.mjs.map → byline-BWb5H-65.mjs.map} +1 -1
- package/dist/{byline-fields-CIx_GuN4.mjs → byline-fields-DO6bAYK8.mjs} +2 -2
- package/dist/{byline-fields-CIx_GuN4.mjs.map → byline-fields-DO6bAYK8.mjs.map} +1 -1
- package/dist/{byline-registry-BOjqDOim.mjs → byline-registry-BCuOp4UF.mjs} +3 -3
- package/dist/{byline-registry-BOjqDOim.mjs.map → byline-registry-BCuOp4UF.mjs.map} +1 -1
- package/dist/{bylines-6tm9mgQb.mjs → bylines-BGuKFaBy.mjs} +4 -4
- package/dist/{bylines-6tm9mgQb.mjs.map → bylines-BGuKFaBy.mjs.map} +1 -1
- package/dist/{bylines-CAZxGSrm.mjs → bylines-CHojDMpj.mjs} +8 -8
- package/dist/{bylines-CAZxGSrm.mjs.map → bylines-CHojDMpj.mjs.map} +1 -1
- package/dist/{cache-CEBAZjir.mjs → cache-BeR7RfN8.mjs} +3 -3
- package/dist/{cache-CEBAZjir.mjs.map → cache-BeR7RfN8.mjs.map} +1 -1
- package/dist/{challenge-store-anhwVER0.mjs → challenge-store-B426wQ6O.mjs} +1 -1
- package/dist/{challenge-store-anhwVER0.mjs.map → challenge-store-B426wQ6O.mjs.map} +1 -1
- package/dist/{chunks-B2isWQhr.mjs → chunks-BU5_nrAC.mjs} +2 -2
- package/dist/{chunks-B2isWQhr.mjs.map → chunks-BU5_nrAC.mjs.map} +1 -1
- package/dist/cli/index.mjs +28 -28
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +34 -2
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +6 -2
- package/dist/client/index.mjs.map +1 -1
- package/dist/{comment-CzeatwBV.mjs → comment-SWh31kS0.mjs} +2 -2
- package/dist/{comment-CzeatwBV.mjs.map → comment-SWh31kS0.mjs.map} +1 -1
- package/dist/{comment-reaction-Cj9QJY7I.mjs → comment-reaction-DgcpziXI.mjs} +2 -2
- package/dist/{comment-reaction-Cj9QJY7I.mjs.map → comment-reaction-DgcpziXI.mjs.map} +1 -1
- package/dist/{comments-BLE-jv5k.mjs → comments-kZYGppMS.mjs} +3 -3
- package/dist/{comments-BLE-jv5k.mjs.map → comments-kZYGppMS.mjs.map} +1 -1
- package/dist/{components-B_sATNUc.mjs → components-CliOkZAs.mjs} +1 -1
- package/dist/{components-B_sATNUc.mjs.map → components-CliOkZAs.mjs.map} +1 -1
- package/dist/{content-DhgEth4k.mjs → content-BO61Sx4j.mjs} +179 -20
- package/dist/content-BO61Sx4j.mjs.map +1 -0
- package/dist/{content-refresh-Br4gMzh8.mjs → content-refresh-BkkApzeS.mjs} +8 -8
- package/dist/{content-refresh-Br4gMzh8.mjs.map → content-refresh-BkkApzeS.mjs.map} +1 -1
- package/dist/{context-BRIpHARC.mjs → context-DtSFYFuS.mjs} +71 -14
- package/dist/context-DtSFYFuS.mjs.map +1 -0
- package/dist/{cron-v4FTEFR_.mjs → cron-YFJ7uNVA.mjs} +1 -1
- package/dist/{cron-v4FTEFR_.mjs.map → cron-YFJ7uNVA.mjs.map} +1 -1
- package/dist/{dashboard-EvEKF5en.mjs → dashboard-xo_gPs_D.mjs} +6 -5
- package/dist/dashboard-xo_gPs_D.mjs.map +1 -0
- package/dist/database/pg-migration-lock.d.mts +21 -0
- package/dist/database/pg-migration-lock.d.mts.map +1 -0
- package/dist/database/pg-migration-lock.mjs +45 -0
- package/dist/database/pg-migration-lock.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/postgres.d.mts.map +1 -1
- package/dist/db/postgres.mjs +2 -8
- package/dist/db/postgres.mjs.map +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{db-errors-CK46D-ly.mjs → db-errors-BKuXh_fi.mjs} +1 -1
- package/dist/{db-errors-CK46D-ly.mjs.map → db-errors-BKuXh_fi.mjs.map} +1 -1
- package/dist/{default-CM_D83Mg.mjs → default-DY5ovGUG.mjs} +1 -1
- package/dist/{default-CM_D83Mg.mjs.map → default-DY5ovGUG.mjs.map} +1 -1
- package/dist/{device-flow-CfGP18Uw.mjs → device-flow-CPXQ_QfW.mjs} +5 -5
- package/dist/{device-flow-CfGP18Uw.mjs.map → device-flow-CPXQ_QfW.mjs.map} +1 -1
- package/dist/{dialect-helpers-DRI5pyY3.mjs → dialect-helpers-Cue7QQOR.mjs} +21 -2
- package/dist/dialect-helpers-Cue7QQOR.mjs.map +1 -0
- package/dist/{email-console-CIf4Lfvv.mjs → email-console-CjkQc7oY.mjs} +1 -1
- package/dist/{email-console-CIf4Lfvv.mjs.map → email-console-CjkQc7oY.mjs.map} +1 -1
- package/dist/{enrich-BQ0mxJRs.mjs → enrich-CFJJgxs_.mjs} +2 -2
- package/dist/{enrich-BQ0mxJRs.mjs.map → enrich-CFJJgxs_.mjs.map} +1 -1
- package/dist/{error-CkAseSqZ.mjs → error-CfJMLSkd.mjs} +12 -3
- package/dist/error-CfJMLSkd.mjs.map +1 -0
- package/dist/{escape-DqD0aCKu.mjs → escape-r8_GbEU2.mjs} +1 -1
- package/dist/{escape-DqD0aCKu.mjs.map → escape-r8_GbEU2.mjs.map} +1 -1
- package/dist/{field-defs-cache-WUI88LX5.mjs → field-defs-cache-BVrNCgSj.mjs} +5 -5
- package/dist/{field-defs-cache-WUI88LX5.mjs.map → field-defs-cache-BVrNCgSj.mjs.map} +1 -1
- package/dist/{fts-manager-BbFaF_V8.mjs → fts-manager-BD9s77qh.mjs} +27 -3
- package/dist/{fts-manager-BbFaF_V8.mjs.map → fts-manager-BD9s77qh.mjs.map} +1 -1
- package/dist/{hash-DrvzIXcz.mjs → hash-DFFrkivP.mjs} +1 -1
- package/dist/{hash-DrvzIXcz.mjs.map → hash-DFFrkivP.mjs.map} +1 -1
- package/dist/hreflang-CgIxhH4k.d.mts +48 -0
- package/dist/hreflang-CgIxhH4k.d.mts.map +1 -0
- package/dist/hreflang-pAWUiPd_.mjs +102 -0
- package/dist/hreflang-pAWUiPd_.mjs.map +1 -0
- package/dist/{import-fYLf14Co.mjs → import-2jHtLzsO.mjs} +6 -6
- package/dist/{import-fYLf14Co.mjs.map → import-2jHtLzsO.mjs.map} +1 -1
- package/dist/{index-B9sIxwe4.d.mts → index-BXOCyLj0.d.mts} +115 -21
- package/dist/index-BXOCyLj0.d.mts.map +1 -0
- package/dist/{index-Bm-Gy8Mh.d.mts → index-DxjWLKGT.d.mts} +3 -3
- package/dist/{index-Bm-Gy8Mh.d.mts.map → index-DxjWLKGT.d.mts.map} +1 -1
- package/dist/index.d.mts +20 -19
- package/dist/index.mjs +68 -64
- package/dist/{init-lock-6b309ZrF.mjs → init-lock-DJkX6Hto.mjs} +1 -1
- package/dist/{init-lock-6b309ZrF.mjs.map → init-lock-DJkX6Hto.mjs.map} +1 -1
- package/dist/{load-Djn3HWQS.mjs → load-DgoWMdRX.mjs} +2 -2
- package/dist/{load-Djn3HWQS.mjs.map → load-DgoWMdRX.mjs.map} +1 -1
- package/dist/{loader-CB6YHeul.mjs → loader-Rb8QlGZp.mjs} +5 -20
- package/dist/loader-Rb8QlGZp.mjs.map +1 -0
- package/dist/{manifest-schema-BHlgZM1W.mjs → manifest-schema-DeGNma2O.mjs} +3 -1
- package/dist/manifest-schema-DeGNma2O.mjs.map +1 -0
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +2 -2
- package/dist/media/local-runtime.d.mts +13 -12
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +8 -8
- package/dist/{media-BrXIaMFN.mjs → media-D2ZFowpn.mjs} +2 -2
- package/dist/media-D2ZFowpn.mjs.map +1 -0
- package/dist/{media-allowlist-CRHEeJ_i.mjs → media-allowlist-Dc05vKtt.mjs} +2 -2
- package/dist/{media-allowlist-CRHEeJ_i.mjs.map → media-allowlist-Dc05vKtt.mjs.map} +1 -1
- package/dist/{media-url-CKi5XSw4.mjs → media-url-DgIEYZr4.mjs} +1 -1
- package/dist/{media-url-CKi5XSw4.mjs.map → media-url-DgIEYZr4.mjs.map} +1 -1
- package/dist/media-usage-B__v9NMm.mjs +421 -0
- package/dist/media-usage-B__v9NMm.mjs.map +1 -0
- package/dist/{menus-Cfivc2Ad.mjs → menus-BpfevlJD.mjs} +3 -3
- package/dist/{menus-Cfivc2Ad.mjs.map → menus-BpfevlJD.mjs.map} +1 -1
- package/dist/{menus-b2T4clbO.mjs → menus-BtvH7Z7t.mjs} +31 -12
- package/dist/menus-BtvH7Z7t.mjs.map +1 -0
- package/dist/{mime-CCEzze7W.mjs → mime-DfIVjNkr.mjs} +1 -1
- package/dist/{mime-CCEzze7W.mjs.map → mime-DfIVjNkr.mjs.map} +1 -1
- package/dist/{mode-BM9QgEmt.mjs → mode-BVnhGZ2o.mjs} +1 -1
- package/dist/{mode-BM9QgEmt.mjs.map → mode-BVnhGZ2o.mjs.map} +1 -1
- package/dist/{normalize-CeglrBT9.mjs → normalize-C-SHXmra.mjs} +1 -1
- package/dist/{normalize-CeglrBT9.mjs.map → normalize-C-SHXmra.mjs.map} +1 -1
- package/dist/{oauth-authorization-CXWkIGT4.mjs → oauth-authorization-BWqWTHBK.mjs} +5 -5
- package/dist/{oauth-authorization-CXWkIGT4.mjs.map → oauth-authorization-BWqWTHBK.mjs.map} +1 -1
- package/dist/{oauth-clients-BmTI5rsl.mjs → oauth-clients-43_XADoa.mjs} +1 -1
- package/dist/{oauth-clients-BmTI5rsl.mjs.map → oauth-clients-43_XADoa.mjs.map} +1 -1
- package/dist/{oauth-state-store-YLFLcH5F.mjs → oauth-state-store-BRSUEkmx.mjs} +1 -1
- package/dist/{oauth-state-store-YLFLcH5F.mjs.map → oauth-state-store-BRSUEkmx.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-Bsc_GsX-.mjs → oauth-user-lookup-Ctgemb0k.mjs} +1 -1
- package/dist/{oauth-user-lookup-Bsc_GsX-.mjs.map → oauth-user-lookup-Ctgemb0k.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{options-DTTML-Tx.mjs → options-BlmBHTvX.mjs} +1 -1
- package/dist/{options-DTTML-Tx.mjs.map → options-BlmBHTvX.mjs.map} +1 -1
- package/dist/{options-iMpRRxIe.d.mts → options-COXGTtqd.d.mts} +3 -3
- package/dist/{options-iMpRRxIe.d.mts.map → options-COXGTtqd.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-GmjecGct.mjs → parse-GLksnn-B.mjs} +2 -2
- package/dist/{parse-GmjecGct.mjs.map → parse-GLksnn-B.mjs.map} +1 -1
- package/dist/{passkey-config-De0ahnRg.mjs → passkey-config-CjA1UbDj.mjs} +1 -1
- package/dist/{passkey-config-De0ahnRg.mjs.map → passkey-config-CjA1UbDj.mjs.map} +1 -1
- package/dist/{patterns-BKmjvM7K.mjs → patterns-CiyXeDgr.mjs} +1 -1
- package/dist/{patterns-BKmjvM7K.mjs.map → patterns-CiyXeDgr.mjs.map} +1 -1
- package/dist/{placeholder-BSKwzRe4.d.mts → placeholder-DR-eeZr-.d.mts} +1 -1
- package/dist/{placeholder-BSKwzRe4.d.mts.map → placeholder-DR-eeZr-.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +1 -1
- package/dist/plugin-utils.d.mts +11 -10
- package/dist/plugin-utils.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +11 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
- package/dist/{portable-text-cCa0cGV6.mjs → portable-text-BAkgEKcv.mjs} +1 -1
- package/dist/{portable-text-cCa0cGV6.mjs.map → portable-text-BAkgEKcv.mjs.map} +1 -1
- package/dist/{preview-SSXNVPAC.mjs → preview-Rloa09Wp.mjs} +2 -2
- package/dist/{preview-SSXNVPAC.mjs.map → preview-Rloa09Wp.mjs.map} +1 -1
- package/dist/{public-url-Danv47cS.mjs → public-url-C0cEvrRu.mjs} +1 -1
- package/dist/{public-url-Danv47cS.mjs.map → public-url-C0cEvrRu.mjs.map} +1 -1
- package/dist/{schema-CX9cfNkZ.mjs → query-BxT95opY.mjs} +5 -10
- package/dist/query-BxT95opY.mjs.map +1 -0
- package/dist/{query-1Cp6U9oo.mjs → query-ZzvXyxWq.mjs} +15 -15
- package/dist/query-ZzvXyxWq.mjs.map +1 -0
- package/dist/{rate-limit-C_Lf63Dd.mjs → rate-limit-Cg4Rvc_-.mjs} +2 -2
- package/dist/{rate-limit-C_Lf63Dd.mjs.map → rate-limit-Cg4Rvc_-.mjs.map} +1 -1
- package/dist/{redirect-CoW3G-0U.mjs → redirect-Ce_6Yb6z.mjs} +1 -1
- package/dist/{redirect-CoW3G-0U.mjs.map → redirect-Ce_6Yb6z.mjs.map} +1 -1
- package/dist/{redirect-IyfNirgS.mjs → redirect-Ch3E98qZ.mjs} +4 -4
- package/dist/{redirect-IyfNirgS.mjs.map → redirect-Ch3E98qZ.mjs.map} +1 -1
- package/dist/{redirects-Bs1g42Ri.mjs → redirects-CXmVGRNZ.mjs} +6 -6
- package/dist/{redirects-Bs1g42Ri.mjs.map → redirects-CXmVGRNZ.mjs.map} +1 -1
- package/dist/{redirects-DXEXBAII.mjs → redirects-CeD7K7EX.mjs} +43 -5
- package/dist/redirects-CeD7K7EX.mjs.map +1 -0
- package/dist/{registry-B57vp_X9.mjs → registry-CyIXPi4E.mjs} +8 -8
- package/dist/{registry-B57vp_X9.mjs.map → registry-CyIXPi4E.mjs.map} +1 -1
- package/dist/relation-Ba68Tm4Z.mjs +334 -0
- package/dist/relation-Ba68Tm4Z.mjs.map +1 -0
- package/dist/{byline-fields-2Lp5Hbgf.mjs → relations-BmBmX4Eb.mjs} +60 -4
- package/dist/relations-BmBmX4Eb.mjs.map +1 -0
- package/dist/relations-C8hVyEy0.mjs +397 -0
- package/dist/relations-C8hVyEy0.mjs.map +1 -0
- package/dist/{byline-fields-CHE8UStY.d.mts → relations-CbBpoOys.d.mts} +182 -29
- package/dist/relations-CbBpoOys.d.mts.map +1 -0
- package/dist/{request-cache-KCNHp_RJ.mjs → request-cache-BSUptuJR.mjs} +1 -1
- package/dist/{request-cache-KCNHp_RJ.mjs.map → request-cache-BSUptuJR.mjs.map} +1 -1
- package/dist/{request-meta-DbvXaAvU.mjs → request-meta-DCwktC5P.mjs} +2 -2
- package/dist/{request-meta-DbvXaAvU.mjs.map → request-meta-DCwktC5P.mjs.map} +1 -1
- package/dist/{resolve-DR3wqMTy.mjs → resolve-Cd9dzclN.mjs} +1 -1
- package/dist/{resolve-DR3wqMTy.mjs.map → resolve-Cd9dzclN.mjs.map} +1 -1
- package/dist/{runner-DvFWoz8-.d.mts → runner-CiNdIk3y.d.mts} +8 -2
- package/dist/runner-CiNdIk3y.d.mts.map +1 -0
- package/dist/{runner-K8XK101B.mjs → runner-jt65bF7F.mjs} +24 -7
- package/dist/{runner-K8XK101B.mjs.map → runner-jt65bF7F.mjs.map} +1 -1
- package/dist/runtime.d.mts +12 -11
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +4 -4
- package/dist/{scheduled-publish-Drffrf2a.d.mts → scheduled-publish-DlJHGcuL.d.mts} +1 -1
- package/dist/scheduled-publish-DlJHGcuL.d.mts.map +1 -0
- package/dist/schema-DwjufZ1S.mjs +9 -0
- package/dist/schema-DwjufZ1S.mjs.map +1 -0
- package/dist/{search-DZN2HZ-V.mjs → search-Cl875CVE.mjs} +62 -12
- package/dist/search-Cl875CVE.mjs.map +1 -0
- package/dist/{secrets-kp760LlD.mjs → secrets-CO_bEmII.mjs} +4 -4
- package/dist/{secrets-kp760LlD.mjs.map → secrets-CO_bEmII.mjs.map} +1 -1
- package/dist/{sections-CpF5SaGr.mjs → sections-DTKzgoiS.mjs} +3 -3
- package/dist/{sections-CpF5SaGr.mjs.map → sections-DTKzgoiS.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +23 -23
- package/dist/seo/index.d.mts +4 -2
- package/dist/seo/index.d.mts.map +1 -1
- package/dist/seo/index.mjs +19 -2
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-DXu2UQnC.mjs → seo-BLm6SXzS.mjs} +2 -2
- package/dist/{seo-DXu2UQnC.mjs.map → seo-BLm6SXzS.mjs.map} +1 -1
- package/dist/{seo-89-53DDs.mjs → seo-BjrbXAd_.mjs} +1 -1
- package/dist/{seo-89-53DDs.mjs.map → seo-BjrbXAd_.mjs.map} +1 -1
- package/dist/{service-DQmiBMzt.mjs → service-D6zDmKXy.mjs} +3 -3
- package/dist/{service-DQmiBMzt.mjs.map → service-D6zDmKXy.mjs.map} +1 -1
- package/dist/{session-user-Cascbax7.mjs → session-user-DoSs6YM8.mjs} +1 -1
- package/dist/{session-user-Cascbax7.mjs.map → session-user-DoSs6YM8.mjs.map} +1 -1
- package/dist/{settings-zhmdKyJQ.mjs → settings-BuQYvLfy.mjs} +6 -6
- package/dist/{settings-zhmdKyJQ.mjs.map → settings-BuQYvLfy.mjs.map} +1 -1
- package/dist/{settings-rZyHEcNT.mjs → settings-CmS3TwXf.mjs} +3 -3
- package/dist/{settings-rZyHEcNT.mjs.map → settings-CmS3TwXf.mjs.map} +1 -1
- package/dist/{setup-complete-Cb3LRyzy.mjs → setup-complete-BPNgLHlU.mjs} +2 -2
- package/dist/{setup-complete-Cb3LRyzy.mjs.map → setup-complete-BPNgLHlU.mjs.map} +1 -1
- package/dist/{setup-nonce-Z8x0tHf8.mjs → setup-nonce-DEPZX96T.mjs} +1 -1
- package/dist/{setup-nonce-Z8x0tHf8.mjs.map → setup-nonce-DEPZX96T.mjs.map} +1 -1
- package/dist/{single-flight-cache-BG3B_GhN.mjs → single-flight-cache-DEtW-OEG.mjs} +2 -2
- package/dist/{single-flight-cache-BG3B_GhN.mjs.map → single-flight-cache-DEtW-OEG.mjs.map} +1 -1
- package/dist/{site-url-BBfDTgZB.mjs → site-url-CcLy5D5s.mjs} +2 -2
- package/dist/{site-url-BBfDTgZB.mjs.map → site-url-CcLy5D5s.mjs.map} +1 -1
- package/dist/{slugify-Cce3dTdg.mjs → slugify-C_tqlU4G.mjs} +1 -1
- package/dist/{slugify-Cce3dTdg.mjs.map → slugify-C_tqlU4G.mjs.map} +1 -1
- package/dist/{ssrf-1g7usGBg.mjs → ssrf-TrKYJAy0.mjs} +1 -1
- package/dist/{ssrf-1g7usGBg.mjs.map → ssrf-TrKYJAy0.mjs.map} +1 -1
- package/dist/{status-CqJQX1QN.mjs → status-D3Gy1Zc6.mjs} +1 -1
- package/dist/{status-CqJQX1QN.mjs.map → status-D3Gy1Zc6.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/{taxonomies-Bs13SN-F.mjs → taxonomies-ClS4RKaZ.mjs} +13 -9
- package/dist/taxonomies-ClS4RKaZ.mjs.map +1 -0
- package/dist/{taxonomies-kH9ABDUF.mjs → taxonomies-pUkuD6nj.mjs} +115 -36
- package/dist/taxonomies-pUkuD6nj.mjs.map +1 -0
- package/dist/{taxonomy-BxGxZZdu.mjs → taxonomy-BkxbUMSw.mjs} +12 -3
- package/dist/{taxonomy-BxGxZZdu.mjs.map → taxonomy-BkxbUMSw.mjs.map} +1 -1
- package/dist/{tokens-BGT0TUUo.mjs → tokens-BV6fgl5A.mjs} +2 -2
- package/dist/{tokens-BGT0TUUo.mjs.map → tokens-BV6fgl5A.mjs.map} +1 -1
- package/dist/{transaction-qfqpPVpu.mjs → transaction-D0FOsb3X.mjs} +1 -1
- package/dist/{transaction-qfqpPVpu.mjs.map → transaction-D0FOsb3X.mjs.map} +1 -1
- package/dist/{transport-DPefPMcz.mjs → transport-DTFhhPOg.mjs} +1 -1
- package/dist/{transport-DPefPMcz.mjs.map → transport-DTFhhPOg.mjs.map} +1 -1
- package/dist/{transport-BMDWHSgZ.d.mts → transport-DmlmzD2U.d.mts} +1 -1
- package/dist/{transport-BMDWHSgZ.d.mts.map → transport-DmlmzD2U.d.mts.map} +1 -1
- package/dist/{trusted-proxy-VTPRiX2s.mjs → trusted-proxy-CSgZVESw.mjs} +1 -1
- package/dist/{trusted-proxy-VTPRiX2s.mjs.map → trusted-proxy-CSgZVESw.mjs.map} +1 -1
- package/dist/{types-CgvhU-hF.d.mts → types-B6-N9cBB.d.mts} +1 -1
- package/dist/{types-CgvhU-hF.d.mts.map → types-B6-N9cBB.d.mts.map} +1 -1
- package/dist/{types-g_aFIdW0.d.mts → types-BCVuUPrL.d.mts} +1 -1
- package/dist/{types-g_aFIdW0.d.mts.map → types-BCVuUPrL.d.mts.map} +1 -1
- package/dist/{types-Jo3UYd6b.mjs → types-BNZsPL9z.mjs} +1 -1
- package/dist/{types-Jo3UYd6b.mjs.map → types-BNZsPL9z.mjs.map} +1 -1
- package/dist/{types-vgEWF18A.d.mts → types-B_pmP7Yq.d.mts} +1 -1
- package/dist/{types-vgEWF18A.d.mts.map → types-B_pmP7Yq.d.mts.map} +1 -1
- package/dist/{types-CuW0zWDA.mjs → types-Ch8pFMEm.mjs} +3 -3
- package/dist/{types-CuW0zWDA.mjs.map → types-Ch8pFMEm.mjs.map} +1 -1
- package/dist/{types-ea9sAPck.d.mts → types-Cm4Cz-8M.d.mts} +1 -1
- package/dist/{types-ea9sAPck.d.mts.map → types-Cm4Cz-8M.d.mts.map} +1 -1
- package/dist/{types-CGbYowGQ.d.mts → types-CtDVagM4.d.mts} +55 -3
- package/dist/types-CtDVagM4.d.mts.map +1 -0
- package/dist/{types-BcLUUbbR.d.mts → types-DLIrNtv5.d.mts} +11 -3
- package/dist/{types-BcLUUbbR.d.mts.map → types-DLIrNtv5.d.mts.map} +1 -1
- package/dist/{types-DmHk7vAt.d.mts → types-QnlQIyPE.d.mts} +1 -1
- package/dist/{types-DmHk7vAt.d.mts.map → types-QnlQIyPE.d.mts.map} +1 -1
- package/dist/{types-_HFLRzTn.d.mts → types-momGysZk.d.mts} +1 -1
- package/dist/{types-_HFLRzTn.d.mts.map → types-momGysZk.d.mts.map} +1 -1
- package/dist/{types-tM44hEcf.mjs → types-o7xo7VgH.mjs} +1 -1
- package/dist/{types-tM44hEcf.mjs.map → types-o7xo7VgH.mjs.map} +1 -1
- package/dist/{types-ClUkdbWb.d.mts → types-qljd1hsL.d.mts} +1 -1
- package/dist/{types-ClUkdbWb.d.mts.map → types-qljd1hsL.d.mts.map} +1 -1
- package/dist/{user-BjAOvU3Z.mjs → user-DTxX_Fha.mjs} +3 -3
- package/dist/{user-BjAOvU3Z.mjs.map → user-DTxX_Fha.mjs.map} +1 -1
- package/dist/{utils-BJXElxdw.mjs → utils-Cz8PVrl4.mjs} +3 -3
- package/dist/{utils-BJXElxdw.mjs.map → utils-Cz8PVrl4.mjs.map} +1 -1
- package/dist/{validate-Z1b86_3B.d.mts → validate-9jLuE301.d.mts} +5 -5
- package/dist/{validate-Z1b86_3B.d.mts.map → validate-9jLuE301.d.mts.map} +1 -1
- package/dist/{validate-CWSnKVIJ.mjs → validate-C3CpWlNt.mjs} +3 -3
- package/dist/{validate-CWSnKVIJ.mjs.map → validate-C3CpWlNt.mjs.map} +1 -1
- package/dist/{validation-0l8-RYj4.mjs → validation-DM2K_NJC.mjs} +10 -10
- package/dist/{validation-0l8-RYj4.mjs.map → validation-DM2K_NJC.mjs.map} +1 -1
- package/dist/version-BlIJvNAZ.mjs +7 -0
- package/dist/{version-qmeO1XZY.mjs.map → version-BlIJvNAZ.mjs.map} +1 -1
- package/dist/{widgets-hWcIicX8.mjs → widgets-B_X6_UXJ.mjs} +4 -4
- package/dist/{widgets-hWcIicX8.mjs.map → widgets-B_X6_UXJ.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-CNFcsNCr.mjs → wxr-taxonomies-oNJB2S81.mjs} +4 -4
- package/dist/{wxr-taxonomies-CNFcsNCr.mjs.map → wxr-taxonomies-oNJB2S81.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-0_uxSrmf.d.mts → wxr-taxonomies-tADW4KTa.d.mts} +1 -1
- package/dist/{wxr-taxonomies-0_uxSrmf.d.mts.map → wxr-taxonomies-tADW4KTa.d.mts.map} +1 -1
- package/dist/{zod-generator-CacrR-i8.mjs → zod-generator-CrfV79De.mjs} +3 -3
- package/dist/{zod-generator-CacrR-i8.mjs.map → zod-generator-CrfV79De.mjs.map} +1 -1
- package/package.json +11 -7
- package/src/api/errors.ts +11 -0
- package/src/api/handlers/content.ts +111 -1
- package/src/api/handlers/dashboard.ts +2 -0
- package/src/api/handlers/index.ts +6 -0
- package/src/api/handlers/media-usage.ts +80 -0
- package/src/api/handlers/relations.ts +474 -0
- package/src/api/handlers/taxonomies.ts +26 -4
- package/src/api/handlers/validate-media-fields.ts +1 -1
- package/src/api/openapi/document.ts +25 -0
- package/src/api/parse.ts +1 -1
- package/src/api/schemas/comments.ts +6 -0
- package/src/api/schemas/content.ts +8 -0
- package/src/api/schemas/index.ts +2 -0
- package/src/api/schemas/media-usage.ts +48 -0
- package/src/api/schemas/relations.ts +109 -0
- package/src/api/schemas/search.ts +1 -0
- package/src/astro/integration/index.ts +1 -0
- package/src/astro/integration/routes.ts +5 -0
- package/src/astro/integration/runtime.ts +24 -0
- package/src/astro/middleware/request-context.ts +162 -20
- package/src/astro/middleware.ts +22 -9
- package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -2
- package/src/astro/routes/api/admin/comments/index.ts +1 -2
- package/src/astro/routes/api/admin/media-usage/repair.ts +24 -0
- package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +1 -2
- package/src/astro/routes/api/auth/oauth/[provider].ts +1 -2
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +13 -0
- package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +97 -0
- package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/parents.ts +48 -0
- package/src/astro/routes/api/relations/[id]/index.ts +84 -0
- package/src/astro/routes/api/relations/[id]/translations.ts +33 -0
- package/src/astro/routes/api/relations/index.ts +56 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +1 -7
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +1 -2
- package/src/astro/routes/api/search/index.ts +2 -0
- package/src/astro/types.ts +2 -0
- package/src/cli/commands/export-seed.ts +1 -10
- package/src/client/index.ts +39 -0
- package/src/comments/service.ts +1 -1
- package/src/comments/turnstile.ts +64 -0
- package/src/components/BlockquoteGroup.astro +34 -0
- package/src/components/CommentForm.astro +12 -5
- package/src/components/EmDashHead.astro +27 -1
- package/src/components/InlinePortableTextEditor.tsx +34 -0
- package/src/components/PortableText.astro +7 -1
- package/src/components/index.ts +2 -0
- package/src/components/portable-text-blockquote-group.ts +68 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +32 -1
- package/src/database/dialect-helpers.ts +34 -0
- package/src/database/migrations/039_fix_fts5_triggers.ts +1 -1
- package/src/database/migrations/runner.ts +46 -6
- package/src/database/pg-migration-lock.ts +72 -0
- package/src/database/repositories/comment.ts +1 -1
- package/src/database/repositories/content.ts +172 -21
- package/src/database/repositories/media.ts +1 -1
- package/src/database/repositories/relation.ts +130 -5
- package/src/database/repositories/taxonomy.ts +9 -0
- package/src/database/repositories/types.ts +8 -0
- package/src/db/postgres.ts +5 -2
- package/src/emdash-runtime.ts +72 -4
- package/src/index.ts +6 -2
- package/src/loader.ts +1 -31
- package/src/mcp/server.ts +29 -3
- package/src/plugins/context.ts +85 -0
- package/src/plugins/define-plugin.ts +1 -0
- package/src/plugins/index.ts +4 -0
- package/src/plugins/manifest-schema.ts +2 -0
- package/src/plugins/types.ts +59 -0
- package/src/schema/byline-registry.ts +1 -1
- package/src/search/fts-manager.ts +34 -0
- package/src/search/match.ts +50 -0
- package/src/search/query.ts +94 -9
- package/src/seo/hreflang.ts +192 -0
- package/src/seo/index.ts +3 -0
- package/src/taxonomies/index.ts +62 -45
- package/src/taxonomies/term-counts.ts +117 -0
- package/src/virtual-modules.d.ts +1 -0
- package/src/visual-editing/editable.ts +41 -35
- package/src/visual-editing/toolbar-bootstrap.ts +120 -0
- package/src/visual-editing/toolbar.ts +46 -0
- package/dist/api-DxFSorgk.mjs.map +0 -1
- package/dist/byline-fields-2Lp5Hbgf.mjs.map +0 -1
- package/dist/byline-fields-CHE8UStY.d.mts.map +0 -1
- package/dist/content-DhgEth4k.mjs.map +0 -1
- package/dist/context-BRIpHARC.mjs.map +0 -1
- package/dist/dashboard-EvEKF5en.mjs.map +0 -1
- package/dist/dialect-helpers-DRI5pyY3.mjs.map +0 -1
- package/dist/error-CkAseSqZ.mjs.map +0 -1
- package/dist/index-B9sIxwe4.d.mts.map +0 -1
- package/dist/loader-CB6YHeul.mjs.map +0 -1
- package/dist/manifest-schema-BHlgZM1W.mjs.map +0 -1
- package/dist/media-BrXIaMFN.mjs.map +0 -1
- package/dist/menus-b2T4clbO.mjs.map +0 -1
- package/dist/query-1Cp6U9oo.mjs.map +0 -1
- package/dist/redirects-DXEXBAII.mjs.map +0 -1
- package/dist/runner-DvFWoz8-.d.mts.map +0 -1
- package/dist/scheduled-publish-Drffrf2a.d.mts.map +0 -1
- package/dist/schema-CX9cfNkZ.mjs.map +0 -1
- package/dist/search-DZN2HZ-V.mjs.map +0 -1
- package/dist/taxonomies-Bs13SN-F.mjs.map +0 -1
- package/dist/taxonomies-kH9ABDUF.mjs.map +0 -1
- package/dist/types-CGbYowGQ.d.mts.map +0 -1
- package/dist/version-qmeO1XZY.mjs +0 -7
- /package/dist/{api-tokens-DsvvCtdh.mjs → api-tokens-Dk2GrJMY.mjs} +0 -0
- /package/dist/{ssrf-CmuGgCq3.mjs → ssrf-B5DOv5E5.mjs} +0 -0
- /package/dist/{types-DROWRxYV.mjs → types-DeCZBZxn.mjs} +0 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
import { ContentRepository } from "../../database/repositories/content.js";
|
|
4
|
+
import {
|
|
5
|
+
RelationRepository,
|
|
6
|
+
type ContentReference,
|
|
7
|
+
type CreateRelationInput,
|
|
8
|
+
type Relation,
|
|
9
|
+
} from "../../database/repositories/relation.js";
|
|
10
|
+
import { InvalidCursorError } from "../../database/repositories/types.js";
|
|
11
|
+
import type { ContentItem } from "../../database/repositories/types.js";
|
|
12
|
+
import type { Database } from "../../database/types.js";
|
|
13
|
+
import { SchemaRegistry } from "../../schema/registry.js";
|
|
14
|
+
import type { ApiResult } from "../types.js";
|
|
15
|
+
|
|
16
|
+
/** Map an edge-read failure: a bad pagination cursor is a 400 client error,
|
|
17
|
+
* everything else is the generic 500-shaped reference-read error. */
|
|
18
|
+
function referencesGetError(error: unknown): ApiResult<never> {
|
|
19
|
+
if (error instanceof InvalidCursorError) {
|
|
20
|
+
return { success: false, error: { code: "INVALID_CURSOR", message: error.message } };
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
success: false,
|
|
24
|
+
error: { code: "REFERENCES_GET_ERROR", message: "Failed to get references" },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** True for SQLite UNIQUE / Postgres unique_violation messages (matches the
|
|
29
|
+
* fingerprint used in the content handlers). Narrow enough not to catch NOT
|
|
30
|
+
* NULL / CHECK violations whose messages also say "constraint". */
|
|
31
|
+
function isUniqueViolation(error: unknown): boolean {
|
|
32
|
+
const message = error instanceof Error ? error.message.toLowerCase() : "";
|
|
33
|
+
return message.includes("unique constraint failed") || message.includes("duplicate key");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function handleRelationCreate(
|
|
37
|
+
db: Kysely<Database>,
|
|
38
|
+
input: CreateRelationInput,
|
|
39
|
+
): Promise<ApiResult<{ relation: Relation }>> {
|
|
40
|
+
try {
|
|
41
|
+
const repo = new RelationRepository(db);
|
|
42
|
+
|
|
43
|
+
// Invariant: a relation must point at collections that exist. There is no
|
|
44
|
+
// SQL FK (group-linking precludes it), so a ghost collection would yield a
|
|
45
|
+
// structurally-valid-but-permanently-useless relation. Skip when
|
|
46
|
+
// `translationOf` is set — structural fields are then inherited from an
|
|
47
|
+
// already-validated source, and the input collections are ignored.
|
|
48
|
+
if (!input.translationOf) {
|
|
49
|
+
if (!input.parentCollection || !input.childCollection) {
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
error: {
|
|
53
|
+
code: "VALIDATION_ERROR",
|
|
54
|
+
message:
|
|
55
|
+
"parentCollection and childCollection are required unless translationOf is set",
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const registry = new SchemaRegistry(db);
|
|
60
|
+
for (const collection of [input.parentCollection, input.childCollection]) {
|
|
61
|
+
if (!(await registry.getCollection(collection))) {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
error: {
|
|
65
|
+
code: "COLLECTION_NOT_FOUND",
|
|
66
|
+
message: `Collection '${collection}' not found`,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const relation = await repo.create(input);
|
|
74
|
+
return { success: true, data: { relation } };
|
|
75
|
+
} catch (error) {
|
|
76
|
+
// A bad `translationOf` makes the repo throw loudly rather than mint an
|
|
77
|
+
// unlinked relation — surface it as 404, not a generic 500.
|
|
78
|
+
if (
|
|
79
|
+
error instanceof Error &&
|
|
80
|
+
error.message.includes("Source relation for translation not found")
|
|
81
|
+
) {
|
|
82
|
+
return {
|
|
83
|
+
success: false,
|
|
84
|
+
error: { code: "NOT_FOUND", message: "Source relation for translation not found" },
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// UNIQUE(name, locale) collision, or a second translation for an
|
|
88
|
+
// already-present (translation_group, locale) — both are client conflicts.
|
|
89
|
+
if (isUniqueViolation(error)) {
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
error: {
|
|
93
|
+
code: "CONFLICT",
|
|
94
|
+
message: "A relation with this name or locale already exists",
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
error: { code: "RELATION_CREATE_ERROR", message: "Failed to create relation" },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function handleRelationGet(
|
|
106
|
+
db: Kysely<Database>,
|
|
107
|
+
id: string,
|
|
108
|
+
): Promise<ApiResult<{ relation: Relation }>> {
|
|
109
|
+
try {
|
|
110
|
+
const repo = new RelationRepository(db);
|
|
111
|
+
const relation = await repo.findById(id);
|
|
112
|
+
if (!relation) {
|
|
113
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Relation not found" } };
|
|
114
|
+
}
|
|
115
|
+
return { success: true, data: { relation } };
|
|
116
|
+
} catch {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
error: { code: "RELATION_GET_ERROR", message: "Failed to get relation" },
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function handleRelationList(
|
|
125
|
+
db: Kysely<Database>,
|
|
126
|
+
opts: { locale?: string },
|
|
127
|
+
): Promise<ApiResult<{ relations: Relation[] }>> {
|
|
128
|
+
try {
|
|
129
|
+
const repo = new RelationRepository(db);
|
|
130
|
+
const relations = await repo.list(opts.locale);
|
|
131
|
+
return { success: true, data: { relations } };
|
|
132
|
+
} catch {
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
error: { code: "RELATION_LIST_ERROR", message: "Failed to list relations" },
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function handleRelationUpdate(
|
|
141
|
+
db: Kysely<Database>,
|
|
142
|
+
id: string,
|
|
143
|
+
input: { parentLabel?: string; childLabel?: string },
|
|
144
|
+
): Promise<ApiResult<{ relation: Relation }>> {
|
|
145
|
+
try {
|
|
146
|
+
const repo = new RelationRepository(db);
|
|
147
|
+
const relation = await repo.update(id, input);
|
|
148
|
+
if (!relation) {
|
|
149
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Relation not found" } };
|
|
150
|
+
}
|
|
151
|
+
return { success: true, data: { relation } };
|
|
152
|
+
} catch {
|
|
153
|
+
return {
|
|
154
|
+
success: false,
|
|
155
|
+
error: { code: "RELATION_UPDATE_ERROR", message: "Failed to update relation" },
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export async function handleRelationDelete(
|
|
161
|
+
db: Kysely<Database>,
|
|
162
|
+
id: string,
|
|
163
|
+
): Promise<ApiResult<{ deleted: true }>> {
|
|
164
|
+
try {
|
|
165
|
+
const repo = new RelationRepository(db);
|
|
166
|
+
const deleted = await repo.delete(id);
|
|
167
|
+
if (!deleted) {
|
|
168
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Relation not found" } };
|
|
169
|
+
}
|
|
170
|
+
return { success: true, data: { deleted: true } };
|
|
171
|
+
} catch {
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
error: { code: "RELATION_DELETE_ERROR", message: "Failed to delete relation" },
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export async function handleRelationTranslations(
|
|
180
|
+
db: Kysely<Database>,
|
|
181
|
+
id: string,
|
|
182
|
+
): Promise<
|
|
183
|
+
ApiResult<{
|
|
184
|
+
translationGroup: string;
|
|
185
|
+
translations: {
|
|
186
|
+
id: string;
|
|
187
|
+
name: string;
|
|
188
|
+
locale: string;
|
|
189
|
+
parentLabel: string;
|
|
190
|
+
childLabel: string;
|
|
191
|
+
}[];
|
|
192
|
+
}>
|
|
193
|
+
> {
|
|
194
|
+
try {
|
|
195
|
+
const repo = new RelationRepository(db);
|
|
196
|
+
const relation = await repo.findById(id);
|
|
197
|
+
if (!relation) {
|
|
198
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Relation not found" } };
|
|
199
|
+
}
|
|
200
|
+
const siblings = await repo.findTranslations(relation.translationGroup);
|
|
201
|
+
return {
|
|
202
|
+
success: true,
|
|
203
|
+
data: {
|
|
204
|
+
translationGroup: relation.translationGroup,
|
|
205
|
+
translations: siblings.map((r) => ({
|
|
206
|
+
id: r.id,
|
|
207
|
+
name: r.name,
|
|
208
|
+
locale: r.locale,
|
|
209
|
+
parentLabel: r.parentLabel,
|
|
210
|
+
childLabel: r.childLabel,
|
|
211
|
+
})),
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
} catch {
|
|
215
|
+
return {
|
|
216
|
+
success: false,
|
|
217
|
+
error: { code: "RELATION_TRANSLATIONS_ERROR", message: "Failed to get translations" },
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export type EntryRef = {
|
|
223
|
+
id: string;
|
|
224
|
+
slug: string | null;
|
|
225
|
+
collection: string;
|
|
226
|
+
/** The actual locale of the resolved variant — see `pickVariant`. */
|
|
227
|
+
locale: string | null;
|
|
228
|
+
sortOrder?: number;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/** Resolve a relation from an id OR its translation_group. */
|
|
232
|
+
async function resolveRelation(
|
|
233
|
+
repo: RelationRepository,
|
|
234
|
+
idOrGroup: string,
|
|
235
|
+
): Promise<Relation | null> {
|
|
236
|
+
const byId = await repo.findById(idOrGroup);
|
|
237
|
+
if (byId) return byId;
|
|
238
|
+
const group = await repo.findTranslations(idOrGroup);
|
|
239
|
+
return group[0] ?? null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Pick the locale variant matching `locale`, falling back to the first entry
|
|
244
|
+
* (lowest locale code). The fallback is intentional — an edge is keyed by
|
|
245
|
+
* `translation_group`, so a referenced entry that exists only in another locale
|
|
246
|
+
* is still a real reference — but the returned ref carries the variant's actual
|
|
247
|
+
* `locale` so callers never mistake a fallback for the requested locale.
|
|
248
|
+
*/
|
|
249
|
+
function pickVariant(items: ContentItem[], locale: string | null): ContentItem | undefined {
|
|
250
|
+
return items.find((i) => i.locale === locale) ?? items[0];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Resolve edge groups to loadable entries in `collection` at `locale`.
|
|
255
|
+
* Dangling groups (no surviving entry) are skipped — cleanup is a later slice.
|
|
256
|
+
*
|
|
257
|
+
* All groups are loaded in one batched query (chunked at `SQL_BATCH_SIZE`)
|
|
258
|
+
* rather than a `findTranslations` per edge, so a parent with N children costs
|
|
259
|
+
* a constant number of queries, not N+1. Edge order (the caller's `sort_order`)
|
|
260
|
+
* is preserved by iterating `edges`.
|
|
261
|
+
*
|
|
262
|
+
* `includeDrafts` is false for callers without `content:read_drafts`: the load
|
|
263
|
+
* is restricted to published entries so a draft/scheduled entry referenced by an
|
|
264
|
+
* edge is skipped exactly like a dangling one, never leaking its id/slug/locale.
|
|
265
|
+
*/
|
|
266
|
+
async function resolveEntries(
|
|
267
|
+
content: ContentRepository,
|
|
268
|
+
collection: string,
|
|
269
|
+
edges: ContentReference[],
|
|
270
|
+
pick: (e: ContentReference) => string,
|
|
271
|
+
locale: string | null,
|
|
272
|
+
includeDrafts: boolean,
|
|
273
|
+
): Promise<EntryRef[]> {
|
|
274
|
+
const groups = edges.map(pick);
|
|
275
|
+
const all = await content.findTranslationsForGroups(collection, groups, {
|
|
276
|
+
publishedOnly: !includeDrafts,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// Group the flat variant list by translation_group so each edge can pick its
|
|
280
|
+
// own locale variant.
|
|
281
|
+
const variantsByGroup = new Map<string, ContentItem[]>();
|
|
282
|
+
for (const item of all) {
|
|
283
|
+
if (item.translationGroup == null) continue;
|
|
284
|
+
const list = variantsByGroup.get(item.translationGroup);
|
|
285
|
+
if (list) list.push(item);
|
|
286
|
+
else variantsByGroup.set(item.translationGroup, [item]);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const refs: EntryRef[] = [];
|
|
290
|
+
for (const edge of edges) {
|
|
291
|
+
const variants = variantsByGroup.get(pick(edge));
|
|
292
|
+
if (!variants) continue;
|
|
293
|
+
const entry = pickVariant(variants, locale);
|
|
294
|
+
if (!entry) continue;
|
|
295
|
+
refs.push({
|
|
296
|
+
id: entry.id,
|
|
297
|
+
slug: entry.slug,
|
|
298
|
+
collection,
|
|
299
|
+
locale: entry.locale,
|
|
300
|
+
sortOrder: edge.sortOrder,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
return refs;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Pagination inputs for the edge read endpoints. */
|
|
307
|
+
export type PageOptions = { limit?: number; cursor?: string };
|
|
308
|
+
|
|
309
|
+
export async function handleReferenceChildrenGet(
|
|
310
|
+
db: Kysely<Database>,
|
|
311
|
+
collection: string,
|
|
312
|
+
entryId: string,
|
|
313
|
+
relation: string,
|
|
314
|
+
page: PageOptions = {},
|
|
315
|
+
includeDrafts = false,
|
|
316
|
+
): Promise<ApiResult<{ children: EntryRef[]; nextCursor?: string }>> {
|
|
317
|
+
try {
|
|
318
|
+
const repo = new RelationRepository(db);
|
|
319
|
+
const content = new ContentRepository(db);
|
|
320
|
+
|
|
321
|
+
const rel = await resolveRelation(repo, relation);
|
|
322
|
+
if (!rel)
|
|
323
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Relation not found" } };
|
|
324
|
+
if (collection !== rel.parentCollection) {
|
|
325
|
+
return {
|
|
326
|
+
success: false,
|
|
327
|
+
error: {
|
|
328
|
+
code: "VALIDATION_ERROR",
|
|
329
|
+
message: "Entry is not the parent side of this relation",
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const entry = await content.findByIdOrSlug(collection, entryId);
|
|
335
|
+
// A caller without draft access must not anchor on a non-published entry —
|
|
336
|
+
// return NOT_FOUND (not 403) so they can't probe draft ids by status code,
|
|
337
|
+
// mirroring the single-item content read.
|
|
338
|
+
if (!entry?.translationGroup || (!includeDrafts && entry.status !== "published")) {
|
|
339
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Content entry not found" } };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const edges = await repo.getChildrenPage(rel.translationGroup, entry.translationGroup, page);
|
|
343
|
+
const children = await resolveEntries(
|
|
344
|
+
content,
|
|
345
|
+
rel.childCollection,
|
|
346
|
+
edges.items,
|
|
347
|
+
(e) => e.childGroup,
|
|
348
|
+
entry.locale,
|
|
349
|
+
includeDrafts,
|
|
350
|
+
);
|
|
351
|
+
return { success: true, data: { children, nextCursor: edges.nextCursor } };
|
|
352
|
+
} catch (error) {
|
|
353
|
+
return referencesGetError(error);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export async function handleReferenceChildrenSet(
|
|
358
|
+
db: Kysely<Database>,
|
|
359
|
+
collection: string,
|
|
360
|
+
entryId: string,
|
|
361
|
+
relation: string,
|
|
362
|
+
childIds: string[],
|
|
363
|
+
): Promise<ApiResult<{ children: EntryRef[]; nextCursor?: string }>> {
|
|
364
|
+
try {
|
|
365
|
+
const repo = new RelationRepository(db);
|
|
366
|
+
const content = new ContentRepository(db);
|
|
367
|
+
|
|
368
|
+
const rel = await resolveRelation(repo, relation);
|
|
369
|
+
if (!rel)
|
|
370
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Relation not found" } };
|
|
371
|
+
if (collection !== rel.parentCollection) {
|
|
372
|
+
return {
|
|
373
|
+
success: false,
|
|
374
|
+
error: {
|
|
375
|
+
code: "VALIDATION_ERROR",
|
|
376
|
+
message: "Entry is not the parent side of this relation",
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const entry = await content.findByIdOrSlug(collection, entryId);
|
|
382
|
+
if (!entry?.translationGroup) {
|
|
383
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Content entry not found" } };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Resolve every child within the relation's child_collection in one batch
|
|
387
|
+
// (constant queries, not an N+1 of point lookups for a set up to 1000). A
|
|
388
|
+
// child id that does not resolve there fails collection-agreement
|
|
389
|
+
// (invariant 3); order is preserved by iterating the caller's `childIds`.
|
|
390
|
+
const resolvedChildren = await content.findManyByIdOrSlug(rel.childCollection, childIds);
|
|
391
|
+
const childGroups: string[] = [];
|
|
392
|
+
for (const childId of childIds) {
|
|
393
|
+
const child = resolvedChildren.get(childId);
|
|
394
|
+
if (!child?.translationGroup) {
|
|
395
|
+
return {
|
|
396
|
+
success: false,
|
|
397
|
+
error: {
|
|
398
|
+
code: "NOT_FOUND",
|
|
399
|
+
message: `Child entry '${childId}' not found in ${rel.childCollection}`,
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
childGroups.push(child.translationGroup);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
await repo.setChildren(rel.translationGroup, entry.translationGroup, childGroups);
|
|
407
|
+
|
|
408
|
+
// Return the first page of the new set, mirroring the GET shape. The actor
|
|
409
|
+
// holds an edit permission (gated by the route), so draft children are
|
|
410
|
+
// included in the echo.
|
|
411
|
+
const edges = await repo.getChildrenPage(rel.translationGroup, entry.translationGroup);
|
|
412
|
+
const children = await resolveEntries(
|
|
413
|
+
content,
|
|
414
|
+
rel.childCollection,
|
|
415
|
+
edges.items,
|
|
416
|
+
(e) => e.childGroup,
|
|
417
|
+
entry.locale,
|
|
418
|
+
true,
|
|
419
|
+
);
|
|
420
|
+
return { success: true, data: { children, nextCursor: edges.nextCursor } };
|
|
421
|
+
} catch {
|
|
422
|
+
return {
|
|
423
|
+
success: false,
|
|
424
|
+
error: { code: "REFERENCES_SET_ERROR", message: "Failed to set references" },
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export async function handleReferenceParentsGet(
|
|
430
|
+
db: Kysely<Database>,
|
|
431
|
+
collection: string,
|
|
432
|
+
entryId: string,
|
|
433
|
+
relation: string,
|
|
434
|
+
page: PageOptions = {},
|
|
435
|
+
includeDrafts = false,
|
|
436
|
+
): Promise<ApiResult<{ parents: EntryRef[]; nextCursor?: string }>> {
|
|
437
|
+
try {
|
|
438
|
+
const repo = new RelationRepository(db);
|
|
439
|
+
const content = new ContentRepository(db);
|
|
440
|
+
|
|
441
|
+
const rel = await resolveRelation(repo, relation);
|
|
442
|
+
if (!rel)
|
|
443
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Relation not found" } };
|
|
444
|
+
if (collection !== rel.childCollection) {
|
|
445
|
+
return {
|
|
446
|
+
success: false,
|
|
447
|
+
error: {
|
|
448
|
+
code: "VALIDATION_ERROR",
|
|
449
|
+
message: "Entry is not the child side of this relation",
|
|
450
|
+
},
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const entry = await content.findByIdOrSlug(collection, entryId);
|
|
455
|
+
// Same draft-anchor guard as the children read: a non-draft-reader anchoring
|
|
456
|
+
// on an unpublished entry gets NOT_FOUND, not its backlinks.
|
|
457
|
+
if (!entry?.translationGroup || (!includeDrafts && entry.status !== "published")) {
|
|
458
|
+
return { success: false, error: { code: "NOT_FOUND", message: "Content entry not found" } };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const edges = await repo.getParentsPage(rel.translationGroup, entry.translationGroup, page);
|
|
462
|
+
const parents = await resolveEntries(
|
|
463
|
+
content,
|
|
464
|
+
rel.parentCollection,
|
|
465
|
+
edges.items,
|
|
466
|
+
(e) => e.parentGroup,
|
|
467
|
+
entry.locale,
|
|
468
|
+
includeDrafts,
|
|
469
|
+
);
|
|
470
|
+
return { success: true, data: { parents, nextCursor: edges.nextCursor } };
|
|
471
|
+
} catch (error) {
|
|
472
|
+
return referencesGetError(error);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
@@ -13,6 +13,7 @@ import { ulid } from "ulidx";
|
|
|
13
13
|
import { TaxonomyRepository } from "../../database/repositories/taxonomy.js";
|
|
14
14
|
import type { Database, TaxonomyDefTable } from "../../database/types.js";
|
|
15
15
|
import { invalidateTaxonomyDefsCache, invalidateTermCache } from "../../taxonomies/index.js";
|
|
16
|
+
import { fetchVisibleTermCounts } from "../../taxonomies/term-counts.js";
|
|
16
17
|
import type { ApiResult } from "../types.js";
|
|
17
18
|
|
|
18
19
|
const NAME_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
@@ -141,6 +142,13 @@ async function requireTaxonomyDef(
|
|
|
141
142
|
return { success: true, def };
|
|
142
143
|
}
|
|
143
144
|
|
|
145
|
+
/** Declared collections of a taxonomy def row (deduped, parsed from JSON). */
|
|
146
|
+
function defCollections(def: Selectable<TaxonomyDefTable>): string[] {
|
|
147
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- column stores a JSON string[] written by handleTaxonomyCreate
|
|
148
|
+
const parsed = def.collections ? (JSON.parse(def.collections) as string[]) : [];
|
|
149
|
+
return [...new Set(parsed)];
|
|
150
|
+
}
|
|
151
|
+
|
|
144
152
|
function rowToDef(row: Selectable<TaxonomyDefTable>): TaxonomyDef {
|
|
145
153
|
return {
|
|
146
154
|
id: row.id,
|
|
@@ -384,11 +392,16 @@ export async function handleTermList(
|
|
|
384
392
|
const repo = new TaxonomyRepository(db);
|
|
385
393
|
const terms = await repo.findByName(taxonomyName, { locale: options.locale });
|
|
386
394
|
|
|
387
|
-
//
|
|
395
|
+
// Counts match what visitors see on the public site: published (or
|
|
396
|
+
// scheduled-and-due) entries that aren't soft-deleted, scoped to the
|
|
397
|
+
// taxonomy's declared collections — one query for the whole list.
|
|
388
398
|
// content_taxonomies.taxonomy_id stores the translation_group, so we
|
|
389
399
|
// look up by group and map back to each term's id.
|
|
390
|
-
const
|
|
391
|
-
|
|
400
|
+
const countsByGroup = await fetchVisibleTermCounts(
|
|
401
|
+
db,
|
|
402
|
+
taxonomyName,
|
|
403
|
+
defCollections(lookup.def),
|
|
404
|
+
);
|
|
392
405
|
|
|
393
406
|
const termData: TermWithCount[] = terms.map((term) => ({
|
|
394
407
|
id: term.id,
|
|
@@ -634,7 +647,16 @@ export async function handleTermGet(
|
|
|
634
647
|
};
|
|
635
648
|
}
|
|
636
649
|
|
|
637
|
-
|
|
650
|
+
// Count matches public visibility (published or scheduled-and-due, not
|
|
651
|
+
// soft-deleted) scoped to the def's declared collections. The def lookup
|
|
652
|
+
// is lenient: a term whose def is missing still resolves, with count 0.
|
|
653
|
+
const lookup = await requireTaxonomyDef(db, taxonomyName);
|
|
654
|
+
const counts = await fetchVisibleTermCounts(
|
|
655
|
+
db,
|
|
656
|
+
taxonomyName,
|
|
657
|
+
lookup.success ? defCollections(lookup.def) : [],
|
|
658
|
+
);
|
|
659
|
+
const count = counts.get(term.translationGroup ?? term.id) ?? 0;
|
|
638
660
|
// Children share this term's translation_group as their parent_id; scope
|
|
639
661
|
// to the term's own locale so the response stays within one locale's tree.
|
|
640
662
|
const children = await repo.findChildren(term.id, term.locale);
|
|
@@ -21,7 +21,7 @@ interface MediaRefValue {
|
|
|
21
21
|
function asMediaRef(value: unknown): MediaRefValue | null {
|
|
22
22
|
if (value === null || value === undefined) return null;
|
|
23
23
|
if (typeof value !== "object" || Array.isArray(value)) return null;
|
|
24
|
-
return value
|
|
24
|
+
return value;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function fail(message: string): ApiResult<never> {
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
contentUpdateBody,
|
|
38
38
|
trashedContentListResponseSchema,
|
|
39
39
|
} from "../schemas/content.js";
|
|
40
|
+
import { mediaUsageRepairBody, mediaUsageRepairResponseSchema } from "../schemas/media-usage.js";
|
|
40
41
|
import {
|
|
41
42
|
DEFAULT_MAX_UPLOAD_SIZE,
|
|
42
43
|
mediaConfirmBody,
|
|
@@ -151,6 +152,7 @@ function standardErrors(
|
|
|
151
152
|
403: "Forbidden",
|
|
152
153
|
404: "Not Found",
|
|
153
154
|
409: "Conflict",
|
|
155
|
+
413: "Payload Too Large",
|
|
154
156
|
500: "Internal Server Error",
|
|
155
157
|
};
|
|
156
158
|
for (const code of codes) {
|
|
@@ -722,6 +724,29 @@ function buildMediaPaths(maxUploadSize: number) {
|
|
|
722
724
|
},
|
|
723
725
|
},
|
|
724
726
|
},
|
|
727
|
+
"/_emdash/api/admin/media-usage/repair": {
|
|
728
|
+
post: {
|
|
729
|
+
operationId: "repairMediaUsage",
|
|
730
|
+
summary: "Repair media usage indexes",
|
|
731
|
+
description:
|
|
732
|
+
"Repairs content media usage indexes for one collection or all collections. The request succeeds with HTTP 200 when a structured repair result is produced; inspect `data.status` because it may be `failed` or `stale`.",
|
|
733
|
+
tags: ["Media"],
|
|
734
|
+
requestBody: {
|
|
735
|
+
required: true,
|
|
736
|
+
content: { [JSON_CONTENT]: { schema: mediaUsageRepairBody } },
|
|
737
|
+
},
|
|
738
|
+
responses: {
|
|
739
|
+
"200": {
|
|
740
|
+
description: "Media usage repair result",
|
|
741
|
+
content: {
|
|
742
|
+
[JSON_CONTENT]: { schema: successEnvelope(mediaUsageRepairResponseSchema) },
|
|
743
|
+
},
|
|
744
|
+
},
|
|
745
|
+
...authErrors,
|
|
746
|
+
...standardErrors(400, 413, 500),
|
|
747
|
+
},
|
|
748
|
+
},
|
|
749
|
+
},
|
|
725
750
|
"/_emdash/api/media/upload-url": {
|
|
726
751
|
post: {
|
|
727
752
|
operationId: "getMediaUploadUrl",
|
package/src/api/parse.ts
CHANGED
|
@@ -104,7 +104,7 @@ function validate<T extends z.ZodType>(schema: T, data: unknown): ParseResult<z.
|
|
|
104
104
|
const result = schema.safeParse(data);
|
|
105
105
|
|
|
106
106
|
if (result.success) {
|
|
107
|
-
return result.data
|
|
107
|
+
return result.data;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
// Format Zod errors into a readable structure
|
|
@@ -12,6 +12,12 @@ export const createCommentBody = z
|
|
|
12
12
|
parentId: z.string().optional(),
|
|
13
13
|
/** Honeypot field — hidden in the form, filled only by bots */
|
|
14
14
|
website_url: z.string().optional(),
|
|
15
|
+
/**
|
|
16
|
+
* Turnstile response token from the form widget. Verified
|
|
17
|
+
* server-side when a Turnstile secret key is configured.
|
|
18
|
+
* Turnstile tokens can be up to 2048 characters.
|
|
19
|
+
*/
|
|
20
|
+
turnstileToken: z.string().max(2048).optional(),
|
|
15
21
|
})
|
|
16
22
|
.meta({ id: "CreateCommentBody" });
|
|
17
23
|
|
|
@@ -59,6 +59,10 @@ export const contentCreateBody = z
|
|
|
59
59
|
locale: localeCode.optional(),
|
|
60
60
|
translationOf: z.string().optional(),
|
|
61
61
|
seo: contentSeoInput.optional(),
|
|
62
|
+
taxonomies: z.record(z.string(), z.array(z.string())).optional().meta({
|
|
63
|
+
description:
|
|
64
|
+
"Taxonomy term assignments as { taxonomyName: [termSlug, ...] }, resolved in the entry's locale.",
|
|
65
|
+
}),
|
|
62
66
|
publishedAt: contentDateOverride,
|
|
63
67
|
createdAt: contentDateOverride,
|
|
64
68
|
})
|
|
@@ -77,6 +81,10 @@ export const contentUpdateBody = z
|
|
|
77
81
|
.meta({ description: "Opaque revision token for optimistic concurrency" }),
|
|
78
82
|
skipRevision: z.boolean().optional(),
|
|
79
83
|
seo: contentSeoInput.optional(),
|
|
84
|
+
taxonomies: z.record(z.string(), z.array(z.string())).optional().meta({
|
|
85
|
+
description:
|
|
86
|
+
"Replace taxonomy assignments as { taxonomyName: [termSlug, ...] }. Only named taxonomies are touched; pass an empty array to clear a taxonomy.",
|
|
87
|
+
}),
|
|
80
88
|
publishedAt: contentDateOverride,
|
|
81
89
|
})
|
|
82
90
|
.meta({ id: "ContentUpdateBody" });
|
package/src/api/schemas/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./common.js";
|
|
2
2
|
export * from "./content.js";
|
|
3
3
|
export * from "./media.js";
|
|
4
|
+
export * from "./media-usage.js";
|
|
4
5
|
export * from "./schema.js";
|
|
5
6
|
export * from "./comments.js";
|
|
6
7
|
export * from "./auth.js";
|
|
@@ -16,3 +17,4 @@ export * from "./widgets.js";
|
|
|
16
17
|
export * from "./redirects.js";
|
|
17
18
|
export * from "./bylines.js";
|
|
18
19
|
export * from "./byline-fields.js";
|
|
20
|
+
export * from "./relations.js";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { slugPattern } from "./common.js";
|
|
4
|
+
|
|
5
|
+
export const mediaUsageRepairStatusSchema = z
|
|
6
|
+
.enum(["complete", "partial", "failed", "stale"])
|
|
7
|
+
.meta({ id: "MediaUsageRepairStatus" });
|
|
8
|
+
|
|
9
|
+
const mediaUsageRepairCollectionBody = z
|
|
10
|
+
.object({
|
|
11
|
+
scope: z.literal("collection"),
|
|
12
|
+
collection: z.string().min(1).max(63).regex(slugPattern, "Invalid collection slug"),
|
|
13
|
+
})
|
|
14
|
+
.strict();
|
|
15
|
+
|
|
16
|
+
const mediaUsageRepairAllBody = z.object({ scope: z.literal("all") }).strict();
|
|
17
|
+
|
|
18
|
+
export const mediaUsageRepairBody = z
|
|
19
|
+
.discriminatedUnion("scope", [mediaUsageRepairCollectionBody, mediaUsageRepairAllBody])
|
|
20
|
+
.meta({ id: "MediaUsageRepairBody" });
|
|
21
|
+
|
|
22
|
+
export const mediaUsageRepairCollectionSummarySchema = z
|
|
23
|
+
.object({
|
|
24
|
+
collection: z.string(),
|
|
25
|
+
status: mediaUsageRepairStatusSchema,
|
|
26
|
+
indexedSourceCount: z.number().int().min(0),
|
|
27
|
+
failedSourceCount: z.number().int().min(0),
|
|
28
|
+
skippedSourceCount: z.number().int().min(0),
|
|
29
|
+
deletedSourceCount: z.number().int().min(0),
|
|
30
|
+
lastErrorCode: z.string().nullable(),
|
|
31
|
+
startedAt: z.string(),
|
|
32
|
+
completedAt: z.string().nullable(),
|
|
33
|
+
})
|
|
34
|
+
.meta({ id: "MediaUsageRepairCollectionSummary" });
|
|
35
|
+
|
|
36
|
+
export const mediaUsageRepairResponseSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
status: mediaUsageRepairStatusSchema,
|
|
39
|
+
indexedSourceCount: z.number().int().min(0),
|
|
40
|
+
failedSourceCount: z.number().int().min(0),
|
|
41
|
+
skippedSourceCount: z.number().int().min(0),
|
|
42
|
+
deletedSourceCount: z.number().int().min(0),
|
|
43
|
+
collections: z.array(mediaUsageRepairCollectionSummarySchema),
|
|
44
|
+
})
|
|
45
|
+
.meta({ id: "MediaUsageRepairResponse" });
|
|
46
|
+
|
|
47
|
+
export type MediaUsageRepairRequest = z.infer<typeof mediaUsageRepairBody>;
|
|
48
|
+
export type MediaUsageRepairResponse = z.infer<typeof mediaUsageRepairResponseSchema>;
|