60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
import { Elysia } from "elysia";
|
|
import { migrate } from "./db";
|
|
import { routes } from "./routes";
|
|
import { checkPayments, expireProPlans } from "./monitor";
|
|
|
|
await migrate();
|
|
|
|
const SECURITY_HEADERS = {
|
|
"X-Content-Type-Options": "nosniff",
|
|
"X-Frame-Options": "DENY",
|
|
"Strict-Transport-Security": "max-age=63072000; includeSubDomains",
|
|
"Referrer-Policy": "strict-origin-when-cross-origin",
|
|
};
|
|
|
|
const CORS_ORIGIN = process.env.CORS_ORIGINS?.split(",") ?? ["https://pingql.com"];
|
|
|
|
const app = new Elysia()
|
|
.onAfterHandle(({ set }) => {
|
|
Object.assign(set.headers, SECURITY_HEADERS);
|
|
})
|
|
// CORS for web app
|
|
.onRequest(({ request, set }) => {
|
|
const origin = request.headers.get("origin") ?? "";
|
|
if (CORS_ORIGIN.includes(origin)) {
|
|
set.headers["access-control-allow-origin"] = origin;
|
|
set.headers["access-control-allow-credentials"] = "true";
|
|
set.headers["access-control-allow-methods"] = "GET, POST, OPTIONS";
|
|
set.headers["access-control-allow-headers"] = "Content-Type, Authorization";
|
|
}
|
|
})
|
|
.options("/*", ({ request }) => {
|
|
const origin = request.headers.get("origin") ?? "";
|
|
const allowed = CORS_ORIGIN.includes(origin) ? origin : CORS_ORIGIN[0];
|
|
return new Response(null, {
|
|
status: 204,
|
|
headers: {
|
|
"access-control-allow-origin": allowed,
|
|
"access-control-allow-credentials": "true",
|
|
"access-control-allow-methods": "GET, POST, OPTIONS",
|
|
"access-control-allow-headers": "Content-Type, Authorization",
|
|
},
|
|
});
|
|
})
|
|
.get("/", () => ({ name: "PingQL Pay", version: "1" }))
|
|
.use(routes)
|
|
.listen(3002);
|
|
|
|
console.log(`PingQL Pay running at http://localhost:${app.server?.port}`);
|
|
|
|
// Run immediately on startup, then every 30 seconds
|
|
checkPayments().catch((err) => console.error("Payment check failed:", err));
|
|
setInterval(() => {
|
|
checkPayments().catch((err) => console.error("Payment check failed:", err));
|
|
}, 30_000);
|
|
|
|
// Expire pro plans every hour
|
|
setInterval(() => {
|
|
expireProPlans().catch((err) => console.error("Plan expiry check failed:", err));
|
|
}, 60 * 60_000);
|