pingql/apps/api/src/index.ts

59 lines
1.8 KiB
TypeScript

import { Elysia } from "elysia";
import { cors } from "@elysiajs/cors";
import { ingest } from "./routes/pings";
import { monitors } from "./routes/monitors";
import { account } from "./routes/auth";
import { internal } from "./routes/internal";
import { migrate } from "./db";
await migrate();
const CORS_ORIGIN = process.env.CORS_ORIGINS?.split(",") ?? ["https://pingql.com"];
const CORS_HEADERS = {
"access-control-allow-credentials": "true",
"access-control-allow-methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
"access-control-allow-headers": "Content-Type, Authorization",
};
const SECURITY_HEADERS = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Strict-Transport-Security": "max-age=63072000; includeSubDomains",
"X-XSS-Protection": "0",
"Referrer-Policy": "strict-origin-when-cross-origin",
};
const app = new Elysia()
// Security headers on all responses
.onAfterHandle(({ set }) => {
Object.assign(set.headers, SECURITY_HEADERS);
})
.use(cors({
origin: CORS_ORIGIN,
credentials: true,
allowedHeaders: ["Content-Type", "Authorization"],
methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
preflight: true,
}))
// Explicit OPTIONS handler for cross-origin preflight
.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: { ...CORS_HEADERS, "access-control-allow-origin": allowed },
});
})
.get("/", () => ({
name: "PingQL API",
version: "1",
docs: "https://pingql.com/docs",
}))
.use(account)
.use(monitors)
.use(ingest)
.use(internal)
.listen(3001);
console.log(`PingQL API running at http://localhost:${app.server?.port}`);