emdash 0.32.0 → 0.34.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-C0ONzkUP.d.mts → adapters-34EN2eXO.d.mts} +34 -2
- package/dist/adapters-34EN2eXO.d.mts.map +1 -0
- package/dist/after-CBU2vkoO.mjs +96 -0
- package/dist/after-CBU2vkoO.mjs.map +1 -0
- package/dist/{allowed-origins-CCEi9bPI.mjs → allowed-origins-DW7sYyqg.mjs} +2 -2
- package/dist/{allowed-origins-CCEi9bPI.mjs.map → allowed-origins-DW7sYyqg.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -4
- package/dist/api/route-utils.d.mts.map +1 -1
- package/dist/api/route-utils.mjs +26 -25
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +6 -5
- package/dist/{api-DgPbMlng.mjs → api-DdAsirBe.mjs} +321 -428
- package/dist/api-DdAsirBe.mjs.map +1 -0
- package/dist/{api-tokens-p-iMzvXR.mjs → api-tokens-CFXu8F_2.mjs} +2 -2
- package/dist/{api-tokens-p-iMzvXR.mjs.map → api-tokens-CFXu8F_2.mjs.map} +1 -1
- package/dist/{apply-1_6ra7NP.mjs → apply-D5zfeD09.mjs} +139 -102
- package/dist/apply-D5zfeD09.mjs.map +1 -0
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +103 -35
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +9 -9
- package/dist/astro/middleware/media-usage-write-fence.d.mts +7 -0
- package/dist/astro/middleware/media-usage-write-fence.d.mts.map +1 -0
- package/dist/astro/middleware/media-usage-write-fence.mjs +35 -0
- package/dist/astro/middleware/media-usage-write-fence.mjs.map +1 -0
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +13 -10
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.mjs +5 -5
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +12 -11
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +1915 -223
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +9 -8
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +9 -8
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
- 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 +12 -11
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +12 -11
- package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +12 -11
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +20 -20
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +20 -20
- package/dist/astro/routes/api/admin/bylines/index.mjs +20 -20
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -17
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/bulk.mjs +14 -13
- package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/index.mjs +14 -13
- 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/collection-deletions/index.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +36 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +36 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +15 -14
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/work/index.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/work/index.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +37 -0
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +37 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.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.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +6 -6
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +52 -46
- 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 +52 -46
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +52 -46
- 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 +52 -46
- 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 +10 -9
- package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/index.mjs +9 -8
- package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.mjs +8 -8
- package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/complete.mjs +14 -13
- package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/index.mjs +12 -11
- package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/register-options.mjs +13 -12
- package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/logout.mjs +4 -4
- package/dist/astro/routes/api/auth/magic-link/send.mjs +14 -13
- package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
- package/dist/astro/routes/api/auth/me.mjs +10 -9
- package/dist/astro/routes/api/auth/me.mjs.map +1 -1
- package/dist/astro/routes/api/auth/mode.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +9 -8
- package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/options.mjs +15 -14
- package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +13 -12
- package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +14 -13
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/verify.mjs +14 -13
- package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/complete.mjs +14 -13
- package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/request.mjs +14 -13
- package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +20 -19
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +17 -16
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +21 -20
- 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 +21 -20
- 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 +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +47 -34
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/index.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/trash.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
- package/dist/astro/routes/api/dashboard.mjs +12 -10
- package/dist/astro/routes/api/dashboard.mjs.map +1 -1
- 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 +22 -20
- package/dist/astro/routes/api/import/probe.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +18 -18
- 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 +14 -12
- package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +13 -12
- package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +15 -15
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +22 -20
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +32 -31
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +6 -6
- package/dist/astro/routes/api/mcp.d.mts.map +1 -1
- package/dist/astro/routes/api/mcp.mjs +174 -72
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +14 -12
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/upload.mjs +7 -7
- package/dist/astro/routes/api/media/_id_/usage.mjs +17 -16
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +16 -15
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- 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 +11 -10
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.mjs +19 -16
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_/items.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_/translations.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_.mjs +13 -13
- package/dist/astro/routes/api/menus/index.mjs +13 -13
- 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 +183 -6
- 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 +8 -7
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/index.mjs +14 -13
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +14 -13
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +16 -14
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +16 -14
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.mjs +21 -20
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +16 -15
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +21 -20
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +52 -46
- 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 +52 -46
- 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 +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.d.mts +8 -0
- package/dist/astro/routes/api/schema/collections/reorder.d.mts.map +1 -0
- package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -0
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -0
- package/dist/astro/routes/api/schema/index.mjs +14 -11
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +52 -46
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +52 -46
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.d.mts +1 -0
- package/dist/astro/routes/api/search/enable.d.mts.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +19 -15
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +13 -13
- package/dist/astro/routes/api/search/rebuild.mjs +15 -15
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +9 -9
- package/dist/astro/routes/api/search/suggest.mjs +13 -13
- package/dist/astro/routes/api/sections/_slug_.mjs +13 -12
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +13 -12
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +8 -8
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
- package/dist/astro/routes/api/settings/backups/export.mjs +8 -8
- package/dist/astro/routes/api/settings/backups/index.mjs +9 -9
- package/dist/astro/routes/api/settings/email.mjs +6 -6
- package/dist/astro/routes/api/settings.mjs +18 -17
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin-verify.mjs +15 -14
- package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin.mjs +14 -13
- package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +34 -32
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
- package/dist/astro/routes/api/setup/index.mjs +36 -34
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +5 -5
- package/dist/astro/routes/api/snapshot.mjs +10 -10
- package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts +8 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +44 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +19 -18
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +19 -18
- 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 +21 -19
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts +8 -0
- package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +46 -0
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_.d.mts +19 -0
- package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_.mjs +88 -0
- package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -0
- package/dist/astro/routes/api/taxonomies/index.mjs +19 -18
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +8 -8
- 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 +10 -9
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +8 -7
- package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
- package/dist/astro/routes/api/widget-components.mjs +4 -4
- package/dist/astro/routes/robots.txt.mjs +11 -10
- package/dist/astro/routes/robots.txt.mjs.map +1 -1
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +14 -14
- package/dist/astro/routes/sitemap.xml.mjs +12 -11
- package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
- package/dist/astro/types.d.mts +41 -17
- 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-R5iYYrpa.mjs → authorize-1iFJzPaZ.mjs} +2 -2
- package/dist/{authorize-R5iYYrpa.mjs.map → authorize-1iFJzPaZ.mjs.map} +1 -1
- package/dist/{backup-LpQ1V_sR.mjs → backup-LHjIAVNP.mjs} +5 -5
- package/dist/{backup-LpQ1V_sR.mjs.map → backup-LHjIAVNP.mjs.map} +1 -1
- package/dist/{base64-B-PsqheR.mjs → base64-CvLhUKQv.mjs} +1 -1
- package/dist/{base64-B-PsqheR.mjs.map → base64-CvLhUKQv.mjs.map} +1 -1
- package/dist/bundle-CBEXrBnb.mjs +663 -0
- package/dist/bundle-CBEXrBnb.mjs.map +1 -0
- package/dist/{byline-fields-T9ZLZMxJ.mjs → byline-fields-C5S8wygO.mjs} +2 -2
- package/dist/{byline-fields-T9ZLZMxJ.mjs.map → byline-fields-C5S8wygO.mjs.map} +1 -1
- package/dist/{byline-C5TAqs8N.mjs → byline-pEcoDps8.mjs} +9 -9
- package/dist/{byline-C5TAqs8N.mjs.map → byline-pEcoDps8.mjs.map} +1 -1
- package/dist/{byline-registry-BCuOp4UF.mjs → byline-registry-DDun8sxh.mjs} +4 -4
- package/dist/{byline-registry-BCuOp4UF.mjs.map → byline-registry-DDun8sxh.mjs.map} +1 -1
- package/dist/{bylines-B8-WGdja.mjs → bylines-BWemdX2k.mjs} +8 -8
- package/dist/{bylines-B8-WGdja.mjs.map → bylines-BWemdX2k.mjs.map} +1 -1
- package/dist/{bylines-DGuqBLjV.mjs → bylines-DJfSfXCL.mjs} +5 -5
- package/dist/{bylines-DGuqBLjV.mjs.map → bylines-DJfSfXCL.mjs.map} +1 -1
- package/dist/cache-CBJaDy_E.mjs +108 -0
- package/dist/cache-CBJaDy_E.mjs.map +1 -0
- package/dist/{challenge-store-BFzgFRog.mjs → challenge-store-CZyFVaad.mjs} +1 -1
- package/dist/{challenge-store-BFzgFRog.mjs.map → challenge-store-CZyFVaad.mjs.map} +1 -1
- package/dist/{chunks-D5dlPeRb.mjs → chunks-DfPax1I0.mjs} +2 -2
- package/dist/{chunks-D5dlPeRb.mjs.map → chunks-DfPax1I0.mjs.map} +1 -1
- package/dist/cli/index.mjs +193 -707
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +74 -4
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +25 -2
- package/dist/client/index.mjs.map +1 -1
- package/dist/collection-deletion-C8BugSGz.mjs +779 -0
- package/dist/collection-deletion-C8BugSGz.mjs.map +1 -0
- package/dist/{comment-DnTxxVHv.mjs → comment-Dxlep6cE.mjs} +3 -3
- package/dist/{comment-DnTxxVHv.mjs.map → comment-Dxlep6cE.mjs.map} +1 -1
- package/dist/{comment-reaction-BUlUz2bh.mjs → comment-reaction-D6qfHKBc.mjs} +2 -2
- package/dist/{comment-reaction-BUlUz2bh.mjs.map → comment-reaction-D6qfHKBc.mjs.map} +1 -1
- package/dist/{comments-QPKgK3nk.mjs → comments-CTOuhTSX.mjs} +3 -3
- package/dist/{comments-QPKgK3nk.mjs.map → comments-CTOuhTSX.mjs.map} +1 -1
- package/dist/{components-DZkL4Fx0.mjs → components-CQy3lh9x.mjs} +1 -1
- package/dist/{components-DZkL4Fx0.mjs.map → components-CQy3lh9x.mjs.map} +1 -1
- package/dist/{config-DyF3OKg_.mjs → config-C3EBstHi.mjs} +18 -2
- package/dist/config-C3EBstHi.mjs.map +1 -0
- package/dist/{content-CpfKV9QE.mjs → content-BNfwh7xX.mjs} +667 -183
- package/dist/content-BNfwh7xX.mjs.map +1 -0
- package/dist/content-list-query-DhQ84eVV.d.mts +26 -0
- package/dist/content-list-query-DhQ84eVV.d.mts.map +1 -0
- package/dist/content-refresh-DNERP4-f.mjs +2560 -0
- package/dist/content-refresh-DNERP4-f.mjs.map +1 -0
- package/dist/{context-kO4YZB03.mjs → context-DRgOvSnW.mjs} +28 -20
- package/dist/context-DRgOvSnW.mjs.map +1 -0
- package/dist/{cron-BlKIMD_e.mjs → cron-Y9aLtgrA.mjs} +1 -1
- package/dist/{cron-BlKIMD_e.mjs.map → cron-Y9aLtgrA.mjs.map} +1 -1
- package/dist/{dashboard-DoBwPnON.mjs → dashboard-CB8J89rJ.mjs} +45 -11
- package/dist/dashboard-CB8J89rJ.mjs.map +1 -0
- package/dist/db/index.d.mts +4 -4
- package/dist/db/index.mjs +3 -3
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{db-errors-CcWLaRiR.mjs → db-errors-Cl-sKYTm.mjs} +1 -1
- package/dist/{db-errors-CcWLaRiR.mjs.map → db-errors-Cl-sKYTm.mjs.map} +1 -1
- package/dist/{default-C4v9KP56.mjs → default-DdDl3fxv.mjs} +1 -1
- package/dist/{default-C4v9KP56.mjs.map → default-DdDl3fxv.mjs.map} +1 -1
- package/dist/deferred-tasks-BMsa9F64.d.mts +9 -0
- package/dist/deferred-tasks-BMsa9F64.d.mts.map +1 -0
- package/dist/{device-flow-DhUsyJU6.mjs → device-flow-CaioYGK3.mjs} +5 -5
- package/dist/{device-flow-DhUsyJU6.mjs.map → device-flow-CaioYGK3.mjs.map} +1 -1
- package/dist/{dialect-helpers-DFwyWjTM.mjs → dialect-helpers-BSbfaO3F.mjs} +24 -16
- package/dist/dialect-helpers-BSbfaO3F.mjs.map +1 -0
- package/dist/dist-D_6CKR8z.mjs +810 -0
- package/dist/dist-D_6CKR8z.mjs.map +1 -0
- package/dist/{email-console-C-9Ng8DM.mjs → email-console-BHNjIwiB.mjs} +1 -1
- package/dist/{email-console-C-9Ng8DM.mjs.map → email-console-BHNjIwiB.mjs.map} +1 -1
- package/dist/{enrich-CFJJgxs_.mjs → enrich-_ySMEvEE.mjs} +2 -2
- package/dist/{enrich-CFJJgxs_.mjs.map → enrich-_ySMEvEE.mjs.map} +1 -1
- package/dist/{error-DmmN74gW.mjs → error-DupyJZE2.mjs} +3 -3
- package/dist/{error-DmmN74gW.mjs.map → error-DupyJZE2.mjs.map} +1 -1
- package/dist/{errors-DtEXIQQV.mjs → errors-CLUPm7aD.mjs} +15 -2
- package/dist/errors-CLUPm7aD.mjs.map +1 -0
- package/dist/{escape-CdW31WsG.mjs → escape-C_aLKP3H.mjs} +1 -1
- package/dist/{escape-CdW31WsG.mjs.map → escape-C_aLKP3H.mjs.map} +1 -1
- package/dist/{field-defs-cache-QMVnzTH6.mjs → field-defs-cache-hg6QkjV9.mjs} +5 -5
- package/dist/{field-defs-cache-QMVnzTH6.mjs.map → field-defs-cache-hg6QkjV9.mjs.map} +1 -1
- package/dist/{fts-manager-vncsZIJm.mjs → fts-manager-CZ-5dVwJ.mjs} +111 -61
- package/dist/fts-manager-CZ-5dVwJ.mjs.map +1 -0
- package/dist/{hash-Cb7U1b5M.mjs → hash-Cg0TXJPV.mjs} +1 -1
- package/dist/{hash-Cb7U1b5M.mjs.map → hash-Cg0TXJPV.mjs.map} +1 -1
- package/dist/{hreflang-CZbSx6Bg.d.mts → hreflang-D3Uehfv2.d.mts} +2 -2
- package/dist/{hreflang-CZbSx6Bg.d.mts.map → hreflang-D3Uehfv2.d.mts.map} +1 -1
- package/dist/{hreflang-Bg-zMpkr.mjs → hreflang-DNswoYsi.mjs} +7 -7
- package/dist/{hreflang-Bg-zMpkr.mjs.map → hreflang-DNswoYsi.mjs.map} +1 -1
- package/dist/{import-PKhLeXvn.mjs → import-B41u8Rot.mjs} +7 -7
- package/dist/{import-PKhLeXvn.mjs.map → import-B41u8Rot.mjs.map} +1 -1
- package/dist/{index-j9rTh3cp.d.mts → index-C3Y-rsyN.d.mts} +286 -93
- package/dist/index-C3Y-rsyN.d.mts.map +1 -0
- package/dist/{index-BeNto_Vs.d.mts → index-Cof4-Fab.d.mts} +5 -10
- package/dist/index-Cof4-Fab.d.mts.map +1 -0
- package/dist/index.d.mts +20 -19
- package/dist/index.mjs +79 -71
- package/dist/{init-lock-DJkX6Hto.mjs → init-lock-6b309ZrF.mjs} +1 -1
- package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-6b309ZrF.mjs.map} +1 -1
- package/dist/{load-BwTdWE8B.mjs → load-DmvJrtxS.mjs} +2 -2
- package/dist/{load-BwTdWE8B.mjs.map → load-DmvJrtxS.mjs.map} +1 -1
- package/dist/{loader-C1XOLV5b.mjs → loader-DLBqRiGP.mjs} +120 -64
- package/dist/loader-DLBqRiGP.mjs.map +1 -0
- package/dist/{manifest-schema-bCq54i7F.mjs → manifest-schema-BXbUAHod.mjs} +1 -1
- package/dist/{manifest-schema-bCq54i7F.mjs.map → manifest-schema-BXbUAHod.mjs.map} +1 -1
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +3 -2
- package/dist/media/index.mjs.map +1 -1
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +10 -9
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/{media-DWIzoVFL.mjs → media-BWWWb8kg.mjs} +92 -3
- package/dist/media-BWWWb8kg.mjs.map +1 -0
- package/dist/{media-tQDZEdu7.mjs → media-CzhAn2--.mjs} +2 -2
- package/dist/{media-tQDZEdu7.mjs.map → media-CzhAn2--.mjs.map} +1 -1
- package/dist/{media-allowlist-B7TPD6aq.mjs → media-allowlist-BD6HhgXA.mjs} +14 -3
- package/dist/media-allowlist-BD6HhgXA.mjs.map +1 -0
- package/dist/{media-upload-Bc9Nc5Zf.mjs → media-upload-9yas9zGH.mjs} +11 -9
- package/dist/{media-upload-Bc9Nc5Zf.mjs.map → media-upload-9yas9zGH.mjs.map} +1 -1
- package/dist/{media-url-BCm5vBn6.mjs → media-url-BvoX88FA.mjs} +1 -1
- package/dist/{media-url-BCm5vBn6.mjs.map → media-url-BvoX88FA.mjs.map} +1 -1
- package/dist/{media-usage-DPJcNaAq.mjs → media-usage-De3qvwjc.mjs} +138 -61
- package/dist/media-usage-De3qvwjc.mjs.map +1 -0
- package/dist/media-usage-work-B9Bksh_b.mjs +152 -0
- package/dist/media-usage-work-B9Bksh_b.mjs.map +1 -0
- package/dist/media-usage-work-DrCbqBcl.mjs +424 -0
- package/dist/media-usage-work-DrCbqBcl.mjs.map +1 -0
- package/dist/media-usage-write-fence-aHEgN1zB.mjs +42 -0
- package/dist/media-usage-write-fence-aHEgN1zB.mjs.map +1 -0
- package/dist/{menus-C6qhqP4X.mjs → menus-CC-yn1F9.mjs} +554 -121
- package/dist/menus-CC-yn1F9.mjs.map +1 -0
- package/dist/{menus-BxPLFfIc.mjs → menus-fxvEDYE6.mjs} +5 -5
- package/dist/{menus-BxPLFfIc.mjs.map → menus-fxvEDYE6.mjs.map} +1 -1
- package/dist/{mode-fiXRMfeA.mjs → mode-Bpe-tNNy.mjs} +1 -1
- package/dist/{mode-fiXRMfeA.mjs.map → mode-Bpe-tNNy.mjs.map} +1 -1
- package/dist/{normalize-C-SHXmra.mjs → normalize-Bc-s_r-a.mjs} +1 -1
- package/dist/{normalize-C-SHXmra.mjs.map → normalize-Bc-s_r-a.mjs.map} +1 -1
- package/dist/{oauth-authorization-C9tFinly.mjs → oauth-authorization-BXO1MKej.mjs} +5 -5
- package/dist/{oauth-authorization-C9tFinly.mjs.map → oauth-authorization-BXO1MKej.mjs.map} +1 -1
- package/dist/{oauth-clients-BwTxE1aE.mjs → oauth-clients-C_DNqtRu.mjs} +1 -1
- package/dist/{oauth-clients-BwTxE1aE.mjs.map → oauth-clients-C_DNqtRu.mjs.map} +1 -1
- package/dist/{oauth-state-store-DaRUwPWO.mjs → oauth-state-store-DwAxMtk4.mjs} +1 -1
- package/dist/{oauth-state-store-DaRUwPWO.mjs.map → oauth-state-store-DwAxMtk4.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-CzuzOSlF.mjs → oauth-user-lookup-BxfZizdk.mjs} +1 -1
- package/dist/{oauth-user-lookup-CzuzOSlF.mjs.map → oauth-user-lookup-BxfZizdk.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-Bok5j2ae.mjs → object-cache-71tPfV4A.mjs} +106 -5
- package/dist/object-cache-71tPfV4A.mjs.map +1 -0
- package/dist/{options-BlmBHTvX.mjs → options-CBXIHUoT.mjs} +1 -1
- package/dist/{options-BlmBHTvX.mjs.map → options-CBXIHUoT.mjs.map} +1 -1
- package/dist/{options-aeIs8WFu.d.mts → options-DRe1pIBL.d.mts} +4 -3
- package/dist/options-DRe1pIBL.d.mts.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-BL49yb9D.mjs → parse-DFbuc-Fh.mjs} +2 -2
- package/dist/{parse-BL49yb9D.mjs.map → parse-DFbuc-Fh.mjs.map} +1 -1
- package/dist/{passkey-config-KMhgFjdQ.mjs → passkey-config-_2GOwwK8.mjs} +1 -1
- package/dist/{passkey-config-KMhgFjdQ.mjs.map → passkey-config-_2GOwwK8.mjs.map} +1 -1
- package/dist/{placeholder-Dxo5Zt58.d.mts → placeholder-CzW7Lshs.d.mts} +1 -1
- package/dist/{placeholder-Dxo5Zt58.d.mts.map → placeholder-CzW7Lshs.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +8 -1
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-utils.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.mjs +7 -4
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/{portable-text-CNahFfj6.mjs → portable-text-DhKbDAGr.mjs} +1 -1
- package/dist/{portable-text-CNahFfj6.mjs.map → portable-text-DhKbDAGr.mjs.map} +1 -1
- package/dist/{preview-D4Jnbfx7.mjs → preview-PW-nOnq4.mjs} +2 -2
- package/dist/{preview-D4Jnbfx7.mjs.map → preview-PW-nOnq4.mjs.map} +1 -1
- package/dist/{public-url-DSGTnJFw.mjs → public-url-CWoFhQT8.mjs} +14 -3
- package/dist/public-url-CWoFhQT8.mjs.map +1 -0
- package/dist/{query-DCiXI7OZ.mjs → query-BgjfiLUQ.mjs} +38 -77
- package/dist/query-BgjfiLUQ.mjs.map +1 -0
- package/dist/{query-1xOcEy18.mjs → query-vgZNwIhh.mjs} +4 -4
- package/dist/{query-1xOcEy18.mjs.map → query-vgZNwIhh.mjs.map} +1 -1
- package/dist/{rate-limit-Vkp9gQ1Y.mjs → rate-limit-L5anykgo.mjs} +2 -2
- package/dist/{rate-limit-Vkp9gQ1Y.mjs.map → rate-limit-L5anykgo.mjs.map} +1 -1
- package/dist/{redirect-BJ6d1yHh.mjs → redirect-COsS6SWJ.mjs} +3 -3
- package/dist/{redirect-BJ6d1yHh.mjs.map → redirect-COsS6SWJ.mjs.map} +1 -1
- package/dist/{redirect-CDgfv9vh.mjs → redirect-KBNE3UEs.mjs} +1 -1
- package/dist/{redirect-CDgfv9vh.mjs.map → redirect-KBNE3UEs.mjs.map} +1 -1
- package/dist/{redirects-Cwkq2H-G.mjs → redirects-CufRQt0Q.mjs} +5 -5
- package/dist/{redirects-Cwkq2H-G.mjs.map → redirects-CufRQt0Q.mjs.map} +1 -1
- package/dist/{redirects-BOn2DIUs.mjs → redirects-cV9g7V-0.mjs} +149 -16
- package/dist/redirects-cV9g7V-0.mjs.map +1 -0
- package/dist/registry-C581V4TP.mjs +1275 -0
- package/dist/registry-C581V4TP.mjs.map +1 -0
- package/dist/{relation-DJ5DZh7B.mjs → relation-DtmAQH7s.mjs} +3 -3
- package/dist/{relation-DJ5DZh7B.mjs.map → relation-DtmAQH7s.mjs.map} +1 -1
- package/dist/{relations-C4duJnwI.mjs → relations-BBApI4e2.mjs} +3 -3
- package/dist/{relations-C4duJnwI.mjs.map → relations-BBApI4e2.mjs.map} +1 -1
- package/dist/{relations-DpTjftCl.mjs → relations-DICSyfsh.mjs} +6 -6
- package/dist/{relations-DpTjftCl.mjs.map → relations-DICSyfsh.mjs.map} +1 -1
- package/dist/{relations-DHFQGX0h.d.mts → relations-DItI3MN9.d.mts} +401 -40
- package/dist/relations-DItI3MN9.d.mts.map +1 -0
- package/dist/request-context.d.mts +3 -0
- package/dist/request-context.d.mts.map +1 -1
- package/dist/request-context.mjs.map +1 -1
- package/dist/{request-meta-DzXYYI-n.mjs → request-meta-DgZJh3zG.mjs} +2 -2
- package/dist/{request-meta-DzXYYI-n.mjs.map → request-meta-DgZJh3zG.mjs.map} +1 -1
- package/dist/{resolve-BUvFE0Lr.mjs → resolve-DOhVEvty.mjs} +2 -2
- package/dist/{resolve-BUvFE0Lr.mjs.map → resolve-DOhVEvty.mjs.map} +1 -1
- package/dist/{runner-BsI18UgP.mjs → runner-BiDvq5dv.mjs} +1404 -235
- package/dist/runner-BiDvq5dv.mjs.map +1 -0
- package/dist/{runner-CHdkERbt.d.mts → runner-CgQbELYC.d.mts} +2 -2
- package/dist/{runner-CHdkERbt.d.mts.map → runner-CgQbELYC.d.mts.map} +1 -1
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +5 -4
- package/dist/runtime.mjs.map +1 -1
- package/dist/{schema-eqZhkR0S.mjs → schema-BFyTg38T.mjs} +3 -3
- package/dist/{schema-eqZhkR0S.mjs.map → schema-BFyTg38T.mjs.map} +1 -1
- package/dist/schema-CeQSNwB3.mjs +390 -0
- package/dist/schema-CeQSNwB3.mjs.map +1 -0
- package/dist/{scopes-Be2d8bSb.mjs → scopes-BVeuhGBE.mjs} +3 -3
- package/dist/{scopes-Be2d8bSb.mjs.map → scopes-BVeuhGBE.mjs.map} +1 -1
- package/dist/{search-CeO678cp.mjs → search-BpuPKZb0.mjs} +26 -16
- package/dist/search-BpuPKZb0.mjs.map +1 -0
- package/dist/{secrets-870d-7yA.mjs → secrets-dtYs2hDo.mjs} +5 -5
- package/dist/{secrets-870d-7yA.mjs.map → secrets-dtYs2hDo.mjs.map} +1 -1
- package/dist/{sections-DSuEfirn.mjs → sections-COctk6hf.mjs} +3 -3
- package/dist/{sections-DSuEfirn.mjs.map → sections-COctk6hf.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +28 -26
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +20 -19
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-C3GDfT0V.mjs → seo-AFpVvTqr.mjs} +6 -4
- package/dist/seo-AFpVvTqr.mjs.map +1 -0
- package/dist/{seo-BAPKiED8.mjs → seo-CvDxfvFb.mjs} +3 -3
- package/dist/{seo-BAPKiED8.mjs.map → seo-CvDxfvFb.mjs.map} +1 -1
- package/dist/{service-DyFT-k-R.mjs → service-xMiMSTsR.mjs} +4 -4
- package/dist/{service-DyFT-k-R.mjs.map → service-xMiMSTsR.mjs.map} +1 -1
- package/dist/{session-user-BrK2zz7S.mjs → session-user-BzVemLkw.mjs} +2 -2
- package/dist/{session-user-BrK2zz7S.mjs.map → session-user-BzVemLkw.mjs.map} +1 -1
- package/dist/{settings-DgKouY2S.mjs → settings-B372MV0p.mjs} +7 -7
- package/dist/{settings-DgKouY2S.mjs.map → settings-B372MV0p.mjs.map} +1 -1
- package/dist/{settings-CREKyj8I.mjs → settings-BE9aqn_9.mjs} +3 -3
- package/dist/{settings-CREKyj8I.mjs.map → settings-BE9aqn_9.mjs.map} +1 -1
- package/dist/{setup-complete-L7bMK2VI.mjs → setup-complete-DF7TAfD5.mjs} +2 -2
- package/dist/{setup-complete-L7bMK2VI.mjs.map → setup-complete-DF7TAfD5.mjs.map} +1 -1
- package/dist/{setup-nonce-Ct5tjWcq.mjs → setup-nonce-Do-U_cg9.mjs} +1 -1
- package/dist/{setup-nonce-Ct5tjWcq.mjs.map → setup-nonce-Do-U_cg9.mjs.map} +1 -1
- package/dist/{single-flight-cache-C2exrGAi.mjs → single-flight-cache-B0eLKS6K.mjs} +2 -2
- package/dist/{single-flight-cache-C2exrGAi.mjs.map → single-flight-cache-B0eLKS6K.mjs.map} +1 -1
- package/dist/site-url-Bowsi9T-.mjs +16 -0
- package/dist/site-url-Bowsi9T-.mjs.map +1 -0
- package/dist/slugify-B994zkXC.mjs +17 -0
- package/dist/slugify-B994zkXC.mjs.map +1 -0
- package/dist/{snapshot-BdpUJKD-.mjs → snapshot-B5h6aPMh.mjs} +2 -2
- package/dist/{snapshot-BdpUJKD-.mjs.map → snapshot-B5h6aPMh.mjs.map} +1 -1
- package/dist/{ssrf-CviKqWmq.mjs → ssrf-Cpvg_n3A.mjs} +1 -1
- package/dist/{ssrf-CviKqWmq.mjs.map → ssrf-Cpvg_n3A.mjs.map} +1 -1
- package/dist/{state-xxv6ZTMv.mjs → state-DYwPue40.mjs} +1 -1
- package/dist/{state-xxv6ZTMv.mjs.map → state-DYwPue40.mjs.map} +1 -1
- package/dist/{status-COfycGIU.mjs → status-CWVYpbD8.mjs} +1 -1
- package/dist/{status-COfycGIU.mjs.map → status-CWVYpbD8.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-B61CRSha.mjs → taxonomies-B0o9ExNV.mjs} +85 -75
- package/dist/taxonomies-B0o9ExNV.mjs.map +1 -0
- package/dist/{taxonomies-Dbdki3Un.mjs → taxonomies-Dk3MAklL.mjs} +360 -56
- package/dist/taxonomies-Dk3MAklL.mjs.map +1 -0
- package/dist/taxonomy-CPeM8d2o.mjs +484 -0
- package/dist/taxonomy-CPeM8d2o.mjs.map +1 -0
- package/dist/{tokens-DVltpO2D.mjs → tokens-C39klX8R.mjs} +2 -2
- package/dist/{tokens-DVltpO2D.mjs.map → tokens-C39klX8R.mjs.map} +1 -1
- package/dist/{transaction-D0FOsb3X.mjs → transaction-NQj4VJ7Z.mjs} +1 -1
- package/dist/{transaction-D0FOsb3X.mjs.map → transaction-NQj4VJ7Z.mjs.map} +1 -1
- package/dist/{transport-BWQo0Foy.mjs → transport--CfOflrp.mjs} +1 -1
- package/dist/{transport-BWQo0Foy.mjs.map → transport--CfOflrp.mjs.map} +1 -1
- package/dist/{transport-DokJOScS.d.mts → transport-B_rfeU-a.d.mts} +1 -1
- package/dist/{transport-DokJOScS.d.mts.map → transport-B_rfeU-a.d.mts.map} +1 -1
- package/dist/{trusted-proxy-CwjQj0YG.mjs → trusted-proxy-CEVekpby.mjs} +1 -1
- package/dist/{trusted-proxy-CwjQj0YG.mjs.map → trusted-proxy-CEVekpby.mjs.map} +1 -1
- package/dist/{types-o7xo7VgH.mjs → types-75KIqzL9.mjs} +20 -3
- package/dist/types-75KIqzL9.mjs.map +1 -0
- package/dist/{types-C9P3ysxq.d.mts → types-BPuloofb.d.mts} +1 -1
- package/dist/{types-C9P3ysxq.d.mts.map → types-BPuloofb.d.mts.map} +1 -1
- package/dist/{types-BD40g7zz.mjs → types-BW1syrlw.mjs} +1 -1
- package/dist/{types-BD40g7zz.mjs.map → types-BW1syrlw.mjs.map} +1 -1
- package/dist/{types-jISEalTX.d.mts → types-C3_AbkDP.d.mts} +53 -10
- package/dist/types-C3_AbkDP.d.mts.map +1 -0
- package/dist/{types-84Bque3-.d.mts → types-CAGdePf3.d.mts} +133 -1
- package/dist/types-CAGdePf3.d.mts.map +1 -0
- package/dist/{types-CcSZCcF1.d.mts → types-CFUfyt1s.d.mts} +1 -1
- package/dist/{types-CcSZCcF1.d.mts.map → types-CFUfyt1s.d.mts.map} +1 -1
- package/dist/{types-DQLZ58GV.d.mts → types-CPx2lIGo.d.mts} +1 -1
- package/dist/{types-DQLZ58GV.d.mts.map → types-CPx2lIGo.d.mts.map} +1 -1
- package/dist/{types-XrQQ-Aex.mjs → types-CQPWhPxE.mjs} +15 -11
- package/dist/types-CQPWhPxE.mjs.map +1 -0
- package/dist/{types-BQY7VYw6.d.mts → types-Cs-TFLNf.d.mts} +28 -8
- package/dist/types-Cs-TFLNf.d.mts.map +1 -0
- package/dist/types-CtzytVXn.mjs +18 -0
- package/dist/types-CtzytVXn.mjs.map +1 -0
- package/dist/{types-DqZVPILm.d.mts → types-D4_1Ga4L.d.mts} +44 -5
- package/dist/types-D4_1Ga4L.d.mts.map +1 -0
- package/dist/{types-Dr2GLlwu.d.mts → types-DefV3OiO.d.mts} +1 -1
- package/dist/{types-Dr2GLlwu.d.mts.map → types-DefV3OiO.d.mts.map} +1 -1
- package/dist/{types-DsAMyD_o.d.mts → types-X0MThr7x.d.mts} +1 -1
- package/dist/{types-DsAMyD_o.d.mts.map → types-X0MThr7x.d.mts.map} +1 -1
- package/dist/{upload-attempts-C5yd6Gae.mjs → upload-attempts-hlne3iA1.mjs} +1 -1
- package/dist/{upload-attempts-C5yd6Gae.mjs.map → upload-attempts-hlne3iA1.mjs.map} +1 -1
- package/dist/url-pattern-BHS0V5Ng.mjs +33 -0
- package/dist/url-pattern-BHS0V5Ng.mjs.map +1 -0
- package/dist/{user-BAumEmpA.mjs → user-sHgJ62SP.mjs} +3 -3
- package/dist/{user-BAumEmpA.mjs.map → user-sHgJ62SP.mjs.map} +1 -1
- package/dist/{utils-BbUgmeZG.mjs → utils-D4vD_Y98.mjs} +3 -3
- package/dist/{utils-BbUgmeZG.mjs.map → utils-D4vD_Y98.mjs.map} +1 -1
- package/dist/{validate-Bs_wT2ul.mjs → validate-BkqIG_Uj.mjs} +24 -5
- package/dist/validate-BkqIG_Uj.mjs.map +1 -0
- package/dist/{validate-VPnKoIzW.mjs → validate-BpwoDOgt.mjs} +25 -2
- package/dist/validate-BpwoDOgt.mjs.map +1 -0
- package/dist/{validate-CdYcY-Ln.d.mts → validate-DeGtBN84.d.mts} +25 -7
- package/dist/validate-DeGtBN84.d.mts.map +1 -0
- package/dist/{validation-BngR0nit.mjs → validation-CiJb_X5o.mjs} +14 -13
- package/dist/{validation-BngR0nit.mjs.map → validation-CiJb_X5o.mjs.map} +1 -1
- package/dist/version-x0NjTScG.mjs +7 -0
- package/dist/{version-Bdfb34kk.mjs.map → version-x0NjTScG.mjs.map} +1 -1
- package/dist/{widgets-L-VndTKD.mjs → widgets-Cwzvww0W.mjs} +3 -3
- package/dist/{widgets-L-VndTKD.mjs.map → widgets-Cwzvww0W.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-DueaLFd9.d.mts → wxr-taxonomies-CmC0ZsDr.d.mts} +1 -1
- package/dist/{wxr-taxonomies-DueaLFd9.d.mts.map → wxr-taxonomies-CmC0ZsDr.d.mts.map} +1 -1
- package/dist/{wxr-taxonomies-BexjtNid.mjs → wxr-taxonomies-QZjWxjyk.mjs} +13 -32
- package/dist/{wxr-taxonomies-BexjtNid.mjs.map → wxr-taxonomies-QZjWxjyk.mjs.map} +1 -1
- package/dist/{zod-generator-DMzfga3g.mjs → zod-generator-D11MhxG4.mjs} +53 -6
- package/dist/zod-generator-D11MhxG4.mjs.map +1 -0
- package/package.json +18 -7
- package/src/after.ts +6 -1
- package/src/api/errors.ts +13 -0
- package/src/api/handlers/content.ts +172 -33
- package/src/api/handlers/dashboard.ts +12 -2
- package/src/api/handlers/index.ts +16 -0
- package/src/api/handlers/manifest.ts +2 -0
- package/src/api/handlers/marketplace.ts +14 -0
- package/src/api/handlers/media-allowlist.ts +13 -2
- package/src/api/handlers/media-usage-work.ts +188 -0
- package/src/api/handlers/media-usage.ts +5 -3
- package/src/api/handlers/registry.ts +14 -0
- package/src/api/handlers/revision.ts +19 -5
- package/src/api/handlers/schema.ts +46 -3
- package/src/api/handlers/seo.ts +5 -2
- package/src/api/handlers/snapshot.ts +1 -1
- package/src/api/handlers/taxonomies.ts +446 -83
- package/src/api/media-usage-write-fence.ts +64 -0
- package/src/api/openapi/document.ts +247 -0
- package/src/api/public-url.ts +14 -2
- package/src/api/schemas/common.ts +3 -1
- package/src/api/schemas/content.ts +122 -1
- package/src/api/schemas/media-usage.ts +133 -0
- package/src/api/schemas/schema.ts +91 -3
- package/src/api/schemas/search.ts +2 -0
- package/src/api/schemas/taxonomies.ts +58 -8
- package/src/api/site-url.ts +16 -6
- package/src/api/types.ts +1 -0
- package/src/astro/integration/index.ts +55 -42
- package/src/astro/integration/routes.ts +48 -4
- package/src/astro/integration/runtime.ts +28 -0
- package/src/astro/integration/virtual-modules.ts +27 -1
- package/src/astro/integration/vite-config.ts +16 -1
- package/src/astro/middleware/media-usage-write-fence.ts +30 -0
- package/src/astro/middleware/redirect.ts +14 -12
- package/src/astro/middleware/scoped-db.ts +35 -4
- package/src/astro/middleware.ts +131 -30
- package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -1
- package/src/astro/routes/api/admin/media-usage/collection-deletions/index.ts +22 -0
- package/src/astro/routes/api/admin/media-usage/collection-deletions/retry.ts +22 -0
- package/src/astro/routes/api/admin/media-usage/work/index.ts +26 -0
- package/src/astro/routes/api/admin/media-usage/work/retry.ts +26 -0
- package/src/astro/routes/api/admin/plugins/[id]/disable.ts +4 -0
- package/src/astro/routes/api/admin/plugins/[id]/enable.ts +4 -0
- package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +4 -0
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +4 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/install.ts +4 -0
- package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +2 -2
- package/src/astro/routes/api/auth/invite/index.ts +2 -2
- package/src/astro/routes/api/auth/magic-link/send.ts +2 -2
- package/src/astro/routes/api/auth/signup/request.ts +2 -2
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +67 -31
- package/src/astro/routes/api/import/wordpress/execute.ts +3 -10
- package/src/astro/routes/api/mcp.ts +1 -0
- package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +7 -1
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +1 -7
- package/src/astro/routes/api/schema/collections/reorder.ts +31 -0
- package/src/astro/routes/api/schema/index.ts +2 -0
- package/src/astro/routes/api/search/enable.ts +5 -1
- package/src/astro/routes/api/search/rebuild.ts +6 -1
- package/src/astro/routes/api/taxonomies/[name]/reorder.ts +41 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +1 -0
- package/src/astro/routes/api/taxonomies/[name]/translations.ts +48 -0
- package/src/astro/routes/api/taxonomies/[name].ts +102 -0
- package/src/astro/types.ts +31 -4
- package/src/cleanup.ts +25 -26
- package/src/cli/commands/dev.ts +13 -3
- package/src/cli/commands/doctor.ts +193 -6
- package/src/cli/commands/export-seed.ts +6 -1
- package/src/cli/index.ts +1 -1
- package/src/client/index.ts +119 -0
- package/src/components/Block.astro +12 -0
- package/src/components/CommentForm.astro +1 -1
- package/src/components/Comments.astro +1 -1
- package/src/components/InlinePortableTextEditor.tsx +260 -32
- package/src/components/OrderedList.astro +14 -0
- package/src/components/PortableText.astro +26 -4
- package/src/components/index.ts +12 -1
- package/src/components/ordered-list.ts +549 -0
- package/src/content/converters/mark-safety.ts +120 -0
- package/src/content/converters/numbered-list.ts +148 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +84 -25
- package/src/content/converters/prosemirror-to-portable-text.ts +35 -14
- package/src/content/converters/types.ts +2 -0
- package/src/content/portable-text-lists.ts +205 -0
- package/src/content-list-query.ts +29 -0
- package/src/database/dialect-helpers.ts +3 -22
- package/src/database/migrations/055_content_translation_group_locale_index.ts +67 -0
- package/src/database/migrations/056_taxonomy_term_sort_order.ts +189 -0
- package/src/database/migrations/057_collection_hidden.ts +24 -0
- package/src/database/migrations/058_collection_sort_order.ts +20 -0
- package/src/database/migrations/059_revision_prune_queue.ts +36 -0
- package/src/database/migrations/060_collection_admin_config.ts +16 -0
- package/src/database/migrations/061_media_usage_cleanup.ts +77 -0
- package/src/database/migrations/062_media_usage_cleanup_fence.ts +295 -0
- package/src/database/migrations/063_media_usage_incremental_work.ts +397 -0
- package/src/database/migrations/064_fts_plain_text.ts +253 -0
- package/src/database/migrations/065_media_usage_collection_deletion.ts +85 -0
- package/src/database/migrations/066_media_usage_reconciliation.ts +115 -0
- package/src/database/migrations/067_indexed_content_fields.ts +39 -0
- package/src/database/migrations/068_content_taxonomy_entry_groups.ts +61 -0
- package/src/database/migrations/069_collection_title_date_fields.ts +45 -0
- package/src/database/migrations/070_collection_routable.ts +18 -0
- package/src/database/migrations/runner.ts +32 -0
- package/src/database/repositories/content.ts +1051 -273
- package/src/database/repositories/media-usage-work.ts +848 -0
- package/src/database/repositories/media-usage.ts +1502 -138
- package/src/database/repositories/revision.ts +98 -22
- package/src/database/repositories/taxonomy.ts +429 -103
- package/src/database/repositories/types.ts +58 -2
- package/src/database/types.ts +147 -17
- package/src/database/validate.ts +39 -0
- package/src/db/adapters.ts +36 -0
- package/src/db/index.ts +3 -0
- package/src/deferred-tasks.ts +71 -0
- package/src/emdash-runtime.ts +493 -110
- package/src/fields/file.ts +7 -4
- package/src/fields/image.ts +8 -1
- package/src/fields/types.ts +18 -5
- package/src/i18n/config.ts +32 -0
- package/src/i18n/repair-locale-casing.ts +0 -14
- package/src/i18n/taxonomy-locale-diagnostic.ts +47 -0
- package/src/import/wxr-taxonomies.ts +7 -47
- package/src/index.ts +27 -2
- package/src/loader.ts +165 -89
- package/src/mcp/server.ts +242 -34
- package/src/media/usage/activation.ts +626 -0
- package/src/media/usage/capture-triggers.ts +543 -0
- package/src/media/usage/cleanup.ts +305 -0
- package/src/media/usage/collection-deletion-processor.ts +356 -0
- package/src/media/usage/collection-deletion.ts +836 -0
- package/src/media/usage/content-fields.ts +40 -3
- package/src/media/usage/content-refresh.ts +356 -47
- package/src/media/usage/content-repair.ts +180 -61
- package/src/media/usage/content-snapshots.ts +85 -105
- package/src/media/usage/gc.ts +50 -0
- package/src/media/usage/projection-fingerprint.ts +129 -0
- package/src/media/usage/reconciliation-processor.ts +372 -0
- package/src/media/usage/reconciliation.ts +1117 -0
- package/src/media/usage/source-key.ts +4 -0
- package/src/media/usage/types.ts +2 -0
- package/src/media/usage/work-processor.ts +248 -0
- package/src/menus/index.ts +246 -141
- package/src/object-cache/index.ts +160 -3
- package/src/plugin-types.ts +8 -0
- package/src/plugins/adapt-sandbox-entry.ts +24 -5
- package/src/plugins/context.ts +24 -7
- package/src/plugins/index.ts +9 -0
- package/src/plugins/routes.ts +77 -1
- package/src/plugins/sandbox/index.ts +10 -1
- package/src/plugins/sandbox/types.ts +78 -1
- package/src/plugins/scheduler/node.ts +13 -1
- package/src/plugins/scheduler/types.ts +2 -0
- package/src/plugins/storage-indexes.ts +50 -11
- package/src/plugins/types.ts +39 -2
- package/src/query.ts +50 -79
- package/src/redirects/cache.ts +79 -19
- package/src/request-context.ts +3 -0
- package/src/scheduled-publish.ts +6 -1
- package/src/scheduler-health.ts +46 -0
- package/src/schema/registry.ts +863 -249
- package/src/schema/types.ts +74 -8
- package/src/schema/url-pattern.ts +33 -0
- package/src/schema/zod-generator.ts +77 -5
- package/src/search/fts-manager.ts +167 -86
- package/src/search/index.ts +2 -0
- package/src/search/query.ts +32 -11
- package/src/search/types.ts +8 -0
- package/src/seed/apply.ts +89 -16
- package/src/seed/types.ts +21 -3
- package/src/seed/validate.ts +52 -2
- package/src/taxonomies/index.ts +88 -82
- package/src/taxonomies/term-counts.ts +23 -12
- package/src/ui-comments.ts +19 -0
- package/src/ui.ts +11 -3
- package/src/utils/slugify.ts +1 -29
- package/src/virtual-modules.d.ts +24 -0
- package/dist/adapters-C0ONzkUP.d.mts.map +0 -1
- package/dist/after-B1IIdH3Y.mjs +0 -29
- package/dist/after-B1IIdH3Y.mjs.map +0 -1
- package/dist/api-DgPbMlng.mjs.map +0 -1
- package/dist/apply-1_6ra7NP.mjs.map +0 -1
- package/dist/cache-B26cufFd.mjs +0 -65
- package/dist/cache-B26cufFd.mjs.map +0 -1
- package/dist/config-DyF3OKg_.mjs.map +0 -1
- package/dist/content-CpfKV9QE.mjs.map +0 -1
- package/dist/content-refresh-DgqUBeTv.mjs +0 -1629
- package/dist/content-refresh-DgqUBeTv.mjs.map +0 -1
- package/dist/context-kO4YZB03.mjs.map +0 -1
- package/dist/dashboard-DoBwPnON.mjs.map +0 -1
- package/dist/dialect-helpers-DFwyWjTM.mjs.map +0 -1
- package/dist/errors-DtEXIQQV.mjs.map +0 -1
- package/dist/fts-manager-vncsZIJm.mjs.map +0 -1
- package/dist/index-BeNto_Vs.d.mts.map +0 -1
- package/dist/index-j9rTh3cp.d.mts.map +0 -1
- package/dist/loader-C1XOLV5b.mjs.map +0 -1
- package/dist/media-DWIzoVFL.mjs.map +0 -1
- package/dist/media-allowlist-B7TPD6aq.mjs.map +0 -1
- package/dist/media-usage-DPJcNaAq.mjs.map +0 -1
- package/dist/menus-C6qhqP4X.mjs.map +0 -1
- package/dist/object-cache-Bok5j2ae.mjs.map +0 -1
- package/dist/options-aeIs8WFu.d.mts.map +0 -1
- package/dist/public-url-DSGTnJFw.mjs.map +0 -1
- package/dist/query-DCiXI7OZ.mjs.map +0 -1
- package/dist/redirects-BOn2DIUs.mjs.map +0 -1
- package/dist/registry-BP1JK2xh.mjs +0 -795
- package/dist/registry-BP1JK2xh.mjs.map +0 -1
- package/dist/relations-DHFQGX0h.d.mts.map +0 -1
- package/dist/runner-BsI18UgP.mjs.map +0 -1
- package/dist/search-CeO678cp.mjs.map +0 -1
- package/dist/seo-C3GDfT0V.mjs.map +0 -1
- package/dist/site-url-8N3kSyVZ.mjs +0 -13
- package/dist/site-url-8N3kSyVZ.mjs.map +0 -1
- package/dist/slugify-C_tqlU4G.mjs +0 -30
- package/dist/slugify-C_tqlU4G.mjs.map +0 -1
- package/dist/taxonomies-B61CRSha.mjs.map +0 -1
- package/dist/taxonomies-Dbdki3Un.mjs.map +0 -1
- package/dist/taxonomy-DvwWAPvA.mjs +0 -304
- package/dist/taxonomy-DvwWAPvA.mjs.map +0 -1
- package/dist/types-84Bque3-.d.mts.map +0 -1
- package/dist/types-BQY7VYw6.d.mts.map +0 -1
- package/dist/types-DqZVPILm.d.mts.map +0 -1
- package/dist/types-XrQQ-Aex.mjs.map +0 -1
- package/dist/types-jISEalTX.d.mts.map +0 -1
- package/dist/types-o7xo7VgH.mjs.map +0 -1
- package/dist/validate-Bs_wT2ul.mjs.map +0 -1
- package/dist/validate-CdYcY-Ln.d.mts.map +0 -1
- package/dist/validate-VPnKoIzW.mjs.map +0 -1
- package/dist/version-Bdfb34kk.mjs +0 -7
- package/dist/zod-generator-DMzfga3g.mjs.map +0 -1
- /package/dist/{api-tokens-CEsW_jCg.mjs → api-tokens-CyTsLszZ.mjs} +0 -0
- /package/dist/{ssrf-BB__xfNM.mjs → ssrf-DpXgKsna.mjs} +0 -0
- /package/dist/{types-CK0LxPUQ.mjs → types-CP1CflWf.mjs} +0 -0
package/src/emdash-runtime.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { Kysely, sql, type Dialect } from "kysely";
|
|
|
13
13
|
import virtualConfig from "virtual:emdash/config";
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
|
|
16
|
+
import { assertMediaUsageActivationWriteAllowed } from "./api/media-usage-write-fence.js";
|
|
16
17
|
import { validateRev } from "./api/rev.js";
|
|
17
18
|
import type {
|
|
18
19
|
EmDashConfig,
|
|
@@ -22,6 +23,7 @@ import type {
|
|
|
22
23
|
import type { EmDashManifest, ManifestCollection } from "./astro/types.js";
|
|
23
24
|
import { getAuthMode } from "./auth/mode.js";
|
|
24
25
|
import { getTrustedProxyHeaders } from "./auth/trusted-proxy.js";
|
|
26
|
+
import type { ContentFieldFilters } from "./content-list-query.js";
|
|
25
27
|
import { isSqlite } from "./database/dialect-helpers.js";
|
|
26
28
|
import { kyselyLogOption } from "./database/instrumentation.js";
|
|
27
29
|
import {
|
|
@@ -30,23 +32,39 @@ import {
|
|
|
30
32
|
runMigrations,
|
|
31
33
|
} from "./database/migrations/runner.js";
|
|
32
34
|
import { AuditRepository } from "./database/repositories/audit.js";
|
|
35
|
+
import { ContentRepository } from "./database/repositories/content.js";
|
|
33
36
|
import { RevisionRepository } from "./database/repositories/revision.js";
|
|
37
|
+
import { ContentMutationConflictError } from "./database/repositories/types.js";
|
|
34
38
|
import type {
|
|
35
39
|
ContentItem as ContentItemInternal,
|
|
36
40
|
ContentDateField,
|
|
37
41
|
} from "./database/repositories/types.js";
|
|
38
|
-
import { validateIdentifier } from "./database/validate.js";
|
|
39
42
|
import { getI18nConfig } from "./i18n/config.js";
|
|
40
43
|
import { repairLocaleCasing } from "./i18n/repair-locale-casing.js";
|
|
44
|
+
import { warnAboutUnconfiguredTaxonomyLocales } from "./i18n/taxonomy-locale-diagnostic.js";
|
|
41
45
|
import { normalizeMediaValue } from "./media/normalize.js";
|
|
42
46
|
import type { MediaProvider, MediaProviderCapabilities } from "./media/types.js";
|
|
47
|
+
import {
|
|
48
|
+
MEDIA_USAGE_COLLECTION_DELETION_LIMITS,
|
|
49
|
+
processDueMediaUsageCollectionDeletions,
|
|
50
|
+
} from "./media/usage/collection-deletion-processor.js";
|
|
43
51
|
import {
|
|
44
52
|
deleteContentMediaUsage,
|
|
45
53
|
findNonTranslatableSiblingContentIds,
|
|
46
54
|
markContentMediaUsageCollectionStale,
|
|
47
55
|
refreshContentMediaUsageAfterWrite,
|
|
48
56
|
} from "./media/usage/content-refresh.js";
|
|
57
|
+
import {
|
|
58
|
+
MEDIA_USAGE_RECONCILIATION_LIMITS,
|
|
59
|
+
processDueMediaUsageReconciliation,
|
|
60
|
+
} from "./media/usage/reconciliation-processor.js";
|
|
61
|
+
import {
|
|
62
|
+
MEDIA_USAGE_WORK_PROCESSING_LIMITS,
|
|
63
|
+
processDueMediaUsageWork,
|
|
64
|
+
processMediaUsageWorkAfterWrite,
|
|
65
|
+
} from "./media/usage/work-processor.js";
|
|
49
66
|
import { createSandboxRunnerOptions } from "./plugins/sandbox/runner-options.js";
|
|
67
|
+
import { getSandboxRouteErrorDetails } from "./plugins/sandbox/types.js";
|
|
50
68
|
import type {
|
|
51
69
|
SandboxedPluginInstance,
|
|
52
70
|
SandboxRunner,
|
|
@@ -65,8 +83,10 @@ import type {
|
|
|
65
83
|
PortableTextBlockConfig,
|
|
66
84
|
FieldWidgetConfig,
|
|
67
85
|
SettingField,
|
|
86
|
+
UserInfo,
|
|
68
87
|
} from "./plugins/types.js";
|
|
69
|
-
import
|
|
88
|
+
import { recordSchedulerHeartbeatSafely } from "./scheduler-health.js";
|
|
89
|
+
import { MAX_COLLECTION_LIST_COLUMNS, type FieldType } from "./schema/types.js";
|
|
70
90
|
import { hashString } from "./utils/hash.js";
|
|
71
91
|
import { createInitLock, type InitLock, initWithLock } from "./utils/init-lock.js";
|
|
72
92
|
import { createSingleFlightCache, singleFlightCached } from "./utils/single-flight-cache.js";
|
|
@@ -182,6 +202,7 @@ import {
|
|
|
182
202
|
type Storage,
|
|
183
203
|
} from "./index.js";
|
|
184
204
|
import { getDb } from "./loader.js";
|
|
205
|
+
import { isRecord } from "./plugin-utils.js";
|
|
185
206
|
import { CronExecutor, type InvokeCronHookFn } from "./plugins/cron.js";
|
|
186
207
|
import { definePlugin } from "./plugins/define-plugin.js";
|
|
187
208
|
import { DEV_CONSOLE_EMAIL_PLUGIN_ID, devConsoleEmailDeliver } from "./plugins/email-console.js";
|
|
@@ -193,9 +214,17 @@ import {
|
|
|
193
214
|
} from "./plugins/hooks.js";
|
|
194
215
|
import { normalizeManifestRoute } from "./plugins/manifest-schema.js";
|
|
195
216
|
import { extractRequestMeta, sanitizeHeadersForSandbox } from "./plugins/request-meta.js";
|
|
196
|
-
import {
|
|
217
|
+
import {
|
|
218
|
+
buildRouteMeta,
|
|
219
|
+
parseRouteInput,
|
|
220
|
+
PluginRouteRegistry,
|
|
221
|
+
toRouteCallerInfo,
|
|
222
|
+
type RouteCallerInput,
|
|
223
|
+
type RouteMeta,
|
|
224
|
+
} from "./plugins/routes.js";
|
|
197
225
|
import type { CronScheduler } from "./plugins/scheduler/types.js";
|
|
198
226
|
import { PluginStateRepository } from "./plugins/state.js";
|
|
227
|
+
import { syncDeclaredStorageIndexes } from "./plugins/storage-indexes.js";
|
|
199
228
|
import { normalizeRegistryConfig } from "./registry/config.js";
|
|
200
229
|
import { requestCached } from "./request-cache.js";
|
|
201
230
|
import { getRequestContext } from "./request-context.js";
|
|
@@ -226,6 +255,17 @@ const FIELD_TYPE_TO_KIND: Record<FieldType, string> = {
|
|
|
226
255
|
};
|
|
227
256
|
|
|
228
257
|
const DRAFT_ONLY_UPDATE_KEYS = new Set(["data", "slug", "locale", "skipRevision"]);
|
|
258
|
+
const MAX_DRAFT_STAGE_ATTEMPTS = 32;
|
|
259
|
+
|
|
260
|
+
const LIST_COLUMN_FIELD_TYPES: ReadonlySet<FieldType> = new Set([
|
|
261
|
+
"string",
|
|
262
|
+
"number",
|
|
263
|
+
"integer",
|
|
264
|
+
"boolean",
|
|
265
|
+
"datetime",
|
|
266
|
+
"select",
|
|
267
|
+
"multiSelect",
|
|
268
|
+
]);
|
|
229
269
|
|
|
230
270
|
/**
|
|
231
271
|
* Sandboxed plugin entry from virtual module
|
|
@@ -243,6 +283,10 @@ export interface SandboxedPluginEntry {
|
|
|
243
283
|
storage: PluginStorageConfig;
|
|
244
284
|
/** Serialized MCP declarations emitted at plugin build time. */
|
|
245
285
|
mcp?: PluginMcpManifestConfig;
|
|
286
|
+
/** Route declarations (name + public/permission/cacheControl), used for route auth decisions */
|
|
287
|
+
routes?: PluginManifest["routes"];
|
|
288
|
+
/** Hook declarations this plugin implements */
|
|
289
|
+
hooks?: PluginManifest["hooks"];
|
|
246
290
|
/** Admin pages */
|
|
247
291
|
adminPages?: Array<{ path: string; label?: string; icon?: string }>;
|
|
248
292
|
/** Dashboard widgets */
|
|
@@ -370,6 +414,7 @@ export interface EmDashRuntimeParts {
|
|
|
370
414
|
pipelineFactoryOptions: {
|
|
371
415
|
db: Kysely<Database>;
|
|
372
416
|
getDb?: () => Kysely<Database>;
|
|
417
|
+
beforeContentWrite?: () => Promise<void>;
|
|
373
418
|
storage?: Storage;
|
|
374
419
|
siteInfo?: {
|
|
375
420
|
siteName?: string;
|
|
@@ -494,12 +539,69 @@ const marketplaceManifestCache = new Map<
|
|
|
494
539
|
settingsSchema?: Record<string, SettingField>;
|
|
495
540
|
};
|
|
496
541
|
mcp?: PluginMcpManifestConfig;
|
|
542
|
+
storage?: PluginManifest["storage"];
|
|
497
543
|
}
|
|
498
544
|
>();
|
|
499
545
|
/** Route metadata for sandboxed plugins: pluginId -> routeName -> RouteMeta */
|
|
500
546
|
const sandboxedRouteMetaCache = new Map<string, Map<string, RouteMeta>>();
|
|
501
547
|
let sandboxRunner: SandboxRunner | null = null;
|
|
502
548
|
|
|
549
|
+
export const MEDIA_USAGE_MAINTENANCE_QUERY_RESERVATIONS = Object.freeze({
|
|
550
|
+
entryWork: MEDIA_USAGE_WORK_PROCESSING_LIMITS.ordinaryStatementsPerJob,
|
|
551
|
+
collectionDeletion: MEDIA_USAGE_COLLECTION_DELETION_LIMITS.maxQueriesPerTick,
|
|
552
|
+
reconciliation: MEDIA_USAGE_RECONCILIATION_LIMITS.maxQueriesPerTick,
|
|
553
|
+
maxClassQueries: Math.max(
|
|
554
|
+
MEDIA_USAGE_WORK_PROCESSING_LIMITS.ordinaryStatementsPerJob,
|
|
555
|
+
MEDIA_USAGE_COLLECTION_DELETION_LIMITS.maxQueriesPerTick,
|
|
556
|
+
MEDIA_USAGE_RECONCILIATION_LIMITS.maxQueriesPerTick,
|
|
557
|
+
),
|
|
558
|
+
eventCeiling: 40,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
export type MediaUsageMaintenanceTaskClass =
|
|
562
|
+
| "entry_work"
|
|
563
|
+
| "collection_deletion"
|
|
564
|
+
| "reconciliation";
|
|
565
|
+
|
|
566
|
+
export type MediaUsageMaintenanceResult =
|
|
567
|
+
| { outcome: "inactive" | "admission_closed"; taskClass: null; turn: null }
|
|
568
|
+
| { outcome: "processed"; taskClass: MediaUsageMaintenanceTaskClass; turn: number };
|
|
569
|
+
|
|
570
|
+
async function runScheduledMediaUsageLane(
|
|
571
|
+
db: Kysely<Database>,
|
|
572
|
+
): Promise<MediaUsageMaintenanceResult> {
|
|
573
|
+
const queriesAlreadySpent = getRequestContext()?.metrics?.dbCount ?? 0;
|
|
574
|
+
if (
|
|
575
|
+
queriesAlreadySpent + 1 + MEDIA_USAGE_MAINTENANCE_QUERY_RESERVATIONS.maxClassQueries >
|
|
576
|
+
MEDIA_USAGE_MAINTENANCE_QUERY_RESERVATIONS.eventCeiling
|
|
577
|
+
) {
|
|
578
|
+
return { outcome: "admission_closed", taskClass: null, turn: null };
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const activation = await db
|
|
582
|
+
.updateTable("_emdash_media_usage_activation")
|
|
583
|
+
.set({
|
|
584
|
+
media_usage_maintenance_turn: sql<number>`(media_usage_maintenance_turn + 1) % 3`,
|
|
585
|
+
})
|
|
586
|
+
.where("task_key", "=", "incremental_capture")
|
|
587
|
+
.where("state", "=", "active")
|
|
588
|
+
.returning("media_usage_maintenance_turn")
|
|
589
|
+
.executeTakeFirst();
|
|
590
|
+
if (!activation) return { outcome: "inactive", taskClass: null, turn: null };
|
|
591
|
+
|
|
592
|
+
const turn = activation.media_usage_maintenance_turn;
|
|
593
|
+
if (turn === 0) {
|
|
594
|
+
await processDueMediaUsageWork(db);
|
|
595
|
+
return { outcome: "processed", taskClass: "entry_work", turn };
|
|
596
|
+
}
|
|
597
|
+
if (turn === 1) {
|
|
598
|
+
await processDueMediaUsageCollectionDeletions(db);
|
|
599
|
+
return { outcome: "processed", taskClass: "collection_deletion", turn };
|
|
600
|
+
}
|
|
601
|
+
await processDueMediaUsageReconciliation(db);
|
|
602
|
+
return { outcome: "processed", taskClass: "reconciliation", turn };
|
|
603
|
+
}
|
|
604
|
+
|
|
503
605
|
/**
|
|
504
606
|
* EmDashRuntime - singleton per worker
|
|
505
607
|
*/
|
|
@@ -555,10 +657,13 @@ export class EmDashRuntime {
|
|
|
555
657
|
/** All plugins eligible for the hook pipeline (includes built-in plugins).
|
|
556
658
|
* Stored so we can rebuild the pipeline when plugins are enabled/disabled. */
|
|
557
659
|
private allPipelinePlugins: ResolvedPlugin[];
|
|
660
|
+
/** Guards the once-per-process plugin storage-index sync. */
|
|
661
|
+
private storageIndexesSynced = false;
|
|
558
662
|
/** Factory options for the hook pipeline context factory */
|
|
559
663
|
private pipelineFactoryOptions: {
|
|
560
664
|
db: Kysely<Database>;
|
|
561
665
|
getDb?: () => Kysely<Database>;
|
|
666
|
+
beforeContentWrite?: () => Promise<void>;
|
|
562
667
|
storage?: Storage;
|
|
563
668
|
siteInfo?: {
|
|
564
669
|
siteName?: string;
|
|
@@ -631,8 +736,16 @@ export class EmDashRuntime {
|
|
|
631
736
|
* Returns the items promoted so callers can invalidate their cache tags.
|
|
632
737
|
*/
|
|
633
738
|
async publishScheduled(): Promise<PublishedRef[]> {
|
|
739
|
+
return this.publishScheduledWithFence();
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
private async publishScheduledWithFence(
|
|
743
|
+
onPublished?: (refs: PublishedRef[]) => Promise<void>,
|
|
744
|
+
): Promise<PublishedRef[]> {
|
|
745
|
+
await assertMediaUsageActivationWriteAllowed(this.db);
|
|
634
746
|
return publishDueContent(this.db, {
|
|
635
747
|
publish: (collection, id, options) => this.handleContentPublish(collection, id, options),
|
|
748
|
+
onPublished,
|
|
636
749
|
});
|
|
637
750
|
}
|
|
638
751
|
|
|
@@ -670,11 +783,7 @@ export class EmDashRuntime {
|
|
|
670
783
|
|
|
671
784
|
let published: PublishedRef[] = [];
|
|
672
785
|
try {
|
|
673
|
-
|
|
674
|
-
published = await publishDueContent(this.db, {
|
|
675
|
-
publish: (collection, id, opts) => this.handleContentPublish(collection, id, opts),
|
|
676
|
-
onPublished: options.onPublished,
|
|
677
|
-
});
|
|
786
|
+
published = await this.publishScheduledWithFence(options.onPublished);
|
|
678
787
|
} catch (error) {
|
|
679
788
|
console.error("[scheduled-publish] Sweep failed:", error);
|
|
680
789
|
}
|
|
@@ -685,12 +794,41 @@ export class EmDashRuntime {
|
|
|
685
794
|
console.error("[cleanup] System cleanup failed:", error);
|
|
686
795
|
}
|
|
687
796
|
|
|
797
|
+
try {
|
|
798
|
+
await this.syncPluginStorageIndexesOnce();
|
|
799
|
+
} catch (error) {
|
|
800
|
+
console.error("[plugins] Storage index sync failed:", error);
|
|
801
|
+
}
|
|
802
|
+
|
|
688
803
|
// Never throws; no-op unless scheduled backups are enabled and due.
|
|
689
804
|
await maybeRunScheduledBackup(this.db, this.storage ?? undefined);
|
|
805
|
+
await recordSchedulerHeartbeatSafely(this.db);
|
|
690
806
|
|
|
691
807
|
return { published };
|
|
692
808
|
}
|
|
693
809
|
|
|
810
|
+
async runScheduledMediaUsageTasks(): Promise<MediaUsageMaintenanceResult> {
|
|
811
|
+
return runScheduledMediaUsageLane(this.db);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Materialize plugin-declared storage indexes, once per process.
|
|
816
|
+
*
|
|
817
|
+
* Called from the scheduler path, not from request handlers — configured
|
|
818
|
+
* plugins have no install handler, so the tick is their only sync moment.
|
|
819
|
+
*/
|
|
820
|
+
async syncPluginStorageIndexesOnce(): Promise<void> {
|
|
821
|
+
if (this.storageIndexesSynced) return;
|
|
822
|
+
this.storageIndexesSynced = true;
|
|
823
|
+
// Sandboxed marketplace/registry plugins never join allPipelinePlugins;
|
|
824
|
+
// their manifests are cached at bundle load. Without them, plugins
|
|
825
|
+
// installed before this feature shipped would never get their indexes.
|
|
826
|
+
await syncDeclaredStorageIndexes(this.db, [
|
|
827
|
+
...this.allPipelinePlugins,
|
|
828
|
+
...marketplaceManifestCache.values(),
|
|
829
|
+
]);
|
|
830
|
+
}
|
|
831
|
+
|
|
694
832
|
/**
|
|
695
833
|
* Stop the cron scheduler gracefully.
|
|
696
834
|
* Call during worker shutdown or hot-reload.
|
|
@@ -898,6 +1036,7 @@ export class EmDashRuntime {
|
|
|
898
1036
|
version: bundle.manifest.version,
|
|
899
1037
|
admin: bundle.manifest.admin,
|
|
900
1038
|
mcp: bundle.manifest.mcp,
|
|
1039
|
+
storage: bundle.manifest.storage,
|
|
901
1040
|
});
|
|
902
1041
|
|
|
903
1042
|
// Cache route metadata from manifest for auth decisions
|
|
@@ -1013,6 +1152,7 @@ export class EmDashRuntime {
|
|
|
1013
1152
|
version: bundle.manifest.version,
|
|
1014
1153
|
admin: bundle.manifest.admin,
|
|
1015
1154
|
mcp: bundle.manifest.mcp,
|
|
1155
|
+
storage: bundle.manifest.storage,
|
|
1016
1156
|
});
|
|
1017
1157
|
if (bundle.manifest.routes.length > 0) {
|
|
1018
1158
|
const routeMetaMap = new Map<string, RouteMeta>();
|
|
@@ -1444,6 +1584,7 @@ export class EmDashRuntime {
|
|
|
1444
1584
|
const pipelineFactoryOptions = {
|
|
1445
1585
|
db,
|
|
1446
1586
|
getDb: resolveDb,
|
|
1587
|
+
beforeContentWrite: () => assertMediaUsageActivationWriteAllowed(resolveDb()),
|
|
1447
1588
|
storage: storage ?? undefined,
|
|
1448
1589
|
siteInfo,
|
|
1449
1590
|
};
|
|
@@ -1589,6 +1730,14 @@ export class EmDashRuntime {
|
|
|
1589
1730
|
if (deps.createScheduler) {
|
|
1590
1731
|
const scheduler = deps.createScheduler(cronExecutor);
|
|
1591
1732
|
cronScheduler = scheduler;
|
|
1733
|
+
const runMediaUsageMaintenance = async () => {
|
|
1734
|
+
const runtime = runtimeRef.current;
|
|
1735
|
+
if (runtime) {
|
|
1736
|
+
await runtime.runScheduledMediaUsageTasks();
|
|
1737
|
+
} else {
|
|
1738
|
+
await runScheduledMediaUsageLane(db);
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1592
1741
|
|
|
1593
1742
|
// Run scheduled publishing and system cleanup alongside each tick.
|
|
1594
1743
|
// Pass storage so cleanupPendingUploads can delete orphaned files.
|
|
@@ -1598,12 +1747,12 @@ export class EmDashRuntime {
|
|
|
1598
1747
|
// Falls back to the raw handler if (improbably) the tick beats
|
|
1599
1748
|
// the post-construction ref assignment.
|
|
1600
1749
|
const runtime = runtimeRef.current;
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
}
|
|
1750
|
+
if (runtime) {
|
|
1751
|
+
await runtime.publishScheduled();
|
|
1752
|
+
} else {
|
|
1753
|
+
await assertMediaUsageActivationWriteAllowed(db);
|
|
1754
|
+
await publishDueContent(db);
|
|
1755
|
+
}
|
|
1607
1756
|
} catch (error) {
|
|
1608
1757
|
console.error("[scheduled-publish] Sweep failed:", error);
|
|
1609
1758
|
}
|
|
@@ -1614,9 +1763,23 @@ export class EmDashRuntime {
|
|
|
1614
1763
|
// by runSystemCleanup. This catches unexpected errors.
|
|
1615
1764
|
console.error("[cleanup] System cleanup failed:", error);
|
|
1616
1765
|
}
|
|
1766
|
+
try {
|
|
1767
|
+
await runtimeRef.current?.syncPluginStorageIndexesOnce();
|
|
1768
|
+
} catch (error) {
|
|
1769
|
+
console.error("[plugins] Storage index sync failed:", error);
|
|
1770
|
+
}
|
|
1617
1771
|
// Never throws; no-op unless scheduled backups are enabled and due.
|
|
1618
1772
|
await maybeRunScheduledBackup(db, storage ?? undefined);
|
|
1773
|
+
await recordSchedulerHeartbeatSafely(db);
|
|
1774
|
+
if (!scheduler.setMediaUsageMaintenance) {
|
|
1775
|
+
try {
|
|
1776
|
+
await runMediaUsageMaintenance();
|
|
1777
|
+
} catch (error) {
|
|
1778
|
+
console.error("[media-usage] Scheduled maintenance failed:", error);
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1619
1781
|
});
|
|
1782
|
+
scheduler.setMediaUsageMaintenance?.(runMediaUsageMaintenance);
|
|
1620
1783
|
|
|
1621
1784
|
// start() is void on the timer scheduler but the interface
|
|
1622
1785
|
// allows a promise (alarm-backed schedulers); we don't block on it.
|
|
@@ -1920,6 +2083,7 @@ export class EmDashRuntime {
|
|
|
1920
2083
|
createSandboxRunnerOptions(
|
|
1921
2084
|
{
|
|
1922
2085
|
db,
|
|
2086
|
+
beforeContentWrite: () => assertMediaUsageActivationWriteAllowed(db),
|
|
1923
2087
|
mediaStorage: mediaStorage
|
|
1924
2088
|
? {
|
|
1925
2089
|
upload: (opts) =>
|
|
@@ -1979,8 +2143,8 @@ export class EmDashRuntime {
|
|
|
1979
2143
|
capabilities: entry.capabilities ?? [],
|
|
1980
2144
|
allowedHosts: entry.allowedHosts ?? [],
|
|
1981
2145
|
storage: entry.storage ?? {},
|
|
1982
|
-
hooks: [],
|
|
1983
|
-
routes: [],
|
|
2146
|
+
hooks: entry.hooks ?? [],
|
|
2147
|
+
routes: entry.routes ?? [],
|
|
1984
2148
|
admin: {},
|
|
1985
2149
|
mcp: entry.mcp,
|
|
1986
2150
|
};
|
|
@@ -1990,6 +2154,17 @@ export class EmDashRuntime {
|
|
|
1990
2154
|
console.log(
|
|
1991
2155
|
`EmDash: Loaded sandboxed plugin ${pluginKey} with capabilities: [${manifest.capabilities.join(", ")}]`,
|
|
1992
2156
|
);
|
|
2157
|
+
|
|
2158
|
+
if (manifest.routes.length > 0) {
|
|
2159
|
+
const routeMetaMap = new Map<string, RouteMeta>();
|
|
2160
|
+
for (const routeEntry of manifest.routes) {
|
|
2161
|
+
const normalized = normalizeManifestRoute(routeEntry);
|
|
2162
|
+
routeMetaMap.set(normalized.name, buildRouteMeta(normalized));
|
|
2163
|
+
}
|
|
2164
|
+
sandboxedRouteMetaCache.set(entry.id, routeMetaMap);
|
|
2165
|
+
} else {
|
|
2166
|
+
sandboxedRouteMetaCache.delete(entry.id);
|
|
2167
|
+
}
|
|
1993
2168
|
} catch (error) {
|
|
1994
2169
|
console.error(`EmDash: Failed to load sandboxed plugin ${entry.id}:`, error);
|
|
1995
2170
|
}
|
|
@@ -2032,6 +2207,7 @@ export class EmDashRuntime {
|
|
|
2032
2207
|
createSandboxRunnerOptions(
|
|
2033
2208
|
{
|
|
2034
2209
|
db,
|
|
2210
|
+
beforeContentWrite: () => assertMediaUsageActivationWriteAllowed(db),
|
|
2035
2211
|
mediaStorage: {
|
|
2036
2212
|
upload: (opts) =>
|
|
2037
2213
|
storage.upload({
|
|
@@ -2092,6 +2268,7 @@ export class EmDashRuntime {
|
|
|
2092
2268
|
version: bundle.manifest.version,
|
|
2093
2269
|
admin: bundle.manifest.admin,
|
|
2094
2270
|
mcp: bundle.manifest.mcp,
|
|
2271
|
+
storage: bundle.manifest.storage,
|
|
2095
2272
|
});
|
|
2096
2273
|
|
|
2097
2274
|
// Cache route metadata from manifest for auth decisions
|
|
@@ -2164,6 +2341,7 @@ export class EmDashRuntime {
|
|
|
2164
2341
|
version: bundle.manifest.version,
|
|
2165
2342
|
admin: bundle.manifest.admin,
|
|
2166
2343
|
mcp: bundle.manifest.mcp,
|
|
2344
|
+
storage: bundle.manifest.storage,
|
|
2167
2345
|
});
|
|
2168
2346
|
if (bundle.manifest.routes.length > 0) {
|
|
2169
2347
|
const routeMeta = new Map<string, RouteMeta>();
|
|
@@ -2358,12 +2536,38 @@ export class EmDashRuntime {
|
|
|
2358
2536
|
fields[field.slug] = entry;
|
|
2359
2537
|
}
|
|
2360
2538
|
|
|
2539
|
+
const configuredListColumns = collection.admin?.listColumns ?? [];
|
|
2540
|
+
const fieldTypes = new Map(collection.fields.map((field) => [field.slug, field.type]));
|
|
2541
|
+
const listColumns: string[] = [];
|
|
2542
|
+
for (const slug of configuredListColumns) {
|
|
2543
|
+
if (listColumns.includes(slug)) continue;
|
|
2544
|
+
const fieldType = fieldTypes.get(slug);
|
|
2545
|
+
if (!fieldType || !LIST_COLUMN_FIELD_TYPES.has(fieldType)) {
|
|
2546
|
+
console.warn(
|
|
2547
|
+
`EmDash: Ignoring unsupported or unknown list column "${slug}" in collection "${collection.slug}".`,
|
|
2548
|
+
);
|
|
2549
|
+
continue;
|
|
2550
|
+
}
|
|
2551
|
+
if (listColumns.length >= MAX_COLLECTION_LIST_COLUMNS) {
|
|
2552
|
+
console.warn(
|
|
2553
|
+
`EmDash: Collection "${collection.slug}" declares more than ${MAX_COLLECTION_LIST_COLUMNS} list columns; extra columns are ignored.`,
|
|
2554
|
+
);
|
|
2555
|
+
break;
|
|
2556
|
+
}
|
|
2557
|
+
listColumns.push(slug);
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2361
2560
|
manifestCollections[collection.slug] = {
|
|
2362
2561
|
label: collection.label,
|
|
2363
2562
|
labelSingular: collection.labelSingular || collection.label,
|
|
2364
2563
|
supports: collection.supports || [],
|
|
2365
2564
|
hasSeo: collection.hasSeo,
|
|
2366
2565
|
urlPattern: collection.urlPattern,
|
|
2566
|
+
routable: collection.routable !== false,
|
|
2567
|
+
titleField: collection.titleField,
|
|
2568
|
+
dateField: collection.dateField,
|
|
2569
|
+
...(collection.hidden ? { hidden: true } : {}),
|
|
2570
|
+
listColumns: listColumns.length > 0 ? listColumns : undefined,
|
|
2367
2571
|
fields,
|
|
2368
2572
|
};
|
|
2369
2573
|
}
|
|
@@ -2478,29 +2682,48 @@ export class EmDashRuntime {
|
|
|
2478
2682
|
|
|
2479
2683
|
// Build taxonomies from database
|
|
2480
2684
|
let manifestTaxonomies: Array<{
|
|
2685
|
+
id: string;
|
|
2481
2686
|
name: string;
|
|
2482
2687
|
label: string;
|
|
2483
2688
|
labelSingular?: string;
|
|
2484
2689
|
hierarchical: boolean;
|
|
2485
2690
|
collections: string[];
|
|
2691
|
+
locale: string;
|
|
2692
|
+
translationGroup: string;
|
|
2486
2693
|
}> = [];
|
|
2694
|
+
let taxonomyDefinitionLocales: string[] = [];
|
|
2487
2695
|
try {
|
|
2488
2696
|
const rows = await this.db
|
|
2489
2697
|
.selectFrom("_emdash_taxonomy_defs")
|
|
2490
2698
|
.selectAll()
|
|
2491
2699
|
.orderBy("name")
|
|
2492
2700
|
.execute();
|
|
2701
|
+
taxonomyDefinitionLocales = rows.map((row) => row.locale);
|
|
2493
2702
|
manifestTaxonomies = rows.map((row) => ({
|
|
2703
|
+
id: row.id,
|
|
2494
2704
|
name: row.name,
|
|
2495
2705
|
label: row.label,
|
|
2496
2706
|
labelSingular: row.label_singular ?? undefined,
|
|
2497
2707
|
hierarchical: row.hierarchical === 1,
|
|
2498
2708
|
collections: parseStringArray(row.collections).toSorted(),
|
|
2709
|
+
locale: row.locale,
|
|
2710
|
+
translationGroup: row.translation_group ?? row.id,
|
|
2499
2711
|
}));
|
|
2500
2712
|
} catch (error) {
|
|
2501
2713
|
console.debug("EmDash: Could not load taxonomy definitions:", error);
|
|
2502
2714
|
}
|
|
2503
2715
|
|
|
2716
|
+
try {
|
|
2717
|
+
const configuredLocales = virtualConfig?.i18n?.locales ?? getI18nConfig()?.locales ?? [];
|
|
2718
|
+
await warnAboutUnconfiguredTaxonomyLocales(
|
|
2719
|
+
this.db,
|
|
2720
|
+
configuredLocales,
|
|
2721
|
+
taxonomyDefinitionLocales,
|
|
2722
|
+
);
|
|
2723
|
+
} catch (error) {
|
|
2724
|
+
console.warn("[i18n] taxonomy locale diagnostic failed:", error);
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2504
2727
|
// Build manifest hash
|
|
2505
2728
|
const manifestHash = await hashString(
|
|
2506
2729
|
JSON.stringify(manifestCollections) +
|
|
@@ -2513,7 +2736,7 @@ export class EmDashRuntime {
|
|
|
2513
2736
|
const authModeValue = authMode.type === "external" ? authMode.providerType : "passkey";
|
|
2514
2737
|
|
|
2515
2738
|
// Include i18n config if enabled (read from virtual module to avoid SSR module singleton mismatch)
|
|
2516
|
-
const i18nConfig = virtualConfig?.i18n;
|
|
2739
|
+
const i18nConfig = virtualConfig?.i18n ?? getI18nConfig();
|
|
2517
2740
|
const i18n =
|
|
2518
2741
|
i18nConfig && i18nConfig.locales && i18nConfig.locales.length > 1
|
|
2519
2742
|
? { defaultLocale: i18nConfig.defaultLocale, locales: i18nConfig.locales }
|
|
@@ -2535,6 +2758,10 @@ export class EmDashRuntime {
|
|
|
2535
2758
|
taxonomies: manifestTaxonomies,
|
|
2536
2759
|
authMode: authModeValue,
|
|
2537
2760
|
i18n,
|
|
2761
|
+
contentLocale: {
|
|
2762
|
+
defaultLocale: i18nConfig?.defaultLocale ?? "en",
|
|
2763
|
+
implicit: i18nConfig === null,
|
|
2764
|
+
},
|
|
2538
2765
|
marketplace: !!this.config.marketplace,
|
|
2539
2766
|
registry,
|
|
2540
2767
|
};
|
|
@@ -2612,6 +2839,10 @@ export class EmDashRuntime {
|
|
|
2612
2839
|
dateField?: ContentDateField;
|
|
2613
2840
|
dateFrom?: string;
|
|
2614
2841
|
dateTo?: string;
|
|
2842
|
+
bylines?: string[];
|
|
2843
|
+
bylinesNone?: boolean;
|
|
2844
|
+
includeInferredBylines?: boolean;
|
|
2845
|
+
fieldFilters?: ContentFieldFilters;
|
|
2615
2846
|
},
|
|
2616
2847
|
) {
|
|
2617
2848
|
return handleContentList(this.db, collection, params);
|
|
@@ -2697,7 +2928,7 @@ export class EmDashRuntime {
|
|
|
2697
2928
|
collection: string,
|
|
2698
2929
|
body: {
|
|
2699
2930
|
data: Record<string, unknown>;
|
|
2700
|
-
slug?: string;
|
|
2931
|
+
slug?: string | null;
|
|
2701
2932
|
status?: string;
|
|
2702
2933
|
authorId?: string;
|
|
2703
2934
|
bylines?: Array<{ bylineId: string; roleLabel?: string | null }>;
|
|
@@ -2757,7 +2988,7 @@ export class EmDashRuntime {
|
|
|
2757
2988
|
id: string,
|
|
2758
2989
|
body: {
|
|
2759
2990
|
data?: Record<string, unknown>;
|
|
2760
|
-
slug?: string;
|
|
2991
|
+
slug?: string | null;
|
|
2761
2992
|
status?: string;
|
|
2762
2993
|
authorId?: string | null;
|
|
2763
2994
|
bylines?: Array<{ bylineId: string; roleLabel?: string | null }>;
|
|
@@ -2771,13 +3002,12 @@ export class EmDashRuntime {
|
|
|
2771
3002
|
taxonomies?: Record<string, string[]>;
|
|
2772
3003
|
publishedAt?: string | null;
|
|
2773
3004
|
locale?: string;
|
|
2774
|
-
/**
|
|
3005
|
+
/** Replace the previous autosave revision after staging this save. */
|
|
2775
3006
|
skipRevision?: boolean;
|
|
2776
3007
|
_rev?: string;
|
|
2777
3008
|
},
|
|
2778
3009
|
) {
|
|
2779
3010
|
// Resolve slug → ID if needed (before any lookups)
|
|
2780
|
-
const { ContentRepository } = await import("./database/repositories/content.js");
|
|
2781
3011
|
const repo = new ContentRepository(this.db);
|
|
2782
3012
|
const resolvedItem = await repo.findByIdOrSlug(collection, id, body.locale);
|
|
2783
3013
|
const resolvedId = resolvedItem?.id ?? id;
|
|
@@ -2840,81 +3070,119 @@ export class EmDashRuntime {
|
|
|
2840
3070
|
let usesDraftRevisions = false;
|
|
2841
3071
|
let draftStorageChanged = false;
|
|
2842
3072
|
if (processedData) {
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
if (existing) {
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
3073
|
+
const collectionInfo = await this.schemaRegistry.getCollectionWithFields(collection);
|
|
3074
|
+
if (collectionInfo?.supports?.includes("revisions")) {
|
|
3075
|
+
usesDraftRevisions = true;
|
|
3076
|
+
const revisionRepo = new RevisionRepository(this.db);
|
|
3077
|
+
let existing = await repo.findById(collection, resolvedId);
|
|
3078
|
+
|
|
3079
|
+
for (let attempt = 0; existing && attempt < MAX_DRAFT_STAGE_ATTEMPTS; attempt++) {
|
|
3080
|
+
let baseData: Record<string, unknown>;
|
|
3081
|
+
if (existing.draftRevisionId) {
|
|
3082
|
+
const draftRevision = await revisionRepo.findById(existing.draftRevisionId);
|
|
3083
|
+
baseData = draftRevision?.data ?? existing.data;
|
|
3084
|
+
} else {
|
|
3085
|
+
baseData = existing.data;
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
const mergedData = { ...baseData, ...processedData };
|
|
3089
|
+
if (bodyWithoutRev.slug !== undefined) {
|
|
3090
|
+
mergedData._slug = bodyWithoutRev.slug;
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
const revision = await revisionRepo.create({
|
|
3094
|
+
collection,
|
|
3095
|
+
entryId: resolvedId,
|
|
3096
|
+
data: mergedData,
|
|
3097
|
+
authorId: bodyWithoutRev.authorId ?? undefined,
|
|
3098
|
+
});
|
|
3099
|
+
|
|
3100
|
+
let staged: boolean;
|
|
3101
|
+
try {
|
|
3102
|
+
staged = await repo.replaceDraftRevision(collection, resolvedId, revision.id, existing);
|
|
3103
|
+
} catch (error) {
|
|
3104
|
+
try {
|
|
3105
|
+
await revisionRepo.deleteIfUnreferenced(collection, resolvedId, revision.id);
|
|
3106
|
+
} catch (cleanupError) {
|
|
3107
|
+
console.error(
|
|
3108
|
+
`[emdash] Failed to clean up unstaged revision ${revision.id}:`,
|
|
3109
|
+
cleanupError,
|
|
3110
|
+
);
|
|
2860
3111
|
}
|
|
3112
|
+
throw error;
|
|
3113
|
+
}
|
|
2861
3114
|
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
3115
|
+
if (!staged) {
|
|
3116
|
+
try {
|
|
3117
|
+
await revisionRepo.deleteIfUnreferenced(collection, resolvedId, revision.id);
|
|
3118
|
+
} catch (cleanupError) {
|
|
3119
|
+
console.error(
|
|
3120
|
+
`[emdash] Failed to clean up unstaged revision ${revision.id}:`,
|
|
3121
|
+
cleanupError,
|
|
3122
|
+
);
|
|
3123
|
+
}
|
|
3124
|
+
if (body._rev || attempt === MAX_DRAFT_STAGE_ATTEMPTS - 1) {
|
|
3125
|
+
const error = new ContentMutationConflictError();
|
|
3126
|
+
return {
|
|
3127
|
+
success: false as const,
|
|
3128
|
+
error: { code: "CONFLICT", message: error.message },
|
|
3129
|
+
};
|
|
2866
3130
|
}
|
|
3131
|
+
existing = await repo.findById(collection, resolvedId);
|
|
3132
|
+
continue;
|
|
3133
|
+
}
|
|
2867
3134
|
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
// Create new draft revision
|
|
2874
|
-
const revision = await revisionRepo.create({
|
|
3135
|
+
draftStorageChanged = true;
|
|
3136
|
+
|
|
3137
|
+
if (bodyWithoutRev.skipRevision && existing.draftRevisionId) {
|
|
3138
|
+
try {
|
|
3139
|
+
await revisionRepo.deleteIfUnreferenced(
|
|
2875
3140
|
collection,
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
validateIdentifier(collection, "collection");
|
|
2885
|
-
const tableName = `ec_${collection}`;
|
|
2886
|
-
await sql`
|
|
2887
|
-
UPDATE ${sql.ref(tableName)}
|
|
2888
|
-
SET draft_revision_id = ${revision.id}
|
|
2889
|
-
WHERE id = ${resolvedId}
|
|
2890
|
-
`.execute(this.db);
|
|
2891
|
-
draftStorageChanged = true;
|
|
2892
|
-
|
|
2893
|
-
// Fire-and-forget: prune old revisions to prevent unbounded growth
|
|
2894
|
-
void revisionRepo.pruneOldRevisions(collection, resolvedId, 50).catch(() => {});
|
|
3141
|
+
resolvedId,
|
|
3142
|
+
existing.draftRevisionId,
|
|
3143
|
+
);
|
|
3144
|
+
} catch (error) {
|
|
3145
|
+
console.error(
|
|
3146
|
+
`[emdash] Failed to clean up superseded revision ${existing.draftRevisionId}:`,
|
|
3147
|
+
error,
|
|
3148
|
+
);
|
|
2895
3149
|
}
|
|
3150
|
+
} else {
|
|
3151
|
+
after(async () => {
|
|
3152
|
+
try {
|
|
3153
|
+
await revisionRepo.pruneQueuedEntry(collection, resolvedId, revision.id, 50);
|
|
3154
|
+
} catch (error) {
|
|
3155
|
+
console.error(
|
|
3156
|
+
`[revisions] Failed to prune revisions for ${collection}/${resolvedId}:`,
|
|
3157
|
+
error,
|
|
3158
|
+
);
|
|
3159
|
+
}
|
|
3160
|
+
});
|
|
2896
3161
|
}
|
|
3162
|
+
break;
|
|
2897
3163
|
}
|
|
2898
|
-
} catch {
|
|
2899
|
-
// Don't fail the update if revision creation fails
|
|
2900
3164
|
}
|
|
2901
3165
|
}
|
|
2902
3166
|
|
|
2903
|
-
// Update the content table:
|
|
2904
|
-
// - If collection uses draft revisions: only update metadata (no data fields, no slug)
|
|
2905
|
-
// - Otherwise: update everything as before
|
|
2906
|
-
const result = await handleContentUpdate(this.db, collection, resolvedId, {
|
|
2907
|
-
...bodyWithoutRev,
|
|
2908
|
-
data: usesDraftRevisions ? undefined : processedData,
|
|
2909
|
-
slug: usesDraftRevisions ? undefined : bodyWithoutRev.slug,
|
|
2910
|
-
authorId: bodyWithoutRev.authorId,
|
|
2911
|
-
bylines: bodyWithoutRev.bylines,
|
|
2912
|
-
});
|
|
2913
|
-
|
|
2914
3167
|
// Public HTML comes from live columns / SEO / taxonomies, not draft revisions.
|
|
2915
3168
|
const liveMetaTouched = Object.entries(bodyWithoutRev).some(
|
|
2916
3169
|
([key, value]) => value !== undefined && !DRAFT_ONLY_UPDATE_KEYS.has(key),
|
|
2917
3170
|
);
|
|
3171
|
+
|
|
3172
|
+
// Update the content table:
|
|
3173
|
+
// - If collection uses draft revisions: only update metadata (no data fields, no slug)
|
|
3174
|
+
// - Otherwise: update everything as before
|
|
3175
|
+
const result =
|
|
3176
|
+
usesDraftRevisions && !liveMetaTouched
|
|
3177
|
+
? await handleContentGet(this.db, collection, resolvedId)
|
|
3178
|
+
: await handleContentUpdate(this.db, collection, resolvedId, {
|
|
3179
|
+
...bodyWithoutRev,
|
|
3180
|
+
data: usesDraftRevisions ? undefined : processedData,
|
|
3181
|
+
slug: usesDraftRevisions ? undefined : bodyWithoutRev.slug,
|
|
3182
|
+
authorId: bodyWithoutRev.authorId,
|
|
3183
|
+
bylines: bodyWithoutRev.bylines,
|
|
3184
|
+
});
|
|
3185
|
+
|
|
2918
3186
|
const liveContentChanged = usesDraftRevisions
|
|
2919
3187
|
? liveMetaTouched
|
|
2920
3188
|
: Boolean(processedData || bodyWithoutRev.slug !== undefined || liveMetaTouched);
|
|
@@ -3072,7 +3340,11 @@ export class EmDashRuntime {
|
|
|
3072
3340
|
async handleContentPublish(
|
|
3073
3341
|
collection: string,
|
|
3074
3342
|
id: string,
|
|
3075
|
-
options: {
|
|
3343
|
+
options: {
|
|
3344
|
+
publishedAt?: string;
|
|
3345
|
+
requireScheduledDue?: boolean;
|
|
3346
|
+
expectedScheduledAt?: string;
|
|
3347
|
+
} = {},
|
|
3076
3348
|
) {
|
|
3077
3349
|
const result = await handleContentPublish(this.db, collection, id, options);
|
|
3078
3350
|
if (result.success && result.data) {
|
|
@@ -3295,6 +3567,18 @@ export class EmDashRuntime {
|
|
|
3295
3567
|
// must then `content_publish` to promote the restored draft to
|
|
3296
3568
|
// live, matching the documented tool contract.
|
|
3297
3569
|
try {
|
|
3570
|
+
const contentRepo = new ContentRepository(this.db);
|
|
3571
|
+
const existing = await contentRepo.findById(revision.collection, revision.entryId);
|
|
3572
|
+
if (!existing) {
|
|
3573
|
+
return {
|
|
3574
|
+
success: false as const,
|
|
3575
|
+
error: {
|
|
3576
|
+
code: "NOT_FOUND",
|
|
3577
|
+
message: `Content item not found: ${revision.entryId}`,
|
|
3578
|
+
},
|
|
3579
|
+
};
|
|
3580
|
+
}
|
|
3581
|
+
|
|
3298
3582
|
const newDraft = await revisionRepo.create({
|
|
3299
3583
|
collection: revision.collection,
|
|
3300
3584
|
entryId: revision.entryId,
|
|
@@ -3302,18 +3586,45 @@ export class EmDashRuntime {
|
|
|
3302
3586
|
authorId: callerUserId,
|
|
3303
3587
|
});
|
|
3304
3588
|
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3589
|
+
try {
|
|
3590
|
+
const staged = await contentRepo.replaceDraftRevision(
|
|
3591
|
+
revision.collection,
|
|
3592
|
+
revision.entryId,
|
|
3593
|
+
newDraft.id,
|
|
3594
|
+
existing,
|
|
3595
|
+
);
|
|
3596
|
+
if (!staged) throw new ContentMutationConflictError();
|
|
3597
|
+
} catch (error) {
|
|
3598
|
+
try {
|
|
3599
|
+
await revisionRepo.deleteIfUnreferenced(
|
|
3600
|
+
revision.collection,
|
|
3601
|
+
revision.entryId,
|
|
3602
|
+
newDraft.id,
|
|
3603
|
+
);
|
|
3604
|
+
} catch (cleanupError) {
|
|
3605
|
+
console.error(
|
|
3606
|
+
`[emdash] Failed to clean up unrestored revision ${newDraft.id}:`,
|
|
3607
|
+
cleanupError,
|
|
3608
|
+
);
|
|
3609
|
+
}
|
|
3610
|
+
throw error;
|
|
3611
|
+
}
|
|
3312
3612
|
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3613
|
+
after(async () => {
|
|
3614
|
+
try {
|
|
3615
|
+
await revisionRepo.pruneQueuedEntry(
|
|
3616
|
+
revision.collection,
|
|
3617
|
+
revision.entryId,
|
|
3618
|
+
newDraft.id,
|
|
3619
|
+
50,
|
|
3620
|
+
);
|
|
3621
|
+
} catch (error) {
|
|
3622
|
+
console.error(
|
|
3623
|
+
`[revisions] Failed to prune revisions for ${revision.collection}/${revision.entryId}:`,
|
|
3624
|
+
error,
|
|
3625
|
+
);
|
|
3626
|
+
}
|
|
3627
|
+
});
|
|
3317
3628
|
|
|
3318
3629
|
// Return the freshly-fetched item with the new draft hydrated
|
|
3319
3630
|
// onto `data`. Without this the response would echo the live
|
|
@@ -3326,6 +3637,12 @@ export class EmDashRuntime {
|
|
|
3326
3637
|
}
|
|
3327
3638
|
return hydrated;
|
|
3328
3639
|
} catch (error) {
|
|
3640
|
+
if (error instanceof ContentMutationConflictError) {
|
|
3641
|
+
return {
|
|
3642
|
+
success: false as const,
|
|
3643
|
+
error: { code: "CONFLICT", message: error.message },
|
|
3644
|
+
};
|
|
3645
|
+
}
|
|
3329
3646
|
console.error("[emdash] revision restore failed:", error);
|
|
3330
3647
|
return {
|
|
3331
3648
|
success: false as const,
|
|
@@ -3343,12 +3660,15 @@ export class EmDashRuntime {
|
|
|
3343
3660
|
): Promise<void> {
|
|
3344
3661
|
for (const contentId of new Set(contentIds)) {
|
|
3345
3662
|
try {
|
|
3663
|
+
const work = await processMediaUsageWorkAfterWrite(this.db, collection, contentId);
|
|
3664
|
+
if (work.outcome !== "inactive") return;
|
|
3346
3665
|
await refreshContentMediaUsageAfterWrite(this.db, collection, contentId);
|
|
3347
3666
|
} catch (error) {
|
|
3348
3667
|
console.error(
|
|
3349
3668
|
`[media-usage] Failed after content write ${collection}/${contentId}:`,
|
|
3350
3669
|
error,
|
|
3351
3670
|
);
|
|
3671
|
+
return;
|
|
3352
3672
|
}
|
|
3353
3673
|
}
|
|
3354
3674
|
}
|
|
@@ -3358,6 +3678,8 @@ export class EmDashRuntime {
|
|
|
3358
3678
|
contentId: string,
|
|
3359
3679
|
): Promise<void> {
|
|
3360
3680
|
try {
|
|
3681
|
+
const work = await processMediaUsageWorkAfterWrite(this.db, collection, contentId);
|
|
3682
|
+
if (work.outcome !== "inactive") return;
|
|
3361
3683
|
const result = await deleteContentMediaUsage(this.db, collection, contentId);
|
|
3362
3684
|
if (!result.success) {
|
|
3363
3685
|
console.error(
|
|
@@ -3437,7 +3759,13 @@ export class EmDashRuntime {
|
|
|
3437
3759
|
return meta.admin?.settingsSchema ?? {};
|
|
3438
3760
|
}
|
|
3439
3761
|
|
|
3440
|
-
async handlePluginApiRoute(
|
|
3762
|
+
async handlePluginApiRoute(
|
|
3763
|
+
pluginId: string,
|
|
3764
|
+
_method: string,
|
|
3765
|
+
path: string,
|
|
3766
|
+
request: Request,
|
|
3767
|
+
user?: RouteCallerInput | null,
|
|
3768
|
+
) {
|
|
3441
3769
|
if (!this.isPluginEnabled(pluginId)) {
|
|
3442
3770
|
return {
|
|
3443
3771
|
success: false,
|
|
@@ -3445,6 +3773,11 @@ export class EmDashRuntime {
|
|
|
3445
3773
|
};
|
|
3446
3774
|
}
|
|
3447
3775
|
|
|
3776
|
+
// Authenticated caller for `ctx.user`. Undefined for public routes
|
|
3777
|
+
// (the catch-all only forwards the caller after private-route auth)
|
|
3778
|
+
// and for machine tokens with no bound user.
|
|
3779
|
+
const caller = user ? toRouteCallerInfo(user) : undefined;
|
|
3780
|
+
|
|
3448
3781
|
// Check trusted (configured) plugins first — this must match the
|
|
3449
3782
|
// resolution order in getPluginRouteMeta to avoid auth/execution mismatches.
|
|
3450
3783
|
const trustedPlugin = this.configuredPlugins.find((p) => p.id === pluginId);
|
|
@@ -3459,20 +3792,16 @@ export class EmDashRuntime {
|
|
|
3459
3792
|
|
|
3460
3793
|
const routeKey = path.replace(LEADING_SLASH_PATTERN, "");
|
|
3461
3794
|
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
body = await request.json();
|
|
3465
|
-
} catch {
|
|
3466
|
-
// No body or not JSON
|
|
3467
|
-
}
|
|
3795
|
+
// Body methods parse JSON; GET/HEAD/DELETE parse the query string (#2146).
|
|
3796
|
+
const body = await parseRouteInput(request);
|
|
3468
3797
|
|
|
3469
|
-
return routeRegistry.invoke(pluginId, routeKey, { request, body });
|
|
3798
|
+
return routeRegistry.invoke(pluginId, routeKey, { request, body, user: caller });
|
|
3470
3799
|
}
|
|
3471
3800
|
|
|
3472
3801
|
// Check sandboxed (marketplace) plugins second
|
|
3473
3802
|
const sandboxedPlugin = this.findSandboxedPlugin(pluginId);
|
|
3474
3803
|
if (sandboxedPlugin) {
|
|
3475
|
-
return this.handleSandboxedRoute(sandboxedPlugin, path, request);
|
|
3804
|
+
return this.handleSandboxedRoute(sandboxedPlugin, path, request, caller);
|
|
3476
3805
|
}
|
|
3477
3806
|
|
|
3478
3807
|
return {
|
|
@@ -3599,6 +3928,7 @@ export class EmDashRuntime {
|
|
|
3599
3928
|
input: unknown,
|
|
3600
3929
|
actorId: string,
|
|
3601
3930
|
request: Request,
|
|
3931
|
+
caller?: RouteCallerInput | null,
|
|
3602
3932
|
) {
|
|
3603
3933
|
const requestMeta = extractRequestMeta(request, getTrustedProxyHeaders(this.config));
|
|
3604
3934
|
const audit = new AuditRepository(this.db);
|
|
@@ -3610,7 +3940,13 @@ export class EmDashRuntime {
|
|
|
3610
3940
|
headers,
|
|
3611
3941
|
body: JSON.stringify(input),
|
|
3612
3942
|
});
|
|
3613
|
-
const result = await this.handlePluginApiRoute(
|
|
3943
|
+
const result = await this.handlePluginApiRoute(
|
|
3944
|
+
pluginId,
|
|
3945
|
+
"POST",
|
|
3946
|
+
route,
|
|
3947
|
+
internalRequest,
|
|
3948
|
+
caller,
|
|
3949
|
+
);
|
|
3614
3950
|
await audit.log({
|
|
3615
3951
|
actorId,
|
|
3616
3952
|
actorIp: requestMeta.ip ?? undefined,
|
|
@@ -3675,7 +4011,13 @@ export class EmDashRuntime {
|
|
|
3675
4011
|
const imageFields = collectionInfo.fields.filter(
|
|
3676
4012
|
(f) => f.type === "image" || f.type === "file",
|
|
3677
4013
|
);
|
|
3678
|
-
|
|
4014
|
+
// Repeater fields can contain image sub-fields, whose values need the same normalization
|
|
4015
|
+
// (a bare media id posted inside a repeater item would otherwise be stored verbatim and
|
|
4016
|
+
// render as "Image not found" in the admin).
|
|
4017
|
+
const repeaterFields = collectionInfo.fields.filter(
|
|
4018
|
+
(f) => f.type === "repeater" && Array.isArray(f.validation?.subFields),
|
|
4019
|
+
);
|
|
4020
|
+
if (imageFields.length === 0 && repeaterFields.length === 0) return data;
|
|
3679
4021
|
|
|
3680
4022
|
const getProvider = (id: string) => this.getMediaProvider(id);
|
|
3681
4023
|
const result = { ...data };
|
|
@@ -3694,6 +4036,37 @@ export class EmDashRuntime {
|
|
|
3694
4036
|
}
|
|
3695
4037
|
}
|
|
3696
4038
|
|
|
4039
|
+
for (const field of repeaterFields) {
|
|
4040
|
+
const value = result[field.slug];
|
|
4041
|
+
if (!Array.isArray(value)) continue;
|
|
4042
|
+
|
|
4043
|
+
const mediaSubFieldSlugs = (field.validation?.subFields ?? [])
|
|
4044
|
+
.filter((sub) => sub.type === "image")
|
|
4045
|
+
.map((sub) => sub.slug);
|
|
4046
|
+
if (mediaSubFieldSlugs.length === 0) continue;
|
|
4047
|
+
|
|
4048
|
+
const items: unknown[] = value;
|
|
4049
|
+
result[field.slug] = await Promise.all(
|
|
4050
|
+
items.map(async (item) => {
|
|
4051
|
+
if (!isRecord(item)) return item;
|
|
4052
|
+
const normalizedItem: Record<string, unknown> = { ...item };
|
|
4053
|
+
for (const slug of mediaSubFieldSlugs) {
|
|
4054
|
+
const subValue = normalizedItem[slug];
|
|
4055
|
+
if (subValue == null) continue;
|
|
4056
|
+
try {
|
|
4057
|
+
const normalized = await normalizeMediaValue(subValue, getProvider);
|
|
4058
|
+
if (normalized) {
|
|
4059
|
+
normalizedItem[slug] = normalized;
|
|
4060
|
+
}
|
|
4061
|
+
} catch {
|
|
4062
|
+
// Don't fail the save if normalization fails for a single sub-field
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
return normalizedItem;
|
|
4066
|
+
}),
|
|
4067
|
+
);
|
|
4068
|
+
}
|
|
4069
|
+
|
|
3697
4070
|
return result;
|
|
3698
4071
|
}
|
|
3699
4072
|
|
|
@@ -3899,19 +4272,17 @@ export class EmDashRuntime {
|
|
|
3899
4272
|
plugin: SandboxedPluginInstance,
|
|
3900
4273
|
path: string,
|
|
3901
4274
|
request: Request,
|
|
4275
|
+
user?: UserInfo,
|
|
3902
4276
|
): Promise<{
|
|
3903
4277
|
success: boolean;
|
|
3904
4278
|
data?: unknown;
|
|
3905
4279
|
error?: { code: string; message: string };
|
|
4280
|
+
status?: number;
|
|
3906
4281
|
}> {
|
|
3907
4282
|
const routeName = path.replace(LEADING_SLASH_PATTERN, "");
|
|
3908
4283
|
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
body = await request.json();
|
|
3912
|
-
} catch {
|
|
3913
|
-
// No body or not JSON
|
|
3914
|
-
}
|
|
4284
|
+
// Body methods parse JSON; GET/HEAD/DELETE parse the query string (#2146).
|
|
4285
|
+
const body = await parseRouteInput(request);
|
|
3915
4286
|
|
|
3916
4287
|
try {
|
|
3917
4288
|
const headers = sanitizeHeadersForSandbox(request.headers);
|
|
@@ -3921,10 +4292,22 @@ export class EmDashRuntime {
|
|
|
3921
4292
|
method: request.method,
|
|
3922
4293
|
headers,
|
|
3923
4294
|
meta,
|
|
4295
|
+
user,
|
|
3924
4296
|
});
|
|
3925
4297
|
return { success: true, data: result };
|
|
3926
4298
|
} catch (error) {
|
|
3927
4299
|
console.error(`EmDash: Sandboxed plugin route error:`, error);
|
|
4300
|
+
const sandboxRouteError = getSandboxRouteErrorDetails(error);
|
|
4301
|
+
if (sandboxRouteError) {
|
|
4302
|
+
return {
|
|
4303
|
+
success: false,
|
|
4304
|
+
status: sandboxRouteError.status,
|
|
4305
|
+
error: {
|
|
4306
|
+
code: sandboxRouteError.code,
|
|
4307
|
+
message: sandboxRouteError.message,
|
|
4308
|
+
},
|
|
4309
|
+
};
|
|
4310
|
+
}
|
|
3928
4311
|
return {
|
|
3929
4312
|
success: false,
|
|
3930
4313
|
error: {
|