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
|
@@ -2,6 +2,9 @@ import { sql, type Kysely } from "kysely";
|
|
|
2
2
|
import { ulid } from "ulidx";
|
|
3
3
|
|
|
4
4
|
import { invalidateCollectionCache } from "../../object-cache/index.js";
|
|
5
|
+
import { buildFtsPrefixMatch, buildSlugGlobPrefix } from "../../search/match.js";
|
|
6
|
+
import { chunks, SQL_BATCH_SIZE } from "../../utils/chunks.js";
|
|
7
|
+
import { isMissingTableError } from "../../utils/db-errors.js";
|
|
5
8
|
import { slugify } from "../../utils/slugify.js";
|
|
6
9
|
import type { Database } from "../types.js";
|
|
7
10
|
import { validateIdentifier } from "../validate.js";
|
|
@@ -402,16 +405,26 @@ export class ContentRepository {
|
|
|
402
405
|
? (t: string, s: string) => this.findBySlugIncludingTrashed(t, s, locale)
|
|
403
406
|
: (t: string, s: string) => this.findBySlug(t, s, locale);
|
|
404
407
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
408
|
+
try {
|
|
409
|
+
if (looksLikeUlid) {
|
|
410
|
+
// Try ID first, fall back to slug
|
|
411
|
+
const byId = await findById(type, identifier);
|
|
412
|
+
if (byId) return byId;
|
|
413
|
+
return await findBySlug(type, identifier);
|
|
414
|
+
}
|
|
415
|
+
// Try slug first, fall back to ID
|
|
416
|
+
const bySlug = await findBySlug(type, identifier);
|
|
417
|
+
if (bySlug) return bySlug;
|
|
418
|
+
return await findById(type, identifier);
|
|
419
|
+
} catch (error) {
|
|
420
|
+
// A collection dropped out from under a still-referencing caller (e.g. a
|
|
421
|
+
// relation whose collection was deleted without cascading) leaves the
|
|
422
|
+
// ec_* table missing. Treat that as "not found", matching
|
|
423
|
+
// findManyByIdOrSlug and findTranslationsForGroups, so callers surface a
|
|
424
|
+
// structured NOT_FOUND instead of a 500.
|
|
425
|
+
if (isMissingTableError(error)) return null;
|
|
426
|
+
throw error;
|
|
410
427
|
}
|
|
411
|
-
// Try slug first, fall back to ID
|
|
412
|
-
const bySlug = await findBySlug(type, identifier);
|
|
413
|
-
if (bySlug) return bySlug;
|
|
414
|
-
return findById(type, identifier);
|
|
415
428
|
}
|
|
416
429
|
|
|
417
430
|
/**
|
|
@@ -513,7 +526,7 @@ export class ContentRepository {
|
|
|
513
526
|
query = query.where("locale" as any, "=", options.where.locale);
|
|
514
527
|
}
|
|
515
528
|
|
|
516
|
-
query = this.applySearchFilter(query, options.where);
|
|
529
|
+
query = this.applySearchFilter(query, options.where, type);
|
|
517
530
|
query = this.applyDateFilter(query, options.where);
|
|
518
531
|
|
|
519
532
|
// Handle cursor pagination — decodeCursor throws InvalidCursorError
|
|
@@ -792,19 +805,46 @@ export class ContentRepository {
|
|
|
792
805
|
}
|
|
793
806
|
|
|
794
807
|
/**
|
|
795
|
-
* Apply the optional
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
* SQLite
|
|
808
|
+
* Apply the optional `q` filter.
|
|
809
|
+
*
|
|
810
|
+
* When the handler sets `useFts` (collection has a healthy FTS5 index
|
|
811
|
+
* covering the display columns; SQLite only), the filter is served from
|
|
812
|
+
* the index: a token-prefix MATCH against `_emdash_fts_<slug>` OR'd with
|
|
813
|
+
* an index-served `slug GLOB 'term*'` prefix (the slug is not in the FTS
|
|
814
|
+
* index). Both sides are index-backed, so SQLite's OR optimization avoids
|
|
815
|
+
* the full-table scan the LIKE fallback needs (#1517). The trade-off is
|
|
816
|
+
* search semantics: token-prefix matching instead of arbitrary substring.
|
|
817
|
+
*
|
|
818
|
+
* Fallback (Postgres, search disabled, or no usable terms): case-
|
|
819
|
+
* insensitive substring LIKE across the handler-resolved `searchColumns`
|
|
820
|
+
* (OR'd). User input is treated literally (LIKE wildcards escaped) and
|
|
821
|
+
* `lower()` is applied on both sides for SQLite/Postgres parity.
|
|
799
822
|
*/
|
|
800
823
|
private applySearchFilter<QB extends { where: (cb: (eb: any) => unknown) => QB }>(
|
|
801
824
|
query: QB,
|
|
802
|
-
where
|
|
825
|
+
where: { q?: string; searchColumns?: string[]; useFts?: boolean } | undefined,
|
|
826
|
+
type: string,
|
|
803
827
|
): QB {
|
|
804
828
|
const term = where?.q?.trim();
|
|
805
829
|
const columns = where?.searchColumns;
|
|
806
830
|
if (!term || !columns || columns.length === 0) return query;
|
|
807
831
|
|
|
832
|
+
if (where.useFts) {
|
|
833
|
+
const match = buildFtsPrefixMatch(term);
|
|
834
|
+
if (match) {
|
|
835
|
+
validateIdentifier(type, "collection slug");
|
|
836
|
+
const ftsTable = `_emdash_fts_${type}`;
|
|
837
|
+
const slugPrefix = buildSlugGlobPrefix(term);
|
|
838
|
+
return query.where((eb) =>
|
|
839
|
+
eb.or([
|
|
840
|
+
sql<boolean>`id IN (SELECT id FROM ${sql.ref(ftsTable)} WHERE ${sql.ref(ftsTable)} MATCH ${match})`,
|
|
841
|
+
sql<boolean>`slug GLOB ${slugPrefix}`,
|
|
842
|
+
]),
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
// No usable terms (e.g. quotes only) — fall through to LIKE.
|
|
846
|
+
}
|
|
847
|
+
|
|
808
848
|
const escaped = term.replace(LIKE_WILDCARD_RE, (c) => `\\${c}`);
|
|
809
849
|
const pattern = `%${escaped}%`;
|
|
810
850
|
|
|
@@ -866,7 +906,7 @@ export class ContentRepository {
|
|
|
866
906
|
query = query.where("locale" as any, "=", where.locale);
|
|
867
907
|
}
|
|
868
908
|
|
|
869
|
-
query = this.applySearchFilter(query, where);
|
|
909
|
+
query = this.applySearchFilter(query, where, type);
|
|
870
910
|
query = this.applyDateFilter(query, where);
|
|
871
911
|
|
|
872
912
|
const result = await query.executeTakeFirst();
|
|
@@ -890,13 +930,13 @@ export class ContentRepository {
|
|
|
890
930
|
.where("author_id" as never, "is not", null)
|
|
891
931
|
.execute();
|
|
892
932
|
|
|
893
|
-
return rows
|
|
894
|
-
.map((row) => (row as { author_id: string | null }).author_id)
|
|
895
|
-
.filter((id): id is string => id !== null);
|
|
933
|
+
return rows.map((row) => row.author_id).filter((id): id is string => id !== null);
|
|
896
934
|
}
|
|
897
935
|
|
|
898
|
-
// get overall statistics
|
|
899
|
-
async getStats(
|
|
936
|
+
// get overall statistics for a content type in a single query
|
|
937
|
+
async getStats(
|
|
938
|
+
type: string,
|
|
939
|
+
): Promise<{ total: number; published: number; draft: number; scheduled: number }> {
|
|
900
940
|
const tableName = getTableName(type);
|
|
901
941
|
|
|
902
942
|
const result = await this.db
|
|
@@ -905,6 +945,7 @@ export class ContentRepository {
|
|
|
905
945
|
eb.fn.count("id").as("total"),
|
|
906
946
|
eb.fn.sum(eb.case().when("status", "=", "published").then(1).else(0).end()).as("published"),
|
|
907
947
|
eb.fn.sum(eb.case().when("status", "=", "draft").then(1).else(0).end()).as("draft"),
|
|
948
|
+
sql<number>`SUM(CASE WHEN scheduled_at IS NOT NULL THEN 1 ELSE 0 END)`.as("scheduled"),
|
|
908
949
|
])
|
|
909
950
|
.where("deleted_at" as never, "is", null)
|
|
910
951
|
.executeTakeFirst();
|
|
@@ -913,6 +954,7 @@ export class ContentRepository {
|
|
|
913
954
|
total: Number(result?.total || 0),
|
|
914
955
|
published: Number(result?.published || 0),
|
|
915
956
|
draft: Number(result?.draft || 0),
|
|
957
|
+
scheduled: Number(result?.scheduled || 0),
|
|
916
958
|
};
|
|
917
959
|
}
|
|
918
960
|
|
|
@@ -1054,6 +1096,115 @@ export class ContentRepository {
|
|
|
1054
1096
|
return result.rows.map((row) => this.mapRow(type, row));
|
|
1055
1097
|
}
|
|
1056
1098
|
|
|
1099
|
+
/**
|
|
1100
|
+
* Batch variant of {@link findTranslations}: every (non-deleted) locale
|
|
1101
|
+
* variant for any of `translationGroups`, in one `WHERE translation_group IN
|
|
1102
|
+
* (...)` query chunked at `SQL_BATCH_SIZE` for D1's bind-parameter limit.
|
|
1103
|
+
* Lets callers resolve many edge groups without an N+1 per group. The caller
|
|
1104
|
+
* groups the flat result by `translationGroup` itself.
|
|
1105
|
+
*
|
|
1106
|
+
* `publishedOnly` restricts the result to `status = 'published'` — reference
|
|
1107
|
+
* reads pass this for callers without `content:read_drafts` so draft/scheduled
|
|
1108
|
+
* entries never leak through an edge traversal.
|
|
1109
|
+
*
|
|
1110
|
+
* A reference edge stores only a collection slug (no SQL FK), so the table may
|
|
1111
|
+
* have been dropped since the edge was written. That is a tolerated dangling
|
|
1112
|
+
* state, not an error: a missing table resolves to no rows, mirroring how the
|
|
1113
|
+
* content read handlers treat `isMissingTableError`.
|
|
1114
|
+
*/
|
|
1115
|
+
async findTranslationsForGroups(
|
|
1116
|
+
type: string,
|
|
1117
|
+
translationGroups: string[],
|
|
1118
|
+
options: { publishedOnly?: boolean } = {},
|
|
1119
|
+
): Promise<ContentItem[]> {
|
|
1120
|
+
if (translationGroups.length === 0) return [];
|
|
1121
|
+
const tableName = getTableName(type);
|
|
1122
|
+
const publishedFilter = options.publishedOnly ? sql`AND status = 'published'` : sql``;
|
|
1123
|
+
|
|
1124
|
+
const items: ContentItem[] = [];
|
|
1125
|
+
try {
|
|
1126
|
+
for (const chunk of chunks(translationGroups, SQL_BATCH_SIZE)) {
|
|
1127
|
+
const result = await sql<Record<string, unknown>>`
|
|
1128
|
+
SELECT * FROM ${sql.ref(tableName)}
|
|
1129
|
+
WHERE translation_group IN (${sql.join(chunk)})
|
|
1130
|
+
AND deleted_at IS NULL
|
|
1131
|
+
${publishedFilter}
|
|
1132
|
+
ORDER BY locale ASC
|
|
1133
|
+
`.execute(this.db);
|
|
1134
|
+
for (const row of result.rows) items.push(this.mapRow(type, row));
|
|
1135
|
+
}
|
|
1136
|
+
} catch (error) {
|
|
1137
|
+
if (isMissingTableError(error)) return [];
|
|
1138
|
+
throw error;
|
|
1139
|
+
}
|
|
1140
|
+
return items;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* Batch variant of {@link findByIdOrSlug}: resolve many identifiers (each an
|
|
1145
|
+
* id OR a slug) within `type` in a constant number of queries — one `WHERE id
|
|
1146
|
+
* IN (...)` and one `WHERE slug IN (...)`, each chunked at `SQL_BATCH_SIZE`.
|
|
1147
|
+
* Returns a map from the input identifier to its resolved item; identifiers
|
|
1148
|
+
* that match nothing are absent. Used on write paths that accept a list of
|
|
1149
|
+
* references, so a single request doesn't fan out to an N+1 of point lookups.
|
|
1150
|
+
*
|
|
1151
|
+
* Resolution mirrors {@link findByIdOrSlug}: a ULID-shaped identifier prefers
|
|
1152
|
+
* the id match and falls back to slug; anything else prefers the slug match
|
|
1153
|
+
* and falls back to id. Slug matches collapse to the lowest-locale variant
|
|
1154
|
+
* (`ORDER BY locale ASC`), matching the slug-without-locale lookup.
|
|
1155
|
+
*/
|
|
1156
|
+
async findManyByIdOrSlug(type: string, identifiers: string[]): Promise<Map<string, ContentItem>> {
|
|
1157
|
+
const resolved = new Map<string, ContentItem>();
|
|
1158
|
+
const unique = [...new Set(identifiers)];
|
|
1159
|
+
if (unique.length === 0) return resolved;
|
|
1160
|
+
|
|
1161
|
+
const tableName = getTableName(type);
|
|
1162
|
+
const byId = new Map<string, ContentItem>();
|
|
1163
|
+
const bySlug = new Map<string, ContentItem>();
|
|
1164
|
+
|
|
1165
|
+
try {
|
|
1166
|
+
for (const chunk of chunks(unique, SQL_BATCH_SIZE)) {
|
|
1167
|
+
const idRows = await sql<Record<string, unknown>>`
|
|
1168
|
+
SELECT * FROM ${sql.ref(tableName)}
|
|
1169
|
+
WHERE id IN (${sql.join(chunk)})
|
|
1170
|
+
AND deleted_at IS NULL
|
|
1171
|
+
`.execute(this.db);
|
|
1172
|
+
for (const row of idRows.rows) {
|
|
1173
|
+
const item = this.mapRow(type, row);
|
|
1174
|
+
byId.set(item.id, item);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
const slugRows = await sql<Record<string, unknown>>`
|
|
1178
|
+
SELECT * FROM ${sql.ref(tableName)}
|
|
1179
|
+
WHERE slug IN (${sql.join(chunk)})
|
|
1180
|
+
AND deleted_at IS NULL
|
|
1181
|
+
ORDER BY locale ASC
|
|
1182
|
+
`.execute(this.db);
|
|
1183
|
+
for (const row of slugRows.rows) {
|
|
1184
|
+
const item = this.mapRow(type, row);
|
|
1185
|
+
// First write wins → lowest locale, matching findBySlug without a locale.
|
|
1186
|
+
if (item.slug != null && !bySlug.has(item.slug)) bySlug.set(item.slug, item);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
} catch (error) {
|
|
1190
|
+
// A collection dropped after a relation was created leaves the relation
|
|
1191
|
+
// pointing at a missing table. Treat it like an empty collection (no
|
|
1192
|
+
// matches) so callers surface a structured NOT_FOUND, not a 500 —
|
|
1193
|
+
// mirroring findTranslationsForGroups.
|
|
1194
|
+
if (isMissingTableError(error)) return resolved;
|
|
1195
|
+
throw error;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
for (const identifier of unique) {
|
|
1199
|
+
const looksLikeUlid = ULID_PATTERN.test(identifier);
|
|
1200
|
+
const item = looksLikeUlid
|
|
1201
|
+
? (byId.get(identifier) ?? bySlug.get(identifier))
|
|
1202
|
+
: (bySlug.get(identifier) ?? byId.get(identifier));
|
|
1203
|
+
if (item) resolved.set(identifier, item);
|
|
1204
|
+
}
|
|
1205
|
+
return resolved;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1057
1208
|
/**
|
|
1058
1209
|
* Publish the current draft
|
|
1059
1210
|
*
|
|
@@ -3,6 +3,7 @@ import { ulid } from "ulidx";
|
|
|
3
3
|
|
|
4
4
|
import { chunks, SQL_BATCH_SIZE } from "../../utils/chunks.js";
|
|
5
5
|
import type { Database, RelationTable, ContentReferenceTable } from "../types.js";
|
|
6
|
+
import { decodeCursor, encodeCursor, InvalidCursorError, type FindManyResult } from "./types.js";
|
|
6
7
|
|
|
7
8
|
export interface Relation {
|
|
8
9
|
id: string;
|
|
@@ -17,8 +18,12 @@ export interface Relation {
|
|
|
17
18
|
|
|
18
19
|
export interface CreateRelationInput {
|
|
19
20
|
name: string;
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
/** Required for a base relation; ignored (inherited from the source) when
|
|
22
|
+
* `translationOf` is set. */
|
|
23
|
+
parentCollection?: string;
|
|
24
|
+
/** Required for a base relation; ignored (inherited from the source) when
|
|
25
|
+
* `translationOf` is set. */
|
|
26
|
+
childCollection?: string;
|
|
22
27
|
parentLabel: string;
|
|
23
28
|
childLabel: string;
|
|
24
29
|
/** Omit to let the DB default (current value: 'en') apply. Higher layers
|
|
@@ -73,9 +78,9 @@ export class RelationRepository {
|
|
|
73
78
|
const now = new Date().toISOString();
|
|
74
79
|
|
|
75
80
|
let translationGroup = id;
|
|
76
|
-
let name
|
|
77
|
-
let parentCollection
|
|
78
|
-
let childCollection
|
|
81
|
+
let name: string;
|
|
82
|
+
let parentCollection: string;
|
|
83
|
+
let childCollection: string;
|
|
79
84
|
|
|
80
85
|
if (input.translationOf) {
|
|
81
86
|
const source = await this.findById(input.translationOf);
|
|
@@ -87,6 +92,18 @@ export class RelationRepository {
|
|
|
87
92
|
name = source.name;
|
|
88
93
|
parentCollection = source.parentCollection;
|
|
89
94
|
childCollection = source.childCollection;
|
|
95
|
+
} else {
|
|
96
|
+
// A base relation carries its own structural fields. The API layer's Zod
|
|
97
|
+
// schema enforces this; guard here too since the repo trusts its inputs
|
|
98
|
+
// and the columns are NOT NULL.
|
|
99
|
+
if (input.parentCollection === undefined || input.childCollection === undefined) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
"parentCollection and childCollection are required unless translationOf is set",
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
name = input.name;
|
|
105
|
+
parentCollection = input.parentCollection;
|
|
106
|
+
childCollection = input.childCollection;
|
|
90
107
|
}
|
|
91
108
|
|
|
92
109
|
await this.db
|
|
@@ -319,6 +336,61 @@ export class RelationRepository {
|
|
|
319
336
|
return rows.map((row) => this.rowToReference(row));
|
|
320
337
|
}
|
|
321
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Forward traversal, paginated: one page of a parent's children for a
|
|
341
|
+
* relation, ordered by `(sort_order, id)`. Use this on request paths — a
|
|
342
|
+
* parent's children are capped but still up to 1000, and an unbounded read
|
|
343
|
+
* scales poorly. Returns `{ items, nextCursor? }`; the cursor's order value is
|
|
344
|
+
* the row's `sort_order`. Default limit 50, max 100.
|
|
345
|
+
*/
|
|
346
|
+
async getChildrenPage(
|
|
347
|
+
relation: string,
|
|
348
|
+
parentGroup: string,
|
|
349
|
+
options: { limit?: number; cursor?: string } = {},
|
|
350
|
+
): Promise<FindManyResult<ContentReference>> {
|
|
351
|
+
const relationGroup = await this.resolveRelationGroup(relation);
|
|
352
|
+
if (!relationGroup) return { items: [] };
|
|
353
|
+
|
|
354
|
+
const limit = Math.min(options.limit || 50, 100);
|
|
355
|
+
|
|
356
|
+
let query = this.db
|
|
357
|
+
.selectFrom("_emdash_content_references")
|
|
358
|
+
.selectAll()
|
|
359
|
+
.where("relation_group", "=", relationGroup)
|
|
360
|
+
.where("parent_group", "=", parentGroup);
|
|
361
|
+
|
|
362
|
+
if (options.cursor) {
|
|
363
|
+
const decoded = decodeCursor(options.cursor);
|
|
364
|
+
const sortOrder = Number(decoded.orderValue);
|
|
365
|
+
// `decodeCursor` only guarantees `orderValue` is a string; a hand-crafted
|
|
366
|
+
// cursor with a non-numeric order value would coerce to NaN and blow up at
|
|
367
|
+
// the driver bind as a 500. A bad cursor is a client error — surface it as
|
|
368
|
+
// INVALID_CURSOR (400). Server-issued cursors are always numeric here.
|
|
369
|
+
if (!Number.isFinite(sortOrder)) throw new InvalidCursorError(options.cursor);
|
|
370
|
+
query = query.where((eb) =>
|
|
371
|
+
eb.or([
|
|
372
|
+
eb("sort_order", ">", sortOrder),
|
|
373
|
+
eb.and([eb("sort_order", "=", sortOrder), eb("id", ">", decoded.id)]),
|
|
374
|
+
]),
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const rows = await query
|
|
379
|
+
.orderBy("sort_order", "asc")
|
|
380
|
+
.orderBy("id", "asc")
|
|
381
|
+
.limit(limit + 1)
|
|
382
|
+
.execute();
|
|
383
|
+
|
|
384
|
+
const hasMore = rows.length > limit;
|
|
385
|
+
const items = rows.slice(0, limit).map((row) => this.rowToReference(row));
|
|
386
|
+
const result: FindManyResult<ContentReference> = { items };
|
|
387
|
+
const last = items.at(-1);
|
|
388
|
+
if (hasMore && last) {
|
|
389
|
+
result.nextCursor = encodeCursor(String(last.sortOrder), last.id);
|
|
390
|
+
}
|
|
391
|
+
return result;
|
|
392
|
+
}
|
|
393
|
+
|
|
322
394
|
/** Backlink traversal: the parents that reference a child for a relation. */
|
|
323
395
|
async getParents(relation: string, childGroup: string): Promise<ContentReference[]> {
|
|
324
396
|
const relationGroup = await this.resolveRelationGroup(relation);
|
|
@@ -346,6 +418,15 @@ export class RelationRepository {
|
|
|
346
418
|
* relying on the insert's onConflict to silently drop them. Not wrapped in a
|
|
347
419
|
* transaction: a crash between the delete and insert leaves the parent with
|
|
348
420
|
* no children — acceptable for a replace-all, since a retry restores state.
|
|
421
|
+
*
|
|
422
|
+
* Concurrency: two simultaneous replace-all calls for the same (relation,
|
|
423
|
+
* parent) can interleave their deletes and inserts and merge into the union of
|
|
424
|
+
* both sets (a lost update — neither "replace" wins). This is non-corrupting —
|
|
425
|
+
* keyset pagination stays totally ordered via the `(sort_order, id)` tiebreak
|
|
426
|
+
* even with duplicate sort_orders — and a single client editing one parent's
|
|
427
|
+
* children serially never hits it. A D1-portable fix isn't available (no
|
|
428
|
+
* multi-statement transactions), so concurrent replace-all on one parent is
|
|
429
|
+
* unsupported by design rather than guarded here.
|
|
349
430
|
*/
|
|
350
431
|
async setChildren(relation: string, parentGroup: string, childGroups: string[]): Promise<void> {
|
|
351
432
|
const relationGroup = await this.resolveRelationGroup(relation);
|
|
@@ -381,6 +462,50 @@ export class RelationRepository {
|
|
|
381
462
|
.execute();
|
|
382
463
|
}
|
|
383
464
|
|
|
465
|
+
/**
|
|
466
|
+
* Backlink traversal, paginated: one page of the parents that reference a
|
|
467
|
+
* child for a relation, ordered by `id`. Unlike a parent's children, a
|
|
468
|
+
* child's backlinks are *unbounded* — one popular entry can be referenced by
|
|
469
|
+
* arbitrarily many parents — so this read must paginate. Returns
|
|
470
|
+
* `{ items, nextCursor? }`; the cursor's order value is the row `id`. Default
|
|
471
|
+
* limit 50, max 100.
|
|
472
|
+
*/
|
|
473
|
+
async getParentsPage(
|
|
474
|
+
relation: string,
|
|
475
|
+
childGroup: string,
|
|
476
|
+
options: { limit?: number; cursor?: string } = {},
|
|
477
|
+
): Promise<FindManyResult<ContentReference>> {
|
|
478
|
+
const relationGroup = await this.resolveRelationGroup(relation);
|
|
479
|
+
if (!relationGroup) return { items: [] };
|
|
480
|
+
|
|
481
|
+
const limit = Math.min(options.limit || 50, 100);
|
|
482
|
+
|
|
483
|
+
let query = this.db
|
|
484
|
+
.selectFrom("_emdash_content_references")
|
|
485
|
+
.selectAll()
|
|
486
|
+
.where("relation_group", "=", relationGroup)
|
|
487
|
+
.where("child_group", "=", childGroup);
|
|
488
|
+
|
|
489
|
+
if (options.cursor) {
|
|
490
|
+
const decoded = decodeCursor(options.cursor);
|
|
491
|
+
query = query.where("id", ">", decoded.id);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const rows = await query
|
|
495
|
+
.orderBy("id", "asc")
|
|
496
|
+
.limit(limit + 1)
|
|
497
|
+
.execute();
|
|
498
|
+
|
|
499
|
+
const hasMore = rows.length > limit;
|
|
500
|
+
const items = rows.slice(0, limit).map((row) => this.rowToReference(row));
|
|
501
|
+
const result: FindManyResult<ContentReference> = { items };
|
|
502
|
+
const last = items.at(-1);
|
|
503
|
+
if (hasMore && last) {
|
|
504
|
+
result.nextCursor = encodeCursor(last.id, last.id);
|
|
505
|
+
}
|
|
506
|
+
return result;
|
|
507
|
+
}
|
|
508
|
+
|
|
384
509
|
/**
|
|
385
510
|
* Remove every edge where `group` is the parent OR the child — i.e. ensure no
|
|
386
511
|
* orphaned reference edges survive when a content entry is deleted. The
|
|
@@ -404,6 +404,12 @@ export class TaxonomyRepository {
|
|
|
404
404
|
/**
|
|
405
405
|
* Count content entries that use any translation of this term. Accepts
|
|
406
406
|
* either a term id or a translation_group — we normalise to the group.
|
|
407
|
+
*
|
|
408
|
+
* Counts raw pivot rows regardless of the entry's status or deletion —
|
|
409
|
+
* drafts and trashed entries are included. User-facing counts (admin term
|
|
410
|
+
* list/get, public widget and term pages) use `fetchVisibleTermCounts`
|
|
411
|
+
* from `taxonomies/term-counts.ts` instead, which counts only publicly
|
|
412
|
+
* visible entries.
|
|
407
413
|
*/
|
|
408
414
|
async countEntriesWithTerm(termIdOrGroup: string): Promise<number> {
|
|
409
415
|
const group = await this.resolveTranslationGroup(termIdOrGroup);
|
|
@@ -453,6 +459,9 @@ export class TaxonomyRepository {
|
|
|
453
459
|
*
|
|
454
460
|
* Pass translation_groups (not term ids) — `content_taxonomies.taxonomy_id`
|
|
455
461
|
* stores the translation_group so a single assignment spans every locale.
|
|
462
|
+
*
|
|
463
|
+
* Like `countEntriesWithTerm`, this counts raw pivot rows regardless of
|
|
464
|
+
* status/deletion; user-facing counts go through `fetchVisibleTermCounts`.
|
|
456
465
|
*/
|
|
457
466
|
async countEntriesForTerms(translationGroups: string[]): Promise<Map<string, number>> {
|
|
458
467
|
if (translationGroups.length === 0) return new Map();
|
|
@@ -158,6 +158,14 @@ export interface FindManyOptions {
|
|
|
158
158
|
* repository stays generic. Each name is validated as a SQL identifier.
|
|
159
159
|
*/
|
|
160
160
|
searchColumns?: string[];
|
|
161
|
+
/**
|
|
162
|
+
* Serve `q` from the collection's FTS5 index (`_emdash_fts_<slug>`)
|
|
163
|
+
* instead of an unindexable substring LIKE. Set by the handler only
|
|
164
|
+
* when the collection has search enabled and the index exists
|
|
165
|
+
* (SQLite only). The repository combines a token-prefix MATCH with
|
|
166
|
+
* an index-served slug prefix so slug lookups keep working.
|
|
167
|
+
*/
|
|
168
|
+
useFts?: boolean;
|
|
161
169
|
/** Inclusive date range over a whitelisted timestamp column. */
|
|
162
170
|
dateFilter?: ContentDateFilter;
|
|
163
171
|
};
|
package/src/db/postgres.ts
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* Loaded at runtime via virtual module.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { PostgresDialect } from "kysely";
|
|
8
|
+
import type { PostgresDialect } from "kysely";
|
|
9
9
|
import { Pool } from "pg";
|
|
10
10
|
|
|
11
|
+
import { FailFastPostgresDialect } from "../database/pg-migration-lock.js";
|
|
11
12
|
import type { PostgresConfig } from "./adapters.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -26,5 +27,7 @@ export function createDialect(config: PostgresConfig): PostgresDialect {
|
|
|
26
27
|
max: config.pool?.max ?? 10,
|
|
27
28
|
});
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
// Fail-fast migration locking instead of Kysely's blocking advisory
|
|
31
|
+
// lock — see pg-migration-lock.ts (#1744).
|
|
32
|
+
return new FailFastPostgresDialect({ pool });
|
|
30
33
|
}
|
package/src/emdash-runtime.ts
CHANGED
|
@@ -22,7 +22,11 @@ import { getAuthMode } from "./auth/mode.js";
|
|
|
22
22
|
import { getTrustedProxyHeaders } from "./auth/trusted-proxy.js";
|
|
23
23
|
import { isSqlite } from "./database/dialect-helpers.js";
|
|
24
24
|
import { kyselyLogOption } from "./database/instrumentation.js";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
ConcurrentMigrationTimeoutError,
|
|
27
|
+
MIGRATION_RACE_WAIT_MS,
|
|
28
|
+
runMigrations,
|
|
29
|
+
} from "./database/migrations/runner.js";
|
|
26
30
|
import { RevisionRepository } from "./database/repositories/revision.js";
|
|
27
31
|
import type {
|
|
28
32
|
ContentItem as ContentItemInternal,
|
|
@@ -385,18 +389,42 @@ const DB_HOLDER_KEY = Symbol.for("emdash:db-cache");
|
|
|
385
389
|
interface DbHolder {
|
|
386
390
|
cache: Map<string, Kysely<Database>>;
|
|
387
391
|
lock: InitLock;
|
|
392
|
+
/**
|
|
393
|
+
* Recent migration failures, keyed like `cache`. A failed migration is
|
|
394
|
+
* near-certain to fail again immediately (schema conflict, broken
|
|
395
|
+
* migration), and without this every request in a warm isolate would
|
|
396
|
+
* re-attempt it — on Workers with Postgres that stampedes the database
|
|
397
|
+
* through the migration advisory lock (#1744). Entries expire after
|
|
398
|
+
* DB_INIT_FAILURE_BACKOFF_MS; a successful init clears them.
|
|
399
|
+
*/
|
|
400
|
+
failures: Map<string, { at: number; message: string }>;
|
|
388
401
|
}
|
|
389
402
|
const globalSymbolStore = globalThis as Record<symbol, unknown>;
|
|
390
403
|
function getDbHolder(): DbHolder {
|
|
391
404
|
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis symbol slot, written only below
|
|
392
405
|
let holder = globalSymbolStore[DB_HOLDER_KEY] as DbHolder | undefined;
|
|
393
406
|
if (!holder) {
|
|
394
|
-
holder = {
|
|
407
|
+
holder = {
|
|
408
|
+
cache: new Map<string, Kysely<Database>>(),
|
|
409
|
+
lock: createInitLock(),
|
|
410
|
+
failures: new Map(),
|
|
411
|
+
};
|
|
395
412
|
globalSymbolStore[DB_HOLDER_KEY] = holder;
|
|
396
413
|
}
|
|
414
|
+
// A holder created by an older copy of this module (dev-server HMR keeps
|
|
415
|
+
// globalThis across reloads) may predate the failures map.
|
|
416
|
+
holder.failures ??= new Map();
|
|
397
417
|
return holder;
|
|
398
418
|
}
|
|
399
419
|
|
|
420
|
+
/**
|
|
421
|
+
* After a database init fails (migrations threw), skip re-attempting for
|
|
422
|
+
* this long. Cold isolates still get one attempt each, so a transient
|
|
423
|
+
* failure heals on its own; a persistently failing migration is retried at
|
|
424
|
+
* most once per backoff window per isolate instead of on every request.
|
|
425
|
+
*/
|
|
426
|
+
const DB_INIT_FAILURE_BACKOFF_MS = 30_000;
|
|
427
|
+
|
|
400
428
|
/**
|
|
401
429
|
* Auto-seed runs at most once per isolate per database. Its lock + "done" set
|
|
402
430
|
* live on globalThis (same bundler-duplication reasoning as the db cache) so a
|
|
@@ -1623,14 +1651,52 @@ export class EmDashRuntime {
|
|
|
1623
1651
|
// owner's init still completes and populates the cache. Net: a stale
|
|
1624
1652
|
// lock is reclaimed after a deadline.
|
|
1625
1653
|
const holder = getDbHolder();
|
|
1654
|
+
|
|
1655
|
+
const throwIfBackingOff = () => {
|
|
1656
|
+
const failure = holder.failures.get(cacheKey);
|
|
1657
|
+
if (!failure) return;
|
|
1658
|
+
if (Date.now() - failure.at < DB_INIT_FAILURE_BACKOFF_MS) {
|
|
1659
|
+
throw new Error(
|
|
1660
|
+
`Database initialization is backing off after a recent migration failure: ${failure.message}`,
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
// Expired — drop it so the map only ever holds active backoffs.
|
|
1664
|
+
holder.failures.delete(cacheKey);
|
|
1665
|
+
};
|
|
1666
|
+
throwIfBackingOff();
|
|
1667
|
+
|
|
1626
1668
|
return initWithLock(
|
|
1627
1669
|
holder.lock,
|
|
1628
1670
|
() => holder.cache.get(cacheKey),
|
|
1629
1671
|
async (isCurrentClaim) => {
|
|
1672
|
+
// Re-check under the lock: a request that entered the wait loop
|
|
1673
|
+
// before the failure was recorded must not immediately re-run
|
|
1674
|
+
// the failing migration when the lock frees up.
|
|
1675
|
+
throwIfBackingOff();
|
|
1676
|
+
|
|
1630
1677
|
const dialect = deps.createDialect(dbConfig.config);
|
|
1631
1678
|
const db = new Kysely<Database>({ dialect, log: kyselyLogOption() });
|
|
1632
1679
|
|
|
1633
|
-
|
|
1680
|
+
try {
|
|
1681
|
+
await runMigrations(db);
|
|
1682
|
+
} catch (error) {
|
|
1683
|
+
// Timing out behind another instance's in-flight migrations
|
|
1684
|
+
// is not a failure of OUR migration — the holder may just be
|
|
1685
|
+
// slow. Don't back off for it: the next request waits again
|
|
1686
|
+
// and init recovers the moment the holder finishes.
|
|
1687
|
+
if (!(error instanceof ConcurrentMigrationTimeoutError)) {
|
|
1688
|
+
holder.failures.set(cacheKey, {
|
|
1689
|
+
at: Date.now(),
|
|
1690
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
// Every attempt builds a fresh dialect/pool; close it or each
|
|
1694
|
+
// failed init leaks its connection(s) (#1744 observed these
|
|
1695
|
+
// piling up as idle Postgres connections).
|
|
1696
|
+
await db.destroy().catch(() => {});
|
|
1697
|
+
throw error;
|
|
1698
|
+
}
|
|
1699
|
+
holder.failures.delete(cacheKey);
|
|
1634
1700
|
|
|
1635
1701
|
// Note: legacy installs may carry a stray `emdash:manifest_cache`
|
|
1636
1702
|
// row in the options table from versions that persisted a JSON
|
|
@@ -2520,7 +2586,7 @@ export class EmDashRuntime {
|
|
|
2520
2586
|
...r.data,
|
|
2521
2587
|
item: { ...item, data: mergedData, liveData },
|
|
2522
2588
|
},
|
|
2523
|
-
}
|
|
2589
|
+
};
|
|
2524
2590
|
} catch (error) {
|
|
2525
2591
|
// Non-fatal — fall back to the unhydrated response. Log so the
|
|
2526
2592
|
// failure isn't completely silent (the response will look stale
|
|
@@ -2540,6 +2606,7 @@ export class EmDashRuntime {
|
|
|
2540
2606
|
bylines?: Array<{ bylineId: string; roleLabel?: string | null }>;
|
|
2541
2607
|
locale?: string;
|
|
2542
2608
|
translationOf?: string;
|
|
2609
|
+
taxonomies?: Record<string, string[]>;
|
|
2543
2610
|
},
|
|
2544
2611
|
) {
|
|
2545
2612
|
// Run beforeSave hooks (trusted plugins)
|
|
@@ -2604,6 +2671,7 @@ export class EmDashRuntime {
|
|
|
2604
2671
|
canonical?: string | null;
|
|
2605
2672
|
noIndex?: boolean;
|
|
2606
2673
|
};
|
|
2674
|
+
taxonomies?: Record<string, string[]>;
|
|
2607
2675
|
publishedAt?: string | null;
|
|
2608
2676
|
locale?: string;
|
|
2609
2677
|
/** Skip revision creation (used by autosave) */
|
package/src/index.ts
CHANGED
|
@@ -247,6 +247,10 @@ export type {
|
|
|
247
247
|
MediaAccess,
|
|
248
248
|
HttpAccess,
|
|
249
249
|
LogAccess,
|
|
250
|
+
TaxonomyAccess,
|
|
251
|
+
TaxonomyDefInfo,
|
|
252
|
+
TaxonomyTermInfo,
|
|
253
|
+
TaxonomyReadOptions,
|
|
250
254
|
PluginHooks,
|
|
251
255
|
HookConfig,
|
|
252
256
|
HookName,
|
|
@@ -404,8 +408,8 @@ export type {
|
|
|
404
408
|
} from "./settings/types.js";
|
|
405
409
|
|
|
406
410
|
// SEO
|
|
407
|
-
export { getSeoMeta, getContentSeo } from "./seo/index.js";
|
|
408
|
-
export type { SeoMeta, SeoMetaOptions } from "./seo/index.js";
|
|
411
|
+
export { getSeoMeta, getContentSeo, getHreflangAlternates } from "./seo/index.js";
|
|
412
|
+
export type { SeoMeta, SeoMetaOptions, HreflangAlternate, HreflangOptions } from "./seo/index.js";
|
|
409
413
|
|
|
410
414
|
// Public page contribution types
|
|
411
415
|
export type {
|