diff --git a/README.md b/README.md index 5265a18..0df6006 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ powerful, flexible and RESTful APIs for enterprise easily! - [API](#api) * [KoaBetterRouter](#koabetterrouter) * [.loadMethods](#loadmethods) - * [.addRoute](#addroute) * [.createRoute](#createroute) + * [.addRoute](#addroute) + * [.groupRoutes](#grouproutes) * [.middleware](#middleware) * [.legacyMiddleware](#legacymiddleware) - * [.groupRoutes](#grouproutes) - [Related](#related) - [Contributing](#contributing) @@ -104,7 +104,44 @@ console.log(router.put) // => function console.log(router.del) // => function ``` -### [.addRoute](index.js#L166) +### [.createRoute](index.js#L143) +> Just creates route object without adding it to `this.routes` array. + +**Params** + +* `` **{String}**: http verb or `'GET /users'` +* `[route]` **{String|Function}**: for what `ctx.path` handler to be called +* `...fns` **{Function}**: can be array or single function, any number of arguments after `route` can be given too +* `returns` **{Object}**: plain `route` object with useful properties + +**Example** + +```js +let router = require('koa-better-router')({ prefix: '/api' }) +let route = router.createRoute('GET', '/users', [ + function (ctx, next) {}, + function (ctx, next) {}, + function (ctx, next) {}, +]) + +console.log(route) +// => { +// prefix: '/api', +// route: '/users', +// pathname: '/users', +// path: '/api/users', +// match: matcher function against `route.path` +// method: 'GET', +// middlewares: array of middlewares for this route +// } + +console.log(route.match('/foobar')) // => false +console.log(route.match('/users')) // => false +console.log(route.match('/api/users')) // => true +console.log(route.middlewares.length) // => 3 +``` + +### [.addRoute](index.js#L240) > Powerful method to add `route` if you don't want to populate you router instance with dozens of methods. The `method` can be just HTTP verb or `method` plus `route` something like `'GET /users'`. Both modern and generators middlewares can be given too, and can be combined too. **Adds routes to `this.routes` array**. **Params** @@ -159,44 +196,49 @@ app.listen(4290, () => { }) ``` -### [.createRoute](index.js#L210) -> Just creates route object without adding it to `this.routes` array. +### [.groupRoutes](index.js#L297) +> Groups multiple _"Route Objects"_ into one which middlewares will be these middlewares from the last "source". So let say you have `dest` route with 2 middlewares appended to it and the `src1` route has 3 middlewares, the final (returned) route object will have these 3 middlewares from `src1` not the middlewares from `dest`. Make sense? If not this not make sense for you, please open an issue here, so we can discuss and change it (then will change it in the [koa-rest-router][] too, because there the things with method `.groupResource` are the same). **Params** -* `` **{String}**: http verb or `'GET /users'` -* `[route]` **{String|Function}**: for what `ctx.path` handler to be called -* `...fns` **{Function}**: can be array or single function, any number of arguments after `route` can be given too -* `returns` **{Object}**: plain `route` object with useful properties +* `dest` **{Object}**: known as _"Route Object"_ +* `src1` **{Object}**: second _"Route Object"_ +* `src2` **{Object}**: third _"Route Object"_ +* `returns` **{Object}**: totally new _"Route Object"_ using `.createRotue` under the hood **Example** ```js -let router = require('koa-better-router')({ prefix: '/api' }) -let route = router.createRoute('GET', '/users', [ - function (ctx, next) {}, - function (ctx, next) {}, - function (ctx, next) {}, -]) +let router = require('./index')({ prefix: '/api/v3' }) -console.log(route) -// => { -// prefix: '/api', -// route: '/users', -// pathname: '/users', -// path: '/api/users', -// match: matcher function against `route.path` -// method: 'GET', -// middlewares: array of middlewares for this route +let foo = router.createRoute('GET /foo/qux/xyz', function (ctx, next) {}) +let bar = router.createRoute('GET /bar', function (ctx, next) {}) + +let baz = router.groupRoutes(foo, bar) +console.log(baz) +// => Route Object { +// prefix: '/api/v3', +// path: '/api/v3/foo/qux/sas/bar', +// pathname: '/foo/qux/sas/bar' +// ... // } -console.log(route.match('/foobar')) // => false -console.log(route.match('/users')) // => false -console.log(route.match('/api/users')) // => true -console.log(route.middlewares.length) // => 3 +// Server part +let Koa = require('koa') +let app = new Koa() + +router.routes = router.routes.concat(baz) +app.use(router.middleware()) +app.listen(2222, () => { + console.log('Server listening on http://localhost:2222') + + router.routes.forEach((route) => { + console.log(`${route.method} http://localhost:2222${route.path}`) + }) +}) ``` -### [.middleware](index.js#L299) +### [.middleware](index.js#L365) > Active all routes that are defined. You can pass `opts` to pass different `prefix` for your routes. So you can have multiple prefixes with multiple routes using just one single router. You can also use multiple router instances. Pass `legacy: true` to `opts` and you will get generator function that can be used in Koa v1. **Params** @@ -242,7 +284,7 @@ app.listen(4321, () => { }) ``` -### [.legacyMiddleware](index.js#L379) +### [.legacyMiddleware](index.js#L445) > Converts the modern middleware routes to generator functions using [koa-convert][].back under the hood. It is sugar for the `.middleware(true)` or `.middleware({ legacy: true })` * `returns` **{Function|GeneratorFunction}** @@ -264,48 +306,6 @@ app.listen(3333, () => { }) ``` -### [.groupRoutes](index.js#L434) -> Groups multiple _"Route Objects"_ into one which middlewares will be these middlewares from the last "source". So let say you have `dest` route with 2 middlewares appended to it and the `src1` route has 3 middlewares, the final (returned) route object will have these 3 middlewares from `src1` not the middlewares from `dest`. Make sense? If not this not make sense for you, please open an issue here, so we can discuss and change it (then will change it in the [koa-rest-router][] too, because there the things with method `.groupResource` are the same). - -**Params** - -* `dest` **{Object}**: known as _"Route Object"_ -* `src1` **{Object}**: second _"Route Object"_ -* `src2` **{Object}**: third _"Route Object"_ -* `returns` **{Object}**: totally new _"Route Object"_ using `.createRotue` under the hood - -**Example** - -```js -let router = require('./index')({ prefix: '/api/v3' }) - -let foo = router.createRoute('GET /foo/qux/xyz', function (ctx, next) {}) -let bar = router.createRoute('GET /bar', function (ctx, next) {}) - -let baz = router.groupRoutes(foo, bar) -console.log(baz) -// => Route Object { -// prefix: '/api/v3', -// path: '/api/v3/foo/qux/sas/bar', -// pathname: '/foo/qux/sas/bar' -// ... -// } - -// Server part -let Koa = require('koa') -let app = new Koa() - -router.routes = router.routes.concat(baz) -app.use(router.middleware()) -app.listen(2222, () => { - console.log('Server listening on http://localhost:2222') - - router.routes.forEach((route) => { - console.log(`${route.method} http://localhost:2222${route.path}`) - }) -}) -``` - ## Related - [koa-bel](https://www.npmjs.com/package/koa-bel): View engine for `koa` without any deps, built to be used with… [more](https://github.com/tunnckocore/koa-bel#readme) | [homepage](https://github.com/tunnckocore/koa-bel#readme "View engine for `koa` without any deps, built to be used with `bel`. Any other engines that can be written in `.js` files would work, too.") - [koa-better-body](https://www.npmjs.com/package/koa-better-body): Full-featured [koa][] body parser! Support parsing text, buffer, json, json patch, json… [more](https://github.com/tunnckocore/koa-better-body#readme) | [homepage](https://github.com/tunnckocore/koa-better-body#readme "Full-featured [koa][] body parser! Support parsing text, buffer, json, json patch, json api, csp-report, multipart, form and urlencoded bodies. Works for koa@1, koa@2 and will work for koa@3.") diff --git a/index.js b/index.js index 3f31499..8b16853 100644 --- a/index.js +++ b/index.js @@ -102,6 +102,80 @@ KoaBetterRouter.prototype.loadMethods = function loadMethods () { return this } +/** + * > Just creates route object without adding it to `this.routes` array. + * + * **Example** + * + * ```js + * let router = require('koa-better-router')({ prefix: '/api' }) + * let route = router.createRoute('GET', '/users', [ + * function (ctx, next) {}, + * function (ctx, next) {}, + * function (ctx, next) {}, + * ]) + * + * console.log(route) + * // => { + * // prefix: '/api', + * // route: '/users', + * // pathname: '/users', + * // path: '/api/users', + * // match: matcher function against `route.path` + * // method: 'GET', + * // middlewares: array of middlewares for this route + * // } + * + * console.log(route.match('/foobar')) // => false + * console.log(route.match('/users')) // => false + * console.log(route.match('/api/users')) // => true + * console.log(route.middlewares.length) // => 3 + * ``` + * + * @param {String} `` http verb or `'GET /users'` + * @param {String|Function} `[route]` for what `ctx.path` handler to be called + * @param {Function} `...fns` can be array or single function, any number of + * arguments after `route` can be given too + * @return {Object} plain `route` object with useful properties + * @api public + */ + +KoaBetterRouter.prototype.createRoute = function createRoute (method, route, fns) { + let args = [].slice.call(arguments, 3) + let middlewares = utils.arrayify(fns).concat(args) + + if (typeof method !== 'string') { + throw new TypeError('.createRoute: expect `method` to be a string') + } + + let parts = method.split(' ') + method = parts[0] || 'get' + method = method.toUpperCase() + + if (typeof route === 'function') { + middlewares = [route].concat(middlewares) + route = parts[1] + } + if (Array.isArray(route)) { + middlewares = route.concat(middlewares) + route = parts[1] + } + if (typeof route !== 'string') { + throw new TypeError('.createRoute: expect `route` be string, array or function') + } + + let prefixed = utils.createPrefix(this.options.prefix, route) + return { + prefix: this.options.prefix, + path: prefixed, + pathname: route, + route: route, + match: this.route(prefixed), + method: method, + middlewares: middlewares + } +} + /** * > Powerful method to add `route` if you don't want * to populate you router instance with dozens of methods. @@ -170,77 +244,69 @@ KoaBetterRouter.prototype.addRoute = function addRoute (method, route, fns) { } /** - * > Just creates route object without adding it to `this.routes` array. + * > Groups multiple _"Route Objects"_ into one which middlewares + * will be these middlewares from the last "source". So let say + * you have `dest` route with 2 middlewares appended to it and + * the `src1` route has 3 middlewares, the + * final (returned) route object will have these 3 middlewares + * from `src1` not the middlewares from `dest`. Make sense? + * If not this not make sense for you, please open an issue here, + * so we can discuss and change it (then will change it + * in the [koa-rest-router][] too, because there the things with + * method `.groupResource` are the same). * * **Example** * * ```js - * let router = require('koa-better-router')({ prefix: '/api' }) - * let route = router.createRoute('GET', '/users', [ - * function (ctx, next) {}, - * function (ctx, next) {}, - * function (ctx, next) {}, - * ]) + * let router = require('./index')({ prefix: '/api/v3' }) * - * console.log(route) - * // => { - * // prefix: '/api', - * // route: '/users', - * // pathname: '/users', - * // path: '/api/users', - * // match: matcher function against `route.path` - * // method: 'GET', - * // middlewares: array of middlewares for this route + * let foo = router.createRoute('GET /foo/qux/xyz', function (ctx, next) {}) + * let bar = router.createRoute('GET /bar', function (ctx, next) {}) + * + * let baz = router.groupRoutes(foo, bar) + * console.log(baz) + * // => Route Object { + * // prefix: '/api/v3', + * // path: '/api/v3/foo/qux/sas/bar', + * // pathname: '/foo/qux/sas/bar' + * // ... * // } * - * console.log(route.match('/foobar')) // => false - * console.log(route.match('/users')) // => false - * console.log(route.match('/api/users')) // => true - * console.log(route.middlewares.length) // => 3 + * // Server part + * let Koa = require('koa') + * let app = new Koa() + * + * router.routes = router.routes.concat(baz) + * app.use(router.middleware()) + * app.listen(2222, () => { + * console.log('Server listening on http://localhost:2222') + * + * router.routes.forEach((route) => { + * console.log(`${route.method} http://localhost:2222${route.path}`) + * }) + * }) * ``` * - * @param {String} `` http verb or `'GET /users'` - * @param {String|Function} `[route]` for what `ctx.path` handler to be called - * @param {Function} `...fns` can be array or single function, any number of - * arguments after `route` can be given too - * @return {Object} plain `route` object with useful properties + * @param {Object} `dest` known as _"Route Object"_ + * @param {Object} `src1` second _"Route Object"_ + * @param {Object} `src2` third _"Route Object"_ + * @return {Object} totally new _"Route Object"_ using `.createRotue` under the hood * @api public */ -KoaBetterRouter.prototype.createRoute = function createRoute (method, route, fns) { - let args = [].slice.call(arguments, 3) - let middlewares = utils.arrayify(fns).concat(args) - - if (typeof method !== 'string') { - throw new TypeError('.createRoute: expect `method` to be a string') +KoaBetterRouter.prototype.groupRoutes = function groupRoutes (dest, src1, src2) { + if (!utils.isObject(dest) && !utils.isObject(src1)) { + throw new TypeError('.groupRoutes: expect both `dest` and `src1` be objects') } + let pathname = dest.route + src1.route + let route = this.createRoute(dest.method, pathname, src1.middlewares) - let parts = method.split(' ') - method = parts[0] || 'get' - method = method.toUpperCase() - - if (typeof route === 'function') { - middlewares = [route].concat(middlewares) - route = parts[1] - } - if (Array.isArray(route)) { - middlewares = route.concat(middlewares) - route = parts[1] - } - if (typeof route !== 'string') { - throw new TypeError('.createRoute: expect `route` be string, array or function') + if (utils.isObject(src2)) { + pathname = route.route + src2.route + route = this.createRoute(dest.method, pathname, src2.middlewares) } - let prefixed = utils.createPrefix(this.options.prefix, route) - return { - prefix: this.options.prefix, - path: prefixed, - pathname: route, - route: route, - match: this.route(prefixed), - method: method, - middlewares: middlewares - } + return route } /** @@ -380,72 +446,6 @@ KoaBetterRouter.prototype.legacyMiddleware = function legacyMiddleware () { return utils.convert.back(this.middleware()) } -/** - * > Groups multiple _"Route Objects"_ into one which middlewares - * will be these middlewares from the last "source". So let say - * you have `dest` route with 2 middlewares appended to it and - * the `src1` route has 3 middlewares, the - * final (returned) route object will have these 3 middlewares - * from `src1` not the middlewares from `dest`. Make sense? - * If not this not make sense for you, please open an issue here, - * so we can discuss and change it (then will change it - * in the [koa-rest-router][] too, because there the things with - * method `.groupResource` are the same). - * - * **Example** - * - * ```js - * let router = require('./index')({ prefix: '/api/v3' }) - * - * let foo = router.createRoute('GET /foo/qux/xyz', function (ctx, next) {}) - * let bar = router.createRoute('GET /bar', function (ctx, next) {}) - * - * let baz = router.groupRoutes(foo, bar) - * console.log(baz) - * // => Route Object { - * // prefix: '/api/v3', - * // path: '/api/v3/foo/qux/sas/bar', - * // pathname: '/foo/qux/sas/bar' - * // ... - * // } - * - * // Server part - * let Koa = require('koa') - * let app = new Koa() - * - * router.routes = router.routes.concat(baz) - * app.use(router.middleware()) - * app.listen(2222, () => { - * console.log('Server listening on http://localhost:2222') - * - * router.routes.forEach((route) => { - * console.log(`${route.method} http://localhost:2222${route.path}`) - * }) - * }) - * ``` - * - * @param {Object} `dest` known as _"Route Object"_ - * @param {Object} `src1` second _"Route Object"_ - * @param {Object} `src2` third _"Route Object"_ - * @return {Object} totally new _"Route Object"_ using `.createRotue` under the hood - * @api public - */ - -KoaBetterRouter.prototype.groupRoutes = function groupRoutes (dest, src1, src2) { - if (!utils.isObject(dest) && !utils.isObject(src1)) { - throw new TypeError('.groupRoutes: expect both `dest` and `src1` be objects') - } - let pathname = dest.route + src1.route - let route = this.createRoute(dest.method, pathname, src1.middlewares) - - if (utils.isObject(src2)) { - pathname = route.route + src2.route - route = this.createRoute(dest.method, pathname, src2.middlewares) - } - - return route -} - /** * Expose `KoaBetterRouter` constructor *