@cfworker/web 2.1.0 → 4.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.
Files changed (60) hide show
  1. package/dist/cjs/accepts.js +81 -0
  2. package/dist/{application.d.ts → cjs/application.d.ts} +1 -1
  3. package/dist/cjs/application.js +46 -0
  4. package/dist/cjs/context.js +26 -0
  5. package/dist/{cookies.d.ts → cjs/cookies.d.ts} +2 -2
  6. package/dist/cjs/cookies.js +21 -0
  7. package/dist/cjs/http-error.js +38 -0
  8. package/dist/cjs/index.js +29 -0
  9. package/dist/cjs/middleware.js +31 -0
  10. package/dist/cjs/normalize-pathname.js +22 -0
  11. package/dist/cjs/req.js +59 -0
  12. package/dist/cjs/response-builder.js +138 -0
  13. package/dist/cjs/router.d.ts +39 -0
  14. package/dist/cjs/router.js +105 -0
  15. package/dist/{validate.d.ts → cjs/validate.d.ts} +1 -1
  16. package/dist/cjs/validate.js +76 -0
  17. package/dist/esm/accepts.d.ts +12 -0
  18. package/dist/esm/application.d.ts +11 -0
  19. package/dist/esm/context.d.ts +15 -0
  20. package/dist/esm/cookies.d.ts +8 -0
  21. package/dist/esm/http-error.d.ts +7 -0
  22. package/dist/esm/index.js +12 -0
  23. package/dist/esm/middleware.d.ts +3 -0
  24. package/dist/esm/normalize-pathname.d.ts +3 -0
  25. package/dist/esm/req.d.ts +24 -0
  26. package/dist/esm/response-builder.d.ts +22 -0
  27. package/dist/esm/router.d.ts +39 -0
  28. package/dist/{router.js → esm/router.js} +4 -5
  29. package/dist/esm/validate.d.ts +21 -0
  30. package/dist/tsconfig-cjs.tsbuildinfo +1 -0
  31. package/dist/tsconfig.tsbuildinfo +1 -0
  32. package/package.json +21 -17
  33. package/src/application.ts +1 -1
  34. package/src/context.ts +1 -1
  35. package/src/cookies.ts +3 -3
  36. package/src/normalize-pathname.ts +1 -1
  37. package/src/req.ts +4 -4
  38. package/src/response-builder.ts +7 -7
  39. package/src/router.ts +37 -26
  40. package/src/validate.ts +2 -2
  41. package/dist/router.d.ts +0 -39
  42. /package/dist/{accepts.d.ts → cjs/accepts.d.ts} +0 -0
  43. /package/dist/{context.d.ts → cjs/context.d.ts} +0 -0
  44. /package/dist/{http-error.d.ts → cjs/http-error.d.ts} +0 -0
  45. /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
  46. /package/dist/{middleware.d.ts → cjs/middleware.d.ts} +0 -0
  47. /package/dist/{normalize-pathname.d.ts → cjs/normalize-pathname.d.ts} +0 -0
  48. /package/dist/{req.d.ts → cjs/req.d.ts} +0 -0
  49. /package/dist/{response-builder.d.ts → cjs/response-builder.d.ts} +0 -0
  50. /package/dist/{accepts.js → esm/accepts.js} +0 -0
  51. /package/dist/{application.js → esm/application.js} +0 -0
  52. /package/dist/{context.js → esm/context.js} +0 -0
  53. /package/dist/{cookies.js → esm/cookies.js} +0 -0
  54. /package/dist/{http-error.js → esm/http-error.js} +0 -0
  55. /package/dist/{index.js → esm/index.d.ts} +0 -0
  56. /package/dist/{middleware.js → esm/middleware.js} +0 -0
  57. /package/dist/{normalize-pathname.js → esm/normalize-pathname.js} +0 -0
  58. /package/dist/{req.js → esm/req.js} +0 -0
  59. /package/dist/{response-builder.js → esm/response-builder.js} +0 -0
  60. /package/dist/{validate.js → esm/validate.js} +0 -0
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Accepts = void 0;
4
+ const charset_js_1 = require("negotiator/lib/charset.js");
5
+ const encoding_js_1 = require("negotiator/lib/encoding.js");
6
+ const language_js_1 = require("negotiator/lib/language.js");
7
+ const mediaType_js_1 = require("negotiator/lib/mediaType.js");
8
+ const parseAccept = mediaType_js_1.preferredMediaTypes;
9
+ const parseAcceptLanguage = language_js_1.preferredLanguages;
10
+ const parseAcceptEncoding = encoding_js_1.preferredEncodings;
11
+ const parseAcceptCharset = charset_js_1.preferredCharsets;
12
+ class Accepts {
13
+ headers;
14
+ _type = undefined;
15
+ _language = undefined;
16
+ _encoding = undefined;
17
+ _charset = undefined;
18
+ constructor(headers) {
19
+ this.headers = headers;
20
+ }
21
+ type(...values) {
22
+ if (!this._type) {
23
+ const header = this.headers.get('accept');
24
+ this._type = header ? parseAccept(header.toLowerCase()) : [];
25
+ }
26
+ for (const accepted of this._type) {
27
+ for (const value of values) {
28
+ if (value === accepted ||
29
+ (accepted.startsWith('*') && value.endsWith(accepted.substr(1))) ||
30
+ (accepted.endsWith('*') &&
31
+ value.startsWith(accepted.substr(0, accepted.length - 2)))) {
32
+ return value;
33
+ }
34
+ }
35
+ }
36
+ return false;
37
+ }
38
+ language(...values) {
39
+ if (!this._language) {
40
+ const header = this.headers.get('accept-language');
41
+ this._language = header ? parseAcceptLanguage(header.toLowerCase()) : [];
42
+ }
43
+ for (const accepted of this._language) {
44
+ for (const value of values) {
45
+ if (value === accepted || value.startsWith(accepted)) {
46
+ return value;
47
+ }
48
+ }
49
+ }
50
+ return false;
51
+ }
52
+ encoding(...values) {
53
+ if (!this._encoding) {
54
+ const header = this.headers.get('accept-encoding');
55
+ this._encoding = header ? parseAcceptEncoding(header.toLowerCase()) : [];
56
+ }
57
+ for (const accepted of this._encoding) {
58
+ for (const value of values) {
59
+ if (value === accepted) {
60
+ return value;
61
+ }
62
+ }
63
+ }
64
+ return false;
65
+ }
66
+ charset(...values) {
67
+ if (!this._charset) {
68
+ const header = this.headers.get('accept-charset');
69
+ this._charset = header ? parseAcceptCharset(header.toLowerCase()) : [];
70
+ }
71
+ for (const accepted of this._charset) {
72
+ for (const value of values) {
73
+ if (value === accepted) {
74
+ return value;
75
+ }
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+ }
81
+ exports.Accepts = Accepts;
@@ -3,7 +3,7 @@ export declare class Application {
3
3
  private readonly middleware;
4
4
  private _composedMiddleware?;
5
5
  private get composedMiddleware();
6
- use(middleware: Middleware): this;
6
+ use(middleware: Middleware): Application;
7
7
  handleRequest(request: Request, env: any, context: {
8
8
  waitUntil(promise: Promise<any>): void;
9
9
  }): Promise<Response>;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Application = void 0;
7
+ const statuses_1 = __importDefault(require("statuses"));
8
+ const context_js_1 = require("./context.js");
9
+ const http_error_js_1 = require("./http-error.js");
10
+ const middleware_js_1 = require("./middleware.js");
11
+ const resolved = Promise.resolve();
12
+ class Application {
13
+ middleware = [];
14
+ _composedMiddleware;
15
+ get composedMiddleware() {
16
+ if (!this._composedMiddleware) {
17
+ this._composedMiddleware = (0, middleware_js_1.composeMiddleware)(this.middleware);
18
+ }
19
+ return this._composedMiddleware;
20
+ }
21
+ use(middleware) {
22
+ this.middleware.push(middleware);
23
+ this._composedMiddleware = undefined;
24
+ return this;
25
+ }
26
+ async handleRequest(request, env, context) {
27
+ return this.invokeMiddleware(new context_js_1.Context(request, env, context), this.composedMiddleware);
28
+ }
29
+ async invokeMiddleware(context, middleware) {
30
+ try {
31
+ await middleware(context, () => resolved);
32
+ return context.res.create();
33
+ }
34
+ catch (err) {
35
+ console.error(err?.stack ?? err);
36
+ if (err instanceof http_error_js_1.HttpError) {
37
+ return err.toResponse();
38
+ }
39
+ const status = 500;
40
+ const statusText = statuses_1.default.message[500];
41
+ const headers = { 'content-type': 'text/plain' };
42
+ return new Response(statusText, { status, statusText, headers });
43
+ }
44
+ }
45
+ }
46
+ exports.Application = Application;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Context = void 0;
4
+ const cookies_js_1 = require("./cookies.js");
5
+ const req_js_1 = require("./req.js");
6
+ const response_builder_js_1 = require("./response-builder.js");
7
+ class Context {
8
+ environmentBindings;
9
+ _context;
10
+ req;
11
+ res;
12
+ cookies;
13
+ state;
14
+ constructor(request, environmentBindings, _context) {
15
+ this.environmentBindings = environmentBindings;
16
+ this._context = _context;
17
+ this.req = new req_js_1.Req(request);
18
+ this.res = new response_builder_js_1.ResponseBuilder();
19
+ this.cookies = new cookies_js_1.Cookies(request.headers, this.res.headers);
20
+ this.state = {};
21
+ }
22
+ waitUntil(promise) {
23
+ this._context.waitUntil(promise);
24
+ }
25
+ }
26
+ exports.Context = Context;
@@ -1,8 +1,8 @@
1
- import { CookieSerializeOptions } from 'cookie';
1
+ import { SerializeOptions } from 'cookie';
2
2
  export declare class Cookies {
3
3
  private readonly responseHeaders;
4
4
  private readonly requestCookies;
5
5
  constructor(requestHeaders: Headers, responseHeaders: Headers);
6
6
  get(name: string): string | null;
7
- set(name: string, val: string, options?: CookieSerializeOptions): void;
7
+ set(name: string, val: string, options?: SerializeOptions): void;
8
8
  }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Cookies = void 0;
4
+ const cookie_1 = require("cookie");
5
+ const noCookies = Object.create(null);
6
+ class Cookies {
7
+ responseHeaders;
8
+ requestCookies;
9
+ constructor(requestHeaders, responseHeaders) {
10
+ this.responseHeaders = responseHeaders;
11
+ const cookie = requestHeaders.get('cookie');
12
+ this.requestCookies = cookie ? (0, cookie_1.parse)(cookie) : noCookies;
13
+ }
14
+ get(name) {
15
+ return this.requestCookies[name] || null;
16
+ }
17
+ set(name, val, options) {
18
+ this.responseHeaders.append('Set-Cookie', (0, cookie_1.serialize)(name, val, options));
19
+ }
20
+ }
21
+ exports.Cookies = Cookies;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HttpError = void 0;
7
+ const statuses_1 = __importDefault(require("statuses"));
8
+ class HttpError extends Error {
9
+ status;
10
+ statusText;
11
+ body;
12
+ constructor(status, body) {
13
+ const statusText = statuses_1.default.message[status];
14
+ super(statusText);
15
+ this.name = this.constructor.name;
16
+ if (typeof Error.captureStackTrace === 'function') {
17
+ Error.captureStackTrace(this, this.constructor);
18
+ }
19
+ this.status = status;
20
+ this.statusText = statusText;
21
+ this.body = body;
22
+ }
23
+ toResponse() {
24
+ let body = this.body || this.statusText;
25
+ let contentType;
26
+ if (typeof body === 'string') {
27
+ contentType = 'text/plain';
28
+ }
29
+ else {
30
+ contentType = 'application/json';
31
+ body = JSON.stringify(body);
32
+ }
33
+ const { status, statusText } = this;
34
+ const headers = { 'content-type': contentType };
35
+ return new Response(body, { status, statusText, headers });
36
+ }
37
+ }
38
+ exports.HttpError = HttpError;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ var html_escaper_1 = require("html-escaper");
18
+ Object.defineProperty(exports, "htmlEncode", { enumerable: true, get: function () { return html_escaper_1.escape; } });
19
+ __exportStar(require("./accepts.js"), exports);
20
+ __exportStar(require("./application.js"), exports);
21
+ __exportStar(require("./context.js"), exports);
22
+ __exportStar(require("./cookies.js"), exports);
23
+ __exportStar(require("./http-error.js"), exports);
24
+ __exportStar(require("./middleware.js"), exports);
25
+ __exportStar(require("./normalize-pathname.js"), exports);
26
+ __exportStar(require("./req.js"), exports);
27
+ __exportStar(require("./response-builder.js"), exports);
28
+ __exportStar(require("./router.js"), exports);
29
+ __exportStar(require("./validate.js"), exports);
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.composeMiddleware = composeMiddleware;
4
+ function composeMiddleware(middleware) {
5
+ if (!Array.isArray(middleware))
6
+ throw new TypeError('Middleware stack must be an array!');
7
+ for (const fn of middleware) {
8
+ if (typeof fn !== 'function')
9
+ throw new TypeError('Middleware must be composed of functions!');
10
+ }
11
+ return function (context, next) {
12
+ let index = -1;
13
+ return dispatch(0);
14
+ function dispatch(i) {
15
+ if (i <= index)
16
+ return Promise.reject(new Error('next() called multiple times'));
17
+ index = i;
18
+ let fn = middleware[i];
19
+ if (i === middleware.length)
20
+ fn = next;
21
+ if (!fn)
22
+ return Promise.resolve();
23
+ try {
24
+ return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
25
+ }
26
+ catch (err) {
27
+ return Promise.reject(err);
28
+ }
29
+ }
30
+ };
31
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizePathnameMiddleware = void 0;
4
+ exports.normalizePathname = normalizePathname;
5
+ const http_error_1 = require("./http-error");
6
+ function normalizePathname(pathname) {
7
+ return decodeURIComponent(pathname).replace(/\/\/+/g, '/').normalize();
8
+ }
9
+ const normalizePathnameMiddleware = async ({ req }, next) => {
10
+ const pathname = req.url.pathname;
11
+ try {
12
+ req.url.pathname = normalizePathname(pathname);
13
+ }
14
+ catch (err) {
15
+ if (err instanceof URIError) {
16
+ throw new http_error_1.HttpError(400, `Unable to decode pathname "${pathname}".`);
17
+ }
18
+ throw err;
19
+ }
20
+ await next();
21
+ };
22
+ exports.normalizePathnameMiddleware = normalizePathnameMiddleware;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReqBody = exports.Req = void 0;
4
+ const secure_json_parse_1 = require("secure-json-parse");
5
+ const accepts_js_1 = require("./accepts.js");
6
+ class Req {
7
+ raw;
8
+ method;
9
+ url;
10
+ headers;
11
+ params;
12
+ accepts;
13
+ body;
14
+ constructor(request) {
15
+ this.raw = request;
16
+ this.method = request.method;
17
+ this.url = new URL(request.url);
18
+ this.headers = request.headers;
19
+ this.params = Object.create(null);
20
+ this.accepts = new accepts_js_1.Accepts(request.headers);
21
+ this.body = new ReqBody(request);
22
+ }
23
+ }
24
+ exports.Req = Req;
25
+ class ReqBody {
26
+ request;
27
+ _arrayBuffer;
28
+ _formData;
29
+ _json;
30
+ _text;
31
+ constructor(request) {
32
+ this.request = request;
33
+ }
34
+ arrayBuffer() {
35
+ if (!this._arrayBuffer) {
36
+ this._arrayBuffer = this.request.arrayBuffer();
37
+ }
38
+ return this._arrayBuffer;
39
+ }
40
+ formData() {
41
+ if (!this._formData) {
42
+ this._formData = this.request.formData();
43
+ }
44
+ return this._formData;
45
+ }
46
+ json(reviver) {
47
+ if (!this._json) {
48
+ this._json = this.text().then(text => (0, secure_json_parse_1.safeParse)(text, reviver));
49
+ }
50
+ return this._json;
51
+ }
52
+ text() {
53
+ if (!this._text) {
54
+ this._text = this.request.text();
55
+ }
56
+ return this._text;
57
+ }
58
+ }
59
+ exports.ReqBody = ReqBody;
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ResponseBuilder = void 0;
7
+ const statuses_1 = __importDefault(require("statuses"));
8
+ class ResponseBuilder {
9
+ headers = new Headers();
10
+ _status = 404;
11
+ _explicitStatus = false;
12
+ _implicitType = false;
13
+ _body = null;
14
+ _stringifyBody = false;
15
+ get status() {
16
+ return this._status;
17
+ }
18
+ set status(value) {
19
+ this._explicitStatus = true;
20
+ this._status = value;
21
+ if (this.body && statuses_1.default.empty[value]) {
22
+ this.body = null;
23
+ }
24
+ }
25
+ get statusText() {
26
+ return statuses_1.default.message[this._status];
27
+ }
28
+ get body() {
29
+ return this._body;
30
+ }
31
+ set body(value) {
32
+ this._body = value;
33
+ if (value === null) {
34
+ if (!statuses_1.default.empty[this.status]) {
35
+ this._status = 204;
36
+ }
37
+ this.headers.delete('content-type');
38
+ this.headers.delete('content-length');
39
+ this.headers.delete('transfer-encoding');
40
+ return;
41
+ }
42
+ if (!this._explicitStatus) {
43
+ this._status = 200;
44
+ }
45
+ if (value instanceof Blob ||
46
+ value instanceof FormData ||
47
+ value instanceof URLSearchParams ||
48
+ ArrayBuffer.isView(value) ||
49
+ value instanceof ArrayBuffer ||
50
+ value instanceof ReadableStream) {
51
+ this._stringifyBody = false;
52
+ if (this._implicitType) {
53
+ this._implicitType = false;
54
+ this.headers.delete('content-type');
55
+ }
56
+ }
57
+ else if (typeof value === 'string') {
58
+ this._stringifyBody = false;
59
+ if (!this.headers.has('content-type') || this._implicitType) {
60
+ this._implicitType = true;
61
+ if (/^\s*</.test(value)) {
62
+ this.headers.set('content-type', 'text/html;charset=UTF-8');
63
+ }
64
+ else {
65
+ this.headers.set('content-type', 'text/plain;charset=UTF-8');
66
+ }
67
+ }
68
+ }
69
+ else {
70
+ this._stringifyBody = true;
71
+ this._implicitType = true;
72
+ this.headers.set('content-type', 'application/json;charset=UTF-8');
73
+ }
74
+ }
75
+ redirect(url) {
76
+ if (url instanceof URL) {
77
+ url = url.href;
78
+ }
79
+ this.headers.set('location', url);
80
+ if (!statuses_1.default.redirect[this.status]) {
81
+ this.status = 302;
82
+ }
83
+ this.type = 'text/plain;charset=UTF-8';
84
+ this.body = `Redirecting to ${url}.`;
85
+ }
86
+ get type() {
87
+ const type = this.headers.get('content-type');
88
+ if (!type) {
89
+ return '';
90
+ }
91
+ return type.split(';', 1)[0];
92
+ }
93
+ set type(value) {
94
+ this._implicitType = false;
95
+ if (value) {
96
+ this.headers.set('content-type', value);
97
+ }
98
+ else {
99
+ this.headers.delete('content-type');
100
+ }
101
+ }
102
+ get lastModified() {
103
+ const date = this.headers.get('last-modified');
104
+ return date ? new Date(date) : null;
105
+ }
106
+ set lastModified(value) {
107
+ if (value === null) {
108
+ this.headers.delete('last-modified');
109
+ return;
110
+ }
111
+ if (typeof value === 'string') {
112
+ value = new Date(value);
113
+ }
114
+ this.headers.set('last-modified', value.toUTCString());
115
+ }
116
+ get etag() {
117
+ return this.headers.get('etag');
118
+ }
119
+ set etag(value) {
120
+ if (value) {
121
+ if (!/^(W\/)?"/.test(value)) {
122
+ value = `"${value}"`;
123
+ }
124
+ this.headers.set('etag', value);
125
+ }
126
+ else {
127
+ this.headers.delete('etag');
128
+ }
129
+ }
130
+ create() {
131
+ const { body: rawBody, status, statusText, headers } = this;
132
+ const body = this._stringifyBody
133
+ ? JSON.stringify(rawBody)
134
+ : rawBody;
135
+ return new Response(body, { status, statusText, headers });
136
+ }
137
+ }
138
+ exports.ResponseBuilder = ResponseBuilder;
@@ -0,0 +1,39 @@
1
+ import { PathToRegexpOptions } from 'path-to-regexp';
2
+ import { Context } from './context.js';
3
+ import { Middleware } from './middleware.js';
4
+ export type Predicate = (context: Context) => boolean;
5
+ export declare const Method: (method: string) => Predicate;
6
+ export declare const Get: Predicate;
7
+ export declare const Post: Predicate;
8
+ export declare const Put: Predicate;
9
+ export declare const Patch: Predicate;
10
+ export declare const Delete: Predicate;
11
+ export declare const Head: Predicate;
12
+ export declare const Options: Predicate;
13
+ export declare const Header: (header: string, value: string) => Predicate;
14
+ export declare const Host: (host: string) => Predicate;
15
+ export declare const Path: (pattern: string, options?: PathToRegexpOptions) => Predicate;
16
+ export type RouteCondition = (context: Context) => boolean;
17
+ export interface Route {
18
+ conditions: RouteCondition[];
19
+ middleware: Middleware;
20
+ }
21
+ export interface RouterOptions {
22
+ pathToRegExpOptions?: PathToRegexpOptions;
23
+ }
24
+ export declare const defaultRouterOptions: RouterOptions;
25
+ export declare class Router {
26
+ private readonly options;
27
+ private readonly routes;
28
+ constructor(options?: RouterOptions);
29
+ get(pathname: string, ...middleware: Middleware[]): Router;
30
+ post(pathname: string, ...middleware: Middleware[]): Router;
31
+ put(pathname: string, ...middleware: Middleware[]): Router;
32
+ patch(pathname: string, ...middleware: Middleware[]): Router;
33
+ delete(pathname: string, ...middleware: Middleware[]): Router;
34
+ head(pathname: string, ...middleware: Middleware[]): Router;
35
+ all(pathname: string, ...middleware: Middleware[]): Router;
36
+ middleware: Middleware;
37
+ compose(conditions: RouteCondition[], ...middleware: Middleware[]): Router;
38
+ resolve(ctx: Context): Route | undefined;
39
+ }
@@ -0,0 +1,105 @@
1
+ "use strict";
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");
5
+ const middleware_js_1 = require("./middleware.js");
6
+ const Method = (method) => {
7
+ method = method.toUpperCase();
8
+ return ({ req }) => req.method === method;
9
+ };
10
+ exports.Method = Method;
11
+ exports.Get = (0, exports.Method)('get');
12
+ exports.Post = (0, exports.Method)('post');
13
+ exports.Put = (0, exports.Method)('put');
14
+ exports.Patch = (0, exports.Method)('patch');
15
+ exports.Delete = (0, exports.Method)('delete');
16
+ exports.Head = (0, exports.Method)('head');
17
+ exports.Options = (0, exports.Method)('options');
18
+ const Header = (header, value) => {
19
+ value = value.toLowerCase();
20
+ return ({ req }) => req.headers.get(header) === value;
21
+ };
22
+ exports.Header = Header;
23
+ const Host = (host) => (0, exports.Header)('host', host);
24
+ exports.Host = Host;
25
+ const Path = (pattern, options) => {
26
+ const { regexp, keys } = (0, path_to_regexp_1.pathToRegexp)(pattern, options);
27
+ return ({ req: { url, params } }) => {
28
+ const match = url.pathname.match(regexp);
29
+ if (!match) {
30
+ return false;
31
+ }
32
+ collectParameters(keys, match, params);
33
+ return true;
34
+ };
35
+ };
36
+ exports.Path = Path;
37
+ exports.defaultRouterOptions = {
38
+ pathToRegExpOptions: {}
39
+ };
40
+ class Router {
41
+ options;
42
+ routes;
43
+ constructor(options = exports.defaultRouterOptions) {
44
+ this.options = options;
45
+ this.routes = [];
46
+ }
47
+ get(pathname, ...middleware) {
48
+ const opts = this.options.pathToRegExpOptions;
49
+ return this.compose([exports.Get, (0, exports.Path)(pathname, opts)], ...middleware);
50
+ }
51
+ post(pathname, ...middleware) {
52
+ const opts = this.options.pathToRegExpOptions;
53
+ return this.compose([exports.Post, (0, exports.Path)(pathname, opts)], ...middleware);
54
+ }
55
+ put(pathname, ...middleware) {
56
+ const opts = this.options.pathToRegExpOptions;
57
+ return this.compose([exports.Put, (0, exports.Path)(pathname, opts)], ...middleware);
58
+ }
59
+ patch(pathname, ...middleware) {
60
+ const opts = this.options.pathToRegExpOptions;
61
+ return this.compose([exports.Patch, (0, exports.Path)(pathname, opts)], ...middleware);
62
+ }
63
+ delete(pathname, ...middleware) {
64
+ const opts = this.options.pathToRegExpOptions;
65
+ return this.compose([exports.Delete, (0, exports.Path)(pathname, opts)], ...middleware);
66
+ }
67
+ head(pathname, ...middleware) {
68
+ const opts = this.options.pathToRegExpOptions;
69
+ return this.compose([exports.Head, (0, exports.Path)(pathname, opts)], ...middleware);
70
+ }
71
+ all(pathname, ...middleware) {
72
+ const opts = this.options.pathToRegExpOptions;
73
+ return this.compose([(0, exports.Path)(pathname, opts)], ...middleware);
74
+ }
75
+ middleware = async (ctx, next) => {
76
+ const resolved = this.resolve(ctx);
77
+ if (resolved) {
78
+ await resolved.middleware(ctx, next);
79
+ }
80
+ else {
81
+ await next();
82
+ }
83
+ };
84
+ compose(conditions, ...middleware) {
85
+ this.routes.push({
86
+ conditions,
87
+ middleware: (0, middleware_js_1.composeMiddleware)(middleware)
88
+ });
89
+ return this;
90
+ }
91
+ resolve(ctx) {
92
+ return this.routes.find(({ conditions }) => conditions.length === 0 || conditions.every(c => c(ctx)));
93
+ }
94
+ }
95
+ exports.Router = Router;
96
+ function collectParameters(keys, match, params) {
97
+ for (let i = 1; i < match.length; i++) {
98
+ const name = keys[i - 1].name;
99
+ const value = match[i];
100
+ if (!value) {
101
+ continue;
102
+ }
103
+ params[name] = decodeURIComponent(value);
104
+ }
105
+ }
@@ -8,7 +8,7 @@ export interface RequestSchemas {
8
8
  }
9
9
  export type RequestPart = keyof RequestSchemas;
10
10
  export type RequestParser = (data: URLSearchParams | FormData) => any;
11
- declare function middlewareFactory(schemas: RequestSchemas, parser?: RequestParser, lookup?: any): Middleware;
11
+ declare function middlewareFactory(schemas: RequestSchemas, parser?: RequestParser, lookup?: Record<string, Schema | boolean>): Middleware;
12
12
  export declare const messages: Record<RequestPart, string>;
13
13
  export interface RequestValidationErrorBody {
14
14
  status: 400;