UNPKG

@glandjs/express

Version:

An Express adapter for Gland HTTP protocol layer, enabling classic middleware-based routing within the Gland architecture solution.

158 lines (157 loc) 5.73 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExpressAdapter = void 0; const http_1 = require("@glandjs/http"); const toolkit_1 = require("@medishn/toolkit"); const express_1 = __importDefault(require("express")); const common_1 = require("@glandjs/common"); const node_stream_1 = require("node:stream"); const context_1 = require("./context"); class ExpressAdapter extends http_1.HttpServerAdapter { constructor() { super((0, express_1.default)()); this.parserMiddleware = []; express_1.default.json(); express_1.default.urlencoded(); express_1.default.raw(); express_1.default.text(); } json(options) { this.parserMiddleware.push(express_1.default.json(options)); return this; } urlencoded(options) { this.parserMiddleware.push(express_1.default.urlencoded(options)); return this; } raw(options) { this.parserMiddleware.push(express_1.default.raw(options)); return this; } text(options) { this.parserMiddleware.push(express_1.default.text(options)); return this; } initialize() { this.logger.info('Initializing Express adapter'); this.events.on('options', (options) => { }); } listen(port, hostname = 'localhost', message) { console.log(`Applying ${this.parserMiddleware.length} parser middleware during listen`); this.parserMiddleware.forEach((middleware, index) => { console.log(`Applying parser middleware #${index + 1}`); this.instance.use(middleware); }); this.instance.use((req, res, next) => { const ctx = new context_1.ExpressContext(this.events, req, res); req.ctx = ctx; next(); }); try { const parsedPort = (0, toolkit_1.isString)(port) ? parseInt(port, 10) : port; const options = this.events.call('options', {}); const defaultMessage = `Server listening on ${hostname}:${parsedPort}`; this.logger.info(message ?? defaultMessage); this.server = http_1.ServerFactory.create(options || {}, this.instance); this.server.listen(parsedPort, hostname); } catch (error) { this.handleError(error, 'Failed to start Express server'); } } reply(response, body, statusCode) { if (statusCode) { response.status(statusCode); } if ((0, toolkit_1.isNil)(body)) { return response.send(); } if (body && body.getStream && typeof body.getStream === 'function') { const streamHeaders = body.getHeaders ? body.getHeaders() : {}; if (response.getHeader('Content-Type') === undefined && streamHeaders.type) { response.setHeader('Content-Type', streamHeaders.type); } return (0, node_stream_1.pipeline)(body.getStream().once('error', (err) => { response.status(500).end(); this.logger.error(err); }), response, (err) => { if (err) { this.logger.error(err); } }); } return (0, toolkit_1.isObject)(body) ? response.json(body) : response.send(String(body)); } use(...args) { const wrapped = args.map((arg) => { if (typeof arg !== 'function') return arg; if (arg.length === 2 || arg.length === 3) { return function (req, res, next) { const ctx = req.ctx; if (!ctx) return next(new Error('No context found in middleware')); try { arg(ctx, next); } catch (err) { next(err); } }; } return arg; }); return this.instance.use(...wrapped); } registerRoute(method, path, action) { const normalizedPath = (0, common_1.normalizePath)(path); this.instance[method.toLowerCase()](normalizedPath, async (req, res, next) => { try { const ctx = req.ctx; ctx.params = req.params; const result = await action(ctx); if (result !== undefined && !res.headersSent) { this.reply(res, result); } } catch (error) { next(error); } }); } enableCors(options) { const cors = (0, common_1.loadPackage)('cors', 'cors is not install'); this.use(cors(options)); } set(key, value) { this.instance.set(key, value); return this; } engine(ext, engine) { this.instance.engine(ext, engine); return this; } setViewEngine(engine) { return this.set('view engine', engine); } setBaseViewsDir(path) { return this.set('views', path); } setGlobalPrefix(prefix) { if (!prefix.startsWith('/')) { prefix = `/${prefix}`; } const router = express_1.default.Router(); this.instance.use(prefix, router); this.logger.info(`Global prefix set to: ${prefix}`); } useStaticAssets(path) { this.instance.use(express_1.default.static(path)); this.logger.info(`Static asset directory registered: ${path}`); } } exports.ExpressAdapter = ExpressAdapter;