@d3vtool/ex-frame
Version:
This library enhances Express.js by providing a more organized structure for web API projects, along with improved control and error handling capabilities.
147 lines (146 loc) • 8.35 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ExFrame_instances, _ExFrame_expressApp, _ExFrame_errorMap, _ExFrame_injectorMap, _ExFrame_getPossibleMatchingRoutes, _ExFrame_globalErrorHandler;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExFrame = void 0;
const express_1 = require("express");
const ex_middleware_1 = require("./ex-middleware");
const ex_helpers_1 = require("./ex-helpers");
class ExFrame {
constructor(expressApp) {
_ExFrame_instances.add(this);
_ExFrame_expressApp.set(this, void 0);
_ExFrame_errorMap.set(this, {});
_ExFrame_injectorMap.set(this, {
transient: {},
scoped: {},
singleton: {}
});
__classPrivateFieldSet(this, _ExFrame_expressApp, expressApp, "f");
}
addTransient(service) {
const serviceName = service.name.toLowerCase();
if (__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").scoped[serviceName] ||
__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").singleton[serviceName]) {
throw new Error(`'${serviceName} is already registered service.'`);
}
__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").transient[serviceName] = service;
}
addScoped(service) {
const serviceName = service.name.toLowerCase();
if (__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").transient[serviceName] ||
__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").singleton[serviceName]) {
throw new Error(`'${serviceName} is already registered service.'`);
}
__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").scoped[serviceName] = service;
}
addSingleton(service) {
const serviceName = service.name.toLowerCase();
if (__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").scoped[serviceName] ||
__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").transient[serviceName]) {
throw new Error(`'${serviceName} is already registered service.'`);
}
__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").singleton[serviceName] = new service();
}
controller(controller) {
const parentRoute = controller?.parentRoute ?? "/";
const parentErrorHandler = controller?.errorHandler;
const parentMiddlewares = controller.handlers ?? [];
const parentHttpMethod = controller?.parentHttpMethod?.toLowerCase();
if (parentErrorHandler && parentRoute !== "/") {
__classPrivateFieldGet(this, _ExFrame_errorMap, "f")[parentRoute] = parentErrorHandler;
}
const parentRouter = (0, express_1.Router)();
for (const staticMethod of (0, ex_helpers_1.getStaticMethods)(controller)) {
const controllerMethod = controller[staticMethod];
const route = controllerMethod?.route;
const httpMethod = controllerMethod?.httpMethod?.toLowerCase();
const controllerMiddleware = controllerMethod?.handlers ?? [];
const errorHandler = controllerMethod?.errorHandler;
const transientServiceName = controllerMethod?.transientServiceName;
const scopedServiceName = controllerMethod?.scopedServiceName;
const singletonServiceName = controllerMethod?.singletonServiceName;
if (!controllerMethod ||
!route ||
!httpMethod)
continue;
if (errorHandler) {
const fullRoute = `${parentRoute}${route === "/" ? "" : route}`.trim();
__classPrivateFieldGet(this, _ExFrame_errorMap, "f")[fullRoute] = errorHandler;
}
parentRouter[httpMethod](route, controllerMiddleware, (0, ex_middleware_1.asyncHandler)(async (req, res, next) => {
let service;
switch (true) {
case Boolean(__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").transient[transientServiceName]):
service = new (__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").transient[transientServiceName])();
break;
case Boolean(__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").scoped[scopedServiceName]):
if (!req["__scope__"][scopedServiceName]) {
service = new (__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").scoped[scopedServiceName])();
req["__scope__"][scopedServiceName] = service;
}
break;
case Boolean(__classPrivateFieldGet(this, _ExFrame_injectorMap, "f").singleton[singletonServiceName]):
service = __classPrivateFieldGet(this, _ExFrame_injectorMap, "f").singleton[singletonServiceName];
break;
default:
throw new Error("Unknown service call.");
}
if (service) {
await controllerMethod(service, req, res, next);
}
else {
await controllerMethod(req, res, next);
}
}));
}
if (parentHttpMethod) {
__classPrivateFieldGet(this, _ExFrame_expressApp, "f")[parentHttpMethod](parentRoute, parentMiddlewares, parentRouter);
return;
}
__classPrivateFieldGet(this, _ExFrame_expressApp, "f").use(parentRoute, parentMiddlewares, parentRouter);
}
listen(...args) {
__classPrivateFieldGet(this, _ExFrame_expressApp, "f").use(__classPrivateFieldGet(this, _ExFrame_instances, "m", _ExFrame_globalErrorHandler).bind(this));
return __classPrivateFieldGet(this, _ExFrame_expressApp, "f").listen(...args);
}
}
exports.ExFrame = ExFrame;
_ExFrame_expressApp = new WeakMap(), _ExFrame_errorMap = new WeakMap(), _ExFrame_injectorMap = new WeakMap(), _ExFrame_instances = new WeakSet(), _ExFrame_getPossibleMatchingRoutes = function _ExFrame_getPossibleMatchingRoutes(route, map) {
const routeSeg = route.split("/");
const viableERoutes = [];
for (const errorRoute in map) {
const eRouteSeg = errorRoute.split("/");
if (errorRoute.includes("/:") && eRouteSeg.length === routeSeg.length) {
viableERoutes.unshift(errorRoute);
}
else if (route.includes(errorRoute)) {
viableERoutes.push(errorRoute);
}
}
return viableERoutes;
}, _ExFrame_globalErrorHandler = function _ExFrame_globalErrorHandler(error, req, res, next) {
const originalUrl = req.originalUrl;
let errorHandler = __classPrivateFieldGet(this, _ExFrame_errorMap, "f")[`${originalUrl}/`];
if (errorHandler) {
return errorHandler(error, req, res, next);
}
const viableERoutes = __classPrivateFieldGet(this, _ExFrame_instances, "m", _ExFrame_getPossibleMatchingRoutes).call(this, originalUrl, __classPrivateFieldGet(this, _ExFrame_errorMap, "f"));
for (let vRoute of viableERoutes) {
errorHandler = __classPrivateFieldGet(this, _ExFrame_errorMap, "f")[vRoute];
if (errorHandler) {
return errorHandler(error, req, res, next);
}
}
next(error);
};