2024-09-01 13:26:37 -05:00
|
|
|
#!/usr/bin/env node
|
|
|
|
import "./polyfill.js";
|
|
|
|
import Koa from "koa";
|
|
|
|
import serve from "koa-static";
|
2024-09-07 16:40:16 -05:00
|
|
|
import path, { join } from "node:path";
|
2024-09-01 13:26:37 -05:00
|
|
|
import cors from "@koa/cors";
|
|
|
|
import fs from "node:fs";
|
|
|
|
import { fileURLToPath } from "node:url";
|
2024-09-07 16:40:16 -05:00
|
|
|
import send from "koa-send";
|
2024-09-01 13:26:37 -05:00
|
|
|
|
|
|
|
import logger from "./logger.js";
|
|
|
|
import { isHttpError } from "./helpers/error.js";
|
|
|
|
import { resolveNpubFromHostname } from "./helpers/dns.js";
|
2024-09-07 16:40:16 -05:00
|
|
|
import { downloadSite } from "./downloader.js";
|
|
|
|
import { downloaded } from "./cache.js";
|
2024-09-01 13:26:37 -05:00
|
|
|
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
|
|
|
|
const app = new Koa();
|
|
|
|
|
|
|
|
// set CORS headers
|
|
|
|
app.use(
|
|
|
|
cors({
|
|
|
|
origin: "*",
|
|
|
|
allowMethods: "*",
|
|
|
|
allowHeaders: "Authorization,*",
|
|
|
|
exposeHeaders: "*",
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
|
|
|
// handle errors
|
|
|
|
app.use(async (ctx, next) => {
|
|
|
|
try {
|
|
|
|
await next();
|
|
|
|
} catch (err) {
|
|
|
|
if (isHttpError(err)) {
|
|
|
|
const status = (ctx.status = err.status || 500);
|
|
|
|
if (status >= 500) console.error(err.stack);
|
|
|
|
ctx.body = status > 500 ? { message: "Something went wrong" } : { message: err.message };
|
|
|
|
} else {
|
|
|
|
console.log(err);
|
|
|
|
ctx.status = 500;
|
|
|
|
ctx.body = { message: "Something went wrong" };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-09-07 16:40:16 -05:00
|
|
|
// map pubkeys to folders in sites dir
|
2024-09-01 13:26:37 -05:00
|
|
|
app.use(async (ctx, next) => {
|
|
|
|
const pubkey = (ctx.state.pubkey = await resolveNpubFromHostname(ctx.hostname));
|
|
|
|
|
|
|
|
if (pubkey) {
|
2024-09-07 16:40:16 -05:00
|
|
|
if (!(await downloaded.get(pubkey))) {
|
2024-09-07 17:15:12 -05:00
|
|
|
// don't wait for download
|
|
|
|
downloadSite(pubkey);
|
|
|
|
|
|
|
|
await downloaded.set(pubkey, true);
|
2024-09-01 13:26:37 -05:00
|
|
|
}
|
|
|
|
|
2024-09-07 16:40:16 -05:00
|
|
|
await send(ctx, join(pubkey, ctx.path), { root: "data/sites", index: "index.html" });
|
2024-09-01 13:26:37 -05:00
|
|
|
} else await next();
|
|
|
|
});
|
|
|
|
|
2024-09-07 16:40:16 -05:00
|
|
|
// serve static sites
|
|
|
|
app.use(serve("sites"));
|
|
|
|
|
2024-09-01 13:26:37 -05:00
|
|
|
// serve static files from public
|
|
|
|
try {
|
|
|
|
const www = path.resolve(process.cwd(), "public");
|
|
|
|
fs.statSync(www);
|
|
|
|
app.use(serve(www));
|
|
|
|
} catch (error) {
|
|
|
|
const www = path.resolve(__dirname, "../public");
|
|
|
|
app.use(serve(www));
|
|
|
|
}
|
|
|
|
|
|
|
|
app.listen(process.env.PORT || 3000);
|
|
|
|
logger("Started on port", process.env.PORT || 3000);
|
|
|
|
|
|
|
|
async function shutdown() {
|
|
|
|
logger("Shutting down...");
|
|
|
|
process.exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
process.addListener("SIGTERM", shutdown);
|
|
|
|
process.addListener("SIGINT", shutdown);
|