Merge pull request #8 from emdash-cms/fix/fresh-deploy-setup-redirect
fix: redirect to setup wizard on fresh deployments
This commit is contained in:
5
.changeset/cruel-forks-float.md
Normal file
5
.changeset/cruel-forks-float.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@emdash-cms/admin": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Update branding
|
||||||
5
.changeset/quick-parks-smoke.md
Normal file
5
.changeset/quick-parks-smoke.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"emdash": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix crash on fresh deployments when the first request hits a public page before setup has run. The middleware now detects an empty database and redirects to the setup wizard instead of letting template helpers query missing tables.
|
||||||
@@ -54,6 +54,16 @@ let runtimeInitializing = false;
|
|||||||
/** Whether i18n config has been initialized from the virtual module */
|
/** Whether i18n config has been initialized from the virtual module */
|
||||||
let i18nInitialized = false;
|
let i18nInitialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we've verified the database has been set up.
|
||||||
|
* On a fresh deployment the first request may hit a public page, bypassing
|
||||||
|
* runtime init. Without this check, template helpers like getSiteSettings()
|
||||||
|
* would query an empty database and crash. Once verified (or once the runtime
|
||||||
|
* has initialized via an admin/API request), this stays true for the worker's
|
||||||
|
* lifetime.
|
||||||
|
*/
|
||||||
|
let setupVerified = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get EmDash configuration from virtual module
|
* Get EmDash configuration from virtual module
|
||||||
*/
|
*/
|
||||||
@@ -190,6 +200,28 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|||||||
if (!isEmDashRoute && !isPublicRuntimeRoute && !hasEditCookie && !hasPreviewToken) {
|
if (!isEmDashRoute && !isPublicRuntimeRoute && !hasEditCookie && !hasPreviewToken) {
|
||||||
const sessionUser = await context.session?.get("user");
|
const sessionUser = await context.session?.get("user");
|
||||||
if (!sessionUser && !playgroundDb) {
|
if (!sessionUser && !playgroundDb) {
|
||||||
|
// On a fresh deployment the database may be completely empty.
|
||||||
|
// Public pages call getSiteSettings() / getMenu() via getDb(), which
|
||||||
|
// bypasses runtime init and would crash with "no such table: options".
|
||||||
|
// Do a one-time lightweight probe using the same getDb() instance the
|
||||||
|
// page will use: if the migrations table doesn't exist, no migrations
|
||||||
|
// have ever run -- redirect to the setup wizard.
|
||||||
|
if (!setupVerified) {
|
||||||
|
try {
|
||||||
|
const { getDb } = await import("../loader.js");
|
||||||
|
const db = await getDb();
|
||||||
|
await db
|
||||||
|
.selectFrom("_emdash_migrations" as keyof Database)
|
||||||
|
.selectAll()
|
||||||
|
.limit(1)
|
||||||
|
.execute();
|
||||||
|
setupVerified = true;
|
||||||
|
} catch {
|
||||||
|
// Table doesn't exist -> fresh database, redirect to setup
|
||||||
|
return context.redirect("/_emdash/admin/setup");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const response = await next();
|
const response = await next();
|
||||||
setBaselineSecurityHeaders(response);
|
setBaselineSecurityHeaders(response);
|
||||||
return response;
|
return response;
|
||||||
@@ -210,6 +242,9 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|||||||
// Get or create runtime
|
// Get or create runtime
|
||||||
const runtime = await getRuntime(config);
|
const runtime = await getRuntime(config);
|
||||||
|
|
||||||
|
// Runtime init runs migrations, so the DB is guaranteed set up
|
||||||
|
setupVerified = true;
|
||||||
|
|
||||||
// Get manifest (cached after first call)
|
// Get manifest (cached after first call)
|
||||||
const manifest = await runtime.getManifest();
|
const manifest = await runtime.getManifest();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user