Comparing version 1.0.0 to 2.0.0
69
index.js
@@ -1,3 +0,1 @@ | ||
var APP_ROOT = process.env.PWD; | ||
var path = require('path'); | ||
@@ -20,21 +18,2 @@ | ||
function route (url, method, instance) { | ||
var router = instance[method.toLowerCase()] || instance[method.toUpperCase()]; | ||
if (router) { | ||
var filters = (instance.filters || []).concat(router.filters || []); | ||
var chain = filters.concat(router instanceof Array ? router : [router]); | ||
var m = method.toLowerCase(); | ||
if (typeof this[m] != 'function') { | ||
console.error('[rainbow]: http method "' + method + '" is not supported.'); | ||
return; | ||
} | ||
this[m].apply(this, | ||
[joinParam(url, router.params)].concat(chain) | ||
); | ||
} | ||
} | ||
/** | ||
@@ -44,7 +23,8 @@ * Main function to initialize routers of a Express app. | ||
* @param {Object} paths (optional) For configure relative paths of | ||
* controllers and filters rather than defaults. | ||
* controllers rather than defaults. | ||
*/ | ||
module.exports = function (options = {}) { | ||
var router = express.Router(); | ||
var ctrlDir = options.controllers || path.join(APP_ROOT, 'controllers'); | ||
var middleware = express.Router(); | ||
var ctrlDir = path.join(path.dirname(module.parent.filename), options.controllers || 'controllers'); | ||
var keyRE = new RegExp('(' + methods.join('|') + ')(?:\\s+((?:\\/(.+)\\/)|([^\\/].*[^\\/])))?', 'i') | ||
@@ -55,15 +35,38 @@ glob.sync(ctrlDir + "/**/*.js").forEach(function (file) { | ||
var instance = require(file); | ||
var single = typeof instance == 'function'; | ||
var url = file.replace(ctrlDir, '').replace(/\/index$/, '/'); | ||
single ? route.call(router, url, 'ALL', {ALL: instance}) : | ||
methods.forEach(function (method) { | ||
if (instance[method.toLowerCase()]) { | ||
console.warn('[rainbow]: Lower case HTTP methods are deprecated. Please change "' + method + '" in file:' + file + ' to upper case.'); | ||
} | ||
route.call(router, url, method, instance); | ||
}); | ||
Object.keys(instance).forEach(function (key) { | ||
if (key === 'filters') { | ||
return; | ||
} | ||
var matcher = key.match(keyRE); | ||
if (!matcher) { | ||
return console.error('[rainbow]: Router key pattern "%s" is invalid.', key); | ||
} | ||
var method = matcher[1].toLowerCase(); | ||
if (methods.indexOf(method) === -1 && method !== 'all') { | ||
return console.error('[rainbow]: Unknown HTTP method "%s".', method); | ||
} | ||
if (typeof middleware[method] !== 'function') { | ||
return console.error('[rainbow]: HTTP method "%s" is not supported.', method); | ||
} | ||
var router = instance[key]; | ||
var filters = (instance.filters || []).concat(router.filters || []); | ||
var chain = filters.concat(router instanceof Array ? router : [router]); | ||
var params = matcher[2] ? | ||
(matcher[3] ? new RegExp(matcher[3]) : matcher[4]) : | ||
router.params; | ||
var pathname = joinParam(url, params); | ||
middleware[method].apply(middleware, [pathname].concat(chain)); | ||
}); | ||
}); | ||
return router; | ||
return middleware; | ||
}; |
{ | ||
"name": "rainbow", | ||
"description": "Express router middleware for RESTful API base on certain folder path", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"author": "mytharcher <mytharcher@gmail.com>", | ||
"main" : "index.js", | ||
"main": "index.js", | ||
"scripts": { | ||
@@ -8,0 +8,0 @@ "test": "mocha" |
124
README.md
Rainbow | ||
======= | ||
[简体中文](http://mytharcher.github.com/posts/npm-rainbow.html) | ||
[简体中文](http://yanjunyi.com/blog/posts/npm-rainbow) | ||
@@ -10,13 +10,15 @@ A node [Express][] router middleware for Ajax RESTful API base on certain folder path. | ||
## Installation ## | ||
Installation | ||
---------- | ||
```bash | ||
~~~bash | ||
$ npm install rainbow | ||
``` | ||
~~~ | ||
## Usage ## | ||
Usage | ||
---------- | ||
In your express application main file `app.js`: | ||
```javascript | ||
~~~javascript | ||
var express = require('express'); | ||
@@ -28,8 +30,9 @@ var rainbow = require('rainbow'); | ||
// Here using Rainbow to initialize all routers | ||
app.use('api/', rainbow()); | ||
app.use('/api', rainbow()); | ||
app.listen(6060); | ||
``` | ||
~~~ | ||
### Controllers ### | ||
Controllers | ||
---------- | ||
@@ -42,13 +45,18 @@ All your controllers for catching HTTP request should be defined in each file in `controllers/` folder (could be changed) as same path in URL. | ||
```javascript | ||
~~~javascript | ||
exports.GET = function (req, res) { | ||
res.send(200, 'Simple getting.'); | ||
}; | ||
``` | ||
~~~ | ||
If you need some filters, just add a `filters` array property which contains your filters each as a function to the handle function like this: | ||
If you need some filters, just use an array (**RECOMMENDED**), or add a `filters` array property which contains your filters each as a function to the handle function like this: | ||
```javascript | ||
~~~javascript | ||
var authorization = require('authorization'); | ||
exports.GET = [authorization, function (req, res) { | ||
res.send(200, 'Using middleware queue array'); | ||
}]; | ||
// or | ||
exports.GET = function (req, res) { | ||
@@ -59,7 +67,7 @@ res.send(200, 'Simple getting.'); | ||
exports.GET.filters = [authorization]; | ||
``` | ||
~~~ | ||
Also you could define other HTTP methods handlers, but make sure in one file each URL! Example in `controllers/user.js`: | ||
```javascript | ||
~~~javascript | ||
exports.GET = function (req, res) { | ||
@@ -79,19 +87,38 @@ User.find({where: req.query.name}).success(function (user) { | ||
// ... | ||
``` | ||
~~~ | ||
If you want all methods to be process in only one controller(something not RESTful), just make exports to be the handle function: | ||
```javascript | ||
~~~javascript | ||
module.exports = function (req, res) { | ||
// all your process | ||
}; | ||
``` | ||
~~~ | ||
CoffeeScript file with `.coffee` suffix will not be supported from v1.0. | ||
Params | ||
---------- | ||
### Params ### | ||
Params config is supported via router key definition (**RECOMMENDED**) from v2.0.0. Now you can define express-like routers as a form of `<method> <params>`. Named params form as in express could be same like `:name`, while regular expression form should also use string type and wrapped with `/` at beginning and end. Here are examples: | ||
Rainbow started to support param form URL from version 0.1.0. Now you can define your controllers URL with params resolved by native Express like this: | ||
~~~javascript | ||
// normal router without params | ||
// will match when GET with no params | ||
exports.GET = function (req, res) {}; | ||
```javascript | ||
// router with named params | ||
// will match when GET /:username | ||
exports['GET :username'] = function (req, res) { | ||
res.send(req.params.username); | ||
}; | ||
// router with regular expression params | ||
// will match when GET /123/profile | ||
exports['GET /(\\d+)/profile/'] = function (req, res) { | ||
res.send('profile by user id: ' + req.params[0]); | ||
}; | ||
~~~ | ||
Params config is also supported via `.params` form URL from v0.1.0. You can define your controllers URL with params resolved by native Express like this: | ||
~~~javascript | ||
exports.GET = function (req, res) { | ||
@@ -103,7 +130,7 @@ var id = req.params.id; | ||
exports.GET.params = ':id?'; | ||
``` | ||
~~~ | ||
Or you can use regular expression also: | ||
```javascript | ||
~~~javascript | ||
exports.GET = function (req, res) { | ||
@@ -114,11 +141,12 @@ console.log(req.params); | ||
exports.GET.params = /(\d+)(?:\.\.(\d+))?/; | ||
``` | ||
~~~ | ||
But make sure no regular expression `^` used as starter and `$` as ender, or rainbow could not resolve the expression correctly. | ||
But make sure no regular expression `^` used as starter and `$` as ender, or rainbow could not resolve the expression correctly. And be ware of the tailing slash when using `.params` definition, the `GET /resource` will be not found, while `GET /resources/` would be match. | ||
### Filters ### | ||
Filters | ||
---------- | ||
Filter is as same as a origin middleware in Express. Define an action with filters by using `.filters` property as an array. Here `authorization.js` is a example for intecepting by non-authenticated user before `GET` `http://yourapp:6060/something`: | ||
```javascript | ||
~~~javascript | ||
module.exports = function (req, res, next) { | ||
@@ -142,7 +170,7 @@ console.log('processing authorization...'); | ||
}; | ||
``` | ||
~~~ | ||
Filters only support function from v1.0. | ||
Filters only support function from v1.0.0. | ||
```javascript | ||
~~~javascript | ||
// controller file test.js route to [GET]/test | ||
@@ -159,7 +187,7 @@ function myFilter (req, res, next) { | ||
exports.GET.filters = [myFilter]; | ||
``` | ||
~~~ | ||
If you need some filters to be applied for all methods in an URL, you could use URL level filters definition: | ||
```javascript | ||
~~~javascript | ||
// controller file test.js route to [GET|POST]/test | ||
@@ -170,3 +198,3 @@ exports.GET = function (req, res) {}; | ||
exports.filters = [session]; | ||
``` | ||
~~~ | ||
@@ -179,12 +207,30 @@ When user `GET:/test` the filter `session` would run, and when `POST:/test` URL level filter `session` run first and then `validation`. | ||
```javascript | ||
~~~javascript | ||
app.use(rainbow({ | ||
controllers: '/your/controllers/path' | ||
controllers: 'controllers/path' | ||
})); | ||
``` | ||
~~~ | ||
These paths are all **ABSOLUTE** file path! | ||
Path option here is **RELATIVE** path to your `app.js` file! | ||
## Troubleshooting ## | ||
Change log | ||
---------- | ||
### 2.0.0 ### | ||
* Parameters definition supports key form with HTTP method (e.g.: `GET :id`). | ||
* Option of controllers path changed from absolute to relative. | ||
### 1.0.0 ### | ||
* Main API changed from `rainbow.route(app)` to `app.use(rainbow())`. | ||
* Add `function` type support for filters definition. | ||
* Remove `string` named filters definition. Also remove the filters path option in config. | ||
* Add `Array` type support for router definition. | ||
* Remove `.coffee` support. | ||
* Add test cases. | ||
Troubleshooting | ||
---------- | ||
0. Gmail me: mytharcher | ||
@@ -191,0 +237,0 @@ 0. Write a [issue](https://github.com/mytharcher/rainbow/issues) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
8920
55
234
2