added jsdoc

This commit is contained in:
Camel Aissani 2016-07-15 21:34:24 +02:00
parent 409c4cd891
commit 6d2dd79194
8 changed files with 477 additions and 20 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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'];

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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];
}

View File

@ -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', () => {