emdash 0.28.0 → 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-BFURZn1i.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-Bu-8nYHL.mjs → apply-D23iUV4q.mjs} +20 -20
- package/dist/{apply-Bu-8nYHL.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_.d.mts.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +7 -15
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
- 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-Woq87129.mjs → bylines-CHojDMpj.mjs} +8 -8
- package/dist/{bylines-Woq87129.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-CA4uKwzH.mjs → content-refresh-BkkApzeS.mjs} +20 -14
- package/dist/content-refresh-BkkApzeS.mjs.map +1 -0
- package/dist/{context-CUsR9dXL.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-CsZ2ZEK2.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-Blhoxp3P.mjs → query-BxT95opY.mjs} +5 -10
- package/dist/query-BxT95opY.mjs.map +1 -0
- package/dist/{query-ByGq6ver.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-B65mUtPa.mjs → registry-CyIXPi4E.mjs} +8 -8
- package/dist/{registry-B65mUtPa.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-Cgrt9-aL.d.mts → relations-CbBpoOys.d.mts} +180 -27
- 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-BGBd16Eu.mjs → taxonomies-ClS4RKaZ.mjs} +13 -9
- package/dist/taxonomies-ClS4RKaZ.mjs.map +1 -0
- package/dist/{taxonomies-Cnb4F-Pb.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-c8WjhH8z.mjs → validation-DM2K_NJC.mjs} +10 -10
- package/dist/{validation-c8WjhH8z.mjs.map → validation-DM2K_NJC.mjs.map} +1 -1
- package/dist/version-BlIJvNAZ.mjs +7 -0
- package/dist/{version-CaccU7DM.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-BC3OYpvx.mjs → wxr-taxonomies-oNJB2S81.mjs} +4 -4
- package/dist/{wxr-taxonomies-BC3OYpvx.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/plugins/[pluginId]/[...path].ts +17 -15
- 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-usage.ts +25 -3
- 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/media/usage/content-repair.ts +206 -22
- package/src/media/usage/content-snapshots.ts +4 -0
- 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-BFURZn1i.mjs.map +0 -1
- package/dist/byline-fields-2Lp5Hbgf.mjs.map +0 -1
- package/dist/byline-fields-Cgrt9-aL.d.mts.map +0 -1
- package/dist/content-DhgEth4k.mjs.map +0 -1
- package/dist/content-refresh-CA4uKwzH.mjs.map +0 -1
- package/dist/context-CUsR9dXL.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-CsZ2ZEK2.mjs.map +0 -1
- package/dist/query-ByGq6ver.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-Blhoxp3P.mjs.map +0 -1
- package/dist/search-DZN2HZ-V.mjs.map +0 -1
- package/dist/taxonomies-BGBd16Eu.mjs.map +0 -1
- package/dist/taxonomies-Cnb4F-Pb.mjs.map +0 -1
- package/dist/types-CGbYowGQ.d.mts.map +0 -1
- package/dist/version-CaccU7DM.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
|
*
|
|
@@ -496,7 +496,7 @@ export class MediaUsageRepository {
|
|
|
496
496
|
.executeTakeFirst();
|
|
497
497
|
deleted = Number(result.numDeletedRows ?? 0) > 0;
|
|
498
498
|
if (!deleted) return;
|
|
499
|
-
await
|
|
499
|
+
await this.deleteSourceGenerationOccurrences(trx, sourceKey, expectedCurrentGeneration);
|
|
500
500
|
});
|
|
501
501
|
|
|
502
502
|
return {
|
|
@@ -518,7 +518,11 @@ export class MediaUsageRepository {
|
|
|
518
518
|
.executeTakeFirst();
|
|
519
519
|
deleted = Number(result.numDeletedRows ?? 0) > 0;
|
|
520
520
|
if (!deleted) return;
|
|
521
|
-
await
|
|
521
|
+
await this.deleteSourceGenerationOccurrences(
|
|
522
|
+
trx,
|
|
523
|
+
sourceKey,
|
|
524
|
+
expectedSource.currentGeneration,
|
|
525
|
+
);
|
|
522
526
|
});
|
|
523
527
|
|
|
524
528
|
return {
|
|
@@ -547,7 +551,11 @@ export class MediaUsageRepository {
|
|
|
547
551
|
.executeTakeFirst();
|
|
548
552
|
deleted = Number(result.numDeletedRows ?? 0) > 0;
|
|
549
553
|
if (!deleted) return;
|
|
550
|
-
await
|
|
554
|
+
await this.deleteSourceGenerationOccurrences(
|
|
555
|
+
trx,
|
|
556
|
+
sourceKey,
|
|
557
|
+
expectedSource.currentGeneration,
|
|
558
|
+
);
|
|
551
559
|
});
|
|
552
560
|
const contentPresent = deleted ? false : await this.contentRowExists(tableName, contentId);
|
|
553
561
|
|
|
@@ -903,6 +911,20 @@ export class MediaUsageRepository {
|
|
|
903
911
|
});
|
|
904
912
|
}
|
|
905
913
|
|
|
914
|
+
private async deleteSourceGenerationOccurrences(
|
|
915
|
+
db: DatabaseExecutor,
|
|
916
|
+
sourceKey: string,
|
|
917
|
+
generation: string,
|
|
918
|
+
): Promise<void> {
|
|
919
|
+
// Guarded source deletes remove only the generation that won the source CAS;
|
|
920
|
+
// unmatched generations become invisible orphans reclaimed by age-gated cleanup.
|
|
921
|
+
await db
|
|
922
|
+
.deleteFrom("_emdash_media_usage")
|
|
923
|
+
.where("source_key", "=", sourceKey)
|
|
924
|
+
.where("generation", "=", generation)
|
|
925
|
+
.execute();
|
|
926
|
+
}
|
|
927
|
+
|
|
906
928
|
private async insertOccurrences(
|
|
907
929
|
db: DatabaseExecutor,
|
|
908
930
|
sourceKey: string,
|
|
@@ -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
|
}
|