mirror of
https://gitlab.silvrtree.co.uk/martind2000/frontexpress.git
synced 2025-02-11 14:19:15 +00:00
270 lines
5.8 KiB
JavaScript
Executable File
270 lines
5.8 KiB
JavaScript
Executable File
/**
|
|
* Module dependencies.
|
|
* @private
|
|
*/
|
|
|
|
import HTTP_METHODS from './methods';
|
|
import {toParameters} from './application';
|
|
import Middleware from './middleware';
|
|
|
|
|
|
/**
|
|
* Route object.
|
|
* @private
|
|
*/
|
|
|
|
export class Route {
|
|
|
|
|
|
/**
|
|
* Initialize the route.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
constructor(router, uriPart, method, middleware) {
|
|
this.router = router;
|
|
this.uriPart = uriPart;
|
|
this.method = method;
|
|
this.middleware = middleware;
|
|
this.visited = false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return route's uri.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
get uri() {
|
|
if (!this.uriPart && !this.method) {
|
|
return undefined;
|
|
}
|
|
|
|
if (this.uriPart instanceof RegExp) {
|
|
return this.uriPart;
|
|
}
|
|
|
|
if (this.router.baseUri instanceof RegExp) {
|
|
return this.router.baseUri;
|
|
}
|
|
|
|
if (this.router.baseUri) {
|
|
const baseUri = this.router.baseUri.trim();
|
|
if (this.uriPart) {
|
|
return ( baseUri + this.uriPart.trim()).replace(/\/{2,}/, '/');
|
|
}
|
|
return baseUri;
|
|
}
|
|
|
|
return this.uriPart;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Router object.
|
|
* @public
|
|
*/
|
|
|
|
const error_middleware_message = 'method takes at least a middleware';
|
|
export default class Router {
|
|
|
|
|
|
/**
|
|
* Initialize the router.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
constructor(uri) {
|
|
this._baseUri = uri;
|
|
this._routes = [];
|
|
}
|
|
|
|
|
|
/**
|
|
* Do some checks and set _baseUri.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
set baseUri(uri) {
|
|
if (!uri) {
|
|
return;
|
|
}
|
|
|
|
if (!this._baseUri) {
|
|
this._baseUri = uri;
|
|
return;
|
|
}
|
|
|
|
if (typeof this._baseUri !== typeof uri) {
|
|
throw new TypeError('router cannot mix regexp and uri');
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Return router's _baseUri.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
get baseUri() {
|
|
return this._baseUri;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a route to the router.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
_add(route) {
|
|
this._routes.push(route);
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Gather routes from routers filtered by _uri_ and HTTP _method_.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
routes(uri, method) {
|
|
return this._routes.filter((route) => {
|
|
if (route.method && route.method !== method) {
|
|
return false;
|
|
}
|
|
|
|
if (!route.uri || !uri) {
|
|
return true;
|
|
}
|
|
|
|
//remove query string from uri to test
|
|
//remove anchor from uri to test
|
|
const match = /^(.*)\?.*#.*|(.*)(?=\?|#)|(.*[^\?#])$/.exec(uri);
|
|
const baseUriToCheck = match[1] || match[2] || match[3];
|
|
|
|
if (route.uri instanceof RegExp) {
|
|
return baseUriToCheck.match(route.uri);
|
|
}
|
|
|
|
return route.uri === baseUriToCheck;
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* Gather visited routes from routers.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
visited() {
|
|
return this._routes.filter(route => route.visited);
|
|
}
|
|
|
|
|
|
/**
|
|
* Use the given middleware function or object on this router.
|
|
*
|
|
* // middleware function
|
|
* router.use((req, res, next) => {console.log('Hello')});
|
|
*
|
|
* // middleware object
|
|
* router.use(new Middleware());
|
|
*
|
|
* @param {Middleware|Function} middleware object or function
|
|
* @return {Router} for chaining
|
|
*
|
|
* @public
|
|
*/
|
|
|
|
use(middleware) {
|
|
if (!(middleware instanceof Middleware) && (typeof middleware !== 'function') ) {
|
|
throw new TypeError(error_middleware_message);
|
|
}
|
|
|
|
this._add(new Route(this, undefined, undefined, middleware));
|
|
|
|
return this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Use the given middleware function or object on this router for
|
|
* all HTTP methods.
|
|
*
|
|
* // middleware function
|
|
* router.all((req, res, next) => {console.log('Hello')});
|
|
*
|
|
* // middleware object
|
|
* router.all(new Middleware());
|
|
*
|
|
* @param {Middleware|Function} middleware object or function
|
|
* @return {Router} for chaining
|
|
*
|
|
* @public
|
|
*/
|
|
|
|
all(...args) {
|
|
const {middleware} = toParameters(args);
|
|
if (!middleware) {
|
|
throw new TypeError(error_middleware_message);
|
|
}
|
|
|
|
HTTP_METHODS.forEach((method) => {
|
|
this[method.toLowerCase()](...args);
|
|
});
|
|
return this;
|
|
}
|
|
}
|
|
|
|
HTTP_METHODS.forEach((method) => {
|
|
|
|
|
|
/**
|
|
* Use the given middleware function or object, with optional _uri_ on
|
|
* HTTP methods: get, post, put, delete...
|
|
* Default _uri_ is "/".
|
|
*
|
|
* // middleware function will be applied on path "/"
|
|
* router.get((req, res, next) => {console.log('Hello')});
|
|
*
|
|
* // middleware object will be applied on path "/" and
|
|
* router.get(new Middleware());
|
|
*
|
|
* // middleware function will be applied on path "/user"
|
|
* router.post('/user', (req, res, next) => {console.log('Hello')});
|
|
*
|
|
* // middleware object will be applied on path "/user" and
|
|
* router.post('/user', new Middleware());
|
|
*
|
|
* @param {String} uri
|
|
* @param {Middleware|Function} middleware object or function
|
|
* @return {Router} for chaining
|
|
* @public
|
|
*/
|
|
|
|
const methodName = method.toLowerCase();
|
|
Router.prototype[methodName] = function(...args) {
|
|
const {baseUri, middleware} = toParameters(args);
|
|
if (!middleware) {
|
|
throw new TypeError(error_middleware_message);
|
|
}
|
|
|
|
if (baseUri && this._baseUri && this._baseUri instanceof RegExp) {
|
|
throw new TypeError('router cannot mix uri/regexp');
|
|
}
|
|
|
|
this._add(new Route(this, baseUri, method, middleware));
|
|
|
|
return this;
|
|
};
|
|
});
|