import { App, Context, staticFiles } from "fresh";
import { type State } from "./utils.ts";
import { loadSync } from "$std/dotenv/mod.ts";
// Allow empty values for optional Stripe variables
loadSync({ allowEmptyValues: true, export: true });
import { checkDatabaseConnection } from "./db/db.ts";
const isDevelopment = Deno.env.get("DEVELOPMENT") === "true";
//console.log("Development mode:", isDevelopment);
/** Error page HTML for service unavailability */
const SERVICE_UNAVAILABLE_HTML = `
Service Unavailable
🔧
The problem is on our side!
We will fix this as soon as we can.
`;
/** Check if required KV cache files exist */
function checkKvCacheFiles(): boolean {
// const requiredFiles = ["./data/kv-cache-shm", "./data/kv-cache-wal"];
// for (const file of requiredFiles) {
// try {
// Deno.statSync(file);
// } catch {
// console.error(`⚠️ Required file missing: ${file}`);
// return false;
// }
// }
return true;
}
/** Perform all startup checks */
async function performStartupChecks(): Promise {
//console.log("Checking startup requirements...");
// Check KV cache files
const kvFilesExist = checkKvCacheFiles();
if (!kvFilesExist) {
console.error(
"⚠️ KV cache files missing - app will display maintenance page",
);
return false;
}
//console.log("✅ KV cache files found");
// Check database connection
//console.log("Checking database connection...");
const dbAvailable = await checkDatabaseConnection();
if (!dbAvailable) {
console.error(
"⚠️ Database connection failed - app will display maintenance page",
);
return false;
}
//console.log("✅ Database connection successful");
return true;
}
// Run startup checks first
const isAppReady = await performStartupChecks();
// Create app based on startup check result
export const app = new App();
if (isAppReady) {
// Full app with all routes and middleware
const { InitiPGSessionMiddleware } = await import(
"./services/stateMiddleware.ts"
);
app.use(staticFiles());
app.get("/health", (_ctx: Context) => {
console.log("Health check");
return new Response("OK");
});
// app.post("/graph-update", async (ctx: Context) => {
// console.log("Graph update");
// const body = await ctx.req.json();
// //console.log(body);
// //const { userId, roles, organization } = body;
// // await inMemoryCacheKv.set(["ciam", userId], {
// // userId,
// // roles,
// // organization,
// // lastSynced: Date.now(),
// // });
// //console.log(`Graph update applied for user ${userId}`);
// return new Response("Graph update stored in cache", { status: 202 });
// });
// TODO: add a well-known endpoint
// app.get("/.well-known/acme-challenge/:token", (ctx: Context) => {
// const token = ctx.params.token;
// const content = `${token}.EXAMPLE_ACCOUNT_THUMBPRINT`;
// return new Response(content, {
// status: 200,
// headers: {
// "content-type": "text/plain; charset=utf-8",
// "cache-control": "public, max-age=0, must-revalidate",
// },
// });
// });
app.use(InitiPGSessionMiddleware());
app.fsRoutes();
//console.log("✅ Full application loaded");
} else {
// Maintenance mode - serve error page for all routes
app.use(staticFiles());
app.get("/health", () => {
return new Response("Service Unavailable", { status: 503 });
});
app.use(() => {
return new Response(SERVICE_UNAVAILABLE_HTML, {
status: 503,
headers: { "Content-Type": "text/html; charset=utf-8" },
});
});
console.log("⚠️ Maintenance mode - serving error page only");
// Start periodic database connection check (every 60 seconds)
setInterval(async () => {
console.log("🔄 Checking if database connection is restored...");
const dbAvailable = await checkDatabaseConnection();
if (dbAvailable) {
console.log("✅ Database connection restored! Restarting app...");
// Check if running in development mode
const restartCmd = isDevelopment ? "exec deno task dev" : "exec ./server";
// Use exec to replace shell with new process, keeping terminal connection
const command = new Deno.Command("sh", {
args: [
"-c",
`lsof -ti:8080 | xargs kill -9 2>/dev/null || true; ${restartCmd}`,
],
cwd: Deno.cwd(),
stdin: "inherit",
stdout: "inherit",
stderr: "inherit",
});
command.spawn();
Deno.exit(0);
} else {
console.log("❌ Database still unavailable, will retry in 60 seconds");
}
}, 60_000);
}
// if (import.meta.main) {
// await app.listen();
// }