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