@koa/router 15.0.0 → 15.1.1

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 DELETED
@@ -1,457 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/layer.ts
21
- var layer_exports = {};
22
- __export(layer_exports, {
23
- default: () => Layer
24
- });
25
- module.exports = __toCommonJS(layer_exports);
26
- var import_node_url = require("url");
27
-
28
- // src/utils/path-to-regexp-wrapper.ts
29
- var import_path_to_regexp = require("path-to-regexp");
30
- function compilePathToRegexp(path, options = {}) {
31
- const normalizedOptions = { ...options };
32
- if ("strict" in normalizedOptions && !("trailing" in normalizedOptions)) {
33
- normalizedOptions.trailing = normalizedOptions.strict !== true;
34
- delete normalizedOptions.strict;
35
- }
36
- delete normalizedOptions.pathAsRegExp;
37
- delete normalizedOptions.ignoreCaptures;
38
- delete normalizedOptions.prefix;
39
- const { regexp, keys } = (0, import_path_to_regexp.pathToRegexp)(path, normalizedOptions);
40
- return { regexp, keys };
41
- }
42
- function compilePath(path, options = {}) {
43
- return (0, import_path_to_regexp.compile)(path, options);
44
- }
45
- function parsePath(path, options) {
46
- return (0, import_path_to_regexp.parse)(path, options);
47
- }
48
- function normalizeLayerOptionsToPathToRegexp(options = {}) {
49
- const normalized = {
50
- sensitive: options.sensitive,
51
- end: options.end,
52
- strict: options.strict,
53
- trailing: options.trailing
54
- };
55
- if ("strict" in normalized && !("trailing" in normalized)) {
56
- normalized.trailing = normalized.strict !== true;
57
- delete normalized.strict;
58
- }
59
- for (const key of Object.keys(normalized)) {
60
- if (normalized[key] === void 0) {
61
- delete normalized[key];
62
- }
63
- }
64
- return normalized;
65
- }
66
-
67
- // src/layer.ts
68
- function safeDecodeURIComponent(text) {
69
- try {
70
- return decodeURIComponent(text);
71
- } catch {
72
- return text;
73
- }
74
- }
75
- var Layer = class {
76
- opts;
77
- name;
78
- methods;
79
- paramNames;
80
- stack;
81
- path;
82
- regexp;
83
- /**
84
- * Initialize a new routing Layer with given `method`, `path`, and `middleware`.
85
- *
86
- * @param path - Path string or regular expression
87
- * @param methods - Array of HTTP verbs
88
- * @param middleware - Layer callback/middleware or series of
89
- * @param opts - Layer options
90
- * @private
91
- */
92
- constructor(path, methods, middleware, options = {}) {
93
- this.opts = options;
94
- this.name = this.opts.name || void 0;
95
- this.methods = this._normalizeHttpMethods(methods);
96
- this.stack = this._normalizeAndValidateMiddleware(
97
- middleware,
98
- methods,
99
- path
100
- );
101
- this.path = path;
102
- this.paramNames = [];
103
- this._configurePathMatching();
104
- }
105
- /**
106
- * Normalize HTTP methods and add automatic HEAD support for GET
107
- * @private
108
- */
109
- _normalizeHttpMethods(methods) {
110
- const normalizedMethods = [];
111
- for (const method of methods) {
112
- const upperMethod = method.toUpperCase();
113
- normalizedMethods.push(upperMethod);
114
- if (upperMethod === "GET") {
115
- normalizedMethods.unshift("HEAD");
116
- }
117
- }
118
- return normalizedMethods;
119
- }
120
- /**
121
- * Normalize middleware to array and validate all are functions
122
- * @private
123
- */
124
- _normalizeAndValidateMiddleware(middleware, methods, path) {
125
- const middlewareArray = Array.isArray(middleware) ? middleware : [middleware];
126
- for (const middlewareFunction of middlewareArray) {
127
- const middlewareType = typeof middlewareFunction;
128
- if (middlewareType !== "function") {
129
- const routeIdentifier = this.opts.name || path;
130
- throw new Error(
131
- `${methods.toString()} \`${routeIdentifier}\`: \`middleware\` must be a function, not \`${middlewareType}\``
132
- );
133
- }
134
- }
135
- return middlewareArray;
136
- }
137
- /**
138
- * Configure path matching regexp and parameters
139
- * @private
140
- */
141
- _configurePathMatching() {
142
- if (this.opts.pathAsRegExp === true) {
143
- this.regexp = this.path instanceof RegExp ? this.path : new RegExp(this.path);
144
- } else if (this.path) {
145
- this._configurePathToRegexp();
146
- }
147
- }
148
- /**
149
- * Configure path-to-regexp for string paths
150
- * @private
151
- */
152
- _configurePathToRegexp() {
153
- const options = normalizeLayerOptionsToPathToRegexp(this.opts);
154
- const { regexp, keys } = compilePathToRegexp(this.path, options);
155
- this.regexp = regexp;
156
- this.paramNames = keys;
157
- }
158
- /**
159
- * Returns whether request `path` matches route.
160
- *
161
- * @param path - Request path
162
- * @returns Whether path matches
163
- * @private
164
- */
165
- match(path) {
166
- return this.regexp.test(path);
167
- }
168
- /**
169
- * Returns map of URL parameters for given `path` and `paramNames`.
170
- *
171
- * @param _path - Request path (not used, kept for API compatibility)
172
- * @param captures - Captured values from regexp
173
- * @param existingParams - Existing params to merge with
174
- * @returns Parameter map
175
- * @private
176
- */
177
- params(_path, captures, existingParameters = {}) {
178
- const parameterValues = { ...existingParameters };
179
- for (const [captureIndex, capturedValue] of captures.entries()) {
180
- const parameterDefinition = this.paramNames[captureIndex];
181
- if (parameterDefinition && capturedValue && capturedValue.length > 0) {
182
- const parameterName = parameterDefinition.name;
183
- parameterValues[parameterName] = safeDecodeURIComponent(capturedValue);
184
- }
185
- }
186
- return parameterValues;
187
- }
188
- /**
189
- * Returns array of regexp url path captures.
190
- *
191
- * @param path - Request path
192
- * @returns Array of captured values
193
- * @private
194
- */
195
- captures(path) {
196
- if (this.opts.ignoreCaptures) {
197
- return [];
198
- }
199
- const match = path.match(this.regexp);
200
- return match ? match.slice(1) : [];
201
- }
202
- /**
203
- * Generate URL for route using given `params`.
204
- *
205
- * @example
206
- *
207
- * ```javascript
208
- * const route = new Layer('/users/:id', ['GET'], fn);
209
- *
210
- * route.url({ id: 123 }); // => "/users/123"
211
- * ```
212
- *
213
- * @param args - URL parameters (various formats supported)
214
- * @returns Generated URL
215
- * @private
216
- */
217
- url(...arguments_) {
218
- const { params, options } = this._parseUrlArguments(arguments_);
219
- const cleanPath = this.path.replaceAll("(.*)", "");
220
- const pathCompiler = compilePath(cleanPath, {
221
- encode: encodeURIComponent,
222
- ...options
223
- });
224
- const parameterReplacements = this._buildParamReplacements(
225
- params,
226
- cleanPath
227
- );
228
- const generatedUrl = pathCompiler(parameterReplacements);
229
- if (options && options.query) {
230
- return this._addQueryString(generatedUrl, options.query);
231
- }
232
- return generatedUrl;
233
- }
234
- /**
235
- * Parse url() arguments into params and options
236
- * Supports multiple call signatures:
237
- * - url({ id: 1 })
238
- * - url(1, 2, 3)
239
- * - url({ query: {...} })
240
- * - url({ id: 1 }, { query: {...} })
241
- * @private
242
- */
243
- _parseUrlArguments(allArguments) {
244
- let parameters = allArguments[0];
245
- let options = allArguments[1];
246
- if (typeof parameters !== "object") {
247
- const argumentsList = [...allArguments];
248
- const lastArgument = argumentsList.at(-1);
249
- if (typeof lastArgument === "object") {
250
- options = lastArgument;
251
- parameters = argumentsList.slice(0, -1);
252
- } else {
253
- parameters = argumentsList;
254
- }
255
- } else if (parameters && parameters.query && !options) {
256
- options = parameters;
257
- parameters = {};
258
- }
259
- return { params: parameters, options };
260
- }
261
- /**
262
- * Build parameter replacements for URL generation
263
- * @private
264
- */
265
- _buildParamReplacements(parameters, cleanPath) {
266
- const { tokens } = parsePath(cleanPath);
267
- const hasNamedParameters = tokens.some(
268
- (token) => "name" in token && token.name
269
- );
270
- const parameterReplacements = {};
271
- if (Array.isArray(parameters)) {
272
- let parameterIndex = 0;
273
- for (const token of tokens) {
274
- if ("name" in token && token.name) {
275
- parameterReplacements[token.name] = String(
276
- parameters[parameterIndex++]
277
- );
278
- }
279
- }
280
- } else if (hasNamedParameters && typeof parameters === "object" && !parameters.query) {
281
- for (const [parameterName, parameterValue] of Object.entries(
282
- parameters
283
- )) {
284
- parameterReplacements[parameterName] = String(parameterValue);
285
- }
286
- }
287
- return parameterReplacements;
288
- }
289
- /**
290
- * Add query string to URL
291
- * @private
292
- */
293
- _addQueryString(baseUrl, query) {
294
- const parsedUrl = (0, import_node_url.parse)(baseUrl);
295
- if (typeof query === "string") {
296
- parsedUrl.search = query;
297
- } else {
298
- parsedUrl.search = void 0;
299
- parsedUrl.query = query;
300
- }
301
- return (0, import_node_url.format)(parsedUrl);
302
- }
303
- /**
304
- * Run validations on route named parameters.
305
- *
306
- * @example
307
- *
308
- * ```javascript
309
- * router
310
- * .param('user', function (id, ctx, next) {
311
- * ctx.user = users[id];
312
- * if (!ctx.user) return ctx.status = 404;
313
- * next();
314
- * })
315
- * .get('/users/:user', function (ctx, next) {
316
- * ctx.body = ctx.user;
317
- * });
318
- * ```
319
- *
320
- * @param paramName - Parameter name
321
- * @param paramHandler - Middleware function
322
- * @returns This layer instance
323
- * @private
324
- */
325
- param(parameterName, parameterHandler) {
326
- const middlewareStack = this.stack;
327
- const routeParameterNames = this.paramNames;
328
- const parameterMiddleware = this._createParamMiddleware(
329
- parameterName,
330
- parameterHandler
331
- );
332
- const parameterNamesList = routeParameterNames.map(
333
- (parameterDefinition) => parameterDefinition.name
334
- );
335
- const parameterPosition = parameterNamesList.indexOf(parameterName);
336
- if (parameterPosition !== -1) {
337
- this._insertParamMiddleware(
338
- middlewareStack,
339
- parameterMiddleware,
340
- parameterNamesList,
341
- parameterPosition
342
- );
343
- }
344
- return this;
345
- }
346
- /**
347
- * Create param middleware with deduplication tracking
348
- * @private
349
- */
350
- _createParamMiddleware(parameterName, parameterHandler) {
351
- const middleware = function(context, next) {
352
- if (!context._matchedParams) {
353
- context._matchedParams = /* @__PURE__ */ new WeakMap();
354
- }
355
- if (context._matchedParams.has(parameterHandler)) {
356
- return next();
357
- }
358
- context._matchedParams.set(parameterHandler, true);
359
- return parameterHandler.call(
360
- this,
361
- context.params[parameterName],
362
- context,
363
- next
364
- );
365
- };
366
- middleware.param = parameterName;
367
- middleware._originalFn = parameterHandler;
368
- return middleware;
369
- }
370
- /**
371
- * Insert param middleware at the correct position in the stack
372
- * @private
373
- */
374
- _insertParamMiddleware(middlewareStack, parameterMiddleware, parameterNamesList, currentParameterPosition) {
375
- middlewareStack.some((existingMiddleware, stackIndex) => {
376
- if (!existingMiddleware.param) {
377
- middlewareStack.splice(stackIndex, 0, parameterMiddleware);
378
- return true;
379
- }
380
- const existingParameterPosition = parameterNamesList.indexOf(
381
- existingMiddleware.param
382
- );
383
- if (existingParameterPosition > currentParameterPosition) {
384
- middlewareStack.splice(stackIndex, 0, parameterMiddleware);
385
- return true;
386
- }
387
- return false;
388
- });
389
- }
390
- /**
391
- * Prefix route path.
392
- *
393
- * @param prefixPath - Prefix to prepend
394
- * @returns This layer instance
395
- * @private
396
- */
397
- setPrefix(prefixPath) {
398
- if (!this.path) {
399
- return this;
400
- }
401
- if (this.path instanceof RegExp) {
402
- return this;
403
- }
404
- this.path = this._applyPrefix(prefixPath);
405
- this._reconfigurePathMatching(prefixPath);
406
- return this;
407
- }
408
- /**
409
- * Apply prefix to the current path
410
- * @private
411
- */
412
- _applyPrefix(prefixPath) {
413
- const isRootPath = this.path === "/";
414
- const isStrictMode = this.opts.strict === true;
415
- const prefixHasParameters = prefixPath.includes(":");
416
- const pathIsRawRegex = this.opts.pathAsRegExp === true && typeof this.path === "string";
417
- if (prefixHasParameters && pathIsRawRegex) {
418
- const currentPath = this.path;
419
- if (currentPath === String.raw`(?:\/|$)` || currentPath === String.raw`(?:\/|$)`) {
420
- this.path = "{/*rest}";
421
- this.opts.pathAsRegExp = false;
422
- }
423
- }
424
- if (isRootPath && !isStrictMode) {
425
- return prefixPath;
426
- }
427
- return `${prefixPath}${this.path}`;
428
- }
429
- /**
430
- * Reconfigure path matching after prefix is applied
431
- * @private
432
- */
433
- _reconfigurePathMatching(prefixPath) {
434
- const treatAsRegExp = this.opts.pathAsRegExp === true;
435
- const prefixHasParameters = prefixPath && prefixPath.includes(":");
436
- if (prefixHasParameters && treatAsRegExp) {
437
- const options = normalizeLayerOptionsToPathToRegexp(this.opts);
438
- const { regexp, keys } = compilePathToRegexp(
439
- this.path,
440
- options
441
- );
442
- this.regexp = regexp;
443
- this.paramNames = keys;
444
- this.opts.pathAsRegExp = false;
445
- } else if (treatAsRegExp) {
446
- this.regexp = this.path instanceof RegExp ? this.path : new RegExp(this.path);
447
- } else {
448
- const options = normalizeLayerOptionsToPathToRegexp(this.opts);
449
- const { regexp, keys } = compilePathToRegexp(
450
- this.path,
451
- options
452
- );
453
- this.regexp = regexp;
454
- this.paramNames = keys;
455
- }
456
- }
457
- };