@tunframework/tun
Version:
tun framework for node with typescript
114 lines (113 loc) • 4.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TunApplication = void 0;
const events_1 = require("events");
const http_1 = require("http");
const symbol_js_1 = require("./constants/http/symbol.js");
const HttpError_js_1 = require("./HttpError.js");
const TunComposable_js_1 = require("./TunComposable.js");
const TunContext_js_1 = require("./TunContext.js");
const TunCookie_js_1 = require("./TunCookie.js");
class TunApplication extends events_1.EventEmitter {
middleware = [];
mountObj = {};
constructor() {
super();
}
use(fn) {
Array.isArray(fn) ? this.middleware.push(...fn) : this.middleware.push(fn);
return this;
}
mount(name, obj) {
this.mountObj[name] = obj;
}
// unmount(name: string) {
// delete this.mountObj[name];
// }
callback() {
return (_req, _res) => {
const fn = (0, TunComposable_js_1.compose)(this.middleware);
const ctx = new TunContext_js_1.TunContext(_req, _res);
// 挂载收集到的属性到ctx.state上
Object.assign(ctx.state, this.mountObj);
return (Promise.resolve(fn(ctx))
.catch(genError)
// finish 处理 设置到 应用上下文 的数据
// body 响应内容
.then((body) => dealResponse(ctx, body))
.catch((err) => dealResponse(ctx, err)));
};
}
listen(option) {
const server = (0, http_1.createServer)(this.callback());
server.on('error', (err) => this.emit('error', err, server));
const host = process.env.HOST ? process.env.HOST : 'localhost';
const port = process.env.PORT ? parseInt(process.env.PORT) : 3000;
let _option = {
host,
port,
// path: '/',
...(option || {})
};
server.listen(_option);
// Handle listening manual:
// server.on('listening', () => {
// let addr = (server.address() || {}) as AddressInfo
// const url = 'http://' + [addr.address, addr.port].filter(Boolean).join(':')
// console.log(`app listening: ${url}`)
// })
return server;
}
}
exports.TunApplication = TunApplication;
function genError(err) {
if (err instanceof HttpError_js_1.HttpError) {
return err;
}
else {
return new HttpError_js_1.HttpError({ error: err });
}
}
async function dealResponse(ctx, _body) {
const _res = ctx.res[symbol_js_1.RAW_RESPONSE];
// Return if response handled by other middleware
if (_res.headersSent || _res.writableEnded)
return;
if (typeof _body !== 'undefined') {
ctx.body = _body;
}
ctx.body = await ctx.body;
if (ctx.body instanceof HttpError_js_1.HttpError) {
ctx.res.status = ctx.body.status;
ctx.body = { status: ctx.res.status, message: ctx.body.message };
}
else if (ctx.body instanceof Error) {
ctx.res.status = 500;
ctx.body = { status: ctx.res.status, message: ctx.body.message };
}
// Write response header
if (!(_res.headersSent || _res.writableEnded)) {
if (typeof ctx.body !== 'undefined' &&
typeof ctx.body === 'object' &&
!ctx.res.type.rawType) {
ctx.res.type = { rawType: 'application/json; charset=utf-8' };
}
// Set response header for collected cookies
const cookies = ctx.res.cookies.map(TunCookie_js_1._stringifyTunCookie);
_res.setHeader.call(_res, 'set-cookie', cookies);
_res.writeHead(ctx.res.status, ctx.res.message);
}
// Write response body
if (!_res.writableEnded) {
if (ctx.body !== null && typeof ctx.body !== 'undefined') {
// fixme: Shouldcheck other types. e.g. Buffer.
if (typeof ctx.body === 'object') {
_res.write(JSON.stringify(ctx.body));
}
else {
_res.write(ctx.body);
}
}
_res.end();
}
}