t00-multiuser/server/controller/Controller.ts

83 lines
3.2 KiB
TypeScript

import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import { Console } from "hsconsole";
import Session from "../objects/Session";
import SessionUser from "../objects/SessionUser";
import RequestCtx from "../objects/RequestCtx";
// prepare for ts-ignore :3
// TODO: figure out some runtime field / type checking so
// can auto badRequest on missing stuff.
export default abstract class Controller {
public static FastifyInstance:FastifyInstance;
public constructor() {
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
const controllerName = this.constructor.name.replace("Controller", "").toLowerCase();
for (const method of methods) {
if (method === "constructor" || method[0] !== method[0].toUpperCase()) { // * Anything that starts with lowercase we'll consider "private"
continue;
}
const params = method.split("_");
const methodNameRaw = params.splice(0, 1)[0]
const methodName = methodNameRaw.toLowerCase();
const doAuth = !params.includes("AllowAnonymous");
// @ts-ignore
const controllerRequestHandler = this[method];
const requestHandler = (req:FastifyRequest, res:FastifyReply) => {
let session = Session.CheckValiditiy(req.cookies);
if (doAuth && session === undefined) {
return res.redirect(`/account/login?returnTo=${encodeURIComponent(req.url)}`);
}
const requestCtx = new RequestCtx(req, res, controllerName, methodName, session);
controllerRequestHandler.bind(requestCtx)(req.method === "GET" ? req.query : req.body);
}
let funcMethods:Array<string> = [];
for (const param of params) {
if (param === "Get" || param === "Post" || param === "Put") {
funcMethods.push(param);
// @ts-ignore
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}/${methodName === "index" ? "" : methodName}`, requestHandler);
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}/${methodName === "index" ? "" : methodName}" as ${param}`);
if (methodName === "index") {
// @ts-ignore
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}/${methodName}`, requestHandler);
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}/${methodName}" as ${param}`);
// @ts-ignore
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}`, requestHandler);
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}" as ${param}`);
}
}
}
if (controllerName === "home" && methodName === "index") {
for (const httpMethod of funcMethods) {
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/" as ${httpMethod}`);
// @ts-ignore
Controller.FastifyInstance[httpMethod.toLowerCase()](`/`, requestHandler);
}
}
}
}
// not real, these RequestCtx so they autocomplete :)
// yeah, i know. this is terrible.
// Fields
// @ts-ignore
public session:SessionUser;
// @ts-ignore
public req: FastifyRequest;
// @ts-ignore
public res: FastifyReply;
// Methods
view(view?:string | Object, model?: Object) {}
redirectToAction(action:string, controller?:string) {}
ok(message?:string) {}
badRequest(message?:string) {}
unauthorised(message?:string) {}
}