UNPKG

@reflet/express

Version:

Well-defined and well-typed express decorators

90 lines (89 loc) 2.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractApplicationClass = exports.Application = void 0; const express = require("express"); const register_1 = require("./register"); const reflet_error_1 = require("./reflet-error"); const metadata_map_1 = require("./metadata-map"); const METAKEY_APPLICATION = Symbol('application'); /** * Express application class to extend, to apply the decorators with a global behavior. * * _Constructor simply returns an express application, augmented with `register` method._ * * @example * ```ts * @Send({ json: true }) * @Use(express.json()) * class App extends Application { * @Get('/healthcheck') * healthcheck() { * return { success: true } * } * } * * @Router('/foo') * class FooRouter { * @Get() * list() { * return db.collection('foo').find({}) * } * } * * const app = new App() * app.register([FooRouter]) * app.listen(3000) * ``` * ------ * @public */ class Application { constructor() { const app = express(); mixinApplication(app, this.constructor); // As the constructor returns an express app, we must keep the class reference // to retrieve metadata attached to its children. const metadata = { class: this.constructor, registered: false, }; (0, metadata_map_1.defineMetadata)(METAKEY_APPLICATION, metadata, app); return app; } register(routers = []) { (0, register_1.register)(this, routers); return this; } } exports.Application = Application; /** * @internal */ function mixinApplication(target, source) { // Build the prototype chain with the top parent as first item, to apply inheritance in the right order. const protoChain = []; let protoChainLink = source; do { protoChain.unshift(protoChainLink); protoChainLink = Object.getPrototypeOf(protoChainLink); } while (protoChainLink !== Function.prototype && protoChainLink !== Object.prototype); for (const proto of protoChain) { const keys = Object.getOwnPropertyNames(proto.prototype); for (const key of keys) { if (key === 'constructor') continue; if (key in target) { throw new reflet_error_1.RefletExpressError('EXPRESS_PROPERTY_PROTECTED', `Cannot overwrite "${key}" on express application.`); } const descriptor = Object.getOwnPropertyDescriptor(proto.prototype, key); Object.defineProperty(target, key, descriptor); } } } /** * @internal */ function extractApplicationClass(target) { return (0, metadata_map_1.getMetadata)(METAKEY_APPLICATION, target); } exports.extractApplicationClass = extractApplicationClass;