@alwatr/nanotron-api-server 4.0.0-alpha.1 → 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 CHANGED
@@ -3,6 +3,22 @@
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.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
+
6
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)
7
23
 
8
24
  ### ⚠ BREAKING CHANGES
@@ -1,21 +1,11 @@
1
- import type { HttpMethod, RouteHandler } from './type.js';
2
- import type { IncomingMessage } from 'node:http';
3
- /**
4
- * Configuration options for the Nanotron Api Client Request.
5
- */
6
- export interface NanotronClientRequestConfig {
7
- /**
8
- * A prefix to be added to the beginning of the `url` of all defined routes.
9
- *
10
- * @default '/api/'
11
- */
12
- prefix: `/${string}/` | '/';
13
- }
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';
14
5
  export declare class NanotronClientRequest {
15
- protected static versionPattern_: RegExp;
16
- readonly url: URL;
17
- readonly method: HttpMethod;
18
- readonly raw_: IncomingMessage;
6
+ readonly url: NanotronUrl;
7
+ readonly serverResponse: NanotronServerResponse;
8
+ readonly routeOption: DefineRouteOption | null;
19
9
  /**
20
10
  * A flag to indicate if the running handlers queue has been terminated.
21
11
  * This can occur due to an error being thrown or by explicitly calling the `replyError` method.
@@ -29,9 +19,9 @@ export declare class NanotronClientRequest {
29
19
  * - Set this flag to `true` to manually stop the execution of subsequent handlers.
30
20
  */
31
21
  terminatedHandlers?: true;
32
- readonly preHandlers_: RouteHandler[];
22
+ readonly sharedMeta: Dictionary;
23
+ readonly raw_: NativeClientRequest;
33
24
  protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
34
- protected readonly config_: NanotronClientRequestConfig;
35
- constructor(clientRequest: IncomingMessage, config: NanotronClientRequestConfig);
25
+ constructor(url: NanotronUrl, nativeClientRequest: NativeClientRequest, nativeServerResponse: NativeServerResponse, routeOption: DefineRouteOption | null);
36
26
  }
37
27
  //# sourceMappingURL=api-client-request.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-client-request.d.ts","sourceRoot":"","sources":["../src/api-client-request.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAE,YAAY,EAAC,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,MAAM,EAAE,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;CAC7B;AAED,qBAAa,qBAAqB;IAChC,SAAS,CAAC,MAAM,CAAC,eAAe,SAA4B;IAE5D,QAAQ,CAAC,GAAG,MAAC;IAEb,QAAQ,CAAC,MAAM,aAAC;IAEhB,QAAQ,CAAC,IAAI,kBAAC;IAEd;;;;;;;;;;;OAWG;IACH,kBAAkB,CAAC,EAAE,IAAI,CAAC;IAE1B,QAAQ,CAAC,YAAY,EAAE,YAAY,EAAE,CAAM;IAE3C,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAC;IAE3B,SAAS,CAAC,QAAQ,CAAC,OAAO,8BAAC;gBAGzB,aAAa,EAAE,eAAe,EAC9B,MAAM,EAAE,2BAA2B;CAqBtC"}
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"}
@@ -1,8 +1,7 @@
1
1
  import { type HttpStatusCode } from './const.js';
2
2
  import type { NanotronClientRequest } from './api-client-request.js';
3
- import type { HttpResponseHeaders, ErrorResponse } from './type.js';
3
+ import type { HttpResponseHeaders, ErrorResponse, NativeServerResponse } from './type.js';
4
4
  import type { Json } from '@alwatr/type-helper';
5
- import type { ServerResponse } from 'node:http';
6
5
  /**
7
6
  * Configuration options for the Nanotron Api Server Response.
8
7
  */
@@ -10,13 +9,13 @@ export interface NanotronServerResponseConfig {
10
9
  clientRequest: NanotronClientRequest;
11
10
  }
12
11
  export declare class NanotronServerResponse {
13
- readonly raw_: ServerResponse<import("http").IncomingMessage>;
12
+ readonly clientRequest: NanotronClientRequest;
13
+ readonly raw_: NativeServerResponse;
14
14
  readonly headers: HttpResponseHeaders;
15
15
  protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
16
- protected readonly config_: NanotronServerResponseConfig;
17
16
  protected hasBeenSent_: boolean;
18
17
  get hasBeenSent(): boolean;
19
- constructor(serverResponse: ServerResponse, config: NanotronServerResponseConfig);
18
+ constructor(nanotronClientRequest: NanotronClientRequest, nativeServerResponse: NativeServerResponse);
20
19
  get statusCode(): HttpStatusCode;
21
20
  set statusCode(value: HttpStatusCode);
22
21
  protected applyHeaders_(): void;
@@ -1 +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,EAAC,MAAM,WAAW,CAAC;AAClE,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,WAAW,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,qBAAqB,CAAC;CACtC;AAED,qBAAa,sBAAsB;IACjC,QAAQ,CAAC,IAAI,iDAAC;IAEd,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IAEtC,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAC;IAE3B,SAAS,CAAC,QAAQ,CAAC,OAAO,+BAAC;IAE3B,SAAS,CAAC,YAAY,UAAS;IAC/B,IAAI,WAAW,IAAI,OAAO,CAEzB;gBAGC,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,4BAA4B;IAiBtC,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;IAyCzD,SAAS,CAAC,YAAY,EAAE,IAAI,GAAG,IAAI;IAwBnC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CA2CtC"}
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"}
@@ -1,6 +1,5 @@
1
- import { IncomingMessage, ServerResponse } from 'node:http';
2
- import { NanotronServerResponse } from './api-server-response.js';
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,41 +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
59
  /**
74
- * Specifies how the `url` should be matched against incoming requests.
60
+ * The maximum size of the request body in bytes.
75
61
  *
76
- * @default 'exact'
77
- */
78
- matchType?: MatchType;
79
- /**
80
- * The functions call before the main handler.
81
- */
82
- preHandlers?: RouteHandler[];
83
- /**
84
- * The function to handle requests to this route.
85
- */
86
- handler: RouteHandler;
87
- /**
88
- * The functions call after the main handler.
62
+ * @default `1_048_576` (1MiB)
89
63
  */
90
- postHandlers?: RouteHandler[];
64
+ bodyLimit?: number;
91
65
  }
92
66
  export declare class NanotronApiServer {
93
67
  protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>>;
94
- protected readonly config_: {
68
+ readonly config_: {
95
69
  port: number;
96
70
  host: string;
97
71
  requestTimeout: number;
@@ -100,18 +74,18 @@ export declare class NanotronApiServer {
100
74
  healthRoute: boolean;
101
75
  allowAllOrigin: boolean;
102
76
  prefix: `/${string}/` | "/";
77
+ bodyLimit: number;
103
78
  };
104
79
  protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
105
- readonly httpServer: import("http").Server<typeof IncomingMessage, typeof ServerResponse>;
80
+ readonly httpServer: import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
106
81
  protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;
107
82
  constructor(config?: Partial<NanotronApiServerConfig>);
108
83
  close(): void;
109
- protected getRouteOption_(option: Required<Pick<DefineRouteOption, 'method' | 'url'>>): Required<DefineRouteOption> | null;
84
+ protected getRouteOption_(url: NanotronUrl): Required<DefineRouteOption> | null;
110
85
  protected setRouteOption_(option: Required<DefineRouteOption>): void;
111
86
  defineRoute(option: DefineRouteOption): void;
112
87
  protected handleServerError_(err: NodeJS.ErrnoException): void;
113
88
  protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void;
114
- protected handleHttpError_(serverResponse: NanotronServerResponse, error?: unknown): void;
115
- protected handleClientRequest_(clientRequest: IncomingMessage, serverResponse: ServerResponse): Promise<void>;
89
+ protected handleClientRequest_(nativeClientRequest: NativeClientRequest, nativeServerResponse: NativeServerResponse): Promise<void>;
116
90
  }
117
91
  //# sourceMappingURL=api-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-server.d.ts","sourceRoot":"","sources":["../src/api-server.ts"],"names":[],"mappings":"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"}
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.1 */
2
- "use strict";var u=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var v=(n,e)=>{for(var t in e)u(n,t,{get:e[t],enumerable:!0})},T=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of C(e))!S.call(n,o)&&o!==t&&u(n,o,{get:()=>e[o],enumerable:!(r=E(e,o))||r.enumerable});return n};var q=n=>T(u({},"__esModule",{value:!0}),n);var w={};v(w,{HttpMethods:()=>H,HttpStatusCodes:()=>s,HttpStatusMessages:()=>c,NanotronApiServer:()=>g,NanotronClientRequest:()=>a,NanotronServerResponse:()=>_});module.exports=q(w);var f=require("@alwatr/logger"),h=class h{constructor(e,t){this.preHandlers_=[];this.config_=t,this.raw_=e,this.method=(this.raw_.method??"GET").toUpperCase();let r=this.raw_.url??"";this.config_.prefix!=="/"&&r.indexOf(this.config_.prefix)===0&&(r=r.slice(this.config_.prefix.length-1)),r=r.replace(h.versionPattern_,"/"),this.url=new URL(r,"http://hostname/"),this.logger_=(0,f.createLogger)("nt-client-request"),this.logger_.logMethodArgs?.("new",{method:this.method,url:this.url.pathname})}};h.versionPattern_=new RegExp("^/v[0-9]+/");var a=h;var H={GET:"GET",HEAD:"HEAD",POST:"POST",PUT:"PUT",DELETE:"DELETE",CONNECT:"CONNECT",OPTIONS:"OPTIONS",TRACE:"TRACE",PATCH:"PATCH"},s={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 m=require("@alwatr/logger"),_=class{constructor(e,t){this.hasBeenSent_=!1;this.config_=t,this.raw_=e,this.logger_=(0,m.createLogger)("nt-server-response"),this.logger_.logMethod?.("new"),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.config_.clientRequest.terminatedHandlers=!0,this.replyJson(e)}replyError(e){this.logger_.logMethodArgs?.("replyError",{error:e}),this.config_.clientRequest.terminatedHandlers=!0;let t=this.statusCode;t<s.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,{url:this.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method}),this.statusCode=s.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",{url:this.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method}),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.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method,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,{url:this.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method}),this.hasBeenSent_=!1}}};var R=require("node:http"),y=require("@alwatr/logger"),p=class p{constructor(e){this.config_={...p.defaultConfig_,...e},this.logger_=(0,y.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,R.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_.logMethodArgs?.("getRouteOption_",e),Object.hasOwn(this.e.exact,e.method)&&Object.hasOwn(this.e.exact[e.method],e.url))return this.e.exact[e.method][e.url];if(Object.hasOwn(this.e.startsWith,e.method)){let t=this.e.startsWith[e.method];for(let r in t)if(r.indexOf(e.url)===0)return t[r]}return this.logger_.incident?.("getRouteOption_","route_not_found",e),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:[],...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
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
- `)}handleHttpError_(e,t){this.logger_.logMethod?.("handleHttpError_"),e.replyError(t)}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 a(e,{prefix:this.config_.prefix}),o=new _(t,{clientRequest:r}),l=this.getRouteOption_({method:r.method,url:r.url.pathname});if(l===null)return o.statusCode=s.Error_Client_404_Not_Found,this.handleHttpError_(o);let d={};try{for(let i of r.preHandlers_){if(r.terminatedHandlers===!0)return;await i(r,o,d)}for(let i of l.preHandlers){if(r.terminatedHandlers===!0)return;await i(r,o,d)}await l.handler(r,o,d);for(let i of l.postHandlers){if(r.terminatedHandlers===!0)return;await i(r,o,d)}}catch(i){this.logger_.error("handleClientRequest_","route_handler_error",i,{url:r.url.pathname,method:r.method}),o.statusCode<s.Error_Client_400_Bad_Request&&(o.statusCode=s.Error_Server_500_Internal_Server_Error),this.handleHttpError_(o,i)}}};p.defaultConfig_={host:"0.0.0.0",port:80,requestTimeout:1e4,headersTimeout:13e4,keepAliveTimeout:12e4,healthRoute:!0,allowAllOrigin:!1,prefix:"/api/"};var g=p;0&&(module.exports={HttpMethods,HttpStatusCodes,HttpStatusMessages,NanotronApiServer,NanotronClientRequest,NanotronServerResponse});
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/api-client-request.ts", "../src/const.ts", "../src/api-server-response.ts", "../src/api-server.ts"],
4
- "sourcesContent": ["export * from './api-server.js';\nexport * from './api-client-request.js';\nexport * from './api-server-response.js';\nexport * from './type.js';\nexport * from './const.js';\n", "import {createLogger} from '@alwatr/logger';\n\nimport type {HttpMethod, RouteHandler} from './type.js';\nimport type {IncomingMessage} from 'node:http';\n\n/**\n * Configuration options for the Nanotron Api Client Request.\n */\nexport interface NanotronClientRequestConfig {\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 NanotronClientRequest {\n protected static versionPattern_ = new RegExp('^/v[0-9]+/');\n\n readonly url;\n\n readonly method;\n\n readonly raw_;\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 preHandlers_: RouteHandler[] = [];\n\n protected readonly logger_;\n\n protected readonly config_;\n\n constructor(\n clientRequest: IncomingMessage,\n config: NanotronClientRequestConfig,\n ) {\n // Store the raw request object and configuration.\n this.config_ = config;\n this.raw_ = clientRequest;\n\n // Parse request method.\n this.method = (this.raw_.method ?? 'GET').toUpperCase() as HttpMethod;\n\n // Parse request URL.\n let url = this.raw_.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(NanotronClientRequest.versionPattern_, '/');\n this.url = new URL(url, 'http://hostname/');\n\n // Create logger.\n this.logger_ = createLogger('nt-client-request'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', {method: this.method, url: this.url.pathname});\n }\n}\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} from './type.js';\nimport type {Json} from '@alwatr/type-helper';\nimport type {ServerResponse} from 'node:http';\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 raw_;\n\n readonly headers: HttpResponseHeaders;\n\n protected readonly logger_;\n\n protected readonly config_;\n\n protected hasBeenSent_ = false;\n get hasBeenSent(): boolean {\n return this.hasBeenSent_;\n }\n\n constructor(\n serverResponse: ServerResponse,\n config: NanotronServerResponseConfig,\n ) {\n // Store the raw request object and configuration.\n this.config_ = config;\n this.raw_ = serverResponse;\n\n // Create logger.\n this.logger_ = createLogger('nt-server-response'); // TODO: add client ip\n this.logger_.logMethod?.('new');\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.config_.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.config_.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'\n ? ('error_' + statusCode) as Lowercase<string>\n : (error.name + '').toLowerCase(),\n errorMessage: error.message,\n });\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\n else if (typeof error === 'object' && error !== null) {\n this.replyJson(error as Json);\n }\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, {\n url: this.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\n });\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', {\n url: this.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\n });\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.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\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 }\n catch (error) {\n this.logger_.error('reply', 'server_response_error', error, {\n url: this.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\n });\n this.hasBeenSent_ = false;\n }\n }\n}\n", "import {createServer, IncomingMessage, ServerResponse} from 'node:http';\n\nimport {createLogger} from '@alwatr/logger';\n\nimport {NanotronClientRequest} from './api-client-request.js';\nimport { NanotronServerResponse } from './api-server-response.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 * Specifies how the `url` should be matched against incoming requests.\n *\n * @default 'exact'\n */\n matchType?: MatchType;\n\n /**\n * The functions call before the main handler.\n */\n preHandlers?: RouteHandler[];\n\n /**\n * The function to handle requests to this route.\n */\n handler: RouteHandler;\n\n /**\n * The functions call after the main handler.\n */\n postHandlers?: RouteHandler[];\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('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_(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 matchType: 'exact',\n preHandlers: [],\n postHandlers: [],\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 handleHttpError_(serverResponse: NanotronServerResponse, error?: unknown): void {\n this.logger_.logMethod?.('handleHttpError_');\n // TODO: custom error template by the user.\n serverResponse.replyError(error);\n }\n\n protected async handleClientRequest_(clientRequest: IncomingMessage, serverResponse: ServerResponse): Promise<void> {\n this.logger_.logMethod?.('handleClientRequest_');\n\n if (clientRequest.url === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_url_undefined');\n return;\n }\n\n if (clientRequest.method === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_method_undefined');\n return;\n }\n\n const nanotronClientRequest = new NanotronClientRequest(clientRequest, {prefix: this.config_.prefix});\n const nanotronServerResponse = new NanotronServerResponse(serverResponse, {clientRequest: nanotronClientRequest});\n\n const routeOption = this.getRouteOption_({\n method: nanotronClientRequest.method,\n url: nanotronClientRequest.url.pathname,\n });\n\n if (routeOption === null) {\n nanotronServerResponse.statusCode = HttpStatusCodes.Error_Client_404_Not_Found;\n return this.handleHttpError_(nanotronServerResponse);\n }\n\n const sharedMeta = {};\n\n try {\n for (const handler of nanotronClientRequest.preHandlers_) {\n if (nanotronClientRequest.terminatedHandlers === true) return;\n await handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n }\n\n for (const handler of routeOption.preHandlers) {\n if (nanotronClientRequest.terminatedHandlers === true) return;\n await handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n }\n\n await routeOption.handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n\n for (const handler of routeOption.postHandlers) {\n if (nanotronClientRequest.terminatedHandlers === true) return;\n await handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n }\n }\n catch (error) {\n this.logger_.error('handleClientRequest_', 'route_handler_error', error, {\n url: nanotronClientRequest.url.pathname,\n method: nanotronClientRequest.method,\n });\n\n if (nanotronServerResponse.statusCode < HttpStatusCodes.Error_Client_400_Bad_Request) {\n nanotronServerResponse.statusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n }\n this.handleHttpError_(nanotronServerResponse, 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", "NanotronClientRequest", "NanotronServerResponse", "__toCommonJS", "import_logger", "_NanotronClientRequest", "clientRequest", "config", "url", "NanotronClientRequest", "HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "import_logger", "NanotronServerResponse", "serverResponse", "config", "value", "key", "errorResponse", "error", "statusCode", "HttpStatusCodes", "HttpStatusMessages", "responseJson", "responseString", "context", "import_node_http", "import_logger", "_NanotronApiServer", "config", "routeHandlerList__", "option", "routeList", "url", "_a", "routeHandlerList", "option_", "err", "socket", "serverResponse", "error", "clientRequest", "nanotronClientRequest", "NanotronClientRequest", "nanotronServerResponse", "NanotronServerResponse", "routeOption", "HttpStatusCodes", "sharedMeta", "handler", "NanotronApiServer"]
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": ";yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,EAAA,oBAAAC,EAAA,uBAAAC,EAAA,sBAAAC,IAAA,eAAAC,EAAAN,GCGO,IAAMO,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,IAAAC,EAA2B,0BAedC,EAAN,KAA6B,CAclC,YAAYC,EAA8CC,EAA4C,CALtG,KAAU,aAAe,GAOvB,KAAK,cAAgBD,EACrB,KAAK,KAAOC,EAGZ,KAAK,WAAU,gBAAa,oBAAoB,EAChD,KAAK,QAAQ,gBAAgB,MAAO,KAAK,cAAc,IAAI,OAAO,EAGlE,KAAK,QAAU,CACb,OAAQ,kBACR,eAAgB,YAClB,CACF,CAlBA,IAAI,aAAuB,CACzB,OAAO,KAAK,YACd,CAkBA,IAAI,YAA6B,CAC/B,OAAO,KAAK,KAAK,UACnB,CAEA,IAAI,WAAWC,EAAuB,CACpC,KAAK,KAAK,WAAaA,CACzB,CAEU,eAAgB,CACxB,KAAK,QAAQ,gBAAgB,gBAAiB,KAAK,OAAO,EAC1D,QAAWC,KAAO,KAAK,QACrB,KAAK,KAAK,UAAUA,EAAK,KAAK,QAAQA,CAAwB,CAAE,CAEpE,CAEA,mBAAmBC,EAAoC,CACrD,KAAK,QAAQ,YAAY,oBAAoB,EAC7C,KAAK,cAAc,mBAAqB,GACxC,KAAK,UAAUA,CAAa,CAC9B,CAEA,WAAWC,EAA+C,CACxD,KAAK,QAAQ,gBAAgB,aAAc,CAAC,MAAAA,CAAK,CAAC,EAElD,KAAK,cAAc,mBAAqB,GACxC,IAAIC,EAAa,KAAK,WAElBA,EAAaC,EAAgB,+BAC/B,KAAK,WAAaD,EAAa,KAG7BD,aAAiB,MACnB,KAAK,UAAU,CACb,GAAI,GACJ,UAAWA,EAAM,OAAS,QAAY,SAAWC,GAAqCD,EAAM,KAAO,IAAI,YAAY,EACnH,aAAcA,EAAM,OACtB,CAAC,EAEM,OAAOA,GAAU,SACxB,KAAK,UAAU,CACb,GAAI,GACJ,UAAY,SAAWC,EACvB,aAAcD,CAChB,CAAC,EAEM,OAAOA,GAAU,UAAYA,IAAU,KAC9C,KAAK,UAAUA,CAAa,EAG5B,KAAK,UAAU,CACb,GAAI,GACJ,UAAY,SAAWC,EACvB,aAAcE,EAAmBF,CAAU,CAC7C,CAAkB,CAEtB,CAEA,UAAUG,EAA0B,CAClC,KAAK,QAAQ,gBAAgB,YAAa,CAAC,aAAAA,CAAY,CAAC,EAExD,IAAIC,EACJ,GAAI,CACFA,EAAiB,KAAK,UAAUD,CAAY,CAC9C,OACOJ,EAAO,CACZ,KAAK,QAAQ,MAAM,YAAa,8BAA+BA,EAAO,KAAK,cAAc,IAAI,OAAO,EACpG,KAAK,WAAaE,EAAgB,uCAClCG,EAAiB,KAAK,UAAU,CAC9B,GAAI,GACJ,UAAW,8BACX,aAAc,oCAChB,CAAkB,CACpB,CAEA,KAAK,QAAQ,cAAc,EAAI,mBAC/B,KAAK,MAAMA,CAAc,CAC3B,CAEA,MAAMC,EAAgC,CASpC,GARA,KAAK,QAAQ,gBAAgB,QAAS,KAAK,cAAc,IAAI,OAAO,EAEhE,KAAK,KAAK,kBAAoB,KAAK,eAAiB,KAEtD,KAAK,QAAQ,SAAS,QAAS,4CAA4C,EAC3E,KAAK,aAAe,IAGlB,KAAK,aAAc,CACrB,KAAK,QAAQ,SAAS,QAAS,qBAAsB,CACnD,IAAK,KAAK,cAAc,IAAI,QAC5B,UAAW,KAAK,aAChB,iBAAkB,KAAK,KAAK,gBAC9B,CAAC,EACD,MACF,CAEA,KAAK,aAAe,GAEpB,GAAI,CACE,OAAOA,GAAY,WACrBA,EAAU,OAAO,KAAKA,CAAO,GAG/B,KAAK,QAAQ,gBAAgB,EAAIA,EAAQ,WAEzC,KAAK,cAAc,EACnB,KAAK,KAAK,IAAIA,EAAS,QAAQ,CACjC,OACON,EAAO,CACZ,KAAK,QAAQ,MAAM,QAAS,wBAAyBA,EAAO,KAAK,cAAc,IAAI,OAAO,EAC1F,KAAK,aAAe,EACtB,CACF,CACF,EC9JA,IAAAO,EAA2B,0BAQdC,EAAN,KAA4B,CA2BjC,YACEC,EACAC,EACAC,EACAC,EACA,CAXF,KAAS,WAAyB,CAAC,EAajC,KAAK,KAAOF,EACZ,KAAK,IAAMD,EACX,KAAK,YAAcG,EAGnB,KAAK,WAAU,gBAAa,mBAAmB,EAC/C,KAAK,QAAQ,gBAAgB,MAAOH,EAAI,OAAO,EAG/C,KAAK,eAAiB,IAAII,EAAuB,KAAMF,CAAoB,CAC7E,CACF,ECrDA,IAAAG,EAAkB,oBAKLC,EAAN,MAAMA,UAAoB,KAAI,CAMnC,YAAYC,EAAgCC,EAA6B,CACvE,IAAIC,EAAMF,EAAc,KAAO,GAC3BC,IAAW,KAAOC,EAAI,QAAQD,CAAM,IAAM,IAC5CC,EAAMA,EAAI,MAAMD,EAAO,OAAS,CAAC,GAEnCC,EAAMA,EAAI,QAAQH,EAAY,gBAAiB,GAAG,EAElD,MAAMG,EAAK,kBAAkB,EAE7B,KAAK,QAAUF,EAAc,QAAU,OAAO,YAAY,EAE1D,KAAK,QAAU,IAAI,KAAK,MAAM,IAAI,KAAK,QAAQ,EACjD,CACF,EAnBaD,EACM,gBAAkB,IAAI,OAAO,YAAY,EADrD,IAAMI,EAANJ,ECLP,IAAAK,EAA2B,qBAE3BC,EAA2B,0BAgFdC,EAAN,MAAMA,CAAkB,CAoB7B,YAAYC,EAA2C,CAErD,KAAK,QAAU,CACb,GAAGD,EAAkB,eACrB,GAAGC,CACL,EAGA,KAAK,WAAU,gBAAa,iBAAmB,KAAK,QAAQ,OAAS,GAAK,IAAM,KAAK,QAAQ,KAAO,GAAG,EACvG,KAAK,QAAQ,gBAAgB,MAAO,CAAC,OAAQ,KAAK,OAAO,CAAC,EAG1D,KAAK,qBAAuB,KAAK,qBAAqB,KAAK,IAAI,EAC/D,KAAK,mBAAqB,KAAK,mBAAmB,KAAK,IAAI,EAC3D,KAAK,mBAAqB,KAAK,mBAAmB,KAAK,IAAI,EAG3D,KAAKC,EAAqB,CACxB,MAAO,CAAC,EACR,WAAY,CAAC,CACf,EAGA,KAAK,cAAa,gBAChB,CACE,UAAW,GACX,sBAAuB,EACvB,QAAS,EACX,EACA,KAAK,oBACP,EAGA,KAAK,WAAW,eAAiB,KAAK,QAAQ,eAC9C,KAAK,WAAW,iBAAmB,KAAK,QAAQ,iBAChD,KAAK,WAAW,eAAiB,KAAK,QAAQ,eAG9C,KAAK,WAAW,OAAO,KAAK,QAAQ,KAAM,KAAK,QAAQ,KAAM,IAAM,CACjE,KAAK,QAAQ,WAAW,gBAAgB,KAAK,QAAQ,IAAI,IAAI,KAAK,QAAQ,IAAI,EAAE,CAClF,CAAC,EAGD,KAAK,WAAW,GAAG,QAAS,KAAK,kBAAkB,EACnD,KAAK,WAAW,GAAG,cAAe,KAAK,kBAAkB,CAC3D,CAEA,OAAc,CACZ,KAAK,QAAQ,YAAY,OAAO,EAChC,KAAK,WAAW,MAAM,CACxB,CAEU,gBAAgBC,EAAsD,CAG9E,GAFA,KAAK,QAAQ,YAAY,iBAAiB,EAGxC,OAAO,OAAO,KAAKD,EAAmB,MAAOC,EAAI,MAAM,GACvD,OAAO,OAAO,KAAKD,EAAmB,MAAMC,EAAI,MAAM,EAAGA,EAAI,QAAQ,EAErE,OAAO,KAAKD,EAAmB,MAAMC,EAAI,MAAM,EAAEA,EAAI,QAAQ,EAG/D,GAAI,OAAO,OAAO,KAAKD,EAAmB,WAAYC,EAAI,MAAM,EAAG,CACjE,IAAMC,EAAY,KAAKF,EAAmB,WAAWC,EAAI,MAAM,EAC/D,QAAWE,KAAYD,EACrB,GAAIC,EAAS,QAAQF,EAAI,QAAQ,IAAM,EACrC,OAAOC,EAAUC,CAAQ,CAG/B,CAEA,YAAK,QAAQ,WAAW,kBAAmB,kBAAmB,CAAC,OAAQF,EAAI,OAAQ,IAAKA,EAAI,QAAQ,CAAC,EAC9F,IACT,CAEU,gBAAgBG,EAA2C,CAjLvE,IAAAC,EAkLI,KAAK,QAAQ,gBAAgB,kBAAmB,CAAC,GAAGD,EAAQ,QAAS,UAAU,CAAC,EAEhF,IAAME,EAAmB,KAAKN,EAAmBI,EAAO,SAAS,EAIjE,GAFAE,EAAAD,EAAiBD,EAAO,UAAxBE,EAAAD,GAAoC,CAAC,GAEjC,OAAO,OAAOC,EAAiBF,EAAO,MAAM,EAAGA,EAAO,GAAG,EAC3D,WAAK,QAAQ,MAAM,cAAe,uBAAwB,CAAC,GAAGA,EAAQ,QAAS,UAAU,CAAC,EACpF,IAAI,MAAM,sBAAsB,EAGxCE,EAAiBF,EAAO,MAAM,EAAEA,EAAO,GAAG,EAAIA,CAChD,CAEA,YAAYA,EAAiC,CAC3C,IAAMG,EAAuC,CAC3C,UAAW,QACX,YAAa,CAAC,EACd,aAAc,CAAC,EACf,UAAW,KAAK,QAAQ,UACxB,GAAGH,CACL,EACA,KAAK,QAAQ,gBAAgB,cAAe,CAAC,GAAGG,EAAS,QAAS,UAAU,CAAC,EAC7E,KAAK,gBAAgBA,CAAO,CAC9B,CAEU,mBAAmBC,EAAkC,CACzDA,EAAI,OAAS,aACf,KAAK,QAAQ,MAAM,qBAAsB,iBAAkBA,CAAG,EAG9D,KAAK,QAAQ,MAAM,qBAAsB,oBAAqBA,EAAI,SAAW,6BAA8BA,CAAG,CAElH,CAEU,mBAAmBA,EAA4BC,EAAsB,CAC7E,KAAK,QAAQ,SAAS,qBAAsB,2BAA4B,CACtE,QAASD,EAAI,KACb,WAAYA,EAAI,OAClB,CAAC,EACDC,EAAO,IAAI;AAAA;AAAA,CAAkC,CAC/C,CAEA,MAAgB,qBACdC,EACAC,EACe,CAGf,GAFA,KAAK,QAAQ,YAAY,sBAAsB,EAE3CD,EAAoB,MAAQ,OAAW,CACzC,KAAK,QAAQ,SAAS,uBAAwB,2BAA2B,EACzE,MACF,CAEA,GAAIA,EAAoB,SAAW,OAAW,CAC5C,KAAK,QAAQ,SAAS,uBAAwB,8BAA8B,EAC5E,MACF,CAEA,IAAMT,EAAM,IAAIW,EAAYF,EAAqB,KAAK,QAAQ,MAAM,EAE9DG,EAAc,KAAK,gBAAgBZ,CAAG,EAEtCa,EAAa,IAAIC,EAAsBd,EAAKS,EAAqBC,EAAsBE,CAAW,EAExG,GAAIA,IAAgB,KAAM,CACxBC,EAAW,eAAe,WAAaE,EAAgB,2BACvDF,EAAW,eAAe,WAAW,EACrC,MACF,CAEA,GAAI,CACF,QAAWG,KAAWJ,EAAY,YAAa,CAC7C,GAAIC,EAAW,qBAAuB,GAAM,OAC5C,MAAMG,EAAQH,EAAYA,EAAW,eAAgBA,EAAW,UAAU,CAC5E,CAEA,MAAMD,EAAY,QAAQC,EAAYA,EAAW,eAAgBA,EAAW,UAAU,EAEtF,QAAWG,KAAWJ,EAAY,aAAc,CAC9C,GAAIC,EAAW,qBAAuB,GAAM,OAC5C,MAAMG,EAAQH,EAAYA,EAAW,eAAgBA,EAAW,UAAU,CAC5E,CACF,OACOI,EAAO,CACZ,KAAK,QAAQ,MAAM,uBAAwB,sBAAuBA,EAAOjB,EAAI,OAAO,EAEhFa,EAAW,eAAe,WAAaE,EAAgB,+BACzDF,EAAW,eAAe,WAAaE,EAAgB,wCAEzDF,EAAW,eAAe,WAAWI,CAAK,CAC5C,CAGF,CACF,EA/LapB,EACe,eAA8D,CACtF,KAAM,UACN,KAAM,GACN,eAAgB,IAChB,eAAgB,KAChB,iBAAkB,KAClB,YAAa,GACb,eAAgB,GAChB,OAAQ,QACR,UAAW,OACb,EAXK,IAAMqB,EAANrB",
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,6 +1,7 @@
1
1
  export * from './api-server.js';
2
- export * from './api-client-request.js';
3
- export * from './api-server-response.js';
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';
4
5
  export * from './type.js';
5
6
  export * from './const.js';
6
7
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
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.1 */
2
- import{createLogger as c}from"@alwatr/logger";var l=class l{constructor(e,t){this.preHandlers_=[];this.config_=t,this.raw_=e,this.method=(this.raw_.method??"GET").toUpperCase();let r=this.raw_.url??"";this.config_.prefix!=="/"&&r.indexOf(this.config_.prefix)===0&&(r=r.slice(this.config_.prefix.length-1)),r=r.replace(l.versionPattern_,"/"),this.url=new URL(r,"http://hostname/"),this.logger_=c("nt-client-request"),this.logger_.logMethodArgs?.("new",{method:this.method,url:this.url.pathname})}};l.versionPattern_=new RegExp("^/v[0-9]+/");var _=l;var C={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 d=class{constructor(e,t){this.hasBeenSent_=!1;this.config_=t,this.raw_=e,this.logger_=g("nt-server-response"),this.logger_.logMethod?.("new"),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.config_.clientRequest.terminatedHandlers=!0,this.replyJson(e)}replyError(e){this.logger_.logMethodArgs?.("replyError",{error:e}),this.config_.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,{url:this.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method}),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",{url:this.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method}),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.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method,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,{url:this.config_.clientRequest.url.pathname,method:this.config_.clientRequest.method}),this.hasBeenSent_=!1}}};import{createServer as f}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=f({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_.logMethodArgs?.("getRouteOption_",e),Object.hasOwn(this.e.exact,e.method)&&Object.hasOwn(this.e.exact[e.method],e.url))return this.e.exact[e.method][e.url];if(Object.hasOwn(this.e.startsWith,e.method)){let t=this.e.startsWith[e.method];for(let r in t)if(r.indexOf(e.url)===0)return t[r]}return this.logger_.incident?.("getRouteOption_","route_not_found",e),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:[],...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
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
- `)}handleHttpError_(e,t){this.logger_.logMethod?.("handleHttpError_"),e.replyError(t)}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 _(e,{prefix:this.config_.prefix}),o=new d(t,{clientRequest:r}),s=this.getRouteOption_({method:r.method,url:r.url.pathname});if(s===null)return o.statusCode=i.Error_Client_404_Not_Found,this.handleHttpError_(o);let a={};try{for(let n of r.preHandlers_){if(r.terminatedHandlers===!0)return;await n(r,o,a)}for(let n of s.preHandlers){if(r.terminatedHandlers===!0)return;await n(r,o,a)}await s.handler(r,o,a);for(let n of s.postHandlers){if(r.terminatedHandlers===!0)return;await n(r,o,a)}}catch(n){this.logger_.error("handleClientRequest_","route_handler_error",n,{url:r.url.pathname,method:r.method}),o.statusCode<i.Error_Client_400_Bad_Request&&(o.statusCode=i.Error_Server_500_Internal_Server_Error),this.handleHttpError_(o,n)}}};h.defaultConfig_={host:"0.0.0.0",port:80,requestTimeout:1e4,headersTimeout:13e4,keepAliveTimeout:12e4,healthRoute:!0,allowAllOrigin:!1,prefix:"/api/"};var u=h;export{C as HttpMethods,i as HttpStatusCodes,p as HttpStatusMessages,u as NanotronApiServer,_ as NanotronClientRequest,d as NanotronServerResponse};
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/api-client-request.ts", "../src/const.ts", "../src/api-server-response.ts", "../src/api-server.ts"],
4
- "sourcesContent": ["import {createLogger} from '@alwatr/logger';\n\nimport type {HttpMethod, RouteHandler} from './type.js';\nimport type {IncomingMessage} from 'node:http';\n\n/**\n * Configuration options for the Nanotron Api Client Request.\n */\nexport interface NanotronClientRequestConfig {\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 NanotronClientRequest {\n protected static versionPattern_ = new RegExp('^/v[0-9]+/');\n\n readonly url;\n\n readonly method;\n\n readonly raw_;\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 preHandlers_: RouteHandler[] = [];\n\n protected readonly logger_;\n\n protected readonly config_;\n\n constructor(\n clientRequest: IncomingMessage,\n config: NanotronClientRequestConfig,\n ) {\n // Store the raw request object and configuration.\n this.config_ = config;\n this.raw_ = clientRequest;\n\n // Parse request method.\n this.method = (this.raw_.method ?? 'GET').toUpperCase() as HttpMethod;\n\n // Parse request URL.\n let url = this.raw_.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(NanotronClientRequest.versionPattern_, '/');\n this.url = new URL(url, 'http://hostname/');\n\n // Create logger.\n this.logger_ = createLogger('nt-client-request'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', {method: this.method, url: this.url.pathname});\n }\n}\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} from './type.js';\nimport type {Json} from '@alwatr/type-helper';\nimport type {ServerResponse} from 'node:http';\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 raw_;\n\n readonly headers: HttpResponseHeaders;\n\n protected readonly logger_;\n\n protected readonly config_;\n\n protected hasBeenSent_ = false;\n get hasBeenSent(): boolean {\n return this.hasBeenSent_;\n }\n\n constructor(\n serverResponse: ServerResponse,\n config: NanotronServerResponseConfig,\n ) {\n // Store the raw request object and configuration.\n this.config_ = config;\n this.raw_ = serverResponse;\n\n // Create logger.\n this.logger_ = createLogger('nt-server-response'); // TODO: add client ip\n this.logger_.logMethod?.('new');\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.config_.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.config_.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'\n ? ('error_' + statusCode) as Lowercase<string>\n : (error.name + '').toLowerCase(),\n errorMessage: error.message,\n });\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\n else if (typeof error === 'object' && error !== null) {\n this.replyJson(error as Json);\n }\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, {\n url: this.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\n });\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', {\n url: this.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\n });\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.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\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 }\n catch (error) {\n this.logger_.error('reply', 'server_response_error', error, {\n url: this.config_.clientRequest.url.pathname,\n method: this.config_.clientRequest.method,\n });\n this.hasBeenSent_ = false;\n }\n }\n}\n", "import {createServer, IncomingMessage, ServerResponse} from 'node:http';\n\nimport {createLogger} from '@alwatr/logger';\n\nimport {NanotronClientRequest} from './api-client-request.js';\nimport { NanotronServerResponse } from './api-server-response.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 * Specifies how the `url` should be matched against incoming requests.\n *\n * @default 'exact'\n */\n matchType?: MatchType;\n\n /**\n * The functions call before the main handler.\n */\n preHandlers?: RouteHandler[];\n\n /**\n * The function to handle requests to this route.\n */\n handler: RouteHandler;\n\n /**\n * The functions call after the main handler.\n */\n postHandlers?: RouteHandler[];\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('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_(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 matchType: 'exact',\n preHandlers: [],\n postHandlers: [],\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 handleHttpError_(serverResponse: NanotronServerResponse, error?: unknown): void {\n this.logger_.logMethod?.('handleHttpError_');\n // TODO: custom error template by the user.\n serverResponse.replyError(error);\n }\n\n protected async handleClientRequest_(clientRequest: IncomingMessage, serverResponse: ServerResponse): Promise<void> {\n this.logger_.logMethod?.('handleClientRequest_');\n\n if (clientRequest.url === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_url_undefined');\n return;\n }\n\n if (clientRequest.method === undefined) {\n this.logger_.accident('handleClientRequest_', 'http_server_method_undefined');\n return;\n }\n\n const nanotronClientRequest = new NanotronClientRequest(clientRequest, {prefix: this.config_.prefix});\n const nanotronServerResponse = new NanotronServerResponse(serverResponse, {clientRequest: nanotronClientRequest});\n\n const routeOption = this.getRouteOption_({\n method: nanotronClientRequest.method,\n url: nanotronClientRequest.url.pathname,\n });\n\n if (routeOption === null) {\n nanotronServerResponse.statusCode = HttpStatusCodes.Error_Client_404_Not_Found;\n return this.handleHttpError_(nanotronServerResponse);\n }\n\n const sharedMeta = {};\n\n try {\n for (const handler of nanotronClientRequest.preHandlers_) {\n if (nanotronClientRequest.terminatedHandlers === true) return;\n await handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n }\n\n for (const handler of routeOption.preHandlers) {\n if (nanotronClientRequest.terminatedHandlers === true) return;\n await handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n }\n\n await routeOption.handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n\n for (const handler of routeOption.postHandlers) {\n if (nanotronClientRequest.terminatedHandlers === true) return;\n await handler(nanotronClientRequest, nanotronServerResponse, sharedMeta);\n }\n }\n catch (error) {\n this.logger_.error('handleClientRequest_', 'route_handler_error', error, {\n url: nanotronClientRequest.url.pathname,\n method: nanotronClientRequest.method,\n });\n\n if (nanotronServerResponse.statusCode < HttpStatusCodes.Error_Client_400_Bad_Request) {\n nanotronServerResponse.statusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n }\n this.handleHttpError_(nanotronServerResponse, error);\n }\n\n // TODO: handled open remained connections.\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["createLogger", "_NanotronClientRequest", "clientRequest", "config", "url", "NanotronClientRequest", "HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "createLogger", "NanotronServerResponse", "serverResponse", "config", "value", "key", "errorResponse", "error", "statusCode", "HttpStatusCodes", "HttpStatusMessages", "responseJson", "responseString", "context", "createServer", "createLogger", "_NanotronApiServer", "config", "routeHandlerList__", "option", "routeList", "url", "_a", "routeHandlerList", "option_", "err", "socket", "serverResponse", "error", "clientRequest", "nanotronClientRequest", "NanotronClientRequest", "nanotronServerResponse", "NanotronServerResponse", "routeOption", "HttpStatusCodes", "sharedMeta", "handler", "NanotronApiServer"]
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,6 +1,7 @@
1
1
  import type { NanotronClientRequest } from './api-client-request.js';
2
2
  import type { NanotronServerResponse } from './api-server-response.js';
3
3
  import type { Dictionary, Json, MaybePromise } from '@alwatr/type-helper';
4
+ import type { IncomingMessage, ServerResponse } from 'node:http';
4
5
  declare module 'http' {
5
6
  interface IncomingHttpHeaders {
6
7
  'x-forwarded-for'?: string;
@@ -8,6 +9,52 @@ declare module 'http' {
8
9
  }
9
10
  export type MatchType = 'exact' | 'startsWith';
10
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
+ }
11
58
  /**
12
59
  * Represents the collection of HTTP response headers.
13
60
  */
@@ -19,11 +66,11 @@ export interface HttpResponseHeaders {
19
66
  /**
20
67
  * Specifies the time in seconds the object has been in a proxy cache.
21
68
  */
22
- 'age'?: string;
69
+ age?: string;
23
70
  /**
24
71
  * Lists the set of HTTP methods supported by the resource identified by the Request-URI.
25
72
  */
26
- 'allow'?: string;
73
+ allow?: string;
27
74
  /**
28
75
  * Specifies caching directives for both requests and responses.
29
76
  */
@@ -31,7 +78,7 @@ export interface HttpResponseHeaders {
31
78
  /**
32
79
  * Controls whether the network connection stays open after the current transaction.
33
80
  */
34
- 'connection'?: string;
81
+ connection?: string;
35
82
  /**
36
83
  * Suggests a filename for the downloaded resource or how the content should be displayed.
37
84
  */
@@ -63,15 +110,15 @@ export interface HttpResponseHeaders {
63
110
  /**
64
111
  * Indicates the date and time at which the message was originated.
65
112
  */
66
- 'date'?: string;
113
+ date?: string;
67
114
  /**
68
115
  * Provides the current value of the entity tag for the requested variant.
69
116
  */
70
- 'etag'?: string;
117
+ etag?: string;
71
118
  /**
72
119
  * Gives the date/time after which the response is considered stale.
73
120
  */
74
- 'expires'?: string;
121
+ expires?: string;
75
122
  /**
76
123
  * Indicates the date and time at which the origin server believes the variant was last modified.
77
124
  */
@@ -79,15 +126,15 @@ export interface HttpResponseHeaders {
79
126
  /**
80
127
  * Provides a list of URIs associated with the resource.
81
128
  */
82
- 'link'?: string;
129
+ link?: string;
83
130
  /**
84
131
  * Used in redirection, or when a new resource has been created.
85
132
  */
86
- 'location'?: string;
133
+ location?: string;
87
134
  /**
88
135
  * Used for backward compatibility with HTTP/1.0 caches.
89
136
  */
90
- 'pragma'?: string;
137
+ pragma?: string;
91
138
  /**
92
139
  * Requests authentication information from the client for a proxy server.
93
140
  */
@@ -99,7 +146,7 @@ export interface HttpResponseHeaders {
99
146
  /**
100
147
  * Contains information about the software used by the origin server to handle the request.
101
148
  */
102
- 'server'?: string;
149
+ server?: string;
103
150
  /**
104
151
  * Used to send cookies from the server to the user agent.
105
152
  */
@@ -111,7 +158,7 @@ export interface HttpResponseHeaders {
111
158
  /**
112
159
  * Allows the sender to include additional fields at the end of chunked messages.
113
160
  */
114
- 'trailer'?: string;
161
+ trailer?: string;
115
162
  /**
116
163
  * Specifies the form of encoding used to safely transfer the entity to the user.
117
164
  */
@@ -120,26 +167,19 @@ export interface HttpResponseHeaders {
120
167
  * Determines how to match future request headers to decide whether a cached response
121
168
  * can be used rather than requesting a fresh one from the origin server.
122
169
  */
123
- 'vary'?: string;
170
+ vary?: string;
124
171
  /**
125
172
  * Lists all intermediate proxies the message has traversed
126
173
  */
127
- 'via'?: string;
174
+ via?: string;
128
175
  /**
129
176
  * Contains additional information about the status or transformation of a message that might not be reflected in the status code.
130
177
  */
131
- 'warning'?: string;
178
+ warning?: string;
132
179
  /**
133
180
  * Indicates the authentication scheme that should be used to access the requested entity.
134
181
  */
135
182
  'www-authenticate'?: string;
136
183
  [headerName: Lowercase<string>]: string | string[] | number | undefined;
137
184
  }
138
- export type ErrorResponse = {
139
- ok: false;
140
- errorCode: Lowercase<string>;
141
- errorMessage: string;
142
- meta?: Json;
143
- };
144
- export type RouteHandler = (clientRequest: NanotronClientRequest, serverResponse: NanotronServerResponse, sharedMeta: Dictionary) => MaybePromise<void>;
145
185
  //# sourceMappingURL=type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"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"}
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.1",
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": "680e1e5804e3b2fee5f1c9ecc4818892de783567"
72
+ "gitHead": "55e4345fd4f5e75b33dbbee0c92a57256c5a7e41"
73
73
  }