emdash 1.3.0 → 1.4.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/{activation-Dim4YMM7.mjs → activation-CGlyigmg.mjs} +3 -3
- package/dist/{activation-Dim4YMM7.mjs.map → activation-CGlyigmg.mjs.map} +1 -1
- package/dist/{adapters-F_xorvWv.d.mts → adapters-D9a1PfqH.d.mts} +1 -1
- package/dist/{adapters-F_xorvWv.d.mts.map → adapters-D9a1PfqH.d.mts.map} +1 -1
- package/dist/{after-PcEvMY_6.mjs → after-32yNRvd2.mjs} +5 -2
- package/dist/{after-PcEvMY_6.mjs.map → after-32yNRvd2.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +4 -4
- package/dist/api/route-utils.mjs +50 -49
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/api/schemas/index.mjs +7 -7
- package/dist/{api-D-7BNHoz.mjs → api--PYoyeTo.mjs} +121 -48
- package/dist/api--PYoyeTo.mjs.map +1 -0
- package/dist/api-tokens-DqSlkDVI.mjs +9 -0
- package/dist/api-tokens-DqSlkDVI.mjs.map +1 -0
- package/dist/{api-tokens-Bx38ZCQp.mjs → api-tokens-GNCsIegW.mjs} +3 -3
- package/dist/{api-tokens-Bx38ZCQp.mjs.map → api-tokens-GNCsIegW.mjs.map} +1 -1
- package/dist/{apply-T7ATgzCh.mjs → apply-DVnupNeS.mjs} +149 -91
- package/dist/apply-DVnupNeS.mjs.map +1 -0
- package/dist/{approvals-D-m6wvGl.mjs → approvals-DTtYSB27.mjs} +2 -2
- package/dist/{approvals-D-m6wvGl.mjs.map → approvals-DTtYSB27.mjs.map} +1 -1
- package/dist/{artifacts-htGyfCSt.mjs → artifacts-Dvdp2KK-.mjs} +29 -13
- package/dist/artifacts-Dvdp2KK-.mjs.map +1 -0
- package/dist/astro/image-endpoint.mjs +12 -2
- package/dist/astro/image-endpoint.mjs.map +1 -1
- package/dist/astro/index.d.mts +15 -14
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +59 -8
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +13 -12
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +10 -8
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +129 -49
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +18 -9
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware.d.mts +13 -12
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +111 -101
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +11 -11
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +11 -11
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +14 -14
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +14 -14
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +14 -14
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +25 -25
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +25 -25
- package/dist/astro/routes/api/admin/bylines/index.mjs +25 -25
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +17 -17
- package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/bulk.mjs +16 -16
- package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/index.mjs +16 -16
- package/dist/astro/routes/api/admin/core-update.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
- package/dist/astro/routes/api/admin/media-usage/activation.mjs +18 -18
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +19 -19
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +19 -19
- package/dist/astro/routes/api/admin/media-usage/progress.mjs +22 -21
- package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +26 -25
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +19 -19
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +19 -19
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +7 -7
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +7 -7
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +66 -65
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +5 -5
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +66 -65
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +66 -65
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +73 -72
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +66 -65
- 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 +66 -65
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +73 -72
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +66 -65
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +66 -65
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +74 -73
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +68 -67
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +67 -66
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +66 -65
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +66 -65
- 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 +66 -65
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/_...path_.mjs +3 -3
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +33 -32
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +33 -32
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/approvals/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/capabilities.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/capabilities.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +36 -35
- package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +36 -35
- package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +36 -35
- package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/exports/index.mjs +37 -36
- package/dist/astro/routes/api/admin/transfer/exports/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +37 -36
- package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +37 -36
- package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +37 -36
- package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +35 -34
- package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/imports/index.mjs +37 -36
- package/dist/astro/routes/api/admin/transfer/imports/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 +12 -12
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
- package/dist/astro/routes/api/admin/users/index.mjs +11 -11
- package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
- package/dist/astro/routes/api/auth/handover.mjs +5 -5
- package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/complete.mjs +15 -15
- package/dist/astro/routes/api/auth/invite/index.mjs +12 -12
- package/dist/astro/routes/api/auth/invite/register-options.mjs +13 -13
- package/dist/astro/routes/api/auth/logout.mjs +3 -3
- package/dist/astro/routes/api/auth/magic-link/send.mjs +14 -14
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +13 -13
- package/dist/astro/routes/api/auth/me.mjs +12 -12
- package/dist/astro/routes/api/auth/mode.mjs +3 -3
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +8 -8
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +11 -11
- package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/options.mjs +15 -15
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +13 -13
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +13 -13
- package/dist/astro/routes/api/auth/passkey/verify.mjs +15 -15
- package/dist/astro/routes/api/auth/signup/complete.mjs +15 -15
- package/dist/astro/routes/api/auth/signup/request.mjs +13 -13
- package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
- package/dist/astro/routes/api/calendar.mjs +12 -12
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +17 -17
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +29 -28
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +34 -33
- 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 +34 -33
- 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 +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +15 -15
- 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 +35 -27
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +8 -4
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/index.mjs +12 -12
- package/dist/astro/routes/api/content/_collection_/trash.mjs +12 -12
- package/dist/astro/routes/api/dashboard.mjs +22 -16
- package/dist/astro/routes/api/dashboard.mjs.map +1 -1
- package/dist/astro/routes/api/dev/emails.mjs +3 -3
- package/dist/astro/routes/api/dev/scheduled-tasks.mjs +97 -95
- package/dist/astro/routes/api/dev/scheduled-tasks.mjs.map +1 -1
- package/dist/astro/routes/api/health.mjs +4 -4
- package/dist/astro/routes/api/import/probe.d.mts +4 -3
- package/dist/astro/routes/api/import/probe.d.mts.map +1 -1
- package/dist/astro/routes/api/import/probe.mjs +27 -25
- package/dist/astro/routes/api/import/probe.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/analyze.d.mts +4 -3
- package/dist/astro/routes/api/import/wordpress/analyze.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +7 -29
- package/dist/astro/routes/api/import/wordpress/analyze.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +14 -13
- package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/execute.mjs +29 -29
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts +13 -12
- package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +14 -14
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +19 -19
- package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +14 -13
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +25 -24
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +27 -25
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +14 -13
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +39 -38
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +4 -4
- package/dist/astro/routes/api/mcp.mjs +99 -83
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +16 -16
- package/dist/astro/routes/api/media/_id_/replace.mjs +12 -12
- package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
- package/dist/astro/routes/api/media/_id_/usage.mjs +28 -27
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +26 -25
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +5 -5
- package/dist/astro/routes/api/media/file/_...key_.d.mts.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +62 -8
- package/dist/astro/routes/api/media/file/_...key_.mjs.map +1 -1
- package/dist/astro/routes/api/media/folders/_id_.mjs +13 -13
- package/dist/astro/routes/api/media/folders/index.mjs +13 -13
- 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 +15 -15
- package/dist/astro/routes/api/media.mjs +30 -29
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -15
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +17 -15
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -15
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -15
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +17 -15
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +17 -15
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +2 -2
- package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
- package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
- package/dist/astro/routes/api/oauth/register.mjs +5 -5
- package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
- package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
- package/dist/astro/routes/api/oauth/token.d.mts.map +1 -1
- package/dist/astro/routes/api/oauth/token.mjs +7 -7
- package/dist/astro/routes/api/oauth/token.mjs.map +1 -1
- package/dist/astro/routes/api/openapi.json.mjs +12 -12
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +9 -9
- package/dist/astro/routes/api/redirects/404s/index.mjs +20 -19
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +20 -19
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +21 -20
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +21 -20
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.mjs +34 -33
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +34 -33
- 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 +15 -15
- package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +66 -65
- package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +66 -65
- package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
- package/dist/astro/routes/api/schema/block-types/index.mjs +66 -65
- package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +66 -65
- 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 +66 -65
- 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 +66 -65
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +66 -65
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +66 -65
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.mjs +66 -65
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +17 -16
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +66 -65
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +66 -65
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +20 -18
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +19 -17
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +20 -18
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +13 -11
- package/dist/astro/routes/api/search/stats.mjs.map +1 -1
- package/dist/astro/routes/api/search/suggest.mjs +19 -17
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +19 -17
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +19 -17
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
- package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
- package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
- package/dist/astro/routes/api/settings/domain-notify.mjs +7 -7
- package/dist/astro/routes/api/settings/domain.mjs +19 -17
- package/dist/astro/routes/api/settings/domain.mjs.map +1 -1
- package/dist/astro/routes/api/settings/email.mjs +5 -5
- package/dist/astro/routes/api/settings.mjs +25 -23
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin-verify.mjs +18 -18
- package/dist/astro/routes/api/setup/admin.mjs +14 -14
- package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -44
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
- package/dist/astro/routes/api/setup/index.mjs +48 -47
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +4 -4
- package/dist/astro/routes/api/site/domain-proof.mjs +17 -15
- package/dist/astro/routes/api/site/domain-proof.mjs.map +1 -1
- package/dist/astro/routes/api/snapshot.mjs +9 -9
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +25 -24
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +25 -24
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +25 -24
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +25 -24
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +25 -24
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_.mjs +25 -24
- package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +35 -34
- package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +25 -24
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +6 -6
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/visual-editing/action-token.mjs +5 -5
- package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +17 -17
- package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +3 -3
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +1 -1
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +24 -13
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +22 -17
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +21 -17
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +14 -10
- package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.mjs +21 -17
- package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
- package/dist/astro/routes/api/widget-components.mjs +3 -3
- package/dist/astro/routes/robots.txt.mjs +16 -14
- package/dist/astro/routes/robots.txt.mjs.map +1 -1
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +18 -16
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +16 -14
- package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
- package/dist/astro/types.d.mts +22 -20
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/{audit-_gieLVGU.mjs → audit-B8XE-0UV.mjs} +2 -2
- package/dist/{audit-_gieLVGU.mjs.map → audit-B8XE-0UV.mjs.map} +1 -1
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/auth/providers/microsoft.d.mts +1 -1
- package/dist/{authorize-DPFBGbE6.mjs → authorize-NJgp8kLI.mjs} +2 -2
- package/dist/{authorize-DPFBGbE6.mjs.map → authorize-NJgp8kLI.mjs.map} +1 -1
- package/dist/{backup-3FgVxiDJ.mjs → backup-8rPSJ28a.mjs} +4 -4
- package/dist/{backup-3FgVxiDJ.mjs.map → backup-8rPSJ28a.mjs.map} +1 -1
- package/dist/{block-types-CYcG56JB.mjs → block-types-BbOrfnWs.mjs} +5 -5
- package/dist/{block-types-CYcG56JB.mjs.map → block-types-BbOrfnWs.mjs.map} +1 -1
- package/dist/{block-values-gCX4HBSl.mjs → block-values-Dg0-8PPS.mjs} +4 -4
- package/dist/{block-values-gCX4HBSl.mjs.map → block-values-Dg0-8PPS.mjs.map} +1 -1
- package/dist/{byline-BR1qhyiw.mjs → byline-DHJS-GGb.mjs} +123 -38
- package/dist/byline-DHJS-GGb.mjs.map +1 -0
- package/dist/{byline-fields-BLXZnX7N.mjs → byline-fields-CiR8FvvF.mjs} +3 -3
- package/dist/{byline-fields-BLXZnX7N.mjs.map → byline-fields-CiR8FvvF.mjs.map} +1 -1
- package/dist/{byline-fields-4ClDC88c.mjs → byline-fields-D6KYsEa7.mjs} +2 -2
- package/dist/{byline-fields-4ClDC88c.mjs.map → byline-fields-D6KYsEa7.mjs.map} +1 -1
- package/dist/{byline-registry-dvt4N3xV.mjs → byline-registry-BhzpO41z.mjs} +3 -3
- package/dist/{byline-registry-dvt4N3xV.mjs.map → byline-registry-BhzpO41z.mjs.map} +1 -1
- package/dist/{bylines-CVOvRUL7.mjs → bylines-Bsg5cH4S.mjs} +7 -7
- package/dist/bylines-Bsg5cH4S.mjs.map +1 -0
- package/dist/{bylines-DxOs9B7z.mjs → bylines-f_ZEc6Sn.mjs} +8 -8
- package/dist/{bylines-DxOs9B7z.mjs.map → bylines-f_ZEc6Sn.mjs.map} +1 -1
- package/dist/{cache-CEU9wo_h.mjs → cache-5DHbpEWu.mjs} +4 -4
- package/dist/{cache-CEU9wo_h.mjs.map → cache-5DHbpEWu.mjs.map} +1 -1
- package/dist/{capture-triggers-CT6dK9zd.mjs → capture-triggers-BezAvWcB.mjs} +2 -2
- package/dist/{capture-triggers-CT6dK9zd.mjs.map → capture-triggers-BezAvWcB.mjs.map} +1 -1
- package/dist/{challenge-store-C17BYx2-.mjs → challenge-store-B1C0V4b3.mjs} +1 -1
- package/dist/{challenge-store-C17BYx2-.mjs.map → challenge-store-B1C0V4b3.mjs.map} +1 -1
- package/dist/{chunks-xC4UD5-S.mjs → chunks-DiW8VMwz.mjs} +2 -2
- package/dist/{chunks-xC4UD5-S.mjs.map → chunks-DiW8VMwz.mjs.map} +1 -1
- package/dist/cli/index.mjs +53 -52
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +61 -61
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +3 -2
- package/dist/client/index.mjs.map +1 -1
- package/dist/{collection-slugs-cache-e09QeJQt.mjs → collection-slugs-cache-DIrLjqH-.mjs} +20 -14
- package/dist/collection-slugs-cache-DIrLjqH-.mjs.map +1 -0
- package/dist/{comment-UvIWDKcW.mjs → comment-DB74Zpa4.mjs} +18 -8
- package/dist/comment-DB74Zpa4.mjs.map +1 -0
- package/dist/{comment-reaction-dGp6_FRo.mjs → comment-reaction-BScxIWUn.mjs} +2 -2
- package/dist/{comment-reaction-dGp6_FRo.mjs.map → comment-reaction-BScxIWUn.mjs.map} +1 -1
- package/dist/{comments-pej-_BUO.mjs → comments-Cor_zKml.mjs} +3 -3
- package/dist/{comments-pej-_BUO.mjs.map → comments-Cor_zKml.mjs.map} +1 -1
- package/dist/config-Cs_AwWXI.mjs +106 -0
- package/dist/config-Cs_AwWXI.mjs.map +1 -0
- package/dist/{config-CFMojMFK.d.mts → config-D44_8G9J.d.mts} +3 -1
- package/dist/config-D44_8G9J.d.mts.map +1 -0
- package/dist/{config-Bsm_u_oE.d.mts → config-sDhZvkLR.d.mts} +56 -20
- package/dist/config-sDhZvkLR.d.mts.map +1 -0
- package/dist/{content-DQSRZTVw.mjs → content-BKHUVsE5.mjs} +67 -30
- package/dist/content-BKHUVsE5.mjs.map +1 -0
- package/dist/{content-list-query-CYKcY6Vi.d.mts → content-list-query-ByP4jRpZ.d.mts} +1 -1
- package/dist/{content-list-query-CYKcY6Vi.d.mts.map → content-list-query-ByP4jRpZ.d.mts.map} +1 -1
- package/dist/{content-policy-Dm32n9C6.mjs → content-policy-BmE0MPZY.mjs} +1 -1
- package/dist/{content-policy-Dm32n9C6.mjs.map → content-policy-BmE0MPZY.mjs.map} +1 -1
- package/dist/{content-repair-DNh5--x5.mjs → content-repair-Ukdxoq-R.mjs} +4 -4
- package/dist/{content-repair-DNh5--x5.mjs.map → content-repair-Ukdxoq-R.mjs.map} +1 -1
- package/dist/{context-BYptmCN0.mjs → context-CzjejcsE.mjs} +32 -33
- package/dist/context-CzjejcsE.mjs.map +1 -0
- package/dist/{credits-B9iORdWB.mjs → credits-BKREepht.mjs} +3 -3
- package/dist/{credits-B9iORdWB.mjs.map → credits-BKREepht.mjs.map} +1 -1
- package/dist/{dashboard-D0jcgBD7.mjs → dashboard-ynr1qJWM.mjs} +10 -9
- package/dist/dashboard-ynr1qJWM.mjs.map +1 -0
- package/dist/database/migration-lock.mjs +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +3 -3
- package/dist/db/libsql-migrations.d.mts +1 -1
- package/dist/db/libsql-migrations.mjs +5 -5
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres-migrations.d.mts +1 -1
- package/dist/db/postgres-migrations.mjs +5 -5
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite-migrations.d.mts +1 -1
- package/dist/db/sqlite-migrations.mjs +5 -5
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{db-errors-CBD5yMro.mjs → db-errors-unnO6yiZ.mjs} +12 -2
- package/dist/db-errors-unnO6yiZ.mjs.map +1 -0
- package/dist/deferred-tasks-wlMFJL95.d.mts +10 -0
- package/dist/deferred-tasks-wlMFJL95.d.mts.map +1 -0
- package/dist/{destination-r2zIAZ2S.mjs → destination-DR3IHjmy.mjs} +1 -1
- package/dist/{destination-r2zIAZ2S.mjs.map → destination-DR3IHjmy.mjs.map} +1 -1
- package/dist/{device-flow-BkFKBoAn.mjs → device-flow-D1U392GC.mjs} +3 -5
- package/dist/device-flow-D1U392GC.mjs.map +1 -0
- package/dist/{dialect-helpers-7_IqPdh9.mjs → dialect-helpers-B1XN2HGB.mjs} +10 -3
- package/dist/dialect-helpers-B1XN2HGB.mjs.map +1 -0
- package/dist/{direct-executor-Cbxzg4qe.mjs → direct-executor-Bs2g0ake.mjs} +4 -4
- package/dist/{direct-executor-Cbxzg4qe.mjs.map → direct-executor-Bs2g0ake.mjs.map} +1 -1
- package/dist/{dist-Cfu8mMBs.mjs → dist-BUmWMTbN.mjs} +1 -1
- package/dist/{dist-Cfu8mMBs.mjs.map → dist-BUmWMTbN.mjs.map} +1 -1
- package/dist/{email-locale-BJ8DjTzZ.mjs → email-locale-Bs3HFdnq.mjs} +1 -1
- package/dist/{email-locale-BJ8DjTzZ.mjs.map → email-locale-Bs3HFdnq.mjs.map} +1 -1
- package/dist/{emdash-runtime-DVi7vtXC.mjs → emdash-runtime-C8T-pZpS.mjs} +108 -62
- package/dist/emdash-runtime-C8T-pZpS.mjs.map +1 -0
- package/dist/{enrich-Duu4sV3a.mjs → enrich-DFlfnd3u.mjs} +3 -3
- package/dist/{enrich-Duu4sV3a.mjs.map → enrich-DFlfnd3u.mjs.map} +1 -1
- package/dist/{entry-lock-C7VX0NGK.d.mts → entry-lock-BulbgPBX.d.mts} +23 -23
- package/dist/{entry-lock-C7VX0NGK.d.mts.map → entry-lock-BulbgPBX.d.mts.map} +1 -1
- package/dist/{entry-lock-Df6-XhIu.mjs → entry-lock-CRVmruM0.mjs} +4 -4
- package/dist/{entry-lock-Df6-XhIu.mjs.map → entry-lock-CRVmruM0.mjs.map} +1 -1
- package/dist/{entry-lock-DLxCffFW.mjs → entry-lock-D-zJQ4q6.mjs} +3 -3
- package/dist/{entry-lock-DLxCffFW.mjs.map → entry-lock-D-zJQ4q6.mjs.map} +1 -1
- package/dist/{entry-locks-DJAqVweV.mjs → entry-locks-CJ9uhqg1.mjs} +2 -2
- package/dist/{entry-locks-DJAqVweV.mjs.map → entry-locks-CJ9uhqg1.mjs.map} +1 -1
- package/dist/{env-types-C3FCVBWe.mjs → env-types-BE3bCvfP.mjs} +5 -5
- package/dist/{env-types-C3FCVBWe.mjs.map → env-types-BE3bCvfP.mjs.map} +1 -1
- package/dist/{error-CVWeIOku.mjs → error-BCMgPxdn.mjs} +3 -3
- package/dist/{error-CVWeIOku.mjs.map → error-BCMgPxdn.mjs.map} +1 -1
- package/dist/{errors-BOYNdIo3.mjs → errors-8gJqv-XV.mjs} +15 -2
- package/dist/{errors-BOYNdIo3.mjs.map → errors-8gJqv-XV.mjs.map} +1 -1
- package/dist/{fence-C3MUitUN.mjs → fence-Dagicj14.mjs} +4 -4
- package/dist/{fence-C3MUitUN.mjs.map → fence-Dagicj14.mjs.map} +1 -1
- package/dist/{field-map-Bft9LKak.mjs → field-map-BSXdNGt5.mjs} +11 -10
- package/dist/field-map-BSXdNGt5.mjs.map +1 -0
- package/dist/{focal-point-JX8kcOTQ.mjs → focal-point-CgCcr1Ca.mjs} +1 -1
- package/dist/{focal-point-JX8kcOTQ.mjs.map → focal-point-CgCcr1Ca.mjs.map} +1 -1
- package/dist/{fts-manager-Beg3e4bI.mjs → fts-manager-6861qcwk.mjs} +68 -22
- package/dist/fts-manager-6861qcwk.mjs.map +1 -0
- package/dist/{gc-ByyAYiYE.mjs → gc-CNkXB3mE.mjs} +8 -8
- package/dist/{gc-ByyAYiYE.mjs.map → gc-CNkXB3mE.mjs.map} +1 -1
- package/dist/{hook-result-BrdLyOdI.d.mts → hook-result-f8t7hIuu.d.mts} +1 -1
- package/dist/{hook-result-BrdLyOdI.d.mts.map → hook-result-f8t7hIuu.d.mts.map} +1 -1
- package/dist/{hreflang-CY_F5OjF.d.mts → hreflang-8dUOJAPJ.d.mts} +2 -2
- package/dist/{hreflang-CY_F5OjF.d.mts.map → hreflang-8dUOJAPJ.d.mts.map} +1 -1
- package/dist/{hreflang-C8Jb-hrf.mjs → hreflang-BW5A4FLK.mjs} +8 -8
- package/dist/{hreflang-C8Jb-hrf.mjs.map → hreflang-BW5A4FLK.mjs.map} +1 -1
- package/dist/{http-route-dispatch-CyeW6iPv.mjs → http-route-dispatch-rXKvTNm9.mjs} +5 -5
- package/dist/{http-route-dispatch-CyeW6iPv.mjs.map → http-route-dispatch-rXKvTNm9.mjs.map} +1 -1
- package/dist/{identity-Cael5uTT.mjs → identity-CPRRSovU.mjs} +3 -3
- package/dist/{identity-Cael5uTT.mjs.map → identity-CPRRSovU.mjs.map} +1 -1
- package/dist/{import-BUXjdZUn.mjs → import-yVbfPyfd.mjs} +5 -5
- package/dist/{import-BUXjdZUn.mjs.map → import-yVbfPyfd.mjs.map} +1 -1
- package/dist/index-VM7Fzxwe.d.mts +260 -0
- package/dist/index-VM7Fzxwe.d.mts.map +1 -0
- package/dist/index.d.mts +25 -24
- package/dist/index.mjs +89 -88
- package/dist/{install-finalization-3JX5qQEA.mjs → install-finalization-RU6VrHOX.mjs} +1 -1
- package/dist/{install-finalization-3JX5qQEA.mjs.map → install-finalization-RU6VrHOX.mjs.map} +1 -1
- package/dist/{json-recordset-BUjxhr77.mjs → json-recordset-D0WhN2UA.mjs} +2 -2
- package/dist/{json-recordset-BUjxhr77.mjs.map → json-recordset-D0WhN2UA.mjs.map} +1 -1
- package/dist/{lifecycle-7vUJeFRe.mjs → lifecycle-B8d7Rdqx.mjs} +1 -1
- package/dist/{lifecycle-7vUJeFRe.mjs.map → lifecycle-B8d7Rdqx.mjs.map} +1 -1
- package/dist/{load-CdAG9wz-.mjs → load-D4xtzm6h.mjs} +2 -2
- package/dist/{load-CdAG9wz-.mjs.map → load-D4xtzm6h.mjs.map} +1 -1
- package/dist/{loader-CswroUbe.mjs → loader-DhnedqY4.mjs} +199 -101
- package/dist/loader-DhnedqY4.mjs.map +1 -0
- package/dist/{loops-uA4iTOzd.mjs → loops-B2YS-Zzr.mjs} +2 -2
- package/dist/{loops-uA4iTOzd.mjs.map → loops-B2YS-Zzr.mjs.map} +1 -1
- package/dist/{manifest-builder-B8zjuH3f.mjs → manifest-builder-g1FLviel.mjs} +10 -3
- package/dist/manifest-builder-g1FLviel.mjs.map +1 -0
- package/dist/media/image-endpoint.d.mts +3 -2
- package/dist/media/image-endpoint.d.mts.map +1 -1
- package/dist/media/image-endpoint.mjs +17 -8
- package/dist/media/image-endpoint.mjs.map +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +7 -6
- package/dist/media/index.mjs.map +1 -1
- package/dist/media/local-runtime.d.mts +15 -14
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +20 -15
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/{media-1WC65OCB.mjs → media-BR4_t-Wd.mjs} +3 -3
- package/dist/{media-1WC65OCB.mjs.map → media-BR4_t-Wd.mjs.map} +1 -1
- package/dist/{media--dJRU6i2.mjs → media-CikS-q6E.mjs} +4 -4
- package/dist/{media--dJRU6i2.mjs.map → media-CikS-q6E.mjs.map} +1 -1
- package/dist/{media-Bws9f18T.mjs → media-DepNLhPq.mjs} +14 -4
- package/dist/media-DepNLhPq.mjs.map +1 -0
- package/dist/{media-allowlist-BJB7MFx6.mjs → media-allowlist-BMBLqyWh.mjs} +2 -2
- package/dist/{media-allowlist-BJB7MFx6.mjs.map → media-allowlist-BMBLqyWh.mjs.map} +1 -1
- package/dist/{media-folders-Dn3C16B8.mjs → media-folders-CI0Wydfo.mjs} +2 -2
- package/dist/{media-folders-Dn3C16B8.mjs.map → media-folders-CI0Wydfo.mjs.map} +1 -1
- package/dist/{media-usage-CF0WVcLO.mjs → media-usage-X1_20MY-.mjs} +8 -8
- package/dist/{media-usage-CF0WVcLO.mjs.map → media-usage-X1_20MY-.mjs.map} +1 -1
- package/dist/{media-usage-activation-C9HwVw5w.mjs → media-usage-activation-bWusy3M2.mjs} +3 -3
- package/dist/{media-usage-activation-C9HwVw5w.mjs.map → media-usage-activation-bWusy3M2.mjs.map} +1 -1
- package/dist/{media-usage-work-m3AWTmmC.mjs → media-usage-work-B2RaoJIa.mjs} +4 -4
- package/dist/{media-usage-work-m3AWTmmC.mjs.map → media-usage-work-B2RaoJIa.mjs.map} +1 -1
- package/dist/{media-usage-work-CkLa5-nc.mjs → media-usage-work-BCK2J-v_.mjs} +7 -7
- package/dist/{media-usage-work-CkLa5-nc.mjs.map → media-usage-work-BCK2J-v_.mjs.map} +1 -1
- package/dist/{menus-BCVSSp1z.mjs → menus-B0Qqv_cS.mjs} +176 -92
- package/dist/menus-B0Qqv_cS.mjs.map +1 -0
- package/dist/{menus-Cl4kwdt7.mjs → menus-oypxT1pI.mjs} +134 -53
- package/dist/menus-oypxT1pI.mjs.map +1 -0
- package/dist/{menus-BSzwObhV.mjs → menus-uEAxWAm1.mjs} +3 -3
- package/dist/{menus-BSzwObhV.mjs.map → menus-uEAxWAm1.mjs.map} +1 -1
- package/dist/migrations/index.d.mts +1 -1
- package/dist/migrations/index.mjs +5 -5
- package/dist/{mime-B5M9R53H.mjs → mime-D1We9jUx.mjs} +1 -1
- package/dist/{mime-B5M9R53H.mjs.map → mime-D1We9jUx.mjs.map} +1 -1
- package/dist/{normalize-BuWa0lvd.mjs → normalize-Cx-bNwhP.mjs} +41 -12
- package/dist/normalize-Cx-bNwhP.mjs.map +1 -0
- package/dist/{oauth-authorization-TpEJrYB7.mjs → oauth-authorization-CPLgBrdo.mjs} +19 -6
- package/dist/oauth-authorization-CPLgBrdo.mjs.map +1 -0
- package/dist/{oauth-state-store-CHMn_mwc.mjs → oauth-state-store-BndCfRum.mjs} +1 -1
- package/dist/{oauth-state-store-CHMn_mwc.mjs.map → oauth-state-store-BndCfRum.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-Bo6DGaC9.mjs → object-cache-DmKr09La.mjs} +21 -4
- package/dist/{object-cache-Bo6DGaC9.mjs.map → object-cache-DmKr09La.mjs.map} +1 -1
- package/dist/{options-DJWaq3Ie.d.mts → options-BUUgroHg.d.mts} +3 -3
- package/dist/{options-DJWaq3Ie.d.mts.map → options-BUUgroHg.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/page/index.mjs +16 -14
- package/dist/page/index.mjs.map +1 -1
- package/dist/{parse-DgQ2NABT.mjs → parse-B_b6gZxG.mjs} +2 -2
- package/dist/{parse-DgQ2NABT.mjs.map → parse-B_b6gZxG.mjs.map} +1 -1
- package/dist/{parse-CWHOFc6z.d.mts → parse-Dndx1QmN.d.mts} +3 -3
- package/dist/{parse-CWHOFc6z.d.mts.map → parse-Dndx1QmN.d.mts.map} +1 -1
- package/dist/{passkey-config-D0kdzEao.mjs → passkey-config-D2Lua5__.mjs} +1 -1
- package/dist/{passkey-config-D0kdzEao.mjs.map → passkey-config-D2Lua5__.mjs.map} +1 -1
- package/dist/{patterns-CMNnYCgf.mjs → patterns-CryGz_EV.mjs} +1 -1
- package/dist/{patterns-CMNnYCgf.mjs.map → patterns-CryGz_EV.mjs.map} +1 -1
- package/dist/{placeholder-D41vk11_.d.mts → placeholder-CSKu5OkD.d.mts} +9 -1
- package/dist/placeholder-CSKu5OkD.d.mts.map +1 -0
- package/dist/plugin-test-runtime.d.mts +17 -15
- package/dist/plugin-test-runtime.d.mts.map +1 -1
- package/dist/plugin-test-runtime.mjs +99 -98
- package/dist/plugin-types.d.mts +2 -2
- package/dist/plugin-utils.d.mts +13 -12
- package/dist/plugin-utils.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +13 -12
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/host.d.mts +5 -5
- package/dist/plugins/host.mjs +48 -47
- package/dist/{policy-DLQ--Hnm.mjs → policy-BPugqmeV.mjs} +13 -5
- package/dist/policy-BPugqmeV.mjs.map +1 -0
- package/dist/{protocol-79kUO7jP.d.mts → protocol-PoAfD_9W.d.mts} +2 -2
- package/dist/{protocol-79kUO7jP.d.mts.map → protocol-PoAfD_9W.d.mts.map} +1 -1
- package/dist/{public-plugin-api-routes-BuAMJ8nN.mjs → public-plugin-api-routes-CMljrTby.mjs} +9 -9
- package/dist/{public-plugin-api-routes-BuAMJ8nN.mjs.map → public-plugin-api-routes-CMljrTby.mjs.map} +1 -1
- package/dist/{public-submission-Di3TsgzX.mjs → public-submission-ayqoyee4.mjs} +10 -10
- package/dist/{public-submission-Di3TsgzX.mjs.map → public-submission-ayqoyee4.mjs.map} +1 -1
- package/dist/query-BFHjCzSh.mjs +37 -0
- package/dist/query-BFHjCzSh.mjs.map +1 -0
- package/dist/{query-CpnRlBh8.mjs → query-D62NntCZ.mjs} +55 -65
- package/dist/query-D62NntCZ.mjs.map +1 -0
- package/dist/{query-haKvLAWl.mjs → query-LmPY2y0C.mjs} +5 -5
- package/dist/{query-haKvLAWl.mjs.map → query-LmPY2y0C.mjs.map} +1 -1
- package/dist/{rate-limit-Xp4d0NBY.mjs → rate-limit-C04Llsoc.mjs} +3 -3
- package/dist/{rate-limit-Xp4d0NBY.mjs.map → rate-limit-C04Llsoc.mjs.map} +1 -1
- package/dist/{redirect-DiS_3mA4.mjs → redirect-DjLdw427.mjs} +6 -6
- package/dist/{redirect-DiS_3mA4.mjs.map → redirect-DjLdw427.mjs.map} +1 -1
- package/dist/{redirect-paths-CNYq7w80.mjs → redirect-paths-DOaVBp6E.mjs} +1 -1
- package/dist/{redirect-paths-CNYq7w80.mjs.map → redirect-paths-DOaVBp6E.mjs.map} +1 -1
- package/dist/{redirects-BHpy-VsZ.mjs → redirects-Cpq1catN.mjs} +6 -6
- package/dist/{redirects-BHpy-VsZ.mjs.map → redirects-Cpq1catN.mjs.map} +1 -1
- package/dist/{redirects-BEVSRMa2.mjs → redirects-CyvvZrCJ.mjs} +2 -2
- package/dist/{redirects-BEVSRMa2.mjs.map → redirects-CyvvZrCJ.mjs.map} +1 -1
- package/dist/{registry-TUVaid9Z.mjs → registry-B0-O575m.mjs} +25 -20
- package/dist/registry-B0-O575m.mjs.map +1 -0
- package/dist/{relations-CA_QuMTU.mjs → relations-WIOojTL4.mjs} +24 -11
- package/dist/relations-WIOojTL4.mjs.map +1 -0
- package/dist/{request-cache-C4CIo5ad.mjs → request-cache-5z2WzWmh.mjs} +1 -1
- package/dist/{request-cache-C4CIo5ad.mjs.map → request-cache-5z2WzWmh.mjs.map} +1 -1
- package/dist/request-context.d.mts +12 -1
- package/dist/request-context.d.mts.map +1 -1
- package/dist/request-context.mjs.map +1 -1
- package/dist/{resolve-DwNM-CXl.mjs → resolve-BNnm8EkB.mjs} +14 -13
- package/dist/{resolve-DwNM-CXl.mjs.map → resolve-BNnm8EkB.mjs.map} +1 -1
- package/dist/{resolve-D-kqyKns.mjs → resolve-DdNXBJSr.mjs} +4 -4
- package/dist/resolve-DdNXBJSr.mjs.map +1 -0
- package/dist/{revision-BVp8S0e_.mjs → revision-Dx7Uth1X.mjs} +5 -5
- package/dist/{revision-BVp8S0e_.mjs.map → revision-Dx7Uth1X.mjs.map} +1 -1
- package/dist/{routes-BerZFrvV.mjs → routes-avqgc-8r.mjs} +3 -3
- package/dist/{routes-BerZFrvV.mjs.map → routes-avqgc-8r.mjs.map} +1 -1
- package/dist/{runner-C5NeAkBQ.mjs → runner-Bkkfk4O8.mjs} +78 -4
- package/dist/runner-Bkkfk4O8.mjs.map +1 -0
- package/dist/{runner-BObHz5FC.d.mts → runner-Dfgp6-S_.d.mts} +7 -2
- package/dist/runner-Dfgp6-S_.d.mts.map +1 -0
- package/dist/runtime.d.mts +14 -13
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +8 -6
- package/dist/runtime.mjs.map +1 -1
- package/dist/schema/project-env-types.mjs +43 -42
- package/dist/schema/project-env-types.mjs.map +1 -1
- package/dist/{schema-DJRfvM_o.mjs → schema-B-3rntlX.mjs} +11 -11
- package/dist/{schema-DJRfvM_o.mjs.map → schema-B-3rntlX.mjs.map} +1 -1
- package/dist/{schema-C4OBuv6Z.mjs → schema-BqBlUZtb.mjs} +4 -4
- package/dist/{schema-C4OBuv6Z.mjs.map → schema-BqBlUZtb.mjs.map} +1 -1
- package/dist/{scopes-BU03K7Uo.mjs → scopes-DNaY7Ey0.mjs} +3 -3
- package/dist/{scopes-BU03K7Uo.mjs.map → scopes-DNaY7Ey0.mjs.map} +1 -1
- package/dist/{search-DfVzks89.mjs → search-BPWTnpnD.mjs} +32 -32
- package/dist/search-BPWTnpnD.mjs.map +1 -0
- package/dist/{secrets-Cc_O3Kp-.mjs → secrets-Dswzrz3k.mjs} +2 -2
- package/dist/{secrets-Cc_O3Kp-.mjs.map → secrets-Dswzrz3k.mjs.map} +1 -1
- package/dist/{sections-BMy4JVUz.mjs → sections-rSao6rBG.mjs} +3 -3
- package/dist/{sections-BMy4JVUz.mjs.map → sections-rSao6rBG.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +42 -41
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +30 -28
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-VZYOEy8f.mjs → seo-B_H_pqOd.mjs} +3 -3
- package/dist/{seo-VZYOEy8f.mjs.map → seo-B_H_pqOd.mjs.map} +1 -1
- package/dist/{service-Bo_usgSk.mjs → service-DpiUQVpp.mjs} +2 -2
- package/dist/{service-Bo_usgSk.mjs.map → service-DpiUQVpp.mjs.map} +1 -1
- package/dist/{session-user-DlpPdf8L.mjs → session-user-DiE4JKPP.mjs} +4 -4
- package/dist/{session-user-DlpPdf8L.mjs.map → session-user-DiE4JKPP.mjs.map} +1 -1
- package/dist/{settings-DS914jjE.mjs → settings--XlUdUaI.mjs} +3 -3
- package/dist/{settings-DS914jjE.mjs.map → settings--XlUdUaI.mjs.map} +1 -1
- package/dist/{settings-CWb84sDm.mjs → settings-D932YP2-.mjs} +111 -44
- package/dist/settings-D932YP2-.mjs.map +1 -0
- package/dist/{setup-complete-BuNxAUiN.mjs → setup-complete-qsJYWutC.mjs} +2 -2
- package/dist/{setup-complete-BuNxAUiN.mjs.map → setup-complete-qsJYWutC.mjs.map} +1 -1
- package/dist/{setup-nonce-BnEAX0iy.mjs → setup-nonce-CBFgUFXw.mjs} +1 -1
- package/dist/{setup-nonce-BnEAX0iy.mjs.map → setup-nonce-CBFgUFXw.mjs.map} +1 -1
- package/dist/{site-domain-Bq5j5bVg.mjs → site-domain-oRGS_JfA.mjs} +2 -2
- package/dist/{site-domain-Bq5j5bVg.mjs.map → site-domain-oRGS_JfA.mjs.map} +1 -1
- package/dist/{sitemap-name-BTg2NJJv.mjs → sitemap-name-B8QP8wud.mjs} +1 -1
- package/dist/{sitemap-name-BTg2NJJv.mjs.map → sitemap-name-B8QP8wud.mjs.map} +1 -1
- package/dist/{slugify-bu2-jKia.mjs → slugify-BDEG9pLk.mjs} +1 -1
- package/dist/{slugify-bu2-jKia.mjs.map → slugify-BDEG9pLk.mjs.map} +1 -1
- package/dist/{snapshot-DYsG4uOq.mjs → snapshot-BjaXDZQ5.mjs} +2 -2
- package/dist/{snapshot-DYsG4uOq.mjs.map → snapshot-BjaXDZQ5.mjs.map} +1 -1
- package/dist/{stage-D8DWgPcO.mjs → stage-CZQnXM_G.mjs} +3 -3
- package/dist/{stage-D8DWgPcO.mjs.map → stage-CZQnXM_G.mjs.map} +1 -1
- package/dist/{staged-CD_imitH.mjs → staged-ByBmPFtX.mjs} +3 -3
- package/dist/{staged-CD_imitH.mjs.map → staged-ByBmPFtX.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/{storage-query-DRyu3bSU.d.mts → storage-query-BFp06Y0s.d.mts} +22 -10
- package/dist/storage-query-BFp06Y0s.d.mts.map +1 -0
- package/dist/{taxonomies-Dd9JJv_a.mjs → taxonomies-5SR76j11.mjs} +15 -17
- package/dist/taxonomies-5SR76j11.mjs.map +1 -0
- package/dist/{taxonomies-ChnU7Mc8.mjs → taxonomies-B__VmCKQ.mjs} +64 -58
- package/dist/taxonomies-B__VmCKQ.mjs.map +1 -0
- package/dist/{taxonomy-C_C_LBAU.mjs → taxonomy-CMI5fczd.mjs} +30 -17
- package/dist/taxonomy-CMI5fczd.mjs.map +1 -0
- package/dist/{transaction-BVYIo_yu.mjs → transaction-CkoQ5wqQ.mjs} +1 -1
- package/dist/{transaction-BVYIo_yu.mjs.map → transaction-CkoQ5wqQ.mjs.map} +1 -1
- package/dist/{transfer-WmWiR3xf.mjs → transfer-BbKfufJ4.mjs} +2 -2
- package/dist/{transfer-WmWiR3xf.mjs.map → transfer-BbKfufJ4.mjs.map} +1 -1
- package/dist/{transfer-ClH6w6BV.mjs → transfer-DTGblAj2.mjs} +71 -34
- package/dist/{transfer-ClH6w6BV.mjs.map → transfer-DTGblAj2.mjs.map} +1 -1
- package/dist/{transfer-download--ofRj9Cw.mjs → transfer-download-D9LQEDX0.mjs} +1 -1
- package/dist/{transfer-download--ofRj9Cw.mjs.map → transfer-download-D9LQEDX0.mjs.map} +1 -1
- package/dist/{transport-DxiXnbXk.d.mts → transport-Dm5QzpT_.d.mts} +1 -1
- package/dist/{transport-DxiXnbXk.d.mts.map → transport-Dm5QzpT_.d.mts.map} +1 -1
- package/dist/{transport-BjbqNiPI.mjs → transport-Dzpn5b3i.mjs} +4 -3
- package/dist/transport-Dzpn5b3i.mjs.map +1 -0
- package/dist/{turnstile-CJwvsOqw.mjs → turnstile-Cs2wfkJG.mjs} +1 -1
- package/dist/{turnstile-CJwvsOqw.mjs.map → turnstile-Cs2wfkJG.mjs.map} +1 -1
- package/dist/{types-BA3ey2QH.d.mts → types-BAsCk5KU.d.mts} +1 -1
- package/dist/{types-BA3ey2QH.d.mts.map → types-BAsCk5KU.d.mts.map} +1 -1
- package/dist/{types-RLgeIpnF.d.mts → types-BuvSwT9Y.d.mts} +8 -7
- package/dist/{types-RLgeIpnF.d.mts.map → types-BuvSwT9Y.d.mts.map} +1 -1
- package/dist/{types-CNB-dj6F.d.mts → types-C4KT3Md2.d.mts} +10 -6
- package/dist/types-C4KT3Md2.d.mts.map +1 -0
- package/dist/{types-DvqVxZXa.d.mts → types-CVXHwIBB.d.mts} +1 -1
- package/dist/{types-DvqVxZXa.d.mts.map → types-CVXHwIBB.d.mts.map} +1 -1
- package/dist/{types-BGmQ0uXs.mjs → types-C_asjp1J.mjs} +1 -1
- package/dist/types-C_asjp1J.mjs.map +1 -0
- package/dist/{types-DHO7Pd25.d.mts → types-CadaL_k8.d.mts} +1 -1
- package/dist/{types-DHO7Pd25.d.mts.map → types-CadaL_k8.d.mts.map} +1 -1
- package/dist/{types-QoPHm-2w.d.mts → types-CjftrmZR.d.mts} +3 -3
- package/dist/{types-QoPHm-2w.d.mts.map → types-CjftrmZR.d.mts.map} +1 -1
- package/dist/{types-DCFavOii.d.mts → types-DKwRUA-x.d.mts} +1 -1
- package/dist/{types-DCFavOii.d.mts.map → types-DKwRUA-x.d.mts.map} +1 -1
- package/dist/{types-D2NEXtgB.mjs → types-DwhEvIVb.mjs} +8 -2
- package/dist/types-DwhEvIVb.mjs.map +1 -0
- package/dist/{types-Bwpzb5o6.d.mts → types-GwAyS5SH.d.mts} +1 -1
- package/dist/{types-Bwpzb5o6.d.mts.map → types-GwAyS5SH.d.mts.map} +1 -1
- package/dist/{types-slSqujQL.d.mts → types-uU2YNYSt.d.mts} +6 -1
- package/dist/types-uU2YNYSt.d.mts.map +1 -0
- package/dist/{update-check-BxNg9T6N.mjs → update-check-ABBJgg6M.mjs} +4 -4
- package/dist/{update-check-BxNg9T6N.mjs.map → update-check-ABBJgg6M.mjs.map} +1 -1
- package/dist/{url-Dn3IStq8.mjs → url-DTfGDJhI.mjs} +1 -1
- package/dist/{url-Dn3IStq8.mjs.map → url-DTfGDJhI.mjs.map} +1 -1
- package/dist/{user-BlCTKVAm.mjs → user-By8SzQxS.mjs} +3 -3
- package/dist/{user-BlCTKVAm.mjs.map → user-By8SzQxS.mjs.map} +1 -1
- package/dist/{utils-TPt7w2cS.mjs → utils-D5uOi6WS.mjs} +13 -5
- package/dist/utils-D5uOi6WS.mjs.map +1 -0
- package/dist/{index-BB9sVisO.d.mts → utils-Szp4iBQB.d.mts} +9 -256
- package/dist/utils-Szp4iBQB.d.mts.map +1 -0
- package/dist/{validate-emKxGC5F.d.mts → validate-DDvxy6qG.d.mts} +8 -8
- package/dist/{validate-emKxGC5F.d.mts.map → validate-DDvxy6qG.d.mts.map} +1 -1
- package/dist/{validate-DxYhJQA-.mjs → validate-Dz-TIOFB.mjs} +7 -7
- package/dist/{validate-DxYhJQA-.mjs.map → validate-Dz-TIOFB.mjs.map} +1 -1
- package/dist/{validation-Ckq4vsVg.mjs → validation-Fc9ZSUS_.mjs} +17 -16
- package/dist/{validation-Ckq4vsVg.mjs.map → validation-Fc9ZSUS_.mjs.map} +1 -1
- package/dist/version-Bu6Nlbb5.mjs +7 -0
- package/dist/{version-DHmGpcch.mjs.map → version-Bu6Nlbb5.mjs.map} +1 -1
- package/dist/version-DqB7LIO7.mjs +49 -0
- package/dist/version-DqB7LIO7.mjs.map +1 -0
- package/dist/{widgets-DA5XmvVC.mjs → widgets-BUx_Mf2q.mjs} +18 -5
- package/dist/widgets-BUx_Mf2q.mjs.map +1 -0
- package/dist/{wxr-taxonomies-RgRG0d5e.mjs → wxr-taxonomies-DbJtWrWM.mjs} +7 -6
- package/dist/wxr-taxonomies-DbJtWrWM.mjs.map +1 -0
- package/dist/{wxr-taxonomies-CrMonejI.d.mts → wxr-taxonomies-Dy2i2ON3.d.mts} +1 -1
- package/dist/wxr-taxonomies-Dy2i2ON3.d.mts.map +1 -0
- package/dist/{zod-generator-D0JKy94C.mjs → zod-generator--nlM0930.mjs} +5 -4
- package/dist/zod-generator--nlM0930.mjs.map +1 -0
- package/package.json +5 -5
- package/src/api/handlers/bulk-tag.ts +11 -3
- package/src/api/handlers/bylines.ts +6 -2
- package/src/api/handlers/content.ts +154 -23
- package/src/api/handlers/dashboard.ts +13 -6
- package/src/api/handlers/device-flow.ts +1 -3
- package/src/api/handlers/menus.ts +27 -13
- package/src/api/handlers/oauth-authorization.ts +1 -3
- package/src/api/handlers/relations.ts +15 -1
- package/src/api/handlers/taxonomies.ts +27 -17
- package/src/astro/image-endpoint.ts +23 -2
- package/src/astro/integration/admin-nav.ts +52 -0
- package/src/astro/integration/index.ts +7 -0
- package/src/astro/integration/runtime.ts +14 -0
- package/src/astro/integration/shims/use-sync-external-store-with-selector.js +2 -0
- package/src/astro/integration/shims/use-sync-external-store.js +4 -1
- package/src/astro/integration/vite-config.ts +16 -8
- package/src/astro/middleware/auth.ts +9 -2
- package/src/astro/middleware/redirect.ts +158 -63
- package/src/astro/middleware/request-context.ts +1 -0
- package/src/astro/middleware.ts +17 -4
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +4 -1
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +14 -1
- package/src/astro/routes/api/dashboard.ts +2 -0
- package/src/astro/routes/api/import/wordpress/analyze.ts +5 -29
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -3
- package/src/astro/routes/api/media/file/[...key].ts +31 -7
- package/src/astro/routes/api/oauth/token.ts +5 -1
- package/src/astro/routes/api/widget-areas/[name]/reorder.ts +7 -1
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +3 -1
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +2 -1
- package/src/astro/routes/api/widget-areas/[name].ts +2 -1
- package/src/astro/routes/api/widget-areas/index.ts +2 -1
- package/src/astro/types.ts +4 -3
- package/src/auth/api-tokens.ts +3 -0
- package/src/auth/types.ts +6 -0
- package/src/cleanup.ts +44 -0
- package/src/cli/commands/export-seed.ts +6 -4
- package/src/cli/commands/login.ts +2 -4
- package/src/client/index.ts +1 -0
- package/src/client/transport.ts +11 -7
- package/src/components/EmDashImage.astro +14 -2
- package/src/components/InlinePortableTextEditor.tsx +4 -1
- package/src/components/inline-bubble-menu.tsx +109 -95
- package/src/components/inline-image.tsx +54 -48
- package/src/database/dialect-helpers.ts +10 -3
- package/src/database/migrations/content-sized.ts +82 -0
- package/src/database/migrations/policy.ts +28 -2
- package/src/database/migrations/runner.ts +48 -0
- package/src/database/repositories/byline.ts +95 -31
- package/src/database/repositories/comment.ts +17 -7
- package/src/database/repositories/content.ts +96 -23
- package/src/database/repositories/media.ts +17 -0
- package/src/database/repositories/menu.ts +236 -139
- package/src/database/repositories/taxonomy-def.ts +9 -2
- package/src/database/repositories/taxonomy.ts +47 -14
- package/src/database/repositories/types.ts +14 -3
- package/src/database/types.ts +1 -1
- package/src/emdash-runtime.ts +60 -17
- package/src/fields/image.ts +1 -0
- package/src/i18n/config.ts +58 -10
- package/src/i18n/normalize.ts +16 -2
- package/src/i18n/query.ts +47 -0
- package/src/i18n/resolve.ts +8 -3
- package/src/import/utils.ts +15 -2
- package/src/import/wxr-taxonomies.ts +3 -2
- package/src/index.ts +1 -0
- package/src/loader.ts +183 -114
- package/src/mcp/server.ts +28 -1
- package/src/media/caption.ts +30 -0
- package/src/media/content-disposition.ts +56 -0
- package/src/media/image-endpoint.ts +13 -6
- package/src/media/local-runtime.ts +3 -0
- package/src/media/normalize.ts +17 -8
- package/src/media/responsive.ts +12 -2
- package/src/media/types.ts +16 -3
- package/src/media/usage/content-fields.ts +2 -1
- package/src/menus/index.ts +158 -36
- package/src/migrations/manifest.ts +1 -0
- package/src/object-cache/index.ts +22 -0
- package/src/plugin-test-runtime.ts +1 -0
- package/src/plugins/byline-access.ts +3 -1
- package/src/plugins/context.ts +1 -2
- package/src/plugins/storage-indexes.ts +7 -3
- package/src/query.ts +67 -53
- package/src/redirects/artifacts.ts +39 -5
- package/src/references/field-map.ts +6 -4
- package/src/request-context.ts +8 -0
- package/src/schema/collection-slugs-cache.ts +31 -17
- package/src/schema/registry.ts +9 -0
- package/src/schema/types.ts +7 -6
- package/src/schema/zod-generator.ts +2 -1
- package/src/search/fts-manager.ts +103 -31
- package/src/search/query.ts +31 -64
- package/src/seed/apply.ts +221 -109
- package/src/seed/types.ts +6 -4
- package/src/settings/index.ts +135 -35
- package/src/settings/version.ts +54 -0
- package/src/taxonomies/index.ts +99 -85
- package/src/taxonomies/term-counts.ts +2 -1
- package/src/transfer/import/advance.ts +12 -1
- package/src/transfer/import/scaffold.ts +7 -1
- package/src/transfer/import/stages.ts +53 -2
- package/src/utils/db-errors.ts +15 -0
- package/src/utils/revalidating-cache.ts +85 -0
- package/src/virtual-modules.d.ts +1 -0
- package/src/visual-editing/toolbar.ts +7 -2
- package/src/widgets/index.ts +27 -13
- package/dist/api-D-7BNHoz.mjs.map +0 -1
- package/dist/api-tokens-CdP49zVF.mjs +0 -3
- package/dist/apply-T7ATgzCh.mjs.map +0 -1
- package/dist/artifacts-htGyfCSt.mjs.map +0 -1
- package/dist/byline-BR1qhyiw.mjs.map +0 -1
- package/dist/bylines-CVOvRUL7.mjs.map +0 -1
- package/dist/collection-slugs-cache-e09QeJQt.mjs.map +0 -1
- package/dist/comment-UvIWDKcW.mjs.map +0 -1
- package/dist/config-Bsm_u_oE.d.mts.map +0 -1
- package/dist/config-CFMojMFK.d.mts.map +0 -1
- package/dist/config-CvmjJcVw.mjs +0 -73
- package/dist/config-CvmjJcVw.mjs.map +0 -1
- package/dist/content-DQSRZTVw.mjs.map +0 -1
- package/dist/context-BYptmCN0.mjs.map +0 -1
- package/dist/dashboard-D0jcgBD7.mjs.map +0 -1
- package/dist/db-errors-CBD5yMro.mjs.map +0 -1
- package/dist/deferred-tasks-ZvUECSzI.d.mts +0 -9
- package/dist/deferred-tasks-ZvUECSzI.d.mts.map +0 -1
- package/dist/device-flow-BkFKBoAn.mjs.map +0 -1
- package/dist/dialect-helpers-7_IqPdh9.mjs.map +0 -1
- package/dist/emdash-runtime-DVi7vtXC.mjs.map +0 -1
- package/dist/field-defs-cache-Dez5iWJJ.mjs +0 -77
- package/dist/field-defs-cache-Dez5iWJJ.mjs.map +0 -1
- package/dist/field-map-Bft9LKak.mjs.map +0 -1
- package/dist/fts-manager-Beg3e4bI.mjs.map +0 -1
- package/dist/index-BB9sVisO.d.mts.map +0 -1
- package/dist/loader-CswroUbe.mjs.map +0 -1
- package/dist/manifest-builder-B8zjuH3f.mjs.map +0 -1
- package/dist/media-Bws9f18T.mjs.map +0 -1
- package/dist/menus-BCVSSp1z.mjs.map +0 -1
- package/dist/menus-Cl4kwdt7.mjs.map +0 -1
- package/dist/normalize-BuWa0lvd.mjs.map +0 -1
- package/dist/oauth-authorization-TpEJrYB7.mjs.map +0 -1
- package/dist/placeholder-D41vk11_.d.mts.map +0 -1
- package/dist/policy-DLQ--Hnm.mjs.map +0 -1
- package/dist/query-CpnRlBh8.mjs.map +0 -1
- package/dist/registry-TUVaid9Z.mjs.map +0 -1
- package/dist/relations-CA_QuMTU.mjs.map +0 -1
- package/dist/resolve-D-kqyKns.mjs.map +0 -1
- package/dist/runner-BObHz5FC.d.mts.map +0 -1
- package/dist/runner-C5NeAkBQ.mjs.map +0 -1
- package/dist/search-DfVzks89.mjs.map +0 -1
- package/dist/settings-CWb84sDm.mjs.map +0 -1
- package/dist/storage-query-DRyu3bSU.d.mts.map +0 -1
- package/dist/taxonomies-ChnU7Mc8.mjs.map +0 -1
- package/dist/taxonomies-Dd9JJv_a.mjs.map +0 -1
- package/dist/taxonomy-C_C_LBAU.mjs.map +0 -1
- package/dist/transport-BjbqNiPI.mjs.map +0 -1
- package/dist/types-BGmQ0uXs.mjs.map +0 -1
- package/dist/types-CNB-dj6F.d.mts.map +0 -1
- package/dist/types-D2NEXtgB.mjs.map +0 -1
- package/dist/types-slSqujQL.d.mts.map +0 -1
- package/dist/utils-TPt7w2cS.mjs.map +0 -1
- package/dist/version-DHmGpcch.mjs +0 -7
- package/dist/widgets-DA5XmvVC.mjs.map +0 -1
- package/dist/wxr-taxonomies-CrMonejI.d.mts.map +0 -1
- package/dist/wxr-taxonomies-RgRG0d5e.mjs.map +0 -1
- package/dist/zod-generator-D0JKy94C.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fts-manager-6861qcwk.mjs","names":["dialectTableExists"],"sources":["../src/search/fts-manager.ts"],"sourcesContent":["/**\n * FTS5 Manager\n *\n * Manages FTS5 virtual tables and triggers for search indexing.\n */\n\nimport type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nimport { isSqlite, tableExists as dialectTableExists } from \"../database/dialect-helpers.js\";\nimport type { Database } from \"../database/types.js\";\nimport { validateIdentifier } from \"../database/validate.js\";\nimport { isStoragelessFieldRow } from \"../schema/types.js\";\nimport { SEARCH_TOKENIZERS } from \"./types.js\";\nimport type { SearchConfig, SearchTokenizer } from \"./types.js\";\n\nconst DEFAULT_SEARCH_TOKENIZER: SearchTokenizer = \"porter unicode61\";\n\nfunction isSearchTokenizer(value: unknown): value is SearchTokenizer {\n\treturn SEARCH_TOKENIZERS.some((tokenizer) => tokenizer === value);\n}\n\nfunction resolveSearchTokenizer(tokenize?: SearchTokenizer): SearchTokenizer {\n\tif (tokenize === undefined) return DEFAULT_SEARCH_TOKENIZER;\n\tif (!isSearchTokenizer(tokenize)) {\n\t\tthrow new Error(`Unsupported FTS5 tokenizer: \"${String(tokenize)}\"`);\n\t}\n\treturn tokenize;\n}\n\nexport interface CollectionSearchMetadata {\n\tconfig: SearchConfig;\n\tsearchableFields: string[];\n\thasTitle: boolean;\n}\n\nfunction parseSearchConfig(searchConfig: string, titleField: string | null): SearchConfig | null {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(searchConfig);\n\t\tif (\n\t\t\ttypeof parsed !== \"object\" ||\n\t\t\tparsed === null ||\n\t\t\t!(\"enabled\" in parsed) ||\n\t\t\ttypeof parsed.enabled !== \"boolean\"\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\tconst config: SearchConfig = { enabled: parsed.enabled };\n\t\tif (titleField) config.titleField = titleField;\n\t\tif (\"weights\" in parsed && typeof parsed.weights === \"object\" && parsed.weights !== null) {\n\t\t\t// weights is a JSON-parsed object — safe to treat as Record<string, number>\n\t\t\tconst weights: Record<string, number> = {};\n\t\t\tfor (const [k, v] of Object.entries(parsed.weights)) {\n\t\t\t\tif (typeof v === \"number\") {\n\t\t\t\t\tweights[k] = v;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconfig.weights = weights;\n\t\t}\n\t\tif (\"tokenize\" in parsed) {\n\t\t\tif (!isSearchTokenizer(parsed.tokenize)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconfig.tokenize = parsed.tokenize;\n\t\t}\n\t\treturn config;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * FTS5 Manager\n *\n * Handles creation, deletion, and management of FTS5 virtual tables\n * for full-text search on content collections.\n */\nexport class FTSManager {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t/**\n\t * Validate a collection slug and its searchable field names.\n\t * Must be called before any raw SQL interpolation.\n\t */\n\tprivate validateInputs(collectionSlug: string, searchableFields?: string[]): void {\n\t\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\t\tif (searchableFields) {\n\t\t\tfor (const field of searchableFields) {\n\t\t\t\tvalidateIdentifier(field, \"searchable field name\");\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the FTS table name for a collection\n\t * Uses _emdash_ prefix to clearly mark as internal/system table\n\t */\n\tgetFtsTableName(collectionSlug: string): string {\n\t\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\t\treturn `_emdash_fts_${collectionSlug}`;\n\t}\n\n\t/**\n\t * Get the content table name for a collection\n\t */\n\tgetContentTableName(collectionSlug: string): string {\n\t\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\t\treturn `ec_${collectionSlug}`;\n\t}\n\n\t/**\n\t * Check if an FTS table exists for a collection\n\t */\n\tasync ftsTableExists(collectionSlug: string): Promise<boolean> {\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\t\treturn dialectTableExists(this.db, ftsTable);\n\t}\n\n\t/**\n\t * Create an FTS5 virtual table for a collection.\n\t * FTS5 is SQLite-only; on other dialects this is a no-op.\n\t *\n\t * @param collectionSlug - The collection slug\n\t * @param searchableFields - Array of field names to index\n\t * @param weights - Optional field weights for ranking\n\t * @param tokenize - Optional FTS5 tokenizer configuration\n\t */\n\tasync createFtsTable(\n\t\tcollectionSlug: string,\n\t\tsearchableFields: string[],\n\t\t_weights?: Record<string, number>,\n\t\ttokenize?: SearchTokenizer,\n\t): Promise<void> {\n\t\tconst tokenizer = resolveSearchTokenizer(tokenize);\n\t\tif (!isSqlite(this.db)) return;\n\t\tthis.validateInputs(collectionSlug, searchableFields);\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\n\t\t// Build the column list for FTS5\n\t\t// id and locale are UNINDEXED (used for joining/filtering, not searched)\n\t\tconst columns = [\"id UNINDEXED\", \"locale UNINDEXED\", ...searchableFields].join(\", \");\n\n\t\t// Create the FTS5 virtual table. The table stores its own copy of the\n\t\t// indexed values (no `content=` option): Portable Text fields are\n\t\t// indexed as extracted plain text — see searchValueExpr — which cannot\n\t\t// mirror the raw JSON in the ec_* column, and external-content FTS5\n\t\t// requires the index to exactly mirror the backing table's values\n\t\t// (snippet() reads them, and the 'delete' command must be fed the\n\t\t// inserted values or the index corrupts — see migration 039's history).\n\t\t// Storing the extracted text also makes snippet() return prose.\n\t\tawait sql\n\t\t\t.raw(`\n\t\t\tCREATE VIRTUAL TABLE IF NOT EXISTS \"${ftsTable}\" USING fts5(\n\t\t\t\t${columns},\n\t\t\t\ttokenize='${tokenizer}'\n\t\t\t)\n\t\t`)\n\t\t\t.execute(this.db);\n\n\t\t// Create triggers for automatic sync\n\t\tawait this.createTriggers(collectionSlug, searchableFields);\n\t}\n\n\t/**\n\t * SQL expression producing the indexed value for one searchable field.\n\t *\n\t * Portable Text fields are stored as JSON; indexing the raw JSON pollutes\n\t * the index with structural tokens (`_type`, style values like `normal`,\n\t * `_key` ULIDs) and makes snippets show JSON fragments. Extract the prose\n\t * instead: every JSON string under a `text`, `alt`, `caption`, or `code`\n\t * key (span text, image alt/caption, code blocks). This is a superset of\n\t * `extractPlainText` in text-extraction.ts, which walks only known block\n\t * shapes — the SQL variant takes those keys at any depth, so search and\n\t * the extractPlainText consumers (vectorize/ai-search) can see different\n\t * text for the same document. Only JSON documents\n\t * (arrays/objects) are extracted; legacy rows holding a bare string or a\n\t * JSON scalar (`Some title`, `2024`) are indexed as-is. Extraction must\n\t * live in SQL because the sync triggers cannot call into JS.\n\t *\n\t * `ref` must be a validated column reference (`NEW.x`, `OLD.x`, `\"x\"`).\n\t */\n\tprivate searchValueExpr(ref: string, fieldType: string | undefined): string {\n\t\tif (fieldType !== \"portableText\") return ref;\n\t\treturn (\n\t\t\t`CASE WHEN ${ref} IS NULL THEN NULL ` +\n\t\t\t`WHEN json_valid(${ref}) AND json_type(${ref}) IN ('array', 'object') THEN (` +\n\t\t\t`SELECT group_concat(j.value, ' ') FROM json_tree(${ref}) AS j ` +\n\t\t\t`WHERE j.key IN ('text', 'alt', 'caption', 'code') AND j.type = 'text') ` +\n\t\t\t`ELSE ${ref} END`\n\t\t);\n\t}\n\n\t/**\n\t * Field type per slug for a collection, for choosing the indexed-value\n\t * expression. Fields missing from the schema fall back to raw indexing.\n\t */\n\tprivate async getFieldTypes(collectionSlug: string): Promise<Map<string, string>> {\n\t\tconst collection = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t\t.executeTakeFirst();\n\t\tif (!collection) return new Map();\n\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.select([\"slug\", \"type\"])\n\t\t\t.where(\"collection_id\", \"=\", collection.id)\n\t\t\t.execute();\n\t\treturn new Map(rows.map((r) => [r.slug, r.type]));\n\t}\n\n\t/**\n\t * Create triggers to keep FTS table in sync with content table.\n\t *\n\t * The insert and update triggers only add rows to the FTS index when\n\t * `deleted_at IS NULL`. This keeps soft-deleted content out of the\n\t * search index and ensures the FTS row count matches the non-deleted\n\t * content count (which `verifyAndRepairIndex` relies on).\n\t *\n\t * The FTS table stores its own values (no `content=` option), so removal\n\t * is a plain `DELETE FROM fts WHERE rowid = OLD.rowid` — a harmless no-op\n\t * for rows that were never indexed (soft-deleted content). The\n\t * external-content `'delete'`-command choreography and its corruption\n\t * modes (migration 039) do not apply to self-contained tables.\n\t *\n\t * `INSERT OR REPLACE` keeps the insert path idempotent: re-running a\n\t * populate (search repair runs per isolate, so two isolates can race) converges\n\t * on one index row per content row instead of failing on the rowid\n\t * constraint.\n\t *\n\t * The trigger SQL emitted here MUST stay in lock-step with migration\n\t * `064_fts_plain_text.ts`. If this changes again, add a new migration\n\t * rather than editing shipped ones — migrations are forward-only.\n\t */\n\tprivate async createTriggers(collectionSlug: string, searchableFields: string[]): Promise<void> {\n\t\tthis.validateInputs(collectionSlug, searchableFields);\n\t\tif (searchableFields.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot create FTS triggers for collection \"${collectionSlug}\": no searchable fields. ` +\n\t\t\t\t\t`Mark at least one field as searchable before enabling search.`,\n\t\t\t);\n\t\t}\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\t\tconst contentTable = this.getContentTableName(collectionSlug);\n\t\tconst fieldTypes = await this.getFieldTypes(collectionSlug);\n\t\tconst fieldList = searchableFields.join(\", \");\n\t\tconst newValueList = searchableFields\n\t\t\t.map((f) => this.searchValueExpr(`NEW.${f}`, fieldTypes.get(f)))\n\t\t\t.join(\", \");\n\n\t\t// Insert trigger - only index non-deleted content\n\t\tawait sql\n\t\t\t.raw(`\n\t\t\tCREATE TRIGGER IF NOT EXISTS \"${ftsTable}_insert\"\n\t\t\tAFTER INSERT ON \"${contentTable}\"\n\t\t\tWHEN NEW.deleted_at IS NULL\n\t\t\tBEGIN\n\t\t\t\tINSERT OR REPLACE INTO \"${ftsTable}\"(rowid, id, locale, ${fieldList})\n\t\t\t\tVALUES (NEW.rowid, NEW.id, NEW.locale, ${newValueList});\n\t\t\tEND\n\t\t`)\n\t\t\t.execute(this.db);\n\n\t\t// Update trigger - drop the old index row, re-insert when the row is\n\t\t// still visible. Trash (deleted_at set) ends at DELETE only; restore\n\t\t// ends at DELETE (no-op) + re-insert.\n\t\t//\n\t\t// The WHEN guard compares raw column values (null-safe IS NOT) so the\n\t\t// trigger fires only when an indexed value, the row's locale, or its\n\t\t// trash state actually changed. Without it every UPDATE re-tokenizes\n\t\t// the whole document — metadata-only saves (status flips, scheduling,\n\t\t// version bumps) and the publish path's rewrite-identical-values\n\t\t// UPDATEs dominate save CPU and WAL volume. deleted_at must stay in\n\t\t// the guard or trash/restore stop syncing the index.\n\t\tconst changedCondition = [\"deleted_at\", \"locale\", ...searchableFields]\n\t\t\t.map((f) => `OLD.${f} IS NOT NEW.${f}`)\n\t\t\t.join(\" OR \");\n\t\tawait sql\n\t\t\t.raw(`\n\t\t\tCREATE TRIGGER IF NOT EXISTS \"${ftsTable}_update\"\n\t\t\tAFTER UPDATE ON \"${contentTable}\"\n\t\t\tWHEN ${changedCondition}\n\t\t\tBEGIN\n\t\t\t\tDELETE FROM \"${ftsTable}\" WHERE rowid = OLD.rowid;\n\t\t\t\tINSERT INTO \"${ftsTable}\"(rowid, id, locale, ${fieldList})\n\t\t\t\tSELECT NEW.rowid, NEW.id, NEW.locale, ${newValueList}\n\t\t\t\tWHERE NEW.deleted_at IS NULL;\n\t\t\tEND\n\t\t`)\n\t\t\t.execute(this.db);\n\n\t\t// Delete trigger\n\t\tawait sql\n\t\t\t.raw(`\n\t\t\tCREATE TRIGGER IF NOT EXISTS \"${ftsTable}_delete\"\n\t\t\tAFTER DELETE ON \"${contentTable}\"\n\t\t\tBEGIN\n\t\t\t\tDELETE FROM \"${ftsTable}\" WHERE rowid = OLD.rowid;\n\t\t\tEND\n\t\t`)\n\t\t\t.execute(this.db);\n\t}\n\n\t/**\n\t * Drop triggers for a collection\n\t */\n\tprivate async dropTriggers(collectionSlug: string): Promise<void> {\n\t\tthis.validateInputs(collectionSlug);\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\n\t\tawait sql.raw(`DROP TRIGGER IF EXISTS \"${ftsTable}_insert\"`).execute(this.db);\n\t\tawait sql.raw(`DROP TRIGGER IF EXISTS \"${ftsTable}_update\"`).execute(this.db);\n\t\tawait sql.raw(`DROP TRIGGER IF EXISTS \"${ftsTable}_delete\"`).execute(this.db);\n\t}\n\n\t/**\n\t * Drop the FTS table and triggers for a collection\n\t */\n\tasync dropFtsTable(collectionSlug: string): Promise<void> {\n\t\tif (!isSqlite(this.db)) return;\n\t\tthis.validateInputs(collectionSlug);\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\n\t\t// Drop triggers first\n\t\tawait this.dropTriggers(collectionSlug);\n\n\t\t// Drop the FTS table\n\t\tawait sql.raw(`DROP TABLE IF EXISTS \"${ftsTable}\"`).execute(this.db);\n\t}\n\n\t/**\n\t * Rebuild the FTS index for a collection\n\t *\n\t * This is useful after bulk imports or if the index gets out of sync.\n\t */\n\tasync rebuildIndex(\n\t\tcollectionSlug: string,\n\t\tsearchableFields: string[],\n\t\tweights?: Record<string, number>,\n\t\ttokenize?: SearchTokenizer,\n\t): Promise<void> {\n\t\tresolveSearchTokenizer(tokenize);\n\t\tif (!isSqlite(this.db)) return;\n\t\t// Drop existing table and triggers\n\t\tawait this.dropFtsTable(collectionSlug);\n\n\t\t// Recreate table and triggers\n\t\tawait this.createFtsTable(collectionSlug, searchableFields, weights, tokenize);\n\n\t\t// Populate from existing content\n\t\tawait this.populateFromContent(collectionSlug, searchableFields);\n\t}\n\n\t/**\n\t * Populate the FTS table from existing content.\n\t *\n\t * `INSERT OR REPLACE` so a concurrent double-populate (search repair runs\n\t * per isolate) converges instead of failing on the rowid constraint.\n\t */\n\tasync populateFromContent(collectionSlug: string, searchableFields: string[]): Promise<void> {\n\t\tif (!isSqlite(this.db)) return;\n\t\tthis.validateInputs(collectionSlug, searchableFields);\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\t\tconst contentTable = this.getContentTableName(collectionSlug);\n\t\tconst fieldTypes = await this.getFieldTypes(collectionSlug);\n\t\tconst fieldList = searchableFields.join(\", \");\n\t\t// Table-qualified references: json_tree exposes columns named\n\t\t// key/value/type/path/..., and inside the extraction subquery a bare\n\t\t// column reference binds to those instead of the ec_* column.\n\t\tconst valueList = searchableFields\n\t\t\t.map((f) => this.searchValueExpr(`\"${contentTable}\".\"${f}\"`, fieldTypes.get(f)))\n\t\t\t.join(\", \");\n\n\t\t// Insert all existing content into FTS table\n\t\tawait sql\n\t\t\t.raw(`\n\t\t\tINSERT OR REPLACE INTO \"${ftsTable}\"(rowid, id, locale, ${fieldList})\n\t\t\tSELECT rowid, id, locale, ${valueList} FROM \"${contentTable}\"\n\t\t\tWHERE deleted_at IS NULL\n\t\t`)\n\t\t\t.execute(this.db);\n\t}\n\n\t/**\n\t * Index up to `limit` content rows with `rowid > afterRowid`, in rowid\n\t * order, so a large collection can be populated across several requests.\n\t * Returns the last rowid covered, or null when no rows remain. Returns\n\t * null on dialects without FTS5.\n\t */\n\tasync populateRange(\n\t\tcollectionSlug: string,\n\t\tsearchableFields: string[],\n\t\tafterRowid: number,\n\t\tlimit: number,\n\t): Promise<number | null> {\n\t\tif (!isSqlite(this.db)) return null;\n\t\tthis.validateInputs(collectionSlug, searchableFields);\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\t\tconst contentTable = this.getContentTableName(collectionSlug);\n\t\tconst range = await sql<{ last: number | null }>`\n\t\t\tSELECT MAX(rowid) AS last FROM (\n\t\t\t\tSELECT rowid FROM ${sql.ref(contentTable)}\n\t\t\t\tWHERE rowid > ${afterRowid}\n\t\t\t\tORDER BY rowid\n\t\t\t\tLIMIT ${limit}\n\t\t\t)\n\t\t`.execute(this.db);\n\t\tconst last = range.rows[0]?.last ?? null;\n\t\tif (last === null) return null;\n\n\t\tconst fieldTypes = await this.getFieldTypes(collectionSlug);\n\t\tconst fieldList = searchableFields.join(\", \");\n\t\tconst valueList = searchableFields\n\t\t\t.map((f) => this.searchValueExpr(`\"${contentTable}\".\"${f}\"`, fieldTypes.get(f)))\n\t\t\t.join(\", \");\n\t\tawait sql`\n\t\t\tINSERT OR REPLACE INTO ${sql.ref(ftsTable)}(rowid, id, locale, ${sql.raw(fieldList)})\n\t\t\tSELECT rowid, id, locale, ${sql.raw(valueList)} FROM ${sql.ref(contentTable)}\n\t\t\tWHERE deleted_at IS NULL AND rowid > ${afterRowid} AND rowid <= ${last}\n\t\t`.execute(this.db);\n\t\treturn Number(last);\n\t}\n\n\t/**\n\t * Get the search configuration for a collection\n\t */\n\tasync getSearchConfig(collectionSlug: string): Promise<SearchConfig | null> {\n\t\tconst result = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select([\"search_config\", \"title_field\"])\n\t\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!result?.search_config) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn parseSearchConfig(result.search_config, result.title_field);\n\t}\n\n\t/**\n\t * Load all metadata needed to search the requested collections in one round trip.\n\t * Omitted or empty slugs select all search-enabled collections.\n\t */\n\tasync getSearchMetadata(\n\t\tcollectionSlugs?: string[],\n\t): Promise<Map<string, CollectionSearchMetadata>> {\n\t\tif (!isSqlite(this.db)) return new Map();\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_collections as c\")\n\t\t\t.select([\n\t\t\t\t\"c.slug\",\n\t\t\t\t\"c.search_config\",\n\t\t\t\t\"c.title_field\",\n\t\t\t\t// bm25 weights are positional, so use the index's physical column order.\n\t\t\t\tsql<string>`(\n\t\t\t\t\tSELECT json_group_array(name ORDER BY cid)\n\t\t\t\t\tFROM pragma_table_info(${\"_emdash_fts_\"} || c.slug)\n\t\t\t\t\tWHERE cid >= 2\n\t\t\t\t)`.as(\"searchable_fields\"),\n\t\t\t\tsql<number>`EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_fields WHERE collection_id = c.id AND slug = 'title'\n\t\t\t\t)`.as(\"has_title\"),\n\t\t\t])\n\t\t\t.where(\"c.search_config\", \"is not\", null).where(sql<boolean>`EXISTS (\n\t\t\t\tSELECT 1 FROM sqlite_master\n\t\t\t\tWHERE type = 'table' AND name = ${\"_emdash_fts_\"} || c.slug\n\t\t\t)`);\n\n\t\tif (collectionSlugs?.length) {\n\t\t\tquery = query.where(\n\t\t\t\t\"c.slug\",\n\t\t\t\t\"in\",\n\t\t\t\tsql<string>`(SELECT value FROM json_each(${JSON.stringify(collectionSlugs)}))`,\n\t\t\t);\n\t\t}\n\n\t\tconst metadata = new Map<string, CollectionSearchMetadata>();\n\t\tfor (const row of await query.execute()) {\n\t\t\tconst config = row.search_config\n\t\t\t\t? parseSearchConfig(row.search_config, row.title_field)\n\t\t\t\t: null;\n\t\t\tif (!config?.enabled) continue;\n\t\t\tconst searchableFields: unknown = JSON.parse(row.searchable_fields);\n\t\t\tif (\n\t\t\t\t!Array.isArray(searchableFields) ||\n\t\t\t\t!searchableFields.every((field: unknown) => typeof field === \"string\")\n\t\t\t) {\n\t\t\t\tthrow new Error(\"Invalid FTS field metadata\");\n\t\t\t}\n\t\t\tmetadata.set(row.slug, {\n\t\t\t\tconfig,\n\t\t\t\tsearchableFields,\n\t\t\t\thasTitle: Boolean(row.has_title),\n\t\t\t});\n\t\t}\n\t\treturn metadata;\n\t}\n\n\t/**\n\t * Update the search configuration for a collection\n\t */\n\tasync setSearchConfig(collectionSlug: string, config: SearchConfig): Promise<void> {\n\t\tif (config.tokenize !== undefined) {\n\t\t\tresolveSearchTokenizer(config.tokenize);\n\t\t}\n\t\tawait this.db\n\t\t\t.updateTable(\"_emdash_collections\")\n\t\t\t.set({ search_config: JSON.stringify(config) })\n\t\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t\t.execute();\n\t}\n\n\t/**\n\t * Get searchable fields for a collection. Fields that store no column (bound\n\t * reference fields) are left out: the index triggers read each field's column.\n\t */\n\tasync getSearchableFields(collectionSlug: string): Promise<string[]> {\n\t\tconst collection = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"slug\", \"=\", collectionSlug)\n\t\t\t.executeTakeFirst();\n\n\t\tif (!collection) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst fields = await this.db\n\t\t\t.selectFrom(\"_emdash_fields\")\n\t\t\t.select([\"slug\", \"type\", \"validation\"])\n\t\t\t.where(\"collection_id\", \"=\", collection.id)\n\t\t\t.where(\"searchable\", \"=\", 1)\n\t\t\t.execute();\n\n\t\treturn fields.filter((f) => !isStoragelessFieldRow(f)).map((f) => f.slug);\n\t}\n\n\t/**\n\t * Whether a collection has a user-defined `title` field.\n\t *\n\t * `title` is not a system column on `ec_*` tables -- it exists only when a\n\t * collection defines a field with slug `title`. Search and suggestion SQL\n\t * that selects `c.title` must check this first; otherwise collections\n\t * without a title field raise \"no such column: c.title\".\n\t */\n\tasync hasTitleColumn(collectionSlug: string): Promise<boolean> {\n\t\tconst withTitle = await this.getCollectionsWithTitleColumn([collectionSlug]);\n\t\treturn withTitle.has(collectionSlug);\n\t}\n\n\t/**\n\t * Bulk variant of `hasTitleColumn()`: which of the given collections have\n\t * a user-defined `title` field. One query instead of one `hasTitleColumn`\n\t * round-trip pair per collection -- callers that check this once per\n\t * collection in a loop (multi-collection search, suggestions) should use\n\t * this instead (AGENTS.md: \"one query beats two\").\n\t */\n\tasync getCollectionsWithTitleColumn(collectionSlugs: string[]): Promise<Set<string>> {\n\t\tif (collectionSlugs.length === 0) return new Set();\n\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_fields as f\")\n\t\t\t.innerJoin(\"_emdash_collections as c\", \"c.id\", \"f.collection_id\")\n\t\t\t.select([\"c.slug as collection_slug\"])\n\t\t\t.where(\"f.slug\", \"=\", \"title\")\n\t\t\t.execute();\n\n\t\tconst withTitle = new Set(rows.map((r) => r.collection_slug));\n\t\treturn new Set(collectionSlugs.filter((slug) => withTitle.has(slug)));\n\t}\n\n\t/**\n\t * Enable search for a collection.\n\t *\n\t * Uses rebuildIndex to ensure a clean state -- drop any existing FTS\n\t * table/triggers, recreate them, and populate from content. This avoids\n\t * duplicate rows when triggers have already populated the index (e.g.\n\t * during seeding where content is inserted before search is enabled).\n\t */\n\tasync enableSearch(\n\t\tcollectionSlug: string,\n\t\toptions?: { weights?: Record<string, number>; tokenize?: SearchTokenizer },\n\t): Promise<void> {\n\t\tif (options?.tokenize !== undefined) {\n\t\t\tresolveSearchTokenizer(options.tokenize);\n\t\t}\n\t\tif (!isSqlite(this.db)) {\n\t\t\tthrow new Error(\"Full-text search is only available with SQLite databases\");\n\t\t}\n\t\t// Get searchable fields\n\t\tconst searchableFields = await this.getSearchableFields(collectionSlug);\n\n\t\tif (searchableFields.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No searchable fields defined for collection \"${collectionSlug}\". ` +\n\t\t\t\t\t`Mark at least one field as searchable before enabling search.`,\n\t\t\t);\n\t\t}\n\n\t\tconst existing = await this.getSearchConfig(collectionSlug);\n\t\tconst weights = options?.weights ?? existing?.weights;\n\t\tconst tokenize = options?.tokenize ?? existing?.tokenize;\n\n\t\t// Rebuild from scratch to ensure clean state (no duplicate rows)\n\t\tawait this.rebuildIndex(collectionSlug, searchableFields, weights, tokenize);\n\n\t\t// Update search config\n\t\tawait this.setSearchConfig(collectionSlug, {\n\t\t\tenabled: true,\n\t\t\tweights,\n\t\t\ttokenize,\n\t\t});\n\t}\n\n\t/**\n\t * Disable search for a collection\n\t *\n\t * Drops the FTS table and triggers.\n\t */\n\tasync disableSearch(collectionSlug: string): Promise<void> {\n\t\tif (!isSqlite(this.db)) return;\n\t\tawait this.dropFtsTable(collectionSlug);\n\t\tconst existing = await this.getSearchConfig(collectionSlug);\n\t\tawait this.setSearchConfig(collectionSlug, {\n\t\t\tenabled: false,\n\t\t\tweights: existing?.weights,\n\t\t\ttokenize: existing?.tokenize,\n\t\t});\n\t}\n\n\t/**\n\t * Get index statistics for a collection\n\t */\n\tasync getIndexStats(\n\t\tcollectionSlug: string,\n\t): Promise<{ indexed: number; lastRebuilt?: string } | null> {\n\t\tif (!isSqlite(this.db)) return null;\n\t\tthis.validateInputs(collectionSlug);\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\t\tconst ftsDocsizeTable = `${ftsTable}_docsize`;\n\n\t\t// Check if table exists\n\t\tif (!(await this.ftsTableExists(collectionSlug))) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Count indexed rows\n\t\tconst result = await sql<{ count: number }>`\n\t\t\tSELECT COUNT(*) as count FROM \"${sql.raw(ftsDocsizeTable)}\"\n\t\t`.execute(this.db);\n\n\t\treturn {\n\t\t\tindexed: result.rows[0]?.count ?? 0,\n\t\t};\n\t}\n\n\t/**\n\t * Verify FTS index integrity and rebuild if drift is detected.\n\t *\n\t * Cheap belt-and-braces check, run lazily on the first search request\n\t * per isolate. The expensive cases (corrupted indexes from pre-fix\n\t * EmDash versions, broken legacy triggers) are handled at boot time by\n\t * migration `039_fix_fts5_triggers`, not here. This routine sticks to:\n\t *\n\t * 1. FTS table missing while config says search is enabled -> rebuild.\n\t * 2. Row count mismatch between content table and FTS docsize -> rebuild.\n\t *\n\t * Returns true if the index was rebuilt, false if it was healthy.\n\t */\n\tasync verifyAndRepairIndex(collectionSlug: string): Promise<boolean> {\n\t\tif (!isSqlite(this.db)) return false;\n\t\tthis.validateInputs(collectionSlug);\n\t\tconst ftsTable = this.getFtsTableName(collectionSlug);\n\t\tconst ftsDocsizeTable = `${ftsTable}_docsize`;\n\t\tconst contentTable = this.getContentTableName(collectionSlug);\n\t\tconst fields = await this.getSearchableFields(collectionSlug);\n\t\tconst config = await this.getSearchConfig(collectionSlug);\n\n\t\tif (!(await this.ftsTableExists(collectionSlug))) {\n\t\t\tif (!config?.enabled || fields.length === 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconsole.warn(`FTS index for \"${collectionSlug}\" is missing. Rebuilding.`);\n\t\t\tawait this.rebuildIndex(collectionSlug, fields, config.weights, config.tokenize);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Row count parity check against the docsize shadow table, which\n\t\t// tracks rows actually present in the full-text index.\n\t\tconst contentCount = await sql<{ count: number }>`\n\t\t\tSELECT COUNT(*) as count FROM ${sql.ref(contentTable)}\n\t\t\tWHERE deleted_at IS NULL\n\t\t`.execute(this.db);\n\n\t\tconst ftsCount = await sql<{ count: number }>`\n\t\t\tSELECT COUNT(*) as count FROM \"${sql.raw(ftsDocsizeTable)}\"\n\t\t`.execute(this.db);\n\n\t\tconst contentRows = contentCount.rows[0]?.count ?? 0;\n\t\tconst ftsRows = ftsCount.rows[0]?.count ?? 0;\n\n\t\tif (contentRows !== ftsRows) {\n\t\t\tconsole.warn(\n\t\t\t\t`FTS index for \"${collectionSlug}\" has ${ftsRows} rows but content table has ${contentRows}. Rebuilding.`,\n\t\t\t);\n\t\t\tif (fields.length > 0) {\n\t\t\t\tawait this.rebuildIndex(collectionSlug, fields, config?.weights, config?.tokenize);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Verify and repair FTS indexes for all search-enabled collections.\n\t *\n\t * Intended to run at startup to auto-heal any corruption from\n\t * previous process crashes.\n\t */\n\tasync verifyAndRepairAll(): Promise<number> {\n\t\tif (!isSqlite(this.db)) return 0;\n\n\t\tconst collections = await this.db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select(\"slug\")\n\t\t\t.where(\"search_config\", \"is not\", null)\n\t\t\t.execute();\n\n\t\tlet repaired = 0;\n\t\tfor (const { slug } of collections) {\n\t\t\tconst config = await this.getSearchConfig(slug);\n\t\t\tif (!config?.enabled) continue;\n\n\t\t\ttry {\n\t\t\t\tconst wasRepaired = await this.verifyAndRepairIndex(slug);\n\t\t\t\tif (wasRepaired) repaired++;\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`Failed to verify/repair FTS index for \"${slug}\":`, error);\n\t\t\t}\n\t\t}\n\n\t\treturn repaired;\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import "./dialect-helpers-
|
|
1
|
+
import "./dialect-helpers-B1XN2HGB.mjs";
|
|
2
2
|
import "./base64-BQBZwXCx.mjs";
|
|
3
|
-
import "./types-
|
|
3
|
+
import "./types-DwhEvIVb.mjs";
|
|
4
4
|
import "./errors-B4f4It-2.mjs";
|
|
5
5
|
import "./canonical-BudtH-Fx.mjs";
|
|
6
6
|
import "./digest-DJ1tHCgy.mjs";
|
|
7
|
-
import "./errors-
|
|
7
|
+
import "./errors-8gJqv-XV.mjs";
|
|
8
8
|
import "./settings-Dd1uivmQ.mjs";
|
|
9
|
-
import "./error-
|
|
10
|
-
import "./fence-
|
|
9
|
+
import "./error-BCMgPxdn.mjs";
|
|
10
|
+
import "./fence-Dagicj14.mjs";
|
|
11
11
|
import "./kinds-B_Qcl5pz.mjs";
|
|
12
12
|
import "./paths-biDzFTY2.mjs";
|
|
13
13
|
import "./version-BZj18Q7G.mjs";
|
|
14
14
|
import "./receipt-BUsQCOeM.mjs";
|
|
15
|
-
import { n as TransferApprovalRepository } from "./approvals-
|
|
16
|
-
import { i as TransferOperationRepository, t as TransferStage } from "./stage-
|
|
15
|
+
import { n as TransferApprovalRepository } from "./approvals-DTtYSB27.mjs";
|
|
16
|
+
import { i as TransferOperationRepository, t as TransferStage } from "./stage-CZQnXM_G.mjs";
|
|
17
17
|
import { i as stagingPrefix } from "./keys-CifIkT0N.mjs";
|
|
18
18
|
|
|
19
19
|
//#region src/transfer/gc.ts
|
|
@@ -72,4 +72,4 @@ async function collectTransferStaging(db, storage, options = {}) {
|
|
|
72
72
|
|
|
73
73
|
//#endregion
|
|
74
74
|
export { collectTransferStaging };
|
|
75
|
-
//# sourceMappingURL=gc-
|
|
75
|
+
//# sourceMappingURL=gc-CNkXB3mE.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gc-
|
|
1
|
+
{"version":3,"file":"gc-CNkXB3mE.mjs","names":[],"sources":["../src/transfer/gc.ts"],"sourcesContent":["/**\n * Bounded collection of transfer staging areas, run from system cleanup.\n *\n * Each tick expires overdue operations and approval grants, then collects\n * the staging area of a few finished operations: staged objects (package\n * files, the plan, and analysis state) first, then child rows, then the\n * operation is marked collected. Work stops when the tick's budgets run out\n * and resumes on the next tick. Operation rows, and the receipts they carry,\n * are kept.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../database/types.js\";\nimport type { Storage } from \"../storage/types.js\";\nimport { TransferApprovalRepository } from \"./ops/approvals.js\";\nimport { TransferOperationRepository } from \"./ops/operations.js\";\nimport { stagingPrefix } from \"./staging/keys.js\";\nimport { TransferStage } from \"./staging/stage.js\";\n\n/** How long a finished import's staging is kept after its last state change. */\nexport const IMPORT_STAGING_RETENTION_SECONDS = 24 * 60 * 60;\n\nexport interface TransferStagingCollectionOptions {\n\t/** Operations to expire, and to collect, per tick. */\n\toperations?: number;\n\t/** Staged objects deleted per tick, across all operations. */\n\tobjects?: number;\n\t/** `deleteChildRows` calls per tick, across all operations. */\n\trowBatches?: number;\n}\n\nexport interface TransferStagingCollectionResult {\n\texpired: number;\n\tcollected: number;\n\tobjectsDeleted: number;\n\trowsDeleted: number;\n}\n\nconst OBJECT_BATCH = 100;\nconst ROW_BATCH = 500;\n\nexport async function collectTransferStaging(\n\tdb: Kysely<Database>,\n\tstorage: Storage,\n\toptions: TransferStagingCollectionOptions = {},\n): Promise<TransferStagingCollectionResult> {\n\tconst operationLimit = options.operations ?? 5;\n\tlet objectBudget = options.objects ?? 1000;\n\tlet rowBatchBudget = options.rowBatches ?? 20;\n\tconst result: TransferStagingCollectionResult = {\n\t\texpired: 0,\n\t\tcollected: 0,\n\t\tobjectsDeleted: 0,\n\t\trowsDeleted: 0,\n\t};\n\n\tconst operations = new TransferOperationRepository(db);\n\tresult.expired = (await operations.expireDue(operationLimit)).length;\n\tawait new TransferApprovalRepository(db).expireDue();\n\n\tconst pending = await operations.listUncollected(operationLimit, {\n\t\timportRetentionSeconds: IMPORT_STAGING_RETENTION_SECONDS,\n\t});\n\tfor (const operation of pending) {\n\t\tif (objectBudget <= 0 || rowBatchBudget <= 0) break;\n\t\ttry {\n\t\t\tconst stage = new TransferStage(\n\t\t\t\tstorage,\n\t\t\t\tstagingPrefix(operation.kind, operation.id, operation.stagingSecret),\n\t\t\t);\n\t\t\tlet objectsDone = false;\n\t\t\twhile (objectBudget > 0) {\n\t\t\t\tconst deleted = await stage.deleteSome(Math.min(OBJECT_BATCH, objectBudget));\n\t\t\t\tobjectBudget -= deleted;\n\t\t\t\tresult.objectsDeleted += deleted;\n\t\t\t\tif (deleted === 0) {\n\t\t\t\t\tobjectsDone = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!objectsDone) break;\n\n\t\t\tlet rowsDone = false;\n\t\t\twhile (rowBatchBudget > 0) {\n\t\t\t\trowBatchBudget--;\n\t\t\t\tconst deleted = await operations.deleteChildRows(operation.id, ROW_BATCH);\n\t\t\t\tresult.rowsDeleted += deleted;\n\t\t\t\tif (deleted === 0) {\n\t\t\t\t\trowsDone = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!rowsDone) break;\n\n\t\t\tawait operations.markCollected(operation.id);\n\t\t\tresult.collected++;\n\t\t} catch (error) {\n\t\t\tconsole.error(`[transfer] Failed to collect staging for operation ${operation.id}:`, error);\n\t\t}\n\t}\n\treturn result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,mCAAmC,OAAU;AAkB1D,MAAM,eAAe;AACrB,MAAM,YAAY;AAElB,eAAsB,uBACrB,IACA,SACA,UAA4C,EAAE,EACH;CAC3C,MAAM,iBAAiB,QAAQ,cAAc;CAC7C,IAAI,eAAe,QAAQ,WAAW;CACtC,IAAI,iBAAiB,QAAQ,cAAc;CAC3C,MAAM,SAA0C;EAC/C,SAAS;EACT,WAAW;EACX,gBAAgB;EAChB,aAAa;EACb;CAED,MAAM,aAAa,IAAI,4BAA4B,GAAG;AACtD,QAAO,WAAW,MAAM,WAAW,UAAU,eAAe,EAAE;AAC9D,OAAM,IAAI,2BAA2B,GAAG,CAAC,WAAW;CAEpD,MAAM,UAAU,MAAM,WAAW,gBAAgB,gBAAgB,EAChE,wBAAwB,kCACxB,CAAC;AACF,MAAK,MAAM,aAAa,SAAS;AAChC,MAAI,gBAAgB,KAAK,kBAAkB,EAAG;AAC9C,MAAI;GACH,MAAM,QAAQ,IAAI,cACjB,SACA,cAAc,UAAU,MAAM,UAAU,IAAI,UAAU,cAAc,CACpE;GACD,IAAI,cAAc;AAClB,UAAO,eAAe,GAAG;IACxB,MAAM,UAAU,MAAM,MAAM,WAAW,KAAK,IAAI,cAAc,aAAa,CAAC;AAC5E,oBAAgB;AAChB,WAAO,kBAAkB;AACzB,QAAI,YAAY,GAAG;AAClB,mBAAc;AACd;;;AAGF,OAAI,CAAC,YAAa;GAElB,IAAI,WAAW;AACf,UAAO,iBAAiB,GAAG;AAC1B;IACA,MAAM,UAAU,MAAM,WAAW,gBAAgB,UAAU,IAAI,UAAU;AACzE,WAAO,eAAe;AACtB,QAAI,YAAY,GAAG;AAClB,gBAAW;AACX;;;AAGF,OAAI,CAAC,SAAU;AAEf,SAAM,WAAW,cAAc,UAAU,GAAG;AAC5C,UAAO;WACC,OAAO;AACf,WAAQ,MAAM,sDAAsD,UAAU,GAAG,IAAI,MAAM;;;AAG7F,QAAO"}
|
|
@@ -28,4 +28,4 @@ type SandboxHookResultInspection = {
|
|
|
28
28
|
declare function inspectSandboxHookResult(value: unknown): SandboxHookResultInspection;
|
|
29
29
|
//#endregion
|
|
30
30
|
export { SandboxSaveRejectedError as a, SandboxHookResultInspection as i, SANDBOX_HOOK_RESULT_VERSION as n, inspectSandboxHookResult as o, SandboxHookErrorEnvelope as r, MAX_SANDBOX_SAVE_REJECTION_REASON_LENGTH as t };
|
|
31
|
-
//# sourceMappingURL=hook-result-
|
|
31
|
+
//# sourceMappingURL=hook-result-f8t7hIuu.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-result-
|
|
1
|
+
{"version":3,"file":"hook-result-f8t7hIuu.d.mts","names":[],"sources":["../src/plugins/sandbox/hook-result.ts"],"mappings":";;cACa,2BAAA;;cAGA,wCAAA;AAAA,UAEI,wBAAA;EAChB,IAAA;EACA,MAAA;AAAA;;;;AAFD;UASiB,wBAAA;EAChB,yBAAA;EACA,OAAA,SAAgB,2BAAA;EAChB,KAAA,EAAO,wBAAA;AAAA;AAAA,KAGI,2BAAA;EACP,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAAe,KAAA,EAAO,wBAAA;AAAA;;iBAOX,wBAAA,CAAyB,KAAA,YAAiB,2BAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Database } from "./types-
|
|
1
|
+
import { t as Database } from "./types-DKwRUA-x.mjs";
|
|
2
2
|
import { Kysely } from "kysely";
|
|
3
3
|
|
|
4
4
|
//#region src/seo/hreflang.d.ts
|
|
@@ -47,4 +47,4 @@ declare function getHreflangAlternates(collection: string, entryId: string, opti
|
|
|
47
47
|
declare function getHreflangAlternatesWithDb(db: Kysely<Database>, collection: string, entryId: string, options?: HreflangOptions): Promise<HreflangAlternate[]>;
|
|
48
48
|
//#endregion
|
|
49
49
|
export { getHreflangAlternatesWithDb as i, HreflangOptions as n, getHreflangAlternates as r, HreflangAlternate as t };
|
|
50
|
-
//# sourceMappingURL=hreflang-
|
|
50
|
+
//# sourceMappingURL=hreflang-8dUOJAPJ.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hreflang-
|
|
1
|
+
{"version":3,"file":"hreflang-8dUOJAPJ.d.mts","names":[],"sources":["../src/seo/hreflang.ts"],"mappings":";;;;;UA4DiB,iBAAA;EAwCN;EAtCV,QAAA;EAsC2B;EApC3B,IAAA;AAAA;AAAA,UAGgB,eAAA;EAkDL;;;;;;EA3CX,OAAA;EA2CI;EAzCJ,aAAA;AAAA;;;;;;;;;;;;;;;;;;iBAoBqB,qBAAA,CACrB,UAAA,UACA,OAAA,UACA,OAAA,GAAS,eAAA,GACP,OAAA,CAAQ,iBAAA;;;;;;;iBAgBW,2BAAA,CACrB,EAAA,EAAI,MAAA,CAAO,QAAA,GACX,UAAA,UACA,OAAA,UACA,OAAA,GAAS,eAAA,GACP,OAAA,CAAQ,iBAAA"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as ContentRepository } from "./content-
|
|
3
|
-
import { r as requestCached } from "./request-cache-
|
|
4
|
-
import { a as resolveLocalizedContentRoutePath } from "./resolve-
|
|
5
|
-
import { n as getCollectionInfoWithDb } from "./query-
|
|
6
|
-
import { s as getSiteSettingsWithDb } from "./settings-
|
|
1
|
+
import { r as getI18nConfig, s as isI18nEnabled } from "./config-Cs_AwWXI.mjs";
|
|
2
|
+
import { t as ContentRepository } from "./content-BKHUVsE5.mjs";
|
|
3
|
+
import { r as requestCached } from "./request-cache-5z2WzWmh.mjs";
|
|
4
|
+
import { a as resolveLocalizedContentRoutePath } from "./resolve-DdNXBJSr.mjs";
|
|
5
|
+
import { n as getCollectionInfoWithDb } from "./query-LmPY2y0C.mjs";
|
|
6
|
+
import { s as getSiteSettingsWithDb } from "./settings-D932YP2-.mjs";
|
|
7
7
|
|
|
8
8
|
//#region src/seo/hreflang.ts
|
|
9
9
|
const TRAILING_SLASH_RE = /\/$/;
|
|
@@ -39,7 +39,7 @@ async function findNoindexIds(db, collection, ids) {
|
|
|
39
39
|
async function getHreflangAlternates(collection, entryId, options = {}) {
|
|
40
40
|
if (!isI18nEnabled()) return [];
|
|
41
41
|
return requestCached(`hreflang:${collection}:${entryId}:${options.siteUrl ?? ""}:${options.trailingSlash ?? "ignore"}`, async () => {
|
|
42
|
-
const { getDb } = await import("./loader-
|
|
42
|
+
const { getDb } = await import("./loader-DhnedqY4.mjs").then((n) => n.f);
|
|
43
43
|
return getHreflangAlternatesWithDb(await getDb(), collection, entryId, options);
|
|
44
44
|
});
|
|
45
45
|
}
|
|
@@ -102,4 +102,4 @@ async function getHreflangAlternatesWithDb(db, collection, entryId, options = {}
|
|
|
102
102
|
|
|
103
103
|
//#endregion
|
|
104
104
|
export { getHreflangAlternatesWithDb as n, getHreflangAlternates as t };
|
|
105
|
-
//# sourceMappingURL=hreflang-
|
|
105
|
+
//# sourceMappingURL=hreflang-BW5A4FLK.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hreflang-
|
|
1
|
+
{"version":3,"file":"hreflang-BW5A4FLK.mjs","names":[],"sources":["../src/seo/hreflang.ts"],"sourcesContent":["/**\n * hreflang alternate resolution for translated content (#1690).\n *\n * Mirrors the sitemap route's semantics so the render path and the\n * sitemap always agree:\n *\n * - Alternates are emitted per published locale variant of a\n * translation group, including a self-referencing entry (Google\n * recommends the page annotate itself).\n * - `x-default` points at the default-locale variant, falling back to\n * the first routable variant when the default locale has no\n * translation.\n * - Variants whose locale isn't in the configured `i18n.locales` list\n * are dropped: linking to a route the site can't serve is worse than\n * no link at all.\n * - Variants flagged `noindex` in the SEO panel are excluded — the\n * sitemap doesn't list them, and pointing search engines at a page\n * that asks not to be indexed is a contradictory signal. When the\n * entry itself is noindex the result is empty: a page opting out of\n * indexing shouldn't announce an hreflang set at all.\n * - When i18n is disabled (or no absolute site URL can be resolved,\n * which hreflang requires) the result is empty and no queries run.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { ContentRepository } from \"../database/repositories/content.js\";\nimport type { Database } from \"../database/types.js\";\nimport { getI18nConfig, isI18nEnabled } from \"../i18n/config.js\";\nimport { resolveLocalizedContentRoutePath } from \"../i18n/resolve.js\";\nimport { requestCached } from \"../request-cache.js\";\nimport { getCollectionInfoWithDb } from \"../schema/query.js\";\nimport { getSiteSettingsWithDb } from \"../settings/index.js\";\n\nconst TRAILING_SLASH_RE = /\\/$/;\nconst ABSOLUTE_URL_RE = /^https?:\\/\\//i;\n\n/**\n * IDs of variants flagged `noindex` in the SEO panel. Entries without\n * an `_emdash_seo` row are indexable by default (same as the sitemap).\n * The id list is bounded by the number of configured locales, so no\n * chunking is needed.\n */\nasync function findNoindexIds(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tids: string[],\n): Promise<Set<string>> {\n\tif (ids.length === 0) return new Set();\n\tconst rows = await db\n\t\t.selectFrom(\"_emdash_seo\")\n\t\t.select(\"content_id\")\n\t\t.where(\"collection\", \"=\", collection)\n\t\t.where(\"content_id\", \"in\", ids)\n\t\t.where(\"seo_no_index\", \"=\", 1)\n\t\t.execute();\n\treturn new Set(rows.map((r) => r.content_id));\n}\n\n/** A single alternate link, ready to render as `<link rel=\"alternate\">`. */\nexport interface HreflangAlternate {\n\t/** Locale code, or `\"x-default\"` for the default variant */\n\threflang: string;\n\t/** Absolute URL of the variant */\n\thref: string;\n}\n\nexport interface HreflangOptions {\n\t/**\n\t * Absolute site origin (e.g. `https://example.com`) used to build\n\t * the alternate URLs. Falls back to the site settings URL; when\n\t * neither is available the result is empty, since hreflang\n\t * requires fully-qualified URLs.\n\t */\n\tsiteUrl?: string;\n\t/** Astro's route trailing-slash policy. */\n\ttrailingSlash?: \"always\" | \"never\" | \"ignore\";\n}\n\n/**\n * Resolve hreflang alternates for a content entry.\n *\n * @example\n * ```astro\n * ---\n * import { getHreflangAlternates } from \"emdash\";\n *\n * const alternates = await getHreflangAlternates(\"posts\", entry.data.id, {\n * siteUrl: Astro.url.origin,\n * });\n * ---\n * <head>\n * {alternates.map((a) => <link rel=\"alternate\" hreflang={a.hreflang} href={a.href} />)}\n * </head>\n * ```\n */\nexport async function getHreflangAlternates(\n\tcollection: string,\n\tentryId: string,\n\toptions: HreflangOptions = {},\n): Promise<HreflangAlternate[]> {\n\tif (!isI18nEnabled()) return [];\n\tconst key = `hreflang:${collection}:${entryId}:${options.siteUrl ?? \"\"}:${options.trailingSlash ?? \"ignore\"}`;\n\treturn requestCached(key, async () => {\n\t\tconst { getDb } = await import(\"../loader.js\");\n\t\tconst db = await getDb();\n\t\treturn getHreflangAlternatesWithDb(db, collection, entryId, options);\n\t});\n}\n\n/**\n * Resolve hreflang alternates with an explicit db handle.\n *\n * @internal Use `getHreflangAlternates()` in templates. This variant is\n * for routes/components that already have a database handle.\n */\nexport async function getHreflangAlternatesWithDb(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tentryId: string,\n\toptions: HreflangOptions = {},\n): Promise<HreflangAlternate[]> {\n\tif (!isI18nEnabled()) return [];\n\n\tlet siteUrl = options.siteUrl;\n\tif (!siteUrl) {\n\t\tconst settings = await getSiteSettingsWithDb(db);\n\t\tsiteUrl = settings.url;\n\t}\n\t// hreflang requires fully-qualified URLs; a relative site URL would\n\t// produce invalid output (and EmDashHead's isSafeHref would drop it).\n\tif (!siteUrl || !ABSOLUTE_URL_RE.test(siteUrl)) return [];\n\tsiteUrl = siteUrl.replace(TRAILING_SLASH_RE, \"\");\n\n\tconst repo = new ContentRepository(db);\n\tconst item = await repo.findByIdOrSlug(collection, entryId);\n\tif (!item) return [];\n\n\t// Legacy rows imported before i18n may have no translation_group;\n\t// treat them as a single-variant group.\n\tconst group = item.translationGroup || item.id;\n\tlet variants = await repo.findTranslations(collection, group);\n\tif (variants.length === 0) variants = [item];\n\n\tlet published = variants.filter((v) => v.status === \"published\");\n\tif (published.length === 0) return [];\n\n\t// Exclude noindex variants, matching the sitemap's `_emdash_seo`\n\t// filter so head and sitemap agree on which variants are\n\t// discoverable. When the requested entry itself is noindex, emit\n\t// nothing: a page opting out of indexing shouldn't announce an\n\t// hreflang set.\n\tconst noindexIds = await findNoindexIds(\n\t\tdb,\n\t\tcollection,\n\t\tpublished.map((v) => v.id),\n\t);\n\tif (noindexIds.has(item.id)) return [];\n\tpublished = published.filter((v) => !noindexIds.has(v.id));\n\n\tconst info = await getCollectionInfoWithDb(db, collection);\n\tconst urlPattern = info?.urlPattern ?? null;\n\n\tconst resolved: Array<{ locale: string; href: string }> = [];\n\tfor (const variant of published) {\n\t\tconst locale = variant.locale || \"en\";\n\t\tconst path = await resolveLocalizedContentRoutePath({\n\t\t\tpattern: urlPattern,\n\t\t\tcollection,\n\t\t\tslug: variant.slug || variant.id,\n\t\t\tid: variant.id,\n\t\t\tdate: variant.publishedAt,\n\t\t\tlocale,\n\t\t\ttrailingSlash: options.trailingSlash,\n\t\t});\n\t\tif (path === null) continue;\n\t\tresolved.push({ locale, href: `${siteUrl}${path}` });\n\t}\n\tif (resolved.length === 0) return [];\n\n\tresolved.sort((a, b) => a.locale.localeCompare(b.locale));\n\tconst alternates: HreflangAlternate[] = resolved.map((r) => ({\n\t\threflang: r.locale,\n\t\thref: r.href,\n\t}));\n\n\t// x-default: default-locale variant, else the first routable one.\n\t// Same fallback the sitemap route uses.\n\tconst defaultLocale = getI18nConfig()?.defaultLocale;\n\tconst xDefault = resolved.find((r) => r.locale === defaultLocale) ?? resolved[0];\n\tif (xDefault) {\n\t\talternates.push({ hreflang: \"x-default\", href: xDefault.href });\n\t}\n\n\treturn alternates;\n}\n"],"mappings":";;;;;;;;AAkCA,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;;;;;;;AAQxB,eAAe,eACd,IACA,YACA,KACuB;AACvB,KAAI,IAAI,WAAW,EAAG,wBAAO,IAAI,KAAK;CACtC,MAAM,OAAO,MAAM,GACjB,WAAW,cAAc,CACzB,OAAO,aAAa,CACpB,MAAM,cAAc,KAAK,WAAW,CACpC,MAAM,cAAc,MAAM,IAAI,CAC9B,MAAM,gBAAgB,KAAK,EAAE,CAC7B,SAAS;AACX,QAAO,IAAI,IAAI,KAAK,KAAK,MAAM,EAAE,WAAW,CAAC;;;;;;;;;;;;;;;;;;;AAwC9C,eAAsB,sBACrB,YACA,SACA,UAA2B,EAAE,EACE;AAC/B,KAAI,CAAC,eAAe,CAAE,QAAO,EAAE;AAE/B,QAAO,cADK,YAAY,WAAW,GAAG,QAAQ,GAAG,QAAQ,WAAW,GAAG,GAAG,QAAQ,iBAAiB,YACzE,YAAY;EACrC,MAAM,EAAE,UAAU,MAAM,OAAO;AAE/B,SAAO,4BADI,MAAM,OAAO,EACe,YAAY,SAAS,QAAQ;GACnE;;;;;;;;AASH,eAAsB,4BACrB,IACA,YACA,SACA,UAA2B,EAAE,EACE;AAC/B,KAAI,CAAC,eAAe,CAAE,QAAO,EAAE;CAE/B,IAAI,UAAU,QAAQ;AACtB,KAAI,CAAC,QAEJ,YADiB,MAAM,sBAAsB,GAAG,EAC7B;AAIpB,KAAI,CAAC,WAAW,CAAC,gBAAgB,KAAK,QAAQ,CAAE,QAAO,EAAE;AACzD,WAAU,QAAQ,QAAQ,mBAAmB,GAAG;CAEhD,MAAM,OAAO,IAAI,kBAAkB,GAAG;CACtC,MAAM,OAAO,MAAM,KAAK,eAAe,YAAY,QAAQ;AAC3D,KAAI,CAAC,KAAM,QAAO,EAAE;CAIpB,MAAM,QAAQ,KAAK,oBAAoB,KAAK;CAC5C,IAAI,WAAW,MAAM,KAAK,iBAAiB,YAAY,MAAM;AAC7D,KAAI,SAAS,WAAW,EAAG,YAAW,CAAC,KAAK;CAE5C,IAAI,YAAY,SAAS,QAAQ,MAAM,EAAE,WAAW,YAAY;AAChE,KAAI,UAAU,WAAW,EAAG,QAAO,EAAE;CAOrC,MAAM,aAAa,MAAM,eACxB,IACA,YACA,UAAU,KAAK,MAAM,EAAE,GAAG,CAC1B;AACD,KAAI,WAAW,IAAI,KAAK,GAAG,CAAE,QAAO,EAAE;AACtC,aAAY,UAAU,QAAQ,MAAM,CAAC,WAAW,IAAI,EAAE,GAAG,CAAC;CAG1D,MAAM,cADO,MAAM,wBAAwB,IAAI,WAAW,GACjC,cAAc;CAEvC,MAAM,WAAoD,EAAE;AAC5D,MAAK,MAAM,WAAW,WAAW;EAChC,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,OAAO,MAAM,iCAAiC;GACnD,SAAS;GACT;GACA,MAAM,QAAQ,QAAQ,QAAQ;GAC9B,IAAI,QAAQ;GACZ,MAAM,QAAQ;GACd;GACA,eAAe,QAAQ;GACvB,CAAC;AACF,MAAI,SAAS,KAAM;AACnB,WAAS,KAAK;GAAE;GAAQ,MAAM,GAAG,UAAU;GAAQ,CAAC;;AAErD,KAAI,SAAS,WAAW,EAAG,QAAO,EAAE;AAEpC,UAAS,MAAM,GAAG,MAAM,EAAE,OAAO,cAAc,EAAE,OAAO,CAAC;CACzD,MAAM,aAAkC,SAAS,KAAK,OAAO;EAC5D,UAAU,EAAE;EACZ,MAAM,EAAE;EACR,EAAE;CAIH,MAAM,gBAAgB,eAAe,EAAE;CACvC,MAAM,WAAW,SAAS,MAAM,MAAM,EAAE,WAAW,cAAc,IAAI,SAAS;AAC9E,KAAI,SACH,YAAW,KAAK;EAAE,UAAU;EAAa,MAAM,SAAS;EAAM,CAAC;AAGhE,QAAO"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as generateFieldSchema } from "./zod-generator
|
|
2
|
-
import { n as apiSuccess, t as apiError } from "./error-
|
|
1
|
+
import { n as generateFieldSchema } from "./zod-generator--nlM0930.mjs";
|
|
2
|
+
import { n as apiSuccess, t as apiError } from "./error-BCMgPxdn.mjs";
|
|
3
3
|
import { i as pluginRouteResponseToWire, n as parseDeclaredPluginRouteInput, r as pluginRouteResponseFromWire, t as PluginRouteRequestError } from "./route-wire-Ca_HWCZ5.mjs";
|
|
4
|
-
import { a as requireOwnerPerm, o as requirePerm } from "./authorize-
|
|
5
|
-
import { n as requireScope } from "./scopes-
|
|
4
|
+
import { a as requireOwnerPerm, o as requirePerm } from "./authorize-NJgp8kLI.mjs";
|
|
5
|
+
import { n as requireScope } from "./scopes-DNaY7Ey0.mjs";
|
|
6
6
|
import { Permissions } from "@emdash-cms/auth";
|
|
7
7
|
import { getLocaleDir, resolveLocale } from "@emdash-cms/admin/locales";
|
|
8
8
|
import { isEditorDraftPatchEffect, validateContentEditorPanelInteraction, validateEditorDraftPatchEffect } from "@emdash-cms/blocks/server";
|
|
@@ -339,4 +339,4 @@ async function dispatchPluginEditorExtensionApiRequest({ runtime, pluginId, kind
|
|
|
339
339
|
|
|
340
340
|
//#endregion
|
|
341
341
|
export { validateEditorDraftRequest as i, dispatchPluginEditorExtensionApiRequest as n, validateEditorDraftPatch as r, dispatchPluginApiRequest as t };
|
|
342
|
-
//# sourceMappingURL=http-route-dispatch-
|
|
342
|
+
//# sourceMappingURL=http-route-dispatch-rXKvTNm9.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-route-dispatch-CyeW6iPv.mjs","names":["isRecord","toRoleLevel"],"sources":["../src/plugins/editor-draft.ts","../src/plugins/http-route-dispatch.ts"],"sourcesContent":["import type {\n\tEditorDraftFieldDefinition,\n\tEditorDraftInvocationReceipt,\n\tEditorDraftPatchEffect,\n\tEditorDraftSnapshot,\n} from \"@emdash-cms/blocks\";\nimport {\n\tisEditorDraftPatchEffect,\n\tvalidateEditorDraftPatchEffect,\n} from \"@emdash-cms/blocks/server\";\n\nimport type { CollectionWithFields, Field } from \"../schema/types.js\";\nimport { generateFieldSchema } from \"../schema/zod-generator.js\";\nimport type { PluginEditorDraftFieldSelector } from \"./types.js\";\n\nexport const EDITOR_DRAFT_LIMITS = {\n\tmaxFields: 32,\n\tmaxSnapshotBytes: 192 * 1024,\n\tmaxFieldBytes: 64 * 1024,\n} as const;\n\nexport type EditorDraftErrorCode =\n\t| \"EDITOR_DRAFT_STALE\"\n\t| \"EDITOR_DRAFT_FIELD_FORBIDDEN\"\n\t| \"EDITOR_DRAFT_INVALID\"\n\t| \"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\"\n\t| \"EDITOR_DRAFT_TOO_LARGE\"\n\t| \"EDITOR_DRAFT_CAPABILITY_REQUIRED\";\n\nexport interface EditorDraftValidationError {\n\tcode: EditorDraftErrorCode;\n\tmessage: string;\n}\n\ninterface BrowserDraftRequest {\n\tcollection: string;\n\tentryId: string;\n\tlocale: string | null;\n\tbaseRevision: string;\n\tgeneration: number;\n\tinvocationId: string;\n\tfields: Record<string, unknown>;\n}\n\nexport interface ValidatedEditorDraftRequest {\n\tsnapshot: EditorDraftSnapshot;\n\treceipt: EditorDraftInvocationReceipt;\n\treadFields: ReadonlySet<string>;\n\tpatchFields: ReadonlySet<string>;\n}\n\nconst ENCODER = new TextEncoder();\nconst INVOCATION_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isBrowserDraftRequest(value: unknown): value is BrowserDraftRequest {\n\treturn (\n\t\tisRecord(value) &&\n\t\ttypeof value.collection === \"string\" &&\n\t\ttypeof value.entryId === \"string\" &&\n\t\t(value.locale === null || typeof value.locale === \"string\") &&\n\t\ttypeof value.baseRevision === \"string\" &&\n\t\ttypeof value.generation === \"number\" &&\n\t\ttypeof value.invocationId === \"string\" &&\n\t\tisRecord(value.fields)\n\t);\n}\n\nfunction jsonBytes(value: unknown): number | null {\n\ttry {\n\t\treturn ENCODER.encode(JSON.stringify(value)).byteLength;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction selectedFields(\n\tcollection: CollectionWithFields,\n\tselector: PluginEditorDraftFieldSelector | undefined,\n): Set<string> {\n\tconst selected = new Set(selector?.fields ?? []);\n\tif (selector?.translatable) {\n\t\tfor (const field of collection.fields) {\n\t\t\tif (field.translatable) selected.add(field.slug);\n\t\t}\n\t}\n\treturn selected;\n}\n\nfunction sanitizeField(field: Field): EditorDraftFieldDefinition {\n\treturn {\n\t\tslug: field.slug,\n\t\tlabel: field.label,\n\t\ttype: field.type,\n\t\trequired: field.required,\n\t\ttranslatable: field.translatable,\n\t\t...(field.validation ? { validation: { ...field.validation } } : {}),\n\t};\n}\n\nfunction fail(code: EditorDraftErrorCode, message: string): EditorDraftValidationError {\n\treturn { code, message };\n}\n\nexport function validateEditorDraftRequest(input: {\n\trequest: unknown;\n\tcollection: CollectionWithFields;\n\tentry: { id: string; locale: string | null; revision: string };\n\treadSelector?: PluginEditorDraftFieldSelector;\n\tpatchSelector?: PluginEditorDraftFieldSelector;\n\tcanRead: boolean;\n\tcanPatch: boolean;\n}): ValidatedEditorDraftRequest | EditorDraftValidationError {\n\tif (!isBrowserDraftRequest(input.request)) {\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Invalid editor draft snapshot\");\n\t}\n\tconst request = input.request;\n\tif (\n\t\trequest.collection !== input.collection.slug ||\n\t\trequest.entryId !== input.entry.id ||\n\t\trequest.locale !== input.entry.locale\n\t) {\n\t\treturn fail(\"EDITOR_DRAFT_STALE\", \"Editor draft identity is stale\");\n\t}\n\tif (request.baseRevision !== input.entry.revision) {\n\t\treturn fail(\"EDITOR_DRAFT_STALE\", \"Editor draft base revision is stale\");\n\t}\n\tif (\n\t\t!Number.isSafeInteger(request.generation) ||\n\t\trequest.generation < 0 ||\n\t\ttypeof request.invocationId !== \"string\" ||\n\t\t!INVOCATION_PATTERN.test(request.invocationId)\n\t) {\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Invalid editor draft invocation identity\");\n\t}\n\tconst size = jsonBytes(request);\n\tif (size === null)\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Editor draft snapshot must be JSON serializable\");\n\tif (size > EDITOR_DRAFT_LIMITS.maxSnapshotBytes) {\n\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", \"Editor draft snapshot exceeds the size limit\");\n\t}\n\n\tconst readFields = selectedFields(input.collection, input.readSelector);\n\tconst patchFields = selectedFields(input.collection, input.patchSelector);\n\tif (\n\t\treadFields.size > EDITOR_DRAFT_LIMITS.maxFields ||\n\t\tpatchFields.size > EDITOR_DRAFT_LIMITS.maxFields\n\t) {\n\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", \"Editor draft selector exceeds the field limit\");\n\t}\n\tconst supplied = Object.keys(request.fields);\n\tif (supplied.length > EDITOR_DRAFT_LIMITS.maxFields) {\n\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", \"Editor draft snapshot exceeds the field limit\");\n\t}\n\tif (supplied.length > 0 && !input.canRead) {\n\t\treturn fail(\"EDITOR_DRAFT_CAPABILITY_REQUIRED\", \"Plugin cannot read unsaved editor content\");\n\t}\n\tconst bySlug = new Map(input.collection.fields.map((field) => [field.slug, field]));\n\tconst patchFieldDefinitions = Array.from(patchFields, (slug) => bySlug.get(slug))\n\t\t.filter((field): field is Field => Boolean(field && !field.unsupportedType))\n\t\t.map(sanitizeField);\n\tconst fields: Record<string, unknown> = {};\n\tconst fieldDefinitions: EditorDraftFieldDefinition[] = [];\n\tfor (const slug of supplied) {\n\t\tif (!readFields.has(slug)) {\n\t\t\treturn fail(\"EDITOR_DRAFT_FIELD_FORBIDDEN\", `Editor draft field '${slug}' is not allowed`);\n\t\t}\n\t\tconst field = bySlug.get(slug);\n\t\tif (!field || field.unsupportedType) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t`Editor draft field '${slug}' has an unsupported type`,\n\t\t\t);\n\t\t}\n\t\tconst fieldSize = jsonBytes(request.fields[slug]);\n\t\tif (fieldSize === null)\n\t\t\treturn fail(\"EDITOR_DRAFT_INVALID\", `Editor draft field '${slug}' is invalid`);\n\t\tif (fieldSize > EDITOR_DRAFT_LIMITS.maxFieldBytes) {\n\t\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", `Editor draft field '${slug}' exceeds the size limit`);\n\t\t}\n\t\tif (!generateFieldSchema(field).safeParse(request.fields[slug]).success) {\n\t\t\treturn fail(\"EDITOR_DRAFT_INVALID\", `Editor draft field '${slug}' is invalid`);\n\t\t}\n\t\tfields[slug] = request.fields[slug];\n\t\tfieldDefinitions.push(sanitizeField(field));\n\t}\n\tif (input.readSelector && !input.canRead) {\n\t\treturn fail(\"EDITOR_DRAFT_CAPABILITY_REQUIRED\", \"Plugin cannot read unsaved editor content\");\n\t}\n\tif (input.patchSelector && !input.canPatch) {\n\t\treturn fail(\"EDITOR_DRAFT_CAPABILITY_REQUIRED\", \"Plugin cannot propose unsaved editor changes\");\n\t}\n\n\treturn {\n\t\tsnapshot: {\n\t\t\tcollection: input.collection.slug,\n\t\t\tentryId: input.entry.id,\n\t\t\tlocale: input.entry.locale,\n\t\t\tbaseRevision: input.entry.revision,\n\t\t\tinvocationId: request.invocationId,\n\t\t\tfields,\n\t\t\tfieldDefinitions,\n\t\t},\n\t\treceipt: {\n\t\t\tentryId: input.entry.id,\n\t\t\tlocale: input.entry.locale,\n\t\t\tbaseRevision: input.entry.revision,\n\t\t\tgeneration: request.generation,\n\t\t\tinvocationId: request.invocationId,\n\t\t\tfieldDefinitions: patchFieldDefinitions,\n\t\t},\n\t\treadFields,\n\t\tpatchFields,\n\t};\n}\n\nexport function validateEditorDraftPatch(input: {\n\tpatch: unknown;\n\tcollection: CollectionWithFields;\n\tallowedFields: ReadonlySet<string>;\n}): EditorDraftPatchEffect | EditorDraftValidationError {\n\tconst structural = validateEditorDraftPatchEffect(input.patch);\n\tif (!structural.valid || !isEditorDraftPatchEffect(input.patch))\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Plugin returned an invalid editor draft patch\");\n\tconst patch = input.patch;\n\tconst bySlug = new Map(input.collection.fields.map((field) => [field.slug, field]));\n\tfor (const operation of patch.operations) {\n\t\tif (!input.allowedFields.has(operation.field)) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_FIELD_FORBIDDEN\",\n\t\t\t\t`Editor draft field '${operation.field}' is not allowed`,\n\t\t\t);\n\t\t}\n\t\tconst field = bySlug.get(operation.field);\n\t\tif (!field || field.unsupportedType) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t`Editor draft field '${operation.field}' has an unsupported type`,\n\t\t\t);\n\t\t}\n\t\tconst value = operation.op === \"clear\" ? null : operation.value;\n\t\tif (!generateFieldSchema(field).safeParse(value).success) {\n\t\t\treturn fail(\"EDITOR_DRAFT_INVALID\", `Editor draft field '${operation.field}' is invalid`);\n\t\t}\n\t\tconst fieldSize = jsonBytes(value);\n\t\tif (fieldSize === null || fieldSize > EDITOR_DRAFT_LIMITS.maxFieldBytes) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_TOO_LARGE\",\n\t\t\t\t`Editor draft field '${operation.field}' exceeds the size limit`,\n\t\t\t);\n\t\t}\n\t}\n\treturn patch;\n}\n","import { getLocaleDir, resolveLocale } from \"@emdash-cms/admin/locales\";\nimport { Permissions, type Permission, type RoleLevel } from \"@emdash-cms/auth\";\nimport { validateContentEditorPanelInteraction } from \"@emdash-cms/blocks/server\";\n\nimport { requirePerm, requireOwnerPerm } from \"../api/authorize.js\";\nimport { apiError, apiSuccess } from \"../api/error.js\";\nimport { requireScope } from \"../auth/scopes.js\";\nimport type { EmDashRuntime, PluginEditorExtensionDispatch } from \"../emdash-runtime.js\";\nimport {\n\tvalidateEditorDraftPatch,\n\tvalidateEditorDraftRequest,\n\ttype ValidatedEditorDraftRequest,\n} from \"./editor-draft.js\";\nimport { pluginRouteResponseFromWire, pluginRouteResponseToWire } from \"./route-wire.js\";\nimport { parseDeclaredPluginRouteInput, PluginRouteRequestError } from \"./route-wire.js\";\nimport type { PluginContentCacheInvalidator, RouteMeta } from \"./routes.js\";\nimport type { UserInfo } from \"./types.js\";\n\nfunction editorDraftErrorResponse(error: { code: string; message: string }): Response {\n\tconst status =\n\t\terror.code === \"EDITOR_DRAFT_STALE\"\n\t\t\t? 409\n\t\t\t: error.code === \"EDITOR_DRAFT_FIELD_FORBIDDEN\" ||\n\t\t\t\t error.code === \"EDITOR_DRAFT_CAPABILITY_REQUIRED\"\n\t\t\t\t? 403\n\t\t\t\t: error.code === \"EDITOR_DRAFT_TOO_LARGE\"\n\t\t\t\t\t? 413\n\t\t\t\t\t: error.code === \"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\"\n\t\t\t\t\t\t? 422\n\t\t\t\t\t\t: 400;\n\treturn apiError(error.code, error.message, status);\n}\n\nfunction toRoleLevel(value: number): RoleLevel | null {\n\tif (value === 10 || value === 20 || value === 30 || value === 40 || value === 50) {\n\t\treturn value;\n\t}\n\treturn null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPermission(value: string): value is Permission {\n\treturn Object.hasOwn(Permissions, value);\n}\n\nfunction authorizePrivatePluginRouteRequest(\n\trouteMeta: RouteMeta,\n\trequest: Request,\n\tuser?: UserInfo | null,\n\ttokenScopes?: string[],\n): Response | null {\n\tconst permission = routeMeta.permission ?? \"plugins:manage\";\n\tif (!isPermission(permission)) {\n\t\treturn apiError(\"INVALID_PLUGIN_ROUTE\", \"Plugin route declares an invalid permission\", 500);\n\t}\n\n\tlet permissionUser: { id: string; role: RoleLevel } | null | undefined;\n\tif (user) {\n\t\tconst role = toRoleLevel(user.role);\n\t\tif (role === null) {\n\t\t\treturn apiError(\"INVALID_USER\", \"Authenticated user has an invalid role\", 500);\n\t\t}\n\t\tpermissionUser = { id: user.id, role };\n\t} else {\n\t\tpermissionUser = user;\n\t}\n\n\tconst denied = requirePerm(permissionUser, permission);\n\tif (denied) return denied;\n\tconst scopeError = requireScope({ tokenScopes }, \"admin\");\n\tif (scopeError) return scopeError;\n\tif (!tokenScopes && request.headers.get(\"X-EmDash-Request\") !== \"1\") {\n\t\treturn apiError(\"CSRF_REJECTED\", \"Missing required header\", 403);\n\t}\n\treturn null;\n}\n\nexport interface PluginApiRequestContext {\n\truntime: EmDashRuntime;\n\tpluginId: string;\n\tpath: string;\n\trequest: Request;\n\tuser?: UserInfo | null;\n\ttokenScopes?: string[];\n\tinvalidateContentCache?: PluginContentCacheInvalidator;\n\teditorDispatch?: PluginEditorExtensionDispatch;\n}\n\n/** Dispatch a request through the production plugin-route policy boundary. */\nexport async function dispatchPluginApiRequest({\n\truntime,\n\tpluginId,\n\tpath,\n\trequest,\n\tuser,\n\ttokenScopes,\n\tinvalidateContentCache,\n\teditorDispatch,\n}: PluginApiRequestContext): Promise<Response> {\n\tconst method = request.method.toUpperCase();\n\tconst routeMeta = runtime.getPluginRouteMeta(pluginId, path);\n\tif (!routeMeta) return apiError(\"NOT_FOUND\", \"Plugin route not found\", 404);\n\n\tif (!routeMeta.public) {\n\t\tconst denied = authorizePrivatePluginRouteRequest(routeMeta, request, user, tokenScopes);\n\t\tif (denied) return denied;\n\t}\n\tif (routeMeta.methods && !routeMeta.methods.some((allowed) => allowed === method)) {\n\t\tconst response = apiError(\"METHOD_NOT_ALLOWED\", \"Method not allowed\", 405);\n\t\tresponse.headers.set(\"Allow\", routeMeta.methods.join(\", \"));\n\t\treturn response;\n\t}\n\n\tconst caller = routeMeta.public ? undefined : (user ?? undefined);\n\tconst result = await runtime.handlePluginApiRoute(\n\t\tpluginId,\n\t\tmethod,\n\t\tpath,\n\t\trequest,\n\t\tcaller,\n\t\tinvalidateContentCache,\n\t\teditorDispatch,\n\t);\n\tif (!result.success) {\n\t\tconst code = result.error?.code ?? \"PLUGIN_ERROR\";\n\t\tconst message =\n\t\t\tcode === \"INTERNAL_ERROR\"\n\t\t\t\t? \"Plugin route error\"\n\t\t\t\t: (result.error?.message ?? \"Plugin route error\");\n\t\tconst status = (result as { status?: number }).status ?? (code === \"NOT_FOUND\" ? 404 : 400);\n\t\tconst details =\n\t\t\tcode !== \"INTERNAL_ERROR\" && result.error && \"details\" in result.error\n\t\t\t\t? result.error.details\n\t\t\t\t: undefined;\n\t\treturn apiError(code, message, status, isRecord(details) ? details : undefined);\n\t}\n\n\tlet response: Response;\n\tif (routeMeta.response === \"raw\") {\n\t\ttry {\n\t\t\tresponse = pluginRouteResponseFromWire(\n\t\t\t\tawait pluginRouteResponseToWire(\n\t\t\t\t\tresult.data,\n\t\t\t\t\trouteMeta.public ? { publicRequestUrl: request.url } : { allowExternalLocation: true },\n\t\t\t\t),\n\t\t\t\tmethod,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tconsole.error(`[plugin:${pluginId}] Invalid raw route response:`, error);\n\t\t\treturn apiError(\"INVALID_PLUGIN_RESPONSE\", \"Plugin returned an invalid response\", 500);\n\t\t}\n\t} else {\n\t\tresponse = apiSuccess(result.data);\n\t}\n\tif (\n\t\tresponse.ok &&\n\t\trouteMeta.public &&\n\t\trouteMeta.cacheControl &&\n\t\t(method === \"GET\" || method === \"HEAD\")\n\t) {\n\t\tresponse.headers.set(\"Cache-Control\", routeMeta.cacheControl);\n\t} else {\n\t\tresponse.headers.set(\"Cache-Control\", \"private, no-store\");\n\t}\n\treturn response;\n}\n\nexport interface PluginEditorExtensionApiRequestContext {\n\truntime: EmDashRuntime;\n\tpluginId: string;\n\tkind: \"panel\" | \"action\";\n\textensionId: string;\n\tcollection: string;\n\tentryId: string;\n\trequest: Request;\n\tuser?: UserInfo | null;\n\ttokenScopes?: string[];\n\tinvalidateContentCache?: PluginContentCacheInvalidator;\n}\n\nconst EDITOR_EXTENSION_REQUEST_MAX_BYTES = 256 * 1024;\n\n/** Dispatch a saved-entry extension through ownership, route, and isolate policy. */\nexport async function dispatchPluginEditorExtensionApiRequest({\n\truntime,\n\tpluginId,\n\tkind,\n\textensionId,\n\tcollection,\n\tentryId,\n\trequest,\n\tuser,\n\ttokenScopes,\n\tinvalidateContentCache,\n}: PluginEditorExtensionApiRequestContext): Promise<Response> {\n\tconst definition = runtime.getPluginEditorExtension(pluginId, kind, extensionId, collection);\n\tif (!definition) return apiError(\"NOT_FOUND\", \"Plugin editor extension not found\", 404);\n\n\tconst routeMeta = runtime.getPluginRouteMeta(pluginId, definition.extension.route);\n\tif (!routeMeta || routeMeta.public) {\n\t\treturn apiError(\n\t\t\t\"INVALID_PLUGIN_EDITOR_EXTENSION\",\n\t\t\t\"Plugin editor extension must reference a private route\",\n\t\t\t500,\n\t\t);\n\t}\n\tconst denied = authorizePrivatePluginRouteRequest(routeMeta, request, user, tokenScopes);\n\tif (denied) return denied;\n\n\tconst requestedLocale = new URL(request.url).searchParams.get(\"locale\") || undefined;\n\tconst contentResult = await runtime.handleContentGet(collection, entryId, requestedLocale);\n\tif (!contentResult.success) {\n\t\treturn contentResult.error?.code === \"NOT_FOUND\"\n\t\t\t? apiError(\"NOT_FOUND\", \"Content item not found\", 404)\n\t\t\t: apiError(\"CONTENT_GET_ERROR\", \"Failed to load content item\", 500);\n\t}\n\tconst contentData = contentResult.data;\n\tconst item =\n\t\ttypeof contentData === \"object\" && contentData !== null && \"item\" in contentData\n\t\t\t? contentData.item\n\t\t\t: null;\n\tif (typeof item !== \"object\" || item === null) {\n\t\treturn apiError(\"CONTENT_GET_ERROR\", \"Failed to load content item\", 500);\n\t}\n\tconst authorId = \"authorId\" in item && typeof item.authorId === \"string\" ? item.authorId : \"\";\n\tlet ownershipUser: { id: string; role: RoleLevel } | null | undefined =\n\t\tuser == null ? user : undefined;\n\tif (user) {\n\t\tconst ownerRole = toRoleLevel(user.role);\n\t\tif (ownerRole === null) {\n\t\t\treturn apiError(\"INVALID_USER\", \"Authenticated user has an invalid role\", 500);\n\t\t}\n\t\townershipUser = { id: user.id, role: ownerRole };\n\t}\n\tconst ownershipDenied = requireOwnerPerm(\n\t\townershipUser,\n\t\tauthorId,\n\t\t\"content:edit_own\",\n\t\t\"content:edit_any\",\n\t);\n\tif (ownershipDenied) return ownershipDenied;\n\n\tconst canonicalId = \"id\" in item && typeof item.id === \"string\" ? item.id : null;\n\tconst canonicalLocale = \"locale\" in item && typeof item.locale === \"string\" ? item.locale : null;\n\tconst version = \"version\" in item && typeof item.version === \"number\" ? item.version : null;\n\tconst baseRevision =\n\t\ttypeof contentData === \"object\" &&\n\t\tcontentData !== null &&\n\t\t\"_rev\" in contentData &&\n\t\ttypeof contentData._rev === \"string\"\n\t\t\t? contentData._rev\n\t\t\t: null;\n\tif (!canonicalId || version === null) {\n\t\treturn apiError(\"CONTENT_GET_ERROR\", \"Content item has invalid identity\", 500);\n\t}\n\n\tlet input: Record<string, unknown>;\n\tlet editorBody: unknown;\n\ttry {\n\t\teditorBody = await parseDeclaredPluginRouteInput(request, {\n\t\t\tbody: \"json\",\n\t\t\tmaxBytes: EDITOR_EXTENSION_REQUEST_MAX_BYTES,\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof PluginRouteRequestError) {\n\t\t\treturn apiError(\n\t\t\t\terror.status === 413 ? \"EDITOR_DRAFT_TOO_LARGE\" : \"INVALID_REQUEST\",\n\t\t\t\terror.status === 413\n\t\t\t\t\t? \"Editor interaction exceeds the size limit\"\n\t\t\t\t\t: \"Invalid editor interaction\",\n\t\t\t\terror.status,\n\t\t\t);\n\t\t}\n\t\treturn apiError(\"INVALID_REQUEST\", \"Editor interaction could not be read\", 400);\n\t}\n\tif (kind === \"panel\") {\n\t\tif (!isRecord(editorBody)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Editor panel interaction must be an object\", 400);\n\t\t}\n\t\tinput = editorBody;\n\t\tconst validation = validateContentEditorPanelInteraction(input);\n\t\tif (!validation.valid) {\n\t\t\treturn apiError(\"INVALID_PLUGIN_UI_CONTEXT\", \"Invalid editor panel interaction\", 400);\n\t\t}\n\t} else {\n\t\tif (!isRecord(editorBody)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid editor action interaction\", 400);\n\t\t}\n\t\tinput = {\n\t\t\ttype: \"editor_action\",\n\t\t\t...(Object.hasOwn(editorBody, \"draft\") ? { draft: editorBody.draft } : {}),\n\t\t};\n\t}\n\n\tlet validatedDraft: ValidatedEditorDraftRequest | null = null;\n\tif (input.draft !== undefined) {\n\t\tif (!baseRevision) {\n\t\t\treturn apiError(\"EDITOR_DRAFT_INVALID\", \"Content item has no draft revision identity\", 409);\n\t\t}\n\t\tconst collectionSchema = await runtime.getPluginEditorDraftSchema(collection);\n\t\tif (!collectionSchema) return apiError(\"NOT_FOUND\", \"Collection not found\", 404);\n\t\tconst draft = validateEditorDraftRequest({\n\t\t\trequest: input.draft,\n\t\t\tcollection: collectionSchema,\n\t\t\tentry: { id: canonicalId, locale: canonicalLocale, revision: baseRevision },\n\t\t\treadSelector: definition.extension.draft?.read,\n\t\t\tpatchSelector: definition.extension.draft?.patch,\n\t\t\tcanRead: definition.capabilities.includes(\"admin.editor-draft:read\"),\n\t\t\tcanPatch: definition.capabilities.includes(\"admin.editor-draft:patch\"),\n\t\t});\n\t\tif (\"code\" in draft) {\n\t\t\tconsole.warn(\n\t\t\t\t`[plugin:${pluginId}] Editor draft ${kind}/${extensionId} rejected: ${draft.code}`,\n\t\t\t);\n\t\t\treturn editorDraftErrorResponse(draft);\n\t\t}\n\t\tvalidatedDraft = draft;\n\t\tinput = { ...input, draft: draft.snapshot };\n\t}\n\n\tconst headers = new Headers(request.headers);\n\theaders.delete(\"content-length\");\n\theaders.delete(\"content-encoding\");\n\theaders.set(\"Content-Type\", \"application/json\");\n\tconst pluginRequest = new Request(request.url, {\n\t\tmethod: \"POST\",\n\t\theaders,\n\t\tbody: JSON.stringify(input),\n\t});\n\tconst locale = resolveLocale(request);\n\tconst response = await dispatchPluginApiRequest({\n\t\truntime,\n\t\tpluginId,\n\t\tpath: definition.extension.route,\n\t\trequest: pluginRequest,\n\t\tuser,\n\t\ttokenScopes,\n\t\tinvalidateContentCache,\n\t\teditorDispatch: {\n\t\t\tkind,\n\t\t\tpolicy: definition.policy,\n\t\t\tui: {\n\t\t\t\tsurface: kind === \"panel\" ? \"content-editor-panel\" : \"content-editor-action\",\n\t\t\t\tlocale,\n\t\t\t\tdirection: getLocaleDir(locale),\n\t\t\t\tcontentLocale: canonicalLocale ?? undefined,\n\t\t\t\textensionId,\n\t\t\t\tentry: {\n\t\t\t\t\tcollection,\n\t\t\t\t\tid: canonicalId,\n\t\t\t\t\tlocale: canonicalLocale,\n\t\t\t\t\tversion,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t});\n\tif (!response.ok) return response;\n\tconst envelope: unknown = await response.clone().json();\n\tif (!isRecord(envelope) || !isRecord(envelope.data)) {\n\t\treturn apiError(\"INVALID_PLUGIN_RESPONSE\", \"Plugin returned an invalid response\", 502);\n\t}\n\tconst data = envelope.data;\n\tif (data.patch === undefined && !validatedDraft) return response;\n\tif (data.patch !== undefined && !validatedDraft) {\n\t\treturn apiError(\n\t\t\t\"EDITOR_DRAFT_INVALID\",\n\t\t\t\"Plugin returned an editor draft patch without a draft invocation\",\n\t\t\t400,\n\t\t);\n\t}\n\tif (data.patch !== undefined) {\n\t\tconst collectionSchema = await runtime.getPluginEditorDraftSchema(collection);\n\t\tif (!collectionSchema) return apiError(\"NOT_FOUND\", \"Collection not found\", 404);\n\t\tconst patch = validateEditorDraftPatch({\n\t\t\tpatch: data.patch,\n\t\t\tcollection: collectionSchema,\n\t\t\tallowedFields: validatedDraft?.patchFields ?? new Set(),\n\t\t});\n\t\tif (\"code\" in patch) {\n\t\t\tconsole.warn(\n\t\t\t\t`[plugin:${pluginId}] Editor draft ${kind}/${extensionId} rejected: ${patch.code}`,\n\t\t\t);\n\t\t\treturn editorDraftErrorResponse(patch);\n\t\t}\n\t\tdata.patch = patch;\n\t}\n\tconst finalResponse = apiSuccess({ ...data, editorInvocation: validatedDraft?.receipt });\n\tfinalResponse.headers.set(\"Cache-Control\", \"private, no-store\");\n\treturn finalResponse;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"http-route-dispatch-rXKvTNm9.mjs","names":["isRecord","toRoleLevel"],"sources":["../src/plugins/editor-draft.ts","../src/plugins/http-route-dispatch.ts"],"sourcesContent":["import type {\n\tEditorDraftFieldDefinition,\n\tEditorDraftInvocationReceipt,\n\tEditorDraftPatchEffect,\n\tEditorDraftSnapshot,\n} from \"@emdash-cms/blocks\";\nimport {\n\tisEditorDraftPatchEffect,\n\tvalidateEditorDraftPatchEffect,\n} from \"@emdash-cms/blocks/server\";\n\nimport type { CollectionWithFields, Field } from \"../schema/types.js\";\nimport { generateFieldSchema } from \"../schema/zod-generator.js\";\nimport type { PluginEditorDraftFieldSelector } from \"./types.js\";\n\nexport const EDITOR_DRAFT_LIMITS = {\n\tmaxFields: 32,\n\tmaxSnapshotBytes: 192 * 1024,\n\tmaxFieldBytes: 64 * 1024,\n} as const;\n\nexport type EditorDraftErrorCode =\n\t| \"EDITOR_DRAFT_STALE\"\n\t| \"EDITOR_DRAFT_FIELD_FORBIDDEN\"\n\t| \"EDITOR_DRAFT_INVALID\"\n\t| \"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\"\n\t| \"EDITOR_DRAFT_TOO_LARGE\"\n\t| \"EDITOR_DRAFT_CAPABILITY_REQUIRED\";\n\nexport interface EditorDraftValidationError {\n\tcode: EditorDraftErrorCode;\n\tmessage: string;\n}\n\ninterface BrowserDraftRequest {\n\tcollection: string;\n\tentryId: string;\n\tlocale: string | null;\n\tbaseRevision: string;\n\tgeneration: number;\n\tinvocationId: string;\n\tfields: Record<string, unknown>;\n}\n\nexport interface ValidatedEditorDraftRequest {\n\tsnapshot: EditorDraftSnapshot;\n\treceipt: EditorDraftInvocationReceipt;\n\treadFields: ReadonlySet<string>;\n\tpatchFields: ReadonlySet<string>;\n}\n\nconst ENCODER = new TextEncoder();\nconst INVOCATION_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isBrowserDraftRequest(value: unknown): value is BrowserDraftRequest {\n\treturn (\n\t\tisRecord(value) &&\n\t\ttypeof value.collection === \"string\" &&\n\t\ttypeof value.entryId === \"string\" &&\n\t\t(value.locale === null || typeof value.locale === \"string\") &&\n\t\ttypeof value.baseRevision === \"string\" &&\n\t\ttypeof value.generation === \"number\" &&\n\t\ttypeof value.invocationId === \"string\" &&\n\t\tisRecord(value.fields)\n\t);\n}\n\nfunction jsonBytes(value: unknown): number | null {\n\ttry {\n\t\treturn ENCODER.encode(JSON.stringify(value)).byteLength;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction selectedFields(\n\tcollection: CollectionWithFields,\n\tselector: PluginEditorDraftFieldSelector | undefined,\n): Set<string> {\n\tconst selected = new Set(selector?.fields ?? []);\n\tif (selector?.translatable) {\n\t\tfor (const field of collection.fields) {\n\t\t\tif (field.translatable) selected.add(field.slug);\n\t\t}\n\t}\n\treturn selected;\n}\n\nfunction sanitizeField(field: Field): EditorDraftFieldDefinition {\n\treturn {\n\t\tslug: field.slug,\n\t\tlabel: field.label,\n\t\ttype: field.type,\n\t\trequired: field.required,\n\t\ttranslatable: field.translatable,\n\t\t...(field.validation ? { validation: { ...field.validation } } : {}),\n\t};\n}\n\nfunction fail(code: EditorDraftErrorCode, message: string): EditorDraftValidationError {\n\treturn { code, message };\n}\n\nexport function validateEditorDraftRequest(input: {\n\trequest: unknown;\n\tcollection: CollectionWithFields;\n\tentry: { id: string; locale: string | null; revision: string };\n\treadSelector?: PluginEditorDraftFieldSelector;\n\tpatchSelector?: PluginEditorDraftFieldSelector;\n\tcanRead: boolean;\n\tcanPatch: boolean;\n}): ValidatedEditorDraftRequest | EditorDraftValidationError {\n\tif (!isBrowserDraftRequest(input.request)) {\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Invalid editor draft snapshot\");\n\t}\n\tconst request = input.request;\n\tif (\n\t\trequest.collection !== input.collection.slug ||\n\t\trequest.entryId !== input.entry.id ||\n\t\trequest.locale !== input.entry.locale\n\t) {\n\t\treturn fail(\"EDITOR_DRAFT_STALE\", \"Editor draft identity is stale\");\n\t}\n\tif (request.baseRevision !== input.entry.revision) {\n\t\treturn fail(\"EDITOR_DRAFT_STALE\", \"Editor draft base revision is stale\");\n\t}\n\tif (\n\t\t!Number.isSafeInteger(request.generation) ||\n\t\trequest.generation < 0 ||\n\t\ttypeof request.invocationId !== \"string\" ||\n\t\t!INVOCATION_PATTERN.test(request.invocationId)\n\t) {\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Invalid editor draft invocation identity\");\n\t}\n\tconst size = jsonBytes(request);\n\tif (size === null)\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Editor draft snapshot must be JSON serializable\");\n\tif (size > EDITOR_DRAFT_LIMITS.maxSnapshotBytes) {\n\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", \"Editor draft snapshot exceeds the size limit\");\n\t}\n\n\tconst readFields = selectedFields(input.collection, input.readSelector);\n\tconst patchFields = selectedFields(input.collection, input.patchSelector);\n\tif (\n\t\treadFields.size > EDITOR_DRAFT_LIMITS.maxFields ||\n\t\tpatchFields.size > EDITOR_DRAFT_LIMITS.maxFields\n\t) {\n\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", \"Editor draft selector exceeds the field limit\");\n\t}\n\tconst supplied = Object.keys(request.fields);\n\tif (supplied.length > EDITOR_DRAFT_LIMITS.maxFields) {\n\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", \"Editor draft snapshot exceeds the field limit\");\n\t}\n\tif (supplied.length > 0 && !input.canRead) {\n\t\treturn fail(\"EDITOR_DRAFT_CAPABILITY_REQUIRED\", \"Plugin cannot read unsaved editor content\");\n\t}\n\tconst bySlug = new Map(input.collection.fields.map((field) => [field.slug, field]));\n\tconst patchFieldDefinitions = Array.from(patchFields, (slug) => bySlug.get(slug))\n\t\t.filter((field): field is Field => Boolean(field && !field.unsupportedType))\n\t\t.map(sanitizeField);\n\tconst fields: Record<string, unknown> = {};\n\tconst fieldDefinitions: EditorDraftFieldDefinition[] = [];\n\tfor (const slug of supplied) {\n\t\tif (!readFields.has(slug)) {\n\t\t\treturn fail(\"EDITOR_DRAFT_FIELD_FORBIDDEN\", `Editor draft field '${slug}' is not allowed`);\n\t\t}\n\t\tconst field = bySlug.get(slug);\n\t\tif (!field || field.unsupportedType) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t`Editor draft field '${slug}' has an unsupported type`,\n\t\t\t);\n\t\t}\n\t\tconst fieldSize = jsonBytes(request.fields[slug]);\n\t\tif (fieldSize === null)\n\t\t\treturn fail(\"EDITOR_DRAFT_INVALID\", `Editor draft field '${slug}' is invalid`);\n\t\tif (fieldSize > EDITOR_DRAFT_LIMITS.maxFieldBytes) {\n\t\t\treturn fail(\"EDITOR_DRAFT_TOO_LARGE\", `Editor draft field '${slug}' exceeds the size limit`);\n\t\t}\n\t\tif (!generateFieldSchema(field).safeParse(request.fields[slug]).success) {\n\t\t\treturn fail(\"EDITOR_DRAFT_INVALID\", `Editor draft field '${slug}' is invalid`);\n\t\t}\n\t\tfields[slug] = request.fields[slug];\n\t\tfieldDefinitions.push(sanitizeField(field));\n\t}\n\tif (input.readSelector && !input.canRead) {\n\t\treturn fail(\"EDITOR_DRAFT_CAPABILITY_REQUIRED\", \"Plugin cannot read unsaved editor content\");\n\t}\n\tif (input.patchSelector && !input.canPatch) {\n\t\treturn fail(\"EDITOR_DRAFT_CAPABILITY_REQUIRED\", \"Plugin cannot propose unsaved editor changes\");\n\t}\n\n\treturn {\n\t\tsnapshot: {\n\t\t\tcollection: input.collection.slug,\n\t\t\tentryId: input.entry.id,\n\t\t\tlocale: input.entry.locale,\n\t\t\tbaseRevision: input.entry.revision,\n\t\t\tinvocationId: request.invocationId,\n\t\t\tfields,\n\t\t\tfieldDefinitions,\n\t\t},\n\t\treceipt: {\n\t\t\tentryId: input.entry.id,\n\t\t\tlocale: input.entry.locale,\n\t\t\tbaseRevision: input.entry.revision,\n\t\t\tgeneration: request.generation,\n\t\t\tinvocationId: request.invocationId,\n\t\t\tfieldDefinitions: patchFieldDefinitions,\n\t\t},\n\t\treadFields,\n\t\tpatchFields,\n\t};\n}\n\nexport function validateEditorDraftPatch(input: {\n\tpatch: unknown;\n\tcollection: CollectionWithFields;\n\tallowedFields: ReadonlySet<string>;\n}): EditorDraftPatchEffect | EditorDraftValidationError {\n\tconst structural = validateEditorDraftPatchEffect(input.patch);\n\tif (!structural.valid || !isEditorDraftPatchEffect(input.patch))\n\t\treturn fail(\"EDITOR_DRAFT_INVALID\", \"Plugin returned an invalid editor draft patch\");\n\tconst patch = input.patch;\n\tconst bySlug = new Map(input.collection.fields.map((field) => [field.slug, field]));\n\tfor (const operation of patch.operations) {\n\t\tif (!input.allowedFields.has(operation.field)) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_FIELD_FORBIDDEN\",\n\t\t\t\t`Editor draft field '${operation.field}' is not allowed`,\n\t\t\t);\n\t\t}\n\t\tconst field = bySlug.get(operation.field);\n\t\tif (!field || field.unsupportedType) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\",\n\t\t\t\t`Editor draft field '${operation.field}' has an unsupported type`,\n\t\t\t);\n\t\t}\n\t\tconst value = operation.op === \"clear\" ? null : operation.value;\n\t\tif (!generateFieldSchema(field).safeParse(value).success) {\n\t\t\treturn fail(\"EDITOR_DRAFT_INVALID\", `Editor draft field '${operation.field}' is invalid`);\n\t\t}\n\t\tconst fieldSize = jsonBytes(value);\n\t\tif (fieldSize === null || fieldSize > EDITOR_DRAFT_LIMITS.maxFieldBytes) {\n\t\t\treturn fail(\n\t\t\t\t\"EDITOR_DRAFT_TOO_LARGE\",\n\t\t\t\t`Editor draft field '${operation.field}' exceeds the size limit`,\n\t\t\t);\n\t\t}\n\t}\n\treturn patch;\n}\n","import { getLocaleDir, resolveLocale } from \"@emdash-cms/admin/locales\";\nimport { Permissions, type Permission, type RoleLevel } from \"@emdash-cms/auth\";\nimport { validateContentEditorPanelInteraction } from \"@emdash-cms/blocks/server\";\n\nimport { requirePerm, requireOwnerPerm } from \"../api/authorize.js\";\nimport { apiError, apiSuccess } from \"../api/error.js\";\nimport { requireScope } from \"../auth/scopes.js\";\nimport type { EmDashRuntime, PluginEditorExtensionDispatch } from \"../emdash-runtime.js\";\nimport {\n\tvalidateEditorDraftPatch,\n\tvalidateEditorDraftRequest,\n\ttype ValidatedEditorDraftRequest,\n} from \"./editor-draft.js\";\nimport { pluginRouteResponseFromWire, pluginRouteResponseToWire } from \"./route-wire.js\";\nimport { parseDeclaredPluginRouteInput, PluginRouteRequestError } from \"./route-wire.js\";\nimport type { PluginContentCacheInvalidator, RouteMeta } from \"./routes.js\";\nimport type { UserInfo } from \"./types.js\";\n\nfunction editorDraftErrorResponse(error: { code: string; message: string }): Response {\n\tconst status =\n\t\terror.code === \"EDITOR_DRAFT_STALE\"\n\t\t\t? 409\n\t\t\t: error.code === \"EDITOR_DRAFT_FIELD_FORBIDDEN\" ||\n\t\t\t\t error.code === \"EDITOR_DRAFT_CAPABILITY_REQUIRED\"\n\t\t\t\t? 403\n\t\t\t\t: error.code === \"EDITOR_DRAFT_TOO_LARGE\"\n\t\t\t\t\t? 413\n\t\t\t\t\t: error.code === \"EDITOR_DRAFT_UNSUPPORTED_FIELD_TYPE\"\n\t\t\t\t\t\t? 422\n\t\t\t\t\t\t: 400;\n\treturn apiError(error.code, error.message, status);\n}\n\nfunction toRoleLevel(value: number): RoleLevel | null {\n\tif (value === 10 || value === 20 || value === 30 || value === 40 || value === 50) {\n\t\treturn value;\n\t}\n\treturn null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPermission(value: string): value is Permission {\n\treturn Object.hasOwn(Permissions, value);\n}\n\nfunction authorizePrivatePluginRouteRequest(\n\trouteMeta: RouteMeta,\n\trequest: Request,\n\tuser?: UserInfo | null,\n\ttokenScopes?: string[],\n): Response | null {\n\tconst permission = routeMeta.permission ?? \"plugins:manage\";\n\tif (!isPermission(permission)) {\n\t\treturn apiError(\"INVALID_PLUGIN_ROUTE\", \"Plugin route declares an invalid permission\", 500);\n\t}\n\n\tlet permissionUser: { id: string; role: RoleLevel } | null | undefined;\n\tif (user) {\n\t\tconst role = toRoleLevel(user.role);\n\t\tif (role === null) {\n\t\t\treturn apiError(\"INVALID_USER\", \"Authenticated user has an invalid role\", 500);\n\t\t}\n\t\tpermissionUser = { id: user.id, role };\n\t} else {\n\t\tpermissionUser = user;\n\t}\n\n\tconst denied = requirePerm(permissionUser, permission);\n\tif (denied) return denied;\n\tconst scopeError = requireScope({ tokenScopes }, \"admin\");\n\tif (scopeError) return scopeError;\n\tif (!tokenScopes && request.headers.get(\"X-EmDash-Request\") !== \"1\") {\n\t\treturn apiError(\"CSRF_REJECTED\", \"Missing required header\", 403);\n\t}\n\treturn null;\n}\n\nexport interface PluginApiRequestContext {\n\truntime: EmDashRuntime;\n\tpluginId: string;\n\tpath: string;\n\trequest: Request;\n\tuser?: UserInfo | null;\n\ttokenScopes?: string[];\n\tinvalidateContentCache?: PluginContentCacheInvalidator;\n\teditorDispatch?: PluginEditorExtensionDispatch;\n}\n\n/** Dispatch a request through the production plugin-route policy boundary. */\nexport async function dispatchPluginApiRequest({\n\truntime,\n\tpluginId,\n\tpath,\n\trequest,\n\tuser,\n\ttokenScopes,\n\tinvalidateContentCache,\n\teditorDispatch,\n}: PluginApiRequestContext): Promise<Response> {\n\tconst method = request.method.toUpperCase();\n\tconst routeMeta = runtime.getPluginRouteMeta(pluginId, path);\n\tif (!routeMeta) return apiError(\"NOT_FOUND\", \"Plugin route not found\", 404);\n\n\tif (!routeMeta.public) {\n\t\tconst denied = authorizePrivatePluginRouteRequest(routeMeta, request, user, tokenScopes);\n\t\tif (denied) return denied;\n\t}\n\tif (routeMeta.methods && !routeMeta.methods.some((allowed) => allowed === method)) {\n\t\tconst response = apiError(\"METHOD_NOT_ALLOWED\", \"Method not allowed\", 405);\n\t\tresponse.headers.set(\"Allow\", routeMeta.methods.join(\", \"));\n\t\treturn response;\n\t}\n\n\tconst caller = routeMeta.public ? undefined : (user ?? undefined);\n\tconst result = await runtime.handlePluginApiRoute(\n\t\tpluginId,\n\t\tmethod,\n\t\tpath,\n\t\trequest,\n\t\tcaller,\n\t\tinvalidateContentCache,\n\t\teditorDispatch,\n\t);\n\tif (!result.success) {\n\t\tconst code = result.error?.code ?? \"PLUGIN_ERROR\";\n\t\tconst message =\n\t\t\tcode === \"INTERNAL_ERROR\"\n\t\t\t\t? \"Plugin route error\"\n\t\t\t\t: (result.error?.message ?? \"Plugin route error\");\n\t\tconst status = (result as { status?: number }).status ?? (code === \"NOT_FOUND\" ? 404 : 400);\n\t\tconst details =\n\t\t\tcode !== \"INTERNAL_ERROR\" && result.error && \"details\" in result.error\n\t\t\t\t? result.error.details\n\t\t\t\t: undefined;\n\t\treturn apiError(code, message, status, isRecord(details) ? details : undefined);\n\t}\n\n\tlet response: Response;\n\tif (routeMeta.response === \"raw\") {\n\t\ttry {\n\t\t\tresponse = pluginRouteResponseFromWire(\n\t\t\t\tawait pluginRouteResponseToWire(\n\t\t\t\t\tresult.data,\n\t\t\t\t\trouteMeta.public ? { publicRequestUrl: request.url } : { allowExternalLocation: true },\n\t\t\t\t),\n\t\t\t\tmethod,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tconsole.error(`[plugin:${pluginId}] Invalid raw route response:`, error);\n\t\t\treturn apiError(\"INVALID_PLUGIN_RESPONSE\", \"Plugin returned an invalid response\", 500);\n\t\t}\n\t} else {\n\t\tresponse = apiSuccess(result.data);\n\t}\n\tif (\n\t\tresponse.ok &&\n\t\trouteMeta.public &&\n\t\trouteMeta.cacheControl &&\n\t\t(method === \"GET\" || method === \"HEAD\")\n\t) {\n\t\tresponse.headers.set(\"Cache-Control\", routeMeta.cacheControl);\n\t} else {\n\t\tresponse.headers.set(\"Cache-Control\", \"private, no-store\");\n\t}\n\treturn response;\n}\n\nexport interface PluginEditorExtensionApiRequestContext {\n\truntime: EmDashRuntime;\n\tpluginId: string;\n\tkind: \"panel\" | \"action\";\n\textensionId: string;\n\tcollection: string;\n\tentryId: string;\n\trequest: Request;\n\tuser?: UserInfo | null;\n\ttokenScopes?: string[];\n\tinvalidateContentCache?: PluginContentCacheInvalidator;\n}\n\nconst EDITOR_EXTENSION_REQUEST_MAX_BYTES = 256 * 1024;\n\n/** Dispatch a saved-entry extension through ownership, route, and isolate policy. */\nexport async function dispatchPluginEditorExtensionApiRequest({\n\truntime,\n\tpluginId,\n\tkind,\n\textensionId,\n\tcollection,\n\tentryId,\n\trequest,\n\tuser,\n\ttokenScopes,\n\tinvalidateContentCache,\n}: PluginEditorExtensionApiRequestContext): Promise<Response> {\n\tconst definition = runtime.getPluginEditorExtension(pluginId, kind, extensionId, collection);\n\tif (!definition) return apiError(\"NOT_FOUND\", \"Plugin editor extension not found\", 404);\n\n\tconst routeMeta = runtime.getPluginRouteMeta(pluginId, definition.extension.route);\n\tif (!routeMeta || routeMeta.public) {\n\t\treturn apiError(\n\t\t\t\"INVALID_PLUGIN_EDITOR_EXTENSION\",\n\t\t\t\"Plugin editor extension must reference a private route\",\n\t\t\t500,\n\t\t);\n\t}\n\tconst denied = authorizePrivatePluginRouteRequest(routeMeta, request, user, tokenScopes);\n\tif (denied) return denied;\n\n\tconst requestedLocale = new URL(request.url).searchParams.get(\"locale\") || undefined;\n\tconst contentResult = await runtime.handleContentGet(collection, entryId, requestedLocale);\n\tif (!contentResult.success) {\n\t\treturn contentResult.error?.code === \"NOT_FOUND\"\n\t\t\t? apiError(\"NOT_FOUND\", \"Content item not found\", 404)\n\t\t\t: apiError(\"CONTENT_GET_ERROR\", \"Failed to load content item\", 500);\n\t}\n\tconst contentData = contentResult.data;\n\tconst item =\n\t\ttypeof contentData === \"object\" && contentData !== null && \"item\" in contentData\n\t\t\t? contentData.item\n\t\t\t: null;\n\tif (typeof item !== \"object\" || item === null) {\n\t\treturn apiError(\"CONTENT_GET_ERROR\", \"Failed to load content item\", 500);\n\t}\n\tconst authorId = \"authorId\" in item && typeof item.authorId === \"string\" ? item.authorId : \"\";\n\tlet ownershipUser: { id: string; role: RoleLevel } | null | undefined =\n\t\tuser == null ? user : undefined;\n\tif (user) {\n\t\tconst ownerRole = toRoleLevel(user.role);\n\t\tif (ownerRole === null) {\n\t\t\treturn apiError(\"INVALID_USER\", \"Authenticated user has an invalid role\", 500);\n\t\t}\n\t\townershipUser = { id: user.id, role: ownerRole };\n\t}\n\tconst ownershipDenied = requireOwnerPerm(\n\t\townershipUser,\n\t\tauthorId,\n\t\t\"content:edit_own\",\n\t\t\"content:edit_any\",\n\t);\n\tif (ownershipDenied) return ownershipDenied;\n\n\tconst canonicalId = \"id\" in item && typeof item.id === \"string\" ? item.id : null;\n\tconst canonicalLocale = \"locale\" in item && typeof item.locale === \"string\" ? item.locale : null;\n\tconst version = \"version\" in item && typeof item.version === \"number\" ? item.version : null;\n\tconst baseRevision =\n\t\ttypeof contentData === \"object\" &&\n\t\tcontentData !== null &&\n\t\t\"_rev\" in contentData &&\n\t\ttypeof contentData._rev === \"string\"\n\t\t\t? contentData._rev\n\t\t\t: null;\n\tif (!canonicalId || version === null) {\n\t\treturn apiError(\"CONTENT_GET_ERROR\", \"Content item has invalid identity\", 500);\n\t}\n\n\tlet input: Record<string, unknown>;\n\tlet editorBody: unknown;\n\ttry {\n\t\teditorBody = await parseDeclaredPluginRouteInput(request, {\n\t\t\tbody: \"json\",\n\t\t\tmaxBytes: EDITOR_EXTENSION_REQUEST_MAX_BYTES,\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof PluginRouteRequestError) {\n\t\t\treturn apiError(\n\t\t\t\terror.status === 413 ? \"EDITOR_DRAFT_TOO_LARGE\" : \"INVALID_REQUEST\",\n\t\t\t\terror.status === 413\n\t\t\t\t\t? \"Editor interaction exceeds the size limit\"\n\t\t\t\t\t: \"Invalid editor interaction\",\n\t\t\t\terror.status,\n\t\t\t);\n\t\t}\n\t\treturn apiError(\"INVALID_REQUEST\", \"Editor interaction could not be read\", 400);\n\t}\n\tif (kind === \"panel\") {\n\t\tif (!isRecord(editorBody)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Editor panel interaction must be an object\", 400);\n\t\t}\n\t\tinput = editorBody;\n\t\tconst validation = validateContentEditorPanelInteraction(input);\n\t\tif (!validation.valid) {\n\t\t\treturn apiError(\"INVALID_PLUGIN_UI_CONTEXT\", \"Invalid editor panel interaction\", 400);\n\t\t}\n\t} else {\n\t\tif (!isRecord(editorBody)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid editor action interaction\", 400);\n\t\t}\n\t\tinput = {\n\t\t\ttype: \"editor_action\",\n\t\t\t...(Object.hasOwn(editorBody, \"draft\") ? { draft: editorBody.draft } : {}),\n\t\t};\n\t}\n\n\tlet validatedDraft: ValidatedEditorDraftRequest | null = null;\n\tif (input.draft !== undefined) {\n\t\tif (!baseRevision) {\n\t\t\treturn apiError(\"EDITOR_DRAFT_INVALID\", \"Content item has no draft revision identity\", 409);\n\t\t}\n\t\tconst collectionSchema = await runtime.getPluginEditorDraftSchema(collection);\n\t\tif (!collectionSchema) return apiError(\"NOT_FOUND\", \"Collection not found\", 404);\n\t\tconst draft = validateEditorDraftRequest({\n\t\t\trequest: input.draft,\n\t\t\tcollection: collectionSchema,\n\t\t\tentry: { id: canonicalId, locale: canonicalLocale, revision: baseRevision },\n\t\t\treadSelector: definition.extension.draft?.read,\n\t\t\tpatchSelector: definition.extension.draft?.patch,\n\t\t\tcanRead: definition.capabilities.includes(\"admin.editor-draft:read\"),\n\t\t\tcanPatch: definition.capabilities.includes(\"admin.editor-draft:patch\"),\n\t\t});\n\t\tif (\"code\" in draft) {\n\t\t\tconsole.warn(\n\t\t\t\t`[plugin:${pluginId}] Editor draft ${kind}/${extensionId} rejected: ${draft.code}`,\n\t\t\t);\n\t\t\treturn editorDraftErrorResponse(draft);\n\t\t}\n\t\tvalidatedDraft = draft;\n\t\tinput = { ...input, draft: draft.snapshot };\n\t}\n\n\tconst headers = new Headers(request.headers);\n\theaders.delete(\"content-length\");\n\theaders.delete(\"content-encoding\");\n\theaders.set(\"Content-Type\", \"application/json\");\n\tconst pluginRequest = new Request(request.url, {\n\t\tmethod: \"POST\",\n\t\theaders,\n\t\tbody: JSON.stringify(input),\n\t});\n\tconst locale = resolveLocale(request);\n\tconst response = await dispatchPluginApiRequest({\n\t\truntime,\n\t\tpluginId,\n\t\tpath: definition.extension.route,\n\t\trequest: pluginRequest,\n\t\tuser,\n\t\ttokenScopes,\n\t\tinvalidateContentCache,\n\t\teditorDispatch: {\n\t\t\tkind,\n\t\t\tpolicy: definition.policy,\n\t\t\tui: {\n\t\t\t\tsurface: kind === \"panel\" ? \"content-editor-panel\" : \"content-editor-action\",\n\t\t\t\tlocale,\n\t\t\t\tdirection: getLocaleDir(locale),\n\t\t\t\tcontentLocale: canonicalLocale ?? undefined,\n\t\t\t\textensionId,\n\t\t\t\tentry: {\n\t\t\t\t\tcollection,\n\t\t\t\t\tid: canonicalId,\n\t\t\t\t\tlocale: canonicalLocale,\n\t\t\t\t\tversion,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t});\n\tif (!response.ok) return response;\n\tconst envelope: unknown = await response.clone().json();\n\tif (!isRecord(envelope) || !isRecord(envelope.data)) {\n\t\treturn apiError(\"INVALID_PLUGIN_RESPONSE\", \"Plugin returned an invalid response\", 502);\n\t}\n\tconst data = envelope.data;\n\tif (data.patch === undefined && !validatedDraft) return response;\n\tif (data.patch !== undefined && !validatedDraft) {\n\t\treturn apiError(\n\t\t\t\"EDITOR_DRAFT_INVALID\",\n\t\t\t\"Plugin returned an editor draft patch without a draft invocation\",\n\t\t\t400,\n\t\t);\n\t}\n\tif (data.patch !== undefined) {\n\t\tconst collectionSchema = await runtime.getPluginEditorDraftSchema(collection);\n\t\tif (!collectionSchema) return apiError(\"NOT_FOUND\", \"Collection not found\", 404);\n\t\tconst patch = validateEditorDraftPatch({\n\t\t\tpatch: data.patch,\n\t\t\tcollection: collectionSchema,\n\t\t\tallowedFields: validatedDraft?.patchFields ?? new Set(),\n\t\t});\n\t\tif (\"code\" in patch) {\n\t\t\tconsole.warn(\n\t\t\t\t`[plugin:${pluginId}] Editor draft ${kind}/${extensionId} rejected: ${patch.code}`,\n\t\t\t);\n\t\t\treturn editorDraftErrorResponse(patch);\n\t\t}\n\t\tdata.patch = patch;\n\t}\n\tconst finalResponse = apiSuccess({ ...data, editorInvocation: validatedDraft?.receipt });\n\tfinalResponse.headers.set(\"Cache-Control\", \"private, no-store\");\n\treturn finalResponse;\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as MIGRATION_NAMES } from "./runner-
|
|
2
|
-
import { n as VERSION } from "./version-
|
|
1
|
+
import { t as MIGRATION_NAMES } from "./runner-Bkkfk4O8.mjs";
|
|
2
|
+
import { n as VERSION } from "./version-Bu6Nlbb5.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/migrations/identity.ts
|
|
5
5
|
function encodeFingerprintInput(emdashVersion, names) {
|
|
@@ -32,4 +32,4 @@ function getCoreMigrationIdentity() {
|
|
|
32
32
|
|
|
33
33
|
//#endregion
|
|
34
34
|
export { fingerprintMigrationSet as n, getCoreMigrationIdentity as r, createCoreMigrationIdentity as t };
|
|
35
|
-
//# sourceMappingURL=identity-
|
|
35
|
+
//# sourceMappingURL=identity-CPRRSovU.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity-
|
|
1
|
+
{"version":3,"file":"identity-CPRRSovU.mjs","names":[],"sources":["../src/migrations/identity.ts"],"sourcesContent":["import { MIGRATION_NAMES } from \"../database/migrations/runner.js\";\nimport { VERSION } from \"../version.js\";\n\nexport interface CoreMigrationIdentity {\n\temdashVersion: string;\n\tnames: readonly string[];\n\tfingerprint: string;\n}\n\nfunction encodeFingerprintInput(emdashVersion: string, names: readonly string[]): ArrayBuffer {\n\tconst encoded = new TextEncoder().encode(JSON.stringify({ emdashVersion, names }));\n\tconst buffer = new ArrayBuffer(encoded.byteLength);\n\tnew Uint8Array(buffer).set(encoded);\n\treturn buffer;\n}\n\nfunction encodeHex(bytes: Uint8Array): string {\n\treturn Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport async function fingerprintMigrationSet(\n\temdashVersion: string,\n\tnames: readonly string[],\n): Promise<string> {\n\tconst digest = await crypto.subtle.digest(\n\t\t\"SHA-256\",\n\t\tencodeFingerprintInput(emdashVersion, names),\n\t);\n\treturn encodeHex(new Uint8Array(digest));\n}\n\nexport async function createCoreMigrationIdentity(\n\temdashVersion: string,\n\tnames: readonly string[],\n): Promise<CoreMigrationIdentity> {\n\tconst nameSnapshot = Object.freeze([...names]);\n\treturn Object.freeze({\n\t\temdashVersion,\n\t\tnames: nameSnapshot,\n\t\tfingerprint: await fingerprintMigrationSet(emdashVersion, nameSnapshot),\n\t});\n}\n\nexport function getCoreMigrationIdentity(): Promise<CoreMigrationIdentity> {\n\treturn createCoreMigrationIdentity(VERSION, MIGRATION_NAMES);\n}\n"],"mappings":";;;;AASA,SAAS,uBAAuB,eAAuB,OAAuC;CAC7F,MAAM,UAAU,IAAI,aAAa,CAAC,OAAO,KAAK,UAAU;EAAE;EAAe;EAAO,CAAC,CAAC;CAClF,MAAM,SAAS,IAAI,YAAY,QAAQ,WAAW;AAClD,KAAI,WAAW,OAAO,CAAC,IAAI,QAAQ;AACnC,QAAO;;AAGR,SAAS,UAAU,OAA2B;AAC7C,QAAO,MAAM,KAAK,QAAQ,SAAS,KAAK,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG;;AAGhF,eAAsB,wBACrB,eACA,OACkB;CAClB,MAAM,SAAS,MAAM,OAAO,OAAO,OAClC,WACA,uBAAuB,eAAe,MAAM,CAC5C;AACD,QAAO,UAAU,IAAI,WAAW,OAAO,CAAC;;AAGzC,eAAsB,4BACrB,eACA,OACiC;CACjC,MAAM,eAAe,OAAO,OAAO,CAAC,GAAG,MAAM,CAAC;AAC9C,QAAO,OAAO,OAAO;EACpB;EACA,OAAO;EACP,aAAa,MAAM,wBAAwB,eAAe,aAAa;EACvE,CAAC;;AAGH,SAAgB,2BAA2D;AAC1E,QAAO,4BAA4B,SAAS,gBAAgB"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as OptionsRepository } from "./options-DhrI7eMv.mjs";
|
|
2
|
-
import { d as
|
|
3
|
-
import { n as slugify } from "./slugify-
|
|
4
|
-
import { c as invalidateSiteSettingsCache } from "./settings-
|
|
2
|
+
import { d as invalidateCommentObjectCache, f as invalidateMenuObjectCache } from "./object-cache-DmKr09La.mjs";
|
|
3
|
+
import { n as slugify } from "./slugify-BDEG9pLk.mjs";
|
|
4
|
+
import { c as invalidateSiteSettingsCache } from "./settings-D932YP2-.mjs";
|
|
5
5
|
import { a as ssrfSafeFetch, r as resolveAndValidateExternalUrl, s as validateExternalUrl } from "./ssrf-BcYjyM4M.mjs";
|
|
6
|
-
import { a as getFilenameFromUrl, c as isInternalMetaKey, d as isTypeCompatible, f as mapMetaKeyToField, g as relativizeContentLinks, h as normalizeUrl$1, i as checkSchemaCompatibility, l as isInternalPostType, m as mapWpStatus, n as FEATURED_IMAGE_FIELD, o as guessMimeType, p as mapPostTypeToCollection, r as buildAttachmentMap, s as inferMetaType, t as BASE_REQUIRED_FIELDS, u as isPluginBookkeepingMeta,
|
|
6
|
+
import { a as getFilenameFromUrl, c as isInternalMetaKey, d as isTypeCompatible, f as mapMetaKeyToField, g as relativizeContentLinks, h as normalizeUrl$1, i as checkSchemaCompatibility, l as isInternalPostType, m as mapWpStatus, n as FEATURED_IMAGE_FIELD, o as guessMimeType, p as mapPostTypeToCollection, r as buildAttachmentMap, s as inferMetaType, t as BASE_REQUIRED_FIELDS, u as isPluginBookkeepingMeta, y as sanitizeFieldSlug } from "./utils-D5uOi6WS.mjs";
|
|
7
7
|
import { ulid } from "ulidx";
|
|
8
8
|
import sax from "sax";
|
|
9
9
|
import { gutenbergToPortableText } from "@emdash-cms/gutenberg-to-portable-text";
|
|
@@ -2123,4 +2123,4 @@ registerSource(wxrSource);
|
|
|
2123
2123
|
|
|
2124
2124
|
//#endregion
|
|
2125
2125
|
export { parseWxr as C, importMenusFromPlugin as S, registerSource as _, fetchPluginOptions as a, importCommentsFromPlugin as b, parseWxrDate as c, clearSources as d, getAllSources as f, probeUrl as g, getUrlSources as h, fetchPluginMenus as i, wxrSource as l, getSource as m, fetchPluginCommentsPage as n, fetchPluginTaxonomies as o, getFileSources as p, fetchPluginContentPage as r, wordpressRestSource as s, fetchPluginComments as t, SiteChallengeError as u, importSiteSettings as v, parseWxrString as w, importReusableBlocksAsSections as x, parseSiteSettingsFromPlugin as y };
|
|
2126
|
-
//# sourceMappingURL=import-
|
|
2126
|
+
//# sourceMappingURL=import-yVbfPyfd.mjs.map
|