emdash 0.31.1 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapters-C0ONzkUP.d.mts → adapters-BMyNSSZi.d.mts} +9 -1
- package/dist/adapters-BMyNSSZi.d.mts.map +1 -0
- package/dist/after-CBU2vkoO.mjs +96 -0
- package/dist/after-CBU2vkoO.mjs.map +1 -0
- package/dist/{allowed-origins-CCEi9bPI.mjs → allowed-origins-CG1pACtS.mjs} +2 -2
- package/dist/{allowed-origins-CCEi9bPI.mjs.map → allowed-origins-CG1pACtS.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -4
- package/dist/api/route-utils.d.mts.map +1 -1
- package/dist/api/route-utils.mjs +23 -21
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +5 -5
- package/dist/{api-BkqFzIu4.mjs → api-D2hunekQ.mjs} +254 -48
- package/dist/api-D2hunekQ.mjs.map +1 -0
- package/dist/{api-tokens-uPt8UDpx.mjs → api-tokens-CSND0i1z.mjs} +2 -2
- package/dist/{api-tokens-uPt8UDpx.mjs.map → api-tokens-CSND0i1z.mjs.map} +1 -1
- package/dist/{apply-DuXsqll7.mjs → apply-kwNEJW2l.mjs} +36 -23
- package/dist/apply-kwNEJW2l.mjs.map +1 -0
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.mjs +17 -3
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +8 -8
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +8 -8
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.mjs +4 -4
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +10 -10
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +370 -171
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -10
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -10
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -10
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +19 -18
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +19 -18
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +19 -19
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +16 -16
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -12
- package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/index.mjs +12 -12
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +13 -11
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +47 -44
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +47 -44
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +5 -5
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +46 -43
- 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 +46 -43
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +46 -43
- 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 +47 -44
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +47 -44
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +46 -43
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +46 -43
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +46 -43
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -8
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/index.mjs +7 -7
- package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
- package/dist/astro/routes/api/auth/invite/index.mjs +10 -10
- package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
- package/dist/astro/routes/api/auth/logout.mjs +3 -3
- package/dist/astro/routes/api/auth/magic-link/send.mjs +12 -12
- package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/me.mjs +8 -8
- package/dist/astro/routes/api/auth/mode.mjs +3 -3
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
- package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +13 -13
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
- package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
- package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
- package/dist/astro/routes/api/auth/signup/request.mjs +12 -12
- package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +18 -18
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +14 -14
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +19 -17
- 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 +19 -17
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -16
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +10 -10
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/index.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
- package/dist/astro/routes/api/dashboard.mjs +9 -9
- package/dist/astro/routes/api/dev/emails.mjs +3 -3
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +19 -19
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -15
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/media.mjs +10 -10
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +13 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +19 -19
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +28 -27
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +5 -5
- package/dist/astro/routes/api/mcp.mjs +42 -42
- package/dist/astro/routes/api/media/_id_/confirm.d.mts.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +106 -37
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/upload.d.mts +8 -0
- package/dist/astro/routes/api/media/_id_/upload.d.mts.map +1 -0
- package/dist/astro/routes/api/media/_id_/upload.mjs +168 -0
- package/dist/astro/routes/api/media/_id_/upload.mjs.map +1 -0
- package/dist/astro/routes/api/media/_id_/usage.mjs +15 -13
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +22 -15
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
- package/dist/astro/routes/api/media/providers/index.mjs +3 -3
- package/dist/astro/routes/api/media/upload-url.d.mts.map +1 -1
- package/dist/astro/routes/api/media/upload-url.mjs +35 -24
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.mjs +14 -13
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +12 -11
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +12 -11
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +12 -11
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +12 -11
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +12 -11
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +12 -11
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
- package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
- package/dist/astro/routes/api/oauth/register.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
- package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
- package/dist/astro/routes/api/oauth/token.mjs +6 -6
- package/dist/astro/routes/api/openapi.json.mjs +62 -9
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
- package/dist/astro/routes/api/redirects/404s/index.mjs +12 -12
- package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -12
- package/dist/astro/routes/api/redirects/_id_.mjs +14 -13
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +14 -13
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.mjs +19 -17
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +14 -12
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +19 -17
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +46 -43
- 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 +46 -43
- 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 +46 -43
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +46 -43
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +46 -43
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.d.mts +8 -0
- package/dist/astro/routes/api/schema/collections/reorder.d.mts.map +1 -0
- package/dist/astro/routes/api/schema/collections/reorder.mjs +66 -0
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -0
- package/dist/astro/routes/api/schema/index.mjs +12 -8
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +46 -43
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +46 -43
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.d.mts +1 -0
- package/dist/astro/routes/api/search/enable.d.mts.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +18 -13
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +12 -11
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +14 -13
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +8 -7
- package/dist/astro/routes/api/search/stats.mjs.map +1 -1
- package/dist/astro/routes/api/search/suggest.mjs +12 -11
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +11 -11
- package/dist/astro/routes/api/sections/index.mjs +11 -11
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -6
- 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 +5 -5
- package/dist/astro/routes/api/settings.mjs +16 -16
- package/dist/astro/routes/api/setup/admin-verify.mjs +13 -13
- package/dist/astro/routes/api/setup/admin.mjs +12 -12
- package/dist/astro/routes/api/setup/dev-bypass.mjs +31 -29
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
- package/dist/astro/routes/api/setup/index.mjs +33 -31
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +4 -4
- package/dist/astro/routes/api/snapshot.mjs +9 -9
- package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts +8 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +43 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +17 -16
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +17 -16
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +22 -18
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +17 -16
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +7 -7
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -11
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -11
- package/dist/astro/routes/api/widget-areas/_name_.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/index.mjs +11 -11
- package/dist/astro/routes/api/widget-components.mjs +3 -3
- package/dist/astro/routes/robots.txt.mjs +9 -9
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -13
- package/dist/astro/routes/sitemap.xml.mjs +10 -10
- package/dist/astro/types.d.mts +20 -13
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{authorize-6WPZa1xZ.mjs → authorize-qRhWQnel.mjs} +2 -2
- package/dist/{authorize-6WPZa1xZ.mjs.map → authorize-qRhWQnel.mjs.map} +1 -1
- package/dist/{backup-DoW-H0r4.mjs → backup-CtA6LDNw.mjs} +5 -5
- package/dist/{backup-DoW-H0r4.mjs.map → backup-CtA6LDNw.mjs.map} +1 -1
- package/dist/{byline-BTOxUlFF.mjs → byline-Cp6csL84.mjs} +9 -9
- package/dist/{byline-BTOxUlFF.mjs.map → byline-Cp6csL84.mjs.map} +1 -1
- package/dist/{byline-fields-CdU_LTF1.mjs → byline-fields-CNc0Yq5i.mjs} +2 -2
- package/dist/{byline-fields-CdU_LTF1.mjs.map → byline-fields-CNc0Yq5i.mjs.map} +1 -1
- package/dist/{byline-registry-BCuOp4UF.mjs → byline-registry-ZkPKqEwC.mjs} +4 -4
- package/dist/{byline-registry-BCuOp4UF.mjs.map → byline-registry-ZkPKqEwC.mjs.map} +1 -1
- package/dist/{bylines-Bc-3xtpz.mjs → bylines-CEj5CdT4.mjs} +7 -7
- package/dist/{bylines-Bc-3xtpz.mjs.map → bylines-CEj5CdT4.mjs.map} +1 -1
- package/dist/{bylines-oVN0iPwX.mjs → bylines-cf-C9lmF.mjs} +5 -5
- package/dist/{bylines-oVN0iPwX.mjs.map → bylines-cf-C9lmF.mjs.map} +1 -1
- package/dist/cache-C9FptTFR.mjs +108 -0
- package/dist/cache-C9FptTFR.mjs.map +1 -0
- package/dist/{challenge-store-BFzgFRog.mjs → challenge-store-D9VNKELo.mjs} +1 -1
- package/dist/{challenge-store-BFzgFRog.mjs.map → challenge-store-D9VNKELo.mjs.map} +1 -1
- package/dist/{chunks-Bq-5DPrD.mjs → chunks-DbYzib_k.mjs} +2 -2
- package/dist/{chunks-Bq-5DPrD.mjs.map → chunks-DbYzib_k.mjs.map} +1 -1
- package/dist/cli/index.mjs +41 -32
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +2 -2
- package/dist/{comment-B9cUud8H.mjs → comment-BIkJ6Fil.mjs} +3 -3
- package/dist/{comment-B9cUud8H.mjs.map → comment-BIkJ6Fil.mjs.map} +1 -1
- package/dist/{comment-reaction-VUXO981F.mjs → comment-reaction-D-laEceb.mjs} +2 -2
- package/dist/{comment-reaction-VUXO981F.mjs.map → comment-reaction-D-laEceb.mjs.map} +1 -1
- package/dist/{comments-PXj1E9Si.mjs → comments-0_w6KChA.mjs} +3 -3
- package/dist/{comments-PXj1E9Si.mjs.map → comments-0_w6KChA.mjs.map} +1 -1
- package/dist/{components-DZkL4Fx0.mjs → components-BPxrRjpE.mjs} +1 -1
- package/dist/{components-DZkL4Fx0.mjs.map → components-BPxrRjpE.mjs.map} +1 -1
- package/dist/{config-B6b_BobR.mjs → config-DyF3OKg_.mjs} +15 -10
- package/dist/config-DyF3OKg_.mjs.map +1 -0
- package/dist/{content-BC43pICM.mjs → content-CJ94NEx5.mjs} +170 -117
- package/dist/content-CJ94NEx5.mjs.map +1 -0
- package/dist/{content-refresh-CPMSauD3.mjs → content-refresh-Xw7aKmou.mjs} +7 -7
- package/dist/{content-refresh-CPMSauD3.mjs.map → content-refresh-Xw7aKmou.mjs.map} +1 -1
- package/dist/{context-DOurRIrb.mjs → context-C_1nrqnW.mjs} +14 -14
- package/dist/{context-DOurRIrb.mjs.map → context-C_1nrqnW.mjs.map} +1 -1
- package/dist/{cron-BlKIMD_e.mjs → cron-DRV-UC4K.mjs} +1 -1
- package/dist/{cron-BlKIMD_e.mjs.map → cron-DRV-UC4K.mjs.map} +1 -1
- package/dist/{dashboard-CBm4zhc3.mjs → dashboard-DINnNVVU.mjs} +5 -5
- package/dist/{dashboard-CBm4zhc3.mjs.map → dashboard-DINnNVVU.mjs.map} +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +3 -2
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{default-C4v9KP56.mjs → default-BD2FG0xV.mjs} +1 -1
- package/dist/{default-C4v9KP56.mjs.map → default-BD2FG0xV.mjs.map} +1 -1
- package/dist/deferred-tasks-C-WRCcKo.d.mts +9 -0
- package/dist/deferred-tasks-C-WRCcKo.d.mts.map +1 -0
- package/dist/{device-flow-BeA6lUS1.mjs → device-flow-CTqd8mud.mjs} +5 -5
- package/dist/{device-flow-BeA6lUS1.mjs.map → device-flow-CTqd8mud.mjs.map} +1 -1
- package/dist/{dialect-helpers-BtOwo2us.mjs → dialect-helpers-BSbfaO3F.mjs} +43 -16
- package/dist/dialect-helpers-BSbfaO3F.mjs.map +1 -0
- package/dist/{email-console-C-9Ng8DM.mjs → email-console-C6WdcWbL.mjs} +1 -1
- package/dist/{email-console-C-9Ng8DM.mjs.map → email-console-C6WdcWbL.mjs.map} +1 -1
- package/dist/{error-DJ98TRbQ.mjs → error-oh_9i6bR.mjs} +3 -3
- package/dist/{error-DJ98TRbQ.mjs.map → error-oh_9i6bR.mjs.map} +1 -1
- package/dist/{errors-DtEXIQQV.mjs → errors-BucQ8VYz.mjs} +2 -1
- package/dist/errors-BucQ8VYz.mjs.map +1 -0
- package/dist/{escape-CFedIB1C.mjs → escape-CXps5F_v.mjs} +1 -1
- package/dist/{escape-CFedIB1C.mjs.map → escape-CXps5F_v.mjs.map} +1 -1
- package/dist/{field-defs-cache-KfNJ_qLQ.mjs → field-defs-cache-WD82dMQq.mjs} +4 -4
- package/dist/{field-defs-cache-KfNJ_qLQ.mjs.map → field-defs-cache-WD82dMQq.mjs.map} +1 -1
- package/dist/{fts-manager-hyCU9OOp.mjs → fts-manager-BITakW_R.mjs} +37 -13
- package/dist/fts-manager-BITakW_R.mjs.map +1 -0
- package/dist/{hash-DFFrkivP.mjs → hash-Cg0TXJPV.mjs} +8 -4
- package/dist/hash-Cg0TXJPV.mjs.map +1 -0
- package/dist/{hreflang-CIxH_LKz.d.mts → hreflang-BaLCNcDx.d.mts} +2 -2
- package/dist/{hreflang-CIxH_LKz.d.mts.map → hreflang-BaLCNcDx.d.mts.map} +1 -1
- package/dist/{hreflang-CbYeCzl9.mjs → hreflang-BdZuVBhL.mjs} +7 -7
- package/dist/{hreflang-CbYeCzl9.mjs.map → hreflang-BdZuVBhL.mjs.map} +1 -1
- package/dist/{import-oDYCgNYQ.mjs → import-C-9uqyT3.mjs} +6 -6
- package/dist/{import-oDYCgNYQ.mjs.map → import-C-9uqyT3.mjs.map} +1 -1
- package/dist/{index-BZJ_5FOX.d.mts → index-M37iz29I.d.mts} +112 -37
- package/dist/index-M37iz29I.d.mts.map +1 -0
- package/dist/{index-BEui-cRd.d.mts → index-MGw47uWq.d.mts} +3 -3
- package/dist/{index-BEui-cRd.d.mts.map → index-MGw47uWq.d.mts.map} +1 -1
- package/dist/index.d.mts +19 -19
- package/dist/index.mjs +69 -67
- package/dist/{load-Dg5gtWma.mjs → load-DV1DZuUJ.mjs} +2 -2
- package/dist/{load-Dg5gtWma.mjs.map → load-DV1DZuUJ.mjs.map} +1 -1
- package/dist/{loader-D4rigvjR.mjs → loader-CGugY7Zl.mjs} +29 -15
- package/dist/loader-CGugY7Zl.mjs.map +1 -0
- package/dist/{manifest-schema-bCq54i7F.mjs → manifest-schema-Da7kj23y.mjs} +1 -1
- package/dist/{manifest-schema-bCq54i7F.mjs.map → manifest-schema-Da7kj23y.mjs.map} +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +8 -8
- package/dist/{media-its1WLYv.mjs → media-BP7S-nHT.mjs} +60 -15
- package/dist/media-BP7S-nHT.mjs.map +1 -0
- package/dist/{media-BJ6SRY3g.mjs → media-OhYL-7Io.mjs} +8 -4
- package/dist/{media-BJ6SRY3g.mjs.map → media-OhYL-7Io.mjs.map} +1 -1
- package/dist/{media-allowlist-jUppPWFy.mjs → media-allowlist-D-peH1H5.mjs} +1 -1
- package/dist/{media-allowlist-jUppPWFy.mjs.map → media-allowlist-D-peH1H5.mjs.map} +1 -1
- package/dist/{media-upload-DNu3QySc.mjs → media-upload-DtrwU2B0.mjs} +7 -7
- package/dist/{media-upload-DNu3QySc.mjs.map → media-upload-DtrwU2B0.mjs.map} +1 -1
- package/dist/{media-url-BCm5vBn6.mjs → media-url-DYs_YLOx.mjs} +1 -1
- package/dist/{media-url-BCm5vBn6.mjs.map → media-url-DYs_YLOx.mjs.map} +1 -1
- package/dist/{media-usage-DPQ3K4xB.mjs → media-usage-BlxfTkN0.mjs} +8 -8
- package/dist/{media-usage-DPQ3K4xB.mjs.map → media-usage-BlxfTkN0.mjs.map} +1 -1
- package/dist/{menus-BMGzWyWH.mjs → menus-BcQWxeXu.mjs} +5 -5
- package/dist/{menus-BMGzWyWH.mjs.map → menus-BcQWxeXu.mjs.map} +1 -1
- package/dist/{menus-CPf_SW7u.mjs → menus-Y54RDPIN.mjs} +215 -38
- package/dist/menus-Y54RDPIN.mjs.map +1 -0
- package/dist/{mode-fiXRMfeA.mjs → mode-BWyTBe3I.mjs} +1 -1
- package/dist/{mode-fiXRMfeA.mjs.map → mode-BWyTBe3I.mjs.map} +1 -1
- package/dist/{oauth-authorization-oqfbBuMH.mjs → oauth-authorization-ClvktmrL.mjs} +5 -5
- package/dist/{oauth-authorization-oqfbBuMH.mjs.map → oauth-authorization-ClvktmrL.mjs.map} +1 -1
- package/dist/{oauth-clients-BlrUHAsf.mjs → oauth-clients-8ao-U66l.mjs} +1 -1
- package/dist/{oauth-clients-BlrUHAsf.mjs.map → oauth-clients-8ao-U66l.mjs.map} +1 -1
- package/dist/{oauth-state-store-DnvjRMy6.mjs → oauth-state-store-B1ofdTiQ.mjs} +1 -1
- package/dist/{oauth-state-store-DnvjRMy6.mjs.map → oauth-state-store-B1ofdTiQ.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-oUllxvAv.mjs → oauth-user-lookup-CscEuIiR.mjs} +1 -1
- package/dist/{oauth-user-lookup-oUllxvAv.mjs.map → oauth-user-lookup-CscEuIiR.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-Bok5j2ae.mjs → object-cache-71tPfV4A.mjs} +106 -5
- package/dist/object-cache-71tPfV4A.mjs.map +1 -0
- package/dist/{options-BqMkWfYa.d.mts → options-CA4eVX6P.d.mts} +3 -3
- package/dist/{options-BqMkWfYa.d.mts.map → options-CA4eVX6P.d.mts.map} +1 -1
- package/dist/{options-BlmBHTvX.mjs → options-CBXIHUoT.mjs} +1 -1
- package/dist/{options-BlmBHTvX.mjs.map → options-CBXIHUoT.mjs.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-53zyxlpv.mjs → parse-CJKNuewM.mjs} +2 -2
- package/dist/{parse-53zyxlpv.mjs.map → parse-CJKNuewM.mjs.map} +1 -1
- package/dist/{passkey-config-C-SKpc0-.mjs → passkey-config-D-zrzMJI.mjs} +1 -1
- package/dist/{passkey-config-C-SKpc0-.mjs.map → passkey-config-D-zrzMJI.mjs.map} +1 -1
- package/dist/{placeholder-Dop47JMM.d.mts → placeholder-DaeNS-VG.d.mts} +1 -1
- package/dist/{placeholder-Dop47JMM.d.mts.map → placeholder-DaeNS-VG.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +1 -1
- package/dist/plugin-utils.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
- package/dist/{portable-text-sDj92Kxv.mjs → portable-text-B_kqBmXB.mjs} +1 -1
- package/dist/{portable-text-sDj92Kxv.mjs.map → portable-text-B_kqBmXB.mjs.map} +1 -1
- package/dist/{preview-D4Jnbfx7.mjs → preview-BU6PaLpM.mjs} +2 -2
- package/dist/{preview-D4Jnbfx7.mjs.map → preview-BU6PaLpM.mjs.map} +1 -1
- package/dist/{public-url-DSGTnJFw.mjs → public-url-Ox9oOlgp.mjs} +14 -3
- package/dist/public-url-Ox9oOlgp.mjs.map +1 -0
- package/dist/{query-Bz9bWZfm.mjs → query-C5w7PsRQ.mjs} +43 -44
- package/dist/query-C5w7PsRQ.mjs.map +1 -0
- package/dist/{query-DdFGHzQF.mjs → query-rC9HKv1N.mjs} +4 -4
- package/dist/{query-DdFGHzQF.mjs.map → query-rC9HKv1N.mjs.map} +1 -1
- package/dist/{rate-limit-D3IEiUi2.mjs → rate-limit-kug6q99V.mjs} +2 -2
- package/dist/{rate-limit-D3IEiUi2.mjs.map → rate-limit-kug6q99V.mjs.map} +1 -1
- package/dist/{redirect-BoUac4NT.mjs → redirect-DIJxXKOG.mjs} +3 -3
- package/dist/{redirect-BoUac4NT.mjs.map → redirect-DIJxXKOG.mjs.map} +1 -1
- package/dist/{redirect-Botom7X6.mjs → redirect-Egf2R9yP.mjs} +1 -1
- package/dist/{redirect-Botom7X6.mjs.map → redirect-Egf2R9yP.mjs.map} +1 -1
- package/dist/{redirects-ChbpqKiS.mjs → redirects-Bzm812bY.mjs} +5 -5
- package/dist/{redirects-ChbpqKiS.mjs.map → redirects-Bzm812bY.mjs.map} +1 -1
- package/dist/{redirects-D457qwt0.mjs → redirects-G8wAhWAf.mjs} +25 -7
- package/dist/redirects-G8wAhWAf.mjs.map +1 -0
- package/dist/{registry-y21kjhfG.mjs → registry-Dbodb4Uo.mjs} +59 -14
- package/dist/registry-Dbodb4Uo.mjs.map +1 -0
- package/dist/{relation-Du0r04E0.mjs → relation-Cbe3Sd3m.mjs} +3 -3
- package/dist/{relation-Du0r04E0.mjs.map → relation-Cbe3Sd3m.mjs.map} +1 -1
- package/dist/{relations-CZMpBqEd.mjs → relations-Bw_E1TXo.mjs} +3 -3
- package/dist/{relations-CZMpBqEd.mjs.map → relations-Bw_E1TXo.mjs.map} +1 -1
- package/dist/{relations-qKmSj9KM.d.mts → relations-G2ta7GIl.d.mts} +50 -12
- package/dist/relations-G2ta7GIl.d.mts.map +1 -0
- package/dist/{relations-DtX1UMBH.mjs → relations-qHwpUe66.mjs} +6 -6
- package/dist/{relations-DtX1UMBH.mjs.map → relations-qHwpUe66.mjs.map} +1 -1
- package/dist/request-context.d.mts +3 -0
- package/dist/request-context.d.mts.map +1 -1
- package/dist/request-context.mjs.map +1 -1
- package/dist/{request-meta-DzXYYI-n.mjs → request-meta-Df-jFbAd.mjs} +2 -2
- package/dist/{request-meta-DzXYYI-n.mjs.map → request-meta-Df-jFbAd.mjs.map} +1 -1
- package/dist/{resolve-DFr4kq72.mjs → resolve-DZzG4HqM.mjs} +2 -2
- package/dist/{resolve-DFr4kq72.mjs.map → resolve-DZzG4HqM.mjs.map} +1 -1
- package/dist/{runner-BdeLEgad.mjs → runner-BFTrkYhu.mjs} +497 -213
- package/dist/runner-BFTrkYhu.mjs.map +1 -0
- package/dist/{runner-Dd8m8k9F.d.mts → runner-BaADli8l.d.mts} +2 -2
- package/dist/{runner-Dd8m8k9F.d.mts.map → runner-BaADli8l.d.mts.map} +1 -1
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +3 -3
- package/dist/{schema-BH8P8vaC.mjs → schema-CiQXr6_F.mjs} +3 -3
- package/dist/{schema-BH8P8vaC.mjs.map → schema-CiQXr6_F.mjs.map} +1 -1
- package/dist/{scopes-DTIkIaGA.mjs → scopes-CNJVT5i5.mjs} +3 -3
- package/dist/{scopes-DTIkIaGA.mjs.map → scopes-CNJVT5i5.mjs.map} +1 -1
- package/dist/{search-D-Yhpmvs.mjs → search-FZhx5dDU.mjs} +7 -7
- package/dist/{search-D-Yhpmvs.mjs.map → search-FZhx5dDU.mjs.map} +1 -1
- package/dist/{secrets-CQ-69kF9.mjs → secrets-DLd8RXee.mjs} +4 -4
- package/dist/{secrets-CQ-69kF9.mjs.map → secrets-DLd8RXee.mjs.map} +1 -1
- package/dist/{sections-CzVBAKjw.mjs → sections-BrIrMUCn.mjs} +3 -3
- package/dist/{sections-CzVBAKjw.mjs.map → sections-BrIrMUCn.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +25 -23
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +18 -16
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-C3GDfT0V.mjs → seo-CobNfOvb.mjs} +2 -2
- package/dist/{seo-C3GDfT0V.mjs.map → seo-CobNfOvb.mjs.map} +1 -1
- package/dist/{seo-kJzVAmmu.mjs → seo-DTHRntNC.mjs} +3 -3
- package/dist/{seo-kJzVAmmu.mjs.map → seo-DTHRntNC.mjs.map} +1 -1
- package/dist/{service-CQnc276a.mjs → service-B-pYGPgR.mjs} +4 -4
- package/dist/{service-CQnc276a.mjs.map → service-B-pYGPgR.mjs.map} +1 -1
- package/dist/{session-user-DbHqKDKe.mjs → session-user-BvM9-zNl.mjs} +2 -2
- package/dist/{session-user-DbHqKDKe.mjs.map → session-user-BvM9-zNl.mjs.map} +1 -1
- package/dist/{settings-Dtc0DU31.mjs → settings-DPHau-WH.mjs} +3 -3
- package/dist/{settings-Dtc0DU31.mjs.map → settings-DPHau-WH.mjs.map} +1 -1
- package/dist/{settings-C2PaBS49.mjs → settings-kJhGiQ4z.mjs} +7 -7
- package/dist/{settings-C2PaBS49.mjs.map → settings-kJhGiQ4z.mjs.map} +1 -1
- package/dist/{setup-complete-CdIlqloh.mjs → setup-complete-u50Qm8rY.mjs} +2 -2
- package/dist/{setup-complete-CdIlqloh.mjs.map → setup-complete-u50Qm8rY.mjs.map} +1 -1
- package/dist/{setup-nonce-DqiIPr-J.mjs → setup-nonce-DCjiiOD2.mjs} +1 -1
- package/dist/{setup-nonce-DqiIPr-J.mjs.map → setup-nonce-DCjiiOD2.mjs.map} +1 -1
- package/dist/{single-flight-cache-C2exrGAi.mjs → single-flight-cache-DW3w11Pu.mjs} +1 -1
- package/dist/{single-flight-cache-C2exrGAi.mjs.map → single-flight-cache-DW3w11Pu.mjs.map} +1 -1
- package/dist/site-url-I-lJ5kma.mjs +16 -0
- package/dist/site-url-I-lJ5kma.mjs.map +1 -0
- package/dist/{snapshot-BdpUJKD-.mjs → snapshot-I_fjLDaD.mjs} +2 -2
- package/dist/{snapshot-BdpUJKD-.mjs.map → snapshot-I_fjLDaD.mjs.map} +1 -1
- package/dist/{ssrf-CviKqWmq.mjs → ssrf-CTa6v21i.mjs} +1 -1
- package/dist/{ssrf-CviKqWmq.mjs.map → ssrf-CTa6v21i.mjs.map} +1 -1
- package/dist/{state-xxv6ZTMv.mjs → state-CQvoefYP.mjs} +1 -1
- package/dist/{state-xxv6ZTMv.mjs.map → state-CQvoefYP.mjs.map} +1 -1
- package/dist/{status-COfycGIU.mjs → status-CIsmlC1E.mjs} +1 -1
- package/dist/{status-COfycGIU.mjs.map → status-CIsmlC1E.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +2 -2
- package/dist/storage/s3.mjs.map +1 -1
- package/dist/{taxonomies-BN6M9Nrv.mjs → taxonomies-CKuaZER5.mjs} +90 -9
- package/dist/taxonomies-CKuaZER5.mjs.map +1 -0
- package/dist/{taxonomies-r7pqLBCn.mjs → taxonomies-CLN1N92E.mjs} +57 -32
- package/dist/taxonomies-CLN1N92E.mjs.map +1 -0
- package/dist/{taxonomy-0mCI25HN.mjs → taxonomy-pOrB2kZe.mjs} +142 -15
- package/dist/taxonomy-pOrB2kZe.mjs.map +1 -0
- package/dist/{tokens-DVltpO2D.mjs → tokens-DagaJGK8.mjs} +1 -1
- package/dist/{tokens-DVltpO2D.mjs.map → tokens-DagaJGK8.mjs.map} +1 -1
- package/dist/{transaction-D0FOsb3X.mjs → transaction-NQj4VJ7Z.mjs} +1 -1
- package/dist/{transaction-D0FOsb3X.mjs.map → transaction-NQj4VJ7Z.mjs.map} +1 -1
- package/dist/{transport-Vd7VdqHv.d.mts → transport-CAwTaTp_.d.mts} +1 -1
- package/dist/{transport-Vd7VdqHv.d.mts.map → transport-CAwTaTp_.d.mts.map} +1 -1
- package/dist/{transport-CKrlqSpD.mjs → transport-DVsa5YYo.mjs} +1 -1
- package/dist/{transport-CKrlqSpD.mjs.map → transport-DVsa5YYo.mjs.map} +1 -1
- package/dist/{trusted-proxy-CwjQj0YG.mjs → trusted-proxy-D20_7fyX.mjs} +1 -1
- package/dist/{trusted-proxy-CwjQj0YG.mjs.map → trusted-proxy-D20_7fyX.mjs.map} +1 -1
- package/dist/{types-BfYUPJdP.d.mts → types-BGWPMiBO.d.mts} +2 -2
- package/dist/{types-BfYUPJdP.d.mts.map → types-BGWPMiBO.d.mts.map} +1 -1
- package/dist/{types-iVeZ5g6N.d.mts → types-BK6U01Ro.d.mts} +1 -1
- package/dist/{types-iVeZ5g6N.d.mts.map → types-BK6U01Ro.d.mts.map} +1 -1
- package/dist/{types-BD40g7zz.mjs → types-BjxTKxrZ.mjs} +1 -1
- package/dist/{types-BD40g7zz.mjs.map → types-BjxTKxrZ.mjs.map} +1 -1
- package/dist/{types-Kmaxdarz.d.mts → types-BnFP1M3J.d.mts} +22 -1
- package/dist/types-BnFP1M3J.d.mts.map +1 -0
- package/dist/{types-C7U0HlEr.d.mts → types-C8oz_ayJ.d.mts} +1 -1
- package/dist/{types-C7U0HlEr.d.mts.map → types-C8oz_ayJ.d.mts.map} +1 -1
- package/dist/{types-B4vm81VH.d.mts → types-CbUcuxxc.d.mts} +1 -1
- package/dist/{types-B4vm81VH.d.mts.map → types-CbUcuxxc.d.mts.map} +1 -1
- package/dist/{types-CrRUFdej.mjs → types-Cd8iuS1J.mjs} +10 -3
- package/dist/{types-CrRUFdej.mjs.map → types-Cd8iuS1J.mjs.map} +1 -1
- package/dist/types-CtzytVXn.mjs +18 -0
- package/dist/types-CtzytVXn.mjs.map +1 -0
- package/dist/{types-BvB7gDOD.d.mts → types-Cz8hNch2.d.mts} +5 -5
- package/dist/{types-BvB7gDOD.d.mts.map → types-Cz8hNch2.d.mts.map} +1 -1
- package/dist/{types-B97jg3aW.d.mts → types-DLG4IFEQ.d.mts} +1 -1
- package/dist/{types-B97jg3aW.d.mts.map → types-DLG4IFEQ.d.mts.map} +1 -1
- package/dist/{types-DPKhI5ib.d.mts → types-Dc4ntQjQ.d.mts} +18 -1
- package/dist/types-Dc4ntQjQ.d.mts.map +1 -0
- package/dist/{types-BNfPHfay.d.mts → types-LoagAGzH.d.mts} +1 -1
- package/dist/{types-BNfPHfay.d.mts.map → types-LoagAGzH.d.mts.map} +1 -1
- package/dist/{types-o7xo7VgH.mjs → types-NBI3rF-_.mjs} +3 -2
- package/dist/types-NBI3rF-_.mjs.map +1 -0
- package/dist/upload-attempts-D8QAFLUJ.mjs +27 -0
- package/dist/upload-attempts-D8QAFLUJ.mjs.map +1 -0
- package/dist/{user-aTXqmXBz.mjs → user-DBrq4UVq.mjs} +3 -3
- package/dist/{user-aTXqmXBz.mjs.map → user-DBrq4UVq.mjs.map} +1 -1
- package/dist/{utils-BbUgmeZG.mjs → utils-hLzi_2Fn.mjs} +2 -2
- package/dist/{utils-BbUgmeZG.mjs.map → utils-hLzi_2Fn.mjs.map} +1 -1
- package/dist/{validate-VPnKoIzW.mjs → validate-BpwoDOgt.mjs} +25 -2
- package/dist/validate-BpwoDOgt.mjs.map +1 -0
- package/dist/{validate-DULfgpJP.d.mts → validate-C3oSmA7F.d.mts} +15 -5
- package/dist/validate-C3oSmA7F.d.mts.map +1 -0
- package/dist/{validate-CDT1jl6_.mjs → validate-mKo3RxBM.mjs} +4 -4
- package/dist/{validate-CDT1jl6_.mjs.map → validate-mKo3RxBM.mjs.map} +1 -1
- package/dist/{validation-DlD0E35W.mjs → validation-BgpucsvF.mjs} +11 -9
- package/dist/{validation-DlD0E35W.mjs.map → validation-BgpucsvF.mjs.map} +1 -1
- package/dist/version-C4PnpmoV.mjs +7 -0
- package/dist/{version-BRMngh9I.mjs.map → version-C4PnpmoV.mjs.map} +1 -1
- package/dist/{widgets-5fipNkMT.mjs → widgets-CJJtkiKh.mjs} +3 -3
- package/dist/{widgets-5fipNkMT.mjs.map → widgets-CJJtkiKh.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-DrihupaC.mjs → wxr-taxonomies-9PPSy8X6.mjs} +4 -4
- package/dist/{wxr-taxonomies-DrihupaC.mjs.map → wxr-taxonomies-9PPSy8X6.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-B4tMuN5T.d.mts → wxr-taxonomies-Bkpp_2tK.d.mts} +1 -1
- package/dist/{wxr-taxonomies-B4tMuN5T.d.mts.map → wxr-taxonomies-Bkpp_2tK.d.mts.map} +1 -1
- package/dist/{zod-generator-CwkHWz4f.mjs → zod-generator-CG64Hnbh.mjs} +3 -3
- package/dist/{zod-generator-CwkHWz4f.mjs.map → zod-generator-CG64Hnbh.mjs.map} +1 -1
- package/package.json +12 -8
- package/src/after.ts +6 -1
- package/src/api/errors.ts +1 -0
- package/src/api/handlers/content.ts +45 -4
- package/src/api/handlers/marketplace.ts +14 -0
- package/src/api/handlers/media.ts +4 -4
- package/src/api/handlers/registry.ts +14 -0
- package/src/api/handlers/revision.ts +19 -5
- package/src/api/handlers/schema.ts +37 -0
- package/src/api/handlers/snapshot.ts +1 -1
- package/src/api/handlers/taxonomies.ts +111 -10
- package/src/api/openapi/document.ts +84 -3
- package/src/api/public-url.ts +14 -2
- package/src/api/schemas/media.ts +9 -2
- package/src/api/schemas/schema.ts +13 -0
- package/src/api/schemas/search.ts +2 -0
- package/src/api/schemas/taxonomies.ts +34 -1
- package/src/api/site-url.ts +16 -6
- package/src/astro/integration/routes.ts +19 -0
- package/src/astro/integration/runtime.ts +13 -0
- package/src/astro/integration/virtual-modules.ts +2 -0
- package/src/astro/middleware/redirect.ts +2 -10
- package/src/astro/middleware/scoped-db.ts +35 -4
- package/src/astro/middleware.ts +56 -22
- package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -1
- package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +2 -2
- package/src/astro/routes/api/auth/invite/index.ts +2 -2
- package/src/astro/routes/api/auth/magic-link/send.ts +2 -2
- package/src/astro/routes/api/auth/signup/request.ts +2 -2
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
- package/src/astro/routes/api/media/[id]/confirm.ts +148 -59
- package/src/astro/routes/api/media/[id]/upload.ts +262 -0
- package/src/astro/routes/api/media/[id].ts +19 -10
- package/src/astro/routes/api/media/upload-url.ts +28 -31
- package/src/astro/routes/api/schema/collections/reorder.ts +31 -0
- package/src/astro/routes/api/schema/index.ts +2 -0
- package/src/astro/routes/api/search/enable.ts +5 -1
- package/src/astro/routes/api/search/rebuild.ts +6 -1
- package/src/astro/routes/api/taxonomies/[name]/reorder.ts +41 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +6 -3
- package/src/astro/types.ts +7 -0
- package/src/cleanup.ts +54 -26
- package/src/cli/commands/dev.ts +13 -3
- package/src/cli/commands/export-seed.ts +2 -0
- package/src/cli/index.ts +1 -1
- package/src/components/CommentForm.astro +1 -1
- package/src/components/Comments.astro +1 -1
- package/src/components/InlinePortableTextEditor.tsx +175 -31
- package/src/components/OrderedList.astro +14 -0
- package/src/components/PortableText.astro +26 -4
- package/src/components/code-mark.ts +11 -0
- package/src/components/index.ts +12 -1
- package/src/components/ordered-list.ts +549 -0
- package/src/content/converters/numbered-list.ts +148 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +59 -9
- package/src/content/converters/prosemirror-to-portable-text.ts +23 -12
- package/src/content/converters/types.ts +2 -0
- package/src/content/portable-text-lists.ts +205 -0
- package/src/database/dialect-helpers.ts +41 -22
- package/src/database/migrations/054_media_upload_attempts.ts +41 -0
- package/src/database/migrations/055_content_translation_group_locale_index.ts +67 -0
- package/src/database/migrations/056_taxonomy_term_sort_order.ts +189 -0
- package/src/database/migrations/057_collection_hidden.ts +24 -0
- package/src/database/migrations/058_collection_sort_order.ts +20 -0
- package/src/database/migrations/059_revision_prune_queue.ts +36 -0
- package/src/database/migrations/runner.ts +12 -0
- package/src/database/repositories/content.ts +193 -183
- package/src/database/repositories/media.ts +158 -28
- package/src/database/repositories/revision.ts +82 -17
- package/src/database/repositories/taxonomy.ts +202 -7
- package/src/database/repositories/types.ts +7 -0
- package/src/database/types.ts +23 -1
- package/src/database/validate.ts +39 -0
- package/src/db/adapters.ts +8 -0
- package/src/deferred-tasks.ts +71 -0
- package/src/emdash-runtime.ts +277 -88
- package/src/i18n/config.ts +17 -10
- package/src/index.ts +3 -0
- package/src/loader.ts +46 -24
- package/src/media/upload-attempts.ts +33 -0
- package/src/media/usage/gc.ts +50 -0
- package/src/object-cache/index.ts +160 -3
- package/src/plugins/routes.ts +34 -0
- package/src/plugins/storage-indexes.ts +50 -11
- package/src/query.ts +50 -44
- package/src/redirects/cache.ts +79 -19
- package/src/request-context.ts +3 -0
- package/src/scheduled-publish.ts +6 -1
- package/src/schema/registry.ts +95 -3
- package/src/schema/types.ts +24 -0
- package/src/search/fts-manager.ts +50 -10
- package/src/search/index.ts +2 -0
- package/src/search/types.ts +6 -0
- package/src/seed/apply.ts +22 -2
- package/src/seed/types.ts +10 -0
- package/src/storage/s3.ts +1 -1
- package/src/taxonomies/index.ts +11 -7
- package/src/taxonomies/term-counts.ts +56 -28
- package/src/ui-comments.ts +19 -0
- package/src/ui.ts +11 -3
- package/src/utils/hash.ts +14 -3
- package/src/virtual-modules.d.ts +8 -0
- package/dist/adapters-C0ONzkUP.d.mts.map +0 -1
- package/dist/after-B1IIdH3Y.mjs +0 -29
- package/dist/after-B1IIdH3Y.mjs.map +0 -1
- package/dist/api-BkqFzIu4.mjs.map +0 -1
- package/dist/apply-DuXsqll7.mjs.map +0 -1
- package/dist/cache-DDwy3JDW.mjs +0 -65
- package/dist/cache-DDwy3JDW.mjs.map +0 -1
- package/dist/config-B6b_BobR.mjs.map +0 -1
- package/dist/content-BC43pICM.mjs.map +0 -1
- package/dist/dialect-helpers-BtOwo2us.mjs.map +0 -1
- package/dist/errors-DtEXIQQV.mjs.map +0 -1
- package/dist/fts-manager-hyCU9OOp.mjs.map +0 -1
- package/dist/hash-DFFrkivP.mjs.map +0 -1
- package/dist/index-BZJ_5FOX.d.mts.map +0 -1
- package/dist/loader-D4rigvjR.mjs.map +0 -1
- package/dist/media-its1WLYv.mjs.map +0 -1
- package/dist/menus-CPf_SW7u.mjs.map +0 -1
- package/dist/object-cache-Bok5j2ae.mjs.map +0 -1
- package/dist/public-url-DSGTnJFw.mjs.map +0 -1
- package/dist/query-Bz9bWZfm.mjs.map +0 -1
- package/dist/redirects-D457qwt0.mjs.map +0 -1
- package/dist/registry-y21kjhfG.mjs.map +0 -1
- package/dist/relations-qKmSj9KM.d.mts.map +0 -1
- package/dist/runner-BdeLEgad.mjs.map +0 -1
- package/dist/site-url-NGJT6NTU.mjs +0 -13
- package/dist/site-url-NGJT6NTU.mjs.map +0 -1
- package/dist/taxonomies-BN6M9Nrv.mjs.map +0 -1
- package/dist/taxonomies-r7pqLBCn.mjs.map +0 -1
- package/dist/taxonomy-0mCI25HN.mjs.map +0 -1
- package/dist/types-DPKhI5ib.d.mts.map +0 -1
- package/dist/types-Kmaxdarz.d.mts.map +0 -1
- package/dist/types-o7xo7VgH.mjs.map +0 -1
- package/dist/validate-DULfgpJP.d.mts.map +0 -1
- package/dist/validate-VPnKoIzW.mjs.map +0 -1
- package/dist/version-BRMngh9I.mjs +0 -7
- /package/dist/{api-tokens-Cvmixds7.mjs → api-tokens-Dai9dND0.mjs} +0 -0
- /package/dist/{ssrf-BB__xfNM.mjs → ssrf-Cj568Dgs.mjs} +0 -0
- /package/dist/{types-CK0LxPUQ.mjs → types-DKuWPYV5.mjs} +0 -0
|
@@ -85,6 +85,9 @@ export interface FindManyMediaOptions {
|
|
|
85
85
|
q?: string;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
const UPLOAD_ATTEMPT_CLEANUP_AGE_MS = 60 * 60 * 1000;
|
|
89
|
+
const UPLOAD_ATTEMPT_CLEANUP_BATCH_SIZE = 100;
|
|
90
|
+
|
|
88
91
|
/**
|
|
89
92
|
* Media repository for database operations
|
|
90
93
|
*/
|
|
@@ -138,6 +141,129 @@ export class MediaRepository {
|
|
|
138
141
|
});
|
|
139
142
|
}
|
|
140
143
|
|
|
144
|
+
async createUploadAttempt(mediaId: string, storageKey: string): Promise<void> {
|
|
145
|
+
const now = new Date().toISOString();
|
|
146
|
+
await this.db
|
|
147
|
+
.insertInto("_emdash_media_upload_attempts")
|
|
148
|
+
.values({
|
|
149
|
+
media_id: mediaId,
|
|
150
|
+
storage_key: storageKey,
|
|
151
|
+
status: "active",
|
|
152
|
+
created_at: now,
|
|
153
|
+
updated_at: now,
|
|
154
|
+
})
|
|
155
|
+
.execute();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async hasUploadAttempt(storageKey: string): Promise<boolean> {
|
|
159
|
+
const row = await this.db
|
|
160
|
+
.selectFrom("_emdash_media_upload_attempts")
|
|
161
|
+
.select("storage_key")
|
|
162
|
+
.where("storage_key", "=", storageKey)
|
|
163
|
+
.executeTakeFirst();
|
|
164
|
+
return row !== undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async claimUploadAttemptForCleanup(storageKey: string): Promise<boolean> {
|
|
168
|
+
const result = await this.db
|
|
169
|
+
.updateTable("_emdash_media_upload_attempts")
|
|
170
|
+
.set({ status: "cleanup", updated_at: new Date().toISOString() })
|
|
171
|
+
.where("storage_key", "=", storageKey)
|
|
172
|
+
.where((eb) =>
|
|
173
|
+
eb.not(
|
|
174
|
+
eb.exists(
|
|
175
|
+
eb
|
|
176
|
+
.selectFrom("media")
|
|
177
|
+
.select("media.id")
|
|
178
|
+
.whereRef("media.storage_key", "=", "_emdash_media_upload_attempts.storage_key"),
|
|
179
|
+
),
|
|
180
|
+
),
|
|
181
|
+
)
|
|
182
|
+
.executeTakeFirst();
|
|
183
|
+
|
|
184
|
+
return Number(result.numUpdatedRows ?? 0) > 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async deleteUploadAttempt(storageKey: string): Promise<void> {
|
|
188
|
+
await this.db
|
|
189
|
+
.deleteFrom("_emdash_media_upload_attempts")
|
|
190
|
+
.where("storage_key", "=", storageKey)
|
|
191
|
+
.execute();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async deleteCompletedUploadAttempts(): Promise<number> {
|
|
195
|
+
const result = await this.db
|
|
196
|
+
.deleteFrom("_emdash_media_upload_attempts")
|
|
197
|
+
.where((eb) =>
|
|
198
|
+
eb.exists(
|
|
199
|
+
eb
|
|
200
|
+
.selectFrom("media")
|
|
201
|
+
.select("media.id")
|
|
202
|
+
.whereRef("media.id", "=", "_emdash_media_upload_attempts.media_id")
|
|
203
|
+
.whereRef("media.storage_key", "=", "_emdash_media_upload_attempts.storage_key")
|
|
204
|
+
.where("media.status", "=", "ready"),
|
|
205
|
+
),
|
|
206
|
+
)
|
|
207
|
+
.executeTakeFirst();
|
|
208
|
+
return Number(result.numDeletedRows ?? 0);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async findUploadAttemptsForCleanup(
|
|
212
|
+
maxAgeMs: number = UPLOAD_ATTEMPT_CLEANUP_AGE_MS,
|
|
213
|
+
limit: number = UPLOAD_ATTEMPT_CLEANUP_BATCH_SIZE,
|
|
214
|
+
): Promise<string[]> {
|
|
215
|
+
const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
|
|
216
|
+
const rows = await this.db
|
|
217
|
+
.selectFrom("_emdash_media_upload_attempts")
|
|
218
|
+
.select("storage_key")
|
|
219
|
+
.where((eb) => eb.or([eb("status", "=", "cleanup"), eb("created_at", "<", cutoff)]))
|
|
220
|
+
.where((eb) =>
|
|
221
|
+
eb.not(
|
|
222
|
+
eb.exists(
|
|
223
|
+
eb
|
|
224
|
+
.selectFrom("media")
|
|
225
|
+
.select("media.id")
|
|
226
|
+
.whereRef("media.storage_key", "=", "_emdash_media_upload_attempts.storage_key"),
|
|
227
|
+
),
|
|
228
|
+
),
|
|
229
|
+
)
|
|
230
|
+
.orderBy("created_at", "asc")
|
|
231
|
+
.limit(limit)
|
|
232
|
+
.execute();
|
|
233
|
+
|
|
234
|
+
return rows.map((row) => row.storage_key);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async publishPendingStorageKey(
|
|
238
|
+
id: string,
|
|
239
|
+
expectedStorageKey: string,
|
|
240
|
+
storageKey: string,
|
|
241
|
+
contentHash?: string,
|
|
242
|
+
): Promise<boolean> {
|
|
243
|
+
const result = await this.db
|
|
244
|
+
.updateTable("media")
|
|
245
|
+
.set({
|
|
246
|
+
storage_key: storageKey,
|
|
247
|
+
...(contentHash !== undefined ? { content_hash: contentHash } : {}),
|
|
248
|
+
})
|
|
249
|
+
.where("id", "=", id)
|
|
250
|
+
.where("status", "=", "pending")
|
|
251
|
+
.where("storage_key", "=", expectedStorageKey)
|
|
252
|
+
.where((eb) =>
|
|
253
|
+
eb.exists(
|
|
254
|
+
eb
|
|
255
|
+
.selectFrom("_emdash_media_upload_attempts")
|
|
256
|
+
.select("storage_key")
|
|
257
|
+
.where("media_id", "=", id)
|
|
258
|
+
.where("storage_key", "=", storageKey)
|
|
259
|
+
.where("status", "=", "active"),
|
|
260
|
+
),
|
|
261
|
+
)
|
|
262
|
+
.executeTakeFirst();
|
|
263
|
+
|
|
264
|
+
return Number(result.numUpdatedRows ?? 0) > 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
141
267
|
/**
|
|
142
268
|
* Confirm upload (mark as ready)
|
|
143
269
|
*/
|
|
@@ -149,13 +275,10 @@ export class MediaRepository {
|
|
|
149
275
|
size?: number;
|
|
150
276
|
blurhash?: string;
|
|
151
277
|
dominantColor?: string;
|
|
278
|
+
contentHash?: string | null;
|
|
152
279
|
},
|
|
280
|
+
expectedStorageKey?: string,
|
|
153
281
|
): Promise<MediaItem | null> {
|
|
154
|
-
const existing = await this.findById(id);
|
|
155
|
-
if (!existing) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
282
|
const updates: Partial<MediaRow> = {
|
|
160
283
|
status: "ready",
|
|
161
284
|
};
|
|
@@ -164,24 +287,33 @@ export class MediaRepository {
|
|
|
164
287
|
if (metadata?.size !== undefined) updates.size = metadata.size;
|
|
165
288
|
if (metadata?.blurhash !== undefined) updates.blurhash = metadata.blurhash;
|
|
166
289
|
if (metadata?.dominantColor !== undefined) updates.dominant_color = metadata.dominantColor;
|
|
290
|
+
if (metadata?.contentHash !== undefined) updates.content_hash = metadata.contentHash;
|
|
167
291
|
|
|
168
|
-
|
|
292
|
+
let query = this.db
|
|
293
|
+
.updateTable("media")
|
|
294
|
+
.set(updates)
|
|
295
|
+
.where("id", "=", id)
|
|
296
|
+
.where("status", "=", "pending");
|
|
297
|
+
if (expectedStorageKey !== undefined) {
|
|
298
|
+
query = query.where("storage_key", "=", expectedStorageKey);
|
|
299
|
+
}
|
|
169
300
|
|
|
170
|
-
|
|
301
|
+
const row = await query.returningAll().executeTakeFirst();
|
|
302
|
+
|
|
303
|
+
return row ? this.rowToItem(row) : null;
|
|
171
304
|
}
|
|
172
305
|
|
|
173
306
|
/**
|
|
174
307
|
* Mark upload as failed
|
|
175
308
|
*/
|
|
176
|
-
async markFailed(id: string): Promise<MediaItem | null> {
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
|
|
309
|
+
async markFailed(id: string, expectedStorageKey?: string): Promise<MediaItem | null> {
|
|
310
|
+
let query = this.db.updateTable("media").set({ status: "failed" }).where("id", "=", id);
|
|
311
|
+
if (expectedStorageKey !== undefined) {
|
|
312
|
+
query = query.where("status", "=", "pending").where("storage_key", "=", expectedStorageKey);
|
|
180
313
|
}
|
|
181
314
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return this.findById(id);
|
|
315
|
+
const row = await query.returningAll().executeTakeFirst();
|
|
316
|
+
return row ? this.rowToItem(row) : null;
|
|
185
317
|
}
|
|
186
318
|
|
|
187
319
|
/**
|
|
@@ -319,10 +451,18 @@ export class MediaRepository {
|
|
|
319
451
|
/**
|
|
320
452
|
* Delete media item
|
|
321
453
|
*/
|
|
322
|
-
async
|
|
323
|
-
const
|
|
454
|
+
async deleteWithStorageKey(id: string): Promise<string | null> {
|
|
455
|
+
const deleted = await this.db
|
|
456
|
+
.deleteFrom("media")
|
|
457
|
+
.where("id", "=", id)
|
|
458
|
+
.returning("storage_key")
|
|
459
|
+
.executeTakeFirst();
|
|
460
|
+
if (deleted) return deleted.storage_key;
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
324
463
|
|
|
325
|
-
|
|
464
|
+
async delete(id: string): Promise<boolean> {
|
|
465
|
+
return (await this.deleteWithStorageKey(id)) !== null;
|
|
326
466
|
}
|
|
327
467
|
|
|
328
468
|
/**
|
|
@@ -350,21 +490,11 @@ export class MediaRepository {
|
|
|
350
490
|
async cleanupPendingUploads(maxAgeMs: number = 60 * 60 * 1000): Promise<string[]> {
|
|
351
491
|
const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
|
|
352
492
|
|
|
353
|
-
// Select the storage keys first -- SQLite doesn't support RETURNING
|
|
354
|
-
// on DELETE in all drivers, and Kysely's RETURNING isn't universal.
|
|
355
493
|
const rows = await this.db
|
|
356
|
-
.selectFrom("media")
|
|
357
|
-
.select("storage_key")
|
|
358
|
-
.where("status", "=", "pending")
|
|
359
|
-
.where("created_at", "<", cutoff)
|
|
360
|
-
.execute();
|
|
361
|
-
|
|
362
|
-
if (rows.length === 0) return [];
|
|
363
|
-
|
|
364
|
-
await this.db
|
|
365
494
|
.deleteFrom("media")
|
|
366
495
|
.where("status", "=", "pending")
|
|
367
496
|
.where("created_at", "<", cutoff)
|
|
497
|
+
.returning("storage_key")
|
|
368
498
|
.execute();
|
|
369
499
|
|
|
370
500
|
return rows.map((r) => r.storage_key);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { sql, type Kysely } from "kysely";
|
|
2
2
|
import { monotonicFactory } from "ulidx";
|
|
3
3
|
|
|
4
4
|
import type { Database, RevisionTable } from "../types.js";
|
|
5
|
+
import { validateIdentifier } from "../validate.js";
|
|
5
6
|
|
|
6
7
|
const monotonic = monotonicFactory();
|
|
7
8
|
|
|
@@ -50,6 +51,26 @@ export class RevisionRepository {
|
|
|
50
51
|
if (!revision) {
|
|
51
52
|
throw new Error("Failed to create revision");
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await this.db
|
|
57
|
+
.insertInto("_emdash_revision_prune_queue")
|
|
58
|
+
.values({
|
|
59
|
+
collection: input.collection,
|
|
60
|
+
entry_id: input.entryId,
|
|
61
|
+
revision_id: id,
|
|
62
|
+
})
|
|
63
|
+
.onConflict((conflict) =>
|
|
64
|
+
conflict.columns(["collection", "entry_id"]).doUpdateSet({ revision_id: id }),
|
|
65
|
+
)
|
|
66
|
+
.execute();
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(
|
|
69
|
+
`[revisions] Failed to queue revision pruning for ${input.collection}/${input.entryId}:`,
|
|
70
|
+
error,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
53
74
|
return revision;
|
|
54
75
|
}
|
|
55
76
|
|
|
@@ -132,6 +153,19 @@ export class RevisionRepository {
|
|
|
132
153
|
.where("entry_id", "=", entryId)
|
|
133
154
|
.executeTakeFirst();
|
|
134
155
|
|
|
156
|
+
try {
|
|
157
|
+
await this.db
|
|
158
|
+
.deleteFrom("_emdash_revision_prune_queue")
|
|
159
|
+
.where("collection", "=", collection)
|
|
160
|
+
.where("entry_id", "=", entryId)
|
|
161
|
+
.execute();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error(
|
|
164
|
+
`[revisions] Failed to clear queued revision pruning for ${collection}/${entryId}:`,
|
|
165
|
+
error,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
135
169
|
return Number(result.numDeletedRows ?? 0);
|
|
136
170
|
}
|
|
137
171
|
|
|
@@ -139,6 +173,8 @@ export class RevisionRepository {
|
|
|
139
173
|
* Delete old revisions, keeping the most recent N
|
|
140
174
|
*/
|
|
141
175
|
async pruneOldRevisions(collection: string, entryId: string, keepCount: number): Promise<number> {
|
|
176
|
+
validateIdentifier(collection, "collection");
|
|
177
|
+
const tableName = `ec_${collection}`;
|
|
142
178
|
// Get IDs of revisions to keep
|
|
143
179
|
const keep = await this.db
|
|
144
180
|
.selectFrom("revisions")
|
|
@@ -154,27 +190,56 @@ export class RevisionRepository {
|
|
|
154
190
|
|
|
155
191
|
if (keepIds.length === 0) return 0;
|
|
156
192
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
.
|
|
162
|
-
|
|
163
|
-
|
|
193
|
+
const result = await sql`
|
|
194
|
+
DELETE FROM revisions
|
|
195
|
+
WHERE collection = ${collection}
|
|
196
|
+
AND entry_id = ${entryId}
|
|
197
|
+
AND id NOT IN (${sql.join(keepIds.map((id) => sql`${id}`))})
|
|
198
|
+
AND NOT EXISTS (
|
|
199
|
+
SELECT 1 FROM ${sql.ref(tableName)} AS content
|
|
200
|
+
WHERE content.live_revision_id = revisions.id
|
|
201
|
+
OR content.draft_revision_id = revisions.id
|
|
202
|
+
)
|
|
203
|
+
`.execute(this.db);
|
|
164
204
|
|
|
165
|
-
return Number(result.
|
|
205
|
+
return Number(result.numAffectedRows ?? 0);
|
|
166
206
|
}
|
|
167
207
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
208
|
+
async pruneQueuedEntry(
|
|
209
|
+
collection: string,
|
|
210
|
+
entryId: string,
|
|
211
|
+
queuedRevisionId: string,
|
|
212
|
+
keepCount: number,
|
|
213
|
+
): Promise<number> {
|
|
214
|
+
const pruned = await this.pruneOldRevisions(collection, entryId, keepCount);
|
|
173
215
|
await this.db
|
|
174
|
-
.
|
|
175
|
-
.
|
|
176
|
-
.where("
|
|
216
|
+
.deleteFrom("_emdash_revision_prune_queue")
|
|
217
|
+
.where("collection", "=", collection)
|
|
218
|
+
.where("entry_id", "=", entryId)
|
|
219
|
+
.where("revision_id", "=", queuedRevisionId)
|
|
177
220
|
.execute();
|
|
221
|
+
return pruned;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async deleteIfUnreferenced(
|
|
225
|
+
collection: string,
|
|
226
|
+
entryId: string,
|
|
227
|
+
revisionId: string,
|
|
228
|
+
): Promise<boolean> {
|
|
229
|
+
validateIdentifier(collection, "collection");
|
|
230
|
+
const tableName = `ec_${collection}`;
|
|
231
|
+
const result = await sql`
|
|
232
|
+
DELETE FROM revisions
|
|
233
|
+
WHERE id = ${revisionId}
|
|
234
|
+
AND collection = ${collection}
|
|
235
|
+
AND entry_id = ${entryId}
|
|
236
|
+
AND NOT EXISTS (
|
|
237
|
+
SELECT 1 FROM ${sql.ref(tableName)} AS content
|
|
238
|
+
WHERE content.live_revision_id = revisions.id
|
|
239
|
+
OR content.draft_revision_id = revisions.id
|
|
240
|
+
)
|
|
241
|
+
`.execute(this.db);
|
|
242
|
+
return (result.numAffectedRows ?? 0n) > 0n;
|
|
178
243
|
}
|
|
179
244
|
|
|
180
245
|
/**
|
|
@@ -3,6 +3,7 @@ import { ulid } from "ulidx";
|
|
|
3
3
|
|
|
4
4
|
import { invalidateTaxonomyObjectCache } from "../../object-cache/index.js";
|
|
5
5
|
import { isMissingTableError } from "../../utils/db-errors.js";
|
|
6
|
+
import { withTransaction } from "../transaction.js";
|
|
6
7
|
import type { Database, TaxonomyTable } from "../types.js";
|
|
7
8
|
import { validateIdentifier } from "../validate.js";
|
|
8
9
|
|
|
@@ -29,6 +30,58 @@ const EMPTY_DENORM: PivotDenorm = {
|
|
|
29
30
|
created_at: null,
|
|
30
31
|
};
|
|
31
32
|
|
|
33
|
+
/** A member of one sibling group and the position it currently holds. */
|
|
34
|
+
export interface SiblingPosition {
|
|
35
|
+
group: string;
|
|
36
|
+
position: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Translation groups per reorder `UPDATE`. Each costs three bound parameters —
|
|
41
|
+
* a CASE `WHEN`/`THEN` pair plus one slot in the `IN` list — which keeps a
|
|
42
|
+
* statement inside D1's 100-parameter ceiling.
|
|
43
|
+
*/
|
|
44
|
+
const GROUPS_PER_UPDATE = 32;
|
|
45
|
+
|
|
46
|
+
/** Deal the listed groups back out over the slots they hold, in the order given. */
|
|
47
|
+
function permuteWithinSlots(
|
|
48
|
+
listed: readonly string[],
|
|
49
|
+
occupied: readonly number[],
|
|
50
|
+
): Map<string, number> {
|
|
51
|
+
const slots = occupied.toSorted((a, b) => a - b);
|
|
52
|
+
const target = new Map<string, number>();
|
|
53
|
+
listed.forEach((group, index) => {
|
|
54
|
+
const position = slots[index];
|
|
55
|
+
if (position !== undefined) target.set(group, position);
|
|
56
|
+
});
|
|
57
|
+
return target;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Renumber a whole sibling group 0..n-1, with the listed groups in the order
|
|
62
|
+
* given and every other member left in the place it already held.
|
|
63
|
+
*
|
|
64
|
+
* Works off each member's index in the sequence rather than its stored value,
|
|
65
|
+
* which is what lets it resolve positions that tie. The sort is stable, so
|
|
66
|
+
* tied members keep the order `siblings` arrives in — deterministic, but a
|
|
67
|
+
* listing that mixes locales breaks a tie on whichever locale's label sorts
|
|
68
|
+
* first, not on the order any one caller rendered.
|
|
69
|
+
*/
|
|
70
|
+
function renumberSiblings(
|
|
71
|
+
listed: readonly string[],
|
|
72
|
+
siblings: readonly SiblingPosition[],
|
|
73
|
+
): Map<string, number> {
|
|
74
|
+
const sequence = siblings.toSorted((a, b) => a.position - b.position);
|
|
75
|
+
const wanted = new Set(listed);
|
|
76
|
+
const target = new Map<string, number>();
|
|
77
|
+
let next = 0;
|
|
78
|
+
sequence.forEach(({ group }, index) => {
|
|
79
|
+
const replacement = wanted.has(group) ? listed[next++] : undefined;
|
|
80
|
+
target.set(replacement ?? group, index);
|
|
81
|
+
});
|
|
82
|
+
return target;
|
|
83
|
+
}
|
|
84
|
+
|
|
32
85
|
export interface Taxonomy {
|
|
33
86
|
id: string;
|
|
34
87
|
name: string;
|
|
@@ -38,6 +91,11 @@ export interface Taxonomy {
|
|
|
38
91
|
data: Record<string, unknown> | null;
|
|
39
92
|
locale: string;
|
|
40
93
|
translationGroup: string | null;
|
|
94
|
+
/**
|
|
95
|
+
* Position among siblings. Shared by every row of a `translation_group` —
|
|
96
|
+
* a term sits in the same place in every locale it is translated into.
|
|
97
|
+
*/
|
|
98
|
+
sortOrder: number;
|
|
41
99
|
}
|
|
42
100
|
|
|
43
101
|
export interface CreateTaxonomyInput {
|
|
@@ -75,6 +133,12 @@ export interface FindOptions {
|
|
|
75
133
|
* The repository does not resolve locale fallbacks on its own — callers supply
|
|
76
134
|
* the locale they want. Runtime helpers and handlers use `getFallbackChain()`
|
|
77
135
|
* from `i18n/config` when they need fallback behaviour.
|
|
136
|
+
*
|
|
137
|
+
* `sort_order` is per translation_group, not per row: every row sharing a
|
|
138
|
+
* translation_group carries the same value, so a term holds one position across
|
|
139
|
+
* all its locales. Sibling groups are keyed on the raw `parent_id` column, which
|
|
140
|
+
* is locale-agnostic for the same reason (it stores the parent's
|
|
141
|
+
* translation_group). Writes must preserve both invariants.
|
|
78
142
|
*/
|
|
79
143
|
export class TaxonomyRepository {
|
|
80
144
|
constructor(private db: Kysely<Database>) {}
|
|
@@ -98,10 +162,17 @@ export class TaxonomyRepository {
|
|
|
98
162
|
const parentId = parentInput ? await this.resolveParentRef(parentInput) : null;
|
|
99
163
|
|
|
100
164
|
let translationGroup = id;
|
|
165
|
+
let sortOrder: number | null = null;
|
|
101
166
|
if (input.translationOf) {
|
|
102
167
|
const source = await this.findById(input.translationOf);
|
|
103
168
|
if (source?.translationGroup) translationGroup = source.translationGroup;
|
|
169
|
+
// A translation is the same term in another locale, so it takes the
|
|
170
|
+
// group's position — but only while it stays in the group that position
|
|
171
|
+
// belongs to. Landing under a different parent makes it a new member of
|
|
172
|
+
// that sibling group, and the source's position means nothing there.
|
|
173
|
+
if (source && source.parentId === parentId) sortOrder = source.sortOrder;
|
|
104
174
|
}
|
|
175
|
+
sortOrder ??= await this.nextSortOrder(input.name, parentId);
|
|
105
176
|
|
|
106
177
|
await this.db
|
|
107
178
|
.insertInto("taxonomies")
|
|
@@ -112,6 +183,7 @@ export class TaxonomyRepository {
|
|
|
112
183
|
label: input.label,
|
|
113
184
|
parent_id: parentId,
|
|
114
185
|
data: input.data ? JSON.stringify(input.data) : null,
|
|
186
|
+
sort_order: sortOrder,
|
|
115
187
|
// When omitted, the DB DEFAULT 'en' is used — keeps behaviour
|
|
116
188
|
// consistent with ContentRepository and lets higher layers
|
|
117
189
|
// supply an explicit locale from request context.
|
|
@@ -155,15 +227,18 @@ export class TaxonomyRepository {
|
|
|
155
227
|
/**
|
|
156
228
|
* Get all terms for a taxonomy (e.g., all categories).
|
|
157
229
|
*
|
|
158
|
-
* `
|
|
159
|
-
*
|
|
160
|
-
*
|
|
230
|
+
* `sort_order` carries the manual order set from the admin; it is 0 for
|
|
231
|
+
* terms nobody has reordered, so an untouched taxonomy still comes back
|
|
232
|
+
* alphabetically. `id asc` is a stable tiebreaker for terms that share both
|
|
233
|
+
* — without it the SQL ordering is implementation-defined when they match,
|
|
234
|
+
* which breaks keyset pagination over `(label, id)`.
|
|
161
235
|
*/
|
|
162
236
|
async findByName(name: string, options: FindOptions = {}): Promise<Taxonomy[]> {
|
|
163
237
|
let query = this.db
|
|
164
238
|
.selectFrom("taxonomies")
|
|
165
239
|
.selectAll()
|
|
166
240
|
.where("name", "=", name)
|
|
241
|
+
.orderBy("sort_order", "asc")
|
|
167
242
|
.orderBy("label", "asc")
|
|
168
243
|
.orderBy("id", "asc");
|
|
169
244
|
|
|
@@ -196,6 +271,7 @@ export class TaxonomyRepository {
|
|
|
196
271
|
.selectFrom("taxonomies")
|
|
197
272
|
.selectAll()
|
|
198
273
|
.where("parent_id", "=", group)
|
|
274
|
+
.orderBy("sort_order", "asc")
|
|
199
275
|
.orderBy("label", "asc")
|
|
200
276
|
.orderBy("id", "asc");
|
|
201
277
|
if (locale !== undefined) query = query.where("locale", "=", locale);
|
|
@@ -222,28 +298,146 @@ export class TaxonomyRepository {
|
|
|
222
298
|
const existing = await this.findById(id);
|
|
223
299
|
if (!existing) return null;
|
|
224
300
|
|
|
301
|
+
// Per-row display fields. `parent_id` and `sort_order` are not here: both
|
|
302
|
+
// belong to the translation_group and are written across it below.
|
|
225
303
|
const updates: Record<string, unknown> = {};
|
|
226
304
|
if (input.slug !== undefined) updates.slug = input.slug;
|
|
227
305
|
if (input.label !== undefined) updates.label = input.label;
|
|
306
|
+
if (input.data !== undefined) updates.data = JSON.stringify(input.data);
|
|
307
|
+
|
|
308
|
+
const group: { parent_id?: string | null; sort_order?: number } = {};
|
|
228
309
|
if (input.parentId !== undefined) {
|
|
229
310
|
// Defense in depth: empty-string parentId means null (no parent).
|
|
230
311
|
// Otherwise persist the parent's translation_group (locale-agnostic),
|
|
231
312
|
// matching create() — see the note there.
|
|
232
|
-
|
|
313
|
+
const parentId =
|
|
233
314
|
input.parentId === "" || input.parentId === null
|
|
234
315
|
? null
|
|
235
316
|
: await this.resolveParentRef(input.parentId);
|
|
317
|
+
|
|
318
|
+
if (parentId !== existing.parentId) {
|
|
319
|
+
group.parent_id = parentId;
|
|
320
|
+
// A position only means anything within one sibling group, so a term
|
|
321
|
+
// that changes parent is appended to the group it lands in.
|
|
322
|
+
group.sort_order = await this.nextSortOrder(existing.name, parentId);
|
|
323
|
+
}
|
|
236
324
|
}
|
|
237
|
-
if (input.data !== undefined) updates.data = JSON.stringify(input.data);
|
|
238
325
|
|
|
239
|
-
|
|
240
|
-
|
|
326
|
+
const hasRowUpdates = Object.keys(updates).length > 0;
|
|
327
|
+
const hasGroupUpdates = Object.keys(group).length > 0;
|
|
328
|
+
if (hasRowUpdates || hasGroupUpdates) {
|
|
329
|
+
await withTransaction(this.db, async (trx) => {
|
|
330
|
+
if (hasRowUpdates) {
|
|
331
|
+
await trx.updateTable("taxonomies").set(updates).where("id", "=", id).execute();
|
|
332
|
+
}
|
|
333
|
+
if (hasGroupUpdates) {
|
|
334
|
+
await trx
|
|
335
|
+
.updateTable("taxonomies")
|
|
336
|
+
.set(group)
|
|
337
|
+
.where("translation_group", "=", existing.translationGroup ?? existing.id)
|
|
338
|
+
.execute();
|
|
339
|
+
}
|
|
340
|
+
});
|
|
241
341
|
invalidateTaxonomyObjectCache();
|
|
242
342
|
}
|
|
243
343
|
|
|
244
344
|
return this.findById(id);
|
|
245
345
|
}
|
|
246
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Move `groups` (translation_groups, in the desired order) into the positions
|
|
349
|
+
* those same groups already occupy, leaving every other member of the sibling
|
|
350
|
+
* group where it is.
|
|
351
|
+
*
|
|
352
|
+
* `groups` may be a subset: a locale renders only the terms translated into
|
|
353
|
+
* it, so an admin in `fr` often cannot name every member. A group left out
|
|
354
|
+
* keeps its place, which is also what makes a stale list harmless.
|
|
355
|
+
*
|
|
356
|
+
* `siblings` is every member of the group with the position it holds, in a
|
|
357
|
+
* listing's order — tied positions are resolved by that order, so pass it as
|
|
358
|
+
* read. Groups already at their target are skipped, so one swap rewrites two
|
|
359
|
+
* groups rather than the whole list.
|
|
360
|
+
*/
|
|
361
|
+
async reorder(groups: string[], siblings: readonly SiblingPosition[]): Promise<void> {
|
|
362
|
+
const current = new Map(siblings.map(({ group, position }) => [group, position]));
|
|
363
|
+
|
|
364
|
+
const listed: string[] = [];
|
|
365
|
+
const occupied: number[] = [];
|
|
366
|
+
for (const group of groups) {
|
|
367
|
+
const position = current.get(group);
|
|
368
|
+
if (position === undefined) continue;
|
|
369
|
+
listed.push(group);
|
|
370
|
+
occupied.push(position);
|
|
371
|
+
}
|
|
372
|
+
if (listed.length === 0) return;
|
|
373
|
+
|
|
374
|
+
// Tied positions have no distinct order to permute into, so the requested
|
|
375
|
+
// one would be dropped without a word. Renumbering is the only way to
|
|
376
|
+
// honour it, and it repairs the tie on the way through.
|
|
377
|
+
const target =
|
|
378
|
+
new Set(occupied).size === occupied.length
|
|
379
|
+
? permuteWithinSlots(listed, occupied)
|
|
380
|
+
: renumberSiblings(listed, siblings);
|
|
381
|
+
|
|
382
|
+
const changed = [...target].filter(([group, position]) => current.get(group) !== position);
|
|
383
|
+
if (changed.length === 0) return;
|
|
384
|
+
|
|
385
|
+
await this.applyPositions(changed);
|
|
386
|
+
|
|
387
|
+
invalidateTaxonomyObjectCache();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Write one position per translation_group, GROUPS_PER_UPDATE at a time so
|
|
392
|
+
* each statement stays inside D1's parameter ceiling.
|
|
393
|
+
*
|
|
394
|
+
* D1 has no transactions — `withTransaction` runs its callback bare there —
|
|
395
|
+
* so a chunk is the unit that can't tear. A reorder spanning several chunks
|
|
396
|
+
* can, and leaves ties, which the next reorder renumbers away.
|
|
397
|
+
*/
|
|
398
|
+
private async applyPositions(positions: readonly (readonly [string, number])[]): Promise<void> {
|
|
399
|
+
for (let index = 0; index < positions.length; index += GROUPS_PER_UPDATE) {
|
|
400
|
+
const chunk = positions.slice(index, index + GROUPS_PER_UPDATE);
|
|
401
|
+
// The CAST types the bound position. Postgres resolves a CASE whose THEN
|
|
402
|
+
// arms are all untyped parameters to text, then refuses to assign text to
|
|
403
|
+
// an integer column.
|
|
404
|
+
const arms = sql.join(
|
|
405
|
+
chunk.map(([group, position]) => sql`WHEN ${group} THEN CAST(${position} AS INTEGER)`),
|
|
406
|
+
sql` `,
|
|
407
|
+
);
|
|
408
|
+
const keys = sql.join(chunk.map(([group]) => sql`${group}`));
|
|
409
|
+
await sql`
|
|
410
|
+
UPDATE taxonomies
|
|
411
|
+
SET sort_order = CASE translation_group ${arms} END
|
|
412
|
+
WHERE translation_group IN (${keys})
|
|
413
|
+
`.execute(this.db);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Position for a term joining a sibling group: one past the last member, or
|
|
419
|
+
* 0 when the group is empty.
|
|
420
|
+
*
|
|
421
|
+
* Bounds are taken across every locale because a position belongs to the
|
|
422
|
+
* translation_group, not to a row — a term translated into only one locale
|
|
423
|
+
* still occupies its slot for all of them.
|
|
424
|
+
*/
|
|
425
|
+
private async nextSortOrder(name: string, parentId: string | null): Promise<number> {
|
|
426
|
+
let query = this.db
|
|
427
|
+
.selectFrom("taxonomies")
|
|
428
|
+
.select((eb) => eb.fn.max("sort_order").as("max"))
|
|
429
|
+
.where("name", "=", name);
|
|
430
|
+
query =
|
|
431
|
+
parentId === null
|
|
432
|
+
? query.where("parent_id", "is", null)
|
|
433
|
+
: query.where("parent_id", "=", parentId);
|
|
434
|
+
|
|
435
|
+
const bounds = await query.executeTakeFirst();
|
|
436
|
+
// Null only when the group is empty.
|
|
437
|
+
if (!bounds || bounds.max === null) return 0;
|
|
438
|
+
return bounds.max + 1;
|
|
439
|
+
}
|
|
440
|
+
|
|
247
441
|
async delete(id: string): Promise<boolean> {
|
|
248
442
|
const term = await this.findById(id);
|
|
249
443
|
if (!term) return false;
|
|
@@ -543,6 +737,7 @@ export class TaxonomyRepository {
|
|
|
543
737
|
data: row.data ? JSON.parse(row.data) : null,
|
|
544
738
|
locale: row.locale,
|
|
545
739
|
translationGroup: row.translation_group,
|
|
740
|
+
sortOrder: row.sort_order,
|
|
546
741
|
};
|
|
547
742
|
}
|
|
548
743
|
}
|
|
@@ -290,3 +290,10 @@ export class ScheduledNotDueError extends Error {
|
|
|
290
290
|
this.name = "ScheduledNotDueError";
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
|
+
|
|
294
|
+
export class ContentMutationConflictError extends Error {
|
|
295
|
+
constructor(message = "Content changed while the operation was in progress") {
|
|
296
|
+
super(message);
|
|
297
|
+
this.name = "ContentMutationConflictError";
|
|
298
|
+
}
|
|
299
|
+
}
|