@e22m4u/js-trie-router 0.5.0 → 0.5.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.
Files changed (41) hide show
  1. package/dist/cjs/index.cjs +1 -0
  2. package/eslint.config.js +1 -0
  3. package/package.json +15 -9
  4. package/src/debuggable-service.d.ts +6 -0
  5. package/src/hooks/hook-invoker.d.ts +25 -0
  6. package/src/hooks/hook-registry.d.ts +93 -0
  7. package/src/hooks/index.d.ts +2 -0
  8. package/src/index.d.ts +9 -0
  9. package/src/parsers/body-parser.d.ts +52 -0
  10. package/src/parsers/cookies-parser.d.ts +15 -0
  11. package/src/parsers/index.d.ts +4 -0
  12. package/src/parsers/query-parser.d.ts +21 -0
  13. package/src/parsers/request-parser.d.ts +34 -0
  14. package/src/request-context.d.ts +101 -0
  15. package/src/route-registry.d.ts +39 -0
  16. package/src/route.d.ts +100 -0
  17. package/src/router-options.d.ts +18 -0
  18. package/src/senders/data-sender.d.ts +15 -0
  19. package/src/senders/error-sender.d.ts +30 -0
  20. package/src/senders/index.d.ts +2 -0
  21. package/src/trie-router.d.ts +104 -0
  22. package/src/types.d.ts +19 -0
  23. package/src/utils/clone-deep.d.ts +6 -0
  24. package/src/utils/create-cookies-string.d.ts +6 -0
  25. package/src/utils/create-debugger.d.ts +11 -0
  26. package/src/utils/create-error.d.ts +14 -0
  27. package/src/utils/create-request-mock.d.ts +27 -0
  28. package/src/utils/create-response-mock.d.ts +17 -0
  29. package/src/utils/create-route-mock.d.ts +18 -0
  30. package/src/utils/fetch-request-body.d.ts +26 -0
  31. package/src/utils/get-request-pathname.d.ts +8 -0
  32. package/src/utils/index.d.ts +16 -0
  33. package/src/utils/is-promise.d.ts +10 -0
  34. package/src/utils/is-readable-stream.d.ts +9 -0
  35. package/src/utils/is-response-sent.d.ts +8 -0
  36. package/src/utils/is-writable-stream.d.ts +9 -0
  37. package/src/utils/parse-content-type.d.ts +15 -0
  38. package/src/utils/parse-cookies.d.ts +19 -0
  39. package/src/utils/to-camel-case.d.ts +6 -0
  40. package/tsconfig.json +14 -0
  41. package/jsconfig.json +0 -7
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
package/eslint.config.js CHANGED
@@ -28,6 +28,7 @@ export default [{
28
28
  ...eslintChaiExpectPlugin.configs['recommended-flat'].rules,
29
29
  ...eslintJsdocPlugin.configs['flat/recommended-error'].rules,
30
30
  'no-duplicate-imports': 'error',
31
+ 'import/export': 0,
31
32
  'jsdoc/reject-any-type': 0,
32
33
  'jsdoc/reject-function-type': 0,
33
34
  'jsdoc/require-param-description': 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-trie-router",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "HTTP маршрутизатор для Node.js на основе префиксного дерева",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
@@ -17,9 +17,11 @@
17
17
  "url": "git+https://gitrepos.ru/e22m4u/js-trie-router.git"
18
18
  },
19
19
  "type": "module",
20
+ "types": "./src/index.d.ts",
20
21
  "module": "./src/index.js",
21
22
  "main": "./dist/cjs/index.cjs",
22
23
  "exports": {
24
+ "types": "./src/index.d.ts",
23
25
  "import": "./src/index.js",
24
26
  "require": "./dist/cjs/index.cjs"
25
27
  },
@@ -27,8 +29,8 @@
27
29
  "node": ">=16"
28
30
  },
29
31
  "scripts": {
30
- "lint": "eslint ./src",
31
- "lint:fix": "eslint ./src --fix",
32
+ "lint": "tsc && eslint ./src",
33
+ "lint:fix": "tsc && eslint ./src --fix",
32
34
  "format": "prettier --write \"./src/**/*.{js,ts}\"",
33
35
  "test": "npm run lint && c8 --reporter=text-summary mocha --bail",
34
36
  "test:coverage": "npm run lint && c8 --reporter=text mocha",
@@ -36,10 +38,10 @@
36
38
  "prepare": "husky"
37
39
  },
38
40
  "dependencies": {
39
- "@e22m4u/js-debug": "~0.4.0",
40
- "@e22m4u/js-format": "~0.3.0",
41
- "@e22m4u/js-path-trie": "~0.1.0",
42
- "@e22m4u/js-service": "~0.5.0",
41
+ "@e22m4u/js-debug": "~0.4.1",
42
+ "@e22m4u/js-format": "~0.3.1",
43
+ "@e22m4u/js-path-trie": "~0.1.1",
44
+ "@e22m4u/js-service": "~0.5.1",
43
45
  "debug": "~4.4.3",
44
46
  "http-errors": "~2.0.1",
45
47
  "statuses": "~2.0.2"
@@ -48,6 +50,9 @@
48
50
  "@commitlint/cli": "~20.1.0",
49
51
  "@commitlint/config-conventional": "~20.0.0",
50
52
  "@eslint/js": "~9.39.1",
53
+ "@types/chai": "~5.2.3",
54
+ "@types/chai-as-promised": "~8.0.2",
55
+ "@types/mocha": "~10.0.10",
51
56
  "c8": "~10.1.3",
52
57
  "chai": "~6.2.1",
53
58
  "chai-as-promised": "~8.0.2",
@@ -61,7 +66,8 @@
61
66
  "globals": "~16.5.0",
62
67
  "husky": "~9.1.7",
63
68
  "mocha": "~11.7.5",
64
- "prettier": "~3.7.3",
65
- "rimraf": "~6.1.2"
69
+ "prettier": "~3.7.4",
70
+ "rimraf": "~6.1.2",
71
+ "typescript": "~5.9.3"
66
72
  }
67
73
  }
@@ -0,0 +1,6 @@
1
+ import {DebuggableService as BaseDebuggableService} from '@e22m4u/js-service';
2
+
3
+ /**
4
+ * Debuggable service.
5
+ */
6
+ declare class DebuggableService extends BaseDebuggableService {}
@@ -0,0 +1,25 @@
1
+ import {Route} from '../route.js';
2
+ import {ServerResponse} from 'http';
3
+ import {ValueOrPromise} from '../types.js';
4
+ import {RouterHookType} from './hook-registry.js';
5
+ import {DebuggableService} from '../debuggable-service.js';
6
+
7
+ /**
8
+ * Hook invoker.
9
+ */
10
+ export declare class HookInvoker extends DebuggableService {
11
+ /**
12
+ * Invoke and continue until value received.
13
+ *
14
+ * @param route
15
+ * @param hookType
16
+ * @param response
17
+ * @param args
18
+ */
19
+ invokeAndContinueUntilValueReceived(
20
+ route: Route,
21
+ hookType: RouterHookType,
22
+ response: ServerResponse,
23
+ ...args: unknown[]
24
+ ): ValueOrPromise<unknown>;
25
+ }
@@ -0,0 +1,93 @@
1
+ import {Callable} from '../types.js';
2
+ import {RequestContext} from '../request-context.js';
3
+ import {DebuggableService} from '../debuggable-service.js';
4
+
5
+ /**
6
+ * Hook type.
7
+ */
8
+ export declare const RouterHookType: {
9
+ PRE_HANDLER: 'preHandler';
10
+ POST_HANDLER: 'postHandler';
11
+ };
12
+
13
+ /**
14
+ * Type of RouterHookType.
15
+ */
16
+ export type RouterHookType =
17
+ (typeof RouterHookType)[keyof typeof RouterHookType];
18
+
19
+ /**
20
+ * Router hook.
21
+ */
22
+ export type RouterHook = Callable;
23
+
24
+ /**
25
+ * Pre handler hook.
26
+ */
27
+ export type PreHandlerHook = (ctx: RequestContext) => unknown;
28
+
29
+ /**
30
+ * Post handler hook.
31
+ */
32
+ export type PostHandlerHook = (ctx: RequestContext, data: unknown) => unknown;
33
+
34
+ /**
35
+ * Hook registry.
36
+ */
37
+ export declare class HookRegistry extends DebuggableService {
38
+ /**
39
+ * Add hook.
40
+ *
41
+ * @param type
42
+ * @param hook
43
+ */
44
+ addHook(type: typeof RouterHookType.PRE_HANDLER, hook: PreHandlerHook): this;
45
+
46
+ /**
47
+ * Add hook.
48
+ *
49
+ * @param type
50
+ * @param hook
51
+ */
52
+ addHook(
53
+ type: typeof RouterHookType.POST_HANDLER,
54
+ hook: PostHandlerHook,
55
+ ): this;
56
+
57
+ /**
58
+ * Add hook.
59
+ *
60
+ * @param type
61
+ * @param hook
62
+ */
63
+ addHook(type: RouterHookType, hook: RouterHook): this;
64
+
65
+ /**
66
+ * Has hook.
67
+ *
68
+ * @param type
69
+ * @param hook
70
+ */
71
+ hasHook(type: RouterHookType, hook: RouterHook): boolean;
72
+
73
+ /**
74
+ * Get hooks.
75
+ *
76
+ * @param type
77
+ */
78
+ getHooks(type: typeof RouterHookType.PRE_HANDLER): PreHandlerHook[];
79
+
80
+ /**
81
+ * Get hooks.
82
+ *
83
+ * @param type
84
+ */
85
+ getHooks(type: typeof RouterHookType.POST_HANDLER): PostHandlerHook[];
86
+
87
+ /**
88
+ * Get hooks.
89
+ *
90
+ * @param type
91
+ */
92
+ getHooks(type: RouterHookType): RouterHook[];
93
+ }
@@ -0,0 +1,2 @@
1
+ export * from './hook-invoker.js';
2
+ export * from './hook-registry.js';
package/src/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from './route.js';
2
+ export * from './utils/index.js';
3
+ export * from './hooks/index.js';
4
+ export * from './trie-router.js';
5
+ export * from './parsers/index.js';
6
+ export * from './senders/index.js';
7
+ export * from './route-registry.js';
8
+ export * from './router-options.js';
9
+ export * from './request-context.js';
@@ -0,0 +1,52 @@
1
+ import {IncomingMessage} from 'http';
2
+ import {ValueOrPromise} from '../types.js';
3
+ import {DebuggableService} from '../debuggable-service.js';
4
+
5
+ /**
6
+ * Method names to be parsed.
7
+ */
8
+ export type METHODS_WITH_BODY = string[];
9
+
10
+ /**
11
+ * Unparsable media types.
12
+ */
13
+ export type UNPARSABLE_MEDIA_TYPES = string[];
14
+
15
+ /**
16
+ * Body parser function.
17
+ */
18
+ export type BodyParserFunction = <T = unknown>(input: string) => T;
19
+
20
+ /**
21
+ * Body parser.
22
+ */
23
+ export declare class BodyParser extends DebuggableService {
24
+ /**
25
+ * Define parser.
26
+ *
27
+ * @param mediaType
28
+ * @param parser
29
+ */
30
+ defineParser(mediaType: string, parser: BodyParserFunction): this;
31
+
32
+ /**
33
+ * Has parser.
34
+ *
35
+ * @param mediaType
36
+ */
37
+ hasParser(mediaType: string): boolean;
38
+
39
+ /**
40
+ * Delete parser.
41
+ *
42
+ * @param mediaType
43
+ */
44
+ deleteParser(mediaType: string): this;
45
+
46
+ /**
47
+ * Parse.
48
+ *
49
+ * @param request
50
+ */
51
+ parse<T = unknown>(request: IncomingMessage): ValueOrPromise<T>;
52
+ }
@@ -0,0 +1,15 @@
1
+ import {IncomingMessage} from 'http';
2
+ import {ParsedCookies} from '../utils/index.js';
3
+ import {DebuggableService} from '../debuggable-service.js';
4
+
5
+ /**
6
+ * Cookies parser.
7
+ */
8
+ export declare class CookiesParser extends DebuggableService {
9
+ /**
10
+ * Parse.
11
+ *
12
+ * @param request
13
+ */
14
+ parse(request: IncomingMessage): ParsedCookies;
15
+ }
@@ -0,0 +1,4 @@
1
+ export * from './body-parser.js';
2
+ export * from './query-parser.js';
3
+ export * from './cookies-parser.js';
4
+ export * from './request-parser.js';
@@ -0,0 +1,21 @@
1
+ import {IncomingMessage} from 'http';
2
+ import {DebuggableService} from '../debuggable-service.js';
3
+
4
+ /**
5
+ * Parsed query.
6
+ */
7
+ export type ParsedQuery = {
8
+ [key: string]: string | undefined;
9
+ };
10
+
11
+ /**
12
+ * Query parser.
13
+ */
14
+ export declare class QueryParser extends DebuggableService {
15
+ /**
16
+ * Parse.
17
+ *
18
+ * @param request
19
+ */
20
+ parse(request: IncomingMessage): ParsedQuery;
21
+ }
@@ -0,0 +1,34 @@
1
+ import {IncomingMessage} from 'http';
2
+ import {ValueOrPromise} from '../types.js';
3
+ import {ParsedQuery} from './query-parser.js';
4
+ import {ParsedCookies} from '../utils/index.js';
5
+ import {DebuggableService} from '../debuggable-service.js';
6
+
7
+ /**
8
+ * Parsed headers.
9
+ */
10
+ export type ParsedHeaders = {
11
+ [key: string]: string | undefined;
12
+ };
13
+
14
+ /**
15
+ * Parsed request.
16
+ */
17
+ type ParsedRequestData = {
18
+ query: ParsedQuery;
19
+ cookies: ParsedCookies;
20
+ body: unknown;
21
+ headers: ParsedHeaders;
22
+ };
23
+
24
+ /**
25
+ * Request parser.
26
+ */
27
+ export declare class RequestParser extends DebuggableService {
28
+ /**
29
+ * Parse.
30
+ *
31
+ * @param request
32
+ */
33
+ parse(request: IncomingMessage): ValueOrPromise<ParsedRequestData>;
34
+ }
@@ -0,0 +1,101 @@
1
+ import {Route, RouteMeta} from './route.js';
2
+ import {ParsedCookies} from './utils/index.js';
3
+ import {ServiceContainer} from '@e22m4u/js-service';
4
+ import {IncomingMessage, ServerResponse} from 'http';
5
+ import {ParsedQuery, ParsedHeaders} from './parsers/index.js';
6
+
7
+ /**
8
+ * Parsed params.
9
+ */
10
+ export type ParsedParams = {
11
+ [key: string]: string | undefined;
12
+ };
13
+
14
+ /**
15
+ * Request context.
16
+ */
17
+ export declare class RequestContext {
18
+ /**
19
+ * Container.
20
+ */
21
+ get container(): ServiceContainer;
22
+
23
+ /**
24
+ * Request.
25
+ */
26
+ get request(): IncomingMessage;
27
+
28
+ /**
29
+ * Response.
30
+ */
31
+ get response(): ServerResponse;
32
+
33
+ /**
34
+ * Route.
35
+ */
36
+ get route(): Route;
37
+
38
+ /**
39
+ * Query.
40
+ */
41
+ query: ParsedQuery;
42
+
43
+ /**
44
+ * Params.
45
+ */
46
+ params: ParsedParams;
47
+
48
+ /**
49
+ * Headers.
50
+ */
51
+ headers: ParsedHeaders;
52
+
53
+ /**
54
+ * Cookies.
55
+ */
56
+ cookies: ParsedCookies;
57
+
58
+ /**
59
+ * Body.
60
+ */
61
+ body: unknown;
62
+
63
+ /**
64
+ * State.
65
+ */
66
+ state: Record<string, any>;
67
+
68
+ /**
69
+ * Route meta.
70
+ */
71
+ get meta(): RouteMeta;
72
+
73
+ /**
74
+ * Method.
75
+ */
76
+ get method(): string;
77
+
78
+ /**
79
+ * Path.
80
+ */
81
+ get path(): string;
82
+
83
+ /**
84
+ * Pathname.
85
+ */
86
+ get pathname(): string;
87
+
88
+ /**
89
+ * Constructor.
90
+ *
91
+ * @param container
92
+ * @param request
93
+ * @param response
94
+ */
95
+ constructor(
96
+ container: ServiceContainer,
97
+ request: IncomingMessage,
98
+ response: ServerResponse,
99
+ route: Route,
100
+ );
101
+ }
@@ -0,0 +1,39 @@
1
+ import {Route} from './route.js';
2
+ import {IncomingMessage} from 'http';
3
+ import {RouteDefinition} from './route.js';
4
+ import {ServiceContainer} from '@e22m4u/js-service';
5
+ import {DebuggableService} from './debuggable-service.js';
6
+
7
+ /**
8
+ * Resolved route.
9
+ */
10
+ export type ResolvedRoute = {
11
+ route: Route;
12
+ params: {[key: string]: string | undefined};
13
+ };
14
+
15
+ /**
16
+ * Route registry.
17
+ */
18
+ export declare class RouteRegistry extends DebuggableService {
19
+ /**
20
+ * Constructor.
21
+ *
22
+ * @param container
23
+ */
24
+ constructor(container: ServiceContainer);
25
+
26
+ /**
27
+ * Define route.
28
+ *
29
+ * @param routeDef
30
+ */
31
+ defineRoute(routeDef: RouteDefinition): Route;
32
+
33
+ /**
34
+ * Match route by request.
35
+ *
36
+ * @param request
37
+ */
38
+ matchRouteByRequest(request: IncomingMessage): ResolvedRoute | undefined;
39
+ }
package/src/route.d.ts ADDED
@@ -0,0 +1,100 @@
1
+ import {ValueOrPromise} from './types.js';
2
+ import {HookRegistry} from './hooks/index.js';
3
+ import {RequestContext} from './request-context.js';
4
+
5
+ /**
6
+ * Http method.
7
+ */
8
+ export declare const HttpMethod: {
9
+ GET: 'GET';
10
+ POST: 'POST';
11
+ PUT: 'PUT';
12
+ PATCH: 'PATCH';
13
+ DELETE: 'DELETE';
14
+ };
15
+
16
+ /**
17
+ * Type of HttpMethod.
18
+ */
19
+ export type HttpMethod = (typeof HttpMethod)[keyof typeof HttpMethod];
20
+
21
+ /**
22
+ * Route handler.
23
+ */
24
+ export type RouteHandler = (ctx: RequestContext) => ValueOrPromise<unknown>;
25
+
26
+ /**
27
+ * Route pre-handler.
28
+ */
29
+ export type RoutePreHandler = RouteHandler;
30
+
31
+ /**
32
+ * Route post-handler.
33
+ */
34
+ export type RoutePostHandler<T = unknown, U = unknown> = (
35
+ ctx: RequestContext,
36
+ data: T,
37
+ ) => ValueOrPromise<U>;
38
+
39
+ /**
40
+ * Route meta.
41
+ */
42
+ export type RouteMeta = {
43
+ [key: string]: unknown;
44
+ };
45
+
46
+ /**
47
+ * Route definition.
48
+ */
49
+ export type RouteDefinition = {
50
+ method: string;
51
+ path: string;
52
+ handler: RouteHandler;
53
+ preHandler?: RoutePreHandler | RoutePreHandler[];
54
+ postHandler?: RoutePostHandler | RoutePostHandler[];
55
+ meta?: RouteMeta;
56
+ };
57
+
58
+ /**
59
+ * Route.
60
+ */
61
+ export declare class Route {
62
+ /**
63
+ * Method.
64
+ */
65
+ get method(): string;
66
+
67
+ /**
68
+ * Path.
69
+ */
70
+ get path(): string;
71
+
72
+ /**
73
+ * Meta.
74
+ */
75
+ get meta(): RouteMeta;
76
+
77
+ /**
78
+ * Handler.
79
+ */
80
+ get handler(): RouteHandler;
81
+
82
+ /**
83
+ * Hook registry.
84
+ */
85
+ get hookRegistry(): HookRegistry;
86
+
87
+ /**
88
+ * Constructor.
89
+ *
90
+ * @param routeDef
91
+ */
92
+ constructor(routeDef: RouteDefinition);
93
+
94
+ /**
95
+ * Handle.
96
+ *
97
+ * @param context
98
+ */
99
+ handle(context: RequestContext): ValueOrPromise<unknown>;
100
+ }
@@ -0,0 +1,18 @@
1
+ import {DebuggableService} from './debuggable-service.js';
2
+
3
+ /**
4
+ * Router options.
5
+ */
6
+ export declare class RouterOptions extends DebuggableService {
7
+ /**
8
+ * Request body bytes limit.
9
+ */
10
+ get requestBodyBytesLimit(): number;
11
+
12
+ /**
13
+ * Set request body bytes limit.
14
+ *
15
+ * @param input
16
+ */
17
+ setRequestBodyBytesLimit(input: number): this;
18
+ }
@@ -0,0 +1,15 @@
1
+ import {ServerResponse} from 'http';
2
+ import {DebuggableService} from '../debuggable-service.js';
3
+
4
+ /**
5
+ * Data sender.
6
+ */
7
+ export declare class DataSender extends DebuggableService {
8
+ /**
9
+ * Send.
10
+ *
11
+ * @param response
12
+ * @param data
13
+ */
14
+ send(response: ServerResponse, data: unknown): void;
15
+ }
@@ -0,0 +1,30 @@
1
+ import {ServerResponse} from 'http';
2
+ import {IncomingMessage} from 'http';
3
+ import {DebuggableService} from '../debuggable-service.js';
4
+
5
+ /**
6
+ * Exposed error properties.
7
+ */
8
+ export const EXPOSED_ERROR_PROPERTIES: ['code', 'details'];
9
+
10
+ /**
11
+ * Error sender.
12
+ */
13
+ export declare class ErrorSender extends DebuggableService {
14
+ /**
15
+ * Send.
16
+ *
17
+ * @param request
18
+ * @param response
19
+ * @param error
20
+ */
21
+ send(request: IncomingMessage, response: ServerResponse, error: Error): void;
22
+
23
+ /**
24
+ * Send 404.
25
+ *
26
+ * @param request
27
+ * @param response
28
+ */
29
+ send404(request: IncomingMessage, response: ServerResponse): void;
30
+ }
@@ -0,0 +1,2 @@
1
+ export * from './data-sender.js';
2
+ export * from './error-sender.js';
@@ -0,0 +1,104 @@
1
+ import {Route} from './route.js';
2
+ import {RequestListener} from 'http';
3
+ import {RouteDefinition} from './route.js';
4
+ import {DebuggableService} from './debuggable-service.js';
5
+
6
+ import {
7
+ RouterHook,
8
+ RouterHookType,
9
+ PostHandlerHook,
10
+ PreHandlerHook,
11
+ } from './hooks/index.js';
12
+
13
+ /**
14
+ * Trie router.
15
+ */
16
+ export declare class TrieRouter extends DebuggableService {
17
+ /**
18
+ * Define route.
19
+ *
20
+ * Example 1:
21
+ * ```
22
+ * const router = new TrieRouter();
23
+ * router.defineRoute({
24
+ * method: HttpMethod.GET, // Request method.
25
+ * path: '/', // Path template.
26
+ * handler: ctx => 'Hello world!', // Request handler.
27
+ * });
28
+ * ```
29
+ *
30
+ * Example 2:
31
+ * ```
32
+ * const router = new TrieRouter();
33
+ * router.defineRoute({
34
+ * method: HttpMethod.POST, // Request method.
35
+ * path: '/users/:id', // The path template may have parameters.
36
+ * preHandler(ctx) { ... }, // The "preHandler" is executed before a route handler.
37
+ * handler(ctx) { ... }, // Request handler function.
38
+ * postHandler(ctx, data) { ... }, // The "postHandler" is executed after a route handler
39
+ * });
40
+ * ```
41
+ *
42
+ * @param routeDef
43
+ */
44
+ defineRoute(routeDef: RouteDefinition): Route;
45
+
46
+ /**
47
+ * Request listener.
48
+ *
49
+ * Example:
50
+ * ```
51
+ * import http from 'http';
52
+ * import {TrieRouter} from '@e22m4u/js-trie-router';
53
+ *
54
+ * const router = new TrieRouter();
55
+ * const server = new http.Server();
56
+ * server.on('request', router.requestListener); // Sets the request listener.
57
+ * server.listen(3000); // Starts listening for connections.
58
+ * ```
59
+ *
60
+ * @returns {Function}
61
+ */
62
+ get requestListener(): RequestListener;
63
+
64
+ /**
65
+ * Add hook.
66
+ *
67
+ * @param type
68
+ * @param hook
69
+ */
70
+ addHook(type: typeof RouterHookType.PRE_HANDLER, hook: PreHandlerHook): this;
71
+
72
+ /**
73
+ * Add hook.
74
+ *
75
+ * @param type
76
+ * @param hook
77
+ */
78
+ addHook(
79
+ type: typeof RouterHookType.POST_HANDLER,
80
+ hook: PostHandlerHook,
81
+ ): this;
82
+
83
+ /**
84
+ * Add hook.
85
+ *
86
+ * @param type
87
+ * @param hook
88
+ */
89
+ addHook(type: RouterHookType, hook: RouterHook): this;
90
+
91
+ /**
92
+ * Add pre-handler hook.
93
+ *
94
+ * @param hook
95
+ */
96
+ addPreHandler(hook: PreHandlerHook): this;
97
+
98
+ /**
99
+ * Add post-handler hook.
100
+ *
101
+ * @param hook
102
+ */
103
+ addPostHandler(hook: PostHandlerHook): this;
104
+ }
package/src/types.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * A callable type with the "new" operator
3
+ * allows class and constructor.
4
+ */
5
+ export interface Constructor<T = unknown> {
6
+ new (...args: any[]): T;
7
+ }
8
+
9
+ /**
10
+ * A function type without class and constructor.
11
+ */
12
+ export type Callable<T = unknown> = (...args: any[]) => T;
13
+
14
+ /**
15
+ * Representing a value or promise. This type is used
16
+ * to represent results of synchronous/asynchronous
17
+ * resolution of values.
18
+ */
19
+ export type ValueOrPromise<T> = T | PromiseLike<T>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Clone deep.
3
+ *
4
+ * @param value
5
+ */
6
+ export declare function cloneDeep<T>(value: T): T;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Create cookies string.
3
+ *
4
+ * @param data
5
+ */
6
+ export declare function createCookiesString(data: object): string;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Debugger.
3
+ */
4
+ export type Debugger = (message: string, ...args: unknown[]) => void;
5
+
6
+ /**
7
+ * Create debugger.
8
+ *
9
+ * @param name
10
+ */
11
+ export declare function createDebugger(name: string): Debugger;
@@ -0,0 +1,14 @@
1
+ import {Constructor} from '../types.js';
2
+
3
+ /**
4
+ * Create error.
5
+ *
6
+ * @param errorCtor
7
+ * @param message
8
+ * @param args
9
+ */
10
+ export declare function createError<T>(
11
+ errorCtor: Constructor<T>,
12
+ message: string,
13
+ ...args: unknown[]
14
+ ): T;
@@ -0,0 +1,27 @@
1
+ import {Readable} from 'stream';
2
+ import {IncomingMessage} from 'http';
3
+
4
+ /**
5
+ * Request patch.
6
+ */
7
+ type RequestPatch = {
8
+ host?: string;
9
+ method?: string;
10
+ secure?: boolean;
11
+ path?: string;
12
+ query?: object;
13
+ cookies?: object;
14
+ headers?: object;
15
+ body?: string;
16
+ stream?: Readable;
17
+ encoding?: BufferEncoding;
18
+ };
19
+
20
+ /**
21
+ * Create request mock.
22
+ *
23
+ * @param patch
24
+ */
25
+ export declare function createRequestMock(
26
+ patch?: RequestPatch,
27
+ ): IncomingMessage;
@@ -0,0 +1,17 @@
1
+ import {ServerResponse} from 'http';
2
+
3
+ /**
4
+ * Server response mock.
5
+ */
6
+ export type ServerResponseMock = ServerResponse & {
7
+ _headersSent: boolean;
8
+ _headers: {[name: string]: string | undefined};
9
+ setEncoding(encoding: string): ServerResponseMock;
10
+ getEncoding(): string | undefined;
11
+ getBody(): Promise<string>;
12
+ };
13
+
14
+ /**
15
+ * Create response mock.
16
+ */
17
+ export declare function createResponseMock(): ServerResponseMock;
@@ -0,0 +1,18 @@
1
+ import {Route, HttpMethod} from '../route.js';
2
+ import type {RouteHandler} from '../route.js';
3
+
4
+ /**
5
+ * Route mock options.
6
+ */
7
+ type RouteMockOptions = {
8
+ method?: HttpMethod;
9
+ path?: string;
10
+ handler?: RouteHandler;
11
+ };
12
+
13
+ /**
14
+ * Create route mock.
15
+ *
16
+ * @param options
17
+ */
18
+ export function createRouteMock(options?: RouteMockOptions): Route;
@@ -0,0 +1,26 @@
1
+ import {IncomingMessage} from 'http';
2
+
3
+ /**
4
+ * Character encoding list.
5
+ */
6
+ export const CHARACTER_ENCODING_LIST: (
7
+ | 'ascii'
8
+ | 'utf8'
9
+ | 'utf-8'
10
+ | 'utf16le'
11
+ | 'utf-16le'
12
+ | 'ucs2'
13
+ | 'ucs-2'
14
+ | 'latin1'
15
+ )[];
16
+
17
+ /**
18
+ * Fetch request body.
19
+ *
20
+ * @param request
21
+ * @param bodyBytesLimit
22
+ */
23
+ export declare function fetchRequestBody(
24
+ request: IncomingMessage,
25
+ bodyBytesLimit?: number,
26
+ ): Promise<string>;
@@ -0,0 +1,8 @@
1
+ import {IncomingMessage} from 'http';
2
+
3
+ /**
4
+ * Get request pathname.
5
+ *
6
+ * @param request
7
+ */
8
+ export declare function getRequestPathname(request: IncomingMessage): string;
@@ -0,0 +1,16 @@
1
+ export * from './clone-deep.js';
2
+ export * from './is-promise.js';
3
+ export * from './create-error.js';
4
+ export * from './parse-cookies.js';
5
+ export * from './to-camel-case.js';
6
+ export * from './create-debugger.js';
7
+ export * from './is-response-sent.js';
8
+ export * from './create-route-mock.js';
9
+ export * from './is-readable-stream.js';
10
+ export * from './parse-content-type.js';
11
+ export * from './is-writable-stream.js';
12
+ export * from './fetch-request-body.js';
13
+ export * from './create-request-mock.js';
14
+ export * from './create-response-mock.js';
15
+ export * from './create-cookies-string.js';
16
+ export * from './get-request-pathname.js';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Check whether a value is a Promise-like
3
+ * instance. Recognizes both native promises
4
+ * and third-party promise libraries.
5
+ *
6
+ * @param value
7
+ */
8
+ export declare function isPromise<T = unknown>(
9
+ value: unknown,
10
+ ): value is Promise<T>;
@@ -0,0 +1,9 @@
1
+ import {Readable} from 'stream';
2
+
3
+ /**
4
+ * Check whether a value has a pipe
5
+ * method.
6
+ *
7
+ * @param value
8
+ */
9
+ export declare function isReadableStream(value: unknown): value is Readable;
@@ -0,0 +1,8 @@
1
+ import {ServerResponse} from 'http';
2
+
3
+ /**
4
+ * Is response sent.
5
+ *
6
+ * @param response
7
+ */
8
+ export declare function isResponseSent(response: ServerResponse): boolean;
@@ -0,0 +1,9 @@
1
+ import {Writable} from 'stream';
2
+
3
+ /**
4
+ * Check whether a value has an end
5
+ * method.
6
+ *
7
+ * @param value
8
+ */
9
+ export declare function isWritableStream(value: unknown): value is Writable;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Parsed content type.
3
+ */
4
+ export type ParsedContentType = {
5
+ boundary: string | undefined;
6
+ charset: string | undefined;
7
+ mediaType: string | undefined;
8
+ };
9
+
10
+ /**
11
+ * Parse content type.
12
+ *
13
+ * @param input
14
+ */
15
+ export declare function parseContentType(input: string): ParsedContentType;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Parsed cookies.
3
+ */
4
+ type ParsedCookies = {
5
+ [key: string]: string | undefined;
6
+ };
7
+
8
+ /**
9
+ * Parse cookies.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * parseCookies('pkg=math; equation=E%3Dmc%5E2');
14
+ * // {pkg: 'math', equation: 'E=mc^2'}
15
+ * ```
16
+ *
17
+ * @param input
18
+ */
19
+ export declare function parseCookies(input: string): ParsedCookies;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * To camel case.
3
+ *
4
+ * @param input
5
+ */
6
+ export declare function toCamelCase(input: string): string;
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "target": "es2022",
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "noEmit": true,
8
+ "allowJs": true
9
+ },
10
+ "include": [
11
+ "./src/**/*.ts",
12
+ "./src/**/*.js"
13
+ ]
14
+ }
package/jsconfig.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext"
6
- }
7
- }