@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
JavaScript
"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;