[SILO-454] chore: refactor decorator, logger packages (#7618)

* [SILO-454] chore: refactor decorator, logger packages

- add registerControllers function abstracting both rest, ws controllers
- update logger to a simple json based logger

* fix: logger instance and middleware

* fix: type and module resolutions

* fix: lodash type package update

* fix: bypass lint errors in decorators

* chore: format changes

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
Surya Prashanth 2025-08-29 14:29:16 +05:30 committed by GitHub
parent 489a6e1e94
commit 258d24bf06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 222 additions and 352 deletions

View file

@ -1,15 +1,9 @@
import { RequestHandler, Router } from "express";
import type { RequestHandler, Router, Request } from "express";
import type { WebSocket } from "ws";
import "reflect-metadata";
type HttpMethod =
| "get"
| "post"
| "put"
| "delete"
| "patch"
| "options"
| "head"
| "ws";
type HttpMethod = "get" | "post" | "put" | "delete" | "patch" | "options" | "head" | "ws";
interface ControllerInstance {
[key: string]: unknown;
@ -22,40 +16,85 @@ interface ControllerConstructor {
export function registerControllers(
router: Router,
Controller: ControllerConstructor,
controllers: ControllerConstructor[],
dependencies: any[] = []
): void {
controllers.forEach((Controller) => {
// Create the controller instance with dependencies
const instance = new Controller(...dependencies);
// Determine if it's a WebSocket controller or REST controller by checking
// if it has any methods with the "ws" method metadata
const isWebsocket = Object.getOwnPropertyNames(Controller.prototype).some((methodName) => {
if (methodName === "constructor") return false;
return Reflect.getMetadata("method", instance, methodName) === "ws";
});
if (isWebsocket) {
// Register as WebSocket controller
// Pass the existing instance with dependencies to avoid creating a new instance without them
registerWebSocketController(router, Controller, instance);
} else {
// Register as REST controller - doesn't accept an instance parameter
registerRestController(router, Controller);
}
});
}
function registerRestController(router: Router, Controller: ControllerConstructor): void {
const instance = new Controller();
const baseRoute = Reflect.getMetadata("baseRoute", Controller) as string;
Object.getOwnPropertyNames(Controller.prototype).forEach((methodName) => {
if (methodName === "constructor") return; // Skip the constructor
const method = Reflect.getMetadata(
"method",
instance,
methodName,
) as HttpMethod;
const method = Reflect.getMetadata("method", instance, methodName) as HttpMethod;
const route = Reflect.getMetadata("route", instance, methodName) as string;
const middlewares =
(Reflect.getMetadata(
"middlewares",
instance,
methodName,
) as RequestHandler[]) || [];
const middlewares = (Reflect.getMetadata("middlewares", instance, methodName) as RequestHandler[]) || [];
if (method && route) {
const handler = instance[methodName] as unknown;
if (typeof handler === "function") {
if (method !== "ws") {
(
router[method] as (
path: string,
...handlers: RequestHandler[]
) => void
)(`${baseRoute}${route}`, ...middlewares, handler.bind(instance));
(router[method] as (path: string, ...handlers: RequestHandler[]) => void)(
`${baseRoute}${route}`,
...middlewares,
handler.bind(instance)
);
}
}
}
});
}
function registerWebSocketController(
router: Router,
Controller: ControllerConstructor,
existingInstance?: ControllerInstance
): void {
const instance = existingInstance || new Controller();
const baseRoute = Reflect.getMetadata("baseRoute", Controller) as string;
Object.getOwnPropertyNames(Controller.prototype).forEach((methodName) => {
if (methodName === "constructor") return; // Skip the constructor
const method = Reflect.getMetadata("method", instance, methodName) as string;
const route = Reflect.getMetadata("route", instance, methodName) as string;
if (method === "ws" && route) {
const handler = instance[methodName] as unknown;
if (typeof handler === "function" && "ws" in router && typeof router.ws === "function") {
router.ws(`${baseRoute}${route}`, (ws: WebSocket, req: Request) => {
try {
handler.call(instance, ws, req);
} catch (error) {
console.error(`WebSocket error in ${Controller.name}.${methodName}`, error);
ws.close(1011, error instanceof Error ? error.message : "Internal server error");
}
});
}
}
});
}