emdash 0.40.1 → 0.41.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/action-token-CbKDcPJi.mjs +26 -0
- package/dist/action-token-CbKDcPJi.mjs.map +1 -0
- package/dist/activation-PtniBLt9.mjs +382 -0
- package/dist/activation-PtniBLt9.mjs.map +1 -0
- package/dist/adapters-C_Tf5x90.d.mts +171 -0
- package/dist/adapters-C_Tf5x90.d.mts.map +1 -0
- package/dist/allowed-origins-U1z4TdEZ.mjs +116 -0
- package/dist/allowed-origins-U1z4TdEZ.mjs.map +1 -0
- package/dist/api/route-utils.d.mts +4 -4
- package/dist/api/route-utils.mjs +46 -45
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +10 -10
- package/dist/api-CXwQkV_m.mjs +5122 -0
- package/dist/api-CXwQkV_m.mjs.map +1 -0
- package/dist/api-tokens-89WlohEN.mjs +166 -0
- package/dist/api-tokens-89WlohEN.mjs.map +1 -0
- package/dist/apply-Do3KNnUk.mjs +1659 -0
- package/dist/apply-Do3KNnUk.mjs.map +1 -0
- package/dist/approvals-CAX9Yw33.mjs +460 -0
- package/dist/approvals-CAX9Yw33.mjs.map +1 -0
- package/dist/artifact-fetch-B9W4CEST.mjs +659 -0
- package/dist/artifact-fetch-B9W4CEST.mjs.map +1 -0
- package/dist/astro/index.d.mts +14 -14
- package/dist/astro/index.mjs +20 -24
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +12 -12
- package/dist/astro/middleware/auth.mjs +10 -10
- package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
- package/dist/astro/middleware/redirect.mjs +7 -7
- package/dist/astro/middleware/request-context.mjs +3 -3
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +12 -12
- package/dist/astro/middleware.mjs +109 -106
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +14 -14
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +14 -14
- 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 +7 -7
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +17 -17
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +17 -17
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +17 -17
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +23 -23
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +23 -23
- package/dist/astro/routes/api/admin/bylines/index.mjs +23 -23
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -18
- package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/bulk.mjs +17 -17
- package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/index.mjs +17 -17
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
- package/dist/astro/routes/api/admin/media-usage/activation.mjs +20 -20
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +22 -22
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +22 -22
- package/dist/astro/routes/api/admin/media-usage/progress.mjs +25 -25
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +31 -31
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +22 -22
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +22 -22
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +8 -8
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +72 -68
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +7 -7
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +71 -67
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +72 -68
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +82 -78
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +72 -68
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +5 -5
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +71 -67
- 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 +81 -77
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +71 -67
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +72 -68
- 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 +83 -79
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +74 -70
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +7 -7
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +72 -68
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +71 -67
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +71 -67
- 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 +5 -5
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +71 -67
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/transfer/_...path_.mjs +4 -4
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +40 -40
- package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +40 -40
- package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/capabilities.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +43 -43
- package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +43 -43
- package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +43 -43
- package/dist/astro/routes/api/admin/transfer/exports/index.mjs +44 -44
- package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +44 -44
- package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +44 -44
- package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +44 -44
- package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +42 -42
- package/dist/astro/routes/api/admin/transfer/imports/index.mjs +44 -44
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +5 -5
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +15 -15
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
- package/dist/astro/routes/api/admin/users/index.mjs +14 -14
- package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
- package/dist/astro/routes/api/auth/invite/accept.mjs +4 -4
- package/dist/astro/routes/api/auth/invite/complete.mjs +18 -18
- package/dist/astro/routes/api/auth/invite/index.mjs +16 -16
- package/dist/astro/routes/api/auth/invite/register-options.mjs +17 -17
- package/dist/astro/routes/api/auth/logout.mjs +5 -5
- package/dist/astro/routes/api/auth/magic-link/send.mjs +18 -18
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +14 -14
- package/dist/astro/routes/api/auth/me.mjs +15 -15
- package/dist/astro/routes/api/auth/mode.mjs +5 -5
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +14 -14
- package/dist/astro/routes/api/auth/passkey/index.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/options.mjs +19 -19
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +17 -17
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +18 -18
- package/dist/astro/routes/api/auth/passkey/verify.mjs +18 -18
- package/dist/astro/routes/api/auth/signup/complete.mjs +18 -18
- package/dist/astro/routes/api/auth/signup/request.mjs +17 -17
- package/dist/astro/routes/api/auth/signup/verify.mjs +4 -4
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -18
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -17
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +17 -17
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +11 -11
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +31 -31
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +17 -17
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +1 -2
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +42 -53
- 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 -29
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +17 -17
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +25 -24
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +17 -17
- package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +18 -18
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/index.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/trash.mjs +15 -15
- package/dist/astro/routes/api/dashboard.mjs +10 -9
- package/dist/astro/routes/api/dashboard.mjs.map +1 -1
- package/dist/astro/routes/api/dev/emails.mjs +5 -5
- package/dist/astro/routes/api/health.mjs +6 -6
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +23 -23
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -13
- package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
- package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -12
- package/dist/astro/routes/api/import/wordpress/media.mjs +19 -19
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +18 -18
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -13
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +28 -28
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +23 -23
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -13
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +34 -34
- package/dist/astro/routes/api/manifest.mjs +6 -6
- package/dist/astro/routes/api/mcp.mjs +91 -91
- package/dist/astro/routes/api/media/_id_/confirm.mjs +19 -19
- package/dist/astro/routes/api/media/_id_/replace.mjs +16 -16
- package/dist/astro/routes/api/media/_id_/upload.mjs +9 -9
- package/dist/astro/routes/api/media/_id_/usage.mjs +33 -33
- package/dist/astro/routes/api/media/_id_.mjs +31 -31
- package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +6 -6
- package/dist/astro/routes/api/media/file/_...key_.mjs +9 -9
- package/dist/astro/routes/api/media/folders/_id_.mjs +16 -16
- package/dist/astro/routes/api/media/folders/index.mjs +16 -16
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +5 -5
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +5 -5
- package/dist/astro/routes/api/media/providers/index.mjs +5 -5
- package/dist/astro/routes/api/media/upload-url.mjs +18 -18
- package/dist/astro/routes/api/media.mjs +35 -35
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -17
- package/dist/astro/routes/api/menus/_name_/items.mjs +17 -17
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -17
- package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -17
- package/dist/astro/routes/api/menus/_name_.mjs +17 -17
- package/dist/astro/routes/api/menus/index.mjs +17 -17
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.d.mts +2 -1
- package/dist/astro/routes/api/oauth/device/authorize.d.mts.map +1 -1
- package/dist/astro/routes/api/oauth/device/authorize.mjs +23 -9
- package/dist/astro/routes/api/oauth/device/authorize.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/device/code.mjs +11 -11
- package/dist/astro/routes/api/oauth/device/token.mjs +10 -10
- package/dist/astro/routes/api/oauth/register.mjs +5 -5
- package/dist/astro/routes/api/oauth/token/refresh.mjs +8 -8
- package/dist/astro/routes/api/oauth/token/revoke.mjs +8 -8
- package/dist/astro/routes/api/oauth/token.mjs +8 -8
- package/dist/astro/routes/api/openapi.json.mjs +20 -20
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +11 -11
- package/dist/astro/routes/api/redirects/404s/index.mjs +19 -19
- package/dist/astro/routes/api/redirects/404s/summary.mjs +19 -19
- package/dist/astro/routes/api/redirects/_id_.mjs +19 -19
- package/dist/astro/routes/api/redirects/index.mjs +19 -19
- package/dist/astro/routes/api/relations/_id_/index.mjs +34 -29
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +36 -31
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +5 -5
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
- package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +71 -67
- 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 +71 -67
- 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 +71 -67
- package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +73 -69
- 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 +71 -67
- 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 +71 -67
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +71 -67
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +71 -67
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -67
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +16 -16
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +71 -67
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +71 -67
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +19 -19
- package/dist/astro/routes/api/search/index.mjs +18 -18
- package/dist/astro/routes/api/search/rebuild.mjs +19 -19
- package/dist/astro/routes/api/search/stats.mjs +9 -9
- package/dist/astro/routes/api/search/suggest.mjs +18 -18
- package/dist/astro/routes/api/sections/_slug_.mjs +18 -18
- package/dist/astro/routes/api/sections/index.mjs +18 -18
- 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/email.mjs +6 -6
- package/dist/astro/routes/api/settings.mjs +21 -21
- package/dist/astro/routes/api/setup/admin-verify.mjs +19 -19
- package/dist/astro/routes/api/setup/admin.mjs +18 -18
- package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -39
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
- package/dist/astro/routes/api/setup/index.mjs +50 -44
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +6 -6
- package/dist/astro/routes/api/snapshot.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -23
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -23
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -23
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -23
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -22
- package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -23
- package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +36 -35
- package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +23 -23
- package/dist/astro/routes/api/themes/preview.mjs +6 -6
- package/dist/astro/routes/api/typegen.mjs +8 -8
- package/dist/astro/routes/api/visual-editing/action-token.mjs +6 -6
- package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +19 -19
- package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +4 -4
- package/dist/astro/routes/api/well-known/auth.mjs +1 -1
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +16 -16
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +19 -19
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +19 -19
- package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -9
- package/dist/astro/routes/api/widget-areas/index.mjs +19 -19
- package/dist/astro/routes/api/widget-components.mjs +5 -5
- package/dist/astro/routes/robots.txt.mjs +6 -6
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
- package/dist/astro/routes/sitemap.xml.mjs +7 -7
- package/dist/astro/types.d.mts +24 -18
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/audit-CrgmE9LE.mjs +127 -0
- package/dist/audit-CrgmE9LE.mjs.map +1 -0
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/authoritative-records-C2YzIdbu.mjs +5172 -0
- package/dist/authoritative-records-C2YzIdbu.mjs.map +1 -0
- package/dist/authorize-WgdKF8QY.mjs +49 -0
- package/dist/authorize-WgdKF8QY.mjs.map +1 -0
- package/dist/backup-Ck8_lMO3.mjs +246 -0
- package/dist/backup-Ck8_lMO3.mjs.map +1 -0
- package/dist/block-types-BQ90asVI.mjs +132 -0
- package/dist/block-types-BQ90asVI.mjs.map +1 -0
- package/dist/block-values-ACFqgB1D.mjs +175 -0
- package/dist/block-values-ACFqgB1D.mjs.map +1 -0
- package/dist/bundle-Db1iNMv_.mjs +667 -0
- package/dist/bundle-Db1iNMv_.mjs.map +1 -0
- package/dist/byline-BayaYGoj.mjs +909 -0
- package/dist/byline-BayaYGoj.mjs.map +1 -0
- package/dist/byline-fields-B8HH-35f.mjs +254 -0
- package/dist/byline-fields-B8HH-35f.mjs.map +1 -0
- package/dist/byline-fields-hMPjf6Eu.mjs +123 -0
- package/dist/byline-fields-hMPjf6Eu.mjs.map +1 -0
- package/dist/byline-registry-B_EK_TQf.mjs +406 -0
- package/dist/byline-registry-B_EK_TQf.mjs.map +1 -0
- package/dist/bylines-DFAaFXWi.mjs +214 -0
- package/dist/bylines-DFAaFXWi.mjs.map +1 -0
- package/dist/bylines-DkIxUxmr.mjs +232 -0
- package/dist/bylines-DkIxUxmr.mjs.map +1 -0
- package/dist/cache-DkvhQ8XE.mjs +108 -0
- package/dist/cache-DkvhQ8XE.mjs.map +1 -0
- package/dist/canonical-CcSuuTlH.mjs +174 -0
- package/dist/canonical-CcSuuTlH.mjs.map +1 -0
- package/dist/capture-triggers-DJEoOTOq.mjs +362 -0
- package/dist/capture-triggers-DJEoOTOq.mjs.map +1 -0
- package/dist/challenge-store-CvBl81AQ.mjs +51 -0
- package/dist/challenge-store-CvBl81AQ.mjs.map +1 -0
- package/dist/checksum-CClweQzI.mjs +162 -0
- package/dist/checksum-CClweQzI.mjs.map +1 -0
- package/dist/chrome-tags-D5caJwwp.mjs +24 -0
- package/dist/chrome-tags-D5caJwwp.mjs.map +1 -0
- package/dist/chunks-DwBaj8aT.mjs +25 -0
- package/dist/chunks-DwBaj8aT.mjs.map +1 -0
- package/dist/cli/index.mjs +374 -761
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +32 -32
- package/dist/client/index.mjs +2 -2
- package/dist/collection-deletion-CLCdXsnV.mjs +436 -0
- package/dist/collection-deletion-CLCdXsnV.mjs.map +1 -0
- package/dist/collection-deletion-processor-hNw8x01F.mjs +217 -0
- package/dist/collection-deletion-processor-hNw8x01F.mjs.map +1 -0
- package/dist/collection-slugs-cache-CUuiduLq.mjs +85 -0
- package/dist/collection-slugs-cache-CUuiduLq.mjs.map +1 -0
- package/dist/comment-D2uvL63j.mjs +313 -0
- package/dist/comment-D2uvL63j.mjs.map +1 -0
- package/dist/comment-reaction-DevUuzg4.mjs +85 -0
- package/dist/comment-reaction-DevUuzg4.mjs.map +1 -0
- package/dist/comments-Cq0s7_hO.mjs +195 -0
- package/dist/comments-Cq0s7_hO.mjs.map +1 -0
- package/dist/comments-M4EDYAHw.mjs +99 -0
- package/dist/comments-M4EDYAHw.mjs.map +1 -0
- package/dist/components-CuIGwXMs.mjs +108 -0
- package/dist/components-CuIGwXMs.mjs.map +1 -0
- package/dist/config-52Ea5IWt.d.mts +39 -0
- package/dist/config-52Ea5IWt.d.mts.map +1 -0
- package/dist/config-CCz3xOLc.mjs +242 -0
- package/dist/config-CCz3xOLc.mjs.map +1 -0
- package/dist/config-D3d5Qudq.d.mts +6669 -0
- package/dist/config-D3d5Qudq.d.mts.map +1 -0
- package/dist/content-CbnufDsM.mjs +2018 -0
- package/dist/content-CbnufDsM.mjs.map +1 -0
- package/dist/content-list-query-D_7B1FE5.d.mts +26 -0
- package/dist/content-list-query-D_7B1FE5.d.mts.map +1 -0
- package/dist/content-policy-CYu6K1KB.mjs +46 -0
- package/dist/content-policy-CYu6K1KB.mjs.map +1 -0
- package/dist/content-repair-DlDUgFGp.mjs +442 -0
- package/dist/content-repair-DlDUgFGp.mjs.map +1 -0
- package/dist/context-CGQLA1-a.mjs +1922 -0
- package/dist/context-CGQLA1-a.mjs.map +1 -0
- package/dist/cron-c4D5C5Fx.mjs +284 -0
- package/dist/cron-c4D5C5Fx.mjs.map +1 -0
- package/dist/dashboard-CBq9kmOn.mjs +151 -0
- package/dist/dashboard-CBq9kmOn.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +1 -1
- package/dist/db/libsql-migrations.d.mts +1 -1
- package/dist/db/libsql-migrations.mjs +4 -4
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres-migrations.d.mts +1 -1
- package/dist/db/postgres-migrations.mjs +4 -4
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite-migrations.d.mts +1 -1
- package/dist/db/sqlite-migrations.mjs +4 -4
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.mjs +1 -1
- package/dist/default-DPsys51U.mjs +81 -0
- package/dist/default-DPsys51U.mjs.map +1 -0
- package/dist/deferred-tasks-CZ7rzBdo.d.mts +9 -0
- package/dist/deferred-tasks-CZ7rzBdo.d.mts.map +1 -0
- package/dist/dev-typegen-HRxwLRcT.mjs +29 -0
- package/dist/dev-typegen-HRxwLRcT.mjs.map +1 -0
- package/dist/device-flow-OcSqE9uY.mjs +521 -0
- package/dist/device-flow-OcSqE9uY.mjs.map +1 -0
- package/dist/digest-DVZ--cE9.mjs +194 -0
- package/dist/digest-DVZ--cE9.mjs.map +1 -0
- package/dist/direct-executor-DyjAqkpT.mjs +104 -0
- package/dist/direct-executor-DyjAqkpT.mjs.map +1 -0
- package/dist/dist-FPR93_xf.mjs +810 -0
- package/dist/dist-FPR93_xf.mjs.map +1 -0
- package/dist/email-console-DyQIgEnz.mjs +50 -0
- package/dist/email-console-DyQIgEnz.mjs.map +1 -0
- package/dist/email-locale-BYb16rVd.mjs +25 -0
- package/dist/email-locale-BYb16rVd.mjs.map +1 -0
- package/dist/emdash-runtime-CrzxJFmF.mjs +4214 -0
- package/dist/emdash-runtime-CrzxJFmF.mjs.map +1 -0
- package/dist/enrich-DBtCncE2.mjs +194 -0
- package/dist/enrich-DBtCncE2.mjs.map +1 -0
- package/dist/entry-lock-BN5y4YbO.d.mts +4481 -0
- package/dist/entry-lock-BN5y4YbO.d.mts.map +1 -0
- package/dist/entry-lock-BaRBHCsH.mjs +1173 -0
- package/dist/entry-lock-BaRBHCsH.mjs.map +1 -0
- package/dist/entry-lock-C6NcnZPV.mjs +163 -0
- package/dist/entry-lock-C6NcnZPV.mjs.map +1 -0
- package/dist/entry-locks-BTyQLdbC.mjs +167 -0
- package/dist/entry-locks-BTyQLdbC.mjs.map +1 -0
- package/dist/error-BfsNNrIE.mjs +90 -0
- package/dist/error-BfsNNrIE.mjs.map +1 -0
- package/dist/errors-BN1QAnEY.mjs +460 -0
- package/dist/errors-BN1QAnEY.mjs.map +1 -0
- package/dist/errors-Bt3goF8I.mjs +120 -0
- package/dist/errors-Bt3goF8I.mjs.map +1 -0
- package/dist/escape-BveidMa2.mjs +9 -0
- package/dist/escape-BveidMa2.mjs.map +1 -0
- package/dist/fence-Bb_IbCxI.mjs +162 -0
- package/dist/fence-Bb_IbCxI.mjs.map +1 -0
- package/dist/field-defs-cache-CsZctvbu.mjs +77 -0
- package/dist/field-defs-cache-CsZctvbu.mjs.map +1 -0
- package/dist/field-map-6m9rF49t.mjs +83 -0
- package/dist/field-map-6m9rF49t.mjs.map +1 -0
- package/dist/focal-point-CZ3d1wK5.mjs +23 -0
- package/dist/focal-point-CZ3d1wK5.mjs.map +1 -0
- package/dist/fts-manager-CCaZTp8y.mjs +443 -0
- package/dist/fts-manager-CCaZTp8y.mjs.map +1 -0
- package/dist/gc-xowRjczI.mjs +75 -0
- package/dist/gc-xowRjczI.mjs.map +1 -0
- package/dist/hash-COVK27Pc.mjs +37 -0
- package/dist/hash-COVK27Pc.mjs.map +1 -0
- package/dist/hook-result-CYSk0XFe.d.mts +31 -0
- package/dist/hook-result-CYSk0XFe.d.mts.map +1 -0
- package/dist/hreflang-CChPV7jx.mjs +105 -0
- package/dist/hreflang-CChPV7jx.mjs.map +1 -0
- package/dist/hreflang-DRslq3QI.d.mts +50 -0
- package/dist/hreflang-DRslq3QI.d.mts.map +1 -0
- package/dist/http-route-dispatch-CAdp2onn.mjs +339 -0
- package/dist/http-route-dispatch-CAdp2onn.mjs.map +1 -0
- package/dist/identity-NVTOOQyq.mjs +35 -0
- package/dist/identity-NVTOOQyq.mjs.map +1 -0
- package/dist/import-wpSO2N0x.mjs +2020 -0
- package/dist/import-wpSO2N0x.mjs.map +1 -0
- package/dist/index-CDs2wq4X.d.mts +623 -0
- package/dist/index-CDs2wq4X.d.mts.map +1 -0
- package/dist/index.d.mts +24 -24
- package/dist/index.mjs +103 -101
- package/dist/install-finalization-D9R9R-W8.mjs +58 -0
- package/dist/install-finalization-D9R9R-W8.mjs.map +1 -0
- package/dist/keys-Bck6LBfF.mjs +61 -0
- package/dist/keys-Bck6LBfF.mjs.map +1 -0
- package/dist/kinds-CYmRESWj.mjs +974 -0
- package/dist/kinds-CYmRESWj.mjs.map +1 -0
- package/dist/lifecycle-C815ZQfV.mjs +25 -0
- package/dist/lifecycle-C815ZQfV.mjs.map +1 -0
- package/dist/load-D99axixL.mjs +28 -0
- package/dist/load-D99axixL.mjs.map +1 -0
- package/dist/loader-CrRPfkHS.mjs +1197 -0
- package/dist/loader-CrRPfkHS.mjs.map +1 -0
- package/dist/loops-DMKlygqX.mjs +203 -0
- package/dist/loops-DMKlygqX.mjs.map +1 -0
- package/dist/manifest-builder-BQzCHNgB.mjs +189 -0
- package/dist/manifest-builder-BQzCHNgB.mjs.map +1 -0
- package/dist/manifest-schema-Ci2gmd0u.mjs +492 -0
- package/dist/manifest-schema-Ci2gmd0u.mjs.map +1 -0
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +4 -4
- package/dist/media/local-runtime.d.mts +14 -14
- package/dist/media/local-runtime.mjs +6 -6
- package/dist/media-BUQePMxP.mjs +373 -0
- package/dist/media-BUQePMxP.mjs.map +1 -0
- package/dist/media-DH8ibNlY.mjs +294 -0
- package/dist/media-DH8ibNlY.mjs.map +1 -0
- package/dist/media-OEIQ3bVc.mjs +408 -0
- package/dist/media-OEIQ3bVc.mjs.map +1 -0
- package/dist/media-allowlist-pYtaBA95.mjs +44 -0
- package/dist/media-allowlist-pYtaBA95.mjs.map +1 -0
- package/dist/media-folders-Bf8_s4de.mjs +210 -0
- package/dist/media-folders-Bf8_s4de.mjs.map +1 -0
- package/dist/media-url-C6klEuNd.mjs +43 -0
- package/dist/media-url-C6klEuNd.mjs.map +1 -0
- package/dist/media-usage-D7Y64m6v.mjs +1629 -0
- package/dist/media-usage-D7Y64m6v.mjs.map +1 -0
- package/dist/media-usage-activation-DrqbmgLA.mjs +78 -0
- package/dist/media-usage-activation-DrqbmgLA.mjs.map +1 -0
- package/dist/media-usage-work-DommYhYA.mjs +152 -0
- package/dist/media-usage-work-DommYhYA.mjs.map +1 -0
- package/dist/media-usage-work-HU63hNDu.mjs +586 -0
- package/dist/media-usage-work-HU63hNDu.mjs.map +1 -0
- package/dist/menus-BQfusWEC.mjs +3608 -0
- package/dist/menus-BQfusWEC.mjs.map +1 -0
- package/dist/menus-BtwjQt5s.mjs +753 -0
- package/dist/menus-BtwjQt5s.mjs.map +1 -0
- package/dist/menus-p_M1V7J_.mjs +139 -0
- package/dist/menus-p_M1V7J_.mjs.map +1 -0
- package/dist/migrations/index.d.mts +1 -1
- package/dist/migrations/index.mjs +3 -3
- package/dist/mime-C94qBG-P.mjs +36 -0
- package/dist/mime-C94qBG-P.mjs.map +1 -0
- package/dist/mode-DpYW3w6U.mjs +23 -0
- package/dist/mode-DpYW3w6U.mjs.map +1 -0
- package/dist/node-sqlite-compat-pWFw0lcc.mjs +46 -0
- package/dist/node-sqlite-compat-pWFw0lcc.mjs.map +1 -0
- package/dist/normalize-DduyxBjf.mjs +191 -0
- package/dist/normalize-DduyxBjf.mjs.map +1 -0
- package/dist/oauth-authorization-DAXsH1H9.mjs +274 -0
- package/dist/oauth-authorization-DAXsH1H9.mjs.map +1 -0
- package/dist/oauth-clients-DENiDQri.mjs +266 -0
- package/dist/oauth-clients-DENiDQri.mjs.map +1 -0
- package/dist/oauth-state-store-y8mEYVq9.mjs +50 -0
- package/dist/oauth-state-store-y8mEYVq9.mjs.map +1 -0
- package/dist/oauth-user-lookup-CtTYAy-O.mjs +26 -0
- package/dist/oauth-user-lookup-CtTYAy-O.mjs.map +1 -0
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/options-BYa1FgIM.d.mts +81 -0
- package/dist/options-BYa1FgIM.d.mts.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/page/index.mjs +5 -5
- package/dist/parse-CORGGhHf.mjs +81 -0
- package/dist/parse-CORGGhHf.mjs.map +1 -0
- package/dist/parse-avNM1xWV.d.mts +168 -0
- package/dist/parse-avNM1xWV.d.mts.map +1 -0
- package/dist/passkey-config-Dih5YeIS.mjs +46 -0
- package/dist/passkey-config-Dih5YeIS.mjs.map +1 -0
- package/dist/paths-d51RFm8M.mjs +77 -0
- package/dist/paths-d51RFm8M.mjs.map +1 -0
- package/dist/patterns-CoqlXUvk.mjs +145 -0
- package/dist/patterns-CoqlXUvk.mjs.map +1 -0
- package/dist/placeholder-D2aksPMF.d.mts +306 -0
- package/dist/placeholder-D2aksPMF.d.mts.map +1 -0
- package/dist/plan-DqeZKuaR.mjs +135 -0
- package/dist/plan-DqeZKuaR.mjs.map +1 -0
- package/dist/plugin-test-runtime.d.mts +14 -14
- package/dist/plugin-test-runtime.mjs +110 -107
- package/dist/plugin-types.d.mts +2 -2
- package/dist/plugin-utils.d.mts +12 -12
- package/dist/plugins/adapt-sandbox-entry.d.mts +12 -12
- package/dist/plugins/adapt-sandbox-entry.mjs +3 -3
- package/dist/plugins/host.d.mts +5 -5
- package/dist/plugins/host.mjs +42 -41
- package/dist/plugins-Bb7oqjQA.mjs +277 -0
- package/dist/plugins-Bb7oqjQA.mjs.map +1 -0
- package/dist/policy-BcEqut3n.mjs +45 -0
- package/dist/policy-BcEqut3n.mjs.map +1 -0
- package/dist/portable-text-DXE8ymtD.mjs +307 -0
- package/dist/portable-text-DXE8ymtD.mjs.map +1 -0
- package/dist/preview-DEDWbwA_.mjs +107 -0
- package/dist/preview-DEDWbwA_.mjs.map +1 -0
- package/dist/protocol-BJbTzvwl.d.mts +61 -0
- package/dist/protocol-BJbTzvwl.d.mts.map +1 -0
- package/dist/public-submission-D9c9S14m.mjs +250 -0
- package/dist/public-submission-D9c9S14m.mjs.map +1 -0
- package/dist/public-url-CIRe-2T6.mjs +101 -0
- package/dist/public-url-CIRe-2T6.mjs.map +1 -0
- package/dist/query-BzifXlPS.mjs +1156 -0
- package/dist/query-BzifXlPS.mjs.map +1 -0
- package/dist/query-OzMJ6vJP.mjs +41 -0
- package/dist/query-OzMJ6vJP.mjs.map +1 -0
- package/dist/rate-limit-Csp60Vik.mjs +120 -0
- package/dist/rate-limit-Csp60Vik.mjs.map +1 -0
- package/dist/receipt-B-aU4hpJ.mjs +43 -0
- package/dist/receipt-B-aU4hpJ.mjs.map +1 -0
- package/dist/redirect-CDSw1sU3.mjs +17 -0
- package/dist/redirect-CDSw1sU3.mjs.map +1 -0
- package/dist/redirect-D1ArbO85.mjs +411 -0
- package/dist/redirect-D1ArbO85.mjs.map +1 -0
- package/dist/redirects-BjTwDTsV.mjs +148 -0
- package/dist/redirects-BjTwDTsV.mjs.map +1 -0
- package/dist/redirects-Ck50kH3n.mjs +446 -0
- package/dist/redirects-Ck50kH3n.mjs.map +1 -0
- package/dist/registry/testing.mjs +3 -3
- package/dist/registry-CFcNCayZ.mjs +6754 -0
- package/dist/registry-CFcNCayZ.mjs.map +1 -0
- package/dist/relations-Cfaa1fDl.mjs +776 -0
- package/dist/relations-Cfaa1fDl.mjs.map +1 -0
- package/dist/request-cache-iHRlHx1d.mjs +104 -0
- package/dist/request-cache-iHRlHx1d.mjs.map +1 -0
- package/dist/request-context.d.mts +1 -1
- package/dist/request-meta-D47mqyev.mjs +141 -0
- package/dist/request-meta-D47mqyev.mjs.map +1 -0
- package/dist/resolve-BPE8sMvx.mjs +99 -0
- package/dist/resolve-BPE8sMvx.mjs.map +1 -0
- package/dist/resolve-C0s1E_fH.mjs +199 -0
- package/dist/resolve-C0s1E_fH.mjs.map +1 -0
- package/dist/revision-j1p4-bOj.mjs +302 -0
- package/dist/revision-j1p4-bOj.mjs.map +1 -0
- package/dist/route-wire-C9PJV9aL.mjs +197 -0
- package/dist/route-wire-C9PJV9aL.mjs.map +1 -0
- package/dist/routes-lyYw0mMf.mjs +272 -0
- package/dist/routes-lyYw0mMf.mjs.map +1 -0
- package/dist/runner-B3eyB9Gb.mjs +6121 -0
- package/dist/runner-B3eyB9Gb.mjs.map +1 -0
- package/dist/runner-DoYH2Jcu.d.mts +68 -0
- package/dist/runner-DoYH2Jcu.d.mts.map +1 -0
- package/dist/runtime.d.mts +13 -13
- package/dist/runtime.mjs +3 -3
- package/dist/schema-BAayK46S.mjs +13 -0
- package/dist/schema-BAayK46S.mjs.map +1 -0
- package/dist/schema-Gqcl-8G4.mjs +815 -0
- package/dist/schema-Gqcl-8G4.mjs.map +1 -0
- package/dist/scopes-BqPOKoKf.mjs +34 -0
- package/dist/scopes-BqPOKoKf.mjs.map +1 -0
- package/dist/search-YJKPIEV6.mjs +448 -0
- package/dist/search-YJKPIEV6.mjs.map +1 -0
- package/dist/sections-BR_e-wK5.mjs +346 -0
- package/dist/sections-BR_e-wK5.mjs.map +1 -0
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +37 -31
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +22 -21
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo-Dsj8hy3j.mjs +114 -0
- package/dist/seo-Dsj8hy3j.mjs.map +1 -0
- package/dist/seo-XvH4LNNp.mjs +133 -0
- package/dist/seo-XvH4LNNp.mjs.map +1 -0
- package/dist/service-BsVG05gS.mjs +150 -0
- package/dist/service-BsVG05gS.mjs.map +1 -0
- package/dist/session-user-DgKbYrlj.mjs +51 -0
- package/dist/session-user-DgKbYrlj.mjs.map +1 -0
- package/dist/settings-CNPUntkh.mjs +51 -0
- package/dist/settings-CNPUntkh.mjs.map +1 -0
- package/dist/settings-D5EHi0Tk.mjs +439 -0
- package/dist/settings-D5EHi0Tk.mjs.map +1 -0
- package/dist/settings-DSfE7wOa.mjs +61 -0
- package/dist/settings-DSfE7wOa.mjs.map +1 -0
- package/dist/setup-complete-B8W8sJ9v.mjs +26 -0
- package/dist/setup-complete-B8W8sJ9v.mjs.map +1 -0
- package/dist/setup-nonce-DnSBP260.mjs +25 -0
- package/dist/setup-nonce-DnSBP260.mjs.map +1 -0
- package/dist/site-settings-NGzdrt7O.mjs +50 -0
- package/dist/site-settings-NGzdrt7O.mjs.map +1 -0
- package/dist/site-url-D6JB7tLW.mjs +16 -0
- package/dist/site-url-D6JB7tLW.mjs.map +1 -0
- package/dist/snapshot-CdcwwWAf.mjs +414 -0
- package/dist/snapshot-CdcwwWAf.mjs.map +1 -0
- package/dist/ssrf-Dv0_tRpo.mjs +406 -0
- package/dist/ssrf-Dv0_tRpo.mjs.map +1 -0
- package/dist/stage-CUjhED3P.mjs +662 -0
- package/dist/stage-CUjhED3P.mjs.map +1 -0
- package/dist/staged-C36IWXff.mjs +659 -0
- package/dist/staged-C36IWXff.mjs.map +1 -0
- package/dist/state-CKouMCSY.mjs +153 -0
- package/dist/state-CKouMCSY.mjs.map +1 -0
- package/dist/status-lzyj4Uu7.mjs +30 -0
- package/dist/status-lzyj4Uu7.mjs.map +1 -0
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/storage-query-B-cWcTjJ.d.mts +1594 -0
- package/dist/storage-query-B-cWcTjJ.d.mts.map +1 -0
- package/dist/tar-DsTXX6ch.mjs +449 -0
- package/dist/tar-DsTXX6ch.mjs.map +1 -0
- package/dist/target-DLQCwp_Z.mjs +27 -0
- package/dist/target-DLQCwp_Z.mjs.map +1 -0
- package/dist/taxonomies-BlAjr4BL.mjs +697 -0
- package/dist/taxonomies-BlAjr4BL.mjs.map +1 -0
- package/dist/taxonomies-Byyo7LOZ.mjs +939 -0
- package/dist/taxonomies-Byyo7LOZ.mjs.map +1 -0
- package/dist/taxonomy-CKDwM61Y.mjs +525 -0
- package/dist/taxonomy-CKDwM61Y.mjs.map +1 -0
- package/dist/tokens-BojXlk49.mjs +171 -0
- package/dist/tokens-BojXlk49.mjs.map +1 -0
- package/dist/transaction-DLPQWik1.mjs +29 -0
- package/dist/transaction-DLPQWik1.mjs.map +1 -0
- package/dist/transfer-XSTh2BCr.mjs +8706 -0
- package/dist/transfer-XSTh2BCr.mjs.map +1 -0
- package/dist/transfer-download-DkoCDA9d.mjs +33 -0
- package/dist/transfer-download-DkoCDA9d.mjs.map +1 -0
- package/dist/transfer-iQ26J-RT.mjs +166 -0
- package/dist/transfer-iQ26J-RT.mjs.map +1 -0
- package/dist/transformations-C7RQabKQ.mjs +196 -0
- package/dist/transformations-C7RQabKQ.mjs.map +1 -0
- package/dist/transport-D3RulfD6.mjs +136 -0
- package/dist/transport-D3RulfD6.mjs.map +1 -0
- package/dist/transport-DhlZlf4D.d.mts +42 -0
- package/dist/transport-DhlZlf4D.d.mts.map +1 -0
- package/dist/trusted-proxy-B6ECOZJc.mjs +51 -0
- package/dist/trusted-proxy-B6ECOZJc.mjs.map +1 -0
- package/dist/turnstile-lqUiY7lP.mjs +53 -0
- package/dist/turnstile-lqUiY7lP.mjs.map +1 -0
- package/dist/types-4Dn9bZhu.mjs +77 -0
- package/dist/types-4Dn9bZhu.mjs.map +1 -0
- package/dist/types-5LSo7PPx.d.mts +85 -0
- package/dist/types-5LSo7PPx.d.mts.map +1 -0
- package/dist/types-BQ3hwYJT.d.mts +896 -0
- package/dist/types-BQ3hwYJT.d.mts.map +1 -0
- package/dist/types-BYEk7qo3.d.mts +198 -0
- package/dist/types-BYEk7qo3.d.mts.map +1 -0
- package/dist/types-CJKsWVFR.mjs +199 -0
- package/dist/types-CJKsWVFR.mjs.map +1 -0
- package/dist/types-Ca_w8mmY.d.mts +363 -0
- package/dist/types-Ca_w8mmY.d.mts.map +1 -0
- package/dist/types-CkE41ZAG.mjs +18 -0
- package/dist/types-CkE41ZAG.mjs.map +1 -0
- package/dist/types-D0aJW2uR.d.mts +1641 -0
- package/dist/types-D0aJW2uR.d.mts.map +1 -0
- package/dist/types-DbpN4Qto.d.mts +372 -0
- package/dist/types-DbpN4Qto.d.mts.map +1 -0
- package/dist/types-ILDI1sdY.mjs +16 -0
- package/dist/types-ILDI1sdY.mjs.map +1 -0
- package/dist/types-OC5c-edM.mjs +22 -0
- package/dist/types-OC5c-edM.mjs.map +1 -0
- package/dist/types-aOOxRSx6.mjs +103 -0
- package/dist/types-aOOxRSx6.mjs.map +1 -0
- package/dist/types-m1WbUffD.d.mts +198 -0
- package/dist/types-m1WbUffD.d.mts.map +1 -0
- package/dist/types-uxLoPBio.d.mts +124 -0
- package/dist/types-uxLoPBio.d.mts.map +1 -0
- package/dist/types-we5uR-tV.d.mts +287 -0
- package/dist/types-we5uR-tV.d.mts.map +1 -0
- package/dist/upload-attempts-DduMy6B0.mjs +32 -0
- package/dist/upload-attempts-DduMy6B0.mjs.map +1 -0
- package/dist/url-pattern-B3EwxAAk.mjs +33 -0
- package/dist/url-pattern-B3EwxAAk.mjs.map +1 -0
- package/dist/user-ElwQjTQT.mjs +171 -0
- package/dist/user-ElwQjTQT.mjs.map +1 -0
- package/dist/utils-BlAXmfOG.mjs +439 -0
- package/dist/utils-BlAXmfOG.mjs.map +1 -0
- package/dist/validate-CH0X5b2c.d.mts +468 -0
- package/dist/validate-CH0X5b2c.d.mts.map +1 -0
- package/dist/validate-CfgRpcjA.mjs +492 -0
- package/dist/validate-CfgRpcjA.mjs.map +1 -0
- package/dist/validation-DvYJtv4k.mjs +218 -0
- package/dist/validation-DvYJtv4k.mjs.map +1 -0
- package/dist/version-DgYjhTud.mjs +9 -0
- package/dist/version-DgYjhTud.mjs.map +1 -0
- package/dist/version-Dq71scUb.mjs +7 -0
- package/dist/version-Dq71scUb.mjs.map +1 -0
- package/dist/widgets-ChFIj0be.mjs +126 -0
- package/dist/widgets-ChFIj0be.mjs.map +1 -0
- package/dist/wxr-taxonomies-CBZMp2YX.mjs +372 -0
- package/dist/wxr-taxonomies-CBZMp2YX.mjs.map +1 -0
- package/dist/wxr-taxonomies-DlKDpWN1.d.mts +34 -0
- package/dist/wxr-taxonomies-DlKDpWN1.d.mts.map +1 -0
- package/dist/zod-generator-DmTKI-Ig.mjs +426 -0
- package/dist/zod-generator-DmTKI-Ig.mjs.map +1 -0
- package/package.json +7 -6
- package/src/api/handlers/content.ts +593 -16
- package/src/api/handlers/device-flow.ts +74 -21
- package/src/api/handlers/manifest.ts +79 -5
- package/src/api/handlers/relations.ts +638 -157
- package/src/api/handlers/revision.ts +30 -0
- package/src/api/handlers/schema.ts +403 -1
- package/src/api/handlers/staged-references.ts +142 -0
- package/src/api/handlers/validate-references.ts +146 -0
- package/src/api/schemas/content.ts +13 -0
- package/src/api/schemas/relations.ts +54 -44
- package/src/api/schemas/schema.ts +14 -0
- package/src/astro/integration/routes.ts +15 -19
- package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +11 -54
- package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
- package/src/astro/routes/api/oauth/device/authorize.ts +33 -4
- package/src/astro/routes/api/relations/index.ts +4 -4
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +6 -2
- package/src/astro/types.ts +5 -0
- package/src/cli/commands/export-seed.ts +510 -89
- package/src/components/WidgetArea.astro +3 -2
- package/src/database/migrations/086_relations_structural.ts +197 -0
- package/src/database/migrations/087_reference_field_relations.ts +407 -0
- package/src/database/migrations/runner.ts +4 -0
- package/src/database/reference-backfill.ts +141 -0
- package/src/database/repositories/content.ts +43 -8
- package/src/database/repositories/relation.ts +620 -208
- package/src/database/repositories/revision.ts +16 -0
- package/src/database/repositories/types.ts +38 -0
- package/src/database/transaction.ts +12 -1
- package/src/database/types.ts +14 -5
- package/src/emdash-runtime.ts +86 -11
- package/src/index.ts +10 -0
- package/src/loader.ts +169 -22
- package/src/query.ts +455 -25
- package/src/references/field-map.ts +115 -0
- package/src/references/resolve.ts +160 -0
- package/src/references/staged.ts +117 -0
- package/src/references/types.ts +16 -0
- package/src/registry/artifact-fetch.ts +45 -271
- package/src/schema/registry.ts +99 -24
- package/src/schema/types.ts +58 -0
- package/src/schema/zod-generator.ts +67 -1
- package/src/seed/apply.ts +519 -62
- package/src/seed/types.ts +36 -2
- package/src/seed/validate.ts +78 -2
- package/src/transfer/analyze/unique-keys.ts +3 -12
- package/src/transfer/analyze/validate.ts +65 -39
- package/src/transfer/analyze/values.ts +12 -1
- package/src/transfer/export/readers.ts +12 -8
- package/src/transfer/format/columns.ts +26 -6
- package/src/transfer/format/kinds.ts +21 -5
- package/src/transfer/import/context.ts +8 -1
- package/src/transfer/ops/package-index.ts +1 -1
- package/dist/action-token-DYwe4Pk0.mjs +0 -26
- package/dist/action-token-DYwe4Pk0.mjs.map +0 -1
- package/dist/activation-LOkDM5WT.mjs +0 -382
- package/dist/activation-LOkDM5WT.mjs.map +0 -1
- package/dist/adapters-B64LbYcB.d.mts +0 -171
- package/dist/adapters-B64LbYcB.d.mts.map +0 -1
- package/dist/allowed-origins-CHB8oZNM.mjs +0 -116
- package/dist/allowed-origins-CHB8oZNM.mjs.map +0 -1
- package/dist/api-CuyNEHZG.mjs +0 -4718
- package/dist/api-CuyNEHZG.mjs.map +0 -1
- package/dist/api-tokens-s4i4aUp_.mjs +0 -166
- package/dist/api-tokens-s4i4aUp_.mjs.map +0 -1
- package/dist/apply-npY1TAhG.mjs +0 -1366
- package/dist/apply-npY1TAhG.mjs.map +0 -1
- package/dist/approvals-CqMfNxak.mjs +0 -460
- package/dist/approvals-CqMfNxak.mjs.map +0 -1
- package/dist/artifact-fetch-DZMOGZ3-.mjs +0 -818
- package/dist/artifact-fetch-DZMOGZ3-.mjs.map +0 -1
- package/dist/astro/routes/api/relations/_id_/translations.d.mts +0 -8
- package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +0 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +0 -47
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +0 -1
- package/dist/audit-RfCugiSB.mjs +0 -127
- package/dist/audit-RfCugiSB.mjs.map +0 -1
- package/dist/authoritative-records-CoJvBXAD.mjs +0 -5172
- package/dist/authoritative-records-CoJvBXAD.mjs.map +0 -1
- package/dist/authorize-seCifOMJ.mjs +0 -49
- package/dist/authorize-seCifOMJ.mjs.map +0 -1
- package/dist/backup-BQRj3afm.mjs +0 -246
- package/dist/backup-BQRj3afm.mjs.map +0 -1
- package/dist/block-type-registry-DUI_3KxT.mjs +0 -6709
- package/dist/block-type-registry-DUI_3KxT.mjs.map +0 -1
- package/dist/block-types-BmZmLmAD.mjs +0 -132
- package/dist/block-types-BmZmLmAD.mjs.map +0 -1
- package/dist/block-values-C_VIPr5t.mjs +0 -175
- package/dist/block-values-C_VIPr5t.mjs.map +0 -1
- package/dist/byline-DYmkXqvo.mjs +0 -909
- package/dist/byline-DYmkXqvo.mjs.map +0 -1
- package/dist/byline-fields-D28AT-Fh.mjs +0 -123
- package/dist/byline-fields-D28AT-Fh.mjs.map +0 -1
- package/dist/byline-registry-gnKscbQX.mjs +0 -406
- package/dist/byline-registry-gnKscbQX.mjs.map +0 -1
- package/dist/bylines-BPwJqoYH.mjs +0 -232
- package/dist/bylines-BPwJqoYH.mjs.map +0 -1
- package/dist/bylines-ukLaYpVZ.mjs +0 -214
- package/dist/bylines-ukLaYpVZ.mjs.map +0 -1
- package/dist/cache-m7UEkRFV.mjs +0 -108
- package/dist/cache-m7UEkRFV.mjs.map +0 -1
- package/dist/canonical-YhEQezjg.mjs +0 -174
- package/dist/canonical-YhEQezjg.mjs.map +0 -1
- package/dist/capture-triggers-kJyl_yyM.mjs +0 -362
- package/dist/capture-triggers-kJyl_yyM.mjs.map +0 -1
- package/dist/challenge-store-ppU6Uv13.mjs +0 -51
- package/dist/challenge-store-ppU6Uv13.mjs.map +0 -1
- package/dist/checksum-B2IINIlN.mjs +0 -162
- package/dist/checksum-B2IINIlN.mjs.map +0 -1
- package/dist/chrome-tags-DApCQSIk.mjs +0 -24
- package/dist/chrome-tags-DApCQSIk.mjs.map +0 -1
- package/dist/chunks-Dms7Uxbt.mjs +0 -25
- package/dist/chunks-Dms7Uxbt.mjs.map +0 -1
- package/dist/collection-deletion-BIm28mo3.mjs +0 -436
- package/dist/collection-deletion-BIm28mo3.mjs.map +0 -1
- package/dist/collection-deletion-processor-Br6rxs3u.mjs +0 -217
- package/dist/collection-deletion-processor-Br6rxs3u.mjs.map +0 -1
- package/dist/collection-slugs-cache-CjGk__zp.mjs +0 -85
- package/dist/collection-slugs-cache-CjGk__zp.mjs.map +0 -1
- package/dist/comment-CrBl22OF.mjs +0 -313
- package/dist/comment-CrBl22OF.mjs.map +0 -1
- package/dist/comment-reaction-JEQ2Fpd8.mjs +0 -85
- package/dist/comment-reaction-JEQ2Fpd8.mjs.map +0 -1
- package/dist/comments-2ah9du9y.mjs +0 -195
- package/dist/comments-2ah9du9y.mjs.map +0 -1
- package/dist/comments-fHZ8ON9O.mjs +0 -99
- package/dist/comments-fHZ8ON9O.mjs.map +0 -1
- package/dist/components-CXbq7CSM.mjs +0 -108
- package/dist/components-CXbq7CSM.mjs.map +0 -1
- package/dist/config-BjEm_3xL.d.mts +0 -6537
- package/dist/config-BjEm_3xL.d.mts.map +0 -1
- package/dist/config-IhybvkIQ.mjs +0 -242
- package/dist/config-IhybvkIQ.mjs.map +0 -1
- package/dist/config-Py43JK9r.d.mts +0 -39
- package/dist/config-Py43JK9r.d.mts.map +0 -1
- package/dist/content-DFaIEDj9.mjs +0 -2281
- package/dist/content-DFaIEDj9.mjs.map +0 -1
- package/dist/content-list-query-Dra4Dalc.d.mts +0 -26
- package/dist/content-list-query-Dra4Dalc.d.mts.map +0 -1
- package/dist/content-policy-DFNw91-d.mjs +0 -46
- package/dist/content-policy-DFNw91-d.mjs.map +0 -1
- package/dist/content-repair-Q8IUrpLL.mjs +0 -442
- package/dist/content-repair-Q8IUrpLL.mjs.map +0 -1
- package/dist/context-BV_7t-Ua.mjs +0 -1921
- package/dist/context-BV_7t-Ua.mjs.map +0 -1
- package/dist/cron-7DCJwPXq.mjs +0 -284
- package/dist/cron-7DCJwPXq.mjs.map +0 -1
- package/dist/dashboard-BP-iJqpd.mjs +0 -151
- package/dist/dashboard-BP-iJqpd.mjs.map +0 -1
- package/dist/default-DQ6vsviu.mjs +0 -81
- package/dist/default-DQ6vsviu.mjs.map +0 -1
- package/dist/deferred-tasks-BPxXUB4x.d.mts +0 -9
- package/dist/deferred-tasks-BPxXUB4x.d.mts.map +0 -1
- package/dist/dev-typegen-CZaPLl3V.mjs +0 -29
- package/dist/dev-typegen-CZaPLl3V.mjs.map +0 -1
- package/dist/device-flow-CRd6DXmW.mjs +0 -466
- package/dist/device-flow-CRd6DXmW.mjs.map +0 -1
- package/dist/digest-BarSh-pN.mjs +0 -194
- package/dist/digest-BarSh-pN.mjs.map +0 -1
- package/dist/direct-executor-D2lNadwo.mjs +0 -104
- package/dist/direct-executor-D2lNadwo.mjs.map +0 -1
- package/dist/dist-BNwANFJR.mjs +0 -810
- package/dist/dist-BNwANFJR.mjs.map +0 -1
- package/dist/email-console-bJn3ctqA.mjs +0 -50
- package/dist/email-console-bJn3ctqA.mjs.map +0 -1
- package/dist/email-locale-CN6WAMx0.mjs +0 -25
- package/dist/email-locale-CN6WAMx0.mjs.map +0 -1
- package/dist/emdash-runtime-CtfnZmPi.mjs +0 -4186
- package/dist/emdash-runtime-CtfnZmPi.mjs.map +0 -1
- package/dist/enrich-Dl3kZ-lP.mjs +0 -194
- package/dist/enrich-Dl3kZ-lP.mjs.map +0 -1
- package/dist/entry-lock-BJYdBfXb.mjs +0 -1097
- package/dist/entry-lock-BJYdBfXb.mjs.map +0 -1
- package/dist/entry-lock-Cf5OoIgN.d.mts +0 -4368
- package/dist/entry-lock-Cf5OoIgN.d.mts.map +0 -1
- package/dist/entry-lock-DHQOxN7R.mjs +0 -163
- package/dist/entry-lock-DHQOxN7R.mjs.map +0 -1
- package/dist/entry-locks-D0foLdjQ.mjs +0 -167
- package/dist/entry-locks-D0foLdjQ.mjs.map +0 -1
- package/dist/error-CfvOHP0M.mjs +0 -90
- package/dist/error-CfvOHP0M.mjs.map +0 -1
- package/dist/errors-BF0_LFhW.mjs +0 -460
- package/dist/errors-BF0_LFhW.mjs.map +0 -1
- package/dist/errors-DgE1zJGG.mjs +0 -120
- package/dist/errors-DgE1zJGG.mjs.map +0 -1
- package/dist/escape-CuaZhZvL.mjs +0 -9
- package/dist/escape-CuaZhZvL.mjs.map +0 -1
- package/dist/fence-CMDXJYc_.mjs +0 -162
- package/dist/fence-CMDXJYc_.mjs.map +0 -1
- package/dist/field-defs-cache-HIgBbqZZ.mjs +0 -77
- package/dist/field-defs-cache-HIgBbqZZ.mjs.map +0 -1
- package/dist/focal-point-Gr34o-4o.mjs +0 -23
- package/dist/focal-point-Gr34o-4o.mjs.map +0 -1
- package/dist/fts-manager-S-K0laoS.mjs +0 -443
- package/dist/fts-manager-S-K0laoS.mjs.map +0 -1
- package/dist/gc-DjKY0Ay1.mjs +0 -75
- package/dist/gc-DjKY0Ay1.mjs.map +0 -1
- package/dist/hash-SDAW6zC-.mjs +0 -37
- package/dist/hash-SDAW6zC-.mjs.map +0 -1
- package/dist/hook-result-B5bXDgS2.d.mts +0 -31
- package/dist/hook-result-B5bXDgS2.d.mts.map +0 -1
- package/dist/hreflang-CbVI4paR.mjs +0 -105
- package/dist/hreflang-CbVI4paR.mjs.map +0 -1
- package/dist/hreflang-D5uNnsGJ.d.mts +0 -50
- package/dist/hreflang-D5uNnsGJ.d.mts.map +0 -1
- package/dist/http-route-dispatch-BitqzwMy.mjs +0 -339
- package/dist/http-route-dispatch-BitqzwMy.mjs.map +0 -1
- package/dist/identity-Be5kzutJ.mjs +0 -35
- package/dist/identity-Be5kzutJ.mjs.map +0 -1
- package/dist/import-YzfKCaco.mjs +0 -2020
- package/dist/import-YzfKCaco.mjs.map +0 -1
- package/dist/index-D-hdtLe8.d.mts +0 -623
- package/dist/index-D-hdtLe8.d.mts.map +0 -1
- package/dist/install-finalization-DfM1fj5x.mjs +0 -58
- package/dist/install-finalization-DfM1fj5x.mjs.map +0 -1
- package/dist/keys-yxLm5l35.mjs +0 -61
- package/dist/keys-yxLm5l35.mjs.map +0 -1
- package/dist/kinds-CRu_T5T5.mjs +0 -961
- package/dist/kinds-CRu_T5T5.mjs.map +0 -1
- package/dist/lifecycle-BzeGPeQ-.mjs +0 -25
- package/dist/lifecycle-BzeGPeQ-.mjs.map +0 -1
- package/dist/load-XgJiE6_3.mjs +0 -28
- package/dist/load-XgJiE6_3.mjs.map +0 -1
- package/dist/loader-BzqeR1ZN.mjs +0 -1086
- package/dist/loader-BzqeR1ZN.mjs.map +0 -1
- package/dist/loops-BQSzv5Zn.mjs +0 -203
- package/dist/loops-BQSzv5Zn.mjs.map +0 -1
- package/dist/manifest-builder-BmSAOOEF.mjs +0 -189
- package/dist/manifest-builder-BmSAOOEF.mjs.map +0 -1
- package/dist/manifest-schema-CY3zng_M.mjs +0 -492
- package/dist/manifest-schema-CY3zng_M.mjs.map +0 -1
- package/dist/media-CPXTbb1R.mjs +0 -373
- package/dist/media-CPXTbb1R.mjs.map +0 -1
- package/dist/media-JXRWDhw3.mjs +0 -294
- package/dist/media-JXRWDhw3.mjs.map +0 -1
- package/dist/media-Pu1L6xir.mjs +0 -408
- package/dist/media-Pu1L6xir.mjs.map +0 -1
- package/dist/media-allowlist-BSoa9Vvm.mjs +0 -44
- package/dist/media-allowlist-BSoa9Vvm.mjs.map +0 -1
- package/dist/media-folders-BE0oo2eX.mjs +0 -210
- package/dist/media-folders-BE0oo2eX.mjs.map +0 -1
- package/dist/media-url-jArBpzIG.mjs +0 -43
- package/dist/media-url-jArBpzIG.mjs.map +0 -1
- package/dist/media-usage-De-zeR9E.mjs +0 -1629
- package/dist/media-usage-De-zeR9E.mjs.map +0 -1
- package/dist/media-usage-activation-HKp7zk7W.mjs +0 -78
- package/dist/media-usage-activation-HKp7zk7W.mjs.map +0 -1
- package/dist/media-usage-work-C2OZLCAd.mjs +0 -586
- package/dist/media-usage-work-C2OZLCAd.mjs.map +0 -1
- package/dist/media-usage-work-DwUNbgvS.mjs +0 -152
- package/dist/media-usage-work-DwUNbgvS.mjs.map +0 -1
- package/dist/menus-BM7BPLOb.mjs +0 -139
- package/dist/menus-BM7BPLOb.mjs.map +0 -1
- package/dist/menus-Cm68rsAq.mjs +0 -3608
- package/dist/menus-Cm68rsAq.mjs.map +0 -1
- package/dist/menus-ITeAbcIF.mjs +0 -753
- package/dist/menus-ITeAbcIF.mjs.map +0 -1
- package/dist/mime-ChLqYwDk.mjs +0 -36
- package/dist/mime-ChLqYwDk.mjs.map +0 -1
- package/dist/mode-CCuKXUci.mjs +0 -23
- package/dist/mode-CCuKXUci.mjs.map +0 -1
- package/dist/node-sqlite-compat-CONMsl-x.mjs +0 -46
- package/dist/node-sqlite-compat-CONMsl-x.mjs.map +0 -1
- package/dist/normalize-CO2P8-iE.mjs +0 -191
- package/dist/normalize-CO2P8-iE.mjs.map +0 -1
- package/dist/oauth-authorization-DlMIL5_h.mjs +0 -274
- package/dist/oauth-authorization-DlMIL5_h.mjs.map +0 -1
- package/dist/oauth-clients-Djq9r_KP.mjs +0 -266
- package/dist/oauth-clients-Djq9r_KP.mjs.map +0 -1
- package/dist/oauth-state-store-BbjnZXNC.mjs +0 -50
- package/dist/oauth-state-store-BbjnZXNC.mjs.map +0 -1
- package/dist/oauth-user-lookup-vue9a64A.mjs +0 -26
- package/dist/oauth-user-lookup-vue9a64A.mjs.map +0 -1
- package/dist/options-SQCHQCPH.d.mts +0 -81
- package/dist/options-SQCHQCPH.d.mts.map +0 -1
- package/dist/parse-CVgO-Qai.d.mts +0 -168
- package/dist/parse-CVgO-Qai.d.mts.map +0 -1
- package/dist/parse-DY6OD1j_.mjs +0 -81
- package/dist/parse-DY6OD1j_.mjs.map +0 -1
- package/dist/passkey-config-X_H8128a.mjs +0 -46
- package/dist/passkey-config-X_H8128a.mjs.map +0 -1
- package/dist/paths-JxokKIbr.mjs +0 -77
- package/dist/paths-JxokKIbr.mjs.map +0 -1
- package/dist/patterns-BhAvqO0S.mjs +0 -145
- package/dist/patterns-BhAvqO0S.mjs.map +0 -1
- package/dist/placeholder-MSEd8gty.d.mts +0 -306
- package/dist/placeholder-MSEd8gty.d.mts.map +0 -1
- package/dist/plan-xjcWrAah.mjs +0 -135
- package/dist/plan-xjcWrAah.mjs.map +0 -1
- package/dist/plugins-DUXUt8B9.mjs +0 -277
- package/dist/plugins-DUXUt8B9.mjs.map +0 -1
- package/dist/policy-CUvwAARc.mjs +0 -45
- package/dist/policy-CUvwAARc.mjs.map +0 -1
- package/dist/portable-text-5O_ZGUjB.mjs +0 -307
- package/dist/portable-text-5O_ZGUjB.mjs.map +0 -1
- package/dist/preview-CIUcPYr6.mjs +0 -107
- package/dist/preview-CIUcPYr6.mjs.map +0 -1
- package/dist/protocol-B97DZaFr.d.mts +0 -61
- package/dist/protocol-B97DZaFr.d.mts.map +0 -1
- package/dist/public-submission-BFBUrqst.mjs +0 -250
- package/dist/public-submission-BFBUrqst.mjs.map +0 -1
- package/dist/public-url-Bn7U0D7-.mjs +0 -101
- package/dist/public-url-Bn7U0D7-.mjs.map +0 -1
- package/dist/query-B48peoRT.mjs +0 -890
- package/dist/query-B48peoRT.mjs.map +0 -1
- package/dist/query-C4IH0uhR.mjs +0 -41
- package/dist/query-C4IH0uhR.mjs.map +0 -1
- package/dist/rate-limit-BZ6nybgc.mjs +0 -120
- package/dist/rate-limit-BZ6nybgc.mjs.map +0 -1
- package/dist/receipt-B4wJj5Jq.mjs +0 -43
- package/dist/receipt-B4wJj5Jq.mjs.map +0 -1
- package/dist/redirect-B29UjdUn.mjs +0 -411
- package/dist/redirect-B29UjdUn.mjs.map +0 -1
- package/dist/redirect-Cd1E7VUt.mjs +0 -17
- package/dist/redirect-Cd1E7VUt.mjs.map +0 -1
- package/dist/redirects-Ca2MPfEG.mjs +0 -446
- package/dist/redirects-Ca2MPfEG.mjs.map +0 -1
- package/dist/redirects-Cv9apQKj.mjs +0 -148
- package/dist/redirects-Cv9apQKj.mjs.map +0 -1
- package/dist/relation-M4NUCb0b.mjs +0 -334
- package/dist/relation-M4NUCb0b.mjs.map +0 -1
- package/dist/relations-CCif47Oq.mjs +0 -403
- package/dist/relations-CCif47Oq.mjs.map +0 -1
- package/dist/relations-CK9CYUyr.mjs +0 -310
- package/dist/relations-CK9CYUyr.mjs.map +0 -1
- package/dist/request-cache-DzLYKm_x.mjs +0 -104
- package/dist/request-cache-DzLYKm_x.mjs.map +0 -1
- package/dist/request-meta-sZXt3sRo.mjs +0 -141
- package/dist/request-meta-sZXt3sRo.mjs.map +0 -1
- package/dist/resolve-2WbQsCvT.mjs +0 -199
- package/dist/resolve-2WbQsCvT.mjs.map +0 -1
- package/dist/route-wire--1hLuACz.mjs +0 -197
- package/dist/route-wire--1hLuACz.mjs.map +0 -1
- package/dist/routes-vrR95WR6.mjs +0 -272
- package/dist/routes-vrR95WR6.mjs.map +0 -1
- package/dist/runner-1y4J9fJB.mjs +0 -5742
- package/dist/runner-1y4J9fJB.mjs.map +0 -1
- package/dist/runner-D5_LzKXI.d.mts +0 -68
- package/dist/runner-D5_LzKXI.d.mts.map +0 -1
- package/dist/schema-BABiRdsH.mjs +0 -13
- package/dist/schema-BABiRdsH.mjs.map +0 -1
- package/dist/schema-Du3MzCG0.mjs +0 -446
- package/dist/schema-Du3MzCG0.mjs.map +0 -1
- package/dist/scopes-Dbk-ElhT.mjs +0 -34
- package/dist/scopes-Dbk-ElhT.mjs.map +0 -1
- package/dist/search-Bt1PL1jf.mjs +0 -448
- package/dist/search-Bt1PL1jf.mjs.map +0 -1
- package/dist/sections-Ddptx_o9.mjs +0 -346
- package/dist/sections-Ddptx_o9.mjs.map +0 -1
- package/dist/seo-CZT2oLtT.mjs +0 -114
- package/dist/seo-CZT2oLtT.mjs.map +0 -1
- package/dist/seo-D5w3-Azy.mjs +0 -133
- package/dist/seo-D5w3-Azy.mjs.map +0 -1
- package/dist/service-DuykXPyW.mjs +0 -150
- package/dist/service-DuykXPyW.mjs.map +0 -1
- package/dist/session-user-BhaVp8w0.mjs +0 -51
- package/dist/session-user-BhaVp8w0.mjs.map +0 -1
- package/dist/settings-B4vDl1fK.mjs +0 -439
- package/dist/settings-B4vDl1fK.mjs.map +0 -1
- package/dist/settings-DYidIB26.mjs +0 -61
- package/dist/settings-DYidIB26.mjs.map +0 -1
- package/dist/settings-Dyj6v8C4.mjs +0 -51
- package/dist/settings-Dyj6v8C4.mjs.map +0 -1
- package/dist/setup-complete-bOogcHWG.mjs +0 -26
- package/dist/setup-complete-bOogcHWG.mjs.map +0 -1
- package/dist/setup-nonce-0EGuKM4s.mjs +0 -25
- package/dist/setup-nonce-0EGuKM4s.mjs.map +0 -1
- package/dist/site-settings-DOgRUoFX.mjs +0 -50
- package/dist/site-settings-DOgRUoFX.mjs.map +0 -1
- package/dist/site-url-BU_bbxwj.mjs +0 -16
- package/dist/site-url-BU_bbxwj.mjs.map +0 -1
- package/dist/snapshot-PawoX-WG.mjs +0 -414
- package/dist/snapshot-PawoX-WG.mjs.map +0 -1
- package/dist/ssrf-CJUnJymJ.mjs +0 -406
- package/dist/ssrf-CJUnJymJ.mjs.map +0 -1
- package/dist/stage-DgrBz_du.mjs +0 -662
- package/dist/stage-DgrBz_du.mjs.map +0 -1
- package/dist/state-DDiPySSG.mjs +0 -153
- package/dist/state-DDiPySSG.mjs.map +0 -1
- package/dist/status-DZKIG4a9.mjs +0 -30
- package/dist/status-DZKIG4a9.mjs.map +0 -1
- package/dist/storage-query-FXJH5pI8.d.mts +0 -1581
- package/dist/storage-query-FXJH5pI8.d.mts.map +0 -1
- package/dist/tar-_1AgTYFu.mjs +0 -449
- package/dist/tar-_1AgTYFu.mjs.map +0 -1
- package/dist/target-_7pn2Gbg.mjs +0 -27
- package/dist/target-_7pn2Gbg.mjs.map +0 -1
- package/dist/taxonomies-C1IwNe8Q.mjs +0 -697
- package/dist/taxonomies-C1IwNe8Q.mjs.map +0 -1
- package/dist/taxonomies-C_XMoRcX.mjs +0 -939
- package/dist/taxonomies-C_XMoRcX.mjs.map +0 -1
- package/dist/taxonomy-C3Fu1YeH.mjs +0 -525
- package/dist/taxonomy-C3Fu1YeH.mjs.map +0 -1
- package/dist/tokens-u78jETkX.mjs +0 -171
- package/dist/tokens-u78jETkX.mjs.map +0 -1
- package/dist/transaction-BcJO4Tmc.mjs +0 -29
- package/dist/transaction-BcJO4Tmc.mjs.map +0 -1
- package/dist/transfer-DIGvR9Af.mjs +0 -166
- package/dist/transfer-DIGvR9Af.mjs.map +0 -1
- package/dist/transfer-DgeCvHnj.mjs +0 -8675
- package/dist/transfer-DgeCvHnj.mjs.map +0 -1
- package/dist/transfer-download-Pml7RMio.mjs +0 -33
- package/dist/transfer-download-Pml7RMio.mjs.map +0 -1
- package/dist/transformations-9gfpwY65.mjs +0 -196
- package/dist/transformations-9gfpwY65.mjs.map +0 -1
- package/dist/transport-BIfH7_hx.d.mts +0 -42
- package/dist/transport-BIfH7_hx.d.mts.map +0 -1
- package/dist/transport-DKWIq53q.mjs +0 -136
- package/dist/transport-DKWIq53q.mjs.map +0 -1
- package/dist/trusted-proxy-tKiVtyTD.mjs +0 -51
- package/dist/trusted-proxy-tKiVtyTD.mjs.map +0 -1
- package/dist/turnstile-DpsoyOfg.mjs +0 -53
- package/dist/turnstile-DpsoyOfg.mjs.map +0 -1
- package/dist/types-B4sUC2p1.d.mts +0 -198
- package/dist/types-B4sUC2p1.d.mts.map +0 -1
- package/dist/types-B7Lmsh1E.d.mts +0 -887
- package/dist/types-B7Lmsh1E.d.mts.map +0 -1
- package/dist/types-BZakh7Ym.mjs +0 -22
- package/dist/types-BZakh7Ym.mjs.map +0 -1
- package/dist/types-B_CppEmv.d.mts +0 -264
- package/dist/types-B_CppEmv.d.mts.map +0 -1
- package/dist/types-BcrBrE6-.mjs +0 -159
- package/dist/types-BcrBrE6-.mjs.map +0 -1
- package/dist/types-BkUg2yHx.mjs +0 -92
- package/dist/types-BkUg2yHx.mjs.map +0 -1
- package/dist/types-CAZgq9fO.d.mts +0 -124
- package/dist/types-CAZgq9fO.d.mts.map +0 -1
- package/dist/types-Cd-O03VG.d.mts +0 -363
- package/dist/types-Cd-O03VG.d.mts.map +0 -1
- package/dist/types-Cr-Kg-3D.d.mts +0 -1641
- package/dist/types-Cr-Kg-3D.d.mts.map +0 -1
- package/dist/types-D2fvWd1i.d.mts +0 -359
- package/dist/types-D2fvWd1i.d.mts.map +0 -1
- package/dist/types-D7HUsguf.mjs +0 -77
- package/dist/types-D7HUsguf.mjs.map +0 -1
- package/dist/types-DA1Te3Oy.d.mts +0 -198
- package/dist/types-DA1Te3Oy.d.mts.map +0 -1
- package/dist/types-DhV6Q5bP.mjs +0 -18
- package/dist/types-DhV6Q5bP.mjs.map +0 -1
- package/dist/types-DnnVSl6Y.d.mts +0 -85
- package/dist/types-DnnVSl6Y.d.mts.map +0 -1
- package/dist/types-VT4-BugW.mjs +0 -16
- package/dist/types-VT4-BugW.mjs.map +0 -1
- package/dist/upload-attempts-B68ZGNu9.mjs +0 -32
- package/dist/upload-attempts-B68ZGNu9.mjs.map +0 -1
- package/dist/url-pattern-CCeZMGOh.mjs +0 -33
- package/dist/url-pattern-CCeZMGOh.mjs.map +0 -1
- package/dist/user-DDSL-sGw.mjs +0 -171
- package/dist/user-DDSL-sGw.mjs.map +0 -1
- package/dist/utils-DdhmO9w9.mjs +0 -439
- package/dist/utils-DdhmO9w9.mjs.map +0 -1
- package/dist/validate-CHosPEhs.mjs +0 -453
- package/dist/validate-CHosPEhs.mjs.map +0 -1
- package/dist/validate-CM79QXYE.d.mts +0 -432
- package/dist/validate-CM79QXYE.d.mts.map +0 -1
- package/dist/validation-BFecQczG.mjs +0 -218
- package/dist/validation-BFecQczG.mjs.map +0 -1
- package/dist/version-BRZXVifl.mjs +0 -9
- package/dist/version-BRZXVifl.mjs.map +0 -1
- package/dist/version-DXsxRrob.mjs +0 -7
- package/dist/version-DXsxRrob.mjs.map +0 -1
- package/dist/widgets-WdV72brA.mjs +0 -126
- package/dist/widgets-WdV72brA.mjs.map +0 -1
- package/dist/wxr-taxonomies-BHTdqkmZ.d.mts +0 -34
- package/dist/wxr-taxonomies-BHTdqkmZ.d.mts.map +0 -1
- package/dist/wxr-taxonomies-DP6ESgMN.mjs +0 -372
- package/dist/wxr-taxonomies-DP6ESgMN.mjs.map +0 -1
- package/dist/zod-generator-D6uE4WiS.mjs +0 -389
- package/dist/zod-generator-D6uE4WiS.mjs.map +0 -1
- package/src/astro/routes/api/relations/[id]/translations.ts +0 -33
- /package/dist/{api-tokens-CE1ECIg0.mjs → api-tokens-FaG1zPsj.mjs} +0 -0
- /package/dist/{ssrf-DpBH7aOt.mjs → ssrf-DZOt8Qof.mjs} +0 -0
|
@@ -1,50 +1,106 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { sql, type Kysely, type Selectable } from "kysely";
|
|
2
2
|
import { ulid } from "ulidx";
|
|
3
3
|
|
|
4
4
|
import { chunks, SQL_BATCH_SIZE } from "../../utils/chunks.js";
|
|
5
5
|
import type { Database, RelationTable, ContentReferenceTable } from "../types.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
decodeCursor,
|
|
8
|
+
encodeCursor,
|
|
9
|
+
InvalidCursorError,
|
|
10
|
+
STAGED_CURSOR_MARKER,
|
|
11
|
+
type FindManyResult,
|
|
12
|
+
} from "./types.js";
|
|
13
|
+
|
|
14
|
+
// Each reference-edge row binds six values. Derive the row count so every
|
|
15
|
+
// INSERT stays within D1's 100-parameter statement ceiling.
|
|
16
|
+
const REFERENCE_INSERT_BIND_COLUMNS = 6;
|
|
17
|
+
const D1_MAX_BOUND_PARAMETERS = 100;
|
|
18
|
+
export const REFERENCE_INSERT_BATCH_SIZE = Math.floor(
|
|
19
|
+
D1_MAX_BOUND_PARAMETERS / REFERENCE_INSERT_BIND_COLUMNS,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// Repositioning binds an edge id twice — once to match the CASE branch, once in
|
|
23
|
+
// the row filter. The new position is a literal and binds nothing.
|
|
24
|
+
const REFERENCE_REPOSITION_BIND_COLUMNS = 2;
|
|
25
|
+
const REFERENCE_REPOSITION_BATCH_SIZE = Math.floor(
|
|
26
|
+
D1_MAX_BOUND_PARAMETERS / REFERENCE_REPOSITION_BIND_COLUMNS,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
/** A reference edge as it is written. */
|
|
30
|
+
interface EdgeInsert {
|
|
31
|
+
id: string;
|
|
32
|
+
relation_id: string;
|
|
33
|
+
parent_group: string;
|
|
34
|
+
child_group: string;
|
|
35
|
+
sort_order: number;
|
|
36
|
+
created_at: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Where an existing edge should sit in its parent's list. */
|
|
40
|
+
interface EdgePosition {
|
|
41
|
+
id: string;
|
|
42
|
+
sortOrder: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Narrow a computed position to a non-negative integer before it is written as
|
|
47
|
+
* a SQL literal. Every caller passes an array index; this is what keeps that
|
|
48
|
+
* true at the one place the value stops being a bound parameter.
|
|
49
|
+
*/
|
|
50
|
+
function asPosition(sortOrder: number): number {
|
|
51
|
+
if (!Number.isInteger(sortOrder) || sortOrder < 0) {
|
|
52
|
+
throw new TypeError(`Invalid reference sort order: ${sortOrder}`);
|
|
53
|
+
}
|
|
54
|
+
return sortOrder;
|
|
55
|
+
}
|
|
7
56
|
|
|
57
|
+
/**
|
|
58
|
+
* A relation definition. Not localized: a relation joins the same two
|
|
59
|
+
* collections whatever language you read it in, and its role labels are
|
|
60
|
+
* single-valued like a collection's or a field's. That is what lets `slug` be
|
|
61
|
+
* unique outright (migration 086) and resolve without a locale.
|
|
62
|
+
*/
|
|
8
63
|
export interface Relation {
|
|
9
64
|
id: string;
|
|
10
|
-
|
|
65
|
+
slug: string;
|
|
11
66
|
parentCollection: string;
|
|
12
67
|
childCollection: string;
|
|
13
68
|
parentLabel: string;
|
|
14
69
|
childLabel: string;
|
|
15
|
-
|
|
16
|
-
|
|
70
|
+
parentLabelSingular: string | null;
|
|
71
|
+
childLabelSingular: string | null;
|
|
72
|
+
/** How many children one parent may hold. `null` means unlimited. */
|
|
73
|
+
maxChildrenPerParent: number | null;
|
|
74
|
+
/** How many parents one child may hold. `null` means unlimited. */
|
|
75
|
+
maxParentsPerChild: number | null;
|
|
17
76
|
}
|
|
18
77
|
|
|
19
78
|
export interface CreateRelationInput {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
parentCollection?: string;
|
|
24
|
-
/** Required for a base relation; ignored (inherited from the source) when
|
|
25
|
-
* `translationOf` is set. */
|
|
26
|
-
childCollection?: string;
|
|
79
|
+
slug: string;
|
|
80
|
+
parentCollection: string;
|
|
81
|
+
childCollection: string;
|
|
27
82
|
parentLabel: string;
|
|
28
83
|
childLabel: string;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* structural fields (name, parentCollection, childCollection). Only locale +
|
|
34
|
-
* labels may differ on a translation. */
|
|
35
|
-
translationOf?: string;
|
|
84
|
+
parentLabelSingular?: string | null;
|
|
85
|
+
childLabelSingular?: string | null;
|
|
86
|
+
maxChildrenPerParent?: number | null;
|
|
87
|
+
maxParentsPerChild?: number | null;
|
|
36
88
|
}
|
|
37
89
|
|
|
38
90
|
export interface UpdateRelationInput {
|
|
39
|
-
/**
|
|
40
|
-
*
|
|
91
|
+
/** Structural fields are immutable: a reference field stores the slug, and
|
|
92
|
+
* the edges are keyed by the id. */
|
|
41
93
|
parentLabel?: string;
|
|
42
94
|
childLabel?: string;
|
|
95
|
+
parentLabelSingular?: string | null;
|
|
96
|
+
childLabelSingular?: string | null;
|
|
97
|
+
maxChildrenPerParent?: number | null;
|
|
98
|
+
maxParentsPerChild?: number | null;
|
|
43
99
|
}
|
|
44
100
|
|
|
45
101
|
export interface ContentReference {
|
|
46
102
|
id: string;
|
|
47
|
-
|
|
103
|
+
relationId: string;
|
|
48
104
|
parentGroup: string;
|
|
49
105
|
childGroup: string;
|
|
50
106
|
sortOrder: number;
|
|
@@ -53,74 +109,47 @@ export interface ContentReference {
|
|
|
53
109
|
/**
|
|
54
110
|
* Content-references repository.
|
|
55
111
|
*
|
|
56
|
-
* Owns relation *definitions* (`_emdash_relations
|
|
57
|
-
* `
|
|
58
|
-
*
|
|
112
|
+
* Owns relation *definitions* (`_emdash_relations`) and the *edge* junction
|
|
113
|
+
* (`_emdash_content_references`, whose endpoints are content
|
|
114
|
+
* `translation_group`s so edges are locale-agnostic, mirroring
|
|
59
115
|
* `content_taxonomies`).
|
|
60
116
|
*
|
|
117
|
+
* A relation is schema, so it is not localized — it sits with
|
|
118
|
+
* `_emdash_collections` and `_emdash_fields`, not with the row-per-locale
|
|
119
|
+
* tables. See migration 086.
|
|
120
|
+
*
|
|
61
121
|
* Like `TaxonomyRepository`, this is not the validation boundary: it trusts its
|
|
62
122
|
* typed inputs. The API slice supplies Zod schemas at the route and enforces
|
|
63
|
-
* collection-agreement / relation-existence invariants in the handler.
|
|
64
|
-
* does not resolve locale fallbacks — callers pass the locale they want.
|
|
123
|
+
* collection-agreement / relation-existence invariants in the handler.
|
|
65
124
|
*/
|
|
66
125
|
export class RelationRepository {
|
|
67
126
|
constructor(private db: Kysely<Database>) {}
|
|
68
127
|
|
|
69
128
|
/**
|
|
70
|
-
* Create a relation.
|
|
71
|
-
*
|
|
72
|
-
* `
|
|
73
|
-
*
|
|
74
|
-
* locale and the two labels are taken from `input`.
|
|
129
|
+
* Create a relation.
|
|
130
|
+
*
|
|
131
|
+
* `slug` is unique across all relations, so a duplicate raises the DB's
|
|
132
|
+
* unique violation for the handler to translate into a conflict.
|
|
75
133
|
*/
|
|
76
134
|
async create(input: CreateRelationInput): Promise<Relation> {
|
|
77
135
|
const id = ulid();
|
|
78
136
|
const now = new Date().toISOString();
|
|
79
137
|
|
|
80
|
-
let translationGroup = id;
|
|
81
|
-
let name: string;
|
|
82
|
-
let parentCollection: string;
|
|
83
|
-
let childCollection: string;
|
|
84
|
-
|
|
85
|
-
if (input.translationOf) {
|
|
86
|
-
const source = await this.findById(input.translationOf);
|
|
87
|
-
// translation_group is NOT NULL here, so we cannot fall back to a
|
|
88
|
-
// fresh group like TaxonomyRepository does — a bad translationOf must
|
|
89
|
-
// fail loudly rather than silently mint an unlinked relation.
|
|
90
|
-
if (!source) throw new Error("Source relation for translation not found");
|
|
91
|
-
translationGroup = source.translationGroup;
|
|
92
|
-
name = source.name;
|
|
93
|
-
parentCollection = source.parentCollection;
|
|
94
|
-
childCollection = source.childCollection;
|
|
95
|
-
} else {
|
|
96
|
-
// A base relation carries its own structural fields. The API layer's Zod
|
|
97
|
-
// schema enforces this; guard here too since the repo trusts its inputs
|
|
98
|
-
// and the columns are NOT NULL.
|
|
99
|
-
if (input.parentCollection === undefined || input.childCollection === undefined) {
|
|
100
|
-
throw new Error(
|
|
101
|
-
"parentCollection and childCollection are required unless translationOf is set",
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
name = input.name;
|
|
105
|
-
parentCollection = input.parentCollection;
|
|
106
|
-
childCollection = input.childCollection;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
138
|
await this.db
|
|
110
139
|
.insertInto("_emdash_relations")
|
|
111
140
|
.values({
|
|
112
141
|
id,
|
|
113
|
-
|
|
114
|
-
parent_collection: parentCollection,
|
|
115
|
-
child_collection: childCollection,
|
|
142
|
+
slug: input.slug,
|
|
143
|
+
parent_collection: input.parentCollection,
|
|
144
|
+
child_collection: input.childCollection,
|
|
116
145
|
parent_label: input.parentLabel,
|
|
117
146
|
child_label: input.childLabel,
|
|
147
|
+
parent_label_singular: input.parentLabelSingular ?? null,
|
|
148
|
+
child_label_singular: input.childLabelSingular ?? null,
|
|
149
|
+
max_children_per_parent: input.maxChildrenPerParent ?? null,
|
|
150
|
+
max_parents_per_child: input.maxParentsPerChild ?? null,
|
|
118
151
|
created_at: now,
|
|
119
152
|
updated_at: now,
|
|
120
|
-
// Omit `locale` so the DB DEFAULT (configured defaultLocale)
|
|
121
|
-
// applies — matches TaxonomyRepository.create.
|
|
122
|
-
...(input.locale !== undefined ? { locale: input.locale } : {}),
|
|
123
|
-
translation_group: translationGroup,
|
|
124
153
|
})
|
|
125
154
|
.execute();
|
|
126
155
|
|
|
@@ -139,62 +168,46 @@ export class RelationRepository {
|
|
|
139
168
|
}
|
|
140
169
|
|
|
141
170
|
/**
|
|
142
|
-
* Find a relation by
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* `TaxonomyRepository.findByName` which returns every term in a taxonomy.
|
|
171
|
+
* Find a relation by its slug. No locale: a slug identifies a relation
|
|
172
|
+
* outright (`UNIQUE(slug)`, migration 086), which is what lets an entry in
|
|
173
|
+
* any locale address it.
|
|
146
174
|
*/
|
|
147
|
-
async
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
175
|
+
async findBySlug(slug: string): Promise<Relation | null> {
|
|
176
|
+
const row = await this.db
|
|
177
|
+
.selectFrom("_emdash_relations")
|
|
178
|
+
.selectAll()
|
|
179
|
+
.where("slug", "=", slug)
|
|
180
|
+
.executeTakeFirst();
|
|
151
181
|
return row ? this.rowToRelation(row) : null;
|
|
152
182
|
}
|
|
153
183
|
|
|
154
|
-
/**
|
|
155
|
-
async
|
|
184
|
+
/** All relations, ordered by slug. */
|
|
185
|
+
async list(): Promise<Relation[]> {
|
|
156
186
|
const rows = await this.db
|
|
157
187
|
.selectFrom("_emdash_relations")
|
|
158
188
|
.selectAll()
|
|
159
|
-
.
|
|
160
|
-
.orderBy("locale", "asc")
|
|
189
|
+
.orderBy("slug", "asc")
|
|
161
190
|
.execute();
|
|
162
191
|
return rows.map((row) => this.rowToRelation(row));
|
|
163
192
|
}
|
|
164
193
|
|
|
165
|
-
/**
|
|
166
|
-
* All relations, ordered by name then id (id is a stable tiebreak for
|
|
167
|
-
* relations sharing a name across locales). Optionally filtered by locale.
|
|
168
|
-
*/
|
|
169
|
-
async list(locale?: string): Promise<Relation[]> {
|
|
170
|
-
let query = this.db
|
|
171
|
-
.selectFrom("_emdash_relations")
|
|
172
|
-
.selectAll()
|
|
173
|
-
.orderBy("name", "asc")
|
|
174
|
-
.orderBy("id", "asc");
|
|
175
|
-
if (locale !== undefined) query = query.where("locale", "=", locale);
|
|
176
|
-
const rows = await query.execute();
|
|
177
|
-
return rows.map((row) => this.rowToRelation(row));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
194
|
/** Relations where `collection` is the parent OR the child side. */
|
|
181
|
-
async findForCollection(collection: string
|
|
182
|
-
|
|
195
|
+
async findForCollection(collection: string): Promise<Relation[]> {
|
|
196
|
+
const rows = await this.db
|
|
183
197
|
.selectFrom("_emdash_relations")
|
|
184
198
|
.selectAll()
|
|
185
199
|
.where((eb) =>
|
|
186
200
|
eb.or([eb("parent_collection", "=", collection), eb("child_collection", "=", collection)]),
|
|
187
201
|
)
|
|
188
|
-
.orderBy("
|
|
189
|
-
.
|
|
190
|
-
if (locale !== undefined) query = query.where("locale", "=", locale);
|
|
191
|
-
const rows = await query.execute();
|
|
202
|
+
.orderBy("slug", "asc")
|
|
203
|
+
.execute();
|
|
192
204
|
return rows.map((row) => this.rowToRelation(row));
|
|
193
205
|
}
|
|
194
206
|
|
|
195
207
|
/**
|
|
196
|
-
* Update
|
|
197
|
-
* immutable
|
|
208
|
+
* Update a relation's role labels and cardinality. Structural fields are
|
|
209
|
+
* immutable — a reference field stores the slug, and the edges are keyed by
|
|
210
|
+
* the id. No-ops when nothing is supplied.
|
|
198
211
|
*/
|
|
199
212
|
async update(id: string, input: UpdateRelationInput): Promise<Relation | null> {
|
|
200
213
|
const existing = await this.findById(id);
|
|
@@ -203,6 +216,18 @@ export class RelationRepository {
|
|
|
203
216
|
const updates: Record<string, unknown> = {};
|
|
204
217
|
if (input.parentLabel !== undefined) updates.parent_label = input.parentLabel;
|
|
205
218
|
if (input.childLabel !== undefined) updates.child_label = input.childLabel;
|
|
219
|
+
if (input.parentLabelSingular !== undefined) {
|
|
220
|
+
updates.parent_label_singular = input.parentLabelSingular;
|
|
221
|
+
}
|
|
222
|
+
if (input.childLabelSingular !== undefined) {
|
|
223
|
+
updates.child_label_singular = input.childLabelSingular;
|
|
224
|
+
}
|
|
225
|
+
if (input.maxChildrenPerParent !== undefined) {
|
|
226
|
+
updates.max_children_per_parent = input.maxChildrenPerParent;
|
|
227
|
+
}
|
|
228
|
+
if (input.maxParentsPerChild !== undefined) {
|
|
229
|
+
updates.max_parents_per_child = input.maxParentsPerChild;
|
|
230
|
+
}
|
|
206
231
|
|
|
207
232
|
if (Object.keys(updates).length > 0) {
|
|
208
233
|
updates.updated_at = new Date().toISOString();
|
|
@@ -213,26 +238,14 @@ export class RelationRepository {
|
|
|
213
238
|
}
|
|
214
239
|
|
|
215
240
|
/**
|
|
216
|
-
* Delete
|
|
217
|
-
*
|
|
218
|
-
* linking precludes a SQL FK). Mirrors `TaxonomyRepository.delete`.
|
|
241
|
+
* Delete a relation and its edges (application-layer cascade — the edge
|
|
242
|
+
* table has no FK).
|
|
219
243
|
*/
|
|
220
244
|
async delete(id: string): Promise<boolean> {
|
|
221
245
|
const relation = await this.findById(id);
|
|
222
246
|
if (!relation) return false;
|
|
223
247
|
|
|
224
|
-
|
|
225
|
-
.selectFrom("_emdash_relations")
|
|
226
|
-
.select("id")
|
|
227
|
-
.where("translation_group", "=", relation.translationGroup)
|
|
228
|
-
.where("id", "!=", id)
|
|
229
|
-
.execute();
|
|
230
|
-
if (siblings.length === 0) {
|
|
231
|
-
await this.db
|
|
232
|
-
.deleteFrom("_emdash_content_references")
|
|
233
|
-
.where("relation_group", "=", relation.translationGroup)
|
|
234
|
-
.execute();
|
|
235
|
-
}
|
|
248
|
+
await this.db.deleteFrom("_emdash_content_references").where("relation_id", "=", id).execute();
|
|
236
249
|
|
|
237
250
|
const result = await this.db
|
|
238
251
|
.deleteFrom("_emdash_relations")
|
|
@@ -241,22 +254,148 @@ export class RelationRepository {
|
|
|
241
254
|
return (result.numDeletedRows ?? 0n) > 0n;
|
|
242
255
|
}
|
|
243
256
|
|
|
244
|
-
/**
|
|
245
|
-
*
|
|
257
|
+
/**
|
|
258
|
+
* Insert one edge only while the end it lands on is still under its limit,
|
|
259
|
+
* deciding and writing in a single statement.
|
|
260
|
+
*
|
|
261
|
+
* A count read before the insert answers for a moment that has passed by the
|
|
262
|
+
* time the row goes in: two requests can both read a free slot and both fill
|
|
263
|
+
* it, and the unique edge constraint does not catch it because they are
|
|
264
|
+
* different pairs. Folding the count into the insert's `WHERE` makes the
|
|
265
|
+
* decision and the write one thing, on D1 as much as anywhere. Returns false
|
|
266
|
+
* when the limit refused the row.
|
|
267
|
+
*/
|
|
268
|
+
private async insertEdgeWithinLimit(
|
|
269
|
+
row: EdgeInsert,
|
|
270
|
+
limitedSide: "parent" | "child",
|
|
271
|
+
limit: number,
|
|
272
|
+
): Promise<boolean> {
|
|
273
|
+
const column = limitedSide === "parent" ? "parent_group" : "child_group";
|
|
274
|
+
const group = limitedSide === "parent" ? row.parent_group : row.child_group;
|
|
275
|
+
const result = await sql`
|
|
276
|
+
INSERT INTO ${sql.ref("_emdash_content_references")}
|
|
277
|
+
(id, relation_id, parent_group, child_group, sort_order, created_at)
|
|
278
|
+
SELECT ${row.id}, ${row.relation_id}, ${row.parent_group}, ${row.child_group},
|
|
279
|
+
${row.sort_order}, ${row.created_at}
|
|
280
|
+
WHERE (
|
|
281
|
+
SELECT COUNT(*) FROM ${sql.ref("_emdash_content_references")}
|
|
282
|
+
WHERE relation_id = ${row.relation_id} AND ${sql.ref(column)} = ${group}
|
|
283
|
+
) < ${limit}
|
|
284
|
+
`.execute(this.db);
|
|
285
|
+
return (result.numAffectedRows ?? 0n) > 0n;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Write new edges, taking back the ones already written if the limited end
|
|
290
|
+
* refuses a later one.
|
|
291
|
+
*
|
|
292
|
+
* Returns the refused group in a one-element array, or an empty array when
|
|
293
|
+
* every row went in. The rollback is what lets a replacement add before it
|
|
294
|
+
* removes: on D1 nothing else can take a partial write back.
|
|
295
|
+
*
|
|
296
|
+
* An unlimited end cannot refuse anything, so its rows go in as batches; a
|
|
297
|
+
* limited one takes a statement per edge, because a limit enforced only by a
|
|
298
|
+
* count before the write is one two requests can both walk past.
|
|
299
|
+
*/
|
|
300
|
+
private async insertEdges(
|
|
301
|
+
rows: EdgeInsert[],
|
|
302
|
+
limitedSide: "parent" | "child",
|
|
303
|
+
limit: number | null,
|
|
304
|
+
): Promise<string[]> {
|
|
305
|
+
if (rows.length === 0) return [];
|
|
306
|
+
|
|
307
|
+
if (limit === null) {
|
|
308
|
+
for (const rowBatch of chunks(rows, REFERENCE_INSERT_BATCH_SIZE)) {
|
|
309
|
+
// oxlint-disable-next-line no-await-in-loop -- one statement per D1-safe batch
|
|
310
|
+
await this.db
|
|
311
|
+
.insertInto("_emdash_content_references")
|
|
312
|
+
.values(rowBatch)
|
|
313
|
+
.onConflict((oc) => oc.doNothing())
|
|
314
|
+
.execute();
|
|
315
|
+
}
|
|
316
|
+
return [];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const written: string[] = [];
|
|
320
|
+
for (const row of rows) {
|
|
321
|
+
// oxlint-disable-next-line no-await-in-loop -- one statement per edge is what makes the limit hold
|
|
322
|
+
const inserted = await this.insertEdgeWithinLimit(row, limitedSide, limit);
|
|
323
|
+
if (inserted) {
|
|
324
|
+
written.push(row.id);
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
await this.deleteEdgesById(written);
|
|
328
|
+
return [limitedSide === "parent" ? row.parent_group : row.child_group];
|
|
329
|
+
}
|
|
330
|
+
return [];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Remove edges by id, in D1-safe batches. */
|
|
334
|
+
private async deleteEdgesById(ids: string[]): Promise<void> {
|
|
335
|
+
for (const idBatch of chunks(ids, SQL_BATCH_SIZE)) {
|
|
336
|
+
// oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
|
|
337
|
+
await this.db.deleteFrom("_emdash_content_references").where("id", "in", idBatch).execute();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Move kept edges to their new positions, a statement per batch rather than
|
|
343
|
+
* one per edge: dragging one entry up a long list moves every entry below it,
|
|
344
|
+
* and that is a single editor action.
|
|
345
|
+
*/
|
|
346
|
+
private async repositionEdges(moves: EdgePosition[]): Promise<void> {
|
|
347
|
+
for (const moveBatch of chunks(moves, REFERENCE_REPOSITION_BATCH_SIZE)) {
|
|
348
|
+
// The position is a literal, not a bind: it is an index this method
|
|
349
|
+
// computed, and every branch of a CASE binding one would leave Postgres
|
|
350
|
+
// inferring the result type from parameters alone.
|
|
351
|
+
const branches = moveBatch.map(
|
|
352
|
+
(move) => sql`WHEN ${move.id} THEN ${sql.lit(asPosition(move.sortOrder))}`,
|
|
353
|
+
);
|
|
354
|
+
// oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
|
|
355
|
+
await this.db
|
|
356
|
+
.updateTable("_emdash_content_references")
|
|
357
|
+
.set({
|
|
358
|
+
sort_order: sql<number>`CASE ${sql.ref("id")} ${sql.join(branches, sql` `)} END`,
|
|
359
|
+
})
|
|
360
|
+
.where(
|
|
361
|
+
"id",
|
|
362
|
+
"in",
|
|
363
|
+
moveBatch.map((move) => move.id),
|
|
364
|
+
)
|
|
365
|
+
.execute();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/** Normalize a relation id OR slug to its id. Returns null for an unknown
|
|
370
|
+
* relation (edge methods then no-op, matching
|
|
246
371
|
* `TaxonomyRepository.attachToEntry`). */
|
|
247
|
-
private async
|
|
372
|
+
private async resolveRelationId(idOrSlug: string): Promise<string | null> {
|
|
373
|
+
return (await this.resolveRelationLimits(idOrSlug))?.id ?? null;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/** The same lookup, carrying the limits an edge write has to hold to. */
|
|
377
|
+
private async resolveRelationLimits(idOrSlug: string): Promise<{
|
|
378
|
+
id: string;
|
|
379
|
+
maxChildrenPerParent: number | null;
|
|
380
|
+
maxParentsPerChild: number | null;
|
|
381
|
+
} | null> {
|
|
248
382
|
const row = await this.db
|
|
249
383
|
.selectFrom("_emdash_relations")
|
|
250
|
-
.select(["
|
|
251
|
-
.where((eb) => eb.or([eb("id", "=",
|
|
384
|
+
.select(["id", "max_children_per_parent", "max_parents_per_child"])
|
|
385
|
+
.where((eb) => eb.or([eb("id", "=", idOrSlug), eb("slug", "=", idOrSlug)]))
|
|
252
386
|
.executeTakeFirst();
|
|
253
|
-
|
|
387
|
+
if (!row) return null;
|
|
388
|
+
return {
|
|
389
|
+
id: row.id,
|
|
390
|
+
maxChildrenPerParent: row.max_children_per_parent,
|
|
391
|
+
maxParentsPerChild: row.max_parents_per_child,
|
|
392
|
+
};
|
|
254
393
|
}
|
|
255
394
|
|
|
256
395
|
private rowToReference(row: Selectable<ContentReferenceTable>): ContentReference {
|
|
257
396
|
return {
|
|
258
397
|
id: row.id,
|
|
259
|
-
|
|
398
|
+
relationId: row.relation_id,
|
|
260
399
|
parentGroup: row.parent_group,
|
|
261
400
|
childGroup: row.child_group,
|
|
262
401
|
sortOrder: row.sort_order,
|
|
@@ -279,15 +418,15 @@ export class RelationRepository {
|
|
|
279
418
|
childGroup: string,
|
|
280
419
|
sortOrder?: number,
|
|
281
420
|
): Promise<void> {
|
|
282
|
-
const
|
|
283
|
-
if (!
|
|
421
|
+
const relationId = await this.resolveRelationId(relation);
|
|
422
|
+
if (!relationId) return;
|
|
284
423
|
|
|
285
424
|
let order = sortOrder;
|
|
286
425
|
if (order === undefined) {
|
|
287
426
|
const max = await this.db
|
|
288
427
|
.selectFrom("_emdash_content_references")
|
|
289
428
|
.select((eb) => eb.fn.max("sort_order").as("max"))
|
|
290
|
-
.where("
|
|
429
|
+
.where("relation_id", "=", relationId)
|
|
291
430
|
.where("parent_group", "=", parentGroup)
|
|
292
431
|
.executeTakeFirst();
|
|
293
432
|
order = max?.max === null || max?.max === undefined ? 0 : Number(max.max) + 1;
|
|
@@ -297,7 +436,7 @@ export class RelationRepository {
|
|
|
297
436
|
.insertInto("_emdash_content_references")
|
|
298
437
|
.values({
|
|
299
438
|
id: ulid(),
|
|
300
|
-
|
|
439
|
+
relation_id: relationId,
|
|
301
440
|
parent_group: parentGroup,
|
|
302
441
|
child_group: childGroup,
|
|
303
442
|
sort_order: order,
|
|
@@ -309,12 +448,12 @@ export class RelationRepository {
|
|
|
309
448
|
|
|
310
449
|
/** Remove one `parentGroup → childGroup` edge under a relation. */
|
|
311
450
|
async removeReference(relation: string, parentGroup: string, childGroup: string): Promise<void> {
|
|
312
|
-
const
|
|
313
|
-
if (!
|
|
451
|
+
const relationId = await this.resolveRelationId(relation);
|
|
452
|
+
if (!relationId) return;
|
|
314
453
|
|
|
315
454
|
await this.db
|
|
316
455
|
.deleteFrom("_emdash_content_references")
|
|
317
|
-
.where("
|
|
456
|
+
.where("relation_id", "=", relationId)
|
|
318
457
|
.where("parent_group", "=", parentGroup)
|
|
319
458
|
.where("child_group", "=", childGroup)
|
|
320
459
|
.execute();
|
|
@@ -322,13 +461,13 @@ export class RelationRepository {
|
|
|
322
461
|
|
|
323
462
|
/** Forward traversal: a parent's children for a relation, ordered. */
|
|
324
463
|
async getChildren(relation: string, parentGroup: string): Promise<ContentReference[]> {
|
|
325
|
-
const
|
|
326
|
-
if (!
|
|
464
|
+
const relationId = await this.resolveRelationId(relation);
|
|
465
|
+
if (!relationId) return [];
|
|
327
466
|
|
|
328
467
|
const rows = await this.db
|
|
329
468
|
.selectFrom("_emdash_content_references")
|
|
330
469
|
.selectAll()
|
|
331
|
-
.where("
|
|
470
|
+
.where("relation_id", "=", relationId)
|
|
332
471
|
.where("parent_group", "=", parentGroup)
|
|
333
472
|
.orderBy("sort_order", "asc")
|
|
334
473
|
.orderBy("id", "asc")
|
|
@@ -348,31 +487,63 @@ export class RelationRepository {
|
|
|
348
487
|
parentGroup: string,
|
|
349
488
|
options: { limit?: number; cursor?: string } = {},
|
|
350
489
|
): Promise<FindManyResult<ContentReference>> {
|
|
351
|
-
const
|
|
352
|
-
if (!
|
|
490
|
+
const relationId = await this.resolveRelationId(relation);
|
|
491
|
+
if (!relationId) return { items: [] };
|
|
492
|
+
return this.getChildrenPageById(relationId, parentGroup, options);
|
|
493
|
+
}
|
|
353
494
|
|
|
495
|
+
/** `getChildrenPage` for a caller that already holds the relation's id. */
|
|
496
|
+
async getChildrenPageById(
|
|
497
|
+
relationId: string,
|
|
498
|
+
parentGroup: string,
|
|
499
|
+
options: { limit?: number; cursor?: string } = {},
|
|
500
|
+
): Promise<FindManyResult<ContentReference>> {
|
|
354
501
|
const limit = Math.min(options.limit || 50, 100);
|
|
355
502
|
|
|
356
503
|
let query = this.db
|
|
357
504
|
.selectFrom("_emdash_content_references")
|
|
358
505
|
.selectAll()
|
|
359
|
-
.where("
|
|
506
|
+
.where("relation_id", "=", relationId)
|
|
360
507
|
.where("parent_group", "=", parentGroup);
|
|
361
508
|
|
|
362
509
|
if (options.cursor) {
|
|
363
510
|
const decoded = decodeCursor(options.cursor);
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
511
|
+
if (decoded.orderValue === STAGED_CURSOR_MARKER) {
|
|
512
|
+
// A cursor issued over a draft's pending selection anchors on a
|
|
513
|
+
// translation group rather than a row here, which is what a render
|
|
514
|
+
// sees when the draft publishes mid-pagination. Resume after that
|
|
515
|
+
// group's edge so the walk continues; if the group is no longer
|
|
516
|
+
// selected there is nothing to resume from, so the page restarts.
|
|
517
|
+
query = query.where((eb) => {
|
|
518
|
+
const anchor = () =>
|
|
519
|
+
eb
|
|
520
|
+
.selectFrom("_emdash_content_references as anchor")
|
|
521
|
+
.where("anchor.relation_id", "=", relationId)
|
|
522
|
+
.where("anchor.parent_group", "=", parentGroup)
|
|
523
|
+
.where("anchor.child_group", "=", decoded.id);
|
|
524
|
+
return eb.or([
|
|
525
|
+
eb.not(eb.exists(anchor().select("anchor.id"))),
|
|
526
|
+
eb("sort_order", ">", anchor().select("anchor.sort_order")),
|
|
527
|
+
eb.and([
|
|
528
|
+
eb("sort_order", "=", anchor().select("anchor.sort_order")),
|
|
529
|
+
eb("id", ">", anchor().select("anchor.id")),
|
|
530
|
+
]),
|
|
531
|
+
]);
|
|
532
|
+
});
|
|
533
|
+
} else {
|
|
534
|
+
const sortOrder = Number(decoded.orderValue);
|
|
535
|
+
// `decodeCursor` only guarantees `orderValue` is a string; a hand-crafted
|
|
536
|
+
// cursor with a non-numeric order value would coerce to NaN and blow up at
|
|
537
|
+
// the driver bind as a 500. A bad cursor is a client error — surface it as
|
|
538
|
+
// INVALID_CURSOR (400). Server-issued cursors are always numeric here.
|
|
539
|
+
if (!Number.isFinite(sortOrder)) throw new InvalidCursorError(options.cursor);
|
|
540
|
+
query = query.where((eb) =>
|
|
541
|
+
eb.or([
|
|
542
|
+
eb("sort_order", ">", sortOrder),
|
|
543
|
+
eb.and([eb("sort_order", "=", sortOrder), eb("id", ">", decoded.id)]),
|
|
544
|
+
]),
|
|
545
|
+
);
|
|
546
|
+
}
|
|
376
547
|
}
|
|
377
548
|
|
|
378
549
|
const rows = await query
|
|
@@ -393,13 +564,13 @@ export class RelationRepository {
|
|
|
393
564
|
|
|
394
565
|
/** Backlink traversal: the parents that reference a child for a relation. */
|
|
395
566
|
async getParents(relation: string, childGroup: string): Promise<ContentReference[]> {
|
|
396
|
-
const
|
|
397
|
-
if (!
|
|
567
|
+
const relationId = await this.resolveRelationId(relation);
|
|
568
|
+
if (!relationId) return [];
|
|
398
569
|
|
|
399
570
|
const rows = await this.db
|
|
400
571
|
.selectFrom("_emdash_content_references")
|
|
401
572
|
.selectAll()
|
|
402
|
-
.where("
|
|
573
|
+
.where("relation_id", "=", relationId)
|
|
403
574
|
.where("child_group", "=", childGroup)
|
|
404
575
|
.orderBy("id", "asc")
|
|
405
576
|
.execute();
|
|
@@ -408,58 +579,254 @@ export class RelationRepository {
|
|
|
408
579
|
|
|
409
580
|
/**
|
|
410
581
|
* Replace all children of `parentGroup` under a relation with `childGroups`,
|
|
411
|
-
* assigning positional sort_order (index in the deduped array).
|
|
412
|
-
*
|
|
413
|
-
* the set is small (one parent's children). Mirrors the intent of
|
|
414
|
-
* `TaxonomyRepository.setTermsForEntry`.
|
|
582
|
+
* assigning positional sort_order (index in the deduped array).
|
|
583
|
+
* Mirrors the intent of `TaxonomyRepository.setTermsForEntry`.
|
|
415
584
|
*
|
|
416
585
|
* A parent references a given child at most once (the unique edge), so
|
|
417
586
|
* duplicate `childGroups` are collapsed first-occurrence-wins rather than
|
|
418
|
-
* relying on the insert's onConflict to silently drop them.
|
|
419
|
-
*
|
|
420
|
-
*
|
|
587
|
+
* relying on the insert's onConflict to silently drop them.
|
|
588
|
+
*
|
|
589
|
+
* Written as a diff, in the order add → remove → reposition, rather than as a
|
|
590
|
+
* delete of the whole end followed by a re-insert. There is no transaction on
|
|
591
|
+
* D1: a replacement that removed first would leave the parent holding nothing
|
|
592
|
+
* the moment the far side refused one of the additions, and report a failed
|
|
593
|
+
* save over an emptied field. Additions already written come back out when a
|
|
594
|
+
* later one is refused, so a refused call leaves the selection as it found it.
|
|
595
|
+
* The diff also keeps an edge the caller is merely re-stating out of the far
|
|
596
|
+
* side's count, which a delete-and-reinsert survives only because its delete
|
|
597
|
+
* frees the slot a moment before it asks for it back.
|
|
421
598
|
*
|
|
422
599
|
* Concurrency: two simultaneous replace-all calls for the same (relation,
|
|
423
|
-
* parent) can interleave
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
600
|
+
* parent) can interleave and merge into the union of both sets (a lost update
|
|
601
|
+
* — neither "replace" wins). This is non-corrupting — keyset pagination stays
|
|
602
|
+
* totally ordered via the `(sort_order, id)` tiebreak even with duplicate
|
|
603
|
+
* sort_orders — and a single client editing one parent's children serially
|
|
604
|
+
* never hits it. A D1-portable fix isn't available (no multi-statement
|
|
605
|
+
* transactions), so concurrent replace-all on one parent is unsupported by
|
|
606
|
+
* design rather than guarded here.
|
|
607
|
+
*
|
|
608
|
+
* Returns the child group `maxParentsPerChild` refused, in a one-element
|
|
609
|
+
* array — empty unless the relation limits that end and something else has
|
|
610
|
+
* taken the slot since the caller resolved its selection.
|
|
430
611
|
*/
|
|
431
|
-
async setChildren(
|
|
432
|
-
|
|
433
|
-
|
|
612
|
+
async setChildren(
|
|
613
|
+
relation: string,
|
|
614
|
+
parentGroup: string,
|
|
615
|
+
childGroups: string[],
|
|
616
|
+
): Promise<string[]> {
|
|
617
|
+
const rel = await this.resolveRelationLimits(relation);
|
|
618
|
+
if (!rel) return [];
|
|
434
619
|
|
|
435
|
-
await this.db
|
|
436
|
-
.
|
|
437
|
-
.
|
|
620
|
+
const existing = await this.db
|
|
621
|
+
.selectFrom("_emdash_content_references")
|
|
622
|
+
.select(["id", "child_group", "sort_order"])
|
|
623
|
+
.where("relation_id", "=", rel.id)
|
|
438
624
|
.where("parent_group", "=", parentGroup)
|
|
439
625
|
.execute();
|
|
626
|
+
const existingChildren = new Set(existing.map((row) => row.child_group));
|
|
440
627
|
|
|
441
628
|
// Collapse duplicates so positional sort_order has no gaps.
|
|
442
629
|
const uniqueChildGroups = [...new Set(childGroups)];
|
|
443
|
-
|
|
630
|
+
const positions = new Map(uniqueChildGroups.map((childGroup, index) => [childGroup, index]));
|
|
444
631
|
|
|
445
632
|
const now = new Date().toISOString();
|
|
446
|
-
|
|
447
|
-
.
|
|
448
|
-
.
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
633
|
+
const additions = uniqueChildGroups
|
|
634
|
+
.map((childGroup, index) => ({ childGroup, index }))
|
|
635
|
+
.filter(({ childGroup }) => !existingChildren.has(childGroup))
|
|
636
|
+
.map(({ childGroup, index }) => ({
|
|
637
|
+
id: ulid(),
|
|
638
|
+
relation_id: rel.id,
|
|
639
|
+
parent_group: parentGroup,
|
|
640
|
+
child_group: childGroup,
|
|
641
|
+
sort_order: index,
|
|
642
|
+
created_at: now,
|
|
643
|
+
}));
|
|
644
|
+
|
|
645
|
+
const rejected = await this.insertEdges(additions, "child", rel.maxParentsPerChild);
|
|
646
|
+
if (rejected.length > 0) return rejected;
|
|
647
|
+
|
|
648
|
+
const removals: string[] = [];
|
|
649
|
+
const repositions: EdgePosition[] = [];
|
|
650
|
+
for (const row of existing) {
|
|
651
|
+
const position = positions.get(row.child_group);
|
|
652
|
+
if (position === undefined) removals.push(row.id);
|
|
653
|
+
else if (position !== row.sort_order) repositions.push({ id: row.id, sortOrder: position });
|
|
654
|
+
}
|
|
655
|
+
await this.deleteEdgesById(removals);
|
|
656
|
+
await this.repositionEdges(repositions);
|
|
657
|
+
return [];
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Replace all parents of `childGroup` under a relation with `parentGroups`:
|
|
662
|
+
* the mirror of `setChildren`, for a field bound to the child side.
|
|
663
|
+
*
|
|
664
|
+
* Duplicates collapse first-occurrence-wins, and the same diff ordering and
|
|
665
|
+
* non-transactional caveats apply — see `setChildren`, including that two
|
|
666
|
+
* concurrent replace-all calls for one (relation, child) can merge.
|
|
667
|
+
*
|
|
668
|
+
* `sort_order` orders children within a parent and has no counterpart on this
|
|
669
|
+
* side, so a *new* edge takes the next position among that parent's existing
|
|
670
|
+
* children rather than a position in this child's list. A parent the caller
|
|
671
|
+
* re-states keeps the position it already holds: that position is the other
|
|
672
|
+
* side's list order, and saving a backlink field must not rewrite it. A
|
|
673
|
+
* child-side field therefore has no order of its own; `getParents` reads by
|
|
674
|
+
* `id`.
|
|
675
|
+
*
|
|
676
|
+
* Returns the parent group `maxChildrenPerParent` refused, the mirror of what
|
|
677
|
+
* `setChildren` returns.
|
|
678
|
+
*/
|
|
679
|
+
async setParents(
|
|
680
|
+
relation: string,
|
|
681
|
+
childGroup: string,
|
|
682
|
+
parentGroups: string[],
|
|
683
|
+
): Promise<string[]> {
|
|
684
|
+
const rel = await this.resolveRelationLimits(relation);
|
|
685
|
+
if (!rel) return [];
|
|
686
|
+
const relationId = rel.id;
|
|
687
|
+
|
|
688
|
+
const existing = await this.db
|
|
689
|
+
.selectFrom("_emdash_content_references")
|
|
690
|
+
.select(["id", "parent_group"])
|
|
691
|
+
.where("relation_id", "=", relationId)
|
|
692
|
+
.where("child_group", "=", childGroup)
|
|
462
693
|
.execute();
|
|
694
|
+
const existingParents = new Set(existing.map((row) => row.parent_group));
|
|
695
|
+
|
|
696
|
+
const uniqueParentGroups = [...new Set(parentGroups)];
|
|
697
|
+
const selected = new Set(uniqueParentGroups);
|
|
698
|
+
const newParents = uniqueParentGroups.filter(
|
|
699
|
+
(parentGroup) => !existingParents.has(parentGroup),
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
// One query for every new parent's highest position, so appending stays a
|
|
703
|
+
// fixed number of round trips rather than one per parent.
|
|
704
|
+
const nextSortOrder = new Map<string, number>();
|
|
705
|
+
for (const groupBatch of chunks(newParents, REFERENCE_INSERT_BATCH_SIZE)) {
|
|
706
|
+
// oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
|
|
707
|
+
const maxima = await this.db
|
|
708
|
+
.selectFrom("_emdash_content_references")
|
|
709
|
+
.select((eb) => ["parent_group", eb.fn.max("sort_order").as("max")])
|
|
710
|
+
.where("relation_id", "=", relationId)
|
|
711
|
+
.where("parent_group", "in", groupBatch)
|
|
712
|
+
.groupBy("parent_group")
|
|
713
|
+
.execute();
|
|
714
|
+
for (const row of maxima) {
|
|
715
|
+
nextSortOrder.set(row.parent_group, row.max === null ? 0 : Number(row.max) + 1);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const now = new Date().toISOString();
|
|
720
|
+
const additions = newParents.map((parentGroup) => ({
|
|
721
|
+
id: ulid(),
|
|
722
|
+
relation_id: relationId,
|
|
723
|
+
parent_group: parentGroup,
|
|
724
|
+
child_group: childGroup,
|
|
725
|
+
sort_order: nextSortOrder.get(parentGroup) ?? 0,
|
|
726
|
+
created_at: now,
|
|
727
|
+
}));
|
|
728
|
+
|
|
729
|
+
const rejected = await this.insertEdges(additions, "parent", rel.maxChildrenPerParent);
|
|
730
|
+
if (rejected.length > 0) return rejected;
|
|
731
|
+
|
|
732
|
+
await this.deleteEdgesById(
|
|
733
|
+
existing.filter((row) => !selected.has(row.parent_group)).map((row) => row.id),
|
|
734
|
+
);
|
|
735
|
+
return [];
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Copy every outgoing edge of `fromParentGroup` onto `toParentGroup`,
|
|
740
|
+
* preserving relation, child, and sort order. Used when duplicating a content
|
|
741
|
+
* entry so the copy carries the same reference selections (edges are
|
|
742
|
+
* storage-less, keyed by translation_group, so they don't ride along in the
|
|
743
|
+
* row's `data`). Only the parent side is copied; backlinks pointing at the
|
|
744
|
+
* original stay on the original. Idempotent per edge via onConflict.
|
|
745
|
+
*
|
|
746
|
+
* A copy is still a new edge, so it holds to `maxParentsPerChild` like any
|
|
747
|
+
* other: a child already at its limit cannot also belong to the copy. Returns
|
|
748
|
+
* the child group that refused, in a one-element array, having taken back
|
|
749
|
+
* every edge this call had already written — the caller decides what a
|
|
750
|
+
* duplicate that cannot carry its selection should do.
|
|
751
|
+
*/
|
|
752
|
+
async copyParentEdges(fromParentGroup: string, toParentGroup: string): Promise<string[]> {
|
|
753
|
+
const rows = await this.db
|
|
754
|
+
.selectFrom("_emdash_content_references")
|
|
755
|
+
.selectAll()
|
|
756
|
+
.where("parent_group", "=", fromParentGroup)
|
|
757
|
+
.execute();
|
|
758
|
+
if (rows.length === 0) return [];
|
|
759
|
+
|
|
760
|
+
const now = new Date().toISOString();
|
|
761
|
+
// Each relation carries its own limit, so the copies are written a relation
|
|
762
|
+
// at a time rather than as one undifferentiated batch.
|
|
763
|
+
const byRelation = new Map<string, EdgeInsert[]>();
|
|
764
|
+
for (const row of rows) {
|
|
765
|
+
const copies = byRelation.get(row.relation_id) ?? [];
|
|
766
|
+
copies.push({
|
|
767
|
+
id: ulid(),
|
|
768
|
+
relation_id: row.relation_id,
|
|
769
|
+
parent_group: toParentGroup,
|
|
770
|
+
child_group: row.child_group,
|
|
771
|
+
sort_order: row.sort_order,
|
|
772
|
+
created_at: now,
|
|
773
|
+
});
|
|
774
|
+
byRelation.set(row.relation_id, copies);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
const written: string[] = [];
|
|
778
|
+
for (const [relationId, copies] of byRelation) {
|
|
779
|
+
// oxlint-disable-next-line no-await-in-loop -- each relation's limit gates its own copies
|
|
780
|
+
const rel = await this.resolveRelationLimits(relationId);
|
|
781
|
+
// oxlint-disable-next-line no-await-in-loop -- sequential so a refusal stops the rest
|
|
782
|
+
const rejected = await this.insertEdges(copies, "child", rel?.maxParentsPerChild ?? null);
|
|
783
|
+
if (rejected.length > 0) {
|
|
784
|
+
// `insertEdges` took back its own partial write; the relations already
|
|
785
|
+
// copied are this call's to undo.
|
|
786
|
+
await this.deleteEdgesById(written);
|
|
787
|
+
return rejected;
|
|
788
|
+
}
|
|
789
|
+
written.push(...copies.map((copy) => copy.id));
|
|
790
|
+
}
|
|
791
|
+
return [];
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* How many edges each of `groups` already holds at one end of a relation,
|
|
796
|
+
* ignoring edges whose opposite end is `excludeOppositeGroup`.
|
|
797
|
+
*
|
|
798
|
+
* The exclusion is what lets a re-save of an unchanged selection pass: the
|
|
799
|
+
* selecting entry's own edges are not counted against the limit it is about
|
|
800
|
+
* to re-establish. Groups with no edges are absent from the map.
|
|
801
|
+
*/
|
|
802
|
+
async countEdgesByGroup(
|
|
803
|
+
relationId: string,
|
|
804
|
+
side: "parent" | "child",
|
|
805
|
+
groups: string[],
|
|
806
|
+
excludeOppositeGroup: string | null,
|
|
807
|
+
): Promise<Map<string, number>> {
|
|
808
|
+
const column = side === "parent" ? "parent_group" : "child_group";
|
|
809
|
+
const opposite = side === "parent" ? "child_group" : "parent_group";
|
|
810
|
+
|
|
811
|
+
const counts = new Map<string, number>();
|
|
812
|
+
for (const groupBatch of chunks([...new Set(groups)], SQL_BATCH_SIZE)) {
|
|
813
|
+
let query = this.db
|
|
814
|
+
.selectFrom("_emdash_content_references")
|
|
815
|
+
.select((eb) => [column, eb.fn.countAll().as("count")])
|
|
816
|
+
.where("relation_id", "=", relationId)
|
|
817
|
+
.where(column, "in", groupBatch);
|
|
818
|
+
// An entry with no group of its own yet holds no links to discount, and
|
|
819
|
+
// `!= NULL` is never true — it would silently count nothing at all.
|
|
820
|
+
if (excludeOppositeGroup !== null) {
|
|
821
|
+
query = query.where(opposite, "!=", excludeOppositeGroup);
|
|
822
|
+
}
|
|
823
|
+
// oxlint-disable-next-line no-await-in-loop -- one statement per bind-parameter batch
|
|
824
|
+
const rows = await query.groupBy(column).execute();
|
|
825
|
+
for (const row of rows) {
|
|
826
|
+
counts.set(row[column], Number(row.count));
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return counts;
|
|
463
830
|
}
|
|
464
831
|
|
|
465
832
|
/**
|
|
@@ -475,20 +842,46 @@ export class RelationRepository {
|
|
|
475
842
|
childGroup: string,
|
|
476
843
|
options: { limit?: number; cursor?: string } = {},
|
|
477
844
|
): Promise<FindManyResult<ContentReference>> {
|
|
478
|
-
const
|
|
479
|
-
if (!
|
|
845
|
+
const relationId = await this.resolveRelationId(relation);
|
|
846
|
+
if (!relationId) return { items: [] };
|
|
847
|
+
return this.getParentsPageById(relationId, childGroup, options);
|
|
848
|
+
}
|
|
480
849
|
|
|
850
|
+
/** `getParentsPage` for a caller that already holds the relation's id. */
|
|
851
|
+
async getParentsPageById(
|
|
852
|
+
relationId: string,
|
|
853
|
+
childGroup: string,
|
|
854
|
+
options: { limit?: number; cursor?: string } = {},
|
|
855
|
+
): Promise<FindManyResult<ContentReference>> {
|
|
481
856
|
const limit = Math.min(options.limit || 50, 100);
|
|
482
857
|
|
|
483
858
|
let query = this.db
|
|
484
859
|
.selectFrom("_emdash_content_references")
|
|
485
860
|
.selectAll()
|
|
486
|
-
.where("
|
|
861
|
+
.where("relation_id", "=", relationId)
|
|
487
862
|
.where("child_group", "=", childGroup);
|
|
488
863
|
|
|
489
864
|
if (options.cursor) {
|
|
490
865
|
const decoded = decodeCursor(options.cursor);
|
|
491
|
-
|
|
866
|
+
if (decoded.orderValue === STAGED_CURSOR_MARKER) {
|
|
867
|
+
// The mirror of `getChildrenPageById`: a staged cursor anchors on a
|
|
868
|
+
// translation group, which compared against `id` would page from an
|
|
869
|
+
// arbitrary point. Resume after that group's edge, or restart when the
|
|
870
|
+
// group is no longer selected.
|
|
871
|
+
query = query.where((eb) => {
|
|
872
|
+
const anchor = eb
|
|
873
|
+
.selectFrom("_emdash_content_references as anchor")
|
|
874
|
+
.where("anchor.relation_id", "=", relationId)
|
|
875
|
+
.where("anchor.child_group", "=", childGroup)
|
|
876
|
+
.where("anchor.parent_group", "=", decoded.id);
|
|
877
|
+
return eb.or([
|
|
878
|
+
eb.not(eb.exists(anchor.select("anchor.id"))),
|
|
879
|
+
eb("id", ">", anchor.select("anchor.id")),
|
|
880
|
+
]);
|
|
881
|
+
});
|
|
882
|
+
} else {
|
|
883
|
+
query = query.where("id", ">", decoded.id);
|
|
884
|
+
}
|
|
492
885
|
}
|
|
493
886
|
|
|
494
887
|
const rows = await query
|
|
@@ -510,8 +903,8 @@ export class RelationRepository {
|
|
|
510
903
|
* Remove every edge where `group` is the parent OR the child — i.e. ensure no
|
|
511
904
|
* orphaned reference edges survive when a content entry is deleted. The
|
|
512
905
|
* application-layer cascade that group-linking precludes at the SQL level.
|
|
513
|
-
*
|
|
514
|
-
* Returns the number of edges removed.
|
|
906
|
+
* Callers must be sure the whole group is gone: edges outlive any single
|
|
907
|
+
* locale row. Returns the number of edges removed.
|
|
515
908
|
*/
|
|
516
909
|
async clearReferencesForGroup(group: string): Promise<number> {
|
|
517
910
|
const result = await this.db
|
|
@@ -523,12 +916,12 @@ export class RelationRepository {
|
|
|
523
916
|
|
|
524
917
|
/** Count a parent's children under a relation. */
|
|
525
918
|
async countChildren(relation: string, parentGroup: string): Promise<number> {
|
|
526
|
-
const
|
|
527
|
-
if (!
|
|
919
|
+
const relationId = await this.resolveRelationId(relation);
|
|
920
|
+
if (!relationId) return 0;
|
|
528
921
|
const result = await this.db
|
|
529
922
|
.selectFrom("_emdash_content_references")
|
|
530
923
|
.select((eb) => eb.fn.count("id").as("count"))
|
|
531
|
-
.where("
|
|
924
|
+
.where("relation_id", "=", relationId)
|
|
532
925
|
.where("parent_group", "=", parentGroup)
|
|
533
926
|
.executeTakeFirst();
|
|
534
927
|
return Number(result?.count ?? 0);
|
|
@@ -536,17 +929,34 @@ export class RelationRepository {
|
|
|
536
929
|
|
|
537
930
|
/** Count a child's parents (backlinks) under a relation. */
|
|
538
931
|
async countParents(relation: string, childGroup: string): Promise<number> {
|
|
539
|
-
const
|
|
540
|
-
if (!
|
|
932
|
+
const relationId = await this.resolveRelationId(relation);
|
|
933
|
+
if (!relationId) return 0;
|
|
541
934
|
const result = await this.db
|
|
542
935
|
.selectFrom("_emdash_content_references")
|
|
543
936
|
.select((eb) => eb.fn.count("id").as("count"))
|
|
544
|
-
.where("
|
|
937
|
+
.where("relation_id", "=", relationId)
|
|
545
938
|
.where("child_group", "=", childGroup)
|
|
546
939
|
.executeTakeFirst();
|
|
547
940
|
return Number(result?.count ?? 0);
|
|
548
941
|
}
|
|
549
942
|
|
|
943
|
+
/**
|
|
944
|
+
* Total edges per relation, for every relation at once. Relations with no
|
|
945
|
+
* edges are absent from the map.
|
|
946
|
+
*
|
|
947
|
+
* One grouped scan rather than a count per relation: the delete dialogs name
|
|
948
|
+
* how many links go with a relation, and the relations list shows the same
|
|
949
|
+
* number on every row.
|
|
950
|
+
*/
|
|
951
|
+
async countEdgesByRelation(): Promise<Map<string, number>> {
|
|
952
|
+
const rows = await this.db
|
|
953
|
+
.selectFrom("_emdash_content_references")
|
|
954
|
+
.select(["relation_id", (eb) => eb.fn.count("id").as("count")])
|
|
955
|
+
.groupBy("relation_id")
|
|
956
|
+
.execute();
|
|
957
|
+
return new Map(rows.map((row) => [row.relation_id, Number(row.count ?? 0)]));
|
|
958
|
+
}
|
|
959
|
+
|
|
550
960
|
/**
|
|
551
961
|
* Batch child-counts for many parents under a relation. Chunks at
|
|
552
962
|
* SQL_BATCH_SIZE for D1's bind-parameter limit. Returns parent_group → count
|
|
@@ -559,14 +969,14 @@ export class RelationRepository {
|
|
|
559
969
|
): Promise<Map<string, number>> {
|
|
560
970
|
const counts = new Map<string, number>();
|
|
561
971
|
if (parentGroups.length === 0) return counts;
|
|
562
|
-
const
|
|
563
|
-
if (!
|
|
972
|
+
const relationId = await this.resolveRelationId(relation);
|
|
973
|
+
if (!relationId) return counts;
|
|
564
974
|
|
|
565
975
|
for (const chunk of chunks(parentGroups, SQL_BATCH_SIZE)) {
|
|
566
976
|
const rows = await this.db
|
|
567
977
|
.selectFrom("_emdash_content_references")
|
|
568
978
|
.select(["parent_group", (eb) => eb.fn.count("id").as("count")])
|
|
569
|
-
.where("
|
|
979
|
+
.where("relation_id", "=", relationId)
|
|
570
980
|
.where("parent_group", "in", chunk)
|
|
571
981
|
.groupBy("parent_group")
|
|
572
982
|
.execute();
|
|
@@ -580,13 +990,15 @@ export class RelationRepository {
|
|
|
580
990
|
private rowToRelation(row: Selectable<RelationTable>): Relation {
|
|
581
991
|
return {
|
|
582
992
|
id: row.id,
|
|
583
|
-
|
|
993
|
+
slug: row.slug,
|
|
584
994
|
parentCollection: row.parent_collection,
|
|
585
995
|
childCollection: row.child_collection,
|
|
586
996
|
parentLabel: row.parent_label,
|
|
587
997
|
childLabel: row.child_label,
|
|
588
|
-
|
|
589
|
-
|
|
998
|
+
parentLabelSingular: row.parent_label_singular,
|
|
999
|
+
childLabelSingular: row.child_label_singular,
|
|
1000
|
+
maxChildrenPerParent: row.max_children_per_parent,
|
|
1001
|
+
maxParentsPerChild: row.max_parents_per_child,
|
|
590
1002
|
};
|
|
591
1003
|
}
|
|
592
1004
|
}
|