1+ import EventEmitter from "node:events" ;
12import http from "node:http" ;
23import packageJson from "../package.json" with { type : "json" } ;
34import { Request } from "./Request.js" ;
@@ -6,7 +7,11 @@ import {Response} from "./response/Response.js";
67import { RouteRegistry } from "./routing/RouteRegistry.js" ;
78import { ServerErrorRegistry } from "./ServerErrorRegistry.js" ;
89
9- class Server {
10+ /**
11+ * An HTTP server.
12+ * @see {@link Server.Events } for events.
13+ */
14+ class Server extends EventEmitter < Server . Events > {
1015 /**
1116 * Headers sent with every response.
1217 */
@@ -29,6 +34,7 @@ class Server {
2934 * @param options Server options.
3035 */
3136 public constructor ( options : Server . Options ) {
37+ super ( ) ;
3238 this . server = http . createServer ( {
3339 joinDuplicateHeaders : true ,
3440 } , this . listener . bind ( this ) ) ;
@@ -40,7 +46,12 @@ class Server {
4046 this . copyOrigin = options . copyOrigin ?? false ;
4147 this . handleConditionalRequests = options . handleConditionalRequests ?? true ;
4248
43- this . server . listen ( options . port ) ;
49+ this . server . listen ( options . port , process . env . HOST , ( ) => this . emit ( "listening" ) ) ;
50+
51+ this . once ( "listening" , ( ) => {
52+ if ( this . listenerCount ( "error" ) === 0 )
53+ this . on ( "error" , e => console . error ( "Internal Server Error:" , e ) ) ;
54+ } ) ;
4455 }
4556
4657 /** @internal **/
@@ -79,7 +90,7 @@ class Server {
7990 if ( e instanceof RouteRegistry . NoRouteError )
8091 response = this . errors . _get ( ServerErrorRegistry . ErrorCodes . NO_ROUTE , apiRequest ) ;
8192 else {
82- console . error ( "Internal Server Error: ", e ) ;
93+ this . emit ( "error ", e as any ) ;
8394 response = this . errors . _get ( ServerErrorRegistry . ErrorCodes . INTERNAL , apiRequest ) ;
8495 }
8596 }
@@ -132,8 +143,9 @@ class Server {
132143 . map ( t => t . trim ( ) )
133144 }
134145
135- public close ( ) : Promise < void > {
136- return Promise . race ( [
146+ public async close ( ) : Promise < void > {
147+ this . emit ( "closing" ) ;
148+ await Promise . race ( [
137149 new Promise < void > ( resolve => {
138150 this . server . close ( ( ) => resolve ( ) ) ;
139151 } ) ,
@@ -142,6 +154,7 @@ class Server {
142154 resolve ( ) ;
143155 } , 5000 ) ) ,
144156 ] ) ;
157+ this . emit ( "closed" ) ;
145158 }
146159}
147160
@@ -176,6 +189,31 @@ namespace Server {
176189 */
177190 readonly handleConditionalRequests ?: boolean ;
178191 }
192+
193+ /**
194+ * Server events map
195+ */
196+ export interface Events {
197+ /**
198+ * Server is listening and ready to accept connections.
199+ */
200+ listening : [ void ] ;
201+
202+ /**
203+ * The server is closing and not accepting new connections.
204+ */
205+ closing : [ void ] ;
206+
207+ /**
208+ * All connections have ended and the server has closed.
209+ */
210+ closed : [ void ] ;
211+
212+ /**
213+ * An uncaught error occurred. Client has been sent {@link ServerErrorRegistry.ErrorCodes.INTERNAL} error.
214+ */
215+ error : [ Error ] ;
216+ }
179217}
180218
181219export { Server } ;
0 commit comments