frontexpress/lib/application.js
2016-06-26 12:10:37 +02:00

161 lines
5.0 KiB
JavaScript
Executable File

import Router, {Route} from './router';
import Middleware from './middleware';
import Requester, {HTTP_METHODS} from './requester';
export default class Application {
constructor() {
this.routers = [];
this.requester = new Requester();
this.lastVisited = null;
this.settingsDef = {
'http-requester': (requester) => {this.requester = requester}
};
}
////////////////////////////////////////////////////////
// Setting
set(name, value) {
const settingFn = this.settingsDef[name];
if (!settingFn) {
throw new ReferenceError(`unsupported setting ${name}`);
}
settingFn(value);
}
////////////////////////////////////////////////////////
// Routes
route(uri) {
const router = new Router(uri);
this.routers.push(router);
return router;
}
use(...args) {
if (args.length === 0) {
throw new TypeError(`use method takes at least a middleware or a router`);
}
let baseUri, middleware, router, which;
if (args.length === 1) {
[which,] = args;
} else {
[baseUri, which,] = args;
}
if (!(which instanceof Middleware) && (typeof which !== 'function') && !(which instanceof Router)) {
throw new TypeError(`use method takes at least a middleware or a router`);
}
if (which instanceof Router) {
router = which;
router.baseUri = baseUri;
} else {
middleware = which;
router = new Router(baseUri);
for (const method of Object.keys(HTTP_METHODS)) {
router[method.toLowerCase()](middleware);
}
}
this.routers.push(router);
}
///////////////////////////////////////////////////////
// Ajax request
_fetch({method, uri, headers, data}, resolve, reject) {
if (this.lastVisited) {
for (const router of this.routers) {
const routes = router.getRoutes(this.lastVisited.uri, this.lastVisited.method);
for (const route of routes) {
if (route.middleware.exited) {
route.middleware.exited(this.lastVisited);
}
}
}
}
const currentRoutes = [];
for (const router of this.routers) {
const routes = router.getRoutes(uri, method);
currentRoutes.push(...routes);
}
for (const route of currentRoutes) {
if (route.middleware.entered) {
route.middleware.entered({method, uri, headers, data});
}
}
this.requester.fetch({uri, method}, (request, response) => {
this.lastVisited = {method, uri, headers, data};
for (const route of currentRoutes) {
if (route.middleware.updated) {
route.middleware.updated(request, response);
} else {
route.middleware(request, response);
}
}
if (resolve) {
resolve(request, response);
}
}, (request, response) => {
for (const route of currentRoutes) {
if (route.middleware.failed) {
route.middleware.failed(request, response);
}
}
if (reject) {
reject(request, response);
}
});
}
}
Object.keys(HTTP_METHODS).reduce((reqProto, method) => {
// Middleware methods
const middlewareMethodeName = method.toLowerCase();
reqProto[middlewareMethodeName] = function(...args) {
if (args.length === 0) {
throw new TypeError(`${middlewareMethodeName} method takes at least a middleware`);
}
let baseUri, middleware, which;
if (args.length === 1) {
[which,] = args;
} else {
[baseUri, which,] = args;
}
if (!(which instanceof Middleware) && (typeof which !== 'function')) {
throw new TypeError(`${middlewareMethodeName} method takes at least a middleware`);
}
const router = new Router();
middleware = which;
router[middlewareMethodeName](baseUri, middleware);
this.routers.push(router);
}
// HTTP methods
const transformer = HTTP_METHODS[method];
const httpMethodName = 'http'+method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
reqProto[httpMethodName] = function(request, resolve, reject) {
let {uri, headers, data} = request;
if (!uri) {
uri = request;
}
return this._fetch({
uri,
method,
headers,
data,
}, resolve, reject);
}
return reqProto;
}, Application.prototype);