@cfworker/web 6.0.0 → 7.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.
@@ -5,6 +5,7 @@ export * from './cookies.js';
5
5
  export * from './http-error.js';
6
6
  export * from './middleware.js';
7
7
  export * from './normalize-pathname.js';
8
+ export * from './parse-entries.js';
8
9
  export * from './req.js';
9
10
  export * from './response-builder.js';
10
11
  export * from './router.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
@@ -21,6 +21,7 @@ __exportStar(require("./cookies.js"), exports);
21
21
  __exportStar(require("./http-error.js"), exports);
22
22
  __exportStar(require("./middleware.js"), exports);
23
23
  __exportStar(require("./normalize-pathname.js"), exports);
24
+ __exportStar(require("./parse-entries.js"), exports);
24
25
  __exportStar(require("./req.js"), exports);
25
26
  __exportStar(require("./response-builder.js"), exports);
26
27
  __exportStar(require("./router.js"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,mDAAiC;AACjC,+CAA6B;AAC7B,+CAA6B;AAC7B,kDAAgC;AAChC,kDAAgC;AAChC,0DAAwC;AACxC,2CAAyB;AACzB,wDAAsC;AACtC,8CAA4B;AAC5B,gDAA8B","sourcesContent":["export * from './accepts.js';\nexport * from './application.js';\nexport * from './context.js';\nexport * from './cookies.js';\nexport * from './http-error.js';\nexport * from './middleware.js';\nexport * from './normalize-pathname.js';\nexport * from './req.js';\nexport * from './response-builder.js';\nexport * from './router.js';\nexport * from './validate.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,mDAAiC;AACjC,+CAA6B;AAC7B,+CAA6B;AAC7B,kDAAgC;AAChC,kDAAgC;AAChC,0DAAwC;AACxC,qDAAmC;AACnC,2CAAyB;AACzB,wDAAsC;AACtC,8CAA4B;AAC5B,gDAA8B","sourcesContent":["export * from './accepts.js';\nexport * from './application.js';\nexport * from './context.js';\nexport * from './cookies.js';\nexport * from './http-error.js';\nexport * from './middleware.js';\nexport * from './normalize-pathname.js';\nexport * from './parse-entries.js';\nexport * from './req.js';\nexport * from './response-builder.js';\nexport * from './router.js';\nexport * from './validate.js';\n"]}
@@ -1,4 +1,3 @@
1
- type ParsedEntries<T> = Record<string, T | T[]>;
1
+ export type ParsedEntries<T> = Record<string, T | T[]>;
2
2
  export declare function parseEntries<T>(input: Iterable<readonly [string, T]>): ParsedEntries<T>;
3
- export {};
4
3
  //# sourceMappingURL=parse-entries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-entries.d.ts","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhD,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GACpC,aAAa,CAAC,CAAC,CAAC,CAkBlB"}
1
+ {"version":3,"file":"parse-entries.d.ts","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEvD,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GACpC,aAAa,CAAC,CAAC,CAAC,CAkBlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"parse-entries.js","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":";;;AAEA,sBACE,KAAqC;IAErC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAEvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI;QACJ,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,MAAM;KAC1C,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["type ParsedEntries<T> = Record<string, T | T[]>;\n\nexport function parseEntries<T>(\n input: Iterable<readonly [string, T]>\n): ParsedEntries<T> {\n const entries = new Map<string, T[]>();\n\n for (const [name, value] of input) {\n const values = entries.get(name);\n if (values === undefined) {\n entries.set(name, [value]);\n } else {\n values.push(value);\n }\n }\n\n return Object.fromEntries(\n Array.from(entries, ([name, values]) => [\n name,\n values.length === 1 ? values[0]! : values\n ])\n );\n}\n"]}
1
+ {"version":3,"file":"parse-entries.js","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":";;;AAEA,sBACE,KAAqC;IAErC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAEvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI;QACJ,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,MAAM;KAC1C,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["export type ParsedEntries<T> = Record<string, T | T[]>;\n\nexport function parseEntries<T>(\n input: Iterable<readonly [string, T]>\n): ParsedEntries<T> {\n const entries = new Map<string, T[]>();\n\n for (const [name, value] of input) {\n const values = entries.get(name);\n if (values === undefined) {\n entries.set(name, [value]);\n } else {\n values.push(value);\n }\n }\n\n return Object.fromEntries(\n Array.from(entries, ([name, values]) => [\n name,\n values.length === 1 ? values[0]! : values\n ])\n );\n}\n"]}
@@ -1,6 +1,8 @@
1
- import { PathToRegexpOptions } from 'path-to-regexp';
2
1
  import { Context } from './context.js';
3
2
  import { Middleware } from './middleware.js';
3
+ export interface URLPatternOptions {
4
+ ignoreCase?: boolean;
5
+ }
4
6
  export type Predicate = (context: Context) => boolean;
5
7
  export declare const Method: (method: string) => Predicate;
6
8
  export declare const Get: Predicate;
@@ -12,14 +14,15 @@ export declare const Head: Predicate;
12
14
  export declare const Options: Predicate;
13
15
  export declare const Header: (header: string, value: string) => Predicate;
14
16
  export declare const Host: (host: string) => Predicate;
15
- export declare const Path: (pattern: string, options?: PathToRegexpOptions) => Predicate;
17
+ export declare const defaultURLPatternOptions: URLPatternOptions;
18
+ export declare const Path: (pattern: string, options?: URLPatternOptions) => Predicate;
16
19
  export type RouteCondition = (context: Context) => boolean;
17
20
  export interface Route {
18
21
  conditions: RouteCondition[];
19
22
  middleware: Middleware;
20
23
  }
21
24
  export interface RouterOptions {
22
- pathToRegExpOptions?: PathToRegexpOptions;
25
+ urlPatternOptions?: URLPatternOptions;
23
26
  }
24
27
  export declare const defaultRouterOptions: RouterOptions;
25
28
  export declare class Router {
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAqB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAEtD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAGxC,CAAC;AACF,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,KAAK,EAAE,SAA2B,CAAC;AAChD,eAAO,MAAM,MAAM,EAAE,SAA4B,CAAC;AAClD,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,OAAO,EAAE,SAA6B,CAAC;AAEpD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,SAMvD,CAAC;AACF,eAAO,MAAM,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SACf,CAAC;AAEvB,eAAO,MAAM,IAAI,EAAE,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,mBAAmB,KAC1B,SAWJ,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAE3D,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C;AAED,eAAO,MAAM,oBAAoB,EAAE,aAIlC,CAAC;AAEF,qBAAa,MAAM;IAGL,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,YAA6B,OAAO,GAAE,aAAoC,EAEzE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGlE;IAEM,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGnE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,UAAU,EAAE,UAAU,CAQ3B;IAEK,OAAO,CACZ,UAAU,EAAE,cAAc,EAAE,EAC5B,GAAG,UAAU,EAAE,UAAU,EAAE,GAC1B,MAAM,CAMR;IAEM,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAK9C;CACF"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAqB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAuBD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAEtD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAGxC,CAAC;AACF,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,KAAK,EAAE,SAA2B,CAAC;AAChD,eAAO,MAAM,MAAM,EAAE,SAA4B,CAAC;AAClD,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,OAAO,EAAE,SAA6B,CAAC;AAEpD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,SAMvD,CAAC;AACF,eAAO,MAAM,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SACf,CAAC;AAEvB,eAAO,MAAM,wBAAwB,EAAE,iBAEtC,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB,KACxB,SAcJ,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAE3D,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,eAAO,MAAM,oBAAoB,EAAE,aAElC,CAAC;AAEF,qBAAa,MAAM;IAGL,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,YAA6B,OAAO,GAAE,aAAoC,EAEzE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGlE;IAEM,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGnE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,UAAU,EAAE,UAAU,CAQ3B;IAEK,OAAO,CACZ,UAAU,EAAE,cAAc,EAAE,EAC5B,GAAG,UAAU,EAAE,UAAU,EAAE,GAC1B,MAAM,CAMR;IAEM,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAK9C;CACF"}
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Router = exports.defaultRouterOptions = exports.Path = exports.Host = exports.Header = exports.Options = exports.Head = exports.Delete = exports.Patch = exports.Put = exports.Post = exports.Get = exports.Method = void 0;
4
- const path_to_regexp_1 = require("path-to-regexp");
3
+ exports.Router = exports.defaultRouterOptions = exports.Path = exports.defaultURLPatternOptions = exports.Host = exports.Header = exports.Options = exports.Head = exports.Delete = exports.Patch = exports.Put = exports.Post = exports.Get = exports.Method = void 0;
5
4
  const middleware_js_1 = require("./middleware.js");
5
+ const URLPattern = globalThis.URLPattern;
6
6
  const Method = (method) => {
7
7
  method = method.toUpperCase();
8
8
  return ({ req }) => req.method === method;
@@ -22,22 +22,23 @@ const Header = (header, value) => {
22
22
  exports.Header = Header;
23
23
  const Host = (host) => (0, exports.Header)('host', host);
24
24
  exports.Host = Host;
25
+ exports.defaultURLPatternOptions = {
26
+ ignoreCase: true
27
+ };
25
28
  const Path = (pattern, options) => {
26
- const regexp = (0, path_to_regexp_1.pathToRegexp)(pattern, options);
29
+ const urlPattern = new URLPattern({ pathname: pattern }, { ...exports.defaultURLPatternOptions, ...options });
27
30
  return ({ req: { url, params } }) => {
28
- const match = url.pathname.match(regexp);
31
+ const match = matchPathname(urlPattern, url.pathname);
29
32
  if (!match) {
30
33
  return false;
31
34
  }
32
- collectParameters(regexp.keys, match, params);
35
+ collectParameters(match.pathname.groups, params);
33
36
  return true;
34
37
  };
35
38
  };
36
39
  exports.Path = Path;
37
40
  exports.defaultRouterOptions = {
38
- pathToRegExpOptions: {
39
- strict: true
40
- }
41
+ urlPatternOptions: exports.defaultURLPatternOptions
41
42
  };
42
43
  class Router {
43
44
  options;
@@ -47,31 +48,31 @@ class Router {
47
48
  this.routes = [];
48
49
  }
49
50
  get(pathname, ...middleware) {
50
- const opts = this.options.pathToRegExpOptions;
51
+ const opts = this.options.urlPatternOptions;
51
52
  return this.compose([exports.Get, (0, exports.Path)(pathname, opts)], ...middleware);
52
53
  }
53
54
  post(pathname, ...middleware) {
54
- const opts = this.options.pathToRegExpOptions;
55
+ const opts = this.options.urlPatternOptions;
55
56
  return this.compose([exports.Post, (0, exports.Path)(pathname, opts)], ...middleware);
56
57
  }
57
58
  put(pathname, ...middleware) {
58
- const opts = this.options.pathToRegExpOptions;
59
+ const opts = this.options.urlPatternOptions;
59
60
  return this.compose([exports.Put, (0, exports.Path)(pathname, opts)], ...middleware);
60
61
  }
61
62
  patch(pathname, ...middleware) {
62
- const opts = this.options.pathToRegExpOptions;
63
+ const opts = this.options.urlPatternOptions;
63
64
  return this.compose([exports.Patch, (0, exports.Path)(pathname, opts)], ...middleware);
64
65
  }
65
66
  delete(pathname, ...middleware) {
66
- const opts = this.options.pathToRegExpOptions;
67
+ const opts = this.options.urlPatternOptions;
67
68
  return this.compose([exports.Delete, (0, exports.Path)(pathname, opts)], ...middleware);
68
69
  }
69
70
  head(pathname, ...middleware) {
70
- const opts = this.options.pathToRegExpOptions;
71
+ const opts = this.options.urlPatternOptions;
71
72
  return this.compose([exports.Head, (0, exports.Path)(pathname, opts)], ...middleware);
72
73
  }
73
74
  all(pathname, ...middleware) {
74
- const opts = this.options.pathToRegExpOptions;
75
+ const opts = this.options.urlPatternOptions;
75
76
  return this.compose([(0, exports.Path)(pathname, opts)], ...middleware);
76
77
  }
77
78
  middleware = async (ctx, next) => {
@@ -95,14 +96,20 @@ class Router {
95
96
  }
96
97
  }
97
98
  exports.Router = Router;
98
- function collectParameters(keys, match, params) {
99
- for (let i = 1; i < match.length; i++) {
100
- const key = keys[i - 1];
101
- const value = match[i];
102
- if (!key || !value) {
99
+ function matchPathname(pattern, pathname) {
100
+ const match = pattern.exec({ pathname });
101
+ if (match || !pathname.endsWith('/')) {
102
+ return match;
103
+ }
104
+ const pathnameWithoutTrailingSlashes = pathname.replace(/\/+$/, '') || '/';
105
+ return pattern.exec({ pathname: pathnameWithoutTrailingSlashes });
106
+ }
107
+ function collectParameters(groups, params) {
108
+ for (const [name, value] of Object.entries(groups)) {
109
+ if (!value) {
103
110
  continue;
104
111
  }
105
- params[key.name] = decodeURIComponent(value);
112
+ params[name] = decodeURIComponent(value);
106
113
  }
107
114
  }
108
115
  //# sourceMappingURL=router.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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","sourcesContent":["import { Key, pathToRegexp, PathToRegexpOptions } from 'path-to-regexp';\nimport { Context } from './context.js';\nimport { composeMiddleware, Middleware } from './middleware.js';\n\nexport type Predicate = (context: Context) => boolean;\n\nexport const Method: (method: string) => Predicate = (method: string) => {\n method = method.toUpperCase();\n return ({ req }: Context) => req.method === method;\n};\nexport const Get: Predicate = Method('get');\nexport const Post: Predicate = Method('post');\nexport const Put: Predicate = Method('put');\nexport const Patch: Predicate = Method('patch');\nexport const Delete: Predicate = Method('delete');\nexport const Head: Predicate = Method('head');\nexport const Options: Predicate = Method('options');\n\nexport const Header: (header: string, value: string) => Predicate = (\n header: string,\n value: string\n) => {\n value = value.toLowerCase();\n return ({ req }: Context) => req.headers.get(header) === value;\n};\nexport const Host: (host: string) => Predicate = (host: string) =>\n Header('host', host);\n\nexport const Path: (\n pattern: string,\n options?: PathToRegexpOptions\n) => Predicate = (pattern: string, options?: PathToRegexpOptions) => {\n const regexp = pathToRegexp(pattern, options);\n\n return ({ req: { url, params } }: Context) => {\n const match = url.pathname.match(regexp);\n if (!match) {\n return false;\n }\n collectParameters(regexp.keys, match, params);\n return true;\n };\n};\n\nexport type RouteCondition = (context: Context) => boolean;\n\nexport interface Route {\n conditions: RouteCondition[];\n middleware: Middleware;\n}\n\nexport interface RouterOptions {\n pathToRegExpOptions?: PathToRegexpOptions;\n}\n\nexport const defaultRouterOptions: RouterOptions = {\n pathToRegExpOptions: {\n strict: true\n }\n};\n\nexport class Router {\n private readonly routes: Route[];\n\n constructor(private readonly options: RouterOptions = defaultRouterOptions) {\n this.routes = [];\n }\n\n public get(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Get, Path(pathname, opts)], ...middleware);\n }\n\n public post(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Post, Path(pathname, opts)], ...middleware);\n }\n\n public put(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Put, Path(pathname, opts)], ...middleware);\n }\n\n public patch(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Patch, Path(pathname, opts)], ...middleware);\n }\n\n public delete(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Delete, Path(pathname, opts)], ...middleware);\n }\n\n public head(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Head, Path(pathname, opts)], ...middleware);\n }\n\n public all(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Path(pathname, opts)], ...middleware);\n }\n\n public middleware: Middleware = async (ctx, next) => {\n const resolved = this.resolve(ctx);\n\n if (resolved) {\n await resolved.middleware(ctx, next);\n } else {\n await next();\n }\n };\n\n public compose(\n conditions: RouteCondition[],\n ...middleware: Middleware[]\n ): Router {\n this.routes.push({\n conditions,\n middleware: composeMiddleware(middleware)\n });\n return this;\n }\n\n public resolve(ctx: Context): Route | undefined {\n return this.routes.find(\n ({ conditions }) =>\n conditions.length === 0 || conditions.every(c => c(ctx))\n );\n }\n}\n\nfunction collectParameters(\n keys: Key[],\n match: RegExpMatchArray,\n params: Record<string, string>\n) {\n for (let i = 1; i < match.length; i++) {\n const key = keys[i - 1];\n const value = match[i];\n if (!key || !value) {\n continue;\n }\n params[key.name] = decodeURIComponent(value);\n }\n}\n"]}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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","sourcesContent":["import { Context } from './context.js';\nimport { composeMiddleware, Middleware } from './middleware.js';\n\nexport interface URLPatternOptions {\n ignoreCase?: boolean;\n}\n\ninterface PathnamePatternResult {\n pathname: {\n groups: Record<string, string | undefined>;\n };\n}\n\ninterface PathnamePattern {\n exec(input: { pathname: string }): PathnamePatternResult | null;\n}\n\ninterface URLPatternConstructor {\n new (\n input: { pathname: string },\n options?: URLPatternOptions\n ): PathnamePattern;\n}\n\nconst URLPattern = (\n globalThis as unknown as { URLPattern: URLPatternConstructor }\n).URLPattern;\n\nexport type Predicate = (context: Context) => boolean;\n\nexport const Method: (method: string) => Predicate = (method: string) => {\n method = method.toUpperCase();\n return ({ req }: Context) => req.method === method;\n};\nexport const Get: Predicate = Method('get');\nexport const Post: Predicate = Method('post');\nexport const Put: Predicate = Method('put');\nexport const Patch: Predicate = Method('patch');\nexport const Delete: Predicate = Method('delete');\nexport const Head: Predicate = Method('head');\nexport const Options: Predicate = Method('options');\n\nexport const Header: (header: string, value: string) => Predicate = (\n header: string,\n value: string\n) => {\n value = value.toLowerCase();\n return ({ req }: Context) => req.headers.get(header) === value;\n};\nexport const Host: (host: string) => Predicate = (host: string) =>\n Header('host', host);\n\nexport const defaultURLPatternOptions: URLPatternOptions = {\n ignoreCase: true\n};\n\nexport const Path: (\n pattern: string,\n options?: URLPatternOptions\n) => Predicate = (pattern: string, options?: URLPatternOptions) => {\n const urlPattern = new URLPattern(\n { pathname: pattern },\n { ...defaultURLPatternOptions, ...options }\n );\n\n return ({ req: { url, params } }: Context) => {\n const match = matchPathname(urlPattern, url.pathname);\n if (!match) {\n return false;\n }\n collectParameters(match.pathname.groups, params);\n return true;\n };\n};\n\nexport type RouteCondition = (context: Context) => boolean;\n\nexport interface Route {\n conditions: RouteCondition[];\n middleware: Middleware;\n}\n\nexport interface RouterOptions {\n urlPatternOptions?: URLPatternOptions;\n}\n\nexport const defaultRouterOptions: RouterOptions = {\n urlPatternOptions: defaultURLPatternOptions\n};\n\nexport class Router {\n private readonly routes: Route[];\n\n constructor(private readonly options: RouterOptions = defaultRouterOptions) {\n this.routes = [];\n }\n\n public get(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Get, Path(pathname, opts)], ...middleware);\n }\n\n public post(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Post, Path(pathname, opts)], ...middleware);\n }\n\n public put(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Put, Path(pathname, opts)], ...middleware);\n }\n\n public patch(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Patch, Path(pathname, opts)], ...middleware);\n }\n\n public delete(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Delete, Path(pathname, opts)], ...middleware);\n }\n\n public head(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Head, Path(pathname, opts)], ...middleware);\n }\n\n public all(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Path(pathname, opts)], ...middleware);\n }\n\n public middleware: Middleware = async (ctx, next) => {\n const resolved = this.resolve(ctx);\n\n if (resolved) {\n await resolved.middleware(ctx, next);\n } else {\n await next();\n }\n };\n\n public compose(\n conditions: RouteCondition[],\n ...middleware: Middleware[]\n ): Router {\n this.routes.push({\n conditions,\n middleware: composeMiddleware(middleware)\n });\n return this;\n }\n\n public resolve(ctx: Context): Route | undefined {\n return this.routes.find(\n ({ conditions }) =>\n conditions.length === 0 || conditions.every(c => c(ctx))\n );\n }\n}\n\nfunction matchPathname(\n pattern: PathnamePattern,\n pathname: string\n): PathnamePatternResult | null {\n const match = pattern.exec({ pathname });\n if (match || !pathname.endsWith('/')) {\n return match;\n }\n\n const pathnameWithoutTrailingSlashes = pathname.replace(/\\/+$/, '') || '/';\n return pattern.exec({ pathname: pathnameWithoutTrailingSlashes });\n}\n\nfunction collectParameters(\n groups: Record<string, string | undefined>,\n params: Record<string, string>\n) {\n for (const [name, value] of Object.entries(groups)) {\n if (!value) {\n continue;\n }\n params[name] = decodeURIComponent(value);\n }\n}\n"]}
@@ -5,6 +5,7 @@ export * from './cookies.js';
5
5
  export * from './http-error.js';
6
6
  export * from './middleware.js';
7
7
  export * from './normalize-pathname.js';
8
+ export * from './parse-entries.js';
8
9
  export * from './req.js';
9
10
  export * from './response-builder.js';
10
11
  export * from './router.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
package/dist/esm/index.js CHANGED
@@ -5,6 +5,7 @@ export * from './cookies.js';
5
5
  export * from './http-error.js';
6
6
  export * from './middleware.js';
7
7
  export * from './normalize-pathname.js';
8
+ export * from './parse-entries.js';
8
9
  export * from './req.js';
9
10
  export * from './response-builder.js';
10
11
  export * from './router.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC","sourcesContent":["export * from './accepts.js';\nexport * from './application.js';\nexport * from './context.js';\nexport * from './cookies.js';\nexport * from './http-error.js';\nexport * from './middleware.js';\nexport * from './normalize-pathname.js';\nexport * from './req.js';\nexport * from './response-builder.js';\nexport * from './router.js';\nexport * from './validate.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC","sourcesContent":["export * from './accepts.js';\nexport * from './application.js';\nexport * from './context.js';\nexport * from './cookies.js';\nexport * from './http-error.js';\nexport * from './middleware.js';\nexport * from './normalize-pathname.js';\nexport * from './parse-entries.js';\nexport * from './req.js';\nexport * from './response-builder.js';\nexport * from './router.js';\nexport * from './validate.js';\n"]}
@@ -1,4 +1,3 @@
1
- type ParsedEntries<T> = Record<string, T | T[]>;
1
+ export type ParsedEntries<T> = Record<string, T | T[]>;
2
2
  export declare function parseEntries<T>(input: Iterable<readonly [string, T]>): ParsedEntries<T>;
3
- export {};
4
3
  //# sourceMappingURL=parse-entries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-entries.d.ts","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhD,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GACpC,aAAa,CAAC,CAAC,CAAC,CAkBlB"}
1
+ {"version":3,"file":"parse-entries.d.ts","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEvD,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GACpC,aAAa,CAAC,CAAC,CAAC,CAkBlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"parse-entries.js","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAC1B,KAAqC;IAErC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAEvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI;QACJ,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,MAAM;KAC1C,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["type ParsedEntries<T> = Record<string, T | T[]>;\n\nexport function parseEntries<T>(\n input: Iterable<readonly [string, T]>\n): ParsedEntries<T> {\n const entries = new Map<string, T[]>();\n\n for (const [name, value] of input) {\n const values = entries.get(name);\n if (values === undefined) {\n entries.set(name, [value]);\n } else {\n values.push(value);\n }\n }\n\n return Object.fromEntries(\n Array.from(entries, ([name, values]) => [\n name,\n values.length === 1 ? values[0]! : values\n ])\n );\n}\n"]}
1
+ {"version":3,"file":"parse-entries.js","sourceRoot":"","sources":["../../src/parse-entries.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAC1B,KAAqC;IAErC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAEvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI;QACJ,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,MAAM;KAC1C,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["export type ParsedEntries<T> = Record<string, T | T[]>;\n\nexport function parseEntries<T>(\n input: Iterable<readonly [string, T]>\n): ParsedEntries<T> {\n const entries = new Map<string, T[]>();\n\n for (const [name, value] of input) {\n const values = entries.get(name);\n if (values === undefined) {\n entries.set(name, [value]);\n } else {\n values.push(value);\n }\n }\n\n return Object.fromEntries(\n Array.from(entries, ([name, values]) => [\n name,\n values.length === 1 ? values[0]! : values\n ])\n );\n}\n"]}
@@ -1,6 +1,8 @@
1
- import { PathToRegexpOptions } from 'path-to-regexp';
2
1
  import { Context } from './context.js';
3
2
  import { Middleware } from './middleware.js';
3
+ export interface URLPatternOptions {
4
+ ignoreCase?: boolean;
5
+ }
4
6
  export type Predicate = (context: Context) => boolean;
5
7
  export declare const Method: (method: string) => Predicate;
6
8
  export declare const Get: Predicate;
@@ -12,14 +14,15 @@ export declare const Head: Predicate;
12
14
  export declare const Options: Predicate;
13
15
  export declare const Header: (header: string, value: string) => Predicate;
14
16
  export declare const Host: (host: string) => Predicate;
15
- export declare const Path: (pattern: string, options?: PathToRegexpOptions) => Predicate;
17
+ export declare const defaultURLPatternOptions: URLPatternOptions;
18
+ export declare const Path: (pattern: string, options?: URLPatternOptions) => Predicate;
16
19
  export type RouteCondition = (context: Context) => boolean;
17
20
  export interface Route {
18
21
  conditions: RouteCondition[];
19
22
  middleware: Middleware;
20
23
  }
21
24
  export interface RouterOptions {
22
- pathToRegExpOptions?: PathToRegexpOptions;
25
+ urlPatternOptions?: URLPatternOptions;
23
26
  }
24
27
  export declare const defaultRouterOptions: RouterOptions;
25
28
  export declare class Router {
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAqB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAEtD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAGxC,CAAC;AACF,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,KAAK,EAAE,SAA2B,CAAC;AAChD,eAAO,MAAM,MAAM,EAAE,SAA4B,CAAC;AAClD,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,OAAO,EAAE,SAA6B,CAAC;AAEpD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,SAMvD,CAAC;AACF,eAAO,MAAM,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SACf,CAAC;AAEvB,eAAO,MAAM,IAAI,EAAE,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,mBAAmB,KAC1B,SAWJ,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAE3D,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C;AAED,eAAO,MAAM,oBAAoB,EAAE,aAIlC,CAAC;AAEF,qBAAa,MAAM;IAGL,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,YAA6B,OAAO,GAAE,aAAoC,EAEzE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGlE;IAEM,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGnE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,UAAU,EAAE,UAAU,CAQ3B;IAEK,OAAO,CACZ,UAAU,EAAE,cAAc,EAAE,EAC5B,GAAG,UAAU,EAAE,UAAU,EAAE,GAC1B,MAAM,CAMR;IAEM,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAK9C;CACF"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAqB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAuBD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAEtD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAGxC,CAAC;AACF,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,GAAG,EAAE,SAAyB,CAAC;AAC5C,eAAO,MAAM,KAAK,EAAE,SAA2B,CAAC;AAChD,eAAO,MAAM,MAAM,EAAE,SAA4B,CAAC;AAClD,eAAO,MAAM,IAAI,EAAE,SAA0B,CAAC;AAC9C,eAAO,MAAM,OAAO,EAAE,SAA6B,CAAC;AAEpD,eAAO,MAAM,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,SAMvD,CAAC;AACF,eAAO,MAAM,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SACf,CAAC;AAEvB,eAAO,MAAM,wBAAwB,EAAE,iBAEtC,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,iBAAiB,KACxB,SAcJ,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAE3D,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,eAAO,MAAM,oBAAoB,EAAE,aAElC,CAAC;AAEF,qBAAa,MAAM;IAGL,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC,YAA6B,OAAO,GAAE,aAAoC,EAEzE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGlE;IAEM,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGnE;IAEM,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGjE;IAEM,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAGhE;IAEM,UAAU,EAAE,UAAU,CAQ3B;IAEK,OAAO,CACZ,UAAU,EAAE,cAAc,EAAE,EAC5B,GAAG,UAAU,EAAE,UAAU,EAAE,GAC1B,MAAM,CAMR;IAEM,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAK9C;CACF"}
@@ -1,5 +1,5 @@
1
- import { pathToRegexp } from 'path-to-regexp';
2
1
  import { composeMiddleware } from './middleware.js';
2
+ const URLPattern = globalThis.URLPattern;
3
3
  export const Method = (method) => {
4
4
  method = method.toUpperCase();
5
5
  return ({ req }) => req.method === method;
@@ -16,21 +16,22 @@ export const Header = (header, value) => {
16
16
  return ({ req }) => req.headers.get(header) === value;
17
17
  };
18
18
  export const Host = (host) => Header('host', host);
19
+ export const defaultURLPatternOptions = {
20
+ ignoreCase: true
21
+ };
19
22
  export const Path = (pattern, options) => {
20
- const regexp = pathToRegexp(pattern, options);
23
+ const urlPattern = new URLPattern({ pathname: pattern }, { ...defaultURLPatternOptions, ...options });
21
24
  return ({ req: { url, params } }) => {
22
- const match = url.pathname.match(regexp);
25
+ const match = matchPathname(urlPattern, url.pathname);
23
26
  if (!match) {
24
27
  return false;
25
28
  }
26
- collectParameters(regexp.keys, match, params);
29
+ collectParameters(match.pathname.groups, params);
27
30
  return true;
28
31
  };
29
32
  };
30
33
  export const defaultRouterOptions = {
31
- pathToRegExpOptions: {
32
- strict: true
33
- }
34
+ urlPatternOptions: defaultURLPatternOptions
34
35
  };
35
36
  export class Router {
36
37
  options;
@@ -40,31 +41,31 @@ export class Router {
40
41
  this.routes = [];
41
42
  }
42
43
  get(pathname, ...middleware) {
43
- const opts = this.options.pathToRegExpOptions;
44
+ const opts = this.options.urlPatternOptions;
44
45
  return this.compose([Get, Path(pathname, opts)], ...middleware);
45
46
  }
46
47
  post(pathname, ...middleware) {
47
- const opts = this.options.pathToRegExpOptions;
48
+ const opts = this.options.urlPatternOptions;
48
49
  return this.compose([Post, Path(pathname, opts)], ...middleware);
49
50
  }
50
51
  put(pathname, ...middleware) {
51
- const opts = this.options.pathToRegExpOptions;
52
+ const opts = this.options.urlPatternOptions;
52
53
  return this.compose([Put, Path(pathname, opts)], ...middleware);
53
54
  }
54
55
  patch(pathname, ...middleware) {
55
- const opts = this.options.pathToRegExpOptions;
56
+ const opts = this.options.urlPatternOptions;
56
57
  return this.compose([Patch, Path(pathname, opts)], ...middleware);
57
58
  }
58
59
  delete(pathname, ...middleware) {
59
- const opts = this.options.pathToRegExpOptions;
60
+ const opts = this.options.urlPatternOptions;
60
61
  return this.compose([Delete, Path(pathname, opts)], ...middleware);
61
62
  }
62
63
  head(pathname, ...middleware) {
63
- const opts = this.options.pathToRegExpOptions;
64
+ const opts = this.options.urlPatternOptions;
64
65
  return this.compose([Head, Path(pathname, opts)], ...middleware);
65
66
  }
66
67
  all(pathname, ...middleware) {
67
- const opts = this.options.pathToRegExpOptions;
68
+ const opts = this.options.urlPatternOptions;
68
69
  return this.compose([Path(pathname, opts)], ...middleware);
69
70
  }
70
71
  middleware = async (ctx, next) => {
@@ -87,14 +88,20 @@ export class Router {
87
88
  return this.routes.find(({ conditions }) => conditions.length === 0 || conditions.every(c => c(ctx)));
88
89
  }
89
90
  }
90
- function collectParameters(keys, match, params) {
91
- for (let i = 1; i < match.length; i++) {
92
- const key = keys[i - 1];
93
- const value = match[i];
94
- if (!key || !value) {
91
+ function matchPathname(pattern, pathname) {
92
+ const match = pattern.exec({ pathname });
93
+ if (match || !pathname.endsWith('/')) {
94
+ return match;
95
+ }
96
+ const pathnameWithoutTrailingSlashes = pathname.replace(/\/+$/, '') || '/';
97
+ return pattern.exec({ pathname: pathnameWithoutTrailingSlashes });
98
+ }
99
+ function collectParameters(groups, params) {
100
+ for (const [name, value] of Object.entries(groups)) {
101
+ if (!value) {
95
102
  continue;
96
103
  }
97
- params[key.name] = decodeURIComponent(value);
104
+ params[name] = decodeURIComponent(value);
98
105
  }
99
106
  }
100
107
  //# sourceMappingURL=router.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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","sourcesContent":["import { Key, pathToRegexp, PathToRegexpOptions } from 'path-to-regexp';\nimport { Context } from './context.js';\nimport { composeMiddleware, Middleware } from './middleware.js';\n\nexport type Predicate = (context: Context) => boolean;\n\nexport const Method: (method: string) => Predicate = (method: string) => {\n method = method.toUpperCase();\n return ({ req }: Context) => req.method === method;\n};\nexport const Get: Predicate = Method('get');\nexport const Post: Predicate = Method('post');\nexport const Put: Predicate = Method('put');\nexport const Patch: Predicate = Method('patch');\nexport const Delete: Predicate = Method('delete');\nexport const Head: Predicate = Method('head');\nexport const Options: Predicate = Method('options');\n\nexport const Header: (header: string, value: string) => Predicate = (\n header: string,\n value: string\n) => {\n value = value.toLowerCase();\n return ({ req }: Context) => req.headers.get(header) === value;\n};\nexport const Host: (host: string) => Predicate = (host: string) =>\n Header('host', host);\n\nexport const Path: (\n pattern: string,\n options?: PathToRegexpOptions\n) => Predicate = (pattern: string, options?: PathToRegexpOptions) => {\n const regexp = pathToRegexp(pattern, options);\n\n return ({ req: { url, params } }: Context) => {\n const match = url.pathname.match(regexp);\n if (!match) {\n return false;\n }\n collectParameters(regexp.keys, match, params);\n return true;\n };\n};\n\nexport type RouteCondition = (context: Context) => boolean;\n\nexport interface Route {\n conditions: RouteCondition[];\n middleware: Middleware;\n}\n\nexport interface RouterOptions {\n pathToRegExpOptions?: PathToRegexpOptions;\n}\n\nexport const defaultRouterOptions: RouterOptions = {\n pathToRegExpOptions: {\n strict: true\n }\n};\n\nexport class Router {\n private readonly routes: Route[];\n\n constructor(private readonly options: RouterOptions = defaultRouterOptions) {\n this.routes = [];\n }\n\n public get(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Get, Path(pathname, opts)], ...middleware);\n }\n\n public post(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Post, Path(pathname, opts)], ...middleware);\n }\n\n public put(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Put, Path(pathname, opts)], ...middleware);\n }\n\n public patch(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Patch, Path(pathname, opts)], ...middleware);\n }\n\n public delete(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Delete, Path(pathname, opts)], ...middleware);\n }\n\n public head(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Head, Path(pathname, opts)], ...middleware);\n }\n\n public all(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.pathToRegExpOptions;\n return this.compose([Path(pathname, opts)], ...middleware);\n }\n\n public middleware: Middleware = async (ctx, next) => {\n const resolved = this.resolve(ctx);\n\n if (resolved) {\n await resolved.middleware(ctx, next);\n } else {\n await next();\n }\n };\n\n public compose(\n conditions: RouteCondition[],\n ...middleware: Middleware[]\n ): Router {\n this.routes.push({\n conditions,\n middleware: composeMiddleware(middleware)\n });\n return this;\n }\n\n public resolve(ctx: Context): Route | undefined {\n return this.routes.find(\n ({ conditions }) =>\n conditions.length === 0 || conditions.every(c => c(ctx))\n );\n }\n}\n\nfunction collectParameters(\n keys: Key[],\n match: RegExpMatchArray,\n params: Record<string, string>\n) {\n for (let i = 1; i < match.length; i++) {\n const key = keys[i - 1];\n const value = match[i];\n if (!key || !value) {\n continue;\n }\n params[key.name] = decodeURIComponent(value);\n }\n}\n"]}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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","sourcesContent":["import { Context } from './context.js';\nimport { composeMiddleware, Middleware } from './middleware.js';\n\nexport interface URLPatternOptions {\n ignoreCase?: boolean;\n}\n\ninterface PathnamePatternResult {\n pathname: {\n groups: Record<string, string | undefined>;\n };\n}\n\ninterface PathnamePattern {\n exec(input: { pathname: string }): PathnamePatternResult | null;\n}\n\ninterface URLPatternConstructor {\n new (\n input: { pathname: string },\n options?: URLPatternOptions\n ): PathnamePattern;\n}\n\nconst URLPattern = (\n globalThis as unknown as { URLPattern: URLPatternConstructor }\n).URLPattern;\n\nexport type Predicate = (context: Context) => boolean;\n\nexport const Method: (method: string) => Predicate = (method: string) => {\n method = method.toUpperCase();\n return ({ req }: Context) => req.method === method;\n};\nexport const Get: Predicate = Method('get');\nexport const Post: Predicate = Method('post');\nexport const Put: Predicate = Method('put');\nexport const Patch: Predicate = Method('patch');\nexport const Delete: Predicate = Method('delete');\nexport const Head: Predicate = Method('head');\nexport const Options: Predicate = Method('options');\n\nexport const Header: (header: string, value: string) => Predicate = (\n header: string,\n value: string\n) => {\n value = value.toLowerCase();\n return ({ req }: Context) => req.headers.get(header) === value;\n};\nexport const Host: (host: string) => Predicate = (host: string) =>\n Header('host', host);\n\nexport const defaultURLPatternOptions: URLPatternOptions = {\n ignoreCase: true\n};\n\nexport const Path: (\n pattern: string,\n options?: URLPatternOptions\n) => Predicate = (pattern: string, options?: URLPatternOptions) => {\n const urlPattern = new URLPattern(\n { pathname: pattern },\n { ...defaultURLPatternOptions, ...options }\n );\n\n return ({ req: { url, params } }: Context) => {\n const match = matchPathname(urlPattern, url.pathname);\n if (!match) {\n return false;\n }\n collectParameters(match.pathname.groups, params);\n return true;\n };\n};\n\nexport type RouteCondition = (context: Context) => boolean;\n\nexport interface Route {\n conditions: RouteCondition[];\n middleware: Middleware;\n}\n\nexport interface RouterOptions {\n urlPatternOptions?: URLPatternOptions;\n}\n\nexport const defaultRouterOptions: RouterOptions = {\n urlPatternOptions: defaultURLPatternOptions\n};\n\nexport class Router {\n private readonly routes: Route[];\n\n constructor(private readonly options: RouterOptions = defaultRouterOptions) {\n this.routes = [];\n }\n\n public get(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Get, Path(pathname, opts)], ...middleware);\n }\n\n public post(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Post, Path(pathname, opts)], ...middleware);\n }\n\n public put(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Put, Path(pathname, opts)], ...middleware);\n }\n\n public patch(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Patch, Path(pathname, opts)], ...middleware);\n }\n\n public delete(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Delete, Path(pathname, opts)], ...middleware);\n }\n\n public head(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Head, Path(pathname, opts)], ...middleware);\n }\n\n public all(pathname: string, ...middleware: Middleware[]): Router {\n const opts = this.options.urlPatternOptions;\n return this.compose([Path(pathname, opts)], ...middleware);\n }\n\n public middleware: Middleware = async (ctx, next) => {\n const resolved = this.resolve(ctx);\n\n if (resolved) {\n await resolved.middleware(ctx, next);\n } else {\n await next();\n }\n };\n\n public compose(\n conditions: RouteCondition[],\n ...middleware: Middleware[]\n ): Router {\n this.routes.push({\n conditions,\n middleware: composeMiddleware(middleware)\n });\n return this;\n }\n\n public resolve(ctx: Context): Route | undefined {\n return this.routes.find(\n ({ conditions }) =>\n conditions.length === 0 || conditions.every(c => c(ctx))\n );\n }\n}\n\nfunction matchPathname(\n pattern: PathnamePattern,\n pathname: string\n): PathnamePatternResult | null {\n const match = pattern.exec({ pathname });\n if (match || !pathname.endsWith('/')) {\n return match;\n }\n\n const pathnameWithoutTrailingSlashes = pathname.replace(/\\/+$/, '') || '/';\n return pattern.exec({ pathname: pathnameWithoutTrailingSlashes });\n}\n\nfunction collectParameters(\n groups: Record<string, string | undefined>,\n params: Record<string, string>\n) {\n for (const [name, value] of Object.entries(groups)) {\n if (!value) {\n continue;\n }\n params[name] = decodeURIComponent(value);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfworker/web",
3
- "version": "6.0.0",
3
+ "version": "7.0.0",
4
4
  "description": "Web framework for Cloudflare Workers and service workers, inspired by Koa and fastify",
5
5
  "keywords": [
6
6
  "middleware",
@@ -46,24 +46,23 @@
46
46
  "test": "node ../../test.mjs"
47
47
  },
48
48
  "dependencies": {
49
- "@cfworker/json-schema": "^4.1.4",
49
+ "@cfworker/json-schema": "^4.1.5",
50
50
  "@hapi/bourne": "^4.0.1",
51
- "@types/statuses": "^2.0.6",
52
51
  "cookie": "^2.0.1",
53
- "html-escaper": "^3.0.3",
54
52
  "negotiator": "^1.1.0",
55
- "path-to-regexp": "7.1.0",
56
53
  "statuses": "^2.0.2"
57
54
  },
58
55
  "devDependencies": {
59
56
  "@types/chai": "^5.2.3",
60
57
  "@types/mocha": "^10.0.10",
58
+ "@types/statuses": "^2.0.6",
61
59
  "chai": "^6.3.0",
62
60
  "esbuild": "^0.28.2",
63
61
  "jsonpointer": "^5.0.1",
64
62
  "mocha": "^12.0.3",
63
+ "tshy": "^4.1.4",
65
64
  "typescript": "^7.0.2",
66
- "wrangler": "^4.156.0"
65
+ "wrangler": "^4.157.0"
67
66
  },
68
67
  "tshy": {
69
68
  "project": "./tsconfig.build.json",