emdash 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapters-C0ONzkUP.d.mts → adapters-34EN2eXO.d.mts} +34 -2
- package/dist/adapters-34EN2eXO.d.mts.map +1 -0
- package/dist/after-CBU2vkoO.mjs +96 -0
- package/dist/after-CBU2vkoO.mjs.map +1 -0
- package/dist/{allowed-origins-CCEi9bPI.mjs → allowed-origins-DW7sYyqg.mjs} +2 -2
- package/dist/{allowed-origins-CCEi9bPI.mjs.map → allowed-origins-DW7sYyqg.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -4
- package/dist/api/route-utils.d.mts.map +1 -1
- package/dist/api/route-utils.mjs +26 -25
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +6 -5
- package/dist/{api-DgPbMlng.mjs → api-DdAsirBe.mjs} +321 -428
- package/dist/api-DdAsirBe.mjs.map +1 -0
- package/dist/{api-tokens-p-iMzvXR.mjs → api-tokens-CFXu8F_2.mjs} +2 -2
- package/dist/{api-tokens-p-iMzvXR.mjs.map → api-tokens-CFXu8F_2.mjs.map} +1 -1
- package/dist/{apply-1_6ra7NP.mjs → apply-D5zfeD09.mjs} +139 -102
- package/dist/apply-D5zfeD09.mjs.map +1 -0
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +103 -35
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +9 -9
- package/dist/astro/middleware/media-usage-write-fence.d.mts +7 -0
- package/dist/astro/middleware/media-usage-write-fence.d.mts.map +1 -0
- package/dist/astro/middleware/media-usage-write-fence.mjs +35 -0
- package/dist/astro/middleware/media-usage-write-fence.mjs.map +1 -0
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +13 -10
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.mjs +5 -5
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +12 -11
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +1915 -223
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +9 -8
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +9 -8
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +12 -11
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +12 -11
- package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +12 -11
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +20 -20
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +20 -20
- package/dist/astro/routes/api/admin/bylines/index.mjs +20 -20
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -17
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/bulk.mjs +14 -13
- package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/index.mjs +14 -13
- package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +36 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +36 -0
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +15 -14
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/work/index.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/work/index.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +37 -0
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +37 -0
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -0
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
- package/dist/astro/routes/api/admin/plugins/_id_/disable.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +6 -6
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +55 -46
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +56 -47
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +52 -46
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +52 -46
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +52 -46
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +10 -9
- package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/index.mjs +9 -8
- package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.mjs +8 -8
- package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/complete.mjs +14 -13
- package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/index.mjs +12 -11
- package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/register-options.mjs +13 -12
- package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/logout.mjs +4 -4
- package/dist/astro/routes/api/auth/magic-link/send.mjs +14 -13
- package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
- package/dist/astro/routes/api/auth/me.mjs +10 -9
- package/dist/astro/routes/api/auth/me.mjs.map +1 -1
- package/dist/astro/routes/api/auth/mode.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +9 -8
- package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/options.mjs +15 -14
- package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +13 -12
- package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +14 -13
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/verify.mjs +14 -13
- package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/complete.mjs +14 -13
- package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/request.mjs +14 -13
- package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +20 -19
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +17 -16
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +15 -15
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +21 -20
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +21 -20
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +47 -34
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/index.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/trash.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
- package/dist/astro/routes/api/dashboard.mjs +12 -10
- package/dist/astro/routes/api/dashboard.mjs.map +1 -1
- package/dist/astro/routes/api/dev/emails.mjs +4 -4
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +22 -20
- package/dist/astro/routes/api/import/probe.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +18 -18
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/media.mjs +14 -12
- package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +13 -12
- package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +15 -15
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +22 -20
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +32 -31
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +6 -6
- package/dist/astro/routes/api/mcp.d.mts.map +1 -1
- package/dist/astro/routes/api/mcp.mjs +174 -72
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +14 -12
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/upload.mjs +7 -7
- package/dist/astro/routes/api/media/_id_/usage.mjs +17 -16
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +16 -15
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
- package/dist/astro/routes/api/media/providers/index.mjs +4 -4
- package/dist/astro/routes/api/media/upload-url.mjs +11 -10
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.mjs +19 -16
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_/items.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_/translations.mjs +13 -13
- package/dist/astro/routes/api/menus/_name_.mjs +13 -13
- package/dist/astro/routes/api/menus/index.mjs +13 -13
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
- package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
- package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
- package/dist/astro/routes/api/oauth/register.mjs +4 -4
- package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
- package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
- package/dist/astro/routes/api/oauth/token.mjs +7 -7
- package/dist/astro/routes/api/openapi.json.mjs +183 -6
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +8 -7
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/index.mjs +14 -13
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +14 -13
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +16 -14
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +16 -14
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.mjs +21 -20
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +16 -15
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +21 -20
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +52 -46
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.d.mts +8 -0
- package/dist/astro/routes/api/schema/collections/reorder.d.mts.map +1 -0
- package/dist/astro/routes/api/schema/collections/reorder.mjs +71 -0
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -0
- package/dist/astro/routes/api/schema/index.mjs +14 -11
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +52 -46
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +52 -46
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.d.mts +1 -0
- package/dist/astro/routes/api/search/enable.d.mts.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +19 -15
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +13 -13
- package/dist/astro/routes/api/search/rebuild.mjs +15 -15
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +9 -9
- package/dist/astro/routes/api/search/suggest.mjs +13 -13
- package/dist/astro/routes/api/sections/_slug_.mjs +13 -12
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +13 -12
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +8 -8
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
- package/dist/astro/routes/api/settings/backups/export.mjs +8 -8
- package/dist/astro/routes/api/settings/backups/index.mjs +9 -9
- package/dist/astro/routes/api/settings/email.mjs +6 -6
- package/dist/astro/routes/api/settings.mjs +18 -17
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin-verify.mjs +15 -14
- package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin.mjs +14 -13
- package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +34 -32
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
- package/dist/astro/routes/api/setup/index.mjs +36 -34
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +5 -5
- package/dist/astro/routes/api/snapshot.mjs +10 -10
- package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts +8 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +44 -0
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +19 -18
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +19 -18
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +21 -19
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts +8 -0
- package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +46 -0
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_.d.mts +19 -0
- package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -0
- package/dist/astro/routes/api/taxonomies/_name_.mjs +88 -0
- package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -0
- package/dist/astro/routes/api/taxonomies/index.mjs +19 -18
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +8 -8
- package/dist/astro/routes/api/typegen.mjs +6 -6
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +10 -9
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +8 -7
- package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
- package/dist/astro/routes/api/widget-components.mjs +4 -4
- package/dist/astro/routes/robots.txt.mjs +11 -10
- package/dist/astro/routes/robots.txt.mjs.map +1 -1
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +14 -14
- package/dist/astro/routes/sitemap.xml.mjs +12 -11
- package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
- package/dist/astro/types.d.mts +41 -17
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{authorize-R5iYYrpa.mjs → authorize-1iFJzPaZ.mjs} +2 -2
- package/dist/{authorize-R5iYYrpa.mjs.map → authorize-1iFJzPaZ.mjs.map} +1 -1
- package/dist/{backup-LpQ1V_sR.mjs → backup-LHjIAVNP.mjs} +5 -5
- package/dist/{backup-LpQ1V_sR.mjs.map → backup-LHjIAVNP.mjs.map} +1 -1
- package/dist/{base64-B-PsqheR.mjs → base64-CvLhUKQv.mjs} +1 -1
- package/dist/{base64-B-PsqheR.mjs.map → base64-CvLhUKQv.mjs.map} +1 -1
- package/dist/bundle-CBEXrBnb.mjs +663 -0
- package/dist/bundle-CBEXrBnb.mjs.map +1 -0
- package/dist/{byline-fields-T9ZLZMxJ.mjs → byline-fields-C5S8wygO.mjs} +2 -2
- package/dist/{byline-fields-T9ZLZMxJ.mjs.map → byline-fields-C5S8wygO.mjs.map} +1 -1
- package/dist/{byline-C5TAqs8N.mjs → byline-pEcoDps8.mjs} +9 -9
- package/dist/{byline-C5TAqs8N.mjs.map → byline-pEcoDps8.mjs.map} +1 -1
- package/dist/{byline-registry-BCuOp4UF.mjs → byline-registry-DDun8sxh.mjs} +4 -4
- package/dist/{byline-registry-BCuOp4UF.mjs.map → byline-registry-DDun8sxh.mjs.map} +1 -1
- package/dist/{bylines-B8-WGdja.mjs → bylines-BWemdX2k.mjs} +8 -8
- package/dist/{bylines-B8-WGdja.mjs.map → bylines-BWemdX2k.mjs.map} +1 -1
- package/dist/{bylines-DGuqBLjV.mjs → bylines-DJfSfXCL.mjs} +5 -5
- package/dist/{bylines-DGuqBLjV.mjs.map → bylines-DJfSfXCL.mjs.map} +1 -1
- package/dist/cache-CBJaDy_E.mjs +108 -0
- package/dist/cache-CBJaDy_E.mjs.map +1 -0
- package/dist/{challenge-store-BFzgFRog.mjs → challenge-store-CZyFVaad.mjs} +1 -1
- package/dist/{challenge-store-BFzgFRog.mjs.map → challenge-store-CZyFVaad.mjs.map} +1 -1
- package/dist/{chunks-D5dlPeRb.mjs → chunks-DfPax1I0.mjs} +2 -2
- package/dist/{chunks-D5dlPeRb.mjs.map → chunks-DfPax1I0.mjs.map} +1 -1
- package/dist/cli/index.mjs +193 -707
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +74 -4
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +25 -2
- package/dist/client/index.mjs.map +1 -1
- package/dist/collection-deletion-C8BugSGz.mjs +779 -0
- package/dist/collection-deletion-C8BugSGz.mjs.map +1 -0
- package/dist/{comment-DnTxxVHv.mjs → comment-Dxlep6cE.mjs} +3 -3
- package/dist/{comment-DnTxxVHv.mjs.map → comment-Dxlep6cE.mjs.map} +1 -1
- package/dist/{comment-reaction-BUlUz2bh.mjs → comment-reaction-D6qfHKBc.mjs} +2 -2
- package/dist/{comment-reaction-BUlUz2bh.mjs.map → comment-reaction-D6qfHKBc.mjs.map} +1 -1
- package/dist/{comments-QPKgK3nk.mjs → comments-CTOuhTSX.mjs} +3 -3
- package/dist/{comments-QPKgK3nk.mjs.map → comments-CTOuhTSX.mjs.map} +1 -1
- package/dist/{components-DZkL4Fx0.mjs → components-CQy3lh9x.mjs} +1 -1
- package/dist/{components-DZkL4Fx0.mjs.map → components-CQy3lh9x.mjs.map} +1 -1
- package/dist/{config-DyF3OKg_.mjs → config-C3EBstHi.mjs} +18 -2
- package/dist/config-C3EBstHi.mjs.map +1 -0
- package/dist/{content-CpfKV9QE.mjs → content-BNfwh7xX.mjs} +667 -183
- package/dist/content-BNfwh7xX.mjs.map +1 -0
- package/dist/content-list-query-DhQ84eVV.d.mts +26 -0
- package/dist/content-list-query-DhQ84eVV.d.mts.map +1 -0
- package/dist/content-refresh-DNERP4-f.mjs +2560 -0
- package/dist/content-refresh-DNERP4-f.mjs.map +1 -0
- package/dist/{context-kO4YZB03.mjs → context-DRgOvSnW.mjs} +28 -20
- package/dist/context-DRgOvSnW.mjs.map +1 -0
- package/dist/{cron-BlKIMD_e.mjs → cron-Y9aLtgrA.mjs} +1 -1
- package/dist/{cron-BlKIMD_e.mjs.map → cron-Y9aLtgrA.mjs.map} +1 -1
- package/dist/{dashboard-DoBwPnON.mjs → dashboard-CB8J89rJ.mjs} +45 -11
- package/dist/dashboard-CB8J89rJ.mjs.map +1 -0
- package/dist/db/index.d.mts +4 -4
- package/dist/db/index.mjs +3 -3
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{db-errors-CcWLaRiR.mjs → db-errors-Cl-sKYTm.mjs} +1 -1
- package/dist/{db-errors-CcWLaRiR.mjs.map → db-errors-Cl-sKYTm.mjs.map} +1 -1
- package/dist/{default-C4v9KP56.mjs → default-DdDl3fxv.mjs} +1 -1
- package/dist/{default-C4v9KP56.mjs.map → default-DdDl3fxv.mjs.map} +1 -1
- package/dist/deferred-tasks-BMsa9F64.d.mts +9 -0
- package/dist/deferred-tasks-BMsa9F64.d.mts.map +1 -0
- package/dist/{device-flow-DhUsyJU6.mjs → device-flow-CaioYGK3.mjs} +5 -5
- package/dist/{device-flow-DhUsyJU6.mjs.map → device-flow-CaioYGK3.mjs.map} +1 -1
- package/dist/{dialect-helpers-DFwyWjTM.mjs → dialect-helpers-BSbfaO3F.mjs} +24 -16
- package/dist/dialect-helpers-BSbfaO3F.mjs.map +1 -0
- package/dist/dist-D_6CKR8z.mjs +810 -0
- package/dist/dist-D_6CKR8z.mjs.map +1 -0
- package/dist/{email-console-C-9Ng8DM.mjs → email-console-BHNjIwiB.mjs} +1 -1
- package/dist/{email-console-C-9Ng8DM.mjs.map → email-console-BHNjIwiB.mjs.map} +1 -1
- package/dist/{enrich-CFJJgxs_.mjs → enrich-_ySMEvEE.mjs} +2 -2
- package/dist/{enrich-CFJJgxs_.mjs.map → enrich-_ySMEvEE.mjs.map} +1 -1
- package/dist/{error-DmmN74gW.mjs → error-DupyJZE2.mjs} +3 -3
- package/dist/{error-DmmN74gW.mjs.map → error-DupyJZE2.mjs.map} +1 -1
- package/dist/{errors-DtEXIQQV.mjs → errors-CLUPm7aD.mjs} +15 -2
- package/dist/errors-CLUPm7aD.mjs.map +1 -0
- package/dist/{escape-CdW31WsG.mjs → escape-C_aLKP3H.mjs} +1 -1
- package/dist/{escape-CdW31WsG.mjs.map → escape-C_aLKP3H.mjs.map} +1 -1
- package/dist/{field-defs-cache-QMVnzTH6.mjs → field-defs-cache-hg6QkjV9.mjs} +5 -5
- package/dist/{field-defs-cache-QMVnzTH6.mjs.map → field-defs-cache-hg6QkjV9.mjs.map} +1 -1
- package/dist/{fts-manager-vncsZIJm.mjs → fts-manager-CZ-5dVwJ.mjs} +111 -61
- package/dist/fts-manager-CZ-5dVwJ.mjs.map +1 -0
- package/dist/{hash-Cb7U1b5M.mjs → hash-Cg0TXJPV.mjs} +1 -1
- package/dist/{hash-Cb7U1b5M.mjs.map → hash-Cg0TXJPV.mjs.map} +1 -1
- package/dist/{hreflang-CZbSx6Bg.d.mts → hreflang-D3Uehfv2.d.mts} +2 -2
- package/dist/{hreflang-CZbSx6Bg.d.mts.map → hreflang-D3Uehfv2.d.mts.map} +1 -1
- package/dist/{hreflang-Bg-zMpkr.mjs → hreflang-DNswoYsi.mjs} +7 -7
- package/dist/{hreflang-Bg-zMpkr.mjs.map → hreflang-DNswoYsi.mjs.map} +1 -1
- package/dist/{import-PKhLeXvn.mjs → import-B41u8Rot.mjs} +7 -7
- package/dist/{import-PKhLeXvn.mjs.map → import-B41u8Rot.mjs.map} +1 -1
- package/dist/{index-j9rTh3cp.d.mts → index-C3Y-rsyN.d.mts} +286 -93
- package/dist/index-C3Y-rsyN.d.mts.map +1 -0
- package/dist/{index-BeNto_Vs.d.mts → index-Cof4-Fab.d.mts} +5 -10
- package/dist/index-Cof4-Fab.d.mts.map +1 -0
- package/dist/index.d.mts +20 -19
- package/dist/index.mjs +79 -71
- package/dist/{init-lock-DJkX6Hto.mjs → init-lock-6b309ZrF.mjs} +1 -1
- package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-6b309ZrF.mjs.map} +1 -1
- package/dist/{load-BwTdWE8B.mjs → load-DmvJrtxS.mjs} +2 -2
- package/dist/{load-BwTdWE8B.mjs.map → load-DmvJrtxS.mjs.map} +1 -1
- package/dist/{loader-C1XOLV5b.mjs → loader-DLBqRiGP.mjs} +120 -64
- package/dist/loader-DLBqRiGP.mjs.map +1 -0
- package/dist/{manifest-schema-bCq54i7F.mjs → manifest-schema-BXbUAHod.mjs} +1 -1
- package/dist/{manifest-schema-bCq54i7F.mjs.map → manifest-schema-BXbUAHod.mjs.map} +1 -1
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +3 -2
- package/dist/media/index.mjs.map +1 -1
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +10 -9
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/{media-DWIzoVFL.mjs → media-BWWWb8kg.mjs} +92 -3
- package/dist/media-BWWWb8kg.mjs.map +1 -0
- package/dist/{media-tQDZEdu7.mjs → media-CzhAn2--.mjs} +2 -2
- package/dist/{media-tQDZEdu7.mjs.map → media-CzhAn2--.mjs.map} +1 -1
- package/dist/{media-allowlist-B7TPD6aq.mjs → media-allowlist-BD6HhgXA.mjs} +14 -3
- package/dist/media-allowlist-BD6HhgXA.mjs.map +1 -0
- package/dist/{media-upload-Bc9Nc5Zf.mjs → media-upload-9yas9zGH.mjs} +11 -9
- package/dist/{media-upload-Bc9Nc5Zf.mjs.map → media-upload-9yas9zGH.mjs.map} +1 -1
- package/dist/{media-url-BCm5vBn6.mjs → media-url-BvoX88FA.mjs} +1 -1
- package/dist/{media-url-BCm5vBn6.mjs.map → media-url-BvoX88FA.mjs.map} +1 -1
- package/dist/{media-usage-DPJcNaAq.mjs → media-usage-De3qvwjc.mjs} +138 -61
- package/dist/media-usage-De3qvwjc.mjs.map +1 -0
- package/dist/media-usage-work-B9Bksh_b.mjs +152 -0
- package/dist/media-usage-work-B9Bksh_b.mjs.map +1 -0
- package/dist/media-usage-work-DrCbqBcl.mjs +424 -0
- package/dist/media-usage-work-DrCbqBcl.mjs.map +1 -0
- package/dist/media-usage-write-fence-aHEgN1zB.mjs +42 -0
- package/dist/media-usage-write-fence-aHEgN1zB.mjs.map +1 -0
- package/dist/{menus-C6qhqP4X.mjs → menus-CC-yn1F9.mjs} +554 -121
- package/dist/menus-CC-yn1F9.mjs.map +1 -0
- package/dist/{menus-BxPLFfIc.mjs → menus-fxvEDYE6.mjs} +5 -5
- package/dist/{menus-BxPLFfIc.mjs.map → menus-fxvEDYE6.mjs.map} +1 -1
- package/dist/{mode-fiXRMfeA.mjs → mode-Bpe-tNNy.mjs} +1 -1
- package/dist/{mode-fiXRMfeA.mjs.map → mode-Bpe-tNNy.mjs.map} +1 -1
- package/dist/{normalize-C-SHXmra.mjs → normalize-Bc-s_r-a.mjs} +1 -1
- package/dist/{normalize-C-SHXmra.mjs.map → normalize-Bc-s_r-a.mjs.map} +1 -1
- package/dist/{oauth-authorization-C9tFinly.mjs → oauth-authorization-BXO1MKej.mjs} +5 -5
- package/dist/{oauth-authorization-C9tFinly.mjs.map → oauth-authorization-BXO1MKej.mjs.map} +1 -1
- package/dist/{oauth-clients-BwTxE1aE.mjs → oauth-clients-C_DNqtRu.mjs} +1 -1
- package/dist/{oauth-clients-BwTxE1aE.mjs.map → oauth-clients-C_DNqtRu.mjs.map} +1 -1
- package/dist/{oauth-state-store-DaRUwPWO.mjs → oauth-state-store-DwAxMtk4.mjs} +1 -1
- package/dist/{oauth-state-store-DaRUwPWO.mjs.map → oauth-state-store-DwAxMtk4.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-CzuzOSlF.mjs → oauth-user-lookup-BxfZizdk.mjs} +1 -1
- package/dist/{oauth-user-lookup-CzuzOSlF.mjs.map → oauth-user-lookup-BxfZizdk.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-Bok5j2ae.mjs → object-cache-71tPfV4A.mjs} +106 -5
- package/dist/object-cache-71tPfV4A.mjs.map +1 -0
- package/dist/{options-BlmBHTvX.mjs → options-CBXIHUoT.mjs} +1 -1
- package/dist/{options-BlmBHTvX.mjs.map → options-CBXIHUoT.mjs.map} +1 -1
- package/dist/{options-aeIs8WFu.d.mts → options-DRe1pIBL.d.mts} +4 -3
- package/dist/options-DRe1pIBL.d.mts.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-BL49yb9D.mjs → parse-DFbuc-Fh.mjs} +2 -2
- package/dist/{parse-BL49yb9D.mjs.map → parse-DFbuc-Fh.mjs.map} +1 -1
- package/dist/{passkey-config-KMhgFjdQ.mjs → passkey-config-_2GOwwK8.mjs} +1 -1
- package/dist/{passkey-config-KMhgFjdQ.mjs.map → passkey-config-_2GOwwK8.mjs.map} +1 -1
- package/dist/{placeholder-Dxo5Zt58.d.mts → placeholder-CzW7Lshs.d.mts} +1 -1
- package/dist/{placeholder-Dxo5Zt58.d.mts.map → placeholder-CzW7Lshs.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +8 -1
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-utils.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.mjs +7 -4
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/{portable-text-CNahFfj6.mjs → portable-text-DhKbDAGr.mjs} +1 -1
- package/dist/{portable-text-CNahFfj6.mjs.map → portable-text-DhKbDAGr.mjs.map} +1 -1
- package/dist/{preview-D4Jnbfx7.mjs → preview-PW-nOnq4.mjs} +2 -2
- package/dist/{preview-D4Jnbfx7.mjs.map → preview-PW-nOnq4.mjs.map} +1 -1
- package/dist/{public-url-DSGTnJFw.mjs → public-url-CWoFhQT8.mjs} +14 -3
- package/dist/public-url-CWoFhQT8.mjs.map +1 -0
- package/dist/{query-DCiXI7OZ.mjs → query-BgjfiLUQ.mjs} +38 -77
- package/dist/query-BgjfiLUQ.mjs.map +1 -0
- package/dist/{query-1xOcEy18.mjs → query-vgZNwIhh.mjs} +4 -4
- package/dist/{query-1xOcEy18.mjs.map → query-vgZNwIhh.mjs.map} +1 -1
- package/dist/{rate-limit-Vkp9gQ1Y.mjs → rate-limit-L5anykgo.mjs} +2 -2
- package/dist/{rate-limit-Vkp9gQ1Y.mjs.map → rate-limit-L5anykgo.mjs.map} +1 -1
- package/dist/{redirect-BJ6d1yHh.mjs → redirect-COsS6SWJ.mjs} +3 -3
- package/dist/{redirect-BJ6d1yHh.mjs.map → redirect-COsS6SWJ.mjs.map} +1 -1
- package/dist/{redirect-CDgfv9vh.mjs → redirect-KBNE3UEs.mjs} +1 -1
- package/dist/{redirect-CDgfv9vh.mjs.map → redirect-KBNE3UEs.mjs.map} +1 -1
- package/dist/{redirects-Cwkq2H-G.mjs → redirects-CufRQt0Q.mjs} +5 -5
- package/dist/{redirects-Cwkq2H-G.mjs.map → redirects-CufRQt0Q.mjs.map} +1 -1
- package/dist/{redirects-BOn2DIUs.mjs → redirects-cV9g7V-0.mjs} +149 -16
- package/dist/redirects-cV9g7V-0.mjs.map +1 -0
- package/dist/registry-C581V4TP.mjs +1275 -0
- package/dist/registry-C581V4TP.mjs.map +1 -0
- package/dist/{relation-DJ5DZh7B.mjs → relation-DtmAQH7s.mjs} +3 -3
- package/dist/{relation-DJ5DZh7B.mjs.map → relation-DtmAQH7s.mjs.map} +1 -1
- package/dist/{relations-C4duJnwI.mjs → relations-BBApI4e2.mjs} +3 -3
- package/dist/{relations-C4duJnwI.mjs.map → relations-BBApI4e2.mjs.map} +1 -1
- package/dist/{relations-DpTjftCl.mjs → relations-DICSyfsh.mjs} +6 -6
- package/dist/{relations-DpTjftCl.mjs.map → relations-DICSyfsh.mjs.map} +1 -1
- package/dist/{relations-DHFQGX0h.d.mts → relations-DItI3MN9.d.mts} +401 -40
- package/dist/relations-DItI3MN9.d.mts.map +1 -0
- package/dist/request-context.d.mts +3 -0
- package/dist/request-context.d.mts.map +1 -1
- package/dist/request-context.mjs.map +1 -1
- package/dist/{request-meta-DzXYYI-n.mjs → request-meta-DgZJh3zG.mjs} +2 -2
- package/dist/{request-meta-DzXYYI-n.mjs.map → request-meta-DgZJh3zG.mjs.map} +1 -1
- package/dist/{resolve-BUvFE0Lr.mjs → resolve-DOhVEvty.mjs} +2 -2
- package/dist/{resolve-BUvFE0Lr.mjs.map → resolve-DOhVEvty.mjs.map} +1 -1
- package/dist/{runner-BsI18UgP.mjs → runner-BiDvq5dv.mjs} +1404 -235
- package/dist/runner-BiDvq5dv.mjs.map +1 -0
- package/dist/{runner-CHdkERbt.d.mts → runner-CgQbELYC.d.mts} +2 -2
- package/dist/{runner-CHdkERbt.d.mts.map → runner-CgQbELYC.d.mts.map} +1 -1
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +5 -4
- package/dist/runtime.mjs.map +1 -1
- package/dist/{schema-eqZhkR0S.mjs → schema-BFyTg38T.mjs} +3 -3
- package/dist/{schema-eqZhkR0S.mjs.map → schema-BFyTg38T.mjs.map} +1 -1
- package/dist/schema-CeQSNwB3.mjs +390 -0
- package/dist/schema-CeQSNwB3.mjs.map +1 -0
- package/dist/{scopes-Be2d8bSb.mjs → scopes-BVeuhGBE.mjs} +3 -3
- package/dist/{scopes-Be2d8bSb.mjs.map → scopes-BVeuhGBE.mjs.map} +1 -1
- package/dist/{search-CeO678cp.mjs → search-BpuPKZb0.mjs} +26 -16
- package/dist/search-BpuPKZb0.mjs.map +1 -0
- package/dist/{secrets-870d-7yA.mjs → secrets-dtYs2hDo.mjs} +5 -5
- package/dist/{secrets-870d-7yA.mjs.map → secrets-dtYs2hDo.mjs.map} +1 -1
- package/dist/{sections-DSuEfirn.mjs → sections-COctk6hf.mjs} +3 -3
- package/dist/{sections-DSuEfirn.mjs.map → sections-COctk6hf.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +28 -26
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +20 -19
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-C3GDfT0V.mjs → seo-AFpVvTqr.mjs} +6 -4
- package/dist/seo-AFpVvTqr.mjs.map +1 -0
- package/dist/{seo-BAPKiED8.mjs → seo-CvDxfvFb.mjs} +3 -3
- package/dist/{seo-BAPKiED8.mjs.map → seo-CvDxfvFb.mjs.map} +1 -1
- package/dist/{service-DyFT-k-R.mjs → service-xMiMSTsR.mjs} +4 -4
- package/dist/{service-DyFT-k-R.mjs.map → service-xMiMSTsR.mjs.map} +1 -1
- package/dist/{session-user-BrK2zz7S.mjs → session-user-BzVemLkw.mjs} +2 -2
- package/dist/{session-user-BrK2zz7S.mjs.map → session-user-BzVemLkw.mjs.map} +1 -1
- package/dist/{settings-DgKouY2S.mjs → settings-B372MV0p.mjs} +7 -7
- package/dist/{settings-DgKouY2S.mjs.map → settings-B372MV0p.mjs.map} +1 -1
- package/dist/{settings-CREKyj8I.mjs → settings-BE9aqn_9.mjs} +3 -3
- package/dist/{settings-CREKyj8I.mjs.map → settings-BE9aqn_9.mjs.map} +1 -1
- package/dist/{setup-complete-L7bMK2VI.mjs → setup-complete-DF7TAfD5.mjs} +2 -2
- package/dist/{setup-complete-L7bMK2VI.mjs.map → setup-complete-DF7TAfD5.mjs.map} +1 -1
- package/dist/{setup-nonce-Ct5tjWcq.mjs → setup-nonce-Do-U_cg9.mjs} +1 -1
- package/dist/{setup-nonce-Ct5tjWcq.mjs.map → setup-nonce-Do-U_cg9.mjs.map} +1 -1
- package/dist/{single-flight-cache-C2exrGAi.mjs → single-flight-cache-B0eLKS6K.mjs} +2 -2
- package/dist/{single-flight-cache-C2exrGAi.mjs.map → single-flight-cache-B0eLKS6K.mjs.map} +1 -1
- package/dist/site-url-Bowsi9T-.mjs +16 -0
- package/dist/site-url-Bowsi9T-.mjs.map +1 -0
- package/dist/slugify-B994zkXC.mjs +17 -0
- package/dist/slugify-B994zkXC.mjs.map +1 -0
- package/dist/{snapshot-BdpUJKD-.mjs → snapshot-B5h6aPMh.mjs} +2 -2
- package/dist/{snapshot-BdpUJKD-.mjs.map → snapshot-B5h6aPMh.mjs.map} +1 -1
- package/dist/{ssrf-CviKqWmq.mjs → ssrf-Cpvg_n3A.mjs} +1 -1
- package/dist/{ssrf-CviKqWmq.mjs.map → ssrf-Cpvg_n3A.mjs.map} +1 -1
- package/dist/{state-xxv6ZTMv.mjs → state-DYwPue40.mjs} +1 -1
- package/dist/{state-xxv6ZTMv.mjs.map → state-DYwPue40.mjs.map} +1 -1
- package/dist/{status-COfycGIU.mjs → status-CWVYpbD8.mjs} +1 -1
- package/dist/{status-COfycGIU.mjs.map → status-CWVYpbD8.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/{taxonomies-B61CRSha.mjs → taxonomies-B0o9ExNV.mjs} +85 -75
- package/dist/taxonomies-B0o9ExNV.mjs.map +1 -0
- package/dist/{taxonomies-Dbdki3Un.mjs → taxonomies-Dk3MAklL.mjs} +360 -56
- package/dist/taxonomies-Dk3MAklL.mjs.map +1 -0
- package/dist/taxonomy-CPeM8d2o.mjs +484 -0
- package/dist/taxonomy-CPeM8d2o.mjs.map +1 -0
- package/dist/{tokens-DVltpO2D.mjs → tokens-C39klX8R.mjs} +2 -2
- package/dist/{tokens-DVltpO2D.mjs.map → tokens-C39klX8R.mjs.map} +1 -1
- package/dist/{transaction-D0FOsb3X.mjs → transaction-NQj4VJ7Z.mjs} +1 -1
- package/dist/{transaction-D0FOsb3X.mjs.map → transaction-NQj4VJ7Z.mjs.map} +1 -1
- package/dist/{transport-BWQo0Foy.mjs → transport--CfOflrp.mjs} +1 -1
- package/dist/{transport-BWQo0Foy.mjs.map → transport--CfOflrp.mjs.map} +1 -1
- package/dist/{transport-DokJOScS.d.mts → transport-B_rfeU-a.d.mts} +1 -1
- package/dist/{transport-DokJOScS.d.mts.map → transport-B_rfeU-a.d.mts.map} +1 -1
- package/dist/{trusted-proxy-CwjQj0YG.mjs → trusted-proxy-CEVekpby.mjs} +1 -1
- package/dist/{trusted-proxy-CwjQj0YG.mjs.map → trusted-proxy-CEVekpby.mjs.map} +1 -1
- package/dist/{types-o7xo7VgH.mjs → types-75KIqzL9.mjs} +20 -3
- package/dist/types-75KIqzL9.mjs.map +1 -0
- package/dist/{types-C9P3ysxq.d.mts → types-BPuloofb.d.mts} +1 -1
- package/dist/{types-C9P3ysxq.d.mts.map → types-BPuloofb.d.mts.map} +1 -1
- package/dist/{types-BD40g7zz.mjs → types-BW1syrlw.mjs} +1 -1
- package/dist/{types-BD40g7zz.mjs.map → types-BW1syrlw.mjs.map} +1 -1
- package/dist/{types-jISEalTX.d.mts → types-C3_AbkDP.d.mts} +53 -10
- package/dist/types-C3_AbkDP.d.mts.map +1 -0
- package/dist/{types-84Bque3-.d.mts → types-CAGdePf3.d.mts} +133 -1
- package/dist/types-CAGdePf3.d.mts.map +1 -0
- package/dist/{types-CcSZCcF1.d.mts → types-CFUfyt1s.d.mts} +1 -1
- package/dist/{types-CcSZCcF1.d.mts.map → types-CFUfyt1s.d.mts.map} +1 -1
- package/dist/{types-DQLZ58GV.d.mts → types-CPx2lIGo.d.mts} +1 -1
- package/dist/{types-DQLZ58GV.d.mts.map → types-CPx2lIGo.d.mts.map} +1 -1
- package/dist/{types-XrQQ-Aex.mjs → types-CQPWhPxE.mjs} +15 -11
- package/dist/types-CQPWhPxE.mjs.map +1 -0
- package/dist/{types-BQY7VYw6.d.mts → types-Cs-TFLNf.d.mts} +28 -8
- package/dist/types-Cs-TFLNf.d.mts.map +1 -0
- package/dist/types-CtzytVXn.mjs +18 -0
- package/dist/types-CtzytVXn.mjs.map +1 -0
- package/dist/{types-DqZVPILm.d.mts → types-D4_1Ga4L.d.mts} +44 -5
- package/dist/types-D4_1Ga4L.d.mts.map +1 -0
- package/dist/{types-Dr2GLlwu.d.mts → types-DefV3OiO.d.mts} +1 -1
- package/dist/{types-Dr2GLlwu.d.mts.map → types-DefV3OiO.d.mts.map} +1 -1
- package/dist/{types-DsAMyD_o.d.mts → types-X0MThr7x.d.mts} +1 -1
- package/dist/{types-DsAMyD_o.d.mts.map → types-X0MThr7x.d.mts.map} +1 -1
- package/dist/{upload-attempts-C5yd6Gae.mjs → upload-attempts-hlne3iA1.mjs} +1 -1
- package/dist/{upload-attempts-C5yd6Gae.mjs.map → upload-attempts-hlne3iA1.mjs.map} +1 -1
- package/dist/url-pattern-BHS0V5Ng.mjs +33 -0
- package/dist/url-pattern-BHS0V5Ng.mjs.map +1 -0
- package/dist/{user-BAumEmpA.mjs → user-sHgJ62SP.mjs} +3 -3
- package/dist/{user-BAumEmpA.mjs.map → user-sHgJ62SP.mjs.map} +1 -1
- package/dist/{utils-BbUgmeZG.mjs → utils-D4vD_Y98.mjs} +3 -3
- package/dist/{utils-BbUgmeZG.mjs.map → utils-D4vD_Y98.mjs.map} +1 -1
- package/dist/{validate-Bs_wT2ul.mjs → validate-BkqIG_Uj.mjs} +24 -5
- package/dist/validate-BkqIG_Uj.mjs.map +1 -0
- package/dist/{validate-VPnKoIzW.mjs → validate-BpwoDOgt.mjs} +25 -2
- package/dist/validate-BpwoDOgt.mjs.map +1 -0
- package/dist/{validate-CdYcY-Ln.d.mts → validate-DeGtBN84.d.mts} +25 -7
- package/dist/validate-DeGtBN84.d.mts.map +1 -0
- package/dist/{validation-BngR0nit.mjs → validation-CiJb_X5o.mjs} +14 -13
- package/dist/{validation-BngR0nit.mjs.map → validation-CiJb_X5o.mjs.map} +1 -1
- package/dist/version-x0NjTScG.mjs +7 -0
- package/dist/{version-Bdfb34kk.mjs.map → version-x0NjTScG.mjs.map} +1 -1
- package/dist/{widgets-L-VndTKD.mjs → widgets-Cwzvww0W.mjs} +3 -3
- package/dist/{widgets-L-VndTKD.mjs.map → widgets-Cwzvww0W.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-DueaLFd9.d.mts → wxr-taxonomies-CmC0ZsDr.d.mts} +1 -1
- package/dist/{wxr-taxonomies-DueaLFd9.d.mts.map → wxr-taxonomies-CmC0ZsDr.d.mts.map} +1 -1
- package/dist/{wxr-taxonomies-BexjtNid.mjs → wxr-taxonomies-QZjWxjyk.mjs} +13 -32
- package/dist/{wxr-taxonomies-BexjtNid.mjs.map → wxr-taxonomies-QZjWxjyk.mjs.map} +1 -1
- package/dist/{zod-generator-DMzfga3g.mjs → zod-generator-D11MhxG4.mjs} +53 -6
- package/dist/zod-generator-D11MhxG4.mjs.map +1 -0
- package/package.json +18 -7
- package/src/after.ts +6 -1
- package/src/api/errors.ts +13 -0
- package/src/api/handlers/content.ts +172 -33
- package/src/api/handlers/dashboard.ts +12 -2
- package/src/api/handlers/index.ts +16 -0
- package/src/api/handlers/manifest.ts +2 -0
- package/src/api/handlers/marketplace.ts +14 -0
- package/src/api/handlers/media-allowlist.ts +13 -2
- package/src/api/handlers/media-usage-work.ts +188 -0
- package/src/api/handlers/media-usage.ts +5 -3
- package/src/api/handlers/registry.ts +14 -0
- package/src/api/handlers/revision.ts +19 -5
- package/src/api/handlers/schema.ts +46 -3
- package/src/api/handlers/seo.ts +5 -2
- package/src/api/handlers/snapshot.ts +1 -1
- package/src/api/handlers/taxonomies.ts +446 -83
- package/src/api/media-usage-write-fence.ts +64 -0
- package/src/api/openapi/document.ts +247 -0
- package/src/api/public-url.ts +14 -2
- package/src/api/schemas/common.ts +3 -1
- package/src/api/schemas/content.ts +122 -1
- package/src/api/schemas/media-usage.ts +133 -0
- package/src/api/schemas/schema.ts +91 -3
- package/src/api/schemas/search.ts +2 -0
- package/src/api/schemas/taxonomies.ts +58 -8
- package/src/api/site-url.ts +16 -6
- package/src/api/types.ts +1 -0
- package/src/astro/integration/index.ts +55 -42
- package/src/astro/integration/routes.ts +48 -4
- package/src/astro/integration/runtime.ts +28 -0
- package/src/astro/integration/virtual-modules.ts +27 -1
- package/src/astro/integration/vite-config.ts +16 -1
- package/src/astro/middleware/media-usage-write-fence.ts +30 -0
- package/src/astro/middleware/redirect.ts +14 -12
- package/src/astro/middleware/scoped-db.ts +35 -4
- package/src/astro/middleware.ts +131 -30
- package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -1
- package/src/astro/routes/api/admin/media-usage/collection-deletions/index.ts +22 -0
- package/src/astro/routes/api/admin/media-usage/collection-deletions/retry.ts +22 -0
- package/src/astro/routes/api/admin/media-usage/work/index.ts +26 -0
- package/src/astro/routes/api/admin/media-usage/work/retry.ts +26 -0
- package/src/astro/routes/api/admin/plugins/[id]/disable.ts +4 -0
- package/src/astro/routes/api/admin/plugins/[id]/enable.ts +4 -0
- package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +4 -0
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +4 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/install.ts +4 -0
- package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +2 -2
- package/src/astro/routes/api/auth/invite/index.ts +2 -2
- package/src/astro/routes/api/auth/magic-link/send.ts +2 -2
- package/src/astro/routes/api/auth/signup/request.ts +2 -2
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +67 -31
- package/src/astro/routes/api/import/wordpress/execute.ts +3 -10
- package/src/astro/routes/api/mcp.ts +1 -0
- package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +7 -1
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +1 -7
- package/src/astro/routes/api/schema/collections/reorder.ts +31 -0
- package/src/astro/routes/api/schema/index.ts +2 -0
- package/src/astro/routes/api/search/enable.ts +5 -1
- package/src/astro/routes/api/search/rebuild.ts +6 -1
- package/src/astro/routes/api/taxonomies/[name]/reorder.ts +41 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +1 -0
- package/src/astro/routes/api/taxonomies/[name]/translations.ts +48 -0
- package/src/astro/routes/api/taxonomies/[name].ts +102 -0
- package/src/astro/types.ts +31 -4
- package/src/cleanup.ts +25 -26
- package/src/cli/commands/dev.ts +13 -3
- package/src/cli/commands/doctor.ts +193 -6
- package/src/cli/commands/export-seed.ts +6 -1
- package/src/cli/index.ts +1 -1
- package/src/client/index.ts +119 -0
- package/src/components/Block.astro +12 -0
- package/src/components/CommentForm.astro +1 -1
- package/src/components/Comments.astro +1 -1
- package/src/components/InlinePortableTextEditor.tsx +260 -32
- package/src/components/OrderedList.astro +14 -0
- package/src/components/PortableText.astro +26 -4
- package/src/components/index.ts +12 -1
- package/src/components/ordered-list.ts +549 -0
- package/src/content/converters/mark-safety.ts +120 -0
- package/src/content/converters/numbered-list.ts +148 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +84 -25
- package/src/content/converters/prosemirror-to-portable-text.ts +35 -14
- package/src/content/converters/types.ts +2 -0
- package/src/content/portable-text-lists.ts +205 -0
- package/src/content-list-query.ts +29 -0
- package/src/database/dialect-helpers.ts +3 -22
- package/src/database/migrations/055_content_translation_group_locale_index.ts +67 -0
- package/src/database/migrations/056_taxonomy_term_sort_order.ts +189 -0
- package/src/database/migrations/057_collection_hidden.ts +24 -0
- package/src/database/migrations/058_collection_sort_order.ts +20 -0
- package/src/database/migrations/059_revision_prune_queue.ts +36 -0
- package/src/database/migrations/060_collection_admin_config.ts +16 -0
- package/src/database/migrations/061_media_usage_cleanup.ts +77 -0
- package/src/database/migrations/062_media_usage_cleanup_fence.ts +295 -0
- package/src/database/migrations/063_media_usage_incremental_work.ts +397 -0
- package/src/database/migrations/064_fts_plain_text.ts +253 -0
- package/src/database/migrations/065_media_usage_collection_deletion.ts +85 -0
- package/src/database/migrations/066_media_usage_reconciliation.ts +115 -0
- package/src/database/migrations/067_indexed_content_fields.ts +39 -0
- package/src/database/migrations/068_content_taxonomy_entry_groups.ts +61 -0
- package/src/database/migrations/069_collection_title_date_fields.ts +45 -0
- package/src/database/migrations/070_collection_routable.ts +18 -0
- package/src/database/migrations/runner.ts +32 -0
- package/src/database/repositories/content.ts +1051 -273
- package/src/database/repositories/media-usage-work.ts +848 -0
- package/src/database/repositories/media-usage.ts +1502 -138
- package/src/database/repositories/revision.ts +98 -22
- package/src/database/repositories/taxonomy.ts +429 -103
- package/src/database/repositories/types.ts +58 -2
- package/src/database/types.ts +147 -17
- package/src/database/validate.ts +39 -0
- package/src/db/adapters.ts +36 -0
- package/src/db/index.ts +3 -0
- package/src/deferred-tasks.ts +71 -0
- package/src/emdash-runtime.ts +493 -110
- package/src/fields/file.ts +7 -4
- package/src/fields/image.ts +8 -1
- package/src/fields/types.ts +18 -5
- package/src/i18n/config.ts +32 -0
- package/src/i18n/repair-locale-casing.ts +0 -14
- package/src/i18n/taxonomy-locale-diagnostic.ts +47 -0
- package/src/import/wxr-taxonomies.ts +7 -47
- package/src/index.ts +27 -2
- package/src/loader.ts +165 -89
- package/src/mcp/server.ts +242 -34
- package/src/media/usage/activation.ts +626 -0
- package/src/media/usage/capture-triggers.ts +543 -0
- package/src/media/usage/cleanup.ts +305 -0
- package/src/media/usage/collection-deletion-processor.ts +356 -0
- package/src/media/usage/collection-deletion.ts +836 -0
- package/src/media/usage/content-fields.ts +40 -3
- package/src/media/usage/content-refresh.ts +356 -47
- package/src/media/usage/content-repair.ts +180 -61
- package/src/media/usage/content-snapshots.ts +85 -105
- package/src/media/usage/gc.ts +50 -0
- package/src/media/usage/projection-fingerprint.ts +129 -0
- package/src/media/usage/reconciliation-processor.ts +372 -0
- package/src/media/usage/reconciliation.ts +1117 -0
- package/src/media/usage/source-key.ts +4 -0
- package/src/media/usage/types.ts +2 -0
- package/src/media/usage/work-processor.ts +248 -0
- package/src/menus/index.ts +246 -141
- package/src/object-cache/index.ts +160 -3
- package/src/plugin-types.ts +8 -0
- package/src/plugins/adapt-sandbox-entry.ts +24 -5
- package/src/plugins/context.ts +24 -7
- package/src/plugins/index.ts +9 -0
- package/src/plugins/routes.ts +77 -1
- package/src/plugins/sandbox/index.ts +10 -1
- package/src/plugins/sandbox/types.ts +78 -1
- package/src/plugins/scheduler/node.ts +13 -1
- package/src/plugins/scheduler/types.ts +2 -0
- package/src/plugins/storage-indexes.ts +50 -11
- package/src/plugins/types.ts +39 -2
- package/src/query.ts +50 -79
- package/src/redirects/cache.ts +79 -19
- package/src/request-context.ts +3 -0
- package/src/scheduled-publish.ts +6 -1
- package/src/scheduler-health.ts +46 -0
- package/src/schema/registry.ts +863 -249
- package/src/schema/types.ts +74 -8
- package/src/schema/url-pattern.ts +33 -0
- package/src/schema/zod-generator.ts +77 -5
- package/src/search/fts-manager.ts +167 -86
- package/src/search/index.ts +2 -0
- package/src/search/query.ts +32 -11
- package/src/search/types.ts +8 -0
- package/src/seed/apply.ts +89 -16
- package/src/seed/types.ts +21 -3
- package/src/seed/validate.ts +52 -2
- package/src/taxonomies/index.ts +88 -82
- package/src/taxonomies/term-counts.ts +23 -12
- package/src/ui-comments.ts +19 -0
- package/src/ui.ts +11 -3
- package/src/utils/slugify.ts +1 -29
- package/src/virtual-modules.d.ts +24 -0
- package/dist/adapters-C0ONzkUP.d.mts.map +0 -1
- package/dist/after-B1IIdH3Y.mjs +0 -29
- package/dist/after-B1IIdH3Y.mjs.map +0 -1
- package/dist/api-DgPbMlng.mjs.map +0 -1
- package/dist/apply-1_6ra7NP.mjs.map +0 -1
- package/dist/cache-B26cufFd.mjs +0 -65
- package/dist/cache-B26cufFd.mjs.map +0 -1
- package/dist/config-DyF3OKg_.mjs.map +0 -1
- package/dist/content-CpfKV9QE.mjs.map +0 -1
- package/dist/content-refresh-DgqUBeTv.mjs +0 -1629
- package/dist/content-refresh-DgqUBeTv.mjs.map +0 -1
- package/dist/context-kO4YZB03.mjs.map +0 -1
- package/dist/dashboard-DoBwPnON.mjs.map +0 -1
- package/dist/dialect-helpers-DFwyWjTM.mjs.map +0 -1
- package/dist/errors-DtEXIQQV.mjs.map +0 -1
- package/dist/fts-manager-vncsZIJm.mjs.map +0 -1
- package/dist/index-BeNto_Vs.d.mts.map +0 -1
- package/dist/index-j9rTh3cp.d.mts.map +0 -1
- package/dist/loader-C1XOLV5b.mjs.map +0 -1
- package/dist/media-DWIzoVFL.mjs.map +0 -1
- package/dist/media-allowlist-B7TPD6aq.mjs.map +0 -1
- package/dist/media-usage-DPJcNaAq.mjs.map +0 -1
- package/dist/menus-C6qhqP4X.mjs.map +0 -1
- package/dist/object-cache-Bok5j2ae.mjs.map +0 -1
- package/dist/options-aeIs8WFu.d.mts.map +0 -1
- package/dist/public-url-DSGTnJFw.mjs.map +0 -1
- package/dist/query-DCiXI7OZ.mjs.map +0 -1
- package/dist/redirects-BOn2DIUs.mjs.map +0 -1
- package/dist/registry-BP1JK2xh.mjs +0 -795
- package/dist/registry-BP1JK2xh.mjs.map +0 -1
- package/dist/relations-DHFQGX0h.d.mts.map +0 -1
- package/dist/runner-BsI18UgP.mjs.map +0 -1
- package/dist/search-CeO678cp.mjs.map +0 -1
- package/dist/seo-C3GDfT0V.mjs.map +0 -1
- package/dist/site-url-8N3kSyVZ.mjs +0 -13
- package/dist/site-url-8N3kSyVZ.mjs.map +0 -1
- package/dist/slugify-C_tqlU4G.mjs +0 -30
- package/dist/slugify-C_tqlU4G.mjs.map +0 -1
- package/dist/taxonomies-B61CRSha.mjs.map +0 -1
- package/dist/taxonomies-Dbdki3Un.mjs.map +0 -1
- package/dist/taxonomy-DvwWAPvA.mjs +0 -304
- package/dist/taxonomy-DvwWAPvA.mjs.map +0 -1
- package/dist/types-84Bque3-.d.mts.map +0 -1
- package/dist/types-BQY7VYw6.d.mts.map +0 -1
- package/dist/types-DqZVPILm.d.mts.map +0 -1
- package/dist/types-XrQQ-Aex.mjs.map +0 -1
- package/dist/types-jISEalTX.d.mts.map +0 -1
- package/dist/types-o7xo7VgH.mjs.map +0 -1
- package/dist/validate-Bs_wT2ul.mjs.map +0 -1
- package/dist/validate-CdYcY-Ln.d.mts.map +0 -1
- package/dist/validate-VPnKoIzW.mjs.map +0 -1
- package/dist/version-Bdfb34kk.mjs +0 -7
- package/dist/zod-generator-DMzfga3g.mjs.map +0 -1
- /package/dist/{api-tokens-CEsW_jCg.mjs → api-tokens-CyTsLszZ.mjs} +0 -0
- /package/dist/{ssrf-BB__xfNM.mjs → ssrf-DpXgKsna.mjs} +0 -0
- /package/dist/{types-CK0LxPUQ.mjs → types-CP1CflWf.mjs} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MIGRATION_LOCK_BUSY_MESSAGE } from "./database/pg-migration-lock.mjs";
|
|
2
|
-
import { t as validateIdentifier } from "./validate-
|
|
3
|
-
import { a as currentTimestamp, c as isSqlite,
|
|
4
|
-
import {
|
|
2
|
+
import { t as validateIdentifier } from "./validate-BpwoDOgt.mjs";
|
|
3
|
+
import { a as currentTimestamp, c as isSqlite, o as currentTimestampValue, p as tableExists, r as columnExists, s as isPostgres, t as binaryType, u as listTablesLike } from "./dialect-helpers-BSbfaO3F.mjs";
|
|
4
|
+
import { r as getI18nConfig } from "./config-C3EBstHi.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { sql } from "kysely";
|
|
7
7
|
import { Migrator } from "kysely/migration";
|
|
@@ -25,8 +25,8 @@ var __exportAll = (all, no_symbols) => {
|
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/database/migrations/001_initial.ts
|
|
27
27
|
var _001_initial_exports = /* @__PURE__ */ __exportAll({
|
|
28
|
-
down: () => down$
|
|
29
|
-
up: () => up$
|
|
28
|
+
down: () => down$68,
|
|
29
|
+
up: () => up$68
|
|
30
30
|
});
|
|
31
31
|
/**
|
|
32
32
|
* Initial schema migration
|
|
@@ -35,7 +35,7 @@ var _001_initial_exports = /* @__PURE__ */ __exportAll({
|
|
|
35
35
|
* by the SchemaRegistry when collections are added via the admin UI.
|
|
36
36
|
* This migration only creates system tables.
|
|
37
37
|
*/
|
|
38
|
-
async function up$
|
|
38
|
+
async function up$68(db) {
|
|
39
39
|
await db.schema.createTable("revisions").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("collection", "text", (col) => col.notNull()).addColumn("entry_id", "text", (col) => col.notNull()).addColumn("data", "text", (col) => col.notNull()).addColumn("author_id", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
40
40
|
await db.schema.createIndex("idx_revisions_entry").ifNotExists().on("revisions").columns(["collection", "entry_id"]).execute();
|
|
41
41
|
await db.schema.createTable("taxonomies").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("name", "text", (col) => col.notNull()).addColumn("slug", "text", (col) => col.notNull()).addColumn("label", "text", (col) => col.notNull()).addColumn("parent_id", "text").addColumn("data", "text").addUniqueConstraint("taxonomies_name_slug_unique", ["name", "slug"]).addForeignKeyConstraint("taxonomies_parent_fk", ["parent_id"], "taxonomies", ["id"], (cb) => cb.onDelete("set null")).execute();
|
|
@@ -55,7 +55,7 @@ async function up$52(db) {
|
|
|
55
55
|
await db.schema.createIndex("idx_audit_action").ifNotExists().on("audit_logs").column("action").execute();
|
|
56
56
|
await db.schema.createIndex("idx_audit_timestamp").ifNotExists().on("audit_logs").column("timestamp").execute();
|
|
57
57
|
}
|
|
58
|
-
async function down$
|
|
58
|
+
async function down$68(db) {
|
|
59
59
|
await db.schema.dropTable("audit_logs").execute();
|
|
60
60
|
await db.schema.dropTable("options").execute();
|
|
61
61
|
await db.schema.dropTable("users").execute();
|
|
@@ -68,26 +68,26 @@ async function down$52(db) {
|
|
|
68
68
|
//#endregion
|
|
69
69
|
//#region src/database/migrations/002_media_status.ts
|
|
70
70
|
var _002_media_status_exports = /* @__PURE__ */ __exportAll({
|
|
71
|
-
down: () => down$
|
|
72
|
-
up: () => up$
|
|
71
|
+
down: () => down$67,
|
|
72
|
+
up: () => up$67
|
|
73
73
|
});
|
|
74
74
|
/**
|
|
75
75
|
* Add status column to media table for tracking upload state.
|
|
76
76
|
* Status values: 'pending' | 'ready' | 'failed'
|
|
77
77
|
*/
|
|
78
|
-
async function up$
|
|
78
|
+
async function up$67(db) {
|
|
79
79
|
await db.schema.alterTable("media").addColumn("status", "text", (col) => col.notNull().defaultTo("ready")).execute();
|
|
80
80
|
await db.schema.createIndex("idx_media_status").on("media").column("status").execute();
|
|
81
81
|
}
|
|
82
|
-
async function down$
|
|
82
|
+
async function down$67(db) {
|
|
83
83
|
await db.schema.dropIndex("idx_media_status").execute();
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
//#endregion
|
|
87
87
|
//#region src/database/migrations/003_schema_registry.ts
|
|
88
88
|
var _003_schema_registry_exports = /* @__PURE__ */ __exportAll({
|
|
89
|
-
down: () => down$
|
|
90
|
-
up: () => up$
|
|
89
|
+
down: () => down$66,
|
|
90
|
+
up: () => up$66
|
|
91
91
|
});
|
|
92
92
|
/**
|
|
93
93
|
* Migration: Schema Registry Tables
|
|
@@ -95,14 +95,14 @@ var _003_schema_registry_exports = /* @__PURE__ */ __exportAll({
|
|
|
95
95
|
* Creates the schema registry tables that store collection and field definitions.
|
|
96
96
|
* This enables dynamic schema management where D1 is the source of truth.
|
|
97
97
|
*/
|
|
98
|
-
async function up$
|
|
98
|
+
async function up$66(db) {
|
|
99
99
|
await db.schema.createTable("_emdash_collections").addColumn("id", "text", (col) => col.primaryKey()).addColumn("slug", "text", (col) => col.notNull().unique()).addColumn("label", "text", (col) => col.notNull()).addColumn("label_singular", "text").addColumn("description", "text").addColumn("icon", "text").addColumn("supports", "text").addColumn("source", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
100
100
|
await db.schema.createTable("_emdash_fields").addColumn("id", "text", (col) => col.primaryKey()).addColumn("collection_id", "text", (col) => col.notNull()).addColumn("slug", "text", (col) => col.notNull()).addColumn("label", "text", (col) => col.notNull()).addColumn("type", "text", (col) => col.notNull()).addColumn("column_type", "text", (col) => col.notNull()).addColumn("required", "integer", (col) => col.defaultTo(0)).addColumn("unique", "integer", (col) => col.defaultTo(0)).addColumn("default_value", "text").addColumn("validation", "text").addColumn("widget", "text").addColumn("options", "text").addColumn("sort_order", "integer", (col) => col.defaultTo(0)).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addForeignKeyConstraint("fields_collection_fk", ["collection_id"], "_emdash_collections", ["id"], (cb) => cb.onDelete("cascade")).execute();
|
|
101
101
|
await db.schema.createIndex("idx_fields_collection_slug").on("_emdash_fields").columns(["collection_id", "slug"]).unique().execute();
|
|
102
102
|
await db.schema.createIndex("idx_fields_collection").on("_emdash_fields").column("collection_id").execute();
|
|
103
103
|
await db.schema.createIndex("idx_fields_sort").on("_emdash_fields").columns(["collection_id", "sort_order"]).execute();
|
|
104
104
|
}
|
|
105
|
-
async function down$
|
|
105
|
+
async function down$66(db) {
|
|
106
106
|
await db.schema.dropTable("_emdash_fields").execute();
|
|
107
107
|
await db.schema.dropTable("_emdash_collections").execute();
|
|
108
108
|
}
|
|
@@ -110,8 +110,8 @@ async function down$50(db) {
|
|
|
110
110
|
//#endregion
|
|
111
111
|
//#region src/database/migrations/004_plugins.ts
|
|
112
112
|
var _004_plugins_exports = /* @__PURE__ */ __exportAll({
|
|
113
|
-
down: () => down$
|
|
114
|
-
up: () => up$
|
|
113
|
+
down: () => down$65,
|
|
114
|
+
up: () => up$65
|
|
115
115
|
});
|
|
116
116
|
/**
|
|
117
117
|
* Migration: Plugin System Tables
|
|
@@ -121,7 +121,7 @@ var _004_plugins_exports = /* @__PURE__ */ __exportAll({
|
|
|
121
121
|
*
|
|
122
122
|
* @see PLUGIN-SYSTEM.md § Plugin Storage
|
|
123
123
|
*/
|
|
124
|
-
async function up$
|
|
124
|
+
async function up$65(db) {
|
|
125
125
|
await db.schema.createTable("_plugin_storage").addColumn("plugin_id", "text", (col) => col.notNull()).addColumn("collection", "text", (col) => col.notNull()).addColumn("id", "text", (col) => col.notNull()).addColumn("data", "text", (col) => col.notNull()).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addPrimaryKeyConstraint("pk_plugin_storage", [
|
|
126
126
|
"plugin_id",
|
|
127
127
|
"collection",
|
|
@@ -139,7 +139,7 @@ async function up$49(db) {
|
|
|
139
139
|
"index_name"
|
|
140
140
|
]).execute();
|
|
141
141
|
}
|
|
142
|
-
async function down$
|
|
142
|
+
async function down$65(db) {
|
|
143
143
|
await db.schema.dropTable("_plugin_indexes").execute();
|
|
144
144
|
await db.schema.dropTable("_plugin_state").execute();
|
|
145
145
|
await db.schema.dropTable("_plugin_storage").execute();
|
|
@@ -148,8 +148,8 @@ async function down$49(db) {
|
|
|
148
148
|
//#endregion
|
|
149
149
|
//#region src/database/migrations/005_menus.ts
|
|
150
150
|
var _005_menus_exports = /* @__PURE__ */ __exportAll({
|
|
151
|
-
down: () => down$
|
|
152
|
-
up: () => up$
|
|
151
|
+
down: () => down$64,
|
|
152
|
+
up: () => up$64
|
|
153
153
|
});
|
|
154
154
|
/**
|
|
155
155
|
* Navigation Menus migration
|
|
@@ -157,13 +157,13 @@ var _005_menus_exports = /* @__PURE__ */ __exportAll({
|
|
|
157
157
|
* Creates tables for admin-editable navigation menus.
|
|
158
158
|
* Menu items can reference content entries, taxonomy terms, or custom URLs.
|
|
159
159
|
*/
|
|
160
|
-
async function up$
|
|
160
|
+
async function up$64(db) {
|
|
161
161
|
await db.schema.createTable("_emdash_menus").addColumn("id", "text", (col) => col.primaryKey()).addColumn("name", "text", (col) => col.notNull().unique()).addColumn("label", "text", (col) => col.notNull()).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
162
162
|
await db.schema.createTable("_emdash_menu_items").addColumn("id", "text", (col) => col.primaryKey()).addColumn("menu_id", "text", (col) => col.notNull()).addColumn("parent_id", "text").addColumn("sort_order", "integer", (col) => col.notNull().defaultTo(0)).addColumn("type", "text", (col) => col.notNull()).addColumn("reference_collection", "text").addColumn("reference_id", "text").addColumn("custom_url", "text").addColumn("label", "text", (col) => col.notNull()).addColumn("title_attr", "text").addColumn("target", "text").addColumn("css_classes", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addForeignKeyConstraint("menu_items_menu_fk", ["menu_id"], "_emdash_menus", ["id"], (cb) => cb.onDelete("cascade")).addForeignKeyConstraint("menu_items_parent_fk", ["parent_id"], "_emdash_menu_items", ["id"], (cb) => cb.onDelete("cascade")).execute();
|
|
163
163
|
await db.schema.createIndex("idx_menu_items_menu").on("_emdash_menu_items").columns(["menu_id", "sort_order"]).execute();
|
|
164
164
|
await db.schema.createIndex("idx_menu_items_parent").on("_emdash_menu_items").column("parent_id").execute();
|
|
165
165
|
}
|
|
166
|
-
async function down$
|
|
166
|
+
async function down$64(db) {
|
|
167
167
|
await db.schema.dropTable("_emdash_menu_items").execute();
|
|
168
168
|
await db.schema.dropTable("_emdash_menus").execute();
|
|
169
169
|
}
|
|
@@ -171,8 +171,8 @@ async function down$48(db) {
|
|
|
171
171
|
//#endregion
|
|
172
172
|
//#region src/database/migrations/006_taxonomy_defs.ts
|
|
173
173
|
var _006_taxonomy_defs_exports = /* @__PURE__ */ __exportAll({
|
|
174
|
-
down: () => down$
|
|
175
|
-
up: () => up$
|
|
174
|
+
down: () => down$63,
|
|
175
|
+
up: () => up$63
|
|
176
176
|
});
|
|
177
177
|
/**
|
|
178
178
|
* Taxonomy definitions migration
|
|
@@ -180,7 +180,7 @@ var _006_taxonomy_defs_exports = /* @__PURE__ */ __exportAll({
|
|
|
180
180
|
* Adds _emdash_taxonomy_defs table to store taxonomy definitions (category, tag, custom)
|
|
181
181
|
* and seeds default category and tag taxonomies.
|
|
182
182
|
*/
|
|
183
|
-
async function up$
|
|
183
|
+
async function up$63(db) {
|
|
184
184
|
await db.schema.createTable("_emdash_taxonomy_defs").addColumn("id", "text", (col) => col.primaryKey()).addColumn("name", "text", (col) => col.notNull().unique()).addColumn("label", "text", (col) => col.notNull()).addColumn("label_singular", "text").addColumn("hierarchical", "integer", (col) => col.defaultTo(0)).addColumn("collections", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
185
185
|
await db.insertInto("_emdash_taxonomy_defs").values([{
|
|
186
186
|
id: "taxdef_category",
|
|
@@ -198,22 +198,22 @@ async function up$47(db) {
|
|
|
198
198
|
collections: JSON.stringify(["posts"])
|
|
199
199
|
}]).execute();
|
|
200
200
|
}
|
|
201
|
-
async function down$
|
|
201
|
+
async function down$63(db) {
|
|
202
202
|
await db.schema.dropTable("_emdash_taxonomy_defs").execute();
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
//#endregion
|
|
206
206
|
//#region src/database/migrations/007_widgets.ts
|
|
207
207
|
var _007_widgets_exports = /* @__PURE__ */ __exportAll({
|
|
208
|
-
down: () => down$
|
|
209
|
-
up: () => up$
|
|
208
|
+
down: () => down$62,
|
|
209
|
+
up: () => up$62
|
|
210
210
|
});
|
|
211
|
-
async function up$
|
|
211
|
+
async function up$62(db) {
|
|
212
212
|
await db.schema.createTable("_emdash_widget_areas").addColumn("id", "text", (col) => col.primaryKey()).addColumn("name", "text", (col) => col.notNull().unique()).addColumn("label", "text", (col) => col.notNull()).addColumn("description", "text").addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
213
213
|
await db.schema.createTable("_emdash_widgets").addColumn("id", "text", (col) => col.primaryKey()).addColumn("area_id", "text", (col) => col.notNull().references("_emdash_widget_areas.id").onDelete("cascade")).addColumn("sort_order", "integer", (col) => col.notNull().defaultTo(0)).addColumn("type", "text", (col) => col.notNull()).addColumn("title", "text").addColumn("content", "text").addColumn("menu_name", "text").addColumn("component_id", "text").addColumn("component_props", "text").addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
214
214
|
await db.schema.createIndex("idx_widgets_area").on("_emdash_widgets").columns(["area_id", "sort_order"]).execute();
|
|
215
215
|
}
|
|
216
|
-
async function down$
|
|
216
|
+
async function down$62(db) {
|
|
217
217
|
await db.schema.dropTable("_emdash_widgets").execute();
|
|
218
218
|
await db.schema.dropTable("_emdash_widget_areas").execute();
|
|
219
219
|
}
|
|
@@ -221,8 +221,8 @@ async function down$46(db) {
|
|
|
221
221
|
//#endregion
|
|
222
222
|
//#region src/database/migrations/008_auth.ts
|
|
223
223
|
var _008_auth_exports = /* @__PURE__ */ __exportAll({
|
|
224
|
-
down: () => down$
|
|
225
|
-
up: () => up$
|
|
224
|
+
down: () => down$61,
|
|
225
|
+
up: () => up$61
|
|
226
226
|
});
|
|
227
227
|
/**
|
|
228
228
|
* Auth migration - passkey-first authentication
|
|
@@ -236,7 +236,7 @@ var _008_auth_exports = /* @__PURE__ */ __exportAll({
|
|
|
236
236
|
* - Creates oauth_accounts table (external provider links)
|
|
237
237
|
* - Creates allowed_domains table (self-signup)
|
|
238
238
|
*/
|
|
239
|
-
async function up$
|
|
239
|
+
async function up$61(db) {
|
|
240
240
|
await db.schema.createTable("users_new").addColumn("id", "text", (col) => col.primaryKey()).addColumn("email", "text", (col) => col.notNull().unique()).addColumn("name", "text").addColumn("avatar_url", "text").addColumn("role", "integer", (col) => col.notNull().defaultTo(10)).addColumn("email_verified", "integer", (col) => col.notNull().defaultTo(0)).addColumn("data", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
241
241
|
await sql`
|
|
242
242
|
INSERT INTO users_new (id, email, name, role, data, created_at, updated_at)
|
|
@@ -269,7 +269,7 @@ async function up$45(db) {
|
|
|
269
269
|
await db.schema.createTable("auth_challenges").addColumn("challenge", "text", (col) => col.primaryKey()).addColumn("type", "text", (col) => col.notNull()).addColumn("user_id", "text").addColumn("data", "text").addColumn("expires_at", "text", (col) => col.notNull()).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
270
270
|
await db.schema.createIndex("idx_auth_challenges_expires").on("auth_challenges").column("expires_at").execute();
|
|
271
271
|
}
|
|
272
|
-
async function down$
|
|
272
|
+
async function down$61(db) {
|
|
273
273
|
await db.schema.dropTable("auth_challenges").execute();
|
|
274
274
|
await db.schema.dropTable("allowed_domains").execute();
|
|
275
275
|
await db.schema.dropTable("oauth_accounts").execute();
|
|
@@ -302,8 +302,8 @@ async function down$45(db) {
|
|
|
302
302
|
//#endregion
|
|
303
303
|
//#region src/database/migrations/009_user_disabled.ts
|
|
304
304
|
var _009_user_disabled_exports = /* @__PURE__ */ __exportAll({
|
|
305
|
-
down: () => down$
|
|
306
|
-
up: () => up$
|
|
305
|
+
down: () => down$60,
|
|
306
|
+
up: () => up$60
|
|
307
307
|
});
|
|
308
308
|
/**
|
|
309
309
|
* User disabled column - for soft-disabling users
|
|
@@ -312,19 +312,19 @@ var _009_user_disabled_exports = /* @__PURE__ */ __exportAll({
|
|
|
312
312
|
* - Adds disabled column to users table (INTEGER, default 0)
|
|
313
313
|
* - Disabled users cannot log in
|
|
314
314
|
*/
|
|
315
|
-
async function up$
|
|
315
|
+
async function up$60(db) {
|
|
316
316
|
await sql`ALTER TABLE users ADD COLUMN disabled INTEGER NOT NULL DEFAULT 0`.execute(db);
|
|
317
317
|
await db.schema.createIndex("idx_users_disabled").on("users").column("disabled").execute();
|
|
318
318
|
}
|
|
319
|
-
async function down$
|
|
319
|
+
async function down$60(db) {
|
|
320
320
|
await db.schema.dropIndex("idx_users_disabled").execute();
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
//#endregion
|
|
324
324
|
//#region src/database/migrations/011_sections.ts
|
|
325
325
|
var _011_sections_exports = /* @__PURE__ */ __exportAll({
|
|
326
|
-
down: () => down$
|
|
327
|
-
up: () => up$
|
|
326
|
+
down: () => down$59,
|
|
327
|
+
up: () => up$59
|
|
328
328
|
});
|
|
329
329
|
/**
|
|
330
330
|
* Migration: Add sections tables and performance indexes
|
|
@@ -333,13 +333,13 @@ var _011_sections_exports = /* @__PURE__ */ __exportAll({
|
|
|
333
333
|
* They provide a library of pre-built page sections (heroes, CTAs, testimonials, etc.)
|
|
334
334
|
* that content authors can browse and insert with a single click.
|
|
335
335
|
*/
|
|
336
|
-
async function up$
|
|
336
|
+
async function up$59(db) {
|
|
337
337
|
await db.schema.createTable("_emdash_section_categories").addColumn("id", "text", (col) => col.primaryKey()).addColumn("slug", "text", (col) => col.notNull().unique()).addColumn("label", "text", (col) => col.notNull()).addColumn("sort_order", "integer", (col) => col.defaultTo(0)).addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
338
338
|
await db.schema.createTable("_emdash_sections").addColumn("id", "text", (col) => col.primaryKey()).addColumn("slug", "text", (col) => col.notNull().unique()).addColumn("title", "text", (col) => col.notNull()).addColumn("description", "text").addColumn("category_id", "text", (col) => col.references("_emdash_section_categories.id").onDelete("set null")).addColumn("keywords", "text").addColumn("content", "text", (col) => col.notNull()).addColumn("preview_media_id", "text").addColumn("source", "text", (col) => col.notNull().defaultTo("user")).addColumn("theme_id", "text").addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).addColumn("updated_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
339
339
|
await db.schema.createIndex("idx_sections_category").on("_emdash_sections").columns(["category_id"]).execute();
|
|
340
340
|
await db.schema.createIndex("idx_sections_source").on("_emdash_sections").columns(["source"]).execute();
|
|
341
341
|
}
|
|
342
|
-
async function down$
|
|
342
|
+
async function down$59(db) {
|
|
343
343
|
await db.schema.dropIndex("idx_sections_source").execute();
|
|
344
344
|
await db.schema.dropIndex("idx_sections_category").execute();
|
|
345
345
|
await db.schema.dropTable("_emdash_sections").execute();
|
|
@@ -349,8 +349,8 @@ async function down$43(db) {
|
|
|
349
349
|
//#endregion
|
|
350
350
|
//#region src/database/migrations/012_search.ts
|
|
351
351
|
var _012_search_exports = /* @__PURE__ */ __exportAll({
|
|
352
|
-
down: () => down$
|
|
353
|
-
up: () => up$
|
|
352
|
+
down: () => down$58,
|
|
353
|
+
up: () => up$58
|
|
354
354
|
});
|
|
355
355
|
/**
|
|
356
356
|
* Migration: Search Support
|
|
@@ -358,11 +358,11 @@ var _012_search_exports = /* @__PURE__ */ __exportAll({
|
|
|
358
358
|
* Adds search configuration to collections and searchable flag to fields.
|
|
359
359
|
* FTS5 tables are created dynamically when search is enabled for a collection.
|
|
360
360
|
*/
|
|
361
|
-
async function up$
|
|
361
|
+
async function up$58(db) {
|
|
362
362
|
await db.schema.alterTable("_emdash_collections").addColumn("search_config", "text").execute();
|
|
363
363
|
await db.schema.alterTable("_emdash_fields").addColumn("searchable", "integer", (col) => col.defaultTo(0)).execute();
|
|
364
364
|
}
|
|
365
|
-
async function down$
|
|
365
|
+
async function down$58(db) {
|
|
366
366
|
await db.schema.alterTable("_emdash_fields").dropColumn("searchable").execute();
|
|
367
367
|
await db.schema.alterTable("_emdash_collections").dropColumn("search_config").execute();
|
|
368
368
|
}
|
|
@@ -370,8 +370,8 @@ async function down$42(db) {
|
|
|
370
370
|
//#endregion
|
|
371
371
|
//#region src/database/migrations/013_scheduled_publishing.ts
|
|
372
372
|
var _013_scheduled_publishing_exports = /* @__PURE__ */ __exportAll({
|
|
373
|
-
down: () => down$
|
|
374
|
-
up: () => up$
|
|
373
|
+
down: () => down$57,
|
|
374
|
+
up: () => up$57
|
|
375
375
|
});
|
|
376
376
|
/**
|
|
377
377
|
* Migration: Add scheduled publishing support
|
|
@@ -380,7 +380,7 @@ var _013_scheduled_publishing_exports = /* @__PURE__ */ __exportAll({
|
|
|
380
380
|
* When scheduled_at is set and status is 'scheduled', the content
|
|
381
381
|
* will be auto-published when the scheduled time is reached.
|
|
382
382
|
*/
|
|
383
|
-
async function up$
|
|
383
|
+
async function up$57(db) {
|
|
384
384
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
385
385
|
for (const tableName of tableNames) {
|
|
386
386
|
const table = { name: tableName };
|
|
@@ -395,7 +395,7 @@ async function up$41(db) {
|
|
|
395
395
|
`.execute(db);
|
|
396
396
|
}
|
|
397
397
|
}
|
|
398
|
-
async function down$
|
|
398
|
+
async function down$57(db) {
|
|
399
399
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
400
400
|
for (const tableName of tableNames) {
|
|
401
401
|
const table = { name: tableName };
|
|
@@ -412,10 +412,10 @@ async function down$41(db) {
|
|
|
412
412
|
//#endregion
|
|
413
413
|
//#region src/database/migrations/014_draft_revisions.ts
|
|
414
414
|
var _014_draft_revisions_exports = /* @__PURE__ */ __exportAll({
|
|
415
|
-
down: () => down$
|
|
416
|
-
up: () => up$
|
|
415
|
+
down: () => down$56,
|
|
416
|
+
up: () => up$56
|
|
417
417
|
});
|
|
418
|
-
async function up$
|
|
418
|
+
async function up$56(db) {
|
|
419
419
|
const tables = await db.selectFrom("_emdash_collections").select("slug").execute();
|
|
420
420
|
for (const row of tables) {
|
|
421
421
|
const tableName = `ec_${row.slug}`;
|
|
@@ -437,7 +437,7 @@ async function up$40(db) {
|
|
|
437
437
|
`.execute(db);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
|
-
async function down$
|
|
440
|
+
async function down$56(db) {
|
|
441
441
|
const tables = await db.selectFrom("_emdash_collections").select("slug").execute();
|
|
442
442
|
for (const row of tables) {
|
|
443
443
|
const tableName = `ec_${row.slug}`;
|
|
@@ -461,8 +461,8 @@ async function down$40(db) {
|
|
|
461
461
|
//#endregion
|
|
462
462
|
//#region src/database/migrations/015_indexes.ts
|
|
463
463
|
var _015_indexes_exports = /* @__PURE__ */ __exportAll({
|
|
464
|
-
down: () => down$
|
|
465
|
-
up: () => up$
|
|
464
|
+
down: () => down$55,
|
|
465
|
+
up: () => up$55
|
|
466
466
|
});
|
|
467
467
|
/**
|
|
468
468
|
* Add performance indexes for common query patterns.
|
|
@@ -475,7 +475,7 @@ var _015_indexes_exports = /* @__PURE__ */ __exportAll({
|
|
|
475
475
|
* 5. Retroactive author_id + updated_at on existing ec_* content tables
|
|
476
476
|
* (new tables get these from createContentTable() in registry.ts)
|
|
477
477
|
*/
|
|
478
|
-
async function up$
|
|
478
|
+
async function up$55(db) {
|
|
479
479
|
await db.schema.createIndex("idx_media_mime_type").on("media").column("mime_type").execute();
|
|
480
480
|
await db.schema.createIndex("idx_media_filename").on("media").column("filename").execute();
|
|
481
481
|
await db.schema.createIndex("idx_media_created_at").on("media").column("created_at").execute();
|
|
@@ -495,7 +495,7 @@ async function up$39(db) {
|
|
|
495
495
|
`.execute(db);
|
|
496
496
|
}
|
|
497
497
|
}
|
|
498
|
-
async function down$
|
|
498
|
+
async function down$55(db) {
|
|
499
499
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
500
500
|
for (const tableName of tableNames) {
|
|
501
501
|
const table = { name: tableName };
|
|
@@ -513,8 +513,8 @@ async function down$39(db) {
|
|
|
513
513
|
//#endregion
|
|
514
514
|
//#region src/database/migrations/016_api_tokens.ts
|
|
515
515
|
var _016_api_tokens_exports = /* @__PURE__ */ __exportAll({
|
|
516
|
-
down: () => down$
|
|
517
|
-
up: () => up$
|
|
516
|
+
down: () => down$54,
|
|
517
|
+
up: () => up$54
|
|
518
518
|
});
|
|
519
519
|
/**
|
|
520
520
|
* API token tables for programmatic access.
|
|
@@ -532,7 +532,7 @@ var _016_api_tokens_exports = /* @__PURE__ */ __exportAll({
|
|
|
532
532
|
* top. Without these guards, the retry crashed with `table ... already
|
|
533
533
|
* exists` and blocked every subsequent boot of the Worker.
|
|
534
534
|
*/
|
|
535
|
-
async function up$
|
|
535
|
+
async function up$54(db) {
|
|
536
536
|
await db.schema.createTable("_emdash_api_tokens").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("name", "text", (col) => col.notNull()).addColumn("token_hash", "text", (col) => col.notNull().unique()).addColumn("prefix", "text", (col) => col.notNull()).addColumn("user_id", "text", (col) => col.notNull()).addColumn("scopes", "text", (col) => col.notNull()).addColumn("expires_at", "text").addColumn("last_used_at", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addForeignKeyConstraint("api_tokens_user_fk", ["user_id"], "users", ["id"], (cb) => cb.onDelete("cascade")).execute();
|
|
537
537
|
await db.schema.createIndex("idx_api_tokens_token_hash").ifNotExists().on("_emdash_api_tokens").column("token_hash").execute();
|
|
538
538
|
await db.schema.createIndex("idx_api_tokens_user_id").ifNotExists().on("_emdash_api_tokens").column("user_id").execute();
|
|
@@ -541,7 +541,7 @@ async function up$38(db) {
|
|
|
541
541
|
await db.schema.createIndex("idx_oauth_tokens_expires").ifNotExists().on("_emdash_oauth_tokens").column("expires_at").execute();
|
|
542
542
|
await db.schema.createTable("_emdash_device_codes").ifNotExists().addColumn("device_code", "text", (col) => col.primaryKey()).addColumn("user_code", "text", (col) => col.notNull().unique()).addColumn("scopes", "text", (col) => col.notNull()).addColumn("user_id", "text").addColumn("status", "text", (col) => col.notNull().defaultTo("pending")).addColumn("expires_at", "text", (col) => col.notNull()).addColumn("interval", "integer", (col) => col.notNull().defaultTo(5)).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
543
543
|
}
|
|
544
|
-
async function down$
|
|
544
|
+
async function down$54(db) {
|
|
545
545
|
await db.schema.dropTable("_emdash_device_codes").ifExists().execute();
|
|
546
546
|
await db.schema.dropTable("_emdash_oauth_tokens").ifExists().execute();
|
|
547
547
|
await db.schema.dropTable("_emdash_api_tokens").ifExists().execute();
|
|
@@ -550,8 +550,8 @@ async function down$38(db) {
|
|
|
550
550
|
//#endregion
|
|
551
551
|
//#region src/database/migrations/017_authorization_codes.ts
|
|
552
552
|
var _017_authorization_codes_exports = /* @__PURE__ */ __exportAll({
|
|
553
|
-
down: () => down$
|
|
554
|
-
up: () => up$
|
|
553
|
+
down: () => down$53,
|
|
554
|
+
up: () => up$53
|
|
555
555
|
});
|
|
556
556
|
/**
|
|
557
557
|
* Authorization codes for OAuth 2.1 Authorization Code + PKCE flow.
|
|
@@ -561,20 +561,20 @@ var _017_authorization_codes_exports = /* @__PURE__ */ __exportAll({
|
|
|
561
561
|
*
|
|
562
562
|
* Also adds client_id tracking to oauth_tokens for per-client revocation.
|
|
563
563
|
*/
|
|
564
|
-
async function up$
|
|
564
|
+
async function up$53(db) {
|
|
565
565
|
await db.schema.createTable("_emdash_authorization_codes").addColumn("code_hash", "text", (col) => col.primaryKey()).addColumn("client_id", "text", (col) => col.notNull()).addColumn("redirect_uri", "text", (col) => col.notNull()).addColumn("user_id", "text", (col) => col.notNull()).addColumn("scopes", "text", (col) => col.notNull()).addColumn("code_challenge", "text", (col) => col.notNull()).addColumn("code_challenge_method", "text", (col) => col.notNull().defaultTo("S256")).addColumn("resource", "text").addColumn("expires_at", "text", (col) => col.notNull()).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addForeignKeyConstraint("auth_codes_user_fk", ["user_id"], "users", ["id"], (cb) => cb.onDelete("cascade")).execute();
|
|
566
566
|
await db.schema.createIndex("idx_auth_codes_expires").on("_emdash_authorization_codes").column("expires_at").execute();
|
|
567
567
|
await sql`ALTER TABLE _emdash_oauth_tokens ADD COLUMN client_id TEXT`.execute(db);
|
|
568
568
|
}
|
|
569
|
-
async function down$
|
|
569
|
+
async function down$53(db) {
|
|
570
570
|
await db.schema.dropTable("_emdash_authorization_codes").execute();
|
|
571
571
|
}
|
|
572
572
|
|
|
573
573
|
//#endregion
|
|
574
574
|
//#region src/database/migrations/018_seo.ts
|
|
575
575
|
var _018_seo_exports = /* @__PURE__ */ __exportAll({
|
|
576
|
-
down: () => down$
|
|
577
|
-
up: () => up$
|
|
576
|
+
down: () => down$52,
|
|
577
|
+
up: () => up$52
|
|
578
578
|
});
|
|
579
579
|
/**
|
|
580
580
|
* Migration: SEO support
|
|
@@ -587,7 +587,7 @@ var _018_seo_exports = /* @__PURE__ */ __exportAll({
|
|
|
587
587
|
* need it. The `has_seo` flag controls whether the admin shows SEO fields
|
|
588
588
|
* and whether the collection's content appears in sitemaps.
|
|
589
589
|
*/
|
|
590
|
-
async function up$
|
|
590
|
+
async function up$52(db) {
|
|
591
591
|
await db.schema.createTable("_emdash_seo").addColumn("collection", "text", (col) => col.notNull()).addColumn("content_id", "text", (col) => col.notNull()).addColumn("seo_title", "text").addColumn("seo_description", "text").addColumn("seo_image", "text").addColumn("seo_canonical", "text").addColumn("seo_no_index", "integer", (col) => col.notNull().defaultTo(0)).addColumn("created_at", "text", (col) => col.notNull().defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.notNull().defaultTo(currentTimestamp(db))).addPrimaryKeyConstraint("_emdash_seo_pk", ["collection", "content_id"]).execute();
|
|
592
592
|
await sql`
|
|
593
593
|
CREATE INDEX idx_emdash_seo_collection
|
|
@@ -598,7 +598,7 @@ async function up$36(db) {
|
|
|
598
598
|
ADD COLUMN has_seo INTEGER NOT NULL DEFAULT 0
|
|
599
599
|
`.execute(db);
|
|
600
600
|
}
|
|
601
|
-
async function down$
|
|
601
|
+
async function down$52(db) {
|
|
602
602
|
await sql`DROP TABLE IF EXISTS _emdash_seo`.execute(db);
|
|
603
603
|
await sql`
|
|
604
604
|
ALTER TABLE _emdash_collections
|
|
@@ -609,8 +609,8 @@ async function down$36(db) {
|
|
|
609
609
|
//#endregion
|
|
610
610
|
//#region src/database/migrations/019_i18n.ts
|
|
611
611
|
var _019_i18n_exports = /* @__PURE__ */ __exportAll({
|
|
612
|
-
down: () => down$
|
|
613
|
-
up: () => up$
|
|
612
|
+
down: () => down$51,
|
|
613
|
+
up: () => up$51
|
|
614
614
|
});
|
|
615
615
|
/**
|
|
616
616
|
* Quote an identifier for use in raw SQL. Escapes embedded double-quotes
|
|
@@ -723,7 +723,7 @@ async function upPostgres$1(db) {
|
|
|
723
723
|
ADD COLUMN translatable INTEGER NOT NULL DEFAULT 1
|
|
724
724
|
`.execute(db);
|
|
725
725
|
}
|
|
726
|
-
async function up$
|
|
726
|
+
async function up$51(db) {
|
|
727
727
|
if (!isSqlite(db)) return upPostgres$1(db);
|
|
728
728
|
const orphanedTmps = await listTablesLike(db, "ec_%_i18n_tmp");
|
|
729
729
|
for (const tmpName of orphanedTmps) {
|
|
@@ -840,7 +840,7 @@ async function downPostgres(db) {
|
|
|
840
840
|
await sql`ALTER TABLE ${sql.ref(t)} DROP COLUMN translation_group`.execute(db);
|
|
841
841
|
}
|
|
842
842
|
}
|
|
843
|
-
async function down$
|
|
843
|
+
async function down$51(db) {
|
|
844
844
|
if (!isSqlite(db)) return downPostgres(db);
|
|
845
845
|
await sql`
|
|
846
846
|
ALTER TABLE _emdash_fields
|
|
@@ -947,8 +947,8 @@ async function down$35(db) {
|
|
|
947
947
|
//#endregion
|
|
948
948
|
//#region src/database/migrations/020_collection_url_pattern.ts
|
|
949
949
|
var _020_collection_url_pattern_exports = /* @__PURE__ */ __exportAll({
|
|
950
|
-
down: () => down$
|
|
951
|
-
up: () => up$
|
|
950
|
+
down: () => down$50,
|
|
951
|
+
up: () => up$50
|
|
952
952
|
});
|
|
953
953
|
/**
|
|
954
954
|
* Migration: URL pattern for collections
|
|
@@ -957,13 +957,13 @@ var _020_collection_url_pattern_exports = /* @__PURE__ */ __exportAll({
|
|
|
957
957
|
* can declare its own URL structure (e.g. "/{slug}" for pages, "/blog/{slug}"
|
|
958
958
|
* for posts). Used for menu URL resolution, sitemaps, and path-based lookups.
|
|
959
959
|
*/
|
|
960
|
-
async function up$
|
|
960
|
+
async function up$50(db) {
|
|
961
961
|
await sql`
|
|
962
962
|
ALTER TABLE _emdash_collections
|
|
963
963
|
ADD COLUMN url_pattern TEXT
|
|
964
964
|
`.execute(db);
|
|
965
965
|
}
|
|
966
|
-
async function down$
|
|
966
|
+
async function down$50(db) {
|
|
967
967
|
await sql`
|
|
968
968
|
ALTER TABLE _emdash_collections
|
|
969
969
|
DROP COLUMN url_pattern
|
|
@@ -973,8 +973,8 @@ async function down$34(db) {
|
|
|
973
973
|
//#endregion
|
|
974
974
|
//#region src/database/migrations/021_remove_section_categories.ts
|
|
975
975
|
var _021_remove_section_categories_exports = /* @__PURE__ */ __exportAll({
|
|
976
|
-
down: () => down$
|
|
977
|
-
up: () => up$
|
|
976
|
+
down: () => down$49,
|
|
977
|
+
up: () => up$49
|
|
978
978
|
});
|
|
979
979
|
/**
|
|
980
980
|
* Migration: Remove section categories
|
|
@@ -983,12 +983,12 @@ var _021_remove_section_categories_exports = /* @__PURE__ */ __exportAll({
|
|
|
983
983
|
* Rather than building the missing UI for a feature with very little need at this stage,
|
|
984
984
|
* we're removing the feature entirely.
|
|
985
985
|
*/
|
|
986
|
-
async function up$
|
|
986
|
+
async function up$49(db) {
|
|
987
987
|
await db.schema.dropIndex("idx_sections_category").ifExists().execute();
|
|
988
988
|
await db.schema.alterTable("_emdash_sections").dropColumn("category_id").execute();
|
|
989
989
|
await db.schema.dropTable("_emdash_section_categories").execute();
|
|
990
990
|
}
|
|
991
|
-
async function down$
|
|
991
|
+
async function down$49(db) {
|
|
992
992
|
await db.schema.createTable("_emdash_section_categories").addColumn("id", "text", (col) => col.primaryKey()).addColumn("slug", "text", (col) => col.notNull().unique()).addColumn("label", "text", (col) => col.notNull()).addColumn("sort_order", "integer", (col) => col.defaultTo(0)).addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
|
|
993
993
|
await db.schema.alterTable("_emdash_sections").addColumn("category_id", "text", (col) => col.references("_emdash_section_categories.id").onDelete("set null")).execute();
|
|
994
994
|
await db.schema.createIndex("idx_sections_category").on("_emdash_sections").columns(["category_id"]).execute();
|
|
@@ -997,8 +997,8 @@ async function down$33(db) {
|
|
|
997
997
|
//#endregion
|
|
998
998
|
//#region src/database/migrations/022_marketplace_plugin_state.ts
|
|
999
999
|
var _022_marketplace_plugin_state_exports = /* @__PURE__ */ __exportAll({
|
|
1000
|
-
down: () => down$
|
|
1001
|
-
up: () => up$
|
|
1000
|
+
down: () => down$48,
|
|
1001
|
+
up: () => up$48
|
|
1002
1002
|
});
|
|
1003
1003
|
/**
|
|
1004
1004
|
* Migration: Add marketplace fields to _plugin_state
|
|
@@ -1007,7 +1007,7 @@ var _022_marketplace_plugin_state_exports = /* @__PURE__ */ __exportAll({
|
|
|
1007
1007
|
* whether a plugin was installed from config or marketplace,
|
|
1008
1008
|
* and which marketplace version is installed.
|
|
1009
1009
|
*/
|
|
1010
|
-
async function up$
|
|
1010
|
+
async function up$48(db) {
|
|
1011
1011
|
await sql`
|
|
1012
1012
|
ALTER TABLE _plugin_state
|
|
1013
1013
|
ADD COLUMN source TEXT NOT NULL DEFAULT 'config'
|
|
@@ -1022,7 +1022,7 @@ async function up$32(db) {
|
|
|
1022
1022
|
WHERE source = 'marketplace'
|
|
1023
1023
|
`.execute(db);
|
|
1024
1024
|
}
|
|
1025
|
-
async function down$
|
|
1025
|
+
async function down$48(db) {
|
|
1026
1026
|
await sql`
|
|
1027
1027
|
DROP INDEX IF EXISTS idx_plugin_state_source
|
|
1028
1028
|
`.execute(db);
|
|
@@ -1039,8 +1039,8 @@ async function down$32(db) {
|
|
|
1039
1039
|
//#endregion
|
|
1040
1040
|
//#region src/database/migrations/023_plugin_metadata.ts
|
|
1041
1041
|
var _023_plugin_metadata_exports = /* @__PURE__ */ __exportAll({
|
|
1042
|
-
down: () => down$
|
|
1043
|
-
up: () => up$
|
|
1042
|
+
down: () => down$47,
|
|
1043
|
+
up: () => up$47
|
|
1044
1044
|
});
|
|
1045
1045
|
/**
|
|
1046
1046
|
* Migration: Add display metadata to _plugin_state
|
|
@@ -1049,7 +1049,7 @@ var _023_plugin_metadata_exports = /* @__PURE__ */ __exportAll({
|
|
|
1049
1049
|
* so the admin UI can show meaningful info without re-fetching
|
|
1050
1050
|
* from the marketplace on every page load.
|
|
1051
1051
|
*/
|
|
1052
|
-
async function up$
|
|
1052
|
+
async function up$47(db) {
|
|
1053
1053
|
await sql`
|
|
1054
1054
|
ALTER TABLE _plugin_state
|
|
1055
1055
|
ADD COLUMN display_name TEXT
|
|
@@ -1059,7 +1059,7 @@ async function up$31(db) {
|
|
|
1059
1059
|
ADD COLUMN description TEXT
|
|
1060
1060
|
`.execute(db);
|
|
1061
1061
|
}
|
|
1062
|
-
async function down$
|
|
1062
|
+
async function down$47(db) {
|
|
1063
1063
|
await sql`
|
|
1064
1064
|
ALTER TABLE _plugin_state
|
|
1065
1065
|
DROP COLUMN description
|
|
@@ -1073,8 +1073,8 @@ async function down$31(db) {
|
|
|
1073
1073
|
//#endregion
|
|
1074
1074
|
//#region src/database/migrations/024_media_placeholders.ts
|
|
1075
1075
|
var _024_media_placeholders_exports = /* @__PURE__ */ __exportAll({
|
|
1076
|
-
down: () => down$
|
|
1077
|
-
up: () => up$
|
|
1076
|
+
down: () => down$46,
|
|
1077
|
+
up: () => up$46
|
|
1078
1078
|
});
|
|
1079
1079
|
/**
|
|
1080
1080
|
* Migration: Add placeholder columns to media table
|
|
@@ -1082,7 +1082,7 @@ var _024_media_placeholders_exports = /* @__PURE__ */ __exportAll({
|
|
|
1082
1082
|
* Stores blurhash and dominant_color for LQIP (Low Quality Image Placeholder)
|
|
1083
1083
|
* support. Generated at upload time from image pixel data.
|
|
1084
1084
|
*/
|
|
1085
|
-
async function up$
|
|
1085
|
+
async function up$46(db) {
|
|
1086
1086
|
await sql`
|
|
1087
1087
|
ALTER TABLE media
|
|
1088
1088
|
ADD COLUMN blurhash TEXT
|
|
@@ -1092,7 +1092,7 @@ async function up$30(db) {
|
|
|
1092
1092
|
ADD COLUMN dominant_color TEXT
|
|
1093
1093
|
`.execute(db);
|
|
1094
1094
|
}
|
|
1095
|
-
async function down$
|
|
1095
|
+
async function down$46(db) {
|
|
1096
1096
|
await sql`
|
|
1097
1097
|
ALTER TABLE media
|
|
1098
1098
|
DROP COLUMN dominant_color
|
|
@@ -1106,8 +1106,8 @@ async function down$30(db) {
|
|
|
1106
1106
|
//#endregion
|
|
1107
1107
|
//#region src/database/migrations/025_oauth_clients.ts
|
|
1108
1108
|
var _025_oauth_clients_exports = /* @__PURE__ */ __exportAll({
|
|
1109
|
-
down: () => down$
|
|
1110
|
-
up: () => up$
|
|
1109
|
+
down: () => down$45,
|
|
1110
|
+
up: () => up$45
|
|
1111
1111
|
});
|
|
1112
1112
|
/**
|
|
1113
1113
|
* Migration: Create OAuth clients table
|
|
@@ -1118,18 +1118,18 @@ var _025_oauth_clients_exports = /* @__PURE__ */ __exportAll({
|
|
|
1118
1118
|
* Each client has a set of pre-registered redirect URIs (JSON array).
|
|
1119
1119
|
* The authorize endpoint rejects any redirect_uri not in the client's list.
|
|
1120
1120
|
*/
|
|
1121
|
-
async function up$
|
|
1121
|
+
async function up$45(db) {
|
|
1122
1122
|
await db.schema.createTable("_emdash_oauth_clients").addColumn("id", "text", (col) => col.primaryKey()).addColumn("name", "text", (col) => col.notNull()).addColumn("redirect_uris", "text", (col) => col.notNull()).addColumn("scopes", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
1123
1123
|
}
|
|
1124
|
-
async function down$
|
|
1124
|
+
async function down$45(db) {
|
|
1125
1125
|
await db.schema.dropTable("_emdash_oauth_clients").execute();
|
|
1126
1126
|
}
|
|
1127
1127
|
|
|
1128
1128
|
//#endregion
|
|
1129
1129
|
//#region src/database/migrations/026_cron_tasks.ts
|
|
1130
1130
|
var _026_cron_tasks_exports = /* @__PURE__ */ __exportAll({
|
|
1131
|
-
down: () => down$
|
|
1132
|
-
up: () => up$
|
|
1131
|
+
down: () => down$44,
|
|
1132
|
+
up: () => up$44
|
|
1133
1133
|
});
|
|
1134
1134
|
/**
|
|
1135
1135
|
* Migration: Create cron tasks table for plugin scheduled tasks.
|
|
@@ -1140,7 +1140,7 @@ var _026_cron_tasks_exports = /* @__PURE__ */ __exportAll({
|
|
|
1140
1140
|
* The `next_run_at` + `status` + `enabled` index drives the "find overdue
|
|
1141
1141
|
* tasks" query used by CronExecutor.tick().
|
|
1142
1142
|
*/
|
|
1143
|
-
async function up$
|
|
1143
|
+
async function up$44(db) {
|
|
1144
1144
|
await db.schema.createTable("_emdash_cron_tasks").addColumn("id", "text", (col) => col.primaryKey()).addColumn("plugin_id", "text", (col) => col.notNull()).addColumn("task_name", "text", (col) => col.notNull()).addColumn("schedule", "text", (col) => col.notNull()).addColumn("is_oneshot", "integer", (col) => col.notNull().defaultTo(0)).addColumn("data", "text").addColumn("next_run_at", "text", (col) => col.notNull()).addColumn("last_run_at", "text").addColumn("status", "text", (col) => col.notNull().defaultTo("idle")).addColumn("locked_at", "text").addColumn("enabled", "integer", (col) => col.notNull().defaultTo(1)).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addUniqueConstraint("uq_cron_tasks_plugin_task", ["plugin_id", "task_name"]).execute();
|
|
1145
1145
|
await db.schema.createIndex("idx_cron_tasks_due").on("_emdash_cron_tasks").columns([
|
|
1146
1146
|
"enabled",
|
|
@@ -1149,17 +1149,17 @@ async function up$28(db) {
|
|
|
1149
1149
|
]).execute();
|
|
1150
1150
|
await db.schema.createIndex("idx_cron_tasks_plugin").on("_emdash_cron_tasks").column("plugin_id").execute();
|
|
1151
1151
|
}
|
|
1152
|
-
async function down$
|
|
1152
|
+
async function down$44(db) {
|
|
1153
1153
|
await db.schema.dropTable("_emdash_cron_tasks").execute();
|
|
1154
1154
|
}
|
|
1155
1155
|
|
|
1156
1156
|
//#endregion
|
|
1157
1157
|
//#region src/database/migrations/027_comments.ts
|
|
1158
1158
|
var _027_comments_exports = /* @__PURE__ */ __exportAll({
|
|
1159
|
-
down: () => down$
|
|
1160
|
-
up: () => up$
|
|
1159
|
+
down: () => down$43,
|
|
1160
|
+
up: () => up$43
|
|
1161
1161
|
});
|
|
1162
|
-
async function up$
|
|
1162
|
+
async function up$43(db) {
|
|
1163
1163
|
await db.schema.createTable("_emdash_comments").addColumn("id", "text", (col) => col.primaryKey()).addColumn("collection", "text", (col) => col.notNull()).addColumn("content_id", "text", (col) => col.notNull()).addColumn("parent_id", "text", (col) => col.references("_emdash_comments.id").onDelete("cascade")).addColumn("author_name", "text", (col) => col.notNull()).addColumn("author_email", "text", (col) => col.notNull()).addColumn("author_url", "text").addColumn("author_user_id", "text", (col) => col.references("users.id").onDelete("set null")).addColumn("body", "text", (col) => col.notNull()).addColumn("status", "text", (col) => col.notNull().defaultTo("pending")).addColumn("ip_hash", "text").addColumn("user_agent", "text").addColumn("moderation_metadata", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
1164
1164
|
await db.schema.createIndex("idx_comments_content").on("_emdash_comments").columns([
|
|
1165
1165
|
"collection",
|
|
@@ -1175,30 +1175,30 @@ async function up$27(db) {
|
|
|
1175
1175
|
await db.schema.alterTable("_emdash_collections").addColumn("comments_closed_after_days", "integer", (col) => col.defaultTo(90)).execute();
|
|
1176
1176
|
await db.schema.alterTable("_emdash_collections").addColumn("comments_auto_approve_users", "integer", (col) => col.defaultTo(1)).execute();
|
|
1177
1177
|
}
|
|
1178
|
-
async function down$
|
|
1178
|
+
async function down$43(db) {
|
|
1179
1179
|
await db.schema.dropTable("_emdash_comments").execute();
|
|
1180
1180
|
}
|
|
1181
1181
|
|
|
1182
1182
|
//#endregion
|
|
1183
1183
|
//#region src/database/migrations/028_drop_author_url.ts
|
|
1184
1184
|
var _028_drop_author_url_exports = /* @__PURE__ */ __exportAll({
|
|
1185
|
-
down: () => down$
|
|
1186
|
-
up: () => up$
|
|
1185
|
+
down: () => down$42,
|
|
1186
|
+
up: () => up$42
|
|
1187
1187
|
});
|
|
1188
|
-
async function up$
|
|
1188
|
+
async function up$42(db) {
|
|
1189
1189
|
await sql`ALTER TABLE _emdash_comments DROP COLUMN author_url`.execute(db);
|
|
1190
1190
|
}
|
|
1191
|
-
async function down$
|
|
1191
|
+
async function down$42(db) {
|
|
1192
1192
|
await db.schema.alterTable("_emdash_comments").addColumn("author_url", "text").execute();
|
|
1193
1193
|
}
|
|
1194
1194
|
|
|
1195
1195
|
//#endregion
|
|
1196
1196
|
//#region src/database/migrations/029_redirects.ts
|
|
1197
1197
|
var _029_redirects_exports = /* @__PURE__ */ __exportAll({
|
|
1198
|
-
down: () => down$
|
|
1199
|
-
up: () => up$
|
|
1198
|
+
down: () => down$41,
|
|
1199
|
+
up: () => up$41
|
|
1200
1200
|
});
|
|
1201
|
-
async function up$
|
|
1201
|
+
async function up$41(db) {
|
|
1202
1202
|
await db.schema.createTable("_emdash_redirects").addColumn("id", "text", (col) => col.primaryKey()).addColumn("source", "text", (col) => col.notNull()).addColumn("destination", "text", (col) => col.notNull()).addColumn("type", "integer", (col) => col.notNull().defaultTo(301)).addColumn("is_pattern", "integer", (col) => col.notNull().defaultTo(0)).addColumn("enabled", "integer", (col) => col.notNull().defaultTo(1)).addColumn("hits", "integer", (col) => col.notNull().defaultTo(0)).addColumn("last_hit_at", "text").addColumn("group_name", "text").addColumn("auto", "integer", (col) => col.notNull().defaultTo(0)).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
1203
1203
|
await db.schema.createIndex("idx_redirects_source").on("_emdash_redirects").column("source").execute();
|
|
1204
1204
|
await db.schema.createIndex("idx_redirects_enabled").on("_emdash_redirects").column("enabled").execute();
|
|
@@ -1207,7 +1207,7 @@ async function up$25(db) {
|
|
|
1207
1207
|
await db.schema.createIndex("idx_404_log_path").on("_emdash_404_log").column("path").execute();
|
|
1208
1208
|
await db.schema.createIndex("idx_404_log_created").on("_emdash_404_log").column("created_at").execute();
|
|
1209
1209
|
}
|
|
1210
|
-
async function down$
|
|
1210
|
+
async function down$41(db) {
|
|
1211
1211
|
await db.schema.dropTable("_emdash_404_log").execute();
|
|
1212
1212
|
await db.schema.dropTable("_emdash_redirects").execute();
|
|
1213
1213
|
}
|
|
@@ -1215,8 +1215,8 @@ async function down$25(db) {
|
|
|
1215
1215
|
//#endregion
|
|
1216
1216
|
//#region src/database/migrations/030_widen_scheduled_index.ts
|
|
1217
1217
|
var _030_widen_scheduled_index_exports = /* @__PURE__ */ __exportAll({
|
|
1218
|
-
down: () => down$
|
|
1219
|
-
up: () => up$
|
|
1218
|
+
down: () => down$40,
|
|
1219
|
+
up: () => up$40
|
|
1220
1220
|
});
|
|
1221
1221
|
/**
|
|
1222
1222
|
* Migration: Widen scheduled publishing index
|
|
@@ -1225,7 +1225,7 @@ var _030_widen_scheduled_index_exports = /* @__PURE__ */ __exportAll({
|
|
|
1225
1225
|
* Published posts can now have scheduled draft changes, so widen the
|
|
1226
1226
|
* index to cover all rows where scheduled_at IS NOT NULL.
|
|
1227
1227
|
*/
|
|
1228
|
-
async function up$
|
|
1228
|
+
async function up$40(db) {
|
|
1229
1229
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
1230
1230
|
for (const tableName of tableNames) {
|
|
1231
1231
|
const table = { name: tableName };
|
|
@@ -1239,7 +1239,7 @@ async function up$24(db) {
|
|
|
1239
1239
|
`.execute(db);
|
|
1240
1240
|
}
|
|
1241
1241
|
}
|
|
1242
|
-
async function down$
|
|
1242
|
+
async function down$40(db) {
|
|
1243
1243
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
1244
1244
|
for (const tableName of tableNames) {
|
|
1245
1245
|
const table = { name: tableName };
|
|
@@ -1257,10 +1257,10 @@ async function down$24(db) {
|
|
|
1257
1257
|
//#endregion
|
|
1258
1258
|
//#region src/database/migrations/031_bylines.ts
|
|
1259
1259
|
var _031_bylines_exports = /* @__PURE__ */ __exportAll({
|
|
1260
|
-
down: () => down$
|
|
1261
|
-
up: () => up$
|
|
1260
|
+
down: () => down$39,
|
|
1261
|
+
up: () => up$39
|
|
1262
1262
|
});
|
|
1263
|
-
async function up$
|
|
1263
|
+
async function up$39(db) {
|
|
1264
1264
|
await db.schema.createTable("_emdash_bylines").addColumn("id", "text", (col) => col.primaryKey()).addColumn("slug", "text", (col) => col.notNull().unique()).addColumn("display_name", "text", (col) => col.notNull()).addColumn("bio", "text").addColumn("avatar_media_id", "text", (col) => col.references("media.id").onDelete("set null")).addColumn("website_url", "text").addColumn("user_id", "text", (col) => col.references("users.id").onDelete("set null")).addColumn("is_guest", "integer", (col) => col.notNull().defaultTo(0)).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
1265
1265
|
await sql`
|
|
1266
1266
|
CREATE UNIQUE INDEX ${sql.ref("idx_bylines_user_id_unique")}
|
|
@@ -1292,7 +1292,7 @@ async function up$23(db) {
|
|
|
1292
1292
|
`.execute(db);
|
|
1293
1293
|
}
|
|
1294
1294
|
}
|
|
1295
|
-
async function down$
|
|
1295
|
+
async function down$39(db) {
|
|
1296
1296
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
1297
1297
|
for (const tableName of tableNames) {
|
|
1298
1298
|
await sql`
|
|
@@ -1310,8 +1310,8 @@ async function down$23(db) {
|
|
|
1310
1310
|
//#endregion
|
|
1311
1311
|
//#region src/database/migrations/032_rate_limits.ts
|
|
1312
1312
|
var _032_rate_limits_exports = /* @__PURE__ */ __exportAll({
|
|
1313
|
-
down: () => down$
|
|
1314
|
-
up: () => up$
|
|
1313
|
+
down: () => down$38,
|
|
1314
|
+
up: () => up$38
|
|
1315
1315
|
});
|
|
1316
1316
|
/**
|
|
1317
1317
|
* Migration: Rate limits table + device code polling tracking.
|
|
@@ -1322,12 +1322,12 @@ var _032_rate_limits_exports = /* @__PURE__ */ __exportAll({
|
|
|
1322
1322
|
* 2. Add last_polled_at column to _emdash_device_codes for
|
|
1323
1323
|
* RFC 8628 slow_down enforcement.
|
|
1324
1324
|
*/
|
|
1325
|
-
async function up$
|
|
1325
|
+
async function up$38(db) {
|
|
1326
1326
|
await db.schema.createTable("_emdash_rate_limits").addColumn("key", "text", (col) => col.notNull()).addColumn("window", "text", (col) => col.notNull()).addColumn("count", "integer", (col) => col.notNull().defaultTo(1)).addPrimaryKeyConstraint("pk_rate_limits", ["key", "window"]).execute();
|
|
1327
1327
|
await db.schema.createIndex("idx_rate_limits_window").on("_emdash_rate_limits").column("window").execute();
|
|
1328
1328
|
await db.schema.alterTable("_emdash_device_codes").addColumn("last_polled_at", "text").execute();
|
|
1329
1329
|
}
|
|
1330
|
-
async function down$
|
|
1330
|
+
async function down$38(db) {
|
|
1331
1331
|
await db.schema.dropTable("_emdash_rate_limits").execute();
|
|
1332
1332
|
await db.schema.alterTable("_emdash_device_codes").dropColumn("last_polled_at").execute();
|
|
1333
1333
|
}
|
|
@@ -1335,8 +1335,8 @@ async function down$22(db) {
|
|
|
1335
1335
|
//#endregion
|
|
1336
1336
|
//#region src/database/migrations/033_optimize_content_indexes.ts
|
|
1337
1337
|
var _033_optimize_content_indexes_exports = /* @__PURE__ */ __exportAll({
|
|
1338
|
-
down: () => down$
|
|
1339
|
-
up: () => up$
|
|
1338
|
+
down: () => down$37,
|
|
1339
|
+
up: () => up$37
|
|
1340
1340
|
});
|
|
1341
1341
|
/**
|
|
1342
1342
|
* Migration: Optimize content table indexes for D1 performance
|
|
@@ -1349,7 +1349,7 @@ var _033_optimize_content_indexes_exports = /* @__PURE__ */ __exportAll({
|
|
|
1349
1349
|
*
|
|
1350
1350
|
* Impact: Reduces D1 row reads by 90%+ for admin panel operations.
|
|
1351
1351
|
*/
|
|
1352
|
-
async function up$
|
|
1352
|
+
async function up$37(db) {
|
|
1353
1353
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
1354
1354
|
for (const tableName of tableNames) {
|
|
1355
1355
|
const table = { name: tableName };
|
|
@@ -1391,7 +1391,7 @@ async function up$21(db) {
|
|
|
1391
1391
|
WHERE status = 'trash'
|
|
1392
1392
|
`.execute(db);
|
|
1393
1393
|
}
|
|
1394
|
-
async function down$
|
|
1394
|
+
async function down$37(db) {
|
|
1395
1395
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
1396
1396
|
for (const tableName of tableNames) {
|
|
1397
1397
|
const table = { name: tableName };
|
|
@@ -1424,10 +1424,10 @@ async function down$21(db) {
|
|
|
1424
1424
|
//#endregion
|
|
1425
1425
|
//#region src/database/migrations/034_published_at_index.ts
|
|
1426
1426
|
var _034_published_at_index_exports = /* @__PURE__ */ __exportAll({
|
|
1427
|
-
down: () => down$
|
|
1428
|
-
up: () => up$
|
|
1427
|
+
down: () => down$36,
|
|
1428
|
+
up: () => up$36
|
|
1429
1429
|
});
|
|
1430
|
-
async function up$
|
|
1430
|
+
async function up$36(db) {
|
|
1431
1431
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
1432
1432
|
for (const tableName of tableNames) {
|
|
1433
1433
|
const table = { name: tableName };
|
|
@@ -1437,7 +1437,7 @@ async function up$20(db) {
|
|
|
1437
1437
|
`.execute(db);
|
|
1438
1438
|
}
|
|
1439
1439
|
}
|
|
1440
|
-
async function down$
|
|
1440
|
+
async function down$36(db) {
|
|
1441
1441
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
1442
1442
|
for (const tableName of tableNames) {
|
|
1443
1443
|
const table = { name: tableName };
|
|
@@ -1448,8 +1448,8 @@ async function down$20(db) {
|
|
|
1448
1448
|
//#endregion
|
|
1449
1449
|
//#region src/database/migrations/035_bounded_404_log.ts
|
|
1450
1450
|
var _035_bounded_404_log_exports = /* @__PURE__ */ __exportAll({
|
|
1451
|
-
down: () => down$
|
|
1452
|
-
up: () => up$
|
|
1451
|
+
down: () => down$35,
|
|
1452
|
+
up: () => up$35
|
|
1453
1453
|
});
|
|
1454
1454
|
/**
|
|
1455
1455
|
* Migration: Bounded 404 logging
|
|
@@ -1467,7 +1467,7 @@ var _035_bounded_404_log_exports = /* @__PURE__ */ __exportAll({
|
|
|
1467
1467
|
* path and summing hits
|
|
1468
1468
|
* - Adds a UNIQUE index on `path` so upsert semantics work
|
|
1469
1469
|
*/
|
|
1470
|
-
async function up$
|
|
1470
|
+
async function up$35(db) {
|
|
1471
1471
|
const hitsExists = await columnExists(db, "_emdash_404_log", "hits");
|
|
1472
1472
|
if (!hitsExists) await db.schema.alterTable("_emdash_404_log").addColumn("hits", "integer", (col) => col.notNull().defaultTo(1)).execute();
|
|
1473
1473
|
if (!await columnExists(db, "_emdash_404_log", "last_seen_at")) await db.schema.alterTable("_emdash_404_log").addColumn("last_seen_at", "text").execute();
|
|
@@ -1516,7 +1516,7 @@ async function up$19(db) {
|
|
|
1516
1516
|
await db.schema.dropIndex("idx_404_log_path").ifExists().execute();
|
|
1517
1517
|
await db.schema.createIndex("idx_404_log_last_seen").ifNotExists().on("_emdash_404_log").column("last_seen_at").execute();
|
|
1518
1518
|
}
|
|
1519
|
-
async function down$
|
|
1519
|
+
async function down$35(db) {
|
|
1520
1520
|
await db.schema.dropIndex("idx_404_log_last_seen").ifExists().execute();
|
|
1521
1521
|
await db.schema.dropIndex("idx_404_log_path_unique").ifExists().execute();
|
|
1522
1522
|
await db.schema.createIndex("idx_404_log_path").ifNotExists().on("_emdash_404_log").column("path").execute();
|
|
@@ -1527,8 +1527,8 @@ async function down$19(db) {
|
|
|
1527
1527
|
//#endregion
|
|
1528
1528
|
//#region src/database/migrations/036_i18n_menus_and_taxonomies.ts
|
|
1529
1529
|
var _036_i18n_menus_and_taxonomies_exports = /* @__PURE__ */ __exportAll({
|
|
1530
|
-
down: () => down$
|
|
1531
|
-
up: () => up$
|
|
1530
|
+
down: () => down$34,
|
|
1531
|
+
up: () => up$34
|
|
1532
1532
|
});
|
|
1533
1533
|
/**
|
|
1534
1534
|
* i18n for menus + taxonomies. Adds `locale` + `translation_group` to system
|
|
@@ -1539,7 +1539,7 @@ var _036_i18n_menus_and_taxonomies_exports = /* @__PURE__ */ __exportAll({
|
|
|
1539
1539
|
function getDefaultLocale$1() {
|
|
1540
1540
|
return getI18nConfig()?.defaultLocale ?? "en";
|
|
1541
1541
|
}
|
|
1542
|
-
async function up$
|
|
1542
|
+
async function up$34(db) {
|
|
1543
1543
|
const defaultLocale = getDefaultLocale$1();
|
|
1544
1544
|
if (isSqlite(db)) {
|
|
1545
1545
|
await rebuildContentTaxonomies(db);
|
|
@@ -1754,7 +1754,7 @@ async function assertSingleLocale$1(db, defaultLocale) {
|
|
|
1754
1754
|
if (count > 0) throw new Error(`Cannot revert migration 036_i18n_menus_and_taxonomies: ${count} row(s) in "${table}" use a non-default locale (defaultLocale="${defaultLocale}"). Reverting would drop them silently. Export translations first (or delete them) and re-run the rollback. See packages/core/src/database/migrations/036_i18n_menus_and_taxonomies.ts.`);
|
|
1755
1755
|
}
|
|
1756
1756
|
}
|
|
1757
|
-
async function down$
|
|
1757
|
+
async function down$34(db) {
|
|
1758
1758
|
const defaultLocale = getDefaultLocale$1();
|
|
1759
1759
|
await assertSingleLocale$1(db, defaultLocale);
|
|
1760
1760
|
await assertContentTaxonomiesResolve(db, defaultLocale);
|
|
@@ -1852,21 +1852,21 @@ async function rebuildTaxonomyDefsDown(db) {
|
|
|
1852
1852
|
//#endregion
|
|
1853
1853
|
//#region src/database/migrations/037_credential_algorithm.ts
|
|
1854
1854
|
var _037_credential_algorithm_exports = /* @__PURE__ */ __exportAll({
|
|
1855
|
-
down: () => down$
|
|
1856
|
-
up: () => up$
|
|
1855
|
+
down: () => down$33,
|
|
1856
|
+
up: () => up$33
|
|
1857
1857
|
});
|
|
1858
|
-
async function up$
|
|
1858
|
+
async function up$33(db) {
|
|
1859
1859
|
if (!await columnExists(db, "credentials", "algorithm")) await db.schema.alterTable("credentials").addColumn("algorithm", "integer", (col) => col.notNull().defaultTo(-7)).execute();
|
|
1860
1860
|
}
|
|
1861
|
-
async function down$
|
|
1861
|
+
async function down$33(db) {
|
|
1862
1862
|
if (await columnExists(db, "credentials", "algorithm")) await db.schema.alterTable("credentials").dropColumn("algorithm").execute();
|
|
1863
1863
|
}
|
|
1864
1864
|
|
|
1865
1865
|
//#endregion
|
|
1866
1866
|
//#region src/database/migrations/038_registry_plugin_state.ts
|
|
1867
1867
|
var _038_registry_plugin_state_exports = /* @__PURE__ */ __exportAll({
|
|
1868
|
-
down: () => down$
|
|
1869
|
-
up: () => up$
|
|
1868
|
+
down: () => down$32,
|
|
1869
|
+
up: () => up$32
|
|
1870
1870
|
});
|
|
1871
1871
|
/**
|
|
1872
1872
|
* Migration: Add registry fields to _plugin_state
|
|
@@ -1894,7 +1894,7 @@ var _038_registry_plugin_state_exports = /* @__PURE__ */ __exportAll({
|
|
|
1894
1894
|
* checks before adding to keep the migration safe under partial
|
|
1895
1895
|
* re-application. The same pattern is used in 019_i18n.ts.
|
|
1896
1896
|
*/
|
|
1897
|
-
async function up$
|
|
1897
|
+
async function up$32(db) {
|
|
1898
1898
|
if (isSqlite(db)) await upSqlite(db);
|
|
1899
1899
|
else await upPostgres(db);
|
|
1900
1900
|
}
|
|
@@ -1937,7 +1937,7 @@ async function upPostgres(db) {
|
|
|
1937
1937
|
WHERE source = 'registry'
|
|
1938
1938
|
`.execute(db);
|
|
1939
1939
|
}
|
|
1940
|
-
async function down$
|
|
1940
|
+
async function down$32(db) {
|
|
1941
1941
|
await sql`
|
|
1942
1942
|
DROP INDEX IF EXISTS idx_plugin_state_registry
|
|
1943
1943
|
`.execute(db);
|
|
@@ -1954,24 +1954,24 @@ async function down$16(db) {
|
|
|
1954
1954
|
//#endregion
|
|
1955
1955
|
//#region src/database/migrations/039_fix_fts5_triggers.ts
|
|
1956
1956
|
var _039_fix_fts5_triggers_exports = /* @__PURE__ */ __exportAll({
|
|
1957
|
-
down: () => down$
|
|
1958
|
-
up: () => up$
|
|
1957
|
+
down: () => down$31,
|
|
1958
|
+
up: () => up$31
|
|
1959
1959
|
});
|
|
1960
|
-
async function up$
|
|
1960
|
+
async function up$31(db) {
|
|
1961
1961
|
if (!isSqlite(db)) return;
|
|
1962
1962
|
const collections = await sql`
|
|
1963
1963
|
SELECT slug, search_config FROM _emdash_collections
|
|
1964
1964
|
WHERE search_config IS NOT NULL
|
|
1965
1965
|
`.execute(db);
|
|
1966
1966
|
for (const collection of collections.rows) {
|
|
1967
|
-
if (!isSearchEnabled(collection.search_config)) continue;
|
|
1967
|
+
if (!isSearchEnabled$1(collection.search_config)) continue;
|
|
1968
1968
|
try {
|
|
1969
1969
|
validateIdentifier(collection.slug, "collection slug");
|
|
1970
1970
|
} catch (error) {
|
|
1971
1971
|
console.warn(`[migration 039] skipping FTS rebuild for collection "${collection.slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
1972
1972
|
continue;
|
|
1973
1973
|
}
|
|
1974
|
-
const fields = await getSearchableFields(db, collection.slug);
|
|
1974
|
+
const fields = await getSearchableFields$1(db, collection.slug);
|
|
1975
1975
|
if (fields.length === 0) {
|
|
1976
1976
|
await dropFtsObjects(db, collection.slug);
|
|
1977
1977
|
await sql`
|
|
@@ -1981,7 +1981,7 @@ async function up$15(db) {
|
|
|
1981
1981
|
`.execute(db);
|
|
1982
1982
|
continue;
|
|
1983
1983
|
}
|
|
1984
|
-
await rebuildIndex(db, collection.slug, fields);
|
|
1984
|
+
await rebuildIndex$1(db, collection.slug, fields);
|
|
1985
1985
|
}
|
|
1986
1986
|
}
|
|
1987
1987
|
/**
|
|
@@ -1991,8 +1991,8 @@ async function up$15(db) {
|
|
|
1991
1991
|
* at runtime, not by this migration, so leaving them in their
|
|
1992
1992
|
* corruption-safe state on rollback is correct.
|
|
1993
1993
|
*/
|
|
1994
|
-
async function down$
|
|
1995
|
-
function isSearchEnabled(searchConfig) {
|
|
1994
|
+
async function down$31(_db) {}
|
|
1995
|
+
function isSearchEnabled$1(searchConfig) {
|
|
1996
1996
|
if (!searchConfig) return false;
|
|
1997
1997
|
try {
|
|
1998
1998
|
const parsed = JSON.parse(searchConfig);
|
|
@@ -2001,7 +2001,7 @@ function isSearchEnabled(searchConfig) {
|
|
|
2001
2001
|
return false;
|
|
2002
2002
|
}
|
|
2003
2003
|
}
|
|
2004
|
-
async function getSearchableFields(db, collectionSlug) {
|
|
2004
|
+
async function getSearchableFields$1(db, collectionSlug) {
|
|
2005
2005
|
const rows = await sql`
|
|
2006
2006
|
SELECT f.slug FROM _emdash_fields f
|
|
2007
2007
|
INNER JOIN _emdash_collections c ON c.id = f.collection_id
|
|
@@ -2016,7 +2016,7 @@ async function getSearchableFields(db, collectionSlug) {
|
|
|
2016
2016
|
}
|
|
2017
2017
|
return out;
|
|
2018
2018
|
}
|
|
2019
|
-
async function rebuildIndex(db, collectionSlug, fields) {
|
|
2019
|
+
async function rebuildIndex$1(db, collectionSlug, fields) {
|
|
2020
2020
|
const ftsTable = `_emdash_fts_${collectionSlug}`;
|
|
2021
2021
|
const contentTable = `ec_${collectionSlug}`;
|
|
2022
2022
|
const columnList = [
|
|
@@ -2083,8 +2083,8 @@ async function dropFtsObjects(db, collectionSlug) {
|
|
|
2083
2083
|
//#endregion
|
|
2084
2084
|
//#region src/database/migrations/040_byline_i18n.ts
|
|
2085
2085
|
var _040_byline_i18n_exports = /* @__PURE__ */ __exportAll({
|
|
2086
|
-
down: () => down$
|
|
2087
|
-
up: () => up$
|
|
2086
|
+
down: () => down$30,
|
|
2087
|
+
up: () => up$30
|
|
2088
2088
|
});
|
|
2089
2089
|
/**
|
|
2090
2090
|
* i18n for bylines. Adds `locale` + `translation_group` to `_emdash_bylines`
|
|
@@ -2112,7 +2112,7 @@ var _040_byline_i18n_exports = /* @__PURE__ */ __exportAll({
|
|
|
2112
2112
|
function getDefaultLocale() {
|
|
2113
2113
|
return getI18nConfig()?.defaultLocale ?? "en";
|
|
2114
2114
|
}
|
|
2115
|
-
async function up$
|
|
2115
|
+
async function up$30(db) {
|
|
2116
2116
|
const defaultLocale = getDefaultLocale();
|
|
2117
2117
|
if (isSqlite(db)) {
|
|
2118
2118
|
await rebuildContentBylines(db);
|
|
@@ -2269,7 +2269,7 @@ async function assertSingleLocale(db, defaultLocale) {
|
|
|
2269
2269
|
const count = Number(result.rows[0]?.count ?? 0);
|
|
2270
2270
|
if (count > 0) throw new Error(`Cannot revert migration 040_byline_i18n: ${count} row(s) in "_emdash_bylines" use a non-default locale (defaultLocale="${defaultLocale}"). Reverting would drop them silently. Export translations first (or delete them) and re-run the rollback. See packages/core/src/database/migrations/040_byline_i18n.ts.`);
|
|
2271
2271
|
}
|
|
2272
|
-
async function down$
|
|
2272
|
+
async function down$30(db) {
|
|
2273
2273
|
const defaultLocale = getDefaultLocale();
|
|
2274
2274
|
await assertSingleLocale(db, defaultLocale);
|
|
2275
2275
|
await assertContentBylinesResolve(db, defaultLocale);
|
|
@@ -2388,8 +2388,8 @@ async function restoreContentBylinesFk(db) {
|
|
|
2388
2388
|
//#endregion
|
|
2389
2389
|
//#region src/database/migrations/041_content_locale_list_index.ts
|
|
2390
2390
|
var _041_content_locale_list_index_exports = /* @__PURE__ */ __exportAll({
|
|
2391
|
-
down: () => down$
|
|
2392
|
-
up: () => up$
|
|
2391
|
+
down: () => down$29,
|
|
2392
|
+
up: () => up$29
|
|
2393
2393
|
});
|
|
2394
2394
|
/**
|
|
2395
2395
|
* Migration: locale-aware composite indexes for content list queries.
|
|
@@ -2409,7 +2409,7 @@ var _041_content_locale_list_index_exports = /* @__PURE__ */ __exportAll({
|
|
|
2409
2409
|
* slugs as short as 40 chars, making both names truncate to the same string.
|
|
2410
2410
|
* Keep these identical to the names in `schema/registry.ts`.
|
|
2411
2411
|
*/
|
|
2412
|
-
async function up$
|
|
2412
|
+
async function up$29(db) {
|
|
2413
2413
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
2414
2414
|
for (const tableName of tableNames) {
|
|
2415
2415
|
await sql`
|
|
@@ -2422,7 +2422,7 @@ async function up$13(db) {
|
|
|
2422
2422
|
`.execute(db);
|
|
2423
2423
|
}
|
|
2424
2424
|
}
|
|
2425
|
-
async function down$
|
|
2425
|
+
async function down$29(db) {
|
|
2426
2426
|
const tableNames = await listTablesLike(db, "ec_%");
|
|
2427
2427
|
for (const tableName of tableNames) {
|
|
2428
2428
|
await sql`DROP INDEX IF EXISTS ${sql.ref(`idx_${tableName}_loc_upd`)}`.execute(db);
|
|
@@ -2433,8 +2433,8 @@ async function down$13(db) {
|
|
|
2433
2433
|
//#endregion
|
|
2434
2434
|
//#region src/database/migrations/042_byline_fields.ts
|
|
2435
2435
|
var _042_byline_fields_exports = /* @__PURE__ */ __exportAll({
|
|
2436
|
-
down: () => down$
|
|
2437
|
-
up: () => up$
|
|
2436
|
+
down: () => down$28,
|
|
2437
|
+
up: () => up$28
|
|
2438
2438
|
});
|
|
2439
2439
|
/**
|
|
2440
2440
|
* Byline custom fields (Discussion #1174). Adds three tables and a
|
|
@@ -2479,7 +2479,7 @@ var _042_byline_fields_exports = /* @__PURE__ */ __exportAll({
|
|
|
2479
2479
|
* reference it. If `down()` runs after a partial `up()`, missing tables
|
|
2480
2480
|
* are tolerated (`DROP TABLE IF EXISTS`).
|
|
2481
2481
|
*/
|
|
2482
|
-
async function up$
|
|
2482
|
+
async function up$28(db) {
|
|
2483
2483
|
await db.schema.createTable("_emdash_byline_fields").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("slug", "text", (col) => col.notNull().unique()).addColumn("label", "text", (col) => col.notNull()).addColumn("type", "text", (col) => col.notNull()).addColumn("required", "integer", (col) => col.notNull().defaultTo(0)).addColumn("translatable", "integer", (col) => col.notNull().defaultTo(1)).addColumn("validation", "text").addColumn("sort_order", "integer", (col) => col.notNull().defaultTo(0)).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
2484
2484
|
await db.schema.createIndex("idx__emdash_byline_fields_sort_order").ifNotExists().on("_emdash_byline_fields").column("sort_order").execute();
|
|
2485
2485
|
await db.schema.createTable("_emdash_byline_field_values").ifNotExists().addColumn("byline_id", "text", (col) => col.notNull().references("_emdash_bylines.id").onDelete("cascade")).addColumn("field_id", "text", (col) => col.notNull().references("_emdash_byline_fields.id").onDelete("cascade")).addColumn("value", "text").addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db))).addPrimaryKeyConstraint("_emdash_byline_field_values_pk", ["byline_id", "field_id"]).execute();
|
|
@@ -2502,7 +2502,7 @@ async function up$12(db) {
|
|
|
2502
2502
|
* `up()` (only one or two tables landed) still settles the database back
|
|
2503
2503
|
* to its pre-042 state.
|
|
2504
2504
|
*/
|
|
2505
|
-
async function down$
|
|
2505
|
+
async function down$28(db) {
|
|
2506
2506
|
await db.schema.dropTable("_emdash_byline_field_group_values").ifExists().execute();
|
|
2507
2507
|
await db.schema.dropTable("_emdash_byline_field_values").ifExists().execute();
|
|
2508
2508
|
await db.schema.dropTable("_emdash_byline_fields").ifExists().execute();
|
|
@@ -2512,8 +2512,8 @@ async function down$12(db) {
|
|
|
2512
2512
|
//#endregion
|
|
2513
2513
|
//#region src/database/migrations/043_content_references.ts
|
|
2514
2514
|
var _043_content_references_exports = /* @__PURE__ */ __exportAll({
|
|
2515
|
-
down: () => down$
|
|
2516
|
-
up: () => up$
|
|
2515
|
+
down: () => down$27,
|
|
2516
|
+
up: () => up$27
|
|
2517
2517
|
});
|
|
2518
2518
|
/**
|
|
2519
2519
|
* Content references.
|
|
@@ -2533,7 +2533,7 @@ var _043_content_references_exports = /* @__PURE__ */ __exportAll({
|
|
|
2533
2533
|
* race-recovery path) re-applies cleanly — including any indexes that landed in
|
|
2534
2534
|
* the failed pass after their table.
|
|
2535
2535
|
*/
|
|
2536
|
-
async function up$
|
|
2536
|
+
async function up$27(db) {
|
|
2537
2537
|
const defaultLocale = getI18nConfig()?.defaultLocale ?? "en";
|
|
2538
2538
|
await db.schema.createTable("_emdash_relations").ifNotExists().addColumn("id", "text", (c) => c.primaryKey()).addColumn("name", "text", (c) => c.notNull()).addColumn("parent_collection", "text", (c) => c.notNull()).addColumn("child_collection", "text", (c) => c.notNull()).addColumn("parent_label", "text", (c) => c.notNull()).addColumn("child_label", "text", (c) => c.notNull()).addColumn("locale", "text", (c) => c.notNull().defaultTo(defaultLocale)).addColumn("translation_group", "text", (c) => c.notNull()).addColumn("created_at", "text", (c) => c.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (c) => c.defaultTo(currentTimestamp(db))).addUniqueConstraint("_emdash_relations_name_locale_unique", ["name", "locale"]).execute();
|
|
2539
2539
|
await db.schema.createIndex("idx__emdash_relations_locale").ifNotExists().on("_emdash_relations").column("locale").execute();
|
|
@@ -2554,7 +2554,7 @@ async function up$11(db) {
|
|
|
2554
2554
|
await db.schema.createIndex("idx__emdash_content_references_child").ifNotExists().on("_emdash_content_references").columns(["child_group", "relation_group"]).execute();
|
|
2555
2555
|
await db.schema.createIndex("idx__emdash_content_references_relation").ifNotExists().on("_emdash_content_references").column("relation_group").execute();
|
|
2556
2556
|
}
|
|
2557
|
-
async function down$
|
|
2557
|
+
async function down$27(db) {
|
|
2558
2558
|
await db.schema.dropTable("_emdash_content_references").ifExists().execute();
|
|
2559
2559
|
await db.schema.dropTable("_emdash_relations").ifExists().execute();
|
|
2560
2560
|
}
|
|
@@ -2562,8 +2562,8 @@ async function down$11(db) {
|
|
|
2562
2562
|
//#endregion
|
|
2563
2563
|
//#region src/database/migrations/044_comment_reactions.ts
|
|
2564
2564
|
var _044_comment_reactions_exports = /* @__PURE__ */ __exportAll({
|
|
2565
|
-
down: () => down$
|
|
2566
|
-
up: () => up$
|
|
2565
|
+
down: () => down$26,
|
|
2566
|
+
up: () => up$26
|
|
2567
2567
|
});
|
|
2568
2568
|
/**
|
|
2569
2569
|
* Comment reactions (Tier 1 of the best-in-class comments RFC).
|
|
@@ -2575,7 +2575,7 @@ var _044_comment_reactions_exports = /* @__PURE__ */ __exportAll({
|
|
|
2575
2575
|
*
|
|
2576
2576
|
* Additive and backward-compatible: a new table, no change to existing schema.
|
|
2577
2577
|
*/
|
|
2578
|
-
async function up$
|
|
2578
|
+
async function up$26(db) {
|
|
2579
2579
|
await db.schema.createTable("_emdash_comment_reactions").ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("comment_id", "text", (col) => col.notNull().references("_emdash_comments.id").onDelete("cascade")).addColumn("reaction", "text", (col) => col.notNull().defaultTo("like")).addColumn("voter_hash", "text", (col) => col.notNull()).addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db))).execute();
|
|
2580
2580
|
await db.schema.createIndex("idx_comment_reactions_unique").ifNotExists().on("_emdash_comment_reactions").columns([
|
|
2581
2581
|
"comment_id",
|
|
@@ -2585,15 +2585,15 @@ async function up$10(db) {
|
|
|
2585
2585
|
await db.schema.createIndex("idx_comment_reactions_comment").ifNotExists().on("_emdash_comment_reactions").column("comment_id").execute();
|
|
2586
2586
|
await db.schema.createIndex("idx_comment_reactions_voter").ifNotExists().on("_emdash_comment_reactions").columns(["voter_hash", "created_at"]).execute();
|
|
2587
2587
|
}
|
|
2588
|
-
async function down$
|
|
2588
|
+
async function down$26(db) {
|
|
2589
2589
|
await db.schema.dropTable("_emdash_comment_reactions").execute();
|
|
2590
2590
|
}
|
|
2591
2591
|
|
|
2592
2592
|
//#endregion
|
|
2593
2593
|
//#region src/database/migrations/045_taxonomy_parent_group.ts
|
|
2594
2594
|
var _045_taxonomy_parent_group_exports = /* @__PURE__ */ __exportAll({
|
|
2595
|
-
down: () => down$
|
|
2596
|
-
up: () => up$
|
|
2595
|
+
down: () => down$25,
|
|
2596
|
+
up: () => up$25
|
|
2597
2597
|
});
|
|
2598
2598
|
/**
|
|
2599
2599
|
* Store the parent's `translation_group` in `taxonomies.parent_id` instead of a
|
|
@@ -2623,7 +2623,7 @@ var _045_taxonomy_parent_group_exports = /* @__PURE__ */ __exportAll({
|
|
|
2623
2623
|
* Dialect-independent: the correlated-subquery `UPDATE` runs on SQLite (incl.
|
|
2624
2624
|
* D1) and Postgres alike.
|
|
2625
2625
|
*/
|
|
2626
|
-
async function up$
|
|
2626
|
+
async function up$25(db) {
|
|
2627
2627
|
await sql`
|
|
2628
2628
|
UPDATE taxonomies
|
|
2629
2629
|
SET parent_id = (
|
|
@@ -2645,7 +2645,7 @@ async function up$9(db) {
|
|
|
2645
2645
|
* locale (the pre-migration shape). Rows with no same-locale parent are left as
|
|
2646
2646
|
* they are rather than nulled, so a rollback never silently detaches a subtree.
|
|
2647
2647
|
*/
|
|
2648
|
-
async function down$
|
|
2648
|
+
async function down$25(db) {
|
|
2649
2649
|
await sql`
|
|
2650
2650
|
UPDATE taxonomies
|
|
2651
2651
|
SET parent_id = COALESCE(
|
|
@@ -2663,8 +2663,8 @@ async function down$9(db) {
|
|
|
2663
2663
|
//#endregion
|
|
2664
2664
|
//#region src/database/migrations/046_media_usage_index.ts
|
|
2665
2665
|
var _046_media_usage_index_exports = /* @__PURE__ */ __exportAll({
|
|
2666
|
-
down: () => down$
|
|
2667
|
-
up: () => up$
|
|
2666
|
+
down: () => down$24,
|
|
2667
|
+
up: () => up$24
|
|
2668
2668
|
});
|
|
2669
2669
|
/**
|
|
2670
2670
|
* Internal media usage projection tables.
|
|
@@ -2673,7 +2673,7 @@ var _046_media_usage_index_exports = /* @__PURE__ */ __exportAll({
|
|
|
2673
2673
|
* imports, and no content-table scans. Production rows are introduced by later
|
|
2674
2674
|
* phases once the central snapshot/indexer path is reviewed.
|
|
2675
2675
|
*/
|
|
2676
|
-
async function up$
|
|
2676
|
+
async function up$24(db) {
|
|
2677
2677
|
await db.schema.createTable("_emdash_media_usage_sources").ifNotExists().addColumn("source_key", "text", (c) => c.primaryKey()).addColumn("source_type", "text", (c) => c.notNull()).addColumn("collection_slug", "text").addColumn("content_id", "text").addColumn("source_variant", "text", (c) => c.notNull()).addColumn("locale", "text").addColumn("translation_group", "text").addColumn("content_slug", "text").addColumn("content_title", "text").addColumn("content_status", "text").addColumn("content_scheduled_at", "text").addColumn("content_deleted_at", "text").addColumn("revision_id", "text").addColumn("current_generation", "text", (c) => c.notNull()).addColumn("schema_version", "integer", (c) => c.notNull().defaultTo(1)).addColumn("indexed_at", "text", (c) => c.notNull().defaultTo(currentTimestamp(db))).addColumn("created_at", "text", (c) => c.defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (c) => c.defaultTo(currentTimestamp(db))).execute();
|
|
2678
2678
|
await db.schema.createIndex("idx__emdash_media_usage_sources_content").ifNotExists().on("_emdash_media_usage_sources").columns([
|
|
2679
2679
|
"source_type",
|
|
@@ -2695,7 +2695,7 @@ async function up$8(db) {
|
|
|
2695
2695
|
await db.schema.createIndex("idx__emdash_media_usage_provider_asset").ifNotExists().on("_emdash_media_usage").columns(["provider", "provider_asset_id"]).execute();
|
|
2696
2696
|
await db.schema.createIndex("idx__emdash_media_usage_source_generation").ifNotExists().on("_emdash_media_usage").columns(["source_key", "generation"]).execute();
|
|
2697
2697
|
}
|
|
2698
|
-
async function down$
|
|
2698
|
+
async function down$24(db) {
|
|
2699
2699
|
await db.schema.dropTable("_emdash_media_usage").ifExists().execute();
|
|
2700
2700
|
await db.schema.dropTable("_emdash_media_usage_sources").ifExists().execute();
|
|
2701
2701
|
}
|
|
@@ -2703,8 +2703,8 @@ async function down$8(db) {
|
|
|
2703
2703
|
//#endregion
|
|
2704
2704
|
//#region src/database/migrations/047_restore_taxonomy_parent_index.ts
|
|
2705
2705
|
var _047_restore_taxonomy_parent_index_exports = /* @__PURE__ */ __exportAll({
|
|
2706
|
-
down: () => down$
|
|
2707
|
-
up: () => up$
|
|
2706
|
+
down: () => down$23,
|
|
2707
|
+
up: () => up$23
|
|
2708
2708
|
});
|
|
2709
2709
|
/**
|
|
2710
2710
|
* Restore `idx_taxonomies_parent` on `taxonomies(parent_id)` (#1665).
|
|
@@ -2721,18 +2721,18 @@ var _047_restore_taxonomy_parent_index_exports = /* @__PURE__ */ __exportAll({
|
|
|
2721
2721
|
* index here. Fresh installs also get it in 036's rebuild for parity with the
|
|
2722
2722
|
* other rebuilt tables, making this a no-op for them.
|
|
2723
2723
|
*/
|
|
2724
|
-
async function up$
|
|
2724
|
+
async function up$23(db) {
|
|
2725
2725
|
await db.schema.createIndex("idx_taxonomies_parent").ifNotExists().on("taxonomies").column("parent_id").execute();
|
|
2726
2726
|
}
|
|
2727
|
-
async function down$
|
|
2727
|
+
async function down$23(db) {
|
|
2728
2728
|
await db.schema.dropIndex("idx_taxonomies_parent").ifExists().execute();
|
|
2729
2729
|
}
|
|
2730
2730
|
|
|
2731
2731
|
//#endregion
|
|
2732
2732
|
//#region src/database/migrations/048_restore_content_taxonomies_term_index.ts
|
|
2733
2733
|
var _048_restore_content_taxonomies_term_index_exports = /* @__PURE__ */ __exportAll({
|
|
2734
|
-
down: () => down$
|
|
2735
|
-
up: () => up$
|
|
2734
|
+
down: () => down$22,
|
|
2735
|
+
up: () => up$22
|
|
2736
2736
|
});
|
|
2737
2737
|
/**
|
|
2738
2738
|
* Restore `idx_content_taxonomies_term` on `content_taxonomies(taxonomy_id)` (#1701).
|
|
@@ -2752,18 +2752,18 @@ var _048_restore_content_taxonomies_term_index_exports = /* @__PURE__ */ __expor
|
|
|
2752
2752
|
*
|
|
2753
2753
|
* Forward-only.
|
|
2754
2754
|
*/
|
|
2755
|
-
async function up$
|
|
2755
|
+
async function up$22(db) {
|
|
2756
2756
|
await db.schema.createIndex("idx_content_taxonomies_term").ifNotExists().on("content_taxonomies").column("taxonomy_id").execute();
|
|
2757
2757
|
}
|
|
2758
|
-
async function down$
|
|
2758
|
+
async function down$22(db) {
|
|
2759
2759
|
await db.schema.dropIndex("idx_content_taxonomies_term").ifExists().execute();
|
|
2760
2760
|
}
|
|
2761
2761
|
|
|
2762
2762
|
//#endregion
|
|
2763
2763
|
//#region src/database/migrations/049_taxonomies_name_locale_index.ts
|
|
2764
2764
|
var _049_taxonomies_name_locale_index_exports = /* @__PURE__ */ __exportAll({
|
|
2765
|
-
down: () => down$
|
|
2766
|
-
up: () => up$
|
|
2765
|
+
down: () => down$21,
|
|
2766
|
+
up: () => up$21
|
|
2767
2767
|
});
|
|
2768
2768
|
/**
|
|
2769
2769
|
* Add composite `idx_taxonomies_name_locale` on `taxonomies(name, locale)` (#1723).
|
|
@@ -2784,11 +2784,11 @@ var _049_taxonomies_name_locale_index_exports = /* @__PURE__ */ __exportAll({
|
|
|
2784
2784
|
* by the new composite's prefix. Create-before-drop keeps name lookups indexed
|
|
2785
2785
|
* at every point. Both statements are idempotent so a partial apply can retry.
|
|
2786
2786
|
*/
|
|
2787
|
-
async function up$
|
|
2787
|
+
async function up$21(db) {
|
|
2788
2788
|
await db.schema.createIndex("idx_taxonomies_name_locale").ifNotExists().on("taxonomies").columns(["name", "locale"]).execute();
|
|
2789
2789
|
await db.schema.dropIndex("idx_taxonomies_name").ifExists().execute();
|
|
2790
2790
|
}
|
|
2791
|
-
async function down$
|
|
2791
|
+
async function down$21(db) {
|
|
2792
2792
|
await db.schema.createIndex("idx_taxonomies_name").ifNotExists().on("taxonomies").column("name").execute();
|
|
2793
2793
|
await db.schema.dropIndex("idx_taxonomies_name_locale").ifExists().execute();
|
|
2794
2794
|
}
|
|
@@ -2796,11 +2796,11 @@ async function down$5(db) {
|
|
|
2796
2796
|
//#endregion
|
|
2797
2797
|
//#region src/database/migrations/050_media_usage_index_status.ts
|
|
2798
2798
|
var _050_media_usage_index_status_exports = /* @__PURE__ */ __exportAll({
|
|
2799
|
-
down: () => down$
|
|
2800
|
-
up: () => up$
|
|
2799
|
+
down: () => down$20,
|
|
2800
|
+
up: () => up$20
|
|
2801
2801
|
});
|
|
2802
2802
|
const SOURCE_TABLE = "_emdash_media_usage_sources";
|
|
2803
|
-
const DUPLICATE_COLUMN_RE = /(?:duplicate column|column .* already exists|already exists.*column)/i;
|
|
2803
|
+
const DUPLICATE_COLUMN_RE$1 = /(?:duplicate column|column .* already exists|already exists.*column)/i;
|
|
2804
2804
|
/**
|
|
2805
2805
|
* Media usage index metadata.
|
|
2806
2806
|
*
|
|
@@ -2808,7 +2808,7 @@ const DUPLICATE_COLUMN_RE = /(?:duplicate column|column .* already exists|alread
|
|
|
2808
2808
|
* tracking for later reference-index reconciliation. No content scans, no
|
|
2809
2809
|
* runtime imports, and no backfill.
|
|
2810
2810
|
*/
|
|
2811
|
-
async function up$
|
|
2811
|
+
async function up$20(db) {
|
|
2812
2812
|
await addSourceMetadataColumns(db);
|
|
2813
2813
|
await db.schema.createTable("_emdash_media_usage_index_status").ifNotExists().addColumn("adapter_id", "text", (c) => c.notNull()).addColumn("scope_type", "text", (c) => c.notNull()).addColumn("scope_key", "text", (c) => c.notNull()).addColumn("status", "text", (c) => c.notNull()).addColumn("schema_version", "integer", (c) => c.notNull().defaultTo(1)).addColumn("started_at", "text").addColumn("completed_at", "text").addColumn("cursor", "text").addColumn("indexed_source_count", "integer", (c) => c.notNull().defaultTo(0)).addColumn("failed_source_count", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_error_code", "text").addColumn("updated_at", "text", (c) => c.notNull().defaultTo(currentTimestamp(db))).addPrimaryKeyConstraint("_emdash_media_usage_index_status_pk", [
|
|
2814
2814
|
"adapter_id",
|
|
@@ -2823,7 +2823,7 @@ async function up$4(db) {
|
|
|
2823
2823
|
await db.schema.createIndex("idx__emdash_media_usage_sources_fingerprint").ifNotExists().on("_emdash_media_usage_sources").column("source_fingerprint").execute();
|
|
2824
2824
|
await db.schema.createIndex("idx__emdash_media_usage_index_status_status").ifNotExists().on("_emdash_media_usage_index_status").columns(["adapter_id", "status"]).execute();
|
|
2825
2825
|
}
|
|
2826
|
-
async function down$
|
|
2826
|
+
async function down$20(db) {
|
|
2827
2827
|
await db.schema.dropIndex("idx__emdash_media_usage_index_status_status").ifExists().execute();
|
|
2828
2828
|
await db.schema.dropIndex("idx__emdash_media_usage_sources_fingerprint").ifExists().execute();
|
|
2829
2829
|
await db.schema.dropIndex("idx__emdash_media_usage_sources_completeness").ifExists().execute();
|
|
@@ -2831,29 +2831,29 @@ async function down$4(db) {
|
|
|
2831
2831
|
await dropSourceMetadataColumns(db);
|
|
2832
2832
|
}
|
|
2833
2833
|
async function addSourceMetadataColumns(db) {
|
|
2834
|
-
await addColumnIfMissing(db, "source_updated_at", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_updated_at", "text").execute());
|
|
2835
|
-
await addColumnIfMissing(db, "source_version", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_version", "integer").execute());
|
|
2836
|
-
await addColumnIfMissing(db, "source_fingerprint", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_fingerprint", "text").execute());
|
|
2837
|
-
await addColumnIfMissing(db, "source_completeness", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_completeness", "text", (c) => c.notNull().defaultTo("unknown")).execute());
|
|
2838
|
-
await addColumnIfMissing(db, "last_attempted_at", () => db.schema.alterTable(SOURCE_TABLE).addColumn("last_attempted_at", "text").execute());
|
|
2839
|
-
await addColumnIfMissing(db, "last_error_code", () => db.schema.alterTable(SOURCE_TABLE).addColumn("last_error_code", "text").execute());
|
|
2840
|
-
}
|
|
2841
|
-
async function addColumnIfMissing(db, columnName, addColumn) {
|
|
2834
|
+
await addColumnIfMissing$1(db, "source_updated_at", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_updated_at", "text").execute());
|
|
2835
|
+
await addColumnIfMissing$1(db, "source_version", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_version", "integer").execute());
|
|
2836
|
+
await addColumnIfMissing$1(db, "source_fingerprint", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_fingerprint", "text").execute());
|
|
2837
|
+
await addColumnIfMissing$1(db, "source_completeness", () => db.schema.alterTable(SOURCE_TABLE).addColumn("source_completeness", "text", (c) => c.notNull().defaultTo("unknown")).execute());
|
|
2838
|
+
await addColumnIfMissing$1(db, "last_attempted_at", () => db.schema.alterTable(SOURCE_TABLE).addColumn("last_attempted_at", "text").execute());
|
|
2839
|
+
await addColumnIfMissing$1(db, "last_error_code", () => db.schema.alterTable(SOURCE_TABLE).addColumn("last_error_code", "text").execute());
|
|
2840
|
+
}
|
|
2841
|
+
async function addColumnIfMissing$1(db, columnName, addColumn) {
|
|
2842
2842
|
if (await columnExists(db, SOURCE_TABLE, columnName)) return;
|
|
2843
2843
|
try {
|
|
2844
2844
|
await addColumn();
|
|
2845
2845
|
} catch (error) {
|
|
2846
|
-
if (DUPLICATE_COLUMN_RE.test(deepErrorMessage$
|
|
2846
|
+
if (DUPLICATE_COLUMN_RE$1.test(deepErrorMessage$2(error))) {
|
|
2847
2847
|
if (await columnExists(db, SOURCE_TABLE, columnName)) return;
|
|
2848
2848
|
}
|
|
2849
2849
|
throw error;
|
|
2850
2850
|
}
|
|
2851
2851
|
}
|
|
2852
|
-
function deepErrorMessage$
|
|
2852
|
+
function deepErrorMessage$2(error) {
|
|
2853
2853
|
if (error instanceof Error) {
|
|
2854
2854
|
const own = error.message ?? "";
|
|
2855
2855
|
if (error.cause) {
|
|
2856
|
-
const causeMessage = deepErrorMessage$
|
|
2856
|
+
const causeMessage = deepErrorMessage$2(error.cause);
|
|
2857
2857
|
return own ? `${own}: ${causeMessage}` : causeMessage;
|
|
2858
2858
|
}
|
|
2859
2859
|
return own;
|
|
@@ -2879,8 +2879,8 @@ async function dropSourceMetadataColumns(db) {
|
|
|
2879
2879
|
//#endregion
|
|
2880
2880
|
//#region src/database/migrations/051_content_taxonomies_denorm.ts
|
|
2881
2881
|
var _051_content_taxonomies_denorm_exports = /* @__PURE__ */ __exportAll({
|
|
2882
|
-
down: () => down$
|
|
2883
|
-
up: () => up$
|
|
2882
|
+
down: () => down$19,
|
|
2883
|
+
up: () => up$19
|
|
2884
2884
|
});
|
|
2885
2885
|
/**
|
|
2886
2886
|
* Denormalize the filter + sort columns from `ec_*` onto `content_taxonomies`
|
|
@@ -2937,7 +2937,7 @@ const INDEXES = [
|
|
|
2937
2937
|
columns: "taxonomy_id, collection, deleted_at, locale, created_at DESC, entry_id DESC"
|
|
2938
2938
|
}
|
|
2939
2939
|
];
|
|
2940
|
-
async function up$
|
|
2940
|
+
async function up$19(db) {
|
|
2941
2941
|
for (const column of DENORM_COLUMNS) {
|
|
2942
2942
|
if (await columnExists(db, "content_taxonomies", column)) continue;
|
|
2943
2943
|
await sql`
|
|
@@ -2963,7 +2963,7 @@ async function up$3(db) {
|
|
|
2963
2963
|
ON content_taxonomies (${sql.raw(index.columns)})
|
|
2964
2964
|
`.execute(db);
|
|
2965
2965
|
}
|
|
2966
|
-
async function down$
|
|
2966
|
+
async function down$19(db) {
|
|
2967
2967
|
for (const index of INDEXES) await sql`DROP INDEX IF EXISTS ${sql.ref(index.name)}`.execute(db);
|
|
2968
2968
|
for (const column of DENORM_COLUMNS) await sql`
|
|
2969
2969
|
ALTER TABLE content_taxonomies DROP COLUMN ${sql.ref(column)}
|
|
@@ -2973,12 +2973,12 @@ async function down$3(db) {
|
|
|
2973
2973
|
//#endregion
|
|
2974
2974
|
//#region src/database/migrations/052_media_usage_read_index.ts
|
|
2975
2975
|
var _052_media_usage_read_index_exports = /* @__PURE__ */ __exportAll({
|
|
2976
|
-
down: () => down$
|
|
2977
|
-
up: () => up$
|
|
2976
|
+
down: () => down$18,
|
|
2977
|
+
up: () => up$18
|
|
2978
2978
|
});
|
|
2979
2979
|
const OLD_INDEX = "idx__emdash_media_usage_media_id";
|
|
2980
2980
|
const READ_INDEX = "idx__emdash_media_usage_media_source_generation";
|
|
2981
|
-
async function up$
|
|
2981
|
+
async function up$18(db) {
|
|
2982
2982
|
await db.schema.createIndex(READ_INDEX).ifNotExists().on("_emdash_media_usage").columns([
|
|
2983
2983
|
"media_id",
|
|
2984
2984
|
"source_key",
|
|
@@ -2986,7 +2986,7 @@ async function up$2(db) {
|
|
|
2986
2986
|
]).execute();
|
|
2987
2987
|
await db.schema.dropIndex(OLD_INDEX).ifExists().execute();
|
|
2988
2988
|
}
|
|
2989
|
-
async function down$
|
|
2989
|
+
async function down$18(db) {
|
|
2990
2990
|
await db.schema.createIndex(OLD_INDEX).ifNotExists().on("_emdash_media_usage").column("media_id").execute();
|
|
2991
2991
|
await db.schema.dropIndex(READ_INDEX).ifExists().execute();
|
|
2992
2992
|
}
|
|
@@ -2994,15 +2994,15 @@ async function down$2(db) {
|
|
|
2994
2994
|
//#endregion
|
|
2995
2995
|
//#region src/database/migrations/053_plugin_mcp_tools.ts
|
|
2996
2996
|
var _053_plugin_mcp_tools_exports = /* @__PURE__ */ __exportAll({
|
|
2997
|
-
down: () => down$
|
|
2998
|
-
up: () => up$
|
|
2997
|
+
down: () => down$17,
|
|
2998
|
+
up: () => up$17
|
|
2999
2999
|
});
|
|
3000
3000
|
/** Persist explicit per-plugin MCP enablement and the declaration consented to by an admin. */
|
|
3001
|
-
async function up$
|
|
3001
|
+
async function up$17(db) {
|
|
3002
3002
|
if (!await columnExists(db, "_plugin_state", "mcp_tools_enabled")) await db.schema.alterTable("_plugin_state").addColumn("mcp_tools_enabled", "integer", (col) => col.notNull().defaultTo(0)).execute();
|
|
3003
3003
|
if (!await columnExists(db, "_plugin_state", "mcp_tools_consent")) await db.schema.alterTable("_plugin_state").addColumn("mcp_tools_consent", "text").execute();
|
|
3004
3004
|
}
|
|
3005
|
-
async function down$
|
|
3005
|
+
async function down$17(db) {
|
|
3006
3006
|
await db.schema.alterTable("_plugin_state").dropColumn("mcp_tools_consent").execute();
|
|
3007
3007
|
await db.schema.alterTable("_plugin_state").dropColumn("mcp_tools_enabled").execute();
|
|
3008
3008
|
}
|
|
@@ -3010,20 +3010,1173 @@ async function down$1(db) {
|
|
|
3010
3010
|
//#endregion
|
|
3011
3011
|
//#region src/database/migrations/054_media_upload_attempts.ts
|
|
3012
3012
|
var _054_media_upload_attempts_exports = /* @__PURE__ */ __exportAll({
|
|
3013
|
-
down: () => down,
|
|
3014
|
-
up: () => up
|
|
3013
|
+
down: () => down$16,
|
|
3014
|
+
up: () => up$16
|
|
3015
3015
|
});
|
|
3016
|
-
async function up(db) {
|
|
3016
|
+
async function up$16(db) {
|
|
3017
3017
|
await db.schema.createTable("_emdash_media_upload_attempts").ifNotExists().addColumn("storage_key", "text", (col) => col.primaryKey()).addColumn("media_id", "text", (col) => col.notNull()).addColumn("status", "text", (col) => col.notNull().defaultTo("active")).addColumn("created_at", "text", (col) => col.notNull().defaultTo(currentTimestamp(db))).addColumn("updated_at", "text", (col) => col.notNull().defaultTo(currentTimestamp(db))).execute();
|
|
3018
3018
|
await db.schema.createIndex("idx_media_upload_attempts_media_id").ifNotExists().on("_emdash_media_upload_attempts").column("media_id").execute();
|
|
3019
3019
|
await db.schema.createIndex("idx_media_upload_attempts_status_created_at").ifNotExists().on("_emdash_media_upload_attempts").columns(["status", "created_at"]).execute();
|
|
3020
3020
|
await db.schema.createIndex("idx_media_storage_key").ifNotExists().on("media").column("storage_key").execute();
|
|
3021
3021
|
}
|
|
3022
|
-
async function down(db) {
|
|
3022
|
+
async function down$16(db) {
|
|
3023
3023
|
await db.schema.dropIndex("idx_media_storage_key").ifExists().execute();
|
|
3024
3024
|
await db.schema.dropTable("_emdash_media_upload_attempts").ifExists().execute();
|
|
3025
3025
|
}
|
|
3026
3026
|
|
|
3027
|
+
//#endregion
|
|
3028
|
+
//#region src/database/migrations/055_content_translation_group_locale_index.ts
|
|
3029
|
+
var _055_content_translation_group_locale_index_exports = /* @__PURE__ */ __exportAll({
|
|
3030
|
+
down: () => down$15,
|
|
3031
|
+
up: () => up$15
|
|
3032
|
+
});
|
|
3033
|
+
/**
|
|
3034
|
+
* Migration: replace the single-column content `translation_group` index with
|
|
3035
|
+
* one index per translation-group read shape.
|
|
3036
|
+
*
|
|
3037
|
+
* There are two shapes. Translation-group reads filter `deleted_at IS NULL`
|
|
3038
|
+
* with `translation_group = ?` / `IN (...)` and order by locale; menu and
|
|
3039
|
+
* reference resolution looks a group up by `translation_group` (+ `locale`)
|
|
3040
|
+
* alone, with no `deleted_at` term.
|
|
3041
|
+
*
|
|
3042
|
+
* Neither shape can borrow the other's index. Seeking migration 041's
|
|
3043
|
+
* `(deleted_at, locale, ...)` composites on `deleted_at` alone already returns
|
|
3044
|
+
* rows in locale order, so a stats-blind planner prefers them over a
|
|
3045
|
+
* single-column `translation_group` index and reads every non-deleted row in
|
|
3046
|
+
* the table; the batched variant is worse still, because the `IN (...)` list
|
|
3047
|
+
* multiplies the planner's row estimate for a `translation_group`-leading index
|
|
3048
|
+
* and it falls back to a `deleted_at` composite from a handful of groups
|
|
3049
|
+
* onward. Going the other way, an index leading with `deleted_at` cannot seek a
|
|
3050
|
+
* lookup that never constrains that column. D1 never has `sqlite_stat1`, so the
|
|
3051
|
+
* index shape is the only lever and each shape needs a prefix matching it term
|
|
3052
|
+
* for term.
|
|
3053
|
+
*
|
|
3054
|
+
* Forward-only and idempotent (`IF NOT EXISTS`).
|
|
3055
|
+
*
|
|
3056
|
+
* Index names use short `tg_locale` / `del_tg_locale` suffixes rather than
|
|
3057
|
+
* spelling out `translation_group`: Postgres truncates identifiers to 63 bytes,
|
|
3058
|
+
* and the longer forms truncate to the same value for long collection slugs.
|
|
3059
|
+
* Keep these identical to the names in `schema/registry.ts`.
|
|
3060
|
+
*/
|
|
3061
|
+
async function up$15(db) {
|
|
3062
|
+
const tableNames = await listTablesLike(db, "ec_%");
|
|
3063
|
+
for (const tableName of tableNames) {
|
|
3064
|
+
await sql`
|
|
3065
|
+
CREATE INDEX IF NOT EXISTS ${sql.ref(`idx_${tableName}_tg_locale`)}
|
|
3066
|
+
ON ${sql.ref(tableName)} (translation_group, locale)
|
|
3067
|
+
`.execute(db);
|
|
3068
|
+
await sql`
|
|
3069
|
+
CREATE INDEX IF NOT EXISTS ${sql.ref(`idx_${tableName}_del_tg_locale`)}
|
|
3070
|
+
ON ${sql.ref(tableName)} (deleted_at, translation_group, locale)
|
|
3071
|
+
`.execute(db);
|
|
3072
|
+
await sql`DROP INDEX IF EXISTS ${sql.ref(`idx_${tableName}_translation_group`)}`.execute(db);
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
async function down$15(db) {
|
|
3076
|
+
const tableNames = await listTablesLike(db, "ec_%");
|
|
3077
|
+
for (const tableName of tableNames) {
|
|
3078
|
+
await sql`
|
|
3079
|
+
CREATE INDEX IF NOT EXISTS ${sql.ref(`idx_${tableName}_translation_group`)}
|
|
3080
|
+
ON ${sql.ref(tableName)} (translation_group)
|
|
3081
|
+
`.execute(db);
|
|
3082
|
+
await sql`DROP INDEX IF EXISTS ${sql.ref(`idx_${tableName}_del_tg_locale`)}`.execute(db);
|
|
3083
|
+
await sql`DROP INDEX IF EXISTS ${sql.ref(`idx_${tableName}_tg_locale`)}`.execute(db);
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
//#endregion
|
|
3088
|
+
//#region src/database/migrations/056_taxonomy_term_sort_order.ts
|
|
3089
|
+
var _056_taxonomy_term_sort_order_exports = /* @__PURE__ */ __exportAll({
|
|
3090
|
+
down: () => down$14,
|
|
3091
|
+
up: () => up$14
|
|
3092
|
+
});
|
|
3093
|
+
/**
|
|
3094
|
+
* Add `taxonomies.sort_order` and mint a position for every existing term.
|
|
3095
|
+
*
|
|
3096
|
+
* A position belongs to a `translation_group`, not a row: every row of a group
|
|
3097
|
+
* carries the same value. Groups are numbered by `(label, id)` — the order term
|
|
3098
|
+
* listings used before this migration — taking the label from the group's lowest
|
|
3099
|
+
* row id. That locale's rendered order is unchanged; every other locale is
|
|
3100
|
+
* re-sorted to match it, since only one locale's collation can win.
|
|
3101
|
+
*
|
|
3102
|
+
* Sibling groups are keyed on the raw `parent_id` column, which holds the
|
|
3103
|
+
* parent's translation_group, so a group whose rows disagree about their parent
|
|
3104
|
+
* is reconciled before numbering — otherwise it lands in whichever sibling group
|
|
3105
|
+
* one arbitrary row happens to name.
|
|
3106
|
+
*
|
|
3107
|
+
* Only the `ALTER` is guarded; the passes below run unconditionally so a run that
|
|
3108
|
+
* dies partway can be retried. Guarding the whole migration strands a partial
|
|
3109
|
+
* numbering, because the retry early-returns on the column it added.
|
|
3110
|
+
*/
|
|
3111
|
+
/**
|
|
3112
|
+
* Translation groups per `UPDATE`. Each costs three bound parameters — a CASE
|
|
3113
|
+
* `WHEN`/`THEN` pair plus one slot in the `IN` list — which keeps a statement
|
|
3114
|
+
* inside D1's 100-parameter ceiling. Writing one group per statement instead
|
|
3115
|
+
* spends a subrequest per term, and a large taxonomy exhausts the 1,000 a
|
|
3116
|
+
* Worker gets on the free plan before the migration finishes.
|
|
3117
|
+
*/
|
|
3118
|
+
const GROUPS_PER_UPDATE = 32;
|
|
3119
|
+
async function up$14(db) {
|
|
3120
|
+
const fresh = !await columnExists(db, "taxonomies", "sort_order");
|
|
3121
|
+
if (fresh) await db.schema.alterTable("taxonomies").addColumn("sort_order", "integer", (col) => col.notNull().defaultTo(0)).execute();
|
|
3122
|
+
await sql`UPDATE taxonomies SET translation_group = id WHERE translation_group IS NULL`.execute(db);
|
|
3123
|
+
const { rows } = await sql`
|
|
3124
|
+
SELECT id, name, label, parent_id, translation_group FROM taxonomies
|
|
3125
|
+
`.execute(db);
|
|
3126
|
+
await repairParents(db, rows);
|
|
3127
|
+
await mintPositions(db, rows, fresh);
|
|
3128
|
+
}
|
|
3129
|
+
/**
|
|
3130
|
+
* Give every row of a translation_group the same `parent_id`, mutating `rows` so
|
|
3131
|
+
* the numbering below sees the reconciled tree.
|
|
3132
|
+
*
|
|
3133
|
+
* `parent_id` holds the parent's translation_group, so it is locale-agnostic and
|
|
3134
|
+
* a group's rows should all agree. Reparenting used to write a single row, which
|
|
3135
|
+
* left a term nested in the locale it was moved in and a root everywhere else.
|
|
3136
|
+
* A non-null parent wins: it is the move somebody made, and the null is the row
|
|
3137
|
+
* that missed it.
|
|
3138
|
+
*
|
|
3139
|
+
* The winner is copied from a sibling row, so it already satisfies the self-FK
|
|
3140
|
+
* on `parent_id` and can't be rewritten into a dangling reference.
|
|
3141
|
+
*/
|
|
3142
|
+
async function repairParents(db, rows) {
|
|
3143
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
3144
|
+
for (const row of rows) {
|
|
3145
|
+
const group = row.translation_group;
|
|
3146
|
+
let members = byGroup.get(group);
|
|
3147
|
+
if (!members) byGroup.set(group, members = []);
|
|
3148
|
+
members.push(row);
|
|
3149
|
+
}
|
|
3150
|
+
const winners = /* @__PURE__ */ new Map();
|
|
3151
|
+
for (const [group, members] of byGroup) {
|
|
3152
|
+
if (new Set(members.map((member) => member.parent_id)).size < 2) continue;
|
|
3153
|
+
const parented = members.filter((member) => member.parent_id !== null);
|
|
3154
|
+
const winner = (parented.find((member) => member.id === group) ?? parented.toSorted((a, b) => a.id.localeCompare(b.id))[0])?.parent_id;
|
|
3155
|
+
if (winner === void 0 || winner === null) continue;
|
|
3156
|
+
winners.set(group, winner);
|
|
3157
|
+
for (const member of members) member.parent_id = winner;
|
|
3158
|
+
}
|
|
3159
|
+
await applyByGroup(db, "parent_id", winners);
|
|
3160
|
+
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Number each sibling group by `(label, id)`.
|
|
3163
|
+
*
|
|
3164
|
+
* When the column was just added every row already reads 0, so those positions
|
|
3165
|
+
* are left to the default. On a retry the column is already there and may hold
|
|
3166
|
+
* numbers from the run that failed, so every position is written explicitly.
|
|
3167
|
+
*/
|
|
3168
|
+
async function mintPositions(db, rows, fresh) {
|
|
3169
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3170
|
+
for (const row of rows) {
|
|
3171
|
+
const group = row.translation_group;
|
|
3172
|
+
const chosen = groups.get(group);
|
|
3173
|
+
if (chosen && chosen.id <= row.id) continue;
|
|
3174
|
+
groups.set(group, {
|
|
3175
|
+
sibling: row.name + "/" + (row.parent_id ?? ""),
|
|
3176
|
+
label: row.label ?? "",
|
|
3177
|
+
id: row.id
|
|
3178
|
+
});
|
|
3179
|
+
}
|
|
3180
|
+
const siblings = /* @__PURE__ */ new Map();
|
|
3181
|
+
for (const [group, { sibling, label, id }] of groups) {
|
|
3182
|
+
let members = siblings.get(sibling);
|
|
3183
|
+
if (!members) siblings.set(sibling, members = []);
|
|
3184
|
+
members.push({
|
|
3185
|
+
group,
|
|
3186
|
+
label,
|
|
3187
|
+
id
|
|
3188
|
+
});
|
|
3189
|
+
}
|
|
3190
|
+
const positions = /* @__PURE__ */ new Map();
|
|
3191
|
+
for (const members of siblings.values()) {
|
|
3192
|
+
members.sort((a, b) => a.label.localeCompare(b.label) || a.id.localeCompare(b.id));
|
|
3193
|
+
for (const [position, member] of members.entries()) {
|
|
3194
|
+
if (position === 0 && fresh) continue;
|
|
3195
|
+
positions.set(member.group, position);
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
await applyByGroup(db, "sort_order", positions);
|
|
3199
|
+
}
|
|
3200
|
+
/**
|
|
3201
|
+
* Set one column per translation_group, chunked to stay inside the parameter
|
|
3202
|
+
* ceiling.
|
|
3203
|
+
*/
|
|
3204
|
+
async function applyByGroup(db, column, values) {
|
|
3205
|
+
const entries = [...values];
|
|
3206
|
+
const valueType = column === "sort_order" ? sql`INTEGER` : sql`TEXT`;
|
|
3207
|
+
for (let index = 0; index < entries.length; index += GROUPS_PER_UPDATE) {
|
|
3208
|
+
const chunk = entries.slice(index, index + GROUPS_PER_UPDATE);
|
|
3209
|
+
const arms = sql.join(chunk.map(([group, value]) => sql`WHEN ${group} THEN CAST(${value} AS ${valueType})`), sql` `);
|
|
3210
|
+
const keys = sql.join(chunk.map(([group]) => sql`${group}`));
|
|
3211
|
+
await sql`
|
|
3212
|
+
UPDATE taxonomies
|
|
3213
|
+
SET ${sql.ref(column)} = CASE translation_group ${arms} END
|
|
3214
|
+
WHERE translation_group IN (${keys})
|
|
3215
|
+
`.execute(db);
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
async function down$14(db) {
|
|
3219
|
+
if (await columnExists(db, "taxonomies", "sort_order")) await db.schema.alterTable("taxonomies").dropColumn("sort_order").execute();
|
|
3220
|
+
}
|
|
3221
|
+
|
|
3222
|
+
//#endregion
|
|
3223
|
+
//#region src/database/migrations/057_collection_hidden.ts
|
|
3224
|
+
var _057_collection_hidden_exports = /* @__PURE__ */ __exportAll({
|
|
3225
|
+
down: () => down$13,
|
|
3226
|
+
up: () => up$13
|
|
3227
|
+
});
|
|
3228
|
+
/**
|
|
3229
|
+
* Migration: hide a collection from the admin sidebar.
|
|
3230
|
+
*
|
|
3231
|
+
* Adds `hidden` to `_emdash_collections`. A hidden collection stays fully
|
|
3232
|
+
* functional (REST API, MCP, plugin hooks, direct `/content/:collection`
|
|
3233
|
+
* URLs) — only its auto-generated sidebar entry is omitted, so plugins that
|
|
3234
|
+
* own a collection end to end can steer editors to their own admin UI.
|
|
3235
|
+
*/
|
|
3236
|
+
async function up$13(db) {
|
|
3237
|
+
if (!await columnExists(db, "_emdash_collections", "hidden")) await db.schema.alterTable("_emdash_collections").addColumn("hidden", "integer", (col) => col.notNull().defaultTo(0)).execute();
|
|
3238
|
+
}
|
|
3239
|
+
async function down$13(db) {
|
|
3240
|
+
await db.schema.alterTable("_emdash_collections").dropColumn("hidden").execute();
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3243
|
+
//#endregion
|
|
3244
|
+
//#region src/database/migrations/058_collection_sort_order.ts
|
|
3245
|
+
var _058_collection_sort_order_exports = /* @__PURE__ */ __exportAll({
|
|
3246
|
+
down: () => down$12,
|
|
3247
|
+
up: () => up$12
|
|
3248
|
+
});
|
|
3249
|
+
/**
|
|
3250
|
+
* Migration: explicit collection order in the admin sidebar.
|
|
3251
|
+
*
|
|
3252
|
+
* Adds `sort_order` to `_emdash_collections`. A NULL `sort_order` means no
|
|
3253
|
+
* explicit position: those collections sort after the ordered ones, keeping
|
|
3254
|
+
* the alphabetical-by-slug order.
|
|
3255
|
+
*/
|
|
3256
|
+
async function up$12(db) {
|
|
3257
|
+
if (!await columnExists(db, "_emdash_collections", "sort_order")) await db.schema.alterTable("_emdash_collections").addColumn("sort_order", "integer").execute();
|
|
3258
|
+
}
|
|
3259
|
+
async function down$12(db) {
|
|
3260
|
+
await db.schema.alterTable("_emdash_collections").dropColumn("sort_order").execute();
|
|
3261
|
+
}
|
|
3262
|
+
|
|
3263
|
+
//#endregion
|
|
3264
|
+
//#region src/database/migrations/059_revision_prune_queue.ts
|
|
3265
|
+
var _059_revision_prune_queue_exports = /* @__PURE__ */ __exportAll({
|
|
3266
|
+
down: () => down$11,
|
|
3267
|
+
up: () => up$11
|
|
3268
|
+
});
|
|
3269
|
+
const REVISION_KEEP_COUNT = 50;
|
|
3270
|
+
async function up$11(db) {
|
|
3271
|
+
await db.schema.createTable("_emdash_revision_prune_queue").ifNotExists().addColumn("collection", "text", (column) => column.notNull()).addColumn("entry_id", "text", (column) => column.notNull()).addColumn("revision_id", "text", (column) => column.notNull()).addPrimaryKeyConstraint("revision_prune_queue_pk", ["collection", "entry_id"]).execute();
|
|
3272
|
+
await db.schema.createIndex("idx_revision_prune_queue_revision_id").ifNotExists().on("_emdash_revision_prune_queue").column("revision_id").execute();
|
|
3273
|
+
await sql`
|
|
3274
|
+
INSERT INTO _emdash_revision_prune_queue (collection, entry_id, revision_id)
|
|
3275
|
+
SELECT collection, entry_id, MAX(id)
|
|
3276
|
+
FROM revisions
|
|
3277
|
+
WHERE true
|
|
3278
|
+
GROUP BY collection, entry_id
|
|
3279
|
+
HAVING COUNT(*) > ${REVISION_KEEP_COUNT}
|
|
3280
|
+
ON CONFLICT (collection, entry_id)
|
|
3281
|
+
DO UPDATE SET revision_id = excluded.revision_id
|
|
3282
|
+
`.execute(db);
|
|
3283
|
+
}
|
|
3284
|
+
async function down$11(db) {
|
|
3285
|
+
await db.schema.dropTable("_emdash_revision_prune_queue").ifExists().execute();
|
|
3286
|
+
}
|
|
3287
|
+
|
|
3288
|
+
//#endregion
|
|
3289
|
+
//#region src/database/migrations/060_collection_admin_config.ts
|
|
3290
|
+
var _060_collection_admin_config_exports = /* @__PURE__ */ __exportAll({
|
|
3291
|
+
down: () => down$10,
|
|
3292
|
+
up: () => up$10
|
|
3293
|
+
});
|
|
3294
|
+
/** Persist collection-level admin presentation options. */
|
|
3295
|
+
async function up$10(db) {
|
|
3296
|
+
if (!await columnExists(db, "_emdash_collections", "admin_config")) await db.schema.alterTable("_emdash_collections").addColumn("admin_config", "text").execute();
|
|
3297
|
+
}
|
|
3298
|
+
async function down$10(db) {
|
|
3299
|
+
if (await columnExists(db, "_emdash_collections", "admin_config")) await db.schema.alterTable("_emdash_collections").dropColumn("admin_config").execute();
|
|
3300
|
+
}
|
|
3301
|
+
|
|
3302
|
+
//#endregion
|
|
3303
|
+
//#region src/database/migrations/061_media_usage_cleanup.ts
|
|
3304
|
+
var _061_media_usage_cleanup_exports = /* @__PURE__ */ __exportAll({
|
|
3305
|
+
down: () => down$9,
|
|
3306
|
+
up: () => up$9
|
|
3307
|
+
});
|
|
3308
|
+
const CLEANUP_TASK_KEY = "projection_gc";
|
|
3309
|
+
const INITIAL_ELIGIBLE_AT = "1970-01-01T00:00:00.000Z";
|
|
3310
|
+
async function up$9(db) {
|
|
3311
|
+
await db.schema.createIndex("idx__emdash_media_usage_cleanup_scan").ifNotExists().on("_emdash_media_usage").columns([
|
|
3312
|
+
"created_at",
|
|
3313
|
+
"id",
|
|
3314
|
+
"source_key",
|
|
3315
|
+
"generation"
|
|
3316
|
+
]).execute();
|
|
3317
|
+
await db.schema.createTable("_emdash_media_usage_cleanup").ifNotExists().addColumn("task_key", "text", (c) => c.primaryKey()).addColumn("lease_token", "text").addColumn("lease_expires_at", "text").addColumn("next_eligible_at", "text", (c) => c.notNull()).addColumn("cursor_created_at", "text").addColumn("cursor_id", "text").addColumn("scan_before_at", "text").addColumn("consecutive_failures", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_started_at", "text").addColumn("last_completed_at", "text").addColumn("last_candidate_count", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_deleted_orphans", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_deleted_stale", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_deleted_abandoned", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_deleted_write_leases", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_backlog_lower_bound", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_scan_has_more", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_duration_ms", "integer", (c) => c.notNull().defaultTo(0)).addColumn("last_error_code", "text").addColumn("updated_at", "text", (c) => c.notNull().defaultTo(currentTimestamp(db))).execute();
|
|
3318
|
+
await db.schema.createTable("_emdash_media_usage_generation_writes").ifNotExists().addColumn("source_key", "text", (c) => c.notNull()).addColumn("generation", "text", (c) => c.notNull()).addColumn("lease_token", "text", (c) => c.primaryKey()).addColumn("expires_at", "text", (c) => c.notNull()).addColumn("created_at", "text", (c) => c.notNull().defaultTo(currentTimestamp(db))).addUniqueConstraint("_emdash_media_usage_generation_writes_source_generation", ["source_key", "generation"]).execute();
|
|
3319
|
+
await db.schema.createIndex("idx__emdash_media_usage_generation_writes_expiry").ifNotExists().on("_emdash_media_usage_generation_writes").columns(["expires_at", "lease_token"]).execute();
|
|
3320
|
+
await sql`
|
|
3321
|
+
INSERT INTO _emdash_media_usage_cleanup (task_key, next_eligible_at)
|
|
3322
|
+
VALUES (${CLEANUP_TASK_KEY}, ${INITIAL_ELIGIBLE_AT})
|
|
3323
|
+
ON CONFLICT (task_key) DO NOTHING
|
|
3324
|
+
`.execute(db);
|
|
3325
|
+
}
|
|
3326
|
+
async function down$9(db) {
|
|
3327
|
+
await db.schema.dropIndex("idx__emdash_media_usage_generation_writes_expiry").ifExists().execute();
|
|
3328
|
+
await db.schema.dropTable("_emdash_media_usage_generation_writes").ifExists().execute();
|
|
3329
|
+
await db.schema.dropTable("_emdash_media_usage_cleanup").ifExists().execute();
|
|
3330
|
+
await db.schema.dropIndex("idx__emdash_media_usage_cleanup_scan").ifExists().execute();
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3333
|
+
//#endregion
|
|
3334
|
+
//#region src/database/migrations/062_media_usage_cleanup_fence.ts
|
|
3335
|
+
var _062_media_usage_cleanup_fence_exports = /* @__PURE__ */ __exportAll({
|
|
3336
|
+
down: () => down$8,
|
|
3337
|
+
up: () => up$8
|
|
3338
|
+
});
|
|
3339
|
+
async function up$8(db) {
|
|
3340
|
+
if (!await columnExists(db, "_emdash_media_usage", "cleanup_lease_token")) await db.schema.alterTable("_emdash_media_usage").addColumn("cleanup_lease_token", "text").execute();
|
|
3341
|
+
await db.schema.createTable("_emdash_media_usage_cleanup_fence").ifNotExists().addColumn("task_key", "text", (c) => c.primaryKey()).addColumn("generation_floor", "text", (c) => c.notNull()).addColumn("updated_at", "text", (c) => c.notNull().defaultTo(currentTimestamp(db))).execute();
|
|
3342
|
+
if (isPostgres(db)) {
|
|
3343
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_record_cleanup_fence ON _emdash_media_usage").execute(db);
|
|
3344
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_fence_source_generation_update ON _emdash_media_usage_sources").execute(db);
|
|
3345
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_fence_source_generation_insert ON _emdash_media_usage_sources").execute(db);
|
|
3346
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_lock_cleanup_update ON _emdash_media_usage_sources").execute(db);
|
|
3347
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_lock_cleanup_insert ON _emdash_media_usage_sources").execute(db);
|
|
3348
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_lock_cleanup_delete ON _emdash_media_usage_sources").execute(db);
|
|
3349
|
+
await sql.raw(`
|
|
3350
|
+
CREATE OR REPLACE FUNCTION emdash_media_usage_lock_cleanup()
|
|
3351
|
+
RETURNS trigger
|
|
3352
|
+
LANGUAGE plpgsql
|
|
3353
|
+
AS $$
|
|
3354
|
+
BEGIN
|
|
3355
|
+
PERFORM 1
|
|
3356
|
+
FROM _emdash_media_usage_cleanup AS cleanup
|
|
3357
|
+
WHERE cleanup.task_key = 'projection_gc'
|
|
3358
|
+
FOR SHARE;
|
|
3359
|
+
RETURN NULL;
|
|
3360
|
+
END;
|
|
3361
|
+
$$
|
|
3362
|
+
`).execute(db);
|
|
3363
|
+
await sql.raw(`
|
|
3364
|
+
CREATE OR REPLACE FUNCTION emdash_media_usage_fence_source_generation()
|
|
3365
|
+
RETURNS trigger
|
|
3366
|
+
LANGUAGE plpgsql
|
|
3367
|
+
AS $$
|
|
3368
|
+
BEGIN
|
|
3369
|
+
IF EXISTS (
|
|
3370
|
+
SELECT 1
|
|
3371
|
+
FROM _emdash_media_usage_cleanup_fence AS fence
|
|
3372
|
+
WHERE fence.task_key = 'projection_gc'
|
|
3373
|
+
AND NEW.current_generation <= fence.generation_floor
|
|
3374
|
+
) AND NOT EXISTS (
|
|
3375
|
+
SELECT 1
|
|
3376
|
+
FROM _emdash_media_usage_generation_writes AS writer
|
|
3377
|
+
WHERE writer.source_key = NEW.source_key
|
|
3378
|
+
AND writer.generation = NEW.current_generation
|
|
3379
|
+
AND writer.expires_at::timestamptz > clock_timestamp()
|
|
3380
|
+
) THEN
|
|
3381
|
+
RETURN NULL;
|
|
3382
|
+
END IF;
|
|
3383
|
+
RETURN NEW;
|
|
3384
|
+
END;
|
|
3385
|
+
$$
|
|
3386
|
+
`).execute(db);
|
|
3387
|
+
await sql.raw(`
|
|
3388
|
+
CREATE TRIGGER emdash_media_usage_lock_cleanup_insert
|
|
3389
|
+
BEFORE INSERT ON _emdash_media_usage_sources
|
|
3390
|
+
FOR EACH STATEMENT
|
|
3391
|
+
EXECUTE FUNCTION emdash_media_usage_lock_cleanup()
|
|
3392
|
+
`).execute(db);
|
|
3393
|
+
await sql.raw(`
|
|
3394
|
+
CREATE TRIGGER emdash_media_usage_lock_cleanup_update
|
|
3395
|
+
BEFORE UPDATE OF current_generation ON _emdash_media_usage_sources
|
|
3396
|
+
FOR EACH STATEMENT
|
|
3397
|
+
EXECUTE FUNCTION emdash_media_usage_lock_cleanup()
|
|
3398
|
+
`).execute(db);
|
|
3399
|
+
await sql.raw(`
|
|
3400
|
+
CREATE TRIGGER emdash_media_usage_lock_cleanup_delete
|
|
3401
|
+
BEFORE DELETE ON _emdash_media_usage_sources
|
|
3402
|
+
FOR EACH STATEMENT
|
|
3403
|
+
EXECUTE FUNCTION emdash_media_usage_lock_cleanup()
|
|
3404
|
+
`).execute(db);
|
|
3405
|
+
await sql.raw(`
|
|
3406
|
+
CREATE OR REPLACE FUNCTION emdash_media_usage_record_cleanup_fence()
|
|
3407
|
+
RETURNS trigger
|
|
3408
|
+
LANGUAGE plpgsql
|
|
3409
|
+
AS $$
|
|
3410
|
+
BEGIN
|
|
3411
|
+
IF OLD.cleanup_lease_token IS NOT NULL AND EXISTS (
|
|
3412
|
+
SELECT 1
|
|
3413
|
+
FROM _emdash_media_usage_cleanup AS cleanup
|
|
3414
|
+
WHERE cleanup.task_key = 'projection_gc'
|
|
3415
|
+
AND cleanup.lease_token = OLD.cleanup_lease_token
|
|
3416
|
+
) THEN
|
|
3417
|
+
INSERT INTO _emdash_media_usage_cleanup_fence (
|
|
3418
|
+
task_key,
|
|
3419
|
+
generation_floor,
|
|
3420
|
+
updated_at
|
|
3421
|
+
)
|
|
3422
|
+
VALUES ('projection_gc', OLD.generation, CURRENT_TIMESTAMP::text)
|
|
3423
|
+
ON CONFLICT (task_key) DO UPDATE SET
|
|
3424
|
+
generation_floor = CASE
|
|
3425
|
+
WHEN EXCLUDED.generation_floor > _emdash_media_usage_cleanup_fence.generation_floor
|
|
3426
|
+
THEN EXCLUDED.generation_floor
|
|
3427
|
+
ELSE _emdash_media_usage_cleanup_fence.generation_floor
|
|
3428
|
+
END,
|
|
3429
|
+
updated_at = EXCLUDED.updated_at;
|
|
3430
|
+
END IF;
|
|
3431
|
+
RETURN OLD;
|
|
3432
|
+
END;
|
|
3433
|
+
$$
|
|
3434
|
+
`).execute(db);
|
|
3435
|
+
await sql.raw(`
|
|
3436
|
+
CREATE TRIGGER emdash_media_usage_fence_source_generation_insert
|
|
3437
|
+
BEFORE INSERT ON _emdash_media_usage_sources
|
|
3438
|
+
FOR EACH ROW
|
|
3439
|
+
EXECUTE FUNCTION emdash_media_usage_fence_source_generation()
|
|
3440
|
+
`).execute(db);
|
|
3441
|
+
await sql.raw(`
|
|
3442
|
+
CREATE TRIGGER emdash_media_usage_fence_source_generation_update
|
|
3443
|
+
BEFORE UPDATE OF current_generation ON _emdash_media_usage_sources
|
|
3444
|
+
FOR EACH ROW
|
|
3445
|
+
EXECUTE FUNCTION emdash_media_usage_fence_source_generation()
|
|
3446
|
+
`).execute(db);
|
|
3447
|
+
await sql.raw(`
|
|
3448
|
+
CREATE TRIGGER emdash_media_usage_record_cleanup_fence
|
|
3449
|
+
BEFORE DELETE ON _emdash_media_usage
|
|
3450
|
+
FOR EACH ROW
|
|
3451
|
+
WHEN (OLD.cleanup_lease_token IS NOT NULL)
|
|
3452
|
+
EXECUTE FUNCTION emdash_media_usage_record_cleanup_fence()
|
|
3453
|
+
`).execute(db);
|
|
3454
|
+
return;
|
|
3455
|
+
}
|
|
3456
|
+
await sql.raw(`
|
|
3457
|
+
CREATE TRIGGER IF NOT EXISTS emdash_media_usage_fence_source_generation_insert
|
|
3458
|
+
BEFORE INSERT ON _emdash_media_usage_sources
|
|
3459
|
+
WHEN EXISTS (
|
|
3460
|
+
SELECT 1
|
|
3461
|
+
FROM _emdash_media_usage_cleanup_fence AS fence
|
|
3462
|
+
WHERE fence.task_key = 'projection_gc'
|
|
3463
|
+
AND NEW.current_generation <= fence.generation_floor
|
|
3464
|
+
) AND NOT EXISTS (
|
|
3465
|
+
SELECT 1
|
|
3466
|
+
FROM _emdash_media_usage_generation_writes AS writer
|
|
3467
|
+
WHERE writer.source_key = NEW.source_key
|
|
3468
|
+
AND writer.generation = NEW.current_generation
|
|
3469
|
+
AND writer.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
3470
|
+
)
|
|
3471
|
+
BEGIN
|
|
3472
|
+
SELECT RAISE(IGNORE);
|
|
3473
|
+
END
|
|
3474
|
+
`).execute(db);
|
|
3475
|
+
await sql.raw(`
|
|
3476
|
+
CREATE TRIGGER IF NOT EXISTS emdash_media_usage_fence_source_generation_update
|
|
3477
|
+
BEFORE UPDATE OF current_generation ON _emdash_media_usage_sources
|
|
3478
|
+
WHEN NEW.current_generation <> OLD.current_generation
|
|
3479
|
+
AND EXISTS (
|
|
3480
|
+
SELECT 1
|
|
3481
|
+
FROM _emdash_media_usage_cleanup_fence AS fence
|
|
3482
|
+
WHERE fence.task_key = 'projection_gc'
|
|
3483
|
+
AND NEW.current_generation <= fence.generation_floor
|
|
3484
|
+
) AND NOT EXISTS (
|
|
3485
|
+
SELECT 1
|
|
3486
|
+
FROM _emdash_media_usage_generation_writes AS writer
|
|
3487
|
+
WHERE writer.source_key = NEW.source_key
|
|
3488
|
+
AND writer.generation = NEW.current_generation
|
|
3489
|
+
AND writer.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
3490
|
+
)
|
|
3491
|
+
BEGIN
|
|
3492
|
+
SELECT RAISE(IGNORE);
|
|
3493
|
+
END
|
|
3494
|
+
`).execute(db);
|
|
3495
|
+
await sql.raw(`
|
|
3496
|
+
CREATE TRIGGER IF NOT EXISTS emdash_media_usage_record_cleanup_fence
|
|
3497
|
+
BEFORE DELETE ON _emdash_media_usage
|
|
3498
|
+
WHEN OLD.cleanup_lease_token IS NOT NULL AND EXISTS (
|
|
3499
|
+
SELECT 1
|
|
3500
|
+
FROM _emdash_media_usage_cleanup AS cleanup
|
|
3501
|
+
WHERE cleanup.task_key = 'projection_gc'
|
|
3502
|
+
AND cleanup.lease_token = OLD.cleanup_lease_token
|
|
3503
|
+
)
|
|
3504
|
+
BEGIN
|
|
3505
|
+
INSERT INTO _emdash_media_usage_cleanup_fence (
|
|
3506
|
+
task_key,
|
|
3507
|
+
generation_floor,
|
|
3508
|
+
updated_at
|
|
3509
|
+
)
|
|
3510
|
+
VALUES ('projection_gc', OLD.generation, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
3511
|
+
ON CONFLICT (task_key) DO UPDATE SET
|
|
3512
|
+
generation_floor = CASE
|
|
3513
|
+
WHEN excluded.generation_floor > _emdash_media_usage_cleanup_fence.generation_floor
|
|
3514
|
+
THEN excluded.generation_floor
|
|
3515
|
+
ELSE _emdash_media_usage_cleanup_fence.generation_floor
|
|
3516
|
+
END,
|
|
3517
|
+
updated_at = excluded.updated_at;
|
|
3518
|
+
END
|
|
3519
|
+
`).execute(db);
|
|
3520
|
+
}
|
|
3521
|
+
async function down$8(db) {
|
|
3522
|
+
if (isPostgres(db)) {
|
|
3523
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_record_cleanup_fence ON _emdash_media_usage").execute(db);
|
|
3524
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_fence_source_generation_update ON _emdash_media_usage_sources").execute(db);
|
|
3525
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_fence_source_generation_insert ON _emdash_media_usage_sources").execute(db);
|
|
3526
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_lock_cleanup_update ON _emdash_media_usage_sources").execute(db);
|
|
3527
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_lock_cleanup_insert ON _emdash_media_usage_sources").execute(db);
|
|
3528
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_lock_cleanup_delete ON _emdash_media_usage_sources").execute(db);
|
|
3529
|
+
await sql.raw("DROP FUNCTION IF EXISTS emdash_media_usage_record_cleanup_fence()").execute(db);
|
|
3530
|
+
await sql.raw("DROP FUNCTION IF EXISTS emdash_media_usage_fence_source_generation()").execute(db);
|
|
3531
|
+
await sql.raw("DROP FUNCTION IF EXISTS emdash_media_usage_lock_cleanup()").execute(db);
|
|
3532
|
+
} else {
|
|
3533
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_record_cleanup_fence").execute(db);
|
|
3534
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_fence_source_generation_update").execute(db);
|
|
3535
|
+
await sql.raw("DROP TRIGGER IF EXISTS emdash_media_usage_fence_source_generation_insert").execute(db);
|
|
3536
|
+
}
|
|
3537
|
+
await db.schema.dropTable("_emdash_media_usage_cleanup_fence").ifExists().execute();
|
|
3538
|
+
if (await columnExists(db, "_emdash_media_usage", "cleanup_lease_token")) await db.schema.alterTable("_emdash_media_usage").dropColumn("cleanup_lease_token").execute();
|
|
3539
|
+
}
|
|
3540
|
+
|
|
3541
|
+
//#endregion
|
|
3542
|
+
//#region src/database/migrations/063_media_usage_incremental_work.ts
|
|
3543
|
+
var _063_media_usage_incremental_work_exports = /* @__PURE__ */ __exportAll({
|
|
3544
|
+
down: () => down$7,
|
|
3545
|
+
up: () => up$7
|
|
3546
|
+
});
|
|
3547
|
+
const ACTIVATION_KEY$1 = "incremental_capture";
|
|
3548
|
+
const CONTENT_ADAPTER_ID = "content-media";
|
|
3549
|
+
const COLLECTION_SCOPE = "collection";
|
|
3550
|
+
const DUPLICATE_COLUMN_RE = /(?:duplicate column|column .* already exists|already exists.*column)/i;
|
|
3551
|
+
async function up$7(db) {
|
|
3552
|
+
await db.schema.createTable("_emdash_media_usage_activation").ifNotExists().addColumn("task_key", "text", (column) => column.primaryKey()).addColumn("state", "text", (column) => column.notNull().defaultTo("expanded")).addColumn("runtime_generation", "integer", (column) => column.notNull().defaultTo(1)).addColumn("collection_cursor", "text").addColumn("drain_confirmed_at", "text").addColumn("lease_token", "text").addColumn("lease_expires_at", "text").addColumn("attempt_count", "integer", (column) => column.notNull().defaultTo(0)).addColumn("last_attempted_at", "text").addColumn("last_error_code", "text").addColumn("activated_at", "text").addColumn("created_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp$2(db))).addColumn("updated_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp$2(db))).execute();
|
|
3553
|
+
await sql`
|
|
3554
|
+
INSERT INTO _emdash_media_usage_activation (task_key, state)
|
|
3555
|
+
VALUES (${ACTIVATION_KEY$1}, 'expanded')
|
|
3556
|
+
ON CONFLICT (task_key) DO NOTHING
|
|
3557
|
+
`.execute(db);
|
|
3558
|
+
await db.schema.createTable("_emdash_media_usage_work").ifNotExists().addColumn("collection_id", "text", (column) => column.notNull()).addColumn("collection_slug", "text", (column) => column.notNull()).addColumn("content_id", "text", (column) => column.notNull()).addColumn("change_epoch", "bigint", (column) => column.notNull()).addColumn("work_version", "bigint", (column) => column.notNull().defaultTo(1)).addColumn("state", "text", (column) => column.notNull().defaultTo("pending")).addColumn("attempt_count", "integer", (column) => column.notNull().defaultTo(0)).addColumn("next_attempt_at", "text", (column) => column.notNull()).addColumn("lease_token", "text").addColumn("lease_expires_at", "text").addColumn("last_attempted_at", "text").addColumn("last_error_code", "text").addColumn("created_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp$2(db))).addColumn("updated_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp$2(db))).addPrimaryKeyConstraint("_emdash_media_usage_work_pk", ["collection_id", "content_id"]).execute();
|
|
3559
|
+
await addStatusColumns(db);
|
|
3560
|
+
await addSourceColumns(db);
|
|
3561
|
+
await db.schema.createIndex("idx__emdash_media_usage_work_due").ifNotExists().on("_emdash_media_usage_work").columns([
|
|
3562
|
+
"state",
|
|
3563
|
+
"next_attempt_at",
|
|
3564
|
+
"updated_at",
|
|
3565
|
+
"collection_id",
|
|
3566
|
+
"content_id"
|
|
3567
|
+
]).execute();
|
|
3568
|
+
await db.schema.createIndex("idx__emdash_media_usage_work_lease").ifNotExists().on("_emdash_media_usage_work").columns([
|
|
3569
|
+
"state",
|
|
3570
|
+
"lease_expires_at",
|
|
3571
|
+
"collection_id",
|
|
3572
|
+
"content_id"
|
|
3573
|
+
]).execute();
|
|
3574
|
+
await db.schema.createIndex("idx__emdash_media_usage_work_operator").ifNotExists().on("_emdash_media_usage_work").columns([
|
|
3575
|
+
"collection_id",
|
|
3576
|
+
"state",
|
|
3577
|
+
"updated_at",
|
|
3578
|
+
"content_id"
|
|
3579
|
+
]).execute();
|
|
3580
|
+
await db.schema.createIndex("idx__emdash_media_usage_status_collection").ifNotExists().unique().on("_emdash_media_usage_index_status").columns([
|
|
3581
|
+
"adapter_id",
|
|
3582
|
+
"scope_type",
|
|
3583
|
+
"collection_id"
|
|
3584
|
+
]).execute();
|
|
3585
|
+
await db.schema.createIndex("idx__emdash_media_usage_sources_identity").ifNotExists().on("_emdash_media_usage_sources").columns([
|
|
3586
|
+
"source_type",
|
|
3587
|
+
"collection_id",
|
|
3588
|
+
"content_id",
|
|
3589
|
+
"source_variant"
|
|
3590
|
+
]).execute();
|
|
3591
|
+
await sql`
|
|
3592
|
+
DELETE FROM _emdash_media_usage_index_status
|
|
3593
|
+
WHERE adapter_id = ${CONTENT_ADAPTER_ID}
|
|
3594
|
+
AND scope_type = ${COLLECTION_SCOPE}
|
|
3595
|
+
AND (
|
|
3596
|
+
(
|
|
3597
|
+
collection_id IS NULL
|
|
3598
|
+
AND NOT EXISTS (
|
|
3599
|
+
SELECT 1
|
|
3600
|
+
FROM _emdash_collections AS collection
|
|
3601
|
+
WHERE collection.slug = _emdash_media_usage_index_status.scope_key
|
|
3602
|
+
)
|
|
3603
|
+
)
|
|
3604
|
+
OR (
|
|
3605
|
+
collection_id IS NOT NULL
|
|
3606
|
+
AND capture_state = 'installing'
|
|
3607
|
+
AND EXISTS (
|
|
3608
|
+
SELECT 1
|
|
3609
|
+
FROM _emdash_media_usage_activation AS activation
|
|
3610
|
+
WHERE activation.task_key = ${ACTIVATION_KEY$1}
|
|
3611
|
+
AND activation.state = 'expanded'
|
|
3612
|
+
)
|
|
3613
|
+
AND NOT EXISTS (
|
|
3614
|
+
SELECT 1
|
|
3615
|
+
FROM _emdash_collections AS collection
|
|
3616
|
+
WHERE collection.id = _emdash_media_usage_index_status.collection_id
|
|
3617
|
+
AND collection.slug = _emdash_media_usage_index_status.scope_key
|
|
3618
|
+
)
|
|
3619
|
+
)
|
|
3620
|
+
)
|
|
3621
|
+
`.execute(db);
|
|
3622
|
+
await sql`
|
|
3623
|
+
UPDATE _emdash_media_usage_index_status
|
|
3624
|
+
SET collection_id = (
|
|
3625
|
+
SELECT collection.id
|
|
3626
|
+
FROM _emdash_collections AS collection
|
|
3627
|
+
WHERE collection.slug = _emdash_media_usage_index_status.scope_key
|
|
3628
|
+
),
|
|
3629
|
+
reconciliation_required = 1,
|
|
3630
|
+
capture_state = COALESCE(capture_state, 'installing')
|
|
3631
|
+
WHERE adapter_id = ${CONTENT_ADAPTER_ID}
|
|
3632
|
+
AND scope_type = ${COLLECTION_SCOPE}
|
|
3633
|
+
AND (
|
|
3634
|
+
collection_id IS NULL
|
|
3635
|
+
OR capture_state IS NULL
|
|
3636
|
+
)
|
|
3637
|
+
AND EXISTS (
|
|
3638
|
+
SELECT 1
|
|
3639
|
+
FROM _emdash_collections AS collection
|
|
3640
|
+
WHERE collection.id = COALESCE(
|
|
3641
|
+
_emdash_media_usage_index_status.collection_id,
|
|
3642
|
+
collection.id
|
|
3643
|
+
)
|
|
3644
|
+
AND collection.slug = _emdash_media_usage_index_status.scope_key
|
|
3645
|
+
)
|
|
3646
|
+
`.execute(db);
|
|
3647
|
+
}
|
|
3648
|
+
async function down$7(db) {
|
|
3649
|
+
await assertRollbackIsEmptyAndInactive(db);
|
|
3650
|
+
await db.schema.dropIndex("idx__emdash_media_usage_sources_identity").ifExists().execute();
|
|
3651
|
+
await db.schema.dropIndex("idx__emdash_media_usage_status_collection").ifExists().execute();
|
|
3652
|
+
await db.schema.dropIndex("idx__emdash_media_usage_work_operator").ifExists().execute();
|
|
3653
|
+
await db.schema.dropIndex("idx__emdash_media_usage_work_lease").ifExists().execute();
|
|
3654
|
+
await db.schema.dropIndex("idx__emdash_media_usage_work_due").ifExists().execute();
|
|
3655
|
+
await db.schema.dropTable("_emdash_media_usage_work").ifExists().execute();
|
|
3656
|
+
await db.schema.dropTable("_emdash_media_usage_activation").ifExists().execute();
|
|
3657
|
+
if (isPostgres(db)) await sql`DROP FUNCTION IF EXISTS emdash_media_usage_capture_work()`.execute(db);
|
|
3658
|
+
for (const columnName of ["identity_version", "collection_id"]) if (await columnExists(db, "_emdash_media_usage_sources", columnName)) await db.schema.alterTable("_emdash_media_usage_sources").dropColumn(columnName).execute();
|
|
3659
|
+
for (const columnName of [
|
|
3660
|
+
"capture_state",
|
|
3661
|
+
"last_incremental_success_at",
|
|
3662
|
+
"reconciliation_required",
|
|
3663
|
+
"change_epoch",
|
|
3664
|
+
"collection_id"
|
|
3665
|
+
]) if (await columnExists(db, "_emdash_media_usage_index_status", columnName)) await db.schema.alterTable("_emdash_media_usage_index_status").dropColumn(columnName).execute();
|
|
3666
|
+
}
|
|
3667
|
+
async function addStatusColumns(db) {
|
|
3668
|
+
await addColumnIfMissing(db, "_emdash_media_usage_index_status", "collection_id", () => db.schema.alterTable("_emdash_media_usage_index_status").addColumn("collection_id", "text").execute());
|
|
3669
|
+
await addColumnIfMissing(db, "_emdash_media_usage_index_status", "change_epoch", () => db.schema.alterTable("_emdash_media_usage_index_status").addColumn("change_epoch", "bigint", (column) => column.notNull().defaultTo(0)).execute());
|
|
3670
|
+
await addColumnIfMissing(db, "_emdash_media_usage_index_status", "reconciliation_required", () => db.schema.alterTable("_emdash_media_usage_index_status").addColumn("reconciliation_required", "integer", (column) => column.notNull().defaultTo(0)).execute());
|
|
3671
|
+
await addStatusTextColumn(db, "last_incremental_success_at");
|
|
3672
|
+
await addStatusTextColumn(db, "capture_state");
|
|
3673
|
+
}
|
|
3674
|
+
async function assertRollbackIsEmptyAndInactive(db) {
|
|
3675
|
+
if (await hasCaptureTriggers(db)) throw new Error("Cannot roll back media usage capture while capture triggers are installed");
|
|
3676
|
+
if (await tableExists(db, "_emdash_media_usage_activation")) {
|
|
3677
|
+
const activation = await sql`
|
|
3678
|
+
SELECT state
|
|
3679
|
+
FROM _emdash_media_usage_activation
|
|
3680
|
+
WHERE task_key = ${ACTIVATION_KEY$1}
|
|
3681
|
+
`.execute(db);
|
|
3682
|
+
if (activation.rows[0] && activation.rows[0].state !== "expanded") throw new Error("Cannot roll back media usage capture after activation has started");
|
|
3683
|
+
}
|
|
3684
|
+
if (await tableExists(db, "_emdash_media_usage_work")) {
|
|
3685
|
+
if ((await sql`
|
|
3686
|
+
SELECT 1 AS present FROM _emdash_media_usage_work LIMIT 1
|
|
3687
|
+
`.execute(db)).rows.length > 0) throw new Error("Cannot roll back media usage capture while durable work exists");
|
|
3688
|
+
}
|
|
3689
|
+
const sourceHasCollectionId = await columnExists(db, "_emdash_media_usage_sources", "collection_id");
|
|
3690
|
+
const sourceHasIdentityVersion = await columnExists(db, "_emdash_media_usage_sources", "identity_version");
|
|
3691
|
+
if (sourceHasCollectionId || sourceHasIdentityVersion) {
|
|
3692
|
+
if ((sourceHasCollectionId ? await sql`
|
|
3693
|
+
SELECT 1 AS present
|
|
3694
|
+
FROM _emdash_media_usage_sources
|
|
3695
|
+
WHERE collection_id IS NOT NULL
|
|
3696
|
+
LIMIT 1
|
|
3697
|
+
`.execute(db) : await sql`
|
|
3698
|
+
SELECT 1 AS present
|
|
3699
|
+
FROM _emdash_media_usage_sources
|
|
3700
|
+
WHERE identity_version IS NOT NULL
|
|
3701
|
+
LIMIT 1
|
|
3702
|
+
`.execute(db)).rows.length > 0) throw new Error("Cannot roll back media usage capture after canonical sources exist");
|
|
3703
|
+
if (sourceHasCollectionId && sourceHasIdentityVersion) {
|
|
3704
|
+
if ((await sql`
|
|
3705
|
+
SELECT 1 AS present
|
|
3706
|
+
FROM _emdash_media_usage_sources
|
|
3707
|
+
WHERE identity_version IS NOT NULL
|
|
3708
|
+
LIMIT 1
|
|
3709
|
+
`.execute(db)).rows.length > 0) throw new Error("Cannot roll back media usage capture after canonical sources exist");
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
if (await columnExists(db, "_emdash_media_usage_index_status", "capture_state")) {
|
|
3713
|
+
if ((await sql`
|
|
3714
|
+
SELECT 1 AS present FROM _emdash_media_usage_index_status
|
|
3715
|
+
WHERE capture_state IN ('active', 'deleting') LIMIT 1
|
|
3716
|
+
`.execute(db)).rows.length > 0) throwRollbackLifecycleError();
|
|
3717
|
+
}
|
|
3718
|
+
if (await columnExists(db, "_emdash_media_usage_index_status", "change_epoch")) {
|
|
3719
|
+
if ((await sql`
|
|
3720
|
+
SELECT 1 AS present FROM _emdash_media_usage_index_status
|
|
3721
|
+
WHERE change_epoch <> 0 LIMIT 1
|
|
3722
|
+
`.execute(db)).rows.length > 0) throwRollbackLifecycleError();
|
|
3723
|
+
}
|
|
3724
|
+
if (await columnExists(db, "_emdash_media_usage_index_status", "last_incremental_success_at")) {
|
|
3725
|
+
if ((await sql`
|
|
3726
|
+
SELECT 1 AS present FROM _emdash_media_usage_index_status
|
|
3727
|
+
WHERE last_incremental_success_at IS NOT NULL LIMIT 1
|
|
3728
|
+
`.execute(db)).rows.length > 0) throwRollbackLifecycleError();
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
function throwRollbackLifecycleError() {
|
|
3732
|
+
throw new Error("Cannot roll back media usage capture while capture lifecycle state exists");
|
|
3733
|
+
}
|
|
3734
|
+
async function hasCaptureTriggers(db) {
|
|
3735
|
+
if (isPostgres(db)) return (await sql`
|
|
3736
|
+
SELECT EXISTS (
|
|
3737
|
+
SELECT 1
|
|
3738
|
+
FROM pg_trigger AS trigger
|
|
3739
|
+
INNER JOIN pg_class AS relation ON relation.oid = trigger.tgrelid
|
|
3740
|
+
INNER JOIN pg_namespace AS namespace ON namespace.oid = relation.relnamespace
|
|
3741
|
+
WHERE namespace.nspname = current_schema()
|
|
3742
|
+
AND NOT trigger.tgisinternal
|
|
3743
|
+
AND left(trigger.tgname, 10) = 'emdash_mu_'
|
|
3744
|
+
) AS present
|
|
3745
|
+
`.execute(db)).rows[0]?.present === true;
|
|
3746
|
+
return (await sql`
|
|
3747
|
+
SELECT 1 AS present
|
|
3748
|
+
FROM sqlite_master
|
|
3749
|
+
WHERE type = 'trigger' AND substr(name, 1, 10) = 'emdash_mu_'
|
|
3750
|
+
LIMIT 1
|
|
3751
|
+
`.execute(db)).rows.length > 0;
|
|
3752
|
+
}
|
|
3753
|
+
async function addStatusTextColumn(db, columnName) {
|
|
3754
|
+
await addColumnIfMissing(db, "_emdash_media_usage_index_status", columnName, () => db.schema.alterTable("_emdash_media_usage_index_status").addColumn(columnName, "text").execute());
|
|
3755
|
+
}
|
|
3756
|
+
async function addSourceColumns(db) {
|
|
3757
|
+
await addColumnIfMissing(db, "_emdash_media_usage_sources", "collection_id", () => db.schema.alterTable("_emdash_media_usage_sources").addColumn("collection_id", "text").execute());
|
|
3758
|
+
await addColumnIfMissing(db, "_emdash_media_usage_sources", "identity_version", () => db.schema.alterTable("_emdash_media_usage_sources").addColumn("identity_version", "integer").execute());
|
|
3759
|
+
}
|
|
3760
|
+
async function addColumnIfMissing(db, tableName, columnName, addColumn) {
|
|
3761
|
+
if (await columnExists(db, tableName, columnName)) return;
|
|
3762
|
+
try {
|
|
3763
|
+
await addColumn();
|
|
3764
|
+
} catch (error) {
|
|
3765
|
+
if (DUPLICATE_COLUMN_RE.test(deepErrorMessage$1(error))) {
|
|
3766
|
+
if (await columnExists(db, tableName, columnName)) return;
|
|
3767
|
+
}
|
|
3768
|
+
throw error;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
function sortableUtcTimestamp$2(db) {
|
|
3772
|
+
if (isPostgres(db)) return sql`to_char(clock_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`;
|
|
3773
|
+
return sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`;
|
|
3774
|
+
}
|
|
3775
|
+
function deepErrorMessage$1(error) {
|
|
3776
|
+
if (error instanceof Error) {
|
|
3777
|
+
const own = error.message ?? "";
|
|
3778
|
+
if (error.cause) {
|
|
3779
|
+
const causeMessage = deepErrorMessage$1(error.cause);
|
|
3780
|
+
return own ? `${own}: ${causeMessage}` : causeMessage;
|
|
3781
|
+
}
|
|
3782
|
+
return own;
|
|
3783
|
+
}
|
|
3784
|
+
if (typeof error === "string") return error;
|
|
3785
|
+
try {
|
|
3786
|
+
return JSON.stringify(error);
|
|
3787
|
+
} catch {
|
|
3788
|
+
return String(error);
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
|
|
3792
|
+
//#endregion
|
|
3793
|
+
//#region src/database/migrations/064_fts_plain_text.ts
|
|
3794
|
+
var _064_fts_plain_text_exports = /* @__PURE__ */ __exportAll({
|
|
3795
|
+
down: () => down$6,
|
|
3796
|
+
up: () => up$6
|
|
3797
|
+
});
|
|
3798
|
+
async function up$6(db) {
|
|
3799
|
+
if (!isSqlite(db)) return;
|
|
3800
|
+
const collections = await sql`
|
|
3801
|
+
SELECT slug, search_config FROM _emdash_collections
|
|
3802
|
+
WHERE search_config IS NOT NULL
|
|
3803
|
+
`.execute(db);
|
|
3804
|
+
for (const collection of collections.rows) {
|
|
3805
|
+
if (!isSearchEnabled(collection.search_config)) continue;
|
|
3806
|
+
try {
|
|
3807
|
+
validateIdentifier(collection.slug, "collection slug");
|
|
3808
|
+
} catch (error) {
|
|
3809
|
+
console.warn(`[migration 064] skipping FTS rebuild for collection "${collection.slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
3810
|
+
continue;
|
|
3811
|
+
}
|
|
3812
|
+
const fields = await getSearchableFields(db, collection.slug);
|
|
3813
|
+
if (fields.length === 0) continue;
|
|
3814
|
+
await rebuildIndex(db, collection.slug, fields, searchTokenizer(collection.search_config));
|
|
3815
|
+
}
|
|
3816
|
+
}
|
|
3817
|
+
/**
|
|
3818
|
+
* Forward-only. Down is a no-op: the FTS tables are managed by FTSManager
|
|
3819
|
+
* at runtime and the self-contained shape remains fully functional for
|
|
3820
|
+
* older code paths that only MATCH and join on id.
|
|
3821
|
+
*/
|
|
3822
|
+
async function down$6(_db) {}
|
|
3823
|
+
function isSearchEnabled(searchConfig) {
|
|
3824
|
+
if (!searchConfig) return false;
|
|
3825
|
+
try {
|
|
3826
|
+
const parsed = JSON.parse(searchConfig);
|
|
3827
|
+
return typeof parsed === "object" && parsed !== null && "enabled" in parsed && parsed.enabled === true;
|
|
3828
|
+
} catch {
|
|
3829
|
+
return false;
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
/**
|
|
3833
|
+
* Tokenizers this migration knows how to carry across the rebuild — a frozen
|
|
3834
|
+
* copy of SEARCH_TOKENIZERS as of this migration, not an import: a replay
|
|
3835
|
+
* after the live allowlist changes must not reinterpret configs this
|
|
3836
|
+
* migration never shipped with.
|
|
3837
|
+
*/
|
|
3838
|
+
const KNOWN_TOKENIZERS = [
|
|
3839
|
+
"porter unicode61",
|
|
3840
|
+
"unicode61",
|
|
3841
|
+
"trigram"
|
|
3842
|
+
];
|
|
3843
|
+
/**
|
|
3844
|
+
* Tokenizer for the rebuilt table, from the collection's search_config.
|
|
3845
|
+
* Values outside the allowlist (or unparsable config) fall back to the
|
|
3846
|
+
* default rather than reaching the raw CREATE VIRTUAL TABLE statement.
|
|
3847
|
+
*/
|
|
3848
|
+
function searchTokenizer(searchConfig) {
|
|
3849
|
+
if (!searchConfig) return "porter unicode61";
|
|
3850
|
+
try {
|
|
3851
|
+
const parsed = JSON.parse(searchConfig);
|
|
3852
|
+
if (typeof parsed === "object" && parsed !== null && "tokenize" in parsed) {
|
|
3853
|
+
const configured = KNOWN_TOKENIZERS.find((tokenizer) => tokenizer === parsed.tokenize);
|
|
3854
|
+
if (configured !== void 0) return configured;
|
|
3855
|
+
}
|
|
3856
|
+
} catch {
|
|
3857
|
+
return "porter unicode61";
|
|
3858
|
+
}
|
|
3859
|
+
return "porter unicode61";
|
|
3860
|
+
}
|
|
3861
|
+
async function getSearchableFields(db, collectionSlug) {
|
|
3862
|
+
const rows = await sql`
|
|
3863
|
+
SELECT f.slug, f.type FROM _emdash_fields f
|
|
3864
|
+
INNER JOIN _emdash_collections c ON c.id = f.collection_id
|
|
3865
|
+
WHERE c.slug = ${collectionSlug} AND f.searchable = 1
|
|
3866
|
+
`.execute(db);
|
|
3867
|
+
const out = [];
|
|
3868
|
+
for (const row of rows.rows) try {
|
|
3869
|
+
validateIdentifier(row.slug, "searchable field name");
|
|
3870
|
+
out.push(row);
|
|
3871
|
+
} catch {
|
|
3872
|
+
console.warn(`[migration 064] skipping invalid searchable field "${row.slug}" on collection "${collectionSlug}"`);
|
|
3873
|
+
}
|
|
3874
|
+
return out;
|
|
3875
|
+
}
|
|
3876
|
+
/** Indexed-value expression for one field; lock-step with FTSManager.searchValueExpr. */
|
|
3877
|
+
function searchValueExpr(ref, fieldType) {
|
|
3878
|
+
if (fieldType !== "portableText") return ref;
|
|
3879
|
+
return `CASE WHEN ${ref} IS NULL THEN NULL WHEN json_valid(${ref}) AND json_type(${ref}) IN ('array', 'object') THEN (SELECT group_concat(j.value, ' ') FROM json_tree(${ref}) AS j WHERE j.key IN ('text', 'alt', 'caption', 'code') AND j.type = 'text') ELSE ${ref} END`;
|
|
3880
|
+
}
|
|
3881
|
+
async function rebuildIndex(db, collectionSlug, fields, tokenizer) {
|
|
3882
|
+
const ftsTable = `_emdash_fts_${collectionSlug}`;
|
|
3883
|
+
const contentTable = `ec_${collectionSlug}`;
|
|
3884
|
+
const slugs = fields.map((f) => f.slug);
|
|
3885
|
+
const columnList = [
|
|
3886
|
+
"id UNINDEXED",
|
|
3887
|
+
"locale UNINDEXED",
|
|
3888
|
+
...slugs
|
|
3889
|
+
].join(", ");
|
|
3890
|
+
const fieldList = slugs.join(", ");
|
|
3891
|
+
const newValueList = fields.map((f) => searchValueExpr(`NEW.${f.slug}`, f.type)).join(", ");
|
|
3892
|
+
const changedCondition = [
|
|
3893
|
+
"deleted_at",
|
|
3894
|
+
"locale",
|
|
3895
|
+
...slugs
|
|
3896
|
+
].map((f) => `OLD.${f} IS NOT NEW.${f}`).join(" OR ");
|
|
3897
|
+
const selectValueList = fields.map((f) => searchValueExpr(`"${contentTable}"."${f.slug}"`, f.type)).join(", ");
|
|
3898
|
+
await sql.raw(`DROP TRIGGER IF EXISTS "${ftsTable}_insert"`).execute(db);
|
|
3899
|
+
await sql.raw(`DROP TRIGGER IF EXISTS "${ftsTable}_update"`).execute(db);
|
|
3900
|
+
await sql.raw(`DROP TRIGGER IF EXISTS "${ftsTable}_delete"`).execute(db);
|
|
3901
|
+
await sql.raw(`DROP TABLE IF EXISTS "${ftsTable}"`).execute(db);
|
|
3902
|
+
await sql.raw(`
|
|
3903
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS "${ftsTable}" USING fts5(
|
|
3904
|
+
${columnList},
|
|
3905
|
+
tokenize='${tokenizer}'
|
|
3906
|
+
)
|
|
3907
|
+
`).execute(db);
|
|
3908
|
+
await sql.raw(`
|
|
3909
|
+
CREATE TRIGGER IF NOT EXISTS "${ftsTable}_insert"
|
|
3910
|
+
AFTER INSERT ON "${contentTable}"
|
|
3911
|
+
WHEN NEW.deleted_at IS NULL
|
|
3912
|
+
BEGIN
|
|
3913
|
+
INSERT OR REPLACE INTO "${ftsTable}"(rowid, id, locale, ${fieldList})
|
|
3914
|
+
VALUES (NEW.rowid, NEW.id, NEW.locale, ${newValueList});
|
|
3915
|
+
END
|
|
3916
|
+
`).execute(db);
|
|
3917
|
+
await sql.raw(`
|
|
3918
|
+
CREATE TRIGGER IF NOT EXISTS "${ftsTable}_update"
|
|
3919
|
+
AFTER UPDATE ON "${contentTable}"
|
|
3920
|
+
WHEN ${changedCondition}
|
|
3921
|
+
BEGIN
|
|
3922
|
+
DELETE FROM "${ftsTable}" WHERE rowid = OLD.rowid;
|
|
3923
|
+
INSERT INTO "${ftsTable}"(rowid, id, locale, ${fieldList})
|
|
3924
|
+
SELECT NEW.rowid, NEW.id, NEW.locale, ${newValueList}
|
|
3925
|
+
WHERE NEW.deleted_at IS NULL;
|
|
3926
|
+
END
|
|
3927
|
+
`).execute(db);
|
|
3928
|
+
await sql.raw(`
|
|
3929
|
+
CREATE TRIGGER IF NOT EXISTS "${ftsTable}_delete"
|
|
3930
|
+
AFTER DELETE ON "${contentTable}"
|
|
3931
|
+
BEGIN
|
|
3932
|
+
DELETE FROM "${ftsTable}" WHERE rowid = OLD.rowid;
|
|
3933
|
+
END
|
|
3934
|
+
`).execute(db);
|
|
3935
|
+
await sql.raw(`
|
|
3936
|
+
INSERT OR REPLACE INTO "${ftsTable}"(rowid, id, locale, ${fieldList})
|
|
3937
|
+
SELECT rowid, id, locale, ${selectValueList} FROM "${contentTable}"
|
|
3938
|
+
WHERE deleted_at IS NULL
|
|
3939
|
+
`).execute(db);
|
|
3940
|
+
}
|
|
3941
|
+
|
|
3942
|
+
//#endregion
|
|
3943
|
+
//#region src/database/migrations/065_media_usage_collection_deletion.ts
|
|
3944
|
+
var _065_media_usage_collection_deletion_exports = /* @__PURE__ */ __exportAll({
|
|
3945
|
+
down: () => down$5,
|
|
3946
|
+
up: () => up$5
|
|
3947
|
+
});
|
|
3948
|
+
async function up$5(db) {
|
|
3949
|
+
await db.schema.createTable("_emdash_media_usage_collection_deletions").ifNotExists().addColumn("collection_id", "text", (column) => column.notNull().primaryKey()).addColumn("collection_slug", "text", (column) => column.notNull().unique()).addColumn("force_delete", "integer", (column) => column.notNull()).addColumn("state", "text", (column) => column.notNull().defaultTo("pending")).addColumn("phase", "text", (column) => column.notNull().defaultTo("fence")).addColumn("work_cursor", "text").addColumn("source_key", "text").addColumn("occurrence_cursor", "text").addColumn("attempt_count", "integer", (column) => column.notNull().defaultTo(0)).addColumn("next_attempt_at", "text", (column) => column.notNull()).addColumn("lease_token", "text").addColumn("lease_expires_at", "text").addColumn("last_error_code", "text").addColumn("created_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp$1(db))).addColumn("updated_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp$1(db))).execute();
|
|
3950
|
+
await db.schema.createIndex("idx__emdash_media_usage_collection_deletions_due").ifNotExists().on("_emdash_media_usage_collection_deletions").columns([
|
|
3951
|
+
"state",
|
|
3952
|
+
"next_attempt_at",
|
|
3953
|
+
"updated_at",
|
|
3954
|
+
"collection_id"
|
|
3955
|
+
]).execute();
|
|
3956
|
+
await db.schema.createIndex("idx__emdash_media_usage_collection_deletions_lease").ifNotExists().on("_emdash_media_usage_collection_deletions").columns([
|
|
3957
|
+
"state",
|
|
3958
|
+
"lease_expires_at",
|
|
3959
|
+
"updated_at",
|
|
3960
|
+
"collection_id"
|
|
3961
|
+
]).execute();
|
|
3962
|
+
await db.schema.createIndex("idx__emdash_media_usage_collection_deletions_operator").ifNotExists().on("_emdash_media_usage_collection_deletions").columns([
|
|
3963
|
+
"state",
|
|
3964
|
+
"updated_at",
|
|
3965
|
+
"collection_id"
|
|
3966
|
+
]).execute();
|
|
3967
|
+
await db.schema.createIndex("idx__emdash_media_usage_sources_collection_cursor").ifNotExists().on("_emdash_media_usage_sources").columns([
|
|
3968
|
+
"source_type",
|
|
3969
|
+
"collection_id",
|
|
3970
|
+
"source_key"
|
|
3971
|
+
]).execute();
|
|
3972
|
+
await db.schema.createIndex("idx__emdash_media_usage_source_cursor").ifNotExists().on("_emdash_media_usage").columns(["source_key", "id"]).execute();
|
|
3973
|
+
}
|
|
3974
|
+
async function down$5(db) {
|
|
3975
|
+
if ((await sql`
|
|
3976
|
+
SELECT 1 AS present
|
|
3977
|
+
FROM _emdash_media_usage_collection_deletions
|
|
3978
|
+
LIMIT 1
|
|
3979
|
+
`.execute(db)).rows.length > 0) throw new Error("Cannot roll back while durable collection deletion evidence exists");
|
|
3980
|
+
await db.schema.dropIndex("idx__emdash_media_usage_source_cursor").ifExists().execute();
|
|
3981
|
+
await db.schema.dropIndex("idx__emdash_media_usage_sources_collection_cursor").ifExists().execute();
|
|
3982
|
+
await db.schema.dropTable("_emdash_media_usage_collection_deletions").ifExists().execute();
|
|
3983
|
+
}
|
|
3984
|
+
function sortableUtcTimestamp$1(db) {
|
|
3985
|
+
if (isPostgres(db)) return sql`to_char(clock_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`;
|
|
3986
|
+
return sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`;
|
|
3987
|
+
}
|
|
3988
|
+
|
|
3989
|
+
//#endregion
|
|
3990
|
+
//#region src/database/migrations/066_media_usage_reconciliation.ts
|
|
3991
|
+
var _066_media_usage_reconciliation_exports = /* @__PURE__ */ __exportAll({
|
|
3992
|
+
down: () => down$4,
|
|
3993
|
+
up: () => up$4
|
|
3994
|
+
});
|
|
3995
|
+
const ACTIVATION_KEY = "incremental_capture";
|
|
3996
|
+
async function up$4(db) {
|
|
3997
|
+
await db.schema.createTable("_emdash_media_usage_reconciliations").ifNotExists().addColumn("collection_id", "text", (column) => column.notNull().primaryKey()).addColumn("collection_slug", "text", (column) => column.notNull()).addColumn("run_token", "text", (column) => column.notNull()).addColumn("target_epoch", "bigint").addColumn("field_fingerprint", "text").addColumn("state", "text", (column) => column.notNull().defaultTo("pending")).addColumn("phase", "text", (column) => column.notNull().defaultTo("scan")).addColumn("scan_cursor", "text").addColumn("scan_upper_id", "text").addColumn("source_cursor", "text").addColumn("source_upper_key", "text").addColumn("attempt_count", "integer", (column) => column.notNull().defaultTo(0)).addColumn("next_attempt_at", "text", (column) => column.notNull()).addColumn("lease_token", "text").addColumn("lease_expires_at", "text").addColumn("last_error_code", "text").addColumn("created_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp(db))).addColumn("updated_at", "text", (column) => column.notNull().defaultTo(sortableUtcTimestamp(db))).execute();
|
|
3998
|
+
await db.schema.createIndex("idx__emdash_media_usage_reconciliations_due").ifNotExists().on("_emdash_media_usage_reconciliations").columns([
|
|
3999
|
+
"state",
|
|
4000
|
+
"next_attempt_at",
|
|
4001
|
+
"updated_at",
|
|
4002
|
+
"collection_id"
|
|
4003
|
+
]).execute();
|
|
4004
|
+
await db.schema.createIndex("idx__emdash_media_usage_reconciliations_lease").ifNotExists().on("_emdash_media_usage_reconciliations").columns([
|
|
4005
|
+
"state",
|
|
4006
|
+
"lease_expires_at",
|
|
4007
|
+
"updated_at",
|
|
4008
|
+
"collection_id"
|
|
4009
|
+
]).execute();
|
|
4010
|
+
await db.schema.createIndex("idx__emdash_media_usage_reconciliations_failed").ifNotExists().on("_emdash_media_usage_reconciliations").columns([
|
|
4011
|
+
"state",
|
|
4012
|
+
"updated_at",
|
|
4013
|
+
"collection_id"
|
|
4014
|
+
]).execute();
|
|
4015
|
+
await db.schema.createIndex("idx__emdash_media_usage_status_reconciliation").ifNotExists().on("_emdash_media_usage_index_status").columns([
|
|
4016
|
+
"adapter_id",
|
|
4017
|
+
"scope_type",
|
|
4018
|
+
"capture_state",
|
|
4019
|
+
"reconciliation_required",
|
|
4020
|
+
"collection_id"
|
|
4021
|
+
]).execute();
|
|
4022
|
+
if (!await columnExists(db, "_emdash_media_usage_activation", "media_usage_maintenance_turn")) await db.schema.alterTable("_emdash_media_usage_activation").addColumn("media_usage_maintenance_turn", "integer", (column) => column.notNull().defaultTo(2)).execute();
|
|
4023
|
+
}
|
|
4024
|
+
async function down$4(db) {
|
|
4025
|
+
if (await tableExists(db, "_emdash_media_usage_reconciliations")) {
|
|
4026
|
+
if ((await sql`
|
|
4027
|
+
SELECT 1 AS present
|
|
4028
|
+
FROM _emdash_media_usage_reconciliations
|
|
4029
|
+
LIMIT 1
|
|
4030
|
+
`.execute(db)).rows.length > 0) throw new Error("Cannot roll back while durable reconciliation evidence exists");
|
|
4031
|
+
}
|
|
4032
|
+
if ((await sql`
|
|
4033
|
+
SELECT state
|
|
4034
|
+
FROM _emdash_media_usage_activation
|
|
4035
|
+
WHERE task_key = ${ACTIVATION_KEY}
|
|
4036
|
+
`.execute(db)).rows[0]?.state !== "expanded") throw new Error("Cannot roll back media usage reconciliation after activation has started");
|
|
4037
|
+
await db.schema.dropIndex("idx__emdash_media_usage_status_reconciliation").ifExists().execute();
|
|
4038
|
+
await db.schema.dropIndex("idx__emdash_media_usage_reconciliations_failed").ifExists().execute();
|
|
4039
|
+
await db.schema.dropIndex("idx__emdash_media_usage_reconciliations_lease").ifExists().execute();
|
|
4040
|
+
await db.schema.dropIndex("idx__emdash_media_usage_reconciliations_due").ifExists().execute();
|
|
4041
|
+
await db.schema.dropTable("_emdash_media_usage_reconciliations").ifExists().execute();
|
|
4042
|
+
if (await columnExists(db, "_emdash_media_usage_activation", "media_usage_maintenance_turn")) await db.schema.alterTable("_emdash_media_usage_activation").dropColumn("media_usage_maintenance_turn").execute();
|
|
4043
|
+
}
|
|
4044
|
+
function sortableUtcTimestamp(db) {
|
|
4045
|
+
if (isPostgres(db)) return sql`to_char(clock_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`;
|
|
4046
|
+
return sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`;
|
|
4047
|
+
}
|
|
4048
|
+
|
|
4049
|
+
//#endregion
|
|
4050
|
+
//#region src/database/migrations/067_indexed_content_fields.ts
|
|
4051
|
+
var _067_indexed_content_fields_exports = /* @__PURE__ */ __exportAll({
|
|
4052
|
+
down: () => down$3,
|
|
4053
|
+
up: () => up$3
|
|
4054
|
+
});
|
|
4055
|
+
const FIELD_ID_PATTERN = /^[0-9A-Z]{26}$/;
|
|
4056
|
+
/** Mark custom fields whose structured list queries are backed by a physical index. */
|
|
4057
|
+
async function up$3(db) {
|
|
4058
|
+
if (!await columnExists(db, "_emdash_fields", "indexed")) await db.schema.alterTable("_emdash_fields").addColumn("indexed", "integer", (column) => column.notNull().defaultTo(0)).execute();
|
|
4059
|
+
}
|
|
4060
|
+
async function down$3(db) {
|
|
4061
|
+
if (!await columnExists(db, "_emdash_fields", "indexed")) return;
|
|
4062
|
+
const indexedFields = await sql`
|
|
4063
|
+
SELECT id FROM _emdash_fields WHERE indexed = 1
|
|
4064
|
+
`.execute(db);
|
|
4065
|
+
for (const field of indexedFields.rows) {
|
|
4066
|
+
if (!FIELD_ID_PATTERN.test(field.id)) throw new Error(`Invalid indexed field id "${field.id}"`);
|
|
4067
|
+
await sql`
|
|
4068
|
+
DROP INDEX IF EXISTS ${sql.ref(`idx_cf_${field.id.toLowerCase()}`)}
|
|
4069
|
+
`.execute(db);
|
|
4070
|
+
await sql`
|
|
4071
|
+
DROP INDEX IF EXISTS ${sql.ref(`idx_cf_${field.id.toLowerCase()}_loc`)}
|
|
4072
|
+
`.execute(db);
|
|
4073
|
+
}
|
|
4074
|
+
await db.schema.alterTable("_emdash_fields").dropColumn("indexed").execute();
|
|
4075
|
+
}
|
|
4076
|
+
|
|
4077
|
+
//#endregion
|
|
4078
|
+
//#region src/database/migrations/068_content_taxonomy_entry_groups.ts
|
|
4079
|
+
var _068_content_taxonomy_entry_groups_exports = /* @__PURE__ */ __exportAll({
|
|
4080
|
+
down: () => down$2,
|
|
4081
|
+
up: () => up$2
|
|
4082
|
+
});
|
|
4083
|
+
const LEGACY_DENORM_INDEXES = [
|
|
4084
|
+
"idx_content_taxonomies_pub",
|
|
4085
|
+
"idx_content_taxonomies_crt",
|
|
4086
|
+
"idx_content_taxonomies_loc_pub",
|
|
4087
|
+
"idx_content_taxonomies_loc_crt"
|
|
4088
|
+
];
|
|
4089
|
+
/**
|
|
4090
|
+
* Store the content translation_group in content_taxonomies.entry_id.
|
|
4091
|
+
* Existing per-locale rows are merged into one assignment per content group
|
|
4092
|
+
* and term group. Rows whose content table or content entry no longer exists
|
|
4093
|
+
* are left untouched.
|
|
4094
|
+
*/
|
|
4095
|
+
async function up$2(db) {
|
|
4096
|
+
const tableNames = await listTablesLike(db, "ec_%");
|
|
4097
|
+
for (const tableName of tableNames) {
|
|
4098
|
+
validateIdentifier(tableName, "content table name");
|
|
4099
|
+
const collection = tableName.slice(3);
|
|
4100
|
+
await sql`
|
|
4101
|
+
INSERT INTO content_taxonomies (collection, entry_id, taxonomy_id)
|
|
4102
|
+
SELECT DISTINCT ${collection}, content.translation_group, pivot.taxonomy_id
|
|
4103
|
+
FROM content_taxonomies AS pivot
|
|
4104
|
+
INNER JOIN ${sql.ref(tableName)} AS content ON content.id = pivot.entry_id
|
|
4105
|
+
WHERE pivot.collection = ${collection}
|
|
4106
|
+
AND content.translation_group IS NOT NULL
|
|
4107
|
+
ON CONFLICT (collection, entry_id, taxonomy_id) DO NOTHING
|
|
4108
|
+
`.execute(db);
|
|
4109
|
+
await sql`
|
|
4110
|
+
DELETE FROM content_taxonomies
|
|
4111
|
+
WHERE collection = ${collection}
|
|
4112
|
+
AND entry_id IN (
|
|
4113
|
+
SELECT id
|
|
4114
|
+
FROM ${sql.ref(tableName)}
|
|
4115
|
+
WHERE translation_group IS NOT NULL AND id != translation_group
|
|
4116
|
+
)
|
|
4117
|
+
`.execute(db);
|
|
4118
|
+
}
|
|
4119
|
+
for (const indexName of LEGACY_DENORM_INDEXES) await sql`DROP INDEX IF EXISTS ${sql.ref(indexName)}`.execute(db);
|
|
4120
|
+
await db.schema.createIndex("idx_content_taxonomies_group_lookup").ifNotExists().on("content_taxonomies").columns([
|
|
4121
|
+
"taxonomy_id",
|
|
4122
|
+
"collection",
|
|
4123
|
+
"entry_id"
|
|
4124
|
+
]).execute();
|
|
4125
|
+
}
|
|
4126
|
+
/** The collapsed per-locale rows cannot be reconstructed. */
|
|
4127
|
+
async function down$2(_db) {}
|
|
4128
|
+
|
|
4129
|
+
//#endregion
|
|
4130
|
+
//#region src/database/migrations/069_collection_title_date_fields.ts
|
|
4131
|
+
var _069_collection_title_date_fields_exports = /* @__PURE__ */ __exportAll({
|
|
4132
|
+
down: () => down$1,
|
|
4133
|
+
up: () => up$1
|
|
4134
|
+
});
|
|
4135
|
+
/**
|
|
4136
|
+
* Migration: configurable title and date fields for collections
|
|
4137
|
+
*
|
|
4138
|
+
* Adds `title_field` and `date_field` columns to `_emdash_collections` so a
|
|
4139
|
+
* collection can override which field powers the Title column and which field
|
|
4140
|
+
* powers the Date column in the admin content list. Both are nullable — NULL
|
|
4141
|
+
* preserves the current defaults (title-style display, last-updated date).
|
|
4142
|
+
*
|
|
4143
|
+
* Column adds/drops are guarded by `columnExists`: D1 has no transactions, so a
|
|
4144
|
+
* migration can partially apply without being recorded and later re-run.
|
|
4145
|
+
*/
|
|
4146
|
+
async function up$1(db) {
|
|
4147
|
+
if (!await columnExists(db, "_emdash_collections", "title_field")) await sql`
|
|
4148
|
+
ALTER TABLE _emdash_collections
|
|
4149
|
+
ADD COLUMN title_field TEXT
|
|
4150
|
+
`.execute(db);
|
|
4151
|
+
if (!await columnExists(db, "_emdash_collections", "date_field")) await sql`
|
|
4152
|
+
ALTER TABLE _emdash_collections
|
|
4153
|
+
ADD COLUMN date_field TEXT
|
|
4154
|
+
`.execute(db);
|
|
4155
|
+
}
|
|
4156
|
+
async function down$1(db) {
|
|
4157
|
+
if (await columnExists(db, "_emdash_collections", "date_field")) await sql`
|
|
4158
|
+
ALTER TABLE _emdash_collections
|
|
4159
|
+
DROP COLUMN date_field
|
|
4160
|
+
`.execute(db);
|
|
4161
|
+
if (await columnExists(db, "_emdash_collections", "title_field")) await sql`
|
|
4162
|
+
ALTER TABLE _emdash_collections
|
|
4163
|
+
DROP COLUMN title_field
|
|
4164
|
+
`.execute(db);
|
|
4165
|
+
}
|
|
4166
|
+
|
|
4167
|
+
//#endregion
|
|
4168
|
+
//#region src/database/migrations/070_collection_routable.ts
|
|
4169
|
+
var _070_collection_routable_exports = /* @__PURE__ */ __exportAll({
|
|
4170
|
+
down: () => down,
|
|
4171
|
+
up: () => up
|
|
4172
|
+
});
|
|
4173
|
+
async function up(db) {
|
|
4174
|
+
if (!await columnExists(db, "_emdash_collections", "routable")) await db.schema.alterTable("_emdash_collections").addColumn("routable", "integer", (col) => col.notNull().defaultTo(1)).execute();
|
|
4175
|
+
}
|
|
4176
|
+
async function down(db) {
|
|
4177
|
+
if (await columnExists(db, "_emdash_collections", "routable")) await db.schema.alterTable("_emdash_collections").dropColumn("routable").execute();
|
|
4178
|
+
}
|
|
4179
|
+
|
|
3027
4180
|
//#endregion
|
|
3028
4181
|
//#region src/database/migrations/runner.ts
|
|
3029
4182
|
const MIGRATIONS = Object.freeze({
|
|
@@ -3079,7 +4232,23 @@ const MIGRATIONS = Object.freeze({
|
|
|
3079
4232
|
"051_content_taxonomies_denorm": _051_content_taxonomies_denorm_exports,
|
|
3080
4233
|
"052_media_usage_read_index": _052_media_usage_read_index_exports,
|
|
3081
4234
|
"053_plugin_mcp_tools": _053_plugin_mcp_tools_exports,
|
|
3082
|
-
"054_media_upload_attempts": _054_media_upload_attempts_exports
|
|
4235
|
+
"054_media_upload_attempts": _054_media_upload_attempts_exports,
|
|
4236
|
+
"055_content_translation_group_locale_index": _055_content_translation_group_locale_index_exports,
|
|
4237
|
+
"056_taxonomy_term_sort_order": _056_taxonomy_term_sort_order_exports,
|
|
4238
|
+
"057_collection_hidden": _057_collection_hidden_exports,
|
|
4239
|
+
"058_collection_sort_order": _058_collection_sort_order_exports,
|
|
4240
|
+
"059_revision_prune_queue": _059_revision_prune_queue_exports,
|
|
4241
|
+
"060_collection_admin_config": _060_collection_admin_config_exports,
|
|
4242
|
+
"061_media_usage_cleanup": _061_media_usage_cleanup_exports,
|
|
4243
|
+
"062_media_usage_cleanup_fence": _062_media_usage_cleanup_fence_exports,
|
|
4244
|
+
"063_media_usage_incremental_work": _063_media_usage_incremental_work_exports,
|
|
4245
|
+
"064_fts_plain_text": _064_fts_plain_text_exports,
|
|
4246
|
+
"065_media_usage_collection_deletion": _065_media_usage_collection_deletion_exports,
|
|
4247
|
+
"066_media_usage_reconciliation": _066_media_usage_reconciliation_exports,
|
|
4248
|
+
"067_indexed_content_fields": _067_indexed_content_fields_exports,
|
|
4249
|
+
"068_content_taxonomy_entry_groups": _068_content_taxonomy_entry_groups_exports,
|
|
4250
|
+
"069_collection_title_date_fields": _069_collection_title_date_fields_exports,
|
|
4251
|
+
"070_collection_routable": _070_collection_routable_exports
|
|
3083
4252
|
});
|
|
3084
4253
|
/** Total number of registered migrations. Exported for use in tests. */
|
|
3085
4254
|
const MIGRATION_COUNT = Object.keys(MIGRATIONS).length;
|
|
@@ -3293,4 +4462,4 @@ async function rollbackMigration(db, options) {
|
|
|
3293
4462
|
|
|
3294
4463
|
//#endregion
|
|
3295
4464
|
export { runMigrations as a, rollbackMigration as i, MIGRATION_RACE_WAIT_MS as n, __exportAll as o, getMigrationStatus as r, ConcurrentMigrationTimeoutError as t };
|
|
3296
|
-
//# sourceMappingURL=runner-
|
|
4465
|
+
//# sourceMappingURL=runner-BiDvq5dv.mjs.map
|