@alwatr/nanotron-api-server 4.0.0-alpha.0 → 4.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -1
- package/dist/api-client-request.d.ts +27 -0
- package/dist/api-client-request.d.ts.map +1 -0
- package/dist/api-server-response.d.ts +27 -0
- package/dist/api-server-response.d.ts.map +1 -0
- package/dist/api-server.d.ts +10 -28
- package/dist/api-server.d.ts.map +1 -1
- package/dist/main.cjs +3 -3
- package/dist/main.cjs.map +4 -4
- package/dist/main.d.ts +3 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.mjs +3 -3
- package/dist/main.mjs.map +4 -4
- package/dist/type.d.ts +64 -23
- package/dist/type.d.ts.map +1 -1
- package/dist/url.d.ts +10 -0
- package/dist/url.d.ts.map +1 -0
- package/package.json +2 -2
- package/dist/api-connection.d.ts +0 -36
- package/dist/api-connection.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,56 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## 4.0.0-alpha.0 (2024-09-
|
|
6
|
+
## [4.0.0-alpha.2](https://github.com/Alwatr/nanotron/compare/v4.0.0-alpha.1...v4.0.0-alpha.2) (2024-09-12)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **api-server:** Add NanotronUrl class for handling client request URLs ([3e41fd6](https://github.com/Alwatr/nanotron/commit/3e41fd650869e7bfdb875dccbc221cb3dd083832)) by @AliMD
|
|
11
|
+
|
|
12
|
+
### Code Refactoring
|
|
13
|
+
|
|
14
|
+
* **api-server:** types ([46d7487](https://github.com/Alwatr/nanotron/commit/46d74871631d47e7bc4c4b188367f4543915031f)) by @AliMD
|
|
15
|
+
* **api-server:** Update HttpResponseHeaders interface properties ([3e44a43](https://github.com/Alwatr/nanotron/commit/3e44a433f287c8d4c6fb18ac13cfa58805bb709b)) by @AliMD
|
|
16
|
+
* **api-server:** Update main.ts exports with NanotronClientRequest, NanotronServerResponse, and NanotronUrl types ([c94c954](https://github.com/Alwatr/nanotron/commit/c94c9546927c13b3b72d24522bd1fc46ce4f6163)) by @AliMD
|
|
17
|
+
* **api-server:** Update NanotronClientRequest class ([468d3d9](https://github.com/Alwatr/nanotron/commit/468d3d910342a6963c07de18e9cccc933934a111)) by @AliMD
|
|
18
|
+
* **api-server:** Update NanotronClientRequest class and NanotronServerResponse class ([7b587e0](https://github.com/Alwatr/nanotron/commit/7b587e06dbcf493424dd0bd70de402f14e2e519a)) by @AliMD
|
|
19
|
+
* **api-server:** Update NanotronServerResponse class ([0f47dd7](https://github.com/Alwatr/nanotron/commit/0f47dd7221a67f5a21269f76c60df125ac6e9c93)) by @AliMD
|
|
20
|
+
* **api-server:** Update type.ts with NativeClientRequest and NativeServerResponse types ([e6b62e5](https://github.com/Alwatr/nanotron/commit/e6b62e50b8873fe77eb4bab084581b0c6c0d3c86)) by @AliMD
|
|
21
|
+
|
|
22
|
+
## [4.0.0-alpha.1](https://github.com/Alwatr/nanotron/compare/v4.0.0-alpha.0...v4.0.0-alpha.1) (2024-09-11)
|
|
23
|
+
|
|
24
|
+
### ⚠ BREAKING CHANGES
|
|
25
|
+
|
|
26
|
+
* **api-server:** separate NanotronClientRequest and NanotronServerResponse classes
|
|
27
|
+
|
|
28
|
+
Co-authored-by: Mohammad Honarvar <honarvar.info@gmail.com>
|
|
29
|
+
Co-authored-by: James Sumners <321201+jsumners@users.noreply.github.com>
|
|
30
|
+
Co-authored-by: Frazer Smith <frazer.dev@icloud.com>
|
|
31
|
+
Co-authored-by: Simone Busoli <simone.busoli@gmail.com>
|
|
32
|
+
Co-authored-by: Carlos Fuentes <me@metcoder.dev>
|
|
33
|
+
Co-authored-by: KaKa <23028015+climba03003@users.noreply.github.com>
|
|
34
|
+
|
|
35
|
+
### Features
|
|
36
|
+
|
|
37
|
+
* **api-server:** add `preHandlers_` property ([80a301e](https://github.com/Alwatr/nanotron/commit/80a301e2ef7fb54e681ca7085582ad48bd47e4e2)) by @AliMD
|
|
38
|
+
* **api-server:** Add preHandlers_ and postHandlers_ properties in DefineRouteOption ([d4f3e8c](https://github.com/Alwatr/nanotron/commit/d4f3e8c20bc94ad16585e64afa4012a5a649e5a4)) by @AliMD
|
|
39
|
+
* **api-server:** prevent to run the handlers when `terminatedHandlers` equals `true` ([185bc11](https://github.com/Alwatr/nanotron/commit/185bc114dbdef952823b5b2be72c87bb01f6780e)) by @AliMD
|
|
40
|
+
* **api-server:** Refactor `replyError` method and add `terminatedHandlers` property ([c6f9c69](https://github.com/Alwatr/nanotron/commit/c6f9c69bdbb3b996b5b0b602476a6f88ecfcbfd5)) by @AliMD
|
|
41
|
+
* **api-server:** Update replyError method and add errorHappened property in api-connection.ts ([166c950](https://github.com/Alwatr/nanotron/commit/166c950fcced582bb2aa5fbc55d29798e8e09b91)) by @AliMD
|
|
42
|
+
* **api-server:** Update replyError method in api-connection.ts ([968b024](https://github.com/Alwatr/nanotron/commit/968b02441610f906032b822ac655ac43a9768fdf)) by @AliMD
|
|
43
|
+
|
|
44
|
+
### Bug Fixes
|
|
45
|
+
|
|
46
|
+
* **api-server:** update exports ([8ed905b](https://github.com/Alwatr/nanotron/commit/8ed905b1f85394a4ce1c42c8bde88d13616d687f)) by @AliMD
|
|
47
|
+
|
|
48
|
+
### Code Refactoring
|
|
49
|
+
|
|
50
|
+
* **api-server:** separate NanotronClientRequest and NanotronServerResponse classes ([c207488](https://github.com/Alwatr/nanotron/commit/c2074888809e6b7ea6fc7ffe1d0dec7e0d60de2a)) by @AliMD
|
|
51
|
+
* **api-server:** Separate NanotronClientRequest and NanotronServerResponse classes ([c02d51b](https://github.com/Alwatr/nanotron/commit/c02d51bd7427493aacdc630a7d08c5bda4f54e59)) by @AliMD
|
|
52
|
+
* **api-server:** Update logger name in NanotronApiServer ([6f0a959](https://github.com/Alwatr/nanotron/commit/6f0a959bfd2bf6d5f60fc518c6a916cd255a9bd0)) by @
|
|
53
|
+
* NanotronApiServer to separate NanotronClientRequest and NanotronServerResponse classes ([3116fdf](https://github.com/Alwatr/nanotron/commit/3116fdf6dc93af93a1e3ff47755f431e12efa228)) by @AliMD
|
|
54
|
+
|
|
55
|
+
## [4.0.0-alpha.0](https://github.com/Alwatr/nanotron/compare/v1.2.7...v4.0.0-alpha.0) (2024-09-10)
|
|
7
56
|
|
|
8
57
|
### ⚠ BREAKING CHANGES
|
|
9
58
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { NanotronServerResponse } from './api-server-response.js';
|
|
2
|
+
import type { DefineRouteOption, NativeClientRequest, NativeServerResponse } from './type.js';
|
|
3
|
+
import type { NanotronUrl } from './url.js';
|
|
4
|
+
import type { Dictionary } from '@alwatr/type-helper';
|
|
5
|
+
export declare class NanotronClientRequest {
|
|
6
|
+
readonly url: NanotronUrl;
|
|
7
|
+
readonly serverResponse: NanotronServerResponse;
|
|
8
|
+
readonly routeOption: DefineRouteOption | null;
|
|
9
|
+
/**
|
|
10
|
+
* A flag to indicate if the running handlers queue has been terminated.
|
|
11
|
+
* This can occur due to an error being thrown or by explicitly calling the `replyError` method.
|
|
12
|
+
*
|
|
13
|
+
* When `terminatedHandlers` is set to `true`, it signifies that the execution of the current
|
|
14
|
+
* sequence of handlers (including pre, main, and post handlers) has been halted and no further
|
|
15
|
+
* handlers in the queue will be executed.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* - Check this flag to determine if the handlers queue has been interrupted.
|
|
19
|
+
* - Set this flag to `true` to manually stop the execution of subsequent handlers.
|
|
20
|
+
*/
|
|
21
|
+
terminatedHandlers?: true;
|
|
22
|
+
readonly sharedMeta: Dictionary;
|
|
23
|
+
readonly raw_: NativeClientRequest;
|
|
24
|
+
protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
|
|
25
|
+
constructor(url: NanotronUrl, nativeClientRequest: NativeClientRequest, nativeServerResponse: NativeServerResponse, routeOption: DefineRouteOption | null);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=api-client-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client-request.d.ts","sourceRoot":"","sources":["../src/api-client-request.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAC;AAEhE,OAAO,KAAK,EAAC,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,WAAW,CAAC;AAC5F,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,qBAAqB,CAAC;AAEpD,qBAAa,qBAAqB;IAChC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAE1B,QAAQ,CAAC,cAAc,EAAE,sBAAsB,CAAC;IAEhD,QAAQ,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAE/C;;;;;;;;;;;OAWG;IACH,kBAAkB,CAAC,EAAE,IAAI,CAAC;IAE1B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAM;IAErC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IAEnC,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAC;gBAGzB,GAAG,EAAE,WAAW,EAChB,mBAAmB,EAAE,mBAAmB,EACxC,oBAAoB,EAAE,oBAAoB,EAC1C,WAAW,EAAE,iBAAiB,GAAG,IAAI;CAcxC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type HttpStatusCode } from './const.js';
|
|
2
|
+
import type { NanotronClientRequest } from './api-client-request.js';
|
|
3
|
+
import type { HttpResponseHeaders, ErrorResponse, NativeServerResponse } from './type.js';
|
|
4
|
+
import type { Json } from '@alwatr/type-helper';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the Nanotron Api Server Response.
|
|
7
|
+
*/
|
|
8
|
+
export interface NanotronServerResponseConfig {
|
|
9
|
+
clientRequest: NanotronClientRequest;
|
|
10
|
+
}
|
|
11
|
+
export declare class NanotronServerResponse {
|
|
12
|
+
readonly clientRequest: NanotronClientRequest;
|
|
13
|
+
readonly raw_: NativeServerResponse;
|
|
14
|
+
readonly headers: HttpResponseHeaders;
|
|
15
|
+
protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
|
|
16
|
+
protected hasBeenSent_: boolean;
|
|
17
|
+
get hasBeenSent(): boolean;
|
|
18
|
+
constructor(nanotronClientRequest: NanotronClientRequest, nativeServerResponse: NativeServerResponse);
|
|
19
|
+
get statusCode(): HttpStatusCode;
|
|
20
|
+
set statusCode(value: HttpStatusCode);
|
|
21
|
+
protected applyHeaders_(): void;
|
|
22
|
+
replyErrorResponse(errorResponse: ErrorResponse): void;
|
|
23
|
+
replyError(error?: Error | string | Json | unknown): void;
|
|
24
|
+
replyJson(responseJson: Json): void;
|
|
25
|
+
reply(context: string | Buffer): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=api-server-response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-server-response.d.ts","sourceRoot":"","sources":["../src/api-server-response.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,cAAc,EAAsC,MAAM,YAAY,CAAC;AAEpF,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAC,mBAAmB,EAAE,aAAa,EAAE,oBAAoB,EAAC,MAAM,WAAW,CAAC;AACxF,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,qBAAqB,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,qBAAqB,CAAC;CACtC;AAED,qBAAa,sBAAsB;IACjC,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;IAE9C,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAEpC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IAEtC,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAC;IAE3B,SAAS,CAAC,YAAY,UAAS;IAC/B,IAAI,WAAW,IAAI,OAAO,CAEzB;gBAEW,qBAAqB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,oBAAoB;IAgBpG,IAAI,UAAU,IAAI,cAAc,CAE/B;IAED,IAAI,UAAU,CAAC,KAAK,EAAE,cAAc,EAEnC;IAED,SAAS,CAAC,aAAa;IAOvB,kBAAkB,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI;IAMtD,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI;IAoCzD,SAAS,CAAC,YAAY,EAAE,IAAI,GAAG,IAAI;IAqBnC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAmCtC"}
|
package/dist/api-server.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import type { HttpMethod, MatchType, RouteHandler } from './type.js';
|
|
1
|
+
import { NanotronUrl } from './url.js';
|
|
2
|
+
import type { DefineRouteOption, MatchType, NativeClientRequest, NativeServerResponse } from './type.js';
|
|
4
3
|
import type { Dictionary } from '@alwatr/type-helper';
|
|
5
4
|
import type { Duplex } from 'node:stream';
|
|
6
5
|
/**
|
|
@@ -57,33 +56,16 @@ export interface NanotronApiServerConfig {
|
|
|
57
56
|
* @default '/api/'
|
|
58
57
|
*/
|
|
59
58
|
prefix?: `/${string}/` | '/';
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Configuration options for defining a route.
|
|
63
|
-
*/
|
|
64
|
-
export interface DefineRouteOption {
|
|
65
|
-
/**
|
|
66
|
-
* The HTTP method for this route.
|
|
67
|
-
*/
|
|
68
|
-
method: HttpMethod;
|
|
69
|
-
/**
|
|
70
|
-
* The URL path for this route.
|
|
71
|
-
*/
|
|
72
|
-
url: string;
|
|
73
|
-
/**
|
|
74
|
-
* The function to handle requests to this route.
|
|
75
|
-
*/
|
|
76
|
-
handler: RouteHandler;
|
|
77
59
|
/**
|
|
78
|
-
*
|
|
60
|
+
* The maximum size of the request body in bytes.
|
|
79
61
|
*
|
|
80
|
-
* @default
|
|
62
|
+
* @default `1_048_576` (1MiB)
|
|
81
63
|
*/
|
|
82
|
-
|
|
64
|
+
bodyLimit?: number;
|
|
83
65
|
}
|
|
84
66
|
export declare class NanotronApiServer {
|
|
85
67
|
protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>>;
|
|
86
|
-
|
|
68
|
+
readonly config_: {
|
|
87
69
|
port: number;
|
|
88
70
|
host: string;
|
|
89
71
|
requestTimeout: number;
|
|
@@ -92,18 +74,18 @@ export declare class NanotronApiServer {
|
|
|
92
74
|
healthRoute: boolean;
|
|
93
75
|
allowAllOrigin: boolean;
|
|
94
76
|
prefix: `/${string}/` | "/";
|
|
77
|
+
bodyLimit: number;
|
|
95
78
|
};
|
|
96
79
|
protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
|
|
97
|
-
readonly httpServer: import("http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
80
|
+
readonly httpServer: import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
|
|
98
81
|
protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;
|
|
99
82
|
constructor(config?: Partial<NanotronApiServerConfig>);
|
|
100
83
|
close(): void;
|
|
101
|
-
protected getRouteOption_(
|
|
84
|
+
protected getRouteOption_(url: NanotronUrl): Required<DefineRouteOption> | null;
|
|
102
85
|
protected setRouteOption_(option: Required<DefineRouteOption>): void;
|
|
103
86
|
defineRoute(option: DefineRouteOption): void;
|
|
104
87
|
protected handleServerError_(err: NodeJS.ErrnoException): void;
|
|
105
88
|
protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void;
|
|
106
|
-
protected
|
|
107
|
-
protected handleIncomingRequest_(incomingMessage: IncomingMessage, serverResponse: ServerResponse): Promise<void>;
|
|
89
|
+
protected handleClientRequest_(nativeClientRequest: NativeClientRequest, nativeServerResponse: NativeServerResponse): Promise<void>;
|
|
108
90
|
}
|
|
109
91
|
//# sourceMappingURL=api-server.d.ts.map
|
package/dist/api-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-server.d.ts","sourceRoot":"","sources":["../src/api-server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api-server.d.ts","sourceRoot":"","sources":["../src/api-server.ts"],"names":[],"mappings":"AAMA,OAAO,EAAC,WAAW,EAAC,MAAM,UAAU,CAAC;AAErC,OAAO,KAAK,EAAC,iBAAiB,EAAE,SAAS,EAAE,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,WAAW,CAAC;AACvG,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;IAE7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,iBAAiB;IAC5B,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAUnF;IAEF,QAAQ,CAAC,OAAO;cA1ET,MAAM;cAON,MAAM;wBAOI,MAAM;wBASN,MAAM;0BAOJ,MAAM;qBAOX,OAAO;wBAOJ,OAAO;gBAOf,IAAI,MAAM,GAAG,GAAG,GAAG;mBAOhB,MAAM;MAgBD;IACjB,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAC;IAE3B,QAAQ,CAAC,UAAU,qGAAC;IAEpB,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;gBAElG,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC;IA+CrD,KAAK,IAAI,IAAI;IAKb,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAuB/E,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAepE,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAY5C,SAAS,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI;IAS9D,SAAS,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;cAQ9D,oBAAoB,CAClC,mBAAmB,EAAE,mBAAmB,EACxC,oBAAoB,EAAE,oBAAoB,GACzC,OAAO,CAAC,IAAI,CAAC;CAiDjB"}
|
package/dist/main.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/* @alwatr/nanotron-api-server v4.0.0-alpha.
|
|
2
|
-
"use strict";var
|
|
1
|
+
/* @alwatr/nanotron-api-server v4.0.0-alpha.2 */
|
|
2
|
+
"use strict";var u=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var N=(i,e)=>{for(var t in e)u(i,t,{get:e[t],enumerable:!0})},q=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of v(e))!S.call(i,s)&&s!==t&&u(i,s,{get:()=>e[s],enumerable:!(r=C(e,s))||r.enumerable});return i};var T=i=>q(u({},"__esModule",{value:!0}),i);var M={};N(M,{HttpMethods:()=>w,HttpStatusCodes:()=>n,HttpStatusMessages:()=>c,NanotronApiServer:()=>g});module.exports=T(M);var w={GET:"GET",HEAD:"HEAD",POST:"POST",PUT:"PUT",DELETE:"DELETE",CONNECT:"CONNECT",OPTIONS:"OPTIONS",TRACE:"TRACE",PATCH:"PATCH"},n={Info_100_Continue:100,Info_101_Switching_Protocols:101,Info_102_Processing:102,Info_103_Early_Hints:103,Success_200_OK:200,Success_201_Created:201,Success_202_Accepted:202,Success_203_Non_Authoritative_Information:203,Success_204_No_Content:204,Success_205_Reset_Content:205,Success_206_Partial_Content:206,Success_207_Multi_Status:207,Success_208_Already_Reported:208,Success_226_IM_Used:226,Redirect_300_Multiple_Choices:300,Redirect_301_Moved_Permanently:301,Redirect_302_Found:302,Redirect_303_See_Other:303,Redirect_304_Not_Modified:304,Redirect_305_Use_Proxy:305,Redirect_306_Switch_Proxy:306,Redirect_307_Temporary_Redirect:307,Redirect_308_Permanent_Redirect:308,Error_Client_400_Bad_Request:400,Error_Client_401_Unauthorized:401,Error_Client_402_Payment_Required:402,Error_Client_403_Forbidden:403,Error_Client_404_Not_Found:404,Error_Client_405_Method_Not_Allowed:405,Error_Client_406_Not_Acceptable:406,Error_Client_407_Proxy_Authentication_Required:407,Error_Client_408_Request_Timeout:408,Error_Client_409_Conflict:409,Error_Client_410_Gone:410,Error_Client_411_Length_Required:411,Error_Client_412_Precondition_Failed:412,Error_Client_413_Payload_Too_Large:413,Error_Client_414_URI_Too_Long:414,Error_Client_415_Unsupported_Media_Type:415,Error_Client_416_Range_Not_Satisfiable:416,Error_Client_417_Expectation_Failed:417,Error_Client_421_Misdirected_Request:421,Error_Client_422_Unprocessable_Entity:422,Error_Client_423_Locked:423,Error_Client_424_Failed_Dependency:424,Error_Client_425_Too_Early:425,Error_Client_426_Upgrade_Required:426,Error_Client_428_Precondition_Required:428,Error_Client_429_Too_Many_Requests:429,Error_Client_431_Request_Header_Fields_Too_Large:431,Error_Client_451_Unavailable_For_Legal_Reasons:451,Error_Server_500_Internal_Server_Error:500,Error_Server_501_Not_Implemented:501,Error_Server_502_Bad_Gateway:502,Error_Server_503_Service_Unavailable:503,Error_Server_504_Gateway_Timeout:504,Error_Server_505_HTTP_Version_Not_Supported:505,Error_Server_506_Variant_Also_Negotiates:506,Error_Server_507_Insufficient_Storage:507,Error_Server_508_Loop_Detected:508,Error_Server_510_Not_Extended:510,Error_Server_511_Network_Authentication_Required:511},c={100:"Continue",101:"Switching Protocols",102:"Processing",103:"Early Hints",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",208:"Already Reported",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",308:"Permanent Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Payload Too Large",414:"URI Too Long",415:"Unsupported Media Type",416:"Range Not Satisfiable",417:"Expectation Failed",418:"I'm a Teapot",421:"Misdirected Request",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",425:"Too Early",426:"Upgrade Required",428:"Precondition Required",429:"Too Many Requests",431:"Request Header Fields Too Large",451:"Unavailable For Legal Reasons",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",508:"Loop Detected",509:"Bandwidth Limit Exceeded",510:"Not Extended",511:"Network Authentication Required"};var f=require("@alwatr/logger"),_=class{constructor(e,t){this.hasBeenSent_=!1;this.clientRequest=e,this.raw_=t,this.logger_=(0,f.createLogger)("nt-server-response"),this.logger_.logMethodArgs?.("new",this.clientRequest.url.debugId),this.headers={server:"Alwatr Nanotron","content-type":"text/plain"}}get hasBeenSent(){return this.hasBeenSent_}get statusCode(){return this.raw_.statusCode}set statusCode(e){this.raw_.statusCode=e}applyHeaders_(){this.logger_.logMethodArgs?.("applyHeaders_",this.headers);for(let e in this.headers)this.raw_.setHeader(e,this.headers[e])}replyErrorResponse(e){this.logger_.logMethod?.("replyErrorResponse"),this.clientRequest.terminatedHandlers=!0,this.replyJson(e)}replyError(e){this.logger_.logMethodArgs?.("replyError",{error:e}),this.clientRequest.terminatedHandlers=!0;let t=this.statusCode;t<n.Error_Client_400_Bad_Request&&(this.statusCode=t=500),e instanceof Error?this.replyJson({ok:!1,errorCode:e.name==="Error"?"error_"+t:(e.name+"").toLowerCase(),errorMessage:e.message}):typeof e=="string"?this.replyJson({ok:!1,errorCode:"error_"+t,errorMessage:e}):typeof e=="object"&&e!==null?this.replyJson(e):this.replyJson({ok:!1,errorCode:"error_"+t,errorMessage:c[t]})}replyJson(e){this.logger_.logMethodArgs?.("replyJson",{responseJson:e});let t;try{t=JSON.stringify(e)}catch(r){this.logger_.error("replyJson","reply_json_stringify_failed",r,this.clientRequest.url.debugId),this.statusCode=n.Error_Server_500_Internal_Server_Error,t=JSON.stringify({ok:!1,errorCode:"reply_json_stringify_failed",errorMessage:"Failed to stringify response JSON."})}this.headers["content-type"]="application/json",this.reply(t)}reply(e){if(this.logger_.logMethodArgs?.("reply",this.clientRequest.url.debugId),this.raw_.writableFinished&&this.hasBeenSent_===!1&&(this.logger_.accident("reply","server_response_writable_finished_directly"),this.hasBeenSent_=!0),this.hasBeenSent_){this.logger_.accident("reply","reply_already_sent",{url:this.clientRequest.url.debugId,replySent:this.hasBeenSent_,writableFinished:this.raw_.writableFinished});return}this.hasBeenSent_=!0;try{typeof e=="string"&&(e=Buffer.from(e)),this.headers["content-length"]=e.byteLength,this.applyHeaders_(),this.raw_.end(e,"binary")}catch(t){this.logger_.error("reply","server_response_error",t,this.clientRequest.url.debugId),this.hasBeenSent_=!1}}};var y=require("@alwatr/logger"),l=class{constructor(e,t,r,s){this.sharedMeta={};this.raw_=t,this.url=e,this.routeOption=s,this.logger_=(0,y.createLogger)("nt-client-request"),this.logger_.logMethodArgs?.("new",e.debugId),this.serverResponse=new _(this,r)}};var R=require("node:url"),h=class h extends R.URL{constructor(e,t){let r=e.url??"";t!=="/"&&r.indexOf(t)===0&&(r=r.slice(t.length-1)),r=r.replace(h.versionPattern_,"/"),super(r,"http://hostname/"),this.method=(e.method??"GET").toUpperCase(),this.debugId=`[${this.method}]${this.pathname}`}};h.versionPattern_=new RegExp("^/v[0-9]+/");var d=h;var m=require("node:http"),E=require("@alwatr/logger"),p=class p{constructor(e){this.config_={...p.defaultConfig_,...e},this.logger_=(0,E.createLogger)("nt-api-server"+(this.config_.port!==80?":"+this.config_.port:"")),this.logger_.logMethodArgs?.("new",{config:this.config_}),this.handleClientRequest_=this.handleClientRequest_.bind(this),this.handleServerError_=this.handleServerError_.bind(this),this.handleClientError_=this.handleClientError_.bind(this),this.e={exact:{},startsWith:{}},this.httpServer=(0,m.createServer)({keepAlive:!0,keepAliveInitialDelay:0,noDelay:!0},this.handleClientRequest_),this.httpServer.requestTimeout=this.config_.requestTimeout,this.httpServer.keepAliveTimeout=this.config_.keepAliveTimeout,this.httpServer.headersTimeout=this.config_.headersTimeout,this.httpServer.listen(this.config_.port,this.config_.host,()=>{this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`)}),this.httpServer.on("error",this.handleServerError_),this.httpServer.on("clientError",this.handleClientError_)}close(){this.logger_.logMethod?.("close"),this.httpServer.close()}getRouteOption_(e){if(this.logger_.logMethod?.("getRouteOption_"),Object.hasOwn(this.e.exact,e.method)&&Object.hasOwn(this.e.exact[e.method],e.pathname))return this.e.exact[e.method][e.pathname];if(Object.hasOwn(this.e.startsWith,e.method)){let t=this.e.startsWith[e.method];for(let r in t)if(r.indexOf(e.pathname)===0)return t[r]}return this.logger_.incident?.("getRouteOption_","route_not_found",{method:e.method,url:e.pathname}),null}setRouteOption_(e){var r;this.logger_.logMethodArgs?.("setRouteOption_",{...e,handler:"function"});let t=this.e[e.matchType];if(t[r=e.method]??(t[r]={}),Object.hasOwn(t[e.method],e.url))throw this.logger_.error("defineRoute","route_already_exists",{...e,handler:"function"}),new Error("route_already_exists");t[e.method][e.url]=e}defineRoute(e){let t={matchType:"exact",preHandlers:[],postHandlers:[],bodyLimit:this.config_.bodyLimit,...e};this.logger_.logMethodArgs?.("defineRoute",{...t,handler:"function"}),this.setRouteOption_(t)}handleServerError_(e){e.code==="EADDRINUSE"?this.logger_.error("handleServerError_","address_in_use",e):this.logger_.error("handleServerError_","http_server_error",e.message||"HTTP server catch an error",e)}handleClientError_(e,t){this.logger_.accident("handleClientError_","http_server_client_error",{errCode:e.code,errMessage:e.message}),t.end(`HTTP/1.1 400 Bad Request\r
|
|
3
3
|
\r
|
|
4
|
-
`)}
|
|
4
|
+
`)}async handleClientRequest_(e,t){if(this.logger_.logMethod?.("handleClientRequest_"),e.url===void 0){this.logger_.accident("handleClientRequest_","http_server_url_undefined");return}if(e.method===void 0){this.logger_.accident("handleClientRequest_","http_server_method_undefined");return}let r=new d(e,this.config_.prefix),s=this.getRouteOption_(r),o=new l(r,e,t,s);if(s===null){o.serverResponse.statusCode=n.Error_Client_404_Not_Found,o.serverResponse.replyError();return}try{for(let a of s.preHandlers){if(o.terminatedHandlers===!0)return;await a(o,o.serverResponse,o.sharedMeta)}await s.handler(o,o.serverResponse,o.sharedMeta);for(let a of s.postHandlers){if(o.terminatedHandlers===!0)return;await a(o,o.serverResponse,o.sharedMeta)}}catch(a){this.logger_.error("handleClientRequest_","route_handler_error",a,r.debugId),o.serverResponse.statusCode<n.Error_Client_400_Bad_Request&&(o.serverResponse.statusCode=n.Error_Server_500_Internal_Server_Error),o.serverResponse.replyError(a)}}};p.defaultConfig_={host:"0.0.0.0",port:80,requestTimeout:1e4,headersTimeout:13e4,keepAliveTimeout:12e4,healthRoute:!0,allowAllOrigin:!1,prefix:"/api/",bodyLimit:1048576};var g=p;0&&(module.exports={HttpMethods,HttpStatusCodes,HttpStatusMessages,NanotronApiServer});
|
|
5
5
|
//# sourceMappingURL=main.cjs.map
|
package/dist/main.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/main.ts", "../src/const.ts", "../src/api-
|
|
4
|
-
"sourcesContent": ["export * from './api-server.js';\nexport * from './api-connection.js';\nexport * from './type.js';\nexport * from './const.js';\n", "/**\n * Object representing standard HTTP methods.\n */\nexport const HttpMethods = {\n /**\n * GET: Requests a representation of the specified resource.\n */\n GET: 'GET',\n\n /**\n * HEAD: Asks for a response identical to that of a GET request, but without the response body.\n */\n HEAD: 'HEAD',\n\n /**\n * POST: Submits data to be processed (e.g., from an HTML form) to the identified resource.\n */\n POST: 'POST',\n\n /**\n * PUT: Uploads a representation of the specified URI.\n */\n PUT: 'PUT',\n\n /**\n * DELETE: Deletes the specified resource.\n */\n DELETE: 'DELETE',\n\n /**\n * CONNECT: Establishes a tunnel to the server identified by the target resource.\n */\n CONNECT: 'CONNECT',\n\n /**\n * OPTIONS: Describes the communication options for the target resource.\n */\n OPTIONS: 'OPTIONS',\n\n /**\n * TRACE: Performs a message loop-back test along the path to the target resource.\n */\n TRACE: 'TRACE',\n\n /**\n * PATCH: Applies partial modifications to a resource.\n */\n PATCH: 'PATCH'\n} as const;\n\n/**\n * Object representing standard HTTP status codes.\n */\nexport const HttpStatusCodes = {\n /**\n * 100 Continue: The server has received the request headers and the client should proceed to send the request body.\n */\n Info_100_Continue: 100,\n\n /**\n * 101 Switching Protocols: The server understands and is willing to comply with the clients request to switch protocols.\n */\n Info_101_Switching_Protocols: 101,\n\n /**\n * 102 Processing: The server has received and is processing the request, but no response is available yet.\n */\n Info_102_Processing: 102,\n\n /**\n * 103 Early Hints: The server is sending some response headers before the final HTTP message.\n */\n Info_103_Early_Hints: 103,\n\n /**\n * 200 OK: The request has succeeded.\n */\n Success_200_OK: 200,\n\n /**\n * 201 Created: The request has been fulfilled and resulted in a new resource being created.\n */\n Success_201_Created: 201,\n\n /**\n * 202 Accepted: The request has been accepted for processing, but the processing has not been completed.\n */\n Success_202_Accepted: 202,\n\n /**\n * 203 Non-Authoritative Information: The server is a transforming proxy that received a 200 OK\n * from the origin server but is returning a modified version of the origins response.\n */\n Success_203_Non_Authoritative_Information: 203,\n\n /**\n * 204 No Content: The server successfully processed the request and is not returning any content.\n */\n Success_204_No_Content: 204,\n\n /**\n * 205 Reset Content: The server successfully processed the request,\n * asks that the client reset its document view, and is not returning any content.\n */\n Success_205_Reset_Content: 205,\n\n /**\n * 206 Partial Content: The server is delivering only part of the resource due to a range header sent by the client.\n */\n Success_206_Partial_Content: 206,\n\n /**\n * 207 Multi-Status: The message body that follows is an XML message\n * and can contain a number of separate response codes, depending on how many sub-requests were made.\n */\n Success_207_Multi_Status: 207,\n\n /**\n * 208 Already Reported: The members of a DAV binding have already been enumerated\n * in a preceding part of the (multi-status) response, and are not being included again.\n */\n Success_208_Already_Reported: 208,\n\n /**\n * 226 IM Used: The server has fulfilled a request for the resource, and the response is a representation\n * of the result of one or more instance-manipulations applied to the current instance.\n */\n Success_226_IM_Used: 226,\n\n /**\n * 300 Multiple Choices: The request has more than one possible response.\n */\n Redirect_300_Multiple_Choices: 300,\n\n /**\n * 301 Moved Permanently: The URL of the requested resource has been changed permanently.\n */\n Redirect_301_Moved_Permanently: 301,\n\n /**\n * 302 Found: The URL of the requested resource has been changed temporarily.\n */\n Redirect_302_Found: 302,\n\n /**\n * 303 See Other: The response to the request can be found under another URI using a GET method.\n */\n Redirect_303_See_Other: 303,\n\n /**\n * 304 Not Modified: The resource has not been modified since the version specified\n * by the request headers If-Modified-Since or If-None-Match.\n */\n Redirect_304_Not_Modified: 304,\n\n /**\n * 305 Use Proxy: The requested resource is only available through a proxy, the address for which is provided in the response.\n */\n Redirect_305_Use_Proxy: 305,\n\n /**\n * 306 Switch Proxy: No longer used. Originally meant \"Subsequent requests should use the specified proxy.\"\n */\n Redirect_306_Switch_Proxy: 306,\n\n /**\n * 307 Temporary Redirect: The server sends this response to direct the client\n * to get the requested resource at another URI with the same method that was used in the prior request.\n */\n Redirect_307_Temporary_Redirect: 307,\n\n /**\n * 308 Permanent Redirect: This means that the resource is now permanently located at another URI,\n * specified by the Location: HTTP Response header.\n */\n Redirect_308_Permanent_Redirect: 308,\n\n /**\n * 400 Bad Request: The server cannot or will not process the request due to something that is perceived to be a client error.\n */\n Error_Client_400_Bad_Request: 400,\n\n /**\n * 401 Unauthorized: The request has not been applied because it lacks valid authentication credentials for the target resource.\n */\n Error_Client_401_Unauthorized: 401,\n\n /**\n * 402 Payment Required: Reserved for future use.\n */\n Error_Client_402_Payment_Required: 402,\n\n /**\n * 403 Forbidden: The client does not have access rights to the content, so the server is refusing to give the requested resource.\n */\n Error_Client_403_Forbidden: 403,\n\n /**\n * 404 Not Found: The server can not find the requested resource.\n */\n Error_Client_404_Not_Found: 404,\n\n /**\n * 405 Method Not Allowed: The request method is known by the server but is not supported by the target resource.\n */\n Error_Client_405_Method_Not_Allowed: 405,\n\n /**\n * 406 Not Acceptable: The target resource does not have a current representation that would be acceptable\n * to the user agent, according to the proactive negotiation header fields received in the request,\n * and the server is unwilling to supply a default representation.\n */\n Error_Client_406_Not_Acceptable: 406,\n\n /**\n * 407 Proxy Authentication Required: Similar to 401 Unauthorized,\n * but it indicates that the client needs to authenticate itself in order to use a proxy.\n */\n Error_Client_407_Proxy_Authentication_Required: 407,\n\n /**\n * 408 Request Timeout: The server timed out waiting for the request.\n */\n Error_Client_408_Request_Timeout: 408,\n\n /**\n * 409 Conflict: The request could not be processed because of conflict in the request, such as an edit conflict.\n */\n Error_Client_409_Conflict: 409,\n\n /**\n * 410 Gone: The requested resource is no longer available and will not be available again.\n */\n Error_Client_410_Gone: 410,\n\n /**\n * 411 Length Required: The server refuses to accept the request without a defined Content-Length header.\n */\n Error_Client_411_Length_Required: 411,\n\n /**\n * 412 Precondition Failed: One or more conditions given in the request header fields evaluated to false when tested on the server.\n */\n Error_Client_412_Precondition_Failed: 412,\n\n /**\n * 413 Payload Too Large: The server is refusing to process a request because the request payload is larger\n * than the server is willing or able to process.\n */\n Error_Client_413_Payload_Too_Large: 413,\n\n /**\n * 414 URI Too Long: The server is refusing to service the request because the URI is longer than the server is willing to interpret.\n */\n Error_Client_414_URI_Too_Long: 414,\n\n /**\n * 415 Unsupported Media Type: The server is refusing to service the request\n * because the entity of the request is in a format not supported by the requested resource for the requested method.\n */\n Error_Client_415_Unsupported_Media_Type: 415,\n\n /**\n * 416 Range Not Satisfiable: The client has asked for a portion of the file, but the server cannot supply that portion.\n */\n Error_Client_416_Range_Not_Satisfiable: 416,\n\n /**\n * 417 Expectation Failed: The server cannot meet the requirements of the Expect request-header field.\n */\n Error_Client_417_Expectation_Failed: 417,\n\n /**\n * 421 Misdirected Request: The request was directed at a server that is not able to produce a response.\n */\n Error_Client_421_Misdirected_Request: 421,\n\n /**\n * 422 Unprocessable Entity: The request was well-formed but was unable to be followed due to semantic errors.\n */\n Error_Client_422_Unprocessable_Entity: 422,\n\n /**\n * 423 Locked: The resource that is being accessed is locked.\n */\n Error_Client_423_Locked: 423,\n\n /**\n * 424 Failed Dependency: The request failed due to a failure of a previous request.\n */\n Error_Client_424_Failed_Dependency: 424,\n\n /**\n * 425 Too Early: The server is unwilling to risk processing a request that might be replayed.\n */\n Error_Client_425_Too_Early: 425,\n\n /**\n * 426 Upgrade Required: The server refuses to perform the request using the current protocol\n * but might be willing to do so after the client upgrades to a different protocol.\n */\n Error_Client_426_Upgrade_Required: 426,\n\n /**\n * 428 Precondition Required: The origin server requires the request to be conditional.\n */\n Error_Client_428_Precondition_Required: 428,\n\n /**\n * 429 Too Many Requests: The user has sent too many requests in a given amount of time (\"rate limiting\").\n */\n Error_Client_429_Too_Many_Requests: 429,\n\n /**\n * 431 Request Header Fields Too Large: The server is unwilling to process the request because its header fields are too large.\n */\n Error_Client_431_Request_Header_Fields_Too_Large: 431,\n\n /**\n * 451 Unavailable For Legal Reasons: The user requests an illegal resource, such as a web page censored by a government.\n */\n Error_Client_451_Unavailable_For_Legal_Reasons: 451,\n\n /**\n * 500 Internal Server Error: A generic error message, given when no more specific message is suitable.\n */\n Error_Server_500_Internal_Server_Error: 500,\n\n /**\n * 501 Not Implemented: The server either does not recognize the request method, or it lacks the ability to fulfill the request.\n */\n Error_Server_501_Not_Implemented: 501,\n\n /**\n * 502 Bad Gateway: The server was acting as a gateway or proxy and received an invalid response from the upstream server.\n */\n Error_Server_502_Bad_Gateway: 502,\n\n /**\n * 503 Service Unavailable: The server is currently unavailable (because it is overloaded or down for maintenance).\n */\n Error_Server_503_Service_Unavailable: 503,\n\n /**\n * 504 Gateway Timeout: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.\n */\n Error_Server_504_Gateway_Timeout: 504,\n\n /**\n * 505 HTTP Version Not Supported: The server does not support the HTTP protocol version used in the request.\n */\n Error_Server_505_HTTP_Version_Not_Supported: 505,\n\n /**\n * 506 Variant Also Negotiates: Transparent content negotiation for the request results in a circular reference.\n */\n Error_Server_506_Variant_Also_Negotiates: 506,\n\n /**\n * 507 Insufficient Storage: The server is unable to store the representation needed to complete the request.\n */\n Error_Server_507_Insufficient_Storage: 507,\n\n /**\n * 508 Loop Detected: The server detected an infinite loop while processing the request.\n */\n Error_Server_508_Loop_Detected: 508,\n\n /**\n * 510 Not Extended: Further extensions to the request are required for the server to fulfill it.\n */\n Error_Server_510_Not_Extended: 510,\n\n /**\n * 511 Network Authentication Required: The client needs to authenticate to gain network access.\n */\n Error_Server_511_Network_Authentication_Required: 511\n} as const;\n\nexport const HttpStatusMessages = {\n 100: 'Continue',\n 101: 'Switching Protocols',\n 102: 'Processing',\n 103: 'Early Hints',\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 203: 'Non-Authoritative Information',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 207: 'Multi-Status',\n 208: 'Already Reported',\n 226: 'IM Used',\n 300: 'Multiple Choices',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 305: 'Use Proxy',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 407: 'Proxy Authentication Required',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 417: 'Expectation Failed',\n 418: 'I\\'m a Teapot',\n 421: 'Misdirected Request',\n 422: 'Unprocessable Entity',\n 423: 'Locked',\n 424: 'Failed Dependency',\n 425: 'Too Early',\n 426: 'Upgrade Required',\n 428: 'Precondition Required',\n 429: 'Too Many Requests',\n 431: 'Request Header Fields Too Large',\n 451: 'Unavailable For Legal Reasons',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n 506: 'Variant Also Negotiates',\n 507: 'Insufficient Storage',\n 508: 'Loop Detected',\n 509: 'Bandwidth Limit Exceeded',\n 510: 'Not Extended',\n 511: 'Network Authentication Required',\n};\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessages;\n", "import {createLogger} from '@alwatr/logger';\n\nimport {type HttpStatusCode, HttpStatusCodes, HttpStatusMessages} from './const.js';\n\nimport type {HttpResponseHeaders, HttpMethod, ErrorResponse} from './type.js';\nimport type {Json} from '@alwatr/type-helper';\nimport type {IncomingMessage, ServerResponse} from 'node:http';\n\n/**\n * Configuration options for the NanotronApiConnection.\n */\nexport interface NanotronApiConnectionConfig {\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix: `/${string}/` | '/';\n}\n\nexport class NanotronApiConnection {\n protected static versionPattern_ = new RegExp('^/v[0-9]+/');\n\n readonly url;\n\n readonly method;\n\n protected readonly logger_;\n\n readonly replyHeaders: HttpResponseHeaders;\n\n protected replySent_ = false;\n get replySent(): boolean {\n return this.replySent_;\n }\n\n constructor(\n public incomingMessage: IncomingMessage,\n public serverResponse: ServerResponse,\n protected config_: NanotronApiConnectionConfig,\n ) {\n // Create logger.\n this.logger_ = createLogger('nanotron-api-connection'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', {method: incomingMessage.method, url: incomingMessage.url});\n\n // Parse request method.\n this.method = (this.incomingMessage.method ?? 'GET').toUpperCase() as HttpMethod;\n\n // Parse request URL.\n let url = this.incomingMessage.url ?? '';\n if (this.config_.prefix !== '/' && url.indexOf(this.config_.prefix) === 0) {\n url = url.slice(this.config_.prefix.length - 1);\n }\n url = url.replace(NanotronApiConnection.versionPattern_, '/');\n this.url = new URL(url, 'http://hostname/');\n\n // Set default reply headers.\n this.replyHeaders = {\n server: 'Alwatr Nanotron',\n 'content-type': 'text/plain',\n };\n }\n\n get replyStatusCode(): HttpStatusCode {\n return this.serverResponse.statusCode as HttpStatusCode;\n }\n\n set replyStatusCode(value: HttpStatusCode) {\n this.serverResponse.statusCode = value;\n }\n\n protected applyReplyHeaders_() {\n this.logger_.logMethodArgs?.('applyReplyHeaders_', this.replyHeaders);\n for (const key in this.replyHeaders) {\n this.serverResponse.setHeader(key, this.replyHeaders[key as Lowercase<string>]!);\n }\n }\n\n replyJsonError(errorResponse: ErrorResponse): void {\n this.logger_.logMethodArgs?.('replyJsonError', {errorResponse});\n this.replyJson(errorResponse);\n }\n\n replyJson(responseJson: Json): void {\n this.logger_.logMethodArgs?.('replyJson', {responseJson});\n\n let responseString: string;\n try {\n responseString = JSON.stringify(responseJson);\n }\n catch (error) {\n this.logger_.error('replyJson', 'reply_json_stringify_failed', error, {\n url: this.url.pathname,\n method: this.method,\n });\n this.replyStatusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n responseString = JSON.stringify({\n ok: false,\n errorCode: 'reply_json_stringify_failed',\n errorMessage: 'Failed to stringify response JSON.',\n } as ErrorResponse);\n }\n\n this.replyHeaders['content-type'] = 'application/json';\n this.reply(responseString);\n }\n\n replyError(error?: Error | unknown): void {\n this.logger_.logMethodArgs?.('replyError', {error});\n\n const statusCode = this.replyStatusCode;\n\n if (error === undefined || error instanceof Error === false) {\n this.replyJson({\n ok: false,\n errorCode: ('error_' + statusCode) as Lowercase<string>,\n errorMessage: HttpStatusMessages[statusCode]\n } as ErrorResponse);\n return;\n }\n\n this.replyJson({\n ok: false,\n errorCode: error.name,\n errorMessage: error.message,\n });\n }\n\n reply(context: string | Buffer): void {\n this.logger_.logMethodArgs?.('reply', {url: this.url.pathname, method: this.method});\n\n if (this.replySent_ || this.serverResponse.writableFinished) {\n this.logger_.accident('reply', 'reply_already_sent', {\n url: this.url.pathname,\n method: this.method,\n replySent: this.replySent_,\n writableFinished: this.serverResponse.writableFinished,\n });\n return;\n }\n\n try {\n if (typeof context === 'string') {\n context = Buffer.from(context);\n }\n\n this.replyHeaders['content-length'] = context.byteLength;\n\n this.applyReplyHeaders_();\n this.serverResponse.end(context, 'binary');\n\n this.replySent_ = true;\n }\n catch (error) {\n this.logger_.error('reply', 'server_response_error', error, {url: this.url.pathname, method: this.method});\n }\n }\n}\n", "import {createServer, IncomingMessage, ServerResponse} from 'node:http';\n\nimport {createLogger} from '@alwatr/logger';\n\nimport {NanotronApiConnection} from './api-connection.js';\nimport {HttpStatusCodes} from './const.js';\n\nimport type {HttpMethod, MatchType, RouteHandler} from './type.js';\nimport type {Dictionary} from '@alwatr/type-helper';\nimport type {Duplex} from 'node:stream';\n\n/**\n * Configuration options for the NanotronApiServer.\n */\nexport interface NanotronApiServerConfig {\n /**\n * The port number to listen on.\n *\n * @default 80\n */\n port?: number;\n\n /**\n * The hostname to listen on.\n *\n * @default '0.0.0.0'\n */\n host?: string;\n\n /**\n * Sets the timeout (ms) for receiving the entire request from the client.\n *\n * @default 10_000 ms\n */\n requestTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * This should be bigger than `keepAliveTimeout + your server's expected response time`.\n *\n * @default 130_000 ms\n */\n headersTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * @default 120_000 ms\n */\n keepAliveTimeout?: number;\n\n /**\n * Add /health route.\n *\n * @default true\n */\n healthRoute?: boolean;\n\n /**\n * Add OPTIONS route for preflight requests to allow access all origins.\n *\n * @default false\n */\n allowAllOrigin?: boolean;\n\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix?: `/${string}/` | '/';\n}\n\n/**\n * Configuration options for defining a route.\n */\nexport interface DefineRouteOption {\n /**\n * The HTTP method for this route.\n */\n method: HttpMethod;\n\n /**\n * The URL path for this route.\n */\n url: string;\n\n /**\n * The function to handle requests to this route.\n */\n handler: RouteHandler;\n\n /**\n * Specifies how the `url` should be matched against incoming requests.\n *\n * @default 'exact'\n */\n matchType?: MatchType;\n}\n\nexport class NanotronApiServer {\n protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>> = {\n host: '0.0.0.0',\n port: 80,\n requestTimeout: 10_000,\n headersTimeout: 130_000,\n keepAliveTimeout: 120_000,\n healthRoute: true,\n allowAllOrigin: false,\n prefix: '/api/',\n };\n\n protected readonly config_;\n protected readonly logger_;\n\n readonly httpServer;\n\n protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;\n\n constructor(config?: Partial<NanotronApiServerConfig>) {\n // Merge the config with the default config.\n this.config_ = {\n ...NanotronApiServer.defaultConfig_,\n ...config,\n };\n\n // Create logger.\n this.logger_ = createLogger('nanotron-api-server' + (this.config_.port !== 80 ? ':' + this.config_.port : ''));\n this.logger_.logMethodArgs?.('new', {config: this.config_});\n\n // Bind methods.\n this.handleIncomingRequest_ = this.handleIncomingRequest_.bind(this);\n this.handleServerError_ = this.handleServerError_.bind(this);\n this.handleClientError_ = this.handleClientError_.bind(this);\n\n // Initialize route handler list.\n this.routeHandlerList__ = {\n exact: {},\n startsWith: {},\n };\n\n // Create the HTTP server.\n this.httpServer = createServer(\n {\n keepAlive: true,\n keepAliveInitialDelay: 0,\n noDelay: true,\n },\n this.handleIncomingRequest_,\n );\n\n // Configure the server.\n this.httpServer.requestTimeout = this.config_.requestTimeout;\n this.httpServer.keepAliveTimeout = this.config_.keepAliveTimeout;\n this.httpServer.headersTimeout = this.config_.headersTimeout;\n\n // Start the server.\n this.httpServer.listen(this.config_.port, this.config_.host, () => {\n this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`);\n });\n\n // Handle server errors.\n this.httpServer.on('error', this.handleServerError_);\n this.httpServer.on('clientError', this.handleClientError_);\n }\n\n close(): void {\n this.logger_.logMethod?.('close');\n this.httpServer.close();\n }\n\n protected getRouteOption_(option: Required<Pick<DefineRouteOption, 'method' | 'url'>>): Required<DefineRouteOption> | null {\n this.logger_.logMethodArgs?.('getRouteOption_', option);\n\n if (\n Object.hasOwn(this.routeHandlerList__.exact, option.method) &&\n Object.hasOwn(this.routeHandlerList__.exact[option.method], option.url)\n ) {\n return this.routeHandlerList__.exact[option.method][option.url];\n }\n\n if (Object.hasOwn(this.routeHandlerList__.startsWith, option.method)) {\n const routeList = this.routeHandlerList__.startsWith[option.method];\n for (const url in routeList) {\n if (url.indexOf(option.url) === 0) {\n return routeList[url];\n }\n }\n }\n\n this.logger_.incident?.('getRouteOption_', 'route_not_found', option);\n return null;\n }\n\n protected setRouteOption_(option: Required<DefineRouteOption>): void {\n this.logger_.logMethodArgs?.('setRouteOption_', {...option, handler: 'function'});\n\n const routeHandlerList = this.routeHandlerList__[option.matchType];\n\n routeHandlerList[option.method] ??= {};\n\n if (Object.hasOwn(routeHandlerList[option.method], option.url)) {\n this.logger_.error('defineRoute', 'route_already_exists', {...option, handler: 'function'});\n throw new Error('route_already_exists');\n }\n\n routeHandlerList[option.method][option.url] = option;\n }\n\n defineRoute(option: DefineRouteOption): void {\n const option_: Required<DefineRouteOption> = {\n ...option,\n matchType: 'exact',\n };\n this.logger_.logMethodArgs?.('defineRoute', {...option_, handler: 'function'});\n this.setRouteOption_(option_);\n }\n\n protected handleServerError_(err: NodeJS.ErrnoException): void {\n if (err.code === 'EADDRINUSE') {\n this.logger_.error('handleServerError_', 'address_in_use', err);\n }\n else {\n this.logger_.error('handleServerError_', 'http_server_error', err.message || 'HTTP server catch an error', err);\n }\n }\n\n protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void {\n this.logger_.accident('handleClientError_', 'http_server_client_error', {\n errCode: err.code,\n errMessage: err.message,\n });\n socket.end('HTTP/1.1 400 Bad Request\\r\\n\\r\\n');\n }\n\n protected handleHttpError_(connection: NanotronApiConnection, error?: unknown): void {\n this.logger_.logMethod?.('handleHttpError_');\n // TODO: custom error template by the user.\n connection.replyError(error);\n }\n\n protected async handleIncomingRequest_(incomingMessage: IncomingMessage, serverResponse: ServerResponse): Promise<void> {\n this.logger_.logMethod?.('handleIncomingRequest_');\n\n if (incomingMessage.url === undefined) {\n this.logger_.accident('handleIncomingRequest_', 'http_server_url_undefined');\n return;\n }\n\n if (incomingMessage.method === undefined) {\n this.logger_.accident('handleIncomingRequest_', 'http_server_method_undefined');\n return;\n }\n\n const connection = new NanotronApiConnection(incomingMessage, serverResponse, {prefix: this.config_.prefix});\n\n const routeOption = this.getRouteOption_({\n method: connection.method,\n url: connection.url.pathname,\n });\n\n if (routeOption === null) {\n connection.replyStatusCode = HttpStatusCodes.Error_Client_404_Not_Found;\n return this.handleHttpError_(connection);\n }\n\n try {\n // TODO: hooks\n await routeOption.handler(connection);\n }\n catch (error) {\n this.logger_.error('handleIncomingRequest_', 'route_handler_error', error, {\n url: connection.url.pathname,\n method: connection.method,\n });\n\n connection.replyStatusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n this.handleHttpError_(connection, error);\n }\n\n // TODO: handled open remained connections.\n }\n}\n"],
|
|
5
|
-
"mappings": ";yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,EAAA,oBAAAC,EAAA,uBAAAC,EAAA,
|
|
6
|
-
"names": ["main_exports", "__export", "HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "
|
|
3
|
+
"sources": ["../src/main.ts", "../src/const.ts", "../src/api-server-response.ts", "../src/api-client-request.ts", "../src/url.ts", "../src/api-server.ts"],
|
|
4
|
+
"sourcesContent": ["export * from './api-server.js';\nexport type {NanotronClientRequest} from './api-client-request.js';\nexport type {NanotronServerResponse} from './api-server-response.js';\nexport type {NanotronUrl} from './url.js';\nexport * from './type.js';\nexport * from './const.js';\n", "/**\n * Object representing standard HTTP methods.\n */\nexport const HttpMethods = {\n /**\n * GET: Requests a representation of the specified resource.\n */\n GET: 'GET',\n\n /**\n * HEAD: Asks for a response identical to that of a GET request, but without the response body.\n */\n HEAD: 'HEAD',\n\n /**\n * POST: Submits data to be processed (e.g., from an HTML form) to the identified resource.\n */\n POST: 'POST',\n\n /**\n * PUT: Uploads a representation of the specified URI.\n */\n PUT: 'PUT',\n\n /**\n * DELETE: Deletes the specified resource.\n */\n DELETE: 'DELETE',\n\n /**\n * CONNECT: Establishes a tunnel to the server identified by the target resource.\n */\n CONNECT: 'CONNECT',\n\n /**\n * OPTIONS: Describes the communication options for the target resource.\n */\n OPTIONS: 'OPTIONS',\n\n /**\n * TRACE: Performs a message loop-back test along the path to the target resource.\n */\n TRACE: 'TRACE',\n\n /**\n * PATCH: Applies partial modifications to a resource.\n */\n PATCH: 'PATCH'\n} as const;\n\n/**\n * Object representing standard HTTP status codes.\n */\nexport const HttpStatusCodes = {\n /**\n * 100 Continue: The server has received the request headers and the client should proceed to send the request body.\n */\n Info_100_Continue: 100,\n\n /**\n * 101 Switching Protocols: The server understands and is willing to comply with the clients request to switch protocols.\n */\n Info_101_Switching_Protocols: 101,\n\n /**\n * 102 Processing: The server has received and is processing the request, but no response is available yet.\n */\n Info_102_Processing: 102,\n\n /**\n * 103 Early Hints: The server is sending some response headers before the final HTTP message.\n */\n Info_103_Early_Hints: 103,\n\n /**\n * 200 OK: The request has succeeded.\n */\n Success_200_OK: 200,\n\n /**\n * 201 Created: The request has been fulfilled and resulted in a new resource being created.\n */\n Success_201_Created: 201,\n\n /**\n * 202 Accepted: The request has been accepted for processing, but the processing has not been completed.\n */\n Success_202_Accepted: 202,\n\n /**\n * 203 Non-Authoritative Information: The server is a transforming proxy that received a 200 OK\n * from the origin server but is returning a modified version of the origins response.\n */\n Success_203_Non_Authoritative_Information: 203,\n\n /**\n * 204 No Content: The server successfully processed the request and is not returning any content.\n */\n Success_204_No_Content: 204,\n\n /**\n * 205 Reset Content: The server successfully processed the request,\n * asks that the client reset its document view, and is not returning any content.\n */\n Success_205_Reset_Content: 205,\n\n /**\n * 206 Partial Content: The server is delivering only part of the resource due to a range header sent by the client.\n */\n Success_206_Partial_Content: 206,\n\n /**\n * 207 Multi-Status: The message body that follows is an XML message\n * and can contain a number of separate response codes, depending on how many sub-requests were made.\n */\n Success_207_Multi_Status: 207,\n\n /**\n * 208 Already Reported: The members of a DAV binding have already been enumerated\n * in a preceding part of the (multi-status) response, and are not being included again.\n */\n Success_208_Already_Reported: 208,\n\n /**\n * 226 IM Used: The server has fulfilled a request for the resource, and the response is a representation\n * of the result of one or more instance-manipulations applied to the current instance.\n */\n Success_226_IM_Used: 226,\n\n /**\n * 300 Multiple Choices: The request has more than one possible response.\n */\n Redirect_300_Multiple_Choices: 300,\n\n /**\n * 301 Moved Permanently: The URL of the requested resource has been changed permanently.\n */\n Redirect_301_Moved_Permanently: 301,\n\n /**\n * 302 Found: The URL of the requested resource has been changed temporarily.\n */\n Redirect_302_Found: 302,\n\n /**\n * 303 See Other: The response to the request can be found under another URI using a GET method.\n */\n Redirect_303_See_Other: 303,\n\n /**\n * 304 Not Modified: The resource has not been modified since the version specified\n * by the request headers If-Modified-Since or If-None-Match.\n */\n Redirect_304_Not_Modified: 304,\n\n /**\n * 305 Use Proxy: The requested resource is only available through a proxy, the address for which is provided in the response.\n */\n Redirect_305_Use_Proxy: 305,\n\n /**\n * 306 Switch Proxy: No longer used. Originally meant \"Subsequent requests should use the specified proxy.\"\n */\n Redirect_306_Switch_Proxy: 306,\n\n /**\n * 307 Temporary Redirect: The server sends this response to direct the client\n * to get the requested resource at another URI with the same method that was used in the prior request.\n */\n Redirect_307_Temporary_Redirect: 307,\n\n /**\n * 308 Permanent Redirect: This means that the resource is now permanently located at another URI,\n * specified by the Location: HTTP Response header.\n */\n Redirect_308_Permanent_Redirect: 308,\n\n /**\n * 400 Bad Request: The server cannot or will not process the request due to something that is perceived to be a client error.\n */\n Error_Client_400_Bad_Request: 400,\n\n /**\n * 401 Unauthorized: The request has not been applied because it lacks valid authentication credentials for the target resource.\n */\n Error_Client_401_Unauthorized: 401,\n\n /**\n * 402 Payment Required: Reserved for future use.\n */\n Error_Client_402_Payment_Required: 402,\n\n /**\n * 403 Forbidden: The client does not have access rights to the content, so the server is refusing to give the requested resource.\n */\n Error_Client_403_Forbidden: 403,\n\n /**\n * 404 Not Found: The server can not find the requested resource.\n */\n Error_Client_404_Not_Found: 404,\n\n /**\n * 405 Method Not Allowed: The request method is known by the server but is not supported by the target resource.\n */\n Error_Client_405_Method_Not_Allowed: 405,\n\n /**\n * 406 Not Acceptable: The target resource does not have a current representation that would be acceptable\n * to the user agent, according to the proactive negotiation header fields received in the request,\n * and the server is unwilling to supply a default representation.\n */\n Error_Client_406_Not_Acceptable: 406,\n\n /**\n * 407 Proxy Authentication Required: Similar to 401 Unauthorized,\n * but it indicates that the client needs to authenticate itself in order to use a proxy.\n */\n Error_Client_407_Proxy_Authentication_Required: 407,\n\n /**\n * 408 Request Timeout: The server timed out waiting for the request.\n */\n Error_Client_408_Request_Timeout: 408,\n\n /**\n * 409 Conflict: The request could not be processed because of conflict in the request, such as an edit conflict.\n */\n Error_Client_409_Conflict: 409,\n\n /**\n * 410 Gone: The requested resource is no longer available and will not be available again.\n */\n Error_Client_410_Gone: 410,\n\n /**\n * 411 Length Required: The server refuses to accept the request without a defined Content-Length header.\n */\n Error_Client_411_Length_Required: 411,\n\n /**\n * 412 Precondition Failed: One or more conditions given in the request header fields evaluated to false when tested on the server.\n */\n Error_Client_412_Precondition_Failed: 412,\n\n /**\n * 413 Payload Too Large: The server is refusing to process a request because the request payload is larger\n * than the server is willing or able to process.\n */\n Error_Client_413_Payload_Too_Large: 413,\n\n /**\n * 414 URI Too Long: The server is refusing to service the request because the URI is longer than the server is willing to interpret.\n */\n Error_Client_414_URI_Too_Long: 414,\n\n /**\n * 415 Unsupported Media Type: The server is refusing to service the request\n * because the entity of the request is in a format not supported by the requested resource for the requested method.\n */\n Error_Client_415_Unsupported_Media_Type: 415,\n\n /**\n * 416 Range Not Satisfiable: The client has asked for a portion of the file, but the server cannot supply that portion.\n */\n Error_Client_416_Range_Not_Satisfiable: 416,\n\n /**\n * 417 Expectation Failed: The server cannot meet the requirements of the Expect request-header field.\n */\n Error_Client_417_Expectation_Failed: 417,\n\n /**\n * 421 Misdirected Request: The request was directed at a server that is not able to produce a response.\n */\n Error_Client_421_Misdirected_Request: 421,\n\n /**\n * 422 Unprocessable Entity: The request was well-formed but was unable to be followed due to semantic errors.\n */\n Error_Client_422_Unprocessable_Entity: 422,\n\n /**\n * 423 Locked: The resource that is being accessed is locked.\n */\n Error_Client_423_Locked: 423,\n\n /**\n * 424 Failed Dependency: The request failed due to a failure of a previous request.\n */\n Error_Client_424_Failed_Dependency: 424,\n\n /**\n * 425 Too Early: The server is unwilling to risk processing a request that might be replayed.\n */\n Error_Client_425_Too_Early: 425,\n\n /**\n * 426 Upgrade Required: The server refuses to perform the request using the current protocol\n * but might be willing to do so after the client upgrades to a different protocol.\n */\n Error_Client_426_Upgrade_Required: 426,\n\n /**\n * 428 Precondition Required: The origin server requires the request to be conditional.\n */\n Error_Client_428_Precondition_Required: 428,\n\n /**\n * 429 Too Many Requests: The user has sent too many requests in a given amount of time (\"rate limiting\").\n */\n Error_Client_429_Too_Many_Requests: 429,\n\n /**\n * 431 Request Header Fields Too Large: The server is unwilling to process the request because its header fields are too large.\n */\n Error_Client_431_Request_Header_Fields_Too_Large: 431,\n\n /**\n * 451 Unavailable For Legal Reasons: The user requests an illegal resource, such as a web page censored by a government.\n */\n Error_Client_451_Unavailable_For_Legal_Reasons: 451,\n\n /**\n * 500 Internal Server Error: A generic error message, given when no more specific message is suitable.\n */\n Error_Server_500_Internal_Server_Error: 500,\n\n /**\n * 501 Not Implemented: The server either does not recognize the request method, or it lacks the ability to fulfill the request.\n */\n Error_Server_501_Not_Implemented: 501,\n\n /**\n * 502 Bad Gateway: The server was acting as a gateway or proxy and received an invalid response from the upstream server.\n */\n Error_Server_502_Bad_Gateway: 502,\n\n /**\n * 503 Service Unavailable: The server is currently unavailable (because it is overloaded or down for maintenance).\n */\n Error_Server_503_Service_Unavailable: 503,\n\n /**\n * 504 Gateway Timeout: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.\n */\n Error_Server_504_Gateway_Timeout: 504,\n\n /**\n * 505 HTTP Version Not Supported: The server does not support the HTTP protocol version used in the request.\n */\n Error_Server_505_HTTP_Version_Not_Supported: 505,\n\n /**\n * 506 Variant Also Negotiates: Transparent content negotiation for the request results in a circular reference.\n */\n Error_Server_506_Variant_Also_Negotiates: 506,\n\n /**\n * 507 Insufficient Storage: The server is unable to store the representation needed to complete the request.\n */\n Error_Server_507_Insufficient_Storage: 507,\n\n /**\n * 508 Loop Detected: The server detected an infinite loop while processing the request.\n */\n Error_Server_508_Loop_Detected: 508,\n\n /**\n * 510 Not Extended: Further extensions to the request are required for the server to fulfill it.\n */\n Error_Server_510_Not_Extended: 510,\n\n /**\n * 511 Network Authentication Required: The client needs to authenticate to gain network access.\n */\n Error_Server_511_Network_Authentication_Required: 511\n} as const;\n\nexport const HttpStatusMessages = {\n 100: 'Continue',\n 101: 'Switching Protocols',\n 102: 'Processing',\n 103: 'Early Hints',\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 203: 'Non-Authoritative Information',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 207: 'Multi-Status',\n 208: 'Already Reported',\n 226: 'IM Used',\n 300: 'Multiple Choices',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 305: 'Use Proxy',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 407: 'Proxy Authentication Required',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 417: 'Expectation Failed',\n 418: 'I\\'m a Teapot',\n 421: 'Misdirected Request',\n 422: 'Unprocessable Entity',\n 423: 'Locked',\n 424: 'Failed Dependency',\n 425: 'Too Early',\n 426: 'Upgrade Required',\n 428: 'Precondition Required',\n 429: 'Too Many Requests',\n 431: 'Request Header Fields Too Large',\n 451: 'Unavailable For Legal Reasons',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n 506: 'Variant Also Negotiates',\n 507: 'Insufficient Storage',\n 508: 'Loop Detected',\n 509: 'Bandwidth Limit Exceeded',\n 510: 'Not Extended',\n 511: 'Network Authentication Required',\n};\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessages;\n", "import {createLogger} from '@alwatr/logger';\n\nimport {type HttpStatusCode, HttpStatusCodes, HttpStatusMessages} from './const.js';\n\nimport type {NanotronClientRequest} from './api-client-request.js';\nimport type {HttpResponseHeaders, ErrorResponse, NativeServerResponse} from './type.js';\nimport type {Json} from '@alwatr/type-helper';\n\n/**\n * Configuration options for the Nanotron Api Server Response.\n */\nexport interface NanotronServerResponseConfig {\n clientRequest: NanotronClientRequest;\n}\n\nexport class NanotronServerResponse {\n readonly clientRequest: NanotronClientRequest;\n\n readonly raw_: NativeServerResponse;\n\n readonly headers: HttpResponseHeaders;\n\n protected readonly logger_;\n\n protected hasBeenSent_ = false;\n get hasBeenSent(): boolean {\n return this.hasBeenSent_;\n }\n\n constructor(nanotronClientRequest: NanotronClientRequest, nativeServerResponse: NativeServerResponse) {\n // Store public properties.\n this.clientRequest = nanotronClientRequest;\n this.raw_ = nativeServerResponse;\n\n // Create logger.\n this.logger_ = createLogger('nt-server-response'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', this.clientRequest.url.debugId);\n\n // Set default reply headers.\n this.headers = {\n server: 'Alwatr Nanotron',\n 'content-type': 'text/plain',\n };\n }\n\n get statusCode(): HttpStatusCode {\n return this.raw_.statusCode as HttpStatusCode;\n }\n\n set statusCode(value: HttpStatusCode) {\n this.raw_.statusCode = value;\n }\n\n protected applyHeaders_() {\n this.logger_.logMethodArgs?.('applyHeaders_', this.headers);\n for (const key in this.headers) {\n this.raw_.setHeader(key, this.headers[key as Lowercase<string>]!);\n }\n }\n\n replyErrorResponse(errorResponse: ErrorResponse): void {\n this.logger_.logMethod?.('replyErrorResponse');\n this.clientRequest.terminatedHandlers = true;\n this.replyJson(errorResponse);\n }\n\n replyError(error?: Error | string | Json | unknown): void {\n this.logger_.logMethodArgs?.('replyError', {error});\n\n this.clientRequest.terminatedHandlers = true;\n let statusCode = this.statusCode;\n\n if (statusCode < HttpStatusCodes.Error_Client_400_Bad_Request) {\n this.statusCode = statusCode = 500;\n }\n\n if (error instanceof Error) {\n this.replyJson({\n ok: false,\n errorCode: error.name === 'Error' ? (('error_' + statusCode) as Lowercase<string>) : (error.name + '').toLowerCase(),\n errorMessage: error.message,\n });\n }\n else if (typeof error === 'string') {\n this.replyJson({\n ok: false,\n errorCode: ('error_' + statusCode) as Lowercase<string>,\n errorMessage: error,\n });\n }\n else if (typeof error === 'object' && error !== null) {\n this.replyJson(error as Json);\n }\n else {\n this.replyJson({\n ok: false,\n errorCode: ('error_' + statusCode) as Lowercase<string>,\n errorMessage: HttpStatusMessages[statusCode],\n } as ErrorResponse);\n }\n }\n\n replyJson(responseJson: Json): void {\n this.logger_.logMethodArgs?.('replyJson', {responseJson});\n\n let responseString: string;\n try {\n responseString = JSON.stringify(responseJson);\n }\n catch (error) {\n this.logger_.error('replyJson', 'reply_json_stringify_failed', error, this.clientRequest.url.debugId);\n this.statusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n responseString = JSON.stringify({\n ok: false,\n errorCode: 'reply_json_stringify_failed',\n errorMessage: 'Failed to stringify response JSON.',\n } as ErrorResponse);\n }\n\n this.headers['content-type'] = 'application/json';\n this.reply(responseString);\n }\n\n reply(context: string | Buffer): void {\n this.logger_.logMethodArgs?.('reply', this.clientRequest.url.debugId);\n\n if (this.raw_.writableFinished && this.hasBeenSent_ === false) {\n // The response has already been sent by direct access to the server api.\n this.logger_.accident('reply', 'server_response_writable_finished_directly');\n this.hasBeenSent_ = true;\n }\n\n if (this.hasBeenSent_) {\n this.logger_.accident('reply', 'reply_already_sent', {\n url: this.clientRequest.url.debugId,\n replySent: this.hasBeenSent_,\n writableFinished: this.raw_.writableFinished,\n });\n return;\n }\n\n this.hasBeenSent_ = true;\n\n try {\n if (typeof context === 'string') {\n context = Buffer.from(context);\n }\n\n this.headers['content-length'] = context.byteLength;\n\n this.applyHeaders_();\n this.raw_.end(context, 'binary');\n }\n catch (error) {\n this.logger_.error('reply', 'server_response_error', error, this.clientRequest.url.debugId);\n this.hasBeenSent_ = false;\n }\n }\n}\n", "import {createLogger} from '@alwatr/logger';\n\nimport {NanotronServerResponse} from './api-server-response.js';\n\nimport type {DefineRouteOption, NativeClientRequest, NativeServerResponse} from './type.js';\nimport type {NanotronUrl} from './url.js';\nimport type {Dictionary} from '@alwatr/type-helper';\n\nexport class NanotronClientRequest {\n readonly url: NanotronUrl;\n\n readonly serverResponse: NanotronServerResponse;\n\n readonly routeOption: DefineRouteOption | null;\n\n /**\n * A flag to indicate if the running handlers queue has been terminated.\n * This can occur due to an error being thrown or by explicitly calling the `replyError` method.\n *\n * When `terminatedHandlers` is set to `true`, it signifies that the execution of the current\n * sequence of handlers (including pre, main, and post handlers) has been halted and no further\n * handlers in the queue will be executed.\n *\n * Usage:\n * - Check this flag to determine if the handlers queue has been interrupted.\n * - Set this flag to `true` to manually stop the execution of subsequent handlers.\n */\n terminatedHandlers?: true;\n\n readonly sharedMeta: Dictionary = {};\n\n readonly raw_: NativeClientRequest;\n\n protected readonly logger_;\n\n constructor(\n url: NanotronUrl,\n nativeClientRequest: NativeClientRequest,\n nativeServerResponse: NativeServerResponse,\n routeOption: DefineRouteOption | null,\n ) {\n // Store public properties.\n this.raw_ = nativeClientRequest;\n this.url = url;\n this.routeOption = routeOption;\n\n // Create logger.\n this.logger_ = createLogger('nt-client-request'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', url.debugId);\n\n // Create server response.\n this.serverResponse = new NanotronServerResponse(this, nativeServerResponse);\n }\n}\n", "import {URL} from 'node:url';\n\nimport type {HttpMethod} from './type.js';\nimport type {IncomingMessage} from 'node:http';\n\nexport class NanotronUrl extends URL {\n protected static versionPattern_ = new RegExp('^/v[0-9]+/');\n\n readonly method: HttpMethod;\n readonly debugId: string;\n\n constructor(clientRequest: IncomingMessage, prefix: `/${string}/` | '/') {\n let url = clientRequest.url ?? '';\n if (prefix !== '/' && url.indexOf(prefix) === 0) {\n url = url.slice(prefix.length - 1); // include `/`\n }\n url = url.replace(NanotronUrl.versionPattern_, '/');\n\n super(url, 'http://hostname/');\n\n this.method = (clientRequest.method ?? 'GET').toUpperCase() as HttpMethod;\n\n this.debugId = `[${this.method}]${this.pathname}`;\n }\n}\n", "import {createServer} from 'node:http';\n\nimport {createLogger} from '@alwatr/logger';\n\nimport {NanotronClientRequest} from './api-client-request.js';\nimport {HttpStatusCodes} from './const.js';\nimport {NanotronUrl} from './url.js';\n\nimport type {DefineRouteOption, MatchType, NativeClientRequest, NativeServerResponse} from './type.js';\nimport type {Dictionary} from '@alwatr/type-helper';\nimport type {Duplex} from 'node:stream';\n\n/**\n * Configuration options for the NanotronApiServer.\n */\nexport interface NanotronApiServerConfig {\n /**\n * The port number to listen on.\n *\n * @default 80\n */\n port?: number;\n\n /**\n * The hostname to listen on.\n *\n * @default '0.0.0.0'\n */\n host?: string;\n\n /**\n * Sets the timeout (ms) for receiving the entire request from the client.\n *\n * @default 10_000 ms\n */\n requestTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * This should be bigger than `keepAliveTimeout + your server's expected response time`.\n *\n * @default 130_000 ms\n */\n headersTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * @default 120_000 ms\n */\n keepAliveTimeout?: number;\n\n /**\n * Add /health route.\n *\n * @default true\n */\n healthRoute?: boolean;\n\n /**\n * Add OPTIONS route for preflight requests to allow access all origins.\n *\n * @default false\n */\n allowAllOrigin?: boolean;\n\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix?: `/${string}/` | '/';\n\n /**\n * The maximum size of the request body in bytes.\n *\n * @default `1_048_576` (1MiB)\n */\n bodyLimit?: number;\n}\n\nexport class NanotronApiServer {\n protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>> = {\n host: '0.0.0.0',\n port: 80,\n requestTimeout: 10_000,\n headersTimeout: 130_000,\n keepAliveTimeout: 120_000,\n healthRoute: true,\n allowAllOrigin: false,\n prefix: '/api/',\n bodyLimit: 1_048_576, // 1MiB\n };\n\n readonly config_;\n protected readonly logger_;\n\n readonly httpServer;\n\n protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;\n\n constructor(config?: Partial<NanotronApiServerConfig>) {\n // Merge the config with the default config.\n this.config_ = {\n ...NanotronApiServer.defaultConfig_,\n ...config,\n };\n\n // Create logger.\n this.logger_ = createLogger('nt-api-server' + (this.config_.port !== 80 ? ':' + this.config_.port : ''));\n this.logger_.logMethodArgs?.('new', {config: this.config_});\n\n // Bind methods.\n this.handleClientRequest_ = this.handleClientRequest_.bind(this);\n this.handleServerError_ = this.handleServerError_.bind(this);\n this.handleClientError_ = this.handleClientError_.bind(this);\n\n // Initialize route handler list.\n this.routeHandlerList__ = {\n exact: {},\n startsWith: {},\n };\n\n // Create the HTTP server.\n this.httpServer = createServer(\n {\n keepAlive: true,\n keepAliveInitialDelay: 0,\n noDelay: true,\n },\n this.handleClientRequest_,\n );\n\n // Configure the server.\n this.httpServer.requestTimeout = this.config_.requestTimeout;\n this.httpServer.keepAliveTimeout = this.config_.keepAliveTimeout;\n this.httpServer.headersTimeout = this.config_.headersTimeout;\n\n // Start the server.\n this.httpServer.listen(this.config_.port, this.config_.host, () => {\n this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`);\n });\n\n // Handle server errors.\n this.httpServer.on('error', this.handleServerError_);\n this.httpServer.on('clientError', this.handleClientError_);\n }\n\n close(): void {\n this.logger_.logMethod?.('close');\n this.httpServer.close();\n }\n\n protected getRouteOption_(url: NanotronUrl): Required<DefineRouteOption> | null {\n this.logger_.logMethod?.('getRouteOption_');\n\n if (\n Object.hasOwn(this.routeHandlerList__.exact, url.method) &&\n Object.hasOwn(this.routeHandlerList__.exact[url.method], url.pathname)\n ) {\n return this.routeHandlerList__.exact[url.method][url.pathname];\n }\n\n if (Object.hasOwn(this.routeHandlerList__.startsWith, url.method)) {\n const routeList = this.routeHandlerList__.startsWith[url.method];\n for (const pathname in routeList) {\n if (pathname.indexOf(url.pathname) === 0) {\n return routeList[pathname];\n }\n }\n }\n\n this.logger_.incident?.('getRouteOption_', 'route_not_found', {method: url.method, url: url.pathname});\n return null;\n }\n\n protected setRouteOption_(option: Required<DefineRouteOption>): void {\n this.logger_.logMethodArgs?.('setRouteOption_', {...option, handler: 'function'});\n\n const routeHandlerList = this.routeHandlerList__[option.matchType];\n\n routeHandlerList[option.method] ??= {};\n\n if (Object.hasOwn(routeHandlerList[option.method], option.url)) {\n this.logger_.error('defineRoute', 'route_already_exists', {...option, handler: 'function'});\n throw new Error('route_already_exists');\n }\n\n routeHandlerList[option.method][option.url] = option;\n }\n\n defineRoute(option: DefineRouteOption): void {\n const option_: Required<DefineRouteOption> = {\n matchType: 'exact',\n preHandlers: [],\n postHandlers: [],\n bodyLimit: this.config_.bodyLimit,\n ...option,\n };\n this.logger_.logMethodArgs?.('defineRoute', {...option_, handler: 'function'});\n this.setRouteOption_(option_);\n }\n\n protected handleServerError_(err: NodeJS.ErrnoException): void {\n if (err.code === 'EADDRINUSE') {\n this.logger_.error('handleServerError_', 'address_in_use', err);\n }\n else {\n this.logger_.error('handleServerError_', 'http_server_error', err.message || 'HTTP server catch an error', err);\n }\n }\n\n protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void {\n this.logger_.accident('handleClientError_', 'http_server_client_error', {\n errCode: err.code,\n errMessage: err.message,\n });\n socket.end('HTTP/1.1 400 Bad Request\\r\\n\\r\\n');\n }\n\n protected async handleClientRequest_(\n nativeClientRequest: NativeClientRequest,\n nativeServerResponse: NativeServerResponse,\n ): Promise<void> {\n this.logger_.logMethod?.('handleClientRequest_');\n\n if (nativeClientRequest.url === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_url_undefined');\n return;\n }\n\n if (nativeClientRequest.method === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_method_undefined');\n return;\n }\n\n const url = new NanotronUrl(nativeClientRequest, this.config_.prefix);\n\n const routeOption = this.getRouteOption_(url);\n\n const connection = new NanotronClientRequest(url, nativeClientRequest, nativeServerResponse, routeOption);\n\n if (routeOption === null) {\n connection.serverResponse.statusCode = HttpStatusCodes.Error_Client_404_Not_Found;\n connection.serverResponse.replyError();\n return;\n }\n\n try {\n for (const handler of routeOption.preHandlers) {\n if (connection.terminatedHandlers === true) return;\n await handler(connection, connection.serverResponse, connection.sharedMeta);\n }\n\n await routeOption.handler(connection, connection.serverResponse, connection.sharedMeta);\n\n for (const handler of routeOption.postHandlers) {\n if (connection.terminatedHandlers === true) return;\n await handler(connection, connection.serverResponse, connection.sharedMeta);\n }\n }\n catch (error) {\n this.logger_.error('handleClientRequest_', 'route_handler_error', error, url.debugId);\n\n if (connection.serverResponse.statusCode < HttpStatusCodes.Error_Client_400_Bad_Request) {\n connection.serverResponse.statusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n }\n connection.serverResponse.replyError(error);\n }\n\n // TODO: handled open remained connections.\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["main_exports", "__export", "HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "NanotronApiServer", "__toCommonJS", "HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "import_logger", "NanotronServerResponse", "nanotronClientRequest", "nativeServerResponse", "value", "key", "errorResponse", "error", "statusCode", "HttpStatusCodes", "HttpStatusMessages", "responseJson", "responseString", "context", "import_logger", "NanotronClientRequest", "url", "nativeClientRequest", "nativeServerResponse", "routeOption", "NanotronServerResponse", "import_node_url", "_NanotronUrl", "clientRequest", "prefix", "url", "NanotronUrl", "import_node_http", "import_logger", "_NanotronApiServer", "config", "routeHandlerList__", "url", "routeList", "pathname", "option", "_a", "routeHandlerList", "option_", "err", "socket", "nativeClientRequest", "nativeServerResponse", "NanotronUrl", "routeOption", "connection", "NanotronClientRequest", "HttpStatusCodes", "handler", "error", "NanotronApiServer"]
|
|
7
7
|
}
|
package/dist/main.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './api-server.js';
|
|
2
|
-
export
|
|
2
|
+
export type { NanotronClientRequest } from './api-client-request.js';
|
|
3
|
+
export type { NanotronServerResponse } from './api-server-response.js';
|
|
4
|
+
export type { NanotronUrl } from './url.js';
|
|
3
5
|
export * from './type.js';
|
|
4
6
|
export * from './const.js';
|
|
5
7
|
//# sourceMappingURL=main.d.ts.map
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,YAAY,EAAC,qBAAqB,EAAC,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAC;AACrE,YAAY,EAAC,WAAW,EAAC,MAAM,UAAU,CAAC;AAC1C,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
|
package/dist/main.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/* @alwatr/nanotron-api-server v4.0.0-alpha.
|
|
2
|
-
var
|
|
1
|
+
/* @alwatr/nanotron-api-server v4.0.0-alpha.2 */
|
|
2
|
+
var E={GET:"GET",HEAD:"HEAD",POST:"POST",PUT:"PUT",DELETE:"DELETE",CONNECT:"CONNECT",OPTIONS:"OPTIONS",TRACE:"TRACE",PATCH:"PATCH"},i={Info_100_Continue:100,Info_101_Switching_Protocols:101,Info_102_Processing:102,Info_103_Early_Hints:103,Success_200_OK:200,Success_201_Created:201,Success_202_Accepted:202,Success_203_Non_Authoritative_Information:203,Success_204_No_Content:204,Success_205_Reset_Content:205,Success_206_Partial_Content:206,Success_207_Multi_Status:207,Success_208_Already_Reported:208,Success_226_IM_Used:226,Redirect_300_Multiple_Choices:300,Redirect_301_Moved_Permanently:301,Redirect_302_Found:302,Redirect_303_See_Other:303,Redirect_304_Not_Modified:304,Redirect_305_Use_Proxy:305,Redirect_306_Switch_Proxy:306,Redirect_307_Temporary_Redirect:307,Redirect_308_Permanent_Redirect:308,Error_Client_400_Bad_Request:400,Error_Client_401_Unauthorized:401,Error_Client_402_Payment_Required:402,Error_Client_403_Forbidden:403,Error_Client_404_Not_Found:404,Error_Client_405_Method_Not_Allowed:405,Error_Client_406_Not_Acceptable:406,Error_Client_407_Proxy_Authentication_Required:407,Error_Client_408_Request_Timeout:408,Error_Client_409_Conflict:409,Error_Client_410_Gone:410,Error_Client_411_Length_Required:411,Error_Client_412_Precondition_Failed:412,Error_Client_413_Payload_Too_Large:413,Error_Client_414_URI_Too_Long:414,Error_Client_415_Unsupported_Media_Type:415,Error_Client_416_Range_Not_Satisfiable:416,Error_Client_417_Expectation_Failed:417,Error_Client_421_Misdirected_Request:421,Error_Client_422_Unprocessable_Entity:422,Error_Client_423_Locked:423,Error_Client_424_Failed_Dependency:424,Error_Client_425_Too_Early:425,Error_Client_426_Upgrade_Required:426,Error_Client_428_Precondition_Required:428,Error_Client_429_Too_Many_Requests:429,Error_Client_431_Request_Header_Fields_Too_Large:431,Error_Client_451_Unavailable_For_Legal_Reasons:451,Error_Server_500_Internal_Server_Error:500,Error_Server_501_Not_Implemented:501,Error_Server_502_Bad_Gateway:502,Error_Server_503_Service_Unavailable:503,Error_Server_504_Gateway_Timeout:504,Error_Server_505_HTTP_Version_Not_Supported:505,Error_Server_506_Variant_Also_Negotiates:506,Error_Server_507_Insufficient_Storage:507,Error_Server_508_Loop_Detected:508,Error_Server_510_Not_Extended:510,Error_Server_511_Network_Authentication_Required:511},p={100:"Continue",101:"Switching Protocols",102:"Processing",103:"Early Hints",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",208:"Already Reported",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",308:"Permanent Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Payload Too Large",414:"URI Too Long",415:"Unsupported Media Type",416:"Range Not Satisfiable",417:"Expectation Failed",418:"I'm a Teapot",421:"Misdirected Request",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",425:"Too Early",426:"Upgrade Required",428:"Precondition Required",429:"Too Many Requests",431:"Request Header Fields Too Large",451:"Unavailable For Legal Reasons",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",508:"Loop Detected",509:"Bandwidth Limit Exceeded",510:"Not Extended",511:"Network Authentication Required"};import{createLogger as g}from"@alwatr/logger";var a=class{constructor(e,t){this.hasBeenSent_=!1;this.clientRequest=e,this.raw_=t,this.logger_=g("nt-server-response"),this.logger_.logMethodArgs?.("new",this.clientRequest.url.debugId),this.headers={server:"Alwatr Nanotron","content-type":"text/plain"}}get hasBeenSent(){return this.hasBeenSent_}get statusCode(){return this.raw_.statusCode}set statusCode(e){this.raw_.statusCode=e}applyHeaders_(){this.logger_.logMethodArgs?.("applyHeaders_",this.headers);for(let e in this.headers)this.raw_.setHeader(e,this.headers[e])}replyErrorResponse(e){this.logger_.logMethod?.("replyErrorResponse"),this.clientRequest.terminatedHandlers=!0,this.replyJson(e)}replyError(e){this.logger_.logMethodArgs?.("replyError",{error:e}),this.clientRequest.terminatedHandlers=!0;let t=this.statusCode;t<i.Error_Client_400_Bad_Request&&(this.statusCode=t=500),e instanceof Error?this.replyJson({ok:!1,errorCode:e.name==="Error"?"error_"+t:(e.name+"").toLowerCase(),errorMessage:e.message}):typeof e=="string"?this.replyJson({ok:!1,errorCode:"error_"+t,errorMessage:e}):typeof e=="object"&&e!==null?this.replyJson(e):this.replyJson({ok:!1,errorCode:"error_"+t,errorMessage:p[t]})}replyJson(e){this.logger_.logMethodArgs?.("replyJson",{responseJson:e});let t;try{t=JSON.stringify(e)}catch(r){this.logger_.error("replyJson","reply_json_stringify_failed",r,this.clientRequest.url.debugId),this.statusCode=i.Error_Server_500_Internal_Server_Error,t=JSON.stringify({ok:!1,errorCode:"reply_json_stringify_failed",errorMessage:"Failed to stringify response JSON."})}this.headers["content-type"]="application/json",this.reply(t)}reply(e){if(this.logger_.logMethodArgs?.("reply",this.clientRequest.url.debugId),this.raw_.writableFinished&&this.hasBeenSent_===!1&&(this.logger_.accident("reply","server_response_writable_finished_directly"),this.hasBeenSent_=!0),this.hasBeenSent_){this.logger_.accident("reply","reply_already_sent",{url:this.clientRequest.url.debugId,replySent:this.hasBeenSent_,writableFinished:this.raw_.writableFinished});return}this.hasBeenSent_=!0;try{typeof e=="string"&&(e=Buffer.from(e)),this.headers["content-length"]=e.byteLength,this.applyHeaders_(),this.raw_.end(e,"binary")}catch(t){this.logger_.error("reply","server_response_error",t,this.clientRequest.url.debugId),this.hasBeenSent_=!1}}};import{createLogger as f}from"@alwatr/logger";var _=class{constructor(e,t,r,s){this.sharedMeta={};this.raw_=t,this.url=e,this.routeOption=s,this.logger_=f("nt-client-request"),this.logger_.logMethodArgs?.("new",e.debugId),this.serverResponse=new a(this,r)}};import{URL as y}from"node:url";var d=class d extends y{constructor(e,t){let r=e.url??"";t!=="/"&&r.indexOf(t)===0&&(r=r.slice(t.length-1)),r=r.replace(d.versionPattern_,"/"),super(r,"http://hostname/"),this.method=(e.method??"GET").toUpperCase(),this.debugId=`[${this.method}]${this.pathname}`}};d.versionPattern_=new RegExp("^/v[0-9]+/");var l=d;import{createServer as R}from"node:http";import{createLogger as m}from"@alwatr/logger";var h=class h{constructor(e){this.config_={...h.defaultConfig_,...e},this.logger_=m("nt-api-server"+(this.config_.port!==80?":"+this.config_.port:"")),this.logger_.logMethodArgs?.("new",{config:this.config_}),this.handleClientRequest_=this.handleClientRequest_.bind(this),this.handleServerError_=this.handleServerError_.bind(this),this.handleClientError_=this.handleClientError_.bind(this),this.e={exact:{},startsWith:{}},this.httpServer=R({keepAlive:!0,keepAliveInitialDelay:0,noDelay:!0},this.handleClientRequest_),this.httpServer.requestTimeout=this.config_.requestTimeout,this.httpServer.keepAliveTimeout=this.config_.keepAliveTimeout,this.httpServer.headersTimeout=this.config_.headersTimeout,this.httpServer.listen(this.config_.port,this.config_.host,()=>{this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`)}),this.httpServer.on("error",this.handleServerError_),this.httpServer.on("clientError",this.handleClientError_)}close(){this.logger_.logMethod?.("close"),this.httpServer.close()}getRouteOption_(e){if(this.logger_.logMethod?.("getRouteOption_"),Object.hasOwn(this.e.exact,e.method)&&Object.hasOwn(this.e.exact[e.method],e.pathname))return this.e.exact[e.method][e.pathname];if(Object.hasOwn(this.e.startsWith,e.method)){let t=this.e.startsWith[e.method];for(let r in t)if(r.indexOf(e.pathname)===0)return t[r]}return this.logger_.incident?.("getRouteOption_","route_not_found",{method:e.method,url:e.pathname}),null}setRouteOption_(e){var r;this.logger_.logMethodArgs?.("setRouteOption_",{...e,handler:"function"});let t=this.e[e.matchType];if(t[r=e.method]??(t[r]={}),Object.hasOwn(t[e.method],e.url))throw this.logger_.error("defineRoute","route_already_exists",{...e,handler:"function"}),new Error("route_already_exists");t[e.method][e.url]=e}defineRoute(e){let t={matchType:"exact",preHandlers:[],postHandlers:[],bodyLimit:this.config_.bodyLimit,...e};this.logger_.logMethodArgs?.("defineRoute",{...t,handler:"function"}),this.setRouteOption_(t)}handleServerError_(e){e.code==="EADDRINUSE"?this.logger_.error("handleServerError_","address_in_use",e):this.logger_.error("handleServerError_","http_server_error",e.message||"HTTP server catch an error",e)}handleClientError_(e,t){this.logger_.accident("handleClientError_","http_server_client_error",{errCode:e.code,errMessage:e.message}),t.end(`HTTP/1.1 400 Bad Request\r
|
|
3
3
|
\r
|
|
4
|
-
`)}
|
|
4
|
+
`)}async handleClientRequest_(e,t){if(this.logger_.logMethod?.("handleClientRequest_"),e.url===void 0){this.logger_.accident("handleClientRequest_","http_server_url_undefined");return}if(e.method===void 0){this.logger_.accident("handleClientRequest_","http_server_method_undefined");return}let r=new l(e,this.config_.prefix),s=this.getRouteOption_(r),o=new _(r,e,t,s);if(s===null){o.serverResponse.statusCode=i.Error_Client_404_Not_Found,o.serverResponse.replyError();return}try{for(let n of s.preHandlers){if(o.terminatedHandlers===!0)return;await n(o,o.serverResponse,o.sharedMeta)}await s.handler(o,o.serverResponse,o.sharedMeta);for(let n of s.postHandlers){if(o.terminatedHandlers===!0)return;await n(o,o.serverResponse,o.sharedMeta)}}catch(n){this.logger_.error("handleClientRequest_","route_handler_error",n,r.debugId),o.serverResponse.statusCode<i.Error_Client_400_Bad_Request&&(o.serverResponse.statusCode=i.Error_Server_500_Internal_Server_Error),o.serverResponse.replyError(n)}}};h.defaultConfig_={host:"0.0.0.0",port:80,requestTimeout:1e4,headersTimeout:13e4,keepAliveTimeout:12e4,healthRoute:!0,allowAllOrigin:!1,prefix:"/api/",bodyLimit:1048576};var u=h;export{E as HttpMethods,i as HttpStatusCodes,p as HttpStatusMessages,u as NanotronApiServer};
|
|
5
5
|
//# sourceMappingURL=main.mjs.map
|
package/dist/main.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/const.ts", "../src/api-
|
|
4
|
-
"sourcesContent": ["/**\n * Object representing standard HTTP methods.\n */\nexport const HttpMethods = {\n /**\n * GET: Requests a representation of the specified resource.\n */\n GET: 'GET',\n\n /**\n * HEAD: Asks for a response identical to that of a GET request, but without the response body.\n */\n HEAD: 'HEAD',\n\n /**\n * POST: Submits data to be processed (e.g., from an HTML form) to the identified resource.\n */\n POST: 'POST',\n\n /**\n * PUT: Uploads a representation of the specified URI.\n */\n PUT: 'PUT',\n\n /**\n * DELETE: Deletes the specified resource.\n */\n DELETE: 'DELETE',\n\n /**\n * CONNECT: Establishes a tunnel to the server identified by the target resource.\n */\n CONNECT: 'CONNECT',\n\n /**\n * OPTIONS: Describes the communication options for the target resource.\n */\n OPTIONS: 'OPTIONS',\n\n /**\n * TRACE: Performs a message loop-back test along the path to the target resource.\n */\n TRACE: 'TRACE',\n\n /**\n * PATCH: Applies partial modifications to a resource.\n */\n PATCH: 'PATCH'\n} as const;\n\n/**\n * Object representing standard HTTP status codes.\n */\nexport const HttpStatusCodes = {\n /**\n * 100 Continue: The server has received the request headers and the client should proceed to send the request body.\n */\n Info_100_Continue: 100,\n\n /**\n * 101 Switching Protocols: The server understands and is willing to comply with the clients request to switch protocols.\n */\n Info_101_Switching_Protocols: 101,\n\n /**\n * 102 Processing: The server has received and is processing the request, but no response is available yet.\n */\n Info_102_Processing: 102,\n\n /**\n * 103 Early Hints: The server is sending some response headers before the final HTTP message.\n */\n Info_103_Early_Hints: 103,\n\n /**\n * 200 OK: The request has succeeded.\n */\n Success_200_OK: 200,\n\n /**\n * 201 Created: The request has been fulfilled and resulted in a new resource being created.\n */\n Success_201_Created: 201,\n\n /**\n * 202 Accepted: The request has been accepted for processing, but the processing has not been completed.\n */\n Success_202_Accepted: 202,\n\n /**\n * 203 Non-Authoritative Information: The server is a transforming proxy that received a 200 OK\n * from the origin server but is returning a modified version of the origins response.\n */\n Success_203_Non_Authoritative_Information: 203,\n\n /**\n * 204 No Content: The server successfully processed the request and is not returning any content.\n */\n Success_204_No_Content: 204,\n\n /**\n * 205 Reset Content: The server successfully processed the request,\n * asks that the client reset its document view, and is not returning any content.\n */\n Success_205_Reset_Content: 205,\n\n /**\n * 206 Partial Content: The server is delivering only part of the resource due to a range header sent by the client.\n */\n Success_206_Partial_Content: 206,\n\n /**\n * 207 Multi-Status: The message body that follows is an XML message\n * and can contain a number of separate response codes, depending on how many sub-requests were made.\n */\n Success_207_Multi_Status: 207,\n\n /**\n * 208 Already Reported: The members of a DAV binding have already been enumerated\n * in a preceding part of the (multi-status) response, and are not being included again.\n */\n Success_208_Already_Reported: 208,\n\n /**\n * 226 IM Used: The server has fulfilled a request for the resource, and the response is a representation\n * of the result of one or more instance-manipulations applied to the current instance.\n */\n Success_226_IM_Used: 226,\n\n /**\n * 300 Multiple Choices: The request has more than one possible response.\n */\n Redirect_300_Multiple_Choices: 300,\n\n /**\n * 301 Moved Permanently: The URL of the requested resource has been changed permanently.\n */\n Redirect_301_Moved_Permanently: 301,\n\n /**\n * 302 Found: The URL of the requested resource has been changed temporarily.\n */\n Redirect_302_Found: 302,\n\n /**\n * 303 See Other: The response to the request can be found under another URI using a GET method.\n */\n Redirect_303_See_Other: 303,\n\n /**\n * 304 Not Modified: The resource has not been modified since the version specified\n * by the request headers If-Modified-Since or If-None-Match.\n */\n Redirect_304_Not_Modified: 304,\n\n /**\n * 305 Use Proxy: The requested resource is only available through a proxy, the address for which is provided in the response.\n */\n Redirect_305_Use_Proxy: 305,\n\n /**\n * 306 Switch Proxy: No longer used. Originally meant \"Subsequent requests should use the specified proxy.\"\n */\n Redirect_306_Switch_Proxy: 306,\n\n /**\n * 307 Temporary Redirect: The server sends this response to direct the client\n * to get the requested resource at another URI with the same method that was used in the prior request.\n */\n Redirect_307_Temporary_Redirect: 307,\n\n /**\n * 308 Permanent Redirect: This means that the resource is now permanently located at another URI,\n * specified by the Location: HTTP Response header.\n */\n Redirect_308_Permanent_Redirect: 308,\n\n /**\n * 400 Bad Request: The server cannot or will not process the request due to something that is perceived to be a client error.\n */\n Error_Client_400_Bad_Request: 400,\n\n /**\n * 401 Unauthorized: The request has not been applied because it lacks valid authentication credentials for the target resource.\n */\n Error_Client_401_Unauthorized: 401,\n\n /**\n * 402 Payment Required: Reserved for future use.\n */\n Error_Client_402_Payment_Required: 402,\n\n /**\n * 403 Forbidden: The client does not have access rights to the content, so the server is refusing to give the requested resource.\n */\n Error_Client_403_Forbidden: 403,\n\n /**\n * 404 Not Found: The server can not find the requested resource.\n */\n Error_Client_404_Not_Found: 404,\n\n /**\n * 405 Method Not Allowed: The request method is known by the server but is not supported by the target resource.\n */\n Error_Client_405_Method_Not_Allowed: 405,\n\n /**\n * 406 Not Acceptable: The target resource does not have a current representation that would be acceptable\n * to the user agent, according to the proactive negotiation header fields received in the request,\n * and the server is unwilling to supply a default representation.\n */\n Error_Client_406_Not_Acceptable: 406,\n\n /**\n * 407 Proxy Authentication Required: Similar to 401 Unauthorized,\n * but it indicates that the client needs to authenticate itself in order to use a proxy.\n */\n Error_Client_407_Proxy_Authentication_Required: 407,\n\n /**\n * 408 Request Timeout: The server timed out waiting for the request.\n */\n Error_Client_408_Request_Timeout: 408,\n\n /**\n * 409 Conflict: The request could not be processed because of conflict in the request, such as an edit conflict.\n */\n Error_Client_409_Conflict: 409,\n\n /**\n * 410 Gone: The requested resource is no longer available and will not be available again.\n */\n Error_Client_410_Gone: 410,\n\n /**\n * 411 Length Required: The server refuses to accept the request without a defined Content-Length header.\n */\n Error_Client_411_Length_Required: 411,\n\n /**\n * 412 Precondition Failed: One or more conditions given in the request header fields evaluated to false when tested on the server.\n */\n Error_Client_412_Precondition_Failed: 412,\n\n /**\n * 413 Payload Too Large: The server is refusing to process a request because the request payload is larger\n * than the server is willing or able to process.\n */\n Error_Client_413_Payload_Too_Large: 413,\n\n /**\n * 414 URI Too Long: The server is refusing to service the request because the URI is longer than the server is willing to interpret.\n */\n Error_Client_414_URI_Too_Long: 414,\n\n /**\n * 415 Unsupported Media Type: The server is refusing to service the request\n * because the entity of the request is in a format not supported by the requested resource for the requested method.\n */\n Error_Client_415_Unsupported_Media_Type: 415,\n\n /**\n * 416 Range Not Satisfiable: The client has asked for a portion of the file, but the server cannot supply that portion.\n */\n Error_Client_416_Range_Not_Satisfiable: 416,\n\n /**\n * 417 Expectation Failed: The server cannot meet the requirements of the Expect request-header field.\n */\n Error_Client_417_Expectation_Failed: 417,\n\n /**\n * 421 Misdirected Request: The request was directed at a server that is not able to produce a response.\n */\n Error_Client_421_Misdirected_Request: 421,\n\n /**\n * 422 Unprocessable Entity: The request was well-formed but was unable to be followed due to semantic errors.\n */\n Error_Client_422_Unprocessable_Entity: 422,\n\n /**\n * 423 Locked: The resource that is being accessed is locked.\n */\n Error_Client_423_Locked: 423,\n\n /**\n * 424 Failed Dependency: The request failed due to a failure of a previous request.\n */\n Error_Client_424_Failed_Dependency: 424,\n\n /**\n * 425 Too Early: The server is unwilling to risk processing a request that might be replayed.\n */\n Error_Client_425_Too_Early: 425,\n\n /**\n * 426 Upgrade Required: The server refuses to perform the request using the current protocol\n * but might be willing to do so after the client upgrades to a different protocol.\n */\n Error_Client_426_Upgrade_Required: 426,\n\n /**\n * 428 Precondition Required: The origin server requires the request to be conditional.\n */\n Error_Client_428_Precondition_Required: 428,\n\n /**\n * 429 Too Many Requests: The user has sent too many requests in a given amount of time (\"rate limiting\").\n */\n Error_Client_429_Too_Many_Requests: 429,\n\n /**\n * 431 Request Header Fields Too Large: The server is unwilling to process the request because its header fields are too large.\n */\n Error_Client_431_Request_Header_Fields_Too_Large: 431,\n\n /**\n * 451 Unavailable For Legal Reasons: The user requests an illegal resource, such as a web page censored by a government.\n */\n Error_Client_451_Unavailable_For_Legal_Reasons: 451,\n\n /**\n * 500 Internal Server Error: A generic error message, given when no more specific message is suitable.\n */\n Error_Server_500_Internal_Server_Error: 500,\n\n /**\n * 501 Not Implemented: The server either does not recognize the request method, or it lacks the ability to fulfill the request.\n */\n Error_Server_501_Not_Implemented: 501,\n\n /**\n * 502 Bad Gateway: The server was acting as a gateway or proxy and received an invalid response from the upstream server.\n */\n Error_Server_502_Bad_Gateway: 502,\n\n /**\n * 503 Service Unavailable: The server is currently unavailable (because it is overloaded or down for maintenance).\n */\n Error_Server_503_Service_Unavailable: 503,\n\n /**\n * 504 Gateway Timeout: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.\n */\n Error_Server_504_Gateway_Timeout: 504,\n\n /**\n * 505 HTTP Version Not Supported: The server does not support the HTTP protocol version used in the request.\n */\n Error_Server_505_HTTP_Version_Not_Supported: 505,\n\n /**\n * 506 Variant Also Negotiates: Transparent content negotiation for the request results in a circular reference.\n */\n Error_Server_506_Variant_Also_Negotiates: 506,\n\n /**\n * 507 Insufficient Storage: The server is unable to store the representation needed to complete the request.\n */\n Error_Server_507_Insufficient_Storage: 507,\n\n /**\n * 508 Loop Detected: The server detected an infinite loop while processing the request.\n */\n Error_Server_508_Loop_Detected: 508,\n\n /**\n * 510 Not Extended: Further extensions to the request are required for the server to fulfill it.\n */\n Error_Server_510_Not_Extended: 510,\n\n /**\n * 511 Network Authentication Required: The client needs to authenticate to gain network access.\n */\n Error_Server_511_Network_Authentication_Required: 511\n} as const;\n\nexport const HttpStatusMessages = {\n 100: 'Continue',\n 101: 'Switching Protocols',\n 102: 'Processing',\n 103: 'Early Hints',\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 203: 'Non-Authoritative Information',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 207: 'Multi-Status',\n 208: 'Already Reported',\n 226: 'IM Used',\n 300: 'Multiple Choices',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 305: 'Use Proxy',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 407: 'Proxy Authentication Required',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 417: 'Expectation Failed',\n 418: 'I\\'m a Teapot',\n 421: 'Misdirected Request',\n 422: 'Unprocessable Entity',\n 423: 'Locked',\n 424: 'Failed Dependency',\n 425: 'Too Early',\n 426: 'Upgrade Required',\n 428: 'Precondition Required',\n 429: 'Too Many Requests',\n 431: 'Request Header Fields Too Large',\n 451: 'Unavailable For Legal Reasons',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n 506: 'Variant Also Negotiates',\n 507: 'Insufficient Storage',\n 508: 'Loop Detected',\n 509: 'Bandwidth Limit Exceeded',\n 510: 'Not Extended',\n 511: 'Network Authentication Required',\n};\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessages;\n", "import {createLogger} from '@alwatr/logger';\n\nimport {type HttpStatusCode, HttpStatusCodes, HttpStatusMessages} from './const.js';\n\nimport type {HttpResponseHeaders, HttpMethod, ErrorResponse} from './type.js';\nimport type {Json} from '@alwatr/type-helper';\nimport type {IncomingMessage, ServerResponse} from 'node:http';\n\n/**\n * Configuration options for the NanotronApiConnection.\n */\nexport interface NanotronApiConnectionConfig {\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix: `/${string}/` | '/';\n}\n\nexport class NanotronApiConnection {\n protected static versionPattern_ = new RegExp('^/v[0-9]+/');\n\n readonly url;\n\n readonly method;\n\n protected readonly logger_;\n\n readonly replyHeaders: HttpResponseHeaders;\n\n protected replySent_ = false;\n get replySent(): boolean {\n return this.replySent_;\n }\n\n constructor(\n public incomingMessage: IncomingMessage,\n public serverResponse: ServerResponse,\n protected config_: NanotronApiConnectionConfig,\n ) {\n // Create logger.\n this.logger_ = createLogger('nanotron-api-connection'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', {method: incomingMessage.method, url: incomingMessage.url});\n\n // Parse request method.\n this.method = (this.incomingMessage.method ?? 'GET').toUpperCase() as HttpMethod;\n\n // Parse request URL.\n let url = this.incomingMessage.url ?? '';\n if (this.config_.prefix !== '/' && url.indexOf(this.config_.prefix) === 0) {\n url = url.slice(this.config_.prefix.length - 1);\n }\n url = url.replace(NanotronApiConnection.versionPattern_, '/');\n this.url = new URL(url, 'http://hostname/');\n\n // Set default reply headers.\n this.replyHeaders = {\n server: 'Alwatr Nanotron',\n 'content-type': 'text/plain',\n };\n }\n\n get replyStatusCode(): HttpStatusCode {\n return this.serverResponse.statusCode as HttpStatusCode;\n }\n\n set replyStatusCode(value: HttpStatusCode) {\n this.serverResponse.statusCode = value;\n }\n\n protected applyReplyHeaders_() {\n this.logger_.logMethodArgs?.('applyReplyHeaders_', this.replyHeaders);\n for (const key in this.replyHeaders) {\n this.serverResponse.setHeader(key, this.replyHeaders[key as Lowercase<string>]!);\n }\n }\n\n replyJsonError(errorResponse: ErrorResponse): void {\n this.logger_.logMethodArgs?.('replyJsonError', {errorResponse});\n this.replyJson(errorResponse);\n }\n\n replyJson(responseJson: Json): void {\n this.logger_.logMethodArgs?.('replyJson', {responseJson});\n\n let responseString: string;\n try {\n responseString = JSON.stringify(responseJson);\n }\n catch (error) {\n this.logger_.error('replyJson', 'reply_json_stringify_failed', error, {\n url: this.url.pathname,\n method: this.method,\n });\n this.replyStatusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n responseString = JSON.stringify({\n ok: false,\n errorCode: 'reply_json_stringify_failed',\n errorMessage: 'Failed to stringify response JSON.',\n } as ErrorResponse);\n }\n\n this.replyHeaders['content-type'] = 'application/json';\n this.reply(responseString);\n }\n\n replyError(error?: Error | unknown): void {\n this.logger_.logMethodArgs?.('replyError', {error});\n\n const statusCode = this.replyStatusCode;\n\n if (error === undefined || error instanceof Error === false) {\n this.replyJson({\n ok: false,\n errorCode: ('error_' + statusCode) as Lowercase<string>,\n errorMessage: HttpStatusMessages[statusCode]\n } as ErrorResponse);\n return;\n }\n\n this.replyJson({\n ok: false,\n errorCode: error.name,\n errorMessage: error.message,\n });\n }\n\n reply(context: string | Buffer): void {\n this.logger_.logMethodArgs?.('reply', {url: this.url.pathname, method: this.method});\n\n if (this.replySent_ || this.serverResponse.writableFinished) {\n this.logger_.accident('reply', 'reply_already_sent', {\n url: this.url.pathname,\n method: this.method,\n replySent: this.replySent_,\n writableFinished: this.serverResponse.writableFinished,\n });\n return;\n }\n\n try {\n if (typeof context === 'string') {\n context = Buffer.from(context);\n }\n\n this.replyHeaders['content-length'] = context.byteLength;\n\n this.applyReplyHeaders_();\n this.serverResponse.end(context, 'binary');\n\n this.replySent_ = true;\n }\n catch (error) {\n this.logger_.error('reply', 'server_response_error', error, {url: this.url.pathname, method: this.method});\n }\n }\n}\n", "import {createServer, IncomingMessage, ServerResponse} from 'node:http';\n\nimport {createLogger} from '@alwatr/logger';\n\nimport {NanotronApiConnection} from './api-connection.js';\nimport {HttpStatusCodes} from './const.js';\n\nimport type {HttpMethod, MatchType, RouteHandler} from './type.js';\nimport type {Dictionary} from '@alwatr/type-helper';\nimport type {Duplex} from 'node:stream';\n\n/**\n * Configuration options for the NanotronApiServer.\n */\nexport interface NanotronApiServerConfig {\n /**\n * The port number to listen on.\n *\n * @default 80\n */\n port?: number;\n\n /**\n * The hostname to listen on.\n *\n * @default '0.0.0.0'\n */\n host?: string;\n\n /**\n * Sets the timeout (ms) for receiving the entire request from the client.\n *\n * @default 10_000 ms\n */\n requestTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * This should be bigger than `keepAliveTimeout + your server's expected response time`.\n *\n * @default 130_000 ms\n */\n headersTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * @default 120_000 ms\n */\n keepAliveTimeout?: number;\n\n /**\n * Add /health route.\n *\n * @default true\n */\n healthRoute?: boolean;\n\n /**\n * Add OPTIONS route for preflight requests to allow access all origins.\n *\n * @default false\n */\n allowAllOrigin?: boolean;\n\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix?: `/${string}/` | '/';\n}\n\n/**\n * Configuration options for defining a route.\n */\nexport interface DefineRouteOption {\n /**\n * The HTTP method for this route.\n */\n method: HttpMethod;\n\n /**\n * The URL path for this route.\n */\n url: string;\n\n /**\n * The function to handle requests to this route.\n */\n handler: RouteHandler;\n\n /**\n * Specifies how the `url` should be matched against incoming requests.\n *\n * @default 'exact'\n */\n matchType?: MatchType;\n}\n\nexport class NanotronApiServer {\n protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>> = {\n host: '0.0.0.0',\n port: 80,\n requestTimeout: 10_000,\n headersTimeout: 130_000,\n keepAliveTimeout: 120_000,\n healthRoute: true,\n allowAllOrigin: false,\n prefix: '/api/',\n };\n\n protected readonly config_;\n protected readonly logger_;\n\n readonly httpServer;\n\n protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;\n\n constructor(config?: Partial<NanotronApiServerConfig>) {\n // Merge the config with the default config.\n this.config_ = {\n ...NanotronApiServer.defaultConfig_,\n ...config,\n };\n\n // Create logger.\n this.logger_ = createLogger('nanotron-api-server' + (this.config_.port !== 80 ? ':' + this.config_.port : ''));\n this.logger_.logMethodArgs?.('new', {config: this.config_});\n\n // Bind methods.\n this.handleIncomingRequest_ = this.handleIncomingRequest_.bind(this);\n this.handleServerError_ = this.handleServerError_.bind(this);\n this.handleClientError_ = this.handleClientError_.bind(this);\n\n // Initialize route handler list.\n this.routeHandlerList__ = {\n exact: {},\n startsWith: {},\n };\n\n // Create the HTTP server.\n this.httpServer = createServer(\n {\n keepAlive: true,\n keepAliveInitialDelay: 0,\n noDelay: true,\n },\n this.handleIncomingRequest_,\n );\n\n // Configure the server.\n this.httpServer.requestTimeout = this.config_.requestTimeout;\n this.httpServer.keepAliveTimeout = this.config_.keepAliveTimeout;\n this.httpServer.headersTimeout = this.config_.headersTimeout;\n\n // Start the server.\n this.httpServer.listen(this.config_.port, this.config_.host, () => {\n this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`);\n });\n\n // Handle server errors.\n this.httpServer.on('error', this.handleServerError_);\n this.httpServer.on('clientError', this.handleClientError_);\n }\n\n close(): void {\n this.logger_.logMethod?.('close');\n this.httpServer.close();\n }\n\n protected getRouteOption_(option: Required<Pick<DefineRouteOption, 'method' | 'url'>>): Required<DefineRouteOption> | null {\n this.logger_.logMethodArgs?.('getRouteOption_', option);\n\n if (\n Object.hasOwn(this.routeHandlerList__.exact, option.method) &&\n Object.hasOwn(this.routeHandlerList__.exact[option.method], option.url)\n ) {\n return this.routeHandlerList__.exact[option.method][option.url];\n }\n\n if (Object.hasOwn(this.routeHandlerList__.startsWith, option.method)) {\n const routeList = this.routeHandlerList__.startsWith[option.method];\n for (const url in routeList) {\n if (url.indexOf(option.url) === 0) {\n return routeList[url];\n }\n }\n }\n\n this.logger_.incident?.('getRouteOption_', 'route_not_found', option);\n return null;\n }\n\n protected setRouteOption_(option: Required<DefineRouteOption>): void {\n this.logger_.logMethodArgs?.('setRouteOption_', {...option, handler: 'function'});\n\n const routeHandlerList = this.routeHandlerList__[option.matchType];\n\n routeHandlerList[option.method] ??= {};\n\n if (Object.hasOwn(routeHandlerList[option.method], option.url)) {\n this.logger_.error('defineRoute', 'route_already_exists', {...option, handler: 'function'});\n throw new Error('route_already_exists');\n }\n\n routeHandlerList[option.method][option.url] = option;\n }\n\n defineRoute(option: DefineRouteOption): void {\n const option_: Required<DefineRouteOption> = {\n ...option,\n matchType: 'exact',\n };\n this.logger_.logMethodArgs?.('defineRoute', {...option_, handler: 'function'});\n this.setRouteOption_(option_);\n }\n\n protected handleServerError_(err: NodeJS.ErrnoException): void {\n if (err.code === 'EADDRINUSE') {\n this.logger_.error('handleServerError_', 'address_in_use', err);\n }\n else {\n this.logger_.error('handleServerError_', 'http_server_error', err.message || 'HTTP server catch an error', err);\n }\n }\n\n protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void {\n this.logger_.accident('handleClientError_', 'http_server_client_error', {\n errCode: err.code,\n errMessage: err.message,\n });\n socket.end('HTTP/1.1 400 Bad Request\\r\\n\\r\\n');\n }\n\n protected handleHttpError_(connection: NanotronApiConnection, error?: unknown): void {\n this.logger_.logMethod?.('handleHttpError_');\n // TODO: custom error template by the user.\n connection.replyError(error);\n }\n\n protected async handleIncomingRequest_(incomingMessage: IncomingMessage, serverResponse: ServerResponse): Promise<void> {\n this.logger_.logMethod?.('handleIncomingRequest_');\n\n if (incomingMessage.url === undefined) {\n this.logger_.accident('handleIncomingRequest_', 'http_server_url_undefined');\n return;\n }\n\n if (incomingMessage.method === undefined) {\n this.logger_.accident('handleIncomingRequest_', 'http_server_method_undefined');\n return;\n }\n\n const connection = new NanotronApiConnection(incomingMessage, serverResponse, {prefix: this.config_.prefix});\n\n const routeOption = this.getRouteOption_({\n method: connection.method,\n url: connection.url.pathname,\n });\n\n if (routeOption === null) {\n connection.replyStatusCode = HttpStatusCodes.Error_Client_404_Not_Found;\n return this.handleHttpError_(connection);\n }\n\n try {\n // TODO: hooks\n await routeOption.handler(connection);\n }\n catch (error) {\n this.logger_.error('handleIncomingRequest_', 'route_handler_error', error, {\n url: connection.url.pathname,\n method: connection.method,\n });\n\n connection.replyStatusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n this.handleHttpError_(connection, error);\n }\n\n // TODO: handled open remained connections.\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAGO,IAAMA,EAAc,CAIzB,IAAK,MAKL,KAAM,OAKN,KAAM,OAKN,IAAK,MAKL,OAAQ,SAKR,QAAS,UAKT,QAAS,UAKT,MAAO,QAKP,MAAO,OACT,EAKaC,EAAkB,CAI7B,kBAAmB,IAKnB,6BAA8B,IAK9B,oBAAqB,IAKrB,qBAAsB,IAKtB,eAAgB,IAKhB,oBAAqB,IAKrB,qBAAsB,IAMtB,0CAA2C,IAK3C,uBAAwB,IAMxB,0BAA2B,IAK3B,4BAA6B,IAM7B,yBAA0B,IAM1B,6BAA8B,IAM9B,oBAAqB,IAKrB,8BAA+B,IAK/B,+BAAgC,IAKhC,mBAAoB,IAKpB,uBAAwB,IAMxB,0BAA2B,IAK3B,uBAAwB,IAKxB,0BAA2B,IAM3B,gCAAiC,IAMjC,gCAAiC,IAKjC,6BAA8B,IAK9B,8BAA+B,IAK/B,kCAAmC,IAKnC,2BAA4B,IAK5B,2BAA4B,IAK5B,oCAAqC,IAOrC,gCAAiC,IAMjC,+CAAgD,IAKhD,iCAAkC,IAKlC,0BAA2B,IAK3B,sBAAuB,IAKvB,iCAAkC,IAKlC,qCAAsC,IAMtC,mCAAoC,IAKpC,8BAA+B,IAM/B,wCAAyC,IAKzC,uCAAwC,IAKxC,oCAAqC,IAKrC,qCAAsC,IAKtC,sCAAuC,IAKvC,wBAAyB,IAKzB,mCAAoC,IAKpC,2BAA4B,IAM5B,kCAAmC,IAKnC,uCAAwC,IAKxC,mCAAoC,IAKpC,iDAAkD,IAKlD,+CAAgD,IAKhD,uCAAwC,IAKxC,iCAAkC,IAKlC,6BAA8B,IAK9B,qCAAsC,IAKtC,iCAAkC,IAKlC,4CAA6C,IAK7C,yCAA0C,IAK1C,sCAAuC,IAKvC,+BAAgC,IAKhC,8BAA+B,IAK/B,iDAAkD,GACpD,EAEaC,EAAqB,CAChC,IAAK,WACL,IAAK,sBACL,IAAK,aACL,IAAK,cACL,IAAK,KACL,IAAK,UACL,IAAK,WACL,IAAK,gCACL,IAAK,aACL,IAAK,gBACL,IAAK,kBACL,IAAK,eACL,IAAK,mBACL,IAAK,UACL,IAAK,mBACL,IAAK,oBACL,IAAK,QACL,IAAK,YACL,IAAK,eACL,IAAK,YACL,IAAK,qBACL,IAAK,qBACL,IAAK,cACL,IAAK,eACL,IAAK,mBACL,IAAK,YACL,IAAK,YACL,IAAK,qBACL,IAAK,iBACL,IAAK,gCACL,IAAK,kBACL,IAAK,WACL,IAAK,OACL,IAAK,kBACL,IAAK,sBACL,IAAK,oBACL,IAAK,eACL,IAAK,yBACL,IAAK,wBACL,IAAK,qBACL,IAAK,eACL,IAAK,sBACL,IAAK,uBACL,IAAK,SACL,IAAK,oBACL,IAAK,YACL,IAAK,mBACL,IAAK,wBACL,IAAK,oBACL,IAAK,kCACL,IAAK,gCACL,IAAK,wBACL,IAAK,kBACL,IAAK,cACL,IAAK,sBACL,IAAK,kBACL,IAAK,6BACL,IAAK,0BACL,IAAK,uBACL,IAAK,gBACL,IAAK,2BACL,IAAK,eACL,IAAK,iCACP,EC3bA,OAAQ,gBAAAC,MAAmB,
|
|
6
|
-
"names": ["HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "createLogger", "
|
|
3
|
+
"sources": ["../src/const.ts", "../src/api-server-response.ts", "../src/api-client-request.ts", "../src/url.ts", "../src/api-server.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Object representing standard HTTP methods.\n */\nexport const HttpMethods = {\n /**\n * GET: Requests a representation of the specified resource.\n */\n GET: 'GET',\n\n /**\n * HEAD: Asks for a response identical to that of a GET request, but without the response body.\n */\n HEAD: 'HEAD',\n\n /**\n * POST: Submits data to be processed (e.g., from an HTML form) to the identified resource.\n */\n POST: 'POST',\n\n /**\n * PUT: Uploads a representation of the specified URI.\n */\n PUT: 'PUT',\n\n /**\n * DELETE: Deletes the specified resource.\n */\n DELETE: 'DELETE',\n\n /**\n * CONNECT: Establishes a tunnel to the server identified by the target resource.\n */\n CONNECT: 'CONNECT',\n\n /**\n * OPTIONS: Describes the communication options for the target resource.\n */\n OPTIONS: 'OPTIONS',\n\n /**\n * TRACE: Performs a message loop-back test along the path to the target resource.\n */\n TRACE: 'TRACE',\n\n /**\n * PATCH: Applies partial modifications to a resource.\n */\n PATCH: 'PATCH'\n} as const;\n\n/**\n * Object representing standard HTTP status codes.\n */\nexport const HttpStatusCodes = {\n /**\n * 100 Continue: The server has received the request headers and the client should proceed to send the request body.\n */\n Info_100_Continue: 100,\n\n /**\n * 101 Switching Protocols: The server understands and is willing to comply with the clients request to switch protocols.\n */\n Info_101_Switching_Protocols: 101,\n\n /**\n * 102 Processing: The server has received and is processing the request, but no response is available yet.\n */\n Info_102_Processing: 102,\n\n /**\n * 103 Early Hints: The server is sending some response headers before the final HTTP message.\n */\n Info_103_Early_Hints: 103,\n\n /**\n * 200 OK: The request has succeeded.\n */\n Success_200_OK: 200,\n\n /**\n * 201 Created: The request has been fulfilled and resulted in a new resource being created.\n */\n Success_201_Created: 201,\n\n /**\n * 202 Accepted: The request has been accepted for processing, but the processing has not been completed.\n */\n Success_202_Accepted: 202,\n\n /**\n * 203 Non-Authoritative Information: The server is a transforming proxy that received a 200 OK\n * from the origin server but is returning a modified version of the origins response.\n */\n Success_203_Non_Authoritative_Information: 203,\n\n /**\n * 204 No Content: The server successfully processed the request and is not returning any content.\n */\n Success_204_No_Content: 204,\n\n /**\n * 205 Reset Content: The server successfully processed the request,\n * asks that the client reset its document view, and is not returning any content.\n */\n Success_205_Reset_Content: 205,\n\n /**\n * 206 Partial Content: The server is delivering only part of the resource due to a range header sent by the client.\n */\n Success_206_Partial_Content: 206,\n\n /**\n * 207 Multi-Status: The message body that follows is an XML message\n * and can contain a number of separate response codes, depending on how many sub-requests were made.\n */\n Success_207_Multi_Status: 207,\n\n /**\n * 208 Already Reported: The members of a DAV binding have already been enumerated\n * in a preceding part of the (multi-status) response, and are not being included again.\n */\n Success_208_Already_Reported: 208,\n\n /**\n * 226 IM Used: The server has fulfilled a request for the resource, and the response is a representation\n * of the result of one or more instance-manipulations applied to the current instance.\n */\n Success_226_IM_Used: 226,\n\n /**\n * 300 Multiple Choices: The request has more than one possible response.\n */\n Redirect_300_Multiple_Choices: 300,\n\n /**\n * 301 Moved Permanently: The URL of the requested resource has been changed permanently.\n */\n Redirect_301_Moved_Permanently: 301,\n\n /**\n * 302 Found: The URL of the requested resource has been changed temporarily.\n */\n Redirect_302_Found: 302,\n\n /**\n * 303 See Other: The response to the request can be found under another URI using a GET method.\n */\n Redirect_303_See_Other: 303,\n\n /**\n * 304 Not Modified: The resource has not been modified since the version specified\n * by the request headers If-Modified-Since or If-None-Match.\n */\n Redirect_304_Not_Modified: 304,\n\n /**\n * 305 Use Proxy: The requested resource is only available through a proxy, the address for which is provided in the response.\n */\n Redirect_305_Use_Proxy: 305,\n\n /**\n * 306 Switch Proxy: No longer used. Originally meant \"Subsequent requests should use the specified proxy.\"\n */\n Redirect_306_Switch_Proxy: 306,\n\n /**\n * 307 Temporary Redirect: The server sends this response to direct the client\n * to get the requested resource at another URI with the same method that was used in the prior request.\n */\n Redirect_307_Temporary_Redirect: 307,\n\n /**\n * 308 Permanent Redirect: This means that the resource is now permanently located at another URI,\n * specified by the Location: HTTP Response header.\n */\n Redirect_308_Permanent_Redirect: 308,\n\n /**\n * 400 Bad Request: The server cannot or will not process the request due to something that is perceived to be a client error.\n */\n Error_Client_400_Bad_Request: 400,\n\n /**\n * 401 Unauthorized: The request has not been applied because it lacks valid authentication credentials for the target resource.\n */\n Error_Client_401_Unauthorized: 401,\n\n /**\n * 402 Payment Required: Reserved for future use.\n */\n Error_Client_402_Payment_Required: 402,\n\n /**\n * 403 Forbidden: The client does not have access rights to the content, so the server is refusing to give the requested resource.\n */\n Error_Client_403_Forbidden: 403,\n\n /**\n * 404 Not Found: The server can not find the requested resource.\n */\n Error_Client_404_Not_Found: 404,\n\n /**\n * 405 Method Not Allowed: The request method is known by the server but is not supported by the target resource.\n */\n Error_Client_405_Method_Not_Allowed: 405,\n\n /**\n * 406 Not Acceptable: The target resource does not have a current representation that would be acceptable\n * to the user agent, according to the proactive negotiation header fields received in the request,\n * and the server is unwilling to supply a default representation.\n */\n Error_Client_406_Not_Acceptable: 406,\n\n /**\n * 407 Proxy Authentication Required: Similar to 401 Unauthorized,\n * but it indicates that the client needs to authenticate itself in order to use a proxy.\n */\n Error_Client_407_Proxy_Authentication_Required: 407,\n\n /**\n * 408 Request Timeout: The server timed out waiting for the request.\n */\n Error_Client_408_Request_Timeout: 408,\n\n /**\n * 409 Conflict: The request could not be processed because of conflict in the request, such as an edit conflict.\n */\n Error_Client_409_Conflict: 409,\n\n /**\n * 410 Gone: The requested resource is no longer available and will not be available again.\n */\n Error_Client_410_Gone: 410,\n\n /**\n * 411 Length Required: The server refuses to accept the request without a defined Content-Length header.\n */\n Error_Client_411_Length_Required: 411,\n\n /**\n * 412 Precondition Failed: One or more conditions given in the request header fields evaluated to false when tested on the server.\n */\n Error_Client_412_Precondition_Failed: 412,\n\n /**\n * 413 Payload Too Large: The server is refusing to process a request because the request payload is larger\n * than the server is willing or able to process.\n */\n Error_Client_413_Payload_Too_Large: 413,\n\n /**\n * 414 URI Too Long: The server is refusing to service the request because the URI is longer than the server is willing to interpret.\n */\n Error_Client_414_URI_Too_Long: 414,\n\n /**\n * 415 Unsupported Media Type: The server is refusing to service the request\n * because the entity of the request is in a format not supported by the requested resource for the requested method.\n */\n Error_Client_415_Unsupported_Media_Type: 415,\n\n /**\n * 416 Range Not Satisfiable: The client has asked for a portion of the file, but the server cannot supply that portion.\n */\n Error_Client_416_Range_Not_Satisfiable: 416,\n\n /**\n * 417 Expectation Failed: The server cannot meet the requirements of the Expect request-header field.\n */\n Error_Client_417_Expectation_Failed: 417,\n\n /**\n * 421 Misdirected Request: The request was directed at a server that is not able to produce a response.\n */\n Error_Client_421_Misdirected_Request: 421,\n\n /**\n * 422 Unprocessable Entity: The request was well-formed but was unable to be followed due to semantic errors.\n */\n Error_Client_422_Unprocessable_Entity: 422,\n\n /**\n * 423 Locked: The resource that is being accessed is locked.\n */\n Error_Client_423_Locked: 423,\n\n /**\n * 424 Failed Dependency: The request failed due to a failure of a previous request.\n */\n Error_Client_424_Failed_Dependency: 424,\n\n /**\n * 425 Too Early: The server is unwilling to risk processing a request that might be replayed.\n */\n Error_Client_425_Too_Early: 425,\n\n /**\n * 426 Upgrade Required: The server refuses to perform the request using the current protocol\n * but might be willing to do so after the client upgrades to a different protocol.\n */\n Error_Client_426_Upgrade_Required: 426,\n\n /**\n * 428 Precondition Required: The origin server requires the request to be conditional.\n */\n Error_Client_428_Precondition_Required: 428,\n\n /**\n * 429 Too Many Requests: The user has sent too many requests in a given amount of time (\"rate limiting\").\n */\n Error_Client_429_Too_Many_Requests: 429,\n\n /**\n * 431 Request Header Fields Too Large: The server is unwilling to process the request because its header fields are too large.\n */\n Error_Client_431_Request_Header_Fields_Too_Large: 431,\n\n /**\n * 451 Unavailable For Legal Reasons: The user requests an illegal resource, such as a web page censored by a government.\n */\n Error_Client_451_Unavailable_For_Legal_Reasons: 451,\n\n /**\n * 500 Internal Server Error: A generic error message, given when no more specific message is suitable.\n */\n Error_Server_500_Internal_Server_Error: 500,\n\n /**\n * 501 Not Implemented: The server either does not recognize the request method, or it lacks the ability to fulfill the request.\n */\n Error_Server_501_Not_Implemented: 501,\n\n /**\n * 502 Bad Gateway: The server was acting as a gateway or proxy and received an invalid response from the upstream server.\n */\n Error_Server_502_Bad_Gateway: 502,\n\n /**\n * 503 Service Unavailable: The server is currently unavailable (because it is overloaded or down for maintenance).\n */\n Error_Server_503_Service_Unavailable: 503,\n\n /**\n * 504 Gateway Timeout: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.\n */\n Error_Server_504_Gateway_Timeout: 504,\n\n /**\n * 505 HTTP Version Not Supported: The server does not support the HTTP protocol version used in the request.\n */\n Error_Server_505_HTTP_Version_Not_Supported: 505,\n\n /**\n * 506 Variant Also Negotiates: Transparent content negotiation for the request results in a circular reference.\n */\n Error_Server_506_Variant_Also_Negotiates: 506,\n\n /**\n * 507 Insufficient Storage: The server is unable to store the representation needed to complete the request.\n */\n Error_Server_507_Insufficient_Storage: 507,\n\n /**\n * 508 Loop Detected: The server detected an infinite loop while processing the request.\n */\n Error_Server_508_Loop_Detected: 508,\n\n /**\n * 510 Not Extended: Further extensions to the request are required for the server to fulfill it.\n */\n Error_Server_510_Not_Extended: 510,\n\n /**\n * 511 Network Authentication Required: The client needs to authenticate to gain network access.\n */\n Error_Server_511_Network_Authentication_Required: 511\n} as const;\n\nexport const HttpStatusMessages = {\n 100: 'Continue',\n 101: 'Switching Protocols',\n 102: 'Processing',\n 103: 'Early Hints',\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 203: 'Non-Authoritative Information',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 207: 'Multi-Status',\n 208: 'Already Reported',\n 226: 'IM Used',\n 300: 'Multiple Choices',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 305: 'Use Proxy',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 407: 'Proxy Authentication Required',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 417: 'Expectation Failed',\n 418: 'I\\'m a Teapot',\n 421: 'Misdirected Request',\n 422: 'Unprocessable Entity',\n 423: 'Locked',\n 424: 'Failed Dependency',\n 425: 'Too Early',\n 426: 'Upgrade Required',\n 428: 'Precondition Required',\n 429: 'Too Many Requests',\n 431: 'Request Header Fields Too Large',\n 451: 'Unavailable For Legal Reasons',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n 506: 'Variant Also Negotiates',\n 507: 'Insufficient Storage',\n 508: 'Loop Detected',\n 509: 'Bandwidth Limit Exceeded',\n 510: 'Not Extended',\n 511: 'Network Authentication Required',\n};\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessages;\n", "import {createLogger} from '@alwatr/logger';\n\nimport {type HttpStatusCode, HttpStatusCodes, HttpStatusMessages} from './const.js';\n\nimport type {NanotronClientRequest} from './api-client-request.js';\nimport type {HttpResponseHeaders, ErrorResponse, NativeServerResponse} from './type.js';\nimport type {Json} from '@alwatr/type-helper';\n\n/**\n * Configuration options for the Nanotron Api Server Response.\n */\nexport interface NanotronServerResponseConfig {\n clientRequest: NanotronClientRequest;\n}\n\nexport class NanotronServerResponse {\n readonly clientRequest: NanotronClientRequest;\n\n readonly raw_: NativeServerResponse;\n\n readonly headers: HttpResponseHeaders;\n\n protected readonly logger_;\n\n protected hasBeenSent_ = false;\n get hasBeenSent(): boolean {\n return this.hasBeenSent_;\n }\n\n constructor(nanotronClientRequest: NanotronClientRequest, nativeServerResponse: NativeServerResponse) {\n // Store public properties.\n this.clientRequest = nanotronClientRequest;\n this.raw_ = nativeServerResponse;\n\n // Create logger.\n this.logger_ = createLogger('nt-server-response'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', this.clientRequest.url.debugId);\n\n // Set default reply headers.\n this.headers = {\n server: 'Alwatr Nanotron',\n 'content-type': 'text/plain',\n };\n }\n\n get statusCode(): HttpStatusCode {\n return this.raw_.statusCode as HttpStatusCode;\n }\n\n set statusCode(value: HttpStatusCode) {\n this.raw_.statusCode = value;\n }\n\n protected applyHeaders_() {\n this.logger_.logMethodArgs?.('applyHeaders_', this.headers);\n for (const key in this.headers) {\n this.raw_.setHeader(key, this.headers[key as Lowercase<string>]!);\n }\n }\n\n replyErrorResponse(errorResponse: ErrorResponse): void {\n this.logger_.logMethod?.('replyErrorResponse');\n this.clientRequest.terminatedHandlers = true;\n this.replyJson(errorResponse);\n }\n\n replyError(error?: Error | string | Json | unknown): void {\n this.logger_.logMethodArgs?.('replyError', {error});\n\n this.clientRequest.terminatedHandlers = true;\n let statusCode = this.statusCode;\n\n if (statusCode < HttpStatusCodes.Error_Client_400_Bad_Request) {\n this.statusCode = statusCode = 500;\n }\n\n if (error instanceof Error) {\n this.replyJson({\n ok: false,\n errorCode: error.name === 'Error' ? (('error_' + statusCode) as Lowercase<string>) : (error.name + '').toLowerCase(),\n errorMessage: error.message,\n });\n }\n else if (typeof error === 'string') {\n this.replyJson({\n ok: false,\n errorCode: ('error_' + statusCode) as Lowercase<string>,\n errorMessage: error,\n });\n }\n else if (typeof error === 'object' && error !== null) {\n this.replyJson(error as Json);\n }\n else {\n this.replyJson({\n ok: false,\n errorCode: ('error_' + statusCode) as Lowercase<string>,\n errorMessage: HttpStatusMessages[statusCode],\n } as ErrorResponse);\n }\n }\n\n replyJson(responseJson: Json): void {\n this.logger_.logMethodArgs?.('replyJson', {responseJson});\n\n let responseString: string;\n try {\n responseString = JSON.stringify(responseJson);\n }\n catch (error) {\n this.logger_.error('replyJson', 'reply_json_stringify_failed', error, this.clientRequest.url.debugId);\n this.statusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n responseString = JSON.stringify({\n ok: false,\n errorCode: 'reply_json_stringify_failed',\n errorMessage: 'Failed to stringify response JSON.',\n } as ErrorResponse);\n }\n\n this.headers['content-type'] = 'application/json';\n this.reply(responseString);\n }\n\n reply(context: string | Buffer): void {\n this.logger_.logMethodArgs?.('reply', this.clientRequest.url.debugId);\n\n if (this.raw_.writableFinished && this.hasBeenSent_ === false) {\n // The response has already been sent by direct access to the server api.\n this.logger_.accident('reply', 'server_response_writable_finished_directly');\n this.hasBeenSent_ = true;\n }\n\n if (this.hasBeenSent_) {\n this.logger_.accident('reply', 'reply_already_sent', {\n url: this.clientRequest.url.debugId,\n replySent: this.hasBeenSent_,\n writableFinished: this.raw_.writableFinished,\n });\n return;\n }\n\n this.hasBeenSent_ = true;\n\n try {\n if (typeof context === 'string') {\n context = Buffer.from(context);\n }\n\n this.headers['content-length'] = context.byteLength;\n\n this.applyHeaders_();\n this.raw_.end(context, 'binary');\n }\n catch (error) {\n this.logger_.error('reply', 'server_response_error', error, this.clientRequest.url.debugId);\n this.hasBeenSent_ = false;\n }\n }\n}\n", "import {createLogger} from '@alwatr/logger';\n\nimport {NanotronServerResponse} from './api-server-response.js';\n\nimport type {DefineRouteOption, NativeClientRequest, NativeServerResponse} from './type.js';\nimport type {NanotronUrl} from './url.js';\nimport type {Dictionary} from '@alwatr/type-helper';\n\nexport class NanotronClientRequest {\n readonly url: NanotronUrl;\n\n readonly serverResponse: NanotronServerResponse;\n\n readonly routeOption: DefineRouteOption | null;\n\n /**\n * A flag to indicate if the running handlers queue has been terminated.\n * This can occur due to an error being thrown or by explicitly calling the `replyError` method.\n *\n * When `terminatedHandlers` is set to `true`, it signifies that the execution of the current\n * sequence of handlers (including pre, main, and post handlers) has been halted and no further\n * handlers in the queue will be executed.\n *\n * Usage:\n * - Check this flag to determine if the handlers queue has been interrupted.\n * - Set this flag to `true` to manually stop the execution of subsequent handlers.\n */\n terminatedHandlers?: true;\n\n readonly sharedMeta: Dictionary = {};\n\n readonly raw_: NativeClientRequest;\n\n protected readonly logger_;\n\n constructor(\n url: NanotronUrl,\n nativeClientRequest: NativeClientRequest,\n nativeServerResponse: NativeServerResponse,\n routeOption: DefineRouteOption | null,\n ) {\n // Store public properties.\n this.raw_ = nativeClientRequest;\n this.url = url;\n this.routeOption = routeOption;\n\n // Create logger.\n this.logger_ = createLogger('nt-client-request'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', url.debugId);\n\n // Create server response.\n this.serverResponse = new NanotronServerResponse(this, nativeServerResponse);\n }\n}\n", "import {URL} from 'node:url';\n\nimport type {HttpMethod} from './type.js';\nimport type {IncomingMessage} from 'node:http';\n\nexport class NanotronUrl extends URL {\n protected static versionPattern_ = new RegExp('^/v[0-9]+/');\n\n readonly method: HttpMethod;\n readonly debugId: string;\n\n constructor(clientRequest: IncomingMessage, prefix: `/${string}/` | '/') {\n let url = clientRequest.url ?? '';\n if (prefix !== '/' && url.indexOf(prefix) === 0) {\n url = url.slice(prefix.length - 1); // include `/`\n }\n url = url.replace(NanotronUrl.versionPattern_, '/');\n\n super(url, 'http://hostname/');\n\n this.method = (clientRequest.method ?? 'GET').toUpperCase() as HttpMethod;\n\n this.debugId = `[${this.method}]${this.pathname}`;\n }\n}\n", "import {createServer} from 'node:http';\n\nimport {createLogger} from '@alwatr/logger';\n\nimport {NanotronClientRequest} from './api-client-request.js';\nimport {HttpStatusCodes} from './const.js';\nimport {NanotronUrl} from './url.js';\n\nimport type {DefineRouteOption, MatchType, NativeClientRequest, NativeServerResponse} from './type.js';\nimport type {Dictionary} from '@alwatr/type-helper';\nimport type {Duplex} from 'node:stream';\n\n/**\n * Configuration options for the NanotronApiServer.\n */\nexport interface NanotronApiServerConfig {\n /**\n * The port number to listen on.\n *\n * @default 80\n */\n port?: number;\n\n /**\n * The hostname to listen on.\n *\n * @default '0.0.0.0'\n */\n host?: string;\n\n /**\n * Sets the timeout (ms) for receiving the entire request from the client.\n *\n * @default 10_000 ms\n */\n requestTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * This should be bigger than `keepAliveTimeout + your server's expected response time`.\n *\n * @default 130_000 ms\n */\n headersTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * @default 120_000 ms\n */\n keepAliveTimeout?: number;\n\n /**\n * Add /health route.\n *\n * @default true\n */\n healthRoute?: boolean;\n\n /**\n * Add OPTIONS route for preflight requests to allow access all origins.\n *\n * @default false\n */\n allowAllOrigin?: boolean;\n\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix?: `/${string}/` | '/';\n\n /**\n * The maximum size of the request body in bytes.\n *\n * @default `1_048_576` (1MiB)\n */\n bodyLimit?: number;\n}\n\nexport class NanotronApiServer {\n protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>> = {\n host: '0.0.0.0',\n port: 80,\n requestTimeout: 10_000,\n headersTimeout: 130_000,\n keepAliveTimeout: 120_000,\n healthRoute: true,\n allowAllOrigin: false,\n prefix: '/api/',\n bodyLimit: 1_048_576, // 1MiB\n };\n\n readonly config_;\n protected readonly logger_;\n\n readonly httpServer;\n\n protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;\n\n constructor(config?: Partial<NanotronApiServerConfig>) {\n // Merge the config with the default config.\n this.config_ = {\n ...NanotronApiServer.defaultConfig_,\n ...config,\n };\n\n // Create logger.\n this.logger_ = createLogger('nt-api-server' + (this.config_.port !== 80 ? ':' + this.config_.port : ''));\n this.logger_.logMethodArgs?.('new', {config: this.config_});\n\n // Bind methods.\n this.handleClientRequest_ = this.handleClientRequest_.bind(this);\n this.handleServerError_ = this.handleServerError_.bind(this);\n this.handleClientError_ = this.handleClientError_.bind(this);\n\n // Initialize route handler list.\n this.routeHandlerList__ = {\n exact: {},\n startsWith: {},\n };\n\n // Create the HTTP server.\n this.httpServer = createServer(\n {\n keepAlive: true,\n keepAliveInitialDelay: 0,\n noDelay: true,\n },\n this.handleClientRequest_,\n );\n\n // Configure the server.\n this.httpServer.requestTimeout = this.config_.requestTimeout;\n this.httpServer.keepAliveTimeout = this.config_.keepAliveTimeout;\n this.httpServer.headersTimeout = this.config_.headersTimeout;\n\n // Start the server.\n this.httpServer.listen(this.config_.port, this.config_.host, () => {\n this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`);\n });\n\n // Handle server errors.\n this.httpServer.on('error', this.handleServerError_);\n this.httpServer.on('clientError', this.handleClientError_);\n }\n\n close(): void {\n this.logger_.logMethod?.('close');\n this.httpServer.close();\n }\n\n protected getRouteOption_(url: NanotronUrl): Required<DefineRouteOption> | null {\n this.logger_.logMethod?.('getRouteOption_');\n\n if (\n Object.hasOwn(this.routeHandlerList__.exact, url.method) &&\n Object.hasOwn(this.routeHandlerList__.exact[url.method], url.pathname)\n ) {\n return this.routeHandlerList__.exact[url.method][url.pathname];\n }\n\n if (Object.hasOwn(this.routeHandlerList__.startsWith, url.method)) {\n const routeList = this.routeHandlerList__.startsWith[url.method];\n for (const pathname in routeList) {\n if (pathname.indexOf(url.pathname) === 0) {\n return routeList[pathname];\n }\n }\n }\n\n this.logger_.incident?.('getRouteOption_', 'route_not_found', {method: url.method, url: url.pathname});\n return null;\n }\n\n protected setRouteOption_(option: Required<DefineRouteOption>): void {\n this.logger_.logMethodArgs?.('setRouteOption_', {...option, handler: 'function'});\n\n const routeHandlerList = this.routeHandlerList__[option.matchType];\n\n routeHandlerList[option.method] ??= {};\n\n if (Object.hasOwn(routeHandlerList[option.method], option.url)) {\n this.logger_.error('defineRoute', 'route_already_exists', {...option, handler: 'function'});\n throw new Error('route_already_exists');\n }\n\n routeHandlerList[option.method][option.url] = option;\n }\n\n defineRoute(option: DefineRouteOption): void {\n const option_: Required<DefineRouteOption> = {\n matchType: 'exact',\n preHandlers: [],\n postHandlers: [],\n bodyLimit: this.config_.bodyLimit,\n ...option,\n };\n this.logger_.logMethodArgs?.('defineRoute', {...option_, handler: 'function'});\n this.setRouteOption_(option_);\n }\n\n protected handleServerError_(err: NodeJS.ErrnoException): void {\n if (err.code === 'EADDRINUSE') {\n this.logger_.error('handleServerError_', 'address_in_use', err);\n }\n else {\n this.logger_.error('handleServerError_', 'http_server_error', err.message || 'HTTP server catch an error', err);\n }\n }\n\n protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void {\n this.logger_.accident('handleClientError_', 'http_server_client_error', {\n errCode: err.code,\n errMessage: err.message,\n });\n socket.end('HTTP/1.1 400 Bad Request\\r\\n\\r\\n');\n }\n\n protected async handleClientRequest_(\n nativeClientRequest: NativeClientRequest,\n nativeServerResponse: NativeServerResponse,\n ): Promise<void> {\n this.logger_.logMethod?.('handleClientRequest_');\n\n if (nativeClientRequest.url === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_url_undefined');\n return;\n }\n\n if (nativeClientRequest.method === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_method_undefined');\n return;\n }\n\n const url = new NanotronUrl(nativeClientRequest, this.config_.prefix);\n\n const routeOption = this.getRouteOption_(url);\n\n const connection = new NanotronClientRequest(url, nativeClientRequest, nativeServerResponse, routeOption);\n\n if (routeOption === null) {\n connection.serverResponse.statusCode = HttpStatusCodes.Error_Client_404_Not_Found;\n connection.serverResponse.replyError();\n return;\n }\n\n try {\n for (const handler of routeOption.preHandlers) {\n if (connection.terminatedHandlers === true) return;\n await handler(connection, connection.serverResponse, connection.sharedMeta);\n }\n\n await routeOption.handler(connection, connection.serverResponse, connection.sharedMeta);\n\n for (const handler of routeOption.postHandlers) {\n if (connection.terminatedHandlers === true) return;\n await handler(connection, connection.serverResponse, connection.sharedMeta);\n }\n }\n catch (error) {\n this.logger_.error('handleClientRequest_', 'route_handler_error', error, url.debugId);\n\n if (connection.serverResponse.statusCode < HttpStatusCodes.Error_Client_400_Bad_Request) {\n connection.serverResponse.statusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n }\n connection.serverResponse.replyError(error);\n }\n\n // TODO: handled open remained connections.\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "createLogger", "NanotronServerResponse", "nanotronClientRequest", "nativeServerResponse", "value", "key", "errorResponse", "error", "statusCode", "HttpStatusCodes", "HttpStatusMessages", "responseJson", "responseString", "context", "createLogger", "NanotronClientRequest", "url", "nativeClientRequest", "nativeServerResponse", "routeOption", "NanotronServerResponse", "URL", "_NanotronUrl", "clientRequest", "prefix", "url", "NanotronUrl", "createServer", "createLogger", "_NanotronApiServer", "config", "routeHandlerList__", "url", "routeList", "pathname", "option", "_a", "routeHandlerList", "option_", "err", "socket", "nativeClientRequest", "nativeServerResponse", "NanotronUrl", "routeOption", "connection", "NanotronClientRequest", "HttpStatusCodes", "handler", "error", "NanotronApiServer"]
|
|
7
7
|
}
|
package/dist/type.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { NanotronClientRequest } from './api-client-request.js';
|
|
2
|
+
import type { NanotronServerResponse } from './api-server-response.js';
|
|
3
|
+
import type { Dictionary, Json, MaybePromise } from '@alwatr/type-helper';
|
|
4
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
5
|
declare module 'http' {
|
|
4
6
|
interface IncomingHttpHeaders {
|
|
5
7
|
'x-forwarded-for'?: string;
|
|
@@ -7,6 +9,52 @@ declare module 'http' {
|
|
|
7
9
|
}
|
|
8
10
|
export type MatchType = 'exact' | 'startsWith';
|
|
9
11
|
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD' | 'CONNECT' | 'TRACE';
|
|
12
|
+
export type ErrorResponse = {
|
|
13
|
+
ok: false;
|
|
14
|
+
errorCode: Lowercase<string>;
|
|
15
|
+
errorMessage: string;
|
|
16
|
+
meta?: Json;
|
|
17
|
+
};
|
|
18
|
+
export type RouteHandler = (clientRequest: NanotronClientRequest, serverResponse: NanotronServerResponse, sharedMeta: Dictionary) => MaybePromise<void>;
|
|
19
|
+
export type NativeClientRequest = IncomingMessage;
|
|
20
|
+
export type NativeServerResponse = ServerResponse;
|
|
21
|
+
/**
|
|
22
|
+
* Configuration options for defining a route.
|
|
23
|
+
*/
|
|
24
|
+
export interface DefineRouteOption {
|
|
25
|
+
/**
|
|
26
|
+
* The HTTP method for this route.
|
|
27
|
+
*/
|
|
28
|
+
method: HttpMethod;
|
|
29
|
+
/**
|
|
30
|
+
* The URL path for this route.
|
|
31
|
+
*/
|
|
32
|
+
url: string;
|
|
33
|
+
/**
|
|
34
|
+
* Specifies how the `url` should be matched against incoming requests.
|
|
35
|
+
*
|
|
36
|
+
* @default 'exact'
|
|
37
|
+
*/
|
|
38
|
+
matchType?: MatchType;
|
|
39
|
+
/**
|
|
40
|
+
* The functions call before the main handler.
|
|
41
|
+
*/
|
|
42
|
+
preHandlers?: RouteHandler[];
|
|
43
|
+
/**
|
|
44
|
+
* The function to handle requests to this route.
|
|
45
|
+
*/
|
|
46
|
+
handler: RouteHandler;
|
|
47
|
+
/**
|
|
48
|
+
* The functions call after the main handler.
|
|
49
|
+
*/
|
|
50
|
+
postHandlers?: RouteHandler[];
|
|
51
|
+
/**
|
|
52
|
+
* The maximum size of the request body in bytes.
|
|
53
|
+
*
|
|
54
|
+
* @default `1_048_576` (1MiB) or the value set in the server configuration.
|
|
55
|
+
*/
|
|
56
|
+
bodyLimit?: number;
|
|
57
|
+
}
|
|
10
58
|
/**
|
|
11
59
|
* Represents the collection of HTTP response headers.
|
|
12
60
|
*/
|
|
@@ -18,11 +66,11 @@ export interface HttpResponseHeaders {
|
|
|
18
66
|
/**
|
|
19
67
|
* Specifies the time in seconds the object has been in a proxy cache.
|
|
20
68
|
*/
|
|
21
|
-
|
|
69
|
+
age?: string;
|
|
22
70
|
/**
|
|
23
71
|
* Lists the set of HTTP methods supported by the resource identified by the Request-URI.
|
|
24
72
|
*/
|
|
25
|
-
|
|
73
|
+
allow?: string;
|
|
26
74
|
/**
|
|
27
75
|
* Specifies caching directives for both requests and responses.
|
|
28
76
|
*/
|
|
@@ -30,7 +78,7 @@ export interface HttpResponseHeaders {
|
|
|
30
78
|
/**
|
|
31
79
|
* Controls whether the network connection stays open after the current transaction.
|
|
32
80
|
*/
|
|
33
|
-
|
|
81
|
+
connection?: string;
|
|
34
82
|
/**
|
|
35
83
|
* Suggests a filename for the downloaded resource or how the content should be displayed.
|
|
36
84
|
*/
|
|
@@ -62,15 +110,15 @@ export interface HttpResponseHeaders {
|
|
|
62
110
|
/**
|
|
63
111
|
* Indicates the date and time at which the message was originated.
|
|
64
112
|
*/
|
|
65
|
-
|
|
113
|
+
date?: string;
|
|
66
114
|
/**
|
|
67
115
|
* Provides the current value of the entity tag for the requested variant.
|
|
68
116
|
*/
|
|
69
|
-
|
|
117
|
+
etag?: string;
|
|
70
118
|
/**
|
|
71
119
|
* Gives the date/time after which the response is considered stale.
|
|
72
120
|
*/
|
|
73
|
-
|
|
121
|
+
expires?: string;
|
|
74
122
|
/**
|
|
75
123
|
* Indicates the date and time at which the origin server believes the variant was last modified.
|
|
76
124
|
*/
|
|
@@ -78,15 +126,15 @@ export interface HttpResponseHeaders {
|
|
|
78
126
|
/**
|
|
79
127
|
* Provides a list of URIs associated with the resource.
|
|
80
128
|
*/
|
|
81
|
-
|
|
129
|
+
link?: string;
|
|
82
130
|
/**
|
|
83
131
|
* Used in redirection, or when a new resource has been created.
|
|
84
132
|
*/
|
|
85
|
-
|
|
133
|
+
location?: string;
|
|
86
134
|
/**
|
|
87
135
|
* Used for backward compatibility with HTTP/1.0 caches.
|
|
88
136
|
*/
|
|
89
|
-
|
|
137
|
+
pragma?: string;
|
|
90
138
|
/**
|
|
91
139
|
* Requests authentication information from the client for a proxy server.
|
|
92
140
|
*/
|
|
@@ -98,7 +146,7 @@ export interface HttpResponseHeaders {
|
|
|
98
146
|
/**
|
|
99
147
|
* Contains information about the software used by the origin server to handle the request.
|
|
100
148
|
*/
|
|
101
|
-
|
|
149
|
+
server?: string;
|
|
102
150
|
/**
|
|
103
151
|
* Used to send cookies from the server to the user agent.
|
|
104
152
|
*/
|
|
@@ -110,7 +158,7 @@ export interface HttpResponseHeaders {
|
|
|
110
158
|
/**
|
|
111
159
|
* Allows the sender to include additional fields at the end of chunked messages.
|
|
112
160
|
*/
|
|
113
|
-
|
|
161
|
+
trailer?: string;
|
|
114
162
|
/**
|
|
115
163
|
* Specifies the form of encoding used to safely transfer the entity to the user.
|
|
116
164
|
*/
|
|
@@ -119,26 +167,19 @@ export interface HttpResponseHeaders {
|
|
|
119
167
|
* Determines how to match future request headers to decide whether a cached response
|
|
120
168
|
* can be used rather than requesting a fresh one from the origin server.
|
|
121
169
|
*/
|
|
122
|
-
|
|
170
|
+
vary?: string;
|
|
123
171
|
/**
|
|
124
172
|
* Lists all intermediate proxies the message has traversed
|
|
125
173
|
*/
|
|
126
|
-
|
|
174
|
+
via?: string;
|
|
127
175
|
/**
|
|
128
176
|
* Contains additional information about the status or transformation of a message that might not be reflected in the status code.
|
|
129
177
|
*/
|
|
130
|
-
|
|
178
|
+
warning?: string;
|
|
131
179
|
/**
|
|
132
180
|
* Indicates the authentication scheme that should be used to access the requested entity.
|
|
133
181
|
*/
|
|
134
182
|
'www-authenticate'?: string;
|
|
135
183
|
[headerName: Lowercase<string>]: string | string[] | number | undefined;
|
|
136
184
|
}
|
|
137
|
-
export type ErrorResponse = {
|
|
138
|
-
ok: false;
|
|
139
|
-
errorCode: Lowercase<string>;
|
|
140
|
-
errorMessage: string;
|
|
141
|
-
meta?: Json;
|
|
142
|
-
};
|
|
143
|
-
export type RouteHandler = (connection: NanotronApiConnection) => MaybePromise<void>;
|
|
144
185
|
//# sourceMappingURL=type.d.ts.map
|
package/dist/type.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAC,UAAU,EAAE,IAAI,EAAE,YAAY,EAAC,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAC,eAAe,EAAE,cAAc,EAAC,MAAM,WAAW,CAAC;AAE/D,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,mBAAmB;QAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B;CACF;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;AAE/C,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhH,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,KAAK,CAAC;IACV,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,aAAa,EAAE,qBAAqB,EACpC,cAAc,EAAE,sBAAsB,EACtC,UAAU,EAAE,UAAU,KACnB,YAAY,CAAC,IAAI,CAAC,CAAC;AAExB,MAAM,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAClD,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,MAAM,EAAE,UAAU,CAAC;IAEnB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAE7B;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,EAAE,CAAC;IAE9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEnC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAErC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAG5B,CAAC,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;CACzE"}
|
package/dist/url.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { URL } from 'node:url';
|
|
2
|
+
import type { HttpMethod } from './type.js';
|
|
3
|
+
import type { IncomingMessage } from 'node:http';
|
|
4
|
+
export declare class NanotronUrl extends URL {
|
|
5
|
+
protected static versionPattern_: RegExp;
|
|
6
|
+
readonly method: HttpMethod;
|
|
7
|
+
readonly debugId: string;
|
|
8
|
+
constructor(clientRequest: IncomingMessage, prefix: `/${string}/` | '/');
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,UAAU,CAAC;AAE7B,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C,qBAAa,WAAY,SAAQ,GAAG;IAClC,SAAS,CAAC,MAAM,CAAC,eAAe,SAA4B;IAE5D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,aAAa,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,MAAM,GAAG,GAAG,GAAG;CAaxE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alwatr/nanotron-api-server",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.2",
|
|
4
4
|
"description": "Nanotron: Your Lightweight, High-Performance Micro/Nano Service Framework.",
|
|
5
5
|
"author": "S. Ali Mihandoost <ali.mihandoost@gmail.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
"jest": "^29.7.0",
|
|
70
70
|
"typescript": "^5.6.2"
|
|
71
71
|
},
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "55e4345fd4f5e75b33dbbee0c92a57256c5a7e41"
|
|
73
73
|
}
|
package/dist/api-connection.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { type HttpStatusCode } from './const.js';
|
|
2
|
-
import type { HttpResponseHeaders, HttpMethod, ErrorResponse } from './type.js';
|
|
3
|
-
import type { Json } from '@alwatr/type-helper';
|
|
4
|
-
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
|
-
/**
|
|
6
|
-
* Configuration options for the NanotronApiConnection.
|
|
7
|
-
*/
|
|
8
|
-
export interface NanotronApiConnectionConfig {
|
|
9
|
-
/**
|
|
10
|
-
* A prefix to be added to the beginning of the `url` of all defined routes.
|
|
11
|
-
*
|
|
12
|
-
* @default '/api/'
|
|
13
|
-
*/
|
|
14
|
-
prefix: `/${string}/` | '/';
|
|
15
|
-
}
|
|
16
|
-
export declare class NanotronApiConnection {
|
|
17
|
-
incomingMessage: IncomingMessage;
|
|
18
|
-
serverResponse: ServerResponse;
|
|
19
|
-
protected config_: NanotronApiConnectionConfig;
|
|
20
|
-
protected static versionPattern_: RegExp;
|
|
21
|
-
readonly url: URL;
|
|
22
|
-
readonly method: HttpMethod;
|
|
23
|
-
protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
|
|
24
|
-
readonly replyHeaders: HttpResponseHeaders;
|
|
25
|
-
protected replySent_: boolean;
|
|
26
|
-
get replySent(): boolean;
|
|
27
|
-
constructor(incomingMessage: IncomingMessage, serverResponse: ServerResponse, config_: NanotronApiConnectionConfig);
|
|
28
|
-
get replyStatusCode(): HttpStatusCode;
|
|
29
|
-
set replyStatusCode(value: HttpStatusCode);
|
|
30
|
-
protected applyReplyHeaders_(): void;
|
|
31
|
-
replyJsonError(errorResponse: ErrorResponse): void;
|
|
32
|
-
replyJson(responseJson: Json): void;
|
|
33
|
-
replyError(error?: Error | unknown): void;
|
|
34
|
-
reply(context: string | Buffer): void;
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=api-connection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api-connection.d.ts","sourceRoot":"","sources":["../src/api-connection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,cAAc,EAAsC,MAAM,YAAY,CAAC;AAEpF,OAAO,KAAK,EAAC,mBAAmB,EAAE,UAAU,EAAE,aAAa,EAAC,MAAM,WAAW,CAAC;AAC9E,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAAC,eAAe,EAAE,cAAc,EAAC,MAAM,WAAW,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,MAAM,EAAE,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;CAC7B;AAED,qBAAa,qBAAqB;IAiBvB,eAAe,EAAE,eAAe;IAChC,cAAc,EAAE,cAAc;IACrC,SAAS,CAAC,OAAO,EAAE,2BAA2B;IAlBhD,SAAS,CAAC,MAAM,CAAC,eAAe,SAA4B;IAE5D,QAAQ,CAAC,GAAG,MAAC;IAEb,QAAQ,CAAC,MAAM,aAAC;IAEhB,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAC;IAE3B,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAE3C,SAAS,CAAC,UAAU,UAAS;IAC7B,IAAI,SAAS,IAAI,OAAO,CAEvB;gBAGQ,eAAe,EAAE,eAAe,EAChC,cAAc,EAAE,cAAc,EAC3B,OAAO,EAAE,2BAA2B;IAwBhD,IAAI,eAAe,IAAI,cAAc,CAEpC;IAED,IAAI,eAAe,CAAC,KAAK,EAAE,cAAc,EAExC;IAED,SAAS,CAAC,kBAAkB;IAO5B,cAAc,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI;IAKlD,SAAS,CAAC,YAAY,EAAE,IAAI,GAAG,IAAI;IAwBnC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI;IAqBzC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CA6BtC"}
|