From c7f2884a49f0dc46305c5c6aeb4fa2667f8e0599 Mon Sep 17 00:00:00 2001 From: XadillaX Date: Tue, 29 Jan 2019 10:59:39 +0800 Subject: [PATCH 01/14] docs: update README for Egg.js --- README.md | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 9222701..2ed9198 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,9 @@ -# koa-router +# egg-router -[![NPM version](https://img.shields.io/npm/v/koa-router.svg?style=flat)](https://npmjs.org/package/koa-router) [![NPM Downloads](https://img.shields.io/npm/dm/koa-router.svg?style=flat)](https://npmjs.org/package/koa-router) [![Node.js Version](https://img.shields.io/node/v/koa-router.svg?style=flat)](http://nodejs.org/download/) [![Build Status](https://img.shields.io/travis/alexmingoia/koa-router.svg?style=flat)](http://travis-ci.org/alexmingoia/koa-router) [![Tips](https://img.shields.io/gratipay/alexmingoia.svg?style=flat)](https://www.gratipay.com/alexmingoia/) [![Gitter Chat](https://img.shields.io/badge/gitter-join%20chat-1dce73.svg?style=flat)](https://gitter.im/alexmingoia/koa-router/) +> **This repository is a fork of [koa-router](https://github.com/alexmingoia/koa-router).** And thanks for the work of +@alexmingoia. koa-router is a awesome project. -> Router middleware for [koa](https://github.com/koajs/koa) - -* Express-style routing using `app.get`, `app.put`, `app.post`, etc. -* Named URL parameters. -* Named routes with URL generation. -* Responds to `OPTIONS` requests with allowed methods. -* Support for `405 Method Not Allowed` and `501 Not Implemented`. -* Multiple route middleware. -* Multiple routers. -* Nestable routers. -* ES7 async/await support. - -## Migrating to 7 / Koa 2 - -- The API has changed to match the new promise-based middleware - signature of koa 2. See the - [koa 2.x readme](https://github.com/koajs/koa/tree/2.0.0-alpha.3) for more - information. -- Middleware is now always run in the order declared by `.use()` (or `.get()`, - etc.), which matches Express 4 API. - -## Installation - -Install using [npm](https://www.npmjs.org/): - -```sh -npm install koa-router -``` +> Router core component for [Egg.js](https://github.com/eggjs). ## API Reference From 4814462850443712c7c5dfcb5ef1339e6cfd08fe Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 10:34:54 +0800 Subject: [PATCH 02/14] refactor: rename to egg-router --- README.md | 119 ++++++++++++++++++++++++++------------------------- package.json | 10 ++--- 2 files changed, 65 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 2ed9198..f539eca 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,34 @@ # egg-router -> **This repository is a fork of [koa-router](https://github.com/alexmingoia/koa-router).** And thanks for the work of -@alexmingoia. koa-router is a awesome project. +Router core component for [Egg.js](https://github.com/eggjs). -> Router core component for [Egg.js](https://github.com/eggjs). +> **This repository is a fork of [koa-router](https://github.com/alexmingoia/koa-router).** with some additional features. + +> And thanks for the greate work of @alexmingoia and the original team. ## API Reference - -* [koa-router](#module_koa-router) - * [Router](#exp_module_koa-router--Router) ⏏ - * [new Router([opts])](#new_module_koa-router--Router_new) + +* [egg-router](#module_egg-router) + * [Router](#exp_module_egg-router--Router) ⏏ + * [new Router([opts])](#new_module_egg-router--Router_new) * _instance_ - * [.get|put|post|patch|delete|del](#module_koa-router--Router+get|put|post|patch|delete|del) ⇒ Router - * [.routes](#module_koa-router--Router+routes) ⇒ function - * [.use([path], middleware)](#module_koa-router--Router+use) ⇒ Router - * [.prefix(prefix)](#module_koa-router--Router+prefix) ⇒ Router - * [.allowedMethods([options])](#module_koa-router--Router+allowedMethods) ⇒ function - * [.redirect(source, destination, [code])](#module_koa-router--Router+redirect) ⇒ Router - * [.route(name)](#module_koa-router--Router+route) ⇒ Layer | false - * [.url(name, params, [options])](#module_koa-router--Router+url) ⇒ String | Error - * [.param(param, middleware)](#module_koa-router--Router+param) ⇒ Router + * [.get|put|post|patch|delete|del](#module_egg-router--Router+get|put|post|patch|delete|del) ⇒ Router + * [.routes](#module_egg-router--Router+routes) ⇒ function + * [.use([path], middleware)](#module_egg-router--Router+use) ⇒ Router + * [.prefix(prefix)](#module_egg-router--Router+prefix) ⇒ Router + * [.allowedMethods([options])](#module_egg-router--Router+allowedMethods) ⇒ function + * [.redirect(source, destination, [code])](#module_egg-router--Router+redirect) ⇒ Router + * [.route(name)](#module_egg-router--Router+route) ⇒ Layer | false + * [.url(name, params, [options])](#module_egg-router--Router+url) ⇒ String | Error + * [.param(param, middleware)](#module_egg-router--Router+param) ⇒ Router * _static_ - * [.url(path, params)](#module_koa-router--Router.url) ⇒ String + * [.url(path, params)](#module_egg-router--Router.url) ⇒ String - + ### Router ⏏ -**Kind**: Exported class - +**Kind**: Exported class + #### new Router([opts]) Create a new router. @@ -38,12 +39,12 @@ Create a new router. | [opts] | Object | | | [opts.prefix] | String | prefix router paths | -**Example** +**Example** Basic usage: ```javascript var Koa = require('koa'); -var Router = require('koa-router'); +var Router = require('egg-router'); var app = new Koa(); var router = new Router(); @@ -56,7 +57,7 @@ app .use(router.routes()) .use(router.allowedMethods()); ``` - + #### router.get|put|post|patch|delete|del ⇒ Router Create `router.verb()` methods, where *verb* is one of the HTTP verbs such @@ -171,7 +172,7 @@ router.get('/:category/:title', (ctx, next) => { The [path-to-regexp](https://github.com/pillarjs/path-to-regexp) module is used to convert paths to regular expressions. -**Kind**: instance property of [Router](#exp_module_koa-router--Router) +**Kind**: instance property of [Router](#exp_module_egg-router--Router) | Param | Type | Description | | --- | --- | --- | @@ -179,13 +180,13 @@ used to convert paths to regular expressions. | [middleware] | function | route middleware(s) | | callback | function | route callback | - + #### router.routes ⇒ function Returns router middleware which dispatches a route matching the request. -**Kind**: instance property of [Router](#exp_module_koa-router--Router) - +**Kind**: instance property of [Router](#exp_module_egg-router--Router) + #### router.use([path], middleware) ⇒ Router Use given middleware. @@ -194,15 +195,15 @@ Middleware run in the order they are defined by `.use()`. They are invoked sequentially, requests start at the first middleware and work their way "down" the middleware stack. -**Kind**: instance method of [Router](#exp_module_koa-router--Router) +**Kind**: instance method of [Router](#exp_module_egg-router--Router) | Param | Type | | --- | --- | -| [path] | String | -| middleware | function | -| [...] | function | +| [path] | String | +| middleware | function | +| [...] | function | -**Example** +**Example** ```javascript // session middleware will run before authorize router @@ -217,29 +218,29 @@ router.use(['/users', '/admin'], userAuth()); app.use(router.routes()); ``` - + #### router.prefix(prefix) ⇒ Router Set the path prefix for a Router instance that was already initialized. -**Kind**: instance method of [Router](#exp_module_koa-router--Router) +**Kind**: instance method of [Router](#exp_module_egg-router--Router) | Param | Type | | --- | --- | -| prefix | String | +| prefix | String | -**Example** +**Example** ```javascript router.prefix('/things/:thing_id') ``` - + #### router.allowedMethods([options]) ⇒ function Returns separate middleware for responding to `OPTIONS` requests with an `Allow` header containing the allowed methods, as well as responding with `405 Method Not Allowed` and `501 Not Implemented` as appropriate. -**Kind**: instance method of [Router](#exp_module_koa-router--Router) +**Kind**: instance method of [Router](#exp_module_egg-router--Router) | Param | Type | Description | | --- | --- | --- | @@ -248,10 +249,10 @@ with `405 Method Not Allowed` and `501 Not Implemented` as appropriate. | [options.notImplemented] | function | throw the returned value in place of the default NotImplemented error | | [options.methodNotAllowed] | function | throw the returned value in place of the default MethodNotAllowed error | -**Example** +**Example** ```javascript var Koa = require('koa'); -var Router = require('koa-router'); +var Router = require('egg-router'); var app = new Koa(); var router = new Router(); @@ -264,7 +265,7 @@ app.use(router.allowedMethods()); ```javascript var Koa = require('koa'); -var Router = require('koa-router'); +var Router = require('egg-router'); var Boom = require('boom'); var app = new Koa(); @@ -277,7 +278,7 @@ app.use(router.allowedMethods({ methodNotAllowed: () => new Boom.methodNotAllowed() })); ``` - + #### router.redirect(source, destination, [code]) ⇒ Router Redirect `source` to `destination` URL with optional 30x status `code`. @@ -297,7 +298,7 @@ router.all('/login', ctx => { }); ``` -**Kind**: instance method of [Router](#exp_module_koa-router--Router) +**Kind**: instance method of [Router](#exp_module_egg-router--Router) | Param | Type | Description | | --- | --- | --- | @@ -305,23 +306,23 @@ router.all('/login', ctx => { | destination | String | URL or route name. | | [code] | Number | HTTP status code (default: 301). | - + #### router.route(name) ⇒ Layer | false Lookup route with given `name`. -**Kind**: instance method of [Router](#exp_module_koa-router--Router) +**Kind**: instance method of [Router](#exp_module_egg-router--Router) | Param | Type | | --- | --- | -| name | String | +| name | String | - + #### router.url(name, params, [options]) ⇒ String | Error Generate URL for route. Takes a route name and map of named `params`. -**Kind**: instance method of [Router](#exp_module_koa-router--Router) +**Kind**: instance method of [Router](#exp_module_egg-router--Router) | Param | Type | Description | | --- | --- | --- | @@ -330,7 +331,7 @@ Generate URL for route. Takes a route name and map of named `params`. | [options] | Object | options parameter | | [options.query] | Object | String | query options | -**Example** +**Example** ```javascript router.get('user', '/users/:id', (ctx, next) => { // ... @@ -353,20 +354,20 @@ router.url('user', { id: 3 }, { query: { limit: 1 } }); router.url('user', { id: 3 }, { query: "limit=1" }); // => "/users/3?limit=1" ``` - + #### router.param(param, middleware) ⇒ Router Run middleware for named route parameters. Useful for auto-loading or validation. -**Kind**: instance method of [Router](#exp_module_koa-router--Router) +**Kind**: instance method of [Router](#exp_module_egg-router--Router) | Param | Type | | --- | --- | -| param | String | -| middleware | function | +| param | String | +| middleware | function | -**Example** +**Example** ```javascript router .param('user', (id, ctx, next) => { @@ -385,12 +386,12 @@ router // /users/3 => {"id": 3, "name": "Alex"} // /users/3/friends => [{"id": 4, "name": "TJ"}] ``` - + #### Router.url(path, params [, options]) ⇒ String Generate URL from url pattern and given `params`. -**Kind**: static method of [Router](#exp_module_koa-router--Router) +**Kind**: static method of [Router](#exp_module_egg-router--Router) | Param | Type | Description | | --- | --- | --- | @@ -399,7 +400,7 @@ Generate URL from url pattern and given `params`. | [options] | Object | options parameter | | [options.query] | Object | String | query options | -**Example** +**Example** ```javascript var url = Router.url('/users/:id', {id: 1}); // => "/users/1" @@ -409,7 +410,7 @@ const url = Router.url('/users/:id', {id: 1}, {query: { active: true }}); ``` ## Contributing -Please submit all issues and pull requests to the [alexmingoia/koa-router](http://github.com/alexmingoia/koa-router) repository! +Please submit all issues and pull requests to the [alexmingoia/egg-router](http://github.com/alexmingoia/egg-router) repository! ## Tests @@ -417,4 +418,4 @@ Run tests using `npm test`. ## Support -If you have any problem or suggestion please open an issue [here](https://github.com/alexmingoia/koa-router/issues). +If you have any problem or suggestion please open an issue [here](https://github.com/alexmingoia/egg-router/issues). diff --git a/package.json b/package.json index 4243eda..11fb649 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,16 @@ { - "name": "koa-router", - "description": "Router middleware for koa. Provides RESTful resource routing.", + "name": "egg-router", + "description": "Router middleware for egg/koa. Provides RESTful resource routing.", "repository": { "type": "git", - "url": "https://github.com/alexmingoia/koa-router.git" + "url": "https://github.com/eggjs/egg-router.git" }, "main": "lib/router.js", "files": [ "lib" ], - "author": "Alex Mingoia ", - "version": "7.4.0", + "author": "eggjs", + "version": "1.0.0", "keywords": [ "koa", "middleware", From 1d8bbfaef86bcbb5d47581cb8de700be31b5753c Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 10:35:21 +0800 Subject: [PATCH 03/14] Release 1.0.0 --- history.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/history.md b/history.md index af49f35..04e18d5 100644 --- a/history.md +++ b/history.md @@ -1,3 +1,10 @@ + +1.0.0 / 2019-01-30 +================== + +**others** + * [[`4814462`](http://github.com/eggjs/egg-router/commit/4814462850443712c7c5dfcb5ef1339e6cfd08fe)] - refactor: rename to egg-router (dead-horse <>),fatal: No names found, cannot describe anything. + # History ## 7.4.0 From d6496e09be6b0f91dcb96611f31ec5ab6ad8ac78 Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 10:40:44 +0800 Subject: [PATCH 04/14] refactor: rename to @eggjs/router --- README.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f539eca..29f395e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# egg-router +# @eggjs/router Router core component for [Egg.js](https://github.com/eggjs). @@ -44,7 +44,7 @@ Basic usage: ```javascript var Koa = require('koa'); -var Router = require('egg-router'); +var Router = require('@eggjs/router'); var app = new Koa(); var router = new Router(); diff --git a/package.json b/package.json index 11fb649..d815a9f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "egg-router", + "name": "@eggjs/router", "description": "Router middleware for egg/koa. Provides RESTful resource routing.", "repository": { "type": "git", From c23f9dcdfce11ed1196e8aa1c239081037e4655d Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 10:42:08 +0800 Subject: [PATCH 05/14] Release 1.0.0 --- history.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/history.md b/history.md index 04e18d5..5d5e2a2 100644 --- a/history.md +++ b/history.md @@ -3,9 +3,11 @@ ================== **others** - * [[`4814462`](http://github.com/eggjs/egg-router/commit/4814462850443712c7c5dfcb5ef1339e6cfd08fe)] - refactor: rename to egg-router (dead-horse <>),fatal: No names found, cannot describe anything. + * [[`d6496e0`](http://github.com/eggjs/egg-router/commit/d6496e09be6b0f91dcb96611f31ec5ab6ad8ac78)] - refactor: rename to @eggjs/router (dead-horse <>) -# History +------------------------------- + +# Release History from koa-router ## 7.4.0 From 6f98c2e83083ef28291b462c9beaf40b6ac1de19 Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 10:42:28 +0800 Subject: [PATCH 06/14] Release 1.0.0 --- history.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/history.md b/history.md index 5d5e2a2..257f827 100644 --- a/history.md +++ b/history.md @@ -1,4 +1,10 @@ +1.0.0 / 2019-01-30 +================== + +**others** + + 1.0.0 / 2019-01-30 ================== From e4f21a8ed6dfd72c4d6f4a13bbda9a4e90b0401c Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 10:45:06 +0800 Subject: [PATCH 07/14] chore: fix history --- history.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/history.md b/history.md index 257f827..5d5e2a2 100644 --- a/history.md +++ b/history.md @@ -1,10 +1,4 @@ -1.0.0 / 2019-01-30 -================== - -**others** - - 1.0.0 / 2019-01-30 ================== From ae4016862fb8bdaf30e730a9278fbb1455d8b75d Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 10:57:03 +0800 Subject: [PATCH 08/14] docs: clean doc --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 29f395e..f9b5485 100644 --- a/README.md +++ b/README.md @@ -408,14 +408,7 @@ var url = Router.url('/users/:id', {id: 1}); const url = Router.url('/users/:id', {id: 1}, {query: { active: true }}); // => "/users/1?active=true" ``` -## Contributing - -Please submit all issues and pull requests to the [alexmingoia/egg-router](http://github.com/alexmingoia/egg-router) repository! ## Tests Run tests using `npm test`. - -## Support - -If you have any problem or suggestion please open an issue [here](https://github.com/alexmingoia/egg-router/issues). From b318dd5ff2eea60013ed62b2a435f803c12bf20f Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 13:41:13 +0800 Subject: [PATCH 09/14] feat: add egg-router --- .travis.yml | 16 +- appveyor.yml | 16 ++ index.js | 10 + lib/README_tpl.hbs | 51 ---- lib/egg_router.js | 327 +++++++++++++++++++++++++ lib/layer.js | 2 +- lib/router.js | 7 +- lib/utils.js | 18 ++ package.json | 20 +- test/index.js | 15 -- test/index.test.js | 14 ++ test/lib/egg_router.test.js | 189 ++++++++++++++ test/lib/{layer.js => layer.test.js} | 2 +- test/lib/{router.js => router.test.js} | 2 +- test/lib/utils.test.js | 59 +++++ 15 files changed, 662 insertions(+), 86 deletions(-) create mode 100644 appveyor.yml create mode 100644 index.js delete mode 100644 lib/README_tpl.hbs create mode 100644 lib/egg_router.js create mode 100644 lib/utils.js delete mode 100644 test/index.js create mode 100644 test/index.test.js create mode 100644 test/lib/egg_router.test.js rename test/lib/{layer.js => layer.test.js} (99%) rename test/lib/{router.js => router.test.js} (99%) create mode 100644 test/lib/utils.test.js diff --git a/.travis.yml b/.travis.yml index bb543f0..bdf6f64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,12 @@ +sudo: false language: node_js node_js: - - "6" - - "7" - - "8" -notifications: - email: - on_success: never + - '6' + - '8' + - '10' +install: + - npm i npminstall && npminstall +script: + - npm run ci +after_script: + - npminstall codecov && codecov diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..3dc637e --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,16 @@ +environment: + matrix: + - nodejs_version: '6' + - nodejs_version: '8' + - nodejs_version: '10' + +install: + - ps: Install-Product node $env:nodejs_version + - npm i npminstall && node_modules\.bin\npminstall + +test_script: + - node --version + - npm --version + - npm run test + +build: off diff --git a/index.js b/index.js new file mode 100644 index 0000000..7a9f149 --- /dev/null +++ b/index.js @@ -0,0 +1,10 @@ +'use strict'; + +const KoaRouter = require('./lib/router'); +const EggRouter = require('./lib/egg_router'); + +// for compact +module.exports = KoaRouter; +module.exports.KoaRouter = KoaRouter; +module.exports.EggRouter = EggRouter; + diff --git a/lib/README_tpl.hbs b/lib/README_tpl.hbs deleted file mode 100644 index e23d8c9..0000000 --- a/lib/README_tpl.hbs +++ /dev/null @@ -1,51 +0,0 @@ -# koa-router - -[![NPM version](https://img.shields.io/npm/v/koa-router.svg?style=flat)](https://npmjs.org/package/koa-router) [![NPM Downloads](https://img.shields.io/npm/dm/koa-router.svg?style=flat)](https://npmjs.org/package/koa-router) [![Node.js Version](https://img.shields.io/node/v/koa-router.svg?style=flat)](http://nodejs.org/download/) [![Build Status](https://img.shields.io/travis/alexmingoia/koa-router.svg?style=flat)](http://travis-ci.org/alexmingoia/koa-router) [![Tips](https://img.shields.io/gratipay/alexmingoia.svg?style=flat)](https://www.gratipay.com/alexmingoia/) [![Gitter Chat](https://img.shields.io/badge/gitter-join%20chat-1dce73.svg?style=flat)](https://gitter.im/alexmingoia/koa-router/) - -> Router middleware for [koa](https://github.com/koajs/koa) - -* Express-style routing using `app.get`, `app.put`, `app.post`, etc. -* Named URL parameters. -* Named routes with URL generation. -* Responds to `OPTIONS` requests with allowed methods. -* Support for `405 Method Not Allowed` and `501 Not Implemented`. -* Multiple route middleware. -* Multiple routers. -* Nestable routers. -* ES7 async/await support. - -{{#module name="koa-router"}}{{>body}}{{/module}}## Migrating to 7 / Koa 2 - -- The API has changed to match the new promise-based middleware - signature of koa 2. See the - [koa 2.x readme](https://github.com/koajs/koa/tree/2.0.0-alpha.3) for more - information. -- Middleware is now always run in the order declared by `.use()` (or `.get()`, - etc.), which matches Express 4 API. - -## Installation - -Install using [npm](https://www.npmjs.org/): - -```sh -npm install koa-router -``` - -## API Reference -{{#module name="koa-router"~}} - {{>body~}} - {{>member-index~}} - {{>members~}} -{{/module~}} - -## Contributing - -Please submit all issues and pull requests to the [alexmingoia/koa-router](http://github.com/alexmingoia/koa-router) repository! - -## Tests - -Run tests using `npm test`. - -## Support - -If you have any problem or suggestion please open an issue [here](https://github.com/alexmingoia/koa-router/issues). diff --git a/lib/egg_router.js b/lib/egg_router.js new file mode 100644 index 0000000..e94f07b --- /dev/null +++ b/lib/egg_router.js @@ -0,0 +1,327 @@ +'use strict'; + +const is = require('is-type-of'); +const Router = require('./router'); +const utility = require('utility'); +const inflection = require('inflection'); +const assert = require('assert'); +const utils = require('./utils'); + +const METHODS = [ 'head', 'options', 'get', 'put', 'patch', 'post', 'delete' ]; + +const REST_MAP = { + index: { + suffix: '', + method: 'GET', + }, + new: { + namePrefix: 'new_', + member: true, + suffix: 'new', + method: 'GET', + }, + create: { + suffix: '', + method: 'POST', + }, + show: { + member: true, + suffix: ':id', + method: 'GET', + }, + edit: { + member: true, + namePrefix: 'edit_', + suffix: ':id/edit', + method: 'GET', + }, + update: { + member: true, + namePrefix: '', + suffix: ':id', + method: ['PATCH', 'PUT'], + }, + destroy: { + member: true, + namePrefix: 'destroy_', + suffix: ':id', + method: 'DELETE', + }, +}; + +/** + * FIXME: move these patch into @eggjs/router + */ +class EggRouter extends Router { + + /** + * @constructor + * @param {Object} opts - Router options. + * @param {Application} app - Application object. + */ + constructor(opts, app) { + super(opts); + this.app = app; + this.patchRouterMethod(); + } + + patchRouterMethod() { + // patch router methods to support generator function middleware and string controller + METHODS.concat(['all']).forEach(method => { + this[method] = (...args) => { + const splited = spliteAndResolveRouterParams({ args, app: this.app }); + // format and rebuild params + args = splited.prefix.concat(splited.middlewares); + return super[method](...args); + }; + }); + } + + /** + * Create and register a route. + * @param {String} path - url path + * @param {Array} methods - Array of HTTP verbs + * @param {Array} middlewares - + * @param {Object} opts - + * @return {Route} this + */ + register(path, methods, middlewares, opts) { + // patch register to support generator function middleware and string controller + middlewares = Array.isArray(middlewares) ? middlewares : [middlewares]; + middlewares = convertMiddlewares(middlewares, this.app); + path = Array.isArray(path) ? path : [path]; + path.forEach(p => super.register(p, methods, middlewares, opts)); + return this; + } + + /** + * restful router api + * @param {String} name - Router name + * @param {String} prefix - url prefix + * @param {Function} middleware - middleware or controller + * @example + * ```js + * app.resources('/posts', 'posts') + * app.resources('posts', '/posts', 'posts') + * app.resources('posts', '/posts', app.role.can('user'), app.controller.posts) + * ``` + * + * Examples: + * + * ```js + * app.resources('/posts', 'posts') + * ``` + * + * yield router mapping + * + * Method | Path | Route Name | Controller.Action + * -------|-----------------|----------------|----------------------------- + * GET | /posts | posts | app.controller.posts.index + * GET | /posts/new | new_post | app.controller.posts.new + * GET | /posts/:id | post | app.controller.posts.show + * GET | /posts/:id/edit | edit_post | app.controller.posts.edit + * POST | /posts | posts | app.controller.posts.create + * PATCH | /posts/:id | post | app.controller.posts.update + * DELETE | /posts/:id | post | app.controller.posts.destroy + * + * app.router.url can generate url based on arguments + * ```js + * app.router.url('posts') + * => /posts + * app.router.url('post', { id: 1 }) + * => /posts/1 + * app.router.url('new_post') + * => /posts/new + * app.router.url('edit_post', { id: 1 }) + * => /posts/1/edit + * ``` + * @return {Router} return route object. + * @since 1.0.0 + */ + resources(...args) { + const splited = spliteAndResolveRouterParams({ args, app: this.app }); + const middlewares = splited.middlewares; + // last argument is Controller object + const controller = splited.middlewares.pop(); + + let name = ''; + let prefix = ''; + if (splited.prefix.length === 2) { + // router.get('users', '/users') + name = splited.prefix[0]; + prefix = splited.prefix[1]; + } else { + // router.get('/users') + prefix = splited.prefix[0]; + } + + for (const key in REST_MAP) { + const action = controller[key]; + if (!action) continue; + + const opts = REST_MAP[key]; + let formatedName; + if (opts.member) { + formatedName = inflection.singularize(name); + } else { + formatedName = inflection.pluralize(name); + } + if (opts.namePrefix) { + formatedName = opts.namePrefix + formatedName; + } + prefix = prefix.replace(/\/$/, ''); + const path = opts.suffix ? `${prefix}/${opts.suffix}` : prefix; + const method = Array.isArray(opts.method) ? opts.method : [opts.method]; + this.register(path, method, middlewares.concat(action), { name: formatedName }); + } + + return this; + } + + /** + * @param {String} name - Router name + * @param {Object} params - more parameters + * @example + * ```js + * router.url('edit_post', { id: 1, name: 'foo', page: 2 }) + * => /posts/1/edit?name=foo&page=2 + * router.url('posts', { name: 'foo&1', page: 2 }) + * => /posts?name=foo%261&page=2 + * ``` + * @return {String} url by path name and query params. + * @since 1.0.0 + */ + url(name, params) { + const route = this.route(name); + if (!route) return ''; + + const args = params; + let url = route.path; + + assert(!is.regExp(url), `Can't get the url for regExp ${url} for by name '${name}'`); + + const queries = []; + if (typeof args === 'object' && args !== null) { + const replacedParams = []; + url = url.replace(/:([a-zA-Z_]\w*)/g, function ($0, key) { + if (utility.has(args, key)) { + const values = args[key]; + replacedParams.push(key); + return utility.encodeURIComponent(Array.isArray(values) ? values[0] : values); + } + return $0; + }); + + for (const key in args) { + if (replacedParams.includes(key)) { + continue; + } + + const values = args[key]; + const encodedKey = utility.encodeURIComponent(key); + if (Array.isArray(values)) { + for (const val of values) { + queries.push(`${encodedKey}=${utility.encodeURIComponent(val)}`); + } + } else { + queries.push(`${encodedKey}=${utility.encodeURIComponent(values)}`); + } + } + } + + if (queries.length > 0) { + const queryStr = queries.join('&'); + if (!url.includes('?')) { + url = `${url}?${queryStr}`; + } else { + url = `${url}&${queryStr}`; + } + } + + return url; + } + + pathFor(name, params) { + return this.url(name, params); + } +} + +/** + * 1. split (name, url, ...middleware, controller) to + * { + * prefix: [name, url] + * middlewares [...middleware, controller] + * } + * + * 2. resolve controller from string to function + * + * @param {Object} options inputs + * @param {Object} options.args router params + * @param {Object} options.app egg application instance + * @return {Object} prefix and middlewares + */ +function spliteAndResolveRouterParams({ args, app }) { + let prefix; + let middlewares; + if (args.length >= 3 && (is.string(args[1]) || is.regExp(args[1]))) { + // app.get(name, url, [...middleware], controller) + prefix = args.slice(0, 2); + middlewares = args.slice(2); + } else { + // app.get(url, [...middleware], controller) + prefix = args.slice(0, 1); + middlewares = args.slice(1); + } + // resolve controller + const controller = middlewares.pop(); + middlewares.push(resolveController(controller, app)); + return { prefix, middlewares }; +} + +/** + * resolve controller from string to function + * @param {String|Function} controller input controller + * @param {Application} app egg application instance + * @return {Function} controller function + */ +function resolveController(controller, app) { + if (is.string(controller)) { + const actions = controller.split('.'); + let obj = app.controller; + actions.forEach(key => { + obj = obj[key]; + if (!obj) throw new Error(`controller '${controller}' not exists`); + }); + controller = obj; + } + // ensure controller is exists + if (!controller) throw new Error('controller not exists'); + return controller; +} + +/** + * 1. ensure controller(last argument) support string + * - [url, controller]: app.get('/home', 'home'); + * - [name, url, controller(string)]: app.get('posts', '/posts', 'posts.list'); + * - [name, url, controller]: app.get('posts', '/posts', app.controller.posts.list); + * - [name, url(regexp), controller]: app.get('regRouter', /\/home\/index/, 'home.index'); + * - [name, url, middleware, [...], controller]: `app.get(/user/:id', hasLogin, canGetUser, 'user.show');` + * + * 2. make middleware support generator function + * + * @param {Array} middlewares middlewares and controller(last middleware) + * @param {Application} app egg application instance + * @return {Array} middlewares + */ +function convertMiddlewares(middlewares, app) { + // ensure controller is resolved + const controller = resolveController(middlewares.pop(), app); + // make middleware support generator function + middlewares = middlewares.map(utils.middleware); + const wrappedController = (ctx, next) => { + return utils.callFn(controller, [ctx, next], ctx); + }; + return middlewares.concat([wrappedController]); +} + +module.exports = EggRouter; diff --git a/lib/layer.js b/lib/layer.js index e24808a..f96d0e4 100644 --- a/lib/layer.js +++ b/lib/layer.js @@ -1,4 +1,4 @@ -var debug = require('debug')('koa-router'); +var debug = require('debug')('egg-router'); var pathToRegExp = require('path-to-regexp'); var uri = require('urijs'); diff --git a/lib/router.js b/lib/router.js index fe1ef44..99c1787 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1,11 +1,8 @@ /** - * RESTful resource routing middleware for koa. - * - * @author Alex Mingoia - * @link https://github.com/alexmingoia/koa-router + * RESTful resource routing middleware for eggjs. */ -var debug = require('debug')('koa-router'); +var debug = require('debug')('egg-router'); var compose = require('koa-compose'); var HttpError = require('http-errors'); var methods = require('methods'); diff --git a/lib/utils.js b/lib/utils.js new file mode 100644 index 0000000..f28c546 --- /dev/null +++ b/lib/utils.js @@ -0,0 +1,18 @@ +'use strict'; + +const convert = require('koa-convert'); +const is = require('is-type-of'); +const co = require('co'); + +module.exports = { + async callFn(fn, args, ctx) { + args = args || []; + if (!is.function(fn)) return; + if (is.generatorFunction(fn)) fn = co.wrap(fn); + return ctx ? fn.call(ctx, ...args) : fn(...args); + }, + + middleware(fn) { + return is.generatorFunction(fn) ? convert(fn) : fn; + }, +}; diff --git a/package.json b/package.json index d815a9f..30d3805 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "type": "git", "url": "https://github.com/eggjs/egg-router.git" }, - "main": "lib/router.js", "files": [ - "lib" + "lib", + "index.js" ], "author": "eggjs", "version": "1.0.0", @@ -18,24 +18,32 @@ "route" ], "dependencies": { + "co": "^4.6.0", "debug": "^3.1.0", "http-errors": "^1.3.1", + "inflection": "^1.12.0", + "is-type-of": "^1.2.1", "koa-compose": "^3.0.0", "methods": "^1.0.1", "path-to-regexp": "^1.1.1", - "urijs": "^1.19.0" + "urijs": "^1.19.0", + "utility": "^1.15.0" }, "devDependencies": { + "egg-bin": "^4.10.0", + "egg-ci": "^1.11.0", "expect.js": "^0.3.1", - "jsdoc-to-markdown": "^1.1.1", "koa": "2.2.0", "mocha": "^2.0.1", "should": "^6.0.3", "supertest": "^1.0.1" }, "scripts": { - "test": "NODE_ENV=test mocha test/**/*.js", - "docs": "NODE_ENV=test jsdoc2md -t ./lib/README_tpl.hbs --src ./lib/*.js >| README.md" + "test": "egg-bin test", + "ci": "egg-bin cov" + }, + "ci": { + "version": "6, 8, 10" }, "engines": { "node": ">= 4" diff --git a/test/index.js b/test/index.js deleted file mode 100644 index 46388ae..0000000 --- a/test/index.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Module tests - */ - -var koa = require('koa') - , should = require('should'); - -describe('module', function() { - it('should expose Router', function(done) { - var Router = require('..'); - should.exist(Router); - Router.should.be.type('function'); - done(); - }); -}); diff --git a/test/index.test.js b/test/index.test.js new file mode 100644 index 0000000..bf0448a --- /dev/null +++ b/test/index.test.js @@ -0,0 +1,14 @@ +/** + * Module tests + */ + +const assert = require('assert'); +const Router = require('..'); + +describe('test/index.test.js', () => { + it('should expose Router', () => { + assert(typeof Router === 'function'); + assert(typeof Router.KoaRouter === 'function'); + assert(typeof Router.EggRouter === 'function'); + }); +}); diff --git a/test/lib/egg_router.test.js b/test/lib/egg_router.test.js new file mode 100644 index 0000000..c0b3a35 --- /dev/null +++ b/test/lib/egg_router.test.js @@ -0,0 +1,189 @@ +'use strict'; + +const EggRouter = require('../../').EggRouter; +const assert = require('assert'); +const is = require('is-type-of'); + +describe('test/lib/egg_router.test.js', () => { + it('creates new router with egg app', function () { + const app = { controller: {} }; + const router = new EggRouter({}, app); + assert(router); + [ 'head', 'options', 'get', 'put', 'patch', 'post', 'delete', 'all', 'resources' ].forEach(method => { + assert(typeof router[method] === 'function'); + }); + }); + + it('should app.verb(url, controller) work', () => { + const app = { + controller: { + async foo() {}, + hello: { + * world() {}, + }, + }, + }; + + const router = new EggRouter({}, app); + router.get('/foo', app.controller.foo); + router.post('/hello/world', app.controller.hello.world); + + assert(router.stack[0].path === '/foo'); + assert.deepEqual(router.stack[0].methods, [ 'HEAD', 'GET' ]); + assert(router.stack[0].stack.length === 1); + assert(router.stack[1].path === '/hello/world'); + assert.deepEqual(router.stack[1].methods, [ 'POST' ]); + assert(router.stack[1].stack.length === 1); + }); + + it('should app.verb(name, url, controller) work', () => { + const app = { + controller: { + async foo() { }, + hello: { + * world() { }, + }, + }, + }; + + const router = new EggRouter({}, app); + router.get('foo', '/foo', app.controller.foo); + router.post('hello', '/hello/world', app.controller.hello.world); + + assert(router.stack[0].name === 'foo'); + assert(router.stack[0].path === '/foo'); + assert.deepEqual(router.stack[0].methods, [ 'HEAD', 'GET' ]); + assert(router.stack[0].stack.length === 1); + assert(router.stack[1].name === 'hello'); + assert(router.stack[1].path === '/hello/world'); + assert.deepEqual(router.stack[1].methods, [ 'POST' ]); + assert(router.stack[1].stack.length === 1); + }); + + it('should app.verb(name, url, controllerString) work', () => { + const app = { + controller: { + async foo() { }, + hello: { + * world() { }, + }, + }, + }; + + const router = new EggRouter({}, app); + router.get('foo', '/foo', 'foo'); + router.post('hello', '/hello/world', 'hello.world'); + + assert(router.stack[0].name === 'foo'); + assert(router.stack[0].path === '/foo'); + assert.deepEqual(router.stack[0].methods, [ 'HEAD', 'GET' ]); + assert(router.stack[0].stack.length === 1); + assert(router.stack[1].name === 'hello'); + assert(router.stack[1].path === '/hello/world'); + assert.deepEqual(router.stack[1].methods, [ 'POST' ]); + assert(router.stack[1].stack.length === 1); + }); + + it('should app.verb() throw if not found controller', () => { + const app = { + controller: { + async foo() { }, + hello: { + * world() { }, + }, + }, + }; + + const router = new EggRouter({}, app); + assert.throws(() => { + router.get('foo', '/foo', 'foobar') + }, /controller 'foobar' not exists/); + + assert.throws(() => { + router.get('/foo', app.bar); + }, /controller not exists/); + }); + + it('should app.verb(name, url, [middlewares], controllerString) work', () => { + const app = { + controller: { + async foo() { }, + hello: { + * world() { }, + }, + }, + }; + + const generatorMiddleware = function* () {}; + const asyncMiddleware = async function() {}; + const commonMiddleware = function() {}; + + const router = new EggRouter({}, app); + router.get('foo', '/foo', generatorMiddleware, asyncMiddleware, commonMiddleware, 'foo'); + router.post('hello', '/hello/world', generatorMiddleware, asyncMiddleware, commonMiddleware, 'hello.world'); + + assert(router.stack[0].name === 'foo'); + assert(router.stack[0].path === '/foo'); + assert.deepEqual(router.stack[0].methods, [ 'HEAD', 'GET' ]); + assert(router.stack[0].stack.length === 4); + assert(!is.generatorFunction(router.stack[0].stack[0])); + assert(is.asyncFunction(router.stack[0].stack[1])); + assert(!is.generatorFunction(router.stack[0].stack[3])); + assert(router.stack[1].name === 'hello'); + assert(router.stack[1].path === '/hello/world'); + assert.deepEqual(router.stack[1].methods, [ 'POST' ]); + assert(router.stack[1].stack.length === 4); + assert(!is.generatorFunction(router.stack[1].stack[0])); + assert(is.asyncFunction(router.stack[1].stack[1])); + assert(!is.generatorFunction(router.stack[1].stack[3])); + }); + + it('should app.resource() work', () => { + const app = { + controller: { + post: { + async index() { }, + async show() { }, + async create() { }, + async update() { }, + async new() {}, + }, + }, + }; + + const asyncMiddleware = async function () { }; + + const router = new EggRouter({}, app); + router.resources('/post', asyncMiddleware, app.controller.post); + assert(router.stack.length === 5); + assert(router.stack[0].stack.length === 2); + + router.resources('api_post', '/api/post', app.controller.post); + assert(router.stack.length === 10); + assert(router.stack[5].stack.length === 1); + assert(router.stack[5].name === 'api_posts'); + }); + + it('should router.url work', () => { + const app = { + controller: { + async foo() { }, + hello: { + * world() { }, + }, + }, + }; + const router = new EggRouter({}, app); + router.get('post', '/post/:id', app.controller.foo); + router.get('hello', '/hello/world', app.controller.hello.world); + + assert(router.url('post', { id: 1, foo: [1, 2], bar: 'bar' }) === '/post/1?foo=1&foo=2&bar=bar'); + assert(router.url('post', { foo: [1, 2], bar: 'bar' }) === '/post/:id?foo=1&foo=2&bar=bar'); + assert(router.url('fooo') === ''); + assert(router.url('hello') === '/hello/world'); + + assert(router.pathFor('post', { id: 1, foo: [1, 2], bar: 'bar' }) === '/post/1?foo=1&foo=2&bar=bar'); + assert(router.pathFor('fooo') === ''); + assert(router.pathFor('hello') === '/hello/world'); + }); +}); diff --git a/test/lib/layer.js b/test/lib/layer.test.js similarity index 99% rename from test/lib/layer.js rename to test/lib/layer.test.js index 6835254..70ce146 100644 --- a/test/lib/layer.js +++ b/test/lib/layer.test.js @@ -9,7 +9,7 @@ var Koa = require('koa') , should = require('should') , Layer = require('../../lib/layer'); -describe('Layer', function() { +describe('test/lib/layer.test.js', function() { it('composes multiple callbacks/middlware', function(done) { var app = new Koa(); var router = new Router(); diff --git a/test/lib/router.js b/test/lib/router.test.js similarity index 99% rename from test/lib/router.js rename to test/lib/router.test.js index 44e7112..4665d46 100644 --- a/test/lib/router.js +++ b/test/lib/router.test.js @@ -13,7 +13,7 @@ var fs = require('fs') , expect = require('expect.js') , should = require('should'); -describe('Router', function () { +describe('test/lib/router.test.js', function () { it('creates new router with koa app', function (done) { var app = new Koa(); var router = new Router(); diff --git a/test/lib/utils.test.js b/test/lib/utils.test.js new file mode 100644 index 0000000..a79be98 --- /dev/null +++ b/test/lib/utils.test.js @@ -0,0 +1,59 @@ +'use strict'; + +const utils = require('../../lib/utils'); +const is = require('is-type-of'); +const assert = require('assert'); + +describe('test/lib/utils.test.js', () => { + describe('callFn', () => { + it('should not function return same', () => { + const res = utils.callFn('foo'); + assert(is.promise(res)); + return res.then(result => assert(result === undefined)); + }); + + it('should async function return promise', () => { + const res = utils.callFn(async (foo, bar) => { + return foo + bar; + }, [ 1, 2 ]); + assert(is.promise(res)); + return res.then(result => assert(result === 3)); + }); + + it('should generator function return promise', () => { + const res = utils.callFn(function* (foo, bar) { + return foo + bar; + }, [ 1, 2 ]); + assert(is.promise(res)); + return res.then(result => assert(result === 3)); + }); + + it('should common function return promise', () => { + const res = utils.callFn((foo, bar) => { + return foo + bar; + }, [ 1, 2 ]); + assert(is.promise(res)); + return res.then(result => assert(result === 3)); + }); + + it('should work with ctx', () => { + const res = utils.callFn(async function(bar) { + return this.foo + bar; + }, [ 2 ], { foo: 1 }); + assert(is.promise(res)); + return res.then(result => assert(result === 3)); + }); + }); + + describe('middleware', () => { + it('should work with async function', () => { + const res = utils.middleware(async () => {}); + assert(is.asyncFunction(res)); + }); + + it('should work with generator function', () => { + const res = utils.middleware(function* () { }); + assert(!is.generatorFunction(res)); + }); + }); +}); From 7a887a252445e602c2ea7e1c6f4cde52a433644d Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 13:51:55 +0800 Subject: [PATCH 10/14] fix: update license --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 01750af..a488e9c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Alexander C. Mingoia +Copyright (c) 2019 eggjs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From c2803368a8256bc9504ae3c821eefeb9d1fcbc4d Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 13:57:08 +0800 Subject: [PATCH 11/14] fix: only support node@8 --- .travis.yml | 1 - appveyor.yml | 1 - package.json | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index bdf6f64..ce21122 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ sudo: false language: node_js node_js: - - '6' - '8' - '10' install: diff --git a/appveyor.yml b/appveyor.yml index 3dc637e..981e82b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,5 @@ environment: matrix: - - nodejs_version: '6' - nodejs_version: '8' - nodejs_version: '10' diff --git a/package.json b/package.json index 30d3805..edb9dcd 100644 --- a/package.json +++ b/package.json @@ -43,10 +43,10 @@ "ci": "egg-bin cov" }, "ci": { - "version": "6, 8, 10" + "version": "8, 10" }, "engines": { - "node": ">= 4" + "node": ">= 8" }, "license": "MIT" } From b3db7b41988d3bf1b4e885ed76b3a8165c1d3b1d Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 14:08:28 +0800 Subject: [PATCH 12/14] fix: add missing dependencies koa-convert --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index edb9dcd..94fa5fe 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "inflection": "^1.12.0", "is-type-of": "^1.2.1", "koa-compose": "^3.0.0", + "koa-convert": "^1.2.0", "methods": "^1.0.1", "path-to-regexp": "^1.1.1", "urijs": "^1.19.0", From 753bbf8e458a67757cc1eacf30d6740c19f869e5 Mon Sep 17 00:00:00 2001 From: dead-horse Date: Wed, 30 Jan 2019 14:08:41 +0800 Subject: [PATCH 13/14] Release 1.1.0 --- history.md | 15 +++++++++++++++ package.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/history.md b/history.md index 5d5e2a2..a1d7b75 100644 --- a/history.md +++ b/history.md @@ -1,4 +1,19 @@ +1.1.0 / 2019-01-30 +================== + +**features** + * [[`b318dd5`](http://github.com/eggjs/egg-router/commit/b318dd5ff2eea60013ed62b2a435f803c12bf20f)] - feat: add egg-router (dead-horse <>) + +**fixes** + * [[`b3db7b4`](http://github.com/eggjs/egg-router/commit/b3db7b41988d3bf1b4e885ed76b3a8165c1d3b1d)] - fix: add missing dependencies koa-convert (dead-horse <>) + * [[`c280336`](http://github.com/eggjs/egg-router/commit/c2803368a8256bc9504ae3c821eefeb9d1fcbc4d)] - fix: only support node@8 (dead-horse <>) + * [[`7a887a2`](http://github.com/eggjs/egg-router/commit/7a887a252445e602c2ea7e1c6f4cde52a433644d)] - fix: update license (dead-horse <>) + +**others** + * [[`ae40168`](http://github.com/eggjs/egg-router/commit/ae4016862fb8bdaf30e730a9278fbb1455d8b75d)] - docs: clean doc (dead-horse <>) + * [[`e4f21a8`](http://github.com/eggjs/egg-router/commit/e4f21a8ed6dfd72c4d6f4a13bbda9a4e90b0401c)] - chore: fix history (dead-horse <>) + 1.0.0 / 2019-01-30 ================== diff --git a/package.json b/package.json index 94fa5fe..cd31115 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "index.js" ], "author": "eggjs", - "version": "1.0.0", + "version": "1.1.0", "keywords": [ "koa", "middleware", From a6e267d57eb68997594ea75d138fdda4bf10741c Mon Sep 17 00:00:00 2001 From: XadillaX Date: Thu, 10 Jan 2019 12:16:44 +0800 Subject: [PATCH 14/14] feat: add routerPath to respond to routerName --- lib/router.js | 1 + test/lib/router.test.js | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/lib/router.js b/lib/router.js index 99c1787..48f81d8 100644 --- a/lib/router.js +++ b/lib/router.js @@ -340,6 +340,7 @@ Router.prototype.routes = Router.prototype.middleware = function () { ctx.captures = layer.captures(path, ctx.captures); ctx.params = layer.params(path, ctx.captures, ctx.params); ctx.routerName = layer.name; + ctx.routerPath = layer.path; return next(); }); return memo.concat(layer.stack); diff --git a/test/lib/router.test.js b/test/lib/router.test.js index 4665d46..ce75958 100644 --- a/test/lib/router.test.js +++ b/test/lib/router.test.js @@ -857,12 +857,16 @@ describe('test/lib/router.test.js', function () { router.get('/notparameter', function (ctx, next) { ctx.body = { param: ctx.params.parameter, + routerName: ctx.routerName, + routerPath: ctx.routerPath, }; }); router.get('/:parameter', function (ctx, next) { ctx.body = { param: ctx.params.parameter, + routerName: ctx.routerName, + routerPath: ctx.routerPath, }; }); @@ -874,6 +878,8 @@ describe('test/lib/router.test.js', function () { if (err) return done(err); expect(res.body.param).to.equal(undefined); + expect(res.body.routerName).to.equal(null); + expect(res.body.routerPath).to.equal('/notparameter'); done(); }); });