import { Page } from "./metadata"; import generators from "./generate"; import express, { Router } from "express"; import morgan from "morgan"; import bodyParser from "body-parser"; import activitypub from "./activitypub"; import validateHttpSig from "./activitypub/middleware/http-signature"; import "reflect-metadata"; import { createConnection} from "typeorm"; import * as path from "path"; import chokidar from "chokidar"; async function generate(): Promise { generators.copy(); generators.css(); generators.errors(); generators.tutorials().then(generators.rss.tutorials); const posts = await generators.posts(); generators.homepage(posts); generators.years(posts); generators.rss.posts(posts) generators.tags(posts).then(generators.rss.tags); generators.archive(posts); return posts; } function watch() { const watcher = chokidar.watch("site/", { ignoreInitial: true, }); watcher.on("all", (event, path) => { console.log(`Regenerating due to ${event} ${path}`); // todo: this could be smarter about not regenerating everything generate(); }); } (async () => { if (process.env.NODE_ENV === undefined) { process.env.NODE_ENV = "development"; } const app = express(); app.use(morgan("dev")); app.use(bodyParser.json({ type: "application/activity+json" })); const connection = await createConnection({ "type": "postgres", "host": process.env.DB_HOST || "localhost", "port": process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 5432, "username": process.env.DB_USERNAME || "blog", "password": process.env.DB_PASSWORD || "blog", "database": process.env.DB_DATABASE || "blog", "synchronize": true, "logging": true, "entities": [ path.join(__dirname, "entity/**/*.{ts,js}") ], "migrations": [ path.join(__dirname, "migration/**/*.{ts,js}") ], "subscribers": [ path.join(__dirname, "subscriber/**/*.{ts,js}") ], "cli": { "entitiesDir": "lib/entity", "migrationsDir": "lib/migration", "subscribersDir": "lib/subscriber" } }); const posts = await generate(); if (process.env.NODE_ENV === "development") { watch(); } await activitypub.articles.setup(posts); const apRouter = Router(); apRouter.use(validateHttpSig); await activitypub.actor(apRouter); activitypub.comments(apRouter); activitypub.followers(apRouter); activitypub.inbox(apRouter); await activitypub.nodeinfo(apRouter); activitypub.webfinger(apRouter); activitypub.articles.route(apRouter); app.use(apRouter); app.use(express.static("out")); // redirect posts with changed permalinks for (const post of posts) { if (post.metadata.oldPermalink) { app.get(post.metadata.oldPermalink, (req, res) => { res.status(301).redirect(post.metadata.permalink); }); } } app.use((err, req, res, next) => { console.error("Unhandled error:", err); res.status(500).sendFile("500.html", { root: "out" }); }); app.use((req, res, next) => { res.status(404).sendFile("404.html", { root: "out" }); }); const port = process.env.PORT || 8083; app.listen(port, async () => { console.log(`Listening on port ${port}`); const toFederate = await activitypub.articles.toFederate(); activitypub.federate(toFederate); }); })();