emdash 0.31.0 → 0.32.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/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +16 -14
- 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-EibxGP-V.mjs → api-DgPbMlng.mjs} +24 -20
- package/dist/api-DgPbMlng.mjs.map +1 -0
- package/dist/{api-tokens-uPt8UDpx.mjs → api-tokens-p-iMzvXR.mjs} +2 -2
- package/dist/{api-tokens-uPt8UDpx.mjs.map → api-tokens-p-iMzvXR.mjs.map} +1 -1
- package/dist/{apply-fGHCAwWN.mjs → apply-1_6ra7NP.mjs} +19 -19
- package/dist/{apply-fGHCAwWN.mjs.map → apply-1_6ra7NP.mjs.map} +1 -1
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.mjs +5 -1
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +5 -5
- package/dist/astro/middleware/redirect.mjs +5 -5
- package/dist/astro/middleware/request-context.mjs +1 -1
- package/dist/astro/middleware.d.mts +10 -10
- package/dist/astro/middleware.mjs +94 -61
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -8
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -8
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -8
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +15 -14
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +15 -14
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +15 -15
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +11 -11
- package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +9 -9
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +9 -9
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +12 -10
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +36 -34
- 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 +36 -34
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +36 -34
- 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 +37 -35
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +37 -35
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +36 -34
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +36 -34
- 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 +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +36 -34
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
- package/dist/astro/routes/api/admin/users/index.mjs +6 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +7 -7
- package/dist/astro/routes/api/auth/invite/index.mjs +7 -7
- package/dist/astro/routes/api/auth/invite/register-options.mjs +7 -7
- package/dist/astro/routes/api/auth/logout.mjs +3 -3
- package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -8
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/me.mjs +7 -7
- package/dist/astro/routes/api/auth/mode.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +8 -8
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +7 -7
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +7 -7
- package/dist/astro/routes/api/auth/passkey/verify.mjs +7 -7
- package/dist/astro/routes/api/auth/signup/complete.mjs +7 -7
- package/dist/astro/routes/api/auth/signup/request.mjs +8 -8
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +10 -10
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +16 -14
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +16 -14
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +14 -13
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/index.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
- package/dist/astro/routes/api/dashboard.mjs +7 -7
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +12 -12
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +12 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/media.mjs +7 -7
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +11 -9
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +12 -12
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +20 -19
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +3 -3
- package/dist/astro/routes/api/mcp.mjs +41 -41
- package/dist/astro/routes/api/media/_id_/confirm.d.mts.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +105 -36
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/upload.d.mts +8 -0
- package/dist/astro/routes/api/media/_id_/upload.d.mts.map +1 -0
- package/dist/astro/routes/api/media/_id_/upload.mjs +168 -0
- package/dist/astro/routes/api/media/_id_/upload.mjs.map +1 -0
- package/dist/astro/routes/api/media/_id_/usage.mjs +14 -12
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +21 -14
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
- package/dist/astro/routes/api/media/providers/index.mjs +3 -3
- package/dist/astro/routes/api/media/upload-url.d.mts.map +1 -1
- package/dist/astro/routes/api/media/upload-url.mjs +34 -23
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.mjs +13 -12
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -8
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +9 -8
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -8
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -8
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +9 -8
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +9 -8
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +5 -5
- package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/code.mjs +7 -7
- package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
- package/dist/astro/routes/api/oauth/register.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
- package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
- package/dist/astro/routes/api/oauth/token.mjs +6 -6
- package/dist/astro/routes/api/openapi.json.mjs +30 -8
- 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 +10 -10
- package/dist/astro/routes/api/redirects/404s/summary.mjs +10 -10
- package/dist/astro/routes/api/redirects/_id_.mjs +11 -11
- package/dist/astro/routes/api/redirects/index.mjs +11 -11
- package/dist/astro/routes/api/relations/_id_/index.mjs +16 -14
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +12 -10
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +16 -14
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +36 -34
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +36 -34
- 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 +36 -34
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +36 -34
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +36 -34
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +10 -8
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +36 -34
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +36 -34
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +12 -11
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +11 -10
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +12 -11
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +8 -7
- package/dist/astro/routes/api/search/stats.mjs.map +1 -1
- package/dist/astro/routes/api/search/suggest.mjs +11 -10
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +10 -10
- package/dist/astro/routes/api/sections/index.mjs +10 -10
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +4 -4
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +4 -4
- package/dist/astro/routes/api/settings/backups/export.mjs +4 -4
- package/dist/astro/routes/api/settings/backups/index.mjs +5 -5
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +12 -12
- package/dist/astro/routes/api/setup/admin-verify.mjs +8 -8
- package/dist/astro/routes/api/setup/admin.mjs +8 -8
- package/dist/astro/routes/api/setup/dev-bypass.mjs +24 -22
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +24 -22
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +3 -3
- package/dist/astro/routes/api/snapshot.mjs +5 -5
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +14 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +14 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +19 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +14 -13
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +4 -4
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +1 -1
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +7 -7
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +10 -10
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +10 -10
- package/dist/astro/routes/api/widget-areas/_name_.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/index.mjs +10 -10
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +5 -5
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +7 -7
- package/dist/astro/routes/sitemap.xml.mjs +5 -5
- package/dist/astro/types.d.mts +14 -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-6WPZa1xZ.mjs → authorize-R5iYYrpa.mjs} +2 -2
- package/dist/{authorize-6WPZa1xZ.mjs.map → authorize-R5iYYrpa.mjs.map} +1 -1
- package/dist/{backup-Qr9PaGUo.mjs → backup-LpQ1V_sR.mjs} +2 -2
- package/dist/{backup-Qr9PaGUo.mjs.map → backup-LpQ1V_sR.mjs.map} +1 -1
- package/dist/{byline-BTOxUlFF.mjs → byline-C5TAqs8N.mjs} +6 -6
- package/dist/{byline-BTOxUlFF.mjs.map → byline-C5TAqs8N.mjs.map} +1 -1
- package/dist/{byline-fields-CdU_LTF1.mjs → byline-fields-T9ZLZMxJ.mjs} +1 -1
- package/dist/{byline-fields-CdU_LTF1.mjs.map → byline-fields-T9ZLZMxJ.mjs.map} +1 -1
- package/dist/{bylines-FyZu6TbJ.mjs → bylines-B8-WGdja.mjs} +6 -6
- package/dist/{bylines-FyZu6TbJ.mjs.map → bylines-B8-WGdja.mjs.map} +1 -1
- package/dist/{bylines-oVN0iPwX.mjs → bylines-DGuqBLjV.mjs} +5 -5
- package/dist/{bylines-oVN0iPwX.mjs.map → bylines-DGuqBLjV.mjs.map} +1 -1
- package/dist/{cache-DDwy3JDW.mjs → cache-B26cufFd.mjs} +2 -2
- package/dist/{cache-DDwy3JDW.mjs.map → cache-B26cufFd.mjs.map} +1 -1
- package/dist/{chunks-Bq-5DPrD.mjs → chunks-D5dlPeRb.mjs} +2 -2
- package/dist/{chunks-Bq-5DPrD.mjs.map → chunks-D5dlPeRb.mjs.map} +1 -1
- package/dist/cli/index.mjs +20 -19
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +2 -2
- package/dist/{comment-B9cUud8H.mjs → comment-DnTxxVHv.mjs} +2 -2
- package/dist/{comment-B9cUud8H.mjs.map → comment-DnTxxVHv.mjs.map} +1 -1
- package/dist/{comment-reaction-VUXO981F.mjs → comment-reaction-BUlUz2bh.mjs} +2 -2
- package/dist/{comment-reaction-VUXO981F.mjs.map → comment-reaction-BUlUz2bh.mjs.map} +1 -1
- package/dist/{comments-PXj1E9Si.mjs → comments-QPKgK3nk.mjs} +3 -3
- package/dist/{comments-PXj1E9Si.mjs.map → comments-QPKgK3nk.mjs.map} +1 -1
- package/dist/{config-B6b_BobR.mjs → config-DyF3OKg_.mjs} +15 -10
- package/dist/config-DyF3OKg_.mjs.map +1 -0
- package/dist/{content-BC43pICM.mjs → content-CpfKV9QE.mjs} +9 -9
- package/dist/content-CpfKV9QE.mjs.map +1 -0
- package/dist/{content-refresh-CPMSauD3.mjs → content-refresh-DgqUBeTv.mjs} +5 -5
- package/dist/{content-refresh-CPMSauD3.mjs.map → content-refresh-DgqUBeTv.mjs.map} +1 -1
- package/dist/{context-DOurRIrb.mjs → context-kO4YZB03.mjs} +10 -10
- package/dist/{context-DOurRIrb.mjs.map → context-kO4YZB03.mjs.map} +1 -1
- package/dist/{dashboard-CBm4zhc3.mjs → dashboard-DoBwPnON.mjs} +4 -4
- package/dist/{dashboard-CBm4zhc3.mjs.map → dashboard-DoBwPnON.mjs.map} +1 -1
- package/dist/db/index.d.mts +2 -2
- package/dist/db/index.mjs +3 -2
- package/dist/db/index.mjs.map +1 -1
- package/dist/{device-flow-BeA6lUS1.mjs → device-flow-DhUsyJU6.mjs} +4 -4
- package/dist/{device-flow-BeA6lUS1.mjs.map → device-flow-DhUsyJU6.mjs.map} +1 -1
- package/dist/{dialect-helpers-BtOwo2us.mjs → dialect-helpers-DFwyWjTM.mjs} +21 -2
- package/dist/dialect-helpers-DFwyWjTM.mjs.map +1 -0
- package/dist/{error-DJ98TRbQ.mjs → error-DmmN74gW.mjs} +2 -2
- package/dist/{error-DJ98TRbQ.mjs.map → error-DmmN74gW.mjs.map} +1 -1
- package/dist/{escape-CFedIB1C.mjs → escape-CdW31WsG.mjs} +1 -1
- package/dist/{escape-CFedIB1C.mjs.map → escape-CdW31WsG.mjs.map} +1 -1
- package/dist/{field-defs-cache-KfNJ_qLQ.mjs → field-defs-cache-QMVnzTH6.mjs} +2 -2
- package/dist/{field-defs-cache-KfNJ_qLQ.mjs.map → field-defs-cache-QMVnzTH6.mjs.map} +1 -1
- package/dist/{fts-manager-hyCU9OOp.mjs → fts-manager-vncsZIJm.mjs} +3 -3
- package/dist/{fts-manager-hyCU9OOp.mjs.map → fts-manager-vncsZIJm.mjs.map} +1 -1
- package/dist/{hash-DFFrkivP.mjs → hash-Cb7U1b5M.mjs} +8 -4
- package/dist/hash-Cb7U1b5M.mjs.map +1 -0
- package/dist/{hreflang-CbYeCzl9.mjs → hreflang-Bg-zMpkr.mjs} +7 -7
- package/dist/{hreflang-CbYeCzl9.mjs.map → hreflang-Bg-zMpkr.mjs.map} +1 -1
- package/dist/{hreflang-CIxH_LKz.d.mts → hreflang-CZbSx6Bg.d.mts} +2 -2
- package/dist/{hreflang-CIxH_LKz.d.mts.map → hreflang-CZbSx6Bg.d.mts.map} +1 -1
- package/dist/{import-oDYCgNYQ.mjs → import-PKhLeXvn.mjs} +2 -2
- package/dist/{import-oDYCgNYQ.mjs.map → import-PKhLeXvn.mjs.map} +1 -1
- package/dist/{index-BEui-cRd.d.mts → index-BeNto_Vs.d.mts} +3 -3
- package/dist/{index-BEui-cRd.d.mts.map → index-BeNto_Vs.d.mts.map} +1 -1
- package/dist/{index-BcEH_FfS.d.mts → index-j9rTh3cp.d.mts} +68 -18
- package/dist/index-j9rTh3cp.d.mts.map +1 -0
- package/dist/index.d.mts +18 -18
- package/dist/index.mjs +49 -49
- package/dist/{load-Dg5gtWma.mjs → load-BwTdWE8B.mjs} +2 -2
- package/dist/{load-Dg5gtWma.mjs.map → load-BwTdWE8B.mjs.map} +1 -1
- package/dist/{loader-D4rigvjR.mjs → loader-C1XOLV5b.mjs} +4 -4
- package/dist/{loader-D4rigvjR.mjs.map → loader-C1XOLV5b.mjs.map} +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +5 -5
- package/dist/{media-BJ6SRY3g.mjs → media-DWIzoVFL.mjs} +8 -4
- package/dist/{media-BJ6SRY3g.mjs.map → media-DWIzoVFL.mjs.map} +1 -1
- package/dist/{media-allowlist-jUppPWFy.mjs → media-allowlist-B7TPD6aq.mjs} +1 -1
- package/dist/{media-allowlist-jUppPWFy.mjs.map → media-allowlist-B7TPD6aq.mjs.map} +1 -1
- package/dist/{media-its1WLYv.mjs → media-tQDZEdu7.mjs} +60 -15
- package/dist/media-tQDZEdu7.mjs.map +1 -0
- package/dist/{media-upload-DNu3QySc.mjs → media-upload-Bc9Nc5Zf.mjs} +6 -6
- package/dist/{media-upload-DNu3QySc.mjs.map → media-upload-Bc9Nc5Zf.mjs.map} +1 -1
- package/dist/{media-usage-DPQ3K4xB.mjs → media-usage-DPJcNaAq.mjs} +6 -6
- package/dist/{media-usage-DPQ3K4xB.mjs.map → media-usage-DPJcNaAq.mjs.map} +1 -1
- package/dist/{menus-BMGzWyWH.mjs → menus-BxPLFfIc.mjs} +3 -3
- package/dist/{menus-BMGzWyWH.mjs.map → menus-BxPLFfIc.mjs.map} +1 -1
- package/dist/{menus-CPf_SW7u.mjs → menus-C6qhqP4X.mjs} +8 -8
- package/dist/{menus-CPf_SW7u.mjs.map → menus-C6qhqP4X.mjs.map} +1 -1
- package/dist/{oauth-authorization-oqfbBuMH.mjs → oauth-authorization-C9tFinly.mjs} +4 -4
- package/dist/{oauth-authorization-oqfbBuMH.mjs.map → oauth-authorization-C9tFinly.mjs.map} +1 -1
- package/dist/{oauth-clients-BlrUHAsf.mjs → oauth-clients-BwTxE1aE.mjs} +1 -1
- package/dist/{oauth-clients-BlrUHAsf.mjs.map → oauth-clients-BwTxE1aE.mjs.map} +1 -1
- package/dist/{oauth-state-store-DnvjRMy6.mjs → oauth-state-store-DaRUwPWO.mjs} +1 -1
- package/dist/{oauth-state-store-DnvjRMy6.mjs.map → oauth-state-store-DaRUwPWO.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-oUllxvAv.mjs → oauth-user-lookup-CzuzOSlF.mjs} +1 -1
- package/dist/{oauth-user-lookup-oUllxvAv.mjs.map → oauth-user-lookup-CzuzOSlF.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{options-BqMkWfYa.d.mts → options-aeIs8WFu.d.mts} +3 -3
- package/dist/{options-BqMkWfYa.d.mts.map → options-aeIs8WFu.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-53zyxlpv.mjs → parse-BL49yb9D.mjs} +2 -2
- package/dist/{parse-53zyxlpv.mjs.map → parse-BL49yb9D.mjs.map} +1 -1
- package/dist/{passkey-config-C-SKpc0-.mjs → passkey-config-KMhgFjdQ.mjs} +1 -1
- package/dist/{passkey-config-C-SKpc0-.mjs.map → passkey-config-KMhgFjdQ.mjs.map} +1 -1
- package/dist/{placeholder-Dop47JMM.d.mts → placeholder-Dxo5Zt58.d.mts} +1 -1
- package/dist/{placeholder-Dop47JMM.d.mts.map → placeholder-Dxo5Zt58.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +1 -1
- package/dist/plugin-utils.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/{portable-text-sDj92Kxv.mjs → portable-text-CNahFfj6.mjs} +1 -1
- package/dist/{portable-text-sDj92Kxv.mjs.map → portable-text-CNahFfj6.mjs.map} +1 -1
- package/dist/{query-DdFGHzQF.mjs → query-1xOcEy18.mjs} +3 -3
- package/dist/{query-DdFGHzQF.mjs.map → query-1xOcEy18.mjs.map} +1 -1
- package/dist/{query-BbJQ-dGg.mjs → query-DCiXI7OZ.mjs} +36 -16
- package/dist/query-DCiXI7OZ.mjs.map +1 -0
- package/dist/{rate-limit-D3IEiUi2.mjs → rate-limit-Vkp9gQ1Y.mjs} +2 -2
- package/dist/{rate-limit-D3IEiUi2.mjs.map → rate-limit-Vkp9gQ1Y.mjs.map} +1 -1
- package/dist/{redirect-BoUac4NT.mjs → redirect-BJ6d1yHh.mjs} +3 -3
- package/dist/{redirect-BoUac4NT.mjs.map → redirect-BJ6d1yHh.mjs.map} +1 -1
- package/dist/{redirect-Botom7X6.mjs → redirect-CDgfv9vh.mjs} +1 -1
- package/dist/{redirect-Botom7X6.mjs.map → redirect-CDgfv9vh.mjs.map} +1 -1
- package/dist/{redirects-D457qwt0.mjs → redirects-BOn2DIUs.mjs} +8 -4
- package/dist/redirects-BOn2DIUs.mjs.map +1 -0
- package/dist/{redirects-ChbpqKiS.mjs → redirects-Cwkq2H-G.mjs} +3 -3
- package/dist/{redirects-ChbpqKiS.mjs.map → redirects-Cwkq2H-G.mjs.map} +1 -1
- package/dist/{registry-y21kjhfG.mjs → registry-BP1JK2xh.mjs} +6 -6
- package/dist/{registry-y21kjhfG.mjs.map → registry-BP1JK2xh.mjs.map} +1 -1
- package/dist/{relation-Du0r04E0.mjs → relation-DJ5DZh7B.mjs} +3 -3
- package/dist/{relation-Du0r04E0.mjs.map → relation-DJ5DZh7B.mjs.map} +1 -1
- package/dist/{relations-CZMpBqEd.mjs → relations-C4duJnwI.mjs} +2 -2
- package/dist/{relations-CZMpBqEd.mjs.map → relations-C4duJnwI.mjs.map} +1 -1
- package/dist/{relations-BKybBoOX.d.mts → relations-DHFQGX0h.d.mts} +19 -8
- package/dist/relations-DHFQGX0h.d.mts.map +1 -0
- package/dist/{relations-DtX1UMBH.mjs → relations-DpTjftCl.mjs} +6 -6
- package/dist/{relations-DtX1UMBH.mjs.map → relations-DpTjftCl.mjs.map} +1 -1
- package/dist/{resolve-DFr4kq72.mjs → resolve-BUvFE0Lr.mjs} +2 -2
- package/dist/{resolve-DFr4kq72.mjs.map → resolve-BUvFE0Lr.mjs.map} +1 -1
- package/dist/{runner-BdeLEgad.mjs → runner-BsI18UgP.mjs} +230 -212
- package/dist/runner-BsI18UgP.mjs.map +1 -0
- package/dist/{runner-Dd8m8k9F.d.mts → runner-CHdkERbt.d.mts} +2 -2
- package/dist/{runner-Dd8m8k9F.d.mts.map → runner-CHdkERbt.d.mts.map} +1 -1
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +3 -3
- package/dist/{schema-BH8P8vaC.mjs → schema-eqZhkR0S.mjs} +3 -3
- package/dist/{schema-BH8P8vaC.mjs.map → schema-eqZhkR0S.mjs.map} +1 -1
- package/dist/{scopes-DTIkIaGA.mjs → scopes-Be2d8bSb.mjs} +3 -3
- package/dist/{scopes-DTIkIaGA.mjs.map → scopes-Be2d8bSb.mjs.map} +1 -1
- package/dist/{search-D-Yhpmvs.mjs → search-CeO678cp.mjs} +6 -6
- package/dist/{search-D-Yhpmvs.mjs.map → search-CeO678cp.mjs.map} +1 -1
- package/dist/{secrets-CQ-69kF9.mjs → secrets-870d-7yA.mjs} +1 -1
- package/dist/{secrets-CQ-69kF9.mjs.map → secrets-870d-7yA.mjs.map} +1 -1
- package/dist/{sections-CzVBAKjw.mjs → sections-DSuEfirn.mjs} +3 -3
- package/dist/{sections-CzVBAKjw.mjs.map → sections-DSuEfirn.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +18 -16
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +14 -12
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-kJzVAmmu.mjs → seo-BAPKiED8.mjs} +2 -2
- package/dist/{seo-kJzVAmmu.mjs.map → seo-BAPKiED8.mjs.map} +1 -1
- package/dist/{service-CQnc276a.mjs → service-DyFT-k-R.mjs} +3 -3
- package/dist/{service-CQnc276a.mjs.map → service-DyFT-k-R.mjs.map} +1 -1
- package/dist/{session-user-DbHqKDKe.mjs → session-user-BrK2zz7S.mjs} +1 -1
- package/dist/{session-user-DbHqKDKe.mjs.map → session-user-BrK2zz7S.mjs.map} +1 -1
- package/dist/{settings-Dtc0DU31.mjs → settings-CREKyj8I.mjs} +3 -3
- package/dist/{settings-Dtc0DU31.mjs.map → settings-CREKyj8I.mjs.map} +1 -1
- package/dist/{settings-C2PaBS49.mjs → settings-DgKouY2S.mjs} +3 -3
- package/dist/{settings-C2PaBS49.mjs.map → settings-DgKouY2S.mjs.map} +1 -1
- package/dist/{setup-complete-CdIlqloh.mjs → setup-complete-L7bMK2VI.mjs} +1 -1
- package/dist/{setup-complete-CdIlqloh.mjs.map → setup-complete-L7bMK2VI.mjs.map} +1 -1
- package/dist/{setup-nonce-DqiIPr-J.mjs → setup-nonce-Ct5tjWcq.mjs} +1 -1
- package/dist/{setup-nonce-DqiIPr-J.mjs.map → setup-nonce-Ct5tjWcq.mjs.map} +1 -1
- package/dist/{site-url-NGJT6NTU.mjs → site-url-8N3kSyVZ.mjs} +1 -1
- package/dist/{site-url-NGJT6NTU.mjs.map → site-url-8N3kSyVZ.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/storage/s3.mjs.map +1 -1
- package/dist/{taxonomies-HI9fnTdp.mjs → taxonomies-B61CRSha.mjs} +94 -39
- package/dist/taxonomies-B61CRSha.mjs.map +1 -0
- package/dist/{taxonomies-rMeBzOjX.mjs → taxonomies-Dbdki3Un.mjs} +9 -8
- package/dist/taxonomies-Dbdki3Un.mjs.map +1 -0
- package/dist/{taxonomy-0mCI25HN.mjs → taxonomy-DvwWAPvA.mjs} +3 -3
- package/dist/{taxonomy-0mCI25HN.mjs.map → taxonomy-DvwWAPvA.mjs.map} +1 -1
- package/dist/{transport-CKrlqSpD.mjs → transport-BWQo0Foy.mjs} +1 -1
- package/dist/{transport-CKrlqSpD.mjs.map → transport-BWQo0Foy.mjs.map} +1 -1
- package/dist/{transport-Vd7VdqHv.d.mts → transport-DokJOScS.d.mts} +1 -1
- package/dist/{transport-Vd7VdqHv.d.mts.map → transport-DokJOScS.d.mts.map} +1 -1
- package/dist/{types-DPKhI5ib.d.mts → types-84Bque3-.d.mts} +9 -1
- package/dist/types-84Bque3-.d.mts.map +1 -0
- package/dist/{types-BvB7gDOD.d.mts → types-BQY7VYw6.d.mts} +2 -2
- package/dist/{types-BvB7gDOD.d.mts.map → types-BQY7VYw6.d.mts.map} +1 -1
- package/dist/{types-B4vm81VH.d.mts → types-C9P3ysxq.d.mts} +1 -1
- package/dist/{types-B4vm81VH.d.mts.map → types-C9P3ysxq.d.mts.map} +1 -1
- package/dist/{types-B97jg3aW.d.mts → types-CcSZCcF1.d.mts} +1 -1
- package/dist/{types-B97jg3aW.d.mts.map → types-CcSZCcF1.d.mts.map} +1 -1
- package/dist/{types-BNfPHfay.d.mts → types-DQLZ58GV.d.mts} +1 -1
- package/dist/{types-BNfPHfay.d.mts.map → types-DQLZ58GV.d.mts.map} +1 -1
- package/dist/{types-BfYUPJdP.d.mts → types-DqZVPILm.d.mts} +2 -2
- package/dist/{types-BfYUPJdP.d.mts.map → types-DqZVPILm.d.mts.map} +1 -1
- package/dist/{types-C7U0HlEr.d.mts → types-Dr2GLlwu.d.mts} +1 -1
- package/dist/{types-C7U0HlEr.d.mts.map → types-Dr2GLlwu.d.mts.map} +1 -1
- package/dist/{types-iVeZ5g6N.d.mts → types-DsAMyD_o.d.mts} +1 -1
- package/dist/{types-iVeZ5g6N.d.mts.map → types-DsAMyD_o.d.mts.map} +1 -1
- package/dist/{types-CrRUFdej.mjs → types-XrQQ-Aex.mjs} +2 -2
- package/dist/{types-CrRUFdej.mjs.map → types-XrQQ-Aex.mjs.map} +1 -1
- package/dist/{types-Kmaxdarz.d.mts → types-jISEalTX.d.mts} +1 -1
- package/dist/{types-Kmaxdarz.d.mts.map → types-jISEalTX.d.mts.map} +1 -1
- package/dist/upload-attempts-C5yd6Gae.mjs +27 -0
- package/dist/upload-attempts-C5yd6Gae.mjs.map +1 -0
- package/dist/{user-aTXqmXBz.mjs → user-BAumEmpA.mjs} +3 -3
- package/dist/{user-aTXqmXBz.mjs.map → user-BAumEmpA.mjs.map} +1 -1
- package/dist/{validate-CDT1jl6_.mjs → validate-Bs_wT2ul.mjs} +3 -3
- package/dist/{validate-CDT1jl6_.mjs.map → validate-Bs_wT2ul.mjs.map} +1 -1
- package/dist/{validate-DULfgpJP.d.mts → validate-CdYcY-Ln.d.mts} +5 -5
- package/dist/{validate-DULfgpJP.d.mts.map → validate-CdYcY-Ln.d.mts.map} +1 -1
- package/dist/{validation-DlD0E35W.mjs → validation-BngR0nit.mjs} +10 -8
- package/dist/{validation-DlD0E35W.mjs.map → validation-BngR0nit.mjs.map} +1 -1
- package/dist/version-Bdfb34kk.mjs +7 -0
- package/dist/{version-Ci6bw6YK.mjs.map → version-Bdfb34kk.mjs.map} +1 -1
- package/dist/{widgets-5fipNkMT.mjs → widgets-L-VndTKD.mjs} +2 -2
- package/dist/{widgets-5fipNkMT.mjs.map → widgets-L-VndTKD.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-BmUnBNgz.mjs → wxr-taxonomies-BexjtNid.mjs} +4 -4
- package/dist/{wxr-taxonomies-BmUnBNgz.mjs.map → wxr-taxonomies-BexjtNid.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-B4tMuN5T.d.mts → wxr-taxonomies-DueaLFd9.d.mts} +1 -1
- package/dist/{wxr-taxonomies-B4tMuN5T.d.mts.map → wxr-taxonomies-DueaLFd9.d.mts.map} +1 -1
- package/dist/{zod-generator-CwkHWz4f.mjs → zod-generator-DMzfga3g.mjs} +3 -3
- package/dist/{zod-generator-CwkHWz4f.mjs.map → zod-generator-DMzfga3g.mjs.map} +1 -1
- package/package.json +8 -7
- package/src/api/handlers/media.ts +4 -4
- package/src/api/handlers/taxonomies.ts +10 -9
- package/src/api/openapi/document.ts +36 -3
- package/src/api/schemas/media.ts +9 -2
- package/src/api/schemas/taxonomies.ts +16 -1
- package/src/astro/integration/routes.ts +5 -0
- package/src/astro/prefetch.ts +7 -2
- package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
- package/src/astro/routes/api/media/[id]/confirm.ts +148 -59
- package/src/astro/routes/api/media/[id]/upload.ts +262 -0
- package/src/astro/routes/api/media/[id].ts +19 -10
- package/src/astro/routes/api/media/upload-url.ts +28 -31
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +6 -3
- package/src/astro/types.ts +1 -0
- package/src/cleanup.ts +24 -1
- package/src/components/InlinePortableTextEditor.tsx +4 -0
- package/src/components/code-mark.ts +11 -0
- package/src/components/widgets/Categories.astro +1 -1
- package/src/components/widgets/Tags.astro +1 -1
- package/src/database/dialect-helpers.ts +38 -0
- package/src/database/migrations/054_media_upload_attempts.ts +41 -0
- package/src/database/migrations/runner.ts +2 -0
- package/src/database/repositories/content.ts +2 -5
- package/src/database/repositories/media.ts +158 -28
- package/src/database/types.ts +10 -0
- package/src/emdash-runtime.ts +13 -0
- package/src/i18n/config.ts +17 -10
- package/src/index.ts +1 -0
- package/src/media/upload-attempts.ts +33 -0
- package/src/query.ts +29 -2
- package/src/storage/s3.ts +1 -1
- package/src/taxonomies/index.ts +64 -23
- package/src/taxonomies/term-counts.ts +54 -24
- package/src/utils/hash.ts +14 -3
- package/dist/api-EibxGP-V.mjs.map +0 -1
- package/dist/config-B6b_BobR.mjs.map +0 -1
- package/dist/content-BC43pICM.mjs.map +0 -1
- package/dist/dialect-helpers-BtOwo2us.mjs.map +0 -1
- package/dist/hash-DFFrkivP.mjs.map +0 -1
- package/dist/index-BcEH_FfS.d.mts.map +0 -1
- package/dist/media-its1WLYv.mjs.map +0 -1
- package/dist/query-BbJQ-dGg.mjs.map +0 -1
- package/dist/redirects-D457qwt0.mjs.map +0 -1
- package/dist/relations-BKybBoOX.d.mts.map +0 -1
- package/dist/runner-BdeLEgad.mjs.map +0 -1
- package/dist/taxonomies-HI9fnTdp.mjs.map +0 -1
- package/dist/taxonomies-rMeBzOjX.mjs.map +0 -1
- package/dist/types-DPKhI5ib.d.mts.map +0 -1
- package/dist/version-Ci6bw6YK.mjs +0 -7
- /package/dist/{api-tokens-Cvmixds7.mjs → api-tokens-CEsW_jCg.mjs} +0 -0
|
@@ -11,7 +11,7 @@ import { requirePerm } from "#api/authorize.js";
|
|
|
11
11
|
import { apiError, handleError, requireDb, unwrapResult } from "#api/error.js";
|
|
12
12
|
import { handleTermCreate, handleTermList } from "#api/handlers/taxonomies.js";
|
|
13
13
|
import { isParseError, parseBody, parseQuery } from "#api/parse.js";
|
|
14
|
-
import { createTermBody,
|
|
14
|
+
import { createTermBody, termListQuery } from "#api/schemas.js";
|
|
15
15
|
|
|
16
16
|
export const prerender = false;
|
|
17
17
|
|
|
@@ -29,11 +29,14 @@ export const GET: APIRoute = async ({ params, request, locals }) => {
|
|
|
29
29
|
const denied = requirePerm(user, "taxonomies:read");
|
|
30
30
|
if (denied) return denied;
|
|
31
31
|
|
|
32
|
-
const query = parseQuery(new URL(request.url),
|
|
32
|
+
const query = parseQuery(new URL(request.url), termListQuery);
|
|
33
33
|
if (isParseError(query)) return query;
|
|
34
34
|
|
|
35
35
|
try {
|
|
36
|
-
const result = await handleTermList(emdash.db, name, {
|
|
36
|
+
const result = await handleTermList(emdash.db, name, {
|
|
37
|
+
locale: query.locale,
|
|
38
|
+
includeCounts: query.includeCounts,
|
|
39
|
+
});
|
|
37
40
|
return unwrapResult(result);
|
|
38
41
|
} catch (error) {
|
|
39
42
|
return handleError(error, "Failed to list terms", "TERM_LIST_ERROR");
|
package/src/astro/types.ts
CHANGED
package/src/cleanup.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { cleanupExpiredChallenges } from "./auth/challenge-store.js";
|
|
|
16
16
|
import { MediaRepository } from "./database/repositories/media.js";
|
|
17
17
|
import { RevisionRepository } from "./database/repositories/revision.js";
|
|
18
18
|
import type { Database } from "./database/types.js";
|
|
19
|
+
import { removeUploadAttempt } from "./media/upload-attempts.js";
|
|
19
20
|
import type { Storage } from "./storage/types.js";
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -27,6 +28,7 @@ export interface CleanupResult {
|
|
|
27
28
|
expiredTokens: number;
|
|
28
29
|
pendingUploads: number;
|
|
29
30
|
pendingUploadFiles: number;
|
|
31
|
+
uploadAttempts: number;
|
|
30
32
|
revisionsPruned: number;
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -56,6 +58,7 @@ export async function runSystemCleanup(
|
|
|
56
58
|
expiredTokens: -1,
|
|
57
59
|
pendingUploads: -1,
|
|
58
60
|
pendingUploadFiles: -1,
|
|
61
|
+
uploadAttempts: -1,
|
|
59
62
|
revisionsPruned: -1,
|
|
60
63
|
};
|
|
61
64
|
|
|
@@ -106,7 +109,27 @@ export async function runSystemCleanup(
|
|
|
106
109
|
console.error("[cleanup] Failed to clean pending uploads:", error);
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
// 4.
|
|
112
|
+
// 4. Uploaded objects that lost publication races or outlived their media row
|
|
113
|
+
try {
|
|
114
|
+
const mediaRepo = new MediaRepository(db);
|
|
115
|
+
const completedAttemptsDeleted = await mediaRepo.deleteCompletedUploadAttempts();
|
|
116
|
+
if (!storage) {
|
|
117
|
+
result.uploadAttempts = completedAttemptsDeleted;
|
|
118
|
+
} else {
|
|
119
|
+
const storageKeys = await mediaRepo.findUploadAttemptsForCleanup();
|
|
120
|
+
let attemptsDeleted = completedAttemptsDeleted;
|
|
121
|
+
for (const storageKey of storageKeys) {
|
|
122
|
+
if (await removeUploadAttempt(storage, mediaRepo, storageKey)) {
|
|
123
|
+
attemptsDeleted++;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
result.uploadAttempts = attemptsDeleted;
|
|
127
|
+
}
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error("[cleanup] Failed to clean media upload attempts:", error);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 5. Revision pruning -- trim entries with excessive revision counts
|
|
110
133
|
try {
|
|
111
134
|
result.revisionsPruned = await pruneExcessiveRevisions(db);
|
|
112
135
|
} catch (error) {
|
|
@@ -26,6 +26,7 @@ import * as React from "react";
|
|
|
26
26
|
import { createPortal } from "react-dom";
|
|
27
27
|
|
|
28
28
|
import { computeThumbnailSize } from "../media/thumbnail.js";
|
|
29
|
+
import { CodeMarkExtension } from "./code-mark.js";
|
|
29
30
|
import { InlineCodeBlockExtension } from "./inline-code-block.js";
|
|
30
31
|
|
|
31
32
|
// ── Portable Text types ────────────────────────────────────────────
|
|
@@ -1942,7 +1943,10 @@ export function InlinePortableTextEditor({
|
|
|
1942
1943
|
dropcursor: { color: "#3b82f6", width: 2 },
|
|
1943
1944
|
// Replaced with InlineCodeBlockExtension below (adds language picker).
|
|
1944
1945
|
codeBlock: false,
|
|
1946
|
+
// Replaced with CodeMarkExtension so inline code can combine with link/etc.
|
|
1947
|
+
code: false,
|
|
1945
1948
|
}),
|
|
1949
|
+
CodeMarkExtension,
|
|
1946
1950
|
InlineCodeBlockExtension,
|
|
1947
1951
|
Image.extend({
|
|
1948
1952
|
addAttributes() {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TipTap's default Code mark sets `excludes: '_'`, which drops every other
|
|
3
|
+
* mark on the same span. Portable Text allows decorator + annotation stacks
|
|
4
|
+
* (e.g. linked inline code), so override only that field.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Code from "@tiptap/extension-code";
|
|
8
|
+
|
|
9
|
+
export const CodeMarkExtension = Code.extend({
|
|
10
|
+
excludes: "",
|
|
11
|
+
});
|
|
@@ -12,7 +12,7 @@ interface Props {
|
|
|
12
12
|
|
|
13
13
|
const { showCount = true, hierarchical = true } = Astro.props;
|
|
14
14
|
|
|
15
|
-
const categories = await getTaxonomyTerms("category");
|
|
15
|
+
const categories = await getTaxonomyTerms("category", { includeCounts: showCount });
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
<ul class="widget-categories">
|
|
@@ -12,7 +12,7 @@ interface Props {
|
|
|
12
12
|
|
|
13
13
|
const { showCount = false, limit = 20 } = Astro.props;
|
|
14
14
|
|
|
15
|
-
const allTags = await getTaxonomyTerms("tag");
|
|
15
|
+
const allTags = await getTaxonomyTerms("tag", { includeCounts: showCount });
|
|
16
16
|
const tags = allTags.slice(0, limit);
|
|
17
17
|
---
|
|
18
18
|
|
|
@@ -37,6 +37,44 @@ export function isPostgres(db: Kysely<any>): boolean {
|
|
|
37
37
|
return detectDialect(db) === "postgres";
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Declared by an adapter whose backend caps the number of terms in a compound
|
|
42
|
+
* SELECT (`UNION ALL`, `INTERSECT`, `EXCEPT`). SQLite's own
|
|
43
|
+
* SQLITE_LIMIT_COMPOUND_SELECT default is 500 — high enough that no query
|
|
44
|
+
* EmDash builds approaches it — but Cloudflare D1 sets it to 5 and rejects
|
|
45
|
+
* anything larger with "too many terms in compound SELECT".
|
|
46
|
+
*/
|
|
47
|
+
export interface CompoundSelectLimitedAdapter {
|
|
48
|
+
/** Maximum terms per compound SELECT. Must be a positive integer. */
|
|
49
|
+
readonly compoundSelectLimit: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The backend's compound-SELECT ceiling, or null when it has none worth
|
|
54
|
+
* splitting statements for. Only the adapter knows: the limit is a property of
|
|
55
|
+
* the SQLite build behind the dialect, not of the SQL flavour, so two "sqlite"
|
|
56
|
+
* dialects can answer differently.
|
|
57
|
+
*
|
|
58
|
+
* A declared ceiling must be a positive integer — callers batch by it, and
|
|
59
|
+
* every other value silently misbehaves rather than failing: 0 and negatives
|
|
60
|
+
* never advance the batch cursor, fractions overlap batches and double-count,
|
|
61
|
+
* NaN yields an empty batch. A malformed declaration throws here, where the
|
|
62
|
+
* message can name the adapter.
|
|
63
|
+
*/
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance
|
|
65
|
+
export function compoundSelectLimit(db: Kysely<any>): number | null {
|
|
66
|
+
const adapter: object = db.getExecutor().adapter;
|
|
67
|
+
if (!("compoundSelectLimit" in adapter)) return null;
|
|
68
|
+
|
|
69
|
+
const limit: unknown = adapter.compoundSelectLimit;
|
|
70
|
+
if (typeof limit !== "number" || !Number.isInteger(limit) || limit < 1) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`${adapter.constructor.name} declares compoundSelectLimit ${String(limit)}; it must be a positive integer.`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return limit;
|
|
76
|
+
}
|
|
77
|
+
|
|
40
78
|
/**
|
|
41
79
|
* Default timestamp expression for column defaults.
|
|
42
80
|
* Wrapped in parens for use in CREATE TABLE ... DEFAULT (...).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
import { currentTimestamp } from "../dialect-helpers.js";
|
|
4
|
+
|
|
5
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
6
|
+
await db.schema
|
|
7
|
+
.createTable("_emdash_media_upload_attempts")
|
|
8
|
+
.ifNotExists()
|
|
9
|
+
.addColumn("storage_key", "text", (col) => col.primaryKey())
|
|
10
|
+
.addColumn("media_id", "text", (col) => col.notNull())
|
|
11
|
+
.addColumn("status", "text", (col) => col.notNull().defaultTo("active"))
|
|
12
|
+
.addColumn("created_at", "text", (col) => col.notNull().defaultTo(currentTimestamp(db)))
|
|
13
|
+
.addColumn("updated_at", "text", (col) => col.notNull().defaultTo(currentTimestamp(db)))
|
|
14
|
+
.execute();
|
|
15
|
+
|
|
16
|
+
await db.schema
|
|
17
|
+
.createIndex("idx_media_upload_attempts_media_id")
|
|
18
|
+
.ifNotExists()
|
|
19
|
+
.on("_emdash_media_upload_attempts")
|
|
20
|
+
.column("media_id")
|
|
21
|
+
.execute();
|
|
22
|
+
|
|
23
|
+
await db.schema
|
|
24
|
+
.createIndex("idx_media_upload_attempts_status_created_at")
|
|
25
|
+
.ifNotExists()
|
|
26
|
+
.on("_emdash_media_upload_attempts")
|
|
27
|
+
.columns(["status", "created_at"])
|
|
28
|
+
.execute();
|
|
29
|
+
|
|
30
|
+
await db.schema
|
|
31
|
+
.createIndex("idx_media_storage_key")
|
|
32
|
+
.ifNotExists()
|
|
33
|
+
.on("media")
|
|
34
|
+
.column("storage_key")
|
|
35
|
+
.execute();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
39
|
+
await db.schema.dropIndex("idx_media_storage_key").ifExists().execute();
|
|
40
|
+
await db.schema.dropTable("_emdash_media_upload_attempts").ifExists().execute();
|
|
41
|
+
}
|
|
@@ -56,6 +56,7 @@ import * as m050 from "./050_media_usage_index_status.js";
|
|
|
56
56
|
import * as m051 from "./051_content_taxonomies_denorm.js";
|
|
57
57
|
import * as m052 from "./052_media_usage_read_index.js";
|
|
58
58
|
import * as m053 from "./053_plugin_mcp_tools.js";
|
|
59
|
+
import * as m054 from "./054_media_upload_attempts.js";
|
|
59
60
|
|
|
60
61
|
const MIGRATIONS: Readonly<Record<string, Migration>> = Object.freeze({
|
|
61
62
|
"001_initial": m001,
|
|
@@ -110,6 +111,7 @@ const MIGRATIONS: Readonly<Record<string, Migration>> = Object.freeze({
|
|
|
110
111
|
"051_content_taxonomies_denorm": m051,
|
|
111
112
|
"052_media_usage_read_index": m052,
|
|
112
113
|
"053_plugin_mcp_tools": m053,
|
|
114
|
+
"054_media_upload_attempts": m054,
|
|
113
115
|
});
|
|
114
116
|
|
|
115
117
|
/** Total number of registered migrations. Exported for use in tests. */
|
|
@@ -322,6 +322,7 @@ export class ContentRepository {
|
|
|
322
322
|
data: newData,
|
|
323
323
|
status: "draft",
|
|
324
324
|
authorId: authorId || original.authorId || undefined,
|
|
325
|
+
locale: original.locale ?? undefined,
|
|
325
326
|
});
|
|
326
327
|
}
|
|
327
328
|
|
|
@@ -660,7 +661,7 @@ export class ContentRepository {
|
|
|
660
661
|
await this.restampEntryPivot(type, id);
|
|
661
662
|
}
|
|
662
663
|
|
|
663
|
-
invalidateCollectionCache(type);
|
|
664
|
+
if (hasColumnWrites) invalidateCollectionCache(type);
|
|
664
665
|
|
|
665
666
|
const updated = await this.findById(type, id);
|
|
666
667
|
if (!updated) {
|
|
@@ -1555,8 +1556,6 @@ export class ContentRepository {
|
|
|
1555
1556
|
WHERE id = ${id}
|
|
1556
1557
|
AND deleted_at IS NULL
|
|
1557
1558
|
`.execute(this.db);
|
|
1558
|
-
|
|
1559
|
-
invalidateCollectionCache(type);
|
|
1560
1559
|
}
|
|
1561
1560
|
|
|
1562
1561
|
/**
|
|
@@ -1588,8 +1587,6 @@ export class ContentRepository {
|
|
|
1588
1587
|
AND deleted_at IS NULL
|
|
1589
1588
|
`.execute(this.db);
|
|
1590
1589
|
|
|
1591
|
-
invalidateCollectionCache(type);
|
|
1592
|
-
|
|
1593
1590
|
const updated = await this.findById(type, id);
|
|
1594
1591
|
if (!updated) {
|
|
1595
1592
|
throw new Error("Content not found");
|
|
@@ -85,6 +85,9 @@ export interface FindManyMediaOptions {
|
|
|
85
85
|
q?: string;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
const UPLOAD_ATTEMPT_CLEANUP_AGE_MS = 60 * 60 * 1000;
|
|
89
|
+
const UPLOAD_ATTEMPT_CLEANUP_BATCH_SIZE = 100;
|
|
90
|
+
|
|
88
91
|
/**
|
|
89
92
|
* Media repository for database operations
|
|
90
93
|
*/
|
|
@@ -138,6 +141,129 @@ export class MediaRepository {
|
|
|
138
141
|
});
|
|
139
142
|
}
|
|
140
143
|
|
|
144
|
+
async createUploadAttempt(mediaId: string, storageKey: string): Promise<void> {
|
|
145
|
+
const now = new Date().toISOString();
|
|
146
|
+
await this.db
|
|
147
|
+
.insertInto("_emdash_media_upload_attempts")
|
|
148
|
+
.values({
|
|
149
|
+
media_id: mediaId,
|
|
150
|
+
storage_key: storageKey,
|
|
151
|
+
status: "active",
|
|
152
|
+
created_at: now,
|
|
153
|
+
updated_at: now,
|
|
154
|
+
})
|
|
155
|
+
.execute();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async hasUploadAttempt(storageKey: string): Promise<boolean> {
|
|
159
|
+
const row = await this.db
|
|
160
|
+
.selectFrom("_emdash_media_upload_attempts")
|
|
161
|
+
.select("storage_key")
|
|
162
|
+
.where("storage_key", "=", storageKey)
|
|
163
|
+
.executeTakeFirst();
|
|
164
|
+
return row !== undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async claimUploadAttemptForCleanup(storageKey: string): Promise<boolean> {
|
|
168
|
+
const result = await this.db
|
|
169
|
+
.updateTable("_emdash_media_upload_attempts")
|
|
170
|
+
.set({ status: "cleanup", updated_at: new Date().toISOString() })
|
|
171
|
+
.where("storage_key", "=", storageKey)
|
|
172
|
+
.where((eb) =>
|
|
173
|
+
eb.not(
|
|
174
|
+
eb.exists(
|
|
175
|
+
eb
|
|
176
|
+
.selectFrom("media")
|
|
177
|
+
.select("media.id")
|
|
178
|
+
.whereRef("media.storage_key", "=", "_emdash_media_upload_attempts.storage_key"),
|
|
179
|
+
),
|
|
180
|
+
),
|
|
181
|
+
)
|
|
182
|
+
.executeTakeFirst();
|
|
183
|
+
|
|
184
|
+
return Number(result.numUpdatedRows ?? 0) > 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async deleteUploadAttempt(storageKey: string): Promise<void> {
|
|
188
|
+
await this.db
|
|
189
|
+
.deleteFrom("_emdash_media_upload_attempts")
|
|
190
|
+
.where("storage_key", "=", storageKey)
|
|
191
|
+
.execute();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async deleteCompletedUploadAttempts(): Promise<number> {
|
|
195
|
+
const result = await this.db
|
|
196
|
+
.deleteFrom("_emdash_media_upload_attempts")
|
|
197
|
+
.where((eb) =>
|
|
198
|
+
eb.exists(
|
|
199
|
+
eb
|
|
200
|
+
.selectFrom("media")
|
|
201
|
+
.select("media.id")
|
|
202
|
+
.whereRef("media.id", "=", "_emdash_media_upload_attempts.media_id")
|
|
203
|
+
.whereRef("media.storage_key", "=", "_emdash_media_upload_attempts.storage_key")
|
|
204
|
+
.where("media.status", "=", "ready"),
|
|
205
|
+
),
|
|
206
|
+
)
|
|
207
|
+
.executeTakeFirst();
|
|
208
|
+
return Number(result.numDeletedRows ?? 0);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async findUploadAttemptsForCleanup(
|
|
212
|
+
maxAgeMs: number = UPLOAD_ATTEMPT_CLEANUP_AGE_MS,
|
|
213
|
+
limit: number = UPLOAD_ATTEMPT_CLEANUP_BATCH_SIZE,
|
|
214
|
+
): Promise<string[]> {
|
|
215
|
+
const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
|
|
216
|
+
const rows = await this.db
|
|
217
|
+
.selectFrom("_emdash_media_upload_attempts")
|
|
218
|
+
.select("storage_key")
|
|
219
|
+
.where((eb) => eb.or([eb("status", "=", "cleanup"), eb("created_at", "<", cutoff)]))
|
|
220
|
+
.where((eb) =>
|
|
221
|
+
eb.not(
|
|
222
|
+
eb.exists(
|
|
223
|
+
eb
|
|
224
|
+
.selectFrom("media")
|
|
225
|
+
.select("media.id")
|
|
226
|
+
.whereRef("media.storage_key", "=", "_emdash_media_upload_attempts.storage_key"),
|
|
227
|
+
),
|
|
228
|
+
),
|
|
229
|
+
)
|
|
230
|
+
.orderBy("created_at", "asc")
|
|
231
|
+
.limit(limit)
|
|
232
|
+
.execute();
|
|
233
|
+
|
|
234
|
+
return rows.map((row) => row.storage_key);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async publishPendingStorageKey(
|
|
238
|
+
id: string,
|
|
239
|
+
expectedStorageKey: string,
|
|
240
|
+
storageKey: string,
|
|
241
|
+
contentHash?: string,
|
|
242
|
+
): Promise<boolean> {
|
|
243
|
+
const result = await this.db
|
|
244
|
+
.updateTable("media")
|
|
245
|
+
.set({
|
|
246
|
+
storage_key: storageKey,
|
|
247
|
+
...(contentHash !== undefined ? { content_hash: contentHash } : {}),
|
|
248
|
+
})
|
|
249
|
+
.where("id", "=", id)
|
|
250
|
+
.where("status", "=", "pending")
|
|
251
|
+
.where("storage_key", "=", expectedStorageKey)
|
|
252
|
+
.where((eb) =>
|
|
253
|
+
eb.exists(
|
|
254
|
+
eb
|
|
255
|
+
.selectFrom("_emdash_media_upload_attempts")
|
|
256
|
+
.select("storage_key")
|
|
257
|
+
.where("media_id", "=", id)
|
|
258
|
+
.where("storage_key", "=", storageKey)
|
|
259
|
+
.where("status", "=", "active"),
|
|
260
|
+
),
|
|
261
|
+
)
|
|
262
|
+
.executeTakeFirst();
|
|
263
|
+
|
|
264
|
+
return Number(result.numUpdatedRows ?? 0) > 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
141
267
|
/**
|
|
142
268
|
* Confirm upload (mark as ready)
|
|
143
269
|
*/
|
|
@@ -149,13 +275,10 @@ export class MediaRepository {
|
|
|
149
275
|
size?: number;
|
|
150
276
|
blurhash?: string;
|
|
151
277
|
dominantColor?: string;
|
|
278
|
+
contentHash?: string | null;
|
|
152
279
|
},
|
|
280
|
+
expectedStorageKey?: string,
|
|
153
281
|
): Promise<MediaItem | null> {
|
|
154
|
-
const existing = await this.findById(id);
|
|
155
|
-
if (!existing) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
282
|
const updates: Partial<MediaRow> = {
|
|
160
283
|
status: "ready",
|
|
161
284
|
};
|
|
@@ -164,24 +287,33 @@ export class MediaRepository {
|
|
|
164
287
|
if (metadata?.size !== undefined) updates.size = metadata.size;
|
|
165
288
|
if (metadata?.blurhash !== undefined) updates.blurhash = metadata.blurhash;
|
|
166
289
|
if (metadata?.dominantColor !== undefined) updates.dominant_color = metadata.dominantColor;
|
|
290
|
+
if (metadata?.contentHash !== undefined) updates.content_hash = metadata.contentHash;
|
|
167
291
|
|
|
168
|
-
|
|
292
|
+
let query = this.db
|
|
293
|
+
.updateTable("media")
|
|
294
|
+
.set(updates)
|
|
295
|
+
.where("id", "=", id)
|
|
296
|
+
.where("status", "=", "pending");
|
|
297
|
+
if (expectedStorageKey !== undefined) {
|
|
298
|
+
query = query.where("storage_key", "=", expectedStorageKey);
|
|
299
|
+
}
|
|
169
300
|
|
|
170
|
-
|
|
301
|
+
const row = await query.returningAll().executeTakeFirst();
|
|
302
|
+
|
|
303
|
+
return row ? this.rowToItem(row) : null;
|
|
171
304
|
}
|
|
172
305
|
|
|
173
306
|
/**
|
|
174
307
|
* Mark upload as failed
|
|
175
308
|
*/
|
|
176
|
-
async markFailed(id: string): Promise<MediaItem | null> {
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
|
|
309
|
+
async markFailed(id: string, expectedStorageKey?: string): Promise<MediaItem | null> {
|
|
310
|
+
let query = this.db.updateTable("media").set({ status: "failed" }).where("id", "=", id);
|
|
311
|
+
if (expectedStorageKey !== undefined) {
|
|
312
|
+
query = query.where("status", "=", "pending").where("storage_key", "=", expectedStorageKey);
|
|
180
313
|
}
|
|
181
314
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return this.findById(id);
|
|
315
|
+
const row = await query.returningAll().executeTakeFirst();
|
|
316
|
+
return row ? this.rowToItem(row) : null;
|
|
185
317
|
}
|
|
186
318
|
|
|
187
319
|
/**
|
|
@@ -319,10 +451,18 @@ export class MediaRepository {
|
|
|
319
451
|
/**
|
|
320
452
|
* Delete media item
|
|
321
453
|
*/
|
|
322
|
-
async
|
|
323
|
-
const
|
|
454
|
+
async deleteWithStorageKey(id: string): Promise<string | null> {
|
|
455
|
+
const deleted = await this.db
|
|
456
|
+
.deleteFrom("media")
|
|
457
|
+
.where("id", "=", id)
|
|
458
|
+
.returning("storage_key")
|
|
459
|
+
.executeTakeFirst();
|
|
460
|
+
if (deleted) return deleted.storage_key;
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
324
463
|
|
|
325
|
-
|
|
464
|
+
async delete(id: string): Promise<boolean> {
|
|
465
|
+
return (await this.deleteWithStorageKey(id)) !== null;
|
|
326
466
|
}
|
|
327
467
|
|
|
328
468
|
/**
|
|
@@ -350,21 +490,11 @@ export class MediaRepository {
|
|
|
350
490
|
async cleanupPendingUploads(maxAgeMs: number = 60 * 60 * 1000): Promise<string[]> {
|
|
351
491
|
const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
|
|
352
492
|
|
|
353
|
-
// Select the storage keys first -- SQLite doesn't support RETURNING
|
|
354
|
-
// on DELETE in all drivers, and Kysely's RETURNING isn't universal.
|
|
355
493
|
const rows = await this.db
|
|
356
|
-
.selectFrom("media")
|
|
357
|
-
.select("storage_key")
|
|
358
|
-
.where("status", "=", "pending")
|
|
359
|
-
.where("created_at", "<", cutoff)
|
|
360
|
-
.execute();
|
|
361
|
-
|
|
362
|
-
if (rows.length === 0) return [];
|
|
363
|
-
|
|
364
|
-
await this.db
|
|
365
494
|
.deleteFrom("media")
|
|
366
495
|
.where("status", "=", "pending")
|
|
367
496
|
.where("created_at", "<", cutoff)
|
|
497
|
+
.returning("storage_key")
|
|
368
498
|
.execute();
|
|
369
499
|
|
|
370
500
|
return rows.map((r) => r.storage_key);
|
package/src/database/types.ts
CHANGED
|
@@ -81,6 +81,15 @@ export interface MediaTable {
|
|
|
81
81
|
author_id: string | null;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
export interface MediaUploadAttemptTable {
|
|
85
|
+
storage_key: string;
|
|
86
|
+
// No foreign key: this row must survive media deletion until storage cleanup succeeds.
|
|
87
|
+
media_id: string;
|
|
88
|
+
status: string; // 'active' | 'cleanup'
|
|
89
|
+
created_at: Generated<string>;
|
|
90
|
+
updated_at: Generated<string>;
|
|
91
|
+
}
|
|
92
|
+
|
|
84
93
|
export interface MediaUsageSourceTable {
|
|
85
94
|
source_key: string;
|
|
86
95
|
source_type: string;
|
|
@@ -495,6 +504,7 @@ export interface Database {
|
|
|
495
504
|
content_taxonomies: ContentTaxonomyTable;
|
|
496
505
|
_emdash_taxonomy_defs: TaxonomyDefTable;
|
|
497
506
|
media: MediaTable;
|
|
507
|
+
_emdash_media_upload_attempts: MediaUploadAttemptTable;
|
|
498
508
|
_emdash_media_usage_sources: MediaUsageSourceTable;
|
|
499
509
|
_emdash_media_usage: MediaUsageTable;
|
|
500
510
|
_emdash_media_usage_index_status: MediaUsageIndexStatusTable;
|
package/src/emdash-runtime.ts
CHANGED
|
@@ -225,6 +225,8 @@ const FIELD_TYPE_TO_KIND: Record<FieldType, string> = {
|
|
|
225
225
|
repeater: "repeater",
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
+
const DRAFT_ONLY_UPDATE_KEYS = new Set(["data", "slug", "locale", "skipRevision"]);
|
|
229
|
+
|
|
228
230
|
/**
|
|
229
231
|
* Sandboxed plugin entry from virtual module
|
|
230
232
|
*/
|
|
@@ -2909,6 +2911,14 @@ export class EmDashRuntime {
|
|
|
2909
2911
|
bylines: bodyWithoutRev.bylines,
|
|
2910
2912
|
});
|
|
2911
2913
|
|
|
2914
|
+
// Public HTML comes from live columns / SEO / taxonomies, not draft revisions.
|
|
2915
|
+
const liveMetaTouched = Object.entries(bodyWithoutRev).some(
|
|
2916
|
+
([key, value]) => value !== undefined && !DRAFT_ONLY_UPDATE_KEYS.has(key),
|
|
2917
|
+
);
|
|
2918
|
+
const liveContentChanged = usesDraftRevisions
|
|
2919
|
+
? liveMetaTouched
|
|
2920
|
+
: Boolean(processedData || bodyWithoutRev.slug !== undefined || liveMetaTouched);
|
|
2921
|
+
|
|
2912
2922
|
// Hydrate draft data BEFORE firing afterSave hooks so the hook sees
|
|
2913
2923
|
// the same effective data the response surfaces — for revision-
|
|
2914
2924
|
// supporting collections, that's the just-saved draft, not the live
|
|
@@ -2957,6 +2967,9 @@ export class EmDashRuntime {
|
|
|
2957
2967
|
this.runAfterSaveHooks(contentItemToRecord(hydrated.data.item), collection, false);
|
|
2958
2968
|
}
|
|
2959
2969
|
|
|
2970
|
+
if (hydrated.success) {
|
|
2971
|
+
return { ...hydrated, liveContentChanged };
|
|
2972
|
+
}
|
|
2960
2973
|
return hydrated;
|
|
2961
2974
|
}
|
|
2962
2975
|
|
package/src/i18n/config.ts
CHANGED
|
@@ -12,14 +12,18 @@ export interface I18nConfig {
|
|
|
12
12
|
prefixDefaultLocale?: boolean;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const I18N_CONFIG_KEY = Symbol.for("emdash:i18n-config");
|
|
16
|
+
|
|
17
|
+
function configStore(): Record<symbol, I18nConfig | null | undefined> {
|
|
18
|
+
return globalThis;
|
|
19
|
+
}
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
22
|
* Initialize i18n config from virtual module data.
|
|
19
23
|
* Called during runtime initialization.
|
|
20
24
|
*/
|
|
21
25
|
export function setI18nConfig(config: I18nConfig | null): void {
|
|
22
|
-
|
|
26
|
+
configStore()[I18N_CONFIG_KEY] = config;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
/**
|
|
@@ -27,13 +31,14 @@ export function setI18nConfig(config: I18nConfig | null): void {
|
|
|
27
31
|
* Returns null if i18n is not configured.
|
|
28
32
|
*/
|
|
29
33
|
export function getI18nConfig(): I18nConfig | null {
|
|
30
|
-
return
|
|
34
|
+
return configStore()[I18N_CONFIG_KEY] ?? null;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
/** Match a locale to the exact casing used by the site configuration. */
|
|
34
38
|
export function resolveConfiguredLocale(locale: string): string {
|
|
39
|
+
const config = getI18nConfig();
|
|
35
40
|
return (
|
|
36
|
-
|
|
41
|
+
config?.locales.find((configured) => configured.toLowerCase() === locale.toLowerCase()) ??
|
|
37
42
|
locale
|
|
38
43
|
);
|
|
39
44
|
}
|
|
@@ -43,7 +48,8 @@ export function resolveConfiguredLocale(locale: string): string {
|
|
|
43
48
|
* Returns true when multiple locales are configured.
|
|
44
49
|
*/
|
|
45
50
|
export function isI18nEnabled(): boolean {
|
|
46
|
-
|
|
51
|
+
const config = getI18nConfig();
|
|
52
|
+
return config != null && config.locales.length > 1;
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/**
|
|
@@ -52,15 +58,16 @@ export function isI18nEnabled(): boolean {
|
|
|
52
58
|
* Always ends with defaultLocale.
|
|
53
59
|
*/
|
|
54
60
|
export function getFallbackChain(locale: string): string[] {
|
|
55
|
-
|
|
61
|
+
const config = getI18nConfig();
|
|
62
|
+
if (!config) return [locale];
|
|
56
63
|
|
|
57
64
|
const chain: string[] = [locale];
|
|
58
65
|
let current = locale;
|
|
59
66
|
const visited = new Set<string>([locale]);
|
|
60
67
|
|
|
61
|
-
while (
|
|
68
|
+
while (config.fallback?.[current]) {
|
|
62
69
|
// eslint-disable-next-line typescript/no-unnecessary-type-assertion -- noUncheckedIndexedAccess
|
|
63
|
-
const next =
|
|
70
|
+
const next = config.fallback[current]!;
|
|
64
71
|
if (visited.has(next)) break; // prevent cycles
|
|
65
72
|
chain.push(next);
|
|
66
73
|
visited.add(next);
|
|
@@ -68,8 +75,8 @@ export function getFallbackChain(locale: string): string[] {
|
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
// Always end with defaultLocale if not already in chain
|
|
71
|
-
if (!visited.has(
|
|
72
|
-
chain.push(
|
|
78
|
+
if (!visited.has(config.defaultLocale)) {
|
|
79
|
+
chain.push(config.defaultLocale);
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
return chain;
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ export type {
|
|
|
28
28
|
FindManyResult,
|
|
29
29
|
} from "./database/repositories/index.js";
|
|
30
30
|
export type { MediaItem, CreateMediaInput } from "./database/repositories/media.js";
|
|
31
|
+
export type { CompoundSelectLimitedAdapter } from "./database/dialect-helpers.js";
|
|
31
32
|
|
|
32
33
|
// Fields
|
|
33
34
|
export { portableText, image, file, reference } from "./fields/index.js";
|