json-routing
Version:
JSON configurable MVC routing for express 4
874 lines (838 loc) • 46.4 kB
HTML
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>json-routing</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="assets/css/main.css">
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="assets/js/search.js" data-base=".">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="index.html" class="title">json-routing</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<input type="checkbox" id="tsd-filter-only-exported" />
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
</div>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="globals.html">Globals</a>
</li>
</ul>
<h1> json-routing</h1>
</div>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<div class="tsd-panel tsd-typography">
<h1 id="json-routes">JSON Routes</h1>
<p><a href="https://travis-ci.org/gimox/json-routing"><img src="https://travis-ci.org/gimox/json-routing.svg?branch=2.0" alt="Build Status"></a>
<a href="https://badge.fury.io/js/json-routing"><img src="https://badge.fury.io/js/json-routing.svg" alt="npm version"></a>
<a href="https://coveralls.io/github/gimox/json-routing?branch=2.0"><img src="https://coveralls.io/repos/github/gimox/json-routing/badge.svg?branch=2.0" alt="Coverage Status"></a></p>
<p>Look at branch <a href="https://github.com/gimox/json-routing/tree/1.x">v1.x</a> for older release.</p>
<ul>
<li>Typescript code, more optimized</li>
<li>more speed</li>
<li>remove some unused option</li>
<li>make code more extensible and simple</li>
<li>add automatic JWT route protection with auth0/express-jwt</li>
<li>add route validator with express-validator</li>
<li>prepare it for something more...... </li>
</ul>
<h2 id="make-me-the-code">MAKE ME THE CODE</h2>
<h4 id="1-init-module">1 init module</h4>
<p><strong>Typescript</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {JsonRoute} <span class="hljs-keyword">from</span> <span class="hljs-string">"json-route"</span>;
<span class="hljs-keyword">let</span> routeInfo:<span class="hljs-built_in">Array</span><any> = <span class="hljs-keyword">new</span> JsonRoute(app, {
<span class="hljs-string">"routesPath"</span>: <span class="hljs-string">"./api/routes"</span>,
<span class="hljs-string">"processdir"</span>: __dirname
}).start();
</code></pre>
<p><strong>JS ES6</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> jsonRoute = <span class="hljs-built_in">require</span>(<span class="hljs-string">"json-route"</span>)
<span class="hljs-keyword">let</span> routeInfo = <span class="hljs-keyword">new</span> JsonRoute(app, {
<span class="hljs-string">"routesPath"</span>: <span class="hljs-string">"./api/routes"</span>,
<span class="hljs-string">"processdir"</span>: __dirname
}).start();
</code></pre>
<h4 id="2-create-routes">2 create routes</h4>
<p><strong>Create a route file definition</strong></p>
<pre><code class="lang-json">{
<span class="hljs-attr">"/admin"</span>: {
<span class="hljs-attr">"GET"</span>: {
<span class="hljs-attr">"route"</span>: <span class="hljs-string">"action"</span>,
<span class="hljs-attr">"policy"</span>: [
<span class="hljs-string">"test:check"</span>,
<span class="hljs-string">"test:all"</span>,
<span class="hljs-string">"./subfolder/test2:index"</span>
]
},
<span class="hljs-attr">"POST"</span>: {
<span class="hljs-attr">"route"</span>: <span class="hljs-string">"action"</span>,
<span class="hljs-attr">"policy"</span>: [
<span class="hljs-string">"test:all"</span>,
]
}
},
<span class="hljs-attr">"/dashboard"</span>: {
<span class="hljs-attr">"GET"</span>: {
<span class="hljs-attr">"route"</span>: <span class="hljs-string">"dashboard"</span>,
}
}
}
</code></pre>
<p>Routig with pure regular expression, add prefix "RE " before uri:</p>
<pre><code class="lang-json">{
<span class="hljs-attr">"RE /.*fly$/"</span>: {
<span class="hljs-attr">"GET"</span>: {
<span class="hljs-attr">"route"</span>: <span class="hljs-string">"index"</span>
}
}
}
</code></pre>
<h2 id="what-is-it-">WHAT IS IT?</h2>
<p>Make routes much easier to use in MVC format.
I've been searching for a while for a nodejs routing solution with a:</p>
<ul>
<li>simple configuration,</li>
<li>super performance,</li>
<li>simple code,</li>
<li>MVC organization,</li>
<li>manage only routing, no other auto magic api creation</li>
<li>customizable</li>
<li>least possible dependency</li>
</ul>
<p>This is: json-routes.</p>
<h2 id="how-it-works">How It Works</h2>
<p><strong>The basic concepts.</strong>
Create a json file with your routing config and add code logic in a external file called <em>controller</em> , creating an MVC style structure.</p>
<p>I followed the Expressjs 4 routing standards, helping the developer to manage the routes creation and project organization faster and in the standard synthax. Look at <a href="http://expressjs.com/en/guide/routing.html">express routing guide</a>
for a complet route pattern syntax </p>
<h2 id="proposed-structure">Proposed Structure</h2>
<p>This is an example of the default proposed structure, you can customize and change as you prefer.</p>
<pre><code>project root
├── controllers/
│ ├── IndexController<span class="hljs-selector-class">.js</span>
│ ├── AuthController<span class="hljs-selector-class">.js</span>
│ ├── UsersController<span class="hljs-selector-class">.js</span>
├── policy/
│ │ ├── AuthorizationPolicy<span class="hljs-selector-class">.js</span>
│ │ ├── mymiddleware<span class="hljs-selector-class">.js</span>
├── routes/
│ │ │ ├── auth<span class="hljs-selector-class">.json</span>
│ │ │ ├── users<span class="hljs-selector-class">.json</span>
│ │ │ ├── index<span class="hljs-selector-class">.json</span>
├── app.js/
├── package.json/
├── README.md/
</code></pre><ul>
<li><strong>Controller</strong>: contains the code's logic</li>
<li><strong>Policy</strong>: contains the function called before the controller = middleware</li>
<li><strong>Routes</strong>: contains all the <code>*.json</code> routing configuration. You can create as many *.json files as you need. By default, all routes within a file look up the corresponding controller (= modules = controllers = middleware) inside the controller's default directory <code>./controller</code> (or within the directory specified by the user), which uses the following naming format: Route-name (without .json) + "Controller.js (the first letter must be capitalized)".</li>
</ul>
<blockquote>
<p><strong>EXAMPLE:</strong>
If you have a definition file called <code>users.json</code>, by default the route searches the controller <code>UsersControllers.js</code>.
For routes <em>auth.json</em> all routes call the controller <code>AuthController.js</code> ecc.. ecc..</p>
<p><strong>NOTE:</strong> this is a proposed structure but you can configure the module for your structure, you can change dir structure or add all routes in a single file.</p>
</blockquote>
<h3 id="creating-json-configuration-file">Creating JSON Configuration file</h3>
<p>The routing file is encoded in the JSON format and by <strong>default is in <code>./routes.</code></strong></p>
<p>Router is created using this syntax:</p>
<p><code>{ "RoutePath" : {"verb": {options} } }</code></p>
<p><em>Example of extended config</em></p>
<pre><code class="lang-javascript">{
<span class="hljs-string">"routePath"</span>: {
<span class="hljs-string">"VERB"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"controller:method"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"controller:method"</span>,
]
}
},
<span class="hljs-string">"/admin"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"action"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"./demo/policycustom/test:check"</span>,
<span class="hljs-string">"test:all"</span>,
<span class="hljs-string">"./subfolder/test2:index"</span>
]
},
<span class="hljs-string">"POST"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"./mycustomfolder/controllername:index"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"./demo/policycustom/test:check"</span>,
<span class="hljs-string">"test:all"</span>,
<span class="hljs-string">"./subfolder/test2:index"</span>
]
}
},
...
more routes
}
</code></pre>
<h3 id="routepath">RoutePath</h3>
<p>This is the routing path and it follows the express4 standard routing. You can use jolly character and other type syntax <code>/admin*,</code> <code>/admin/:name</code> etc. etc.;</p>
<h3 id="verb">Verb</h3>
<p>Relates to the call verb and can assume any valid http verbs like GET, POST, PUT, DELETE etc etc. You can add more verbs for a single routePath:</p>
<pre><code class="lang-javascript">{
<span class="hljs-string">"/admin"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"action"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"./demo/policycustom/test:check"</span>,
<span class="hljs-string">"test:all"</span>,
<span class="hljs-string">"./subfolder/test2:index"</span>
]
},
<span class="hljs-string">"POST"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"action"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"test:all"</span>,
]
}
}
</code></pre>
<p><code>/admin</code> has GET and POST verbs.</p>
<h3 id="route">Route</h3>
<p>Relates to <code>file:method</code> to call a route address.</p>
<p>By default, the routing search controller file inside the default controller directory is: <code>./controlles</code>, and you can change it using the global options explained in this document.</p>
<p>If the controller is not set, the routing will search a file called with the same name as the json file, with "Controller" as suffix.</p>
<blockquote>
<p><strong>Example:</strong>
If you have a definition file called <code>users.json</code>, by default the route searches the controller <code>UsersControllers.json</code>.
For routes <em>auth.json</em> all routes call the controller <code>AuthController.js</code> etc.. etc..</p>
</blockquote>
<p><strong>Summarize route params</strong></p>
<p>If you omit the route params, the system routing assumes you have a default route controller path/name and a method called "index".</p>
<p>If you add only a parameter, it assumes that the controller is in the default directory with standard name <code>nameController.js</code> , and the parameter is the method that should be called. example route: "testall"</p>
<p>If the route params contain both values <code>./path/controllername:method</code> (user:index) it will search the controller using the default directory path structured as controller name followed by method. For example, route: "./test/user:index" searches for a controller called ./test/user with method index.</p>
<p>If you <strong>need to call a controller in a subfolder</strong>, simply add the path before the controller name. Example route: "./afolder/user:index", fire ./controller/afolder/user with method index.</p>
<p>If you <strong>need to call a controller starting to your project root</strong> simply add <code>.</code> before the path. Example route: "./lib/user:index", fire ./lib/user.js with method index.</p>
<h3 id="policy">Policy</h3>
<p>Is a module/function called before the controller (= middleware), by default it calls a file in ./policy named as you set in parameters "fileName" and a function named as you set in "functionName".</p>
<p>Example: policy: "auth/index" calls ./policy/auth.js and method index</p>
<p><strong>The syntax is the same as <code>route</code> params</strong></p>
<p>It can be a string for a single policy or an array for multiple policy files.</p>
<h3 id="cors">CORS</h3>
<p>Enable or disable Cross-origin resource sharing. default is true, look at global options for more info.</p>
<h3 id="regex">Regex</h3>
<p>You can set a regex to validate your route, however I discourage using it. Instead, I prefer to add this logic in the controller for better code speed. <strong>To set a rexeg route, use the prefix "RE " before pattern.</strong>. </p>
<pre><code class="lang-javascript">{
<span class="hljs-string">"RE /.*fly$/"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"action"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"./demo/policycustom/test:check"</span>,
<span class="hljs-string">"test:all"</span>,
<span class="hljs-string">"./subfolder/test2:index"</span>
]
}
}
</code></pre>
<h3 id="init-module">Init Module</h3>
<p>Configure the routing modules in your main js file, as any other nodes modules.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> routes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'json-routing'</span>);
<span class="hljs-keyword">new</span> routes(expressApp, options).start();
</code></pre>
<p>Example: </p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Includes</span>
<span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">var</span> app = express();
<span class="hljs-keyword">var</span> routes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'json-routing'</span>); <span class="hljs-comment">// add module</span>
...
<span class="hljs-comment">// your code..</span>
app.set(...);
app.use(...);
<span class="hljs-comment">// this is the magic!</span>
<span class="hljs-keyword">new</span> routes(app, {
<span class="hljs-string">"processdir"</span>: __dirname
}).start();
</code></pre>
<p><strong>IT'S VERY IMPORTANT TO SET <code>processdir": __dirname</code> if your project is in a subfolder of root. (example ./src/)</strong></p>
<h2 id="change-default-options">Change default Options</h2>
<p>When you initialize the module, you can specify a few options to customize the directory structure.
All are listed below with the default values. An explanation follows.</p>
<p>your main.js file. </p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Includes</span>
<span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">var</span> app = express();
<span class="hljs-keyword">var</span> routes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'json-routing'</span>); <span class="hljs-comment">// add module</span>
<span class="hljs-comment">// your code..</span>
app.set(...);
app.use(...);
<span class="hljs-comment">//define routes default options</span>
<span class="hljs-keyword">var</span> routeOptions = {
<span class="hljs-attr">routesPath</span> : <span class="hljs-string">"./api/routes"</span>,
<span class="hljs-attr">controllerPath</span> : <span class="hljs-string">"./api/controllers"</span>,
<span class="hljs-attr">policyPath</span> : <span class="hljs-string">"./api/policy"</span>,
<span class="hljs-attr">cors</span> : <span class="hljs-literal">true</span>,
<span class="hljs-attr">displayRoute</span> : <span class="hljs-literal">true</span>,
<span class="hljs-attr">defaultAction</span> : <span class="hljs-string">"index"</span>,
<span class="hljs-attr">processDir</span> : process.cwd()
}
<span class="hljs-comment">//init routes</span>
<span class="hljs-keyword">var</span> routeInfo = <span class="hljs-keyword">new</span> routes(app, routeOptions);
</code></pre>
<ul>
<li>routesPath : the path to your routes folder. <code>Default ./routes</code></li>
<li>controllerPath : the path to your controller folder. <code>Default ./controllers</code></li>
<li>policyPath : the path to your policy folder. <code>Default ./policy</code></li>
<li>cors : enable cross origin resource sharing for all routes. (more cors options coming soon..). <code>Default false</code></li>
<li>displayRoute : display in console loading route info, <code>default true</code>.</li>
<li>defaultAction : the function called in route if not specified. It's not so useful, but it's here!.<code>Default index</code></li>
<li>processDir : The root base path of the project, default <code>process.cwd()</code> set as <code>__dirname</code> if you need to start in a subfolder or complex project.</li>
</ul>
<p>If you omit routeOptions or some params it use defaults values.</p>
<h2 id="change-json-file-global-options">Change json file Global Options</h2>
<p>If you need to change options for all routes only for a specific *.json file, you can set in your file the key <code>GLOBAL</code> as in the following example:</p>
<p>user.json</p>
<pre><code class="lang-javascript">{
<span class="hljs-string">"GLOBAL"</span>: {
<span class="hljs-string">"controller"</span>: <span class="hljs-string">"./customdir/customControllerName"</span>,
<span class="hljs-string">"policy"</span>:[<span class="hljs-string">"config:setall"</span>,<span class="hljs-string">"config:connection"</span>],
<span class="hljs-string">"baseUrl"</span>:<span class="hljs-string">"/user"</span>
},
<span class="hljs-string">"/create"</span>: {
<span class="hljs-string">"PUT"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"index"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"auth:check"</span>,
<span class="hljs-string">"auth:adduserparams"</span>
]
}
}
}
</code></pre>
<p>Example: route controller is ./customdir/UserController.js</p>
<ul>
<li>controller: set a custom controller path for all routing file</li>
<li>policy: is an array of policy <code>file:action</code> to fire before controller</li>
<li>baseUrl: is a base path for all url routes in file. Example, inside a file all routes start with <code>/api/*</code>, i can set base url as <code>/api</code>. Now all file routes start with <code>/api</code>. If i have a routes <code>/users</code>, it fired when user called <code>/api/users</code></li>
</ul>
<blockquote>
<p><strong>NOTE:</strong> the key "GLOBAL" must be uppercase.</p>
</blockquote>
<h2 id="full-extended-example">Full extended example</h2>
<p><em>app.js</em></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>)
, app = express()
, port = process.env.PORT || <span class="hljs-number">3000</span>
, routing = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./lib/route'</span>);
<span class="hljs-comment">/**
* global options for routing
*
* set all file inside /api/* for a more cleaner code
*/</span>
<span class="hljs-keyword">var</span> routeOptions = {
<span class="hljs-attr">routesPath</span>: <span class="hljs-string">"./api/routes"</span>
, <span class="hljs-attr">controllersPath</span>: <span class="hljs-string">"./api/controllers"</span>
, <span class="hljs-attr">policyPath</span>: <span class="hljs-string">'./api/policy'</span>
, <span class="hljs-attr">cors</span>: <span class="hljs-literal">false</span>
, <span class="hljs-attr">processDir</span>: __dirname
};
<span class="hljs-comment">/**
* init json-routing
*/</span>
<span class="hljs-keyword">new</span> routing(app, routeOptions);
<span class="hljs-comment">/**
* standard express 4 routing
* yes.. you can use both routing together if you need
*/</span>
<span class="hljs-keyword">var</span> router = express.Router();
router.get(<span class="hljs-string">'/express/'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">req, res</span>) </span>{
res.send(<span class="hljs-string">' this is a standard routing '</span>);
});
app.use(<span class="hljs-string">'/'</span>, router);
<span class="hljs-comment">/**
* server start
*
* @type {http.Server}
*/</span>
<span class="hljs-keyword">var</span> server = app.listen(port, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Listening on port %d'</span>, server.address().port);
});
</code></pre>
<p>This is the main file, we set routing and add global setting to use ./api as root directory</p>
<p><em>./api/routes/users.json</em></p>
<pre><code class="lang-javascript">{
<span class="hljs-string">"/banned"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"./lib/bannedCustom:index"</span>,
}
},
<span class="hljs-string">"/user"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"find"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"auth:check"</span>,
<span class="hljs-string">"auth:adduserparams"</span>
]
},
<span class="hljs-string">"PUT"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"create"</span>,
<span class="hljs-string">"policy"</span>: [
<span class="hljs-string">"auth:check"</span>,
]
}
}
}
</code></pre>
<p>define the routes</p>
<p><em>./api/controllers/UsersController.js</em></p>
<pre><code class="lang-javascript">exports.index = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>) </span>{
res.send(<span class="hljs-string">' index routes '</span>);
};
exports.create = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>) </span>{
res.send(<span class="hljs-string">' create routes params:'</span>+req.params.name);
};
</code></pre>
<p>a basic controller logic</p>
<p><em>./api/controllers/bannedCustom.js</em></p>
<pre><code class="lang-javascript">exports.getbanned = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>) </span>{
res.send(<span class="hljs-string">' custom controller name '</span>);
};
</code></pre>
<p>this is the controller with custom name</p>
<p><em>./api/policy/auth.js</em></p>
<pre><code class="lang-javascript">exports.check = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>) </span>{
<span class="hljs-keyword">if</span> (!req.session.isLogged){
<span class="hljs-keyword">return</span> res.redirect(<span class="hljs-string">'http://'</span>+req.hostname+<span class="hljs-string">":3000/403"</span>);
}
next();
};
</code></pre>
<p>Let me explain this policy: it checks if a user is logged, else set a redirect, so we can use the middleware to check ACL, authorization or get/set global vars, and this is very useful.</p>
<h2 id="create-a-policy-file-and-pass-vars-to-controller">Create a Policy File and Pass vars to controller</h2>
<p>We encourage to use standard tecnique for best performance: use middleware.
using the full example described below we can create a standard policy file to attach a global var using <code>req</code></p>
<p><em>./api/policy/auth.js</em></p>
<pre><code class="lang-javascript">exports.getbanned = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>) </span>{
<span class="hljs-keyword">if</span> (!req.session.isLogged){
<span class="hljs-keyword">return</span> res.redirect(<span class="hljs-string">'http://'</span>+req.hostname+<span class="hljs-string">":3000/403"</span>);
}
<span class="hljs-comment">//use req</span>
req.session.lastPing = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
next();
};
</code></pre>
<p><strong>Read the value in the controller or policy</strong></p>
<p><em>./api/controllers/bannedCustom.js</em></p>
<pre><code class="lang-javascript">exports.getbanned = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req,res,next</span>) </span>{
res.send(<span class="hljs-string">' custom controller name, middleware loaded at: '</span>+req.session.lastPing);
};
</code></pre>
<h2 id="case-using-middleware">Case: using middleware</h2>
<p>A special case: if we want to add an authentication before some route, take a look at this example:</p>
<pre><code class="lang-javascript">{
<span class="hljs-string">"/admin*"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"./policy/auth:check"</span>,
},
<span class="hljs-string">"POST"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"auth:check"</span>,
},
<span class="hljs-string">"PUT"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"auth:check"</span>,
},
<span class="hljs-string">"DELETE"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"auth:check"</span>,
},
},
<span class="hljs-string">"/admin/dashboard"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"getItem"</span>,
}
},
<span class="hljs-string">"/admin/user"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"find"</span>,
},
<span class="hljs-string">"PUT"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"create"</span>,
}
}
}}
</code></pre>
<p>All <code>admin*</code> route calls the controller <code>auth</code>, so now <code>auth:check</code> is executed before all <code>admin*</code> controller and it becomes
a policy (=middleware) and for a clear structure i put the file in policy dir.</p>
<p>An alternative example use the global file option:</p>
<pre><code class="lang-javascript">{
<span class="hljs-string">"GLOBAL"</span>: {
<span class="hljs-string">"policy"</span>:[<span class="hljs-string">"auth:check"</span>],
<span class="hljs-string">"baseUrl"</span>:<span class="hljs-string">"/admin"</span>
},
<span class="hljs-string">"/dashboard"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"getItem"</span>,
}
},
<span class="hljs-string">"/user"</span>: {
<span class="hljs-string">"GET"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"find"</span>,
},
<span class="hljs-string">"PUT"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"create"</span>,
}
}
}}
</code></pre>
<h2 id="protected-route-with-jwt">Protected route with JWT</h2>
<p>You can protect a routes using <a href="https://jwt.io/">jwt</a>. Json-routing use <a href="https://github.com/auth0/express-jwt">auth0/express-jwt</a>.
To protect a route add a property <code>jwt:true</code> and set the global options for jwt as example.</p>
<p><strong>Before using jwt you need to install express-jwt manually: <code>npm install --save express-jwt</code></strong></p>
<p><em>Route file: protected.json</em> </p>
<pre><code>{
<span class="hljs-string">"/protected"</span>: {
<span class="hljs-string">"<span class="hljs-keyword">GET</span>"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"index"</span>,
<span class="hljs-string">"jwt"</span>: true
}
},
<span class="hljs-string">"/notprotected"</span>: {
<span class="hljs-string">"<span class="hljs-keyword">GET</span>"</span>: {
<span class="hljs-string">"route"</span>: <span class="hljs-string">"indexnot"</span>,
<span class="hljs-string">"jwt"</span>: false
}
}
}
</code></pre><p>NB note to pretect a route we need to set <code>jwt:true</code></p>
<p>In main file: server.ts/js</p>
<pre><code><span class="hljs-params">...</span>
export const routeInfo: <span class="hljs-built_in">Array</span><IRouteInfo> = <span class="hljs-literal">new</span> JsonRoute(app, {
<span class="hljs-string">"processdir"</span>: __dirname,
<span class="hljs-string">"jwt"</span>: {
<span class="hljs-string">"secret"</span>: <span class="hljs-string">"12345678910abc"</span>
}
}).start();
<span class="hljs-params">...</span>
</code></pre><p>NB in json-routing init we need to set jwt object with secret</p>
<p>DONE!!!!!</p>
<h3 id="jwt-extra-route-for-error">jwt extra route for error</h3>
<p>to make a better jwt unauthorized response we can add a specific route like this:</p>
<pre><code>export <span class="hljs-keyword">const</span> routeInfo: <span class="hljs-built_in">Array</span><IRouteInfo> = <span class="hljs-keyword">new</span> JsonRoute(app, {
<span class="hljs-string">"processdir"</span>: __dirname,
<span class="hljs-string">"jwt"</span>: {
<span class="hljs-string">"secret"</span>: <span class="hljs-string">"12345678910abc"</span>
}
}).start();
app.use((<span class="hljs-built_in">err</span>: any, req: express.<span class="hljs-built_in">Request</span>, res: express.<span class="hljs-built_in">Response</span>, <span class="hljs-keyword">next</span>: express.NextFunction) => {
<span class="hljs-keyword">if</span> (<span class="hljs-built_in">err</span>.name === <span class="hljs-comment">'UnauthorizedError') {</span>
res.status(<span class="hljs-number">401</span>).json({<span class="hljs-string">"message"</span>: <span class="hljs-string">"invalid token..."</span>});
}
<span class="hljs-keyword">next</span>();
});
</code></pre><h2 id="add-a-global-route-prefix">Add a global route prefix</h2>
<p>You can add a global prefix path for all routes set options.urlPrefix</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> routeInfo: <span class="hljs-built_in">Array</span><IRouteInfo> = <span class="hljs-keyword">new</span> JsonRoute(app, {
<span class="hljs-string">"processdir"</span>: __dirname,
<span class="hljs-string">"urlPrefix"</span>:<span class="hljs-string">"/api/v1"</span>
}).start();
</code></pre><p>All routes now start with <code>/api/vi</code></p>
<h2 id="route-validation-params">Route validation params</h2>
<p>It can be done by express-validator using schema. Add <code>validators</code> object with: </p>
<ul>
<li>params -> route params es /home/:id</li>
<li>query -> query params es -> /home?id=124</li>
<li>boby -> body params es post params like {"id":"1233"}</li>
</ul>
<p>according <a href="https://github.com/ctavan/express-validator">express-validator</a> "validation by Schema"</p>
<p>route file.json</p>
<pre><code>{
<span class="hljs-attr">"/validateparam/:id"</span>: {
<span class="hljs-attr">"GET"</span>: {
<span class="hljs-attr">"route"</span>: <span class="hljs-string">"validateparam"</span>,
<span class="hljs-attr">"jwt"</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">"validators"</span>: {
<span class="hljs-attr">"params"</span>: {
<span class="hljs-attr">"id"</span>: {
<span class="hljs-attr">"notEmpty"</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">"isLength"</span>: {
<span class="hljs-attr">"options"</span>: [
{
<span class="hljs-attr">"min"</span>: <span class="hljs-number">5</span>,
<span class="hljs-attr">"max"</span>: <span class="hljs-number">10</span>
}
],
<span class="hljs-attr">"errorMessage"</span>: <span class="hljs-string">"Must be between 2 and 10 chars long"</span>
},
<span class="hljs-attr">"errorMessage"</span>: <span class="hljs-string">"id is required"</span>
}
}
}
}
}
}
</code></pre><p><strong>NB body-parser middleware is injected by json-routing, you can pass params in global params</strong></p>
<h2 id="all-options">ALL OPTIONS</h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> interface IOptions {
routesPath?: string
, controllersPath?: string
, policyPath?: string
, processdir?: string
, cors?: boolean
, displayRoute?: boolean
, defaultAction?: string
, urlPrefix?: string
, jwt?: {
<span class="hljs-attr">secret</span>: any
}
, bodyParserUrlEncoded?: any
}
...
let options: IOptions;
...
<span class="hljs-comment">// add params to optins object</span>
<span class="hljs-keyword">let</span> routeInfo:<span class="hljs-built_in">Array</span><any> = <span class="hljs-keyword">new</span> JsonRoute(app, options}).start();
</code></pre>
<h2 id="example">Example</h2>
<p>Look at ./demo for a fully working example.</p>
<h2 id="changelog-2-0-5">Changelog 2.0.5</h2>
<ul>
<li>better cors support</li>
<li>can be enable/disable cors for single routes</li>
<li>better console output</li>
</ul>
<h2 id="changelog-2-0-4">Changelog 2.0.4</h2>
<ul>
<li>add validator</li>
</ul>
<h2 id="changelog-2-0-1">Changelog 2.0.1</h2>
<ul>
<li>add protected route with JWT</li>
</ul>
<h2 id="changelog-2-0-0">Changelog 2.0.0</h2>
<ul>
<li>add urlPrefix for all routes</li>
</ul>
<h2 id="changelog-2-0-0rc1">Changelog 2.0.0Rc1</h2>
<ul>
<li>minor fix</li>
<li>route with regular expression</li>
</ul>
<h2 id="changelog-2-0-0b1">Changelog 2.0.0b1</h2>
<ul>
<li>completely rewrite in typecript (build transpiled in es6)</li>
<li>remove global policy options </li>
<li>global now has "controller" option</li>
<li>make more simple</li>
<li>regex now work good!</li>
<li>more speed</li>
<li>add test and coverage</li>
</ul>
<h2 id="changelog-0-1-5">Changelog 0.1.5</h2>
<ul>
<li>Preparing for typescript... es6 and node > 6.4 rewrite, removed underscore. No esternal modules deps!!</li>
</ul>
<h2 id="changelog-0-1-0">Changelog 0.1.0</h2>
<ul>
<li>minor fix</li>
</ul>
<h2 id="changelog-0-1-0">Changelog 0.1.0</h2>
<ul>
<li>removed not working cors features for file definition and route... working on it.. cors for global setting work good.</li>
</ul>
<h2 id="changelog-0-0-27">Changelog 0.0.27</h2>
<ul>
<li>improve log info</li>
</ul>
<h2 id="changelog-0-0-26">Changelog 0.0.26</h2>
<ul>
<li>add <code>defaultAction</code>, not so useful, but it's here!.</li>
<li>start cleaning code</li>
<li>add <code>CORS</code> Global file options, to enable CORS only in specific *.json routes</li>
<li>add <code>CORS</code> for specific routes.</li>
<li>route log info display CORS status</li>
</ul>
<h2 id="changelog-0-0-25">Changelog 0.0.25</h2>
<ul>
<li>improve route info on load, it can disabled with global options "displayRoute:false"</li>
</ul>
<h2 id="changelog-0-0-24">Changelog 0.0.24</h2>
<ul>
<li>initial CORS support (look at "Change default Options"), more CORS options coming soon...</li>
</ul>
<h2 id="changelog-0-23">Changelog 0.23</h2>
<ul>
<li>fix url union for windows platform</li>
</ul>
<h2 id="changelog-0-0-20">Changelog 0.0.20</h2>
<ul>
<li>fix policy string is not added if global policy is set</li>
<li>working test</li>
</ul>
<h2 id="changelog-0-0-19">Changelog 0.0.19</h2>
<ul>
<li>add Global base Url</li>
</ul>
<h2 id="changelog-0-0-17">Changelog 0.0.17</h2>
<ul>
<li>fix default route</li>
<li>add mre error check</li>
</ul>
<h2 id="changelog-0-0-15">Changelog 0.0.15</h2>
<ul>
<li>add goblal file policy (=middleware)</li>
</ul>
<h2 id="changelog-from-version-0-0-13">Changelog from version 0.0.13</h2>
<ul>
<li>No longer compatible with <0.13 version</li>
<li>new json syntax</li>
</ul>
</div>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class="globals ">
<a href="globals.html"><em>Globals</em></a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_interfaces_icontrollerglobal_.html">"interfaces/IController<wbr>Global"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_interfaces_ihandler_.html">"interfaces/IHandler"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_interfaces_ijsonroute_.html">"interfaces/IJson<wbr>Route"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_interfaces_ioptions_.html">"interfaces/IOptions"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_interfaces_irouteinfo_.html">"interfaces/IRoute<wbr>Info"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_jroute_handler_.html">"jroute-<wbr>handler"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_json_route_.html">"json-<wbr>route"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_route_controller_.html">"route-<wbr>controller"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_route_middleware_.html">"route-<wbr>middleware"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_route_validator_.html">"route-<wbr>validator"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_routes_display_.html">"routes-<wbr>display"</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
</ul>
</nav>
</div>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
</ul>
</div>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="http://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="assets/js/search.js"><' + '/script>');</script>
</body>
</html>