mirror of
https://gitlab.silvrtree.co.uk/martind2000/frontexpress.git
synced 2025-01-25 18:56:16 +00:00
added jsdoc
This commit is contained in:
parent
409c4cd891
commit
6d2dd79194
@ -1,23 +1,80 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
import HTTP_METHODS from './methods';
|
||||
import Settings from './settings';
|
||||
import Router, {Route} from './router';
|
||||
import Middleware from './middleware';
|
||||
|
||||
|
||||
/**
|
||||
* Application class.
|
||||
*/
|
||||
|
||||
export default class Application {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the application.
|
||||
*
|
||||
* - setup default configuration
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
constructor() {
|
||||
this.routers = [];
|
||||
this.DOMLoading = false;
|
||||
this.settings = new Settings();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Settings
|
||||
set(name, value) {
|
||||
|
||||
/**
|
||||
* Assign `setting` to `val`, or return `setting`'s value.
|
||||
*
|
||||
* app.set('foo', 'bar');
|
||||
* app.set('foo');
|
||||
* // => "bar"
|
||||
*
|
||||
* @param {String} setting
|
||||
* @param {*} [val]
|
||||
* @return {app} for chaining
|
||||
* @public
|
||||
*/
|
||||
|
||||
set(...args) {
|
||||
// get behaviour
|
||||
if (args.length === 1) {
|
||||
const name = [args];
|
||||
return this.settings.get(name);
|
||||
}
|
||||
|
||||
// set behaviour
|
||||
const [name, value] = args;
|
||||
this.settings.set(name, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Start listening requests
|
||||
|
||||
/**
|
||||
* Listen for DOM initialization and history state changes.
|
||||
*
|
||||
* The callback function is called once the DOM has
|
||||
* the `document.readyState` equals to 'interactive'.
|
||||
*
|
||||
* app.listen(()=> {
|
||||
* console.log('App is listening requests');
|
||||
* console.log('DOM is ready!');
|
||||
* });
|
||||
*
|
||||
*
|
||||
* @param {Function} callback
|
||||
* @public
|
||||
*/
|
||||
|
||||
listen(callback) {
|
||||
document.onreadystatechange = () => {
|
||||
const uri = window.location.pathname + window.location.search;
|
||||
@ -48,14 +105,44 @@ export default class Application {
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Routes
|
||||
|
||||
/**
|
||||
* Returns a new `Router` instance for the _uri_.
|
||||
* See the Router api docs for details.
|
||||
*
|
||||
* app.route('/');
|
||||
* // => new Router instance
|
||||
*
|
||||
* @param {String} uri
|
||||
* @return {Router} for chaining
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
route(uri) {
|
||||
const router = new Router(uri);
|
||||
this.routers.push(router);
|
||||
return router;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use the given middleware function or object, with optional _uri_.
|
||||
* Default _uri_ is "/".
|
||||
*
|
||||
* // middleware function will be applied on path "/"
|
||||
* app.use((req, res, next) => {console.log('Hello')});
|
||||
*
|
||||
* // middleware object will be applied on path "/"
|
||||
* app.use(new Middleware());
|
||||
*
|
||||
* @param {String} uri
|
||||
* @param {Middleware|Function} middleware or fn
|
||||
* @return {app} for chaining
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
use(...args) {
|
||||
if (args.length === 0) {
|
||||
throw new TypeError('use method takes at least a middleware or a router');
|
||||
@ -84,8 +171,18 @@ export default class Application {
|
||||
}
|
||||
}
|
||||
this.routers.push(router);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gather routes from all routers filtered by _uri_ and HTTP _method_.
|
||||
* See Router#routes() documentation for details.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
_routes(uri, method) {
|
||||
const currentRoutes = [];
|
||||
for (const router of this.routers) {
|
||||
@ -95,6 +192,15 @@ export default class Application {
|
||||
return currentRoutes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call `Middleware#entered` on _currentRoutes_.
|
||||
* Invoked before sending ajax request or when DOM
|
||||
* is loading (document.readyState === 'loading').
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
_callMiddlewareEntered(currentRoutes, request) {
|
||||
for (const route of currentRoutes) {
|
||||
if (route.middleware.entered) {
|
||||
@ -106,6 +212,15 @@ export default class Application {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call `Middleware#updated` or middleware function on _currentRoutes_.
|
||||
* Invoked on ajax request responding or on DOM ready
|
||||
* (document.readyState === 'interactive').
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
_callMiddlewareUpdated(currentRoutes, request, response) {
|
||||
for (const route of currentRoutes) {
|
||||
route.visited = request;
|
||||
@ -129,6 +244,14 @@ export default class Application {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call `Middleware#exited` on _currentRoutes_.
|
||||
* Invoked before sending a new ajax request or before DOM unloading.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
_callMiddlewareExited() {
|
||||
// calls middleware exited method
|
||||
for (const router of this.routers) {
|
||||
@ -142,6 +265,14 @@ export default class Application {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call `Middleware#failed` or middleware function on _currentRoutes_.
|
||||
* Invoked when ajax request fails.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
_callMiddlewareFailed(currentRoutes, request, response) {
|
||||
for (const route of currentRoutes) {
|
||||
// calls middleware failed method
|
||||
@ -164,8 +295,13 @@ export default class Application {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Ajax request
|
||||
|
||||
/**
|
||||
* Make an ajax request.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
_fetch({method, uri, headers, data}, resolve, reject) {
|
||||
|
||||
const httpMethodTransformer = this.get(`http ${method} transformer`);
|
||||
@ -202,7 +338,30 @@ export default class Application {
|
||||
}
|
||||
|
||||
HTTP_METHODS.reduce((reqProto, method) => {
|
||||
// Middleware methods
|
||||
|
||||
|
||||
/**
|
||||
* 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 "/"
|
||||
* app.get((req, res, next) => {console.log('Hello')});
|
||||
*
|
||||
* // middleware object will be applied on path "/" and
|
||||
* app.get(new Middleware());
|
||||
*
|
||||
* // get a setting value
|
||||
* app.set('foo', 'bar');
|
||||
* app.get('foo');
|
||||
* // => "bar"
|
||||
*
|
||||
* @param {String} uri or setting
|
||||
* @param {Middleware|Function} middleware or fn
|
||||
* @return {app} for chaining
|
||||
* @public
|
||||
*/
|
||||
|
||||
const middlewareMethodName = method.toLowerCase();
|
||||
reqProto[middlewareMethodName] = function(...args) {
|
||||
if (middlewareMethodName === 'get') {
|
||||
@ -235,9 +394,27 @@ HTTP_METHODS.reduce((reqProto, method) => {
|
||||
router[middlewareMethodName](baseUri, middleware);
|
||||
|
||||
this.routers.push(router);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// HTTP methods
|
||||
/**
|
||||
* Ajax request (get, post, put, delete...).
|
||||
*
|
||||
* // HTTP GET method
|
||||
* httpGet('/route1');
|
||||
* httpGet({uri: '/route1', data: {'p1': 'val1'});
|
||||
* // uri invoked => /route1?p1=val1
|
||||
*
|
||||
* // HTTP POST method
|
||||
* httpPost('/user');
|
||||
* ...
|
||||
*
|
||||
* @param {String|Object} uri or object containing uri, http headers, data
|
||||
* @param {Function} success callback
|
||||
* @param {Function} failure callback
|
||||
* @public
|
||||
*/
|
||||
const httpMethodName = 'http'+method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
|
||||
reqProto[httpMethodName] = function(request, resolve, reject) {
|
||||
let {uri, headers, data} = request;
|
||||
|
@ -1,8 +1,24 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
import Application from './application';
|
||||
import Router from './router';
|
||||
import Middleware from './middleware';
|
||||
|
||||
|
||||
/**
|
||||
* Create a frontexpress application.
|
||||
*
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
const frontexpress = () => new Application();
|
||||
|
||||
/**
|
||||
* Expose constructors.
|
||||
*/
|
||||
frontexpress.Router = (baseUri) => new Router(baseUri);
|
||||
frontexpress.Middleware = (name) => new Middleware(name);
|
||||
|
||||
|
@ -1 +1,6 @@
|
||||
export default ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'];
|
||||
/**
|
||||
* HTTP method list
|
||||
* @private
|
||||
*/
|
||||
|
||||
export default ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'];
|
@ -1,19 +1,85 @@
|
||||
/**
|
||||
* Middleware object.
|
||||
* @public
|
||||
*/
|
||||
|
||||
export default class Middleware {
|
||||
|
||||
|
||||
/**
|
||||
* Middleware initialization
|
||||
*
|
||||
* @param {String} middleware name
|
||||
*/
|
||||
|
||||
constructor(name='') {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
entered(request) {
|
||||
}
|
||||
/**
|
||||
* Invoked by the app before ajax request are sent or
|
||||
* during the DOM loading (document.readyState === 'loading').
|
||||
* See Application#_callMiddlewareEntered documentation for details.
|
||||
*
|
||||
* Override this method to add your custom behaviour
|
||||
*
|
||||
* @param {Object} request
|
||||
* @public
|
||||
*/
|
||||
|
||||
exited(request) {
|
||||
}
|
||||
entered(request) { }
|
||||
|
||||
updated(request, response) {
|
||||
}
|
||||
|
||||
failed(request, response) {
|
||||
}
|
||||
/**
|
||||
* Invoked by the app before a new ajax request is sent or before the DOM unloading.
|
||||
* See Application#_callMiddlewareExited documentation for details.
|
||||
*
|
||||
* Override this method to add your custom behaviour
|
||||
*
|
||||
* @param {Object} request
|
||||
* @public
|
||||
*/
|
||||
|
||||
exited(request) { }
|
||||
|
||||
|
||||
/**
|
||||
* Invoked on ajax request responding or on DOM ready
|
||||
* (document.readyState === 'interactive').
|
||||
* See Application#_callMiddlewareUpdated documentation for details.
|
||||
*
|
||||
* Override this method to add your custom behaviour
|
||||
*
|
||||
* @param {Object} request
|
||||
* @param {Object} response
|
||||
* @public
|
||||
*/
|
||||
|
||||
updated(request, response) { }
|
||||
|
||||
|
||||
/**
|
||||
* Invoked when ajax request fails.
|
||||
*
|
||||
* Override this method to add your custom behaviour
|
||||
*
|
||||
* @param {Object} request
|
||||
* @param {Object} response
|
||||
* @public
|
||||
*/
|
||||
failed(request, response) { }
|
||||
|
||||
|
||||
/**
|
||||
* Allow the hand over to the next middleware object or function.
|
||||
*
|
||||
* Override this method and return `false` to break execution of
|
||||
* middleware chain.
|
||||
*
|
||||
* @return {Boolean} `true` by default
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
next() {
|
||||
return true;
|
||||
|
@ -1,5 +1,19 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
export default class Requester {
|
||||
|
||||
/**
|
||||
* Make an ajax request.
|
||||
*
|
||||
* @param {Object} request
|
||||
* @param {Function} success callback
|
||||
* @param {Function} failure callback
|
||||
* @private
|
||||
*/
|
||||
|
||||
fetch({method, uri, headers, data}, resolve, reject) {
|
||||
const success = (responseText) => {
|
||||
resolve(
|
||||
@ -43,6 +57,13 @@ export default class Requester {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Analyse response errors.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
_analyzeErrors(response) {
|
||||
// manage exceptions
|
||||
if (response.errorThrown) {
|
||||
|
133
lib/router.js
133
lib/router.js
@ -1,7 +1,26 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
import HTTP_METHODS from './methods';
|
||||
import Middleware from './middleware';
|
||||
|
||||
|
||||
/**
|
||||
* Route object.
|
||||
* @private
|
||||
*/
|
||||
|
||||
class Route {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the route.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
constructor(router, uriPart, method, middleware) {
|
||||
this.router = router;
|
||||
this.uriPart = uriPart;
|
||||
@ -10,6 +29,13 @@ class Route {
|
||||
this.visited = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return route's uri.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
get uri() {
|
||||
if (!this.uriPart && !this.method) {
|
||||
return undefined;
|
||||
@ -35,7 +61,21 @@ class Route {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Router object.
|
||||
* @public
|
||||
*/
|
||||
|
||||
export default class Router {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the router.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
constructor(uri) {
|
||||
if (uri) {
|
||||
this._baseUri = uri;
|
||||
@ -43,6 +83,13 @@ export default class Router {
|
||||
this._routes = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do some checks and set _baseUri.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
set baseUri(uri) {
|
||||
if (!uri) {
|
||||
return;
|
||||
@ -62,15 +109,36 @@ export default class Router {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.uri && !route.method) {
|
||||
@ -106,12 +174,35 @@ export default class Router {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gather visited routes from routers.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
visited() {
|
||||
return this._routes.filter((route) => {
|
||||
return 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 or fn
|
||||
* @return {Router} for chaining
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
use(middleware) {
|
||||
if (!(middleware instanceof Middleware) && (typeof middleware !== 'function') ) {
|
||||
throw new TypeError('use method takes at least a middleware');
|
||||
@ -122,6 +213,23 @@ export default class Router {
|
||||
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 or fn
|
||||
* @return {Router} for chaining
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
all(...args) {
|
||||
if (args.length === 0) {
|
||||
throw new TypeError('use all method takes at least a middleware');
|
||||
@ -146,6 +254,31 @@ export default class Router {
|
||||
}
|
||||
|
||||
for (const method of HTTP_METHODS) {
|
||||
|
||||
|
||||
/**
|
||||
* 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 or setting
|
||||
* @param {Middleware|Function} middleware or fn
|
||||
* @return {Router} for chaining
|
||||
* @public
|
||||
*/
|
||||
|
||||
const methodName = method.toLowerCase();
|
||||
Router.prototype[methodName] = function(...args) {
|
||||
if (args.length === 0) {
|
||||
|
@ -1,6 +1,27 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
import Requester from './requester';
|
||||
|
||||
|
||||
/**
|
||||
* Settings object.
|
||||
* @private
|
||||
*/
|
||||
|
||||
export default class {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the settings.
|
||||
*
|
||||
* - setup default configuration
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
constructor() {
|
||||
// default settings
|
||||
this.settings = {
|
||||
@ -47,6 +68,15 @@ export default class {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assign `setting` to `val`
|
||||
*
|
||||
* @param {String} setting
|
||||
* @param {*} [val]
|
||||
* @private
|
||||
*/
|
||||
|
||||
set(name, value) {
|
||||
const checkRules = this.rules[name];
|
||||
if (checkRules) {
|
||||
@ -55,6 +85,14 @@ export default class {
|
||||
this.settings[name] = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return `setting`'s value.
|
||||
*
|
||||
* @param {String} setting
|
||||
* @private
|
||||
*/
|
||||
|
||||
get(name) {
|
||||
return this.settings[name];
|
||||
}
|
||||
|
@ -114,6 +114,7 @@ describe('Application', () => {
|
||||
const app = frontexpress();
|
||||
app.set('http requester', requester);
|
||||
assert(app.get('http requester') === requester);
|
||||
assert(app.set('http requester') === requester);
|
||||
});
|
||||
|
||||
it('bad core setting', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user