@boo-labs/server 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +287 -2
  3. package/index.mjs +23 -0
  4. package/package.json +71 -4
  5. package/source/application/Kernel/index.mjs +1137 -0
  6. package/source/application/Server/index.mjs +1201 -0
  7. package/source/application/configurations/Http2CleartextServerConfiguration/index.mjs +168 -0
  8. package/source/application/configurations/Http2SecureServerConfiguration/index.mjs +172 -0
  9. package/source/application/configurations/HttpServerConfiguration/index.mjs +169 -0
  10. package/source/application/configurations/HttpsServerConfiguration/index.mjs +172 -0
  11. package/source/application/configurations/ServerConfiguration/Options/CORSOptions/CORSOptionsValue.mjs +158 -0
  12. package/source/application/configurations/ServerConfiguration/Options/CORSOptions/index.mjs +87 -0
  13. package/source/application/configurations/ServerConfiguration/Options/CSRFOptions/CSRFOptionsValue.mjs +178 -0
  14. package/source/application/configurations/ServerConfiguration/Options/CSRFOptions/index.mjs +80 -0
  15. package/source/application/configurations/ServerConfiguration/Options/CompressOptions/CompressOptionsValue.mjs +126 -0
  16. package/source/application/configurations/ServerConfiguration/Options/CompressOptions/index.mjs +81 -0
  17. package/source/application/configurations/ServerConfiguration/Options/CookieParserOptions/CookieParserOptionsValue.mjs +107 -0
  18. package/source/application/configurations/ServerConfiguration/Options/CookieParserOptions/index.mjs +82 -0
  19. package/source/application/configurations/ServerConfiguration/Options/CookieSessionOptions/CookieSessionOptionsValue.mjs +182 -0
  20. package/source/application/configurations/ServerConfiguration/Options/CookieSessionOptions/index.mjs +86 -0
  21. package/source/application/configurations/ServerConfiguration/Options/ListenOptions/ListenOptionsValue.mjs +95 -0
  22. package/source/application/configurations/ServerConfiguration/Options/ListenOptions/index.mjs +47 -0
  23. package/source/application/configurations/ServerConfiguration/Options/MiddlewareOption.mjs +102 -0
  24. package/source/application/configurations/ServerConfiguration/Options/Options.mjs +105 -0
  25. package/source/application/configurations/ServerConfiguration/Options/RateLimitOptions/RateLimitOptionsValue.mjs +164 -0
  26. package/source/application/configurations/ServerConfiguration/Options/RateLimitOptions/index.mjs +84 -0
  27. package/source/application/configurations/ServerConfiguration/Options/RequestOptions/RequestOptionsValue.mjs +108 -0
  28. package/source/application/configurations/ServerConfiguration/Options/RequestOptions/index.mjs +47 -0
  29. package/source/application/configurations/ServerConfiguration/Options/ResponseOptions/ResponseOptionsValue.mjs +101 -0
  30. package/source/application/configurations/ServerConfiguration/Options/ResponseOptions/index.mjs +47 -0
  31. package/source/application/configurations/ServerConfiguration/Options/SecurityHeadersOptions/SecurityHeadersOptionsValue.mjs +272 -0
  32. package/source/application/configurations/ServerConfiguration/Options/SecurityHeadersOptions/index.mjs +85 -0
  33. package/source/application/configurations/ServerConfiguration/Options/ServerOption.mjs +50 -0
  34. package/source/application/configurations/ServerConfiguration/Options/StaticOptions/StaticOptionsValue.mjs +164 -0
  35. package/source/application/configurations/ServerConfiguration/Options/StaticOptions/index.mjs +89 -0
  36. package/source/application/configurations/ServerConfiguration/index.mjs +781 -0
  37. package/source/application/resolvers/TransportResolver/index.mjs +119 -0
  38. package/source/application/use-cases/CloseServer/index.mjs +85 -0
  39. package/source/application/use-cases/ListenServer/index.mjs +98 -0
  40. package/source/core/EventSystem/index.mjs +110 -0
  41. package/source/core/Exchange/ExchangeContext.mjs +291 -0
  42. package/source/core/Exchange/Telemetry.mjs +193 -0
  43. package/source/core/Exchange/index.mjs +604 -0
  44. package/source/core/ExchangeLayerBuilder/index.mjs +133 -0
  45. package/source/core/IPCMain/IPCMain.mjs +507 -0
  46. package/source/core/IPCMain/IPCProtocol.mjs +441 -0
  47. package/source/core/IPCMain/IPCServerChannel.mjs +331 -0
  48. package/source/core/IPCMain/WebSocketAdapter.mjs +189 -0
  49. package/source/core/Request/BodyParser/BodyParser.mjs +197 -0
  50. package/source/core/Request/BodyParser/JSONParser.mjs +70 -0
  51. package/source/core/Request/BodyParser/MultipartParser.mjs +612 -0
  52. package/source/core/Request/BodyParser/URLEncodedParser.mjs +71 -0
  53. package/source/core/Request/RequestHeaders.mjs +177 -0
  54. package/source/core/Request/index.mjs +805 -0
  55. package/source/core/Response/ResponseHeaders.mjs +402 -0
  56. package/source/core/Response/index.mjs +1370 -0
  57. package/source/core/middlewares/CORSMiddleware/index.mjs +289 -0
  58. package/source/core/middlewares/CSRFMiddleware/index.mjs +284 -0
  59. package/source/core/middlewares/CompressMiddleware/index.mjs +460 -0
  60. package/source/core/middlewares/CookieParserMiddleware/index.mjs +194 -0
  61. package/source/core/middlewares/CookieSessionMiddleware/index.mjs +460 -0
  62. package/source/core/middlewares/RateLimitMiddleware/index.mjs +245 -0
  63. package/source/core/middlewares/SecurityHeadersMiddleware/index.mjs +151 -0
  64. package/source/core/middlewares/StaticMiddleware/index.mjs +628 -0
  65. package/source/core/routing/ExchangeLayer/ExchangeMatcher.mjs +127 -0
  66. package/source/core/routing/ExchangeLayer/index.mjs +254 -0
  67. package/source/core/routing/Pipeline/index.mjs +157 -0
  68. package/source/core/routing/Router/Route.mjs +184 -0
  69. package/source/core/routing/Router/index.mjs +523 -0
  70. package/source/core/routing/RouterRegister/OptionsMiddleware.mjs +147 -0
  71. package/source/core/routing/RouterRegister/index.mjs +150 -0
  72. package/source/core/routing/RouterSystem/index.mjs +225 -0
  73. package/source/core/value-objects/Address/index.mjs +281 -0
  74. package/source/core/value-objects/Endpoint/index.mjs +293 -0
  75. package/source/index.mjs +62 -0
  76. package/source/infrastructure/adapters/Http2Adapter/index.mjs +144 -0
  77. package/source/infrastructure/adapters/Http2CleartextAdapter/index.mjs +147 -0
  78. package/source/infrastructure/adapters/HttpAdapter/index.mjs +124 -0
  79. package/source/infrastructure/adapters/HttpsAdapter/index.mjs +124 -0
  80. package/source/infrastructure/adapters/TransportAdapter/createWebSocketOpenRequest.mjs +843 -0
  81. package/source/infrastructure/adapters/TransportAdapter/index.mjs +555 -0
  82. package/source/shared/Identifier/index.mjs +671 -0
  83. package/source/shared/constants/symbols/brands/index.mjs +45 -0
  84. package/source/shared/domain/UUIDV7/index.mjs +346 -0
  85. package/source/shared/errors/BaseError/index.mjs +157 -0
  86. package/source/shared/errors/IPCError/index.mjs +97 -0
  87. package/source/shared/errors/MiddlewareError/index.mjs +106 -0
  88. package/source/shared/errors/PathnamePatternError/index.mjs +103 -0
  89. package/source/shared/errors/RequestError/index.mjs +116 -0
  90. package/source/shared/errors/ResponseError/index.mjs +140 -0
  91. package/source/shared/errors/RouterError/index.mjs +90 -0
  92. package/source/shared/errors/ServerConfigurationError/index.mjs +551 -0
  93. package/source/shared/errors/ServerError/index.mjs +127 -0
  94. package/source/shared/errors/WebSocketError/index.mjs +58 -0
  95. package/source/shared/outcome/ErrorSchema.mjs +361 -0
  96. package/source/shared/outcome/Result/index.mjs +239 -0
  97. package/source/shared/outcome/Validation/index.mjs +208 -0
  98. package/source/shared/validations/Middleware/index.mjs +160 -0
  99. package/source/shared/validations/PathnamePattern/index.mjs +256 -0
  100. package/source/shared/validations/Server/NotFoundHandler/index.mjs +94 -0
  101. package/source/shared/validations/Server/Router/index.mjs +68 -0
  102. package/source/shared/validations/Server/ServerConfiguration/index.mjs +68 -0
  103. package/source/shared/validations/Server/SystemErrorHandler/index.mjs +94 -0
  104. package/source/shared/validations/ServerConfiguration/CORSOptions/index.mjs +310 -0
  105. package/source/shared/validations/ServerConfiguration/CSRFOptions/index.mjs +299 -0
  106. package/source/shared/validations/ServerConfiguration/CompressOptions/index.mjs +204 -0
  107. package/source/shared/validations/ServerConfiguration/CookieParserOptions/index.mjs +102 -0
  108. package/source/shared/validations/ServerConfiguration/CookieSessionOptions/index.mjs +332 -0
  109. package/source/shared/validations/ServerConfiguration/ListenOptions/index.mjs +178 -0
  110. package/source/shared/validations/ServerConfiguration/RateLimitOptions/index.mjs +229 -0
  111. package/source/shared/validations/ServerConfiguration/RequestOptions/index.mjs +132 -0
  112. package/source/shared/validations/ServerConfiguration/ResponseOptions/index.mjs +122 -0
  113. package/source/shared/validations/ServerConfiguration/SecurityHeadersOptions/index.mjs +137 -0
  114. package/source/shared/validations/ServerConfiguration/StaticOptions/index.mjs +248 -0
  115. package/types/index.d.ts +719 -0
@@ -0,0 +1,1137 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Central orchestration component of the HTTP server runtime.
4
+ *
5
+ * @description Central orchestration component of the HTTP server runtime.
6
+ *
7
+ * Kernel coordinates the server lifecycle, request processing pipeline,
8
+ * exchange lifecycle events, and server-level error handling. It delegates
9
+ * transport operations such as listening and closing to their corresponding
10
+ * use cases while retaining control over the HTTP execution flow.
11
+ *
12
+ * The kernel does not expose the underlying HTTP adapter directly. Instead,
13
+ * it composes the adapter-dependent use cases and provides the runtime
14
+ * behavior required by HttpServer.
15
+ *
16
+ * @module Kernel
17
+ */
18
+
19
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
20
+ // » IMPORT NATIVE NODEJS MODULES
21
+
22
+ // » IMPORT THIRD PARTY MODULES
23
+
24
+ // » IMPORT LOCAL MODULES
25
+ import RouterSystem from '#routing/RouterSystem';
26
+ import EventSystem from '#EventSystem';
27
+ import IPCMain from '#IPCMain';
28
+ import ListenServer from '#use-cases/ListenServer';
29
+ import CloseServer from '#use-cases/CloseServer';
30
+ import TransportResolver from '#resolvers/TransportResolver';
31
+ import Exchange, { discardResponseState } from '#Exchange';
32
+ import ServerError from '#shared/errors/ServerError';
33
+ import ExchangeLayerBuilder from '#ExchangeLayerBuilder';
34
+ import { composeConfiguration } from '#configurations/ServerConfiguration';
35
+
36
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
37
+ /**
38
+ * Represents a Node.js HTTP/1.1 or HTTPS/1.1 incoming request.
39
+ *
40
+ * @typedef {import('node:http').IncomingMessage} HttpIncomingMessage
41
+ */
42
+
43
+ /**
44
+ * Represents a Node.js HTTP/2 incoming request.
45
+ *
46
+ * @typedef {import('node:http2').Http2ServerRequest} Http2IncomingMessage
47
+ */
48
+
49
+ /**
50
+ * Represents a Node.js HTTP/1.1 response.
51
+ *
52
+ * @typedef {import('node:http').ServerResponse} HttpServerResponse
53
+ */
54
+
55
+ /**
56
+ * Represents a Node.js HTTP/2 response.
57
+ *
58
+ * @typedef {import('node:http2').Http2ServerResponse} Http2ServerResponse
59
+ */
60
+
61
+ /**
62
+ * Represents a permitted transport identity.
63
+ *
64
+ * @typedef {import('#adapters/TransportAdapter').TransportIdentity} TransportIdentity
65
+ */
66
+
67
+ /**
68
+ * Represents a transport adapter capable of managing a permitted transport.
69
+ *
70
+ * @typedef {import('#adapters/TransportAdapter').default<TransportIdentity>} TransportAdapter
71
+ */
72
+
73
+ /**
74
+ * Represents a permitted server configuration identity.
75
+ *
76
+ * @typedef {import('#configurations/ServerConfiguration').ServerConfigurationIdentity} ServerConfigurationIdentity
77
+ */
78
+
79
+ /**
80
+ * Represents a server configuration constrained to a permitted identity.
81
+ *
82
+ * @typedef {import('#configurations/ServerConfiguration').default<ServerConfigurationIdentity>} ServerConfiguration
83
+ */
84
+
85
+ /**
86
+ * Represents the network options used to start the server.
87
+ *
88
+ * @typedef {import('#ServerOptions/ListenOptions').ListenOptionsData} ListenOptions
89
+ */
90
+
91
+ /**
92
+ * Represents the options forwarded to the Request constructor.
93
+ *
94
+ * @typedef {import('#ServerOptions/RequestOptions').RequestOptionsData} RequestOptions
95
+ */
96
+
97
+ /**
98
+ * Represents the options forwarded to the Response constructor.
99
+ *
100
+ * @typedef {import('#ServerOptions/ResponseOptions').ResponseOptionsData} ResponseOptions
101
+ */
102
+
103
+ /**
104
+ * Represents an HTTP method supported by the routing layer.
105
+ *
106
+ * @typedef {import('#routing/ExchangeLayer').HTTPMethod} HTTPMethod
107
+ */
108
+
109
+ /**
110
+ * Represents an exchange middleware function.
111
+ *
112
+ * @typedef {import('#routing/ExchangeLayer').MiddlewareFunction} MiddlewareFunction
113
+ */
114
+
115
+ /**
116
+ * Represents a router instance.
117
+ *
118
+ * @typedef {import('#routing/Router').default} Router
119
+ */
120
+
121
+ /**
122
+ * Represents a complete network endpoint.
123
+ *
124
+ * @typedef {import('#value-objects/Endpoint').default} Endpoint
125
+ */
126
+
127
+ /**
128
+ * Represents the network address of an HTTP server.
129
+ *
130
+ * @typedef {import('#value-objects/Address').default} Address
131
+ */
132
+
133
+ /**
134
+ * Represents the processing outcome of an HTTP exchange.
135
+ *
136
+ * @typedef {import('#Exchange').ExchangeOutcome} ExchangeOutcome
137
+ */
138
+
139
+ /**
140
+ * Provides information about an exchange when processing starts.
141
+ *
142
+ * @typedef {import('#Exchange').ExchangeStartInfo} ExchangeStartInfo
143
+ */
144
+
145
+ /**
146
+ * Provides information about an exchange when processing fails.
147
+ *
148
+ * @typedef {import('#Exchange').ExchangeErrorInfo} ExchangeErrorInfo
149
+ */
150
+
151
+ /**
152
+ * Provides information about an exchange when processing completes.
153
+ *
154
+ * @typedef {import('#Exchange').ExchangeEndInfo} ExchangeEndInfo
155
+ */
156
+
157
+ /**
158
+ * Represents an incoming request supported by the transport abstraction.
159
+ *
160
+ * @typedef {HttpIncomingMessage|Http2IncomingMessage} IncomingRequest
161
+ */
162
+
163
+ /**
164
+ * Represents a response supported by the transport abstraction.
165
+ *
166
+ * @typedef {HttpServerResponse|Http2ServerResponse} ServerResponse
167
+ */
168
+
169
+ /**
170
+ * Represents the connection options forwarded to the transport adapter.
171
+ *
172
+ * @typedef {ServerConfiguration['connection']} ServerConnectionOptions
173
+ */
174
+
175
+ /**
176
+ * Represents the transport identifier used to resolve the transport adapter.
177
+ *
178
+ * @typedef {ServerConfiguration['transport']} ServerTransportOption
179
+ */
180
+
181
+ /**
182
+ * Callback invoked to resolve a not-found exchange.
183
+ *
184
+ * @typedef {(exchange: Exchange) => void|Promise<void>} NotFoundHandler
185
+ */
186
+
187
+ /**
188
+ * Callback invoked to resolve a system error exchange.
189
+ *
190
+ * @typedef {(error: Error, exchange: Exchange) => void|Promise<void>} SystemErrorHandler
191
+ */
192
+
193
+ /**
194
+ * Represents an event name accepted by the kernel event system.
195
+ *
196
+ * @typedef {'listen'|'close'|'error'|'exchange:start'|'exchange:end'|'exchange:error'|symbol} EventName
197
+ */
198
+
199
+ /**
200
+ * Data emitted with the `listen` event.
201
+ *
202
+ * @typedef {object} ListenEventData
203
+ * @property {Endpoint} endpoint - Endpoint where the server is listening.
204
+ * @property {Address} address - Network address where the server is listening.
205
+ * @property {number} elapsed - Elapsed time in milliseconds.
206
+ */
207
+
208
+ /**
209
+ * Data emitted with the `close` event.
210
+ *
211
+ * @typedef {object} CloseEventData
212
+ * @property {number} elapsed - Elapsed time in milliseconds.
213
+ */
214
+
215
+ /**
216
+ * Listener registered for the `listen` event.
217
+ *
218
+ * @typedef {(data: ListenEventData) => void} ListenEventListener
219
+ */
220
+
221
+ /**
222
+ * Listener registered for the `close` event.
223
+ *
224
+ * @typedef {(data: CloseEventData) => void} CloseEventListener
225
+ */
226
+
227
+ /**
228
+ * Listener registered for the `error` event.
229
+ *
230
+ * @typedef {(error: Error) => void} ErrorEventListener
231
+ */
232
+
233
+ /**
234
+ * Listener registered for the `exchange:start` event.
235
+ *
236
+ * @typedef {(data: ExchangeStartInfo) => void} ExchangeStartEventListener
237
+ */
238
+
239
+ /**
240
+ * Listener registered for the `exchange:end` event.
241
+ *
242
+ * @typedef {(data: ExchangeEndInfo) => void} ExchangeEndEventListener
243
+ */
244
+
245
+ /**
246
+ * Listener registered for the `exchange:error` event.
247
+ *
248
+ * @typedef {(data: ExchangeErrorInfo) => void} ExchangeErrorEventListener
249
+ */
250
+
251
+ /**
252
+ * Represents a listener registered for a kernel event.
253
+ *
254
+ * @typedef {(data?: any) => void} EventListener
255
+ */
256
+
257
+ /**
258
+ * Represents a successful pipeline execution.
259
+ *
260
+ * @typedef {object} PipelineExecutionSuccess
261
+ * @property {true} success - Indicates that the pipeline completed successfully.
262
+ */
263
+
264
+ /**
265
+ * Represents a failed pipeline execution.
266
+ *
267
+ * @typedef {object} PipelineExecutionFailure
268
+ * @property {false} success - Indicates that the pipeline failed.
269
+ * @property {Error} error - The error raised during pipeline execution.
270
+ */
271
+
272
+ /**
273
+ * Represents the outcome of pipeline execution.
274
+ *
275
+ * @typedef {PipelineExecutionSuccess|PipelineExecutionFailure} PipelineExecutionResult
276
+ */
277
+
278
+ // ━━ FUNCTIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
279
+ /**
280
+ * Normalizes a thrown value into an `Error` instance.
281
+ *
282
+ * - `Error` instances (including subclasses) are returned as-is.
283
+ * - Any other value is converted to an `Error` whose message is `String(value)`.
284
+ *
285
+ * @private
286
+ * @param {unknown} error - The value thrown or rejected.
287
+ * @returns {Error} The normalized error instance.
288
+ */
289
+ const normalizeError = error => {
290
+ return error instanceof Error ? error : new Error(String(error));
291
+ };
292
+
293
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
294
+ /**
295
+ * Coordinates the HTTP server lifecycle and request execution pipeline.
296
+ *
297
+ * @classdesc Kernel acts as the central orchestration component between the
298
+ * public HttpServer API and the application-level HTTP runtime. It manages
299
+ * server lifecycle operations, registers pipeline entries, creates exchange
300
+ * contexts, emits lifecycle events, and handles errors occurring during
301
+ * server or exchange execution.
302
+ *
303
+ * Transport-specific lifecycle operations are delegated to ListenServer
304
+ * and CloseServer. Request delivery is connected directly to the transport
305
+ * adapter and routed into the exchange processing pipeline.
306
+ */
307
+ class Kernel {
308
+ /**
309
+ * Resolved transport adapter instance.
310
+ *
311
+ * @type {TransportAdapter}
312
+ */
313
+ #server;
314
+
315
+ /**
316
+ * Network configuration used to start the server.
317
+ *
318
+ * @type {ListenOptions|undefined}
319
+ */
320
+ #listenOptions;
321
+
322
+ /**
323
+ * Options forwarded to the Request constructor.
324
+ *
325
+ * @type {RequestOptions|undefined}
326
+ */
327
+ #requestOptions;
328
+
329
+ /**
330
+ * Options forwarded to the Response constructor.
331
+ *
332
+ * @type {ResponseOptions|undefined}
333
+ */
334
+ #responseOptions;
335
+
336
+ /**
337
+ * Use case responsible for starting the server.
338
+ *
339
+ * @type {ListenServer}
340
+ */
341
+ #listenServer;
342
+
343
+ /**
344
+ * Use case responsible for stopping the server.
345
+ *
346
+ * @type {CloseServer}
347
+ */
348
+ #closeServer;
349
+
350
+ /**
351
+ * Routing system responsible for registering routes and executing the pipeline.
352
+ *
353
+ * @type {RouterSystem}
354
+ */
355
+ #routerSystem = new RouterSystem();
356
+
357
+ /**
358
+ * Event system used to report kernel lifecycle and exchange events.
359
+ *
360
+ * @type {EventSystem}
361
+ */
362
+ #eventSystem = new EventSystem();
363
+
364
+ /**
365
+ * IPC subsystem owned by the kernel.
366
+ *
367
+ * @type {IPCMain}
368
+ */
369
+ #ipc;
370
+
371
+ /**
372
+ * User-provided handler for not-found exchanges.
373
+ *
374
+ * @type {NotFoundHandler|null}
375
+ */
376
+ #notFoundHandler = null;
377
+
378
+ /**
379
+ * User-provided handler for system error exchanges.
380
+ *
381
+ * @type {SystemErrorHandler|null}
382
+ */
383
+ #systemErrorHandler = null;
384
+
385
+ /**
386
+ * Creates an HTTP kernel.
387
+ *
388
+ * @param {ServerConfiguration} configuration - Configuration options for server startup.
389
+ * @example
390
+ * ```js
391
+ * const configuration = new HttpsServerConfiguration({
392
+ * listen: {
393
+ * host: 'localhost',
394
+ * port: 3443,
395
+ * },
396
+ * connection: {
397
+ * cert: './cert.pem',
398
+ * key: './key.pem',
399
+ * },
400
+ * });
401
+ *
402
+ * const kernel = new Kernel(configuration);
403
+ * ```
404
+ */
405
+ constructor(configuration) {
406
+ const { serverOptions, middlewareOptions } = composeConfiguration(configuration);
407
+
408
+ this.#server = Kernel.#ensureAdapter(serverOptions.transport, serverOptions.connection);
409
+ this.#listenOptions = serverOptions.listen;
410
+ this.#requestOptions = serverOptions.request;
411
+ this.#responseOptions = serverOptions.response;
412
+
413
+ this.#listenServer = new ListenServer(this.#server);
414
+ this.#closeServer = new CloseServer(this.#server);
415
+ this.#ipc = new IPCMain(this.#server);
416
+
417
+ const layerOptions = ExchangeLayerBuilder.build(middlewareOptions);
418
+
419
+ this.#routerSystem.registerLayerOptionsBatch(layerOptions);
420
+
421
+ /**
422
+ * Handles one incoming HTTP request.
423
+ *
424
+ * @param {IncomingRequest} incomingMessage - Native Node.js incoming HTTP message.
425
+ * @param {ServerResponse} serverResponse - Native Node.js outgoing HTTP message.
426
+ * @returns {void}
427
+ */
428
+ const onRequestHandler = (incomingMessage, serverResponse) => {
429
+ void this.#handleExchange(incomingMessage, serverResponse);
430
+ };
431
+
432
+ this.#server.onRequest(onRequestHandler);
433
+ }
434
+
435
+ /**
436
+ * Returns whether the server is currently listening for requests.
437
+ *
438
+ * @readonly
439
+ * @type {boolean}
440
+ */
441
+ get listening() {
442
+ return this.#server.listening;
443
+ }
444
+
445
+ /**
446
+ * The IPC subsystem owned by the kernel.
447
+ *
448
+ * @readonly
449
+ * @type {IPCMain}
450
+ */
451
+ get ipc() {
452
+ return this.#ipc;
453
+ }
454
+
455
+ /**
456
+ * @overload
457
+ * @param {'listen'} event - Event name.
458
+ * @param {ListenEventListener} listener - Function invoked when the server starts listening.
459
+ * @returns {Kernel} The current kernel instance.
460
+ */
461
+ /**
462
+ * @overload
463
+ * @param {'close'} event - Event name.
464
+ * @param {CloseEventListener} listener - Function invoked when the server closes.
465
+ * @returns {Kernel} The current kernel instance.
466
+ */
467
+ /**
468
+ * @overload
469
+ * @param {'error'} event - Event name.
470
+ * @param {ErrorEventListener} listener - Function invoked when a server-level error occurs.
471
+ * @returns {Kernel} The current kernel instance.
472
+ */
473
+ /**
474
+ * @overload
475
+ * @param {'exchange:start'} event - Event name.
476
+ * @param {ExchangeStartEventListener} listener - Function invoked during the exchange starts.
477
+ * @returns {Kernel} The current kernel instance.
478
+ */
479
+ /**
480
+ * @overload
481
+ * @param {'exchange:end'} event - Event name.
482
+ * @param {ExchangeEndEventListener} listener - Function invoked during the exchange ends.
483
+ * @returns {Kernel} The current kernel instance.
484
+ */
485
+ /**
486
+ * @overload
487
+ * @param {'exchange:error'} event - Event name.
488
+ * @param {ExchangeErrorEventListener} listener - Function invoked when an exchange fails.
489
+ * @returns {Kernel} The current kernel instance.
490
+ */
491
+ /**
492
+ * Registers a listener for a kernel event.
493
+ *
494
+ * @param {EventName} event - Event name.
495
+ * @param {EventListener} listener - Function invoked when the event is emitted.
496
+ * @returns {Kernel} The current kernel instance.
497
+ * @example
498
+ * ```js
499
+ * kernel.onListen(({ endpoint, address, elapsed }) => {
500
+ * console.log(`Server listening at ${endpoint.displayUrl} in ${elapsed}ms`);
501
+ * console.log(`Bound to ${address} (${address.family})`);
502
+ * // Bound to [::1]:3000 (IPv6)
503
+ * });
504
+ * ```
505
+ */
506
+ on(event, listener) {
507
+ this.#eventSystem.on(event, listener);
508
+ return this;
509
+ }
510
+
511
+ /**
512
+ * @overload
513
+ * @param {'listen'} event - Event name.
514
+ * @param {ListenEventListener} listener - Function invoked when the server starts listening.
515
+ * @returns {Kernel} The current kernel instance.
516
+ */
517
+ /**
518
+ * @overload
519
+ * @param {'close'} event - Event name.
520
+ * @param {CloseEventListener} listener - Function invoked when the server closes.
521
+ * @returns {Kernel} The current kernel instance.
522
+ */
523
+ /**
524
+ * @overload
525
+ * @param {'error'} event - Event name.
526
+ * @param {ErrorEventListener} listener - Function invoked when a server-level error occurs.
527
+ * @returns {Kernel} The current kernel instance.
528
+ */
529
+ /**
530
+ * @overload
531
+ * @param {'exchange:start'} event - Event name.
532
+ * @param {ExchangeStartEventListener} listener - Function invoked during the exchange starts.
533
+ * @returns {Kernel} The current kernel instance.
534
+ */
535
+ /**
536
+ * @overload
537
+ * @param {'exchange:end'} event - Event name.
538
+ * @param {ExchangeEndEventListener} listener - Function invoked during the exchange ends.
539
+ * @returns {Kernel} The current kernel instance.
540
+ */
541
+ /**
542
+ * @overload
543
+ * @param {'exchange:error'} event - Event name.
544
+ * @param {ExchangeErrorEventListener} listener - Function invoked when an exchange fails.
545
+ * @returns {Kernel} The current kernel instance.
546
+ */
547
+ /**
548
+ * Registers a listener that is invoked only once for a kernel event.
549
+ *
550
+ * @param {EventName} event - Event name.
551
+ * @param {EventListener} listener - Function invoked when the event is emitted.
552
+ * @returns {Kernel} The current kernel instance.
553
+ * @example
554
+ * ```js
555
+ * kernel.once('listen', ({ endpoint }) => {
556
+ * console.log(`Server started at ${endpoint.displayUrl}`);
557
+ * });
558
+ * ```
559
+ */
560
+ once(event, listener) {
561
+ this.#eventSystem.once(event, listener);
562
+ return this;
563
+ }
564
+
565
+ /**
566
+ * @overload
567
+ * @param {'listen'} event - Event name.
568
+ * @param {ListenEventListener} listener - Function invoked when the server starts listening.
569
+ * @returns {Kernel} The current kernel instance.
570
+ */
571
+ /**
572
+ * @overload
573
+ * @param {'close'} event - Event name.
574
+ * @param {CloseEventListener} listener - Function invoked when the server closes.
575
+ * @returns {Kernel} The current kernel instance.
576
+ */
577
+ /**
578
+ * @overload
579
+ * @param {'error'} event - Event name.
580
+ * @param {ErrorEventListener} listener - Function invoked when a server-level error occurs.
581
+ * @returns {Kernel} The current kernel instance.
582
+ */
583
+ /**
584
+ * @overload
585
+ * @param {'exchange:start'} event - Event name.
586
+ * @param {ExchangeStartEventListener} listener - Function invoked during the exchange starts.
587
+ * @returns {Kernel} The current kernel instance.
588
+ */
589
+ /**
590
+ * @overload
591
+ * @param {'exchange:end'} event - Event name.
592
+ * @param {ExchangeEndEventListener} listener - Function invoked during the exchange ends.
593
+ * @returns {Kernel} The current kernel instance.
594
+ */
595
+ /**
596
+ * @overload
597
+ * @param {'exchange:error'} event - Event name.
598
+ * @param {ExchangeErrorEventListener} listener - Function invoked when an exchange fails.
599
+ * @returns {Kernel} The current kernel instance.
600
+ */
601
+ /**
602
+ * Removes a listener from a kernel event.
603
+ *
604
+ * @param {EventName} event - Event name.
605
+ * @param {EventListener} listener - Listener to remove.
606
+ * @returns {Kernel} The current kernel instance.
607
+ * @example
608
+ * ```js
609
+ * const listener = () => {
610
+ * console.log('Server started');
611
+ * };
612
+ *
613
+ * kernel.on('listen', listener);
614
+ * kernel.off('listen', listener);
615
+ * ```
616
+ */
617
+ off(event, listener) {
618
+ this.#eventSystem.off(event, listener);
619
+ return this;
620
+ }
621
+
622
+ /**
623
+ * Registers a listener for the `listen` event.
624
+ *
625
+ * @param {ListenEventListener} listener - Function invoked when the server starts listening.
626
+ * @returns {Kernel} The current kernel instance.
627
+ *
628
+ * @example
629
+ * ```js
630
+ * kernel.onListen(({ endpoint, address, elapsed }) => {
631
+ * console.log(`Server listening at ${endpoint.displayUrl} in ${elapsed}ms`);
632
+ * console.log(`Bound to ${address} (${address.family})`);
633
+ * // Bound to [::1]:3000 (IPv6)
634
+ * });
635
+ * ```
636
+ */
637
+ onListen(listener) {
638
+ this.#eventSystem.on(Kernel.#EVENTS.LISTEN, listener);
639
+ return this;
640
+ }
641
+
642
+ /**
643
+ * Registers a listener for the `close` event.
644
+ *
645
+ * @param {CloseEventListener} listener - Function invoked when the server closes.
646
+ * @returns {Kernel} The current kernel instance.
647
+ *
648
+ * @example
649
+ * ```js
650
+ * kernel.onClose(({ elapsed }) => {
651
+ * console.log(`Server closed in ${elapsed}ms`);
652
+ * });
653
+ * ```
654
+ */
655
+ onClose(listener) {
656
+ this.#eventSystem.on(Kernel.#EVENTS.CLOSE, listener);
657
+ return this;
658
+ }
659
+
660
+ /**
661
+ * Registers a listener for the `error` event.
662
+ *
663
+ * @param {ErrorEventListener} listener - Function invoked when a server-level error occurs.
664
+ * @returns {Kernel} The current kernel instance.
665
+ *
666
+ * @example
667
+ * ```js
668
+ * kernel.onError(error => {
669
+ * console.error('Server error:', error);
670
+ * });
671
+ * ```
672
+ */
673
+ onError(listener) {
674
+ this.#eventSystem.on(Kernel.#EVENTS.ERROR, listener);
675
+ return this;
676
+ }
677
+
678
+ /**
679
+ * Registers a listener for the `exchange:start` event.
680
+ *
681
+ * @param {ExchangeStartEventListener} listener - Function invoked when an exchange starts.
682
+ * @returns {Kernel} The current kernel instance.
683
+ *
684
+ * @example
685
+ * ```js
686
+ * kernel.onExchangeStart(information => {
687
+ * console.log(
688
+ * information.id,
689
+ * information.request.method,
690
+ * information.request.pathname,
691
+ * );
692
+ * });
693
+ * ```
694
+ */
695
+ onExchangeStart(listener) {
696
+ this.#eventSystem.on(Kernel.#EVENTS.EXCHANGE_START, listener);
697
+ return this;
698
+ }
699
+
700
+ /**
701
+ * Registers a listener for the `exchange:end` event.
702
+ *
703
+ * @param {ExchangeEndEventListener} listener - Function invoked when exchange processing ends.
704
+ * @returns {Kernel} The current kernel instance.
705
+ *
706
+ * @example
707
+ * ```js
708
+ * kernel.onExchangeEnd(information => {
709
+ * console.log(
710
+ * information.outcome, // 'success' | 'error'
711
+ * information.timing.duration, // number
712
+ * );
713
+ * });
714
+ * ```
715
+ */
716
+ onExchangeEnd(listener) {
717
+ this.#eventSystem.on(Kernel.#EVENTS.EXCHANGE_END, listener);
718
+ return this;
719
+ }
720
+
721
+ /**
722
+ * Registers a listener for the `exchange:error` event.
723
+ *
724
+ * @param {ExchangeErrorEventListener} listener - Function invoked when an exchange fails.
725
+ * @returns {Kernel} The current kernel instance.
726
+ *
727
+ * @example
728
+ * ```js
729
+ * kernel.onExchangeError(information => {
730
+ * console.error(
731
+ * information.id,
732
+ * information.error,
733
+ * information.request.pathname,
734
+ * );
735
+ * });
736
+ * ```
737
+ */
738
+ onExchangeError(listener) {
739
+ this.#eventSystem.on(Kernel.#EVENTS.EXCHANGE_ERROR, listener);
740
+ return this;
741
+ }
742
+
743
+ /**
744
+ * Registers a route entry.
745
+ *
746
+ * @param {HTTPMethod|undefined} method - The HTTP method to match.
747
+ * @param {string|undefined} pathnamePattern - The URL pathname pattern to match.
748
+ * @param {MiddlewareFunction[]} middlewares - The middleware functions to execute.
749
+ * @returns {Kernel} The current kernel instance.
750
+ *
751
+ * @example
752
+ * ```js
753
+ * kernel.registerRouteEntry('GET', '/users', [
754
+ * async (exchange, next) => {
755
+ * exchange.response.json({ users: [] });
756
+ * await next();
757
+ * },
758
+ * ]);
759
+ * ```
760
+ */
761
+ registerRouteEntry(method, pathnamePattern, middlewares) {
762
+ this.#routerSystem.registerRouteEntry(method, pathnamePattern, middlewares);
763
+ return this;
764
+ }
765
+
766
+ /**
767
+ * Registers a mounted router by prefixing its routes with a base pathname pattern.
768
+ *
769
+ * @param {string} basePathnamePattern - The base URL pathname pattern to prefix.
770
+ * @param {Router} router - The router instance to mount.
771
+ * @returns {Kernel} The current kernel instance.
772
+ *
773
+ * @example
774
+ * ```js
775
+ * const usersRouter = new Router();
776
+ *
777
+ * usersRouter.get('/users', async exchange => {
778
+ * exchange.response.json({ users: [] });
779
+ * });
780
+ *
781
+ * kernel.registerMountEntry('/api', usersRouter);
782
+ * ```
783
+ */
784
+ registerMountEntry(basePathnamePattern, router) {
785
+ this.#routerSystem.registerMountEntry(basePathnamePattern, router);
786
+ return this;
787
+ }
788
+
789
+ /**
790
+ * Registers a handler for not-found exchanges.
791
+ *
792
+ * @param {NotFoundHandler} handler - Handler invoked when no route matches the exchange.
793
+ * @returns {Kernel} The current kernel instance.
794
+ *
795
+ * @example
796
+ * ```js
797
+ * kernel.notFound(exchange => {
798
+ * exchange.response.status(404).json({
799
+ * error: 'Resource not found',
800
+ * });
801
+ * });
802
+ * ```
803
+ */
804
+ notFound(handler) {
805
+ this.#notFoundHandler = handler;
806
+ return this;
807
+ }
808
+
809
+ /**
810
+ * Registers a handler for system errors raised during exchange processing.
811
+ *
812
+ * @param {SystemErrorHandler} handler - Handler invoked when an exchange fails.
813
+ * @returns {Kernel} The current kernel instance.
814
+ *
815
+ * @example
816
+ * ```js
817
+ * kernel.systemError((error, exchange) => {
818
+ * console.error(error);
819
+ *
820
+ * exchange.response.status(500).json({
821
+ * error: 'Request failed',
822
+ * });
823
+ * });
824
+ * ```
825
+ */
826
+ systemError(handler) {
827
+ this.#systemErrorHandler = handler;
828
+ return this;
829
+ }
830
+
831
+ /**
832
+ * Starts the HTTP server.
833
+ *
834
+ * @returns {Promise<void>} Resolves when the server has successfully started listening.
835
+ * @throws {ServerError} Thrown when the server cannot start listening.
836
+ *
837
+ * @example
838
+ * ```js
839
+ * await kernel.listen();
840
+ *
841
+ * console.log('Server started');
842
+ * ```
843
+ */
844
+ async listen() {
845
+ const startedAt = performance.now();
846
+
847
+ try {
848
+ await this.#listenServer.execute(this.#listenOptions);
849
+ } catch (error) {
850
+ const serverError = new ServerError('SERVER_LISTEN_FAILED', { cause: normalizeError(error) });
851
+ this.#emit(Kernel.#EVENTS.ERROR, serverError);
852
+ throw serverError;
853
+ }
854
+
855
+ this.#emit(Kernel.#EVENTS.LISTEN, {
856
+ endpoint: this.#server.endpoint(),
857
+ address: this.#server.address(),
858
+ elapsed: Math.round(performance.now() - startedAt),
859
+ });
860
+ }
861
+
862
+ /**
863
+ * Closes the HTTP server.
864
+ *
865
+ * @returns {Promise<void>} Resolves when the server has successfully closed.
866
+ * @throws {ServerError} Thrown when the server cannot be closed successfully.
867
+ *
868
+ * @example
869
+ * ```js
870
+ * await kernel.close();
871
+ *
872
+ * console.log('Server closed');
873
+ * ```
874
+ */
875
+ async close() {
876
+ const startedAt = performance.now();
877
+
878
+ if (this.#server.listening) {
879
+ this.#closeIPC();
880
+
881
+ try {
882
+ await this.#closeServer.execute();
883
+ } catch (error) {
884
+ const serverError = new ServerError('SERVER_CLOSE_FAILED', {
885
+ cause: normalizeError(error),
886
+ });
887
+
888
+ this.#emit(Kernel.#EVENTS.ERROR, serverError);
889
+
890
+ throw serverError;
891
+ }
892
+
893
+ this.#emit(Kernel.#EVENTS.CLOSE, {
894
+ elapsed: Math.round(performance.now() - startedAt),
895
+ });
896
+ }
897
+ }
898
+
899
+ /**
900
+ * Processes a single HTTP exchange.
901
+ *
902
+ * @param {IncomingRequest} incomingMessage - Native Node.js incoming HTTP message.
903
+ * @param {ServerResponse} serverResponse - Native Node.js outgoing HTTP message.
904
+ * @returns {Promise<void>} Resolves when the exchange lifecycle has completed.
905
+ */
906
+ async #handleExchange(incomingMessage, serverResponse) {
907
+ const exchange = this.#createExchange(incomingMessage, serverResponse);
908
+
909
+ if (exchange !== null) {
910
+ await this.#processExchange(exchange);
911
+ }
912
+ }
913
+
914
+ /**
915
+ * Creates an exchange for an incoming HTTP request.
916
+ *
917
+ * If initialization fails, emits a server-level error and attempts to send
918
+ * a minimal `500` response.
919
+ *
920
+ * @param {IncomingRequest} incomingMessage - Incoming HTTP request.
921
+ * @param {ServerResponse} serverResponse - Outgoing HTTP response.
922
+ * @returns {Exchange|null} The created exchange, or `null` if initialization fails.
923
+ */
924
+ #createExchange(incomingMessage, serverResponse) {
925
+ try {
926
+ return new Exchange(incomingMessage, serverResponse, {
927
+ request: this.#requestOptions,
928
+ response: this.#responseOptions,
929
+ onCommitError: (error, exchangeSource) => {
930
+ this.#emitExchangeError(error, exchangeSource);
931
+ },
932
+ });
933
+ } catch (error) {
934
+ const serverError = new ServerError('SERVER_EXCHANGE_INIT_FAILED', {
935
+ cause: normalizeError(error),
936
+ });
937
+ this.#emit(Kernel.#EVENTS.ERROR, serverError);
938
+
939
+ if (!serverResponse.headersSent && !serverResponse.writableEnded) {
940
+ serverResponse.statusCode = 500;
941
+ serverResponse.end();
942
+ }
943
+
944
+ return null;
945
+ }
946
+ }
947
+
948
+ /**
949
+ * Handles an exchange processing error and attempts to produce an error response.
950
+ *
951
+ * @param {Error} error - The error raised during exchange processing.
952
+ * @param {Exchange} exchange - The exchange associated with the error.
953
+ * @returns {Promise<void>} Resolves when the error has been handled.
954
+ */
955
+ async #handleExchangeError(error, exchange) {
956
+ this.#emitExchangeError(error, exchange);
957
+
958
+ if (!exchange.response.isCommitted) {
959
+ discardResponseState(exchange.response);
960
+
961
+ try {
962
+ await this.#handleSystemError(error, exchange);
963
+ } finally {
964
+ exchange.response.end();
965
+ }
966
+ }
967
+ }
968
+
969
+ /**
970
+ * Processes an exchange and emits its lifecycle events.
971
+ *
972
+ * Lifecycle events are emitted with the snapshot produced by
973
+ * `Exchange.createSnapshot`:
974
+ *
975
+ * - `exchange:start` carries a `pending` snapshot.
976
+ * - `exchange:end` carries a terminal snapshot (success or error).
977
+ * - `exchange:error` carries the snapshot of a failure observed before or during commit.
978
+ *
979
+ * @param {Exchange} exchange - The exchange to process.
980
+ */
981
+ async #processExchange(exchange) {
982
+ this.#emit(
983
+ Kernel.#EVENTS.EXCHANGE_START,
984
+ Exchange.createSnapshot(exchange, 'pending', undefined, undefined),
985
+ );
986
+
987
+ const result = await this.#runPipeline(exchange);
988
+
989
+ try {
990
+ if (!result.success) {
991
+ await this.#handleExchangeError(result.error, exchange);
992
+ }
993
+ } finally {
994
+ const endedAt = performance.now();
995
+
996
+ this.#emit(
997
+ Kernel.#EVENTS.EXCHANGE_END,
998
+ Exchange.createSnapshot(
999
+ exchange,
1000
+ result.success ? 'success' : 'error',
1001
+ endedAt,
1002
+ result.success ? undefined : result.error,
1003
+ ),
1004
+ );
1005
+ }
1006
+ }
1007
+
1008
+ /**
1009
+ * Executes the exchange pipeline and captures its outcome.
1010
+ *
1011
+ * @param {Exchange} exchange - Exchange to process.
1012
+ * @returns {Promise<PipelineExecutionResult>} The pipeline execution result.
1013
+ */
1014
+ async #runPipeline(exchange) {
1015
+ try {
1016
+ await this.#routerSystem.executePipeline(exchange, this.#handleNotFound);
1017
+
1018
+ if (!exchange.response.isCommitted) {
1019
+ exchange.response.end();
1020
+ }
1021
+
1022
+ return { success: true };
1023
+ } catch (error) {
1024
+ return {
1025
+ success: false,
1026
+ error: normalizeError(error),
1027
+ };
1028
+ }
1029
+ }
1030
+
1031
+ /**
1032
+ * Handles an exchange that did not match any route.
1033
+ *
1034
+ * @type {(exchange: Exchange) => Promise<void>}
1035
+ */
1036
+ #handleNotFound = async exchange => {
1037
+ if (this.#notFoundHandler === null) {
1038
+ exchange.response.status(404).json({ error: 'Not Found' });
1039
+ } else {
1040
+ await this.#notFoundHandler(exchange);
1041
+ }
1042
+ };
1043
+
1044
+ /**
1045
+ * Handles a system error raised during exchange processing.
1046
+ *
1047
+ * @param {Error} error - Error raised during exchange processing.
1048
+ * @param {Exchange} exchange - Exchange associated with the failed request.
1049
+ * @returns {Promise<void>} Resolves when the system error handler has completed.
1050
+ */
1051
+ async #handleSystemError(error, exchange) {
1052
+ if (this.#systemErrorHandler === null) {
1053
+ exchange.response.status(500).json({ error: 'Internal Server Error' });
1054
+ } else {
1055
+ await this.#systemErrorHandler(error, exchange);
1056
+ }
1057
+ }
1058
+
1059
+ /**
1060
+ * Emits a kernel event.
1061
+ *
1062
+ * @param {EventName} event - Event name.
1063
+ * @param {unknown} [eventPayload] - Optional event payload.
1064
+ * @returns {void}
1065
+ */
1066
+ #emit(event, eventPayload) {
1067
+ this.#eventSystem.emit(event, eventPayload);
1068
+ }
1069
+
1070
+ /**
1071
+ * Emits an exchange error event.
1072
+ *
1073
+ * @param {Error} error - The error to report.
1074
+ * @param {Exchange} exchange - The exchange associated with the error.
1075
+ */
1076
+ #emitExchangeError(error, exchange) {
1077
+ this.#emit(
1078
+ Kernel.#EVENTS.EXCHANGE_ERROR,
1079
+ Exchange.createSnapshot(exchange, 'error', undefined, error),
1080
+ );
1081
+ }
1082
+
1083
+ /**
1084
+ * Closes the IPC subsystem without propagating close failures.
1085
+ *
1086
+ * Invoked during kernel shutdown. Failures are intentionally ignored
1087
+ * because the server is already shutting down.
1088
+ */
1089
+ #closeIPC() {
1090
+ try {
1091
+ this.#ipc.close();
1092
+ } catch {
1093
+ // Ignore IPC close failures — the server is shutting down.
1094
+ }
1095
+ }
1096
+
1097
+ /**
1098
+ * Kernel lifecycle event names.
1099
+ *
1100
+ * @type {Readonly<{
1101
+ * EXCHANGE_START: 'exchange:start',
1102
+ * EXCHANGE_END: 'exchange:end',
1103
+ * EXCHANGE_ERROR: 'exchange:error',
1104
+ * LISTEN: 'listen',
1105
+ * CLOSE: 'close',
1106
+ * ERROR: 'error'
1107
+ * }>}
1108
+ */
1109
+ static #EVENTS = Object.freeze({
1110
+ EXCHANGE_START: 'exchange:start',
1111
+ EXCHANGE_END: 'exchange:end',
1112
+ EXCHANGE_ERROR: 'exchange:error',
1113
+ LISTEN: 'listen',
1114
+ CLOSE: 'close',
1115
+ ERROR: 'error',
1116
+ });
1117
+
1118
+ /**
1119
+ * Resolves and creates the transport adapter for the server.
1120
+ *
1121
+ * @param {ServerTransportOption} transport - Transport identifier used to resolve the adapter.
1122
+ * @param {ServerConnectionOptions} connection - Connection options passed to the adapter.
1123
+ * @returns {TransportAdapter} The initialized transport adapter.
1124
+ * @throws {ServerError} Thrown when the transport adapter cannot be resolved or initialized.
1125
+ */
1126
+ static #ensureAdapter(transport, connection) {
1127
+ try {
1128
+ const Adapter = TransportResolver.resolve(transport);
1129
+ return new Adapter(connection);
1130
+ } catch (error) {
1131
+ throw new ServerError('SERVER_ADAPTER_INIT_FAILED', { cause: normalizeError(error) });
1132
+ }
1133
+ }
1134
+ }
1135
+
1136
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1137
+ export default Kernel;