emdash 0.34.0 → 0.35.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-34EN2eXO.d.mts → adapters-Bb1vG41D.d.mts} +8 -1
- package/dist/adapters-Bb1vG41D.d.mts.map +1 -0
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +9 -9
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/api/schemas/index.mjs +1 -1
- package/dist/{api-DdAsirBe.mjs → api-BeBglVxU.mjs} +10 -10
- package/dist/{api-DdAsirBe.mjs.map → api-BeBglVxU.mjs.map} +1 -1
- package/dist/{api-tokens-CFXu8F_2.mjs → api-tokens-KO24G1Fd.mjs} +2 -2
- package/dist/{api-tokens-CFXu8F_2.mjs.map → api-tokens-KO24G1Fd.mjs.map} +1 -1
- package/dist/{apply-D5zfeD09.mjs → apply-kUDt80-G.mjs} +16 -16
- package/dist/{apply-D5zfeD09.mjs.map → apply-kUDt80-G.mjs.map} +1 -1
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +71 -15
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +4 -4
- package/dist/astro/middleware/redirect.mjs +2 -2
- package/dist/astro/middleware/request-context.mjs +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +10 -10
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +143 -74
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +1 -1
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +2 -2
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +2 -2
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +2 -2
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +3 -3
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +3 -3
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +3 -3
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +7 -7
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +7 -7
- package/dist/astro/routes/api/admin/bylines/index.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/_id_.mjs +2 -2
- package/dist/astro/routes/api/admin/comments/bulk.mjs +3 -3
- package/dist/astro/routes/api/admin/comments/counts.mjs +2 -2
- package/dist/astro/routes/api/admin/comments/index.mjs +3 -3
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +1 -1
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +1 -1
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +7 -7
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +7 -7
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +4 -4
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +7 -7
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +7 -7
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +1 -1
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/index.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +29 -29
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +29 -29
- package/dist/astro/routes/api/admin/plugins/updates.mjs +28 -28
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +28 -28
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +28 -28
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +1 -1
- package/dist/astro/routes/api/admin/users/index.mjs +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.d.mts.map +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.mjs +2 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/complete.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/index.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/register-options.mjs +3 -3
- package/dist/astro/routes/api/auth/logout.mjs +1 -1
- package/dist/astro/routes/api/auth/magic-link/send.mjs +3 -3
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +1 -1
- package/dist/astro/routes/api/auth/me.mjs +2 -2
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/options.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/signup/complete.mjs +3 -3
- package/dist/astro/routes/api/auth/signup/request.mjs +3 -3
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +5 -5
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +6 -6
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/authors.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/index.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/trash.mjs +2 -2
- package/dist/astro/routes/api/dashboard.mjs +4 -4
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +5 -5
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +1 -1
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +7 -7
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/media.mjs +2 -2
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +5 -5
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +11 -11
- package/dist/astro/routes/api/manifest.mjs +2 -2
- package/dist/astro/routes/api/mcp.mjs +38 -38
- package/dist/astro/routes/api/media/_id_/confirm.mjs +2 -2
- package/dist/astro/routes/api/media/_id_/upload.mjs +2 -2
- package/dist/astro/routes/api/media/_id_/usage.mjs +6 -6
- package/dist/astro/routes/api/media/_id_.mjs +5 -5
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +1 -1
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +1 -1
- package/dist/astro/routes/api/media/providers/index.mjs +1 -1
- package/dist/astro/routes/api/media/upload-url.mjs +3 -3
- package/dist/astro/routes/api/media.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +3 -3
- package/dist/astro/routes/api/menus/_name_/items.mjs +3 -3
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +3 -3
- package/dist/astro/routes/api/menus/_name_/translations.mjs +3 -3
- package/dist/astro/routes/api/menus/_name_.mjs +3 -3
- package/dist/astro/routes/api/menus/index.mjs +3 -3
- package/dist/astro/routes/api/oauth/authorize.mjs +5 -5
- package/dist/astro/routes/api/oauth/device/authorize.mjs +3 -3
- package/dist/astro/routes/api/oauth/device/code.mjs +4 -4
- package/dist/astro/routes/api/oauth/device/token.mjs +4 -4
- package/dist/astro/routes/api/oauth/register.mjs +1 -1
- package/dist/astro/routes/api/oauth/token/refresh.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/revoke.mjs +3 -3
- package/dist/astro/routes/api/oauth/token.mjs +4 -4
- package/dist/astro/routes/api/openapi.json.mjs +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
- package/dist/astro/routes/api/redirects/404s/index.mjs +3 -3
- package/dist/astro/routes/api/redirects/404s/summary.mjs +3 -3
- package/dist/astro/routes/api/redirects/_id_.mjs +4 -4
- package/dist/astro/routes/api/redirects/index.mjs +4 -4
- package/dist/astro/routes/api/relations/_id_/index.mjs +9 -9
- package/dist/astro/routes/api/relations/_id_/translations.mjs +8 -8
- package/dist/astro/routes/api/relations/index.mjs +9 -9
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/index.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/reorder.mjs +28 -28
- package/dist/astro/routes/api/schema/index.mjs +6 -6
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +28 -28
- package/dist/astro/routes/api/schema/orphans/index.mjs +28 -28
- package/dist/astro/routes/api/search/enable.mjs +5 -5
- package/dist/astro/routes/api/search/index.mjs +4 -4
- package/dist/astro/routes/api/search/rebuild.mjs +5 -5
- package/dist/astro/routes/api/search/stats.mjs +4 -4
- package/dist/astro/routes/api/search/suggest.mjs +4 -4
- package/dist/astro/routes/api/sections/_slug_.mjs +4 -4
- package/dist/astro/routes/api/sections/index.mjs +4 -4
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +3 -3
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +3 -3
- package/dist/astro/routes/api/settings/backups/export.mjs +3 -3
- package/dist/astro/routes/api/settings/backups/index.mjs +3 -3
- package/dist/astro/routes/api/settings/email.mjs +1 -1
- package/dist/astro/routes/api/settings.mjs +5 -5
- package/dist/astro/routes/api/setup/admin-verify.mjs +4 -4
- package/dist/astro/routes/api/setup/admin.mjs +4 -4
- package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +18 -21
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/index.d.mts.map +1 -1
- package/dist/astro/routes/api/setup/index.mjs +15 -21
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +2 -2
- package/dist/astro/routes/api/snapshot.mjs +4 -4
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +6 -6
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +6 -6
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +6 -6
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +6 -6
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +6 -6
- package/dist/astro/routes/api/taxonomies/_name_.mjs +6 -6
- package/dist/astro/routes/api/taxonomies/index.mjs +6 -6
- package/dist/astro/routes/api/themes/preview.mjs +2 -2
- package/dist/astro/routes/api/typegen.mjs +3 -3
- package/dist/astro/routes/api/well-known/auth.mjs +1 -1
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +1 -1
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +4 -4
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +4 -4
- package/dist/astro/routes/api/widget-areas/_name_.mjs +3 -3
- package/dist/astro/routes/api/widget-areas/index.mjs +4 -4
- package/dist/astro/routes/robots.txt.mjs +2 -2
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +2 -2
- package/dist/astro/routes/sitemap.xml.mjs +2 -2
- package/dist/astro/types.d.mts +14 -14
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{authorize-1iFJzPaZ.mjs → authorize-DUElxgOQ.mjs} +1 -1
- package/dist/{authorize-1iFJzPaZ.mjs.map → authorize-DUElxgOQ.mjs.map} +1 -1
- package/dist/{backup-LHjIAVNP.mjs → backup-DWYpJlLj.mjs} +3 -3
- package/dist/{backup-LHjIAVNP.mjs.map → backup-DWYpJlLj.mjs.map} +1 -1
- package/dist/{bundle-CBEXrBnb.mjs → bundle-vn56sLos.mjs} +5 -5
- package/dist/{bundle-CBEXrBnb.mjs.map → bundle-vn56sLos.mjs.map} +1 -1
- package/dist/{byline-fields-C5S8wygO.mjs → byline-fields-txaLGoME.mjs} +1 -1
- package/dist/{byline-fields-C5S8wygO.mjs.map → byline-fields-txaLGoME.mjs.map} +1 -1
- package/dist/{byline-pEcoDps8.mjs → byline-yjvWq4ip.mjs} +4 -4
- package/dist/{byline-pEcoDps8.mjs.map → byline-yjvWq4ip.mjs.map} +1 -1
- package/dist/{bylines-DJfSfXCL.mjs → bylines-Bu7pchQ4.mjs} +3 -3
- package/dist/{bylines-DJfSfXCL.mjs.map → bylines-Bu7pchQ4.mjs.map} +1 -1
- package/dist/{bylines-BWemdX2k.mjs → bylines-DjXS5p0P.mjs} +5 -5
- package/dist/{bylines-BWemdX2k.mjs.map → bylines-DjXS5p0P.mjs.map} +1 -1
- package/dist/{cache-CBJaDy_E.mjs → cache-C46-3Irl.mjs} +2 -2
- package/dist/{cache-CBJaDy_E.mjs.map → cache-C46-3Irl.mjs.map} +1 -1
- package/dist/{challenge-store-CZyFVaad.mjs → challenge-store-SIL5DsF2.mjs} +1 -1
- package/dist/{challenge-store-CZyFVaad.mjs.map → challenge-store-SIL5DsF2.mjs.map} +1 -1
- package/dist/{chunks-DfPax1I0.mjs → chunks-fiZ8G9RJ.mjs} +2 -2
- package/dist/{chunks-DfPax1I0.mjs.map → chunks-fiZ8G9RJ.mjs.map} +1 -1
- package/dist/cli/index.mjs +551 -51
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.mjs +2 -2
- package/dist/{collection-deletion-C8BugSGz.mjs → collection-deletion-DQPvMD8R.mjs} +2 -2
- package/dist/{collection-deletion-C8BugSGz.mjs.map → collection-deletion-DQPvMD8R.mjs.map} +1 -1
- package/dist/{comment-reaction-D6qfHKBc.mjs → comment-reaction-D-2J84UE.mjs} +2 -2
- package/dist/{comment-reaction-D6qfHKBc.mjs.map → comment-reaction-D-2J84UE.mjs.map} +1 -1
- package/dist/{comments-CTOuhTSX.mjs → comments-CTfZtLmM.mjs} +1 -1
- package/dist/{comments-CTOuhTSX.mjs.map → comments-CTfZtLmM.mjs.map} +1 -1
- package/dist/config-COQzTe5Q.d.mts +34 -0
- package/dist/config-COQzTe5Q.d.mts.map +1 -0
- package/dist/{content-BNfwh7xX.mjs → content-ZHCc1ngN.mjs} +3 -3
- package/dist/{content-BNfwh7xX.mjs.map → content-ZHCc1ngN.mjs.map} +1 -1
- package/dist/{content-list-query-DhQ84eVV.d.mts → content-list-query-wJ2WN8Vp.d.mts} +1 -1
- package/dist/{content-list-query-DhQ84eVV.d.mts.map → content-list-query-wJ2WN8Vp.d.mts.map} +1 -1
- package/dist/{content-refresh-DNERP4-f.mjs → content-refresh-B_8SJzuU.mjs} +2 -2
- package/dist/{content-refresh-DNERP4-f.mjs.map → content-refresh-B_8SJzuU.mjs.map} +1 -1
- package/dist/{context-DRgOvSnW.mjs → context-ZldbZcle.mjs} +7 -7
- package/dist/{context-DRgOvSnW.mjs.map → context-ZldbZcle.mjs.map} +1 -1
- package/dist/{dashboard-CB8J89rJ.mjs → dashboard-DvHbk_cv.mjs} +3 -3
- package/dist/{dashboard-CB8J89rJ.mjs.map → dashboard-DvHbk_cv.mjs.map} +1 -1
- package/dist/db/index.d.mts +4 -4
- package/dist/db/index.mjs +30 -7
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql-migrations.d.mts +11 -0
- package/dist/db/libsql-migrations.d.mts.map +1 -0
- package/dist/db/libsql-migrations.mjs +57 -0
- package/dist/db/libsql-migrations.mjs.map +1 -0
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres-migrations.d.mts +10 -0
- package/dist/db/postgres-migrations.d.mts.map +1 -0
- package/dist/db/postgres-migrations.mjs +47 -0
- package/dist/db/postgres-migrations.mjs.map +1 -0
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite-migrations.d.mts +10 -0
- package/dist/db/sqlite-migrations.d.mts.map +1 -0
- package/dist/db/sqlite-migrations.mjs +28 -0
- package/dist/db/sqlite-migrations.mjs.map +1 -0
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{deferred-tasks-BMsa9F64.d.mts → deferred-tasks-SDWxrgzJ.d.mts} +1 -1
- package/dist/{deferred-tasks-BMsa9F64.d.mts.map → deferred-tasks-SDWxrgzJ.d.mts.map} +1 -1
- package/dist/{device-flow-CaioYGK3.mjs → device-flow-C0GdD_z8.mjs} +4 -4
- package/dist/{device-flow-CaioYGK3.mjs.map → device-flow-C0GdD_z8.mjs.map} +1 -1
- package/dist/direct-executor-CDXeJCSs.mjs +85 -0
- package/dist/direct-executor-CDXeJCSs.mjs.map +1 -0
- package/dist/{escape-C_aLKP3H.mjs → escape-DUY2r2Zs.mjs} +1 -1
- package/dist/{escape-C_aLKP3H.mjs.map → escape-DUY2r2Zs.mjs.map} +1 -1
- package/dist/{field-defs-cache-hg6QkjV9.mjs → field-defs-cache-BzwBlJrR.mjs} +2 -2
- package/dist/{field-defs-cache-hg6QkjV9.mjs.map → field-defs-cache-BzwBlJrR.mjs.map} +1 -1
- package/dist/{fts-manager-CZ-5dVwJ.mjs → fts-manager-DyZEohZC.mjs} +2 -2
- package/dist/{fts-manager-CZ-5dVwJ.mjs.map → fts-manager-DyZEohZC.mjs.map} +1 -1
- package/dist/{hreflang-DNswoYsi.mjs → hreflang-BBe83kKa.mjs} +5 -5
- package/dist/{hreflang-DNswoYsi.mjs.map → hreflang-BBe83kKa.mjs.map} +1 -1
- package/dist/{hreflang-D3Uehfv2.d.mts → hreflang-DwT2E0Sa.d.mts} +2 -2
- package/dist/{hreflang-D3Uehfv2.d.mts.map → hreflang-DwT2E0Sa.d.mts.map} +1 -1
- package/dist/identity-Ys6Dlc9C.mjs +35 -0
- package/dist/identity-Ys6Dlc9C.mjs.map +1 -0
- package/dist/{import-B41u8Rot.mjs → import-DPkLmeXO.mjs} +2 -2
- package/dist/{import-B41u8Rot.mjs.map → import-DPkLmeXO.mjs.map} +1 -1
- package/dist/{index-C3Y-rsyN.d.mts → index-BVBZj4-7.d.mts} +28 -49
- package/dist/index-BVBZj4-7.d.mts.map +1 -0
- package/dist/{index-Cof4-Fab.d.mts → index-C9KuQyO-.d.mts} +3 -3
- package/dist/{index-Cof4-Fab.d.mts.map → index-C9KuQyO-.d.mts.map} +1 -1
- package/dist/index.d.mts +21 -20
- package/dist/index.mjs +42 -42
- package/dist/{load-DmvJrtxS.mjs → load-YJ2xl3ra.mjs} +2 -2
- package/dist/{load-DmvJrtxS.mjs.map → load-YJ2xl3ra.mjs.map} +1 -1
- package/dist/{loader-DLBqRiGP.mjs → loader-CdG_Ci3H.mjs} +2 -2
- package/dist/{loader-DLBqRiGP.mjs.map → loader-CdG_Ci3H.mjs.map} +1 -1
- package/dist/manifest-builder-B252yQUf.mjs +189 -0
- package/dist/manifest-builder-B252yQUf.mjs.map +1 -0
- package/dist/media/index.d.mts +1 -1
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +2 -2
- package/dist/{media-allowlist-BD6HhgXA.mjs → media-allowlist-D6x-Us02.mjs} +1 -1
- package/dist/{media-allowlist-BD6HhgXA.mjs.map → media-allowlist-D6x-Us02.mjs.map} +1 -1
- package/dist/{media-upload-9yas9zGH.mjs → media-upload-CHBVn6m-.mjs} +2 -2
- package/dist/{media-upload-9yas9zGH.mjs.map → media-upload-CHBVn6m-.mjs.map} +1 -1
- package/dist/{media-usage-De3qvwjc.mjs → media-usage-BZCydfvu.mjs} +4 -4
- package/dist/{media-usage-De3qvwjc.mjs.map → media-usage-BZCydfvu.mjs.map} +1 -1
- package/dist/{media-usage-work-B9Bksh_b.mjs → media-usage-work-CLo_6tct.mjs} +2 -2
- package/dist/{media-usage-work-B9Bksh_b.mjs.map → media-usage-work-CLo_6tct.mjs.map} +1 -1
- package/dist/{menus-CC-yn1F9.mjs → menus-DSo5QeW0.mjs} +6 -6
- package/dist/{menus-CC-yn1F9.mjs.map → menus-DSo5QeW0.mjs.map} +1 -1
- package/dist/{menus-fxvEDYE6.mjs → menus-TCNSd2vp.mjs} +2 -2
- package/dist/{menus-fxvEDYE6.mjs.map → menus-TCNSd2vp.mjs.map} +1 -1
- package/dist/migrations/index.d.mts +22 -0
- package/dist/migrations/index.d.mts.map +1 -0
- package/dist/migrations/index.mjs +7 -0
- package/dist/{mode-Bpe-tNNy.mjs → mode-BDoH_WcF.mjs} +1 -1
- package/dist/{mode-Bpe-tNNy.mjs.map → mode-BDoH_WcF.mjs.map} +1 -1
- package/dist/{oauth-authorization-BXO1MKej.mjs → oauth-authorization-iOikmrJd.mjs} +4 -4
- package/dist/{oauth-authorization-BXO1MKej.mjs.map → oauth-authorization-iOikmrJd.mjs.map} +1 -1
- package/dist/{oauth-clients-C_DNqtRu.mjs → oauth-clients-CvI0nHMJ.mjs} +1 -1
- package/dist/{oauth-clients-C_DNqtRu.mjs.map → oauth-clients-CvI0nHMJ.mjs.map} +1 -1
- package/dist/{oauth-state-store-DwAxMtk4.mjs → oauth-state-store-Ba8KZlwW.mjs} +1 -1
- package/dist/{oauth-state-store-DwAxMtk4.mjs.map → oauth-state-store-Ba8KZlwW.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-BxfZizdk.mjs → oauth-user-lookup-C5SQwGYC.mjs} +1 -1
- package/dist/{oauth-user-lookup-BxfZizdk.mjs.map → oauth-user-lookup-C5SQwGYC.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{options-DRe1pIBL.d.mts → options--hhz-jZ1.d.mts} +3 -3
- package/dist/{options-DRe1pIBL.d.mts.map → options--hhz-jZ1.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{passkey-config-_2GOwwK8.mjs → passkey-config-DFAmUyuE.mjs} +1 -1
- package/dist/{passkey-config-_2GOwwK8.mjs.map → passkey-config-DFAmUyuE.mjs.map} +1 -1
- package/dist/{placeholder-CzW7Lshs.d.mts → placeholder-Dp0K3RkD.d.mts} +1 -1
- package/dist/{placeholder-CzW7Lshs.d.mts.map → placeholder-Dp0K3RkD.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +1 -1
- package/dist/plugin-utils.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/policy-TluUIxuu.mjs +45 -0
- package/dist/policy-TluUIxuu.mjs.map +1 -0
- package/dist/{portable-text-DhKbDAGr.mjs → portable-text-imBW5cHK.mjs} +1 -1
- package/dist/{portable-text-DhKbDAGr.mjs.map → portable-text-imBW5cHK.mjs.map} +1 -1
- package/dist/protocol-DjsJHTlK.d.mts +52 -0
- package/dist/protocol-DjsJHTlK.d.mts.map +1 -0
- package/dist/{query-vgZNwIhh.mjs → query-BWs7O5Il.mjs} +3 -3
- package/dist/{query-vgZNwIhh.mjs.map → query-BWs7O5Il.mjs.map} +1 -1
- package/dist/{query-BgjfiLUQ.mjs → query-zTVAR1Sl.mjs} +12 -12
- package/dist/{query-BgjfiLUQ.mjs.map → query-zTVAR1Sl.mjs.map} +1 -1
- package/dist/{rate-limit-L5anykgo.mjs → rate-limit-Bx4g9m3p.mjs} +1 -1
- package/dist/{rate-limit-L5anykgo.mjs.map → rate-limit-Bx4g9m3p.mjs.map} +1 -1
- package/dist/{redirect-KBNE3UEs.mjs → redirect-BgAOGHDq.mjs} +1 -1
- package/dist/{redirect-KBNE3UEs.mjs.map → redirect-BgAOGHDq.mjs.map} +1 -1
- package/dist/{redirects-cV9g7V-0.mjs → redirects-DTDHWH31.mjs} +2 -2
- package/dist/{redirects-cV9g7V-0.mjs.map → redirects-DTDHWH31.mjs.map} +1 -1
- package/dist/{redirects-CufRQt0Q.mjs → redirects-DyChwDkG.mjs} +1 -1
- package/dist/{redirects-CufRQt0Q.mjs.map → redirects-DyChwDkG.mjs.map} +1 -1
- package/dist/{registry-C581V4TP.mjs → registry-Cqa2I749.mjs} +6 -6
- package/dist/{registry-C581V4TP.mjs.map → registry-Cqa2I749.mjs.map} +1 -1
- package/dist/{relation-DtmAQH7s.mjs → relation-BnHB0T4J.mjs} +2 -2
- package/dist/{relation-DtmAQH7s.mjs.map → relation-BnHB0T4J.mjs.map} +1 -1
- package/dist/{relations-DItI3MN9.d.mts → relations-BHo5A8Zf.d.mts} +35 -35
- package/dist/{relations-DItI3MN9.d.mts.map → relations-BHo5A8Zf.d.mts.map} +1 -1
- package/dist/{relations-DICSyfsh.mjs → relations-D5sM5fW0.mjs} +4 -4
- package/dist/{relations-DICSyfsh.mjs.map → relations-D5sM5fW0.mjs.map} +1 -1
- package/dist/request-context.d.mts +1 -1
- package/dist/{runner-CgQbELYC.d.mts → runner-BYHZn3Jy.d.mts} +16 -3
- package/dist/runner-BYHZn3Jy.d.mts.map +1 -0
- package/dist/{runner-BiDvq5dv.mjs → runner-C1T11CfC.mjs} +34 -4
- package/dist/{runner-BiDvq5dv.mjs.map → runner-C1T11CfC.mjs.map} +1 -1
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +1 -1
- package/dist/{schema-CeQSNwB3.mjs → schema-2AOsSn2v.mjs} +4 -4
- package/dist/{schema-CeQSNwB3.mjs.map → schema-2AOsSn2v.mjs.map} +1 -1
- package/dist/{schema-BFyTg38T.mjs → schema-DZ5YVVZj.mjs} +3 -3
- package/dist/{schema-BFyTg38T.mjs.map → schema-DZ5YVVZj.mjs.map} +1 -1
- package/dist/{scopes-BVeuhGBE.mjs → scopes-8ClPF2bC.mjs} +2 -2
- package/dist/{scopes-BVeuhGBE.mjs.map → scopes-8ClPF2bC.mjs.map} +1 -1
- package/dist/{search-BpuPKZb0.mjs → search-u1QYdOCG.mjs} +4 -4
- package/dist/{search-BpuPKZb0.mjs.map → search-u1QYdOCG.mjs.map} +1 -1
- package/dist/{secrets-dtYs2hDo.mjs → secrets-BEgsAQEU.mjs} +1 -1
- package/dist/{secrets-dtYs2hDo.mjs.map → secrets-BEgsAQEU.mjs.map} +1 -1
- package/dist/{sections-COctk6hf.mjs → sections-DmHviGyM.mjs} +2 -2
- package/dist/{sections-COctk6hf.mjs.map → sections-DmHviGyM.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +13 -13
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +9 -9
- package/dist/{seo-CvDxfvFb.mjs → seo-Dq4G-RrO.mjs} +2 -2
- package/dist/{seo-CvDxfvFb.mjs.map → seo-Dq4G-RrO.mjs.map} +1 -1
- package/dist/{service-xMiMSTsR.mjs → service-BpArayPr.mjs} +2 -2
- package/dist/{service-xMiMSTsR.mjs.map → service-BpArayPr.mjs.map} +1 -1
- package/dist/{session-user-BzVemLkw.mjs → session-user-BEorKVT-.mjs} +1 -1
- package/dist/{session-user-BzVemLkw.mjs.map → session-user-BEorKVT-.mjs.map} +1 -1
- package/dist/{settings-BE9aqn_9.mjs → settings-DE9xtzqd.mjs} +3 -3
- package/dist/{settings-BE9aqn_9.mjs.map → settings-DE9xtzqd.mjs.map} +1 -1
- package/dist/{settings-B372MV0p.mjs → settings-xRdoUZr0.mjs} +2 -2
- package/dist/{settings-B372MV0p.mjs.map → settings-xRdoUZr0.mjs.map} +1 -1
- package/dist/{setup-complete-DF7TAfD5.mjs → setup-complete-BnT8pq_C.mjs} +1 -1
- package/dist/{setup-complete-DF7TAfD5.mjs.map → setup-complete-BnT8pq_C.mjs.map} +1 -1
- package/dist/{setup-nonce-Do-U_cg9.mjs → setup-nonce-CBitf_oQ.mjs} +1 -1
- package/dist/{setup-nonce-Do-U_cg9.mjs.map → setup-nonce-CBitf_oQ.mjs.map} +1 -1
- package/dist/{site-url-Bowsi9T-.mjs → site-url-DjpIXMXJ.mjs} +1 -1
- package/dist/{site-url-Bowsi9T-.mjs.map → site-url-DjpIXMXJ.mjs.map} +1 -1
- package/dist/{snapshot-B5h6aPMh.mjs → snapshot-BBlGkb2q.mjs} +1 -1
- package/dist/{snapshot-B5h6aPMh.mjs.map → snapshot-BBlGkb2q.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +2 -2
- package/dist/storage/s3.d.mts +1 -1
- package/dist/target-DixqqV5i.mjs +27 -0
- package/dist/target-DixqqV5i.mjs.map +1 -0
- package/dist/{taxonomies-B0o9ExNV.mjs → taxonomies-BlrncHi9.mjs} +5 -5
- package/dist/{taxonomies-B0o9ExNV.mjs.map → taxonomies-BlrncHi9.mjs.map} +1 -1
- package/dist/{taxonomies-Dk3MAklL.mjs → taxonomies-OHUIiIpI.mjs} +4 -4
- package/dist/{taxonomies-Dk3MAklL.mjs.map → taxonomies-OHUIiIpI.mjs.map} +1 -1
- package/dist/{taxonomy-CPeM8d2o.mjs → taxonomy-BqCZ1TdU.mjs} +3 -3
- package/dist/{taxonomy-CPeM8d2o.mjs.map → taxonomy-BqCZ1TdU.mjs.map} +1 -1
- package/dist/{transport--CfOflrp.mjs → transport-DBJwa-Si.mjs} +1 -1
- package/dist/{transport--CfOflrp.mjs.map → transport-DBJwa-Si.mjs.map} +1 -1
- package/dist/{transport-B_rfeU-a.d.mts → transport-RQE36APG.d.mts} +1 -1
- package/dist/{transport-B_rfeU-a.d.mts.map → transport-RQE36APG.d.mts.map} +1 -1
- package/dist/{types-CFUfyt1s.d.mts → types-BcqdcT-r.d.mts} +1 -1
- package/dist/{types-CFUfyt1s.d.mts.map → types-BcqdcT-r.d.mts.map} +1 -1
- package/dist/{types-CPx2lIGo.d.mts → types-BntycPTF.d.mts} +1 -1
- package/dist/{types-CPx2lIGo.d.mts.map → types-BntycPTF.d.mts.map} +1 -1
- package/dist/{types-C3_AbkDP.d.mts → types-C2pMvO62.d.mts} +1 -1
- package/dist/{types-C3_AbkDP.d.mts.map → types-C2pMvO62.d.mts.map} +1 -1
- package/dist/{types-DefV3OiO.d.mts → types-CXnOzDe1.d.mts} +1 -1
- package/dist/{types-DefV3OiO.d.mts.map → types-CXnOzDe1.d.mts.map} +1 -1
- package/dist/{types-D4_1Ga4L.d.mts → types-DN64_zzZ.d.mts} +3 -3
- package/dist/{types-D4_1Ga4L.d.mts.map → types-DN64_zzZ.d.mts.map} +1 -1
- package/dist/{types-CAGdePf3.d.mts → types-DQIDRKF2.d.mts} +1 -1
- package/dist/{types-CAGdePf3.d.mts.map → types-DQIDRKF2.d.mts.map} +1 -1
- package/dist/{types-BPuloofb.d.mts → types-DWRhk9xZ.d.mts} +1 -1
- package/dist/{types-BPuloofb.d.mts.map → types-DWRhk9xZ.d.mts.map} +1 -1
- package/dist/{types-X0MThr7x.d.mts → types-Dfk8KI5R.d.mts} +1 -1
- package/dist/{types-X0MThr7x.d.mts.map → types-Dfk8KI5R.d.mts.map} +1 -1
- package/dist/{types-Cs-TFLNf.d.mts → types-DrJrVCT1.d.mts} +3 -3
- package/dist/{types-Cs-TFLNf.d.mts.map → types-DrJrVCT1.d.mts.map} +1 -1
- package/dist/{upload-attempts-hlne3iA1.mjs → upload-attempts-D4FS8LT6.mjs} +1 -1
- package/dist/{upload-attempts-hlne3iA1.mjs.map → upload-attempts-D4FS8LT6.mjs.map} +1 -1
- package/dist/{user-sHgJ62SP.mjs → user-DJZfUJVE.mjs} +2 -2
- package/dist/{user-sHgJ62SP.mjs.map → user-DJZfUJVE.mjs.map} +1 -1
- package/dist/{validate-BkqIG_Uj.mjs → validate-BMLBvxOC.mjs} +2 -2
- package/dist/{validate-BkqIG_Uj.mjs.map → validate-BMLBvxOC.mjs.map} +1 -1
- package/dist/{validate-DeGtBN84.d.mts → validate-CTqt5nuE.d.mts} +5 -5
- package/dist/{validate-DeGtBN84.d.mts.map → validate-CTqt5nuE.d.mts.map} +1 -1
- package/dist/{validation-CiJb_X5o.mjs → validation-npvENUCB.mjs} +7 -7
- package/dist/{validation-CiJb_X5o.mjs.map → validation-npvENUCB.mjs.map} +1 -1
- package/dist/version-DB_fqCSI.mjs +7 -0
- package/dist/{version-x0NjTScG.mjs.map → version-DB_fqCSI.mjs.map} +1 -1
- package/dist/{widgets-Cwzvww0W.mjs → widgets-BD3ho7Rq.mjs} +2 -2
- package/dist/{widgets-Cwzvww0W.mjs.map → widgets-BD3ho7Rq.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-QZjWxjyk.mjs → wxr-taxonomies-B1R3vBoD.mjs} +3 -3
- package/dist/{wxr-taxonomies-QZjWxjyk.mjs.map → wxr-taxonomies-B1R3vBoD.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-CmC0ZsDr.d.mts → wxr-taxonomies-Ca68766D.d.mts} +1 -1
- package/dist/{wxr-taxonomies-CmC0ZsDr.d.mts.map → wxr-taxonomies-Ca68766D.d.mts.map} +1 -1
- package/dist/{zod-generator-D11MhxG4.mjs → zod-generator-LC-on_Vb.mjs} +2 -2
- package/dist/{zod-generator-D11MhxG4.mjs.map → zod-generator-LC-on_Vb.mjs.map} +1 -1
- package/package.json +21 -5
- package/src/astro/integration/index.ts +46 -14
- package/src/astro/integration/runtime.ts +3 -0
- package/src/astro/middleware/scoped-db.ts +21 -0
- package/src/astro/middleware.ts +67 -10
- package/src/astro/routes/api/auth/dev-bypass.ts +0 -4
- package/src/astro/routes/api/setup/dev-bypass.ts +2 -7
- package/src/astro/routes/api/setup/index.ts +5 -13
- package/src/cli/commands/migrate.ts +593 -0
- package/src/cli/index.ts +2 -23
- package/src/database/index.ts +8 -2
- package/src/database/migrations/policy.ts +70 -0
- package/src/database/migrations/runner.ts +49 -3
- package/src/db/adapters.ts +50 -2
- package/src/db/index.ts +3 -1
- package/src/db/libsql-migrations.ts +72 -0
- package/src/db/postgres-migrations.ts +59 -0
- package/src/db/sqlite-migrations.ts +37 -0
- package/src/emdash-runtime.ts +44 -15
- package/src/i18n/normalize.ts +31 -0
- package/src/index.ts +7 -1
- package/src/migrations/config-loader.ts +205 -0
- package/src/migrations/direct-executor.ts +141 -0
- package/src/migrations/identity.ts +46 -0
- package/src/migrations/index.ts +19 -0
- package/src/migrations/integration-metadata.ts +67 -0
- package/src/migrations/manifest-builder.ts +55 -0
- package/src/migrations/manifest-writer.ts +63 -0
- package/src/migrations/manifest.ts +197 -0
- package/src/migrations/protocol.ts +59 -0
- package/src/migrations/target.ts +35 -0
- package/src/virtual-modules.d.ts +8 -0
- package/dist/adapters-34EN2eXO.d.mts.map +0 -1
- package/dist/index-C3Y-rsyN.d.mts.map +0 -1
- package/dist/runner-CgQbELYC.d.mts.map +0 -1
- package/dist/version-x0NjTScG.mjs +0 -7
- /package/dist/{api-tokens-CyTsLszZ.mjs → api-tokens-rIXC6LdE.mjs} +0 -0
package/src/database/index.ts
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
// `connection.ts`, which statically imports `better-sqlite3`. See #947.
|
|
3
3
|
export { EmDashDatabaseError } from "./errors.js";
|
|
4
4
|
export type { DatabaseConfig } from "./connection.js";
|
|
5
|
-
export {
|
|
6
|
-
|
|
5
|
+
export {
|
|
6
|
+
runMigrations,
|
|
7
|
+
getMigrationStatus,
|
|
8
|
+
getExactMigrationStatus,
|
|
9
|
+
rollbackMigration,
|
|
10
|
+
MIGRATION_NAMES,
|
|
11
|
+
} from "./migrations/runner.js";
|
|
12
|
+
export type { MigrationStatus, ExactMigrationStatus } from "./migrations/runner.js";
|
|
7
13
|
export type * from "./types.js";
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
import type { Database } from "../types.js";
|
|
4
|
+
import { getExactMigrationStatus, runMigrations } from "./runner.js";
|
|
5
|
+
|
|
6
|
+
export type RuntimeMigrationMode = "auto" | "check" | "manual";
|
|
7
|
+
|
|
8
|
+
export interface RuntimeMigrationConfig {
|
|
9
|
+
runtime: RuntimeMigrationMode;
|
|
10
|
+
dev?: RuntimeMigrationMode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parseMigrationMode(value: unknown, source: string): RuntimeMigrationMode {
|
|
14
|
+
if (value === "auto" || value === "check" || value === "manual") {
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Invalid ${source} value ${JSON.stringify(value)}; expected "auto", "check", or "manual"`,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function normalizeMigrationConfig(value: unknown): RuntimeMigrationConfig {
|
|
23
|
+
if (value === undefined) return { runtime: "auto" };
|
|
24
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
25
|
+
throw new Error("Invalid migrations configuration; expected an object");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const runtimeValue = Reflect.get(value, "runtime");
|
|
29
|
+
const devValue = Reflect.get(value, "dev");
|
|
30
|
+
const runtime = parseMigrationMode(runtimeValue, "migrations.runtime");
|
|
31
|
+
const dev = devValue === undefined ? undefined : parseMigrationMode(devValue, "migrations.dev");
|
|
32
|
+
return dev === undefined ? { runtime } : { runtime, dev };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function resolveRuntimeMigrationMode(
|
|
36
|
+
config: RuntimeMigrationConfig | undefined,
|
|
37
|
+
options: { dev: boolean; override?: unknown },
|
|
38
|
+
): RuntimeMigrationMode {
|
|
39
|
+
if (options.override !== undefined) {
|
|
40
|
+
return parseMigrationMode(options.override, "EMDASH_MIGRATIONS_MODE");
|
|
41
|
+
}
|
|
42
|
+
if (options.dev) return config?.dev ?? "auto";
|
|
43
|
+
return config?.runtime ?? "auto";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class PendingMigrationsError extends Error {
|
|
47
|
+
readonly pending: string[];
|
|
48
|
+
|
|
49
|
+
constructor(pending: readonly string[]) {
|
|
50
|
+
super(`Database has pending EmDash migrations: ${pending.join(", ")}`);
|
|
51
|
+
this.name = "PendingMigrationsError";
|
|
52
|
+
this.pending = [...pending];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function enforceRuntimeMigrationPolicy(
|
|
57
|
+
db: Kysely<Database>,
|
|
58
|
+
mode: RuntimeMigrationMode,
|
|
59
|
+
): Promise<void> {
|
|
60
|
+
if (mode === "manual") return;
|
|
61
|
+
if (mode === "auto") {
|
|
62
|
+
await runMigrations(db);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const status = await getExactMigrationStatus(db);
|
|
67
|
+
if (status.pending.length > 0) {
|
|
68
|
+
throw new PendingMigrationsError(status.pending);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -146,8 +146,11 @@ const MIGRATIONS: Readonly<Record<string, Migration>> = Object.freeze({
|
|
|
146
146
|
"070_collection_routable": m070,
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
+
/** Ordered names from the statically registered migration set. */
|
|
150
|
+
export const MIGRATION_NAMES: readonly string[] = Object.freeze(Object.keys(MIGRATIONS));
|
|
151
|
+
|
|
149
152
|
/** Total number of registered migrations. Exported for use in tests. */
|
|
150
|
-
export const MIGRATION_COUNT =
|
|
153
|
+
export const MIGRATION_COUNT = MIGRATION_NAMES.length;
|
|
151
154
|
|
|
152
155
|
/**
|
|
153
156
|
* Migration provider that uses statically imported migrations.
|
|
@@ -164,6 +167,12 @@ export interface MigrationStatus {
|
|
|
164
167
|
pending: string[];
|
|
165
168
|
}
|
|
166
169
|
|
|
170
|
+
export interface ExactMigrationStatus {
|
|
171
|
+
knownApplied: string[];
|
|
172
|
+
pending: string[];
|
|
173
|
+
unknownApplied: string[];
|
|
174
|
+
}
|
|
175
|
+
|
|
167
176
|
/**
|
|
168
177
|
* Thrown when another instance held the migration lock for the whole wait
|
|
169
178
|
* window. This is NOT a migration failure — the holder may simply be slow
|
|
@@ -286,8 +295,8 @@ const MIGRATION_RACE_POLL_MS = 100;
|
|
|
286
295
|
* built from `MIGRATION_TABLE` so a rename cannot drift.
|
|
287
296
|
*/
|
|
288
297
|
const MIGRATION_TABLE_MISSING_PATTERN = new RegExp(
|
|
289
|
-
`(?:no such table:\\s
|
|
290
|
-
`|(?:relation|table)\\s+"?${escapeRegExp(MIGRATION_TABLE)}"?\\s+does(?:n't| not) exist\\b)`,
|
|
298
|
+
`(?:no such table:\\s*(?:[a-z][a-z0-9_]*\\.)?${escapeRegExp(MIGRATION_TABLE)}\\b` +
|
|
299
|
+
`|(?:relation|table)\\s+"?(?:[a-z][a-z0-9_]*\\.)?${escapeRegExp(MIGRATION_TABLE)}"?\\s+does(?:n't| not) exist\\b)`,
|
|
291
300
|
"i",
|
|
292
301
|
);
|
|
293
302
|
|
|
@@ -359,6 +368,43 @@ function deepErrorMessage(error: unknown): string {
|
|
|
359
368
|
}
|
|
360
369
|
}
|
|
361
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Read exact migration status without invoking Kysely's migration
|
|
373
|
+
* introspection. Registered names retain execution order; unknown database
|
|
374
|
+
* records are sorted so reports remain stable across dialects.
|
|
375
|
+
*/
|
|
376
|
+
export async function getExactMigrationStatus(
|
|
377
|
+
db: Kysely<Database>,
|
|
378
|
+
options?: MigrationOptions,
|
|
379
|
+
): Promise<ExactMigrationStatus> {
|
|
380
|
+
const table = options?.migrationTableSchema
|
|
381
|
+
? sql`${sql.ref(options.migrationTableSchema)}.${sql.ref(MIGRATION_TABLE)}`
|
|
382
|
+
: sql.ref(MIGRATION_TABLE);
|
|
383
|
+
|
|
384
|
+
let rows: readonly { name: string }[];
|
|
385
|
+
try {
|
|
386
|
+
const result = await sql<{ name: string }>`SELECT name FROM ${table}`.execute(db);
|
|
387
|
+
rows = result.rows;
|
|
388
|
+
} catch (error) {
|
|
389
|
+
if (MIGRATION_TABLE_MISSING_PATTERN.test(deepErrorMessage(error))) {
|
|
390
|
+
return {
|
|
391
|
+
knownApplied: [],
|
|
392
|
+
pending: [...MIGRATION_NAMES],
|
|
393
|
+
unknownApplied: [],
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const appliedNames = new Set(rows.map((row) => row.name));
|
|
400
|
+
const knownApplied = MIGRATION_NAMES.filter((name) => appliedNames.has(name));
|
|
401
|
+
const pending = MIGRATION_NAMES.filter((name) => !appliedNames.has(name));
|
|
402
|
+
const knownNames = new Set(MIGRATION_NAMES);
|
|
403
|
+
const unknownApplied = [...appliedNames].filter((name) => !knownNames.has(name)).toSorted();
|
|
404
|
+
|
|
405
|
+
return { knownApplied, pending, unknownApplied };
|
|
406
|
+
}
|
|
407
|
+
|
|
362
408
|
/**
|
|
363
409
|
* Run all pending migrations.
|
|
364
410
|
*
|
package/src/db/adapters.ts
CHANGED
|
@@ -52,6 +52,20 @@ export type ExecuteCollectionDeletionGuard = (
|
|
|
52
52
|
input: CollectionDeletionGuardInput,
|
|
53
53
|
) => Promise<CollectionDeletionGuardResult>;
|
|
54
54
|
|
|
55
|
+
const ENVIRONMENT_VARIABLE_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
56
|
+
|
|
57
|
+
function migrationEnvironmentVariable(
|
|
58
|
+
value: string | undefined,
|
|
59
|
+
fallback: string,
|
|
60
|
+
optionName: string,
|
|
61
|
+
): string {
|
|
62
|
+
const name = value ?? fallback;
|
|
63
|
+
if (!ENVIRONMENT_VARIABLE_PATTERN.test(name)) {
|
|
64
|
+
throw new Error(`${optionName} must be a valid environment variable name.`);
|
|
65
|
+
}
|
|
66
|
+
return name;
|
|
67
|
+
}
|
|
68
|
+
|
|
55
69
|
/**
|
|
56
70
|
* Database descriptor - serializable config for virtual modules
|
|
57
71
|
*/
|
|
@@ -59,6 +73,11 @@ export interface DatabaseDescriptor {
|
|
|
59
73
|
entrypoint: string;
|
|
60
74
|
config: unknown;
|
|
61
75
|
type: DatabaseDialectType;
|
|
76
|
+
/** Deployment migration capability with configuration safe for a build artifact. */
|
|
77
|
+
migrations?: {
|
|
78
|
+
entrypoint: string;
|
|
79
|
+
manifestConfig: unknown;
|
|
80
|
+
};
|
|
62
81
|
/**
|
|
63
82
|
* When true, the adapter's runtime entrypoint MUST export a named
|
|
64
83
|
* `createRequestScopedDb` function matching the signature declared in
|
|
@@ -111,6 +130,7 @@ export interface LibsqlConfig {
|
|
|
111
130
|
* Auth token for remote libSQL
|
|
112
131
|
*/
|
|
113
132
|
authToken?: string;
|
|
133
|
+
migrationAuthTokenEnv?: string;
|
|
114
134
|
}
|
|
115
135
|
|
|
116
136
|
/**
|
|
@@ -128,6 +148,10 @@ export function sqlite(config: SqliteConfig): DatabaseDescriptor {
|
|
|
128
148
|
entrypoint: "emdash/db/sqlite",
|
|
129
149
|
config,
|
|
130
150
|
type: "sqlite",
|
|
151
|
+
migrations: {
|
|
152
|
+
entrypoint: "emdash/db/sqlite-migrations",
|
|
153
|
+
manifestConfig: { url: config.url },
|
|
154
|
+
},
|
|
131
155
|
};
|
|
132
156
|
}
|
|
133
157
|
|
|
@@ -145,10 +169,22 @@ export function sqlite(config: SqliteConfig): DatabaseDescriptor {
|
|
|
145
169
|
* ```
|
|
146
170
|
*/
|
|
147
171
|
export function libsql(config: LibsqlConfig): DatabaseDescriptor {
|
|
172
|
+
const { migrationAuthTokenEnv, ...runtimeConfig } = config;
|
|
148
173
|
return {
|
|
149
174
|
entrypoint: "emdash/db/libsql",
|
|
150
|
-
config,
|
|
175
|
+
config: runtimeConfig,
|
|
151
176
|
type: "sqlite",
|
|
177
|
+
migrations: {
|
|
178
|
+
entrypoint: "emdash/db/libsql-migrations",
|
|
179
|
+
manifestConfig: {
|
|
180
|
+
url: config.url,
|
|
181
|
+
authTokenEnv: migrationEnvironmentVariable(
|
|
182
|
+
migrationAuthTokenEnv,
|
|
183
|
+
"TURSO_AUTH_TOKEN",
|
|
184
|
+
"migrationAuthTokenEnv",
|
|
185
|
+
),
|
|
186
|
+
},
|
|
187
|
+
},
|
|
152
188
|
};
|
|
153
189
|
}
|
|
154
190
|
|
|
@@ -164,6 +200,7 @@ export interface PostgresConfig {
|
|
|
164
200
|
password?: string;
|
|
165
201
|
ssl?: boolean;
|
|
166
202
|
pool?: { min?: number; max?: number };
|
|
203
|
+
migrationConnectionStringEnv?: string;
|
|
167
204
|
}
|
|
168
205
|
|
|
169
206
|
/**
|
|
@@ -177,9 +214,20 @@ export interface PostgresConfig {
|
|
|
177
214
|
* ```
|
|
178
215
|
*/
|
|
179
216
|
export function postgres(config: PostgresConfig): DatabaseDescriptor {
|
|
217
|
+
const { migrationConnectionStringEnv, ...runtimeConfig } = config;
|
|
180
218
|
return {
|
|
181
219
|
entrypoint: "emdash/db/postgres",
|
|
182
|
-
config,
|
|
220
|
+
config: runtimeConfig,
|
|
183
221
|
type: "postgres",
|
|
222
|
+
migrations: {
|
|
223
|
+
entrypoint: "emdash/db/postgres-migrations",
|
|
224
|
+
manifestConfig: {
|
|
225
|
+
connectionStringEnv: migrationEnvironmentVariable(
|
|
226
|
+
migrationConnectionStringEnv,
|
|
227
|
+
"DATABASE_URL",
|
|
228
|
+
"migrationConnectionStringEnv",
|
|
229
|
+
),
|
|
230
|
+
},
|
|
231
|
+
},
|
|
184
232
|
};
|
|
185
233
|
}
|
package/src/db/index.ts
CHANGED
|
@@ -35,6 +35,8 @@ export type {
|
|
|
35
35
|
export {
|
|
36
36
|
runMigrations,
|
|
37
37
|
getMigrationStatus,
|
|
38
|
+
getExactMigrationStatus,
|
|
38
39
|
rollbackMigration,
|
|
40
|
+
MIGRATION_NAMES,
|
|
39
41
|
} from "../database/migrations/runner.js";
|
|
40
|
-
export type { MigrationStatus } from "../database/migrations/runner.js";
|
|
42
|
+
export type { MigrationStatus, ExactMigrationStatus } from "../database/migrations/runner.js";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { createDirectMigrationExecutor } from "../migrations/direct-executor.js";
|
|
5
|
+
import type { MigrationExecutor, MigrationExecutorFactoryContext } from "../migrations/protocol.js";
|
|
6
|
+
import { createMigrationTarget, requireMigrationEnvironment } from "../migrations/target.js";
|
|
7
|
+
import { createDialect } from "./libsql.js";
|
|
8
|
+
|
|
9
|
+
export interface LibsqlMigrationManifestConfig {
|
|
10
|
+
url: string;
|
|
11
|
+
authTokenEnv: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface ResolvedLibsqlUrl {
|
|
15
|
+
connectionUrl: string;
|
|
16
|
+
label: string;
|
|
17
|
+
identity: string[];
|
|
18
|
+
requiresAuthToken: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function resolveLibsqlUrl(url: unknown, projectRoot: string): ResolvedLibsqlUrl {
|
|
22
|
+
if (typeof url !== "string" || url.length === 0) {
|
|
23
|
+
throw new Error("libSQL migration URL is missing.");
|
|
24
|
+
}
|
|
25
|
+
if (url.startsWith("file:")) {
|
|
26
|
+
const configuredPath = url.slice(5);
|
|
27
|
+
if (configuredPath.length === 0) throw new Error("libSQL migration URL is invalid.");
|
|
28
|
+
const fileUrl = pathToFileURL(resolve(projectRoot, configuredPath));
|
|
29
|
+
return {
|
|
30
|
+
connectionUrl: fileUrl.href,
|
|
31
|
+
label: fileUrl.href,
|
|
32
|
+
identity: [fileUrl.protocol, fileUrl.pathname],
|
|
33
|
+
requiresAuthToken: false,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let parsed: URL;
|
|
38
|
+
try {
|
|
39
|
+
parsed = new URL(url);
|
|
40
|
+
} catch {
|
|
41
|
+
throw new Error("libSQL migration URL is invalid.");
|
|
42
|
+
}
|
|
43
|
+
if (parsed.username || parsed.password) {
|
|
44
|
+
throw new Error("libSQL migration URL must not contain credentials.");
|
|
45
|
+
}
|
|
46
|
+
const label = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
|
|
47
|
+
return {
|
|
48
|
+
connectionUrl: url,
|
|
49
|
+
label,
|
|
50
|
+
identity: [parsed.protocol, parsed.host, parsed.pathname],
|
|
51
|
+
requiresAuthToken: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function createMigrationExecutor(
|
|
56
|
+
manifestConfig: LibsqlMigrationManifestConfig,
|
|
57
|
+
context: MigrationExecutorFactoryContext,
|
|
58
|
+
): Promise<MigrationExecutor> {
|
|
59
|
+
const resolvedUrl = resolveLibsqlUrl(manifestConfig.url, context.projectRoot);
|
|
60
|
+
const authToken = resolvedUrl.requiresAuthToken
|
|
61
|
+
? requireMigrationEnvironment(manifestConfig.authTokenEnv, context.env)
|
|
62
|
+
: undefined;
|
|
63
|
+
const target = await createMigrationTarget("libsql", resolvedUrl.label, resolvedUrl.identity);
|
|
64
|
+
return createDirectMigrationExecutor({
|
|
65
|
+
target,
|
|
66
|
+
createDialect: () =>
|
|
67
|
+
createDialect({
|
|
68
|
+
url: resolvedUrl.connectionUrl,
|
|
69
|
+
authToken,
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createDirectMigrationExecutor } from "../migrations/direct-executor.js";
|
|
2
|
+
import type { MigrationExecutor, MigrationExecutorFactoryContext } from "../migrations/protocol.js";
|
|
3
|
+
import { createMigrationTarget, requireMigrationEnvironment } from "../migrations/target.js";
|
|
4
|
+
import { createDialect } from "./postgres.js";
|
|
5
|
+
|
|
6
|
+
export interface PostgresMigrationManifestConfig {
|
|
7
|
+
connectionStringEnv: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface PostgresTargetIdentity {
|
|
11
|
+
host: string;
|
|
12
|
+
port: string;
|
|
13
|
+
database: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function parseTargetIdentity(connectionString: string): PostgresTargetIdentity {
|
|
17
|
+
let parsed: URL;
|
|
18
|
+
try {
|
|
19
|
+
parsed = new URL(connectionString);
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error("PostgreSQL migration connection string is invalid.");
|
|
22
|
+
}
|
|
23
|
+
if (parsed.protocol !== "postgres:" && parsed.protocol !== "postgresql:") {
|
|
24
|
+
throw new Error("PostgreSQL migration connection string is invalid.");
|
|
25
|
+
}
|
|
26
|
+
const database = parsed.pathname.slice(1);
|
|
27
|
+
if (!parsed.hostname || !database) {
|
|
28
|
+
throw new Error("PostgreSQL migration connection string must identify a host and database.");
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
host: parsed.hostname,
|
|
32
|
+
port: parsed.port || "5432",
|
|
33
|
+
database,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function createMigrationExecutor(
|
|
38
|
+
manifestConfig: PostgresMigrationManifestConfig,
|
|
39
|
+
context: MigrationExecutorFactoryContext,
|
|
40
|
+
): Promise<MigrationExecutor> {
|
|
41
|
+
const connectionStringEnv =
|
|
42
|
+
context.overrides?.databaseUrlEnv ?? manifestConfig.connectionStringEnv;
|
|
43
|
+
const connectionString = requireMigrationEnvironment(connectionStringEnv, context.env);
|
|
44
|
+
const identity = parseTargetIdentity(connectionString);
|
|
45
|
+
const label = `${identity.host}:${identity.port}/${identity.database}`;
|
|
46
|
+
const target = await createMigrationTarget("postgres", label, [
|
|
47
|
+
identity.host,
|
|
48
|
+
identity.port,
|
|
49
|
+
identity.database,
|
|
50
|
+
]);
|
|
51
|
+
return createDirectMigrationExecutor({
|
|
52
|
+
target,
|
|
53
|
+
createDialect: () =>
|
|
54
|
+
createDialect({
|
|
55
|
+
connectionString,
|
|
56
|
+
pool: { min: 0, max: 1 },
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from "node:path";
|
|
2
|
+
|
|
3
|
+
import { createDirectMigrationExecutor } from "../migrations/direct-executor.js";
|
|
4
|
+
import type { MigrationExecutor, MigrationExecutorFactoryContext } from "../migrations/protocol.js";
|
|
5
|
+
import { createMigrationTarget } from "../migrations/target.js";
|
|
6
|
+
import { createDialect } from "./sqlite.js";
|
|
7
|
+
|
|
8
|
+
export interface SqliteMigrationManifestConfig {
|
|
9
|
+
url: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function resolveDatabasePath(
|
|
13
|
+
manifestConfig: SqliteMigrationManifestConfig,
|
|
14
|
+
context: MigrationExecutorFactoryContext,
|
|
15
|
+
): string {
|
|
16
|
+
const configuredUrl = context.overrides?.database ?? manifestConfig.url;
|
|
17
|
+
if (typeof configuredUrl !== "string" || configuredUrl.length === 0) {
|
|
18
|
+
throw new Error("SQLite migration database path is missing.");
|
|
19
|
+
}
|
|
20
|
+
const path = configuredUrl.startsWith("file:") ? configuredUrl.slice(5) : configuredUrl;
|
|
21
|
+
if (path.length === 0) {
|
|
22
|
+
throw new Error("SQLite migration database path is missing.");
|
|
23
|
+
}
|
|
24
|
+
return isAbsolute(path) ? resolve(path) : resolve(context.projectRoot, path);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function createMigrationExecutor(
|
|
28
|
+
manifestConfig: SqliteMigrationManifestConfig,
|
|
29
|
+
context: MigrationExecutorFactoryContext,
|
|
30
|
+
): Promise<MigrationExecutor> {
|
|
31
|
+
const databasePath = resolveDatabasePath(manifestConfig, context);
|
|
32
|
+
const target = await createMigrationTarget("sqlite", databasePath, [databasePath]);
|
|
33
|
+
return createDirectMigrationExecutor({
|
|
34
|
+
target,
|
|
35
|
+
createDialect: () => createDialect({ url: databasePath }),
|
|
36
|
+
});
|
|
37
|
+
}
|
package/src/emdash-runtime.ts
CHANGED
|
@@ -26,10 +26,14 @@ import { getTrustedProxyHeaders } from "./auth/trusted-proxy.js";
|
|
|
26
26
|
import type { ContentFieldFilters } from "./content-list-query.js";
|
|
27
27
|
import { isSqlite } from "./database/dialect-helpers.js";
|
|
28
28
|
import { kyselyLogOption } from "./database/instrumentation.js";
|
|
29
|
+
import {
|
|
30
|
+
enforceRuntimeMigrationPolicy,
|
|
31
|
+
PendingMigrationsError,
|
|
32
|
+
type RuntimeMigrationMode,
|
|
33
|
+
} from "./database/migrations/policy.js";
|
|
29
34
|
import {
|
|
30
35
|
ConcurrentMigrationTimeoutError,
|
|
31
36
|
MIGRATION_RACE_WAIT_MS,
|
|
32
|
-
runMigrations,
|
|
33
37
|
} from "./database/migrations/runner.js";
|
|
34
38
|
import { AuditRepository } from "./database/repositories/audit.js";
|
|
35
39
|
import { ContentRepository } from "./database/repositories/content.js";
|
|
@@ -87,6 +91,7 @@ import type {
|
|
|
87
91
|
} from "./plugins/types.js";
|
|
88
92
|
import { recordSchedulerHeartbeatSafely } from "./scheduler-health.js";
|
|
89
93
|
import { MAX_COLLECTION_LIST_COLUMNS, type FieldType } from "./schema/types.js";
|
|
94
|
+
import { isMissingTableError } from "./utils/db-errors.js";
|
|
90
95
|
import { hashString } from "./utils/hash.js";
|
|
91
96
|
import { createInitLock, type InitLock, initWithLock } from "./utils/init-lock.js";
|
|
92
97
|
import { createSingleFlightCache, singleFlightCached } from "./utils/single-flight-cache.js";
|
|
@@ -347,6 +352,8 @@ export type CreateSchedulerFn = (executor: CronExecutor) => CronScheduler;
|
|
|
347
352
|
*/
|
|
348
353
|
export interface RuntimeDependencies {
|
|
349
354
|
config: EmDashConfig;
|
|
355
|
+
/** Effective migration mode, resolved once by the runtime entrypoint. */
|
|
356
|
+
migrationMode?: RuntimeMigrationMode;
|
|
350
357
|
plugins: ResolvedPlugin[];
|
|
351
358
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
352
359
|
createDialect: (config: any) => Dialect;
|
|
@@ -1247,8 +1254,10 @@ export class EmDashRuntime {
|
|
|
1247
1254
|
}
|
|
1248
1255
|
};
|
|
1249
1256
|
|
|
1250
|
-
// Initialize database
|
|
1251
|
-
const db = await phase("rt.db", "DB init +
|
|
1257
|
+
// Initialize the database and enforce its configured migration policy.
|
|
1258
|
+
const db = await phase("rt.db", "DB init + migration policy", () =>
|
|
1259
|
+
EmDashRuntime.getDatabase(deps),
|
|
1260
|
+
);
|
|
1252
1261
|
|
|
1253
1262
|
// Resolver for the live connection, mirroring the `get db()` getter
|
|
1254
1263
|
// below (which can't be used here — the runtime instance doesn't exist
|
|
@@ -1311,6 +1320,16 @@ export class EmDashRuntime {
|
|
|
1311
1320
|
// fall back to the singleton, where serialization costs nothing.
|
|
1312
1321
|
let readDb = db;
|
|
1313
1322
|
let readDbDisposable: Kysely<Database> | undefined;
|
|
1323
|
+
const disposeReadDb = async () => {
|
|
1324
|
+
const disposable = readDbDisposable;
|
|
1325
|
+
readDbDisposable = undefined;
|
|
1326
|
+
if (!disposable) return;
|
|
1327
|
+
try {
|
|
1328
|
+
await disposable.destroy();
|
|
1329
|
+
} catch {
|
|
1330
|
+
// Non-fatal — the underlying binding is shared and needs no teardown.
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1314
1333
|
if (ownsConfiguredDb && deps.createCoalescingDialect && deps.config.database) {
|
|
1315
1334
|
try {
|
|
1316
1335
|
const dialect = deps.createCoalescingDialect(deps.config.database.config);
|
|
@@ -1323,6 +1342,12 @@ export class EmDashRuntime {
|
|
|
1323
1342
|
}
|
|
1324
1343
|
}
|
|
1325
1344
|
const optionsRepo = new OptionsRepository(readDb);
|
|
1345
|
+
let missingManualSchemaError: unknown;
|
|
1346
|
+
const captureMissingManualSchema = (error: unknown) => {
|
|
1347
|
+
if ((deps.migrationMode ?? "auto") === "manual" && isMissingTableError(error)) {
|
|
1348
|
+
missingManualSchemaError ??= error;
|
|
1349
|
+
}
|
|
1350
|
+
};
|
|
1326
1351
|
|
|
1327
1352
|
const readSiteInfo = async () => {
|
|
1328
1353
|
const siteOpts = await optionsRepo.getMany<string>([
|
|
@@ -1351,14 +1376,16 @@ export class EmDashRuntime {
|
|
|
1351
1376
|
.select(["plugin_id", "status"])
|
|
1352
1377
|
.execute();
|
|
1353
1378
|
pluginStates = new Map(states.map((s) => [s.plugin_id, s.status]));
|
|
1354
|
-
} catch {
|
|
1379
|
+
} catch (error) {
|
|
1380
|
+
captureMissingManualSchema(error);
|
|
1355
1381
|
// _plugin_state may not exist yet on a pre-migration db.
|
|
1356
1382
|
}
|
|
1357
1383
|
}),
|
|
1358
1384
|
phase("rt.site", "Site info options", async () => {
|
|
1359
1385
|
try {
|
|
1360
1386
|
siteInfo = await readSiteInfo();
|
|
1361
|
-
} catch {
|
|
1387
|
+
} catch (error) {
|
|
1388
|
+
captureMissingManualSchema(error);
|
|
1362
1389
|
// options may not exist yet on a pre-migration db.
|
|
1363
1390
|
}
|
|
1364
1391
|
}),
|
|
@@ -1387,7 +1414,8 @@ export class EmDashRuntime {
|
|
|
1387
1414
|
}
|
|
1388
1415
|
})();
|
|
1389
1416
|
seedGate = { collectionCount: collectionCount.count, setupDone };
|
|
1390
|
-
} catch {
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
captureMissingManualSchema(error);
|
|
1391
1419
|
// Leave the "already set up" default so a read failure never
|
|
1392
1420
|
// triggers a seed onto a half-built db.
|
|
1393
1421
|
}
|
|
@@ -1396,6 +1424,10 @@ export class EmDashRuntime {
|
|
|
1396
1424
|
}
|
|
1397
1425
|
|
|
1398
1426
|
await Promise.all(coldStartReads);
|
|
1427
|
+
if (missingManualSchemaError) {
|
|
1428
|
+
await disposeReadDb();
|
|
1429
|
+
throw missingManualSchemaError;
|
|
1430
|
+
}
|
|
1399
1431
|
|
|
1400
1432
|
if (
|
|
1401
1433
|
localeCasingRepairVersion &&
|
|
@@ -1452,13 +1484,7 @@ export class EmDashRuntime {
|
|
|
1452
1484
|
}
|
|
1453
1485
|
|
|
1454
1486
|
// The read connection is single-use; everything below uses the singleton.
|
|
1455
|
-
|
|
1456
|
-
try {
|
|
1457
|
-
await readDbDisposable.destroy();
|
|
1458
|
-
} catch {
|
|
1459
|
-
// Non-fatal — the underlying binding is shared and needs no teardown.
|
|
1460
|
-
}
|
|
1461
|
-
}
|
|
1487
|
+
await disposeReadDb();
|
|
1462
1488
|
|
|
1463
1489
|
const enabledPlugins = new Set<string>();
|
|
1464
1490
|
for (const plugin of deps.plugins) {
|
|
@@ -1911,13 +1937,16 @@ export class EmDashRuntime {
|
|
|
1911
1937
|
const db = new Kysely<Database>({ dialect, log: kyselyLogOption() });
|
|
1912
1938
|
|
|
1913
1939
|
try {
|
|
1914
|
-
await
|
|
1940
|
+
await enforceRuntimeMigrationPolicy(db, deps.migrationMode ?? "auto");
|
|
1915
1941
|
} catch (error) {
|
|
1916
1942
|
// Timing out behind another instance's in-flight migrations
|
|
1917
1943
|
// is not a failure of OUR migration — the holder may just be
|
|
1918
1944
|
// slow. Don't back off for it: the next request waits again
|
|
1919
1945
|
// and init recovers the moment the holder finishes.
|
|
1920
|
-
if (
|
|
1946
|
+
if (
|
|
1947
|
+
!(error instanceof ConcurrentMigrationTimeoutError) &&
|
|
1948
|
+
!(error instanceof PendingMigrationsError)
|
|
1949
|
+
) {
|
|
1921
1950
|
holder.failures.set(cacheKey, {
|
|
1922
1951
|
at: Date.now(),
|
|
1923
1952
|
message: error instanceof Error ? error.message : String(error),
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { I18nConfig } from "./config.js";
|
|
2
|
+
|
|
3
|
+
export interface AstroLocaleObject {
|
|
4
|
+
path: string;
|
|
5
|
+
codes: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface AstroI18nInput {
|
|
9
|
+
defaultLocale: string;
|
|
10
|
+
locales: readonly (string | AstroLocaleObject)[];
|
|
11
|
+
fallback?: Readonly<Record<string, string | undefined>>;
|
|
12
|
+
routing?: string | { prefixDefaultLocale?: boolean };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function normalizeAstroI18n(config: AstroI18nInput | null | undefined): I18nConfig | null {
|
|
16
|
+
if (!config) return null;
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
defaultLocale: config.defaultLocale,
|
|
20
|
+
locales: config.locales.map((locale) => (typeof locale === "string" ? locale : locale.path)),
|
|
21
|
+
fallback: config.fallback
|
|
22
|
+
? Object.fromEntries(
|
|
23
|
+
Object.entries(config.fallback).filter(
|
|
24
|
+
(entry): entry is [string, string] => entry[1] !== undefined,
|
|
25
|
+
),
|
|
26
|
+
)
|
|
27
|
+
: undefined,
|
|
28
|
+
prefixDefaultLocale:
|
|
29
|
+
typeof config.routing === "object" ? (config.routing.prefixDefaultLocale ?? false) : false,
|
|
30
|
+
};
|
|
31
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
// Database (only types and utilities - internal functions not exported)
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
EmDashDatabaseError,
|
|
4
|
+
getMigrationStatus,
|
|
5
|
+
getExactMigrationStatus,
|
|
6
|
+
MIGRATION_NAMES,
|
|
7
|
+
} from "./database/index.js";
|
|
3
8
|
export type {
|
|
4
9
|
DatabaseConfig,
|
|
5
10
|
MigrationStatus,
|
|
11
|
+
ExactMigrationStatus,
|
|
6
12
|
Database,
|
|
7
13
|
UserTable,
|
|
8
14
|
MediaTable,
|