@eggjs/router 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/layer.js DELETED
@@ -1,217 +0,0 @@
1
- 'use strict';
2
-
3
- const debug = require('debug')('egg-router:layer');
4
- const pathToRegExp = require('path-to-regexp');
5
- const uri = require('urijs');
6
- const utility = require('utility');
7
-
8
- module.exports = class Layer {
9
- /**
10
- * Initialize a new routing Layer with given `method`, `path`, and `middleware`.
11
- *
12
- * @param {String|RegExp} path Path string or regular expression.
13
- * @param {Array} methods Array of HTTP verbs.
14
- * @param {Array} middleware Layer callback/middleware or series of.
15
- * @param {Object=} opts optional params
16
- * @param {String=} opts.name route name
17
- * @param {String=} opts.sensitive case sensitive (default: false)
18
- * @param {String=} opts.strict require the trailing slash (default: false)
19
- * @private
20
- */
21
- constructor(path, methods, middleware, opts) {
22
- this.opts = opts || {};
23
- this.name = this.opts.name || null;
24
- this.methods = [];
25
- this.paramNames = [];
26
- this.stack = Array.isArray(middleware) ? middleware : [ middleware ];
27
-
28
- methods.forEach(function(method) {
29
- const l = this.methods.push(method.toUpperCase());
30
- if (this.methods[l - 1] === 'GET') {
31
- this.methods.unshift('HEAD');
32
- }
33
- }, this);
34
-
35
- // ensure middleware is a function
36
- this.stack.forEach(function(fn) {
37
- const type = (typeof fn);
38
- if (type !== 'function') {
39
- throw new Error(
40
- methods.toString() + ' `' + (this.opts.name || path) + '`: `middleware` '
41
- + 'must be a function, not `' + type + '`'
42
- );
43
- }
44
- }, this);
45
-
46
- this.path = path;
47
- this.regexp = pathToRegExp(path, this.paramNames, this.opts);
48
-
49
- debug('defined route %s %s', this.methods, this.opts.prefix + this.path);
50
- }
51
-
52
- /**
53
- * Returns whether request `path` matches route.
54
- *
55
- * @param {String} path path string
56
- * @return {Boolean} matched or not
57
- * @private
58
- */
59
- match(path) {
60
- return this.regexp.test(path);
61
- }
62
-
63
- /**
64
- * Returns map of URL parameters for given `path` and `paramNames`.
65
- *
66
- * @param {String} path path string
67
- * @param {Array.<String>} captures captures strings
68
- * @param {Object=} existingParams existing params
69
- * @return {Object} params object
70
- * @private
71
- */
72
- params(path, captures, existingParams) {
73
- const params = existingParams || {};
74
-
75
- for (let len = captures.length, i = 0; i < len; i++) {
76
- if (this.paramNames[i]) {
77
- const c = captures[i];
78
- params[this.paramNames[i].name] = c ? utility.decodeURIComponent(c) : c;
79
- }
80
- }
81
- return params;
82
- }
83
-
84
- /**
85
- * Returns array of regexp url path captures.
86
- *
87
- * @param {String} path path string
88
- * @return {Array.<String>} captures strings
89
- * @private
90
- */
91
- captures(path) {
92
- if (this.opts.ignoreCaptures) return [];
93
- return path.match(this.regexp).slice(1);
94
- }
95
-
96
- /**
97
- * Generate URL for route using given `params`.
98
- *
99
- * @example
100
- *
101
- * ```javascript
102
- * var route = new Layer(['GET'], '/users/:id', fn);
103
- *
104
- * route.url({ id: 123 }); // => "/users/123"
105
- * ```
106
- *
107
- * @param {Object} params url parameters
108
- * @param {Object} [options] optional parameters
109
- * @return {String} url string
110
- * @private
111
- */
112
- url(params, options) {
113
- let args = params;
114
- const url = this.path.replace(/\(\.\*\)/g, '');
115
- const toPath = pathToRegExp.compile(url);
116
-
117
- if (typeof params !== 'object') {
118
- args = Array.prototype.slice.call(arguments);
119
- if (typeof args[args.length - 1] === 'object') {
120
- options = args[args.length - 1];
121
- args = args.slice(0, args.length - 1);
122
- }
123
- }
124
-
125
- const tokens = pathToRegExp.parse(url);
126
- let replace = {};
127
-
128
- if (args instanceof Array) {
129
- for (let len = tokens.length, i = 0, j = 0; i < len; i++) {
130
- if (tokens[i].name) replace[tokens[i].name] = args[j++];
131
- }
132
- } else if (tokens.some(token => token.name)) {
133
- replace = params;
134
- } else {
135
- options = params;
136
- }
137
-
138
- let replaced = toPath(replace);
139
-
140
- if (options && options.query) {
141
- replaced = new uri(replaced);
142
- replaced.search(options.query);
143
- return replaced.toString();
144
- }
145
-
146
- return replaced;
147
- }
148
-
149
- /**
150
- * Run validations on route named parameters.
151
- *
152
- * @example
153
- *
154
- * ```javascript
155
- * router
156
- * .param('user', function (id, ctx, next) {
157
- * ctx.user = users[id];
158
- * if (!user) return ctx.status = 404;
159
- * next();
160
- * })
161
- * .get('/users/:user', function (ctx, next) {
162
- * ctx.body = ctx.user;
163
- * });
164
- * ```
165
- *
166
- * @param {String} param param string
167
- * @param {Function} fn middleware function
168
- * @return {Layer} layer instance
169
- * @private
170
- */
171
- param(param, fn) {
172
- const stack = this.stack;
173
- const params = this.paramNames;
174
- const middleware = function(ctx, next) {
175
- return fn.call(this, ctx.params[param], ctx, next);
176
- };
177
- middleware.param = param;
178
-
179
- const names = params.map(function(p) {
180
- return p.name;
181
- });
182
-
183
- const x = names.indexOf(param);
184
- if (x > -1) {
185
- // iterate through the stack, to figure out where to place the handler fn
186
- stack.some(function(fn, i) {
187
- // param handlers are always first, so when we find an fn w/o a param property, stop here
188
- // if the param handler at this part of the stack comes after the one we are adding, stop here
189
- if (!fn.param || names.indexOf(fn.param) > x) {
190
- // inject this param handler right before the current item
191
- stack.splice(i, 0, middleware);
192
- return true; // then break the loop
193
- }
194
- return false;
195
- });
196
- }
197
-
198
- return this;
199
- }
200
-
201
- /**
202
- * Prefix route path.
203
- *
204
- * @param {String} prefix prefix string
205
- * @return {Layer} layer instance
206
- * @private
207
- */
208
- setPrefix(prefix) {
209
- if (this.path) {
210
- this.path = prefix + this.path;
211
- this.paramNames = [];
212
- this.regexp = pathToRegExp(this.path, this.paramNames, this.opts);
213
- }
214
-
215
- return this;
216
- }
217
- };