aztec
Version:
Node Js Framework for creating API Services
146 lines (114 loc) • 3.86 kB
text/typescript
import http = require('http');
import { ImportSystem } from './import-system.class';
import { Handler } from './handler.class';
import { extendServerResponse as extendRes } from './extends/res.func';
import { extendServerRequest as extendReq } from './extends/req.func';
import { logger } from './logger.func';
import { wait, generateId } from "./lib";
import { concat, isObject } from 'lodash';
import { $Middleware } from "./models.lib";
import { middleware } from './middleware.func';
import { Router } from './router/router.class';
export class Service extends ImportSystem {
constructor(params) {
super();
this.readonly([
'address',
'app',
'init',
'includeRouters',
'startServer',
'id',
'name',
'baseDir',
'protocol',
'format',
'x-powered-by'
]);
this.name = params.name;
this.port = params.port;
this.filepath = params.path;
let path = params.path.split('/');
path.pop();
this.baseDir = path.join('/');
this.router = new Router(this);
global['AZTEC']['SERVICES'][this.name] = this;
this.init();
}
address(): string {
return `${this.protocol}://${this.domain}:${this.port}`;
}
plugin(func: $Middleware) {
this.pluginQueue.push(func);
}
app(app): void {
wait('for routes in app', () => {
if (isObject(app)) {
this.apps.push(app);
} else {
Handler.error(`Undefined application ${app}`);
}
});
}
private run(): void {
if (this.server) this.server.close();
Handler.env = this.env;
this.router.mergeRoutes();
this.startServer();
}
private init() {
wait('for options', () => {
this.appRoutes();
if (require(this.filepath)) this.run();
});
}
private appRoutes(): void {
wait('for apps', () => {
this.apps.forEach(app => {
this.router.set('routers', concat(this.router.get('routers'), app.router.routers));
});
});
}
private startServer(): void {
this.server = http.createServer((req, res) => {
this.format = '';
req.on('data', chunk => req['body'] = JSON.parse(chunk.toString()));
req = extendReq(req); res = extendRes(this, res);
req.setEncoding('utf-8');
wait('for data', () => {
if (this.pluginQueue.length) middleware(req, res, this.pluginQueue);
if (this.v2 && req.url.indexOf(`/${this['api-prefix']}1`) > -1) this.format = 'json';
if (this.v2 && req.url.indexOf(`/${this['api-prefix']}2`) > -1) this.format = 'xml';
if (!this.v2 || !this.format) this.format = this['default-format'];
switch (this.format) {
case 'json': res.setHeader('Content-Type', 'application/json'); break;
case 'xml': res.setHeader('Content-Type', 'text/xml'); break;
}
if (this['x-powered-by']) res.setHeader('X-Powered-By', this['x-powered-by']);
this.routerController.parseRequest(this, req, res);
if (this.env === 'development') logger(req, res);
});
});
this.server.on('error', e => Handler.error(e));
this.server.listen(this.port, this.serverStartingMessage.bind(this));
}
private serverStartingMessage(): void {
Handler.info(`Server listening on port ${this.port}`);
}
private id: string = generateId();
private name: string;
private filepath: string;
private baseDir: string;
private server: any;
protected ['x-powered-by']: string = 'Aztec';
protected ['public-path']: string;
protected ['default-format']: string = 'json';
protected v2: boolean = false;
protected format: string;
protected env: string = 'development';
protected protocol: string = 'http';
protected domain: string = 'localhost';
protected port: number = 5050;
protected pluginQueue: $Middleware[] = [];
protected apps: any[] = [];
}